GBA SIO: Move starting/end timing logic out of drivers

This commit is contained in:
Vicki Pfau 2024-05-27 23:11:22 -07:00
parent 435c4aa243
commit 621eb4d425
9 changed files with 104 additions and 103 deletions

View File

@ -119,6 +119,10 @@ struct GBASIODriver {
int (*deviceId)(struct GBASIODriver* driver); int (*deviceId)(struct GBASIODriver* driver);
uint16_t (*writeSIOCNT)(struct GBASIODriver* driver, uint16_t value); uint16_t (*writeSIOCNT)(struct GBASIODriver* driver, uint16_t value);
uint16_t (*writeRCNT)(struct GBASIODriver* driver, uint16_t value); uint16_t (*writeRCNT)(struct GBASIODriver* driver, uint16_t value);
bool (*start)(struct GBASIODriver* driver);
void (*finishMultiplayer)(struct GBASIODriver* driver, uint16_t data[4]);
uint8_t (*finishNormal8)(struct GBASIODriver* driver);
uint32_t (*finishNormal32)(struct GBASIODriver* driver);
}; };
enum GBASIOBattleChipGateFlavor { enum GBASIOBattleChipGateFlavor {
@ -130,7 +134,6 @@ enum GBASIOBattleChipGateFlavor {
struct GBASIOBattlechipGate { struct GBASIOBattlechipGate {
struct GBASIODriver d; struct GBASIODriver d;
struct mTimingEvent event;
uint16_t chipId; uint16_t chipId;
uint16_t data[2]; uint16_t data[2];
int state; int state;

View File

@ -191,7 +191,7 @@ mLOG_DECLARE_CATEGORY(GBA_STATE);
* | bits 2 - 3: GB Player inputs posted * | bits 2 - 3: GB Player inputs posted
* | bits 4 - 8: GB Player transmit position * | bits 4 - 8: GB Player transmit position
* | bits 9 - 23: Reserved * | bits 9 - 23: Reserved
* 0x002C4 - 0x002C7: Game Boy Player next event * 0x002C4 - 0x002C7: SIO next event
* 0x002C8 - 0x002CB: Current DMA transfer word * 0x002C8 - 0x002CB: Current DMA transfer word
* 0x002CC - 0x002CF: Last DMA transfer PC * 0x002CC - 0x002CF: Last DMA transfer PC
* 0x002D0 - 0x002DF: Matrix memory command buffer * 0x002D0 - 0x002DF: Matrix memory command buffer
@ -370,7 +370,7 @@ struct GBASerializedState {
uint8_t lightSample; uint8_t lightSample;
GBASerializedHWFlags2 flags2; GBASerializedHWFlags2 flags2;
GBASerializedHWFlags3 flags3; GBASerializedHWFlags3 flags3;
uint32_t gbpNextEvent; uint32_t sioNextEvent;
} hw; } hw;
uint32_t dmaTransferRegister; uint32_t dmaTransferRegister;

View File

@ -21,7 +21,6 @@ struct GBASIOPlayer {
struct GBA* p; struct GBA* p;
unsigned inputsPosted; unsigned inputsPosted;
int txPosition; int txPosition;
struct mTimingEvent event;
struct GBASIOPlayerKeyCallback callback; struct GBASIOPlayerKeyCallback callback;
bool oldOpposingDirections; bool oldOpposingDirections;
struct mKeyCallback* oldCallback; struct mKeyCallback* oldCallback;

View File

@ -486,10 +486,10 @@ void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASeria
flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState); flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter); flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
// GBP stuff is only here for legacy reasons // GBP/SIO stuff is only here for legacy reasons
flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->p->sio.gbp.inputsPosted); flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->p->sio.gbp.inputsPosted);
flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->p->sio.gbp.txPosition); flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->p->sio.gbp.txPosition);
STORE_32(hw->p->sio.gbp.event.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.gbpNextEvent); STORE_32(hw->p->sio.completeEvent.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.sioNextEvent);
state->hw.flags2 = flags2; state->hw.flags2 = flags2;
} }
@ -520,16 +520,16 @@ void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASer
hw->lightSample = state->hw.lightSample; hw->lightSample = state->hw.lightSample;
hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1); hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
// GBP stuff is only here for legacy reasons // GBP/SIO stuff is only here for legacy reasons
hw->p->sio.gbp.inputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2); hw->p->sio.gbp.inputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
hw->p->sio.gbp.txPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2); hw->p->sio.gbp.txPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
uint32_t when; uint32_t when;
LOAD_32(when, 0, &state->hw.gbpNextEvent); 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, GBA_SIO_NORMAL_32);
if (hw->p->memory.io[GBA_REG(SIOCNT)] & 0x0080) { }
mTimingSchedule(&hw->p->timing, &hw->p->sio.gbp.event, when); if ((hw->p->memory.io[GBA_REG(SIOCNT)] & 0x0080) && when < 0x20000) {
} mTimingSchedule(&hw->p->timing, &hw->p->sio.completeEvent, when);
} }
} }

View File

@ -37,25 +37,15 @@ static bool GBASIOBattlechipGateLoad(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);
static void GBASIOBattlechipGateFinishMultiplayer(struct GBASIODriver* driver, uint16_t data[4]);
static void _battlechipTransfer(struct GBASIOBattlechipGate* gate);
static void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cyclesLate);
void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate* gate) { void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate* gate) {
gate->d.init = NULL; memset(&gate->d, 0, sizeof(gate->d));
gate->d.deinit = NULL;
gate->d.load = GBASIOBattlechipGateLoad; gate->d.load = GBASIOBattlechipGateLoad;
gate->d.unload = NULL;
gate->d.writeSIOCNT = GBASIOBattlechipGateWriteSIOCNT; gate->d.writeSIOCNT = GBASIOBattlechipGateWriteSIOCNT;
gate->d.setMode = NULL;
gate->d.handlesMode = GBASIOBattlechipGateHandlesMode; gate->d.handlesMode = GBASIOBattlechipGateHandlesMode;
gate->d.connectedDevices = GBASIOBattlechipGateConnectedDevices; gate->d.connectedDevices = GBASIOBattlechipGateConnectedDevices;
gate->d.deviceId = NULL; gate->d.finishMultiplayer = GBASIOBattlechipGateFinishMultiplayer;
gate->d.writeRCNT = NULL;
gate->event.context = gate;
gate->event.callback = _battlechipTransferEvent;
gate->event.priority = 0x80;
gate->chipId = 0; gate->chipId = 0;
gate->flavor = GBA_FLAVOR_BATTLECHIP_GATE; gate->flavor = GBA_FLAVOR_BATTLECHIP_GATE;
@ -70,12 +60,9 @@ bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver) {
} }
uint16_t GBASIOBattlechipGateWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) { uint16_t GBASIOBattlechipGateWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) {
struct GBASIOBattlechipGate* gate = (struct GBASIOBattlechipGate*) driver; UNUSED(driver);
value &= ~0xC; value &= ~0xC;
value |= 0x8; value |= 0x8;
if (value & 0x80) {
_battlechipTransfer(gate);
}
return value; return value;
} }
@ -95,20 +82,8 @@ static int GBASIOBattlechipGateConnectedDevices(struct GBASIODriver* driver) {
return 1; return 1;
} }
void _battlechipTransfer(struct GBASIOBattlechipGate* gate) { static void GBASIOBattlechipGateFinishMultiplayer(struct GBASIODriver* driver, uint16_t data[4]) {
int32_t cycles = GBASIOTransferCycles(gate->d.p); struct GBASIOBattlechipGate* gate = (struct GBASIOBattlechipGate*) driver;
mTimingDeschedule(&gate->d.p->p->timing, &gate->event);
mTimingSchedule(&gate->d.p->p->timing, &gate->event, cycles);
}
void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cyclesLate) {
UNUSED(timing);
struct GBASIOBattlechipGate* gate = user;
if (gate->d.p->mode == GBA_SIO_NORMAL_32) {
GBASIONormal32FinishTransfer(gate->d.p, 0, cyclesLate);
return;
}
uint16_t cmd = gate->d.p->p->memory.io[GBA_REG(SIOMLT_SEND)]; uint16_t cmd = gate->d.p->p->memory.io[GBA_REG(SIOMLT_SEND)];
uint16_t reply = 0xFFFF; uint16_t reply = 0xFFFF;
@ -189,8 +164,8 @@ void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cycle
mLOG(GBA_BATTLECHIP, DEBUG, "Gate: %04X (%i)", reply, gate->state); mLOG(GBA_BATTLECHIP, DEBUG, "Gate: %04X (%i)", reply, gate->state);
++gate->state; ++gate->state;
uint16_t data[4] = { data[0] = cmd;
cmd, reply, 0xFFFF, 0xFFFF data[1] = reply;
}; data[2] = 0xFFFF;
GBASIOMultiplayerFinishTransfer(gate->d.p, data, cyclesLate); data[3] = 0xFFFF;
} }

