Skip to content

Commit

Permalink
Merge branch 'xenia-canary:canary_experimental' into Xmp
Browse files Browse the repository at this point in the history
  • Loading branch information
backgamon authored Nov 1, 2024
2 parents fd0ab4e + 996b874 commit 916f6e0
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 14 deletions.
50 changes: 37 additions & 13 deletions src/xenia/kernel/xam/profile_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
std::filesystem::path profile_path = GetProfilePath(xuid);
std::string mount_path = fmt::format("{:016X}", xuid) + ':';
Expand Down Expand Up @@ -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<uint8_t> 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;
}

Expand Down
3 changes: 3 additions & 0 deletions src/xenia/kernel/xam/profile_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down
78 changes: 77 additions & 1 deletion src/xenia/kernel/xam/xam_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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")) {
Expand Down

0 comments on commit 916f6e0

Please sign in to comment.