From dde8adc140f723e47a59c011dda2286d8bd1b20d Mon Sep 17 00:00:00 2001 From: Gliniak Date: Fri, 15 Apr 2022 09:28:42 +0200 Subject: [PATCH] Allow XamUserReadProfileSettings to use xuid to define profile --- src/xenia/kernel/kernel_state.cc | 2 +- src/xenia/kernel/kernel_state.h | 21 ++++++++++++++++++-- src/xenia/kernel/xam/content_manager.cc | 3 ++- src/xenia/kernel/xam/xam_user.cc | 26 +++++++++++++++++++------ 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 93c74b527..890c6ddd1 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -960,7 +960,7 @@ uint8_t KernelState::GetConnectedUsers() const { void KernelState::UpdateUsedUserProfiles() { const uint8_t used_slots_bitmask = GetConnectedUsers(); - for (uint8_t i = 1; i < 4; i++) { + for (uint32_t i = 1; i < 4; i++) { bool is_used = used_slots_bitmask & (1 << i); if (IsUserSignedIn(i) && !is_used) { diff --git a/src/xenia/kernel/kernel_state.h b/src/xenia/kernel/kernel_state.h index 3b25c3e5c..123a2b91f 100644 --- a/src/xenia/kernel/kernel_state.h +++ b/src/xenia/kernel/kernel_state.h @@ -108,14 +108,31 @@ class KernelState { uint8_t GetConnectedUsers() const; void UpdateUsedUserProfiles(); - bool IsUserSignedIn(uint8_t index) const { + bool IsUserSignedIn(uint32_t index) const { return user_profiles_.find(index) != user_profiles_.cend(); } - xam::UserProfile* user_profile(uint8_t index) const { + bool IsUserSignedIn(uint64_t xuid) const { + return user_profile(xuid) != nullptr; + } + + xam::UserProfile* user_profile(uint32_t index) const { + if (!IsUserSignedIn(index)) { + return nullptr; + } + return user_profiles_.at(index).get(); } + xam::UserProfile* user_profile(uint64_t xuid) const { + for (const auto& [key, value] : user_profiles_) { + if (value->xuid() == xuid) { + return user_profiles_.at(key).get(); + } + } + return nullptr; + } + // Access must be guarded by the global critical region. util::ObjectTable* object_table() { return &object_table_; } diff --git a/src/xenia/kernel/xam/content_manager.cc b/src/xenia/kernel/xam/content_manager.cc index 59a58a7f5..50f88075c 100644 --- a/src/xenia/kernel/xam/content_manager.cc +++ b/src/xenia/kernel/xam/content_manager.cc @@ -321,7 +321,8 @@ X_RESULT ContentManager::DeleteContent(const XCONTENT_AGGREGATE_DATA& data) { std::filesystem::path ContentManager::ResolveGameUserContentPath() { auto title_id = fmt::format("{:08X}", kernel_state_->title_id()); - auto user_name = xe::to_path(kernel_state_->user_profile(0)->name()); + auto user_name = + xe::to_path(kernel_state_->user_profile(uint32_t(0))->name()); // Per-game per-profile data location: // content_root/title_id/profile/user_name diff --git a/src/xenia/kernel/xam/xam_user.cc b/src/xenia/kernel/xam/xam_user.cc index 0ebef83ae..073315258 100644 --- a/src/xenia/kernel/xam/xam_user.cc +++ b/src/xenia/kernel/xam/xam_user.cc @@ -224,17 +224,31 @@ uint32_t XamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index, // Title ID = 0 means us. // 0xfffe07d1 = profile? - if (!kernel_state()->IsUserSignedIn(user_index)) { + if (!kernel_state()->IsUserSignedIn(user_index) && !xuids) { if (overlapped) { - kernel_state()->CompleteOverlappedImmediate( - kernel_state()->memory()->HostToGuestVirtual(overlapped), - X_ERROR_NO_SUCH_USER); + kernel_state()->CompleteOverlappedImmediate( + kernel_state()->memory()->HostToGuestVirtual(overlapped), + X_ERROR_NO_SUCH_USER); return X_ERROR_IO_PENDING; } return X_ERROR_NO_SUCH_USER; } - const auto& user_profile = kernel_state()->user_profile(user_index); + auto user_profile = kernel_state()->user_profile(user_index); + + if (xuids) { + uint64_t user_xuid = static_cast(xuids[0]); + if (!kernel_state()->IsUserSignedIn(user_xuid)) { + if (overlapped) { + kernel_state()->CompleteOverlappedImmediate( + kernel_state()->memory()->HostToGuestVirtual(overlapped), + X_ERROR_NO_SUCH_USER); + return X_ERROR_IO_PENDING; + } + return X_ERROR_NO_SUCH_USER; + } + user_profile = kernel_state()->user_profile(user_xuid); + } // First call asks for size (fill buffer_size_ptr). // Second call asks for buffer contents with that size. @@ -529,7 +543,7 @@ dword_result_t XamShowSigninUI_entry(dword_t unk, dword_t unk_mask) { // Mask values vary. Probably matching user types? Local/remote? // Games seem to sit and loop until we trigger this notification: - for (uint8_t i = 0; i < 4; i++) { + for (uint32_t i = 0; i < 4; i++) { if (kernel_state()->IsUserSignedIn(i)) { // XN_SYS_SIGNINCHANGED kernel_state()->BroadcastNotification(0xA, i);