diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 12053c1851..06292eb2d5 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -236,7 +236,24 @@ int MetaFileSystem::MapFilePath(std::string_view _inpath, std::string *outpath, size_t prefLen = fileSystems[i].prefix.size(); if (strncasecmp(fileSystems[i].prefix.c_str(), prefix.c_str(), prefLen) == 0) { - *outpath = realpath.substr(prefixPos + 1); + // Map into the underlying filesystem. If the mount specifies a subDir, + // join that with the path inside the device. + std::string basePath = realpath.substr(prefixPos + 1); // may be empty or start with '/' + const std::string &mountSub = fileSystems[i].subDir; + if (mountSub.empty()) { + *outpath = basePath; + } else { + // Normalize subDir: ensure it starts with '/' and has no trailing slash (unless it's root "/"). + std::string s = mountSub; + if (s.empty()) s = "/"; + if (s[0] != '/') s.insert(s.begin(), '/'); + if (s.size() > 1 && s.back() == '/') s.pop_back(); + if (basePath.empty()) { + *outpath = s; + } else { + *outpath = s + basePath; // basePath usually starts with '/' + } + } *system = &(fileSystems[i]); VERBOSE_LOG(Log::FileSystem, "MapFilePath: mapped \"%s\" to prefix: \"%s\", path: \"%s\"", inpath.c_str(), fileSystems[i].prefix.c_str(), outpath->c_str()); @@ -252,31 +269,30 @@ int MetaFileSystem::MapFilePath(std::string_view _inpath, std::string *outpath, return error; } -std::string MetaFileSystem::NormalizePrefix(std::string_view prefix) const { +std::string_view MetaFileSystem::NormalizePrefix(std::string_view prefix) const { // Let's apply some mapping here since it won't break savestates. if (prefix == "memstick:") - prefix = "ms0:"; + return "ms0:"; // Seems like umd00: etc. work just fine... avoid umd1/umd for tests. if (startsWith(prefix, "umd") && prefix != "umd1:" && prefix != "umd:") - prefix = "umd0:"; + return "umd0:"; // Seems like umd00: etc. work just fine... if (startsWith(prefix, "host")) - prefix = "host0:"; + return "host0:"; // Should we simply make this case insensitive? if (prefix == "DISC0:") - prefix = "disc0:"; - - return std::string(prefix); + return "disc0:"; + return prefix; } -void MetaFileSystem::Mount(std::string_view prefix, std::shared_ptr system) { +void MetaFileSystem::Mount(std::string_view prefix, std::shared_ptr system, std::string_view subDir) { std::lock_guard guard(lock); for (auto &it : fileSystems) { if (it.prefix == prefix) { // Overwrite the old mount. - // shared_ptr makes sure there's no leak. it.system = system; + it.subDir = std::string(subDir); return; } } @@ -285,6 +301,7 @@ void MetaFileSystem::Mount(std::string_view prefix, std::shared_ptr MountPoint x; x.prefix = prefix; x.system = system; + x.subDir = std::string(subDir); fileSystems.push_back(x); } diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index c0362be8e9..59fd96c134 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -31,9 +31,13 @@ private: struct MountPoint { std::string prefix; std::shared_ptr system; + // Optional subdirectory inside the filesystem to treat as the root for this mount. + // Example: mounting "ms0:" with subDir "/PSP/GAME" will map "ms0:/file" + // to the underlying filesystem path "/PSP/GAME/file". + std::string subDir; bool operator == (const MountPoint &other) const { - return prefix == other.prefix && system == other.system; + return prefix == other.prefix && system == other.system && subDir == other.subDir; } }; @@ -59,9 +63,8 @@ public: Reset(); } - // Will replace the existing mount if already exists. - void Mount(std::string_view prefix, std::shared_ptr system); - + // Will replace the existing mount if already exists. Mount with an optional sub-directory inside the filesystem to treat as the root. + void Mount(std::string_view prefix, std::shared_ptr system, std::string_view subDir = std::string_view()); void UnmountAll(); void Unmount(std::string_view prefix); @@ -107,7 +110,7 @@ public: return error; } - std::string NormalizePrefix(std::string_view prefix) const; + std::string_view NormalizePrefix(std::string_view prefix) const; std::vector GetDirListing(std::string_view path, bool *exists = nullptr) override; int OpenFile(std::string filename, FileAccess access, const char *devicename = nullptr) override;