Qt: Make reseting when pasued frame-accurate

This commit is contained in:
Jeffrey Pfau 2016-08-22 10:09:57 -07:00
parent 193d2d1f4a
commit a088ad781a
4 changed files with 33 additions and 4 deletions

View File

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

View File

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

View File

@ -54,6 +54,7 @@ struct mCoreThread {
struct mThreadLogger logger;
enum mLogLevel logLevel;
ThreadCallback startCallback;
ThreadCallback resetCallback;
ThreadCallback cleanCallback;
ThreadCallback frameCallback;
void* userData;

View File

@ -136,6 +136,18 @@ GameController::GameController(QObject* parent)
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 @@ 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() {