summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2015-04-29 01:03:01 +0200
committerbunnei <bunneidev@gmail.com>2015-05-02 00:27:07 +0200
commite4ea133717a5292339c134160da984ba186d3de8 (patch)
treef6c3e289eaee3c79375d136279509523d4b3aca8
parentQt: Fix loading a new game without stopping emulation. (diff)
downloadyuzu-e4ea133717a5292339c134160da984ba186d3de8.tar
yuzu-e4ea133717a5292339c134160da984ba186d3de8.tar.gz
yuzu-e4ea133717a5292339c134160da984ba186d3de8.tar.bz2
yuzu-e4ea133717a5292339c134160da984ba186d3de8.tar.lz
yuzu-e4ea133717a5292339c134160da984ba186d3de8.tar.xz
yuzu-e4ea133717a5292339c134160da984ba186d3de8.tar.zst
yuzu-e4ea133717a5292339c134160da984ba186d3de8.zip
-rw-r--r--src/citra_qt/bootmanager.cpp43
-rw-r--r--src/citra_qt/bootmanager.h44
-rw-r--r--src/citra_qt/debugger/disassembler.cpp10
-rw-r--r--src/citra_qt/main.cpp33
4 files changed, 40 insertions, 90 deletions
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index fa4e976f4..1e902a8b6 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -28,9 +28,8 @@
#define COPYRIGHT "Copyright (C) 2013-2014 Citra Team"
EmuThread::EmuThread(GRenderWindow* render_window) :
- exec_cpu_step(false), cpu_running(false), stop_run(false), render_window(render_window) {
+ exec_step(false), running(false), stop_run(false), render_window(render_window) {
- shutdown_event.Reset();
connect(this, SIGNAL(started()), render_window, SLOT(moveContext()));
}
@@ -42,20 +41,20 @@ void EmuThread::run() {
// next execution step
bool was_active = false;
while (!stop_run) {
- if (cpu_running) {
+ if (running) {
if (!was_active)
emit DebugModeLeft();
Core::RunLoop();
- was_active = cpu_running || exec_cpu_step;
+ was_active = running || exec_step;
if (!was_active)
emit DebugModeEntered();
- } else if (exec_cpu_step) {
+ } else if (exec_step) {
if (!was_active)
emit DebugModeLeft();
- exec_cpu_step = false;
+ exec_step = false;
Core::SingleStep();
emit DebugModeEntered();
yieldCurrentThread();
@@ -65,40 +64,8 @@ void EmuThread::run() {
}
render_window->moveContext();
-
- shutdown_event.Set();
}
-void EmuThread::Stop() {
- if (!isRunning()) {
- LOG_WARNING(Frontend, "EmuThread::Stop called while emu thread wasn't running, returning...");
- return;
- }
- stop_run = true;
-
- // Release emu threads from any breakpoints, so that this doesn't hang forever.
- Pica::g_debug_context->ClearBreakpoints();
-
- //core::g_state = core::SYS_DIE;
-
- // TODO: Waiting here is just a bad workaround for retarded shutdown logic.
- wait(1000);
- 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()) {
- LOG_CRITICAL(Frontend, "EmuThread STILL running, something is wrong here...");
- terminate();
- }
- }
- LOG_INFO(Frontend, "EmuThread stopped");
-}
-
-
// This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL context.
// The corresponding functionality is handled in EmuThread instead
class GGLWidgetInternal : public QGLWidget
diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h
index f6f09773c..e9b3ea664 100644
--- a/src/citra_qt/bootmanager.h
+++ b/src/citra_qt/bootmanager.h
@@ -25,66 +25,46 @@ public:
/**
* Start emulation (on new thread)
- *
* @warning Only call when not running!
*/
void run() override;
/**
- * Allow the CPU to process a single instruction (if cpu is not running)
- *
+ * Steps the emulation thread by a single CPU instruction (if the CPU is not already running)
* @note This function is thread-safe
*/
- void ExecStep() { exec_cpu_step = true; }
+ void ExecStep() { exec_step = true; }
/**
- * Sets whether the CPU is running
- *
+ * Sets whether the emulation thread is running or not
+ * @param running Boolean value, set the emulation thread to running if true
* @note This function is thread-safe
*/
- void SetCpuRunning(bool running) { cpu_running = running; }
+ void SetRunning(bool running) { this->running = running; }
/**
- * Allow the CPU to continue processing instructions without interruption
- *
+ * Check if the emulation thread is running or not
+ * @return True if the emulation thread is running, otherwise false
* @note This function is thread-safe
*/
- bool IsCpuRunning() { return cpu_running; }
-
-
- /**
- * Shutdown (permantently stops) the CPU
- */
- void ShutdownCpu() { stop_run = true; };
+ bool IsRunning() { return running; }
/**
- * Waits for the CPU shutdown to complete
+ * Shutdown (permanently stops) the emulation thread
*/
- void WaitForCpuShutdown() { shutdown_event.Wait(); }
-
-
-public slots:
- /**
- * Stop emulation and wait for the thread to finish.
- *
- * @details: This function will wait a second for the thread to finish; if it hasn't finished until then, we'll terminate() it and wait another second, hoping that it will be terminated by then.
- * @note: This function is thread-safe.
- */
- void Stop();
+ void Shutdown() { stop_run = true; };
private:
friend class GMainWindow;
EmuThread(GRenderWindow* render_window);
- bool exec_cpu_step;
- bool cpu_running;
+ bool exec_step;
+ bool running;
std::atomic<bool> stop_run;
GRenderWindow* render_window;
- Common::Event shutdown_event;
-
signals:
/**
* Emitted when the CPU has halted execution
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
index b58edafe7..f9423e1d6 100644
--- a/src/citra_qt/debugger/disassembler.cpp
+++ b/src/citra_qt/debugger/disassembler.cpp
@@ -201,7 +201,7 @@ void DisassemblerWidget::Init()
void DisassemblerWidget::OnContinue()
{
- main_window.GetEmuThread()->SetCpuRunning(true);
+ main_window.GetEmuThread()->SetRunning(true);
}
void DisassemblerWidget::OnStep()
@@ -211,13 +211,13 @@ void DisassemblerWidget::OnStep()
void DisassemblerWidget::OnStepInto()
{
- main_window.GetEmuThread()->SetCpuRunning(false);
+ main_window.GetEmuThread()->SetRunning(false);
main_window.GetEmuThread()->ExecStep();
}
void DisassemblerWidget::OnPause()
{
- main_window.GetEmuThread()->SetCpuRunning(false);
+ main_window.GetEmuThread()->SetRunning(false);
// TODO: By now, the CPU might not have actually stopped...
if (Core::g_app_core) {
@@ -227,7 +227,7 @@ void DisassemblerWidget::OnPause()
void DisassemblerWidget::OnToggleStartStop()
{
- main_window.GetEmuThread()->SetCpuRunning(!main_window.GetEmuThread()->IsCpuRunning());
+ main_window.GetEmuThread()->SetRunning(!main_window.GetEmuThread()->IsRunning());
}
void DisassemblerWidget::OnDebugModeEntered()
@@ -235,7 +235,7 @@ void DisassemblerWidget::OnDebugModeEntered()
ARMword next_instr = Core::g_app_core->GetPC();
if (model->GetBreakPoints().IsAddressBreakPoint(next_instr))
- main_window.GetEmuThread()->SetCpuRunning(false);
+ main_window.GetEmuThread()->SetRunning(false);
model->SetNextInstruction(next_instr);
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 5441c17f1..dd180baa4 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -199,10 +199,6 @@ void GMainWindow::OnDisplayTitleBars(bool show)
void GMainWindow::BootGame(std::string filename) {
LOG_INFO(Frontend, "Citra starting...\n");
- // Shutdown previous session if the emu thread is still active...
- if (emu_thread != nullptr)
- ShutdownGame();
-
System::Init(render_window);
// Load a game or die...
@@ -222,29 +218,36 @@ void GMainWindow::BootGame(std::string filename) {
}
void GMainWindow::ShutdownGame() {
- emu_thread->SetCpuRunning(false);
-
- emu_thread->ShutdownCpu();
- emu_thread->WaitForCpuShutdown();
- emu_thread->Stop();
-
+ // Shutdown the emulation thread and wait for it to complete
+ emu_thread->SetRunning(false);
+ emu_thread->Shutdown();
+ emu_thread->wait();
delete emu_thread;
emu_thread = nullptr;
+ // Release emu threads from any breakpoints
+ Pica::g_debug_context->ClearBreakpoints();
+
+ // Shutdown the core emulation
System::Shutdown();
+ // Update the GUI
ui.action_Start->setEnabled(true);
ui.action_Pause->setEnabled(false);
ui.action_Stop->setEnabled(false);
-
render_window->hide();
}
void GMainWindow::OnMenuLoadFile()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), QString(), tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.bin *.cci *.cxi)"));
- if (filename.size())
- BootGame(filename.toLatin1().data());
+ if (filename.size()) {
+ // Shutdown previous session if the emu thread is still active...
+ if (emu_thread != nullptr)
+ ShutdownGame();
+
+ BootGame(filename.toLatin1().data());
+ }
}
void GMainWindow::OnMenuLoadSymbolMap() {
@@ -255,7 +258,7 @@ void GMainWindow::OnMenuLoadSymbolMap() {
void GMainWindow::OnStartGame()
{
- emu_thread->SetCpuRunning(true);
+ emu_thread->SetRunning(true);
ui.action_Start->setEnabled(false);
ui.action_Pause->setEnabled(true);
@@ -264,7 +267,7 @@ void GMainWindow::OnStartGame()
void GMainWindow::OnPauseGame()
{
- emu_thread->SetCpuRunning(false);
+ emu_thread->SetRunning(false);
ui.action_Start->setEnabled(true);
ui.action_Pause->setEnabled(false);