Merge pull request #515 from Armada651/threading

Make the emulation stop asynchronous to prevent deadlocks.
This commit is contained in:
Dolphin Bot 2014-07-10 21:02:47 +02:00
commit bc655d1a82
15 changed files with 176 additions and 119 deletions

View File

@ -83,6 +83,7 @@ bool g_bStarted = false;
void *g_pWindowHandle = nullptr; void *g_pWindowHandle = nullptr;
std::string g_stateFileName; std::string g_stateFileName;
std::thread g_EmuThread; std::thread g_EmuThread;
static StoppedCallbackFunc s_onStoppedCb = nullptr;
static std::thread g_cpu_thread; static std::thread g_cpu_thread;
static bool g_requestRefreshInfo = false; static bool g_requestRefreshInfo = false;
@ -155,7 +156,7 @@ bool IsRunning()
bool IsRunningAndStarted() bool IsRunningAndStarted()
{ {
return g_bStarted; return g_bStarted && !g_bStopping;
} }
bool IsRunningInCurrentThread() bool IsRunningInCurrentThread()
@ -191,8 +192,14 @@ bool Init()
if (g_EmuThread.joinable()) if (g_EmuThread.joinable())
{ {
PanicAlertT("Emu Thread already running"); if (IsRunning())
return false; {
PanicAlertT("Emu Thread already running");
return false;
}
// The Emu Thread was stopped, synchronize with it.
g_EmuThread.join();
} }
g_CoreStartupParameter = _CoreParameter; g_CoreStartupParameter = _CoreParameter;
@ -226,12 +233,8 @@ bool Init()
// Called from GUI thread // Called from GUI thread
void Stop() // - Hammertime! void Stop() // - Hammertime!
{ {
if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN) if (GetState() == CORE_STOPPING)
{
if (g_EmuThread.joinable())
g_EmuThread.join();
return; return;
}
const SCoreStartupParameter& _CoreParameter = const SCoreStartupParameter& _CoreParameter =
SConfig::GetInstance().m_LocalCoreStartupParameter; SConfig::GetInstance().m_LocalCoreStartupParameter;
@ -258,28 +261,6 @@ void Stop() // - Hammertime!
g_video_backend->Video_ExitLoop(); 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. // 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 // Wait for g_cpu_thread to exit
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str()); INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str());
@ -510,6 +493,27 @@ void EmuThread()
Wiimote::Shutdown(); Wiimote::Shutdown();
g_video_backend->Shutdown(); g_video_backend->Shutdown();
AudioCommon::ShutdownSoundStream(); 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 // Set or get the running state
@ -534,15 +538,17 @@ void SetState(EState _State)
EState GetState() EState GetState()
{ {
if (g_bStopping)
return CORE_STOPPING;
if (g_bHwInit) if (g_bHwInit)
{ {
if (CCPU::IsStepping()) if (CCPU::IsStepping())
return CORE_PAUSE; return CORE_PAUSE;
else if (g_bStopping)
return CORE_STOPPING;
else else
return CORE_RUN; return CORE_RUN;
} }
return CORE_UNINITIALIZED; return CORE_UNINITIALIZED;
} }
@ -740,4 +746,15 @@ void UpdateTitle()
} }
} }
void Shutdown()
{
if (g_EmuThread.joinable())
g_EmuThread.join();
}
void SetOnStoppedCallback(StoppedCallbackFunc callback)
{
s_onStoppedCb = callback;
}
} // Core } // Core

View File

@ -39,6 +39,7 @@ enum EState
bool Init(); bool Init();
void Stop(); void Stop();
void Shutdown();
std::string StopMessage(bool, std::string); 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. // 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); 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 } // namespace

View File

