mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Qt: Create emu thread on bootup, kill it on shutdown.
This commit is contained in:
		
							parent
							
								
									d5665fea89
								
							
						
					
					
						commit
						28df8dbfeb
					
				
					 3 changed files with 44 additions and 31 deletions
				
			
		|  | @ -30,21 +30,19 @@ | ||||||
| EmuThread::EmuThread(GRenderWindow* render_window) : | EmuThread::EmuThread(GRenderWindow* render_window) : | ||||||
|     exec_cpu_step(false), cpu_running(false), stop_run(false), render_window(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())); |     connect(this, SIGNAL(started()), render_window, SLOT(moveContext())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmuThread::run() | void EmuThread::run() { | ||||||
| { |  | ||||||
|     stop_run = false; |     stop_run = false; | ||||||
| 
 | 
 | ||||||
|     // holds whether the cpu was running during the last iteration,
 |     // holds whether the cpu was running during the last iteration,
 | ||||||
|     // so that the DebugModeLeft signal can be emitted before the
 |     // so that the DebugModeLeft signal can be emitted before the
 | ||||||
|     // next execution step
 |     // next execution step
 | ||||||
|     bool was_active = false; |     bool was_active = false; | ||||||
|     while (!stop_run) |     while (!stop_run) { | ||||||
|     { |         if (cpu_running) { | ||||||
|         if (cpu_running) |  | ||||||
|         { |  | ||||||
|             if (!was_active) |             if (!was_active) | ||||||
|                 emit DebugModeLeft(); |                 emit DebugModeLeft(); | ||||||
| 
 | 
 | ||||||
|  | @ -53,9 +51,7 @@ void EmuThread::run() | ||||||
|             was_active = cpu_running || exec_cpu_step; |             was_active = cpu_running || exec_cpu_step; | ||||||
|             if (!was_active) |             if (!was_active) | ||||||
|                 emit DebugModeEntered(); |                 emit DebugModeEntered(); | ||||||
|         } |         } else if (exec_cpu_step) { | ||||||
|         else if (exec_cpu_step) |  | ||||||
|         { |  | ||||||
|             if (!was_active) |             if (!was_active) | ||||||
|                 emit DebugModeLeft(); |                 emit DebugModeLeft(); | ||||||
| 
 | 
 | ||||||
|  | @ -67,15 +63,14 @@ void EmuThread::run() | ||||||
|             was_active = false; |             was_active = false; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     render_window->moveContext(); |     render_window->moveContext(); | ||||||
| 
 | 
 | ||||||
|     Core::Stop(); |     shutdown_event.Set(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmuThread::Stop() | void EmuThread::Stop() { | ||||||
| { |     if (!isRunning()) { | ||||||
|     if (!isRunning()) |  | ||||||
|     { |  | ||||||
|         LOG_WARNING(Frontend, "EmuThread::Stop called while emu thread wasn't running, returning..."); |         LOG_WARNING(Frontend, "EmuThread::Stop called while emu thread wasn't running, returning..."); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  | @ -88,23 +83,19 @@ void EmuThread::Stop() | ||||||
| 
 | 
 | ||||||
|     // TODO: Waiting here is just a bad workaround for retarded shutdown logic.
 |     // TODO: Waiting here is just a bad workaround for retarded shutdown logic.
 | ||||||
|     wait(1000); |     wait(1000); | ||||||
|     if (isRunning()) |     if (isRunning()) { | ||||||
|     { |  | ||||||
|         LOG_WARNING(Frontend, "EmuThread still running, terminating..."); |         LOG_WARNING(Frontend, "EmuThread still running, terminating..."); | ||||||
|         quit(); |         quit(); | ||||||
| 
 | 
 | ||||||
|         // TODO: Waiting 50 seconds can be necessary if the logging subsystem has a lot of spam
 |         // TODO: Waiting 50 seconds can be necessary if the logging subsystem has a lot of spam
 | ||||||
|         // queued... This should be fixed.
 |         // queued... This should be fixed.
 | ||||||
|         wait(50000); |         wait(50000); | ||||||
|         if (isRunning()) |         if (isRunning()) { | ||||||
|         { |  | ||||||
|             LOG_CRITICAL(Frontend, "EmuThread STILL running, something is wrong here..."); |             LOG_CRITICAL(Frontend, "EmuThread STILL running, something is wrong here..."); | ||||||
|             terminate(); |             terminate(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     LOG_INFO(Frontend, "EmuThread stopped"); |     LOG_INFO(Frontend, "EmuThread stopped"); | ||||||
| 
 |  | ||||||
|     System::Shutdown(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common.h" | #include "common/common.h" | ||||||
| #include "common/emu_window.h" | #include "common/emu_window.h" | ||||||
|  | #include "common/thread.h" | ||||||
| 
 | 
 | ||||||
| class QScreen; | class QScreen; | ||||||
| class QKeyEvent; | class QKeyEvent; | ||||||
|  | @ -37,7 +38,7 @@ public: | ||||||
|     void ExecStep() { exec_cpu_step = true; } |     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 |      * @note This function is thread-safe | ||||||
|      */ |      */ | ||||||
|  | @ -51,6 +52,17 @@ public: | ||||||
|     bool IsCpuRunning() { return cpu_running; } |     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: | public slots: | ||||||
|     /**
 |     /**
 | ||||||
|      * Stop emulation and wait for the thread to finish. |      * Stop emulation and wait for the thread to finish. | ||||||
|  | @ -71,6 +83,8 @@ private: | ||||||
| 
 | 
 | ||||||
|     GRenderWindow* render_window; |     GRenderWindow* render_window; | ||||||
| 
 | 
 | ||||||
|  |     Common::Event shutdown_event; | ||||||
|  | 
 | ||||||
| signals: | signals: | ||||||
|     /**
 |     /**
 | ||||||
|      * Emitted when the CPU has halted execution |      * Emitted when the CPU has halted execution | ||||||
|  |  | ||||||
|  | @ -57,7 +57,6 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) | ||||||
| 
 | 
 | ||||||
|     render_window = new GRenderWindow(this, *this); |     render_window = new GRenderWindow(this, *this); | ||||||
|     render_window->hide(); |     render_window->hide(); | ||||||
|     emu_thread = new EmuThread(render_window); |  | ||||||
| 
 | 
 | ||||||
|     profilerWidget = new ProfilerWidget(this); |     profilerWidget = new ProfilerWidget(this); | ||||||
|     addDockWidget(Qt::BottomDockWidgetArea, profilerWidget); |     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"); |     LOG_INFO(Frontend, "Citra starting...\n"); | ||||||
|  | 
 | ||||||
|     System::Init(render_window); |     System::Init(render_window); | ||||||
| 
 | 
 | ||||||
|     // Load a game or die...
 |     // Load a game or die...
 | ||||||
|  | @ -211,6 +210,7 @@ void GMainWindow::BootGame(std::string filename) | ||||||
|     registersWidget->OnDebugModeEntered(); |     registersWidget->OnDebugModeEntered(); | ||||||
|     callstackWidget->OnDebugModeEntered(); |     callstackWidget->OnDebugModeEntered(); | ||||||
| 
 | 
 | ||||||
|  |     emu_thread = new EmuThread(render_window); | ||||||
|     emu_thread->start(); |     emu_thread->start(); | ||||||
| 
 | 
 | ||||||
|     render_window->show(); |     render_window->show(); | ||||||
|  | @ -248,14 +248,22 @@ void GMainWindow::OnPauseGame() | ||||||
|     ui.action_Stop->setEnabled(true); |     ui.action_Stop->setEnabled(true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GMainWindow::OnStopGame() | void GMainWindow::OnStopGame() { | ||||||
| { |  | ||||||
|     emu_thread->SetCpuRunning(false); |     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_Start->setEnabled(true); | ||||||
|     ui.action_Pause->setEnabled(false); |     ui.action_Pause->setEnabled(false); | ||||||
|     ui.action_Stop->setEnabled(false); |     ui.action_Stop->setEnabled(false); | ||||||
|  | 
 | ||||||
|  |     render_window->hide(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GMainWindow::OnOpenHotkeysDialog() | void GMainWindow::OnOpenHotkeysDialog() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue