GBA SIO: Remove driver sets and driver load/unload concepts

This commit is contained in:
Vicki Pfau 2024-09-10 03:19:02 -07:00
parent f2bbf8e66c
commit 0823797671
12 changed files with 77 additions and 199 deletions

View File

@ -111,8 +111,6 @@ struct GBASIODriver {
bool (*init)(struct GBASIODriver* driver); bool (*init)(struct GBASIODriver* driver);
void (*deinit)(struct GBASIODriver* driver); void (*deinit)(struct GBASIODriver* driver);
void (*reset)(struct GBASIODriver* driver); void (*reset)(struct GBASIODriver* driver);
bool (*load)(struct GBASIODriver* driver);
bool (*unload)(struct GBASIODriver* driver);
uint32_t (*driverId)(const struct GBASIODriver* renderer); uint32_t (*driverId)(const struct GBASIODriver* renderer);
bool (*loadState)(struct GBASIODriver* renderer, const void* state, size_t size); bool (*loadState)(struct GBASIODriver* renderer, const void* state, size_t size);
void (*saveState)(struct GBASIODriver* renderer, void** state, size_t* size); void (*saveState)(struct GBASIODriver* renderer, void** state, size_t* size);

View File

@ -62,18 +62,11 @@ DECL_BIT(GBASIORegisterRCNT, SdDirection, 5);
DECL_BIT(GBASIORegisterRCNT, SiDirection, 6); DECL_BIT(GBASIORegisterRCNT, SiDirection, 6);
DECL_BIT(GBASIORegisterRCNT, SoDirection, 7); DECL_BIT(GBASIORegisterRCNT, SoDirection, 7);
struct GBASIODriverSet {
struct GBASIODriver* normal;
struct GBASIODriver* multiplayer;
struct GBASIODriver* joybus;
};
struct GBASIO { struct GBASIO {
struct GBA* p; struct GBA* p;
enum GBASIOMode mode; enum GBASIOMode mode;
struct GBASIODriverSet drivers; struct GBASIODriver* driver;
struct GBASIODriver* activeDriver;
uint16_t rcnt; uint16_t rcnt;
uint16_t siocnt; uint16_t siocnt;
@ -86,8 +79,7 @@ void GBASIOInit(struct GBASIO* sio);
void GBASIODeinit(struct GBASIO* sio); void GBASIODeinit(struct GBASIO* sio);
void GBASIOReset(struct GBASIO* sio); void GBASIOReset(struct GBASIO* sio);
void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers); void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver);
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

@ -527,7 +527,7 @@ void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASer
uint32_t when; uint32_t when;
LOAD_32(when, 0, &state->hw.sioNextEvent); LOAD_32(when, 0, &state->hw.sioNextEvent);
if (hw->devices & HW_GB_PLAYER) { if (hw->devices & HW_GB_PLAYER) {
GBASIOSetDriver(&hw->p->sio, &hw->p->sio.gbp.d, GBA_SIO_NORMAL_32); GBASIOSetDriver(&hw->p->sio, &hw->p->sio.gbp.d);
} }
if ((hw->p->memory.io[GBA_REG(SIOCNT)] & 0x0080) && when < 0x20000) { if ((hw->p->memory.io[GBA_REG(SIOCNT)] & 0x0080) && when < 0x20000) {
mTimingSchedule(&hw->p->timing, &hw->p->sio.completeEvent, when); mTimingSchedule(&hw->p->timing, &hw->p->sio.completeEvent, when);

View File

@ -848,13 +848,13 @@ static bool _GBACoreLoadExtraState(struct mCore* core, const struct mStateExtdat
ok = false; ok = false;
} }
} }
if (gba->sio.activeDriver && gba->sio.activeDriver->driverId && gba->sio.activeDriver->loadState && if (gba->sio.driver && gba->sio.driver->driverId && gba->sio.driver->loadState &&
mStateExtdataGet(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_SIO_DRIVER, &item)) { mStateExtdataGet(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_SIO_DRIVER, &item)) {
if ((uint32_t) item.size > sizeof(uint32_t)) { if ((uint32_t) item.size > sizeof(uint32_t)) {
uint32_t type; uint32_t type;
LOAD_32(type, 0, item.data); LOAD_32(type, 0, item.data);
if (type == gba->sio.activeDriver->driverId(gba->sio.activeDriver)) { if (type == gba->sio.driver->driverId(gba->sio.driver)) {
ok = gba->sio.activeDriver->loadState(gba->sio.activeDriver, ok = gba->sio.driver->loadState(gba->sio.driver,
(void*) ((uintptr_t) item.data + sizeof(uint32_t)), (void*) ((uintptr_t) item.data + sizeof(uint32_t)),
item.size - sizeof(type)) && ok; item.size - sizeof(type)) && ok;
} }
@ -886,14 +886,14 @@ static bool _GBACoreSaveExtraState(struct mCore* core, struct mStateExtdata* ext
} }
size = 0; size = 0;
if (gba->sio.activeDriver && gba->sio.activeDriver->driverId && gba->sio.activeDriver->saveState) { if (gba->sio.driver && gba->sio.driver->driverId && gba->sio.driver->saveState) {
gba->sio.activeDriver->saveState(gba->sio.activeDriver, &buffer, &size); gba->sio.driver->saveState(gba->sio.driver, &buffer, &size);
if (size > 0 && buffer) { if (size > 0 && buffer) {
struct mStateExtdataItem item; struct mStateExtdataItem item;
item.size = size + sizeof(uint32_t); item.size = size + sizeof(uint32_t);
item.data = malloc(item.size); item.data = malloc(item.size);
item.clean = free; item.clean = free;
uint32_t type = gba->sio.activeDriver->driverId(gba->sio.activeDriver); uint32_t type = gba->sio.driver->driverId(gba->sio.driver);
STORE_32(type, 0, item.data); STORE_32(type, 0, item.data);
memcpy((void*) ((uintptr_t) item.data + sizeof(uint32_t)), buffer, size); memcpy((void*) ((uintptr_t) item.data + sizeof(uint32_t)), buffer, size);
mStateExtdataPut(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_SIO_DRIVER, &item); mStateExtdataPut(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_SIO_DRIVER, &item);
@ -963,8 +963,7 @@ static void _GBACoreSetPeripheral(struct mCore* core, int type, void* periph) {
gba->luminanceSource = periph; gba->luminanceSource = periph;
break; break;
case mPERIPH_GBA_BATTLECHIP_GATE: case mPERIPH_GBA_BATTLECHIP_GATE:
GBASIOSetDriver(&gba->sio, periph, GBA_SIO_MULTI); GBASIOSetDriver(&gba->sio, periph);
GBASIOSetDriver(&gba->sio, periph, GBA_SIO_NORMAL_32);
break; break;
default: default:
return; return;

View File

@ -33,7 +33,7 @@ enum {
BATTLECHIP_CONTINUE = 0xFFFF, BATTLECHIP_CONTINUE = 0xFFFF,
}; };
static bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver); static bool GBASIOBattlechipGateInit(struct GBASIODriver* driver);
static uint16_t GBASIOBattlechipGateWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); static uint16_t GBASIOBattlechipGateWriteSIOCNT(struct GBASIODriver* driver, uint16_t value);
static bool GBASIOBattlechipGateHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); static bool GBASIOBattlechipGateHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode);
static int GBASIOBattlechipGateConnectedDevices(struct GBASIODriver* driver); static int GBASIOBattlechipGateConnectedDevices(struct GBASIODriver* driver);
@ -41,7 +41,7 @@ static void GBASIOBattlechipGateFinishMultiplayer(struct GBASIODriver* driver, u
void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate* gate) { void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate* gate) {
memset(&gate->d, 0, sizeof(gate->d)); memset(&gate->d, 0, sizeof(gate->d));
gate->d.load = GBASIOBattlechipGateLoad; gate->d.init = GBASIOBattlechipGateInit;
gate->d.writeSIOCNT = GBASIOBattlechipGateWriteSIOCNT; gate->d.writeSIOCNT = GBASIOBattlechipGateWriteSIOCNT;
gate->d.handlesMode = GBASIOBattlechipGateHandlesMode; gate->d.handlesMode = GBASIOBattlechipGateHandlesMode;
gate->d.connectedDevices = GBASIOBattlechipGateConnectedDevices; gate->d.connectedDevices = GBASIOBattlechipGateConnectedDevices;
@ -51,7 +51,7 @@ void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate* gate) {
gate->flavor = GBA_FLAVOR_BATTLECHIP_GATE; gate->flavor = GBA_FLAVOR_BATTLECHIP_GATE;
} }
bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver) { bool GBASIOBattlechipGateInit(struct GBASIODriver* driver) {
struct GBASIOBattlechipGate* gate = (struct GBASIOBattlechipGate*) driver; struct GBASIOBattlechipGate* gate = (struct GBASIOBattlechipGate*) driver;
gate->state = BATTLECHIP_STATE_SYNC; gate->state = BATTLECHIP_STATE_SYNC;
gate->data[0] = 0x00FE; gate->data[0] = 0x00FE;

View File

@ -263,8 +263,8 @@ void GBAReset(struct ARMCore* cpu) {
// GB Player SIO control should not be engaged before detection, even if we already know it's GBP // GB Player SIO control should not be engaged before detection, even if we already know it's GBP
gba->memory.hw.devices &= ~HW_GB_PLAYER; gba->memory.hw.devices &= ~HW_GB_PLAYER;
if (gba->sio.drivers.normal == &gba->sio.gbp.d) { if (gba->sio.driver == &gba->sio.gbp.d) {
GBASIOSetDriver(&gba->sio, NULL, GBA_SIO_NORMAL_32); GBASIOSetDriver(&gba->sio, NULL);
} }
bool isELF = false; bool isELF = false;

View File

@ -20,20 +20,6 @@ static const int GBASIOCyclesPerTransfer[4][MAX_GBAS] = {
static void _sioFinish(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _sioFinish(struct mTiming* timing, void* user, uint32_t cyclesLate);
static struct GBASIODriver* _lookupDriver(struct GBASIO* sio, enum GBASIOMode mode) {
switch (mode) {
case GBA_SIO_NORMAL_8:
case GBA_SIO_NORMAL_32:
return sio->drivers.normal;
case GBA_SIO_MULTI:
return sio->drivers.multiplayer;
case GBA_SIO_JOYBUS:
return sio->drivers.joybus;
default:
return 0;
}
}
static const char* _modeName(enum GBASIOMode mode) { static const char* _modeName(enum GBASIOMode mode) {
switch (mode) { switch (mode) {
case GBA_SIO_NORMAL_8: case GBA_SIO_NORMAL_8:
@ -60,31 +46,19 @@ static void _switchMode(struct GBASIO* sio) {
newMode = (enum GBASIOMode) (mode & 0xC); newMode = (enum GBASIOMode) (mode & 0xC);
} }
if (newMode != sio->mode) { if (newMode != sio->mode) {
struct GBASIODriver* driver = _lookupDriver(sio, newMode);
if (sio->mode != (enum GBASIOMode) -1) { if (sio->mode != (enum GBASIOMode) -1) {
mLOG(GBA_SIO, DEBUG, "Switching mode from %s to %s", _modeName(sio->mode), _modeName(newMode)); mLOG(GBA_SIO, DEBUG, "Switching mode from %s to %s", _modeName(sio->mode), _modeName(newMode));
} }
if (driver != sio->activeDriver || (driver && !driver->setMode)) {
if (sio->activeDriver && sio->activeDriver->unload) {
sio->activeDriver->unload(sio->activeDriver);
}
sio->mode = newMode; sio->mode = newMode;
sio->activeDriver = driver; if (sio->driver && sio->driver->setMode) {
if (sio->activeDriver && sio->activeDriver->load) { sio->driver->setMode(sio->driver, newMode);
sio->activeDriver->load(sio->activeDriver);
}
} else {
sio->mode = newMode;
if (sio->activeDriver && sio->activeDriver->setMode) {
sio->activeDriver->setMode(sio->activeDriver, newMode);
}
} }
int id = 0; int id = 0;
switch (newMode) { switch (newMode) {
case GBA_SIO_MULTI: case GBA_SIO_MULTI:
if (sio->activeDriver && sio->activeDriver->deviceId) { if (sio->driver && sio->driver->deviceId) {
id = sio->activeDriver->deviceId(sio->activeDriver); id = sio->driver->deviceId(sio->driver);
} }
sio->rcnt = GBASIORegisterRCNTSetSi(sio->rcnt, !!id); sio->rcnt = GBASIORegisterRCNTSetSi(sio->rcnt, !!id);
break; break;
@ -96,10 +70,7 @@ static void _switchMode(struct GBASIO* sio) {
} }
void GBASIOInit(struct GBASIO* sio) { void GBASIOInit(struct GBASIO* sio) {
sio->drivers.normal = NULL; sio->driver = NULL;
sio->drivers.multiplayer = NULL;
sio->drivers.joybus = NULL;
sio->activeDriver = NULL;
sio->completeEvent.context = sio; sio->completeEvent.context = sio;
sio->completeEvent.name = "GBA SIO Complete"; sio->completeEvent.name = "GBA SIO Complete";
@ -113,73 +84,28 @@ void GBASIOInit(struct GBASIO* sio) {
} }
void GBASIODeinit(struct GBASIO* sio) { void GBASIODeinit(struct GBASIO* sio) {
if (sio->activeDriver && sio->activeDriver->unload) { if (sio->driver && sio->driver->deinit) {
sio->activeDriver->unload(sio->activeDriver); sio->driver->deinit(sio->driver);
}
if (sio->drivers.multiplayer && sio->drivers.multiplayer->deinit) {
sio->drivers.multiplayer->deinit(sio->drivers.multiplayer);
}
if (sio->drivers.joybus && sio->drivers.joybus->deinit) {
sio->drivers.joybus->deinit(sio->drivers.joybus);
}
if (sio->drivers.normal && sio->drivers.normal->deinit) {
sio->drivers.normal->deinit(sio->drivers.normal);
} }
} }
void GBASIOReset(struct GBASIO* sio) { void GBASIOReset(struct GBASIO* sio) {
if (sio->activeDriver && sio->activeDriver->unload) { if (sio->driver && sio->driver->reset) {
sio->activeDriver->unload(sio->activeDriver); sio->driver->reset(sio->driver);
}
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->rcnt = RCNT_INITIAL;
sio->siocnt = 0; sio->siocnt = 0;
sio->mode = -1; sio->mode = -1;
sio->activeDriver = NULL;
_switchMode(sio); _switchMode(sio);
GBASIOPlayerReset(&sio->gbp); GBASIOPlayerReset(&sio->gbp);
} }
void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers) { void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver) {
GBASIOSetDriver(sio, drivers->normal, GBA_SIO_NORMAL_8); if (sio->driver && sio->driver->deinit) {
GBASIOSetDriver(sio, drivers->multiplayer, GBA_SIO_MULTI); sio->driver->deinit(sio->driver);
GBASIOSetDriver(sio, drivers->joybus, GBA_SIO_JOYBUS);
}
void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode) {
struct GBASIODriver** driverLoc;
switch (mode) {
case GBA_SIO_NORMAL_8:
case GBA_SIO_NORMAL_32:
driverLoc = &sio->drivers.normal;
break;
case GBA_SIO_MULTI:
driverLoc = &sio->drivers.multiplayer;
break;
case GBA_SIO_JOYBUS:
driverLoc = &sio->drivers.joybus;
break;
default:
mLOG(GBA_SIO, ERROR, "Setting an unsupported SIO driver: %x", mode);
return;
}
if (*driverLoc) {
if ((*driverLoc)->unload) {
(*driverLoc)->unload(*driverLoc);
}
if ((*driverLoc)->deinit) {
(*driverLoc)->deinit(*driverLoc);
}
} }
sio->driver = driver;
if (driver) { if (driver) {
driver->p = sio; driver->p = sio;
@ -191,26 +117,19 @@ void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASI
} }
} }
} }
if (sio->activeDriver == *driverLoc) {
sio->activeDriver = driver;
if (driver && driver->load) {
driver->load(driver);
}
}
*driverLoc = driver;
} }
void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) { void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) {
sio->rcnt &= 0x1FF; sio->rcnt &= 0x1FF;
sio->rcnt |= value & 0xC000; sio->rcnt |= value & 0xC000;
_switchMode(sio); _switchMode(sio);
if (sio->activeDriver && sio->activeDriver->writeRCNT) { if (sio->driver && sio->driver->writeRCNT) {
switch (sio->mode) { switch (sio->mode) {
case GBA_SIO_GPIO: case GBA_SIO_GPIO:
sio->rcnt = (sio->activeDriver->writeRCNT(sio->activeDriver, value) & 0x01FF) | (sio->rcnt & 0xC000); sio->rcnt = (sio->driver->writeRCNT(sio->driver, value) & 0x01FF) | (sio->rcnt & 0xC000);
break; break;
default: default:
sio->rcnt = (sio->activeDriver->writeRCNT(sio->activeDriver, value) & 0x01F0) | (sio->rcnt & 0xC00F); sio->rcnt = (sio->driver->writeRCNT(sio->driver, value) & 0x01F0) | (sio->rcnt & 0xC00F);
} }
} else if (sio->mode == GBA_SIO_GPIO) { } else if (sio->mode == GBA_SIO_GPIO) {
sio->rcnt &= 0xC000; sio->rcnt &= 0xC000;
@ -222,15 +141,15 @@ void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) {
} }
static void _startTransfer(struct GBASIO* sio) { static void _startTransfer(struct GBASIO* sio) {
if (sio->activeDriver && sio->activeDriver->start) { if (sio->driver && sio->driver->start) {
if (!sio->activeDriver->start(sio->activeDriver)) { if (!sio->driver->start(sio->driver)) {
// Transfer completion is handled internally to the driver // Transfer completion is handled internally to the driver
return; return;
} }
} }
int connected = 0; int connected = 0;
if (sio->activeDriver && sio->activeDriver->connectedDevices) { if (sio->driver && sio->driver->connectedDevices) {
connected = sio->activeDriver->connectedDevices(sio->activeDriver); connected = sio->driver->connectedDevices(sio->driver);
} }
mTimingDeschedule(&sio->p->timing, &sio->completeEvent); mTimingDeschedule(&sio->p->timing, &sio->completeEvent);
mTimingSchedule(&sio->p->timing, &sio->completeEvent, GBASIOTransferCycles(sio->mode, sio->siocnt, connected)); mTimingSchedule(&sio->p->timing, &sio->completeEvent, GBASIOTransferCycles(sio->mode, sio->siocnt, connected));
@ -244,14 +163,14 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
int id = 0; int id = 0;
int connected = 0; int connected = 0;
bool handled = false; bool handled = false;
if (sio->activeDriver) { if (sio->driver) {
handled = sio->activeDriver->handlesMode(sio->activeDriver, sio->mode); handled = sio->driver->handlesMode(sio->driver, sio->mode);
if (handled) { if (handled) {
if (sio->activeDriver->deviceId) { if (sio->driver->deviceId) {
id = sio->activeDriver->deviceId(sio->activeDriver); id = sio->driver->deviceId(sio->driver);
} }
connected = sio->activeDriver->connectedDevices(sio->activeDriver); connected = sio->driver->connectedDevices(sio->driver);
handled = !!sio->activeDriver->writeSIOCNT; handled = !!sio->driver->writeSIOCNT;
} }
} }
@ -304,7 +223,7 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
break; break;
} }
if (handled) { if (handled) {
value = sio->activeDriver->writeSIOCNT(sio->activeDriver, value); value = sio->driver->writeSIOCNT(sio->driver, value);
} else { } else {
// Dummy drivers // Dummy drivers
switch (sio->mode) { switch (sio->mode) {
@ -325,8 +244,8 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
uint16_t GBASIOWriteRegister(struct GBASIO* sio, uint32_t address, uint16_t value) { uint16_t GBASIOWriteRegister(struct GBASIO* sio, uint32_t address, uint16_t value) {
int id = 0; int id = 0;
if (sio->activeDriver && sio->activeDriver->deviceId) { if (sio->driver && sio->driver->deviceId) {
id = sio->activeDriver->deviceId(sio->activeDriver); id = sio->driver->deviceId(sio->driver);
} }
bool handled = true; bool handled = true;
@ -455,8 +374,8 @@ int32_t GBASIOTransferCycles(enum GBASIOMode mode, uint16_t siocnt, int connecte
void GBASIOMultiplayerFinishTransfer(struct GBASIO* sio, uint16_t data[4], uint32_t cyclesLate) { void GBASIOMultiplayerFinishTransfer(struct GBASIO* sio, uint16_t data[4], uint32_t cyclesLate) {
int id = 0; int id = 0;
if (sio->activeDriver && sio->activeDriver->deviceId) { if (sio->driver && sio->driver->deviceId) {
id = sio->activeDriver->deviceId(sio->activeDriver); id = sio->driver->deviceId(sio->driver);
} }
sio->p->memory.io[GBA_REG(SIOMULTI0)] = data[0]; sio->p->memory.io[GBA_REG(SIOMULTI0)] = data[0];
sio->p->memory.io[GBA_REG(SIOMULTI1)] = data[1]; sio->p->memory.io[GBA_REG(SIOMULTI1)] = data[1];
@ -500,20 +419,20 @@ static void _sioFinish(struct mTiming* timing, void* user, uint32_t cyclesLate)
} data = {0}; } data = {0};
switch (sio->mode) { switch (sio->mode) {
case GBA_SIO_MULTI: case GBA_SIO_MULTI:
if (sio->activeDriver && sio->activeDriver->finishMultiplayer) { if (sio->driver && sio->driver->finishMultiplayer) {
sio->activeDriver->finishMultiplayer(sio->activeDriver, data.multi); sio->driver->finishMultiplayer(sio->driver, data.multi);
} }
GBASIOMultiplayerFinishTransfer(sio, data.multi, cyclesLate); GBASIOMultiplayerFinishTransfer(sio, data.multi, cyclesLate);
break; break;
case GBA_SIO_NORMAL_8: case GBA_SIO_NORMAL_8:
if (sio->activeDriver && sio->activeDriver->finishNormal8) { if (sio->driver && sio->driver->finishNormal8) {
data.normal8 = sio->activeDriver->finishNormal8(sio->activeDriver); data.normal8 = sio->driver->finishNormal8(sio->driver);
} }
GBASIONormal8FinishTransfer(sio, data.normal8, cyclesLate); GBASIONormal8FinishTransfer(sio, data.normal8, cyclesLate);
break; break;
case GBA_SIO_NORMAL_32: case GBA_SIO_NORMAL_32:
if (sio->activeDriver && sio->activeDriver->finishNormal32) { if (sio->driver && sio->driver->finishNormal32) {
data.normal32 = sio->activeDriver->finishNormal32(sio->activeDriver); data.normal32 = sio->driver->finishNormal32(sio->driver);
} }
GBASIONormal32FinishTransfer(sio, data.normal32, cyclesLate); GBASIONormal32FinishTransfer(sio, data.normal32, cyclesLate);
break; break;

View File

@ -23,8 +23,8 @@ enum {
}; };
static bool GBASIODolphinInit(struct GBASIODriver* driver); static bool GBASIODolphinInit(struct GBASIODriver* driver);
static bool GBASIODolphinLoad(struct GBASIODriver* driver); static void GBASIODolphinReset(struct GBASIODriver* driver);
static bool GBASIODolphinUnload(struct GBASIODriver* driver); static void GBASIODolphinSetMode(struct GBASIODriver* driver, enum GBASIOMode mode);
static bool GBASIODolphinHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); static bool GBASIODolphinHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode);
static int GBASIODolphinConnectedDevices(struct GBASIODriver* driver); static int GBASIODolphinConnectedDevices(struct GBASIODriver* driver);
static void GBASIODolphinProcessEvents(struct mTiming* timing, void* context, uint32_t cyclesLate); static void GBASIODolphinProcessEvents(struct mTiming* timing, void* context, uint32_t cyclesLate);
@ -35,8 +35,8 @@ static void _flush(struct GBASIODolphin* dol);
void GBASIODolphinCreate(struct GBASIODolphin* dol) { void GBASIODolphinCreate(struct GBASIODolphin* dol) {
memset(&dol->d, 0, sizeof(dol->d)); memset(&dol->d, 0, sizeof(dol->d));
dol->d.init = GBASIODolphinInit; dol->d.init = GBASIODolphinInit;
dol->d.load = GBASIODolphinLoad; dol->d.reset = GBASIODolphinReset;
dol->d.unload = GBASIODolphinUnload; dol->d.setMode = GBASIODolphinSetMode;
dol->d.handlesMode = GBASIODolphinHandlesMode; dol->d.handlesMode = GBASIODolphinHandlesMode;
dol->d.connectedDevices = GBASIODolphinConnectedDevices; dol->d.connectedDevices = GBASIODolphinConnectedDevices;
dol->event.context = dol; dol->event.context = dol;
@ -98,26 +98,23 @@ bool GBASIODolphinConnect(struct GBASIODolphin* dol, const struct Address* addre
static bool GBASIODolphinInit(struct GBASIODriver* driver) { static bool GBASIODolphinInit(struct GBASIODriver* driver) {
struct GBASIODolphin* dol = (struct GBASIODolphin*) driver; struct GBASIODolphin* dol = (struct GBASIODolphin*) driver;
dol->active = false;
dol->clockSlice = 0; dol->clockSlice = 0;
dol->state = WAIT_FOR_FIRST_CLOCK; dol->state = WAIT_FOR_FIRST_CLOCK;
_flush(dol); GBASIODolphinReset(driver);
return true; return true;
} }
static bool GBASIODolphinLoad(struct GBASIODriver* driver) { static void GBASIODolphinReset(struct GBASIODriver* driver) {
struct GBASIODolphin* dol = (struct GBASIODolphin*) driver; struct GBASIODolphin* dol = (struct GBASIODolphin*) driver;
dol->active = true; dol->active = false;
_flush(dol); _flush(dol);
mTimingDeschedule(&dol->d.p->p->timing, &dol->event); mTimingDeschedule(&dol->d.p->p->timing, &dol->event);
mTimingSchedule(&dol->d.p->p->timing, &dol->event, 0); mTimingSchedule(&dol->d.p->p->timing, &dol->event, 0);
return true;
} }
static bool GBASIODolphinUnload(struct GBASIODriver* driver) { static void GBASIODolphinSetMode(struct GBASIODriver* driver, enum GBASIOMode mode) {
struct GBASIODolphin* dol = (struct GBASIODolphin*) driver; struct GBASIODolphin* dol = (struct GBASIODolphin*) driver;
dol->active = false; dol->active = mode == GBA_SIO_JOYBUS;
return true;
} }
static bool GBASIODolphinHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) { static bool GBASIODolphinHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) {

View File

@ -55,8 +55,8 @@ void GBASIOPlayerInit(struct GBASIOPlayer* gbp) {
} }
void GBASIOPlayerReset(struct GBASIOPlayer* gbp) { void GBASIOPlayerReset(struct GBASIOPlayer* gbp) {
if (gbp->p->sio.drivers.normal == &gbp->d) { if (gbp->p->sio.driver == &gbp->d) {
GBASIOSetDriver(&gbp->p->sio, NULL, GBA_SIO_NORMAL_32); GBASIOSetDriver(&gbp->p->sio, NULL);
} }
} }
@ -88,7 +88,7 @@ void GBASIOPlayerUpdate(struct GBA* gba) {
gba->sio.gbp.oldCallback = gba->keyCallback; gba->sio.gbp.oldCallback = gba->keyCallback;
gba->keyCallback = &gba->sio.gbp.callback.d; gba->keyCallback = &gba->sio.gbp.callback.d;
// TODO: Check if the SIO driver is actually used first // TODO: Check if the SIO driver is actually used first
GBASIOSetDriver(&gba->sio, &gba->sio.gbp.d, GBA_SIO_NORMAL_32); GBASIOSetDriver(&gba->sio, &gba->sio.gbp.d);
} }
} }

View File

@ -79,8 +79,6 @@ static_assert(sizeof(struct GBASIOLockstepSerializedState) == 0x1F0, "GBA lockst
static bool GBASIOLockstepDriverInit(struct GBASIODriver* driver); static bool GBASIOLockstepDriverInit(struct GBASIODriver* driver);
static void GBASIOLockstepDriverDeinit(struct GBASIODriver* driver); static void GBASIOLockstepDriverDeinit(struct GBASIODriver* driver);
static void GBASIOLockstepDriverReset(struct GBASIODriver* driver); static void GBASIOLockstepDriverReset(struct GBASIODriver* driver);
static bool GBASIOLockstepDriverLoad(struct GBASIODriver* driver);
static bool GBASIOLockstepDriverUnload(struct GBASIODriver* driver);
static uint32_t GBASIOLockstepDriverId(const struct GBASIODriver* driver); static uint32_t GBASIOLockstepDriverId(const struct GBASIODriver* driver);
static bool GBASIOLockstepDriverLoadState(struct GBASIODriver* driver, const void* state, size_t size); static bool GBASIOLockstepDriverLoadState(struct GBASIODriver* driver, const void* state, size_t size);
static void GBASIOLockstepDriverSaveState(struct GBASIODriver* driver, void** state, size_t* size); static void GBASIOLockstepDriverSaveState(struct GBASIODriver* driver, void** state, size_t* size);
@ -119,8 +117,6 @@ void GBASIOLockstepDriverCreate(struct GBASIOLockstepDriver* driver, struct mLoc
driver->d.init = GBASIOLockstepDriverInit; driver->d.init = GBASIOLockstepDriverInit;
driver->d.deinit = GBASIOLockstepDriverDeinit; driver->d.deinit = GBASIOLockstepDriverDeinit;
driver->d.reset = GBASIOLockstepDriverReset; driver->d.reset = GBASIOLockstepDriverReset;
driver->d.load = GBASIOLockstepDriverLoad;
driver->d.unload = GBASIOLockstepDriverUnload;
driver->d.driverId = GBASIOLockstepDriverId; driver->d.driverId = GBASIOLockstepDriverId;
driver->d.loadState = GBASIOLockstepDriverLoadState; driver->d.loadState = GBASIOLockstepDriverLoadState;
driver->d.saveState = GBASIOLockstepDriverSaveState; driver->d.saveState = GBASIOLockstepDriverSaveState;
@ -220,27 +216,6 @@ static void GBASIOLockstepDriverReset(struct GBASIODriver* driver) {
mTimingSchedule(&lockstep->d.p->p->timing, &lockstep->event, nextEvent); mTimingSchedule(&lockstep->d.p->p->timing, &lockstep->event, nextEvent);
} }
static bool GBASIOLockstepDriverLoad(struct GBASIODriver* driver) {
struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver;
if (lockstep->lockstepId) {
struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator;
MutexLock(&coordinator->mutex);
struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId);
_setReady(coordinator, player, 0, coordinator->transferMode);
MutexUnlock(&coordinator->mutex);
GBASIOLockstepDriverSetMode(driver, driver->p->mode);
}
return true;
}
static bool GBASIOLockstepDriverUnload(struct GBASIODriver* driver) {
struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver;
if (lockstep->lockstepId) {
GBASIOLockstepDriverSetMode(driver, -1);
}
return true;
}
static uint32_t GBASIOLockstepDriverId(const struct GBASIODriver* driver) { static uint32_t GBASIOLockstepDriverId(const struct GBASIODriver* driver) {
UNUSED(driver); UNUSED(driver);
return DRIVER_ID; return DRIVER_ID;

View File

@ -424,7 +424,7 @@ bool CoreController::attachDolphin(const Address& address) {
} }
if (GBASIODolphinConnect(&m_dolphin, &address, 0, 0)) { if (GBASIODolphinConnect(&m_dolphin, &address, 0, 0)) {
GBA* gba = static_cast<GBA*>(m_threadContext.core->board); GBA* gba = static_cast<GBA*>(m_threadContext.core->board);
GBASIOSetDriver(&gba->sio, &m_dolphin.d, GBA_SIO_JOYBUS); GBASIOSetDriver(&gba->sio, &m_dolphin.d);
return true; return true;
} }
return false; return false;
@ -433,7 +433,8 @@ bool CoreController::attachDolphin(const Address& address) {
void CoreController::detachDolphin() { void CoreController::detachDolphin() {
if (platform() == mPLATFORM_GBA) { if (platform() == mPLATFORM_GBA) {
GBA* gba = static_cast<GBA*>(m_threadContext.core->board); GBA* gba = static_cast<GBA*>(m_threadContext.core->board);
GBASIOSetDriver(&gba->sio, nullptr, GBA_SIO_JOYBUS); // TODO: Reattach to multiplayer controller
GBASIOSetDriver(&gba->sio, nullptr);
} }
GBASIODolphinDestroy(&m_dolphin); GBASIODolphinDestroy(&m_dolphin);
} }

View File

@ -265,9 +265,7 @@ bool MultiplayerController::attachGame(CoreController* controller) {
GBASIOLockstepCoordinatorAttach(&m_gbaCoordinator, node); GBASIOLockstepCoordinatorAttach(&m_gbaCoordinator, node);
player.node.gba = node; player.node.gba = node;
GBASIOSetDriver(&gba->sio, &node->d, GBA_SIO_MULTI); GBASIOSetDriver(&gba->sio, &node->d);
GBASIOSetDriver(&gba->sio, &node->d, GBA_SIO_NORMAL_8);
GBASIOSetDriver(&gba->sio, &node->d, GBA_SIO_NORMAL_32);
break; break;
} }
#endif #endif
@ -356,10 +354,8 @@ void MultiplayerController::detachGame(CoreController* controller) {
#ifdef M_CORE_GBA #ifdef M_CORE_GBA
case mPLATFORM_GBA: { case mPLATFORM_GBA: {
GBA* gba = static_cast<GBA*>(thread->core->board); GBA* gba = static_cast<GBA*>(thread->core->board);
GBASIOLockstepDriver* node = reinterpret_cast<GBASIOLockstepDriver*>(gba->sio.drivers.multiplayer); GBASIOLockstepDriver* node = reinterpret_cast<GBASIOLockstepDriver*>(gba->sio.driver);
GBASIOSetDriver(&gba->sio, nullptr, GBA_SIO_MULTI); GBASIOSetDriver(&gba->sio, nullptr);
GBASIOSetDriver(&gba->sio, nullptr, GBA_SIO_NORMAL_8);
GBASIOSetDriver(&gba->sio, nullptr, GBA_SIO_NORMAL_32);
if (node) { if (node) {
GBASIOLockstepCoordinatorDetach(&m_gbaCoordinator, node); GBASIOLockstepCoordinatorDetach(&m_gbaCoordinator, node);
delete node->user; delete node->user;
@ -485,12 +481,13 @@ void MultiplayerController::fixOrder() {
switch (m_platform) { switch (m_platform) {
#ifdef M_CORE_GBA #ifdef M_CORE_GBA
case mPLATFORM_GBA: case mPLATFORM_GBA:
for (int pid : m_pids.keys()) { // TODO: fix
/*for (int pid : m_pids.keys()) {
Player& p = m_pids.find(pid).value(); Player& p = m_pids.find(pid).value();
GBA* gba = static_cast<GBA*>(p.controller->thread()->core->board); GBA* gba = static_cast<GBA*>(p.controller->thread()->core->board);
GBASIOLockstepDriver* node = reinterpret_cast<GBASIOLockstepDriver*>(gba->sio.drivers.multiplayer); GBASIOLockstepDriver* node = reinterpret_cast<GBASIOLockstepDriver*>(gba->sio.driver);
m_players[node->d.deviceId(&node->d)] = pid; m_players[node->d.deviceId(&node->d)] = pid;
} }*/
break; break;
#endif #endif
#ifdef M_CORE_GB #ifdef M_CORE_GB