mirror of https://github.com/mgba-emu/mgba.git
Fill out SIO driver infrastructure
This commit is contained in:
parent
70e1661342
commit
e5ee1aa07f
|
@ -2,14 +2,34 @@
|
|||
|
||||
#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 @@ void GBASIOInit(struct GBASIO* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,24 +12,32 @@ enum GBASIOMode {
|
|||
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 @@ struct GBASIO {
|
|||
};
|
||||
|
||||
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);
|
||||
|
|
|
@ -99,6 +99,8 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
|||
ARMDebuggerEnter(threadContext->debugger, DEBUGGER_ENTER_ATTACHED);
|
||||
}
|
||||
|
||||
GBASIOSetDriverSet(&gba.sio, &threadContext->sioDrivers);
|
||||
|
||||
gba.keySource = &threadContext->activeKeys;
|
||||
|
||||
if (threadContext->startCallback) {
|
||||
|
|
|
@ -36,6 +36,7 @@ struct GBAThread {
|
|||
|
||||
// Input
|
||||
struct GBAVideoRenderer* renderer;
|
||||
struct GBASIODriverSet sioDrivers;
|
||||
struct ARMDebugger* debugger;
|
||||
int fd;
|
||||
int biosFd;
|
||||
|
|
Loading…
Reference in New Issue