ppsspp/Core/Dialog/SavedataParam.h
Henrik Rydgård f18715bb7c Some renaming
2024-07-16 22:04:41 +02:00

403 lines
13 KiB
C++

// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include <memory>
#include <mutex>
#include <set>
#include <unordered_map>
#include <cstdint>
#include "Common/CommonTypes.h"
#include "Core/ELF/ParamSFO.h"
#include "Core/MemMap.h"
#include "Core/HLE/sceRtc.h"
#include "Core/Dialog/PSPDialog.h"
#undef st_ctime
#undef st_atime
#undef st_mtime
class PPGeImage;
struct PSPFileInfo;
typedef u32_le SceSize_le;
enum SceUtilitySavedataType
{
SCE_UTILITY_SAVEDATA_TYPE_AUTOLOAD = 0,
SCE_UTILITY_SAVEDATA_TYPE_AUTOSAVE = 1,
SCE_UTILITY_SAVEDATA_TYPE_LOAD = 2,
SCE_UTILITY_SAVEDATA_TYPE_SAVE = 3,
SCE_UTILITY_SAVEDATA_TYPE_LISTLOAD = 4,
SCE_UTILITY_SAVEDATA_TYPE_LISTSAVE = 5,
SCE_UTILITY_SAVEDATA_TYPE_LISTDELETE = 6,
SCE_UTILITY_SAVEDATA_TYPE_LISTALLDELETE = 7,// When run on a PSP, displays a list of all saves on the PSP. Weird. (Not really, it's to let you free up space)
SCE_UTILITY_SAVEDATA_TYPE_SIZES = 8,
SCE_UTILITY_SAVEDATA_TYPE_AUTODELETE = 9,
SCE_UTILITY_SAVEDATA_TYPE_DELETE = 10,
SCE_UTILITY_SAVEDATA_TYPE_LIST = 11,
SCE_UTILITY_SAVEDATA_TYPE_FILES = 12,
SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE = 13,
SCE_UTILITY_SAVEDATA_TYPE_MAKEDATA = 14,
SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE = 15,
SCE_UTILITY_SAVEDATA_TYPE_READDATA = 16,
SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE = 17,
SCE_UTILITY_SAVEDATA_TYPE_WRITEDATA = 18,
SCE_UTILITY_SAVEDATA_TYPE_ERASESECURE = 19,
SCE_UTILITY_SAVEDATA_TYPE_ERASE = 20,
SCE_UTILITY_SAVEDATA_TYPE_DELETEDATA = 21,
SCE_UTILITY_SAVEDATA_TYPE_GETSIZE = 22,
};
static const char *const utilitySavedataTypeNames[] = {
"AUTOLOAD",
"AUTOSAVE",
"LOAD",
"SAVE",
"LISTLOAD",
"LISTSAVE",
"LISTDELETE",
"LISTALLDELETE",
"SIZES",
"AUTODELETE",
"DELETE",
"LIST",
"FILES",
"MAKEDATASECURE",
"MAKEDATA",
"READDATASECURE",
"READDATA",
"WRITEDATASECURE",
"WRITEDATA",
"ERASESECURE",
"ERASE",
"DELETEDATA",
"GETSIZE",
};
enum SceUtilitySavedataFocus
{
SCE_UTILITY_SAVEDATA_FOCUS_NAME = 0, // specified by saveName[]
SCE_UTILITY_SAVEDATA_FOCUS_FIRSTLIST = 1, // first listed (on screen or of all?)
SCE_UTILITY_SAVEDATA_FOCUS_LASTLIST = 2, // last listed (on screen or of all?)
SCE_UTILITY_SAVEDATA_FOCUS_LATEST = 3, // latest by modification date (first if none)
SCE_UTILITY_SAVEDATA_FOCUS_OLDEST = 4, // oldest by modification date (first if none)
SCE_UTILITY_SAVEDATA_FOCUS_FIRSTDATA = 5, // first non-empty (first if none)
SCE_UTILITY_SAVEDATA_FOCUS_LASTDATA = 6, // last non-empty (first if none)
SCE_UTILITY_SAVEDATA_FOCUS_FIRSTEMPTY = 7, // first empty (what if no empty?)
SCE_UTILITY_SAVEDATA_FOCUS_LASTEMPTY = 8, // last empty (what if no empty?)
};
#if COMMON_LITTLE_ENDIAN
typedef SceUtilitySavedataType SceUtilitySavedataType_le;
typedef SceUtilitySavedataFocus SceUtilitySavedataFocus_le;
#else
typedef swap_struct_t<SceUtilitySavedataType, swap_32_t<SceUtilitySavedataType> > SceUtilitySavedataType_le;
typedef swap_struct_t<SceUtilitySavedataFocus, swap_32_t<SceUtilitySavedataFocus> > SceUtilitySavedataFocus_le;
#endif
typedef char SceUtilitySavedataSaveName[20];
// title, savedataTitle, detail: parts of the unencrypted SFO
// data, it contains what the VSH and standard load screen shows
struct PspUtilitySavedataSFOParam
{
char title[0x80];
char savedataTitle[0x80];
char detail[0x400];
unsigned char parentalLevel;
unsigned char unknown[3];
};
struct PspUtilitySavedataFileData {
PSPPointer<u8> buf;
SceSize_le bufSize; // Size of the buffer pointed to by buf
SceSize_le size; // Actual file size to write / was read
s32_le unknown;
};
struct PspUtilitySavedataSizeEntry {
u64_le size;
char name[16];
};
struct PspUtilitySavedataSizeInfo {
s32_le numSecureEntries;
s32_le numNormalEntries;
PSPPointer<PspUtilitySavedataSizeEntry> secureEntries;
PSPPointer<PspUtilitySavedataSizeEntry> normalEntries;
s32_le sectorSize;
s32_le freeSectors;
s32_le freeKB;
char freeString[8];
s32_le neededKB;
char neededString[8];
s32_le overwriteKB;
char overwriteString[8];
};
struct SceUtilitySavedataIdListEntry
{
s32_le st_mode;
ScePspDateTime st_ctime;
ScePspDateTime st_atime;
ScePspDateTime st_mtime;
SceUtilitySavedataSaveName name;
};
struct SceUtilitySavedataIdListInfo
{
s32_le maxCount;
s32_le resultCount;
PSPPointer<SceUtilitySavedataIdListEntry> entries;
};
struct SceUtilitySavedataFileListEntry
{
s32_le st_mode;
u32_le st_unk0;
u64_le st_size;
ScePspDateTime st_ctime;
ScePspDateTime st_atime;
ScePspDateTime st_mtime;
char name[16];
};
struct SceUtilitySavedataFileListInfo
{
u32_le maxSecureEntries;
u32_le maxNormalEntries;
u32_le maxSystemEntries;
u32_le resultNumSecureEntries;
u32_le resultNumNormalEntries;
u32_le resultNumSystemEntries;
PSPPointer<SceUtilitySavedataFileListEntry> secureEntries;
PSPPointer<SceUtilitySavedataFileListEntry> normalEntries;
PSPPointer<SceUtilitySavedataFileListEntry> systemEntries;
};
struct SceUtilitySavedataMsFreeInfo
{
s32_le clusterSize;
s32_le freeClusters;
s32_le freeSpaceKB;
char freeSpaceStr[8];
};
struct SceUtilitySavedataUsedDataInfo
{
s32_le usedClusters;
s32_le usedSpaceKB;
char usedSpaceStr[8];
s32_le usedSpace32KB;
char usedSpace32Str[8];
};
struct SceUtilitySavedataMsDataInfo
{
char gameName[13];
char pad[3];
SceUtilitySavedataSaveName saveName;
SceUtilitySavedataUsedDataInfo info;
};
// Structure to hold the parameters for the sceUtilitySavedataInitStart function.
struct SceUtilitySavedataParam
{
pspUtilityDialogCommon common;
SceUtilitySavedataType_le mode; // 0 to load, 1 to save
s32_le bind;
s32_le overwriteMode; // use 0x10 ?
/** gameName: name used from the game for saves, equal for all saves */
char gameName[13];
char unused[3];
/** saveName: name of the particular save, normally a number */
SceUtilitySavedataSaveName saveName;
PSPPointer<SceUtilitySavedataSaveName> saveNameList;
/** fileName: name of the data file of the game for example DATA.BIN */
char fileName[13];
char unused2[3];
/** pointer to a buffer that will contain data file unencrypted data */
PSPPointer<u8> dataBuf;
/** size of allocated space to dataBuf */
SceSize_le dataBufSize;
SceSize_le dataSize; // Size of the actual save data
PspUtilitySavedataSFOParam sfoParam;
PspUtilitySavedataFileData icon0FileData;
PspUtilitySavedataFileData icon1FileData;
PspUtilitySavedataFileData pic1FileData;
PspUtilitySavedataFileData snd0FileData;
PSPPointer<PspUtilitySavedataFileData> newData;
SceUtilitySavedataFocus_le focus;
s32_le abortStatus;
// Function SCE_UTILITY_SAVEDATA_TYPE_SIZES
PSPPointer<SceUtilitySavedataMsFreeInfo> msFree;
PSPPointer<SceUtilitySavedataMsDataInfo> msData;
PSPPointer<SceUtilitySavedataUsedDataInfo> utilityData;
u8 key[16];
u32_le secureVersion;
s32_le multiStatus;
// Function 11 LIST
PSPPointer<SceUtilitySavedataIdListInfo> idList;
// Function 12 FILES
PSPPointer<SceUtilitySavedataFileListInfo> fileList;
// Function 22 GETSIZES
PSPPointer<PspUtilitySavedataSizeInfo> sizeInfo;
};
// Non native, this one we can reorganize as we like
struct SaveFileInfo
{
s64 size = 0;
std::string saveName;
std::string saveDir;
int idx = 0;
char title[128]{};
char saveTitle[128]{};
char saveDetail[1024]{};
bool broken = false;
tm modif_time{};
PPGeImage *texture = nullptr;
void DoState(PointerWrap &p);
};
struct SaveSFOFileListEntry {
char filename[13];
u8 hash[16];
u8 pad[3];
};
class SavedataParam
{
public:
SavedataParam();
static void Init();
std::string GetSaveFilePath(const SceUtilitySavedataParam *param, int saveId = -1) const;
std::string GetSaveFilePath(const SceUtilitySavedataParam *param, const std::string &saveDir) const;
std::string GetSaveDirName(const SceUtilitySavedataParam *param, int saveId = -1) const;
std::string GetSaveDir(const SceUtilitySavedataParam *param, int saveId = -1) const;
std::string GetSaveDir(const SceUtilitySavedataParam *param, const std::string &saveDirName) const;
bool Delete(SceUtilitySavedataParam* param, int saveId = -1);
int DeleteData(SceUtilitySavedataParam* param);
int Save(SceUtilitySavedataParam* param, const std::string &saveDirName, bool secureMode = true);
int Load(SceUtilitySavedataParam* param, const std::string &saveDirName, int saveId = -1, bool secureMode = true);
int GetSizes(SceUtilitySavedataParam* param);
bool GetList(SceUtilitySavedataParam* param);
int GetFilesList(SceUtilitySavedataParam* param, u32 requestAddr);
bool GetSize(SceUtilitySavedataParam* param);
int GetSaveCryptMode(const SceUtilitySavedataParam *param, const std::string &saveDirName);
bool IsInSaveDataList(const std::string &saveName, int count);
std::string GetGameName(const SceUtilitySavedataParam *param) const;
std::string GetSaveName(const SceUtilitySavedataParam *param) const;
std::string GetFileName(const SceUtilitySavedataParam *param) const;
std::string GetKey(const SceUtilitySavedataParam *param) const;
bool HasKey(const SceUtilitySavedataParam *param) const;
static std::string GetSpaceText(u64 size, bool roundUp);
void SetIgnoreTextures(bool state) {
ignoreTextures_ = state;
}
int SetPspParam(SceUtilitySavedataParam* param);
SceUtilitySavedataParam *GetPspParam();
const SceUtilitySavedataParam *GetPspParam() const;
int GetFilenameCount();
const SaveFileInfo& GetFileInfo(int idx);
std::string GetFilename(int idx) const;
std::string GetSaveDir(int idx) const;
int GetSelectedSave();
void SetSelectedSave(int idx);
int GetFirstListSave();
int GetLastListSave();
int GetLatestSave();
int GetOldestSave();
int GetFirstDataSave();
int GetLastDataSave();
int GetFirstEmptySave();
int GetLastEmptySave();
int GetSaveNameIndex(const SceUtilitySavedataParam *param);
bool WouldHaveMultiSaveName(const SceUtilitySavedataParam *param);
void ClearSFOCache();
void DoState(PointerWrap &p);
private:
void Clear();
void SetFileInfo(int idx, PSPFileInfo &info, const std::string &saveName, const std::string &saveDir = "");
void SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, const std::string &saveName, const std::string &saveDir = "");
void ClearFileInfo(SaveFileInfo &saveInfo, const std::string &saveName);
PSPFileInfo GetSaveInfo(const std::string &saveDir);
int LoadSaveData(SceUtilitySavedataParam *param, const std::string &saveDirName, const std::string& dirPath, bool secureMode);
u32 LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, const u8 *saveData, int &saveSize, int prevCryptMode, const u8 *expectedHash, bool &saveDone);
u32 LoadNotCryptedSave(SceUtilitySavedataParam *param, u8 *data, u8 *saveData, int &saveSize);
bool LoadSFO(SceUtilitySavedataParam *param, const std::string& dirPath);
void LoadFile(const std::string& dirPath, const std::string& filename, PspUtilitySavedataFileData *fileData);
int DecryptData(unsigned int mode, unsigned char *data, int *dataLen, int *alignedLen, unsigned char *cryptkey, const u8 *expectedHash);
int EncryptData(unsigned int mode, unsigned char *data, int *dataLen, int *alignedLen, unsigned char *hash, unsigned char *cryptkey);
int UpdateHash(u8* sfoData, int sfoSize, int sfoDataParamsOffset, int encryptmode);
// data must be zero-padded from len to alignedLen (which should be the next multiply of 16)!
int BuildHash(uint8_t *output, const uint8_t *data, unsigned int len, unsigned int alignedLen, int mode, const uint8_t *cryptkey);
int DetermineCryptMode(const SceUtilitySavedataParam *param) const;
std::vector<SaveSFOFileListEntry> GetSFOEntries(const std::string &dirPath);
std::set<std::string> GetSecureFileNames(const std::string &dirPath);
bool GetExpectedHash(const std::string &dirPath, const std::string &filename, u8 hash[16]);
std::shared_ptr<ParamSFOData> LoadCachedSFO(const std::string &path, bool orCreate = false);
SceUtilitySavedataParam* pspParam = nullptr;
int selectedSave = 0;
SaveFileInfo *saveDataList = nullptr;
SaveFileInfo *noSaveIcon = nullptr;
int saveDataListCount = 0;
int saveNameListDataCount = 0;
bool ignoreTextures_ = false;
// Cleared before returning to PSP, no need to save state.
std::mutex cacheLock_;
std::unordered_map<std::string, std::shared_ptr<ParamSFOData>> sfoCache_;
};