platinum trophy support + extract trophy data on startup

This commit is contained in:
CrazyBloo 2024-09-09 14:44:23 -04:00
parent 315afc52fa
commit dbd0404ed5
4 changed files with 98 additions and 49 deletions

View File

@ -9,8 +9,8 @@
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
#include "externals/pugixml/src/pugixml.hpp" #include "externals/pugixml/src/pugixml.hpp"
#include "trophy_ui.h"
#include "np_trophy.h" #include "np_trophy.h"
#include "trophy_ui.h"
namespace Libraries::NpTrophy { namespace Libraries::NpTrophy {
@ -213,6 +213,9 @@ s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(OrbisNpTrophyContext context,
return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT;
// flags->flag_bits = 0u; // flags->flag_bits = 0u;
// temporary workaround till i implement this properly
uint32_t* flagTemp = reinterpret_cast<uint32_t*>(flags);
*flagTemp = 0u;
*count = 0; *count = 0;
return ORBIS_OK; return ORBIS_OK;
} }
@ -549,49 +552,106 @@ int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTr
pugi::xml_parse_result result = pugi::xml_parse_result result =
doc.load_file((trophyDir.string() + "/trophy00/Xml/TROP.XML").c_str()); doc.load_file((trophyDir.string() + "/trophy00/Xml/TROP.XML").c_str());
// only do this if platinum is not unlocked
*platinumId = ORBIS_NP_TROPHY_INVALID_TROPHY_ID; *platinumId = ORBIS_NP_TROPHY_INVALID_TROPHY_ID;
// check if all trophies are unlocked and if they are unlock plat and set its ID
int numTrophies = 0;
int numTrophiesUnlocked = 0;
pugi::xml_node_iterator platinumIt;
int platinumTrophyGroup = -1;
if (result) { if (result) {
bool foundTrophy = false;
auto trophyconf = doc.child("trophyconf"); auto trophyconf = doc.child("trophyconf");
for (pugi::xml_node_iterator it = trophyconf.children().begin(); for (pugi::xml_node_iterator it = trophyconf.children().begin();
it != trophyconf.children().end() && !foundTrophy; ++it) { it != trophyconf.children().end(); ++it) {
std::string currentTrophyId = std::string currentTrophyId = it->attribute("id").value();
reinterpret_cast<const char*>(it->attribute("id").value()); std::string currentTrophyName = it->child("name").text().as_string();
std::string currentTrophyName = std::string currentTrophyDescription = it->child("detail").text().as_string();
reinterpret_cast<const char*>(it->child("name").text().as_string()); std::string currentTrophyType = it->attribute("ttype").value();
std::string currentTrophyDescription = std::string currentTrophyUnlockState = it->attribute("unlockstate").value();
reinterpret_cast<const char*>(it->child("detail").text().as_string());
std::string currentTrophyType =
reinterpret_cast<const char*>(it->attribute("ttype").value());
std::string currentTrophyUnlockState =
reinterpret_cast<const char*>(it->attribute("unlockstate").value());
if (std::string(it->name()) == "trophy" && std::stoi(currentTrophyId) == trophyId) { if (currentTrophyType == "P") {
platinumIt = it;
LOG_INFO(Lib_NpTrophy, "Found trophy to unlock {} : {}", if (std::string(platinumIt->attribute("gid").value()).empty()) {
it->child("name").text().as_string(), platinumTrophyGroup = -1;
it->child("detail").text().as_string());
if (currentTrophyUnlockState == "unlocked") {
LOG_INFO(Lib_NpTrophy, "Trophy already unlocked");
return ORBIS_NP_TROPHY_ERROR_TROPHY_ALREADY_UNLOCKED;
} else { } else {
if (std::string(it->attribute("unlockstate").value()).empty()) { platinumTrophyGroup =
it->append_attribute("unlockstate") = "unlocked"; std::stoi(std::string(platinumIt->attribute("gid").value()));
} else { }
it->attribute("unlockstate").set_value("unlocked");
} if (trophyId == std::stoi(currentTrophyId)) {
return ORBIS_NP_TROPHY_ERROR_PLATINUM_CANNOT_UNLOCK;
g_trophy_ui.AddTrophyToQueue(trophyId, currentTrophyName, TrophyType::BRONZE); }
}
//doc.save_file((trophyDir.string() + "/trophy00/Xml/TROP.XML").c_str());
if (std::string(it->name()) == "trophy") {
if (platinumTrophyGroup == -1) {
if (std::string(it->attribute("gid").value()).empty()) {
numTrophies++;
if (currentTrophyUnlockState == "unlocked") {
numTrophiesUnlocked++;
}
}
} else {
if (!std::string(it->attribute("gid").value()).empty()) {
if (std::stoi(std::string(it->attribute("gid").value())) ==
platinumTrophyGroup) {
numTrophies++;
if (currentTrophyUnlockState == "unlocked") {
numTrophiesUnlocked++;
}
}
}
}
if (std::stoi(currentTrophyId) == trophyId) {
LOG_INFO(Lib_NpTrophy, "Found trophy to unlock {} : {}",
it->child("name").text().as_string(),
it->child("detail").text().as_string());
if (currentTrophyUnlockState == "unlocked") {
LOG_INFO(Lib_NpTrophy, "Trophy already unlocked");
return ORBIS_NP_TROPHY_ERROR_TROPHY_ALREADY_UNLOCKED;
} else {
if (std::string(it->attribute("unlockstate").value()).empty()) {
it->append_attribute("unlockstate") = "unlocked";
} else {
it->attribute("unlockstate").set_value("unlocked");
}
g_trophy_ui.AddTrophyToQueue(trophyId, currentTrophyName);
}
} }
foundTrophy = true;
} }
} }
if (std::string(platinumIt->attribute("unlockstate").value()).empty()) {
if ((numTrophies - 2) == numTrophiesUnlocked) {
platinumIt->append_attribute("unlockstate") = "unlocked";
std::string platinumTrophyId = platinumIt->attribute("id").value();
std::string platinumTrophyName = platinumIt->child("name").text().as_string();
*platinumId = std::stoi(platinumTrophyId);
g_trophy_ui.AddTrophyToQueue(*platinumId, platinumTrophyName);
}
} else if (std::string(platinumIt->attribute("unlockstate").value()) == "locked") {
if ((numTrophies - 2) == numTrophiesUnlocked) {
platinumIt->attribute("unlockstate").set_value("unlocked");
std::string platinumTrophyId = platinumIt->attribute("id").value();
std::string platinumTrophyName = platinumIt->child("name").text().as_string();
*platinumId = std::stoi(platinumTrophyId);
g_trophy_ui.AddTrophyToQueue(*platinumId, platinumTrophyName);
}
}
doc.save_file((trophyDir.string() + "/trophy00/Xml/TROP.XML").c_str());
} else } else
LOG_INFO(Lib_NpTrophy, "couldnt parse xml : {}", result.description()); LOG_INFO(Lib_NpTrophy, "couldnt parse xml : {}", result.description());

View File

@ -19,12 +19,10 @@ TrophyUI::~TrophyUI() {
Finish(); Finish();
} }
void Libraries::NpTrophy::TrophyUI::AddTrophyToQueue(int trophyId, std::string trophyName, void Libraries::NpTrophy::TrophyUI::AddTrophyToQueue(int trophyId, std::string trophyName) {
TrophyType trophyType) {
TrophyInfo newInfo; TrophyInfo newInfo;
newInfo.trophyId = trophyId; newInfo.trophyId = trophyId;
newInfo.trophyName = trophyName; newInfo.trophyName = trophyName;
newInfo.trophyType = trophyType;
trophyQueue.push_back(newInfo); trophyQueue.push_back(newInfo);
} }
@ -66,8 +64,8 @@ void TrophyUI::Draw() {
TrophyInfo currentTrophyInfo = trophyQueue[0]; TrophyInfo currentTrophyInfo = trophyQueue[0];
if (Begin("Trophy Window", nullptr, if (Begin("Trophy Window", nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
| ImGuiWindowFlags_NoInputs)) { ImGuiWindowFlags_NoInputs)) {
Text("Trophy earned!"); Text("Trophy earned!");
TextWrapped(currentTrophyInfo.trophyName.c_str()); TextWrapped(currentTrophyInfo.trophyName.c_str());

View File

@ -14,18 +14,9 @@
namespace Libraries::NpTrophy { namespace Libraries::NpTrophy {
enum TrophyType {
UNKNOWN,
PLATINUM,
GOLD,
SILVER,
BRONZE,
};
struct TrophyInfo { struct TrophyInfo {
int trophyId = -1; int trophyId = -1;
std::string trophyName; std::string trophyName;
TrophyType trophyType;
}; };
class TrophyUI final : public ImGui::Layer { class TrophyUI final : public ImGui::Layer {
@ -36,7 +27,7 @@ public:
TrophyUI(); TrophyUI();
~TrophyUI() override; ~TrophyUI() override;
void AddTrophyToQueue(int trophyId, std::string trophyName, TrophyType trophyType); void AddTrophyToQueue(int trophyId, std::string trophyName);
void Finish(); void Finish();

View File

@ -102,8 +102,8 @@ void Emulator::Run(const std::filesystem::path& file) {
param_sfo->open(sce_sys_folder.string() + "/param.sfo", {}); param_sfo->open(sce_sys_folder.string() + "/param.sfo", {});
id = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9); id = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9);
Libraries::NpTrophy::game_serial = id; Libraries::NpTrophy::game_serial = id;
const auto trophyDir = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / const auto trophyDir =
id / "TrophyFiles"; Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / id / "TrophyFiles";
if (!std::filesystem::exists(trophyDir)) { if (!std::filesystem::exists(trophyDir)) {
TRP trp; TRP trp;
if (!trp.Extract(file.parent_path())) { if (!trp.Extract(file.parent_path())) {