// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include #include #include "common/logging/log.h" #include "common/path_util.h" #include "common/slot_vector.h" #include "core/libraries/libs.h" #include "core/libraries/np/np_error.h" #include "core/libraries/np/np_trophy.h" #include "core/libraries/np/np_trophy_error.h" #include "core/libraries/np/trophy_ui.h" #include "core/memory.h" namespace Libraries::Np::NpTrophy { std::string game_serial; static constexpr auto MaxTrophyHandles = 4u; static constexpr auto MaxTrophyContexts = 8u; using ContextKey = std::pair; // struct ContextKeyHash { size_t operator()(const ContextKey& key) const { return key.first + (u64(key.second) << 32u); } }; struct TrophyContext { u32 context_id; }; static Common::SlotVector trophy_handles{}; static Common::SlotVector trophy_contexts{}; static std::unordered_map contexts_internal{}; void ORBIS_NP_TROPHY_FLAG_ZERO(OrbisNpTrophyFlagArray* p) { for (int i = 0; i < ORBIS_NP_TROPHY_NUM_MAX; i++) { uint32_t array_index = i / 32; uint32_t bit_position = i % 32; p->flag_bits[array_index] &= ~(1U << bit_position); } } void ORBIS_NP_TROPHY_FLAG_SET(int32_t trophyId, OrbisNpTrophyFlagArray* p) { uint32_t array_index = trophyId / 32; uint32_t bit_position = trophyId % 32; p->flag_bits[array_index] |= (1U << bit_position); } void ORBIS_NP_TROPHY_FLAG_SET_ALL(OrbisNpTrophyFlagArray* p) { for (int i = 0; i < ORBIS_NP_TROPHY_NUM_MAX; i++) { uint32_t array_index = i / 32; uint32_t bit_position = i % 32; p->flag_bits[array_index] |= (1U << bit_position); } } void ORBIS_NP_TROPHY_FLAG_CLR(int32_t trophyId, OrbisNpTrophyFlagArray* p) { uint32_t array_index = trophyId / 32; uint32_t bit_position = trophyId % 32; p->flag_bits[array_index] &= ~(1U << bit_position); } bool ORBIS_NP_TROPHY_FLAG_ISSET(int32_t trophyId, OrbisNpTrophyFlagArray* p) { uint32_t array_index = trophyId / 32; uint32_t bit_position = trophyId % 32; return (p->flag_bits[array_index] & (1U << bit_position)) ? 1 : 0; } OrbisNpTrophyGrade GetTrophyGradeFromChar(char trophyType) { switch (trophyType) { default: return ORBIS_NP_TROPHY_GRADE_UNKNOWN; break; case 'B': return ORBIS_NP_TROPHY_GRADE_BRONZE; break; case 'S': return ORBIS_NP_TROPHY_GRADE_SILVER; break; case 'G': return ORBIS_NP_TROPHY_GRADE_GOLD; break; case 'P': return ORBIS_NP_TROPHY_GRADE_PLATINUM; break; } } int PS4_SYSV_ABI sceNpTrophyAbortHandle(OrbisNpTrophyHandle handle) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyCaptureScreenshot() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyConfigGetTrophyDetails() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyConfigGetTrophyFlagArray() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyConfigGetTrophyGroupArray() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyConfigGetTrophyGroupDetails() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyConfigGetTrophySetInfo() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyConfigGetTrophySetInfoInGroup() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyConfigGetTrophySetVersion() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyConfigGetTrophyTitleDetails() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyConfigHasGroupFeature() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } s32 PS4_SYSV_ABI sceNpTrophyCreateContext(OrbisNpTrophyContext* context, s32 user_id, uint32_t service_label, u64 options) { ASSERT(options == 0ull); if (!context) { return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; } if (trophy_contexts.size() >= MaxTrophyContexts) { return ORBIS_NP_TROPHY_ERROR_CONTEXT_EXCEEDS_MAX; } const auto& key = ContextKey{user_id, service_label}; if (contexts_internal.contains(key)) { return ORBIS_NP_TROPHY_ERROR_CONTEXT_ALREADY_EXISTS; } const auto ctx_id = trophy_contexts.insert(user_id, service_label); *context = ctx_id.index + 1; contexts_internal[key].context_id = *context; LOG_INFO(Lib_NpTrophy, "New context = {}, user_id = {} service label = {}", *context, user_id, service_label); return ORBIS_OK; } s32 PS4_SYSV_ABI sceNpTrophyCreateHandle(OrbisNpTrophyHandle* handle) { if (!handle) { return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; } if (trophy_handles.size() >= MaxTrophyHandles) { return ORBIS_NP_TROPHY_ERROR_HANDLE_EXCEEDS_MAX; } const auto handle_id = trophy_handles.insert(); *handle = handle_id.index + 1; LOG_INFO(Lib_NpTrophy, "New handle = {}", *handle); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyDestroyContext(OrbisNpTrophyContext context) { LOG_INFO(Lib_NpTrophy, "Destroyed Context {}", context); if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) { return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; } 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]; trophy_contexts.erase(contextId); contexts_internal.erase(contextkey); return ORBIS_OK; } s32 PS4_SYSV_ABI sceNpTrophyDestroyHandle(OrbisNpTrophyHandle handle) { if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; s32 handle_index = handle - 1; if (handle_index >= trophy_handles.size()) { LOG_ERROR(Lib_NpTrophy, "Invalid handle {}", handle); return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; } if (!trophy_handles.is_allocated({static_cast(handle_index)})) { return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; } trophy_handles.erase({static_cast(handle_index)}); LOG_INFO(Lib_NpTrophy, "Handle {} destroyed", handle); return ORBIS_OK; } u64 ReadFile(Common::FS::IOFile& file, void* buf, u64 nbytes) { const auto* memory = Core::Memory::Instance(); // Invalidate up to the actual number of bytes that could be read. const auto remaining = file.GetSize() - file.Tell(); memory->InvalidateMemory(reinterpret_cast(buf), std::min(nbytes, remaining)); return file.ReadRaw(buf, 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 / trophy_folder / "Icons" / "ICON0.PNG"; Common::FS::IOFile icon(icon_file, Common::FS::FileAccessMode::Read); if (!icon.IsOpen()) { LOG_ERROR(Lib_NpTrophy, "Failed to open trophy icon file: {}", icon_file.string()); return ORBIS_NP_TROPHY_ERROR_ICON_FILE_NOT_FOUND; } u64 icon_size = icon.GetSize(); if (buffer != nullptr) { ReadFile(icon, buffer, *size); } else { *size = icon_size; } return ORBIS_OK; } struct GameTrophyInfo { uint32_t num_groups; uint32_t num_trophies; uint32_t num_trophies_by_rarity[5]; uint32_t unlocked_trophies; uint32_t unlocked_trophies_by_rarity[5]; }; int PS4_SYSV_ABI sceNpTrophyGetGameInfo(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, OrbisNpTrophyGameDetails* details, OrbisNpTrophyGameData* data) { LOG_INFO(Lib_NpTrophy, "Getting Game Trophy"); if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; if (details == nullptr || data == nullptr) return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; 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 / trophy_folder / "Xml" / "TROP.XML"; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); if (!result) { LOG_ERROR(Lib_NpTrophy, "Failed to parse trophy xml : {}", result.description()); return ORBIS_OK; } GameTrophyInfo game_info{}; auto trophyconf = doc.child("trophyconf"); for (const pugi::xml_node& node : trophyconf.children()) { std::string_view node_name = node.name(); if (node_name == "title-name") { strncpy(details->title, node.text().as_string(), ORBIS_NP_TROPHY_GAME_TITLE_MAX_SIZE); } if (node_name == "title-detail") { strncpy(details->description, node.text().as_string(), ORBIS_NP_TROPHY_GAME_DESCR_MAX_SIZE); } if (node_name == "group") game_info.num_groups++; if (node_name == "trophy") { bool current_trophy_unlockstate = node.attribute("unlockstate").as_bool(); std::string_view current_trophy_grade = node.attribute("ttype").value(); if (current_trophy_grade.empty()) { continue; } game_info.num_trophies++; int trophy_grade = GetTrophyGradeFromChar(current_trophy_grade.at(0)); game_info.num_trophies_by_rarity[trophy_grade]++; if (current_trophy_unlockstate) { game_info.unlocked_trophies++; game_info.unlocked_trophies_by_rarity[trophy_grade]++; } } } details->num_groups = game_info.num_groups; details->num_trophies = game_info.num_trophies; details->num_platinum = game_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_PLATINUM]; details->num_gold = game_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_GOLD]; details->num_silver = game_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_SILVER]; details->num_bronze = game_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_BRONZE]; data->unlocked_trophies = game_info.unlocked_trophies; data->unlocked_platinum = game_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_PLATINUM]; data->unlocked_gold = game_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_GOLD]; data->unlocked_silver = game_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_SILVER]; data->unlocked_bronze = game_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_BRONZE]; // maybe this should be 1 instead of 100? data->progress_percentage = 100; return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyGetGroupIcon(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, OrbisNpTrophyGroupId groupId, void* buffer, u64* size) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } struct GroupTrophyInfo { uint32_t num_trophies; uint32_t num_trophies_by_rarity[5]; uint32_t unlocked_trophies; uint32_t unlocked_trophies_by_rarity[5]; }; int PS4_SYSV_ABI sceNpTrophyGetGroupInfo(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, OrbisNpTrophyGroupId groupId, OrbisNpTrophyGroupDetails* details, OrbisNpTrophyGroupData* data) { LOG_INFO(Lib_NpTrophy, "Getting Trophy Group Info for id {}", groupId); if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; if (details == nullptr || data == nullptr) return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; 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 / trophy_folder / "Xml" / "TROP.XML"; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); if (!result) { LOG_ERROR(Lib_NpTrophy, "Failed to open trophy xml : {}", result.description()); return ORBIS_OK; } GroupTrophyInfo group_info{}; auto trophyconf = doc.child("trophyconf"); for (const pugi::xml_node& node : trophyconf.children()) { std::string_view node_name = node.name(); if (node_name == "group") { int current_group_id = node.attribute("id").as_int(ORBIS_NP_TROPHY_INVALID_GROUP_ID); if (current_group_id != ORBIS_NP_TROPHY_INVALID_GROUP_ID) { if (current_group_id == groupId) { std::string_view current_group_name = node.child("name").text().as_string(); std::string_view current_group_description = node.child("detail").text().as_string(); strncpy(details->title, current_group_name.data(), ORBIS_NP_TROPHY_GROUP_TITLE_MAX_SIZE); strncpy(details->description, current_group_description.data(), ORBIS_NP_TROPHY_GAME_DESCR_MAX_SIZE); } } } details->group_id = groupId; data->group_id = groupId; if (node_name == "trophy") { bool current_trophy_unlockstate = node.attribute("unlockstate").as_bool(); std::string_view current_trophy_grade = node.attribute("ttype").value(); int current_trophy_group_id = node.attribute("gid").as_int(-1); if (current_trophy_grade.empty()) { continue; } if (current_trophy_group_id == groupId) { group_info.num_trophies++; int trophyGrade = GetTrophyGradeFromChar(current_trophy_grade.at(0)); group_info.num_trophies_by_rarity[trophyGrade]++; if (current_trophy_unlockstate) { group_info.unlocked_trophies++; group_info.unlocked_trophies_by_rarity[trophyGrade]++; } } } } details->num_trophies = group_info.num_trophies; details->num_platinum = group_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_PLATINUM]; details->num_gold = group_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_GOLD]; details->num_silver = group_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_SILVER]; details->num_bronze = group_info.num_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_BRONZE]; data->unlocked_trophies = group_info.unlocked_trophies; data->unlocked_platinum = group_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_PLATINUM]; data->unlocked_gold = group_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_GOLD]; data->unlocked_silver = group_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_SILVER]; data->unlocked_bronze = group_info.unlocked_trophies_by_rarity[ORBIS_NP_TROPHY_GRADE_BRONZE]; // maybe this should be 1 instead of 100? data->progress_percentage = 100; return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyGetTrophyIcon(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, OrbisNpTrophyId trophyId, void* buffer, u64* size) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyGetTrophyInfo(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, OrbisNpTrophyId trophyId, OrbisNpTrophyDetails* details, OrbisNpTrophyData* data) { LOG_INFO(Lib_NpTrophy, "Getting trophy info for id {}", trophyId); if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; if (trophyId >= 127) return ORBIS_NP_TROPHY_ERROR_INVALID_TROPHY_ID; if (details == nullptr || data == nullptr) return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; 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 / trophy_folder / "Xml" / "TROP.XML"; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); if (!result) { LOG_ERROR(Lib_NpTrophy, "Failed to open trophy xml : {}", result.description()); return ORBIS_OK; } auto trophyconf = doc.child("trophyconf"); for (const pugi::xml_node& node : trophyconf.children()) { std::string_view node_name = node.name(); if (node_name == "trophy") { int current_trophy_id = node.attribute("id").as_int(ORBIS_NP_TROPHY_INVALID_TROPHY_ID); if (current_trophy_id == trophyId) { bool current_trophy_unlockstate = node.attribute("unlockstate").as_bool(); std::string_view current_trophy_grade = node.attribute("ttype").value(); std::string_view current_trophy_name = node.child("name").text().as_string(); std::string_view current_trophy_description = node.child("detail").text().as_string(); uint64_t current_trophy_timestamp = node.attribute("timestamp").as_ullong(); int current_trophy_groupid = node.attribute("gid").as_int(-1); bool current_trophy_hidden = node.attribute("hidden").as_bool(); details->trophy_id = trophyId; details->trophy_grade = GetTrophyGradeFromChar(current_trophy_grade.at(0)); details->group_id = current_trophy_groupid; details->hidden = current_trophy_hidden; strncpy(details->name, current_trophy_name.data(), ORBIS_NP_TROPHY_NAME_MAX_SIZE); strncpy(details->description, current_trophy_description.data(), ORBIS_NP_TROPHY_DESCR_MAX_SIZE); data->trophy_id = trophyId; data->unlocked = current_trophy_unlockstate; data->timestamp.tick = current_trophy_timestamp; } } } return ORBIS_OK; } s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, OrbisNpTrophyFlagArray* flags, u32* count) { LOG_INFO(Lib_NpTrophy, "called"); if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; if (flags == nullptr || count == nullptr) return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; 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 / trophy_folder / "Xml" / "TROP.XML"; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); if (!result) { LOG_ERROR(Lib_NpTrophy, "Failed to open trophy XML: {}", result.description()); *count = 0; return ORBIS_OK; } int num_trophies = 0; auto trophyconf = doc.child("trophyconf"); for (const pugi::xml_node& node : trophyconf.children()) { std::string_view node_name = node.name(); int current_trophy_id = node.attribute("id").as_int(ORBIS_NP_TROPHY_INVALID_TROPHY_ID); bool current_trophy_unlockstate = node.attribute("unlockstate").as_bool(); if (node_name == "trophy") { num_trophies++; } if (current_trophy_unlockstate) { ORBIS_NP_TROPHY_FLAG_SET(current_trophy_id, flags); } } *count = num_trophies; return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyGroupArrayGetNum() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntAbortHandle() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntCheckNetSyncTitles() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntCreateHandle() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntDestroyHandle() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntGetLocalTrophySummary() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntGetProgress() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntGetRunningTitle() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntGetRunningTitles() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntGetTrpIconByUri() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntNetSyncTitle() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyIntNetSyncTitles() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyNumInfoGetTotal() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyRegisterContext(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, uint64_t options) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySetInfoGetTrophyFlagArray() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySetInfoGetTrophyNum() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyShowTrophyList(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemAbortHandle() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemBuildGroupIconUri() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemBuildNetTrophyIconUri() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemBuildTitleIconUri() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemBuildTrophyIconUri() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemCheckNetSyncTitles() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemCheckRecoveryRequired() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemCloseStorage() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemCreateContext() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemCreateHandle() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemDbgCtl() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemDebugLockTrophy() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemDebugUnlockTrophy() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemDestroyContext() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemDestroyHandle() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemDestroyTrophyConfig() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetDbgParam() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetDbgParamInt() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetGroupIcon() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetLocalTrophySummary() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetNextTitleFileEntryStatus() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetProgress() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetTitleFileStatus() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetTitleIcon() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetTitleSyncStatus() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetTrophyConfig() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetTrophyData() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetTrophyGroupData() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetTrophyIcon() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetTrophyTitleData() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetTrophyTitleIds() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetUserFileInfo() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemGetUserFileStatus() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemIsServerAvailable() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemNetSyncTitle() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemNetSyncTitles() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemOpenStorage() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemPerformRecovery() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemRemoveAll() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemRemoveTitleData() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemRemoveUserData() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemSetDbgParam() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophySystemSetDbgParamInt() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTrophyHandle handle, OrbisNpTrophyId trophyId, OrbisNpTrophyId* platinumId) { LOG_INFO(Lib_NpTrophy, "Unlocking trophy id {}", trophyId); if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT; if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE) return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; if (trophyId >= 127) return ORBIS_NP_TROPHY_ERROR_INVALID_TROPHY_ID; 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 / trophy_folder / "Xml" / "TROP.XML"; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str()); if (!result) { LOG_ERROR(Lib_NpTrophy, "Failed to parse trophy xml : {}", result.description()); return ORBIS_OK; } *platinumId = ORBIS_NP_TROPHY_INVALID_TROPHY_ID; int num_trophies = 0; int num_trophies_unlocked = 0; pugi::xml_node platinum_node; auto trophyconf = doc.child("trophyconf"); for (pugi::xml_node& node : trophyconf.children()) { int current_trophy_id = node.attribute("id").as_int(ORBIS_NP_TROPHY_INVALID_TROPHY_ID); bool current_trophy_unlockstate = node.attribute("unlockstate").as_bool(); const char* current_trophy_name = node.child("name").text().as_string(); std::string_view current_trophy_description = node.child("detail").text().as_string(); std::string_view current_trophy_type = node.attribute("ttype").value(); if (current_trophy_type == "P") { platinum_node = node; if (trophyId == current_trophy_id) { return ORBIS_NP_TROPHY_ERROR_PLATINUM_CANNOT_UNLOCK; } } if (std::string_view(node.name()) == "trophy") { if (node.attribute("pid").as_int(-1) != ORBIS_NP_TROPHY_INVALID_TROPHY_ID) { num_trophies++; if (current_trophy_unlockstate) { num_trophies_unlocked++; } } if (current_trophy_id == trophyId) { if (current_trophy_unlockstate) { LOG_INFO(Lib_NpTrophy, "Trophy already unlocked"); return ORBIS_NP_TROPHY_ERROR_TROPHY_ALREADY_UNLOCKED; } else { if (node.attribute("unlockstate").empty()) { node.append_attribute("unlockstate") = "true"; } else { node.attribute("unlockstate").set_value("true"); } auto trophyTimestamp = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); if (node.attribute("timestamp").empty()) { node.append_attribute("timestamp") = std::to_string(trophyTimestamp).c_str(); } else { node.attribute("timestamp") .set_value(std::to_string(trophyTimestamp).c_str()); } std::string trophy_icon_file = "TROP"; trophy_icon_file.append(node.attribute("id").value()); trophy_icon_file.append(".PNG"); std::filesystem::path current_icon_path = trophy_dir / trophy_folder / "Icons" / trophy_icon_file; AddTrophyToQueue(current_icon_path, current_trophy_name, current_trophy_type); } } } } if (!platinum_node.attribute("unlockstate").as_bool()) { if ((num_trophies - 1) == num_trophies_unlocked) { if (platinum_node.attribute("unlockstate").empty()) { platinum_node.append_attribute("unlockstate") = "true"; } else { platinum_node.attribute("unlockstate").set_value("true"); } auto trophyTimestamp = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); if (platinum_node.attribute("timestamp").empty()) { platinum_node.append_attribute("timestamp") = std::to_string(trophyTimestamp).c_str(); } else { platinum_node.attribute("timestamp") .set_value(std::to_string(trophyTimestamp).c_str()); } int platinum_trophy_id = platinum_node.attribute("id").as_int(ORBIS_NP_TROPHY_INVALID_TROPHY_ID); const char* platinum_trophy_name = platinum_node.child("name").text().as_string(); std::string platinum_icon_file = "TROP"; platinum_icon_file.append(platinum_node.attribute("id").value()); platinum_icon_file.append(".PNG"); std::filesystem::path platinum_icon_path = 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 / trophy_folder / "Xml" / "TROP.XML").native().c_str()); return ORBIS_OK; } int PS4_SYSV_ABI Func_149656DA81D41C59() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_9F80071876FFA5F6() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_F8EF6F5350A91990() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_FA7A2DD770447552() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; } void RegisterLib(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("aTnHs7W-9Uk", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyAbortHandle); LIB_FUNCTION("cqGkYAN-gRw", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyCaptureScreenshot); LIB_FUNCTION("lhE4XS9OJXs", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyConfigGetTrophyDetails); LIB_FUNCTION("qJ3IvrOoXg0", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyConfigGetTrophyFlagArray); LIB_FUNCTION("zDjF2G+6tI0", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyConfigGetTrophyGroupArray); LIB_FUNCTION("7Kh86vJqtxw", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyConfigGetTrophyGroupDetails); LIB_FUNCTION("ndLeNWExeZE", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyConfigGetTrophySetInfo); LIB_FUNCTION("6EOfS5SDgoo", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyConfigGetTrophySetInfoInGroup); LIB_FUNCTION("MW5ygoZqEBs", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyConfigGetTrophySetVersion); LIB_FUNCTION("3tWKpNKn5+I", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyConfigGetTrophyTitleDetails); LIB_FUNCTION("iqYfxC12sak", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyConfigHasGroupFeature); LIB_FUNCTION("XbkjbobZlCY", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyCreateContext); LIB_FUNCTION("q7U6tEAQf7c", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyCreateHandle); LIB_FUNCTION("E1Wrwd07Lr8", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyDestroyContext); LIB_FUNCTION("GNcF4oidY0Y", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyDestroyHandle); LIB_FUNCTION("HLwz1fRIycA", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyGetGameIcon); LIB_FUNCTION("YYP3f2W09og", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyGetGameInfo); LIB_FUNCTION("w4uMPmErD4I", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyGetGroupIcon); LIB_FUNCTION("wTUwGfspKic", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyGetGroupInfo); LIB_FUNCTION("eBL+l6HG9xk", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyGetTrophyIcon); LIB_FUNCTION("qqUVGDgQBm0", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyGetTrophyInfo); LIB_FUNCTION("LHuSmO3SLd8", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyGetTrophyUnlockState); LIB_FUNCTION("Ht6MNTl-je4", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyGroupArrayGetNum); LIB_FUNCTION("u9plkqa2e0k", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntAbortHandle); LIB_FUNCTION("pE5yhroy9m0", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntCheckNetSyncTitles); LIB_FUNCTION("edPIOFpEAvU", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntCreateHandle); LIB_FUNCTION("DSh3EXpqAQ4", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntDestroyHandle); LIB_FUNCTION("sng98qULzPA", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntGetLocalTrophySummary); LIB_FUNCTION("t3CQzag7-zs", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntGetProgress); LIB_FUNCTION("jF-mCgGuvbQ", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntGetRunningTitle); LIB_FUNCTION("PeAyBjC5kp8", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntGetRunningTitles); LIB_FUNCTION("PEo09Dkqv0o", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntGetTrpIconByUri); LIB_FUNCTION("kF9zjnlAzIA", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntNetSyncTitle); LIB_FUNCTION("UXiyfabxFNQ", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyIntNetSyncTitles); LIB_FUNCTION("hvdThnVvwdY", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyNumInfoGetTotal); LIB_FUNCTION("TJCAxto9SEU", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyRegisterContext); LIB_FUNCTION("ITUmvpBPaG0", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySetInfoGetTrophyFlagArray); LIB_FUNCTION("BSoSgiMVHnY", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySetInfoGetTrophyNum); LIB_FUNCTION("d9jpdPz5f-8", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyShowTrophyList); LIB_FUNCTION("JzJdh-JLtu0", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemAbortHandle); LIB_FUNCTION("z8RCP536GOM", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemBuildGroupIconUri); LIB_FUNCTION("Rd2FBOQE094", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemBuildNetTrophyIconUri); LIB_FUNCTION("Q182x0rT75I", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemBuildTitleIconUri); LIB_FUNCTION("lGnm5Kg-zpA", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemBuildTrophyIconUri); LIB_FUNCTION("20wAMbXP-u0", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemCheckNetSyncTitles); LIB_FUNCTION("sKGFFY59ksY", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemCheckRecoveryRequired); LIB_FUNCTION("JMSapEtDH9Q", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemCloseStorage); LIB_FUNCTION("dk27olS4CEE", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemCreateContext); LIB_FUNCTION("cBzXEdzVzvs", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemCreateHandle); LIB_FUNCTION("8aLlLHKP+No", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemDbgCtl); LIB_FUNCTION("NobVwD8qcQY", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemDebugLockTrophy); LIB_FUNCTION("yXJlgXljItk", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemDebugUnlockTrophy); LIB_FUNCTION("U0TOSinfuvw", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemDestroyContext); LIB_FUNCTION("-LC9hudmD+Y", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemDestroyHandle); LIB_FUNCTION("q6eAMucXIEM", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemDestroyTrophyConfig); LIB_FUNCTION("WdCUUJLQodM", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetDbgParam); LIB_FUNCTION("4QYFwC7tn4U", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetDbgParamInt); LIB_FUNCTION("OcllHFFcQkI", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetGroupIcon); LIB_FUNCTION("tQ3tXfVZreU", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetLocalTrophySummary); LIB_FUNCTION("g0dxBNTspC0", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetNextTitleFileEntryStatus); LIB_FUNCTION("sJSDnJRJHhI", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetProgress); LIB_FUNCTION("X47s4AamPGg", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetTitleFileStatus); LIB_FUNCTION("7WPj4KCF3D8", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetTitleIcon); LIB_FUNCTION("pzL+aAk0tQA", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetTitleSyncStatus); LIB_FUNCTION("Ro4sI9xgYl4", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetTrophyConfig); LIB_FUNCTION("7+OR1TU5QOA", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetTrophyData); LIB_FUNCTION("aXhvf2OmbiE", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetTrophyGroupData); LIB_FUNCTION("Rkt0bVyaa4Y", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetTrophyIcon); LIB_FUNCTION("nXr5Rho8Bqk", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetTrophyTitleData); LIB_FUNCTION("eV1rtLr+eys", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetTrophyTitleIds); LIB_FUNCTION("SsGLKTfWfm0", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetUserFileInfo); LIB_FUNCTION("XqLLsvl48kA", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemGetUserFileStatus); LIB_FUNCTION("-qjm2fFE64M", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemIsServerAvailable); LIB_FUNCTION("50BvYYzPTsY", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemNetSyncTitle); LIB_FUNCTION("yDJ-r-8f4S4", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemNetSyncTitles); LIB_FUNCTION("mWtsnHY8JZg", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemOpenStorage); LIB_FUNCTION("tAxnXpzDgFw", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemPerformRecovery); LIB_FUNCTION("tV18n8OcheI", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemRemoveAll); LIB_FUNCTION("kV4DP0OTMNo", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemRemoveTitleData); LIB_FUNCTION("lZSZoN8BstI", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemRemoveUserData); LIB_FUNCTION("nytN-3-pdvI", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemSetDbgParam); LIB_FUNCTION("JsRnDKRzvRw", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophySystemSetDbgParamInt); LIB_FUNCTION("28xmRUFao68", "libSceNpTrophy", 1, "libSceNpTrophy", sceNpTrophyUnlockTrophy); LIB_FUNCTION("FJZW2oHUHFk", "libSceNpTrophy", 1, "libSceNpTrophy", Func_149656DA81D41C59); LIB_FUNCTION("n4AHGHb-pfY", "libSceNpTrophy", 1, "libSceNpTrophy", Func_9F80071876FFA5F6); LIB_FUNCTION("+O9vU1CpGZA", "libSceNpTrophy", 1, "libSceNpTrophy", Func_F8EF6F5350A91990); LIB_FUNCTION("+not13BEdVI", "libSceNpTrophy", 1, "libSceNpTrophy", Func_FA7A2DD770447552); }; } // namespace Libraries::Np::NpTrophy