From 5dbe2404423e3c24703694cfe3393bebddfb4323 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 11 Sep 2022 02:49:04 -0700 Subject: [PATCH] Qt: Resume crashed game when loading a save state --- CHANGES | 1 + include/mgba/core/thread.h | 6 ++++-- src/core/thread.c | 13 +++++++++++++ src/platform/qt/CoreController.cpp | 3 +++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 8e02fa02e..35a4bf926 100644 --- a/CHANGES +++ b/CHANGES @@ -107,6 +107,7 @@ Misc: - Qt: Improve cheat parsing (fixes mgba.io/i/2297) - Qt: Change lossless setting to use WavPack audio - Qt: Use FFmpeg to convert additional camera formats, if available + - Qt: Resume crashed game when loading a save state - SDL: Support exposing an axis directly as the gyro value (closes mgba.io/i/2531) - Windows: Attach to console if present - Vita: Add bilinear filtering option (closes mgba.io/i/344) diff --git a/include/mgba/core/thread.h b/include/mgba/core/thread.h index 55d6a99e8..fee447ae7 100644 --- a/include/mgba/core/thread.h +++ b/include/mgba/core/thread.h @@ -101,8 +101,6 @@ struct mCoreThreadInternal { bool mCoreThreadStart(struct mCoreThread* threadContext); bool mCoreThreadHasStarted(struct mCoreThread* threadContext); bool mCoreThreadHasExited(struct mCoreThread* threadContext); -bool mCoreThreadHasCrashed(struct mCoreThread* threadContext); -void mCoreThreadMarkCrashed(struct mCoreThread* threadContext); void mCoreThreadEnd(struct mCoreThread* threadContext); void mCoreThreadReset(struct mCoreThread* threadContext); void mCoreThreadJoin(struct mCoreThread* threadContext); @@ -122,6 +120,10 @@ void mCoreThreadPauseFromThread(struct mCoreThread* threadContext); void mCoreThreadWaitFromThread(struct mCoreThread* threadContext); void mCoreThreadStopWaiting(struct mCoreThread* threadContext); +bool mCoreThreadHasCrashed(struct mCoreThread* threadContext); +void mCoreThreadMarkCrashed(struct mCoreThread* threadContext); +void mCoreThreadClearCrashed(struct mCoreThread* threadContext); + void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool); void mCoreThreadRewindParamsChanged(struct mCoreThread* threadContext); diff --git a/src/core/thread.c b/src/core/thread.c index ad65ae51d..7101b5a54 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -526,6 +526,15 @@ void mCoreThreadMarkCrashed(struct mCoreThread* threadContext) { MutexUnlock(&threadContext->impl->stateMutex); } +void mCoreThreadClearCrashed(struct mCoreThread* threadContext) { + MutexLock(&threadContext->impl->stateMutex); + if (threadContext->impl->state == mTHREAD_CRASHED) { + threadContext->impl->state = mTHREAD_REQUEST; + ConditionWake(&threadContext->impl->stateCond); + } + MutexUnlock(&threadContext->impl->stateMutex); +} + void mCoreThreadEnd(struct mCoreThread* threadContext) { MutexLock(&threadContext->impl->stateMutex); _waitOnInterrupt(threadContext->impl); @@ -685,6 +694,10 @@ void mCoreThreadPauseFromThread(struct mCoreThread* threadContext) { void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool rewinding) { MutexLock(&threadContext->impl->stateMutex); threadContext->impl->rewinding = rewinding; + if (rewinding && threadContext->impl->state == mTHREAD_CRASHED) { + threadContext->impl->state = mTHREAD_REQUEST; + ConditionWake(&threadContext->impl->stateCond); + } MutexUnlock(&threadContext->impl->stateMutex); } diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 421433191..61774de71 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -613,6 +613,7 @@ void CoreController::loadState(int slot) { m_stateSlot = slot; m_backupSaveState.clear(); } + mCoreThreadClearCrashed(&m_threadContext); mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { CoreController* controller = static_cast(context->userData); if (!controller->m_backupLoadState.isOpen()) { @@ -632,6 +633,7 @@ void CoreController::loadState(const QString& path, int flags) { if (flags != -1) { m_loadStateFlags = flags; } + mCoreThreadClearCrashed(&m_threadContext); mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { CoreController* controller = static_cast(context->userData); VFile* vf = VFileDevice::open(controller->m_statePath, O_RDONLY); @@ -660,6 +662,7 @@ void CoreController::loadState(QIODevice* iodev, int flags) { if (flags != -1) { m_loadStateFlags = flags; } + mCoreThreadClearCrashed(&m_threadContext); mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { CoreController* controller = static_cast(context->userData); VFile* vf = controller->m_stateVf;