GBA SIO: Fix Normal mode transfer start timing (fixes #425)
Vicki Pfau vi@endrift.com
Sat, 13 Feb 2021 04:01:04 -0800
2 files changed,
33 insertions(+),
10 deletions(-)
M
CHANGES
→
CHANGES
@@ -51,6 +51,7 @@ - GBA SIO: Fix copying Normal mode transfer values
- GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800) - GBA SIO: Fix deseralizing SIO registers - GBA SIO: Fix hanging on starting a second multiplayer window (fixes mgba.io/i/854) + - GBA SIO: Fix Normal mode transfer start timing (fixes mgba.io/i/425) - GBA Timers: Fix toggling timer cascading while timer is active (fixes mgba.io/i/2043) - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319) - GBA Video: Fix Hblank timing
M
src/gba/sio/lockstep.c
→
src/gba/sio/lockstep.c
@@ -367,17 +367,22 @@ }
static uint32_t _slaveUpdate(struct GBASIOLockstepNode* node) { enum mLockstepPhase transferActive; - int attachedMulti, attached; + int attached; + int attachedMode; ATOMIC_LOAD(transferActive, node->p->d.transferActive); - ATOMIC_LOAD(attachedMulti, node->p->attachedMulti); ATOMIC_LOAD(attached, node->p->d.attached); - node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, attachedMulti == attached); + if (node->mode == SIO_MULTI) { + ATOMIC_LOAD(attachedMode, node->p->attachedMulti); + node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, attachedMode == attached); + } else { + ATOMIC_LOAD(attachedMode, node->p->attachedNormal); + } bool signal = false; switch (transferActive) { case TRANSFER_IDLE: - if (!GBASIOMultiplayerIsReady(node->d.p->siocnt)) { + if (attachedMode != attached) { node->p->d.addCycles(&node->p->d, node->id, LOCKSTEP_INCREMENT); } break;@@ -479,15 +484,32 @@ value = GBASIONormalClearSi(value);
} if (value & 0x0080) { if (!node->id) { - // Internal shift clock - if (value & 1) { - ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); - } // Frequency + int32_t cycles; if (value & 2) { - node->p->d.transferCycles = GBA_ARM7TDMI_FREQUENCY / 1024; + cycles = 8 * 8; + } else { + cycles = 64 * 8; + } + if (value & 0x1000) { + cycles *= 4; + } + + enum mLockstepPhase transferActive; + ATOMIC_LOAD(transferActive, node->p->d.transferActive); + + if (transferActive == TRANSFER_IDLE) { + mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id); + ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); + ATOMIC_STORE(node->p->d.transferCycles, cycles); + + if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { + node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); + mTimingDeschedule(&driver->p->p->timing, &node->event); + } + mTimingSchedule(&driver->p->p->timing, &node->event, 0); } else { - node->p->d.transferCycles = GBA_ARM7TDMI_FREQUENCY / 8192; + value &= ~0x0080; } } else {