Fill out SIO driver infrastructure

This commit is contained in:
Jeffrey Pfau 2014-02-04 01:28:16 -08:00
parent 70e1661342
commit e5ee1aa07f
4 changed files with 91 additions and 7 deletions

View File

@ -2,14 +2,34 @@
#include "gba-io.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) { static void _switchMode(struct GBASIO* sio) {
int mode = ((sio->rcnt >> 14) & 0xC) | ((sio->siocnt >> 12) & 0x3); int mode = ((sio->rcnt >> 14) & 0xC) | ((sio->siocnt >> 12) & 0x3);
enum GBASIOMode oldMode = sio->mode;
if (mode < 8) { if (mode < 8) {
sio->mode = (enum GBASIOMode) (mode & 0x3); sio->mode = (enum GBASIOMode) (mode & 0x3);
} else { } else {
sio->mode = (enum GBASIOMode) (mode & 0xC); 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) { void GBASIOInit(struct GBASIO* sio) {
@ -18,12 +38,63 @@ void GBASIOInit(struct GBASIO* sio) {
_switchMode(sio); _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) { void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) {
sio->rcnt = value; sio->rcnt = value;
_switchMode(sio); _switchMode(sio);
if (sio->activeDriver && sio->activeDriver->writeRegister) {
sio->activeDriver->writeRegister(sio->activeDriver, REG_RCNT, value);
}
} }
void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) { void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
sio->siocnt = value; sio->siocnt = value;
_switchMode(sio); _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);
}
} }

View File

@ -12,24 +12,32 @@ enum GBASIOMode {
SIO_JOYBUS = 12 SIO_JOYBUS = 12
}; };
enum GBASIOMultiMode {
VBA_LINK_COMPAT
};
enum { enum {
RCNT_INITIAL = 0x8000 RCNT_INITIAL = 0x8000
}; };
struct GBASIO;
struct GBASIODriver { struct GBASIODriver {
void (*init)(struct GBASIODriver* driver, struct GBASIO* sio);
void (*deinit)(struct GBASIODriver* driver);
int (*attach)(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 GBASIO {
struct GBA* p; struct GBA* p;
enum GBASIOMode mode; enum GBASIOMode mode;
enum GBASIOMultiMode multiMode; struct GBASIODriverSet drivers;
struct GBASIODriver* driver; struct GBASIODriver* activeDriver;
uint16_t rcnt; uint16_t rcnt;
union { union {
@ -64,6 +72,8 @@ struct GBASIO {
}; };
void GBASIOInit(struct GBASIO* sio); 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 GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value);
void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value); void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value);

View File

@ -99,6 +99,8 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
ARMDebuggerEnter(threadContext->debugger, DEBUGGER_ENTER_ATTACHED); ARMDebuggerEnter(threadContext->debugger, DEBUGGER_ENTER_ATTACHED);
} }
GBASIOSetDriverSet(&gba.sio, &threadContext->sioDrivers);
gba.keySource = &threadContext->activeKeys; gba.keySource = &threadContext->activeKeys;
if (threadContext->startCallback) { if (threadContext->startCallback) {

View File

@ -36,6 +36,7 @@ struct GBAThread {
// Input // Input
struct GBAVideoRenderer* renderer; struct GBAVideoRenderer* renderer;
struct GBASIODriverSet sioDrivers;
struct ARMDebugger* debugger; struct ARMDebugger* debugger;
int fd; int fd;
int biosFd; int biosFd;