From 996b874d74110e52e7dde83dbf59d51cc57c17d8 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Fri, 1 Nov 2024 22:43:44 +0100 Subject: [PATCH] [Profile] Added option to modify Gamertag --- src/xenia/kernel/xam/profile_manager.cc | 50 +++++++++++----- src/xenia/kernel/xam/profile_manager.h | 3 + src/xenia/kernel/xam/xam_ui.cc | 78 ++++++++++++++++++++++++- 3 files changed, 117 insertions(+), 14 deletions(-) diff --git a/src/xenia/kernel/xam/profile_manager.cc b/src/xenia/kernel/xam/profile_manager.cc index 35399e1f3c..ad31f84022 100644 --- a/src/xenia/kernel/xam/profile_manager.cc +++ b/src/xenia/kernel/xam/profile_manager.cc @@ -233,6 +233,26 @@ void ProfileManager::LoadAccounts(const std::vector profiles_xuids) { } } +void ProfileManager::ModifyGamertag(const uint64_t xuid, std::string gamertag) { + if (!accounts_.count(xuid)) { + return; + } + + xe::X_XAMACCOUNTINFO* account = &accounts_[xuid]; + + std::u16string gamertag_u16 = xe::to_utf16(gamertag); + + string_util::copy_truncating(account->gamertag, gamertag_u16, + sizeof(account->gamertag)); + + if (!MountProfile(xuid)) { + return; + } + + UpdateAccount(xuid, account); + DismountProfile(xuid); +} + bool ProfileManager::MountProfile(const uint64_t xuid) { std::filesystem::path profile_path = GetProfilePath(xuid); std::string mount_path = fmt::format("{:016X}", xuid) + ':'; @@ -448,40 +468,44 @@ bool ProfileManager::CreateProfile(const std::string gamertag, bool autologin, bool ProfileManager::CreateAccount(const uint64_t xuid, const std::string gamertag) { + X_XAMACCOUNTINFO account = {}; + std::u16string gamertag_u16 = xe::to_utf16(gamertag); + + string_util::copy_truncating(account.gamertag, gamertag_u16, + sizeof(account.gamertag)); + + UpdateAccount(xuid, &account); + DismountProfile(xuid); + + accounts_.insert({xuid, account}); + return true; +} + +bool ProfileManager::UpdateAccount(const uint64_t xuid, + X_XAMACCOUNTINFO* account) { const std::string guest_path = xe::string_util::to_hex_string(xuid) + ":\\Account"; xe::vfs::File* output_file; xe::vfs::FileAction action = {}; auto status = kernel_state_->file_system()->OpenFile( - nullptr, guest_path, xe::vfs::FileDisposition::kCreate, + nullptr, guest_path, xe::vfs::FileDisposition::kOpenIf, xe::vfs::FileAccess::kFileWriteData, false, true, &output_file, &action); if (XFAILED(status) || !output_file || !output_file->entry()) { XELOGI("{}: Failed to open Account file for creation: {:08X}", __func__, status); - DismountProfile(xuid); return false; } - X_XAMACCOUNTINFO account = {}; - std::u16string gamertag_u16 = xe::to_utf16(gamertag); - - string_util::copy_truncating(account.gamertag, gamertag_u16, - sizeof(account.gamertag)); - std::vector encrypted_data; encrypted_data.resize(sizeof(X_XAMACCOUNTINFO) + 0x18); - EncryptAccountFile(&account, encrypted_data.data()); + EncryptAccountFile(account, encrypted_data.data()); size_t written_bytes = 0; output_file->WriteSync(encrypted_data.data(), encrypted_data.size(), 0, &written_bytes); output_file->Destroy(); - - DismountProfile(xuid); - - accounts_.insert({xuid, account}); return true; } diff --git a/src/xenia/kernel/xam/profile_manager.h b/src/xenia/kernel/xam/profile_manager.h index 76f5a86f1f..93cc36879d 100644 --- a/src/xenia/kernel/xam/profile_manager.h +++ b/src/xenia/kernel/xam/profile_manager.h @@ -84,6 +84,8 @@ class ProfileManager { // bool CreateProfile(const X_XAMACCOUNTINFO* account_info); bool DeleteProfile(const uint64_t xuid); + void ModifyGamertag(const uint64_t xuid, std::string gamertag); + bool MountProfile(const uint64_t xuid); bool DismountProfile(const uint64_t xuid); @@ -116,6 +118,7 @@ class ProfileManager { private: void UpdateConfig(const uint64_t xuid, const uint8_t slot); bool CreateAccount(const uint64_t xuid, const std::string gamertag); + bool UpdateAccount(const uint64_t xuid, X_XAMACCOUNTINFO* account); std::filesystem::path GetProfilePath(const uint64_t xuid) const; std::filesystem::path GetProfilePath(const std::string xuid) const; diff --git a/src/xenia/kernel/xam/xam_ui.cc b/src/xenia/kernel/xam/xam_ui.cc index eabcd71e5b..1bda07b4bb 100644 --- a/src/xenia/kernel/xam/xam_ui.cc +++ b/src/xenia/kernel/xam/xam_ui.cc @@ -315,6 +315,72 @@ class MessageBoxDialog : public XamDialog { uint32_t chosen_button_ = 0; }; +class GamertagModifyDialog final : public ui::ImGuiDialog { + public: + GamertagModifyDialog(ui::ImGuiDrawer* imgui_drawer, + ProfileManager* profile_manager, uint64_t xuid) + : ui::ImGuiDialog(imgui_drawer), + profile_manager_(profile_manager), + xuid_(xuid) { + memset(gamertag_, 0, sizeof(gamertag_)); + } + + private: + void OnDraw(ImGuiIO& io) override { + if (!has_opened_) { + ImGui::OpenPopup("Modify Gamertag"); + has_opened_ = true; + } + + bool dialog_open = true; + if (!ImGui::BeginPopupModal("Modify Gamertag", &dialog_open, + ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_HorizontalScrollbar)) { + Close(); + return; + } + + if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && + !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)) { + ImGui::SetKeyboardFocusHere(0); + } + + ImGui::TextUnformatted("New gamertag:"); + ImGui::InputText("##Gamertag", gamertag_, sizeof(gamertag_)); + + const std::string gamertag_string = std::string(gamertag_); + bool valid = profile_manager_->IsGamertagValid(gamertag_string); + + ImGui::BeginDisabled(!valid); + if (ImGui::Button("Update")) { + profile_manager_->ModifyGamertag(xuid_, gamertag_string); + std::fill(std::begin(gamertag_), std::end(gamertag_), '\0'); + dialog_open = false; + } + ImGui::EndDisabled(); + ImGui::SameLine(); + + if (ImGui::Button("Cancel")) { + std::fill(std::begin(gamertag_), std::end(gamertag_), '\0'); + dialog_open = false; + } + + if (!dialog_open) { + ImGui::CloseCurrentPopup(); + Close(); + ImGui::EndPopup(); + return; + } + ImGui::EndPopup(); + }; + + bool has_opened_ = false; + char gamertag_[16] = ""; + const uint64_t xuid_; + ProfileManager* profile_manager_; +}; + static dword_result_t XamShowMessageBoxUi( dword_t user_index, lpu16string_t title_ptr, lpu16string_t text_ptr, dword_t button_count, lpdword_t button_ptrs, dword_t active_button, @@ -873,7 +939,17 @@ bool xeDrawProfileContent(ui::ImGuiDrawer* imgui_drawer, const uint64_t xuid, } } - ImGui::MenuItem("Modify (unsupported)"); + ImGui::BeginDisabled(kernel_state()->emulator()->is_title_open()); + if (ImGui::BeginMenu("Modify")) { + if (ImGui::MenuItem("Gamertag")) { + new GamertagModifyDialog(imgui_drawer, profile_manager, xuid); + } + + ImGui::MenuItem("Profile Icon (Unsupported)"); + ImGui::EndMenu(); + } + ImGui::EndDisabled(); + ImGui::MenuItem("Show Achievements (unsupported)"); if (ImGui::MenuItem("Show Content Directory")) {