Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Savedata: Update filelist on file erasure #16239

Merged
merged 1 commit into from
Oct 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Core/Dialog/PSPSaveDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ static bool IsNotVisibleAction(SceUtilitySavedataType type) {
case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATA:
case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE:
case SCE_UTILITY_SAVEDATA_TYPE_READDATA:
case SCE_UTILITY_SAVEDATA_TYPE_ERASESECURE:
case SCE_UTILITY_SAVEDATA_TYPE_ERASE:
case SCE_UTILITY_SAVEDATA_TYPE_DELETEDATA:
case SCE_UTILITY_SAVEDATA_TYPE_AUTODELETE:
return true;
Expand Down Expand Up @@ -222,6 +224,8 @@ int PSPSaveDialog::Init(int paramAddr)
case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATA:
case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE:
case SCE_UTILITY_SAVEDATA_TYPE_READDATA:
case SCE_UTILITY_SAVEDATA_TYPE_ERASESECURE:
case SCE_UTILITY_SAVEDATA_TYPE_ERASE:
case SCE_UTILITY_SAVEDATA_TYPE_DELETEDATA:
display = DS_NONE;
break;
Expand Down
43 changes: 38 additions & 5 deletions Core/Dialog/SavedataParam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.

#include <algorithm>
#include <memory>
#include "Common/Log.h"
#include "Common/Data/Text/I18n.h"
#include "Common/Data/Format/ZIMLoad.h"
Expand All @@ -36,14 +38,15 @@
#include "Core/HW/MemoryStick.h"
#include "Core/Util/PPGeDraw.h"

#include <algorithm>

static const std::string ICON0_FILENAME = "ICON0.PNG";
static const std::string ICON1_FILENAME = "ICON1.PMF";
static const std::string PIC1_FILENAME = "PIC1.PNG";
static const std::string SND0_FILENAME = "SND0.AT3";
static const std::string SFO_FILENAME = "PARAM.SFO";

static const int FILE_LIST_COUNT_MAX = 99;
static const u32 FILE_LIST_TOTAL_SIZE = sizeof(SaveSFOFileListEntry) * FILE_LIST_COUNT_MAX;

static const std::string savePath = "ms0:/PSP/SAVEDATA/";

namespace
Expand Down Expand Up @@ -382,6 +385,39 @@ int SavedataParam::DeleteData(SceUtilitySavedataParam* param) {
ClearCaches();
pspFileSystem.RemoveFile(filePath);

// Update PARAM.SFO to remove the file, if it was in the list.
std::shared_ptr<ParamSFOData> sfoFile = LoadCachedSFO(sfoPath);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be a unique_ptr, right? (less overhead, though hardly matters here)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoadCachedSFO() returns a shared_ptr, because it returns a common pointer from a cache but you can clear its cache, so I just wanted to be safe from any crashes. For example, saving a file loads the SFO data, then clears the SFO cache (because it modifies things.)

It definitely can't be a unique_ptr, because the whole point of LoadCachedSFO() is to reuse the already loaded SFO data. Would not want it freed on each use.

-[Unknown]

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, yeah, should have gone looking inside LoadCachedSFO.

This is correct, ignore me.

if (sfoFile) {
// Note: do not update values such as TITLE in this operation.
u32 fileListSize = 0;
SaveSFOFileListEntry *fileList = (SaveSFOFileListEntry *)sfoFile->GetValueData("SAVEDATA_FILE_LIST", &fileListSize);
size_t fileListCount = fileListSize / sizeof(SaveSFOFileListEntry);
bool changed = false;
for (size_t i = 0; i < fileListCount; ++i) {
if (strncmp(fileList[i].filename, fileName.c_str(), sizeof(fileList[i].filename)) != 0)
continue;

memset(fileList[i].filename, 0, sizeof(fileList[i].filename));
memset(fileList[i].hash, 0, sizeof(fileList[i].hash));
changed = true;
break;
}

if (changed) {
std::unique_ptr<u8[]> updatedList(new u8[fileListSize]);
memcpy(updatedList.get(), fileList, fileListSize);
sfoFile->SetValue("SAVEDATA_FILE_LIST", updatedList.get(), fileListSize, (int)FILE_LIST_TOTAL_SIZE);

u8 *sfoData;
size_t sfoSize;
sfoFile->WriteSFO(&sfoData, &sfoSize);

ClearCaches();
WritePSPFile(sfoPath, sfoData, (SceSize)sfoSize);
delete[] sfoData;
}
}

return 0;
}

Expand Down Expand Up @@ -470,8 +506,6 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD

// Always write and update the file list.
// For each file, 13 bytes for filename, 16 bytes for file hash (0 in PPSSPP), 3 byte for padding
const int FILE_LIST_COUNT_MAX = 99;
const u32 FILE_LIST_TOTAL_SIZE = sizeof(SaveSFOFileListEntry) * FILE_LIST_COUNT_MAX;
u32 tmpDataSize = 0;
SaveSFOFileListEntry *tmpDataOrig = (SaveSFOFileListEntry *)sfoFile->GetValueData("SAVEDATA_FILE_LIST", &tmpDataSize);
SaveSFOFileListEntry *updatedList = new SaveSFOFileListEntry[FILE_LIST_COUNT_MAX];
Expand Down Expand Up @@ -825,7 +859,6 @@ std::vector<SaveSFOFileListEntry> SavedataParam::GetSFOEntries(const std::string
return result;
}

const int FILE_LIST_COUNT_MAX = 99;
u32 sfoFileListSize = 0;
SaveSFOFileListEntry *sfoFileList = (SaveSFOFileListEntry *)sfoFile->GetValueData("SAVEDATA_FILE_LIST", &sfoFileListSize);
const u32 count = std::min((u32)FILE_LIST_COUNT_MAX, sfoFileListSize / (u32)sizeof(SaveSFOFileListEntry));
Expand Down