From 06b2fe0024dd12bd4a6da7cdfa9107a2b4d6da85 Mon Sep 17 00:00:00 2001 From: Damian Parrino Date: Mon, 8 Apr 2024 10:34:10 -0300 Subject: [PATCH] improvements remove vmc saves import vmc saves from usb/hdd vmc save details --- include/ps1card.h | 2 +- include/saves.h | 14 ++++--- source/exec_cmd.c | 49 +++++++++++++++--------- source/mcio.c | 7 ++-- source/menu_main.c | 84 +++++++++++++++++++++++++++++++--------- source/ps1card.c | 6 ++- source/ps2classic.c | 2 +- source/psv_resign.c | 28 ++++++++++++++ source/saves.c | 93 +++++++++++++++++++++++++++------------------ 9 files changed, 200 insertions(+), 85 deletions(-) diff --git a/include/ps1card.h b/include/ps1card.h index 279038a..f753795 100644 --- a/include/ps1card.h +++ b/include/ps1card.h @@ -86,7 +86,7 @@ uint8_t* getSaveBytes(int slotNumber, uint32_t* saveLen); void toggleDeleteSave(int slotNumber); //Format save -void formatSave(int slotNumber); +int formatSave(int slotNumber); //Get Memory Card data ps1mcData_t* getMemoryCardData(void); diff --git a/include/saves.h b/include/saves.h index 9fd1e95..d2c1534 100644 --- a/include/saves.h +++ b/include/saves.h @@ -95,6 +95,7 @@ enum cmd_code_enum CMD_COPY_DUMMY_PSV, CMD_IMPORT_DATA_FILE, CMD_HEX_EDIT_FILE, + CMD_DELETE_VMCSAVE, // Bulk commands CMD_RESIGN_SAVES, @@ -105,10 +106,8 @@ enum cmd_code_enum CMD_COPY_ALL_SAVES_HDD, CMD_SAVE_WEB_SERVER, CMD_RESIGN_VMP, - CMD_EXP_SAVES_VMC1, - CMD_EXP_ALL_SAVES_VMC1, - CMD_EXP_SAVES_VMC2, - CMD_EXP_ALL_SAVES_VMC2, + CMD_EXP_SAVES_VMC, + CMD_EXP_ALL_SAVES_VMC, // Export commands CMD_EXP_EXDATA_USB, @@ -156,11 +155,13 @@ enum cmd_code_enum #define SAVE_FLAG_ONLINE 256 #define SAVE_FLAG_SELECTED 512 #define SAVE_FLAG_VMC 1024 +#define SAVE_FLAG_UPDATED 2048 enum save_type_enum { FILE_TYPE_NULL, FILE_TYPE_MENU, + FILE_TYPE_PS3, FILE_TYPE_PSV, FILE_TYPE_TRP, FILE_TYPE_VMC, @@ -204,10 +205,10 @@ enum char_flag_enum CHAR_TAG_LOCKED, CHAR_TAG_NET, CHAR_RES_LF, - CHAR_TAG_TRANSFER, + CHAR_TAG_VMC, CHAR_TAG_ZIP, CHAR_RES_CR, - CHAR_TAG_VMC, + CHAR_TAG_TRANSFER, CHAR_TAG_WARNING, CHAR_BTN_X, CHAR_BTN_S, @@ -335,6 +336,7 @@ int vmc_export_psv(const char* save, const char* out_path); int vmc_export_psu(const char* path, const char* output); int vmc_import_psv(const char *input); int vmc_import_psu(const char *input); +int vmc_delete_save(const char* path); char* sjis2utf8(char* input); uint8_t* getIconPS2(const char* folder, const char* iconfile); diff --git a/source/exec_cmd.c b/source/exec_cmd.c index 143174f..93463f1 100644 --- a/source/exec_cmd.c +++ b/source/exec_cmd.c @@ -679,7 +679,7 @@ static void exportAllSavesVMC(const save_entry_t* save, int dev, int all) continue; if (item->type == FILE_TYPE_PS1) - (saveSingleSave(outPath, save->path[strlen(save->path)+1], PS1SAVE_PSV) ? done++ : err_count++); + (saveSingleSave(outPath, save->dir_name[0], PS1SAVE_PSV) ? done++ : err_count++); if (item->type == FILE_TYPE_PS2) (vmc_export_psv(item->dir_name, outPath) ? done++ : err_count++); @@ -695,7 +695,7 @@ static void exportVmcSave(const save_entry_t* save, int type, int dst_id) char outPath[256]; struct tm t; - _set_dest_path(outPath, dst_id, PS1_IMP_PATH_USB); + _set_dest_path(outPath, dst_id, (type == PS1SAVE_PSV) ? PSV_SAVES_PATH_USB : PS1_IMP_PATH_USB); mkdirs(outPath); if (type != PS1SAVE_PSV) { @@ -706,7 +706,7 @@ static void exportVmcSave(const save_entry_t* save, int type, int dst_id) (type == PS1SAVE_MCS) ? "mcs" : "psx"); } - if (saveSingleSave(outPath, save->path[strlen(save->path)+1], type)) + if (saveSingleSave(outPath, save->dir_name[0], type)) show_message("Save successfully exported to:\n%s", outPath); else show_message("Error exporting save:\n%s", save->path); @@ -1543,16 +1543,27 @@ static void downloadLink(const char* path) show_message("Error! File couldn't be downloaded"); } +static void deleteVmcSave(const save_entry_t* save) +{ + if (!show_dialog(DIALOG_TYPE_YESNO, "Do you want to delete %s?", save->dir_name)) + return; + + if ((save->flags & SAVE_FLAG_PS1) ? formatSave(save->dir_name[0]) : vmc_delete_save(save->dir_name)) + show_message("Save successfully deleted:\n%s", save->dir_name); + else + show_message("Error! Couldn't delete save:\n%s", save->dir_name); +} + static void import_mcr2vmp(const save_entry_t* save, const char* src) { char mcrPath[256]; uint8_t *data = NULL; size_t size = 0; - snprintf(mcrPath, sizeof(mcrPath), VMC_PS2_PATH_HDD "%s/%s", save->title_id, src); + snprintf(mcrPath, sizeof(mcrPath), "%s%s", VMC_PS2_PATH_HDD, src); read_buffer(mcrPath, &data, &size); - if (openMemoryCardStream(data, size, 0) && saveMemoryCard(save->path, 0, 0)) + if (openMemoryCardStream(data, size, 0)) show_message("Memory card successfully imported to:\n%s", save->path); else show_message("Error importing memory card:\n%s", mcrPath); @@ -1562,8 +1573,8 @@ static void export_vmp2mcr(const save_entry_t* save) { char mcrPath[256]; - snprintf(mcrPath, sizeof(mcrPath), VMC_PS2_PATH_HDD "%s/%s", save->title_id, strrchr(save->path, '/') + 1); - strcpy(strrchr(mcrPath, '.'), ".MCR"); + snprintf(mcrPath, sizeof(mcrPath), "%s%s", VMC_PS2_PATH_HDD, strrchr(save->path, '/') + 1); + strcpy(strrchr(mcrPath, '.'), ".VM1"); mkdirs(mcrPath); if (saveMemoryCard(mcrPath, PS1CARD_RAW, 0)) @@ -1802,9 +1813,9 @@ void execCodeCommand(code_entry_t* code, const char* codecmd) code->activated = 0; break; - case CMD_EXP_SAVES_VMC1: - case CMD_EXP_ALL_SAVES_VMC1: - exportAllSavesVMC(selected_entry, codecmd[1], codecmd[0] == CMD_EXP_ALL_SAVES_VMC1); + case CMD_EXP_SAVES_VMC: + case CMD_EXP_ALL_SAVES_VMC: + exportAllSavesVMC(selected_entry, codecmd[1], codecmd[0] == CMD_EXP_ALL_SAVES_VMC); code->activated = 0; break; @@ -1815,18 +1826,11 @@ void execCodeCommand(code_entry_t* code, const char* codecmd) case CMD_IMP_VMC1SAVE: if (openSingleSave(code->file, (int*) host_buf)) - { - saveMemoryCard(selected_entry->dir_name, 0, 0); show_message("Save successfully imported:\n%s", code->file); - } else show_message("Error! Couldn't import save:\n%s", code->file); - code->activated = 0; - break; - case CMD_EXP_SAVES_VMC2: - case CMD_EXP_ALL_SAVES_VMC2: - exportAllSavesVMC(selected_entry, codecmd[1], codecmd[0] == CMD_EXP_ALL_SAVES_VMC2); + selected_entry->flags |= SAVE_FLAG_UPDATED; code->activated = 0; break; @@ -1837,16 +1841,25 @@ void execCodeCommand(code_entry_t* code, const char* codecmd) case CMD_IMP_VMC2SAVE: import_save2vmc(code->file, codecmd[1]); + selected_entry->flags |= SAVE_FLAG_UPDATED; code->activated = 0; break; case CMD_IMP_MCR2VMP: import_mcr2vmp(selected_entry, code->options[0].name[code->options[0].sel]); + selected_entry->flags |= SAVE_FLAG_UPDATED; code->activated = 0; break; case CMD_IMP_PS2VMC_USB: importPS2VMC(selected_entry->path, code->file); + selected_entry->flags |= SAVE_FLAG_UPDATED; + code->activated = 0; + break; + + case CMD_DELETE_VMCSAVE: + deleteVmcSave(selected_entry); + selected_entry->flags |= SAVE_FLAG_UPDATED; code->activated = 0; break; diff --git a/source/mcio.c b/source/mcio.c index c27457a..6b56bf4 100644 --- a/source/mcio.c +++ b/source/mcio.c @@ -47,7 +47,7 @@ static const char SUPERBLOCK_MAGIC[] = "Sony PS2 Memory Card Format "; static const char SUPERBLOCK_VERSION[] = "1.2.0.0\0\0\0\0"; static FILE *vmc_fp = NULL; -static char vmcpath[256]; +static char vmcpath[256] = ""; struct MCDevInfo { /* size = 384 */ uint8_t magic[28]; /* Superblock magic, on PS2 MC : "Sony PS2 Memory Card Format " */ @@ -2980,10 +2980,8 @@ static int Card_FileWrite(int fd, void *buffer, int nbyte) int mcio_vmcInit(const char* vmc) { int r; - vmcpath[0] = 0; - if (vmc_fp) - fclose(vmc_fp); + mcio_vmcFinish(); // decrypt ps2classic format if (strcmp(".VME", strrchr(vmc, '.')) == 0) @@ -3022,6 +3020,7 @@ void mcio_vmcFinish(void) unlink_secure(vmcpath); } + vmcpath[0] = 0; vmc_fp = NULL; } diff --git a/source/menu_main.c b/source/menu_main.c index 4c1c72f..faeef75 100644 --- a/source/menu_main.c +++ b/source/menu_main.c @@ -125,20 +125,59 @@ static code_entry_t* LoadRawPatch(void) return centry; } -static code_entry_t* LoadSaveDetails(void) +static code_entry_t* LoadSaveDetails(const save_entry_t* save) { char sfoPath[256]; code_entry_t* centry = calloc(1, sizeof(code_entry_t)); - centry->name = strdup(selected_entry->title_id); + centry->name = strdup(save->title_id); + + if(save->type == FILE_TYPE_PS1) + { + asprintf(¢ry->codes, "%s\n\n----- PS1 Save -----\n" + "Game: %s\n" + "Title ID: %s\n" + "File: %s\n", + save->path, + save->name, + save->title_id, + save->dir_name+1); + return(centry); + } + + if(save->type == FILE_TYPE_PS2) + { + asprintf(¢ry->codes, "%s\n\n----- PS2 Save -----\n" + "Game: %s\n" + "Title ID: %s\n" + "Folder: %s\n" + "Icon: %s\n", + save->path, + save->name, + save->title_id, + save->dir_name, + strrchr(save->path, '\n')+1); + return(centry); + } - if (!(selected_entry->flags & SAVE_FLAG_PS3)) + if(save->type == FILE_TYPE_VMC) { - asprintf(¢ry->codes, "%s\n\nTitle: %s\n", selected_entry->path, selected_entry->name); + asprintf(¢ry->codes, "%s\n\n----- Virtual Memory Card -----\n" + "File: %s\n" + "Folder: %s\n", + save->path, + strrchr(save->path, '/')+1, + save->dir_name); return(centry); } - snprintf(sfoPath, sizeof(sfoPath), "%s" "PARAM.SFO", selected_entry->path); + if (!(save->flags & SAVE_FLAG_PS3)) + { + asprintf(¢ry->codes, "%s\n\nTitle: %s\n", save->path, save->name); + return(centry); + } + + snprintf(sfoPath, sizeof(sfoPath), "%s" "PARAM.SFO", save->path); LOG("Save Details :: Reading %s...", sfoPath); sfo_context_t* sfo = sfo_alloc(); @@ -148,13 +187,13 @@ static code_entry_t* LoadSaveDetails(void) return centry; } - if (selected_entry->flags & SAVE_FLAG_TROPHY) + if (save->flags & SAVE_FLAG_TROPHY) { char* account = (char*) sfo_get_param_value(sfo, "ACCOUNTID"); asprintf(¢ry->codes, "%s\n\n" "Title: %s\n" "NP Comm ID: %s\n" - "Account ID: %.16s\n", selected_entry->path, selected_entry->name, selected_entry->title_id, account); + "Account ID: %.16s\n", save->path, save->name, save->title_id, account); LOG(centry->codes); sfo_free(sfo); @@ -172,11 +211,11 @@ static code_entry_t* LoadSaveDetails(void) "Lock: %s\n\n" "User ID: %08d\n" "Account ID: %.16s (%s)\n" - "PSID: %016lX %016lX\n", selected_entry->path, selected_entry->name, subtitle, - selected_entry->dir_name, - (selected_entry->flags & SAVE_FLAG_LOCKED ? "Copying Prohibited" : "Unlocked"), + "PSID: %016lX %016lX\n", save->path, save->name, subtitle, + save->dir_name, + (save->flags & SAVE_FLAG_LOCKED ? "Copying Prohibited" : "Unlocked"), param_ids->user_id, param_ids->account_id, - (selected_entry->flags & SAVE_FLAG_OWNER ? "Owner" : "Not Owner"), + (save->flags & SAVE_FLAG_OWNER ? "Owner" : "Not Owner"), param_ids->psid[0], param_ids->psid[1]); LOG(centry->codes); @@ -191,11 +230,8 @@ static void SetMenu(int id) case MENU_PS1VMC_SAVES: if (id == MENU_MAIN_SCREEN) { - init_loading_screen("Saving PS1 Memory Card..."); UnloadGameList(vmc1_saves.list); vmc1_saves.list = NULL; - saveMemoryCard(vmc1_saves.path, 0, 0); - stop_loading_screen(); } break; @@ -221,7 +257,21 @@ static void SetMenu(int id) case MENU_SETTINGS: //Options Menu case MENU_CREDITS: //About Menu + break; + case MENU_PATCHES: //Cheat Selection Menu + if (selected_entry->flags & SAVE_FLAG_UPDATED && id == MENU_PS1VMC_SAVES) + { + selected_entry->flags ^= SAVE_FLAG_UPDATED; + saveMemoryCard(vmc1_saves.path, 0, 0); + ReloadUserSaves(&vmc1_saves); + } + + else if (selected_entry->flags & SAVE_FLAG_UPDATED && id == MENU_PS2VMC_SAVES) + { + selected_entry->flags ^= SAVE_FLAG_UPDATED; + ReloadUserSaves(&vmc2_saves); + } break; case MENU_SAVE_DETAILS: @@ -334,7 +384,7 @@ static void SetMenu(int id) } if (selected_entry->flags & SAVE_FLAG_VMC && selected_entry->type == FILE_TYPE_PS1) - LoadVmcTexture(16, 16, getIconRGBA(selected_entry->path[strlen(selected_entry->path)+1], 0)); + LoadVmcTexture(16, 16, getIconRGBA(selected_entry->dir_name[0], 0)); if (selected_entry->flags & SAVE_FLAG_VMC && selected_entry->type == FILE_TYPE_PS2) LoadVmcTexture(128, 128, getIconPS2(selected_entry->dir_name, strrchr(selected_entry->path, '\n')+1)); @@ -480,7 +530,7 @@ static void doSaveMenu(save_list_t * save_list) selected_entry = list_get_item(save_list->list, menu_sel); if (selected_entry->type != FILE_TYPE_MENU) { - selected_centry = LoadSaveDetails(); + selected_centry = LoadSaveDetails(selected_entry); SetMenu(MENU_SAVE_DETAILS); return; } @@ -877,7 +927,7 @@ static void doPatchMenu(void) if (selected_centry->codes[0] == CMD_VIEW_DETAILS) { selected_centry->activated = 0; - selected_centry = LoadSaveDetails(); + selected_centry = LoadSaveDetails(selected_entry); SetMenu(MENU_SAVE_DETAILS); return; } diff --git a/source/ps1card.c b/source/ps1card.c index d0b5756..27f56d5 100644 --- a/source/ps1card.c +++ b/source/ps1card.c @@ -568,7 +568,7 @@ static void formatSlot(int slotNumber) } //Format save -void formatSave(int slotNumber) +int formatSave(int slotNumber) { //Get all linked saves int saveSlots_Length; @@ -576,6 +576,9 @@ void formatSave(int slotNumber) saveSlots_Length = findSaveLinks(slotNumber, saveSlots); + if (!saveSlots_Length) + return false; + //Cycle through each slot for (int i = 0; i < saveSlots_Length; i++) { @@ -594,6 +597,7 @@ void formatSave(int slotNumber) //Set changedFlag to edited changedFlag = true; + return true; } //Find and return continuous free slots diff --git a/source/ps2classic.c b/source/ps2classic.c index 8cf3623..49df31b 100644 --- a/source/ps2classic.c +++ b/source/ps2classic.c @@ -750,7 +750,7 @@ void ps2_crypt_vmc(u8 dex_mode, const char* vmc_path, const char* vmc_out, int c LOG("VMC (dex)\n"); memcpy(ps2_vmc_key, ps2_key_dex_vmc, 0x10); }else{ - LOG("VMC (cex)\n"); + LOG("VMC (cex) '%s' -> '%s'", vmc_path, vmc_out); memcpy(ps2_vmc_key, ps2_key_cex_vmc, 0x10); } diff --git a/source/psv_resign.c b/source/psv_resign.c index 2c1352c..6b8e2b1 100644 --- a/source/psv_resign.c +++ b/source/psv_resign.c @@ -911,3 +911,31 @@ int vmc_export_psu(const char* path, const char* output) return (i > 0); } + +int vmc_delete_save(const char* path) +{ + int r, dd; + struct io_dirent dirent; + char filepath[256]; + + LOG("Deleting '%s'...", path); + + dd = mcio_mcDopen(path); + if (dd < 0) + return 0; + + do { + r = mcio_mcDread(dd, &dirent); + if (r && (strcmp(dirent.name, ".")) && (strcmp(dirent.name, ".."))) + { + snprintf(filepath, sizeof(filepath), "%s/%s", path, dirent.name); + LOG("Deleting '%s'", filepath); + mcio_mcRemove(filepath); + } + } while (r); + + mcio_mcDclose(dd); + r = mcio_mcRmDir(path); + + return (r == sceMcResSucceed); +} diff --git a/source/saves.c b/source/saves.c index eb477fc..d618656 100644 --- a/source/saves.c +++ b/source/saves.c @@ -26,8 +26,8 @@ #define CHAR_ICON_NET "\x09" #define CHAR_ICON_ZIP "\x0C" -#define CHAR_ICON_VMC "\x0E" -#define CHAR_ICON_COPY "\x0B" +#define CHAR_ICON_VMC "\x0B" +#define CHAR_ICON_COPY "\x0E" #define CHAR_ICON_SIGN "\x06" #define CHAR_ICON_USER "\x07" #define CHAR_ICON_LOCK "\x08" @@ -401,14 +401,13 @@ static void add_vmp_commands(save_entry_t* save) list_append(save->codes, cmd); } - cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export Memory Card to .MCR", CMD_EXP_VMP2MCR); + cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export Memory Card to .VM1", CMD_EXP_VMP2MCR); list_append(save->codes, cmd); - snprintf(path, sizeof(path), CHAR_ICON_COPY " Import .MCR files to %s", strrchr(save->path, '/')+1); + snprintf(path, sizeof(path), CHAR_ICON_COPY " Import .VM1 file to %s", strrchr(save->path, '/')+1); cmd = _createCmdCode(PATCH_COMMAND, path, CMD_CODE_NULL); cmd->options_count = 1; - snprintf(path, sizeof(path), VMC_PS2_PATH_HDD "%s/", save->title_id); - cmd->options = _getFileOptions(path, "*.MCR", CMD_IMP_MCR2VMP); + cmd->options = _getFileOptions(VMC_PS2_PATH_HDD, "*.VM1", CMD_IMP_MCR2VMP); list_append(save->codes, cmd); return; @@ -777,10 +776,13 @@ 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); + list_append(save->codes, cmd); + cmd = _createCmdCode(PATCH_NULL, "----- " UTF8_CHAR_STAR " Save Game Backup " UTF8_CHAR_STAR " -----", CMD_CODE_NULL); list_append(save->codes, cmd); - cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export save game to MCS format", CMD_CODE_NULL); + cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export save game to .MCS format", CMD_CODE_NULL); cmd->options_count = 1; cmd->options = _createOptions(3, "Copy .MCS Save to USB", CMD_EXP_VMC1SAVE); asprintf(&cmd->options->name[2], "Copy .MCS Save to HDD"); @@ -788,7 +790,7 @@ int ReadVmc1Codes(save_entry_t * save) cmd->options[0].id = PS1SAVE_MCS; list_append(save->codes, cmd); - cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export save game to PSV format", CMD_CODE_NULL); + cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export save game to .PSV format", CMD_CODE_NULL); cmd->options_count = 1; cmd->options = _createOptions(3, "Copy .PSV Save to USB", CMD_EXP_VMC1SAVE); asprintf(&cmd->options->name[2], "Copy .PSV Save to HDD"); @@ -796,7 +798,7 @@ int ReadVmc1Codes(save_entry_t * save) cmd->options[0].id = PS1SAVE_PSV; list_append(save->codes, cmd); - cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export save game to PSX format", CMD_CODE_NULL); + cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export save game to .PSX format", CMD_CODE_NULL); cmd->options_count = 1; cmd->options = _createOptions(3, "Copy .PSX Save to USB", CMD_EXP_VMC1SAVE); asprintf(&cmd->options->name[2], "Copy .PSX Save to HDD"); @@ -896,6 +898,9 @@ 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); + list_append(save->codes, cmd); + cmd = _createCmdCode(PATCH_NULL, "----- " UTF8_CHAR_STAR " Save Game Backup " UTF8_CHAR_STAR " -----", CMD_CODE_NULL); list_append(save->codes, cmd); @@ -942,11 +947,11 @@ int ReadOnlineSaves(save_entry_t * game) stat(path, &stats); // re-download if file is +1 day old if ((stats.st_mtime + ONLINE_CACHE_TIMEOUT) < time(NULL)) - http_download(game->path, "saves.txt", path, 0); + http_download(game->path, "saves.txt", path, 1); } else { - if (!http_download(game->path, "saves.txt", path, 0)) + if (!http_download(game->path, "saves.txt", path, 1)) return -1; } @@ -1547,6 +1552,7 @@ static void read_savegames(const char* userPath, const char* folder, list_t *lis { sfo_data = (char*) sfo_get_param_value(sfo, "ATTRIBUTE"); item->flags |= (sfo_data[0] ? SAVE_FLAG_LOCKED : 0); + item->type = FILE_TYPE_PS3; snprintf(sfoPath, sizeof(sfoPath), "%*lx", SFO_ACCOUNT_ID_SIZE, apollo_config.account_id); sfo_data = (char*) sfo_get_param_value(sfo, "ACCOUNT_ID"); @@ -1648,6 +1654,7 @@ static void read_psv_savegames(const char* userPath, const char* folder, list_t item = (save_entry_t *)malloc(sizeof(save_entry_t)); memset(item, 0, sizeof(save_entry_t)); item->flags = SAVE_FLAG_PSV | (type == 1 ? SAVE_FLAG_PS1 : SAVE_FLAG_PS2); + item->type = FILE_TYPE_PSV; asprintf(&item->path, "%s%s%s", userPath, folder, dir->d_name); asprintf(&item->title_id, "%.10s", dir->d_name + 2); @@ -1958,6 +1965,7 @@ list_t * ReadOnlineList(const char* urlPath) list_t * ReadVmc1List(const char* userPath) { + char filePath[256]; save_entry_t *item; code_entry_t *cmd; list_t *list; @@ -1986,30 +1994,36 @@ list_t * ReadVmc1List(const char* userPath) cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export selected Saves to USB", CMD_CODE_NULL); cmd->options_count = 1; - cmd->options = _createOptions(2, "Copy selected Saves to USB", CMD_EXP_SAVES_VMC1); + cmd->options = _createOptions(2, "Copy selected Saves to USB", CMD_EXP_SAVES_VMC); list_append(item->codes, cmd); cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export all Saves to USB", CMD_CODE_NULL); cmd->options_count = 1; - cmd->options = _createOptions(2, "Copy all Saves to USB", CMD_EXP_ALL_SAVES_VMC1); + cmd->options = _createOptions(2, "Copy all Saves to USB", CMD_EXP_ALL_SAVES_VMC); list_append(item->codes, cmd); add_vmp_commands(item); list_append(list, item); item = _createSaveEntry(SAVE_FLAG_PS1, CHAR_ICON_COPY " Import Saves to Virtual Card"); - if (strncmp(userPath, USB_PATH, 8) == 0) - { - item->path = strdup(userPath); - strchr(item->path + 1, '/')[1] = 0; - } - else - item->path = strdup(FAKE_USB_PATH); - - item->title_id = strdup(item->path); - strchr(item->title_id + 1, '/')[0] = 0; + item->path = strdup(FAKE_USB_PATH); + item->title_id = strdup("HDD"); item->dir_name = strdup(userPath); item->type = FILE_TYPE_MENU; list_append(list, item); + for (int i = 0; i <= MAX_USB_DEVICES; i++) + { + snprintf(filePath, sizeof(filePath), USB_PATH, i); + if (i && dir_exists(filePath) != SUCCESS) + continue; + + item = _createSaveEntry(SAVE_FLAG_PS1, CHAR_ICON_COPY " Import Saves to Virtual Card"); + asprintf(&item->path, USB_PATH, i); + asprintf(&item->title_id, "USB %d", i); + item->dir_name = strdup(userPath); + item->type = FILE_TYPE_MENU; + list_append(list, item); + } + for (int i = 0; i < PS1CARD_MAX_SLOTS; i++) { if (mcdata[i].saveType != PS1BLOCK_INITIAL) @@ -2020,10 +2034,10 @@ list_t * ReadVmc1List(const char* userPath) char* tmp = sjis2utf8(mcdata[i].saveTitle); item = _createSaveEntry(SAVE_FLAG_PS1 | SAVE_FLAG_VMC, tmp); item->type = FILE_TYPE_PS1; - item->dir_name = strdup(mcdata[i].saveName); item->title_id = strdup(mcdata[i].saveProdCode); //hack to keep the save block - asprintf(&item->path, "%s\n%s/%c%c", userPath, mcdata[i].saveName, 0, i); + asprintf(&item->dir_name, "%c%s", i, mcdata[i].saveName); + asprintf(&item->path, "%s\n%s", userPath, mcdata[i].saveName); free(tmp); LOG("[%s] F(%X) name '%s'", item->title_id, item->flags, item->name); @@ -2062,11 +2076,11 @@ list_t * ReadVmc2List(const char* userPath) cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export selected Saves to USB", CMD_CODE_NULL); cmd->options_count = 1; - cmd->options = _createOptions(2, "Copy selected Saves to USB", CMD_EXP_SAVES_VMC2); + cmd->options = _createOptions(2, "Copy selected Saves to USB", CMD_EXP_SAVES_VMC); list_append(item->codes, cmd); cmd = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Export all Saves to USB", CMD_CODE_NULL); cmd->options_count = 1; - cmd->options = _createOptions(2, "Copy all Saves to USB", CMD_EXP_ALL_SAVES_VMC2); + cmd->options = _createOptions(2, "Copy all Saves to USB", CMD_EXP_ALL_SAVES_VMC); list_append(item->codes, cmd); list_append(list, item); @@ -2100,19 +2114,24 @@ list_t * ReadVmc2List(const char* userPath) } item = _createSaveEntry(SAVE_FLAG_PS2, CHAR_ICON_COPY " Import Saves to Virtual Card"); - if (strncmp(userPath, USB_PATH, 8) == 0) - { - item->path = strdup(userPath); - strchr(item->path + 1, '/')[1] = 0; - } - else - item->path = strdup(FAKE_USB_PATH); - - item->title_id = strdup(item->path); - strchr(item->title_id + 1, '/')[0] = 0; + item->path = strdup(FAKE_USB_PATH); + item->title_id = strdup("HDD"); item->type = FILE_TYPE_MENU; list_append(list, item); + for (int i = 0; i <= MAX_USB_DEVICES; i++) + { + snprintf(filePath, sizeof(filePath), USB_PATH, i); + if (i && dir_exists(filePath) != SUCCESS) + continue; + + item = _createSaveEntry(SAVE_FLAG_PS2, CHAR_ICON_COPY " Import Saves to Virtual Card"); + asprintf(&item->path, USB_PATH, i); + asprintf(&item->title_id, "USB %d", i); + item->type = FILE_TYPE_MENU; + list_append(list, item); + } + dd = mcio_mcDopen("/"); if (dd < 0) {