diff --git a/include/mgba/internal/gba/sio.h b/include/mgba/internal/gba/sio.h index 260772f55..a546017dc 100644 --- a/include/mgba/internal/gba/sio.h +++ b/include/mgba/internal/gba/sio.h @@ -85,6 +85,8 @@ void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value); void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value); uint16_t GBASIOWriteRegister(struct GBASIO* sio, uint32_t address, uint16_t value); +void GBASIOMultiplayerFinishTransfer(struct GBASIO* sio, uint16_t data[4], uint32_t cyclesLate); + int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data); CXX_GUARD_END diff --git a/src/gba/extra/battlechip.c b/src/gba/extra/battlechip.c index 841981fb7..12750f67b 100644 --- a/src/gba/extra/battlechip.c +++ b/src/gba/extra/battlechip.c @@ -131,11 +131,6 @@ void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cycle uint16_t cmd = gate->d.p->p->memory.io[GBA_REG(SIOMLT_SEND)]; uint16_t reply = 0xFFFF; - gate->d.p->p->memory.io[GBA_REG(SIOMULTI0)] = cmd; - gate->d.p->p->memory.io[GBA_REG(SIOMULTI2)] = 0xFFFF; - gate->d.p->p->memory.io[GBA_REG(SIOMULTI3)] = 0xFFFF; - 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); @@ -168,7 +163,7 @@ void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cycle case 0xA3D0: // EXE 4 case 0xA6C0: - mLOG(GBA_BATTLECHIP, DEBUG, "Resync detected"); + mLOG(GBA_BATTLECHIP, DEBUG, "Resync detected"); gate->state = BATTLECHIP_STATE_SYNC; break; } @@ -213,9 +208,8 @@ void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cycle mLOG(GBA_BATTLECHIP, DEBUG, "Gate: %04X (%i)", reply, gate->state); ++gate->state; - gate->d.p->p->memory.io[GBA_REG(SIOMULTI1)] = reply; - - if (GBASIOMultiplayerIsIrq(gate->d.p->siocnt)) { - GBARaiseIRQ(gate->d.p->p, GBA_IRQ_SIO, cyclesLate); - } + uint16_t data[4] = { + cmd, reply, 0xFFFF, 0xFFFF + }; + GBASIOMultiplayerFinishTransfer(gate->d.p, data, cyclesLate); } diff --git a/src/gba/sio.c b/src/gba/sio.c index 4eb9cfa3c..cdccf1ea3 100644 --- a/src/gba/sio.c +++ b/src/gba/sio.c @@ -318,6 +318,23 @@ uint16_t GBASIOWriteRegister(struct GBASIO* sio, uint32_t address, uint16_t valu return value; } +void GBASIOMultiplayerFinishTransfer(struct GBASIO* sio, uint16_t data[4], uint32_t cyclesLate) { + int id = 0; + if (sio->activeDriver && sio->activeDriver->deviceId) { + id = sio->activeDriver->deviceId(sio->activeDriver); + } + sio->p->memory.io[GBA_REG(SIOMULTI0)] = data[0]; + sio->p->memory.io[GBA_REG(SIOMULTI1)] = data[1]; + sio->p->memory.io[GBA_REG(SIOMULTI2)] = data[2]; + sio->p->memory.io[GBA_REG(SIOMULTI3)] = data[3]; + sio->rcnt |= 1; + sio->siocnt = GBASIOMultiplayerClearBusy(sio->siocnt); + sio->siocnt = GBASIOMultiplayerSetId(sio->siocnt, id); + if (GBASIOMultiplayerIsIrq(sio->siocnt)) { + GBARaiseIRQ(sio->p, GBA_IRQ_SIO, cyclesLate); + } +} + int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data) { switch (command) { case JOY_RESET: diff --git a/src/gba/sio/lockstep.c b/src/gba/sio/lockstep.c index 9709f633b..b7f5752b4 100644 --- a/src/gba/sio/lockstep.c +++ b/src/gba/sio/lockstep.c @@ -280,16 +280,7 @@ static void _finishTransfer(struct GBASIOLockstepNode* node) { struct GBASIO* sio = node->d.p; switch (node->mode) { case GBA_SIO_MULTI: - sio->p->memory.io[GBA_REG(SIOMULTI0)] = node->p->multiRecv[0]; - sio->p->memory.io[GBA_REG(SIOMULTI1)] = node->p->multiRecv[1]; - sio->p->memory.io[GBA_REG(SIOMULTI2)] = node->p->multiRecv[2]; - sio->p->memory.io[GBA_REG(SIOMULTI3)] = node->p->multiRecv[3]; - sio->rcnt |= 1; - sio->siocnt = GBASIOMultiplayerClearBusy(sio->siocnt); - sio->siocnt = GBASIOMultiplayerSetId(sio->siocnt, node->id); - if (GBASIOMultiplayerIsIrq(sio->siocnt)) { - GBARaiseIRQ(sio->p, GBA_IRQ_SIO, 0); - } + GBASIOMultiplayerFinishTransfer(sio, node->p->multiRecv, 0); break; case GBA_SIO_NORMAL_8: // TODO