From 451da0f8a4d486987192e1c34348ad1fa3ab08fe Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 16 May 2024 15:11:19 -0700 Subject: [PATCH] GBA SIO: Start adding new SIO callbacks for revamped API --- include/mgba/gba/interface.h | 5 ++++ src/gba/extra/battlechip.c | 22 +++++++++++++++ src/gba/sio.c | 9 +++++++ src/gba/sio/gbp.c | 24 ++++++++++++++--- src/gba/sio/joybus.c | 16 +++++++++++ src/gba/sio/lockstep.c | 52 +++++++++++++++++++++++++++++++++++- 6 files changed, 123 insertions(+), 5 deletions(-) diff --git a/include/mgba/gba/interface.h b/include/mgba/gba/interface.h index 97e0a5b9c..6b663b4a7 100644 --- a/include/mgba/gba/interface.h +++ b/include/mgba/gba/interface.h @@ -110,8 +110,13 @@ struct GBASIODriver { bool (*init)(struct GBASIODriver* driver); void (*deinit)(struct GBASIODriver* driver); + void (*reset)(struct GBASIODriver* driver); bool (*load)(struct GBASIODriver* driver); bool (*unload)(struct GBASIODriver* driver); + void (*setMode)(struct GBASIODriver* driver, enum GBASIOMode mode); + 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); }; diff --git a/src/gba/extra/battlechip.c b/src/gba/extra/battlechip.c index 3ab9f1403..841981fb7 100644 --- a/src/gba/extra/battlechip.c +++ b/src/gba/extra/battlechip.c @@ -35,6 +35,8 @@ enum { static bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver); static uint16_t GBASIOBattlechipGateWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); +static bool GBASIOBattlechipGateHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); +static int GBASIOBattlechipGateConnectedDevices(struct GBASIODriver* driver); static void _battlechipTransfer(struct GBASIOBattlechipGate* gate); static void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cyclesLate); @@ -45,6 +47,10 @@ void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate* gate) { gate->d.load = GBASIOBattlechipGateLoad; gate->d.unload = NULL; gate->d.writeRegister = GBASIOBattlechipGateWriteRegister; + gate->d.setMode = NULL; + gate->d.handlesMode = GBASIOBattlechipGateHandlesMode; + gate->d.connectedDevices = GBASIOBattlechipGateConnectedDevices; + gate->d.deviceId = NULL; gate->event.context = gate; gate->event.callback = _battlechipTransferEvent; @@ -82,6 +88,22 @@ uint16_t GBASIOBattlechipGateWriteRegister(struct GBASIODriver* driver, uint32_t return value; } +static bool GBASIOBattlechipGateHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) { + UNUSED(driver); + switch (mode) { + case GBA_SIO_NORMAL_32: + case GBA_SIO_MULTI: + return true; + default: + return false; + } +} + +static int GBASIOBattlechipGateConnectedDevices(struct GBASIODriver* driver) { + UNUSED(driver); + return 1; +} + void _battlechipTransfer(struct GBASIOBattlechipGate* gate) { int32_t cycles; if (gate->d.p->mode == GBA_SIO_NORMAL_32) { diff --git a/src/gba/sio.c b/src/gba/sio.c index 4ffeb6388..ae1132dfe 100644 --- a/src/gba/sio.c +++ b/src/gba/sio.c @@ -103,6 +103,15 @@ void GBASIOReset(struct GBASIO* sio) { if (sio->activeDriver && sio->activeDriver->unload) { sio->activeDriver->unload(sio->activeDriver); } + if (sio->drivers.multiplayer && sio->drivers.multiplayer->reset) { + sio->drivers.multiplayer->reset(sio->drivers.multiplayer); + } + if (sio->drivers.joybus && sio->drivers.joybus->reset) { + sio->drivers.joybus->reset(sio->drivers.joybus); + } + if (sio->drivers.normal && sio->drivers.normal->reset) { + sio->drivers.normal->reset(sio->drivers.normal); + } sio->rcnt = RCNT_INITIAL; sio->siocnt = 0; sio->mode = -1; diff --git a/src/gba/sio/gbp.c b/src/gba/sio/gbp.c index d992ebe2e..e1f008274 100644 --- a/src/gba/sio/gbp.c +++ b/src/gba/sio/gbp.c @@ -14,6 +14,8 @@ static uint16_t _gbpRead(struct mKeyCallback*); static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, 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); static const uint8_t _logoPalette[] = { @@ -43,11 +45,15 @@ void GBASIOPlayerInit(struct GBASIOPlayer* gbp) { gbp->callback.d.readKeys = _gbpRead; gbp->callback.d.requireOpposingDirections = true; gbp->callback.p = gbp; - gbp->d.init = 0; - gbp->d.deinit = 0; - gbp->d.load = 0; - gbp->d.unload = 0; + gbp->d.init = NULL; + gbp->d.deinit = NULL; + gbp->d.load = NULL; + gbp->d.unload = NULL; gbp->d.writeRegister = _gbpSioWriteRegister; + gbp->d.setMode = NULL; + gbp->d.handlesMode = _gbpSioHandlesMode; + gbp->d.connectedDevices = _gbpSioConnectedDevices; + gbp->d.deviceId = NULL; gbp->event.context = gbp; gbp->event.name = "GBA SIO Game Boy Player"; gbp->event.callback = _gbpSioProcessEvents; @@ -125,6 +131,16 @@ uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uin return value; } +static bool _gbpSioHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) { + UNUSED(driver); + return mode == GBA_SIO_NORMAL_32; +} + +static int _gbpSioConnectedDevices(struct GBASIODriver* driver) { + UNUSED(driver); + return 1; +} + void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) { UNUSED(timing); UNUSED(cyclesLate); diff --git a/src/gba/sio/joybus.c b/src/gba/sio/joybus.c index 941527439..f1e86d6ed 100644 --- a/src/gba/sio/joybus.c +++ b/src/gba/sio/joybus.c @@ -9,6 +9,8 @@ #include static uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint16_t value); +static bool GBASIOJOYHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); +static int GBASIOJOYConnectedDevices(struct GBASIODriver* driver); void GBASIOJOYCreate(struct GBASIODriver* sio) { sio->init = NULL; @@ -16,6 +18,10 @@ void GBASIOJOYCreate(struct GBASIODriver* sio) { sio->load = NULL; sio->unload = NULL; sio->writeRegister = GBASIOJOYWriteRegister; + sio->setMode = NULL; + sio->handlesMode = GBASIOJOYHandlesMode; + sio->connectedDevices = GBASIOJOYConnectedDevices; + sio->deviceId = NULL; } uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint16_t value) { @@ -41,6 +47,16 @@ uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint return value; } +static bool GBASIOJOYHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) { + UNUSED(driver); + return mode == GBA_SIO_JOYBUS; +} + +static int GBASIOJOYConnectedDevices(struct GBASIODriver* driver) { + UNUSED(driver); + return 1; +} + 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 ba620911e..9ac1e7174 100644 --- a/src/gba/sio/lockstep.c +++ b/src/gba/sio/lockstep.c @@ -15,6 +15,10 @@ static bool GBASIOLockstepNodeInit(struct GBASIODriver* driver); static void GBASIOLockstepNodeDeinit(struct GBASIODriver* driver); static bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver); static bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver); +static void GBASIOLockstepNodeSetMode(struct GBASIODriver* driver, enum GBASIOMode mode); +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 void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* driver, uint32_t cyclesLate); @@ -38,7 +42,11 @@ void GBASIOLockstepNodeCreate(struct GBASIOLockstepNode* node) { node->d.deinit = GBASIOLockstepNodeDeinit; node->d.load = GBASIOLockstepNodeLoad; node->d.unload = GBASIOLockstepNodeUnload; - node->d.writeRegister = 0; + node->d.setMode = GBASIOLockstepNodeSetMode; + node->d.handlesMode = GBASIOLockstepNodeHandlesMode; + node->d.connectedDevices = GBASIOLockstepNodeConnectedDevices; + node->d.deviceId = GBASIOLockstepNodeDeviceId; + node->d.writeRegister = NULL; } bool GBASIOLockstepAttachNode(struct GBASIOLockstep* lockstep, struct GBASIOLockstepNode* node) { @@ -186,6 +194,48 @@ bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver) { return true; } +static void GBASIOLockstepNodeSetMode(struct GBASIODriver* driver, enum GBASIOMode mode) { + struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; + mLockstepLock(&node->p->d); + node->mode = mode; + mLockstepUnlock(&node->p->d); +} + +static bool GBASIOLockstepNodeHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) { + UNUSED(driver); + switch (mode) { + case GBA_SIO_NORMAL_8: + case GBA_SIO_NORMAL_32: + case GBA_SIO_MULTI: + return true; + default: + return false; + } +} + +static int GBASIOLockstepNodeConnectedDevices(struct GBASIODriver* driver) { + struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; + int attached = 0; + + switch (node->mode) { + case GBA_SIO_NORMAL_8: + case GBA_SIO_NORMAL_32: + ATOMIC_LOAD(attached, node->p->attachedNormal); + break; + case GBA_SIO_MULTI: + ATOMIC_LOAD(attached, node->p->attachedMulti); + break; + default: + break; + } + return attached - 1; +} + +static int GBASIOLockstepNodeDeviceId(struct GBASIODriver* driver) { + struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; + return node->id; +} + static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) { struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver;