Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls
Jeffrey Pfau jeffrey@endrift.com
Sun, 09 Aug 2015 23:25:03 -0700
3 files changed,
11 insertions(+),
8 deletions(-)
M
CHANGES
→
CHANGES
@@ -69,6 +69,7 @@ - GBA Cheats: Fix Pro Action Replay and GameShark issues when used together
- 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
M
src/platform/qt/GBAApp.cpp
→
src/platform/qt/GBAApp.cpp
@@ -15,6 +15,7 @@ #include <QFileOpenEvent>
#include <QIcon> extern "C" { +#include "gba/supervisor/thread.h" #include "platform/commandline.h" #include "util/socket.h" }@@ -37,6 +38,7 @@ setWindowIcon(QIcon(":/res/mgba-1024.png"));
SocketSubsystemInit(); qRegisterMetaType<const uint32_t*>("const uint32_t*"); + qRegisterMetaType<GBAThread*>("GBAThread*"); QApplication::setApplicationName(projectName); QApplication::setApplicationVersion(projectVersion);
M
src/platform/qt/GameController.cpp
→
src/platform/qt/GameController.cpp
@@ -114,25 +114,25 @@ if (vf) {
vf->truncate(vf, 0); } } - controller->gameStarted(context); + QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(GBAThread*, context)); }; m_threadContext.cleanCallback = [](GBAThread* context) { GameController* controller = static_cast<GameController*>(context->userData); - controller->gameStopped(context); + QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(GBAThread*, context)); }; m_threadContext.frameCallback = [](GBAThread* context) { GameController* controller = static_cast<GameController*>(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 @@ va_list argc;
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 @@ return;
} 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]() {