Qt: Handle a game crash without crashing

This commit is contained in:
Jeffrey Pfau 2014-12-19 20:34:48 -08:00
parent 802e4b8720
commit 9aed9754d0
5 changed files with 27 additions and 2 deletions

View File

@ -12,6 +12,7 @@ Bugfixes:
Misc:
- Qt: Disable sync to video by default
- GBA: Exit cleanly on FATAL if the port supports it
- Qt: Handle a game crash without crashing
0.1.0: (2014-12-13)
- Initial release

View File

@ -73,7 +73,12 @@ GameController::GameController(QObject* parent)
m_threadContext.logHandler = [] (GBAThread* context, enum GBALogLevel level, const char* format, va_list args) {
GameController* controller = static_cast<GameController*>(context->userData);
if (!(controller->m_logLevels & level)) {
if (level == GBA_LOG_FATAL) {
MutexLock(&controller->m_threadContext.stateMutex);
controller->m_threadContext.state = THREAD_EXITING;
MutexUnlock(&controller->m_threadContext.stateMutex);
QMetaObject::invokeMethod(controller, "crashGame", Q_ARG(const QString&, QString().vsprintf(format, args)));
} else if (!(controller->m_logLevels & level)) {
return;
}
controller->postLog(level, QString().vsprintf(format, args));
@ -207,6 +212,11 @@ void GameController::closeGame() {
emit gameStopped(&m_threadContext);
}
void GameController::crashGame(const QString& crashMessage) {
closeGame();
emit gameCrashed(crashMessage);
}
bool GameController::isPaused() {
if (!m_gameOpen) {
return false;

View File

@ -64,6 +64,7 @@ signals:
void gameStopped(GBAThread*);
void gamePaused(GBAThread*);
void gameUnpaused(GBAThread*);
void gameCrashed(const QString& errorMessage);
void stateLoaded(GBAThread*);
void postLog(int level, const QString& log);
@ -94,8 +95,10 @@ public slots:
void enableLogLevel(int);
void disableLogLevel(int);
#ifdef BUILD_SDL
private slots:
void crashGame(const QString& crashMessage);
#ifdef BUILD_SDL
void testSDLEvents();
private:

View File

@ -9,6 +9,7 @@
#include <QKeyEvent>
#include <QKeySequence>
#include <QMenuBar>
#include <QMessageBox>
#include <QStackedLayout>
#include "ConfigController.h"
@ -74,6 +75,7 @@ Window::Window(ConfigController* config, QWidget* parent)
connect(m_controller, SIGNAL(gameUnpaused(GBAThread*)), m_display, SLOT(unpauseDrawing()));
connect(m_controller, SIGNAL(postLog(int, const QString&)), m_logView, SLOT(postLog(int, const QString&)));
connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(recordFrame()));
connect(m_controller, SIGNAL(gameCrashed(const QString&)), this, SLOT(gameCrashed(const QString&)));
connect(m_logView, SIGNAL(levelsSet(int)), m_controller, SLOT(setLogLevel(int)));
connect(m_logView, SIGNAL(levelsEnabled(int)), m_controller, SLOT(enableLogLevel(int)));
connect(m_logView, SIGNAL(levelsDisabled(int)), m_controller, SLOT(disableLogLevel(int)));
@ -325,6 +327,14 @@ void Window::gameStopped() {
m_fpsTimer.stop();
}
void Window::gameCrashed(const QString& errorMessage) {
QMessageBox* crash = new QMessageBox(QMessageBox::Critical, tr("Crash"),
tr("The game has crashed with the following error:\n\n%1").arg(errorMessage),
QMessageBox::Ok, this, Qt::Sheet);
crash->setAttribute(Qt::WA_DeleteOnClose);
crash->show();
}
void Window::redoLogo() {
if (m_controller->isLoaded()) {
return;

View File

@ -87,6 +87,7 @@ protected:
private slots:
void gameStarted(GBAThread*);
void gameStopped();
void gameCrashed(const QString&);
void redoLogo();
void recordFrame();