diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index 22ff67c5..8ec6ff0a 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -209,7 +209,7 @@ void InfoLog_TitleLoaded() fs::path effectiveSavePath = getTitleSavePath(); std::error_code ec; const bool saveDirExists = fs::exists(effectiveSavePath, ec); - cemuLog_force("Save path: {}{}", _utf8Wrapper(effectiveSavePath), saveDirExists ? "" : " (not present)"); + cemuLog_force("Save path: {}{}", _pathToUtf8(effectiveSavePath), saveDirExists ? "" : " (not present)"); // log shader cache name cemuLog_log(LogType::Force, "Shader cache file: shaderCache/transferable/{:016x}.bin", titleId); @@ -617,7 +617,7 @@ namespace CafeSystem sLaunchModeIsStandalone = true; cemuLog_log(LogType::Force, "Launching executable in standalone mode due to incorrect layout or missing meta files"); fs::path executablePath = path; - std::string dirName = _utf8Wrapper(executablePath.parent_path().filename()); + std::string dirName = _pathToUtf8(executablePath.parent_path().filename()); if (boost::iequals(dirName, "code")) { // check for content folder @@ -626,18 +626,18 @@ namespace CafeSystem if (fs::is_directory(contentPath, ec)) { // mounting content folder - bool r = FSCDeviceHostFS_Mount(std::string("/vol/content").c_str(), boost::nowide::widen(_utf8Wrapper(contentPath)).c_str(), FSC_PRIORITY_BASE); + bool r = FSCDeviceHostFS_Mount(std::string("/vol/content").c_str(), _pathToUtf8(contentPath), FSC_PRIORITY_BASE); if (!r) { - cemuLog_log(LogType::Force, "Failed to mount {}", _utf8Wrapper(contentPath).c_str()); + cemuLog_log(LogType::Force, "Failed to mount {}", _pathToUtf8(contentPath)); return STATUS_CODE::UNABLE_TO_MOUNT; } } } // mount code folder to a virtual temporary path - FSCDeviceHostFS_Mount(std::string("/internal/code/").c_str(), boost::nowide::widen(_utf8Wrapper(executablePath.parent_path())).c_str(), FSC_PRIORITY_BASE); + FSCDeviceHostFS_Mount(std::string("/internal/code/").c_str(), _pathToUtf8(executablePath.parent_path()), FSC_PRIORITY_BASE); std::string internalExecutablePath = "/internal/code/"; - internalExecutablePath.append(_utf8Wrapper(executablePath.filename())); + internalExecutablePath.append(_pathToUtf8(executablePath.filename())); _pathToExecutable = internalExecutablePath; // since a lot of systems (including save folder location) rely on a TitleId, we derive a placeholder id from the executable hash auto execData = fsc_extractFile(_pathToExecutable.c_str()); diff --git a/src/Cafe/Filesystem/FST/fstUtil.h b/src/Cafe/Filesystem/FST/fstUtil.h index d0779e59..4ea9465d 100644 --- a/src/Cafe/Filesystem/FST/fstUtil.h +++ b/src/Cafe/Filesystem/FST/fstUtil.h @@ -1,354 +1,13 @@ #pragma once #include -class parsedPathW -{ - static const int MAX_NODES = 32; - -public: - parsedPathW(std::wstring_view path) - { - // init vars - this->numNodes = 0; - // init parsed path data - if (path.front() == '/') - path.remove_prefix(1); - pathData.assign(path.begin(), path.end()); - pathData.push_back('\0'); - // start parsing - sint32 offset = 0; - sint32 startOffset = 0; - if (offset < pathData.size()-1) - { - this->nodeOffset[this->numNodes] = offset; - this->numNodes++; - } - while (offset < pathData.size() - 1) - { - if (this->pathData[offset] == '/' || this->pathData[offset] == '\\') - { - this->pathData[offset] = '\0'; - offset++; - // double slashes are ignored and instead are handled like a single slash - if (this->pathData[offset] == '/' || this->pathData[offset] == '\\') - { - // if we're in the beginning and having a \\ it's a network path - if (offset != 1) - { - this->pathData[offset] = '\0'; - offset++; - } - } - // start new node - if (this->numNodes < MAX_NODES) - { - if (offset < pathData.size() - 1) - { - this->nodeOffset[this->numNodes] = offset; - this->numNodes++; - } - } - continue; - } - offset++; - } - // handle special nodes like '.' or '..' - sint32 nodeIndex = 0; - while (nodeIndex < this->numNodes) - { - if (compareNodeName(nodeIndex, L"..")) - { - assert(false); - } - else if (compareNodeName(nodeIndex, L".")) - { - removeNode(nodeIndex); - continue; - } - nodeIndex++; - } - } - - // returns true if the names match (case sensitive) - bool compareNodeName(sint32 index, std::wstring_view name) - { - if (index < 0 || index >= this->numNodes) - return false; - const wchar_t* nodeName = this->pathData.data() + this->nodeOffset[index]; - if (boost::iequals(nodeName, name)) - return true; - return false; - } - - static bool compareNodeName(std::wstring_view name1, std::wstring_view name2) - { - if (boost::iequals(name1, name2)) - return true; - return false; - } - - static bool compareNodeNameCaseInsensitive(std::wstring_view name1, std::wstring_view name2) - { - if (boost::iequals(name1, name2)) - return true; - return false; - } - - const wchar_t* getNodeName(sint32 index) - { - if (index < 0 || index >= this->numNodes) - return nullptr; - return this->pathData.data() + this->nodeOffset[index]; - } - - void removeNode(sint32 index) - { - if (index < 0 || index >= numNodes) - return; - numNodes--; - for (sint32 i = 0; i < numNodes; i++) - { - nodeOffset[i] = nodeOffset[i + 1]; - } - // remove empty space - if (numNodes > 0) - updateOffsets(nodeOffset[0]); - } - - void prependNode(wchar_t* newNode) - { - if (numNodes >= MAX_NODES) - return; - sint32 len = (sint32)wcslen(newNode); - updateOffsets(-(len + 1)); - numNodes++; - for (sint32 i = numNodes - 1; i >= 1; i--) - { - nodeOffset[i] = nodeOffset[i - 1]; - } - nodeOffset[0] = 0; - memcpy(pathData.data() + 0, newNode, (len + 1) * sizeof(wchar_t)); - } - - void buildPathString(std::wstring& pathStr, bool appendSlash = false) - { - pathStr.resize(0); - for (sint32 i = 0; i < numNodes; i++) - { - if (numNodes > 1) - pathStr.append(L"/"); - pathStr.append(pathData.data() + nodeOffset[i]); - } - if(appendSlash) - pathStr.append(L"/"); - } -private: - void updateOffsets(sint32 newBaseOffset) - { - if (numNodes == 0 || newBaseOffset == 0) - return; - cemu_assert_debug(newBaseOffset <= nodeOffset[0]); - if (newBaseOffset > 0) - { - // decrease size - memmove(pathData.data(), pathData.data() + newBaseOffset, (pathData.size() - newBaseOffset) * sizeof(wchar_t)); - pathData.resize(pathData.size() - newBaseOffset); - // update node offsets - for (sint32 i = 0; i < numNodes; i++) - { - nodeOffset[i] -= newBaseOffset; - } - } - else - { - // increase size - newBaseOffset = -newBaseOffset; - pathData.resize(pathData.size() + newBaseOffset); - memmove(pathData.data() + newBaseOffset, pathData.data(), (pathData.size() - newBaseOffset) * sizeof(wchar_t)); - // update node offsets - for (sint32 i = 0; i < numNodes; i++) - { - nodeOffset[i] += newBaseOffset; - } - } - } - -private: - //std::wstring pathData; - std::vector pathData; - sint32 nodeOffset[MAX_NODES + 1]; - -public: - sint32 numNodes; -}; - - -template -class FileTree -{ -public: - -private: - - enum NODETYPE : uint8 - { - NODETYPE_DIRECTORY, - NODETYPE_FILE, - }; - - typedef struct _node_t - { - std::wstring name; - std::vector<_node_t*> subnodes; - F* custom; - NODETYPE type; - }node_t; - - node_t* getByNodePath(parsedPathW& p, sint32 numNodes, bool createAsDirectories) - { - node_t* currentNode = &rootNode; - for (sint32 i = 0; i < numNodes; i++) - { - // find subnode by path - node_t* foundSubnode = getSubnode(currentNode, p.getNodeName(i)); - if (foundSubnode == nullptr) - { - // no subnode found -> create new directory node (if requested) - if (createAsDirectories == false) - return nullptr; // path not found - currentNode = newNode(currentNode, NODETYPE_DIRECTORY, p.getNodeName(i)); - } - else - { - currentNode = foundSubnode; - } - } - return currentNode; - } - - node_t* getSubnode(node_t* parentNode, std::wstring_view name) - { - for (auto& sn : parentNode->subnodes) - { - if constexpr (isCaseSensitive) - { - if (parsedPathW::compareNodeName(sn->name.c_str(), name)) - return sn; - } - else - { - if (parsedPathW::compareNodeNameCaseInsensitive(sn->name.c_str(), name)) - return sn; - } - } - return nullptr; - } - - node_t* newNode(node_t* parentNode, NODETYPE type, std::wstring_view name) - { - node_t* newNode = new node_t; - newNode->name = std::wstring(name); - newNode->type = type; - newNode->custom = nullptr; - parentNode->subnodes.push_back(newNode); - return newNode; - } - -public: - FileTree() - { - rootNode.type = NODETYPE_DIRECTORY; - } - - bool addFile(const wchar_t* path, F* custom) - { - parsedPathW p(path); - if (p.numNodes == 0) - return false; - node_t* directoryNode = getByNodePath(p, p.numNodes - 1, true); - // check if a node with same name already exists - if (getSubnode(directoryNode, p.getNodeName(p.numNodes - 1)) != nullptr) - return false; // node already exists - // add file node - node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.getNodeName(p.numNodes - 1)); - fileNode->custom = custom; - return true; - } - - bool getFile(std::wstring_view path, F* &custom) - { - parsedPathW p(path); - if (p.numNodes == 0) - return false; - node_t* node = getByNodePath(p, p.numNodes, false); - if (node == nullptr) - return false; - if (node->type != NODETYPE_FILE) - return false; - custom = node->custom; - return true; - } - - bool removeFile(std::wstring_view path) - { - parsedPathW p(path); - if (p.numNodes == 0) - return false; - node_t* directoryNode = getByNodePath(p, p.numNodes - 1, false); - if (directoryNode == nullptr) - return false; - // find node - node_t* fileNode = getSubnode(directoryNode, p.getNodeName(p.numNodes - 1)); - if (fileNode == nullptr) - return false; - if (fileNode->type != NODETYPE_FILE) - return false; - if (fileNode->subnodes.empty() == false) - { - // files shouldn't have subnodes - assert(false); - } - // remove node from parent - directoryNode->subnodes.erase(std::remove(directoryNode->subnodes.begin(), directoryNode->subnodes.end(), fileNode), directoryNode->subnodes.end()); - // delete node - delete fileNode; - return true; - } - - template - bool listDirectory(const wchar_t* path, TFunc fn) - { - parsedPathW p(path); - node_t* node = getByNodePath(p, p.numNodes, false); - if (node == nullptr) - return false; - if (node->type != NODETYPE_DIRECTORY) - return false; - for (auto& it : node->subnodes) - { - if (it->type == NODETYPE_DIRECTORY) - { - fn(it->name, true, it->custom); - } - else if (it->type == NODETYPE_FILE) - { - fn(it->name, false, it->custom); - } - } - return true; - } - -private: - node_t rootNode; -}; - #include // path parser and utility class for Wii U paths // optimized to be allocation-free for common path lengths class FSCPath { - struct PathNode + struct PathNode { PathNode(uint16 offset, uint16 len) : offset(offset), len(len) {}; @@ -383,7 +42,7 @@ public: m_isAbsolute = true; path.remove_prefix(1); // skip any additional leading slashes - while(!path.empty() && isSlash(path.front())) + while (!path.empty() && isSlash(path.front())) path.remove_prefix(1); } // parse nodes @@ -427,17 +86,15 @@ public: return std::basic_string_view(m_names.data() + m_nodes[index].offset, m_nodes[index].len); } - bool MatchNode(sint32 index, std::string_view name) const + // returns true if the node names match according to FSA case-insensitivity rules + static bool MatchNodeName(std::string_view name1, std::string_view name2) { - if (index < 0 || index >= (sint32)m_nodes.size()) + if (name1.size() != name2.size()) return false; - auto nodeName = GetNodeName(index); - if (nodeName.size() != name.size()) - return false; - for (size_t i = 0; i < nodeName.size(); i++) + for (size_t i = 0; i < name1.size(); i++) { - char c1 = nodeName[i]; - char c2 = name[i]; + char c1 = name1[i]; + char c2 = name2[i]; if (c1 >= 'A' && c1 <= 'Z') c1 += ('a' - 'A'); if (c2 >= 'A' && c2 <= 'Z') @@ -447,6 +104,165 @@ public: } return true; } + + bool MatchNodeName(sint32 index, std::string_view name) const + { + if (index < 0 || index >= (sint32)m_nodes.size()) + return false; + auto nodeName = GetNodeName(index); + return MatchNodeName(nodeName, name); + } +}; + +template +class FSAFileTree +{ +public: + +private: + + enum NODETYPE : uint8 + { + NODETYPE_DIRECTORY, + NODETYPE_FILE, + }; + + struct node_t + { + std::string name; + std::vector subnodes; + F* custom; + NODETYPE type; + }; + + node_t* getByNodePath(FSCPath& p, sint32 numNodes, bool createAsDirectories) + { + node_t* currentNode = &rootNode; + for (sint32 i = 0; i < numNodes; i++) + { + // find subnode by path + node_t* foundSubnode = getSubnode(currentNode, p.GetNodeName(i)); + if (foundSubnode == nullptr) + { + // no subnode found -> create new directory node (if requested) + if (createAsDirectories == false) + return nullptr; // path not found + currentNode = newNode(currentNode, NODETYPE_DIRECTORY, p.GetNodeName(i)); + } + else + { + currentNode = foundSubnode; + } + } + return currentNode; + } + + node_t* getSubnode(node_t* parentNode, std::string_view name) + { + for (auto& sn : parentNode->subnodes) + { + if (FSCPath::MatchNodeName(sn->name, name)) + return sn; + } + return nullptr; + } + + node_t* newNode(node_t* parentNode, NODETYPE type, std::string_view name) + { + node_t* newNode = new node_t; + newNode->name.assign(name); + newNode->type = type; + newNode->custom = nullptr; + parentNode->subnodes.push_back(newNode); + return newNode; + } + +public: + FSAFileTree() + { + rootNode.type = NODETYPE_DIRECTORY; + } + + bool addFile(std::string_view path, F* custom) + { + FSCPath p(path); + if (p.GetNodeCount() == 0) + return false; + node_t* directoryNode = getByNodePath(p, p.GetNodeCount() - 1, true); + // check if a node with same name already exists + if (getSubnode(directoryNode, p.GetNodeName(p.GetNodeCount() - 1)) != nullptr) + return false; // node already exists + // add file node + node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.GetNodeName(p.GetNodeCount() - 1)); + fileNode->custom = custom; + return true; + } + + bool getFile(std::string_view path, F* &custom) + { + FSCPath p(path); + if (p.GetNodeCount() == 0) + return false; + node_t* node = getByNodePath(p, p.GetNodeCount(), false); + if (node == nullptr) + return false; + if (node->type != NODETYPE_FILE) + return false; + custom = node->custom; + return true; + } + + bool removeFile(std::string_view path) + { + FSCPath p(path); + if (p.GetNodeCount() == 0) + return false; + node_t* directoryNode = getByNodePath(p, p.GetNodeCount() - 1, false); + if (directoryNode == nullptr) + return false; + // find node + node_t* fileNode = getSubnode(directoryNode, p.GetNodeName(p.GetNodeCount() - 1)); + if (fileNode == nullptr) + return false; + if (fileNode->type != NODETYPE_FILE) + return false; + if (fileNode->subnodes.empty() == false) + { + // files shouldn't have subnodes + assert(false); + } + // remove node from parent + directoryNode->subnodes.erase(std::remove(directoryNode->subnodes.begin(), directoryNode->subnodes.end(), fileNode), directoryNode->subnodes.end()); + // delete node + delete fileNode; + return true; + } + + template + bool listDirectory(std::string_view path, TFunc fn) + { + FSCPath p(path); + node_t* node = getByNodePath(p, p.GetNodeCount(), false); + if (node == nullptr) + return false; + if (node->type != NODETYPE_DIRECTORY) + return false; + for (auto& it : node->subnodes) + { + if (it->type == NODETYPE_DIRECTORY) + { + fn(it->name, true, it->custom); + } + else if (it->type == NODETYPE_FILE) + { + fn(it->name, false, it->custom); + } + } + return true; + } + +private: + node_t rootNode; }; static void FSTPathUnitTest() @@ -454,28 +270,28 @@ static void FSTPathUnitTest() // test 1 FSCPath p1("/vol/content"); cemu_assert_debug(p1.GetNodeCount() == 2); - cemu_assert_debug(p1.MatchNode(0, "tst") == false); - cemu_assert_debug(p1.MatchNode(0, "vol")); - cemu_assert_debug(p1.MatchNode(1, "CONTENT")); + cemu_assert_debug(p1.MatchNodeName(0, "tst") == false); + cemu_assert_debug(p1.MatchNodeName(0, "vol")); + cemu_assert_debug(p1.MatchNodeName(1, "CONTENT")); // test 2 FSCPath p2("/vol/content/"); cemu_assert_debug(p2.GetNodeCount() == 2); - cemu_assert_debug(p2.MatchNode(0, "vol")); - cemu_assert_debug(p2.MatchNode(1, "content")); + cemu_assert_debug(p2.MatchNodeName(0, "vol")); + cemu_assert_debug(p2.MatchNodeName(1, "content")); // test 3 FSCPath p3("/vol//content/\\/"); cemu_assert_debug(p3.GetNodeCount() == 2); - cemu_assert_debug(p3.MatchNode(0, "vol")); - cemu_assert_debug(p3.MatchNode(1, "content")); + cemu_assert_debug(p3.MatchNodeName(0, "vol")); + cemu_assert_debug(p3.MatchNodeName(1, "content")); // test 4 FSCPath p4("vol/content/"); cemu_assert_debug(p4.GetNodeCount() == 2); // test 5 FSCPath p5("/vol/content/test.bin"); cemu_assert_debug(p5.GetNodeCount() == 3); - cemu_assert_debug(p5.MatchNode(0, "vol")); - cemu_assert_debug(p5.MatchNode(1, "content")); - cemu_assert_debug(p5.MatchNode(2, "TEST.BIN")); + cemu_assert_debug(p5.MatchNodeName(0, "vol")); + cemu_assert_debug(p5.MatchNodeName(1, "content")); + cemu_assert_debug(p5.MatchNodeName(2, "TEST.BIN")); // test 6 - empty paths FSCPath p6(""); cemu_assert_debug(p6.GetNodeCount() == 0); diff --git a/src/Cafe/Filesystem/fsc.cpp b/src/Cafe/Filesystem/fsc.cpp index bab2d19e..d7d9971f 100644 --- a/src/Cafe/Filesystem/fsc.cpp +++ b/src/Cafe/Filesystem/fsc.cpp @@ -1,14 +1,15 @@ #include "Cafe/Filesystem/fsc.h" +#include "Cafe/Filesystem/FST/fstUtil.h" struct FSCMountPathNode { std::string path; std::vector subnodes; FSCMountPathNode* parent; - // device target and path (if list_subnodes is nullptr) + // device target and path (if subnodes is empty) fscDeviceC* device{ nullptr }; void* ctx{ nullptr }; - std::wstring targetPath; + std::string deviceTargetPath; // the destination base path for the device, utf8 // priority sint32 priority{}; @@ -24,7 +25,7 @@ struct FSCMountPathNode } }; -// compare two file or directory names using FS rules +// compare two file or directory names using FSA rules bool FSA_CompareNodeName(std::string_view a, std::string_view b) { if (a.size() != b.size()) @@ -74,25 +75,25 @@ void fsc_reset() * /vol/content/data -> Map to HostFS * If overlapping paths with different priority are created, then the higher priority one will be checked first */ -FSCMountPathNode* fsc_createMountPath(CoreinitFSParsedPath* parsedMountPath, sint32 priority) +FSCMountPathNode* fsc_createMountPath(const FSCPath& mountPath, sint32 priority) { cemu_assert(priority >= 0 && priority < FSC_PRIORITY_COUNT); fscEnter(); FSCMountPathNode* nodeParent = s_fscRootNodePerPrio[priority]; - for(sint32 i=0; inumNodes; i++) + for (size_t i=0; i< mountPath.GetNodeCount(); i++) { // search for subdirectory FSCMountPathNode* nodeSub = nullptr; // set if we found a subnode with a matching name, else this is used to store the new nodes - for(auto& nodeItr : nodeParent->subnodes) + for (auto& nodeItr : nodeParent->subnodes) { - if( coreinitFS_checkNodeName(parsedMountPath, i, nodeItr->path.c_str()) ) + if (mountPath.MatchNodeName(i, nodeItr->path)) { // subnode found nodeSub = nodeItr; break; } } - if( nodeSub ) + if (nodeSub) { // traverse subnode nodeParent = nodeSub; @@ -100,10 +101,10 @@ FSCMountPathNode* fsc_createMountPath(CoreinitFSParsedPath* parsedMountPath, sin } // no matching subnode, add new entry nodeSub = new FSCMountPathNode(nodeParent); - nodeSub->path = coreinitFS_getNodeName(parsedMountPath, i); + nodeSub->path = mountPath.GetNodeName(i); nodeSub->priority = priority; nodeParent->subnodes.emplace_back(nodeSub); - if( i == (parsedMountPath->numNodes-1) ) + if (i == (mountPath.GetNodeCount() - 1)) { // last node fscLeave(); @@ -114,47 +115,44 @@ FSCMountPathNode* fsc_createMountPath(CoreinitFSParsedPath* parsedMountPath, sin } // path is empty or already mounted fscLeave(); - if (parsedMountPath->numNodes == 0) + if (mountPath.GetNodeCount() == 0) return nodeParent; return nullptr; } -// Map a virtual FSC directory to a device and device directory -sint32 fsc_mount(const char* mountPath, const wchar_t* _targetPath, fscDeviceC* fscDevice, void* ctx, sint32 priority) +// Map a virtual FSC directory to a device. targetPath points to the destination base directory within the device +sint32 fsc_mount(std::string_view mountPath, std::string_view targetPath, fscDeviceC* fscDevice, void* ctx, sint32 priority) { - cemu_assert(fscDevice); // device must not be nullptr + cemu_assert(fscDevice); + std::string mountPathTmp(mountPath); // make sure the target path ends with a slash - std::wstring targetPath(_targetPath); - if (!targetPath.empty() && (targetPath.back() != '/' && targetPath.back() != '\\')) - targetPath.push_back('/'); + std::string targetPathWithSlash(targetPath); + if (!targetPathWithSlash.empty() && (targetPathWithSlash.back() != '/' && targetPathWithSlash.back() != '\\')) + targetPathWithSlash.push_back('/'); - // parse mount path - CoreinitFSParsedPath parsedMountPath; - coreinitFS_parsePath(&parsedMountPath, mountPath); + FSCPath parsedMountPath(mountPathTmp); // register path fscEnter(); - FSCMountPathNode* node = fsc_createMountPath(&parsedMountPath, priority); + FSCMountPathNode* node = fsc_createMountPath(parsedMountPath, priority); if( !node ) { // path empty, invalid or already used - cemuLog_log(LogType::Force, "fsc_mount failed (virtual path: %s)", mountPath); + cemuLog_log(LogType::Force, "fsc_mount failed (virtual path: {})", mountPath); fscLeave(); return FSC_STATUS_INVALID_PATH; } node->device = fscDevice; node->ctx = ctx; - node->targetPath = targetPath; + node->deviceTargetPath = targetPathWithSlash; fscLeave(); return FSC_STATUS_OK; } -bool fsc_unmount(const char* mountPath, sint32 priority) +bool fsc_unmount(std::string_view mountPath, sint32 priority) { - CoreinitFSParsedPath parsedMountPath; - coreinitFS_parsePath(&parsedMountPath, mountPath); - + std::string _tmp(mountPath); fscEnter(); - FSCMountPathNode* mountPathNode = fsc_lookupPathVirtualNode(mountPath, priority); + FSCMountPathNode* mountPathNode = fsc_lookupPathVirtualNode(_tmp.c_str(), priority); if (!mountPathNode) { fscLeave(); @@ -185,21 +183,19 @@ void fsc_unmountAll() } // lookup virtual path and find mounted device and relative device directory -bool fsc_lookupPath(const char* path, std::wstring& devicePathOut, fscDeviceC** fscDeviceOut, void** ctxOut, sint32 priority = FSC_PRIORITY_BASE) +bool fsc_lookupPath(const char* path, std::string& devicePathOut, fscDeviceC** fscDeviceOut, void** ctxOut, sint32 priority = FSC_PRIORITY_BASE) { - // parse path - CoreinitFSParsedPath parsedPath; - coreinitFS_parsePath(&parsedPath, path); + FSCPath parsedPath(path); FSCMountPathNode* nodeParent = s_fscRootNodePerPrio[priority]; - sint32 i; + size_t i; fscEnter(); - for (i = 0; i < parsedPath.numNodes; i++) + for (i = 0; i < parsedPath.GetNodeCount(); i++) { // search for subdirectory FSCMountPathNode* nodeSub = nullptr; for(auto& nodeItr : nodeParent->subnodes) - { - if (coreinitFS_checkNodeName(&parsedPath, i, nodeItr->path.c_str())) + { + if (parsedPath.MatchNodeName(i, nodeItr->path)) { nodeSub = nodeItr; break; @@ -213,17 +209,17 @@ bool fsc_lookupPath(const char* path, std::wstring& devicePathOut, fscDeviceC** // no matching subnode break; } - // find deepest device mount point + // if the found node is not a device mount point, then travel back towards the root until we find one while (nodeParent) { if (nodeParent->device) { - devicePathOut = nodeParent->targetPath; - for (sint32 f = i; f < parsedPath.numNodes; f++) + devicePathOut = nodeParent->deviceTargetPath; + for (size_t f = i; f < parsedPath.GetNodeCount(); f++) { - const char* nodeName = coreinitFS_getNodeName(&parsedPath, f); - devicePathOut.append(boost::nowide::widen(nodeName)); - if (f < (parsedPath.numNodes - 1)) + auto nodeName = parsedPath.GetNodeName(f); + devicePathOut.append(nodeName); + if (f < (parsedPath.GetNodeCount() - 1)) devicePathOut.push_back('/'); } *fscDeviceOut = nodeParent->device; @@ -241,19 +237,16 @@ bool fsc_lookupPath(const char* path, std::wstring& devicePathOut, fscDeviceC** // lookup path and find virtual device node FSCMountPathNode* fsc_lookupPathVirtualNode(const char* path, sint32 priority) { - // parse path - CoreinitFSParsedPath parsedPath; - coreinitFS_parsePath(&parsedPath, path); + FSCPath parsedPath(path); FSCMountPathNode* nodeCurrentDir = s_fscRootNodePerPrio[priority]; - sint32 i; fscEnter(); - for (i = 0; i < parsedPath.numNodes; i++) + for (size_t i = 0; i < parsedPath.GetNodeCount(); i++) { // search for subdirectory FSCMountPathNode* nodeSub = nullptr; for (auto& nodeItr : nodeCurrentDir->subnodes) { - if (coreinitFS_checkNodeName(&parsedPath, i, nodeItr->path.c_str())) + if (parsedPath.MatchNodeName(i, nodeItr->path)) { nodeSub = nodeItr; break; @@ -360,11 +353,9 @@ private: FSCVirtualFile* fsc_open(const char* path, FSC_ACCESS_FLAG accessFlags, sint32* fscStatus, sint32 maxPriority) { cemu_assert_debug(HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE) || HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR)); // must open either file or directory - FSCVirtualFile* dirList[FSC_PRIORITY_COUNT]; uint8 dirListCount = 0; - - std::wstring devicePath; + std::string devicePath; fscDeviceC* fscDevice = NULL; *fscStatus = FSC_STATUS_UNDEFINED; void* ctx; @@ -455,7 +446,7 @@ bool fsc_createDir(char* path, sint32* fscStatus) fscDeviceC* fscDevice = NULL; *fscStatus = FSC_STATUS_UNDEFINED; void* ctx; - std::wstring devicePath; + std::string devicePath; fscEnter(); if( fsc_lookupPath(path, devicePath, &fscDevice, &ctx) ) { @@ -472,8 +463,8 @@ bool fsc_createDir(char* path, sint32* fscStatus) */ bool fsc_rename(char* srcPath, char* dstPath, sint32* fscStatus) { - std::wstring srcDevicePath; - std::wstring dstDevicePath; + std::string srcDevicePath; + std::string dstDevicePath; void* srcCtx; void* dstCtx; fscDeviceC* fscSrcDevice = NULL; @@ -492,7 +483,7 @@ bool fsc_rename(char* srcPath, char* dstPath, sint32* fscStatus) */ bool fsc_remove(char* path, sint32* fscStatus) { - std::wstring devicePath; + std::string devicePath; fscDeviceC* fscDevice = NULL; *fscStatus = FSC_STATUS_UNDEFINED; void* ctx; @@ -691,7 +682,7 @@ bool fsc_doesFileExist(const char* path, sint32 maxPriority) return true; } -// helper function to check if a folder exists +// helper function to check if a directory exists bool fsc_doesDirectoryExist(const char* path, sint32 maxPriority) { fscDeviceC* fscDevice = nullptr; @@ -708,93 +699,7 @@ bool fsc_doesDirectoryExist(const char* path, sint32 maxPriority) return true; } - -void coreinitFS_parsePath(CoreinitFSParsedPath* parsedPath, const char* path) -{ - // if the path starts with a '/', skip it - if (*path == '/') - path++; - // init parsedPath struct - memset(parsedPath, 0x00, sizeof(CoreinitFSParsedPath)); - // init parsed path data - size_t pathLength = std::min((size_t)640, strlen(path)); - memcpy(parsedPath->pathData, path, pathLength); - // start parsing - sint32 offset = 0; - sint32 startOffset = 0; - if (offset < pathLength) - { - parsedPath->nodeOffset[parsedPath->numNodes] = offset; - parsedPath->numNodes++; - } - while (offset < pathLength) - { - if (parsedPath->pathData[offset] == '/' || parsedPath->pathData[offset] == '\\') - { - parsedPath->pathData[offset] = '\0'; - offset++; - // double slashes are ignored and instead are handled like a single slash - if (parsedPath->pathData[offset] == '/' || parsedPath->pathData[offset] == '\\') - { - // if we're in the beginning and having a \\ it's a network path - if (offset != 1) - { - parsedPath->pathData[offset] = '\0'; - offset++; - } - } - // start new node - if (parsedPath->numNodes < FSC_PARSED_PATH_NODES_MAX) - { - if (offset < pathLength) - { - parsedPath->nodeOffset[parsedPath->numNodes] = offset; - parsedPath->numNodes++; - } - } - continue; - } - offset++; - } - // handle special nodes like '.' or '..' - sint32 nodeIndex = 0; - while (nodeIndex < parsedPath->numNodes) - { - if (coreinitFS_checkNodeName(parsedPath, nodeIndex, "..")) - cemu_assert_suspicious(); // how does Cafe OS handle .. ? - else if (coreinitFS_checkNodeName(parsedPath, nodeIndex, ".")) - { - // remove this node and shift back all following nodes by 1 - parsedPath->numNodes--; - for (sint32 i = nodeIndex; i < parsedPath->numNodes; i++) - { - parsedPath->nodeOffset[i] = parsedPath->nodeOffset[i + 1]; - } - // continue without increasing nodeIndex - continue; - } - nodeIndex++; - } -} - -bool coreinitFS_checkNodeName(CoreinitFSParsedPath* parsedPath, sint32 index, const char* name) -{ - if (index < 0 || index >= parsedPath->numNodes) - return false; - char* nodeName = parsedPath->pathData + parsedPath->nodeOffset[index]; - if (boost::iequals(nodeName, name)) - return true; - return false; -} - -char* coreinitFS_getNodeName(CoreinitFSParsedPath* parsedPath, sint32 index) -{ - if (index < 0 || index >= parsedPath->numNodes) - return nullptr; - return parsedPath->pathData + parsedPath->nodeOffset[index]; -} - -// Initialize Cemu's virtual filesystem +// initialize Cemu's virtual filesystem void fsc_init() { fsc_reset(); diff --git a/src/Cafe/Filesystem/fsc.h b/src/Cafe/Filesystem/fsc.h index 972d5d0a..9420d69d 100644 --- a/src/Cafe/Filesystem/fsc.h +++ b/src/Cafe/Filesystem/fsc.h @@ -57,25 +57,25 @@ struct FSCDirEntry class fscDeviceC { public: - virtual FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) + virtual FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) { cemu_assert_unimplemented(); return nullptr; } - virtual bool fscDeviceCreateDir(std::wstring_view path, void* ctx, sint32* fscStatus) + virtual bool fscDeviceCreateDir(std::string_view path, void* ctx, sint32* fscStatus) { cemu_assert_unimplemented(); return false; } - virtual bool fscDeviceRemoveFileOrDir(std::wstring_view path, void* ctx, sint32* fscStatus) + virtual bool fscDeviceRemoveFileOrDir(std::string_view path, void* ctx, sint32* fscStatus) { cemu_assert_unimplemented(); return false; } - virtual bool fscDeviceRename(std::wstring_view srcPath, std::wstring_view dstPath, void* ctx, sint32* fscStatus) + virtual bool fscDeviceRename(std::string_view srcPath, std::string_view dstPath, void* ctx, sint32* fscStatus) { cemu_assert_unimplemented(); return false; @@ -161,8 +161,8 @@ struct FSCVirtualFile #define FSC_PRIORITY_COUNT (4) void fsc_init(); -sint32 fsc_mount(const char* mountPath, const wchar_t* targetPath, fscDeviceC* fscDevice, void* ctx, sint32 priority=0); -bool fsc_unmount(const char* mountPath, sint32 priority); +sint32 fsc_mount(std::string_view mountPath, std::string_view targetPath, fscDeviceC* fscDevice, void* ctx, sint32 priority=0); +bool fsc_unmount(std::string_view mountPath, sint32 priority); void fsc_unmountAll(); FSCVirtualFile* fsc_open(const char* path, FSC_ACCESS_FLAG accessFlags, sint32* fscStatus, sint32 maxPriority=FSC_PRIORITY_MAX); @@ -188,32 +188,15 @@ bool fsc_doesFileExist(const char* path, sint32 maxPriority = FSC_PRIORITY_MAX); bool fsc_doesDirectoryExist(const char* path, sint32 maxPriority = FSC_PRIORITY_MAX); // wud device -bool FSCDeviceWUD_Mount(const char* mountPath, std::string_view destinationBaseDir, class FSTVolume* mountedVolume, sint32 priority); +bool FSCDeviceWUD_Mount(std::string_view mountPath, std::string_view destinationBaseDir, class FSTVolume* mountedVolume, sint32 priority); // wua device -bool FSCDeviceWUA_Mount(const char* mountPath, std::string_view destinationBaseDir, class ZArchiveReader* archive, sint32 priority); +bool FSCDeviceWUA_Mount(std::string_view mountPath, std::string_view destinationBaseDir, class ZArchiveReader* archive, sint32 priority); // hostFS device void fscDeviceHostFS_mapBaseDirectories_deprecated(); -bool FSCDeviceHostFS_Mount(const char* mountPath, const wchar_t* hostFSPath, sint32 priority); +bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority); // redirect device void fscDeviceRedirect_map(); void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority); - - -// Old path parser helper functions -// Replace with FSCPath - -#define FSC_PARSED_PATH_NODES_MAX (32) - -struct CoreinitFSParsedPath -{ - char pathData[640 + 1]; - uint16 nodeOffset[FSC_PARSED_PATH_NODES_MAX]; - sint32 numNodes; -}; - -void coreinitFS_parsePath(CoreinitFSParsedPath* parsedPath, const char* path); -bool coreinitFS_checkNodeName(CoreinitFSParsedPath* parsedPath, sint32 index, const char* name); -char* coreinitFS_getNodeName(CoreinitFSParsedPath* parsedPath, sint32 index); diff --git a/src/Cafe/Filesystem/fscDeviceHostFS.cpp b/src/Cafe/Filesystem/fscDeviceHostFS.cpp index cb54cacf..da28700d 100644 --- a/src/Cafe/Filesystem/fscDeviceHostFS.cpp +++ b/src/Cafe/Filesystem/fscDeviceHostFS.cpp @@ -127,7 +127,7 @@ bool FSCVirtualFile_Host::fscDirNext(FSCDirEntry* dirEntry) m_dirIterator.reset(new fs::directory_iterator(*m_path)); if (!m_dirIterator) { - cemuLog_force("Failed to iterate directory: {}", _utf8Wrapper(m_path->generic_u8string())); + cemuLog_force("Failed to iterate directory: {}", _pathToUtf8(*m_path)); return false; } } @@ -175,14 +175,14 @@ FSCVirtualFile* FSCVirtualFile_Host::OpenFile(const fs::path& path, FSC_ACCESS_F cemu_assert_debug(writeAccessRequested); fs = FileStream::createFile2(path); if (!fs) - cemuLog_force("FSC: File create failed for {}", _utf8Wrapper(path)); + cemuLog_force("FSC: File create failed for {}", _pathToUtf8(path)); } } else if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::FILE_ALWAYS_CREATE)) { fs = FileStream::createFile2(path); if (!fs) - cemuLog_force("FSC: File create failed for {}", _utf8Wrapper(path)); + cemuLog_force("FSC: File create failed for {}", _pathToUtf8(path)); } else { @@ -221,36 +221,36 @@ FSCVirtualFile* FSCVirtualFile_Host::OpenFile(const fs::path& path, FSC_ACCESS_F class fscDeviceHostFSC : public fscDeviceC { public: - FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override + FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override { *fscStatus = FSC_STATUS_OK; - FSCVirtualFile* vf = FSCVirtualFile_Host::OpenFile(path, accessFlags, *fscStatus); + FSCVirtualFile* vf = FSCVirtualFile_Host::OpenFile(_utf8ToPath(path), accessFlags, *fscStatus); cemu_assert_debug((bool)vf == (*fscStatus == FSC_STATUS_OK)); return vf; } - bool fscDeviceCreateDir(std::wstring_view path, void* ctx, sint32* fscStatus) override + bool fscDeviceCreateDir(std::string_view path, void* ctx, sint32* fscStatus) override { - fs::path dirPath(path); - if (fs::exists(path)) + fs::path dirPath = _utf8ToPath(path); + if (fs::exists(dirPath)) { if (!fs::is_directory(dirPath)) - cemuLog_force("CreateDir: {} already exists but is not a directory", _utf8Wrapper(dirPath)); + cemuLog_force("CreateDir: {} already exists but is not a directory", path); *fscStatus = FSC_STATUS_ALREADY_EXISTS; return false; } std::error_code ec; bool r = fs::create_directories(dirPath, ec); - if(!r) - cemuLog_force("CreateDir: Failed to create {}", _utf8Wrapper(dirPath)); + if (!r) + cemuLog_force("CreateDir: Failed to create {}", path); *fscStatus = FSC_STATUS_OK; return true; } - bool fscDeviceRemoveFileOrDir(std::wstring_view path, void* ctx, sint32* fscStatus) override + bool fscDeviceRemoveFileOrDir(std::string_view path, void* ctx, sint32* fscStatus) override { *fscStatus = FSC_STATUS_OK; - fs::path _path(path); + fs::path _path = _utf8ToPath(path); std::error_code ec; if (!fs::exists(_path, ec)) { @@ -266,11 +266,11 @@ public: return true; } - bool fscDeviceRename(std::wstring_view srcPath, std::wstring_view dstPath, void* ctx, sint32* fscStatus) override + bool fscDeviceRename(std::string_view srcPath, std::string_view dstPath, void* ctx, sint32* fscStatus) override { *fscStatus = FSC_STATUS_OK; - fs::path _srcPath(srcPath); - fs::path _dstPath(dstPath); + fs::path _srcPath = _utf8ToPath(srcPath); + fs::path _dstPath = _utf8ToPath(dstPath); std::error_code ec; if (!fs::exists(_srcPath, ec)) { @@ -293,14 +293,11 @@ public: void fscDeviceHostFS_mapBaseDirectories_deprecated() { const auto mlc = ActiveSettings::GetMlcPath(); - fsc_mount("/cemuBossStorage/", (mlc / "usr/boss/").generic_wstring().c_str(), &fscDeviceHostFSC::instance(), NULL, FSC_PRIORITY_BASE); - fsc_mount("/vol/storage_mlc01/", (mlc / "").generic_wstring().c_str(), &fscDeviceHostFSC::instance(), NULL, FSC_PRIORITY_BASE); + fsc_mount("/cemuBossStorage/", _pathToUtf8(mlc / "usr/boss/"), &fscDeviceHostFSC::instance(), NULL, FSC_PRIORITY_BASE); + fsc_mount("/vol/storage_mlc01/", _pathToUtf8(mlc / ""), &fscDeviceHostFSC::instance(), NULL, FSC_PRIORITY_BASE); } -bool FSCDeviceHostFS_Mount(const char* mountPath, const wchar_t* hostFSPath, sint32 priority) +bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority) { - std::wstring hostTargetPath(hostFSPath); - if (!hostTargetPath.empty() && (hostTargetPath.back() != '/' && hostTargetPath.back() != '\\')) - hostTargetPath.push_back('/'); - return fsc_mount(mountPath, hostTargetPath.c_str(), &fscDeviceHostFSC::instance(), nullptr, priority) == FSC_STATUS_OK; + return fsc_mount(mountPath, hostTargetPath, &fscDeviceHostFSC::instance(), nullptr, priority) == FSC_STATUS_OK; } \ No newline at end of file diff --git a/src/Cafe/Filesystem/fscDeviceRedirect.cpp b/src/Cafe/Filesystem/fscDeviceRedirect.cpp index 5d5edb9e..d25bff86 100644 --- a/src/Cafe/Filesystem/fscDeviceRedirect.cpp +++ b/src/Cafe/Filesystem/fscDeviceRedirect.cpp @@ -9,31 +9,30 @@ struct RedirectEntry sint32 priority; }; -FileTree redirectTree; +FSAFileTree redirectTree; void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority) { - std::wstring virtualSourcePathW = boost::nowide::widen(std::string(virtualSourcePath)); // check if source already has a redirection RedirectEntry* existingEntry; - if (redirectTree.getFile(virtualSourcePathW, existingEntry)) + if (redirectTree.getFile(virtualSourcePath, existingEntry)) { if (existingEntry->priority >= priority) return; // dont replace entries with equal or higher priority // unregister existing entry - redirectTree.removeFile(virtualSourcePathW.c_str()); + redirectTree.removeFile(virtualSourcePath); delete existingEntry; } RedirectEntry* entry = new RedirectEntry(targetFilePath, priority); - redirectTree.addFile(virtualSourcePathW.c_str(), entry); + redirectTree.addFile(virtualSourcePath, entry); } class fscDeviceTypeRedirect : public fscDeviceC { - FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view pathW, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override + FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override { RedirectEntry* redirectionEntry; - if (redirectTree.getFile(pathW, redirectionEntry)) + if (redirectTree.getFile(path, redirectionEntry)) return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus); return nullptr; } @@ -52,6 +51,6 @@ void fscDeviceRedirect_map() { if (_redirectMapped) return; - fsc_mount("/", L"/", &fscDeviceTypeRedirect::instance(), nullptr, FSC_PRIORITY_REDIRECT); + fsc_mount("/", "/", &fscDeviceTypeRedirect::instance(), nullptr, FSC_PRIORITY_REDIRECT); _redirectMapped = true; } diff --git a/src/Cafe/Filesystem/fscDeviceWua.cpp b/src/Cafe/Filesystem/fscDeviceWua.cpp index 96eb920a..f9014bdb 100644 --- a/src/Cafe/Filesystem/fscDeviceWua.cpp +++ b/src/Cafe/Filesystem/fscDeviceWua.cpp @@ -119,14 +119,12 @@ private: class fscDeviceWUAC : public fscDeviceC { - FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override + FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override { ZArchiveReader* archive = (ZArchiveReader*)ctx; cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to WUA is not supported - std::string pathU8 = boost::nowide::narrow(path.data(), path.size()); - - ZArchiveNodeHandle fileHandle = archive->LookUp(pathU8, true, true); + ZArchiveNodeHandle fileHandle = archive->LookUp(path, true, true); if (fileHandle == ZARCHIVE_INVALID_NODE) { *fscStatus = FSC_STATUS_FILE_NOT_FOUND; @@ -169,10 +167,7 @@ public: } }; -bool FSCDeviceWUA_Mount(const char* mountPath, std::string_view destinationBaseDir, ZArchiveReader* archive, sint32 priority) +bool FSCDeviceWUA_Mount(std::string_view mountPath, std::string_view destinationBaseDir, ZArchiveReader* archive, sint32 priority) { - std::wstring hostTargetPath(boost::nowide::widen(destinationBaseDir.data(), destinationBaseDir.size())); - if (!hostTargetPath.empty() && (hostTargetPath.back() != '/' && hostTargetPath.back() != '\\')) - hostTargetPath.push_back('/'); - return fsc_mount(mountPath, hostTargetPath.c_str(), &fscDeviceWUAC::instance(), archive, priority) == FSC_STATUS_OK; + return fsc_mount(mountPath, destinationBaseDir, &fscDeviceWUAC::instance(), archive, priority) == FSC_STATUS_OK; } \ No newline at end of file diff --git a/src/Cafe/Filesystem/fscDeviceWud.cpp b/src/Cafe/Filesystem/fscDeviceWud.cpp index 10054bad..bf43bf3e 100644 --- a/src/Cafe/Filesystem/fscDeviceWud.cpp +++ b/src/Cafe/Filesystem/fscDeviceWud.cpp @@ -120,16 +120,15 @@ private: class fscDeviceWUDC : public fscDeviceC { - FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override + FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override { FSTVolume* mountedVolume = (FSTVolume*)ctx; cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to FST is never allowed - std::string pathU8 = boost::nowide::narrow(path.data(), path.size()); if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE)) { FSTFileHandle fstFileHandle; - if (mountedVolume->OpenFile(pathU8, fstFileHandle, true)) + if (mountedVolume->OpenFile(path, fstFileHandle, true)) { *fscStatus = FSC_STATUS_OK; return new FSCDeviceWudFileCtx(mountedVolume, fstFileHandle); @@ -138,7 +137,7 @@ class fscDeviceWUDC : public fscDeviceC if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR)) { FSTDirectoryIterator dirIterator; - if (mountedVolume->OpenDirectoryIterator(pathU8, dirIterator)) + if (mountedVolume->OpenDirectoryIterator(path, dirIterator)) { *fscStatus = FSC_STATUS_OK; return new FSCDeviceWudFileCtx(mountedVolume, dirIterator); @@ -157,10 +156,7 @@ public: } }; -bool FSCDeviceWUD_Mount(const char* mountPath, std::string_view destinationBaseDir, FSTVolume* mountedVolume, sint32 priority) +bool FSCDeviceWUD_Mount(std::string_view mountPath, std::string_view destinationBaseDir, FSTVolume* mountedVolume, sint32 priority) { - std::wstring hostTargetPath(boost::nowide::widen(destinationBaseDir.data(), destinationBaseDir.size())); - if (!hostTargetPath.empty() && (hostTargetPath.back() != '/' && hostTargetPath.back() != '\\')) - hostTargetPath.push_back('/'); - return fsc_mount(mountPath, hostTargetPath.c_str(), &fscDeviceWUDC::instance(), mountedVolume, priority) == FSC_STATUS_OK; + return fsc_mount(mountPath, destinationBaseDir, &fscDeviceWUDC::instance(), mountedVolume, priority) == FSC_STATUS_OK; } \ No newline at end of file diff --git a/src/Cafe/GraphicPack/GraphicPack2.cpp b/src/Cafe/GraphicPack/GraphicPack2.cpp index 41e33a19..808536d5 100644 --- a/src/Cafe/GraphicPack/GraphicPack2.cpp +++ b/src/Cafe/GraphicPack/GraphicPack2.cpp @@ -31,12 +31,12 @@ void GraphicPack2::LoadGraphicPack(fs::path graphicPackPath) if (!iniParser.NextSection()) { - cemuLog_force("{}: Does not contain any sections", _utf8Wrapper(rulesPath)); + cemuLog_force("{}: Does not contain any sections", _pathToUtf8(rulesPath)); return; } if (!boost::iequals(iniParser.GetCurrentSectionName(), "Definition")) { - cemuLog_force("{}: [Definition] must be the first section", _utf8Wrapper(rulesPath)); + cemuLog_force("{}: [Definition] must be the first section", _pathToUtf8(rulesPath)); return; } @@ -47,7 +47,7 @@ void GraphicPack2::LoadGraphicPack(fs::path graphicPackPath) auto [ptr, ec] = std::from_chars(option_version->data(), option_version->data() + option_version->size(), versionNum); if (ec != std::errc{}) { - cemuLog_force("{}: Unable to parse version", _utf8Wrapper(rulesPath)); + cemuLog_force("{}: Unable to parse version", _pathToUtf8(rulesPath)); return; } @@ -57,7 +57,7 @@ void GraphicPack2::LoadGraphicPack(fs::path graphicPackPath) return; } } - cemuLog_force("{}: Outdated graphic pack", _utf8Wrapper(rulesPath)); + cemuLog_force("{}: Outdated graphic pack", _pathToUtf8(rulesPath)); } void GraphicPack2::LoadAll() diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp index 3d13fdbe..1598429f 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp @@ -109,7 +109,7 @@ namespace coreinit std::error_code ec; const auto path = ActiveSettings::GetPath("sdcard/"); fs::create_directories(path, ec); - FSCDeviceHostFS_Mount("/vol/external01", path.generic_wstring().c_str() , FSC_PRIORITY_BASE); + FSCDeviceHostFS_Mount("/vol/external01", _pathToUtf8(path), FSC_PRIORITY_BASE); _sdCard01Mounted = true; } @@ -142,7 +142,7 @@ namespace coreinit std::error_code ec; const auto path = ActiveSettings::GetPath("sdcard/"); fs::create_directories(path, ec); - if (!FSCDeviceHostFS_Mount(mountPathOut, path.generic_wstring().c_str(), FSC_PRIORITY_BASE)) + if (!FSCDeviceHostFS_Mount(mountPathOut, _pathToUtf8(path), FSC_PRIORITY_BASE)) return FS_RESULT::ERR_PLACEHOLDER; _sdCard01Mounted = true; } @@ -150,7 +150,7 @@ namespace coreinit if (_mlc01Mounted) return FS_RESULT::ERR_PLACEHOLDER; - if (!FSCDeviceHostFS_Mount(mountPathOut, ActiveSettings::GetMlcPath().generic_wstring().c_str(), FSC_PRIORITY_BASE)) + if (!FSCDeviceHostFS_Mount(mountPathOut, _pathToUtf8(ActiveSettings::GetMlcPath()), FSC_PRIORITY_BASE)) return FS_RESULT::ERR_PLACEHOLDER; _mlc01Mounted = true; } diff --git a/src/Cafe/OS/libs/nn_acp/nn_acp.cpp b/src/Cafe/OS/libs/nn_acp/nn_acp.cpp index 23d21434..3200cf62 100644 --- a/src/Cafe/OS/libs/nn_acp/nn_acp.cpp +++ b/src/Cafe/OS/libs/nn_acp/nn_acp.cpp @@ -51,7 +51,7 @@ namespace acp // mount save path const auto mlc = ActiveSettings::GetMlcPath("usr/save/{:08x}/{:08x}/user/", high, low); - FSCDeviceHostFS_Mount("/vol/save/", mlc.generic_wstring().c_str(), FSC_PRIORITY_BASE); + FSCDeviceHostFS_Mount("/vol/save/", _pathToUtf8(mlc), FSC_PRIORITY_BASE); nnResult mountResult = BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_ACP, 0); return _ACPConvertResultToACPStatus(&mountResult, "ACPMountSaveDir", 0x60); } diff --git a/src/Cafe/TitleList/SaveList.cpp b/src/Cafe/TitleList/SaveList.cpp index 224d47b0..a86e8498 100644 --- a/src/Cafe/TitleList/SaveList.cpp +++ b/src/Cafe/TitleList/SaveList.cpp @@ -66,7 +66,7 @@ void CafeSaveList::RefreshThreadWorker() { if(!it_titleHigh.is_directory(ec)) continue; - std::string dirName = _utf8Wrapper(it_titleHigh.path().filename()); + std::string dirName = _pathToUtf8(it_titleHigh.path().filename()); if(dirName.empty()) continue; uint32 titleIdHigh; @@ -78,7 +78,7 @@ void CafeSaveList::RefreshThreadWorker() { if (!it_titleLow.is_directory(ec)) continue; - dirName = _utf8Wrapper(it_titleLow.path().filename()); + dirName = _pathToUtf8(it_titleLow.path().filename()); if (dirName.empty()) continue; uint32 titleIdLow; diff --git a/src/Cafe/TitleList/TitleInfo.cpp b/src/Cafe/TitleList/TitleInfo.cpp index 6606c130..c58e1841 100644 --- a/src/Cafe/TitleList/TitleInfo.cpp +++ b/src/Cafe/TitleList/TitleInfo.cpp @@ -177,12 +177,12 @@ bool TitleInfo::DetectFormat(const fs::path& path, fs::path& pathOut, TitleDataF std::error_code ec; if (path.has_extension() && fs::is_regular_file(path, ec)) { - std::string filenameStr = _utf8Wrapper(path.filename()); + std::string filenameStr = _pathToUtf8(path.filename()); if (boost::iends_with(filenameStr, ".rpx")) { // is in code folder? fs::path parentPath = path.parent_path(); - if (boost::iequals(_utf8Wrapper(parentPath.filename()), "code")) + if (boost::iequals(_pathToUtf8(parentPath.filename()), "code")) { parentPath = parentPath.parent_path(); // next to content and meta? @@ -370,7 +370,7 @@ bool TitleInfo::Mount(std::string_view virtualPath, std::string_view subfolder, { fs::path hostFSPath = m_fullPath; hostFSPath.append(subfolder); - bool r = FSCDeviceHostFS_Mount(std::string(virtualPath).c_str(), boost::nowide::widen(_utf8Wrapper(hostFSPath)).c_str(), mountPriority); + bool r = FSCDeviceHostFS_Mount(std::string(virtualPath).c_str(), _pathToUtf8(hostFSPath), mountPriority); cemu_assert_debug(r); if (!r) { @@ -387,7 +387,7 @@ bool TitleInfo::Mount(std::string_view virtualPath, std::string_view subfolder, } if (!m_wudVolume) return false; - bool r = FSCDeviceWUD_Mount(std::string(virtualPath).c_str(), subfolder, m_wudVolume, mountPriority); + bool r = FSCDeviceWUD_Mount(virtualPath, subfolder, m_wudVolume, mountPriority); cemu_assert_debug(r); if (!r) { @@ -404,7 +404,7 @@ bool TitleInfo::Mount(std::string_view virtualPath, std::string_view subfolder, if (!m_zarchive) return false; } - bool r = FSCDeviceWUA_Mount(std::string(virtualPath).c_str(), std::string(m_subPath).append("/").append(subfolder), m_zarchive, mountPriority); + bool r = FSCDeviceWUA_Mount(virtualPath, std::string(m_subPath).append("/").append(subfolder), m_zarchive, mountPriority); if (!r) { cemuLog_log(LogType::Force, "Failed to mount {} to {}", virtualPath, subfolder); @@ -495,7 +495,7 @@ bool TitleInfo::ParseXmlInfo() if (!m_parsedMetaXml || !m_parsedAppXml || !m_parsedCosXml) { if (hasAnyXml) - cemuLog_log(LogType::Force, "Title has missing meta .xml files. Title path: {}", _utf8Wrapper(m_fullPath)); + cemuLog_log(LogType::Force, "Title has missing meta .xml files. Title path: {}", _pathToUtf8(m_fullPath)); delete m_parsedMetaXml; delete m_parsedAppXml; delete m_parsedCosXml; @@ -621,7 +621,7 @@ std::string TitleInfo::GetPrintPath() const if (!m_isValid) return "invalid"; std::string tmp; - tmp.append(_utf8Wrapper(m_fullPath)); + tmp.append(_pathToUtf8(m_fullPath)); switch (m_titleFormat) { case TitleDataFormat::HOST_FS: diff --git a/src/Cafe/TitleList/TitleList.cpp b/src/Cafe/TitleList/TitleList.cpp index 315103dd..f7c1b6f8 100644 --- a/src/Cafe/TitleList/TitleList.cpp +++ b/src/Cafe/TitleList/TitleList.cpp @@ -79,7 +79,7 @@ void CafeTitleList::LoadCacheFile() cacheEntry.titleDataFormat = format; cacheEntry.region = region; cacheEntry.titleName = name; - cacheEntry.path = _asUtf8(path); + cacheEntry.path = _utf8ToPath(path); cacheEntry.subPath = sub_path; cacheEntry.group_id = group_id; cacheEntry.app_type = app_type; @@ -120,16 +120,16 @@ void CafeTitleList::StoreCacheFile() titleInfoNode.append_child("region").append_child(pugi::node_pcdata).set_value(fmt::format("{}", (uint32)info.region).c_str()); titleInfoNode.append_child("name").append_child(pugi::node_pcdata).set_value(info.titleName.c_str()); titleInfoNode.append_child("format").append_child(pugi::node_pcdata).set_value(fmt::format("{}", (uint32)info.titleDataFormat).c_str()); - titleInfoNode.append_child("path").append_child(pugi::node_pcdata).set_value(_utf8Wrapper(info.path).c_str()); + titleInfoNode.append_child("path").append_child(pugi::node_pcdata).set_value(_pathToUtf8(info.path).c_str()); if(!info.subPath.empty()) - titleInfoNode.append_child("sub_path").append_child(pugi::node_pcdata).set_value(_utf8Wrapper(info.subPath).c_str()); + titleInfoNode.append_child("sub_path").append_child(pugi::node_pcdata).set_value(_pathToUtf8(info.subPath).c_str()); } - fs::path tmpPath = fs::path(sTLCacheFilePath.parent_path()).append(fmt::format("{}__tmp", _utf8Wrapper(sTLCacheFilePath.filename()))); + fs::path tmpPath = fs::path(sTLCacheFilePath.parent_path()).append(fmt::format("{}__tmp", _pathToUtf8(sTLCacheFilePath.filename()))); std::ofstream fileOut(tmpPath, std::ios::out | std::ios::binary | std::ios::trunc); if (!fileOut.is_open()) { - cemuLog_log(LogType::Force, "Unable to store title list in {}", _utf8Wrapper(tmpPath)); + cemuLog_log(LogType::Force, "Unable to store title list in {}", _pathToUtf8(tmpPath)); return; } doc.save(fileOut, " ", 1, pugi::xml_encoding::encoding_utf8); @@ -158,7 +158,7 @@ void CafeTitleList::SetMLCPath(fs::path path) std::error_code ec; if (!fs::is_directory(path, ec)) { - cemuLog_log(LogType::Force, "MLC set to invalid path: {}", _utf8Wrapper(path)); + cemuLog_log(LogType::Force, "MLC set to invalid path: {}", _pathToUtf8(path)); return; } sTLMLCPath = path; @@ -211,12 +211,12 @@ void _RemoveTitleFromMultimap(TitleInfo* titleInfo) // in the special case that path points to a WUA file, all contained titles will be added void CafeTitleList::AddTitleFromPath(fs::path path) { - if (path.has_extension() && boost::iequals(_utf8Wrapper(path.extension()), ".wua")) + if (path.has_extension() && boost::iequals(_pathToUtf8(path.extension()), ".wua")) { ZArchiveReader* zar = ZArchiveReader::OpenFromFile(path); if (!zar) { - cemuLog_log(LogType::Force, "Found {} but it is not a valid Wii U archive file", _utf8Wrapper(path)); + cemuLog_log(LogType::Force, "Found {} but it is not a valid Wii U archive file", _pathToUtf8(path)); return; } // enumerate all contained titles @@ -233,7 +233,7 @@ void CafeTitleList::AddTitleFromPath(fs::path path) uint16 parsedVersion; if (!TitleInfo::ParseWuaTitleFolderName(dirEntry.name, parsedId, parsedVersion)) { - cemuLog_log(LogType::Force, "Invalid title directory in {}: \"{}\"", _utf8Wrapper(path), dirEntry.name); + cemuLog_log(LogType::Force, "Invalid title directory in {}: \"{}\"", _pathToUtf8(path), dirEntry.name); continue; } // valid subdirectory @@ -351,7 +351,7 @@ void CafeTitleList::ScanGamePath(const fs::path& path) { dirsInDirectory.emplace_back(it.path()); - std::string dirName = _utf8Wrapper(it.path().filename()); + std::string dirName = _pathToUtf8(it.path().filename()); if (boost::iequals(dirName, "content")) hasContentFolder = true; else if (boost::iequals(dirName, "code")) @@ -366,7 +366,7 @@ void CafeTitleList::ScanGamePath(const fs::path& path) // since checking files is slow, we only do it for known file extensions if (!it.has_extension()) continue; - if (!_IsKnownFileExtension(_utf8Wrapper(it.extension()))) + if (!_IsKnownFileExtension(_pathToUtf8(it.extension()))) continue; AddTitleFromPath(it); } @@ -384,7 +384,7 @@ void CafeTitleList::ScanGamePath(const fs::path& path) { for (auto& it : dirsInDirectory) { - std::string dirName = _utf8Wrapper(it.filename()); + std::string dirName = _pathToUtf8(it.filename()); if (!boost::iequals(dirName, "content") && !boost::iequals(dirName, "code") && !boost::iequals(dirName, "meta")) @@ -408,7 +408,7 @@ void CafeTitleList::ScanMLCPath(const fs::path& path) if (!it.is_directory()) continue; // only scan directories which match the title id naming scheme - std::string dirName = _utf8Wrapper(it.path().filename()); + std::string dirName = _pathToUtf8(it.path().filename()); if(dirName.size() != 8) continue; bool containsNoHexCharacter = false; diff --git a/src/Common/precompiled.h b/src/Common/precompiled.h index 57929c2a..57f69c57 100644 --- a/src/Common/precompiled.h +++ b/src/Common/precompiled.h @@ -420,25 +420,19 @@ inline std::string_view _utf8Wrapper(std::u8string_view input) return v; } -// returns a std::u8string as std::string, the contents are left as-is -inline std::string _utf8Wrapper(const std::u8string& u8str) +// convert fs::path to utf8 encoded string +inline std::string _pathToUtf8(const fs::path& path) { - std::string v; - v.resize(u8str.size()); - memcpy(v.data(), u8str.data(), u8str.size()); + std::u8string strU8 = path.generic_u8string(); + std::string v((const char*)strU8.data(), strU8.size()); return v; } -// get utf8 generic path string directly from std::filesystem::path -inline std::string _utf8Wrapper(const fs::path& path) +// convert utf8 encoded string to fs::path +inline fs::path _utf8ToPath(std::string_view input) { - return _utf8Wrapper(path.generic_u8string()); -} - -inline std::u8string_view _asUtf8(std::string_view input) -{ - std::basic_string_view v((char8_t*)input.data(), input.size()); - return v; + std::basic_string_view v((char8_t*)input.data(), input.size()); + return fs::path(v); } class RunAtCemuBoot // -> replaces this with direct function calls. Linkers other than MSVC may optimize way object files entirely if they are not referenced from outside. So a source file self-registering using this would be causing issues diff --git a/src/config/ActiveSettings.h b/src/config/ActiveSettings.h index 95ceae16..69f6d34a 100644 --- a/src/config/ActiveSettings.h +++ b/src/config/ActiveSettings.h @@ -47,7 +47,7 @@ public: { cemu_assert_debug(format.empty() || (format[0] != '/' && format[0] != '\\')); auto tmp = fmt::format(fmt::runtime(format), std::forward(args)...); - return GetMlcPath() / fs::path(_asUtf8(tmp)); + return GetMlcPath() / _utf8ToPath(tmp); } template diff --git a/src/config/CemuConfig.cpp b/src/config/CemuConfig.cpp index bc1f9f97..31a3b3e2 100644 --- a/src/config/CemuConfig.cpp +++ b/src/config/CemuConfig.cpp @@ -417,7 +417,7 @@ void CemuConfig::Save(XMLConfigParser& parser) for (const auto& game : graphic_pack_entries) { auto entry = graphic_pack_parser.set("Entry"); - entry.set_attribute("filename",_utf8Wrapper(game.first).c_str()); + entry.set_attribute("filename",_pathToUtf8(game.first).c_str()); for(const auto& kv : game.second) { // TODO: less hacky pls diff --git a/src/gui/GameUpdateWindow.cpp b/src/gui/GameUpdateWindow.cpp index c689dd6f..3ea3f9d1 100644 --- a/src/gui/GameUpdateWindow.cpp +++ b/src/gui/GameUpdateWindow.cpp @@ -251,7 +251,7 @@ void GameUpdateWindow::ThreadWork() error_msg << GetSystemErrorMessage(ex); if(currentDirEntry != fs::directory_entry{}) - error_msg << fmt::format("\n{}\n{}",_("Current file:").ToStdString(), _utf8Wrapper(currentDirEntry.path())); + error_msg << fmt::format("\n{}\n{}",_("Current file:").ToStdString(), _pathToUtf8(currentDirEntry.path())); m_thread_exception = error_msg.str(); m_thread_state = ThreadCanceled; diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 53363ae3..5b65c7a1 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1947,7 +1947,7 @@ public: "/*****************************************************************************/\r\n" ); delete fs; - wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(tempPath)))); + wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _pathToUtf8(tempPath)))); }); lineSizer->Add(noticeLink, 0); lineSizer->Add(new wxStaticText(parent, -1, ")"), 0); diff --git a/src/gui/MemorySearcherTool.cpp b/src/gui/MemorySearcherTool.cpp index 904be1a0..3423e73b 100644 --- a/src/gui/MemorySearcherTool.cpp +++ b/src/gui/MemorySearcherTool.cpp @@ -275,7 +275,7 @@ void MemorySearcherTool::Load() if (!memSearcherIniContents) return; - IniParser iniParser(*memSearcherIniContents, _utf8Wrapper(memorySearcherPath)); + IniParser iniParser(*memSearcherIniContents, _pathToUtf8(memorySearcherPath)); while (iniParser.NextSection()) { auto option_description = iniParser.FindOption("description"); diff --git a/src/gui/TitleManager.cpp b/src/gui/TitleManager.cpp index b643ab8f..657fa3ce 100644 --- a/src/gui/TitleManager.cpp +++ b/src/gui/TitleManager.cpp @@ -480,7 +480,7 @@ void TitleManager::OnSaveOpenDirectory(wxCommandEvent& event) if (!fs::exists(target) || !fs::is_directory(target)) return; - wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(target)))); + wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _pathToUtf8(target)))); } void TitleManager::OnSaveDelete(wxCommandEvent& event) diff --git a/src/gui/components/wxGameList.cpp b/src/gui/components/wxGameList.cpp index 68dde7c6..39eeb100 100644 --- a/src/gui/components/wxGameList.cpp +++ b/src/gui/components/wxGameList.cpp @@ -563,7 +563,7 @@ void wxGameList::OnContextMenuSelected(wxCommandEvent& event) { fs::path path(gameInfo.GetBase().GetPath()); _stripPathFilename(path); - wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(path)))); + wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _pathToUtf8(path)))); break; } case kWikiPage: @@ -584,21 +584,21 @@ void wxGameList::OnContextMenuSelected(wxCommandEvent& event) case kContextMenuSaveFolder: { - wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(gameInfo.GetSaveFolder())))); + wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _pathToUtf8(gameInfo.GetSaveFolder())))); break; } case kContextMenuUpdateFolder: { fs::path path(gameInfo.GetUpdate().GetPath()); _stripPathFilename(path); - wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(path)))); + wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _pathToUtf8(path)))); break; } case kContextMenuDLCFolder: { fs::path path(gameInfo.GetAOC().front().GetPath()); _stripPathFilename(path); - wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(path)))); + wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _pathToUtf8(path)))); break; } case kContextMenuEditGraphicPacks: diff --git a/src/gui/components/wxTitleManagerList.cpp b/src/gui/components/wxTitleManagerList.cpp index 57e9ee22..7252d872 100644 --- a/src/gui/components/wxTitleManagerList.cpp +++ b/src/gui/components/wxTitleManagerList.cpp @@ -293,21 +293,21 @@ void wxTitleManagerList::OnConvertToCompressedFormat(uint64 titleId) std::string msg = wxHelper::MakeUTF8(_("The following content will be converted to a compressed Wii U archive file (.wua):\n \n")); if (titleInfo_base.IsValid()) - msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("Base game: {}"))), _utf8Wrapper(titleInfo_base.GetPath()))); + msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("Base game: {}"))), _pathToUtf8(titleInfo_base.GetPath()))); else msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("Base game: Not installed"))))); msg.append("\n"); if (titleInfo_update.IsValid()) - msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("Update: {}"))), _utf8Wrapper(titleInfo_update.GetPath()))); + msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("Update: {}"))), _pathToUtf8(titleInfo_update.GetPath()))); else msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("Update: Not installed"))))); msg.append("\n"); if (titleInfo_aoc.IsValid()) - msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("DLC: {}"))), _utf8Wrapper(titleInfo_aoc.GetPath()))); + msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("DLC: {}"))), _pathToUtf8(titleInfo_aoc.GetPath()))); else msg.append(fmt::format(fmt::runtime(wxHelper::MakeUTF8(_("DLC: Not installed"))))); @@ -778,9 +778,9 @@ bool wxTitleManagerList::DeleteEntry(long index, const TitleEntry& entry) wxString msg; const bool is_directory = fs::is_directory(entry.path); if(is_directory) - msg = wxStringFormat2(_("Are you really sure that you want to delete the following folder:\n{}"), wxHelper::FromUtf8(_utf8Wrapper(entry.path))); + msg = wxStringFormat2(_("Are you really sure that you want to delete the following folder:\n{}"), wxHelper::FromUtf8(_pathToUtf8(entry.path))); else - msg = wxStringFormat2(_("Are you really sure that you want to delete the following file:\n{}"), wxHelper::FromUtf8(_utf8Wrapper(entry.path))); + msg = wxStringFormat2(_("Are you really sure that you want to delete the following file:\n{}"), wxHelper::FromUtf8(_pathToUtf8(entry.path))); const auto result = wxMessageBox(msg, _("Warning"), wxYES_NO | wxCENTRE | wxICON_EXCLAMATION, this); if (result == wxNO) @@ -852,7 +852,7 @@ void wxTitleManagerList::OnContextMenuSelected(wxCommandEvent& event) case kContextMenuOpenDirectory: { const auto path = fs::is_directory(entry->path) ? entry->path : entry->path.parent_path(); - wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _utf8Wrapper(path)))); + wxLaunchDefaultBrowser(wxHelper::FromUtf8(fmt::format("file:{}", _pathToUtf8(path)))); } break; case kContextMenuDelete: diff --git a/src/gui/dialogs/SaveImport/SaveImportWindow.cpp b/src/gui/dialogs/SaveImport/SaveImportWindow.cpp index bfdb00b4..9b7b20cc 100644 --- a/src/gui/dialogs/SaveImport/SaveImportWindow.cpp +++ b/src/gui/dialogs/SaveImport/SaveImportWindow.cpp @@ -170,7 +170,7 @@ void SaveImportWindow::OnImport(wxCommandEvent& event) { if (!fs::is_directory(target_path)) { - const auto msg = wxStringFormat2(_("There's already a file at the target directory:\n{}"), _utf8Wrapper(target_path)); + const auto msg = wxStringFormat2(_("There's already a file at the target directory:\n{}"), _pathToUtf8(target_path)); wxMessageBox(msg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR, this); m_return_code = wxCANCEL; Close(); diff --git a/src/gui/dialogs/SaveImport/SaveTransfer.cpp b/src/gui/dialogs/SaveImport/SaveTransfer.cpp index bcccf1dd..ad11fba6 100644 --- a/src/gui/dialogs/SaveImport/SaveTransfer.cpp +++ b/src/gui/dialogs/SaveImport/SaveTransfer.cpp @@ -108,7 +108,7 @@ void SaveTransfer::OnTransfer(wxCommandEvent& event) { if(!fs::is_directory(target_path)) { - const auto msg = wxStringFormat2(_("There's already a file at the target directory:\n{}"), _utf8Wrapper(target_path)); + const auto msg = wxStringFormat2(_("There's already a file at the target directory:\n{}"), _pathToUtf8(target_path)); wxMessageBox(msg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR, this); m_return_code = wxCANCEL; Close(); diff --git a/src/main.cpp b/src/main.cpp index f94b2761..67b640b4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -166,7 +166,7 @@ void reconfigureGLDrivers() fs::create_directories(nvCacheDir, err); std::string nvCacheDirEnvOption("__GL_SHADER_DISK_CACHE_PATH="); - nvCacheDirEnvOption.append(_utf8Wrapper(nvCacheDir)); + nvCacheDirEnvOption.append(_pathToUtf8(nvCacheDir)); #if BOOST_OS_WINDOWS std::wstring tmpW = boost::nowide::widen(nvCacheDirEnvOption);