[XAM/User] GetTitleId -> GetTitleData, check flags/titletype before adding to profile

This commit is contained in:
emoose 2019-12-26 01:35:38 +00:00 committed by illusion
parent e6172cdc28
commit b48c03ab32
4 changed files with 53 additions and 25 deletions

View File

@ -258,31 +258,46 @@ xdbf::GpdFile* UserProfile::SetTitleSpaData(const xdbf::SpaFile& spa_data) {
curr_title_id_ = 0; curr_title_id_ = 0;
curr_gpd_ = nullptr; curr_gpd_ = nullptr;
uint32_t spa_title = spa_data.GetTitleId(); xdbf::X_XDBF_XTHD_DATA title_data;
spa_data.GetTitleData(&title_data);
curr_title_id_ = spa_title; curr_title_id_ = title_data.title_id;
std::vector<xdbf::Achievement> spa_achievements; std::vector<xdbf::Achievement> spa_achievements;
// TODO: let user choose locale? // TODO: let user choose locale?
spa_data.GetAchievements(spa_data.GetDefaultLocale(), &spa_achievements); spa_data.GetAchievements(spa_data.GetDefaultLocale(), &spa_achievements);
xdbf::TitlePlayed title_info; bool title_included =
title_data.title_type == xdbf::X_XDBF_XTHD_DATA::TitleType::kFull ||
title_data.title_type == xdbf::X_XDBF_XTHD_DATA::TitleType::kDownload;
auto gpd = title_gpds_.find(spa_title); if (title_data.flags &
(uint32_t)xdbf::X_XDBF_XTHD_DATA::Flags::kAlwaysIncludeInProfile) {
title_included = true;
}
if (title_data.flags &
(uint32_t)xdbf::X_XDBF_XTHD_DATA::Flags::kNeverIncludeInProfile) {
title_included = false;
}
// TODO: set title_included if 'owned' (license_mask check?)
xdbf::TitlePlayed title_info;
auto gpd = title_gpds_.find(title_data.title_id);
if (gpd != title_gpds_.end()) { if (gpd != title_gpds_.end()) {
auto& title_gpd = (*gpd).second; auto& title_gpd = (*gpd).second;
XELOGI("Loaded existing GPD for title %X", spa_title); XELOGI("Loaded existing GPD for title %X", title_data.title_id);
bool always_update_title = false; bool always_update_title = false;
if (!dash_gpd_.GetTitle(spa_title, &title_info)) { if (!dash_gpd_.GetTitle(title_data.title_id, &title_info)) {
assert_always(); assert_always();
XELOGE( XELOGE(
"GPD exists but is missing XbdfTitlePlayed entry? (this shouldn't be " "GPD exists but is missing XbdfTitlePlayed entry? (this shouldn't be "
"happening!)"); "happening!)");
// Try to work around it... // Try to work around it...
title_info.title_name = xe::to_wstring(spa_data.GetTitleName()); title_info.title_name = xe::to_wstring(spa_data.GetTitleName());
title_info.title_id = spa_title; title_info.title_id = title_data.title_id;
title_info.achievements_possible = 0; title_info.achievements_possible = 0;
title_info.achievements_earned = 0; title_info.achievements_earned = 0;
title_info.gamerscore_total = 0; title_info.gamerscore_total = 0;
@ -317,25 +332,27 @@ xdbf::GpdFile* UserProfile::SetTitleSpaData(const xdbf::SpaFile& spa_data) {
} }
// Update dash with new title_info // Update dash with new title_info
dash_gpd_.UpdateTitle(title_info); if (title_included) {
dash_gpd_.UpdateTitle(title_info);
}
// Only write game GPD if achievements were updated // Only write game GPD if achievements were updated
if (ach_updated) { if (ach_updated) {
UpdateGpd(spa_title, title_gpd); UpdateGpd(title_data.title_id, title_gpd);
} }
UpdateGpd(kDashboardID, dash_gpd_); UpdateGpd(kDashboardID, dash_gpd_);
} else { } else {
// GPD not found... have to create it! // GPD not found... have to create it!
XELOGI("Creating new GPD for title %X", spa_title); XELOGI("Creating new GPD for title %X", title_data.title_id);
title_info.title_name = xe::to_wstring(spa_data.GetTitleName()); title_info.title_name = xe::to_wstring(spa_data.GetTitleName());
title_info.title_id = spa_title; title_info.title_id = title_data.title_id;
title_info.last_played = Clock::QueryHostSystemTime(); title_info.last_played = Clock::QueryHostSystemTime();
// Copy cheevos from SPA -> GPD // Copy cheevos from SPA -> GPD
auto& title_gpd = dash_gpd_; auto& title_gpd = dash_gpd_;
if (spa_title != kDashboardID) { if (title_data.title_id != kDashboardID) {
title_gpd = xdbf::GpdFile(spa_title); title_gpd = xdbf::GpdFile(title_data.title_id);
for (auto ach : spa_achievements) { for (auto ach : spa_achievements) {
title_gpd.UpdateAchievement(ach); title_gpd.UpdateAchievement(ach);
@ -373,20 +390,22 @@ xdbf::GpdFile* UserProfile::SetTitleSpaData(const xdbf::SpaFile& spa_data) {
title_gpd.UpdateEntry(title_name_ent); title_gpd.UpdateEntry(title_name_ent);
} }
title_gpds_[spa_title] = title_gpd; title_gpds_[title_data.title_id] = title_gpd;
// Update dash GPD with title and write updated GPDs // Update dash GPD with title and write updated GPDs
if (spa_title != kDashboardID) { if (title_data.title_id != kDashboardID) {
title_gpds_[spa_title] = title_gpd; title_gpds_[title_data.title_id] = title_gpd;
dash_gpd_.UpdateTitle(title_info); if (title_included) {
UpdateGpd(spa_title, title_gpds_[spa_title]); dash_gpd_.UpdateTitle(title_info);
}
UpdateGpd(title_data.title_id, title_gpds_[title_data.title_id]);
} }
UpdateGpd(kDashboardID, dash_gpd_); UpdateGpd(kDashboardID, dash_gpd_);
} }
if (spa_title != kDashboardID) { if (title_data.title_id != kDashboardID) {
curr_gpd_ = &title_gpds_[spa_title]; curr_gpd_ = &title_gpds_[title_data.title_id];
} else { } else {
curr_gpd_ = &dash_gpd_; curr_gpd_ = &dash_gpd_;
} }

View File

@ -258,17 +258,20 @@ std::string SpaFile::GetTitleName() const {
static_cast<uint16_t>(SpaID::Title)); static_cast<uint16_t>(SpaID::Title));
} }
uint32_t SpaFile::GetTitleId() const { bool SpaFile::GetTitleData(X_XDBF_XTHD_DATA* title_data) const {
auto block = GetEntry(static_cast<uint16_t>(SpaSection::kMetadata), auto block = GetEntry(static_cast<uint16_t>(SpaSection::kMetadata),
static_cast<uint64_t>(SpaID::Xthd)); static_cast<uint64_t>(SpaID::Xthd));
if (!block) { if (!block) {
return -1; return false;
} }
auto xthd = reinterpret_cast<const X_XDBF_XTHD_DATA*>(block->data.data()); auto xthd = reinterpret_cast<const X_XDBF_XTHD_DATA*>(block->data.data());
assert_true(xthd->header.magic == static_cast<uint32_t>(SpaID::Xthd)); assert_true(xthd->header.magic == static_cast<uint32_t>(SpaID::Xthd));
return xthd->title_id; if (title_data) {
*title_data = *xthd;
}
return true;
} }
bool GpdFile::GetAchievement(uint16_t id, Achievement* dest) { bool GpdFile::GetAchievement(uint16_t id, Achievement* dest) {

View File

@ -359,7 +359,7 @@ class SpaFile : public XdbfFile {
Entry* GetIcon() const; Entry* GetIcon() const;
Locale GetDefaultLocale() const; Locale GetDefaultLocale() const;
std::string GetTitleName() const; std::string GetTitleName() const;
uint32_t GetTitleId() const; bool GetTitleData(X_XDBF_XTHD_DATA* title_data) const;
}; };
class GpdFile : public XdbfFile { class GpdFile : public XdbfFile {

View File

@ -62,13 +62,19 @@ struct X_XDBF_XSTC_DATA {
static_assert_size(X_XDBF_XSTC_DATA, 16); static_assert_size(X_XDBF_XSTC_DATA, 16);
struct X_XDBF_XTHD_DATA { struct X_XDBF_XTHD_DATA {
enum class TitleType : uint32_t {
kSystem = 0,
kFull = 1,
kDemo = 2,
kDownload = 3,
};
enum class Flags { enum class Flags {
kAlwaysIncludeInProfile = 1, kAlwaysIncludeInProfile = 1,
kNeverIncludeInProfile = 2, kNeverIncludeInProfile = 2,
}; };
X_XDBF_SECTION_HEADER header; X_XDBF_SECTION_HEADER header;
xe::be<uint32_t> title_id; xe::be<uint32_t> title_id;
xe::be<uint32_t> title_type; xe::be<TitleType> title_type;
xe::be<uint16_t> title_version_major; xe::be<uint16_t> title_version_major;
xe::be<uint16_t> title_version_minor; xe::be<uint16_t> title_version_minor;
xe::be<uint16_t> title_version_build; xe::be<uint16_t> title_version_build;