diff --git a/CHANGES b/CHANGES index afbd738ab..81cfea178 100644 --- a/CHANGES +++ b/CHANGES @@ -46,6 +46,7 @@ Misc: - Debugger: Free watchpoints in addition to breakpoints - Qt: Move GL frame drawing back onto its own thread - GBA: Add status log level + - GBA Thread: Add functionality for running callbacks on the GBA thread 0.2.0: (2015-04-03) Features: diff --git a/src/gba/supervisor/thread.c b/src/gba/supervisor/thread.c index f9f04a411..97296f1bd 100644 --- a/src/gba/supervisor/thread.c +++ b/src/gba/supervisor/thread.c @@ -274,6 +274,13 @@ static THREAD_ENTRY _GBAThreadRun(void* context) { threadContext->state = THREAD_INTERRUPTED; ConditionWake(&threadContext->stateCond); } + if (threadContext->state == THREAD_RUN_ON) { + if (threadContext->run) { + threadContext->run(threadContext); + } + threadContext->state = THREAD_RUNNING; + ConditionWake(&threadContext->stateCond); + } if (threadContext->state == THREAD_RESETING) { threadContext->state = THREAD_RUNNING; resetScheduled = 1; @@ -598,6 +605,17 @@ void GBAThreadContinue(struct GBAThread* threadContext) { MutexUnlock(&threadContext->stateMutex); } +void GBARunOnThread(struct GBAThread* threadContext, void (*run)(struct GBAThread*)) { + MutexLock(&threadContext->stateMutex); + threadContext->run = run; + _waitOnInterrupt(threadContext); + threadContext->state = THREAD_RUN_ON; + threadContext->gba->cpu->nextEvent = 0; + ConditionWake(&threadContext->stateCond); + _waitUntilNotState(threadContext, THREAD_RUN_ON); + MutexUnlock(&threadContext->stateMutex); +} + void GBAThreadPause(struct GBAThread* threadContext) { bool frameOn = true; MutexLock(&threadContext->stateMutex); diff --git a/src/gba/supervisor/thread.h b/src/gba/supervisor/thread.h index 933cf2830..02e766955 100644 --- a/src/gba/supervisor/thread.h +++ b/src/gba/supervisor/thread.h @@ -28,6 +28,7 @@ enum ThreadState { THREAD_INTERRUPTING, THREAD_PAUSED, THREAD_PAUSING, + THREAD_RUN_ON, THREAD_RESETING, THREAD_EXITING, THREAD_SHUTDOWN, @@ -97,6 +98,7 @@ struct GBAThread { ThreadCallback cleanCallback; ThreadCallback frameCallback; void* userData; + void (*run)(struct GBAThread*); struct GBASync sync; @@ -126,6 +128,8 @@ bool GBAThreadIsActive(struct GBAThread* threadContext); void GBAThreadInterrupt(struct GBAThread* threadContext); void GBAThreadContinue(struct GBAThread* threadContext); +void GBARunOnThread(struct GBAThread* threadContext, void (*run)(struct GBAThread*)); + void GBAThreadPause(struct GBAThread* threadContext); void GBAThreadUnpause(struct GBAThread* threadContext); bool GBAThreadIsPaused(struct GBAThread* threadContext); diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 92c843f6b..e0ea70863 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -506,17 +506,21 @@ void GameController::setUseBIOS(bool use) { } void GameController::loadState(int slot) { - threadInterrupt(); - GBALoadState(&m_threadContext, m_threadContext.stateDir, slot); - threadContinue(); - emit stateLoaded(&m_threadContext); - emit frameAvailable(m_drawContext); + m_stateSlot = slot; + GBARunOnThread(&m_threadContext, [](GBAThread* context) { + GameController* controller = static_cast(context->userData); + GBALoadState(context, context->stateDir, controller->m_stateSlot); + controller->stateLoaded(context); + controller->frameAvailable(controller->m_drawContext); + }); } void GameController::saveState(int slot) { - threadInterrupt(); - GBASaveState(&m_threadContext, m_threadContext.stateDir, slot, true); - threadContinue(); + m_stateSlot = slot; + GBARunOnThread(&m_threadContext, [](GBAThread* context) { + GameController* controller = static_cast(context->userData); + GBASaveState(context, context->stateDir, controller->m_stateSlot, true); + }); } void GameController::setVideoSync(bool set) { @@ -595,9 +599,7 @@ void GameController::clearAVStream() { #ifdef USE_PNG void GameController::screenshot() { - GBAThreadInterrupt(&m_threadContext); - GBAThreadTakeScreenshot(&m_threadContext); - GBAThreadContinue(&m_threadContext); + GBARunOnThread(&m_threadContext, GBAThreadTakeScreenshot); } #endif diff --git a/src/platform/qt/GameController.h b/src/platform/qt/GameController.h index ac39b7c5d..b2bcd859d 100644 --- a/src/platform/qt/GameController.h +++ b/src/platform/qt/GameController.h @@ -184,6 +184,8 @@ private: bool m_turbo; bool m_turboForced; + int m_stateSlot; + InputController* m_inputController; std::shared_ptr m_multiplayer;