diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 19c073c020..04c3c801fa 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -326,6 +326,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) // Trusting server for good map value (>=0 && <4) // add to pad buffer m_pad_buffer.at(map).Push(pad); + m_gc_pad_event.Set(); } break; @@ -344,6 +345,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) // Trusting server for good map value (>=0 && <4) // add to Wiimote buffer m_wiimote_buffer.at(map).Push(nw); + m_wii_pad_event.Set(); } break; @@ -996,15 +998,18 @@ bool NetPlayClient::GetNetPads(const u8 pad_nb, GCPadStatus* pad_status) // Now, we either use the data pushed earlier, or wait for the // other clients to send it to us - while (!m_pad_buffer[pad_nb].Pop(*pad_status)) + while (m_pad_buffer[pad_nb].Size() == 0) { if (!m_is_running.load()) + { return false; + } - // TODO: use a condition instead of sleeping - Common::SleepCurrentThread(1); + m_gc_pad_event.Wait(); } + m_pad_buffer[pad_nb].Pop(*pad_status); + if (Movie::IsRecordingInput()) { Movie::RecordInput(pad_status, pad_nb); @@ -1042,14 +1047,19 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size) } // unlock players - while (!m_wiimote_buffer[_number].Pop(nw)) + while (m_wiimote_buffer[_number].Size() == 0) { - // wait for receiving thread to push some data - Common::SleepCurrentThread(1); if (!m_is_running.load()) + { return false; + } + + // wait for receiving thread to push some data + m_wii_pad_event.Wait(); } + m_wiimote_buffer[_number].Pop(nw); + // If the reporting mode has changed, we just need to pop through the buffer, // until we reach a good input if (nw.size() != size) @@ -1057,12 +1067,19 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size) u32 tries = 0; while (nw.size() != size) { - while (!m_wiimote_buffer[_number].Pop(nw)) + while (m_wiimote_buffer[_number].Size() == 0) { - Common::SleepCurrentThread(1); if (!m_is_running.load()) + { return false; + } + + // wait for receiving thread to push some data + m_wii_pad_event.Wait(); } + + m_wiimote_buffer[_number].Pop(nw); + ++tries; if (tries > m_target_buffer_size * 200 / 120) break; @@ -1083,13 +1100,12 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size) // called from ---GUI--- thread and ---NETPLAY--- thread (client side) bool NetPlayClient::StopGame() { - if (!m_is_running.load()) - { - PanicAlertT("Game isn't running!"); - return false; - } - m_is_running.store(false); + + // stop waiting for input + m_gc_pad_event.Set(); + m_wii_pad_event.Set(); + NetPlay_Disable(); // stop game @@ -1104,6 +1120,12 @@ void NetPlayClient::Stop() if (!m_is_running.load()) return; + m_is_running.store(false); + + // stop waiting for input + m_gc_pad_event.Set(); + m_wii_pad_event.Set(); + // Tell the server to stop if we have a pad mapped in game. if (LocalPlayerHasControllerMapped()) SendStopGamePacket(); diff --git a/Source/Core/Core/NetPlayClient.h b/Source/Core/Core/NetPlayClient.h index 4eddc36adf..57d60c978c 100644 --- a/Source/Core/Core/NetPlayClient.h +++ b/Source/Core/Core/NetPlayClient.h @@ -14,6 +14,7 @@ #include #include #include "Common/CommonTypes.h" +#include "Common/Event.h" #include "Common/FifoQueue.h" #include "Common/TraversalClient.h" #include "Core/NetPlayProto.h" @@ -175,6 +176,8 @@ private: TraversalClient* m_traversal_client = nullptr; std::thread m_MD5_thread; bool m_should_compute_MD5 = false; + Common::Event m_gc_pad_event; + Common::Event m_wii_pad_event; u32 m_timebase_frame = 0; }; diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 0ea5685a17..b3689e9ab5 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -1132,10 +1132,17 @@ void CFrame::DoStop() // Pause the state during confirmation and restore it afterwards Core::EState state = Core::GetState(); + // Do not pause if netplay is running as CPU thread might be blocked + // waiting on inputs + bool should_pause = !NetPlayDialog::GetNetPlayClient(); + // If exclusive fullscreen is not enabled then we can pause the emulation // before we've exited fullscreen. If not then we need to exit fullscreen first. - if (!RendererIsFullscreen() || !g_Config.ExclusiveFullscreenEnabled() || - SConfig::GetInstance().bRenderToMain) + should_pause = + should_pause && (!RendererIsFullscreen() || !g_Config.ExclusiveFullscreenEnabled() || + SConfig::GetInstance().bRenderToMain); + + if (should_pause) { Core::SetState(Core::CORE_PAUSE); } @@ -1149,7 +1156,9 @@ void CFrame::DoStop() HotkeyManagerEmu::Enable(true); if (Ret != wxID_YES) { - Core::SetState(state); + if (should_pause) + Core::SetState(state); + m_confirmStop = false; return; }