GB SIO: Fix lockstep failing games aren't reloaded

This commit is contained in:
Vicki Pfau 2019-06-17 13:28:03 -07:00
parent 918caf87c4
commit a9e96c7d00
3 changed files with 31 additions and 6 deletions

View File

@ -31,6 +31,7 @@ Other fixes:
- 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

View File

@ -31,6 +31,7 @@ void GBSIOInit(struct GBSIO* sio) {
void GBSIOReset(struct GBSIO* sio) {
sio->nextEvent = INT_MAX;
sio->remainingBits = 0;
GBSIOSetDriver(sio, sio->driver);
}
void GBSIODeinit(struct GBSIO* sio) {

View File

@ -103,9 +103,12 @@ static void _finishTransfer(struct GBSIOLockstepNode* node) {
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 @@ static int32_t _masterUpdate(struct GBSIOLockstepNode* node) {
}
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 @@ static uint32_t _slaveUpdate(struct GBSIOLockstepNode* node) {
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 uint32_t _slaveUpdate(struct GBSIOLockstepNode* node) {
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 @@ static void _GBSIOLockstepNodeProcessEvents(struct mTiming* timing, void* user,
} else {
cycles = node->nextEvent;
}
mLockstepUnlock(&node->p->d);
if (cycles > 0) {
node->nextEvent = 0;
node->eventDiff += cycles;
@ -227,17 +245,22 @@ static void GBSIOLockstepNodeWriteSB(struct GBSIODriver* driver, uint8_t value)
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;
}