From feafc3809c319887c110d1901f984411f4d7d3bd Mon Sep 17 00:00:00 2001 From: Adrian <78108584+AdrianCassar@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:38:17 +0000 Subject: [PATCH] [XAM] Implemented XamProfileCreateEnumerator & XamProfileEnumerate --- src/xenia/kernel/xam/xam_enum.cc | 44 ++++++++++++++++++++++++++++++++ src/xenia/kernel/xam/xam_ui.cc | 13 +++++++++- src/xenia/xbox.h | 7 +++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/xenia/kernel/xam/xam_enum.cc b/src/xenia/kernel/xam/xam_enum.cc index c293d8f66..8158906f5 100644 --- a/src/xenia/kernel/xam/xam_enum.cc +++ b/src/xenia/kernel/xam/xam_enum.cc @@ -123,6 +123,50 @@ dword_result_t XamGetPrivateEnumStructureFromHandle_entry( } DECLARE_XAM_EXPORT1(XamGetPrivateEnumStructureFromHandle, kNone, kStub); +dword_result_t XamProfileCreateEnumerator_entry(dword_t device_id, + lpdword_t handle_ptr) { + if (!handle_ptr) { + return X_ERROR_INVALID_PARAMETER; + } + + auto e = new XStaticEnumerator(kernel_state(), 1); + + auto result = e->Initialize(XUserIndexAny, 0xFE, 0x23001, 0x23003, 0); + + if (XFAILED(result)) { + return result; + } + + const auto& profiles = + kernel_state()->xam_state()->profile_manager()->GetProfiles(); + + for (const auto& [xuid, account] : *profiles) { + X_PROFILEENUMRESULT* profile = e->AppendItem(); + + profile->xuid_offline = xuid; + profile->device_id = 1; + memcpy(&profile->account, &account, sizeof(X_XAMACCOUNTINFO)); + + xe::string_util::copy_and_swap_truncating( + profile->account.gamertag, account.gamertag, sizeof(account.gamertag)); + } + + *handle_ptr = e->handle(); + return X_ERROR_SUCCESS; +} +DECLARE_XAM_EXPORT1(XamProfileCreateEnumerator, kNone, kImplemented); + +dword_result_t XamProfileEnumerate_entry(dword_t handle, dword_t flags, + lpvoid_t buffer, + pointer_t overlapped) { + uint32_t dummy = 0; + auto result = xeXamEnumerate(handle, flags, buffer, 0, + !overlapped ? &dummy : nullptr, overlapped); + + return result; +} +DECLARE_XAM_EXPORT1(XamProfileEnumerate, kNone, kImplemented); + } // namespace xam } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xam/xam_ui.cc b/src/xenia/kernel/xam/xam_ui.cc index 1bda07b4b..79b5d9716 100644 --- a/src/xenia/kernel/xam/xam_ui.cc +++ b/src/xenia/kernel/xam/xam_ui.cc @@ -1275,7 +1275,8 @@ class SigninDialog : public XamDialog { char gamertag_[16] = ""; }; -dword_result_t XamShowSigninUI_entry(dword_t users_needed, dword_t unk_mask) { +X_RESULT xeXamShowSigninUI(uint32_t user_index, uint32_t users_needed, + uint32_t flags) { // Mask values vary. Probably matching user types? Local/remote? // Games seem to sit and loop until we trigger sign in notification. if (users_needed != 1 && users_needed != 2 && users_needed != 4) { @@ -1305,8 +1306,18 @@ dword_result_t XamShowSigninUI_entry(dword_t users_needed, dword_t unk_mask) { return xeXamDispatchDialogAsync( new SigninDialog(imgui_drawer, users_needed), close); } + +dword_result_t XamShowSigninUI_entry(dword_t users_needed, dword_t flags) { + return xeXamShowSigninUI(XUserIndexAny, users_needed, flags); +} DECLARE_XAM_EXPORT1(XamShowSigninUI, kUserProfiles, kImplemented); +dword_result_t XamShowSigninUIp_entry(dword_t user_index, dword_t users_needed, + dword_t flags) { + return xeXamShowSigninUI(user_index, users_needed, flags); +} +DECLARE_XAM_EXPORT1(XamShowSigninUIp, kUserProfiles, kImplemented); + } // namespace xam } // namespace kernel } // namespace xe diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 4f10728c6..307348608 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -642,6 +642,13 @@ struct X_XAMACCOUNTINFO { static_assert_size(X_XAMACCOUNTINFO, 0x17C); #pragma pack(pop) +struct X_PROFILEENUMRESULT { + xe::be xuid_offline; // E0..... + X_XAMACCOUNTINFO account; + xe::be device_id; +}; +static_assert_size(X_PROFILEENUMRESULT, 0x188); + } // namespace xe // clang-format on