Merge pull request #515 from Armada651/threading
Make the emulation stop asynchronous to prevent deadlocks.
This commit is contained in:
commit
bc655d1a82
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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'."),
|
||||||
|
|
Loading…
Reference in New Issue