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"
|
#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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue