diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp index 50c523ce1d..d344c680a3 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -75,25 +75,35 @@ void pad_info::save(utils::serial& ar) extern void send_sys_io_connect_event(usz index, u32 state); -void cellPad_NotifyStateChange(usz index, u64 /*state*/, bool locked) +bool cellPad_NotifyStateChange(usz index, u64 /*state*/, bool locked, bool is_blocking = true) { auto info = g_fxo->try_get(); if (!info) { - return; + return true; } std::unique_lock lock(pad::g_pad_mutex, std::defer_lock); if (locked) { - lock.lock(); + if (is_blocking) + { + lock.lock(); + } + else + { + if (!lock.try_lock()) + { + return false; + } + } } if (index >= info->get_max_connect()) { - return; + return true; } const auto handler = pad::get_current_handler(); @@ -102,7 +112,7 @@ void cellPad_NotifyStateChange(usz index, u64 /*state*/, bool locked) if (pad->is_fake_pad) { - return; + return true; } pad_data_internal& reported_info = info->reported_info[index]; @@ -117,7 +127,7 @@ void cellPad_NotifyStateChange(usz index, u64 /*state*/, bool locked) if (~(old_status ^ new_status) & CELL_PAD_STATUS_CONNECTED) { // old and new have the same connection status - return; + return true; } reported_info.port_status = new_status | CELL_PAD_STATUS_ASSIGN_CHANGES; @@ -139,6 +149,8 @@ void cellPad_NotifyStateChange(usz index, u64 /*state*/, bool locked) reported_info.vendor_id = pad->m_vendor_id; reported_info.product_id = pad->m_product_id; } + + return true; } extern void pad_state_notify_state_change(usz index, u32 state) diff --git a/rpcs3/Emu/Cell/Modules/sys_io_.cpp b/rpcs3/Emu/Cell/Modules/sys_io_.cpp index d44401db79..e0505f4c41 100644 --- a/rpcs3/Emu/Cell/Modules/sys_io_.cpp +++ b/rpcs3/Emu/Cell/Modules/sys_io_.cpp @@ -36,10 +36,12 @@ extern void sys_io_serialize(utils::serial& ar) ensure(g_fxo->try_get())->save_or_load(ar); } -extern void cellPad_NotifyStateChange(usz index, u64 state, bool lock = true); +extern bool cellPad_NotifyStateChange(usz index, u64 state, bool lock = true, bool is_blocking = true); void config_event_entry(ppu_thread& ppu) { + ppu.state += cpu_flag::wait; + auto& cfg = *ensure(g_fxo->try_get()); if (!ppu.loaded_from_savestate) @@ -48,7 +50,10 @@ void config_event_entry(ppu_thread& ppu) ppu.check_state(); } - while (!sys_event_queue_receive(ppu, cfg.queue_id, vm::null, 0)) + const u32 queue_id = cfg.queue_id; + auto queue = idm::get(queue_id); + + while (queue && sys_event_queue_receive(ppu, queue_id, vm::null, 0) == CELL_OK) { if (ppu.is_stopped()) { @@ -61,6 +66,7 @@ void config_event_entry(ppu_thread& ppu) // Wakeup ppu.check_state(); + ppu.state += cpu_flag::wait; const u64 arg1 = ppu.gpr[5]; const u64 arg2 = ppu.gpr[6]; @@ -70,7 +76,17 @@ void config_event_entry(ppu_thread& ppu) if (arg1 == 1) { - cellPad_NotifyStateChange(arg2, arg3); + while (!cellPad_NotifyStateChange(arg2, arg3, false)) + { + if (!queue->exists) + { + // Exit condition + queue = nullptr; + break; + } + + thread_ctrl::wait_for(100); + } } }