mirror of https://github.com/mgba-emu/mgba.git
GBA SIO: Stop using bitfield structs
This commit is contained in:
parent
d048917b72
commit
4787eb29c5
|
@ -33,6 +33,23 @@ enum {
|
|||
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 GBASIO {
|
|||
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);
|
||||
|
|
|
@ -87,7 +87,7 @@ void _battlechipTransfer(struct GBASIOBattlechipGate* gate) {
|
|||
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 @@ void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cycle
|
|||
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 @@ void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cycle
|
|||
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 @@ void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cycle
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -584,10 +584,10 @@ void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLat
|
|||
++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;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ void GBASIOLockstepDetachNode(struct GBASIOLockstep* lockstep, struct GBASIOLock
|
|||
|
||||
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 @@ bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) {
|
|||
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 @@ static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver
|
|||
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 @@ static void _finishTransfer(struct GBASIOLockstepNode* node) {
|
|||
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 @@ static int32_t _masterUpdate(struct GBASIOLockstepNode* node) {
|
|||
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 @@ static uint32_t _slaveUpdate(struct GBASIOLockstepNode* node) {
|
|||
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 @@ static uint32_t _slaveUpdate(struct GBASIOLockstepNode* node) {
|
|||
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 @@ static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* drive
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue