Spamming some notifications on startup to unhang games.

This commit is contained in:
Ben Vanik 2014-10-29 21:09:54 -07:00
parent 1566b4c890
commit 6053f1d35c
5 changed files with 39 additions and 8 deletions

View File

@ -33,7 +33,8 @@ KernelState* shared_kernel_state_ = nullptr;
KernelState::KernelState(Emulator* emulator) KernelState::KernelState(Emulator* emulator)
: emulator_(emulator), : emulator_(emulator),
memory_(emulator->memory()), memory_(emulator->memory()),
executable_module_(NULL) { has_notified_startup_(false),
executable_module_(nullptr) {
processor_ = emulator->processor(); processor_ = emulator->processor();
file_system_ = emulator->file_system(); file_system_ = emulator->file_system();
@ -51,7 +52,7 @@ KernelState::KernelState(Emulator* emulator)
} }
KernelState::~KernelState() { KernelState::~KernelState() {
SetExecutableModule(NULL); SetExecutableModule(nullptr);
// Delete all objects. // Delete all objects.
delete object_table_; delete object_table_;
@ -62,7 +63,7 @@ KernelState::~KernelState() {
delete dispatcher_; delete dispatcher_;
assert_true(shared_kernel_state_ == this); assert_true(shared_kernel_state_ == this);
shared_kernel_state_ = NULL; shared_kernel_state_ = nullptr;
} }
KernelState* KernelState::shared() { return shared_kernel_state_; } KernelState* KernelState::shared() { return shared_kernel_state_; }
@ -86,17 +87,17 @@ XModule* KernelState::GetModule(const char* name) {
return module; return module;
} else if (strcasecmp(name, "kernel32.dll") == 0) { } else if (strcasecmp(name, "kernel32.dll") == 0) {
// Some games request this, for some reason. wtf. // Some games request this, for some reason. wtf.
return NULL; return nullptr;
} else { } else {
// TODO(benvanik): support user modules/loading/etc. // TODO(benvanik): support user modules/loading/etc.
assert_always(); assert_always();
return NULL; return nullptr;
} }
} }
XUserModule* KernelState::GetExecutableModule() { XUserModule* KernelState::GetExecutableModule() {
if (!executable_module_) { if (!executable_module_) {
return NULL; return nullptr;
} }
executable_module_->Retain(); executable_module_->Retain();
@ -132,7 +133,7 @@ void KernelState::UnregisterThread(XThread* thread) {
XThread* KernelState::GetThreadByID(uint32_t thread_id) { XThread* KernelState::GetThreadByID(uint32_t thread_id) {
std::lock_guard<std::mutex> lock(object_mutex_); std::lock_guard<std::mutex> lock(object_mutex_);
XThread* thread = NULL; XThread* thread = nullptr;
auto it = threads_by_id_.find(thread_id); auto it = threads_by_id_.find(thread_id);
if (it != threads_by_id_.end()) { if (it != threads_by_id_.end()) {
thread = it->second; thread = it->second;
@ -145,6 +146,25 @@ XThread* KernelState::GetThreadByID(uint32_t thread_id) {
void KernelState::RegisterNotifyListener(XNotifyListener* listener) { void KernelState::RegisterNotifyListener(XNotifyListener* listener) {
std::lock_guard<std::mutex> lock(object_mutex_); std::lock_guard<std::mutex> lock(object_mutex_);
notify_listeners_.push_back(listener); notify_listeners_.push_back(listener);
// Games seem to expect a few notifications on startup, only for the first
// listener.
// http://cs.rin.ru/forum/viewtopic.php?f=38&t=60668&hilit=resident+evil+5&start=375
if (!has_notified_startup_ && listener->mask() & 0x00000001) {
has_notified_startup_ = true;
// XN_SYS_UI (on, off)
listener->EnqueueNotification(0x00000009, 1);
listener->EnqueueNotification(0x00000009, 0);
// XN_SYS_SIGNINCHANGED x2
listener->EnqueueNotification(0x0000000A, 1);
listener->EnqueueNotification(0x0000000A, 1);
// XN_SYS_INPUTDEVICESCHANGED x2
listener->EnqueueNotification(0x00000012, 0);
listener->EnqueueNotification(0x00000012, 0);
// XN_SYS_INPUTDEVICECONFIGCHANGED x2
listener->EnqueueNotification(0x00000013, 0);
listener->EnqueueNotification(0x00000013, 0);
}
} }
void KernelState::UnregisterNotifyListener(XNotifyListener* listener) { void KernelState::UnregisterNotifyListener(XNotifyListener* listener) {

View File

@ -93,6 +93,7 @@ class KernelState {
std::mutex object_mutex_; std::mutex object_mutex_;
std::unordered_map<uint32_t, XThread*> threads_by_id_; std::unordered_map<uint32_t, XThread*> threads_by_id_;
std::vector<XNotifyListener*> notify_listeners_; std::vector<XNotifyListener*> notify_listeners_;
bool has_notified_startup_;
XUserModule* executable_module_; XUserModule* executable_module_;

View File

@ -23,6 +23,8 @@ class XNotifyListener : public XObject {
XNotifyListener(KernelState* kernel_state); XNotifyListener(KernelState* kernel_state);
virtual ~XNotifyListener(); virtual ~XNotifyListener();
uint64_t mask() const { return mask_; }
void Initialize(uint64_t mask); void Initialize(uint64_t mask);
void EnqueueNotification(XNotificationID id, uint32_t data); void EnqueueNotification(XNotificationID id, uint32_t data);

View File

@ -113,6 +113,7 @@ SHIM_CALL XamEnumerate_shim(PPCContext* ppc_state, KernelState* state) {
return; return;
} }
// 0 items.
if (item_count_ptr) { if (item_count_ptr) {
assert_zero(overlapped_ptr); assert_zero(overlapped_ptr);
SHIM_SET_MEM_32(item_count_ptr, 0); SHIM_SET_MEM_32(item_count_ptr, 0);

View File

@ -48,9 +48,16 @@ SHIM_CALL XamUserGetSigninState_shim(PPCContext* ppc_state,
// from initializing the network. // from initializing the network.
if (user_index == 0 || (user_index & 0xFF) == 0xFF) { if (user_index == 0 || (user_index & 0xFF) == 0xFF) {
const auto& user_profile = state->user_profile(); const auto& user_profile = state->user_profile();
SHIM_SET_RETURN_64(user_profile->signin_state()); auto signin_state = user_profile->signin_state();
SHIM_SET_RETURN_64(signin_state);
// Notify we exist, just for fun.
state->BroadcastNotification(0x0000000A, signin_state ? 1 : 0);
} else { } else {
SHIM_SET_RETURN_64(0); SHIM_SET_RETURN_64(0);
// Notify no users.
state->BroadcastNotification(0x0000000A, 0);
} }
} }