From bc7bc76d68677d1cf85dd12f624ed91dac0d4d23 Mon Sep 17 00:00:00 2001 From: Adrian <78108584+AdrianCassar@users.noreply.github.com> Date: Sun, 22 Mar 2026 20:37:51 +0000 Subject: [PATCH 1/4] [APP] Fixed loading profile icon via login slots --- src/xenia/app/profile_dialogs.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/xenia/app/profile_dialogs.cc b/src/xenia/app/profile_dialogs.cc index 54b166d85..11d6f5df3 100644 --- a/src/xenia/app/profile_dialogs.cc +++ b/src/xenia/app/profile_dialogs.cc @@ -216,7 +216,21 @@ void ProfileConfigDialog::OnDraw(ImGuiIO& io) { if (ImGui::BeginMenu("Login to slot:")) { for (uint8_t i = 1; i <= XUserMaxUserCount; i++) { if (ImGui::MenuItem(fmt::format("slot {}", i).c_str())) { + uint64_t current_slot_xuid = 0; + + if (const auto current_profile = profile_manager->GetProfile( + static_cast(i - 1)); + current_profile) { + current_slot_xuid = current_profile->xuid(); + } + profile_manager->Login(xuid, i - 1); + LoadProfileIcon(xuid); + + // Release resources + if (current_slot_xuid) { + LoadProfileIcon(current_slot_xuid); + } } } ImGui::EndMenu(); From 049a55f03679b204379b17996bd032ce54bff156 Mon Sep 17 00:00:00 2001 From: Gliniak <153369+Gliniak@users.noreply.github.com> Date: Sun, 19 Apr 2026 20:21:24 +0200 Subject: [PATCH 2/4] [CPU/Posix] Fixed crash caused by calling mmap on empty file --- src/xenia/cpu/xex_module.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc index a4455173a..e2a35a55e 100644 --- a/src/xenia/cpu/xex_module.cc +++ b/src/xenia/cpu/xex_module.cc @@ -1372,20 +1372,20 @@ void XexInfoCache::Init(XexModule* xexmod) { auto try_open = [this, &infocache_path, num_codebytes]() { bool did_exist = true; + const size_t file_size = sizeof(InfoCacheFlagsHeader) + + (sizeof(InfoCacheFlags) * (num_codebytes / 4)); if (!std::filesystem::exists(infocache_path)) { xe::filesystem::CreateEmptyFile(infocache_path); + std::filesystem::resize_file(infocache_path, file_size); did_exist = false; } // todo: prepopulate with stuff from pdata, dll exports - - this->executable_addr_flags_ = std::move(xe::MappedMemory::Open( + this->executable_addr_flags_ = MappedMemory::Open( infocache_path, xe::MappedMemory::Mode::kReadWrite, 0, - sizeof(InfoCacheFlagsHeader) + - (sizeof(InfoCacheFlags) * - (num_codebytes / - 4)))); // one infocacheflags entry for each PPC instr-sized addr + file_size); // one infocacheflags entry for each PPC instr-sized addr + return did_exist; }; From 73e3caa5e164655b8146db9df75163155600593a Mon Sep 17 00:00:00 2001 From: Adrian <78108584+AdrianCassar@users.noreply.github.com> Date: Tue, 14 Apr 2026 15:59:50 +0100 Subject: [PATCH 3/4] [CPU] Disable instruction info cache if context promotion is disabled Fixed XMA writing to unknown registers when context promotion is disabled. --- src/xenia/cpu/xex_module.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc index e2a35a55e..1034dcac7 100644 --- a/src/xenia/cpu/xex_module.cc +++ b/src/xenia/cpu/xex_module.cc @@ -49,6 +49,8 @@ DEFINE_bool( DECLARE_bool(allow_plugins); +DECLARE_bool(disable_context_promotion); + static constexpr uint8_t xe_xex1_retail_key[16] = { 0xA2, 0x6C, 0x10, 0xF7, 0x1F, 0xD9, 0x35, 0xE9, 0x8B, 0x99, 0x92, 0x2C, 0xE9, 0x32, 0x15, 0x72}; @@ -1352,7 +1354,10 @@ std::unique_ptr XexModule::CreateFunction(uint32_t address) { processor_->backend()->CreateGuestFunction(this, address)); } void XexInfoCache::Init(XexModule* xexmod) { - if (cvars::disable_instruction_infocache) { + // If context promotion is disabled then disable instruction info cache as + // well, otherwise XMA will write to unknown registers. + if (cvars::disable_instruction_infocache || + cvars::disable_context_promotion) { return; } From a6e92f43ea5225836cdc86cc5cfd9730d0f91320 Mon Sep 17 00:00:00 2001 From: The-Little-Wolf <116989599+The-Little-Wolf@users.noreply.github.com> Date: Sat, 31 Jan 2026 10:56:34 -0800 Subject: [PATCH 4/4] [XAM/XNOTIFY] - Fixes and more flags - Properly set is_system in XamNotifyCreateListener - Save is_system for later use - Correct X_NOTIFICATION_ID - Add missing XNotificationID flags --- src/xenia/kernel/xam/xam_notify.cc | 9 ++++-- src/xenia/kernel/xnotifylistener.cc | 7 +++-- src/xenia/kernel/xnotifylistener.h | 4 ++- src/xenia/xbox.h | 44 ++++++++++++++++++----------- 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/xenia/kernel/xam/xam_notify.cc b/src/xenia/kernel/xam/xam_notify.cc index e98299541..2f88d5e7d 100644 --- a/src/xenia/kernel/xam/xam_notify.cc +++ b/src/xenia/kernel/xam/xam_notify.cc @@ -10,7 +10,9 @@ #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xam/xam_private.h" +#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h" #include "xenia/kernel/xnotifylistener.h" +#include "xenia/kernel/xthread.h" #include "xenia/xbox.h" namespace xe { @@ -27,7 +29,7 @@ uint32_t xeXamNotifyCreateListener(uint64_t mask, uint32_t is_system, auto listener = object_ref(new XNotifyListener(kernel_state())); - listener->Initialize(mask, max_version); + listener->Initialize(mask, is_system, max_version); // Handle ref is incremented, so return that. uint32_t handle = listener->handle(); @@ -37,7 +39,10 @@ uint32_t xeXamNotifyCreateListener(uint64_t mask, uint32_t is_system, dword_result_t XamNotifyCreateListener_entry(qword_t mask, dword_t max_version) { - return xeXamNotifyCreateListener(mask, 0, max_version); + auto thread = kernel::XThread::GetCurrentThread(); + auto ctx = thread->thread_state()->context(); + auto type = xboxkrnl::xeKeGetCurrentProcessType(ctx); + return xeXamNotifyCreateListener(mask, type == 2, max_version); } DECLARE_XAM_EXPORT1(XamNotifyCreateListener, kNone, kImplemented); diff --git a/src/xenia/kernel/xnotifylistener.cc b/src/xenia/kernel/xnotifylistener.cc index fc2d24c98..2cce3b1ee 100644 --- a/src/xenia/kernel/xnotifylistener.cc +++ b/src/xenia/kernel/xnotifylistener.cc @@ -22,12 +22,14 @@ XNotifyListener::XNotifyListener(KernelState* kernel_state) XNotifyListener::~XNotifyListener() {} -void XNotifyListener::Initialize(uint64_t mask, uint32_t max_version) { +void XNotifyListener::Initialize(uint64_t mask, uint32_t is_system, + uint32_t max_version) { assert_false(wait_handle_); wait_handle_ = xe::threading::Event::CreateManualResetEvent(false); assert_not_null(wait_handle_); mask_ = mask; + is_system_ = is_system; max_version_ = max_version; kernel_state_->RegisterNotifyListener(this); @@ -109,8 +111,9 @@ object_ref XNotifyListener::Restore(KernelState* kernel_state, notify->RestoreObject(stream); auto mask = stream->Read(); + auto is_system = stream->Read(); auto max_version = stream->Read(); - notify->Initialize(mask, max_version); + notify->Initialize(mask, is_system, max_version); auto notification_count_ = stream->Read(); for (size_t i = 0; i < notification_count_; i++) { diff --git a/src/xenia/kernel/xnotifylistener.h b/src/xenia/kernel/xnotifylistener.h index 7ec5be2c9..a489ba2e3 100644 --- a/src/xenia/kernel/xnotifylistener.h +++ b/src/xenia/kernel/xnotifylistener.h @@ -48,9 +48,10 @@ class XNotifyListener : public XObject { ~XNotifyListener() override; uint64_t mask() const { return mask_; } + uint32_t is_system() const { return is_system_; } uint32_t max_version() const { return max_version_; } - void Initialize(uint64_t mask, uint32_t max_version); + void Initialize(uint64_t mask, uint32_t is_system, uint32_t max_version); void EnqueueNotification(XNotificationID id, uint32_t data); bool DequeueNotification(XNotificationID* out_id, uint32_t* out_data); @@ -70,6 +71,7 @@ class XNotifyListener : public XObject { xe::global_critical_region global_critical_region_; std::vector> notifications_; uint64_t mask_ = 0; + uint32_t is_system_ = 0; uint32_t max_version_ = 0; }; diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index f159a58ab..2565380d6 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -162,10 +162,10 @@ constexpr uint8_t XUserIndexAny = 0xFF; typedef uint32_t XNotificationID; struct X_NOTIFICATION_ID { - uint32_t reserved : 1; // Always one - uint32_t area : 6; - uint32_t version : 9; - uint32_t message_id : 16; + uint32_t message_id : 16; // 0b0 sz:16 + uint32_t version : 9; // 0b16 sz:9 + uint32_t area : 6; // 0b25 sz:6 + uint32_t Internal : 1; // 0b31 sz:1 }; static_assert_size(X_NOTIFICATION_ID, 4); @@ -180,6 +180,11 @@ enum : XNotificationID { kXNotifyParty = 0x00000080, kXNotifyAll = 0x000000EF, + // Special Flags + kXNotificationInternal = 0x80000000, + kXNotificationAreaMask = 0x7e000000, + kXNotificationVersionMask = 0x01FF0000, + // XNotification System /* System Notes: - for some functions if XamIsNuiUIActive returns false then @@ -187,14 +192,6 @@ enum : XNotificationID { - XNotifyBroadcast(kXNotificationSystemNUIHardwareStatusChanged, device_state) */ - kXNotificationSystemTitleLoad = 0x80000001, - kXNotificationSystemTimeZone = 0x80000002, - kXNotificationSystemLanguage = 0x80000003, - kXNotificationSystemVideoFlags = 0x80000004, - kXNotificationSystemAudioFlags = 0x80000005, - kXNotificationSystemParentalControlGames = 0x80000006, - kXNotificationSystemParentalControlPassword = 0x80000007, - kXNotificationSystemParentalControlMovies = 0x80000008, kXNotificationSystemUI = 0x00000009, kXNotificationSystemSignInChanged = 0x0000000A, kXNotificationSystemStorageDevicesChanged = 0x0000000B, @@ -211,7 +208,6 @@ enum : XNotificationID { some funcs the third param is used with XNotifyBroadcast(kXNotificationSystemUnknown, unk) */ - kXNotificationSystemUnknown = 0x80010014, kXNotificationSystemPlayerTimerNotice = 0x00030015, kXNotificationSystemAvatarChanged = 0x00040017, kXNotificationSystemNUIHardwareStatusChanged = 0x00060019, @@ -222,23 +218,35 @@ enum : XNotificationID { kXNotificationSystemAudioLatencyChanged = 0x0008001E, kXNotificationSystemNUIChatBindingChanged = 0x0008001F, kXNotificationSystemInputActivityChanged = 0x00090020, + kXNotificationSystemProfileSettingChanged = 0x0000000E, + // XNotification System Internal + kXNotificationSystemTitleLoad = 0x80000001, + kXNotificationSystemTimeZone = 0x80000002, + kXNotificationSystemLanguage = 0x80000003, + kXNotificationSystemVideoFlags = 0x80000004, + kXNotificationSystemAudioFlags = 0x80000005, + kXNotificationSystemParentalControlGames = 0x80000006, + kXNotificationSystemParentalControlPassword = 0x80000007, + kXNotificationSystemParentalControlMovies = 0x80000008, kXNotificationSystemDashContextChanged = 0x8000000C, kXNotificationSystemTrayStateChanged = 0x8000000D, - kXNotificationSystemProfileSettingChanged = 0x0000000E, kXNotificationSystemThemeChanged = 0x8000000F, kXNotificationSystemSystemUpdateChanged = 0x80000010, + kXNotificationSystemUnknown = 0x80010014, + kXNotificationSystemDashboard = 0x80040016, // XNotification Live kXNotificationLiveConnectionChanged = 0x02000001, kXNotificationLiveInviteAccepted = 0x02000002, kXNotificationLiveLinkStateChanged = 0x02000003, - kXNotificationLiveInvitedRecieved = 0x82000004, - kXNotificationLiveInvitedAnswerRecieved = 0x82000005, - kXNotificationLiveMessageListChanged = 0x82000006, kXNotificationLiveContentInstalled = 0x02000007, kXNotificationLiveMembershipPurchased = 0x02000008, kXNotificationLiveVoicechatAway = 0x02000009, kXNotificationLivePresenceChanged = 0x0200000A, + // XNotification Live Internal + kXNotificationLiveInvitedRecieved = 0x82000004, + kXNotificationLiveInvitedAnswerRecieved = 0x82000005, + kXNotificationLiveMessageListChanged = 0x82000006, kXNotificationLivePointsBalanceChanged = 0x8200000B, kXNotificationLivePlayerListChanged = 0x8200000C, kXNotificationLiveItemPurchased = 0x8200000D, @@ -247,6 +255,7 @@ enum : XNotificationID { kXNotificationFriendsPresenceChanged = 0x04000001, kXNotificationFriendsFriendAdded = 0x04000002, kXNotificationFriendsFriendRemoved = 0x04000003, + // XNotification Friends Internal kXNotificationFriendsFriendRequestReceived = 0x84000004, kXNotificationFriendsFriendAnswerReceived = 0x84000005, kXNotificationFriendsFriendRequestResult = 0x84000006, @@ -259,6 +268,7 @@ enum : XNotificationID { kXNotificationXmpStateChanged = 0x0A000001, kXNotificationXmpPlaybackBehaviorChanged = 0x0A000002, kXNotificationXmpPlaybackControllerChanged = 0x0A000003, + // XNotification XMP Internal kXNotificationXmpMediaSourceConnectionChanged = 0x8A000004, kXNotificationXmpTitlePlayListContentChanged = 0x8A000005, kXNotificationXmpLocalMediaContentChanged = 0x8A000006,