mirror of https://github.com/mgba-emu/mgba.git
GB SIO: Further fix bidirectional transfer starting
This commit is contained in:
parent
9b2d4bc68e
commit
6f08b740f9
1
CHANGES
1
CHANGES
|
@ -4,6 +4,7 @@ Features:
|
||||||
- Debugger: Add range watchpoints
|
- Debugger: Add range watchpoints
|
||||||
Emulation fixes:
|
Emulation fixes:
|
||||||
- GB Serialize: Don't write BGP/OBP when loading SCGB state (fixes mgba.io/i/2694)
|
- GB Serialize: Don't write BGP/OBP when loading SCGB state (fixes mgba.io/i/2694)
|
||||||
|
- GB SIO: Further fix bidirectional transfer starting
|
||||||
- GBA: Fix resetting key IRQ state (fixes mgba.io/i/2716)
|
- GBA: Fix resetting key IRQ state (fixes mgba.io/i/2716)
|
||||||
- GBA Video: Ignore disabled backgrounds as OBJ blend target (fixes mgba.io/i/2489)
|
- GBA Video: Ignore disabled backgrounds as OBJ blend target (fixes mgba.io/i/2489)
|
||||||
- GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722)
|
- GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722)
|
||||||
|
|
|
@ -157,7 +157,7 @@ static int32_t _masterUpdate(struct GBSIOLockstepNode* node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Tell the other GBs they can continue up to where we were
|
// Tell the other GBs they can continue up to where we were
|
||||||
node->p->d.addCycles(&node->p->d, node->id, node->eventDiff);
|
node->p->d.addCycles(&node->p->d, 0, node->eventDiff);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
node->phase = node->p->d.transferActive;
|
node->phase = node->p->d.transferActive;
|
||||||
#endif
|
#endif
|
||||||
|
@ -169,26 +169,28 @@ static int32_t _masterUpdate(struct GBSIOLockstepNode* node) {
|
||||||
|
|
||||||
static uint32_t _slaveUpdate(struct GBSIOLockstepNode* node) {
|
static uint32_t _slaveUpdate(struct GBSIOLockstepNode* node) {
|
||||||
enum mLockstepPhase transferActive;
|
enum mLockstepPhase transferActive;
|
||||||
|
int id;
|
||||||
|
|
||||||
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
|
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
|
||||||
|
ATOMIC_LOAD(id, node->id);
|
||||||
|
|
||||||
bool signal = false;
|
bool signal = false;
|
||||||
switch (transferActive) {
|
switch (transferActive) {
|
||||||
case TRANSFER_IDLE:
|
case TRANSFER_IDLE:
|
||||||
node->p->d.addCycles(&node->p->d, node->id, LOCKSTEP_INCREMENT);
|
node->p->d.addCycles(&node->p->d, id, LOCKSTEP_INCREMENT);
|
||||||
break;
|
break;
|
||||||
case TRANSFER_STARTING:
|
case TRANSFER_STARTING:
|
||||||
case TRANSFER_FINISHING:
|
case TRANSFER_FINISHING:
|
||||||
break;
|
break;
|
||||||
case TRANSFER_STARTED:
|
case TRANSFER_STARTED:
|
||||||
if (node->p->d.unusedCycles(&node->p->d, node->id) > node->eventDiff) {
|
if (node->p->d.unusedCycles(&node->p->d, id) > node->eventDiff) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
node->transferFinished = false;
|
node->transferFinished = false;
|
||||||
signal = true;
|
signal = true;
|
||||||
break;
|
break;
|
||||||
case TRANSFER_FINISHED:
|
case TRANSFER_FINISHED:
|
||||||
if (node->p->d.unusedCycles(&node->p->d, node->id) > node->eventDiff) {
|
if (node->p->d.unusedCycles(&node->p->d, id) > node->eventDiff) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_finishTransfer(node);
|
_finishTransfer(node);
|
||||||
|
@ -199,7 +201,7 @@ static uint32_t _slaveUpdate(struct GBSIOLockstepNode* node) {
|
||||||
node->phase = node->p->d.transferActive;
|
node->phase = node->p->d.transferActive;
|
||||||
#endif
|
#endif
|
||||||
if (signal) {
|
if (signal) {
|
||||||
node->p->d.signal(&node->p->d, 1 << node->id);
|
node->p->d.signal(&node->p->d, 1 << id);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -215,11 +217,13 @@ static void _GBSIOLockstepNodeProcessEvents(struct mTiming* timing, void* user,
|
||||||
int32_t cycles = 0;
|
int32_t cycles = 0;
|
||||||
node->nextEvent -= cyclesLate;
|
node->nextEvent -= cyclesLate;
|
||||||
if (node->nextEvent <= 0) {
|
if (node->nextEvent <= 0) {
|
||||||
if (!node->id) {
|
int id;
|
||||||
|
ATOMIC_LOAD(id, node->id);
|
||||||
|
if (!id) {
|
||||||
cycles = _masterUpdate(node);
|
cycles = _masterUpdate(node);
|
||||||
} else {
|
} else {
|
||||||
cycles = _slaveUpdate(node);
|
cycles = _slaveUpdate(node);
|
||||||
cycles += node->p->d.useCycles(&node->p->d, node->id, node->eventDiff);
|
cycles += node->p->d.useCycles(&node->p->d, id, node->eventDiff);
|
||||||
}
|
}
|
||||||
node->eventDiff = 0;
|
node->eventDiff = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -240,7 +244,9 @@ static void _GBSIOLockstepNodeProcessEvents(struct mTiming* timing, void* user,
|
||||||
|
|
||||||
static void GBSIOLockstepNodeWriteSB(struct GBSIODriver* driver, uint8_t value) {
|
static void GBSIOLockstepNodeWriteSB(struct GBSIODriver* driver, uint8_t value) {
|
||||||
struct GBSIOLockstepNode* node = (struct GBSIOLockstepNode*) driver;
|
struct GBSIOLockstepNode* node = (struct GBSIOLockstepNode*) driver;
|
||||||
node->p->pendingSB[node->id] = value;
|
int id;
|
||||||
|
ATOMIC_LOAD(id, node->id);
|
||||||
|
node->p->pendingSB[id] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t GBSIOLockstepNodeWriteSC(struct GBSIODriver* driver, uint8_t value) {
|
static uint8_t GBSIOLockstepNodeWriteSC(struct GBSIODriver* driver, uint8_t value) {
|
||||||
|
@ -252,11 +258,17 @@ static uint8_t GBSIOLockstepNodeWriteSC(struct GBSIODriver* driver, uint8_t valu
|
||||||
mLockstepLock(&node->p->d);
|
mLockstepLock(&node->p->d);
|
||||||
bool claimed = false;
|
bool claimed = false;
|
||||||
if (ATOMIC_CMPXCHG(node->p->masterClaimed, claimed, true)) {
|
if (ATOMIC_CMPXCHG(node->p->masterClaimed, claimed, true)) {
|
||||||
if (node->id != 0) {
|
int id;
|
||||||
|
ATOMIC_LOAD(id, node->id);
|
||||||
|
if (id != 0) {
|
||||||
|
unsigned sb;
|
||||||
node->p->players[0]->id = 1;
|
node->p->players[0]->id = 1;
|
||||||
node->p->players[1] = node->p->players[0];
|
|
||||||
node->p->players[0] = node->p->players[1];
|
|
||||||
node->id = 0;
|
node->id = 0;
|
||||||
|
node->p->players[1] = node->p->players[0];
|
||||||
|
node->p->players[0] = node;
|
||||||
|
sb = node->p->pendingSB[0];
|
||||||
|
node->p->pendingSB[0] = node->p->pendingSB[1];
|
||||||
|
node->p->pendingSB[1] = sb;
|
||||||
}
|
}
|
||||||
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
|
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
|
||||||
ATOMIC_STORE(node->p->d.transferCycles, GBSIOCyclesPerTransfer[(value >> 1) & 1]);
|
ATOMIC_STORE(node->p->d.transferCycles, GBSIOCyclesPerTransfer[(value >> 1) & 1]);
|
||||||
|
|
Loading…
Reference in New Issue