GBA SIO: Disable sync of secondary units

This commit is contained in:
Jeffrey Pfau 2016-09-03 12:19:18 -07:00
parent 08b78cb468
commit ba4f3ae9c6
5 changed files with 56 additions and 9 deletions

View File

@ -129,11 +129,7 @@ bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver) {
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;
}

View File

@ -31,6 +31,7 @@ struct GBASIOLockstep {
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;

View File

@ -50,6 +50,7 @@ GameController::GameController(QObject* parent)
, 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,10 +939,13 @@ 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;
m_turboForced = set && forced;
enableTurbo();
@ -954,25 +958,41 @@ void GameController::setTurboSpeed(float ratio) {
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;

View File

@ -135,7 +135,8 @@ public slots:
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 @@ private:
QAtomicInt m_pauseAfterFrame;
QList<std::function<void ()>> m_resetActions;
bool m_sync;
bool m_videoSync;
bool m_audioSync;
float m_fpsTarget;

View File

@ -56,9 +56,11 @@ MultiplayerController::MultiplayerController() {
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 @@ MultiplayerController::MultiplayerController() {
}
}
} else {
controller->m_players[id].controller->setSync(true);
controller->m_players[id].cyclesPosted += cycles;
}
controller->m_lock.unlock();
@ -84,6 +87,31 @@ MultiplayerController::MultiplayerController() {
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();
};
}
MultiplayerController::~MultiplayerController() {