GBA SIO: Fix Normal mode transfer start timing (fixes #425)

This commit is contained in:
Vicki Pfau 2021-02-13 04:01:04 -08:00
parent e12ca74d1e
commit 7a3f2b12b5
2 changed files with 33 additions and 10 deletions

View File

@ -51,6 +51,7 @@ Emulation fixes:
- 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

View File

@ -367,17 +367,22 @@ static int32_t _masterUpdate(struct GBASIOLockstepNode* node) {
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 @@ static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* drive
}
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 {
node->p->d.transferCycles = GBA_ARM7TDMI_FREQUENCY / 8192;
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 {
value &= ~0x0080;
}
} else {