mirror of https://github.com/mgba-emu/mgba.git
Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls
This commit is contained in:
parent
709f4f7a83
commit
9352f75e6f
1
CHANGES
1
CHANGES
|
@ -69,6 +69,7 @@ Bugfixes:
|
||||||
- Qt: Fix analog buttons not getting unmapped
|
- Qt: Fix analog buttons not getting unmapped
|
||||||
- GBA Video: Prevent tiles < 512 from being used in modes 3 - 5
|
- GBA Video: Prevent tiles < 512 from being used in modes 3 - 5
|
||||||
- Qt: Fix passing command line options
|
- Qt: Fix passing command line options
|
||||||
|
- Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls
|
||||||
Misc:
|
Misc:
|
||||||
- Qt: Handle saving input settings better
|
- Qt: Handle saving input settings better
|
||||||
- Debugger: Free watchpoints in addition to breakpoints
|
- Debugger: Free watchpoints in addition to breakpoints
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
#include "gba/supervisor/thread.h"
|
||||||
#include "platform/commandline.h"
|
#include "platform/commandline.h"
|
||||||
#include "util/socket.h"
|
#include "util/socket.h"
|
||||||
}
|
}
|
||||||
|
@ -37,6 +38,7 @@ GBAApp::GBAApp(int& argc, char* argv[])
|
||||||
|
|
||||||
SocketSubsystemInit();
|
SocketSubsystemInit();
|
||||||
qRegisterMetaType<const uint32_t*>("const uint32_t*");
|
qRegisterMetaType<const uint32_t*>("const uint32_t*");
|
||||||
|
qRegisterMetaType<GBAThread*>("GBAThread*");
|
||||||
|
|
||||||
QApplication::setApplicationName(projectName);
|
QApplication::setApplicationName(projectName);
|
||||||
QApplication::setApplicationVersion(projectVersion);
|
QApplication::setApplicationVersion(projectVersion);
|
||||||
|
|
|
@ -114,25 +114,25 @@ GameController::GameController(QObject* parent)
|
||||||
vf->truncate(vf, 0);
|
vf->truncate(vf, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
controller->gameStarted(context);
|
QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(GBAThread*, context));
|
||||||
};
|
};
|
||||||
|
|
||||||
m_threadContext.cleanCallback = [](GBAThread* context) {
|
m_threadContext.cleanCallback = [](GBAThread* context) {
|
||||||
GameController* controller = static_cast<GameController*>(context->userData);
|
GameController* controller = static_cast<GameController*>(context->userData);
|
||||||
controller->gameStopped(context);
|
QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(GBAThread*, context));
|
||||||
};
|
};
|
||||||
|
|
||||||
m_threadContext.frameCallback = [](GBAThread* context) {
|
m_threadContext.frameCallback = [](GBAThread* context) {
|
||||||
GameController* controller = static_cast<GameController*>(context->userData);
|
GameController* controller = static_cast<GameController*>(context->userData);
|
||||||
if (GBASyncDrawingFrame(&controller->m_threadContext.sync)) {
|
if (GBASyncDrawingFrame(&controller->m_threadContext.sync)) {
|
||||||
memcpy(controller->m_frontBuffer, controller->m_drawContext, 256 * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL);
|
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 {
|
} else {
|
||||||
controller->frameAvailable(nullptr);
|
QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, nullptr));
|
||||||
}
|
}
|
||||||
if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) {
|
if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) {
|
||||||
GBAThreadPauseFromThread(context);
|
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);
|
va_copy(argc, args);
|
||||||
int immediate = va_arg(argc, int);
|
int immediate = va_arg(argc, int);
|
||||||
va_end(argc);
|
va_end(argc);
|
||||||
controller->unimplementedBiosCall(immediate);
|
QMetaObject::invokeMethod(controller, "unimplementedBiosCall", Q_ARG(int, immediate));
|
||||||
} else if (level == GBA_LOG_STATUS) {
|
} else if (level == GBA_LOG_STATUS) {
|
||||||
// Slot 0 is reserved for suspend points
|
// Slot 0 is reserved for suspend points
|
||||||
if (strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) {
|
if (strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) {
|
||||||
|
@ -189,9 +189,9 @@ GameController::GameController(QObject* parent)
|
||||||
}
|
}
|
||||||
QString message(QString().vsprintf(format, args));
|
QString message(QString().vsprintf(format, args));
|
||||||
if (level == GBA_LOG_STATUS) {
|
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]() {
|
connect(&m_rewindTimer, &QTimer::timeout, [this]() {
|
||||||
|
|
Loading…
Reference in New Issue