all repos — mgba @ a088ad781a815f66c227b42a64dbb660880fdb52

mGBA Game Boy Advance Emulator

Qt: Make reseting when pasued frame-accurate
Jeffrey Pfau jeffrey@endrift.com
Mon, 22 Aug 2016 10:09:57 -0700
commit

a088ad781a815f66c227b42a64dbb660880fdb52

parent

193d2d1f4aa358b2454016d44cccae8316261b7f

4 files changed, 33 insertions(+), 4 deletions(-)

jump to
M CHANGESCHANGES

@@ -69,6 +69,7 @@ - Util: Add rtrim

- 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:
M src/core/thread.csrc/core/thread.c

@@ -114,6 +114,9 @@

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 @@ }

MutexUnlock(&threadContext->stateMutex); if (resetScheduled) { core->reset(core); + if (threadContext->resetCallback) { + threadContext->resetCallback(threadContext); + } } }

@@ -258,8 +264,11 @@ }

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 @@

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; }
M src/core/thread.hsrc/core/thread.h

@@ -54,6 +54,7 @@

struct mThreadLogger logger; enum mLogLevel logLevel; ThreadCallback startCallback; + ThreadCallback resetCallback; ThreadCallback cleanCallback; ThreadCallback frameCallback; void* userData;
M src/platform/qt/GameController.cppsrc/platform/qt/GameController.cpp

@@ -136,6 +136,18 @@ QMetaObject::invokeMethod(controller, "gameStarted", Qt::BlockingQueuedConnection, Q_ARG(mCoreThread*, context), Q_ARG(const QString&, controller->m_fname));

mCoreThreadContinue(context); }; + m_threadContext.resetCallback = [](mCoreThread* context) { + GameController* controller = static_cast<GameController*>(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<GameController*>(context->userData); QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(mCoreThread*, context));

@@ -153,6 +165,7 @@ QMetaObject::invokeMethod(controller, "gamePaused", Q_ARG(mCoreThread*, context));

} }; + // TODO: Put back /*m_threadContext.stopCallback = [](mCoreThread* context) { if (!context) { return false;

@@ -553,10 +566,12 @@ return;

} bool wasPaused = isPaused(); setPaused(false); + threadInterrupt(); mCoreThreadReset(&m_threadContext); if (wasPaused) { setPaused(true); } + threadContinue(); } void GameController::threadInterrupt() {