Io: Cache SAVEDATA usage between writes.

Some games will loop over saves to check the size of each, and calculating
the total usage is expensive.  We don't need to recalculate each time.
This commit is contained in:
Unknown W. Brackets 2021-09-11 07:29:15 -07:00
parent d264cbef32
commit 906664b9d8
3 changed files with 29 additions and 6 deletions

View File

@ -392,6 +392,9 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File
if (fullName.FilePathContains("PSP/GAME/")) {
inGameDir_ = true;
}
if (access & (FILEACCESS_APPEND | FILEACCESS_CREATE | FILEACCESS_WRITE)) {
MemoryStick_NotifyWrite();
}
return success;
}
@ -446,6 +449,8 @@ size_t DirectoryFileHandle::Write(const u8* pointer, s64 size)
bytesWritten = ReplayApplyDiskWrite(pointer, (uint64_t)bytesWritten, (uint64_t)size, &diskFull, inGameDir_, CoreTiming::GetGlobalTimeUs());
}
MemoryStick_NotifyWrite();
if (diskFull) {
ERROR_LOG(FILESYS, "Disk full");
auto err = GetI18NCategory("Error");
@ -545,6 +550,7 @@ bool DirectoryFileSystem::MkDir(const std::string &dirname) {
#else
result = File::CreateFullPath(GetLocalPath(dirname));
#endif
MemoryStick_NotifyWrite();
return ReplayApplyDisk(ReplayAction::MKDIR, result, CoreTiming::GetGlobalTimeUs()) != 0;
}
@ -553,8 +559,10 @@ bool DirectoryFileSystem::RmDir(const std::string &dirname) {
#if HOST_IS_CASE_SENSITIVE
// Maybe we're lucky?
if (File::DeleteDirRecursively(fullName))
if (File::DeleteDirRecursively(fullName)) {
MemoryStick_NotifyWrite();
return (bool)ReplayApplyDisk(ReplayAction::RMDIR, true, CoreTiming::GetGlobalTimeUs());
}
// Nope, fix case and try again. Should we try again?
std::string fullPath = dirname;
@ -565,6 +573,7 @@ bool DirectoryFileSystem::RmDir(const std::string &dirname) {
#endif
bool result = File::DeleteDirRecursively(fullName);
MemoryStick_NotifyWrite();
return ReplayApplyDisk(ReplayAction::RMDIR, result, CoreTiming::GetGlobalTimeUs()) != 0;
}
@ -612,6 +621,7 @@ int DirectoryFileSystem::RenameFile(const std::string &from, const std::string &
// TODO: Better error codes.
int result = retValue ? 0 : (int)SCE_KERNEL_ERROR_ERRNO_FILE_ALREADY_EXISTS;
MemoryStick_NotifyWrite();
return ReplayApplyDisk(ReplayAction::FILE_RENAME, result, CoreTiming::GetGlobalTimeUs());
}
@ -633,6 +643,7 @@ bool DirectoryFileSystem::RemoveFile(const std::string &filename) {
}
#endif
MemoryStick_NotifyWrite();
return ReplayApplyDisk(ReplayAction::FILE_REMOVE, retValue, CoreTiming::GetGlobalTimeUs()) != 0;
}

View File

@ -33,6 +33,8 @@ static MemStickFatState memStickFatState;
static bool memStickNeedsAssign = false;
static u64 memStickInsertedAt = 0;
static uint64_t memstickInitialFree = 0;
static uint64_t memstickCurrentUse = 0;
static bool memstickCurrentUseValid = false;
enum FreeCalcStatus {
NONE,
@ -122,11 +124,16 @@ u64 MemoryStick_FreeSpace() {
// not planned for back then (even though 2GB cards were available.)
// We have a compat setting to make it even smaller for Harry Potter : Goblet of Fire, see #13266.
const u64 memStickSize = flags.ReportSmallMemstick ? smallMemstickSize : (u64)g_Config.iMemStickSizeGB * 1024 * 1024 * 1024;
// Assume the memory stick is only used to store savedata.
u64 usedSpace = pspFileSystem.getDirSize("ms0:/PSP/SAVEDATA/");
if (!memstickCurrentUseValid) {
memstickCurrentUse = pspFileSystem.getDirSize("ms0:/PSP/SAVEDATA/");
memstickCurrentUseValid = true;
}
u64 simulatedFreeSpace = 0;
if (usedSpace < memStickSize) {
simulatedFreeSpace = memStickSize - usedSpace;
if (memstickCurrentUse < memStickSize) {
simulatedFreeSpace = memStickSize - memstickCurrentUse;
} else if (flags.ReportSmallMemstick) {
// There's more stuff in the memstick than the size we report.
// This doesn't work, so we'll just have to lie. Not sure what the best way is.
@ -135,14 +142,18 @@ u64 MemoryStick_FreeSpace() {
if (flags.MemstickFixedFree) {
// Assassin's Creed: Bloodlines fails to save if free space changes incorrectly during game.
realFreeSpace = 0;
if (usedSpace <= memstickInitialFree) {
realFreeSpace = memstickInitialFree - usedSpace;
if (memstickCurrentUse <= memstickInitialFree) {
realFreeSpace = memstickInitialFree - memstickCurrentUse;
}
}
return std::min(simulatedFreeSpace, realFreeSpace);
}
void MemoryStick_NotifyWrite() {
memstickCurrentUseValid = false;
}
void MemoryStick_SetFatState(MemStickFatState state) {
memStickFatState = state;
memStickNeedsAssign = false;

View File

@ -51,3 +51,4 @@ void MemoryStick_SetFatState(MemStickFatState state);
u64 MemoryStick_SectorSize();
u64 MemoryStick_FreeSpace();
void MemoryStick_NotifyWrite();