diff --git a/include/mgba/gba/interface.h b/include/mgba/gba/interface.h index c2a4fb5d2..b698f4030 100644 --- a/include/mgba/gba/interface.h +++ b/include/mgba/gba/interface.h @@ -117,7 +117,7 @@ struct GBASIODriver { bool (*handlesMode)(struct GBASIODriver* driver, enum GBASIOMode mode); int (*connectedDevices)(struct GBASIODriver* driver); int (*deviceId)(struct GBASIODriver* driver); - uint16_t (*writeRegister)(struct GBASIODriver* driver, uint32_t address, uint16_t value); + uint16_t (*writeSIOCNT)(struct GBASIODriver* driver, uint16_t value); }; enum GBASIOBattleChipGateFlavor { diff --git a/src/gba/extra/battlechip.c b/src/gba/extra/battlechip.c index 040ec80b8..b71b4e33e 100644 --- a/src/gba/extra/battlechip.c +++ b/src/gba/extra/battlechip.c @@ -34,7 +34,7 @@ enum { }; static bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver); -static uint16_t GBASIOBattlechipGateWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); +static uint16_t GBASIOBattlechipGateWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); static bool GBASIOBattlechipGateHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); static int GBASIOBattlechipGateConnectedDevices(struct GBASIODriver* driver); @@ -46,7 +46,7 @@ void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate* gate) { gate->d.deinit = NULL; gate->d.load = GBASIOBattlechipGateLoad; gate->d.unload = NULL; - gate->d.writeRegister = GBASIOBattlechipGateWriteRegister; + gate->d.writeSIOCNT = GBASIOBattlechipGateWriteSIOCNT; gate->d.setMode = NULL; gate->d.handlesMode = GBASIOBattlechipGateHandlesMode; gate->d.connectedDevices = GBASIOBattlechipGateConnectedDevices; @@ -68,22 +68,12 @@ bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver) { return true; } -uint16_t GBASIOBattlechipGateWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) { +uint16_t GBASIOBattlechipGateWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) { struct GBASIOBattlechipGate* gate = (struct GBASIOBattlechipGate*) driver; - switch (address) { - case GBA_REG_SIOCNT: - value &= ~0xC; - value |= 0x8; - if (value & 0x80) { - _battlechipTransfer(gate); - } - break; - case GBA_REG_SIOMLT_SEND: - break; - case GBA_REG_RCNT: - break; - default: - break; + value &= ~0xC; + value |= 0x8; + if (value & 0x80) { + _battlechipTransfer(gate); } return value; } diff --git a/src/gba/sio.c b/src/gba/sio.c index e0b0a6d1d..68b8fcb48 100644 --- a/src/gba/sio.c +++ b/src/gba/sio.c @@ -193,9 +193,6 @@ void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) { sio->rcnt &= 0xF; sio->rcnt |= value & ~0xF; _switchMode(sio); - if (sio->activeDriver && sio->activeDriver->writeRegister) { - sio->activeDriver->writeRegister(sio->activeDriver, GBA_REG_RCNT, value); - } } void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) { @@ -213,7 +210,7 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) { id = sio->activeDriver->deviceId(sio->activeDriver); } connected = sio->activeDriver->connectedDevices(sio->activeDriver); - handled = !!sio->activeDriver->writeRegister; + handled = !!sio->activeDriver->writeSIOCNT; } } @@ -229,7 +226,7 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) { break; } if (handled) { - value = sio->activeDriver->writeRegister(sio->activeDriver, GBA_REG_SIOCNT, value); + value = sio->activeDriver->writeSIOCNT(sio->activeDriver, value); } else { // Dummy drivers switch (sio->mode) { @@ -328,10 +325,6 @@ uint16_t GBASIOWriteRegister(struct GBASIO* sio, uint32_t address, uint16_t valu // TODO break; } - - if (sio->activeDriver && sio->activeDriver->writeRegister && sio->activeDriver->handlesMode(sio->activeDriver, sio->mode)) { - sio->activeDriver->writeRegister(sio->activeDriver, address, value); - } return value; } diff --git a/src/gba/sio/dolphin.c b/src/gba/sio/dolphin.c index badbd05f7..039f9b528 100644 --- a/src/gba/sio/dolphin.c +++ b/src/gba/sio/dolphin.c @@ -36,7 +36,7 @@ void GBASIODolphinCreate(struct GBASIODolphin* dol) { dol->d.init = GBASIODolphinInit; dol->d.load = GBASIODolphinLoad; dol->d.unload = GBASIODolphinUnload; - dol->d.writeRegister = NULL; + dol->d.writeSIOCNT = NULL; dol->d.setMode = NULL; dol->d.handlesMode = GBASIODolphinHandlesMode; dol->d.connectedDevices = GBASIODolphinConnectedDevices; diff --git a/src/gba/sio/gbp.c b/src/gba/sio/gbp.c index 37944d596..7aeef1b0b 100644 --- a/src/gba/sio/gbp.c +++ b/src/gba/sio/gbp.c @@ -13,7 +13,7 @@ #include static uint16_t _gbpRead(struct mKeyCallback*); -static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); +static uint16_t _gbpSioWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); static bool _gbpSioHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); static int _gbpSioConnectedDevices(struct GBASIODriver* driver); static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate); @@ -49,7 +49,7 @@ void GBASIOPlayerInit(struct GBASIOPlayer* gbp) { gbp->d.deinit = NULL; gbp->d.load = NULL; gbp->d.unload = NULL; - gbp->d.writeRegister = _gbpSioWriteRegister; + gbp->d.writeSIOCNT = _gbpSioWriteSIOCNT; gbp->d.setMode = NULL; gbp->d.handlesMode = _gbpSioHandlesMode; gbp->d.connectedDevices = _gbpSioConnectedDevices; @@ -106,28 +106,27 @@ uint16_t _gbpRead(struct mKeyCallback* callback) { return 0; } -uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) { +uint16_t _gbpSioWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) { struct GBASIOPlayer* gbp = (struct GBASIOPlayer*) driver; - if (address == GBA_REG_SIOCNT) { - if (value & 0x0080) { - uint32_t rx = gbp->p->memory.io[GBA_REG(SIODATA32_LO)] | (gbp->p->memory.io[GBA_REG(SIODATA32_HI)] << 16); - if (gbp->txPosition < 12 && gbp->txPosition > 0) { - // TODO: Check expected - } else if (gbp->txPosition >= 12) { - // 0x00 = Stop - // 0x11 = Hard Stop - // 0x22 = Start - if (gbp->p->rumble) { - int32_t currentTime = mTimingCurrentTime(&gbp->p->timing); - gbp->p->rumble->setRumble(gbp->p->rumble, (rx & 0x33) == 0x22, currentTime - gbp->p->lastRumble); - gbp->p->lastRumble = currentTime; - } + if (value & 0x0080) { + uint32_t rx = gbp->p->memory.io[GBA_REG(SIODATA32_LO)] | (gbp->p->memory.io[GBA_REG(SIODATA32_HI)] << 16); + if (gbp->txPosition < 12 && gbp->txPosition > 0) { + // TODO: Check expected + } else if (gbp->txPosition >= 12) { + uint32_t mask = 0x33; + // 0x00 = Stop + // 0x11 = Hard Stop + // 0x22 = Start + if (gbp->p->rumble) { + int32_t currentTime = mTimingCurrentTime(&gbp->p->timing); + gbp->p->rumble->setRumble(gbp->p->rumble, (rx & 0x33) == 0x22, currentTime - gbp->p->lastRumble); + gbp->p->lastRumble = currentTime; } - mTimingDeschedule(&gbp->p->timing, &gbp->event); - mTimingSchedule(&gbp->p->timing, &gbp->event, 2048); } - value &= 0x78FB; + mTimingDeschedule(&gbp->p->timing, &gbp->event); + mTimingSchedule(&gbp->p->timing, &gbp->event, 2048); } + value &= 0x78FB; return value; } diff --git a/src/gba/sio/lockstep.c b/src/gba/sio/lockstep.c index 67b359234..526d83575 100644 --- a/src/gba/sio/lockstep.c +++ b/src/gba/sio/lockstep.c @@ -19,8 +19,8 @@ static void GBASIOLockstepNodeSetMode(struct GBASIODriver* driver, enum GBASIOMo static bool GBASIOLockstepNodeHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); static int GBASIOLockstepNodeConnectedDevices(struct GBASIODriver* driver); static int GBASIOLockstepNodeDeviceId(struct GBASIODriver* driver); -static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); -static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); +static uint16_t GBASIOLockstepNodeMultiWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); +static uint16_t GBASIOLockstepNodeNormalWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* driver, uint32_t cyclesLate); static void _finishTransfer(struct GBASIOLockstepNode* node); @@ -46,7 +46,7 @@ void GBASIOLockstepNodeCreate(struct GBASIOLockstepNode* node) { node->d.handlesMode = GBASIOLockstepNodeHandlesMode; node->d.connectedDevices = GBASIOLockstepNodeConnectedDevices; node->d.deviceId = GBASIOLockstepNodeDeviceId; - node->d.writeRegister = NULL; + node->d.writeSIOCNT = NULL; } bool GBASIOLockstepAttachNode(struct GBASIOLockstep* lockstep, struct GBASIOLockstepNode* node) { @@ -112,7 +112,7 @@ bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) { switch (node->mode) { case GBA_SIO_MULTI: - node->d.writeRegister = GBASIOLockstepNodeMultiWriteRegister; + node->d.writeSIOCNT = GBASIOLockstepNodeMultiWriteSIOCNT; ATOMIC_ADD(node->p->attachedMulti, 1); node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, node->p->attachedMulti == node->p->d.attached); if (node->id) { @@ -134,7 +134,7 @@ bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) { } else { node->d.p->siocnt = GBASIONormalClearSi(node->d.p->siocnt); } - node->d.writeRegister = GBASIOLockstepNodeNormalWriteRegister; + node->d.writeSIOCNT = GBASIOLockstepNodeNormalWriteSIOCNT; break; default: break; @@ -231,41 +231,35 @@ static int GBASIOLockstepNodeDeviceId(struct GBASIODriver* driver) { return node->id; } -static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) { +static uint16_t GBASIOLockstepNodeMultiWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) { struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; mLockstepLock(&node->p->d); - if (address == GBA_REG_SIOCNT) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value); + mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value); - enum mLockstepPhase transferActive; - int attached; - ATOMIC_LOAD(transferActive, node->p->d.transferActive); - ATOMIC_LOAD(attached, node->p->d.attached); + enum mLockstepPhase transferActive; + int attached; + ATOMIC_LOAD(transferActive, node->p->d.transferActive); + ATOMIC_LOAD(attached, node->p->d.attached); - driver->p->siocnt = GBASIOMultiplayerSetSlave(driver->p->siocnt, node->id || attached < 2); + driver->p->siocnt = GBASIOMultiplayerSetSlave(driver->p->siocnt, node->id || attached < 2); - if (value & 0x0080 && transferActive == TRANSFER_IDLE) { - if (!node->id && attached > 1 && 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, GBASIOTransferCycles(node->d.p)); + if (value & 0x0080 && transferActive == TRANSFER_IDLE) { + if (!node->id && attached > 1 && 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, GBASIOTransferCycles(node->d.p)); - if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { - node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); - mTimingDeschedule(&driver->p->p->timing, &node->event); - } - mTimingSchedule(&driver->p->p->timing, &node->event, 0); + if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { + node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); + mTimingDeschedule(&driver->p->p->timing, &node->event); } + mTimingSchedule(&driver->p->p->timing, &node->event, 0); } - value &= 0xFF83; - value |= driver->p->siocnt & 0x00FC; - } else if (address == GBA_REG_SIOMLT_SEND) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOMLT_SEND <- %04X", node->id, value); - } else { - mLOG(GBA_SIO, STUB, "Lockstep %i: Unknown reg %03X <- %04X", node->id, address, value); } + value &= 0xFF83; + value |= driver->p->siocnt & 0x00FC; mLockstepUnlock(&node->p->d); @@ -525,62 +519,54 @@ static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* user, mLockstepUnlock(&node->p->d); } -static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) { +static uint16_t GBASIOLockstepNodeNormalWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) { struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; mLockstepLock(&node->p->d); - if (address == GBA_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 > 0) { - value = GBASIONormalSetSi(value, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt)); - } else { - value = GBASIONormalClearSi(value); - } + mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value); + int attached; + ATOMIC_LOAD(attached, node->p->attachedNormal); + value &= 0xFF8B; + if (node->id > 0) { + value = GBASIONormalSetSi(value, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt)); + } else { + value = GBASIONormalClearSi(value); + } - enum mLockstepPhase transferActive; - ATOMIC_LOAD(transferActive, node->p->d.transferActive); - if (node->id < 3 && attached > node->id + 1 && transferActive == TRANSFER_IDLE) { - int try; - for (try = 0; try < 3; ++try) { - GBASIONormal nextSiocnct; - ATOMIC_LOAD(nextSiocnct, node->p->players[node->id + 1]->d.p->siocnt); - if (ATOMIC_CMPXCHG(node->p->players[node->id + 1]->d.p->siocnt, nextSiocnct, GBASIONormalSetSi(nextSiocnct, GBASIONormalGetIdleSo(value)))) { - break; - } + enum mLockstepPhase transferActive; + ATOMIC_LOAD(transferActive, node->p->d.transferActive); + if (node->id < 3 && attached > node->id + 1 && transferActive == TRANSFER_IDLE) { + int try; + for (try = 0; try < 3; ++try) { + GBASIONormal nextSiocnct; + ATOMIC_LOAD(nextSiocnct, node->p->players[node->id + 1]->d.p->siocnt); + if (ATOMIC_CMPXCHG(node->p->players[node->id + 1]->d.p->siocnt, nextSiocnct, GBASIONormalSetSi(nextSiocnct, GBASIONormalGetIdleSo(value)))) { + break; } } - if ((value & 0x0081) == 0x0081) { - if (!node->id) { - // Frequency - int32_t cycles = GBASIOTransferCycles(node->d.p); + } + if ((value & 0x0081) == 0x0081) { + if (!node->id) { + // Frequency + int32_t cycles = GBASIOTransferCycles(node->d.p); - if (transferActive == TRANSFER_IDLE) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id); - ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); - ATOMIC_STORE(node->p->d.transferCycles, cycles); + if (transferActive == TRANSFER_IDLE) { + mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id); + ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); + ATOMIC_STORE(node->p->d.transferCycles, cycles); - if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { - node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); - mTimingDeschedule(&driver->p->p->timing, &node->event); - } - mTimingSchedule(&driver->p->p->timing, &node->event, 0); - } else { - value &= ~0x0080; + if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { + node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); + mTimingDeschedule(&driver->p->p->timing, &node->event); } + mTimingSchedule(&driver->p->p->timing, &node->event, 0); } else { - // TODO + value &= ~0x0080; } + } else { + // TODO } - } else if (address == GBA_REG_SIODATA32_LO) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_LO <- %04X", node->id, value); - } else if (address == GBA_REG_SIODATA32_HI) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_HI <- %04X", node->id, value); - } else if (address == GBA_REG_SIODATA8) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA8 <- %02X", node->id, value); } mLockstepUnlock(&node->p->d);