View File

@ -221,6 +221,17 @@ void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) {
} }
} }
static void _startTransfer(struct GBASIO* sio) {
if (sio->activeDriver && sio->activeDriver->start) {
if (!sio->activeDriver->start(sio->activeDriver)) {
// Transfer completion is handled internally to the driver
return;
}
}
mTimingDeschedule(&sio->p->timing, &sio->completeEvent);
mTimingSchedule(&sio->p->timing, &sio->completeEvent, GBASIOTransferCycles(sio));
}
void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) { void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
if ((value ^ sio->siocnt) & 0x3000) { if ((value ^ sio->siocnt) & 0x3000) {
sio->siocnt = value & 0x3000; sio->siocnt = value & 0x3000;
@ -256,6 +267,18 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
// investigation than I managed, apparently. // investigation than I managed, apparently.
sio->rcnt = GBASIORegisterRCNTFillSc(sio->rcnt); sio->rcnt = GBASIORegisterRCNTFillSc(sio->rcnt);
if (GBASIOMultiplayerIsBusy(value) && !GBASIOMultiplayerIsBusy(sio->siocnt)) {
if (!id) {
sio->p->memory.io[GBA_REG(SIOMULTI0)] = 0xFFFF;
sio->p->memory.io[GBA_REG(SIOMULTI1)] = 0xFFFF;
sio->p->memory.io[GBA_REG(SIOMULTI2)] = 0xFFFF;
sio->p->memory.io[GBA_REG(SIOMULTI3)] = 0xFFFF;
sio->rcnt = GBASIORegisterRCNTClearSc(sio->rcnt);
_startTransfer(sio);
} else {
// TODO
}
}
break; break;
case GBA_SIO_NORMAL_8: case GBA_SIO_NORMAL_8:
case GBA_SIO_NORMAL_32: case GBA_SIO_NORMAL_32:
@ -264,6 +287,13 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
if (GBASIONormalGetSc(value)) { if (GBASIONormalGetSc(value)) {
sio->rcnt = GBASIORegisterRCNTFillSc(sio->rcnt); sio->rcnt = GBASIORegisterRCNTFillSc(sio->rcnt);
} }
if (GBASIONormalIsStart(value) && !GBASIONormalIsStart(sio->siocnt)) {
if (GBASIONormalIsSc(value)) {
_startTransfer(sio);
} else {
// TODO
}
}
break; break;
default: default:
// TODO // TODO
@ -277,15 +307,6 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
case GBA_SIO_NORMAL_8: case GBA_SIO_NORMAL_8:
case GBA_SIO_NORMAL_32: case GBA_SIO_NORMAL_32:
value = GBASIONormalFillSi(value); value = GBASIONormalFillSi(value);
if ((value & 0x0081) == 0x0081) {
if (GBASIONormalIsIrq(value)) {
mTimingDeschedule(&sio->p->timing, &sio->completeEvent);
mTimingSchedule(&sio->p->timing, &sio->completeEvent, GBASIOTransferCycles(sio));
} else {
// TODO: Test this on hardware to see if this is correct
value = GBASIONormalClearStart(value);
}
}
break; break;
case GBA_SIO_MULTI: case GBA_SIO_MULTI:
value = GBASIOMultiplayerFillReady(value); value = GBASIOMultiplayerFillReady(value);
@ -473,16 +494,29 @@ void GBASIONormal32FinishTransfer(struct GBASIO* sio, uint32_t data, uint32_t cy
static void _sioFinish(struct mTiming* timing, void* user, uint32_t cyclesLate) { static void _sioFinish(struct mTiming* timing, void* user, uint32_t cyclesLate) {
UNUSED(timing); UNUSED(timing);
struct GBASIO* sio = user; struct GBASIO* sio = user;
uint16_t data[4] = {0, 0, 0, 0}; union {
uint16_t multi[4];
uint8_t normal8;
uint32_t normal32;
} data = {0};
switch (sio->mode) { switch (sio->mode) {
case GBA_SIO_MULTI: case GBA_SIO_MULTI:
GBASIOMultiplayerFinishTransfer(sio, data, cyclesLate); if (sio->activeDriver && sio->activeDriver->finishMultiplayer) {
sio->activeDriver->finishMultiplayer(sio->activeDriver, data.multi);
}
GBASIOMultiplayerFinishTransfer(sio, data.multi, cyclesLate);
break; break;
case GBA_SIO_NORMAL_8: case GBA_SIO_NORMAL_8:
GBASIONormal8FinishTransfer(sio, 0, cyclesLate); if (sio->activeDriver && sio->activeDriver->finishNormal8) {
data.normal8 = sio->activeDriver->finishNormal8(sio->activeDriver);
}
GBASIONormal8FinishTransfer(sio, data.normal8, cyclesLate);
break; break;
case GBA_SIO_NORMAL_32: case GBA_SIO_NORMAL_32:
GBASIONormal32FinishTransfer(sio, 0, cyclesLate); if (sio->activeDriver && sio->activeDriver->finishNormal32) {
data.normal32 = sio->activeDriver->finishNormal32(sio->activeDriver);
}
GBASIONormal32FinishTransfer(sio, data.normal32, cyclesLate);
break; break;
default: default:
// TODO // TODO

View File

@ -33,15 +33,12 @@ static int32_t _processCommand(struct GBASIODolphin* dol, uint32_t cyclesLate);
static void _flush(struct GBASIODolphin* dol); static void _flush(struct GBASIODolphin* dol);
void GBASIODolphinCreate(struct GBASIODolphin* dol) { void GBASIODolphinCreate(struct GBASIODolphin* dol) {
memset(&dol->d, 0, sizeof(dol->d));
dol->d.init = GBASIODolphinInit; dol->d.init = GBASIODolphinInit;
dol->d.load = GBASIODolphinLoad; dol->d.load = GBASIODolphinLoad;
dol->d.unload = GBASIODolphinUnload; dol->d.unload = GBASIODolphinUnload;
dol->d.writeSIOCNT = NULL;
dol->d.setMode = NULL;
dol->d.handlesMode = GBASIODolphinHandlesMode; dol->d.handlesMode = GBASIODolphinHandlesMode;
dol->d.connectedDevices = GBASIODolphinConnectedDevices; dol->d.connectedDevices = GBASIODolphinConnectedDevices;
dol->d.deviceId = NULL;
dol->d.writeSIOCNT = NULL;
dol->event.context = dol; dol->event.context = dol;
dol->event.name = "GB SIO Lockstep"; dol->event.name = "GB SIO Lockstep";
dol->event.callback = GBASIODolphinProcessEvents; dol->event.callback = GBASIODolphinProcessEvents;

View File

@ -16,7 +16,8 @@ static uint16_t _gbpRead(struct mKeyCallback*);
static uint16_t _gbpSioWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); static uint16_t _gbpSioWriteSIOCNT(struct GBASIODriver* driver, uint16_t value);
static bool _gbpSioHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); static bool _gbpSioHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode);
static int _gbpSioConnectedDevices(struct GBASIODriver* driver); static int _gbpSioConnectedDevices(struct GBASIODriver* driver);
static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate); static bool _gbpSioStart(struct GBASIODriver* driver);
static uint32_t _gbpSioFinishNormal32(struct GBASIODriver* driver);
static const uint8_t _logoPalette[] = { static const uint8_t _logoPalette[] = {
0xDF, 0xFF, 0x0C, 0x64, 0x0C, 0xE4, 0x2D, 0xE4, 0x4E, 0x64, 0x4E, 0xE4, 0x6E, 0xE4, 0xAF, 0x68, 0xDF, 0xFF, 0x0C, 0x64, 0x0C, 0xE4, 0x2D, 0xE4, 0x4E, 0x64, 0x4E, 0xE4, 0x6E, 0xE4, 0xAF, 0x68,
@ -45,20 +46,12 @@ void GBASIOPlayerInit(struct GBASIOPlayer* gbp) {
gbp->callback.d.readKeys = _gbpRead; gbp->callback.d.readKeys = _gbpRead;
gbp->callback.d.requireOpposingDirections = true; gbp->callback.d.requireOpposingDirections = true;
gbp->callback.p = gbp; gbp->callback.p = gbp;
gbp->d.init = NULL; memset(&gbp->d, 0, sizeof(gbp->d));
gbp->d.deinit = NULL;
gbp->d.load = NULL;
gbp->d.unload = NULL;
gbp->d.writeSIOCNT = _gbpSioWriteSIOCNT; gbp->d.writeSIOCNT = _gbpSioWriteSIOCNT;
gbp->d.setMode = NULL;
gbp->d.handlesMode = _gbpSioHandlesMode; gbp->d.handlesMode = _gbpSioHandlesMode;
gbp->d.connectedDevices = _gbpSioConnectedDevices; gbp->d.connectedDevices = _gbpSioConnectedDevices;
gbp->d.deviceId = NULL; gbp->d.start = _gbpSioStart;
gbp->d.writeRCNT = NULL; gbp->d.finishNormal32 = _gbpSioFinishNormal32;
gbp->event.context = gbp;
gbp->event.name = "GBA SIO Game Boy Player";
gbp->event.callback = _gbpSioProcessEvents;
gbp->event.priority = 0x80;
} }
void GBASIOPlayerReset(struct GBASIOPlayer* gbp) { void GBASIOPlayerReset(struct GBASIOPlayer* gbp) {
@ -108,27 +101,26 @@ uint16_t _gbpRead(struct mKeyCallback* callback) {
} }
uint16_t _gbpSioWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) { uint16_t _gbpSioWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) {
UNUSED(driver);
return value & 0x78FB;
}
bool _gbpSioStart(struct GBASIODriver* driver) {
struct GBASIOPlayer* gbp = (struct GBASIOPlayer*) driver; struct GBASIOPlayer* gbp = (struct GBASIOPlayer*) driver;
if (value & 0x0080) { uint32_t rx = gbp->p->memory.io[GBA_REG(SIODATA32_LO)] | (gbp->p->memory.io[GBA_REG(SIODATA32_HI)] << 16);
uint32_t rx = gbp->p->memory.io[GBA_REG(SIODATA32_LO)] | (gbp->p->memory.io[GBA_REG(SIODATA32_HI)] << 16); if (gbp->txPosition < 12 && gbp->txPosition > 0) {
if (gbp->txPosition < 12 && gbp->txPosition > 0) { // TODO: Check expected
// TODO: Check expected } else if (gbp->txPosition >= 12) {
} else if (gbp->txPosition >= 12) { // 0x00 = Stop
uint32_t mask = 0x33; // 0x11 = Hard Stop
// 0x00 = Stop // 0x22 = Start
// 0x11 = Hard Stop if (gbp->p->rumble) {
// 0x22 = Start int32_t currentTime = mTimingCurrentTime(&gbp->p->timing);
if (gbp->p->rumble) { gbp->p->rumble->setRumble(gbp->p->rumble, (rx & 0x33) == 0x22, currentTime - gbp->p->lastRumble);
int32_t currentTime = mTimingCurrentTime(&gbp->p->timing); gbp->p->lastRumble = currentTime;
gbp->p->rumble->setRumble(gbp->p->rumble, (rx & 0x33) == 0x22, currentTime - gbp->p->lastRumble);
gbp->p->lastRumble = currentTime;
}
} }
mTimingDeschedule(&gbp->p->timing, &gbp->event);
mTimingSchedule(&gbp->p->timing, &gbp->event, 2048);
} }
value &= 0x78FB; return true;
return value;
} }
static bool _gbpSioHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) { static bool _gbpSioHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) {
@ -141,9 +133,8 @@ static int _gbpSioConnectedDevices(struct GBASIODriver* driver) {
return 1; return 1;
} }
void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) { uint32_t _gbpSioFinishNormal32(struct GBASIODriver* driver) {
UNUSED(timing); struct GBASIOPlayer* gbp = (struct GBASIOPlayer*) driver;
struct GBASIOPlayer* gbp = user;
uint32_t tx = 0; uint32_t tx = 0;
int txPosition = gbp->txPosition; int txPosition = gbp->txPosition;
if (txPosition > 16) { if (txPosition > 16) {
@ -154,5 +145,5 @@ void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLat
} }
tx = _gbpTxData[txPosition]; tx = _gbpTxData[txPosition];
++gbp->txPosition; ++gbp->txPosition;
GBASIONormal32FinishTransfer(gbp->d.p, tx, cyclesLate); return tx;
} }

View File

@ -18,6 +18,7 @@ static bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver);
static bool GBASIOLockstepNodeHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); static bool GBASIOLockstepNodeHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode);
static int GBASIOLockstepNodeConnectedDevices(struct GBASIODriver* driver); static int GBASIOLockstepNodeConnectedDevices(struct GBASIODriver* driver);
static int GBASIOLockstepNodeDeviceId(struct GBASIODriver* driver); static int GBASIOLockstepNodeDeviceId(struct GBASIODriver* driver);
static bool GBASIOLockstepNodeStart(struct GBASIODriver* driver);
static uint16_t GBASIOLockstepNodeMultiWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); static uint16_t GBASIOLockstepNodeMultiWriteSIOCNT(struct GBASIODriver* driver, uint16_t value);
static uint16_t GBASIOLockstepNodeNormalWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); static uint16_t GBASIOLockstepNodeNormalWriteSIOCNT(struct GBASIODriver* driver, uint16_t value);
static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* driver, uint32_t cyclesLate); static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* driver, uint32_t cyclesLate);
@ -37,16 +38,16 @@ void GBASIOLockstepInit(struct GBASIOLockstep* lockstep) {
} }
void GBASIOLockstepNodeCreate(struct GBASIOLockstepNode* node) { void GBASIOLockstepNodeCreate(struct GBASIOLockstepNode* node) {
memset(&node->d, 0, sizeof(node->d));
node->d.init = GBASIOLockstepNodeInit; node->d.init = GBASIOLockstepNodeInit;
node->d.deinit = GBASIOLockstepNodeDeinit; node->d.deinit = GBASIOLockstepNodeDeinit;
node->d.load = GBASIOLockstepNodeLoad; node->d.load = GBASIOLockstepNodeLoad;
node->d.unload = GBASIOLockstepNodeUnload; node->d.unload = GBASIOLockstepNodeUnload;
node->d.setMode = NULL;
node->d.handlesMode = GBASIOLockstepNodeHandlesMode; node->d.handlesMode = GBASIOLockstepNodeHandlesMode;
node->d.connectedDevices = GBASIOLockstepNodeConnectedDevices; node->d.connectedDevices = GBASIOLockstepNodeConnectedDevices;
node->d.deviceId = GBASIOLockstepNodeDeviceId; node->d.deviceId = GBASIOLockstepNodeDeviceId;
node->d.start = GBASIOLockstepNodeStart;
node->d.writeSIOCNT = NULL; node->d.writeSIOCNT = NULL;
node->d.writeRCNT = NULL;
} }
bool GBASIOLockstepAttachNode(struct GBASIOLockstep* lockstep, struct GBASIOLockstepNode* node) { bool GBASIOLockstepAttachNode(struct GBASIOLockstep* lockstep, struct GBASIOLockstepNode* node) {
@ -224,6 +225,11 @@ static int GBASIOLockstepNodeDeviceId(struct GBASIODriver* driver) {
return node->id; return node->id;
} }
static bool GBASIOLockstepNodeStart(struct GBASIODriver* driver) {
UNUSED(driver);
return false;
}
static uint16_t GBASIOLockstepNodeMultiWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) { static uint16_t GBASIOLockstepNodeMultiWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) {
struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver;
@ -319,10 +325,6 @@ static int32_t _masterUpdate(struct GBASIOLockstepNode* node) {
switch (node->mode) { switch (node->mode) {
case GBA_SIO_MULTI: case GBA_SIO_MULTI:
node->p->multiRecv[0] = node->d.p->p->memory.io[GBA_REG(SIOMLT_SEND)]; node->p->multiRecv[0] = node->d.p->p->memory.io[GBA_REG(SIOMLT_SEND)];
node->d.p->p->memory.io[GBA_REG(SIOMULTI0)] = 0xFFFF;
node->d.p->p->memory.io[GBA_REG(SIOMULTI1)] = 0xFFFF;
node->d.p->p->memory.io[GBA_REG(SIOMULTI2)] = 0xFFFF;
node->d.p->p->memory.io[GBA_REG(SIOMULTI3)] = 0xFFFF;
node->p->multiRecv[1] = 0xFFFF; node->p->multiRecv[1] = 0xFFFF;
node->p->multiRecv[2] = 0xFFFF; node->p->multiRecv[2] = 0xFFFF;
node->p->multiRecv[3] = 0xFFFF; node->p->multiRecv[3] = 0xFFFF;