GBA SIO: Move cycle estimation values into core

This commit is contained in:
Vicki Pfau 2024-05-21 23:24:06 -07:00
parent cd4132fba3
commit 1b0b540de6
4 changed files with 32 additions and 20 deletions

View File

@ -16,8 +16,6 @@ CXX_GUARD_START
#define MAX_GBAS 4 #define MAX_GBAS 4
extern const int GBASIOCyclesPerTransfer[4][MAX_GBAS];
mLOG_DECLARE_CATEGORY(GBA_SIO); mLOG_DECLARE_CATEGORY(GBA_SIO);
enum { enum {
@ -85,6 +83,8 @@ void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value);
void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value); 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);
int32_t GBASIOTransferCycles(struct GBASIO* sio);
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 GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data); int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data);

View File

@ -105,12 +105,7 @@ static int GBASIOBattlechipGateConnectedDevices(struct GBASIODriver* driver) {
} }
void _battlechipTransfer(struct GBASIOBattlechipGate* gate) { void _battlechipTransfer(struct GBASIOBattlechipGate* gate) {
int32_t cycles; int32_t cycles = GBASIOTransferCycles(gate->d.p);
if (gate->d.p->mode == GBA_SIO_NORMAL_32) {
cycles = GBA_ARM7TDMI_FREQUENCY / 0x40000;
} else {
cycles = GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(gate->d.p->siocnt)][1];
}
mTimingDeschedule(&gate->d.p->p->timing, &gate->event); mTimingDeschedule(&gate->d.p->p->timing, &gate->event);
mTimingSchedule(&gate->d.p->p->timing, &gate->event, cycles); mTimingSchedule(&gate->d.p->p->timing, &gate->event, cycles);
} }

View File

@ -11,7 +11,7 @@
mLOG_DEFINE_CATEGORY(GBA_SIO, "GBA Serial I/O", "gba.sio"); mLOG_DEFINE_CATEGORY(GBA_SIO, "GBA Serial I/O", "gba.sio");
const int GBASIOCyclesPerTransfer[4][MAX_GBAS] = { static const int GBASIOCyclesPerTransfer[4][MAX_GBAS] = {
{ 31976, 63427, 94884, 125829 }, { 31976, 63427, 94884, 125829 },
{ 8378, 16241, 24104, 31457 }, { 8378, 16241, 24104, 31457 },
{ 5750, 10998, 16241, 20972 }, { 5750, 10998, 16241, 20972 },
@ -318,6 +318,31 @@ uint16_t GBASIOWriteRegister(struct GBASIO* sio, uint32_t address, uint16_t valu
return value; return value;
} }
int32_t GBASIOTransferCycles(struct GBASIO* sio) {
int connected = 0;
if (sio->activeDriver) {
connected = sio->activeDriver->connectedDevices(sio->activeDriver);
}
if (connected < 0 || connected >= MAX_GBAS) {
mLOG(GBA_SIO, ERROR, "SIO driver returned invalid device count %i", connected);
return 0;
}
switch (sio->mode) {
case GBA_SIO_MULTI:
return GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(sio->siocnt)][connected];
case GBA_SIO_NORMAL_8:
return 8 * GBA_ARM7TDMI_FREQUENCY / ((GBASIONormalIsInternalSc(sio->siocnt) ? 2048 : 256) * 1024);
case GBA_SIO_NORMAL_32:
return 32 * GBA_ARM7TDMI_FREQUENCY / ((GBASIONormalIsInternalSc(sio->siocnt) ? 2048 : 256) * 1024);
default:
mLOG(GBA_SIO, STUB, "No cycle count implemented for mode %s", _modeName(sio->mode));
break;
}
return 0;
}
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->activeDriver && sio->activeDriver->deviceId) {

View File

@ -250,7 +250,7 @@ static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver
if (!node->id && attached > 1 && GBASIOMultiplayerIsReady(node->d.p->siocnt)) { if (!node->id && attached > 1 && GBASIOMultiplayerIsReady(node->d.p->siocnt)) {
mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id); mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id);
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
ATOMIC_STORE(node->p->d.transferCycles, GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][node->p->d.attached - 1]); ATOMIC_STORE(node->p->d.transferCycles, GBASIOTransferCycles(node->d.p));
if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) {
node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing);
@ -502,7 +502,7 @@ static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* user,
if (node->p->d.attached < 2) { if (node->p->d.attached < 2) {
switch (node->mode) { switch (node->mode) {
case GBA_SIO_MULTI: case GBA_SIO_MULTI:
cycles = GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][0]; cycles = GBASIOTransferCycles(node->d.p);
break; break;
case GBA_SIO_NORMAL_8: case GBA_SIO_NORMAL_8:
case GBA_SIO_NORMAL_32: case GBA_SIO_NORMAL_32:
@ -568,15 +568,7 @@ static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* drive
if ((value & 0x0081) == 0x0081) { if ((value & 0x0081) == 0x0081) {
if (!node->id) { if (!node->id) {
// Frequency // Frequency
int32_t cycles; int32_t cycles = GBASIOTransferCycles(node->d.p);
if (value & 2) {
cycles = 8 * 8;
} else {
cycles = 64 * 8;
}
if (value & 0x1000) {
cycles *= 4;
}
if (transferActive == TRANSFER_IDLE) { if (transferActive == TRANSFER_IDLE) {
mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id); mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id);