diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index e83d0dab60..8b096f410c 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -895,34 +895,22 @@ int SavedataParam::BuildHash(unsigned char *output, return 0; } -std::string SavedataParam::GetSpaceText(int size) +std::string SavedataParam::GetSpaceText(u64 size) { + static const char *suffixes[] = {"B", "KB", "MB", "GB"}; char text[50]; - if(size < 1024) + for (size_t i = 0; i < ARRAY_SIZE(suffixes); ++i) { - sprintf(text,"%d B",size); - return std::string(text); + if (size < 1024) + { + snprintf(text, sizeof(text), "%d %s", size, suffixes[i]); + return std::string(text); + } + size /= 1024; } - size /= 1024; - - if(size < 1024) - { - sprintf(text,"%d KB",size); - return std::string(text); - } - - size /= 1024; - - if(size < 1024) - { - sprintf(text,"%d MB",size); - return std::string(text); - } - - size /= 1024; - sprintf(text,"%d GB",size); + snprintf(text, sizeof(text), "%d TB"); return std::string(text); } @@ -936,10 +924,11 @@ int SavedataParam::GetSizes(SceUtilitySavedataParam *param) if (param->msFree.IsValid()) { + const u64 freeBytes = MemoryStick_FreeSpace(); param->msFree->clusterSize = (u32)MemoryStick_SectorSize(); - param->msFree->freeClusters = (u32)(MemoryStick_FreeSpace() / MemoryStick_SectorSize()); - param->msFree->freeSpaceKB = (u32)(MemoryStick_FreeSpace() / 0x400); - const std::string spaceTxt = SavedataParam::GetSpaceText((int)MemoryStick_FreeSpace()); + param->msFree->freeClusters = (u32)(freeBytes / MemoryStick_SectorSize()); + param->msFree->freeSpaceKB = (u32)(freeBytes / 0x400); + const std::string spaceTxt = SavedataParam::GetSpaceText(freeBytes); memset(param->msFree->freeSpaceStr, 0, sizeof(param->msFree->freeSpaceStr)); strncpy(param->msFree->freeSpaceStr, spaceTxt.c_str(), sizeof(param->msFree->freeSpaceStr)); } @@ -1184,14 +1173,15 @@ bool SavedataParam::GetSize(SceUtilitySavedataParam *param) if (param->sizeInfo.IsValid()) { + const u64 freeBytes = MemoryStick_FreeSpace(); // TODO: Read the entries and count up the size vs. existing size? param->sizeInfo->sectorSize = (int)MemoryStick_SectorSize(); - param->sizeInfo->freeSectors = (int)(MemoryStick_FreeSpace() / MemoryStick_SectorSize()); + param->sizeInfo->freeSectors = (int)(freeBytes / MemoryStick_SectorSize()); // TODO: Is this after the specified files? Before? - param->sizeInfo->freeKB = (int)(MemoryStick_FreeSpace() / 1024); - std::string spaceTxt = SavedataParam::GetSpaceText((int)MemoryStick_FreeSpace()); + param->sizeInfo->freeKB = (int)(freeBytes / 1024); + std::string spaceTxt = SavedataParam::GetSpaceText(freeBytes); strncpy(param->sizeInfo->freeString, spaceTxt.c_str(), 8); param->sizeInfo->freeString[7] = '\0'; diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index 6745bd6a20..0dc0aaae57 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -323,7 +323,7 @@ public: std::string GetKey(const SceUtilitySavedataParam *param) const; bool HasKey(const SceUtilitySavedataParam *param) const; - static std::string GetSpaceText(int size); + static std::string GetSpaceText(u64 size); int SetPspParam(SceUtilitySavedataParam* param); SceUtilitySavedataParam *GetPspParam(); diff --git a/Core/FileSystems/BlockDevices.cpp b/Core/FileSystems/BlockDevices.cpp index 73a0549a91..12a0a205f0 100644 --- a/Core/FileSystems/BlockDevices.cpp +++ b/Core/FileSystems/BlockDevices.cpp @@ -293,7 +293,7 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr) } if (z.total_out != frameSize) { - ERROR_LOG(LOADER, "block %d: block size error %d != %d\n", blockNumber, z.total_out, frameSize); + ERROR_LOG(LOADER, "block %d: block size error %d != %d\n", blockNumber, (u32)z.total_out, frameSize); inflateEnd(&z); memset(outPtr, 0, GetBlockSize()); return false; diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 142be2ab3c..7bfcf47d0e 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include #include "ChunkFile.h" #include "FileUtil.h" #include "DirectoryFileSystem.h" @@ -30,6 +31,13 @@ #include #include #include +#if defined(ANDROID) +#include +#include +#define statvfs statfs +#elif !defined(__SYMBIAN32__) +#include +#endif #include #include #endif @@ -687,7 +695,7 @@ std::vector DirectoryFileSystem::GetDirListing(std::string path) { DIR *dp = opendir(localPath.c_str()); #if HOST_IS_CASE_SENSITIVE - if(dp == NULL && FixPathCase(basePath,path, FPC_FILE_MUST_EXIST)) { + if (dp == NULL && FixPathCase(basePath,path, FPC_FILE_MUST_EXIST)) { // May have failed due to case sensitivity, try again localPath = GetLocalPath(path); dp = opendir(localPath.c_str()); @@ -721,6 +729,40 @@ std::vector DirectoryFileSystem::GetDirListing(std::string path) { return myVector; } +u64 DirectoryFileSystem::FreeSpace(const std::string &path) { +#ifdef _WIN32 + const std::wstring w32path = ConvertUTF8ToWString(GetLocalPath(path)); + ULARGE_INTEGER free; + if (GetDiskFreeSpaceExW(w32path.c_str(), &free, nullptr, nullptr)) + return free.QuadPart; +#elif !defined(__SYMBIAN32__) + std::string localPath = GetLocalPath(path); + struct statvfs diskstat; + int res = statvfs(localPath.c_str(), &diskstat); + +#if HOST_IS_CASE_SENSITIVE + std::string fixedCase = path; + if (res != 0 && FixPathCase(basePath, fixedCase, FPC_FILE_MUST_EXIST)) { + // May have failed due to case sensitivity, try again. + localPath = GetLocalPath(fixedCase); + res = statvfs(localPath.c_str(), &diskstat); + } +#endif + + if (res == 0) { +#ifndef ANDROID + if (diskstat.f_flag & ST_RDONLY) { + return 0; + } +#endif + return (u64)diskstat.f_bavail * (u64)diskstat.f_frsize; + } +#endif + + // Just assume they're swimming in free disk space if we don't know otherwise. + return std::numeric_limits::max(); +} + void DirectoryFileSystem::DoState(PointerWrap &p) { auto s = p.Section("DirectoryFileSystem", 0, 2); if (!s) diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index 7d6a8793bc..dd39c9196f 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -109,6 +109,7 @@ public: bool RemoveFile(const std::string &filename); bool GetHostPath(const std::string &inpath, std::string &outpath); int Flags() { return flags; } + u64 FreeSpace(const std::string &path) override; private: struct OpenFileEntry { @@ -151,6 +152,7 @@ public: bool RemoveFile(const std::string &filename); bool GetHostPath(const std::string &inpath, std::string &outpath); int Flags() { return 0; } + u64 FreeSpace(const std::string &path) override { return 0; } private: struct OpenFileEntry { diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index 82855b9b44..eaf6241acf 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -117,6 +117,7 @@ public: 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 u64 FreeSpace(const std::string &path) = 0; }; @@ -140,6 +141,7 @@ public: 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 Flags() { return 0; } + virtual u64 FreeSpace(const std::string &path) override { return 0; } }; diff --git a/Core/FileSystems/ISOFileSystem.h b/Core/FileSystems/ISOFileSystem.h index cefe3eba07..084546f1a2 100644 --- a/Core/FileSystems/ISOFileSystem.h +++ b/Core/FileSystems/ISOFileSystem.h @@ -43,6 +43,7 @@ public: 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; } + u64 FreeSpace(const std::string &path) override { return 0; } size_t WriteFile(u32 handle, const u8 *pointer, s64 size) override; bool GetHostPath(const std::string &inpath, std::string &outpath) {return false;} @@ -131,6 +132,7 @@ public: return isoFileSystem_->DevType(handle); } int 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 { return isoFileSystem_->WriteFile(handle, pointer, size); diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index c52ca15d8f..27ea5bc119 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -591,6 +591,17 @@ int MetaFileSystem::ReadEntireFile(const std::string &filename, std::vector return 0; } +u64 MetaFileSystem::FreeSpace(const std::string &path) +{ + lock_guard guard(lock); + std::string of; + IFileSystem *system; + if (MapFilePath(path, of, &system)) + return system->FreeSpace(of); + else + return 0; +} + void MetaFileSystem::DoState(PointerWrap &p) { lock_guard guard(lock); diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index 7d9eb8ba4d..63adea1474 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -108,6 +108,7 @@ public: 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; } + virtual u64 FreeSpace(const std::string &path) override; // 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 42b09abb81..d1d5e45bf9 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.h +++ b/Core/FileSystems/VirtualDiscFileSystem.h @@ -41,6 +41,7 @@ public: bool GetHostPath(const std::string &inpath, std::string &outpath); std::vector GetDirListing(std::string path); int Flags() { return 0; } + u64 FreeSpace(const std::string &path) override { 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 37728c60e7..6b778316c0 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -438,7 +438,7 @@ void __IoWakeManager() { } void __IoInit() { - MemoryStick_SetFatState(PSP_FAT_MEMORYSTICK_STATE_ASSIGNED); + MemoryStick_Init(); asyncNotifyEvent = CoreTiming::RegisterEvent("IoAsyncNotify", __IoAsyncNotify); syncNotifyEvent = CoreTiming::RegisterEvent("IoSyncNotify", __IoSyncNotify); diff --git a/Core/HW/MemoryStick.cpp b/Core/HW/MemoryStick.cpp index 1029d9770b..d1a9a5e118 100644 --- a/Core/HW/MemoryStick.cpp +++ b/Core/HW/MemoryStick.cpp @@ -1,18 +1,26 @@ -#include "MemoryStick.h" -#include "ChunkFile.h" +#include "Common/ChunkFile.h" +#include "Core/FileSystems/MetaFileSystem.h" +#include "Core/HW/MemoryStick.h" +#include "Core/System.h" // MS and FatMS states. -static MemStickState memStickState = PSP_MEMORYSTICK_STATE_DRIVER_READY; -static MemStickFatState memStickFatState = PSP_FAT_MEMORYSTICK_STATE_ASSIGNED; +static MemStickState memStickState; +static MemStickFatState memStickFatState; +static u64 memStickSize; void MemoryStick_DoState(PointerWrap &p) { - auto s = p.Section("MemoryStick", 1); + auto s = p.Section("MemoryStick", 1, 2); if (!s) return; p.Do(memStickState); p.Do(memStickFatState); + if (s >= 2) + p.Do(memStickSize); + else + memStickSize = 1ULL * 1024 * 1024 * 1024; + } MemStickState MemoryStick_State() @@ -32,10 +40,20 @@ u64 MemoryStick_SectorSize() u64 MemoryStick_FreeSpace() { - return 1ULL * 1024 * 1024 * 1024; // 1GB + u64 freeSpace = pspFileSystem.FreeSpace("ms0:/"); + if (freeSpace < memStickSize) + return freeSpace; + return memStickSize; } void MemoryStick_SetFatState(MemStickFatState state) { memStickFatState = state; } + +void MemoryStick_Init() +{ + memStickState = PSP_MEMORYSTICK_STATE_DRIVER_READY; + memStickFatState = PSP_FAT_MEMORYSTICK_STATE_ASSIGNED; + memStickSize = 8ULL * 1024 * 1024 * 1024; // 8GB +} diff --git a/Core/HW/MemoryStick.h b/Core/HW/MemoryStick.h index c574ca85fe..db5800efb7 100644 --- a/Core/HW/MemoryStick.h +++ b/Core/HW/MemoryStick.h @@ -18,6 +18,7 @@ enum MemStickFatState { PSP_FAT_MEMORYSTICK_STATE_ASSIGNED = 1, }; +void MemoryStick_Init(); void MemoryStick_DoState(PointerWrap &p); MemStickState MemoryStick_State(); MemStickFatState MemoryStick_FatState();