diff --git a/src/frontend/qt_sdl/EmuInstance.cpp b/src/frontend/qt_sdl/EmuInstance.cpp index b39bf040..62097f6d 100644 --- a/src/frontend/qt_sdl/EmuInstance.cpp +++ b/src/frontend/qt_sdl/EmuInstance.cpp @@ -180,12 +180,12 @@ bool EmuInstance::emuIsActive() void EmuInstance::emuStop(StopReason reason) { - emuThread->emuStop(); + if (reason != StopReason::External) + emuThread->emuStop(false); switch (reason) { case StopReason::GBAModeNotSupported: - Log(LogLevel::Error, "!! GBA MODE NOT SUPPORTED\n"); osdAddMessage(0xFFA0A0, "GBA mode not supported"); break; case StopReason::BadExceptionRegion: diff --git a/src/frontend/qt_sdl/EmuThread.cpp b/src/frontend/qt_sdl/EmuThread.cpp index 536643e4..c95a1ad8 100644 --- a/src/frontend/qt_sdl/EmuThread.cpp +++ b/src/frontend/qt_sdl/EmuThread.cpp @@ -460,6 +460,8 @@ void EmuThread::run() ContextRequest = contextRequest_None; } } + + handleMessages(); } file = Platform::OpenLocalFile("rtc.bin", Platform::FileMode::Write); @@ -476,6 +478,45 @@ void EmuThread::run() NDS::Current = nullptr; } +void EmuThread::sendMessage(Message msg) +{ + msgMutex.lock(); + msgQueue.enqueue(msg); + msgMutex.unlock(); +} + +void EmuThread::waitMessage() +{ + msgSemaphore.acquire(); +} + +void EmuThread::waitAllMessages() +{ + msgSemaphore.acquire(msgSemaphore.available()); +} + +void EmuThread::handleMessages() +{ + msgMutex.lock(); + while (!msgQueue.empty()) + { + Message msg = msgQueue.dequeue(); + switch (msg.type) + { + case msg_EmuStop: + if (msg.stopExternal) emuInstance->nds->Stop(); + EmuRunning = emuStatus_Paused; + emuActive = false; + emuInstance->audioDisable(); + emit windowEmuStop(); + break; + } + + msgSemaphore.release(); + } + msgMutex.unlock(); +} + void EmuThread::changeWindowTitle(char* title) { emit windowTitleChange(QString(title)); @@ -528,10 +569,9 @@ void EmuThread::emuUnpause() emuInstance->audioEnable(); } -void EmuThread::emuStop() +void EmuThread::emuStop(bool external) { - emuPause(); - emuActive = false; + sendMessage({.type = msg_EmuStop, .stopExternal = external}); } void EmuThread::emuExit() diff --git a/src/frontend/qt_sdl/EmuThread.h b/src/frontend/qt_sdl/EmuThread.h index 4e6f592f..c4bd8f77 100644 --- a/src/frontend/qt_sdl/EmuThread.h +++ b/src/frontend/qt_sdl/EmuThread.h @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include @@ -53,13 +55,36 @@ public: void attachWindow(MainWindow* window); void detachWindow(MainWindow* window); + enum MessageType + { + msg_EmuStop, + }; + + struct Message + { + MessageType type; + union + { + bool stopExternal; + }; + }; + + void sendMessage(Message msg); + void waitMessage(); + void waitAllMessages(); + + void sendMessage(MessageType type) + { + return sendMessage({.type = type}); + } + void changeWindowTitle(char* title); // to be called from the UI thread void emuRun(); void emuPause(); void emuUnpause(); - void emuStop(); + void emuStop(bool external); void emuExit(); void emuFrameStep(); @@ -95,6 +120,8 @@ signals: void syncVolumeLevel(); private: + void handleMessages(); + void updateRenderer(); void compileShaders(); @@ -115,6 +142,10 @@ private: constexpr static int EmuPauseStackPauseThreshold = 1; int EmuPauseStack; + QMutex msgMutex; + QSemaphore msgSemaphore; + QQueue msgQueue; + enum ContextRequestKind { contextRequest_None = 0, diff --git a/src/frontend/qt_sdl/Window.cpp b/src/frontend/qt_sdl/Window.cpp index b3ee7a0c..02777ea4 100644 --- a/src/frontend/qt_sdl/Window.cpp +++ b/src/frontend/qt_sdl/Window.cpp @@ -1621,8 +1621,8 @@ void MainWindow::onStop() { if (!emuThread->emuIsActive()) return; - emuThread->emuPause(); - emuInstance->nds->Stop(); + emuThread->emuStop(true); + emuThread->waitMessage(); } void MainWindow::onFrameStep() @@ -2068,8 +2068,6 @@ void MainWindow::onEmuStart() void MainWindow::onEmuStop() { - emuThread->emuStop(); - for (int i = 0; i < 9; i++) { actSaveState[i]->setEnabled(false);