GBA SIO: Stop using bitfield structs
Vicki Pfau vi@endrift.com
Tue, 04 Jun 2019 16:21:53 -0700
4 files changed,
45 insertions(+),
57 deletions(-)
M
include/mgba/internal/gba/sio.h
→
include/mgba/internal/gba/sio.h
@@ -33,6 +33,23 @@ JOYSTAT_TRANS_BIT = 8,
JOYSTAT_RECV_BIT = 2, }; +DECL_BITFIELD(GBASIONormal, uint16_t); +DECL_BIT(GBASIONormal, Sc, 0); +DECL_BIT(GBASIONormal, InternalSc, 1); +DECL_BIT(GBASIONormal, Si, 2); +DECL_BIT(GBASIONormal, IdleSo, 3); +DECL_BIT(GBASIONormal, Start, 7); +DECL_BIT(GBASIONormal, Length, 12); +DECL_BIT(GBASIONormal, Irq, 14); +DECL_BITFIELD(GBASIOMultiplayer, uint16_t); +DECL_BITS(GBASIOMultiplayer, Baud, 0, 2); +DECL_BIT(GBASIOMultiplayer, Slave, 2); +DECL_BIT(GBASIOMultiplayer, Ready, 3); +DECL_BITS(GBASIOMultiplayer, Id, 4, 2); +DECL_BIT(GBASIOMultiplayer, Error, 6); +DECL_BIT(GBASIOMultiplayer, Busy, 8); +DECL_BIT(GBASIOMultiplayer, Irq, 14); + struct GBASIODriverSet { struct GBASIODriver* normal; struct GBASIODriver* multiplayer;@@ -47,36 +64,7 @@ struct GBASIODriverSet drivers;
struct GBASIODriver* activeDriver; uint16_t rcnt; - // TODO: Convert to bitfields - union { - struct { - unsigned sc : 1; - unsigned internalSc : 1; - unsigned si : 1; - unsigned idleSo : 1; - unsigned : 3; - unsigned start : 1; - unsigned : 4; - unsigned length : 1; - unsigned : 1; - unsigned irq : 1; - unsigned : 1; - } normalControl; - - struct { - unsigned baud : 2; - unsigned slave : 1; - unsigned ready : 1; - unsigned id : 2; - unsigned error : 1; - unsigned busy : 1; - unsigned : 6; - unsigned irq : 1; - unsigned : 1; - } multiplayerControl; - - uint16_t siocnt; - }; + uint16_t siocnt; }; void GBASIOInit(struct GBASIO* sio);
M
src/gba/extra/battlechip.c
→
src/gba/extra/battlechip.c
@@ -87,7 +87,7 @@ int32_t cycles;
if (gate->d.p->mode == SIO_NORMAL_32) { cycles = GBA_ARM7TDMI_FREQUENCY / 0x40000; } else { - cycles = GBASIOCyclesPerTransfer[gate->d.p->multiplayerControl.baud][1]; + cycles = GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(gate->d.p->siocnt)][1]; } mTimingDeschedule(&gate->d.p->p->timing, &gate->event); mTimingSchedule(&gate->d.p->p->timing, &gate->event, cycles);@@ -100,8 +100,8 @@
if (gate->d.p->mode == SIO_NORMAL_32) { gate->d.p->p->memory.io[REG_SIODATA32_LO >> 1] = 0; gate->d.p->p->memory.io[REG_SIODATA32_HI >> 1] = 0; - gate->d.p->normalControl.start = 0; - if (gate->d.p->normalControl.irq) { + gate->d.p->siocnt = GBASIONormalClearStart(gate->d.p->siocnt); + if (GBASIONormalIsIrq(gate->d.p->siocnt)) { GBARaiseIRQ(gate->d.p->p, IRQ_SIO, cyclesLate); } return;@@ -112,8 +112,8 @@ uint16_t reply = 0xFFFF;
gate->d.p->p->memory.io[REG_SIOMULTI0 >> 1] = cmd; gate->d.p->p->memory.io[REG_SIOMULTI2 >> 1] = 0xFFFF; gate->d.p->p->memory.io[REG_SIOMULTI3 >> 1] = 0xFFFF; - gate->d.p->multiplayerControl.busy = 0; - gate->d.p->multiplayerControl.id = 0; + gate->d.p->siocnt = GBASIOMultiplayerClearBusy(gate->d.p->siocnt); + gate->d.p->siocnt = GBASIOMultiplayerSetId(gate->d.p->siocnt, 0); mLOG(GBA_BATTLECHIP, DEBUG, "Game: %04X (%i)", cmd, gate->state);@@ -193,7 +193,7 @@ ++gate->state;
gate->d.p->p->memory.io[REG_SIOMULTI1 >> 1] = reply; - if (gate->d.p->multiplayerControl.irq) { + if (GBASIOMultiplayerIsIrq(gate->d.p->siocnt)) { GBARaiseIRQ(gate->d.p->p, IRQ_SIO, cyclesLate); } }
M
src/gba/hardware.c
→
src/gba/hardware.c
@@ -584,10 +584,10 @@ tx = _gbpTxData[txPosition];
++gbp->p->gbpTxPosition; gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx; gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16; - if (gbp->d.p->normalControl.irq) { + if (GBASIONormalIsIrq(gbp->d.p->siocnt)) { GBARaiseIRQ(gbp->p->p, IRQ_SIO, cyclesLate); } - gbp->d.p->normalControl.start = 0; + gbp->d.p->siocnt = GBASIONormalClearStart(gbp->d.p->siocnt); gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt & ~0x0080; }
M
src/gba/sio/lockstep.c
→
src/gba/sio/lockstep.c
@@ -71,7 +71,7 @@ }
bool GBASIOLockstepNodeInit(struct GBASIODriver* driver) { struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; - node->d.p->multiplayerControl.slave = node->id > 0; + node->d.p->siocnt = GBASIOMultiplayerSetSlave(node->d.p->siocnt, node->id > 0); mLOG(GBA_SIO, DEBUG, "Lockstep %i: Node init", node->id); node->event.context = node; node->event.name = "GBA SIO Lockstep";@@ -99,10 +99,10 @@ case SIO_MULTI:
node->d.writeRegister = GBASIOLockstepNodeMultiWriteRegister; node->d.p->rcnt |= 3; ATOMIC_ADD(node->p->attachedMulti, 1); - node->d.p->multiplayerControl.ready = node->p->attachedMulti == node->p->d.attached; + node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, node->p->attachedMulti == node->p->d.attached); if (node->id) { node->d.p->rcnt |= 4; - node->d.p->multiplayerControl.slave = 1; + node->d.p->siocnt = GBASIOMultiplayerFillSlave(node->d.p->siocnt); } break; case SIO_NORMAL_32:@@ -178,10 +178,10 @@ enum mLockstepPhase transferActive;
ATOMIC_LOAD(transferActive, node->p->d.transferActive); if (value & 0x0080 && transferActive == TRANSFER_IDLE) { - if (!node->id && node->d.p->multiplayerControl.ready) { + if (!node->id && GBASIOMultiplayerIsReady(node->d.p->siocnt)) { mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id); ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); - ATOMIC_STORE(node->p->d.transferCycles, GBASIOCyclesPerTransfer[node->d.p->multiplayerControl.baud][node->p->d.attached - 1]); + ATOMIC_STORE(node->p->d.transferCycles, GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][node->p->d.attached - 1]); bool scheduled = mTimingIsScheduled(&driver->p->p->timing, &node->event); int oldWhen = node->event.when;@@ -220,37 +220,37 @@ sio->p->memory.io[REG_SIOMULTI1 >> 1] = node->p->multiRecv[1];
sio->p->memory.io[REG_SIOMULTI2 >> 1] = node->p->multiRecv[2]; sio->p->memory.io[REG_SIOMULTI3 >> 1] = node->p->multiRecv[3]; sio->rcnt |= 1; - sio->multiplayerControl.busy = 0; - sio->multiplayerControl.id = node->id; - if (sio->multiplayerControl.irq) { + sio->siocnt = GBASIOMultiplayerClearBusy(sio->siocnt); + sio->siocnt = GBASIOMultiplayerSetId(sio->siocnt, node->id); + if (GBASIOMultiplayerIsIrq(sio->siocnt)) { GBARaiseIRQ(sio->p, IRQ_SIO, 0); } break; case SIO_NORMAL_8: // TODO - sio->normalControl.start = 0; + sio->siocnt = GBASIONormalClearStart(sio->siocnt); if (node->id) { - sio->normalControl.si = node->p->players[node->id - 1]->d.p->normalControl.idleSo; + sio->siocnt = GBASIONormalSetSi(sio->siocnt, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt)); node->d.p->p->memory.io[REG_SIODATA8 >> 1] = node->p->normalRecv[node->id - 1] & 0xFF; } else { node->d.p->p->memory.io[REG_SIODATA8 >> 1] = 0xFFFF; } - if (sio->multiplayerControl.irq) { + if (GBASIONormalIsIrq(sio->siocnt)) { GBARaiseIRQ(sio->p, IRQ_SIO, 0); } break; case SIO_NORMAL_32: // TODO - sio->normalControl.start = 0; + sio->siocnt = GBASIONormalClearStart(sio->siocnt); if (node->id) { - sio->normalControl.si = node->p->players[node->id - 1]->d.p->normalControl.idleSo; + sio->siocnt = GBASIONormalSetSi(sio->siocnt, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt)); node->d.p->p->memory.io[REG_SIODATA32_LO >> 1] = node->p->normalRecv[node->id - 1]; node->d.p->p->memory.io[REG_SIODATA32_HI >> 1] |= node->p->normalRecv[node->id - 1] >> 16; } else { node->d.p->p->memory.io[REG_SIODATA32_LO >> 1] = 0xFFFF; node->d.p->p->memory.io[REG_SIODATA32_HI >> 1] = 0xFFFF; } - if (sio->multiplayerControl.irq) { + if (GBASIONormalIsIrq(sio->siocnt)) { GBARaiseIRQ(sio->p, IRQ_SIO, 0); } break;@@ -278,7 +278,7 @@ switch (transferActive) {
case TRANSFER_IDLE: // If the master hasn't initiated a transfer, it can keep going. node->nextEvent += LOCKSTEP_INCREMENT; - node->d.p->multiplayerControl.ready = attachedMulti == attached; + node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, attachedMulti == attached); break; case TRANSFER_STARTING: // Start the transfer, but wait for the other GBAs to catch up@@ -352,11 +352,11 @@ ATOMIC_LOAD(transferActive, node->p->d.transferActive);
ATOMIC_LOAD(attachedMulti, node->p->attachedMulti); ATOMIC_LOAD(attached, node->p->d.attached); - node->d.p->multiplayerControl.ready = attachedMulti == attached; + node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, attachedMulti == attached); bool signal = false; switch (transferActive) { case TRANSFER_IDLE: - if (!node->d.p->multiplayerControl.ready) { + if (!GBASIOMultiplayerIsReady(node->d.p->siocnt)) { node->p->d.addCycles(&node->p->d, node->id, LOCKSTEP_INCREMENT); } break;@@ -376,7 +376,7 @@ node->d.p->p->memory.io[REG_SIOMULTI0 >> 1] = 0xFFFF;
node->d.p->p->memory.io[REG_SIOMULTI1 >> 1] = 0xFFFF; node->d.p->p->memory.io[REG_SIOMULTI2 >> 1] = 0xFFFF; node->d.p->p->memory.io[REG_SIOMULTI3 >> 1] = 0xFFFF; - node->d.p->multiplayerControl.busy = 1; + node->d.p->siocnt = GBASIOMultiplayerFillBusy(node->d.p->siocnt); break; case SIO_NORMAL_8: node->p->multiRecv[node->id] = 0xFFFF;@@ -455,7 +455,7 @@ if (address == REG_SIOCNT) {
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04x", node->id, value); value &= 0xFF8B; if (!node->id) { - driver->p->normalControl.si = 1; + driver->p->siocnt = GBASIONormalFillSi(driver->p->siocnt); } if (value & 0x0080 && !node->id) { // Internal shift clock