GBA SIO: Fix unconnected normal mode SIOCNT SI bit (fixes #2810)

This commit is contained in:
Vicki Pfau 2023-02-03 02:06:20 -08:00
parent 4e85de3a42
commit f046596ca7
2 changed files with 25 additions and 6 deletions

View File

@ -7,6 +7,7 @@ Emulation fixes:
- GBA Audio: Fix improperly deserializing GB audio registers (fixes mgba.io/i/2793)
- GBA Memory: Make VRAM access stalls only apply to BG RAM
- GBA SIO: Fix SIOCNT SI pin value after attaching player 2 (fixes mgba.io/i/2805)
- GBA SIO: Fix unconnected normal mode SIOCNT SI bit (fixes mgba.io/i/2810)
- GBA Timers: Cascading timers don't tick when disabled (fixes mgba.io/i/2812)
- GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722)
Other fixes:

View File

@ -127,7 +127,11 @@ bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) {
break;
case SIO_NORMAL_8:
case SIO_NORMAL_32:
ATOMIC_ADD(node->p->attachedNormal, 1);
if (ATOMIC_ADD(node->p->attachedNormal, 1) > node->id + 1 && node->id < 3) {
node->d.p->siocnt = GBASIONormalSetSi(node->d.p->siocnt, GBASIONormalGetIdleSo(node->p->players[node->id + 1]->d.p->siocnt));
} else {
node->d.p->siocnt = GBASIONormalFillSi(node->d.p->siocnt);
}
node->d.writeRegister = GBASIOLockstepNodeNormalWriteRegister;
break;
default:
@ -507,9 +511,26 @@ static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* drive
if (address == REG_SIOCNT) {
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value);
int attached;
ATOMIC_LOAD(attached, node->p->attachedNormal);
value &= 0xFF8B;
if (!node->id) {
value = GBASIONormalClearSi(value);
if (node->id < 3 && attached > node->id + 1) {
value = GBASIONormalSetSi(value, GBASIONormalGetIdleSo(node->p->players[node->id + 1]->d.p->siocnt));
} else {
value = GBASIONormalFillSi(value);
}
enum mLockstepPhase transferActive;
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
if (node->id > 0 && transferActive == TRANSFER_IDLE) {
int try;
for (try = 0; try < 3; ++try) {
GBASIONormal parentSiocnt;
ATOMIC_LOAD(parentSiocnt, node->p->players[node->id - 1]->d.p->siocnt);
if (ATOMIC_CMPXCHG(node->p->players[node->id - 1]->d.p->siocnt, parentSiocnt, GBASIONormalSetSi(parentSiocnt, GBASIONormalGetIdleSo(value)))) {
break;
}
}
}
if (value & 0x0080) {
if (!node->id) {
@ -524,9 +545,6 @@ static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* drive
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);