all repos — mgba @ ba4f3ae9c693e29ca504133d8e263d5d439d4af4

mGBA Game Boy Advance Emulator

GBA SIO: Disable sync of secondary units
Jeffrey Pfau jeffrey@endrift.com
Sat, 03 Sep 2016 12:19:18 -0700
commit

ba4f3ae9c693e29ca504133d8e263d5d439d4af4

parent

08b78cb468d97102d896c68a07a25f705faaebc7

M src/gba/sio/lockstep.csrc/gba/sio/lockstep.c

@@ -129,11 +129,7 @@ break;

default: break; } - if (node->id) { - node->p->signal(node->p, 1 << node->id); - } else { - node->p->addCycles(node->p, 0, node->eventDiff); - } + node->p->unload(node->p, node->id); return true; }
M src/gba/sio/lockstep.hsrc/gba/sio/lockstep.h

@@ -31,6 +31,7 @@ bool (*signal)(struct GBASIOLockstep*, unsigned mask);

bool (*wait)(struct GBASIOLockstep*, unsigned mask); void (*addCycles)(struct GBASIOLockstep*, int id, int32_t cycles); int32_t (*useCycles)(struct GBASIOLockstep*, int id, int32_t cycles); + void (*unload)(struct GBASIOLockstep*, int id); void* context; #ifndef NDEBUG int transferId;
M src/platform/qt/GameController.cppsrc/platform/qt/GameController.cpp

@@ -50,6 +50,7 @@ , m_useBios(false)

, m_audioThread(new QThread(this)) , m_audioProcessor(AudioProcessor::create()) , m_pauseAfterFrame(false) + , m_sync(true) , m_videoSync(VIDEO_SYNC) , m_audioSync(AUDIO_SYNC) , m_fpsTarget(-1)

@@ -938,8 +939,11 @@ void GameController::setTurbo(bool set, bool forced) {

if (m_turboForced && !forced) { return; } - if (m_turbo == set && m_turboForced == forced) { + if (m_turbo == set && m_turboForced == (set && forced)) { // Don't interrupt the thread if we don't need to + return; + } + if (!m_sync) { return; } m_turbo = set;

@@ -954,25 +958,41 @@ }

void GameController::enableTurbo() { threadInterrupt(); + bool shouldRedoSamples = false; if (!m_turbo) { + shouldRedoSamples = m_threadContext.sync.fpsTarget != m_fpsTarget; m_threadContext.sync.fpsTarget = m_fpsTarget; m_threadContext.sync.audioWait = m_audioSync; m_threadContext.sync.videoFrameWait = m_videoSync; } else if (m_turboSpeed <= 0) { + shouldRedoSamples = m_threadContext.sync.fpsTarget != m_fpsTarget; m_threadContext.sync.fpsTarget = m_fpsTarget; m_threadContext.sync.audioWait = false; m_threadContext.sync.videoFrameWait = false; } else { + shouldRedoSamples = m_threadContext.sync.fpsTarget != m_fpsTarget * m_turboSpeed; m_threadContext.sync.fpsTarget = m_fpsTarget * m_turboSpeed; m_threadContext.sync.audioWait = true; m_threadContext.sync.videoFrameWait = false; } - if (m_audioProcessor) { + if (m_audioProcessor && shouldRedoSamples) { redoSamples(m_audioProcessor->getBufferSamples()); } threadContinue(); } +void GameController::setSync(bool enable) { + m_turbo = false; + m_turboForced = false; + if (!enable) { + m_threadContext.sync.audioWait = false; + m_threadContext.sync.videoFrameWait = false; + } else { + m_threadContext.sync.audioWait = m_audioSync; + m_threadContext.sync.videoFrameWait = m_videoSync; + } + m_sync = enable; +} void GameController::setAVStream(mAVStream* stream) { threadInterrupt(); m_stream = stream;
M src/platform/qt/GameController.hsrc/platform/qt/GameController.h

@@ -135,7 +135,8 @@ void saveState(int slot = 0);

void loadBackupState(); void saveBackupState(); void setTurbo(bool, bool forced = true); - void setTurboSpeed(float ratio = -1); + void setTurboSpeed(float ratio); + void setSync(bool); void setAVStream(mAVStream*); void clearAVStream(); void reloadAudioDriver();

@@ -197,6 +198,7 @@

QAtomicInt m_pauseAfterFrame; QList<std::function<void ()>> m_resetActions; + bool m_sync; bool m_videoSync; bool m_audioSync; float m_fpsTarget;
M src/platform/qt/MultiplayerController.cppsrc/platform/qt/MultiplayerController.cpp

@@ -56,9 +56,11 @@ controller->m_lock.lock();

if (!id) { for (int i = 1; i < controller->m_players.count(); ++i) { Player* player = &controller->m_players[i]; - if (player->node->mode != controller->m_players[0].node->mode) { + if (player->node->d.p->mode != controller->m_players[0].node->d.p->mode) { + player->controller->setSync(true); continue; } + player->controller->setSync(false); player->cyclesPosted += cycles; if (player->awake < 1) { player->node->nextEvent += player->cyclesPosted;

@@ -67,6 +69,7 @@ player->awake = 1;

} } } else { + controller->m_players[id].controller->setSync(true); controller->m_players[id].cyclesPosted += cycles; } controller->m_lock.unlock();

@@ -83,6 +86,31 @@ }

cycles = player->cyclesPosted; controller->m_lock.unlock(); return cycles; + }; + m_lockstep.unload = [](GBASIOLockstep* lockstep, int id) { + MultiplayerController* controller = static_cast<MultiplayerController*>(lockstep->context); + controller->m_lock.lock(); + Player* player = &controller->m_players[id]; + if (id) { + player->controller->setSync(true); + player->waitMask &= ~(1 << id); + if (!player->waitMask && player->awake < 1) { + mCoreThreadStopWaiting(player->controller->thread()); + player->awake = 1; + } + } else { + for (int i = 1; i < controller->m_players.count(); ++i) { + Player* player = &controller->m_players[i]; + player->controller->setSync(true); + player->cyclesPosted += lockstep->players[0]->eventDiff; + if (player->awake < 1) { + player->node->nextEvent += player->cyclesPosted; + mCoreThreadStopWaiting(player->controller->thread()); + player->awake = 1; + } + } + } + controller->m_lock.unlock(); }; }