diff --git a/Core/FileSystems/BlobFileSystem.cpp b/Core/FileSystems/BlobFileSystem.cpp index 0f02bbd821..730dca7854 100644 --- a/Core/FileSystems/BlobFileSystem.cpp +++ b/Core/FileSystems/BlobFileSystem.cpp @@ -108,8 +108,8 @@ int BlobFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 out return -1; } -int BlobFileSystem::DevType(u32 handle) { - return -1; +PSPDevType BlobFileSystem::DevType(u32 handle) { + return PSPDevType::FILE; } bool BlobFileSystem::MkDir(const std::string &dirname) { diff --git a/Core/FileSystems/BlobFileSystem.h b/Core/FileSystems/BlobFileSystem.h index 2a877918d9..3657522ddd 100644 --- a/Core/FileSystems/BlobFileSystem.h +++ b/Core/FileSystems/BlobFileSystem.h @@ -43,8 +43,8 @@ public: PSPFileInfo GetFileInfo(std::string filename) override; bool OwnsHandle(u32 handle) override; int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override; - int DevType(u32 handle) override; - int Flags() override { return 0; } + PSPDevType DevType(u32 handle) override; + FileSystemFlags Flags() override { return FileSystemFlags::FLASH; } bool MkDir(const std::string &dirname) override; bool RmDir(const std::string &dirname) override; diff --git a/Core/FileSystems/BlockDevices.h b/Core/FileSystems/BlockDevices.h index 6e17aaa4ea..2db068c777 100644 --- a/Core/FileSystems/BlockDevices.h +++ b/Core/FileSystems/BlockDevices.h @@ -45,6 +45,7 @@ public: } int GetBlockSize() const { return 2048;} // forced, it cannot be changed by subclasses virtual u32 GetNumBlocks() = 0; + virtual bool IsDisc() = 0; u32 CalculateCRC(); void NotifyReadError(); @@ -60,6 +61,7 @@ public: bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override; bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override; u32 GetNumBlocks() override { return numBlocks; } + bool IsDisc() override { return true; } private: FileLoader *fileLoader_; @@ -83,6 +85,7 @@ public: bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override; bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override; u32 GetNumBlocks() override {return (u32)(filesize_ / GetBlockSize());} + bool IsDisc() override { return true; } private: FileLoader *fileLoader_; @@ -107,6 +110,7 @@ public: bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override; u32 GetNumBlocks() override {return (u32)lbaSize;} + bool IsDisc() override { return false; } private: FileLoader *fileLoader_; diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index f5bbf8e03b..1e38103ff2 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -150,7 +150,7 @@ bool FixPathCase(const std::string &basePath, std::string &path, FixPathCaseBeha #endif -DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath, int _flags) : basePath(_basePath), flags(_flags) { +DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath, FileSystemFlags _flags) : basePath(_basePath), flags(_flags) { File::CreateFullPath(basePath); hAlloc = _hAlloc; } @@ -663,8 +663,8 @@ int DirectoryFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u3 return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED; } -int DirectoryFileSystem::DevType(u32 handle) { - return PSP_DEV_TYPE_FILE; +PSPDevType DirectoryFileSystem::DevType(u32 handle) { + return PSPDevType::FILE; } size_t DirectoryFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) { @@ -742,11 +742,6 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) { File::FileDetails details; if (!File::GetFileDetails(fullName, &details)) { ERROR_LOG(FILESYS, "DirectoryFileSystem::GetFileInfo: GetFileDetails failed: %s", fullName.c_str()); - x.size = 0; - x.access = 0; - memset(&x.atime, 0, sizeof(x.atime)); - memset(&x.ctime, 0, sizeof(x.ctime)); - memset(&x.mtime, 0, sizeof(x.mtime)); } else { x.size = details.size; x.access = details.access; @@ -874,7 +869,9 @@ std::vector DirectoryFileSystem::GetDirListing(std::string path) { entry.size = 4096; else entry.size = findData.nFileSizeLow | ((u64)findData.nFileSizeHigh<<32); - entry.name = SimulateVFATBug(ConvertWStringToUTF8(findData.cFileName)); + entry.name = ConvertWStringToUTF8(findData.cFileName); + if (Flags() & FileSystemFlags::SIMULATE_FAT32) + entry.name = SimulateVFATBug(entry.name); bool hideFile = false; if (hideISOFiles && (endsWithNoCase(entry.name, ".cso") || endsWithNoCase(entry.name, ".iso"))) { @@ -921,7 +918,9 @@ std::vector DirectoryFileSystem::GetDirListing(std::string path) { else entry.type = FILETYPE_NORMAL; entry.access = s.st_mode & 0x1FF; - entry.name = SimulateVFATBug(dirp->d_name); + entry.name = dirp->d_name; + if (Flags() & FileSystemFlags::SIMULATE_FAT32) + entry.name = SimulateVFATBug(entry.name); entry.size = s.st_size; bool hideFile = false; @@ -1090,6 +1089,7 @@ PSPFileInfo VFSFileSystem::GetFileInfo(std::string filename) { if (x.exists) { x.size = fo.size; x.type = fo.isDirectory ? FILETYPE_DIRECTORY : FILETYPE_NORMAL; + x.access = fo.isWritable ? 0666 : 0444; } } else { x.exists = false; @@ -1117,8 +1117,8 @@ int VFSFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outd return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED; } -int VFSFileSystem::DevType(u32 handle) { - return PSP_DEV_TYPE_FILE; +PSPDevType VFSFileSystem::DevType(u32 handle) { + return PSPDevType::FILE; } size_t VFSFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) { diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index e00a4c4946..84e51bbf32 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -20,8 +20,7 @@ // TODO: Remove the Windows-specific code, FILE is fine there too. #include - -#include "../Core/FileSystems/FileSystem.h" +#include "Core/FileSystems/FileSystem.h" #ifdef _WIN32 typedef void * HANDLE; @@ -85,7 +84,7 @@ struct DirectoryFileHandle { class DirectoryFileSystem : public IFileSystem { public: - DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath, int _flags = 0); + DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath, FileSystemFlags _flags = FileSystemFlags::NONE); ~DirectoryFileSystem(); void CloseAll(); @@ -102,14 +101,14 @@ public: PSPFileInfo GetFileInfo(std::string filename) override; bool OwnsHandle(u32 handle) override; int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override; - int DevType(u32 handle) override; + PSPDevType DevType(u32 handle) override; bool MkDir(const std::string &dirname) override; bool RmDir(const std::string &dirname) override; int RenameFile(const std::string &from, const std::string &to) override; bool RemoveFile(const std::string &filename) override; bool GetHostPath(const std::string &inpath, std::string &outpath) override; - int Flags() override { return flags; } + FileSystemFlags Flags() override { return flags; } u64 FreeSpace(const std::string &path) override; private: @@ -123,7 +122,7 @@ private: EntryMap entries; std::string basePath; IHandleAllocator *hAlloc; - int flags; + FileSystemFlags flags; // In case of Windows: Translate slashes, etc. std::string GetLocalPath(std::string localpath); }; @@ -147,14 +146,14 @@ public: PSPFileInfo GetFileInfo(std::string filename) override; bool OwnsHandle(u32 handle) override; int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override; - int DevType(u32 handle) override; + PSPDevType DevType(u32 handle) override; bool MkDir(const std::string &dirname) override; bool RmDir(const std::string &dirname) override; int RenameFile(const std::string &from, const std::string &to) override; bool RemoveFile(const std::string &filename) override; bool GetHostPath(const std::string &inpath, std::string &outpath) override; - int Flags() override { return 0; } + FileSystemFlags Flags() override { return FileSystemFlags::FLASH; } u64 FreeSpace(const std::string &path) override { return 0; } private: diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index 4f87736613..6c069efe0d 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -20,6 +20,7 @@ #include #include #include +#include "base/basictypes.h" #include "Core/HLE/sceKernel.h" @@ -44,15 +45,24 @@ enum FileType { FILETYPE_DIRECTORY = 2 }; -enum DevType { - PSP_DEV_TYPE_BLOCK = 0x04, - PSP_DEV_TYPE_FILE = 0x10, - PSP_DEV_TYPE_ALIAS = 0x20, +enum class PSPDevType { + INVALID = 0, + BLOCK = 0x04, + FILE = 0x10, + ALIAS = 0x20, + EMU_MASK = 0xFF, + EMU_LBN = 0x10000, }; +ENUM_CLASS_BITOPS(PSPDevType); -enum FileSystemFlags { - FILESYSTEM_SIMULATE_FAT32 = 1, +enum class FileSystemFlags { + NONE = 0, + SIMULATE_FAT32 = 1, + UMD = 2, + CARD = 4, + FLASH = 8, }; +ENUM_CLASS_BITOPS(FileSystemFlags); class IHandleAllocator { public: @@ -78,29 +88,25 @@ private: }; struct PSPFileInfo { - PSPFileInfo() - : size(0), access(0), exists(false), type(FILETYPE_NORMAL), isOnSectorSystem(false), startSector(0), numSectors(0), sectorSize(0) { - memset(&ctime, 0, sizeof(ctime)); - memset(&atime, 0, sizeof(atime)); - memset(&mtime, 0, sizeof(mtime)); + PSPFileInfo() { } void DoState(PointerWrap &p); std::string name; - s64 size; - u32 access; //unix 777 - bool exists; - FileType type; + s64 size = 0; + u32 access = 0; //unix 777 + bool exists = false; + FileType type = FILETYPE_NORMAL; - tm atime; - tm ctime; - tm mtime; + tm atime{}; + tm ctime{}; + tm mtime{}; - bool isOnSectorSystem; - u32 startSector; - u32 numSectors; - u32 sectorSize; + bool isOnSectorSystem = false; + u32 startSector = 0; + u32 numSectors = 0; + u32 sectorSize = 0; }; @@ -125,8 +131,8 @@ public: virtual bool RemoveFile(const std::string &filename) = 0; 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; + virtual PSPDevType DevType(u32 handle) = 0; + virtual FileSystemFlags Flags() = 0; virtual u64 FreeSpace(const std::string &path) = 0; }; @@ -151,8 +157,8 @@ public: virtual bool RemoveFile(const std::string &filename) override {return false;} virtual bool GetHostPath(const std::string &inpath, std::string &outpath) override {return false;} virtual int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override {return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED; } - virtual int DevType(u32 handle) override { return 0; } - virtual int Flags() override { return 0; } + virtual PSPDevType DevType(u32 handle) override { return PSPDevType::INVALID; } + virtual FileSystemFlags Flags() override { return FileSystemFlags::NONE; } virtual u64 FreeSpace(const std::string &path) override { return 0; } }; diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index 39e54b8bb6..3f481a2f9b 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -461,10 +461,18 @@ int ISOFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outd return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED; } -int ISOFileSystem::DevType(u32 handle) -{ +PSPDevType ISOFileSystem::DevType(u32 handle) { EntryMap::iterator iter = entries.find(handle); - return iter->second.isBlockSectorMode ? PSP_DEV_TYPE_BLOCK : PSP_DEV_TYPE_FILE; + PSPDevType type = iter->second.isBlockSectorMode ? PSPDevType::BLOCK : PSPDevType::FILE; + if (iter->second.isRawSector) + type |= PSPDevType::EMU_LBN; + return type; +} + +FileSystemFlags ISOFileSystem::Flags() { + // TODO: Here may be a good place to force things, in case users recompress games + // as PBP or CSO when they were originally the other type. + return blockDevice->IsDisc() ? FileSystemFlags::UMD : FileSystemFlags::CARD; } size_t ISOFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) @@ -607,7 +615,9 @@ PSPFileInfo ISOFileSystem::GetFileInfo(std::string filename) { PSPFileInfo fileInfo; fileInfo.name = filename; fileInfo.exists = true; + fileInfo.type = FILETYPE_NORMAL; fileInfo.size = readSize; + fileInfo.access = 0444; fileInfo.startSector = sectorStart; fileInfo.isOnSectorSystem = true; fileInfo.numSectors = (readSize + sectorSize - 1) / sectorSize; @@ -616,12 +626,10 @@ PSPFileInfo ISOFileSystem::GetFileInfo(std::string filename) { TreeEntry *entry = GetFromPath(filename, false); PSPFileInfo x; - if (!entry) { - x.size = 0; - x.exists = false; - } else { + if (entry) { x.name = entry->name; - x.access = FILEACCESS_READ; + // Strangely, it seems to be executable even for files. + x.access = 0555; x.size = entry->size; x.exists = true; x.type = entry->isDirectory ? FILETYPE_DIRECTORY : FILETYPE_NORMAL; @@ -649,16 +657,14 @@ std::vector ISOFileSystem::GetDirListing(std::string path) { PSPFileInfo x; x.name = e->name; - x.access = FILEACCESS_READ; + // Strangely, it seems to be executable even for files. + x.access = 0555; x.size = e->size; x.type = e->isDirectory ? FILETYPE_DIRECTORY : FILETYPE_NORMAL; x.isOnSectorSystem = true; x.startSector = e->startingPosition/2048; x.sectorSize = sectorSize; x.numSectors = (u32)((e->size + sectorSize - 1) / sectorSize); - memset(&x.atime, 0, sizeof(x.atime)); - memset(&x.mtime, 0, sizeof(x.mtime)); - memset(&x.ctime, 0, sizeof(x.ctime)); myVector.push_back(x); } return myVector; diff --git a/Core/FileSystems/ISOFileSystem.h b/Core/FileSystems/ISOFileSystem.h index 34b24bb081..273d845301 100644 --- a/Core/FileSystems/ISOFileSystem.h +++ b/Core/FileSystems/ISOFileSystem.h @@ -41,8 +41,8 @@ public: PSPFileInfo GetFileInfo(std::string filename) override; bool OwnsHandle(u32 handle) override; int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override; - int DevType(u32 handle) override; - int Flags() override { return 0; } + PSPDevType DevType(u32 handle) override; + FileSystemFlags Flags() override; u64 FreeSpace(const std::string &path) override { return 0; } size_t WriteFile(u32 handle, const u8 *pointer, s64 size) override; @@ -134,10 +134,10 @@ public: int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override { return isoFileSystem_->Ioctl(handle, cmd, indataPtr, inlen, outdataPtr, outlen, usec); } - int DevType(u32 handle) override { + PSPDevType DevType(u32 handle) override { return isoFileSystem_->DevType(handle); } - int Flags() override { return isoFileSystem_->Flags(); } + FileSystemFlags Flags() override { return isoFileSystem_->Flags(); } u64 FreeSpace(const std::string &path) override { return isoFileSystem_->FreeSpace(path); } size_t WriteFile(u32 handle, const u8 *pointer, s64 size) override { diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 19bddf251e..3b6d487e9f 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -178,7 +178,7 @@ IFileSystem *MetaFileSystem::GetHandleOwner(u32 handle) int MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpath, MountPoint **system) { - int error = -1; + int error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND; std::lock_guard guard(lock); std::string realpath; @@ -246,6 +246,8 @@ int MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpath return error == SCE_KERNEL_ERROR_NOCWD ? error : 0; } } + + error = SCE_KERNEL_ERROR_NODEV; } DEBUG_LOG(FILESYS, "MapFilePath: failed mapping \"%s\", returning false", inpath.c_str()); @@ -256,8 +258,8 @@ std::string MetaFileSystem::NormalizePrefix(std::string prefix) const { // Let's apply some mapping here since it won't break savestates. if (prefix == "memstick:") prefix = "ms0:"; - // Seems like umd00: etc. work just fine... - if (startsWith(prefix, "umd")) + // Seems like umd00: etc. work just fine... avoid umd1/umd for tests. + if (startsWith(prefix, "umd") && prefix != "umd1:" && prefix != "umd:") prefix = "umd0:"; // Seems like umd00: etc. work just fine... if (startsWith(prefix, "host")) @@ -353,7 +355,7 @@ int MetaFileSystem::OpenFile(std::string filename, FileAccess access, const char if (error == 0) return mount->system->OpenFile(of, access, mount->prefix.c_str()); else - return error == -1 ? SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND : error; + return error; } PSPFileInfo MetaFileSystem::GetFileInfo(std::string filename) @@ -368,7 +370,7 @@ PSPFileInfo MetaFileSystem::GetFileInfo(std::string filename) } else { - PSPFileInfo bogus; // TODO + PSPFileInfo bogus; return bogus; } } @@ -536,13 +538,13 @@ int MetaFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 out return SCE_KERNEL_ERROR_ERROR; } -int MetaFileSystem::DevType(u32 handle) +PSPDevType MetaFileSystem::DevType(u32 handle) { std::lock_guard guard(lock); IFileSystem *sys = GetHandleOwner(handle); if (sys) return sys->DevType(handle); - return SCE_KERNEL_ERROR_ERROR; + return PSPDevType::INVALID; } void MetaFileSystem::CloseFile(u32 handle) diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index c4bfd8d37f..8294ba16da 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -56,6 +56,10 @@ public: IFileSystem *GetSystem(const std::string &prefix); IFileSystem *GetSystemFromFilename(const std::string &filename); + FileSystemFlags FlagsFromFilename(const std::string &filename) { + IFileSystem *sys = GetSystemFromFilename(filename); + return sys ? sys->Flags() : FileSystemFlags::NONE; + } void ThreadEnded(int threadID); @@ -114,8 +118,8 @@ public: int RenameFile(const std::string &from, const std::string &to) override; bool RemoveFile(const std::string &filename) override; int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override; - int DevType(u32 handle) override; - int Flags() override { return 0; } + PSPDevType DevType(u32 handle) override; + FileSystemFlags Flags() override { return FileSystemFlags::NONE; } u64 FreeSpace(const std::string &path) override; // Convenience helper - returns < 0 on failure. diff --git a/Core/FileSystems/VirtualDiscFileSystem.cpp b/Core/FileSystems/VirtualDiscFileSystem.cpp index 7ff3dc07ed..81ecbeef57 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.cpp +++ b/Core/FileSystems/VirtualDiscFileSystem.cpp @@ -552,9 +552,12 @@ int VirtualDiscFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED; } -int VirtualDiscFileSystem::DevType(u32 handle) { +PSPDevType VirtualDiscFileSystem::DevType(u32 handle) { EntryMap::iterator iter = entries.find(handle); - return iter->second.type == VFILETYPE_ISO ? PSP_DEV_TYPE_BLOCK : PSP_DEV_TYPE_FILE; + PSPDevType type = iter->second.type == VFILETYPE_ISO ? PSPDevType::BLOCK : PSPDevType::FILE; + if (iter->second.type == VFILETYPE_LBN) + type |= PSPDevType::EMU_LBN; + return type; } PSPFileInfo VirtualDiscFileSystem::GetFileInfo(std::string filename) { @@ -569,7 +572,9 @@ PSPFileInfo VirtualDiscFileSystem::GetFileInfo(std::string filename) { PSPFileInfo fileInfo; fileInfo.name = filename; fileInfo.exists = true; + fileInfo.type = FILETYPE_NORMAL; fileInfo.size = readSize; + fileInfo.access = 0444; fileInfo.startSector = sectorStart; fileInfo.isOnSectorSystem = true; fileInfo.numSectors = (readSize + 2047) / 2048; @@ -581,6 +586,7 @@ PSPFileInfo VirtualDiscFileSystem::GetFileInfo(std::string filename) { x.type = FILETYPE_NORMAL; x.isOnSectorSystem = true; x.startSector = fileList[fileIndex].firstBlock; + x.access = 0555; HandlerFileHandle temp = fileList[fileIndex].handler; if (temp.Open(basePath, filename, FILEACCESS_READ)) { @@ -609,6 +615,7 @@ PSPFileInfo VirtualDiscFileSystem::GetFileInfo(std::string filename) { x.type = File::IsDirectory(fullName) ? FILETYPE_DIRECTORY : FILETYPE_NORMAL; x.exists = true; + x.access = 0555; if (fileIndex != -1) { x.isOnSectorSystem = true; x.startSector = fileList[fileIndex].firstBlock; @@ -620,12 +627,8 @@ PSPFileInfo VirtualDiscFileSystem::GetFileInfo(std::string filename) { ERROR_LOG(FILESYS, "DirectoryFileSystem::GetFileInfo: GetFileDetails failed: %s", fullName.c_str()); x.size = 0; x.access = 0; - memset(&x.atime, 0, sizeof(x.atime)); - memset(&x.ctime, 0, sizeof(x.ctime)); - memset(&x.mtime, 0, sizeof(x.mtime)); } else { x.size = details.size; - x.access = details.access; time_t atime = details.atime; time_t ctime = details.ctime; time_t mtime = details.mtime; @@ -690,7 +693,7 @@ std::vector VirtualDiscFileSystem::GetDirListing(std::string path) entry.type = FILETYPE_NORMAL; } - entry.access = FILEACCESS_READ; + entry.access = 0555; entry.size = findData.nFileSizeLow | ((u64)findData.nFileSizeHigh<<32); entry.name = ConvertWStringToUTF8(findData.cFileName); tmFromFiletime(entry.atime, findData.ftLastAccessTime); @@ -736,7 +739,7 @@ std::vector VirtualDiscFileSystem::GetDirListing(std::string path) entry.type = FILETYPE_DIRECTORY; else entry.type = FILETYPE_NORMAL; - entry.access = s.st_mode & 0x1FF; + entry.access = 0555; entry.name = dirp->d_name; entry.size = s.st_size; localtime_r((time_t*)&s.st_atime,&entry.atime); diff --git a/Core/FileSystems/VirtualDiscFileSystem.h b/Core/FileSystems/VirtualDiscFileSystem.h index b4ad72924b..cdf6a54ccd 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.h +++ b/Core/FileSystems/VirtualDiscFileSystem.h @@ -38,10 +38,10 @@ public: PSPFileInfo GetFileInfo(std::string filename) override; bool OwnsHandle(u32 handle) override; int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override; - int DevType(u32 handle) override; + PSPDevType DevType(u32 handle) override; bool GetHostPath(const std::string &inpath, std::string &outpath) override; std::vector GetDirListing(std::string path) override; - int Flags() override { return 0; } + FileSystemFlags Flags() override { return FileSystemFlags::UMD; } u64 FreeSpace(const std::string &path) override { return 0; } // unsupported operations diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index fad7769c02..d49005228a 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -621,9 +621,9 @@ void __IoInit() { asyncNotifyEvent = CoreTiming::RegisterEvent("IoAsyncNotify", __IoAsyncNotify); syncNotifyEvent = CoreTiming::RegisterEvent("IoSyncNotify", __IoSyncNotify); - memstickSystem = new DirectoryFileSystem(&pspFileSystem, g_Config.memStickDirectory, FILESYSTEM_SIMULATE_FAT32); + memstickSystem = new DirectoryFileSystem(&pspFileSystem, g_Config.memStickDirectory, FileSystemFlags::SIMULATE_FAT32 | FileSystemFlags::CARD); #if defined(USING_WIN_UI) || defined(APPLE) - flash0System = new DirectoryFileSystem(&pspFileSystem, g_Config.flash0Directory); + flash0System = new DirectoryFileSystem(&pspFileSystem, g_Config.flash0Directory, FileSystemFlags::FLASH); #else flash0System = new VFSFileSystem(&pspFileSystem, "flash0"); #endif @@ -637,7 +637,7 @@ void __IoInit() { const std::string gameId = g_paramSFO.GetValueString("DISC_ID"); const std::string exdataPath = g_Config.memStickDirectory + "exdata/" + gameId + "/"; if (File::Exists(exdataPath)) { - exdataSystem = new DirectoryFileSystem(&pspFileSystem, exdataPath, FILESYSTEM_SIMULATE_FAT32); + exdataSystem = new DirectoryFileSystem(&pspFileSystem, exdataPath, FileSystemFlags::SIMULATE_FAT32 | FileSystemFlags::CARD); pspFileSystem.Mount("exdata0:", exdataSystem); INFO_LOG(SCEIO, "Mounted exdata/%s/ under memstick for exdata0:/", gameId.c_str()); } else { @@ -1251,7 +1251,7 @@ static u32 sceIoWriteAsync(int id, u32 data_addr, int size) { static u32 sceIoGetDevType(int id) { if (id == PSP_STDOUT || id == PSP_STDERR || id == PSP_STDIN) { DEBUG_LOG(SCEIO, "sceIoGetDevType(%d)", id); - return PSP_DEV_TYPE_FILE; + return (u32)PSPDevType::FILE; } u32 error; @@ -1260,7 +1260,7 @@ static u32 sceIoGetDevType(int id) { if (f) { // TODO: When would this return PSP_DEV_TYPE_ALIAS? WARN_LOG(SCEIO, "sceIoGetDevType(%d - %s)", id, f->fullpath.c_str()); - result = pspFileSystem.DevType(f->handle); + result = (u32)pspFileSystem.DevType(f->handle) & (u32)PSPDevType::EMU_MASK; } else { ERROR_LOG(SCEIO, "sceIoGetDevType: unknown id %d", id); result = SCE_KERNEL_ERROR_BADF; @@ -1429,8 +1429,7 @@ static u32 sceIoLseek32Async(int id, int offset, int whence) { return 0; } -static FileNode *__IoOpen(int &error, const char* filename, int flags, int mode) { - //memory stick filename +static FileNode *__IoOpen(int &error, const char *filename, int flags, int mode) { int access = FILEACCESS_NONE; if (flags & PSP_O_RDONLY) access |= FILEACCESS_READ; @@ -1469,41 +1468,49 @@ static FileNode *__IoOpen(int &error, const char* filename, int flags, int mode) } static u32 sceIoOpen(const char *filename, int flags, int mode) { - if (!__KernelIsDispatchEnabled()) - return -1; + hleEatCycles(18000); + + if (!__KernelIsDispatchEnabled()) { + hleEatCycles(48000); + return hleLogError(SCEIO, SCE_KERNEL_ERROR_CAN_NOT_WAIT, "dispatch disabled"); + } int error; FileNode *f = __IoOpen(error, filename, flags, mode); - if (f == NULL) - { - // Timing is not accurate, aiming low for now. - if (error == (int)SCE_KERNEL_ERROR_NOCWD) - { - ERROR_LOG(SCEIO, "SCE_KERNEL_ERROR_NOCWD=sceIoOpen(%s, %08x, %08x) - no current working directory", filename, flags, mode); - return hleDelayResult(SCE_KERNEL_ERROR_NOCWD, "no cwd", 10000); - } - else if (error != 0) - { - ERROR_LOG(SCEIO, "%08x=sceIoOpen(%s, %08x, %08x)", error, filename, flags, mode); - return hleDelayResult(error, "file opened", 10000); - } - else - { - ERROR_LOG(SCEIO, "ERROR_ERRNO_FILE_NOT_FOUND=sceIoOpen(%s, %08x, %08x) - file not found", filename, flags, mode); - return hleDelayResult(SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND, "file opened", 10000); + if (!f) { + assert(error != 0); + if (error == (int)SCE_KERNEL_ERROR_NOCWD) { + // TODO: Timing is not accurate. + return hleLogError(SCEIO, hleDelayResult(error, "file opened", 10000), "no current working directory"); + } else if (error == (int)SCE_KERNEL_ERROR_NODEV) { + return hleLogError(SCEIO, error, "device not found"); + } else if (error == (int)SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND) { + // UMD: Varies between 5-10ms, could take longer if disc spins up. + // TODO: Bad filename at root (disc0:/no.exist) should take ~200us. + // Card: Path depth matters, but typically between 10-13ms on a standard Pro Duo. + // TODO: If a UMD and spun down, this can easily take 1s+. + int delay = pspFileSystem.FlagsFromFilename(filename) & FileSystemFlags::UMD ? 6000 : 10000; + return hleLogWarning(SCEIO, hleDelayResult(error, "file opened", delay), "file not found"); + } else { + return hleLogError(SCEIO, hleDelayResult(error, "file opened", 10000)); } } int id = __IoAllocFd(f); if (id < 0) { - ERROR_LOG(SCEIO, "%08x=sceIoOpen(%s, %08x, %08x): out of fds", id, filename, flags, mode); kernelObjects.Destroy(f->GetUID()); - return id; + return hleLogError(SCEIO, hleDelayResult(id, "file opened", 1000), "out of fds"); } else { - DEBUG_LOG(SCEIO, "%i=sceIoOpen(%s, %08x, %08x)", id, filename, flags, mode); asyncParams[id].priority = asyncDefaultPriority; - // Timing is not accurate, aiming low for now. - return hleDelayResult(id, "file opened", 100); + IFileSystem *sys = pspFileSystem.GetSystemFromFilename(filename); + if (sys && (sys->DevType(f->handle) & (PSPDevType::BLOCK | PSPDevType::EMU_LBN))) { + // These are fast to open, no delay or even rescheduling happens. + return hleLogSuccessI(SCEIO, id); + } + // UMD: Speed varies from 1-6ms. + // Card: Path depth matters, but typically between 10-13ms on a standard Pro Duo. + int delay = pspFileSystem.FlagsFromFilename(filename) & FileSystemFlags::UMD ? 4000 : 10000; + return hleLogSuccessI(SCEIO, hleDelayResult(id, "file opened", delay)); } } @@ -2038,8 +2045,9 @@ static u32 sceIoSetAsyncCallback(int id, u32 clbckId, u32 clbckArg) } } -static u32 sceIoOpenAsync(const char *filename, int flags, int mode) -{ +static u32 sceIoOpenAsync(const char *filename, int flags, int mode) { + hleEatCycles(18000); + // TOOD: Use an internal method so as not to pollute the log? // Intentionally does not work when interrupts disabled. if (!__KernelIsDispatchEnabled()) @@ -2050,8 +2058,9 @@ static u32 sceIoOpenAsync(const char *filename, int flags, int mode) // We have to return an fd here, which may have been destroyed when we reach Wait if it failed. if (f == nullptr) { - if (error == 0) - error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND; + assert(error != 0); + if (error == SCE_KERNEL_ERROR_NODEV) + return hleLogError(SCEIO, error, "device not found"); f = new FileNode(); f->handle = kernelObjects.Create(f); @@ -2063,7 +2072,7 @@ static u32 sceIoOpenAsync(const char *filename, int flags, int mode) int fd = __IoAllocFd(f); if (fd < 0) { kernelObjects.Destroy(f->GetUID()); - return hleLogError(SCEIO, fd, "out of fds"); + return hleLogError(SCEIO, hleDelayResult(fd, "file opened", 1000), "out of fds"); } auto ¶ms = asyncParams[fd]; @@ -2299,13 +2308,7 @@ static 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; - + bool isFAT = pspFileSystem.FlagsFromFilename(dir->name) & FileSystemFlags::SIMULATE_FAT32; // Only write d_private for memory stick if (isFAT) { // write d_private for supporting Custom BGM @@ -2718,10 +2721,24 @@ static int IoAsyncFinish(int id) { break; case IoAsyncOp::OPEN: - // TODO: Timing is very inconsistent. From ms0, 10ms - 20ms depending on filesize/dir depth? From umd, can take > 1s. - // For now let's aim low. - us = 100; + { + // See notes on timing in sceIoOpen. + const std::string filename = Memory::GetCharPointer(params.open.filenameAddr); + IFileSystem *sys = pspFileSystem.GetSystemFromFilename(filename); + if (sys) { + if (f->asyncResult == (int)SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND) { + us = sys->Flags() & FileSystemFlags::UMD ? 6000 : 10000; + } else if (sys->DevType(f->handle) & (PSPDevType::BLOCK | PSPDevType::EMU_LBN)) { + // These are fast to open, no delay or even rescheduling happens. + us = 80; + } else { + us = sys->Flags() & FileSystemFlags::UMD ? 4000 : 10000; + } + } else { + us = 80; + } break; + } case IoAsyncOp::CLOSE: f->asyncResult = 0; diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 8f61f3542c..53bdc35722 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -340,10 +340,11 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { auto bd = constructBlockDevice(PSP_CoreParameter().mountIsoLoader); if (bd != NULL) { ISOFileSystem *umd2 = new ISOFileSystem(&pspFileSystem, bd); + ISOBlockSystem *blockSystem = new ISOBlockSystem(umd2); - pspFileSystem.Mount("umd1:", umd2); + pspFileSystem.Mount("umd1:", blockSystem); pspFileSystem.Mount("disc0:", umd2); - pspFileSystem.Mount("umd:", umd2); + pspFileSystem.Mount("umd:", blockSystem); } } @@ -386,7 +387,7 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { pspFileSystem.SetStartingDirectory(ms_path); } - DirectoryFileSystem *fs = new DirectoryFileSystem(&pspFileSystem, path); + DirectoryFileSystem *fs = new DirectoryFileSystem(&pspFileSystem, path, FileSystemFlags::SIMULATE_FAT32 | FileSystemFlags::CARD); pspFileSystem.Mount("umd0:", fs); std::string finalName = ms_path + file + extension; diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h index 30395ab161..d08f556c98 100644 --- a/GPU/Common/PresentationCommon.h +++ b/GPU/Common/PresentationCommon.h @@ -17,6 +17,7 @@ #pragma once +#include "base/basictypes.h" #include "GPU/Common/ShaderCommon.h" struct CardboardSettings { @@ -69,17 +70,7 @@ enum class OutputFlags { POSITION_FLIPPED = 0x0008, PILLARBOX = 0x0010, }; - -inline OutputFlags operator | (const OutputFlags &lhs, const OutputFlags &rhs) { - return OutputFlags((int)lhs | (int)rhs); -} -inline OutputFlags operator |= (OutputFlags &lhs, const OutputFlags &rhs) { - lhs = lhs | rhs; - return lhs; -} -inline bool operator & (const OutputFlags &lhs, const OutputFlags &rhs) { - return ((int)lhs & (int)rhs) != 0; -} +ENUM_CLASS_BITOPS(OutputFlags); class PresentationCommon { public: diff --git a/UI/MainScreen.h b/UI/MainScreen.h index 832d104043..fe1b09ad4b 100644 --- a/UI/MainScreen.h +++ b/UI/MainScreen.h @@ -36,14 +36,7 @@ enum class BrowseFlags { HOMEBREW_STORE = 8, STANDARD = 1 | 2 | 4, }; - -static inline BrowseFlags operator |(const BrowseFlags &lhs, const BrowseFlags &rhs) { - return BrowseFlags((int)lhs | (int)rhs); -} - -static inline bool operator &(const BrowseFlags &lhs, const BrowseFlags &rhs) { - return ((int)lhs & (int)rhs) != 0; -} +ENUM_CLASS_BITOPS(BrowseFlags); class GameBrowser : public UI::LinearLayout { public: diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index 78801f6145..fe06b18d83 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -928,7 +928,7 @@ namespace MainWindow { u32 handle = pspFileSystem.OpenFile(filename, FILEACCESS_READ, ""); // Note: len may be in blocks. size_t len = pspFileSystem.SeekFile(handle, 0, FILEMOVE_END); - bool isBlockMode = pspFileSystem.DevType(handle) == PSP_DEV_TYPE_BLOCK; + bool isBlockMode = pspFileSystem.DevType(handle) & PSPDevType::BLOCK; FILE *fp = File::OpenCFile(fn, "wb"); pspFileSystem.SeekFile(handle, 0, FILEMOVE_BEGIN); diff --git a/ext/native/base/basictypes.h b/ext/native/base/basictypes.h index 8cd0fd0e1e..2f9c7d0321 100644 --- a/ext/native/base/basictypes.h +++ b/ext/native/base/basictypes.h @@ -14,6 +14,20 @@ void operator =(const t &other) = delete; #endif +#ifndef ENUM_CLASS_BITOPS +#define ENUM_CLASS_BITOPS(T) \ + static inline T operator |(const T &lhs, const T &rhs) { \ + return T((int)lhs | (int)rhs); \ + } \ + static inline T &operator |= (T &lhs, const T &rhs) { \ + lhs = lhs | rhs; \ + return lhs; \ + } \ + static inline bool operator &(const T &lhs, const T &rhs) { \ + return ((int)lhs & (int)rhs) != 0; \ + } +#endif + #ifdef _WIN32 typedef intptr_t ssize_t;