From 8e80063e6f8c6500a87afe7e0cf527d9f5372767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Parrino?= Date: Tue, 17 Dec 2024 22:13:20 -0300 Subject: [PATCH] Delete saves option (#196) * delete saves * improve encrypted saves --- include/menu.h | 2 -- include/saves.h | 4 ++- source/common.c | 7 ++++ source/exec_cmd.c | 50 +++++++++++++++++++++-------- source/menu_main.c | 31 ++++++++++++------ source/orbis_jbc.c | 4 +-- source/saves.c | 79 ++++++++++++++++++++++++++++++++-------------- 7 files changed, 127 insertions(+), 50 deletions(-) diff --git a/include/menu.h b/include/menu.h index c3652a9..f6465bb 100644 --- a/include/menu.h +++ b/include/menu.h @@ -263,12 +263,10 @@ void drawEndLogo(void); int load_app_settings(app_config_t* config); int save_app_settings(app_config_t* config); -int reset_app_settings(app_config_t* config); int initialize_jbc(void); void terminate_jbc(void); int initVshDataMount(void); int get_max_pfskey_ver(void); -char* get_fw_by_pfskey_ver(int key_ver); #endif diff --git a/include/saves.h b/include/saves.h index 2bd22f3..4253b03 100644 --- a/include/saves.h +++ b/include/saves.h @@ -95,7 +95,7 @@ enum cmd_code_enum CMD_HEX_EDIT_FILE, CMD_COPY_PFS, CMD_IMPORT_DATA_FILE, - CMD_DELETE_VMCSAVE, + CMD_DELETE_SAVE, // Bulk commands CMD_RESIGN_SAVES, @@ -312,6 +312,7 @@ int regMgr_SetAccountId(int userNumber, uint64_t* psnAccountId); int get_save_details(const save_entry_t *save, char** details); int orbis_SaveUmount(const char* mountPath); int orbis_SaveMount(const save_entry_t *save, uint32_t mode, char* mountPath); +int orbis_SaveDelete(const save_entry_t *save); int orbis_UpdateSaveParams(const save_entry_t* save, const char* title, const char* subtitle, const char* details, uint32_t up); int vmc_export_psv(const char* save, const char* out_path); @@ -329,3 +330,4 @@ int vmp_resign(const char *src_vmp); char* sjis2utf8(char* input); uint8_t* getIconPS2(const char* folder, const char* iconfile); +const char* get_fw_by_pfskey_ver(int key_ver); diff --git a/source/common.c b/source/common.c index b239b2f..88623de 100644 --- a/source/common.c +++ b/source/common.c @@ -207,6 +207,13 @@ int clean_directory(const char* inputdir) if (strcmp(dir->d_name, ".") != 0 && strcmp(dir->d_name, "..") != 0) { snprintf(dataPath, sizeof(dataPath), "%s" "%s", inputdir, dir->d_name); + + if (dir->d_type == DT_DIR) { + strcat(dataPath, "/"); + clean_directory(dataPath); + rmdir(dataPath); + } + unlink_secure(dataPath); } } diff --git a/source/exec_cmd.c b/source/exec_cmd.c index 5a93dcc..e05a606 100644 --- a/source/exec_cmd.c +++ b/source/exec_cmd.c @@ -451,7 +451,7 @@ static void copySavePFS(const save_entry_t* save) if (!orbis_SaveMount(save, ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON, mount)) { - LOG("[!] Error: can't create/mount save!"); + show_message("Error: can't create HDD save"); return; } orbis_SaveUmount(mount); @@ -476,7 +476,6 @@ static void copySavePFS(const save_entry_t* save) if (!orbis_SaveMount(save, ORBIS_SAVE_DATA_MOUNT_MODE_RDWR, mount)) { - LOG("[!] Error: can't remount save"); show_message("Error! Can't mount encrypted save.\n(incompatible save-game firmware version)"); return; } @@ -638,9 +637,9 @@ static int webReqHandler(dWebRequest_t* req, dWebResponse_t* res, void* list) { base = strdup(item->path); path = strdup(item->path); - *strrchr(base, '/') = 0; } *strrchr(base, '/') = 0; + *strrchr(base, '/') = 0; id = zip_directory(base, path, res->data); if (item->flags & SAVE_FLAG_HDD) @@ -673,7 +672,7 @@ static int webReqHandler(dWebRequest_t* req, dWebResponse_t* res, void* list) // http://ps3-ip:8080/icon/CUSA12345-DIR-NAME/sce_sys/icon0.png if (wildcard_match(req->resource, "/icon/*/sce_sys/icon0.png")) { - asprintf(&res->data, "%sAPOLLO/%s", selected_entry->path, req->resource + 6); + asprintf(&res->data, "%sPS4/APOLLO/%s", selected_entry->path, req->resource + 6); return (file_exists(res->data) == SUCCESS); } @@ -891,14 +890,37 @@ static void import_save2vmc(const char* src, int type) show_message("Error importing save:\n%s", src); } -static int deleteVmcSave(const save_entry_t* save) +static int deleteSave(const save_entry_t* save) { - int ret; + int ret = 0; + char fpath[256]; if (!show_dialog(DIALOG_TYPE_YESNO, "Do you want to delete %s?", save->dir_name)) return 0; - ret = (save->flags & SAVE_FLAG_PS1) ? formatSave(save->blocks) : vmc_delete_save(save->dir_name); + if (save->flags & SAVE_FLAG_PS1) + ret = formatSave(save->blocks); + + else if (save->flags & SAVE_FLAG_PS2) + ret = vmc_delete_save(save->dir_name); + + else if (save->flags & SAVE_FLAG_PS4) + { + if (save->flags & SAVE_FLAG_HDD) + ret = orbis_SaveDelete(save); + + else if (save->flags & SAVE_FLAG_LOCKED) + { + snprintf(fpath, sizeof(fpath), "%s%s.bin", save->path, save->dir_name); + ret = (unlink_secure(fpath) == SUCCESS); + + snprintf(fpath, sizeof(fpath), "%s%s", save->path, save->dir_name); + ret &= (unlink_secure(fpath) == SUCCESS); + } + else + ret = (clean_directory(save->path) == SUCCESS); + } + if (ret) show_message("Save successfully deleted:\n%s", save->dir_name); else @@ -1298,11 +1320,13 @@ static void toggleBrowserHistory(int usr) void execCodeCommand(code_entry_t* code, const char* codecmd) { - char *tmp, mount[ORBIS_SAVE_DATA_DIRNAME_DATA_MAXSIZE]; + char *tmp = NULL; + char mount[ORBIS_SAVE_DATA_DIRNAME_DATA_MAXSIZE]; - if (selected_entry->flags & SAVE_FLAG_HDD) + if (selected_entry->flags & (SAVE_FLAG_HDD|SAVE_FLAG_LOCKED) && + codecmd[0] != CMD_DELETE_SAVE && codecmd[0] != CMD_COPY_PFS) { - if (!orbis_SaveMount(selected_entry, (selected_entry->flags & SAVE_FLAG_TROPHY), mount)) + if (!orbis_SaveMount(selected_entry, selected_entry->flags & (SAVE_FLAG_TROPHY|SAVE_FLAG_LOCKED), mount)) { LOG("Error Mounting Save! Check Save Mount Patches"); return; @@ -1493,8 +1517,8 @@ void execCodeCommand(code_entry_t* code, const char* codecmd) code->activated = 0; break; - case CMD_DELETE_VMCSAVE: - if (deleteVmcSave(selected_entry)) + case CMD_DELETE_SAVE: + if (deleteSave(selected_entry)) selected_entry->flags |= SAVE_FLAG_UPDATED; else code->activated = 0; @@ -1531,7 +1555,7 @@ void execCodeCommand(code_entry_t* code, const char* codecmd) break; } - if (selected_entry->flags & SAVE_FLAG_HDD) + if (tmp) { orbis_SaveUmount(mount); free(selected_entry->path); diff --git a/source/menu_main.c b/source/menu_main.c index ac0812d..618aa54 100644 --- a/source/menu_main.c +++ b/source/menu_main.c @@ -161,16 +161,29 @@ static void SetMenu(int id) break; case MENU_PATCHES: //Cheat Selection Menu - if (selected_entry->flags & SAVE_FLAG_UPDATED && id == MENU_PS2VMC_SAVES) - { - selected_entry->flags ^= SAVE_FLAG_UPDATED; - ReloadUserSaves(&vmc2_saves); - } - else if (selected_entry->flags & SAVE_FLAG_UPDATED && id == MENU_PS1VMC_SAVES) + if (selected_entry->flags & SAVE_FLAG_UPDATED) { + switch (id) + { + case MENU_PS2VMC_SAVES: + ReloadUserSaves(&vmc2_saves); + break; + + case MENU_PS1VMC_SAVES: + saveMemoryCard(vmc1_saves.path, 0, 0); + ReloadUserSaves(&vmc1_saves); + break; + + case MENU_HDD_SAVES: + ReloadUserSaves(&hdd_saves); + break; + + case MENU_USB_SAVES: + ReloadUserSaves(&usb_saves); + break; + } + selected_entry->flags ^= SAVE_FLAG_UPDATED; - saveMemoryCard(vmc1_saves.path, 0, 0); - ReloadUserSaves(&vmc1_saves); } break; @@ -813,7 +826,7 @@ static void doPatchMenu(void) return; } - if (selected_centry->codes[0] == CMD_DELETE_VMCSAVE) + if (selected_centry->codes[0] == CMD_DELETE_SAVE) { selected_centry->activated = 0; SetMenu(last_menu_id[MENU_PATCHES]); diff --git a/source/orbis_jbc.c b/source/orbis_jbc.c index ad7aa5b..156400c 100644 --- a/source/orbis_jbc.c +++ b/source/orbis_jbc.c @@ -214,9 +214,9 @@ int get_max_pfskey_ver(void) return 0; } -char* get_fw_by_pfskey_ver(int key_ver) +const char* get_fw_by_pfskey_ver(int key_ver) { - char* fw[] = {"???", "Any", "4.50+", "4.70+", "5.00+", "5.50+", "6.00+", "6.50+", "7.00+", "7.50+", "8.00+"}; + const char* fw[] = {"???", "Any", "4.50+", "4.70+", "5.00+", "5.50+", "6.00+", "6.50+", "7.00+", "7.50+", "8.00+"}; if (key_ver > 10) key_ver = 0; return fw[key_ver]; diff --git a/source/saves.c b/source/saves.c index 6a1cb28..340d7d1 100644 --- a/source/saves.c +++ b/source/saves.c @@ -719,6 +719,9 @@ static void _addBackupCommands(save_entry_t* item) cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_USER " View Save Details", CMD_VIEW_DETAILS); list_append(item->codes, cmd); + cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_WARN " Delete Save Game", CMD_DELETE_SAVE); + list_append(item->codes, cmd); + cmd = _createCmdCode(PATCH_NULL, "----- " UTF8_CHAR_STAR " File Backup " UTF8_CHAR_STAR " -----", CMD_CODE_NULL); list_append(item->codes, cmd); @@ -728,7 +731,7 @@ static void _addBackupCommands(save_entry_t* item) if (!(item->flags & SAVE_FLAG_HDD)) { asprintf(&cmd->options->name[2], "Copy Save to HDD"); - asprintf(&cmd->options->value[2], "%c", CMD_COPY_SAVE_HDD); + asprintf(&cmd->options->value[2], "%c", (item->flags & SAVE_FLAG_LOCKED) ? CMD_COPY_PFS : CMD_COPY_SAVE_HDD); } list_append(item->codes, cmd); @@ -840,12 +843,19 @@ static void _addSfoCommands(save_entry_t* save) static int set_pfs_codes(save_entry_t* item) { + uint8_t data[16]; + char savePath[256]; code_entry_t* cmd; item->codes = list_alloc(); cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_USER " View Save Details", CMD_VIEW_DETAILS); list_append(item->codes, cmd); - cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Copy Save game to HDD", CMD_COPY_PFS); + + snprintf(savePath, sizeof(savePath), "%s%s.bin", item->path, item->dir_name); + read_file(savePath, data, sizeof(data)); + snprintf(savePath, sizeof(savePath), CHAR_ICON_WARN " --- Encrypted save requires firmware %s --- " CHAR_ICON_WARN, get_fw_by_pfskey_ver(data[8])); + + cmd = _createCmdCode(PATCH_NULL, savePath, CMD_CODE_NULL); list_append(item->codes, cmd); return list_count(item->codes); @@ -872,18 +882,18 @@ int ReadCodes(save_entry_t * save) char filePath[256]; char * buffer = NULL; char mount[ORBIS_SAVE_DATA_DIRNAME_DATA_MAXSIZE]; - char *tmp; + char *tmp = NULL; - if (save->flags & SAVE_FLAG_LOCKED) + if (save->type == FILE_TYPE_NULL) return set_pfs_codes(save); save->codes = list_alloc(); - if (save->flags & SAVE_FLAG_HDD) + if (save->flags & (SAVE_FLAG_HDD|SAVE_FLAG_LOCKED)) { - if (!orbis_SaveMount(save, ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY, mount)) + if (!orbis_SaveMount(save, (save->flags & SAVE_FLAG_LOCKED), mount)) { - code = _createCmdCode(PATCH_NULL, CHAR_ICON_WARN " --- Error Mounting Save! Check Save Mount Patches --- " CHAR_ICON_WARN, CMD_CODE_NULL); + code = _createCmdCode(PATCH_NULL, CHAR_ICON_WARN " --- Error Mounting Save! --- " CHAR_ICON_WARN, CMD_CODE_NULL); list_append(save->codes, code); return list_count(save->codes); } @@ -911,7 +921,7 @@ int ReadCodes(save_entry_t * save) LOG("Loaded %zu codes", list_count(save->codes)); skip_end: - if (save->flags & SAVE_FLAG_HDD) + if (tmp) { orbis_SaveUmount(mount); free(save->path); @@ -1107,7 +1117,7 @@ int ReadVmc1Codes(save_entry_t * save) cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_USER " View Save Details", CMD_VIEW_DETAILS); list_append(save->codes, cmd); - cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_WARN " Delete Save Game", CMD_DELETE_VMCSAVE); + cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_WARN " Delete Save Game", CMD_DELETE_SAVE); list_append(save->codes, cmd); cmd = _createCmdCode(PATCH_NULL, "----- " UTF8_CHAR_STAR " Save Game Backup " UTF8_CHAR_STAR " -----", CMD_CODE_NULL); @@ -1243,7 +1253,7 @@ int ReadVmc2Codes(save_entry_t * save) cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_USER " View Save Details", CMD_VIEW_DETAILS); list_append(save->codes, cmd); - cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_WARN " Delete Save Game", CMD_DELETE_VMCSAVE); + cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_WARN " Delete Save Game", CMD_DELETE_SAVE); list_append(save->codes, cmd); cmd = _createCmdCode(PATCH_NULL, "----- " UTF8_CHAR_STAR " Save Game Backup " UTF8_CHAR_STAR " -----", CMD_CODE_NULL); @@ -1678,8 +1688,9 @@ static void read_usb_encrypted_saves(const char* userPath, list_t *list, uint64_ { DIR *d, *d2; struct dirent *dir, *dir2; - save_entry_t *item; + save_entry_t *item, tmp; char savePath[256]; + char mount[ORBIS_SAVE_DATA_DIRNAME_DATA_MAXSIZE]; d = opendir(userPath); @@ -1704,30 +1715,51 @@ static void read_usb_encrypted_saves(const char* userPath, list_t *list, uint64_ if (dir2->d_type != DT_REG || endsWith(dir2->d_name, ".bin")) continue; - snprintf(savePath, sizeof(savePath), "%s%s/%s.bin", userPath, dir->d_name, dir2->d_name); - if (file_exists(savePath) != SUCCESS) + snprintf(savePath, sizeof(savePath), "%s%s/", userPath, dir->d_name); + tmp.path = savePath; + tmp.title_id = dir->d_name; + tmp.dir_name = dir2->d_name; + if (!orbis_SaveMount(&tmp, SAVE_FLAG_LOCKED, mount)) + { + snprintf(savePath, sizeof(savePath), CHAR_ICON_WARN "%s/%s", dir->d_name, dir2->d_name); + item = _createSaveEntry(SAVE_FLAG_PS4 | SAVE_FLAG_LOCKED, savePath); + item->type = FILE_TYPE_NULL; + item->dir_name = strdup(dir2->d_name); + asprintf(&item->path, "%s%s/", userPath, dir->d_name); + asprintf(&item->title_id, "%.9s", dir->d_name); + list_append(list, item); + continue; + } + + snprintf(savePath, sizeof(savePath), APOLLO_SANDBOX_PATH "sce_sys/param.sfo", mount); + LOG("Reading %s...", savePath); + + sfo_context_t* sfo = sfo_alloc(); + if (sfo_read(sfo, savePath) < 0) { + LOG("Unable to read from '%s'", savePath); + sfo_free(sfo); continue; + } - snprintf(savePath, sizeof(savePath), "(Encrypted) %s/%s", dir->d_name, dir2->d_name); + snprintf(savePath, sizeof(savePath), "%s - %s", sfo_get_param_value(sfo, "MAINTITLE"), sfo_get_param_value(sfo, "SUBTITLE")); item = _createSaveEntry(SAVE_FLAG_PS4 | SAVE_FLAG_LOCKED, savePath); item->type = FILE_TYPE_PS4; - + item->dir_name = strdup(dir2->d_name); asprintf(&item->path, "%s%s/", userPath, dir->d_name); asprintf(&item->title_id, "%.9s", dir->d_name); - item->dir_name = strdup(dir2->d_name); - if (apollo_config.account_id == account) + uint64_t* int_data = (uint64_t*) sfo_get_param_value(sfo, "ACCOUNT_ID"); + if (int_data && (apollo_config.account_id == *int_data)) item->flags |= SAVE_FLAG_OWNER; - snprintf(savePath, sizeof(savePath), "%s%s/%s", userPath, dir->d_name, dir2->d_name); - - uint64_t size = 0; - get_file_size(savePath, &size); - item->blocks = size / ORBIS_SAVE_DATA_BLOCK_SIZE; + int_data = (uint64_t*) sfo_get_param_value(sfo, "SAVEDATA_BLOCKS"); + item->blocks = (*int_data); + + sfo_free(sfo); + orbis_SaveUmount(mount); LOG("[%s] F(%X) name '%s'", item->title_id, item->flags, item->name); list_append(list, item); - } closedir(d2); } @@ -2127,6 +2159,7 @@ static void _ReadOnlineListEx(const char* urlPath, uint16_t flag, list_t *list) { *tmp++ = 0; item = _createSaveEntry(flag | SAVE_FLAG_ONLINE, tmp); + item->type = FILE_TYPE_ZIP; item->title_id = strdup(content); asprintf(&item->path, "%s%s/", urlPath, item->title_id);