@ -69,8 +69,7 @@ void WalkTheStack(const std::function<void(u32)>& stack_step)
// instead of "pointing ahead" // instead of "pointing ahead"
bool GetCallstack(std::vector<CallstackEntry> &output) bool GetCallstack(std::vector<CallstackEntry> &output)
{ {
if (Core::GetState() == Core::CORE_UNINITIALIZED || if (!Core::IsRunning() || !Memory::IsRAMAddress(PowerPC::ppcState.gpr[1]))
!Memory::IsRAMAddress(PowerPC::ppcState.gpr[1]))
return false; return false;
if (LR == 0) if (LR == 0)

View File

@ -382,7 +382,7 @@ bool IsNetPlayRecording()
void ChangePads(bool instantly) void ChangePads(bool instantly)
{ {
if (Core::GetState() == Core::CORE_UNINITIALIZED) if (!Core::IsRunning())
return; return;
int controllers = 0; int controllers = 0;
@ -444,7 +444,7 @@ bool BeginRecordingInput(int controllers)
if (SConfig::GetInstance().m_SIDevice[i] == SIDEVICE_GC_TARUKONGA) if (SConfig::GetInstance().m_SIDevice[i] == SIDEVICE_GC_TARUKONGA)
bongos |= (1 << i); bongos |= (1 << i);
if (Core::IsRunning()) if (Core::IsRunningAndStarted())
{ {
if (File::Exists(tmpStateFilename)) if (File::Exists(tmpStateFilename))
File::Delete(tmpStateFilename); File::Delete(tmpStateFilename);

View File

@ -424,7 +424,7 @@ void LoadFileStateData(const std::string& filename, std::vector<u8>& ret_data)
void LoadAs(const std::string& filename) void LoadAs(const std::string& filename)
{ {
if (Core::GetState() == Core::CORE_UNINITIALIZED) if (!Core::IsRunning())
return; return;
// Stop the core while we load the state // Stop the core while we load the state

View File

@ -230,7 +230,7 @@ void CConfigMain::SetSelectedTab(int tab)
// Used to restrict changing of some options while emulator is running // Used to restrict changing of some options while emulator is running
void CConfigMain::UpdateGUI() void CConfigMain::UpdateGUI()
{ {
if (Core::GetState() != Core::CORE_UNINITIALIZED) if (Core::IsRunning())
{ {
// Disable the Core stuff on GeneralPage // Disable the Core stuff on GeneralPage
CPUThread->Disable(); CPUThread->Disable();
@ -669,7 +669,7 @@ void CConfigMain::CreateGUIControls()
Latency->Bind(wxEVT_SPINCTRL, &CConfigMain::AudioSettingsChanged, this); Latency->Bind(wxEVT_SPINCTRL, &CConfigMain::AudioSettingsChanged, this);
if (Core::GetState() != Core::CORE_UNINITIALIZED) if (Core::IsRunning())
{ {
Latency->Disable(); Latency->Disable();
BackendSelection->Disable(); BackendSelection->Disable();
@ -888,7 +888,7 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event)
{ {
// Core - Basic // Core - Basic
case ID_CPUTHREAD: case ID_CPUTHREAD:
if (Core::GetState() != Core::CORE_UNINITIALIZED) if (Core::IsRunning())
return; return;
SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread = CPUThread->IsChecked(); SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread = CPUThread->IsChecked();
break; break;
@ -1099,7 +1099,7 @@ void CConfigMain::ChooseMemcardPath(std::string& strMemcard, bool isSlotA)
{ {
strMemcard = filename; strMemcard = filename;
if (Core::GetState() != Core::CORE_UNINITIALIZED) if (Core::IsRunning())
{ {
// Change memcard to the new file // Change memcard to the new file
ExpansionInterface::ChangeDevice( ExpansionInterface::ChangeDevice(
@ -1136,7 +1136,7 @@ void CConfigMain::ChooseSIDevice(wxString deviceName, int deviceNum)
SConfig::GetInstance().m_SIDevice[deviceNum] = tempType; SConfig::GetInstance().m_SIDevice[deviceNum] = tempType;
if (Core::GetState() != Core::CORE_UNINITIALIZED) if (Core::IsRunning())
{ {
// Change plugged device! :D // Change plugged device! :D
SerialInterface::ChangeDevice(tempType, deviceNum); SerialInterface::ChangeDevice(tempType, deviceNum);
@ -1172,7 +1172,7 @@ void CConfigMain::ChooseEXIDevice(wxString deviceName, int deviceNum)
SConfig::GetInstance().m_EXIDevice[deviceNum] = tempType; SConfig::GetInstance().m_EXIDevice[deviceNum] = tempType;
if (Core::GetState() != Core::CORE_UNINITIALIZED) if (Core::IsRunning())
{ {
// Change plugged device! :D // Change plugged device! :D
ExpansionInterface::ChangeDevice( ExpansionInterface::ChangeDevice(

View File

@ -219,7 +219,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
{ {
Parent->ClearStatusBar(); Parent->ClearStatusBar();
if (Core::GetState() == Core::CORE_UNINITIALIZED) return; if (!Core::IsRunning()) return;
std::string existing_map_file, writable_map_file; std::string existing_map_file, writable_map_file;
bool map_exists = CBoot::FindMapFile(&existing_map_file, bool map_exists = CBoot::FindMapFile(&existing_map_file,

View File

@ -217,7 +217,7 @@ WXLRESULT CRenderFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPa
case WM_CLOSE: case WM_CLOSE:
// Let Core finish initializing before accepting any WM_CLOSE messages // 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 // Use default action otherwise
default: default:
@ -352,7 +352,7 @@ CFrame::CFrame(wxFrame* parent,
, m_LogWindow(nullptr), m_LogConfigWindow(nullptr) , m_LogWindow(nullptr), m_LogConfigWindow(nullptr)
, m_FifoPlayerDlg(nullptr), UseDebugger(_UseDebugger) , m_FifoPlayerDlg(nullptr), UseDebugger(_UseDebugger)
, m_bBatchMode(_BatchMode), m_bEdit(false), m_bTabSplit(false), m_bNoDocking(false) , 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++) for (int i = 0; i <= IDM_CODEWINDOW - IDM_LOGWINDOW; i++)
bFloatWindow[i] = false; bFloatWindow[i] = false;
@ -425,6 +425,7 @@ CFrame::CFrame(wxFrame* parent,
Movie::SetInputManip(TASManipFunction); Movie::SetInputManip(TASManipFunction);
State::SetOnAfterLoadCallback(OnAfterLoadCallback); State::SetOnAfterLoadCallback(OnAfterLoadCallback);
Core::SetOnStoppedCallback(OnStoppedCallback);
// Setup perspectives // Setup perspectives
if (g_pCodeWindow) if (g_pCodeWindow)
@ -535,15 +536,18 @@ void CFrame::OnActive(wxActivateEvent& event)
void CFrame::OnClose(wxCloseEvent& 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) if (Core::GetState() != Core::CORE_UNINITIALIZED)
{ {
DoStop(); DoStop();
if (Core::GetState() != Core::CORE_UNINITIALIZED) event.Veto();
return; return;
UpdateGUI();
} }
//Stop Dolphin from saving the minimized Xpos and Ypos // Stop Dolphin from saving the minimized Xpos and Ypos
if (main_frame->IsIconized()) if (main_frame->IsIconized())
main_frame->Iconize(false); main_frame->Iconize(false);
@ -692,6 +696,10 @@ void CFrame::OnHostMessage(wxCommandEvent& event)
case WM_USER_STOP: case WM_USER_STOP:
DoStop(); DoStop();
break; break;
case IDM_STOPPED:
OnStopped();
break;
} }
} }
@ -714,7 +722,7 @@ void CFrame::GetRenderWindowSize(int& x, int& y, int& width, int& height)
void CFrame::OnRenderWindowSizeRequest(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 || !SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderWindowAutoSize ||
RendererIsFullscreen() || m_RenderFrame->IsMaximized()) RendererIsFullscreen() || m_RenderFrame->IsMaximized())
return; return;
@ -904,6 +912,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) void TASManipFunction(SPADStatus *PadStatus, int controllerID)
{ {
if (main_frame) if (main_frame)
@ -1091,8 +1109,7 @@ void CFrame::OnKeyDown(wxKeyEvent& event)
void CFrame::OnKeyUp(wxKeyEvent& event) void CFrame::OnKeyUp(wxKeyEvent& event)
{ {
if(Core::GetState() != Core::CORE_UNINITIALIZED && if(Core::IsRunning() && (RendererHasFocus() || TASInputHasFocus()))
(RendererHasFocus() || TASInputHasFocus()))
{ {
if (IsHotkey(event, HK_TOGGLE_THROTTLE)) if (IsHotkey(event, HK_TOGGLE_THROTTLE))
{ {

View File

@ -123,6 +123,7 @@ public:
void InitBitmaps(); void InitBitmaps();
void DoPause(); void DoPause();
void DoStop(); void DoStop();
void OnStopped();
void DoRecordingSave(); void DoRecordingSave();
void UpdateGUI(); void UpdateGUI();
void UpdateGameList(); void UpdateGameList();
@ -185,6 +186,7 @@ private:
bool m_bTabSplit; bool m_bTabSplit;
bool m_bNoDocking; bool m_bNoDocking;
bool m_bGameLoading; bool m_bGameLoading;
bool m_bClosing;
std::vector<std::string> drives; std::vector<std::string> drives;
@ -353,6 +355,7 @@ private:
int GetCmdForHotkey(unsigned int key); int GetCmdForHotkey(unsigned int key);
void OnAfterLoadCallback(); void OnAfterLoadCallback();
void OnStoppedCallback();
// For TASInputDlg // For TASInputDlg
void TASManipFunction(SPADStatus *PadStatus, int controllerID); void TASManipFunction(SPADStatus *PadStatus, int controllerID);

View File

@ -802,7 +802,7 @@ void CFrame::OnRecordExport(wxCommandEvent& WXUNUSED (event))
void CFrame::OnPlay(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 // Core is initialized and emulator is running
if (UseDebugger) if (UseDebugger)
@ -832,9 +832,16 @@ void CFrame::OnPlay(wxCommandEvent& WXUNUSED (event))
void CFrame::OnRenderParentClose(wxCloseEvent& event) void CFrame::OnRenderParentClose(wxCloseEvent& event)
{ {
DoStop(); // Before closing the window we need to shut down the emulation core.
if (Core::GetState() == Core::CORE_UNINITIALIZED) // We'll try to close this window again once that is done.
event.Skip(); if (Core::GetState() != Core::CORE_UNINITIALIZED)
{
DoStop();
event.Veto();
return;
}
event.Skip();
} }
void CFrame::OnRenderParentMove(wxMoveEvent& event) void CFrame::OnRenderParentMove(wxMoveEvent& event)
@ -1120,72 +1127,78 @@ void CFrame::DoStop()
wxBeginBusyCursor(); wxBeginBusyCursor();
BootManager::Stop(); BootManager::Stop();
wxEndBusyCursor(); UpdateGUI();
confirmStop = false; }
}
void CFrame::OnStopped()
{
wxEndBusyCursor();
confirmStop = false;
#if defined(HAVE_X11) && HAVE_X11 #if defined(HAVE_X11) && HAVE_X11
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bDisableScreenSaver) if (SConfig::GetInstance().m_LocalCoreStartupParameter.bDisableScreenSaver)
X11Utils::InhibitScreensaver(X11Utils::XDisplayFromHandle(GetHandle()), X11Utils::InhibitScreensaver(X11Utils::XDisplayFromHandle(GetHandle()),
X11Utils::XWindowFromHandle(GetHandle()), false); X11Utils::XWindowFromHandle(GetHandle()), false);
#endif #endif
m_RenderFrame->SetTitle(StrToWxStr(scm_rev_str)); m_RenderFrame->SetTitle(StrToWxStr(scm_rev_str));
// Destroy the renderer frame when not rendering to main // Destroy the renderer frame when not rendering to main
m_RenderParent->Unbind(wxEVT_SIZE, &CFrame::OnRenderParentResize, this); m_RenderParent->Unbind(wxEVT_SIZE, &CFrame::OnRenderParentResize, this);
// Keyboard // Keyboard
wxTheApp->Unbind(wxEVT_KEY_DOWN, &CFrame::OnKeyDown, this); wxTheApp->Unbind(wxEVT_KEY_DOWN, &CFrame::OnKeyDown, this);
wxTheApp->Unbind(wxEVT_KEY_UP, &CFrame::OnKeyUp, this); wxTheApp->Unbind(wxEVT_KEY_UP, &CFrame::OnKeyUp, this);
// Mouse // Mouse
wxTheApp->Unbind(wxEVT_RIGHT_DOWN, &CFrame::OnMouse, this); wxTheApp->Unbind(wxEVT_RIGHT_DOWN, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_RIGHT_UP, &CFrame::OnMouse, this); wxTheApp->Unbind(wxEVT_RIGHT_UP, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_MIDDLE_DOWN, &CFrame::OnMouse, this); wxTheApp->Unbind(wxEVT_MIDDLE_DOWN, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_MIDDLE_UP, &CFrame::OnMouse, this); wxTheApp->Unbind(wxEVT_MIDDLE_UP, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_MOTION, &CFrame::OnMouse, this); wxTheApp->Unbind(wxEVT_MOTION, &CFrame::OnMouse, this);
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor) if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor)
m_RenderParent->SetCursor(wxNullCursor); m_RenderParent->SetCursor(wxNullCursor);
DoFullscreen(false); DoFullscreen(false);
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain) if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)
{ {
m_RenderFrame->Destroy(); m_RenderFrame->Destroy();
} }
else else
{ {
#if defined(__APPLE__) #if defined(__APPLE__)
// Disable the full screen button when not in a game. // Disable the full screen button when not in a game.
NSView *view = (NSView *) m_RenderFrame->GetHandle(); NSView *view = (NSView *)m_RenderFrame->GetHandle();
NSWindow *window = [view window]; NSWindow *window = [view window];
[window setCollectionBehavior:NSWindowCollectionBehaviorDefault]; [window setCollectionBehavior : NSWindowCollectionBehaviorDefault];
#endif #endif
// Make sure the window is not longer set to stay on top // Make sure the window is not longer set to stay on top
m_RenderFrame->SetWindowStyle(m_RenderFrame->GetWindowStyle() & ~wxSTAY_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();
} }
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 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.
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() void CFrame::DoRecordingSave()
@ -1568,7 +1581,7 @@ void CFrame::OnLoadLastState(wxCommandEvent& event)
void CFrame::OnSaveFirstState(wxCommandEvent& WXUNUSED(event)) void CFrame::OnSaveFirstState(wxCommandEvent& WXUNUSED(event))
{ {
if (Core::GetState() != Core::CORE_UNINITIALIZED) if (Core::IsRunningAndStarted())
State::SaveFirstSaved(); State::SaveFirstSaved();
} }
@ -1626,6 +1639,7 @@ void CFrame::UpdateGUI()
bool Initialized = Core::IsRunning(); bool Initialized = Core::IsRunning();
bool Running = Core::GetState() == Core::CORE_RUN; bool Running = Core::GetState() == Core::CORE_RUN;
bool Paused = Core::GetState() == Core::CORE_PAUSE; bool Paused = Core::GetState() == Core::CORE_PAUSE;
bool Stopping = Core::GetState() == Core::CORE_STOPPING;
bool RunningWii = Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii; bool RunningWii = Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii;
bool RunningGamecube = Initialized && !SConfig::GetInstance().m_LocalCoreStartupParameter.bWii; bool RunningGamecube = Initialized && !SConfig::GetInstance().m_LocalCoreStartupParameter.bWii;
@ -1772,8 +1786,8 @@ void CFrame::UpdateGUI()
{ {
// Game has been loaded, enable the pause button // Game has been loaded, enable the pause button
if (m_ToolBar) if (m_ToolBar)
m_ToolBar->EnableTool(IDM_PLAY, true); m_ToolBar->EnableTool(IDM_PLAY, !Stopping);
GetMenuBar()->FindItem(IDM_PLAY)->Enable(true); GetMenuBar()->FindItem(IDM_PLAY)->Enable(!Stopping);
// Reset game loading flag // Reset game loading flag
m_bGameLoading = false; m_bGameLoading = false;

View File

@ -254,6 +254,7 @@ enum
IDM_PANIC, IDM_PANIC,
IDM_KEYSTATE, IDM_KEYSTATE,
IDM_WINDOWSIZEREQUEST, IDM_WINDOWSIZEREQUEST,
IDM_STOPPED,
IDM_HOST_MESSAGE, IDM_HOST_MESSAGE,
IDM_MPANEL, ID_STATUSBAR, IDM_MPANEL, ID_STATUSBAR,

View File

@ -37,6 +37,7 @@
#include "Common/Logging/LogManager.h" #include "Common/Logging/LogManager.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreParameter.h" #include "Core/CoreParameter.h"
#include "Core/Movie.h" #include "Core/Movie.h"
#include "Core/HW/Wiimote.h" #include "Core/HW/Wiimote.h"
@ -455,6 +456,7 @@ int DolphinApp::OnExit()
VideoBackend::ClearList(); VideoBackend::ClearList();
SConfig::Shutdown(); SConfig::Shutdown();
LogManager::Shutdown(); LogManager::Shutdown();
Core::Shutdown();
delete m_locale; delete m_locale;

View File

@ -131,7 +131,7 @@ void Host_SetWiiMoteConnectionState(int _State) {}
void X11_MainLoop() void X11_MainLoop()
{ {
bool fullscreen = SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen; bool fullscreen = SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen;
while (Core::GetState() == Core::CORE_UNINITIALIZED) while (!Core::IsRunning())
updateMainFrameEvent.Wait(); updateMainFrameEvent.Wait();
Display *dpy = XOpenDisplay(0); Display *dpy = XOpenDisplay(0);

View File

@ -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(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5);
szr_basic->Add(choice_backend, 1, 0, 0); szr_basic->Add(choice_backend, 1, 0, 0);
if (Core::GetState() != Core::CORE_UNINITIALIZED) if (Core::IsRunning())
{ {
label_backend->Disable(); label_backend->Disable();
choice_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(label_display_resolution, 1, wxALIGN_CENTER_VERTICAL, 0);
szr_display->Add(choice_display_resolution); szr_display->Add(choice_display_resolution);
if (Core::GetState() != Core::CORE_UNINITIALIZED) if (Core::IsRunning())
{ {
label_display_resolution->Disable(); label_display_resolution->Disable();
choice_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(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)); 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(); 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")); wxCheckBox* const cb_prog_scan = new wxCheckBox(page_advanced, wxID_ANY, _("Enable Progressive Scan"));
RegisterControl(cb_prog_scan, wxGetTranslation(prog_scan_desc)); RegisterControl(cb_prog_scan, wxGetTranslation(prog_scan_desc));
cb_prog_scan->Bind(wxEVT_CHECKBOX, &VideoConfigDiag::Event_ProgressiveScan, this); 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->Disable();
cb_prog_scan->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bProgressive); cb_prog_scan->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bProgressive);

View File

@ -86,7 +86,7 @@ protected:
VideoBackend* new_backend = g_available_video_backends[ev.GetInt()]; VideoBackend* new_backend = g_available_video_backends[ev.GetInt()];
if (g_video_backend != new_backend) 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") 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'."), 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'."),