diff --git a/src/xenia/kernel/xam/xam_ui.cc b/src/xenia/kernel/xam/xam_ui.cc index a3871577b..e2e01d015 100644 --- a/src/xenia/kernel/xam/xam_ui.cc +++ b/src/xenia/kernel/xam/xam_ui.cc @@ -111,6 +111,9 @@ dword_result_t XamShowMessageBoxUI(dword_t user_index, lpwstring_t title_ptr, buttons.push_back(button); } + // Broadcast XN_SYS_UI = true + kernel_state()->BroadcastNotification(0x9, true); + uint32_t chosen_button; if (cvars::headless) { // Auto-pick the focused button. @@ -144,6 +147,9 @@ dword_result_t XamShowMessageBoxUI(dword_t user_index, lpwstring_t title_ptr, } *result_ptr = chosen_button; + // Broadcast XN_SYS_UI = false + kernel_state()->BroadcastNotification(0x9, false); + if (overlapped) { kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS); return X_ERROR_IO_PENDING; @@ -232,6 +238,9 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags, return X_ERROR_INVALID_PARAMETER; } + // Broadcast XN_SYS_UI = true + kernel_state()->BroadcastNotification(0x9, true); + if (cvars::headless) { // Redirect default_text back into the buffer. std::memset(buffer, 0, buffer_length * 2); @@ -239,6 +248,9 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags, xe::store_and_swap(buffer, default_text.value()); } + // Broadcast XN_SYS_UI = false + kernel_state()->BroadcastNotification(0x9, false); + if (overlapped) { kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS); return X_ERROR_IO_PENDING; @@ -269,6 +281,9 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags, out_text = out_text.substr(0, buffer_length - 1); xe::store_and_swap(buffer, out_text); + // Broadcast XN_SYS_UI = false + kernel_state()->BroadcastNotification(0x9, false); + if (overlapped) { kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS); return X_ERROR_IO_PENDING; @@ -300,6 +315,10 @@ dword_result_t XamShowDeviceSelectorUI(dword_t user_index, dword_t content_type, break; } + // Broadcast XN_SYS_UI = true followed by XN_SYS_UI = false + kernel_state()->BroadcastNotification(0x9, true); + kernel_state()->BroadcastNotification(0x9, false); + if (overlapped) { kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS); return X_ERROR_IO_PENDING; diff --git a/src/xenia/kernel/xnotifylistener.cc b/src/xenia/kernel/xnotifylistener.cc index 747f53574..0770bd2d8 100644 --- a/src/xenia/kernel/xnotifylistener.cc +++ b/src/xenia/kernel/xnotifylistener.cc @@ -36,14 +36,7 @@ void XNotifyListener::EnqueueNotification(XNotificationID id, uint32_t data) { } auto global_lock = global_critical_region_.Acquire(); - if (notifications_.count(id)) { - // Already exists. Overwrite. - notifications_[id] = data; - } else { - // New. - notification_count_++; - notifications_.insert({id, data}); - } + notifications_.push_back(std::pair(id, data)); wait_handle_->Set(); } @@ -51,14 +44,13 @@ bool XNotifyListener::DequeueNotification(XNotificationID* out_id, uint32_t* out_data) { auto global_lock = global_critical_region_.Acquire(); bool dequeued = false; - if (notification_count_) { + if (notifications_.size()) { dequeued = true; auto it = notifications_.begin(); *out_id = it->first; *out_data = it->second; notifications_.erase(it); - notification_count_--; - if (!notification_count_) { + if (!notifications_.size()) { wait_handle_->Reset(); } } @@ -69,17 +61,22 @@ bool XNotifyListener::DequeueNotification(XNotificationID id, uint32_t* out_data) { auto global_lock = global_critical_region_.Acquire(); bool dequeued = false; - if (notification_count_) { - auto it = notifications_.find(id); - if (it != notifications_.end()) { - dequeued = true; - *out_data = it->second; - notifications_.erase(it); - notification_count_--; - if (!notification_count_) { - wait_handle_->Reset(); - } + if (!notifications_.size()) { + return dequeued; + } + + for (auto it = notifications_.begin(); it != notifications_.end(); ++it) { + if (it->first != id) { + continue; } + + dequeued = true; + *out_data = it->second; + notifications_.erase(it); + if (!notifications_.size()) { + wait_handle_->Reset(); + } + break; } return dequeued; } @@ -88,8 +85,8 @@ bool XNotifyListener::Save(ByteStream* stream) { SaveObject(stream); stream->Write(mask_); - stream->Write(notification_count_); - if (notification_count_) { + stream->Write(notifications_.size()); + if (notifications_.size()) { for (auto pair : notifications_) { stream->Write(pair.first); stream->Write(pair.second); @@ -107,12 +104,12 @@ object_ref XNotifyListener::Restore(KernelState* kernel_state, notify->RestoreObject(stream); notify->Initialize(stream->Read()); - notify->notification_count_ = stream->Read(); - for (size_t i = 0; i < notify->notification_count_; i++) { + auto notification_count_ = stream->Read(); + for (size_t i = 0; i < notification_count_; i++) { std::pair pair; pair.first = stream->Read(); pair.second = stream->Read(); - notify->notifications_.insert(pair); + notify->notifications_.push_back(pair); } return object_ref(notify); diff --git a/src/xenia/kernel/xnotifylistener.h b/src/xenia/kernel/xnotifylistener.h index 83599dd0b..800fa047d 100644 --- a/src/xenia/kernel/xnotifylistener.h +++ b/src/xenia/kernel/xnotifylistener.h @@ -48,8 +48,7 @@ class XNotifyListener : public XObject { private: std::unique_ptr wait_handle_; xe::global_critical_region global_critical_region_; - std::unordered_map notifications_; - size_t notification_count_ = 0; + std::vector> notifications_; uint64_t mask_ = 0; };