all repos — mgba @ 7a3f2b12b5045fa67354c657d9c11b46a55fe173

mGBA Game Boy Advance Emulator

GBA SIO: Fix Normal mode transfer start timing (fixes #425)
Vicki Pfau vi@endrift.com
Sat, 13 Feb 2021 04:01:04 -0800
commit

7a3f2b12b5045fa67354c657d9c11b46a55fe173

parent

e12ca74d1e891349a01be852e0ff555529868e50

2 files changed, 33 insertions(+), 10 deletions(-)

jump to
M CHANGESCHANGES

@@ -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.csrc/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 {