diff options
author | bunnei <bunneidev@gmail.com> | 2015-04-29 01:03:01 +0200 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2015-05-02 00:27:07 +0200 |
commit | e4ea133717a5292339c134160da984ba186d3de8 (patch) | |
tree | f6c3e289eaee3c79375d136279509523d4b3aca8 | |
parent | Qt: Fix loading a new game without stopping emulation. (diff) | |
download | yuzu-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.cpp | 43 | ||||
-rw-r--r-- | src/citra_qt/bootmanager.h | 44 | ||||
-rw-r--r-- | src/citra_qt/debugger/disassembler.cpp | 10 | ||||
-rw-r--r-- | src/citra_qt/main.cpp | 33 |
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); |