all repos — mgba @ e5ee1aa07f0f7bffe86ddda36747b5480964e9fe

mGBA Game Boy Advance Emulator

Fill out SIO driver infrastructure
Jeffrey Pfau jeffrey@endrift.com
Tue, 04 Feb 2014 01:28:16 -0800
commit

e5ee1aa07f0f7bffe86ddda36747b5480964e9fe

parent

70e16613420f3f84149810e9621c4cb65c52bd2c

4 files changed, 91 insertions(+), 7 deletions(-)

jump to
M src/gba/gba-sio.csrc/gba/gba-sio.c

@@ -2,14 +2,34 @@ #include "gba-sio.h"

#include "gba-io.h" +static struct GBASIODriver* _lookupDriver(struct GBASIO* sio, enum GBASIOMode mode) { + switch (mode) { + case SIO_MULTI: + return sio->drivers.multiplayer; + case SIO_JOYBUS: + return sio->drivers.joybus; + default: + return 0; + } +} + static void _switchMode(struct GBASIO* sio) { int mode = ((sio->rcnt >> 14) & 0xC) | ((sio->siocnt >> 12) & 0x3); + enum GBASIOMode oldMode = sio->mode; if (mode < 8) { sio->mode = (enum GBASIOMode) (mode & 0x3); } else { sio->mode = (enum GBASIOMode) (mode & 0xC); } - // TODO: hangup if we have an existing connection + if (oldMode != mode) { + if (sio->activeDriver && sio->activeDriver->detach) { + sio->activeDriver->detach(sio->activeDriver); + } + sio->activeDriver = _lookupDriver(sio, mode); + if (sio->activeDriver && sio->activeDriver->attach) { + sio->activeDriver->attach(sio->activeDriver); + } + } } void GBASIOInit(struct GBASIO* sio) {

@@ -18,12 +38,63 @@ sio->siocnt = 0;

_switchMode(sio); } +void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers) { + if (drivers->multiplayer) { + GBASIOSetDriver(sio, drivers->multiplayer, SIO_MULTI); + } + if (drivers->joybus) { + GBASIOSetDriver(sio, drivers->multiplayer, SIO_JOYBUS); + } +} + +void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode) { + struct GBASIODriver** driverLoc; + switch (mode) { + case SIO_MULTI: + driverLoc = &sio->drivers.multiplayer; + break; + case SIO_JOYBUS: + driverLoc = &sio->drivers.joybus; + break; + default: + GBALog(sio->p, GBA_LOG_ERROR, "Setting an unsupported SIO driver: %x", mode); + return; + } + if (*driverLoc) { + if ((*driverLoc)->detach) { + (*driverLoc)->detach(*driverLoc); + } + if ((*driverLoc)->deinit) { + (*driverLoc)->deinit(*driverLoc); + } + } + if (*driverLoc == sio->activeDriver) { + sio->activeDriver = driver; + } + *driverLoc = driver; + if (driver && driver->init) { + driver->init(driver, sio); + } +} + void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) { sio->rcnt = value; _switchMode(sio); + if (sio->activeDriver && sio->activeDriver->writeRegister) { + sio->activeDriver->writeRegister(sio->activeDriver, REG_RCNT, value); + } } void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) { sio->siocnt = value; _switchMode(sio); + if (sio->activeDriver && sio->activeDriver->writeRegister) { + sio->activeDriver->writeRegister(sio->activeDriver, REG_SIOCNT, value); + } +} + +void GBASIOWriteSIOMLT_SEND(struct GBASIO* sio, uint16_t value) { + if (sio->activeDriver && sio->activeDriver->writeRegister) { + sio->activeDriver->writeRegister(sio->activeDriver, REG_SIOMLT_SEND, value); + } }
M src/gba/gba-sio.hsrc/gba/gba-sio.h

@@ -12,24 +12,32 @@ SIO_GPIO = 8,

SIO_JOYBUS = 12 }; -enum GBASIOMultiMode { - VBA_LINK_COMPAT -}; - enum { RCNT_INITIAL = 0x8000 }; +struct GBASIO; + struct GBASIODriver { + void (*init)(struct GBASIODriver* driver, struct GBASIO* sio); + void (*deinit)(struct GBASIODriver* driver); + int (*attach)(struct GBASIODriver* driver); + int (*detach)(struct GBASIODriver* driver); + void (*writeRegister)(struct GBASIODriver* driver, uint32_t address, uint16_t value); +}; + +struct GBASIODriverSet { + struct GBASIODriver* multiplayer; + struct GBASIODriver* joybus; }; struct GBASIO { struct GBA* p; enum GBASIOMode mode; - enum GBASIOMultiMode multiMode; - struct GBASIODriver* driver; + struct GBASIODriverSet drivers; + struct GBASIODriver* activeDriver; uint16_t rcnt; union {

@@ -64,6 +72,8 @@ };

}; void GBASIOInit(struct GBASIO* sio); +void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers); +void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode); void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value); void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value);
M src/gba/gba-thread.csrc/gba/gba-thread.c

@@ -99,6 +99,8 @@ GBAAttachDebugger(&gba, threadContext->debugger);

ARMDebuggerEnter(threadContext->debugger, DEBUGGER_ENTER_ATTACHED); } + GBASIOSetDriverSet(&gba.sio, &threadContext->sioDrivers); + gba.keySource = &threadContext->activeKeys; if (threadContext->startCallback) {
M src/gba/gba-thread.hsrc/gba/gba-thread.h

@@ -36,6 +36,7 @@ struct GBA* gba;

// Input struct GBAVideoRenderer* renderer; + struct GBASIODriverSet sioDrivers; struct ARMDebugger* debugger; int fd; int biosFd;