From 8ab627d6e981d299bc1ffe2d446bfa97fa1e576d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 24 Jul 2021 18:16:12 +0200 Subject: [PATCH] Workaround for the /PSP path thing. Needs testing. --- Core/FileSystems/DirectoryFileSystem.cpp | 37 +++++++++++++++------- Core/FileSystems/DirectoryFileSystem.h | 15 +++++---- Core/FileSystems/FileSystem.h | 1 + Core/FileSystems/VirtualDiscFileSystem.cpp | 7 ++-- Core/FileSystems/VirtualDiscFileSystem.h | 28 +++++++++------- Core/HLE/sceIo.cpp | 16 +++++++--- Core/System.cpp | 2 ++ Core/System.h | 1 + 8 files changed, 70 insertions(+), 37 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 06fea1f5a9..4a7bde8f8b 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -177,17 +177,40 @@ DirectoryFileSystem::~DirectoryFileSystem() { CloseAll(); } -Path DirectoryFileHandle::GetLocalPath(const Path &basePath, std::string localpath) -{ +// TODO(scoped): Merge the two below functions somehow. + +Path DirectoryFileHandle::GetLocalPath(const Path &basePath, std::string localpath) const { if (localpath.empty()) return basePath; if (localpath[0] == '/') localpath.erase(0, 1); + if (fileSystemFlags_ & FileSystemFlags::STRIP_PSP) { + if (startsWith(localpath, "/PSP")) { + localpath = localpath.substr(4); + } + } + return basePath / localpath; } +Path DirectoryFileSystem::GetLocalPath(std::string internalPath) const { + if (internalPath.empty()) + return basePath; + + if (internalPath[0] == '/') + internalPath.erase(0, 1); + + if (flags & FileSystemFlags::STRIP_PSP) { + if (startsWith(internalPath, "/PSP")) { + internalPath = internalPath.substr(4); + } + } + + return basePath / internalPath; +} + bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, FileAccess access, u32 &error) { error = 0; @@ -508,16 +531,6 @@ void DirectoryFileSystem::CloseAll() { entries.clear(); } -Path DirectoryFileSystem::GetLocalPath(std::string internalPath) { - if (internalPath.empty()) - return basePath; - - if (internalPath[0] == '/') - internalPath.erase(0, 1); - - return basePath / internalPath; -} - bool DirectoryFileSystem::MkDir(const std::string &dirname) { bool result; #if HOST_IS_CASE_SENSITIVE diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index b7b71c7c34..9d8478d691 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -72,11 +72,14 @@ struct DirectoryFileHandle { s64 needsTrunc_ = -1; bool replay_ = true; bool inGameDir_ = false; + FileSystemFlags fileSystemFlags_ = (FileSystemFlags)0; - DirectoryFileHandle(Flags flags) : replay_(flags != SKIP_REPLAY) { - } + DirectoryFileHandle() {} - Path GetLocalPath(const Path &basePath, std::string localpath); + DirectoryFileHandle(Flags flags, FileSystemFlags fileSystemFlags) + : replay_(flags != SKIP_REPLAY), fileSystemFlags_(fileSystemFlags) {} + + Path GetLocalPath(const Path &basePath, std::string localpath) const; bool Open(const Path &basePath, std::string &fileName, FileAccess access, u32 &err); size_t Read(u8* pointer, s64 size); size_t Write(const u8* pointer, s64 size); @@ -114,7 +117,7 @@ public: private: struct OpenFileEntry { - DirectoryFileHandle hFile = DirectoryFileHandle::NORMAL; + DirectoryFileHandle hFile; std::string guestFilename; FileAccess access = FILEACCESS_NONE; }; @@ -124,8 +127,8 @@ private: Path basePath; IHandleAllocator *hAlloc; FileSystemFlags flags; - // In case of Windows: Translate slashes, etc. - Path GetLocalPath(std::string internalPath); + + Path GetLocalPath(std::string internalPath) const; }; // VFSFileSystem: Ability to map in Android APK paths as well! Does not support all features, only meant for fonts. diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index 87e8c92e07..5df227dd1f 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -63,6 +63,7 @@ enum class FileSystemFlags { UMD = 2, CARD = 4, FLASH = 8, + STRIP_PSP = 16, }; ENUM_CLASS_BITOPS(FileSystemFlags); diff --git a/Core/FileSystems/VirtualDiscFileSystem.cpp b/Core/FileSystems/VirtualDiscFileSystem.cpp index 276a89f1be..889bc506fc 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.cpp +++ b/Core/FileSystems/VirtualDiscFileSystem.cpp @@ -187,7 +187,7 @@ void VirtualDiscFileSystem::DoState(PointerWrap &p) for (int i = 0; i < entryCount; i++) { u32 fd = 0; - OpenFileEntry of; + OpenFileEntry of(Flags()); Do(p, fd); Do(p, of.fileIndex); @@ -214,6 +214,7 @@ void VirtualDiscFileSystem::DoState(PointerWrap &p) } } + // TODO: I think we only need to write to the map on load? entries[fd] = of; } } else { @@ -321,7 +322,7 @@ int VirtualDiscFileSystem::getFileListIndex(u32 accessBlock, u32 accessSize, boo int VirtualDiscFileSystem::OpenFile(std::string filename, FileAccess access, const char *devicename) { - OpenFileEntry entry; + OpenFileEntry entry(Flags()); entry.curOffset = 0; entry.size = 0; entry.startOffset = 0; @@ -471,7 +472,7 @@ size_t VirtualDiscFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size, int &u return 0; } - OpenFileEntry temp; + OpenFileEntry temp(Flags()); if (fileList[fileIndex].handler != NULL) { temp.handler = fileList[fileIndex].handler; } diff --git a/Core/FileSystems/VirtualDiscFileSystem.h b/Core/FileSystems/VirtualDiscFileSystem.h index bd8604ae3d..6c76d6b6fb 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.h +++ b/Core/FileSystems/VirtualDiscFileSystem.h @@ -87,17 +87,15 @@ private: ReadFunc Read; CloseFunc Close; - bool IsValid() const { return library != NULL; } + bool IsValid() const { return library != nullptr; } }; struct HandlerFileHandle { Handler *handler; HandlerHandle handle; - HandlerFileHandle() : handler(NULL), handle(0) { - } - HandlerFileHandle(Handler *handler_) : handler(handler_), handle(-1) { - } + HandlerFileHandle() : handler(nullptr), handle(0) {} + HandlerFileHandle(Handler *handler_) : handler(handler_), handle(-1) {} bool Open(const std::string& basePath, const std::string& fileName, FileAccess access) { // Ignore access, read only. @@ -115,7 +113,7 @@ private: } bool IsValid() { - return handler != NULL && handler->IsValid(); + return handler != nullptr && handler->IsValid(); } HandlerFileHandle &operator =(Handler *_handler) { @@ -127,13 +125,18 @@ private: typedef enum { VFILETYPE_NORMAL, VFILETYPE_LBN, VFILETYPE_ISO } VirtualFileType; struct OpenFileEntry { - DirectoryFileHandle hFile = DirectoryFileHandle::SKIP_REPLAY; + OpenFileEntry() {} + OpenFileEntry(FileSystemFlags fileSystemFlags) { + hFile = DirectoryFileHandle(DirectoryFileHandle::SKIP_REPLAY, fileSystemFlags); + } + + DirectoryFileHandle hFile; HandlerFileHandle handler; - VirtualFileType type; - u32 fileIndex; - u64 curOffset; - u64 startOffset; // only used by lbn files - u64 size; // only used by lbn files + VirtualFileType type = VFILETYPE_NORMAL; + u32 fileIndex = 0; + u64 curOffset = 0; + u64 startOffset = 0; // only used by lbn files + u64 size = 0; // only used by lbn files bool Open(const Path &basePath, std::string& fileName, FileAccess access) { // Ignored, we're read only. @@ -168,6 +171,7 @@ private: }; typedef std::map EntryMap; + EntryMap entries; IHandleAllocator *hAlloc; Path basePath; diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 7128bfa73d..3b99c2d2d3 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -631,19 +631,28 @@ void __IoInit() { asyncNotifyEvent = CoreTiming::RegisterEvent("IoAsyncNotify", __IoAsyncNotify); syncNotifyEvent = CoreTiming::RegisterEvent("IoSyncNotify", __IoSyncNotify); - auto memstickSystem = std::shared_ptr(new DirectoryFileSystem(&pspFileSystem, g_Config.memStickDirectory, FileSystemFlags::SIMULATE_FAT32 | FileSystemFlags::CARD)); + // TODO(scoped): This won't work if memStickDirectory points at the contents of /PSP... #if defined(USING_WIN_UI) || defined(APPLE) auto flash0System = std::shared_ptr(new DirectoryFileSystem(&pspFileSystem, g_Config.flash0Directory, FileSystemFlags::FLASH)); #else auto flash0System = std::shared_ptr(new VFSFileSystem(&pspFileSystem, "flash0")); #endif + FileSystemFlags memstickFlags = FileSystemFlags::SIMULATE_FAT32 | FileSystemFlags::CARD; + + Path pspDir = GetSysDirectory(DIRECTORY_PSP); + if (pspDir == g_Config.memStickDirectory) { + // Initially tried to do this with dual mounts, but failed due to save state compatibility issues. + INFO_LOG(SCEIO, "Enabling /PSP compatibility mode"); + memstickFlags |= FileSystemFlags::STRIP_PSP; + } + + auto memstickSystem = std::shared_ptr(new DirectoryFileSystem(&pspFileSystem, g_Config.memStickDirectory, memstickFlags)); - // TODO(scoped): This won't work if memStickDirectory points at the contents of /PSP... - // Will fix later with dual mounts (first mount ms0:/PSP/ at memstickSystem), then also mount ms0:/ on it) pspFileSystem.Mount("ms0:", memstickSystem); pspFileSystem.Mount("fatms0:", memstickSystem); pspFileSystem.Mount("fatms:", memstickSystem); pspFileSystem.Mount("pfat0:", memstickSystem); + pspFileSystem.Mount("flash0:", flash0System); if (g_RemasterMode) { @@ -768,7 +777,6 @@ void __IoShutdown() { pspFileSystem.UnmountAll(); - // All the file systems will be removed when we shut down pspFileSystem later. MemoryStick_Shutdown(); memStickCallbacks.clear(); memStickFatCallbacks.clear(); diff --git a/Core/System.cpp b/Core/System.cpp index b9f2ccf0e8..d2427d43fd 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -592,6 +592,8 @@ Path GetSysDirectory(PSPDirectories directoryType) { } switch (directoryType) { + case DIRECTORY_PSP: + return pspDirectory; case DIRECTORY_CHEATS: return pspDirectory / "Cheats"; case DIRECTORY_GAME: diff --git a/Core/System.h b/Core/System.h index 29b95bb7a4..13423a0167 100644 --- a/Core/System.h +++ b/Core/System.h @@ -37,6 +37,7 @@ enum GlobalUIState { // Use these in conjunction with GetSysDirectory. enum PSPDirectories { + DIRECTORY_PSP, DIRECTORY_CHEATS, DIRECTORY_SCREENSHOT, DIRECTORY_SYSTEM,