mirror of https://github.com/mgba-emu/mgba.git
GBA Thread: Add functionality for running callbacks on the GBA thread
This commit is contained in:
parent
9c07698068
commit
91ee44c458
1
CHANGES
1
CHANGES
|
@ -46,6 +46,7 @@ Misc:
|
||||||
- Debugger: Free watchpoints in addition to breakpoints
|
- Debugger: Free watchpoints in addition to breakpoints
|
||||||
- Qt: Move GL frame drawing back onto its own thread
|
- Qt: Move GL frame drawing back onto its own thread
|
||||||
- GBA: Add status log level
|
- GBA: Add status log level
|
||||||
|
- GBA Thread: Add functionality for running callbacks on the GBA thread
|
||||||
|
|
||||||
0.2.0: (2015-04-03)
|
0.2.0: (2015-04-03)
|
||||||
Features:
|
Features:
|
||||||
|
|
|
@ -274,6 +274,13 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
||||||
threadContext->state = THREAD_INTERRUPTED;
|
threadContext->state = THREAD_INTERRUPTED;
|
||||||
ConditionWake(&threadContext->stateCond);
|
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) {
|
if (threadContext->state == THREAD_RESETING) {
|
||||||
threadContext->state = THREAD_RUNNING;
|
threadContext->state = THREAD_RUNNING;
|
||||||
resetScheduled = 1;
|
resetScheduled = 1;
|
||||||
|
@ -598,6 +605,17 @@ void GBAThreadContinue(struct GBAThread* threadContext) {
|
||||||
MutexUnlock(&threadContext->stateMutex);
|
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) {
|
void GBAThreadPause(struct GBAThread* threadContext) {
|
||||||
bool frameOn = true;
|
bool frameOn = true;
|
||||||
MutexLock(&threadContext->stateMutex);
|
MutexLock(&threadContext->stateMutex);
|
||||||
|
|
|
@ -28,6 +28,7 @@ enum ThreadState {
|
||||||
THREAD_INTERRUPTING,
|
THREAD_INTERRUPTING,
|
||||||
THREAD_PAUSED,
|
THREAD_PAUSED,
|
||||||
THREAD_PAUSING,
|
THREAD_PAUSING,
|
||||||
|
THREAD_RUN_ON,
|
||||||
THREAD_RESETING,
|
THREAD_RESETING,
|
||||||
THREAD_EXITING,
|
THREAD_EXITING,
|
||||||
THREAD_SHUTDOWN,
|
THREAD_SHUTDOWN,
|
||||||
|
@ -97,6 +98,7 @@ struct GBAThread {
|
||||||
ThreadCallback cleanCallback;
|
ThreadCallback cleanCallback;
|
||||||
ThreadCallback frameCallback;
|
ThreadCallback frameCallback;
|
||||||
void* userData;
|
void* userData;
|
||||||
|
void (*run)(struct GBAThread*);
|
||||||
|
|
||||||
struct GBASync sync;
|
struct GBASync sync;
|
||||||
|
|
||||||
|
@ -126,6 +128,8 @@ bool GBAThreadIsActive(struct GBAThread* threadContext);
|
||||||
void GBAThreadInterrupt(struct GBAThread* threadContext);
|
void GBAThreadInterrupt(struct GBAThread* threadContext);
|
||||||
void GBAThreadContinue(struct GBAThread* threadContext);
|
void GBAThreadContinue(struct GBAThread* threadContext);
|
||||||
|
|
||||||
|
void GBARunOnThread(struct GBAThread* threadContext, void (*run)(struct GBAThread*));
|
||||||
|
|
||||||
void GBAThreadPause(struct GBAThread* threadContext);
|
void GBAThreadPause(struct GBAThread* threadContext);
|
||||||
void GBAThreadUnpause(struct GBAThread* threadContext);
|
void GBAThreadUnpause(struct GBAThread* threadContext);
|
||||||
bool GBAThreadIsPaused(struct GBAThread* threadContext);
|
bool GBAThreadIsPaused(struct GBAThread* threadContext);
|
||||||
|
|
|
@ -506,17 +506,21 @@ void GameController::setUseBIOS(bool use) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::loadState(int slot) {
|
void GameController::loadState(int slot) {
|
||||||
threadInterrupt();
|
m_stateSlot = slot;
|
||||||
GBALoadState(&m_threadContext, m_threadContext.stateDir, slot);
|
GBARunOnThread(&m_threadContext, [](GBAThread* context) {
|
||||||
threadContinue();
|
GameController* controller = static_cast<GameController*>(context->userData);
|
||||||
emit stateLoaded(&m_threadContext);
|
GBALoadState(context, context->stateDir, controller->m_stateSlot);
|
||||||
emit frameAvailable(m_drawContext);
|
controller->stateLoaded(context);
|
||||||
|
controller->frameAvailable(controller->m_drawContext);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::saveState(int slot) {
|
void GameController::saveState(int slot) {
|
||||||
threadInterrupt();
|
m_stateSlot = slot;
|
||||||
GBASaveState(&m_threadContext, m_threadContext.stateDir, slot, true);
|
GBARunOnThread(&m_threadContext, [](GBAThread* context) {
|
||||||
threadContinue();
|
GameController* controller = static_cast<GameController*>(context->userData);
|
||||||
|
GBASaveState(context, context->stateDir, controller->m_stateSlot, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::setVideoSync(bool set) {
|
void GameController::setVideoSync(bool set) {
|
||||||
|
@ -595,9 +599,7 @@ void GameController::clearAVStream() {
|
||||||
|
|
||||||
#ifdef USE_PNG
|
#ifdef USE_PNG
|
||||||
void GameController::screenshot() {
|
void GameController::screenshot() {
|
||||||
GBAThreadInterrupt(&m_threadContext);
|
GBARunOnThread(&m_threadContext, GBAThreadTakeScreenshot);
|
||||||
GBAThreadTakeScreenshot(&m_threadContext);
|
|
||||||
GBAThreadContinue(&m_threadContext);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -184,6 +184,8 @@ private:
|
||||||
bool m_turbo;
|
bool m_turbo;
|
||||||
bool m_turboForced;
|
bool m_turboForced;
|
||||||
|
|
||||||
|
int m_stateSlot;
|
||||||
|
|
||||||
InputController* m_inputController;
|
InputController* m_inputController;
|
||||||
std::shared_ptr<MultiplayerController> m_multiplayer;
|
std::shared_ptr<MultiplayerController> m_multiplayer;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue