all repos — mgba @ a9e96c7d00f7816cebf1edf50575e7d9f59219d8

mGBA Game Boy Advance Emulator

GB SIO: Fix lockstep failing games aren't reloaded
Vicki Pfau vi@endrift.com
Mon, 17 Jun 2019 13:28:03 -0700
commit

a9e96c7d00f7816cebf1edf50575e7d9f59219d8

parent

918caf87c476a60685dffab94c3b6f615991c231

3 files changed, 31 insertions(+), 6 deletions(-)

jump to
M CHANGESCHANGES

@@ -31,6 +31,7 @@ - Switch: Fix threading-related crash on second launch

- Qt: Fix FPS target maxing out at 59.727 (fixes mgba.io/i/1421) - Core: Fix crashes if core directories aren't set - Qt: Fix menu bar staying hidden in full screen (fixes mgba.io/i/317) + - GB SIO: Fix lockstep failing games aren't reloaded Misc: - GBA Savedata: EEPROM performance fixes - GBA Savedata: Automatically map 1Mbit Flash files as 1Mbit Flash
M src/gb/sio.csrc/gb/sio.c

@@ -31,6 +31,7 @@

void GBSIOReset(struct GBSIO* sio) { sio->nextEvent = INT_MAX; sio->remainingBits = 0; + GBSIOSetDriver(sio, sio->driver); } void GBSIODeinit(struct GBSIO* sio) {
M src/gb/sio/lockstep.csrc/gb/sio/lockstep.c

@@ -103,9 +103,12 @@ }

static int32_t _masterUpdate(struct GBSIOLockstepNode* node) { + enum mLockstepPhase transferActive; + ATOMIC_LOAD(transferActive, node->p->d.transferActive); + bool needsToWait = false; int i; - switch (node->p->d.transferActive) { + switch (transferActive) { case TRANSFER_IDLE: // If the master hasn't initiated a transfer, it can keep going. node->nextEvent += LOCKSTEP_INCREMENT;

@@ -165,8 +168,12 @@ return node->nextEvent;

} static uint32_t _slaveUpdate(struct GBSIOLockstepNode* node) { + enum mLockstepPhase transferActive; + + ATOMIC_LOAD(transferActive, node->p->d.transferActive); + bool signal = false; - switch (node->p->d.transferActive) { + switch (transferActive) { case TRANSFER_IDLE: node->p->d.addCycles(&node->p->d, node->id, LOCKSTEP_INCREMENT); break;

@@ -174,10 +181,16 @@ case TRANSFER_STARTING:

case TRANSFER_FINISHING: break; case TRANSFER_STARTED: + if (node->p->d.unusedCycles(&node->p->d, node->id) > node->eventDiff) { + break; + } node->transferFinished = false; signal = true; break; case TRANSFER_FINISHED: + if (node->p->d.unusedCycles(&node->p->d, node->id) > node->eventDiff) { + break; + } _finishTransfer(node); signal = true; break;

@@ -193,7 +206,10 @@ }

static void _GBSIOLockstepNodeProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) { struct GBSIOLockstepNode* node = user; + mLockstepLock(&node->p->d); if (node->p->d.attached < 2) { + mTimingSchedule(timing, &node->event, (GBSIOCyclesPerTransfer[0] >> 1) - cyclesLate); + mLockstepUnlock(&node->p->d); return; } int32_t cycles = 0;

@@ -209,6 +225,8 @@ node->eventDiff = 0;

} else { cycles = node->nextEvent; } + mLockstepUnlock(&node->p->d); + if (cycles > 0) { node->nextEvent = 0; node->eventDiff += cycles;

@@ -227,17 +245,22 @@ }

static uint8_t GBSIOLockstepNodeWriteSC(struct GBSIODriver* driver, uint8_t value) { struct GBSIOLockstepNode* node = (struct GBSIOLockstepNode*) driver; - if ((value & 0x81) == 0x81 && node->p->d.attached > 1) { + int attached; + ATOMIC_LOAD(attached, node->p->d.attached); + + if ((value & 0x81) == 0x81 && attached > 1) { + mLockstepLock(&node->p->d); bool claimed = false; if (ATOMIC_CMPXCHG(node->p->masterClaimed, claimed, true)) { - node->p->d.transferActive = TRANSFER_STARTING; - node->p->d.transferCycles = GBSIOCyclesPerTransfer[(value >> 1) & 1]; + ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); + ATOMIC_STORE(node->p->d.transferCycles, GBSIOCyclesPerTransfer[(value >> 1) & 1]); mTimingDeschedule(&driver->p->p->timing, &driver->p->event); mTimingDeschedule(&driver->p->p->timing, &node->event); mTimingSchedule(&driver->p->p->timing, &node->event, 0); } else { - mLOG(GB_SIO, FATAL, "GBSIOLockstepNodeWriteSC() failed to write to masterClaimed\n"); + mLOG(GB_SIO, DEBUG, "GBSIOLockstepNodeWriteSC() failed to write to masterClaimed\n"); } + mLockstepUnlock(&node->p->d); } return value; }