From a088ad781a815f66c227b42a64dbb660880fdb52 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 22 Aug 2016 10:09:57 -0700 Subject: [PATCH] Qt: Make reseting when pasued frame-accurate --- CHANGES | 1 + src/core/thread.c | 20 ++++++++++++++++---- src/core/thread.h | 1 + src/platform/qt/GameController.cpp | 15 +++++++++++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 686e9fc8d..657ec089b 100644 --- a/CHANGES +++ b/CHANGES @@ -69,6 +69,7 @@ Misc: - GBA Memory: Optimize Load-/StoreMultiple - 3DS: Adjustable filering - PSP2: Screenshots are now saved into the Photo Gallery + - Qt: Make reseting when pasued frame-accurate 0.4.1: (2016-07-11) Bugfixes: diff --git a/src/core/thread.c b/src/core/thread.c index e3018495f..177d94eed 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -114,6 +114,9 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { if (threadContext->startCallback) { threadContext->startCallback(threadContext); } + if (threadContext->resetCallback) { + threadContext->resetCallback(threadContext); + } while (threadContext->state < THREAD_EXITING) { struct mDebugger* debugger = core->debugger; @@ -157,6 +160,9 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { MutexUnlock(&threadContext->stateMutex); if (resetScheduled) { core->reset(core); + if (threadContext->resetCallback) { + threadContext->resetCallback(threadContext); + } } } @@ -258,8 +264,11 @@ void mCoreThreadEnd(struct mCoreThread* threadContext) { void mCoreThreadReset(struct mCoreThread* threadContext) { MutexLock(&threadContext->stateMutex); - _waitOnInterrupt(threadContext); - threadContext->state = THREAD_RESETING; + if (threadContext->state == THREAD_INTERRUPTED) { + threadContext->savedState = THREAD_RESETING; + } else { + threadContext->state = THREAD_RESETING; + } ConditionWake(&threadContext->stateCond); MutexUnlock(&threadContext->stateMutex); } @@ -374,8 +383,11 @@ void mCoreThreadUnpause(struct mCoreThread* threadContext) { bool mCoreThreadIsPaused(struct mCoreThread* threadContext) { bool isPaused; MutexLock(&threadContext->stateMutex); - _waitOnInterrupt(threadContext); - isPaused = threadContext->state == THREAD_PAUSED; + if (threadContext->state == THREAD_INTERRUPTED) { + isPaused = threadContext->savedState == THREAD_PAUSED; + } else { + isPaused = threadContext->state == THREAD_PAUSED; + } MutexUnlock(&threadContext->stateMutex); return isPaused; } diff --git a/src/core/thread.h b/src/core/thread.h index 870afc606..9540c841b 100644 --- a/src/core/thread.h +++ b/src/core/thread.h @@ -54,6 +54,7 @@ struct mCoreThread { struct mThreadLogger logger; enum mLogLevel logLevel; ThreadCallback startCallback; + ThreadCallback resetCallback; ThreadCallback cleanCallback; ThreadCallback frameCallback; void* userData; diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 3c664aa54..f3704a0ad 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -136,6 +136,18 @@ GameController::GameController(QObject* parent) mCoreThreadContinue(context); }; + m_threadContext.resetCallback = [](mCoreThread* context) { + GameController* controller = static_cast(context->userData); + unsigned width, height; + controller->m_threadContext.core->desiredVideoDimensions(controller->m_threadContext.core, &width, &height); + memset(controller->m_frontBuffer, 0xF8, width * height * BYTES_PER_PIXEL); + QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer)); + if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) { + mCoreThreadPauseFromThread(context); + QMetaObject::invokeMethod(controller, "gamePaused", Q_ARG(mCoreThread*, context)); + } + }; + m_threadContext.cleanCallback = [](mCoreThread* context) { GameController* controller = static_cast(context->userData); QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(mCoreThread*, context)); @@ -153,6 +165,7 @@ GameController::GameController(QObject* parent) } }; + // TODO: Put back /*m_threadContext.stopCallback = [](mCoreThread* context) { if (!context) { return false; @@ -553,10 +566,12 @@ void GameController::reset() { } bool wasPaused = isPaused(); setPaused(false); + threadInterrupt(); mCoreThreadReset(&m_threadContext); if (wasPaused) { setPaused(true); } + threadContinue(); } void GameController::threadInterrupt() {