[XAM] Allow deleting titles with achievements earned from profiles

This commit is contained in:
NicknineTheEagle
2026-08-10 09:33:11 +03:00
committed by Radosław Gliński
parent 052cb95f24
commit 12f5084b93
4 changed files with 72 additions and 8 deletions

View File

@@ -8,6 +8,8 @@
*/
#include "xenia/kernel/xam/ui/title_info_ui.h"
#include "xenia/emulator.h"
#include "xenia/kernel/xam/ui/game_achievements_ui.h"
#include "xenia/base/system.h"
@@ -142,6 +144,8 @@ void TitleListUI::DrawTitleEntry(ImGuiIO& io, TitleInfo& entry) {
ImGui::Separator();
ImGui::BeginDisabled(kernel_state()->emulator()->is_title_open());
const auto title_info =
kernel_state()->xam_state()->user_tracker()->GetUserTitleInfo(
profile_->xuid(), entry.id);
@@ -156,13 +160,29 @@ void TitleListUI::DrawTitleEntry(ImGuiIO& io, TitleInfo& entry) {
}
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);
if (ImGui::BeginMenu("Delete title")) {
if (entry.unlocked_achievements_count != 0) {
ImGui::BeginTooltip();
ImGui::TextUnformatted(
fmt::format(
"This will erase all unlocked achievements and potentially "
"erase progress for this title. Are you sure?")
.c_str());
ImGui::EndTooltip();
}
if (ImGui::MenuItem("Yes, delete it!")) {
kernel_state()
->xam_state()
->user_tracker()
->RemoveTitleFromPlayedList(profile_->xuid(), entry.id);
}
ImGui::EndMenu();
}
}
ImGui::EndDisabled();
ImGui::EndPopup();
}
}

View File

@@ -181,6 +181,23 @@ bool UserProfile::WriteGpd(const uint32_t title_id) {
return true;
}
bool UserProfile::RemoveGpd(const uint32_t title_id) {
auto it = games_gpd_.find(title_id);
if (it == games_gpd_.end()) {
return false;
}
const std::string mounted_path =
fmt::format("User_{:016X}:\\{:08X}.gpd", xuid_, title_id);
if (!kernel_state()->file_system()->DeletePath(mounted_path)) {
return false;
}
games_gpd_.erase(it);
return true;
}
} // namespace xam
} // namespace kernel
} // namespace xe

View File

@@ -174,6 +174,7 @@ class UserProfile {
std::span<const uint8_t> icon_data);
std::vector<uint8_t> LoadGpd(const uint32_t title_id);
bool WriteGpd(const uint32_t title_id);
bool RemoveGpd(const uint32_t title_id);
};
} // namespace xam

View File

@@ -191,11 +191,37 @@ void UserTracker::RemoveTitleFromPlayedList(uint64_t xuid, uint32_t title_id) {
return;
}
if (user->dashboard_gpd_.RemoveTitle(title_id)) {
UpdateSettingValue(xuid, kDashboardID,
UserSettingId::XPROFILE_GAMERCARD_TITLES_PLAYED, -1);
FlushUserData(xuid);
auto title_data = user->dashboard_gpd_.GetTitleInfo(title_id);
if (!title_data) {
return;
}
// Get the number of achievements and gamer score we got from this title.
int32_t gamerscore_earned =
static_cast<int32_t>(title_data->gamerscore_earned);
int32_t achievements_unlocked =
static_cast<int32_t>(title_data->achievements_unlocked);
// Remove the title's GPD.
if (!user->RemoveGpd(title_id)) {
return;
}
// Remove the title from dashboard GPD.
if (!user->dashboard_gpd_.RemoveTitle(title_id)) {
return;
}
// Lower the profile's stats.
UpdateSettingValue(xuid, kDashboardID,
UserSettingId::XPROFILE_GAMERCARD_TITLES_PLAYED, -1);
UpdateSettingValue(xuid, kDashboardID, UserSettingId::XPROFILE_GAMERCARD_CRED,
-gamerscore_earned);
UpdateSettingValue(xuid, kDashboardID,
UserSettingId::XPROFILE_GAMERCARD_ACHIEVEMENTS_EARNED,
-achievements_unlocked);
FlushUserData(xuid);
}
// Privates