From a53ecd7da31f4b48664942ba44354c1040f4ba18 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 13 Apr 2014 23:22:17 +0200 Subject: [PATCH 1/3] More elegant way of solving #5839 (d_private in sceIoDread) We flag filesystems as being FAT32 instead of checking for "ms0:". --- Core/FileSystems/DirectoryFileSystem.cpp | 10 +++---- Core/FileSystems/DirectoryFileSystem.h | 5 ++-- Core/FileSystems/FileSystem.h | 8 +++++- Core/FileSystems/ISOFileSystem.h | 1 + Core/FileSystems/MetaFileSystem.cpp | 11 ++++++++ Core/FileSystems/MetaFileSystem.h | 2 ++ Core/FileSystems/VirtualDiscFileSystem.h | 1 + Core/HLE/sceIo.cpp | 33 ++++++++++++++++++++---- 8 files changed, 58 insertions(+), 13 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 9586d1f580..d887ccb005 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -134,6 +134,11 @@ bool FixPathCase(std::string& basePath, std::string &path, FixPathCaseBehavior b #endif +DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath, int _flags) : basePath(_basePath), flags(_flags) { + File::CreateFullPath(basePath); + hAlloc = _hAlloc; +} + std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string localpath) { if (localpath.empty()) @@ -326,11 +331,6 @@ void DirectoryFileHandle::Close() #endif } -DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) { - File::CreateFullPath(basePath); - hAlloc = _hAlloc; -} - void DirectoryFileSystem::CloseAll() { for (auto iter = entries.begin(); iter != entries.end(); ++iter) { iter->second.hFile.Close(); diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index 1f71d7315e..bfce1ec896 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -86,7 +86,7 @@ struct DirectoryFileHandle class DirectoryFileSystem : public IFileSystem { public: - DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath); + DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath, int _flags = 0); ~DirectoryFileSystem(); void CloseAll(); @@ -108,6 +108,7 @@ public: int RenameFile(const std::string &from, const std::string &to); bool RemoveFile(const std::string &filename); bool GetHostPath(const std::string &inpath, std::string &outpath); + int Flags() { return flags; } private: struct OpenFileEntry { @@ -120,7 +121,7 @@ private: EntryMap entries; std::string basePath; IHandleAllocator *hAlloc; - + int flags; // In case of Windows: Translate slashes, etc. std::string GetLocalPath(std::string localpath); }; diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index 9f938aa6ef..82855b9b44 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -50,6 +50,10 @@ enum DevType PSP_DEV_TYPE_ALIAS = 0x20, }; +enum FileSystemFlags +{ + FILESYSTEM_SIMULATE_FAT32 = 1, +}; class IHandleAllocator { public: @@ -112,6 +116,7 @@ public: virtual bool GetHostPath(const std::string &inpath, std::string &outpath) = 0; virtual int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) = 0; virtual int DevType(u32 handle) = 0; + virtual int Flags() = 0; }; @@ -133,7 +138,8 @@ public: virtual bool RemoveFile(const std::string &filename) {return false;} virtual bool GetHostPath(const std::string &inpath, std::string &outpath) {return false;} virtual int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) {return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED; } - virtual int DevType(u32 handle) {return 0;} + virtual int DevType(u32 handle) { return 0; } + virtual int Flags() { return 0; } }; diff --git a/Core/FileSystems/ISOFileSystem.h b/Core/FileSystems/ISOFileSystem.h index 78ae4003b9..f124dfdf43 100644 --- a/Core/FileSystems/ISOFileSystem.h +++ b/Core/FileSystems/ISOFileSystem.h @@ -41,6 +41,7 @@ public: bool OwnsHandle(u32 handle); int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec); int DevType(u32 handle); + int Flags() { return 0; } size_t WriteFile(u32 handle, const u8 *pointer, s64 size); bool GetHostPath(const std::string &inpath, std::string &outpath) {return false;} diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index cec688554b..1c7197cd33 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -255,6 +255,10 @@ std::string MetaFileSystem::NormalizePrefix(std::string prefix) const { if (startsWith(prefix, "host")) prefix = "host0:"; + // Should we simply make this case insensitive? + if (prefix == "DISC0:") + prefix = "disc0:"; + return prefix; } @@ -284,6 +288,13 @@ void MetaFileSystem::Remount(IFileSystem *oldSystem, IFileSystem *newSystem) { } } +IFileSystem *MetaFileSystem::GetSystemFromFilename(const std::string &filename) { + size_t prefixPos = filename.find(':'); + if (prefixPos == filename.npos) + return 0; + return GetSystem(filename.substr(0, prefixPos + 1)); +} + IFileSystem *MetaFileSystem::GetSystem(const std::string &prefix) { for (auto it = fileSystems.begin(); it != fileSystems.end(); ++it) { if (it->prefix == NormalizePrefix(prefix)) diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index bae0408b92..7d9eb8ba4d 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -54,6 +54,7 @@ public: void Remount(IFileSystem *oldSystem, IFileSystem *newSystem); IFileSystem *GetSystem(const std::string &prefix); + IFileSystem *GetSystemFromFilename(const std::string &filename); void ThreadEnded(int threadID); @@ -106,6 +107,7 @@ public: virtual bool RemoveFile(const std::string &filename); virtual int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec); virtual int DevType(u32 handle); + virtual int Flags() { return 0; } // Convenience helper - returns < 0 on failure. int ReadEntireFile(const std::string &filename, std::vector &data); diff --git a/Core/FileSystems/VirtualDiscFileSystem.h b/Core/FileSystems/VirtualDiscFileSystem.h index 09a3d488e1..42b09abb81 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.h +++ b/Core/FileSystems/VirtualDiscFileSystem.h @@ -40,6 +40,7 @@ public: int DevType(u32 handle); bool GetHostPath(const std::string &inpath, std::string &outpath); std::vector GetDirListing(std::string path); + int Flags() { return 0; } // unsupported operations size_t WriteFile(u32 handle, const u8 *pointer, s64 size); diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index ee4aae5443..a1aad26ee0 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -457,7 +457,7 @@ void __IoInit() { asyncNotifyEvent = CoreTiming::RegisterEvent("IoAsyncNotify", __IoAsyncNotify); syncNotifyEvent = CoreTiming::RegisterEvent("IoSyncNotify", __IoSyncNotify); - memstickSystem = new DirectoryFileSystem(&pspFileSystem, g_Config.memCardDirectory); + memstickSystem = new DirectoryFileSystem(&pspFileSystem, g_Config.memCardDirectory, FILESYSTEM_SIMULATE_FAT32); #if defined(USING_WIN_UI) || defined(APPLE) flash0System = new DirectoryFileSystem(&pspFileSystem, g_Config.flash0Directory); #else @@ -716,7 +716,7 @@ u32 npdrmRead(FileNode *f, u8 *data, int size) { memcpy(data, pgd->block_buf+offset, copy_size); block += 1; offset = 0; - }else{ + } else { copy_size = remain_size; memcpy(data, pgd->block_buf+offset, copy_size); } @@ -1925,6 +1925,19 @@ u32 sceIoDopen(const char *path) { return id; } +// For some reason strncpy will fill up the entire output buffer. No reason to do that, +// so we use this trivial replacement. +static void strcpy_limit(char *dest, const char *src, int count) { + int i; + for (i = 0; i < count; i++) { + if (!src[i]) // Do the check afterwards, so we don't exit before copying the null terminator. + break; + dest[i] = src[i]; + } + // Always null terminate. + dest[i] = 0; +} + u32 sceIoDread(int id, u32 dirent_addr) { u32 error; DirListing *dir = kernelObjects.Get(id, error); @@ -1943,8 +1956,15 @@ u32 sceIoDread(int id, u32 dirent_addr) { strncpy(entry->d_name, info.name.c_str(), 256); entry->d_name[255] = '\0'; + bool isFAT = false; + IFileSystem *sys = pspFileSystem.GetSystemFromFilename(dir->name); + if (sys && (sys->Flags() & FILESYSTEM_SIMULATE_FAT32)) + isFAT = true; + else + isFAT = false; + // Only write d_private for memory stick - if (dir->name.substr(0, 3) == "ms0") { + if (isFAT) { // write d_private for supporting Custom BGM // ref JPCSP https://code.google.com/p/jpcsp/source/detail?r=3468 if (Memory::IsValidAddress(entry->d_private)){ @@ -1952,7 +1972,9 @@ u32 sceIoDread(int id, u32 dirent_addr) { // d_private is pointing to an area of unknown size // - [0..12] "8.3" file name (null-terminated), could be empty. // - [13..???] long file name (null-terminated) - strncpy((char*)Memory::GetPointer(entry->d_private + 13), (const char*)entry->d_name, ARRAY_SIZE(entry->d_name)); + + // Hm, so currently we don't write the short name at all to d_private? TODO + strcpy_limit((char*)Memory::GetPointer(entry->d_private + 13), (const char*)entry->d_name, ARRAY_SIZE(entry->d_name)); } else { // d_private is pointing to an area of total size 1044 @@ -1960,8 +1982,9 @@ u32 sceIoDread(int id, u32 dirent_addr) { // - [4..19] "8.3" file name (null-terminated), could be empty. // - [20..???] long file name (null-terminated) auto size = Memory::Read_U32(entry->d_private); + // Hm, so currently we don't write the short name at all to d_private? TODO if (size >= 1044) { - strncpy((char*)Memory::GetPointer(entry->d_private + 20), (const char*)entry->d_name, ARRAY_SIZE(entry->d_name)); + strcpy_limit((char*)Memory::GetPointer(entry->d_private + 20), (const char*)entry->d_name, ARRAY_SIZE(entry->d_name)); } } } From c9eb4a1916ddbf07a9a5d3cfa443e52a748b342a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 13 Apr 2014 23:34:08 +0200 Subject: [PATCH 2/3] VFSFileSystem too --- Core/FileSystems/DirectoryFileSystem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index bfce1ec896..7d6a8793bc 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -150,6 +150,7 @@ public: int RenameFile(const std::string &from, const std::string &to); bool RemoveFile(const std::string &filename); bool GetHostPath(const std::string &inpath, std::string &outpath); + int Flags() { return 0; } private: struct OpenFileEntry { From f285b12dcfb3f0cecefe915287c7da0893003b31 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 13 Apr 2014 23:43:32 +0200 Subject: [PATCH 3/3] Make strcpy_limit slightly more sane. --- Core/HLE/sceIo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index a1aad26ee0..76607a0038 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -1927,10 +1927,10 @@ u32 sceIoDopen(const char *path) { // For some reason strncpy will fill up the entire output buffer. No reason to do that, // so we use this trivial replacement. -static void strcpy_limit(char *dest, const char *src, int count) { +static void strcpy_limit(char *dest, const char *src, int limit) { int i; - for (i = 0; i < count; i++) { - if (!src[i]) // Do the check afterwards, so we don't exit before copying the null terminator. + for (i = 0; i < limit - 1; i++) { + if (!src[i]) break; dest[i] = src[i]; }