From d0d0179a494ba1a1f13f5515354b76bf7c0e8b18 Mon Sep 17 00:00:00 2001 From: bucanero Date: Fri, 20 Dec 2024 13:49:37 -0300 Subject: [PATCH] xmb trophy lock/unlock --- include/saves.h | 5 +- source/exec_cmd.c | 46 +++++++++++++++++++ source/menu_main.c | 4 +- source/saves.c | 111 +++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 155 insertions(+), 11 deletions(-) diff --git a/include/saves.h b/include/saves.h index 4253b03..9dd8912 100644 --- a/include/saves.h +++ b/include/saves.h @@ -73,7 +73,7 @@ enum cmd_code_enum CMD_CODE_NULL, // Trophy commands - CMD_RESIGN_TROPHY, + CMD_UPDATE_TROPHY, CMD_EXP_TROPHY_USB, CMD_COPY_TROPHIES_USB, CMD_COPY_ALL_TROPHIES_USB, @@ -315,6 +315,9 @@ 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 trophy_lock(const save_entry_t* game, int trp_id, int type); +int trophy_unlock(const save_entry_t* game, int trp_id, int type); + 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); diff --git a/source/exec_cmd.c b/source/exec_cmd.c index 85d3c94..0e72390 100644 --- a/source/exec_cmd.c +++ b/source/exec_cmd.c @@ -337,6 +337,47 @@ static void exportFingerprint(const save_entry_t* save, int silent) fclose(fp); } +static void toggleTrophy(const save_entry_t* entry) +{ + int ret = 1; + uint32_t trophy_id; + code_entry_t* code; + list_node_t* node; + + init_loading_screen("Applying changes..."); + + for (node = list_head(entry->codes); (code = list_get(node)); node = list_next(node)) + { + if (!code->activated || (code->type != PATCH_TROP_UNLOCK && code->type != PATCH_TROP_LOCK)) + continue; + + trophy_id = *(uint32_t*)(code->file); + LOG("Active code: [%d] '%s'", trophy_id, code->name+2); + + if (code->type == PATCH_TROP_UNLOCK) + { + ret &= trophy_unlock(entry, trophy_id, code->name[0]); + code->type = PATCH_TROP_LOCK; + code->name[1] = ' '; + } + else + { + ret &= trophy_lock(entry, trophy_id, code->name[0]); + code->type = PATCH_TROP_UNLOCK; + code->name[1] = CHAR_TAG_LOCKED; + } + + code->activated = 0; + } + + stop_loading_screen(); + + if(ret) + show_message("Trophies successfully updated!"); + else + show_message("Error! Couldn't update trophies"); +} + static void exportTrophiesZip(const char* exp_path) { char* export_file; @@ -1393,6 +1434,11 @@ void execCodeCommand(code_entry_t* code, const char* codecmd) code->activated = 0; break; + case CMD_UPDATE_TROPHY: + toggleTrophy(selected_entry); + code->activated = 0; + break; + case CMD_ZIP_TROPHY_USB: exportTrophiesZip(codecmd[1] ? EXPORT_PATH_USB1 : EXPORT_PATH_USB0); code->activated = 0; diff --git a/source/menu_main.c b/source/menu_main.c index 618aa54..a8df4b7 100644 --- a/source/menu_main.c +++ b/source/menu_main.c @@ -124,7 +124,7 @@ static void SetMenu(int id) if(strncmp(APOLLO_SANDBOX_PATH, vmc1_saves.path, 16) == 0) { *strrchr(vmc1_saves.path, '/') = 0; - orbis_SaveUmount(strrchr(vmc1_saves.path, '/')); + orbis_SaveUmount(strrchr(vmc1_saves.path, '/')+1); } } break; @@ -140,7 +140,7 @@ static void SetMenu(int id) if(strncmp(APOLLO_SANDBOX_PATH, vmc2_saves.path, 16) == 0) { *strrchr(vmc2_saves.path, '/') = 0; - orbis_SaveUmount(strrchr(vmc2_saves.path, '/')); + orbis_SaveUmount(strrchr(vmc2_saves.path, '/')+1); } stop_loading_screen(); diff --git a/source/saves.c b/source/saves.c index b59235c..8b2bd20 100644 --- a/source/saves.c +++ b/source/saves.c @@ -382,6 +382,101 @@ int appdb_rebuild(const char* db_path, uint32_t userid) return 1; } +static const char* trophy_type_field(int type) +{ + switch (type) + { + case CHAR_TRP_PLATINUM: + return "unlocked_platinum_num"; + + case CHAR_TRP_GOLD: + return "unlocked_gold_num"; + + case CHAR_TRP_SILVER: + return "unlocked_silver_num"; + + case CHAR_TRP_BRONZE: + return "unlocked_bronze_num"; + + default: + return NULL; + } +} + +int trophy_unlock(const save_entry_t* game, int trp_id, int type) +{ + char dbpath[256]; + sqlite3 *db; + const char *field = trophy_type_field(type); + + if (!field) + return 0; + + snprintf(dbpath, sizeof(dbpath), TROPHY_DB_PATH, apollo_config.user_id); + if ((db = open_sqlite_db(dbpath)) == NULL) + return 0; + + char* query = sqlite3_mprintf("UPDATE tbl_trophy_flag SET (visible, unlocked, time_unlocked, time_unlocked_uc) =" + "(1, 1, strftime('%%Y-%%m-%%dT%%H:%%M:%%S.00Z', CURRENT_TIMESTAMP), strftime('%%Y-%%m-%%dT%%H:%%M:%%S.00Z', CURRENT_TIMESTAMP))" + "WHERE (title_id = %d AND trophyid = %d);\n" + "UPDATE tbl_trophy_title SET (progress, unlocked_trophy_num, %s) =" + "(((unlocked_trophy_num+1)*100)/trophy_num, unlocked_trophy_num+1, %s+1) WHERE (id=%d);", + game->blocks, trp_id, + field, field, game->blocks); + + if (sqlite3_exec(db, query, NULL, NULL, NULL) != SQLITE_OK) + { + LOG("Error updating '%s': %s", game->title_id, sqlite3_errmsg(db)); + sqlite3_free(query); + sqlite3_close(db); + return 0; + } + + LOG("Saving database to %s", dbpath); + sqlite3_memvfs_dump(db, NULL, dbpath); + sqlite3_free(query); + sqlite3_close(db); + + return 1; +} + +int trophy_lock(const save_entry_t* game, int trp_id, int type) +{ + char dbpath[256]; + sqlite3 *db; + const char *field = trophy_type_field(type); + + if (!field) + return 0; + + snprintf(dbpath, sizeof(dbpath), TROPHY_DB_PATH, apollo_config.user_id); + if ((db = open_sqlite_db(dbpath)) == NULL) + return 0; + + char* query = sqlite3_mprintf("UPDATE tbl_trophy_flag SET (visible, unlocked, time_unlocked, time_unlocked_uc) =" + "((~(hidden&1))&(hidden|1), 0, '0001-01-01T00:00:00.00Z', '0001-01-01T00:00:00.00Z') " + "WHERE (title_id = %d AND trophyid = %d);\n" + "UPDATE tbl_trophy_title SET (progress, unlocked_trophy_num, %s) =" + "(((unlocked_trophy_num-1)*100)/trophy_num, unlocked_trophy_num-1, %s-1) WHERE (id=%d);", + game->blocks, trp_id, + field, field, game->blocks); + + if (sqlite3_exec(db, query, NULL, NULL, NULL) != SQLITE_OK) + { + LOG("Error updating '%s': %s", game->title_id, sqlite3_errmsg(db)); + sqlite3_free(query); + sqlite3_close(db); + return 0; + } + + LOG("Saving database to %s", dbpath); + sqlite3_memvfs_dump(db, NULL, dbpath); + sqlite3_free(query); + sqlite3_close(db); + + return 1; +} + int orbis_SaveDelete(const save_entry_t *save) { OrbisSaveDataDelete del; @@ -934,7 +1029,7 @@ int ReadCodes(save_entry_t * save) int ReadTrophies(save_entry_t * game) { - int trop_count = 0; + int trop_id = 0; code_entry_t * trophy; char query[256]; char mount[ORBIS_SAVE_DATA_DIRNAME_DATA_MAXSIZE]; @@ -956,8 +1051,8 @@ int ReadTrophies(save_entry_t * game) tmp = game->path; asprintf(&game->path, APOLLO_SANDBOX_PATH, mount); -// trophy = _createCmdCode(PATCH_COMMAND, CHAR_ICON_SIGN " Apply Changes & Resign Trophy Set", CMD_RESIGN_TROPHY); -// list_append(game->codes, trophy); + trophy = _createCmdCode(PATCH_COMMAND, CHAR_ICON_SIGN " Apply Changes to Trophy Set", CMD_UPDATE_TROPHY); + list_append(game->codes, trophy); trophy = _createCmdCode(PATCH_COMMAND, CHAR_ICON_COPY " Backup Trophy files to USB", CMD_CODE_NULL); trophy->file = strdup(game->path); @@ -993,7 +1088,7 @@ int ReadTrophies(save_entry_t * game) trophy = _createCmdCode(PATCH_NULL, "----- " UTF8_CHAR_STAR " Trophies " UTF8_CHAR_STAR " -----", CMD_CODE_NULL); list_append(game->codes, trophy); - snprintf(query, sizeof(query), "SELECT title_id, trophy_title_id, title, description, grade, unlocked, id FROM tbl_trophy_flag WHERE title_id = %d", game->blocks); + snprintf(query, sizeof(query), "SELECT trophyid, trophy_title_id, title, description, grade, unlocked FROM tbl_trophy_flag WHERE title_id = %d", game->blocks); if (sqlite3_prepare_v2(db, query, -1, &res, NULL) != SQLITE_OK) { @@ -1031,9 +1126,9 @@ int ReadTrophies(save_entry_t * game) break; } - trop_count = sqlite3_column_int(res, 6); - trophy->file = malloc(sizeof(trop_count)); - memcpy(trophy->file, &trop_count, sizeof(trop_count)); + trop_id = sqlite3_column_int(res, 0); + trophy->file = malloc(sizeof(trop_id)); + memcpy(trophy->file, &trop_id, sizeof(trop_id)); if (!sqlite3_column_int(res, 5)) trophy->name[1] = CHAR_TAG_LOCKED; @@ -1044,7 +1139,7 @@ int ReadTrophies(save_entry_t * game) else trophy->type = (sqlite3_column_int(res, 5) ? PATCH_TROP_LOCK : PATCH_TROP_UNLOCK); - LOG("Trophy=%d [%d] '%s' (%s)", trop_count, trophy->type, trophy->name, trophy->codes); + LOG("Trophy=%d [%d] '%s' (%s)", trop_id, trophy->type, trophy->name+2, trophy->codes); list_append(game->codes, trophy); }