From 28df8dbfeb17cf5a002a5504a6bd2ba5091bf07c Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 16 Apr 2015 23:31:14 -0400 Subject: [PATCH] Qt: Create emu thread on bootup, kill it on shutdown. --- src/citra_qt/bootmanager.cpp | 31 +++++++++++-------------------- src/citra_qt/bootmanager.h | 24 +++++++++++++++++++----- src/citra_qt/main.cpp | 20 ++++++++++++++------ 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index c2b7ba0e2..fa4e976f4 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -30,21 +30,19 @@ EmuThread::EmuThread(GRenderWindow* render_window) : exec_cpu_step(false), cpu_running(false), stop_run(false), render_window(render_window) { + shutdown_event.Reset(); connect(this, SIGNAL(started()), render_window, SLOT(moveContext())); } -void EmuThread::run() -{ +void EmuThread::run() { stop_run = false; // holds whether the cpu was running during the last iteration, // so that the DebugModeLeft signal can be emitted before the // next execution step bool was_active = false; - while (!stop_run) - { - if (cpu_running) - { + while (!stop_run) { + if (cpu_running) { if (!was_active) emit DebugModeLeft(); @@ -53,9 +51,7 @@ void EmuThread::run() was_active = cpu_running || exec_cpu_step; if (!was_active) emit DebugModeEntered(); - } - else if (exec_cpu_step) - { + } else if (exec_cpu_step) { if (!was_active) emit DebugModeLeft(); @@ -67,15 +63,14 @@ void EmuThread::run() was_active = false; } } + render_window->moveContext(); - Core::Stop(); + shutdown_event.Set(); } -void EmuThread::Stop() -{ - if (!isRunning()) - { +void EmuThread::Stop() { + if (!isRunning()) { LOG_WARNING(Frontend, "EmuThread::Stop called while emu thread wasn't running, returning..."); return; } @@ -88,23 +83,19 @@ void EmuThread::Stop() // TODO: Waiting here is just a bad workaround for retarded shutdown logic. wait(1000); - if (isRunning()) - { + if (isRunning()) { LOG_WARNING(Frontend, "EmuThread still running, terminating..."); quit(); // TODO: Waiting 50 seconds can be necessary if the logging subsystem has a lot of spam // queued... This should be fixed. wait(50000); - if (isRunning()) - { + if (isRunning()) { LOG_CRITICAL(Frontend, "EmuThread STILL running, something is wrong here..."); terminate(); } } LOG_INFO(Frontend, "EmuThread stopped"); - - System::Shutdown(); } diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h index 8083d275b..f6f09773c 100644 --- a/src/citra_qt/bootmanager.h +++ b/src/citra_qt/bootmanager.h @@ -9,6 +9,7 @@ #include "common/common.h" #include "common/emu_window.h" +#include "common/thread.h" class QScreen; class QKeyEvent; @@ -37,20 +38,31 @@ public: void ExecStep() { exec_cpu_step = true; } /** - * Allow the CPU to continue processing instructions without interruption + * Sets whether the CPU is running * * @note This function is thread-safe */ void SetCpuRunning(bool running) { cpu_running = running; } /** - * Allow the CPU to continue processing instructions without interruption - * - * @note This function is thread-safe - */ + * Allow the CPU to continue processing instructions without interruption + * + * @note This function is thread-safe + */ bool IsCpuRunning() { return cpu_running; } + /** + * Shutdown (permantently stops) the CPU + */ + void ShutdownCpu() { stop_run = true; }; + + /** + * Waits for the CPU shutdown to complete + */ + void WaitForCpuShutdown() { shutdown_event.Wait(); } + + public slots: /** * Stop emulation and wait for the thread to finish. @@ -71,6 +83,8 @@ private: GRenderWindow* render_window; + Common::Event shutdown_event; + signals: /** * Emitted when the CPU has halted execution diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 9f9ebc918..fe1dac622 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -57,7 +57,6 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) render_window = new GRenderWindow(this, *this); render_window->hide(); - emu_thread = new EmuThread(render_window); profilerWidget = new ProfilerWidget(this); addDockWidget(Qt::BottomDockWidgetArea, profilerWidget); @@ -197,9 +196,9 @@ void GMainWindow::OnDisplayTitleBars(bool show) } } -void GMainWindow::BootGame(std::string filename) -{ +void GMainWindow::BootGame(std::string filename) { LOG_INFO(Frontend, "Citra starting...\n"); + System::Init(render_window); // Load a game or die... @@ -211,6 +210,7 @@ void GMainWindow::BootGame(std::string filename) registersWidget->OnDebugModeEntered(); callstackWidget->OnDebugModeEntered(); + emu_thread = new EmuThread(render_window); emu_thread->start(); render_window->show(); @@ -248,14 +248,22 @@ void GMainWindow::OnPauseGame() ui.action_Stop->setEnabled(true); } -void GMainWindow::OnStopGame() -{ +void GMainWindow::OnStopGame() { emu_thread->SetCpuRunning(false); - // TODO: Shutdown core + + emu_thread->ShutdownCpu(); + emu_thread->WaitForCpuShutdown(); + emu_thread->Stop(); + + delete emu_thread; + + System::Shutdown(); ui.action_Start->setEnabled(true); ui.action_Pause->setEnabled(false); ui.action_Stop->setEnabled(false); + + render_window->hide(); } void GMainWindow::OnOpenHotkeysDialog()