From 3266394dfbb564f69e3cd6470ad608a4db314916 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 20 Jun 2014 02:43:57 +0200 Subject: [PATCH 1/6] Make the emulation stop asynchronous to prevent deadlocks. This may expose bugs which relied on the Main Thread to be suspended in the stopping state. --- Source/Core/Core/Core.cpp | 75 ++++++++++-------- Source/Core/Core/Core.h | 5 ++ Source/Core/DolphinWX/Frame.cpp | 15 ++++ Source/Core/DolphinWX/Frame.h | 2 + Source/Core/DolphinWX/FrameTools.cpp | 109 ++++++++++++++------------- Source/Core/DolphinWX/Globals.h | 1 + Source/Core/DolphinWX/Main.cpp | 2 + 7 files changed, 127 insertions(+), 82 deletions(-) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 3fffedb7fb..245b489663 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -83,6 +83,7 @@ bool g_bStarted = false; void *g_pWindowHandle = nullptr; std::string g_stateFileName; std::thread g_EmuThread; +static StoppedCallbackFunc s_onStoppedCb = nullptr; static std::thread g_cpu_thread; static bool g_requestRefreshInfo = false; @@ -155,7 +156,7 @@ bool IsRunning() bool IsRunningAndStarted() { - return g_bStarted; + return g_bStarted && !g_bStopping; } bool IsRunningInCurrentThread() @@ -191,8 +192,14 @@ bool Init() if (g_EmuThread.joinable()) { - PanicAlertT("Emu Thread already running"); - return false; + if (IsRunning()) + { + PanicAlertT("Emu Thread already running"); + return false; + } + + // The Emu Thread was stopped, synchronize with it. + g_EmuThread.join(); } g_CoreStartupParameter = _CoreParameter; @@ -226,12 +233,8 @@ bool Init() // Called from GUI thread void Stop() // - Hammertime! { - if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN) - { - if (g_EmuThread.joinable()) - g_EmuThread.join(); + if (GetState() == CORE_STOPPING) return; - } const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter; @@ -258,28 +261,6 @@ void Stop() // - Hammertime! g_video_backend->Video_ExitLoop(); } - - INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str()); - - g_EmuThread.join(); // Wait for emuthread to close. - - INFO_LOG(CONSOLE, "%s", StopMessage(true, "Main Emu thread stopped").c_str()); - - // Clear on screen messages that haven't expired - g_video_backend->Video_ClearMessages(); - - // Close the trace file - Core::StopTrace(); - - // Reload sysconf file in order to see changes committed during emulation - if (_CoreParameter.bWii) - SConfig::GetInstance().m_SYSCONF->Reload(); - - INFO_LOG(CONSOLE, "Stop [Main Thread]\t\t---- Shutdown complete ----"); - Movie::Shutdown(); - PatchEngine::Shutdown(); - - g_bStopping = false; } // Create the CPU thread, which is a CPU + Video thread in Single Core mode. @@ -478,6 +459,8 @@ void EmuThread() } } + INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str()); + // Wait for g_cpu_thread to exit INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str()); @@ -510,6 +493,27 @@ void EmuThread() Wiimote::Shutdown(); g_video_backend->Shutdown(); AudioCommon::ShutdownSoundStream(); + + INFO_LOG(CONSOLE, "%s", StopMessage(true, "Main Emu thread stopped").c_str()); + + // Clear on screen messages that haven't expired + g_video_backend->Video_ClearMessages(); + + // Close the trace file + Core::StopTrace(); + + // Reload sysconf file in order to see changes committed during emulation + if (_CoreParameter.bWii) + SConfig::GetInstance().m_SYSCONF->Reload(); + + INFO_LOG(CONSOLE, "Stop [Video Thread]\t\t---- Shutdown complete ----"); + Movie::Shutdown(); + PatchEngine::Shutdown(); + + g_bStopping = false; + + if (s_onStoppedCb) + s_onStoppedCb(); } // Set or get the running state @@ -740,4 +744,15 @@ void UpdateTitle() } } +void Shutdown() +{ + if (g_EmuThread.joinable()) + g_EmuThread.join(); +} + +void SetOnStoppedCallback(StoppedCallbackFunc callback) +{ + s_onStoppedCb = callback; +} + } // Core diff --git a/Source/Core/Core/Core.h b/Source/Core/Core/Core.h index 862160daf0..655c5f9301 100644 --- a/Source/Core/Core/Core.h +++ b/Source/Core/Core/Core.h @@ -39,6 +39,7 @@ enum EState bool Init(); void Stop(); +void Shutdown(); std::string StopMessage(bool, std::string); @@ -81,4 +82,8 @@ void UpdateTitle(); // the return value of the first call should be passed in as the second argument of the second call. bool PauseAndLock(bool doLock, bool unpauseOnUnlock=true); +// for calling back into UI code without introducing a dependency on it in core +typedef void(*StoppedCallbackFunc)(void); +void SetOnStoppedCallback(StoppedCallbackFunc callback); + } // namespace diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 5284eefd57..1807c5e53b 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -425,6 +425,7 @@ CFrame::CFrame(wxFrame* parent, Movie::SetInputManip(TASManipFunction); State::SetOnAfterLoadCallback(OnAfterLoadCallback); + Core::SetOnStoppedCallback(OnStoppedCallback); // Setup perspectives if (g_pCodeWindow) @@ -692,6 +693,10 @@ void CFrame::OnHostMessage(wxCommandEvent& event) case WM_USER_STOP: DoStop(); break; + + case IDM_STOPPED: + OnStopped(); + break; } } @@ -904,6 +909,16 @@ void OnAfterLoadCallback() } } +void OnStoppedCallback() +{ + // warning: this gets called from the EmuThread, so we should only queue things to do on the proper thread + if (main_frame) + { + wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_STOPPED); + main_frame->GetEventHandler()->AddPendingEvent(event); + } +} + void TASManipFunction(SPADStatus *PadStatus, int controllerID) { if (main_frame) diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index 32292c1cb4..e32b91f918 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -123,6 +123,7 @@ public: void InitBitmaps(); void DoPause(); void DoStop(); + void OnStopped(); void DoRecordingSave(); void UpdateGUI(); void UpdateGameList(); @@ -353,6 +354,7 @@ private: int GetCmdForHotkey(unsigned int key); void OnAfterLoadCallback(); +void OnStoppedCallback(); // For TASInputDlg void TASManipFunction(SPADStatus *PadStatus, int controllerID); diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 6548deb5f0..7c72aad691 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -1120,72 +1120,77 @@ void CFrame::DoStop() wxBeginBusyCursor(); BootManager::Stop(); - wxEndBusyCursor(); - confirmStop = false; + } +} + +void CFrame::OnStopped() +{ + wxEndBusyCursor(); + + confirmStop = false; #if defined(HAVE_X11) && HAVE_X11 if (SConfig::GetInstance().m_LocalCoreStartupParameter.bDisableScreenSaver) X11Utils::InhibitScreensaver(X11Utils::XDisplayFromHandle(GetHandle()), X11Utils::XWindowFromHandle(GetHandle()), false); #endif - m_RenderFrame->SetTitle(StrToWxStr(scm_rev_str)); + m_RenderFrame->SetTitle(StrToWxStr(scm_rev_str)); - // Destroy the renderer frame when not rendering to main - m_RenderParent->Unbind(wxEVT_SIZE, &CFrame::OnRenderParentResize, this); + // Destroy the renderer frame when not rendering to main + m_RenderParent->Unbind(wxEVT_SIZE, &CFrame::OnRenderParentResize, this); - // Keyboard - wxTheApp->Unbind(wxEVT_KEY_DOWN, &CFrame::OnKeyDown, this); - wxTheApp->Unbind(wxEVT_KEY_UP, &CFrame::OnKeyUp, this); + // Keyboard + wxTheApp->Unbind(wxEVT_KEY_DOWN, &CFrame::OnKeyDown, this); + wxTheApp->Unbind(wxEVT_KEY_UP, &CFrame::OnKeyUp, this); - // Mouse - wxTheApp->Unbind(wxEVT_RIGHT_DOWN, &CFrame::OnMouse, this); - wxTheApp->Unbind(wxEVT_RIGHT_UP, &CFrame::OnMouse, this); - wxTheApp->Unbind(wxEVT_MIDDLE_DOWN, &CFrame::OnMouse, this); - wxTheApp->Unbind(wxEVT_MIDDLE_UP, &CFrame::OnMouse, this); - wxTheApp->Unbind(wxEVT_MOTION, &CFrame::OnMouse, this); - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor) - m_RenderParent->SetCursor(wxNullCursor); - DoFullscreen(false); - if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain) - { - m_RenderFrame->Destroy(); - } - else - { + // Mouse + wxTheApp->Unbind(wxEVT_RIGHT_DOWN, &CFrame::OnMouse, this); + wxTheApp->Unbind(wxEVT_RIGHT_UP, &CFrame::OnMouse, this); + wxTheApp->Unbind(wxEVT_MIDDLE_DOWN, &CFrame::OnMouse, this); + wxTheApp->Unbind(wxEVT_MIDDLE_UP, &CFrame::OnMouse, this); + wxTheApp->Unbind(wxEVT_MOTION, &CFrame::OnMouse, this); + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor) + m_RenderParent->SetCursor(wxNullCursor); + DoFullscreen(false); + if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain) + { + m_RenderFrame->Destroy(); + } + else + { #if defined(__APPLE__) - // Disable the full screen button when not in a game. - NSView *view = (NSView *) m_RenderFrame->GetHandle(); - NSWindow *window = [view window]; + // Disable the full screen button when not in a game. + NSView *view = (NSView *)m_RenderFrame->GetHandle(); + NSWindow *window = [view window]; - [window setCollectionBehavior:NSWindowCollectionBehaviorDefault]; + [window setCollectionBehavior : NSWindowCollectionBehaviorDefault]; #endif - // Make sure the window is not longer set to stay on top - m_RenderFrame->SetWindowStyle(m_RenderFrame->GetWindowStyle() & ~wxSTAY_ON_TOP); - } - m_RenderParent = nullptr; - - // Clean framerate indications from the status bar. - GetStatusBar()->SetStatusText(" ", 0); - - // Clear wiimote connection status from the status bar. - GetStatusBar()->SetStatusText(" ", 1); - - // If batch mode was specified on the command-line, exit now. - if (m_bBatchMode) - Close(true); - - // If using auto size with render to main, reset the application size. - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain && - SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderWindowAutoSize) - SetSize(SConfig::GetInstance().m_LocalCoreStartupParameter.iWidth, - SConfig::GetInstance().m_LocalCoreStartupParameter.iHeight); - - m_GameListCtrl->Enable(); - m_GameListCtrl->Show(); - m_GameListCtrl->SetFocus(); - UpdateGUI(); + // Make sure the window is not longer set to stay on top + m_RenderFrame->SetWindowStyle(m_RenderFrame->GetWindowStyle() & ~wxSTAY_ON_TOP); } + m_RenderParent = nullptr; + + // Clean framerate indications from the status bar. + GetStatusBar()->SetStatusText(" ", 0); + + // Clear wiimote connection status from the status bar. + GetStatusBar()->SetStatusText(" ", 1); + + // If batch mode was specified on the command-line, exit now. + if (m_bBatchMode) + Close(true); + + // If using auto size with render to main, reset the application size. + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain && + SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderWindowAutoSize) + SetSize(SConfig::GetInstance().m_LocalCoreStartupParameter.iWidth, + SConfig::GetInstance().m_LocalCoreStartupParameter.iHeight); + + m_GameListCtrl->Enable(); + m_GameListCtrl->Show(); + m_GameListCtrl->SetFocus(); + UpdateGUI(); } void CFrame::DoRecordingSave() diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index d51ee2c135..401f4265ad 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -254,6 +254,7 @@ enum IDM_PANIC, IDM_KEYSTATE, IDM_WINDOWSIZEREQUEST, + IDM_STOPPED, IDM_HOST_MESSAGE, IDM_MPANEL, ID_STATUSBAR, diff --git a/Source/Core/DolphinWX/Main.cpp b/Source/Core/DolphinWX/Main.cpp index 3643d6e5ec..0559e9b7bf 100644 --- a/Source/Core/DolphinWX/Main.cpp +++ b/Source/Core/DolphinWX/Main.cpp @@ -37,6 +37,7 @@ #include "Common/Logging/LogManager.h" #include "Core/ConfigManager.h" +#include "Core/Core.h" #include "Core/CoreParameter.h" #include "Core/Movie.h" #include "Core/HW/Wiimote.h" @@ -455,6 +456,7 @@ int DolphinApp::OnExit() VideoBackend::ClearList(); SConfig::Shutdown(); LogManager::Shutdown(); + Core::Shutdown(); delete m_locale; From b30d5dccbe46c4bf9977a1437a826d082abebee0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 20 Jun 2014 03:03:00 +0200 Subject: [PATCH 2/6] Frame: OnClose now handles asynchronous behaviour of DoStop(). --- Source/Core/DolphinWX/Frame.cpp | 13 ++++++++----- Source/Core/DolphinWX/Frame.h | 1 + Source/Core/DolphinWX/FrameTools.cpp | 17 ++++++++++++----- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 1807c5e53b..38b8ae7df0 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -352,7 +352,7 @@ CFrame::CFrame(wxFrame* parent, , m_LogWindow(nullptr), m_LogConfigWindow(nullptr) , m_FifoPlayerDlg(nullptr), UseDebugger(_UseDebugger) , m_bBatchMode(_BatchMode), m_bEdit(false), m_bTabSplit(false), m_bNoDocking(false) - , m_bGameLoading(false) + , m_bGameLoading(false), m_bClosing(false) { for (int i = 0; i <= IDM_CODEWINDOW - IDM_LOGWINDOW; i++) bFloatWindow[i] = false; @@ -536,15 +536,18 @@ void CFrame::OnActive(wxActivateEvent& event) void CFrame::OnClose(wxCloseEvent& event) { + m_bClosing = true; + + // Before closing the window we need to shut down the emulation core. + // We'll try to close this window again once that is done. if (Core::GetState() != Core::CORE_UNINITIALIZED) { DoStop(); - if (Core::GetState() != Core::CORE_UNINITIALIZED) - return; - UpdateGUI(); + event.Veto(); + return; } - //Stop Dolphin from saving the minimized Xpos and Ypos + // Stop Dolphin from saving the minimized Xpos and Ypos if (main_frame->IsIconized()) main_frame->Iconize(false); diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index e32b91f918..27f88690c9 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -186,6 +186,7 @@ private: bool m_bTabSplit; bool m_bNoDocking; bool m_bGameLoading; + bool m_bClosing; std::vector drives; diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 7c72aad691..6fb0f0106a 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -832,9 +832,16 @@ void CFrame::OnPlay(wxCommandEvent& WXUNUSED (event)) void CFrame::OnRenderParentClose(wxCloseEvent& event) { - DoStop(); - if (Core::GetState() == Core::CORE_UNINITIALIZED) - event.Skip(); + // Before closing the window we need to shut down the emulation core. + // We'll try to close this window again once that is done. + if (Core::GetState() != Core::CORE_UNINITIALIZED) + { + DoStop(); + event.Veto(); + return; + } + + event.Skip(); } void CFrame::OnRenderParentMove(wxMoveEvent& event) @@ -1177,8 +1184,8 @@ void CFrame::OnStopped() // Clear wiimote connection status from the status bar. GetStatusBar()->SetStatusText(" ", 1); - // If batch mode was specified on the command-line, exit now. - if (m_bBatchMode) + // If batch mode was specified on the command-line or we were already closing, exit now. + if (m_bBatchMode || m_bClosing) Close(true); // If using auto size with render to main, reset the application size. From 49eade69a3938b75c2ace7848161d30c845e940c Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 20 Jun 2014 03:26:06 +0200 Subject: [PATCH 3/6] Core: Return CORE_STOPPING even if hardware is already uninitialized. --- Source/Core/Core/Core.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 245b489663..b5be916b1e 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -538,15 +538,17 @@ void SetState(EState _State) EState GetState() { + if (g_bStopping) + return CORE_STOPPING; + if (g_bHwInit) { if (CCPU::IsStepping()) return CORE_PAUSE; - else if (g_bStopping) - return CORE_STOPPING; else return CORE_RUN; } + return CORE_UNINITIALIZED; } From ad1b61af2e5d5b4c63c6d7ed052775e1c2858c39 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 28 Jun 2014 18:56:53 +0200 Subject: [PATCH 4/6] FrameTools: Update GUI and disable Play button when in stopping state. --- Source/Core/DolphinWX/FrameTools.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 6fb0f0106a..66a5aa6858 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -1127,6 +1127,7 @@ void CFrame::DoStop() wxBeginBusyCursor(); BootManager::Stop(); + UpdateGUI(); } } @@ -1638,6 +1639,7 @@ void CFrame::UpdateGUI() bool Initialized = Core::IsRunning(); bool Running = Core::GetState() == Core::CORE_RUN; bool Paused = Core::GetState() == Core::CORE_PAUSE; + bool Stopping = Core::GetState() == Core::CORE_STOPPING; bool RunningWii = Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii; bool RunningGamecube = Initialized && !SConfig::GetInstance().m_LocalCoreStartupParameter.bWii; @@ -1784,8 +1786,8 @@ void CFrame::UpdateGUI() { // Game has been loaded, enable the pause button if (m_ToolBar) - m_ToolBar->EnableTool(IDM_PLAY, true); - GetMenuBar()->FindItem(IDM_PLAY)->Enable(true); + m_ToolBar->EnableTool(IDM_PLAY, !Stopping); + GetMenuBar()->FindItem(IDM_PLAY)->Enable(!Stopping); // Reset game loading flag m_bGameLoading = false; From db7e746cb423de5ca47be7a3df7c4918a610ff5a Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 8 Jul 2014 00:47:57 +0200 Subject: [PATCH 5/6] Check whether the core is running instead of checking if it is unitialized. This properly handles the stopping state and more accurately represents the intended check. --- Source/Core/Core/Debugger/Debugger_SymbolMap.cpp | 3 +-- Source/Core/Core/Movie.cpp | 2 +- Source/Core/Core/State.cpp | 2 +- Source/Core/DolphinWX/ConfigMain.cpp | 12 ++++++------ .../Core/DolphinWX/Debugger/CodeWindowFunctions.cpp | 2 +- Source/Core/DolphinWX/Frame.cpp | 7 +++---- Source/Core/DolphinWX/FrameTools.cpp | 4 ++-- Source/Core/DolphinWX/MainNoGUI.cpp | 2 +- Source/Core/DolphinWX/VideoConfigDiag.cpp | 9 ++++----- Source/Core/DolphinWX/VideoConfigDiag.h | 2 +- 10 files changed, 21 insertions(+), 24 deletions(-) diff --git a/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp b/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp index 112c4c310b..b0dab163a5 100644 --- a/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp +++ b/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp @@ -69,8 +69,7 @@ void WalkTheStack(const std::function& stack_step) // instead of "pointing ahead" bool GetCallstack(std::vector &output) { - if (Core::GetState() == Core::CORE_UNINITIALIZED || - !Memory::IsRAMAddress(PowerPC::ppcState.gpr[1])) + if (!Core::IsRunning() || !Memory::IsRAMAddress(PowerPC::ppcState.gpr[1])) return false; if (LR == 0) diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index c90b0e2512..538248c909 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -382,7 +382,7 @@ bool IsNetPlayRecording() void ChangePads(bool instantly) { - if (Core::GetState() == Core::CORE_UNINITIALIZED) + if (!Core::IsRunning()) return; int controllers = 0; diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 55cd1a2fa7..a4619ad752 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -424,7 +424,7 @@ void LoadFileStateData(const std::string& filename, std::vector& ret_data) void LoadAs(const std::string& filename) { - if (Core::GetState() == Core::CORE_UNINITIALIZED) + if (!Core::IsRunning()) return; // Stop the core while we load the state diff --git a/Source/Core/DolphinWX/ConfigMain.cpp b/Source/Core/DolphinWX/ConfigMain.cpp index c74400a73f..9208b70b08 100644 --- a/Source/Core/DolphinWX/ConfigMain.cpp +++ b/Source/Core/DolphinWX/ConfigMain.cpp @@ -230,7 +230,7 @@ void CConfigMain::SetSelectedTab(int tab) // Used to restrict changing of some options while emulator is running void CConfigMain::UpdateGUI() { - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) { // Disable the Core stuff on GeneralPage CPUThread->Disable(); @@ -669,7 +669,7 @@ void CConfigMain::CreateGUIControls() Latency->Bind(wxEVT_SPINCTRL, &CConfigMain::AudioSettingsChanged, this); - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) { Latency->Disable(); BackendSelection->Disable(); @@ -888,7 +888,7 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event) { // Core - Basic case ID_CPUTHREAD: - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) return; SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread = CPUThread->IsChecked(); break; @@ -1099,7 +1099,7 @@ void CConfigMain::ChooseMemcardPath(std::string& strMemcard, bool isSlotA) { strMemcard = filename; - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) { // Change memcard to the new file ExpansionInterface::ChangeDevice( @@ -1136,7 +1136,7 @@ void CConfigMain::ChooseSIDevice(wxString deviceName, int deviceNum) SConfig::GetInstance().m_SIDevice[deviceNum] = tempType; - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) { // Change plugged device! :D SerialInterface::ChangeDevice(tempType, deviceNum); @@ -1172,7 +1172,7 @@ void CConfigMain::ChooseEXIDevice(wxString deviceName, int deviceNum) SConfig::GetInstance().m_EXIDevice[deviceNum] = tempType; - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) { // Change plugged device! :D ExpansionInterface::ChangeDevice( diff --git a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp index 41abb27300..9f3c081c16 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp @@ -219,7 +219,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) { Parent->ClearStatusBar(); - if (Core::GetState() == Core::CORE_UNINITIALIZED) return; + if (!Core::IsRunning()) return; std::string existing_map_file, writable_map_file; bool map_exists = CBoot::FindMapFile(&existing_map_file, diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 38b8ae7df0..03cc67250d 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -217,7 +217,7 @@ WXLRESULT CRenderFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPa case WM_CLOSE: // Let Core finish initializing before accepting any WM_CLOSE messages - if (Core::GetState() == Core::CORE_UNINITIALIZED) break; + if (!Core::IsRunning()) break; // Use default action otherwise default: @@ -722,7 +722,7 @@ void CFrame::GetRenderWindowSize(int& x, int& y, int& width, int& height) void CFrame::OnRenderWindowSizeRequest(int width, int height) { - if (Core::GetState() == Core::CORE_UNINITIALIZED || + if (!Core::IsRunning() || !SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderWindowAutoSize || RendererIsFullscreen() || m_RenderFrame->IsMaximized()) return; @@ -1109,8 +1109,7 @@ void CFrame::OnKeyDown(wxKeyEvent& event) void CFrame::OnKeyUp(wxKeyEvent& event) { - if(Core::GetState() != Core::CORE_UNINITIALIZED && - (RendererHasFocus() || TASInputHasFocus())) + if(Core::IsRunning() && (RendererHasFocus() || TASInputHasFocus())) { if (IsHotkey(event, HK_TOGGLE_THROTTLE)) { diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 66a5aa6858..7cd29d7ef5 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -802,7 +802,7 @@ void CFrame::OnRecordExport(wxCommandEvent& WXUNUSED (event)) void CFrame::OnPlay(wxCommandEvent& WXUNUSED (event)) { - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) { // Core is initialized and emulator is running if (UseDebugger) @@ -1581,7 +1581,7 @@ void CFrame::OnLoadLastState(wxCommandEvent& event) void CFrame::OnSaveFirstState(wxCommandEvent& WXUNUSED(event)) { - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunningAndStarted()) State::SaveFirstSaved(); } diff --git a/Source/Core/DolphinWX/MainNoGUI.cpp b/Source/Core/DolphinWX/MainNoGUI.cpp index d4b75d83cb..0345e20b2b 100644 --- a/Source/Core/DolphinWX/MainNoGUI.cpp +++ b/Source/Core/DolphinWX/MainNoGUI.cpp @@ -131,7 +131,7 @@ void Host_SetWiiMoteConnectionState(int _State) {} void X11_MainLoop() { bool fullscreen = SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen; - while (Core::GetState() == Core::CORE_UNINITIALIZED) + while (!Core::IsRunning()) updateMainFrameEvent.Wait(); Display *dpy = XOpenDisplay(0); diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 26d8b6c76e..2d70863452 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -246,7 +246,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con szr_basic->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5); szr_basic->Add(choice_backend, 1, 0, 0); - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) { label_backend->Disable(); choice_backend->Disable(); @@ -291,7 +291,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con szr_display->Add(label_display_resolution, 1, wxALIGN_CENTER_VERTICAL, 0); szr_display->Add(choice_display_resolution); - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) { label_display_resolution->Disable(); choice_display_resolution->Disable(); @@ -328,9 +328,8 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con szr_other->Add(CreateCheckBox(page_general, _("Hide Mouse Cursor"), wxGetTranslation(hide_mouse_cursor_desc), SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor)); szr_other->Add(render_to_main_cb = CreateCheckBox(page_general, _("Render to Main Window"), wxGetTranslation(render_to_main_win_desc), SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)); - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) render_to_main_cb->Disable(); - } @@ -576,7 +575,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con wxCheckBox* const cb_prog_scan = new wxCheckBox(page_advanced, wxID_ANY, _("Enable Progressive Scan")); RegisterControl(cb_prog_scan, wxGetTranslation(prog_scan_desc)); cb_prog_scan->Bind(wxEVT_CHECKBOX, &VideoConfigDiag::Event_ProgressiveScan, this); - if (Core::GetState() != Core::CORE_UNINITIALIZED) + if (Core::IsRunning()) cb_prog_scan->Disable(); cb_prog_scan->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bProgressive); diff --git a/Source/Core/DolphinWX/VideoConfigDiag.h b/Source/Core/DolphinWX/VideoConfigDiag.h index 695a01ee7a..c17506351b 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.h +++ b/Source/Core/DolphinWX/VideoConfigDiag.h @@ -86,7 +86,7 @@ protected: VideoBackend* new_backend = g_available_video_backends[ev.GetInt()]; if (g_video_backend != new_backend) { - bool do_switch = Core::GetState() == Core::CORE_UNINITIALIZED; + bool do_switch = !Core::IsRunning(); if (new_backend->GetName() == "Software Renderer") { do_switch = (wxYES == wxMessageBox(_("Software rendering is an order of magnitude slower than using the other backends.\nIt's only useful for debugging purposes.\nDo you really want to enable software rendering? If unsure, select 'No'."), From 4df00ae5441aefe8a13548152036f91dd3e4dda0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 8 Jul 2014 22:32:35 +0200 Subject: [PATCH 6/6] Movie: Do not attempt to record input when the emulation has not started yet. Fixes a null pointer exception when the user starts the recording during a state transition. --- Source/Core/Core/Movie.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index 538248c909..e14f6068da 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -444,7 +444,7 @@ bool BeginRecordingInput(int controllers) if (SConfig::GetInstance().m_SIDevice[i] == SIDEVICE_GC_TARUKONGA) bongos |= (1 << i); - if (Core::IsRunning()) + if (Core::IsRunningAndStarted()) { if (File::Exists(tmpStateFilename)) File::Delete(tmpStateFilename);