diff --git a/src/xenia/kernel/xam/ui/title_info_ui.cc b/src/xenia/kernel/xam/ui/title_info_ui.cc index 567ca709e..84f19ef7a 100644 --- a/src/xenia/kernel/xam/ui/title_info_ui.cc +++ b/src/xenia/kernel/xam/ui/title_info_ui.cc @@ -112,18 +112,6 @@ void TitleListUI::DrawTitleEntry(ImGuiIO& io, TitleInfo& entry) { if (ImGui::BeginPopupContextItem( fmt::format("Title Menu {:08X}", entry.id).c_str())) { selected_title_ = entry.id; - if (ImGui::MenuItem("Refresh title stats", nullptr, nullptr, true)) { - kernel_state()->xam_state()->user_tracker()->RefreshTitleSummary( - profile_->xuid(), entry.id); - - const auto title_info = - kernel_state()->xam_state()->user_tracker()->GetUserTitleInfo( - profile_->xuid(), entry.id); - - if (title_info) { - entry = title_info.value(); - } - } const auto savefile_path = profile_manager_->GetProfileContentPath( profile_->xuid(), entry.id, XContentType::kSavedGame); @@ -150,6 +138,29 @@ void TitleListUI::DrawTitleEntry(ImGuiIO& io, TitleInfo& entry) { path_open.detach(); } + ImGui::Separator(); + + const auto title_info = + kernel_state()->xam_state()->user_tracker()->GetUserTitleInfo( + profile_->xuid(), entry.id); + + if (ImGui::MenuItem("Refresh title stats", nullptr, nullptr, true)) { + kernel_state()->xam_state()->user_tracker()->RefreshTitleSummary( + profile_->xuid(), entry.id); + + if (title_info) { + entry = title_info.value(); + } + } + + if (title_info) { + if (ImGui::MenuItem("Delete title", nullptr, nullptr, + !title_info->unlocked_achievements_count)) { + kernel_state()->xam_state()->user_tracker()->RemoveTitleFromPlayedList( + profile_->xuid(), entry.id); + } + } + ImGui::EndPopup(); } } diff --git a/src/xenia/kernel/xam/user_tracker.cc b/src/xenia/kernel/xam/user_tracker.cc index 8065ee32f..182f7322e 100644 --- a/src/xenia/kernel/xam/user_tracker.cc +++ b/src/xenia/kernel/xam/user_tracker.cc @@ -185,6 +185,19 @@ void UserTracker::AddTitleToPlayedList(uint64_t xuid) { UpdateProfileGpd(); } +void UserTracker::RemoveTitleFromPlayedList(uint64_t xuid, uint32_t title_id) { + auto user = kernel_state()->xam_state()->GetUserProfile(xuid); + if (!user) { + return; + } + + if (user->dashboard_gpd_.RemoveTitle(title_id)) { + UpdateSettingValue(xuid, kDashboardID, + UserSettingId::XPROFILE_GAMERCARD_TITLES_PLAYED, -1); + FlushUserData(xuid); + } +} + // Privates bool UserTracker::IsUserTracked(uint64_t xuid) const { return tracked_xuids_.find(xuid) != tracked_xuids_.cend(); diff --git a/src/xenia/kernel/xam/user_tracker.h b/src/xenia/kernel/xam/user_tracker.h index 8c089adc2..58f022b63 100644 --- a/src/xenia/kernel/xam/user_tracker.h +++ b/src/xenia/kernel/xam/user_tracker.h @@ -84,6 +84,7 @@ class UserTracker { // Titles void AddTitleToPlayedList(); + void RemoveTitleFromPlayedList(uint64_t xuid, uint32_t title_id); std::vector GetPlayedTitles(uint64_t xuid) const; std::optional GetUserTitleInfo(uint64_t xuid, uint32_t title_id) const; diff --git a/src/xenia/kernel/xam/xdbf/gpd_info.h b/src/xenia/kernel/xam/xdbf/gpd_info.h index 5770ea230..44113654a 100644 --- a/src/xenia/kernel/xam/xdbf/gpd_info.h +++ b/src/xenia/kernel/xam/xdbf/gpd_info.h @@ -135,6 +135,7 @@ class GpdInfo : public XdbfFile { const GpdSection section); void UpsertEntry(Entry* entry); + void DeleteEntry(const Entry* entry); uint32_t FindFreeLocation(const uint32_t entry_size); @@ -144,7 +145,6 @@ class GpdInfo : public XdbfFile { uint32_t title_id_ = 0; void InsertEntry(Entry* entry); - void DeleteEntry(const Entry* entry); std::vector GetSortedEntries() const; diff --git a/src/xenia/kernel/xam/xdbf/gpd_info_profile.cc b/src/xenia/kernel/xam/xdbf/gpd_info_profile.cc index 2f48129a7..f07904e85 100644 --- a/src/xenia/kernel/xam/xdbf/gpd_info_profile.cc +++ b/src/xenia/kernel/xam/xdbf/gpd_info_profile.cc @@ -88,6 +88,17 @@ void GpdInfoProfile::AddNewTitle(const SpaInfo* title_data) { UpsertEntry(&entry); } +bool GpdInfoProfile::RemoveTitle(const uint32_t title_id) { + const Entry* entry = + GetEntry(static_cast(GpdSection::kTitle), title_id); + if (!entry) { + return false; + } + + DeleteEntry(entry); + return true; +} + X_XDBF_GPD_TITLE_PLAYED GpdInfoProfile::FillTitlePlayedData( const SpaInfo* title_data) const { X_XDBF_GPD_TITLE_PLAYED title_gpd_data = {}; diff --git a/src/xenia/kernel/xam/xdbf/gpd_info_profile.h b/src/xenia/kernel/xam/xdbf/gpd_info_profile.h index 2389600a0..cce21d00c 100644 --- a/src/xenia/kernel/xam/xdbf/gpd_info_profile.h +++ b/src/xenia/kernel/xam/xdbf/gpd_info_profile.h @@ -32,6 +32,7 @@ class GpdInfoProfile : public GpdInfo { ~GpdInfoProfile() = default; void AddNewTitle(const SpaInfo* title_data); + bool RemoveTitle(const uint32_t title_id); void UpdateTitleInfo(const uint32_t title_id, X_XDBF_GPD_TITLE_PLAYED* title_data);