mirror of
https://github.com/xenia-project/xenia.git
synced 2025-12-06 07:12:03 +01:00
[Profile] Added option to modify Gamertag
This commit is contained in:
parent
cf0ee05da6
commit
996b874d74
|
|
@ -233,6 +233,26 @@ void ProfileManager::LoadAccounts(const std::vector<uint64_t> 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) {
|
bool ProfileManager::MountProfile(const uint64_t xuid) {
|
||||||
std::filesystem::path profile_path = GetProfilePath(xuid);
|
std::filesystem::path profile_path = GetProfilePath(xuid);
|
||||||
std::string mount_path = fmt::format("{:016X}", 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,
|
bool ProfileManager::CreateAccount(const uint64_t xuid,
|
||||||
const std::string gamertag) {
|
const std::string gamertag) {
|
||||||
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,
|
|
||||||
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 = {};
|
X_XAMACCOUNTINFO account = {};
|
||||||
std::u16string gamertag_u16 = xe::to_utf16(gamertag);
|
std::u16string gamertag_u16 = xe::to_utf16(gamertag);
|
||||||
|
|
||||||
string_util::copy_truncating(account.gamertag, gamertag_u16,
|
string_util::copy_truncating(account.gamertag, gamertag_u16,
|
||||||
sizeof(account.gamertag));
|
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::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);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> encrypted_data;
|
std::vector<uint8_t> encrypted_data;
|
||||||
encrypted_data.resize(sizeof(X_XAMACCOUNTINFO) + 0x18);
|
encrypted_data.resize(sizeof(X_XAMACCOUNTINFO) + 0x18);
|
||||||
EncryptAccountFile(&account, encrypted_data.data());
|
EncryptAccountFile(account, encrypted_data.data());
|
||||||
|
|
||||||
size_t written_bytes = 0;
|
size_t written_bytes = 0;
|
||||||
output_file->WriteSync(encrypted_data.data(), encrypted_data.size(), 0,
|
output_file->WriteSync(encrypted_data.data(), encrypted_data.size(), 0,
|
||||||
&written_bytes);
|
&written_bytes);
|
||||||
output_file->Destroy();
|
output_file->Destroy();
|
||||||
|
|
||||||
DismountProfile(xuid);
|
|
||||||
|
|
||||||
accounts_.insert({xuid, account});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ class ProfileManager {
|
||||||
// bool CreateProfile(const X_XAMACCOUNTINFO* account_info);
|
// bool CreateProfile(const X_XAMACCOUNTINFO* account_info);
|
||||||
bool DeleteProfile(const uint64_t xuid);
|
bool DeleteProfile(const uint64_t xuid);
|
||||||
|
|
||||||
|
void ModifyGamertag(const uint64_t xuid, std::string gamertag);
|
||||||
|
|
||||||
bool MountProfile(const uint64_t xuid);
|
bool MountProfile(const uint64_t xuid);
|
||||||
bool DismountProfile(const uint64_t xuid);
|
bool DismountProfile(const uint64_t xuid);
|
||||||
|
|
||||||
|
|
@ -116,6 +118,7 @@ class ProfileManager {
|
||||||
private:
|
private:
|
||||||
void UpdateConfig(const uint64_t xuid, const uint8_t slot);
|
void UpdateConfig(const uint64_t xuid, const uint8_t slot);
|
||||||
bool CreateAccount(const uint64_t xuid, const std::string gamertag);
|
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 uint64_t xuid) const;
|
||||||
std::filesystem::path GetProfilePath(const std::string xuid) const;
|
std::filesystem::path GetProfilePath(const std::string xuid) const;
|
||||||
|
|
|
||||||
|
|
@ -315,6 +315,72 @@ class MessageBoxDialog : public XamDialog {
|
||||||
uint32_t chosen_button_ = 0;
|
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(
|
static dword_result_t XamShowMessageBoxUi(
|
||||||
dword_t user_index, lpu16string_t title_ptr, lpu16string_t text_ptr,
|
dword_t user_index, lpu16string_t title_ptr, lpu16string_t text_ptr,
|
||||||
dword_t button_count, lpdword_t button_ptrs, dword_t active_button,
|
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)");
|
ImGui::MenuItem("Show Achievements (unsupported)");
|
||||||
|
|
||||||
if (ImGui::MenuItem("Show Content Directory")) {
|
if (ImGui::MenuItem("Show Content Directory")) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue