From 11229c1dc02fcb6380ac0225c340baa30d9cd891 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Sun, 5 Oct 2025 10:39:14 -0500 Subject: [PATCH] Use correct trophy folder for games with multiple trophy lists (#3704) Based on the games I've checked, it seems like the service label parameter of sceNpTrophyCreateContext is what determines the trophy list. Since we're already storing the service label in our contexts, and we're already extracting all trophy lists, all that needs doing is using the service label to select the right trophy list. --- src/core/libraries/np/np_trophy.cpp | 73 +++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/src/core/libraries/np/np_trophy.cpp b/src/core/libraries/np/np_trophy.cpp index f50d1d498..7468de13b 100644 --- a/src/core/libraries/np/np_trophy.cpp +++ b/src/core/libraries/np/np_trophy.cpp @@ -243,9 +243,19 @@ u64 ReadFile(Common::FS::IOFile& file, void* buf, u64 nbytes) { int PS4_SYSV_ABI sceNpTrophyGetGameIcon(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, void* buffer, u64* size) { ASSERT(size != nullptr); + + Common::SlotId contextId; + contextId.index = context - 1; + if (contextId.index >= trophy_contexts.size()) { + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + } + ContextKey contextkey = trophy_contexts[contextId]; + char trophy_folder[9]; + snprintf(trophy_folder, sizeof(trophy_folder), "trophy%02d", contextkey.second); + const auto trophy_dir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; - auto icon_file = trophy_dir / "trophy00" / "Icons" / "ICON0.PNG"; + auto icon_file = trophy_dir / trophy_folder / "Icons" / "ICON0.PNG"; Common::FS::IOFile icon(icon_file, Common::FS::FileAccessMode::Read); if (!icon.IsOpen()) { @@ -287,9 +297,18 @@ int PS4_SYSV_ABI sceNpTrophyGetGameInfo(OrbisNpTrophyContext context, OrbisNpTro if (details->size != 0x4A0 || data->size != 0x20) return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + Common::SlotId contextId; + contextId.index = context - 1; + if (contextId.index >= trophy_contexts.size()) { + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + } + ContextKey contextkey = trophy_contexts[contextId]; + char trophy_folder[9]; + snprintf(trophy_folder, sizeof(trophy_folder), "trophy%02d", contextkey.second); + const auto trophy_dir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; - auto trophy_file = trophy_dir / "trophy00" / "Xml" / "TROP.XML"; + auto trophy_file = trophy_dir / trophy_folder / "Xml" / "TROP.XML"; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); @@ -385,9 +404,18 @@ int PS4_SYSV_ABI sceNpTrophyGetGroupInfo(OrbisNpTrophyContext context, OrbisNpTr if (details->size != 0x4A0 || data->size != 0x28) return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + Common::SlotId contextId; + contextId.index = context - 1; + if (contextId.index >= trophy_contexts.size()) { + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + } + ContextKey contextkey = trophy_contexts[contextId]; + char trophy_folder[9]; + snprintf(trophy_folder, sizeof(trophy_folder), "trophy%02d", contextkey.second); + const auto trophy_dir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; - auto trophy_file = trophy_dir / "trophy00" / "Xml" / "TROP.XML"; + auto trophy_file = trophy_dir / trophy_folder / "Xml" / "TROP.XML"; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); @@ -487,9 +515,18 @@ int PS4_SYSV_ABI sceNpTrophyGetTrophyInfo(OrbisNpTrophyContext context, OrbisNpT if (details->size != 0x498 || data->size != 0x18) return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + Common::SlotId contextId; + contextId.index = context - 1; + if (contextId.index >= trophy_contexts.size()) { + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + } + ContextKey contextkey = trophy_contexts[contextId]; + char trophy_folder[9]; + snprintf(trophy_folder, sizeof(trophy_folder), "trophy%02d", contextkey.second); + const auto trophy_dir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; - auto trophy_file = trophy_dir / "trophy00" / "Xml" / "TROP.XML"; + auto trophy_file = trophy_dir / trophy_folder / "Xml" / "TROP.XML"; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); @@ -552,9 +589,18 @@ s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(OrbisNpTrophyContext context, ORBIS_NP_TROPHY_FLAG_ZERO(flags); + Common::SlotId contextId; + contextId.index = context - 1; + if (contextId.index >= trophy_contexts.size()) { + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + } + ContextKey contextkey = trophy_contexts[contextId]; + char trophy_folder[9]; + snprintf(trophy_folder, sizeof(trophy_folder), "trophy%02d", contextkey.second); + const auto trophy_dir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; - auto trophy_file = trophy_dir / "trophy00" / "Xml" / "TROP.XML"; + auto trophy_file = trophy_dir / trophy_folder / "Xml" / "TROP.XML"; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); @@ -911,9 +957,18 @@ int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTr if (platinumId == nullptr) return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + Common::SlotId contextId; + contextId.index = context - 1; + if (contextId.index >= trophy_contexts.size()) { + return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; + } + ContextKey contextkey = trophy_contexts[contextId]; + char trophy_folder[9]; + snprintf(trophy_folder, sizeof(trophy_folder), "trophy%02d", contextkey.second); + const auto trophy_dir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / game_serial / "TrophyFiles"; - auto trophy_file = trophy_dir / "trophy00" / "Xml" / "TROP.XML"; + auto trophy_file = trophy_dir / trophy_folder / "Xml" / "TROP.XML"; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); @@ -981,7 +1036,7 @@ int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTr trophy_icon_file.append(".PNG"); std::filesystem::path current_icon_path = - trophy_dir / "trophy00" / "Icons" / trophy_icon_file; + trophy_dir / trophy_folder / "Icons" / trophy_icon_file; AddTrophyToQueue(current_icon_path, current_trophy_name, current_trophy_type); } @@ -1018,14 +1073,14 @@ int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTr platinum_icon_file.append(".PNG"); std::filesystem::path platinum_icon_path = - trophy_dir / "trophy00" / "Icons" / platinum_icon_file; + trophy_dir / trophy_folder / "Icons" / platinum_icon_file; *platinumId = platinum_trophy_id; AddTrophyToQueue(platinum_icon_path, platinum_trophy_name, "P"); } } - doc.save_file((trophy_dir / "trophy00" / "Xml" / "TROP.XML").native().c_str()); + doc.save_file((trophy_dir / trophy_folder / "Xml" / "TROP.XML").native().c_str()); return ORBIS_OK; }