// 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 "Core/HLE/sceKernel.h" #include "Core/HLE/sceRtc.h" #include "Core/System.h" #include "Core/Dialog/PSPDialog.h" #include "Core/Util/PPGeDraw.h" #include "Common/CommonTypes.h" #undef st_ctime #undef st_atime #undef st_mtime 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_DELETE = 6, SCE_UTILITY_SAVEDATA_TYPE_LISTDELETE = 7, SCE_UTILITY_SAVEDATA_TYPE_SIZES = 8, SCE_UTILITY_SAVEDATA_TYPE_AUTODELETE = 9, SCE_UTILITY_SAVEDATA_TYPE_SINGLEDELETE = 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, }; 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_le; typedef swap_struct_t > 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 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 secureEntries; PSPPointer 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 entries; }; struct SceUtilitySavedataFileListEntry { s32_le st_mode; 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 secureEntries; PSPPointer normalEntries; PSPPointer 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 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 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 newData; SceUtilitySavedataFocus_le focus; s32_le abortStatus; // Function SCE_UTILITY_SAVEDATA_TYPE_SIZES PSPPointer msFree; PSPPointer msData; PSPPointer utilityData; u8 key[16]; s32_le secureVersion; s32_le multiStatus; // Function 11 LIST PSPPointer idList; // Function 12 FILES PSPPointer fileList; // Function 22 GETSIZES PSPPointer sizeInfo; }; // Non native, this one we can reorganize as we like struct SaveFileInfo { s64 size; std::string saveName; int idx; char title[128]; char saveTitle[128]; char saveDetail[1024]; tm modif_time; PPGeImage *texture; SaveFileInfo() : size(0), saveName(""), idx(0), texture(NULL) { memset(title, 0, 128); memset(saveTitle, 0, 128); memset(saveDetail, 0, 1024); memset(&modif_time, 0, sizeof(modif_time)); } void DoState(PointerWrap &p) { auto s = p.Section("SaveFileInfo", 1, 2); if (!s) return; p.Do(size); p.Do(saveName); p.Do(idx); p.DoArray(title, sizeof(title)); p.DoArray(saveTitle, sizeof(saveTitle)); p.DoArray(saveDetail, sizeof(saveDetail)); p.Do(modif_time); if (s <= 1) { u32 textureData; int textureWidth; int textureHeight; p.Do(textureData); p.Do(textureWidth); p.Do(textureHeight); if (textureData != 0) { // Must be MODE_READ. texture = new PPGeImage(""); texture->CompatLoad(textureData, textureWidth, textureHeight); } } else { bool hasTexture = texture != NULL; p.Do(hasTexture); if (hasTexture) { if (p.mode == p.MODE_READ) { texture = new PPGeImage(""); } texture->DoState(p); } } } }; class SavedataParam { public: SavedataParam(); static void Init(); std::string GetSaveFilePath(SceUtilitySavedataParam* param, int saveId = -1); std::string GetSaveFilePath(SceUtilitySavedataParam* param, const std::string &saveDir); std::string GetSaveDirName(SceUtilitySavedataParam* param, int saveId = -1); std::string GetSaveDir(SceUtilitySavedataParam* param, int saveId = -1); std::string GetSaveDir(SceUtilitySavedataParam* param, const std::string &saveDirName); bool Delete(SceUtilitySavedataParam* param, int saveId = -1); int DeleteData(SceUtilitySavedataParam* param); bool Save(SceUtilitySavedataParam* param, const std::string &saveDirName, bool secureMode = true); bool 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); bool GetSize(SceUtilitySavedataParam* param); bool IsSaveEncrypted(SceUtilitySavedataParam* param, const std::string &saveDirName); bool IsInSaveDataList(std::string saveName, int count); bool secureCanSkip(SceUtilitySavedataParam* param, bool secureMode); std::string GetGameName(SceUtilitySavedataParam* param); std::string GetSaveName(SceUtilitySavedataParam* param); std::string GetFileName(SceUtilitySavedataParam* param); static std::string GetSpaceText(int size); int SetPspParam(SceUtilitySavedataParam* param); SceUtilitySavedataParam* GetPspParam(); int GetFilenameCount(); const SaveFileInfo& GetFileInfo(int idx); std::string GetFilename(int idx); int GetSelectedSave(); void SetSelectedSave(int idx); int GetFirstListSave(); int GetLastListSave(); int GetLatestSave(); int GetOldestSave(); int GetFirstDataSave(); int GetLastDataSave(); int GetFirstEmptySave(); int GetLastEmptySave(); int GetSaveNameIndex(SceUtilitySavedataParam* param); void DoState(PointerWrap &p); private: void Clear(); void SetFileInfo(int idx, PSPFileInfo &info, std::string saveName); void SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::string saveName); void ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName); bool LoadSaveData(SceUtilitySavedataParam *param, const std::string &saveDirName, const std::string dirPath, bool secureMode); void LoadDecryptedSave(SceUtilitySavedataParam *param, u8 *data, u8 *saveData, int &saveSize, bool &saveDone); void LoadNotCryptedSave(SceUtilitySavedataParam *param, u8 *data, u8 *saveData, int &saveSize); void LoadSFO(SceUtilitySavedataParam *param, const std::string dirPath); void LoadFile(const std::string dirPath, const std::string filename, PspUtilitySavedataFileData *fileData); int DecryptSave(unsigned int mode, unsigned char *data, int *dataLen, int *alignedLen, unsigned char *cryptkey); 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); int BuildHash(unsigned char *output, unsigned char *data, unsigned int len, unsigned int alignedLen, int mode, unsigned char *cryptkey); std::set getSecureFileNames(std::string dirPath); SceUtilitySavedataParam* pspParam; int selectedSave; SaveFileInfo *saveDataList; SaveFileInfo *noSaveIcon; int saveDataListCount; int saveNameListDataCount; };