Skip to content

Commit

Permalink
Io: Cache SAVEDATA usage between writes.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
unknownbrackets committed Sep 11, 2021
1 parent d264cbe commit 906664b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 6 deletions.
13 changes: 12 additions & 1 deletion Core/FileSystems/DirectoryFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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());
}

Expand All @@ -633,6 +643,7 @@ bool DirectoryFileSystem::RemoveFile(const std::string &filename) {
}
#endif

MemoryStick_NotifyWrite();
return ReplayApplyDisk(ReplayAction::FILE_REMOVE, retValue, CoreTiming::GetGlobalTimeUs()) != 0;
}

Expand Down
21 changes: 16 additions & 5 deletions Core/HW/MemoryStick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions Core/HW/MemoryStick.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ void MemoryStick_SetFatState(MemStickFatState state);

u64 MemoryStick_SectorSize();
u64 MemoryStick_FreeSpace();
void MemoryStick_NotifyWrite();

0 comments on commit 906664b

Please sign in to comment.