TROPUSR: Loader Improvements

* Replace invalid TROPUSR.DAT with empty new ones. (+report an error)
* Fix return code of Load whenever TROPUSR.DAT hadn't existed before.
* Add header magic test.
* sceNpTrophyRegisterContext will abort if TROPUSR.DAT generation failed.
This commit is contained in:
Eladash 2021-03-13 15:36:59 +02:00 committed by Ivan
parent 1f93fc902b
commit 48870f3e8b
4 changed files with 49 additions and 17 deletions

View file

@ -578,11 +578,11 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE; return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE;
} }
TROPUSRLoader* tropusr = new TROPUSRLoader(); const auto& tropusr = ctxt->tropusr = std::make_unique<TROPUSRLoader>();
const std::string trophyUsrPath = trophyPath + "/TROPUSR.DAT"; const std::string trophyUsrPath = trophyPath + "/TROPUSR.DAT";
const std::string trophyConfPath = trophyPath + "/TROPCONF.SFM"; const std::string trophyConfPath = trophyPath + "/TROPCONF.SFM";
tropusr->Load(trophyUsrPath, trophyConfPath);
ctxt->tropusr.reset(tropusr); ensure(tropusr->Load(trophyUsrPath, trophyConfPath).success);
// This emulates vsh sending the events and ensures that not 2 events are processed at once // This emulates vsh sending the events and ensures that not 2 events are processed at once
const std::pair<u32, s32> statuses[] = const std::pair<u32, s32> statuses[] =

View file

@ -5,25 +5,52 @@
LOG_CHANNEL(trp_log, "Trophy"); LOG_CHANNEL(trp_log, "Trophy");
bool TROPUSRLoader::Load(const std::string& filepath, const std::string& configpath) enum : u32
{
TROPUSR_MAGIC = 0x818F54AD
};
TROPUSRLoader::load_result TROPUSRLoader::Load(const std::string& filepath, const std::string& configpath)
{ {
const std::string& path = vfs::get(filepath); const std::string& path = vfs::get(filepath);
if (!m_file.open(path, fs::read)) load_result res{};
// Generate TROPUSR.DAT
auto generate = [&]
{ {
if (!Generate(filepath, configpath)) // Reset filesystem error
fs::g_tls_error = fs::error::ok;
// Generate TROPUSR.DAT if not existing
res.success = Generate(filepath, configpath);
if (!res.success)
{ {
return false; trp_log.error("TROPUSRLoader::Load(): Failed to generate TROPUSR.DAT (path='%s', cfg='%s', %s)", path, configpath, fs::g_tls_error);
} }
m_file.close();
return res;
};
if (!m_file.open(path))
{
return generate();
} }
if (!LoadHeader() || !LoadTableHeaders() || !LoadTables()) if (!LoadHeader() || !LoadTableHeaders() || !LoadTables())
{ {
return false; // Ignore existing TROPUSR.DAT because it is invalid
m_file.close();
res.discarded_existing = true;
trp_log.error("TROPUSRLoader::Load(): Failed to load existing TROPUSR.DAT, trying to generate new file with empty trophies history! (path='%s')", path);
return generate();
} }
m_file.release(); m_file.close();
return true; res.success = true;
return res;
} }
bool TROPUSRLoader::LoadHeader() bool TROPUSRLoader::LoadHeader()
@ -35,7 +62,7 @@ bool TROPUSRLoader::LoadHeader()
m_file.seek(0); m_file.seek(0);
if (!m_file.read(m_header)) if (!m_file.read(m_header) || m_header.magic != TROPUSR_MAGIC)
{ {
return false; return false;
} }
@ -180,14 +207,13 @@ bool TROPUSRLoader::Generate(const std::string& filepath, const std::string& con
m_tableHeaders.push_back(table4header); m_tableHeaders.push_back(table4header);
m_tableHeaders.push_back(table6header); m_tableHeaders.push_back(table6header);
m_header.magic = 0x818F54AD; std::memset(&m_header, 0, sizeof(m_header));
m_header.magic = TROPUSR_MAGIC;
m_header.unk1 = 0x00010000; m_header.unk1 = 0x00010000;
m_header.tables_count = ::size32(m_tableHeaders); m_header.tables_count = ::size32(m_tableHeaders);
m_header.unk2 = 0; m_header.unk2 = 0;
Save(filepath); return Save(filepath);
return true;
} }
u32 TROPUSRLoader::GetTrophiesCount() u32 TROPUSRLoader::GetTrophiesCount()

View file

@ -80,7 +80,13 @@ class TROPUSRLoader
public: public:
virtual ~TROPUSRLoader() = default; virtual ~TROPUSRLoader() = default;
virtual bool Load(const std::string& filepath, const std::string& configpath); struct load_result
{
bool discarded_existing;
bool success;
};
virtual load_result Load(const std::string& filepath, const std::string& configpath);
virtual bool Save(const std::string& filepath); virtual bool Save(const std::string& filepath);
virtual u32 GetTrophiesCount(); virtual u32 GetTrophiesCount();

View file

@ -358,7 +358,7 @@ bool trophy_manager_dialog::LoadTrophyFolderToDB(const std::string& trop_name)
game_trophy_data->trop_usr.reset(new TROPUSRLoader()); game_trophy_data->trop_usr.reset(new TROPUSRLoader());
const std::string trophyUsrPath = trophyPath + "/TROPUSR.DAT"; const std::string trophyUsrPath = trophyPath + "/TROPUSR.DAT";
const std::string trophyConfPath = trophyPath + "/TROPCONF.SFM"; const std::string trophyConfPath = trophyPath + "/TROPCONF.SFM";
const bool success = game_trophy_data->trop_usr->Load(trophyUsrPath, trophyConfPath); const bool success = game_trophy_data->trop_usr->Load(trophyUsrPath, trophyConfPath).success;
fs::file config(vfs::get(trophyConfPath)); fs::file config(vfs::get(trophyConfPath));