From 9352f75e6fa0cd4e2f6b482ef2f8cc3e62626e25 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 9 Aug 2015 23:25:03 -0700 Subject: [PATCH] Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls --- CHANGES | 1 + src/platform/qt/GBAApp.cpp | 2 ++ src/platform/qt/GameController.cpp | 16 ++++++++-------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 466341681..46842b914 100644 --- a/CHANGES +++ b/CHANGES @@ -69,6 +69,7 @@ Bugfixes: - Qt: Fix analog buttons not getting unmapped - GBA Video: Prevent tiles < 512 from being used in modes 3 - 5 - Qt: Fix passing command line options + - Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls Misc: - Qt: Handle saving input settings better - Debugger: Free watchpoints in addition to breakpoints diff --git a/src/platform/qt/GBAApp.cpp b/src/platform/qt/GBAApp.cpp index 786dd2f7b..a651f4698 100644 --- a/src/platform/qt/GBAApp.cpp +++ b/src/platform/qt/GBAApp.cpp @@ -15,6 +15,7 @@ #include extern "C" { +#include "gba/supervisor/thread.h" #include "platform/commandline.h" #include "util/socket.h" } @@ -37,6 +38,7 @@ GBAApp::GBAApp(int& argc, char* argv[]) SocketSubsystemInit(); qRegisterMetaType("const uint32_t*"); + qRegisterMetaType("GBAThread*"); QApplication::setApplicationName(projectName); QApplication::setApplicationVersion(projectVersion); diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 63df80baa..3253a5b9f 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -114,25 +114,25 @@ GameController::GameController(QObject* parent) vf->truncate(vf, 0); } } - controller->gameStarted(context); + QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(GBAThread*, context)); }; m_threadContext.cleanCallback = [](GBAThread* context) { GameController* controller = static_cast(context->userData); - controller->gameStopped(context); + QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(GBAThread*, context)); }; m_threadContext.frameCallback = [](GBAThread* context) { GameController* controller = static_cast(context->userData); if (GBASyncDrawingFrame(&controller->m_threadContext.sync)) { memcpy(controller->m_frontBuffer, controller->m_drawContext, 256 * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); - controller->frameAvailable(controller->m_frontBuffer); + QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer)); } else { - controller->frameAvailable(nullptr); + QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, nullptr)); } if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) { GBAThreadPauseFromThread(context); - controller->gamePaused(&controller->m_threadContext); + QMetaObject::invokeMethod(controller, "gamePaused", Q_ARG(GBAThread*, context)); } }; @@ -161,7 +161,7 @@ GameController::GameController(QObject* parent) va_copy(argc, args); int immediate = va_arg(argc, int); va_end(argc); - controller->unimplementedBiosCall(immediate); + QMetaObject::invokeMethod(controller, "unimplementedBiosCall", Q_ARG(int, immediate)); } else if (level == GBA_LOG_STATUS) { // Slot 0 is reserved for suspend points if (strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) { @@ -189,9 +189,9 @@ GameController::GameController(QObject* parent) } QString message(QString().vsprintf(format, args)); if (level == GBA_LOG_STATUS) { - controller->statusPosted(message); + QMetaObject::invokeMethod(controller, "statusPosted", Q_ARG(const QString&, message)); } - controller->postLog(level, message); + QMetaObject::invokeMethod(controller, "postLog", Q_ARG(int, level), Q_ARG(const QString&, message)); }; connect(&m_rewindTimer, &QTimer::timeout, [this]() {