mirror of https://github.com/mgba-emu/mgba.git
GBA SIO: Replace writeRegister with writeSIOCNT
This commit is contained in:
parent
9998de4880
commit
5da4b1fc4d
|
@ -117,7 +117,7 @@ struct GBASIODriver {
|
|||
bool (*handlesMode)(struct GBASIODriver* driver, enum GBASIOMode mode);
|
||||
int (*connectedDevices)(struct GBASIODriver* driver);
|
||||
int (*deviceId)(struct GBASIODriver* driver);
|
||||
uint16_t (*writeRegister)(struct GBASIODriver* driver, uint32_t address, uint16_t value);
|
||||
uint16_t (*writeSIOCNT)(struct GBASIODriver* driver, uint16_t value);
|
||||
};
|
||||
|
||||
enum GBASIOBattleChipGateFlavor {
|
||||
|
|
|
@ -34,7 +34,7 @@ enum {
|
|||
};
|
||||
|
||||
static bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver);
|
||||
static uint16_t GBASIOBattlechipGateWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value);
|
||||
static uint16_t GBASIOBattlechipGateWriteSIOCNT(struct GBASIODriver* driver, uint16_t value);
|
||||
static bool GBASIOBattlechipGateHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode);
|
||||
static int GBASIOBattlechipGateConnectedDevices(struct GBASIODriver* driver);
|
||||
|
||||
|
@ -46,7 +46,7 @@ void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate* gate) {
|
|||
gate->d.deinit = NULL;
|
||||
gate->d.load = GBASIOBattlechipGateLoad;
|
||||
gate->d.unload = NULL;
|
||||
gate->d.writeRegister = GBASIOBattlechipGateWriteRegister;
|
||||
gate->d.writeSIOCNT = GBASIOBattlechipGateWriteSIOCNT;
|
||||
gate->d.setMode = NULL;
|
||||
gate->d.handlesMode = GBASIOBattlechipGateHandlesMode;
|
||||
gate->d.connectedDevices = GBASIOBattlechipGateConnectedDevices;
|
||||
|
@ -68,22 +68,12 @@ bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver) {
|
|||
return true;
|
||||
}
|
||||
|
||||
uint16_t GBASIOBattlechipGateWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
|
||||
uint16_t GBASIOBattlechipGateWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) {
|
||||
struct GBASIOBattlechipGate* gate = (struct GBASIOBattlechipGate*) driver;
|
||||
switch (address) {
|
||||
case GBA_REG_SIOCNT:
|
||||
value &= ~0xC;
|
||||
value |= 0x8;
|
||||
if (value & 0x80) {
|
||||
_battlechipTransfer(gate);
|
||||
}
|
||||
break;
|
||||
case GBA_REG_SIOMLT_SEND:
|
||||
break;
|
||||
case GBA_REG_RCNT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
value &= ~0xC;
|
||||
value |= 0x8;
|
||||
if (value & 0x80) {
|
||||
_battlechipTransfer(gate);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -193,9 +193,6 @@ void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) {
|
|||
sio->rcnt &= 0xF;
|
||||
sio->rcnt |= value & ~0xF;
|
||||
_switchMode(sio);
|
||||
if (sio->activeDriver && sio->activeDriver->writeRegister) {
|
||||
sio->activeDriver->writeRegister(sio->activeDriver, GBA_REG_RCNT, value);
|
||||
}
|
||||
}
|
||||
|
||||
void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
|
||||
|
@ -213,7 +210,7 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
|
|||
id = sio->activeDriver->deviceId(sio->activeDriver);
|
||||
}
|
||||
connected = sio->activeDriver->connectedDevices(sio->activeDriver);
|
||||
handled = !!sio->activeDriver->writeRegister;
|
||||
handled = !!sio->activeDriver->writeSIOCNT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +226,7 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
|
|||
break;
|
||||
}
|
||||
if (handled) {
|
||||
value = sio->activeDriver->writeRegister(sio->activeDriver, GBA_REG_SIOCNT, value);
|
||||
value = sio->activeDriver->writeSIOCNT(sio->activeDriver, value);
|
||||
} else {
|
||||
// Dummy drivers
|
||||
switch (sio->mode) {
|
||||
|
@ -328,10 +325,6 @@ uint16_t GBASIOWriteRegister(struct GBASIO* sio, uint32_t address, uint16_t valu
|
|||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
if (sio->activeDriver && sio->activeDriver->writeRegister && sio->activeDriver->handlesMode(sio->activeDriver, sio->mode)) {
|
||||
sio->activeDriver->writeRegister(sio->activeDriver, address, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ void GBASIODolphinCreate(struct GBASIODolphin* dol) {
|
|||
dol->d.init = GBASIODolphinInit;
|
||||
dol->d.load = GBASIODolphinLoad;
|
||||
dol->d.unload = GBASIODolphinUnload;
|
||||
dol->d.writeRegister = NULL;
|
||||
dol->d.writeSIOCNT = NULL;
|
||||
dol->d.setMode = NULL;
|
||||
dol->d.handlesMode = GBASIODolphinHandlesMode;
|
||||
dol->d.connectedDevices = GBASIODolphinConnectedDevices;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include <mgba-util/memory.h>
|
||||
|
||||
static uint16_t _gbpRead(struct mKeyCallback*);
|
||||
static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value);
|
||||
static uint16_t _gbpSioWriteSIOCNT(struct GBASIODriver* driver, uint16_t value);
|
||||
static bool _gbpSioHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode);
|
||||
static int _gbpSioConnectedDevices(struct GBASIODriver* driver);
|
||||
static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate);
|
||||
|
@ -49,7 +49,7 @@ void GBASIOPlayerInit(struct GBASIOPlayer* gbp) {
|
|||
gbp->d.deinit = NULL;
|
||||
gbp->d.load = NULL;
|
||||
gbp->d.unload = NULL;
|
||||
gbp->d.writeRegister = _gbpSioWriteRegister;
|
||||
gbp->d.writeSIOCNT = _gbpSioWriteSIOCNT;
|
||||
gbp->d.setMode = NULL;
|
||||
gbp->d.handlesMode = _gbpSioHandlesMode;
|
||||
gbp->d.connectedDevices = _gbpSioConnectedDevices;
|
||||
|
@ -106,28 +106,27 @@ uint16_t _gbpRead(struct mKeyCallback* callback) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
|
||||
uint16_t _gbpSioWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) {
|
||||
struct GBASIOPlayer* gbp = (struct GBASIOPlayer*) driver;
|
||||
if (address == GBA_REG_SIOCNT) {
|
||||
if (value & 0x0080) {
|
||||
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) {
|
||||
// TODO: Check expected
|
||||
} else if (gbp->txPosition >= 12) {
|
||||
// 0x00 = Stop
|
||||
// 0x11 = Hard Stop
|
||||
// 0x22 = Start
|
||||
if (gbp->p->rumble) {
|
||||
int32_t currentTime = mTimingCurrentTime(&gbp->p->timing);
|
||||
gbp->p->rumble->setRumble(gbp->p->rumble, (rx & 0x33) == 0x22, currentTime - gbp->p->lastRumble);
|
||||
gbp->p->lastRumble = currentTime;
|
||||
}
|
||||
if (value & 0x0080) {
|
||||
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) {
|
||||
// TODO: Check expected
|
||||
} else if (gbp->txPosition >= 12) {
|
||||
uint32_t mask = 0x33;
|
||||
// 0x00 = Stop
|
||||
// 0x11 = Hard Stop
|
||||
// 0x22 = Start
|
||||
if (gbp->p->rumble) {
|
||||
int32_t currentTime = mTimingCurrentTime(&gbp->p->timing);
|
||||
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;
|
||||
mTimingDeschedule(&gbp->p->timing, &gbp->event);
|
||||
mTimingSchedule(&gbp->p->timing, &gbp->event, 2048);
|
||||
}
|
||||
value &= 0x78FB;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ static void GBASIOLockstepNodeSetMode(struct GBASIODriver* driver, enum GBASIOMo
|
|||
static bool GBASIOLockstepNodeHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode);
|
||||
static int GBASIOLockstepNodeConnectedDevices(struct GBASIODriver* driver);
|
||||
static int GBASIOLockstepNodeDeviceId(struct GBASIODriver* driver);
|
||||
static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value);
|
||||
static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value);
|
||||
static uint16_t GBASIOLockstepNodeMultiWriteSIOCNT(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 _finishTransfer(struct GBASIOLockstepNode* node);
|
||||
|
||||
|
@ -46,7 +46,7 @@ void GBASIOLockstepNodeCreate(struct GBASIOLockstepNode* node) {
|
|||
node->d.handlesMode = GBASIOLockstepNodeHandlesMode;
|
||||
node->d.connectedDevices = GBASIOLockstepNodeConnectedDevices;
|
||||
node->d.deviceId = GBASIOLockstepNodeDeviceId;
|
||||
node->d.writeRegister = NULL;
|
||||
node->d.writeSIOCNT = NULL;
|
||||
}
|
||||
|
||||
bool GBASIOLockstepAttachNode(struct GBASIOLockstep* lockstep, struct GBASIOLockstepNode* node) {
|
||||
|
@ -112,7 +112,7 @@ bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) {
|
|||
|
||||
switch (node->mode) {
|
||||
case GBA_SIO_MULTI:
|
||||
node->d.writeRegister = GBASIOLockstepNodeMultiWriteRegister;
|
||||
node->d.writeSIOCNT = GBASIOLockstepNodeMultiWriteSIOCNT;
|
||||
ATOMIC_ADD(node->p->attachedMulti, 1);
|
||||
node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, node->p->attachedMulti == node->p->d.attached);
|
||||
if (node->id) {
|
||||
|
@ -134,7 +134,7 @@ bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) {
|
|||
} else {
|
||||
node->d.p->siocnt = GBASIONormalClearSi(node->d.p->siocnt);
|
||||
}
|
||||
node->d.writeRegister = GBASIOLockstepNodeNormalWriteRegister;
|
||||
node->d.writeSIOCNT = GBASIOLockstepNodeNormalWriteSIOCNT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -231,41 +231,35 @@ static int GBASIOLockstepNodeDeviceId(struct GBASIODriver* driver) {
|
|||
return node->id;
|
||||
}
|
||||
|
||||
static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
|
||||
static uint16_t GBASIOLockstepNodeMultiWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) {
|
||||
struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver;
|
||||
|
||||
mLockstepLock(&node->p->d);
|
||||
|
||||
if (address == GBA_REG_SIOCNT) {
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value);
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value);
|
||||
|
||||
enum mLockstepPhase transferActive;
|
||||
int attached;
|
||||
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
|
||||
ATOMIC_LOAD(attached, node->p->d.attached);
|
||||
enum mLockstepPhase transferActive;
|
||||
int attached;
|
||||
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
|
||||
ATOMIC_LOAD(attached, node->p->d.attached);
|
||||
|
||||
driver->p->siocnt = GBASIOMultiplayerSetSlave(driver->p->siocnt, node->id || attached < 2);
|
||||
driver->p->siocnt = GBASIOMultiplayerSetSlave(driver->p->siocnt, node->id || attached < 2);
|
||||
|
||||
if (value & 0x0080 && transferActive == TRANSFER_IDLE) {
|
||||
if (!node->id && attached > 1 && GBASIOMultiplayerIsReady(node->d.p->siocnt)) {
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id);
|
||||
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
|
||||
ATOMIC_STORE(node->p->d.transferCycles, GBASIOTransferCycles(node->d.p));
|
||||
if (value & 0x0080 && transferActive == TRANSFER_IDLE) {
|
||||
if (!node->id && attached > 1 && GBASIOMultiplayerIsReady(node->d.p->siocnt)) {
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id);
|
||||
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
|
||||
ATOMIC_STORE(node->p->d.transferCycles, GBASIOTransferCycles(node->d.p));
|
||||
|
||||
if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) {
|
||||
node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing);
|
||||
mTimingDeschedule(&driver->p->p->timing, &node->event);
|
||||
}
|
||||
mTimingSchedule(&driver->p->p->timing, &node->event, 0);
|
||||
if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) {
|
||||
node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing);
|
||||
mTimingDeschedule(&driver->p->p->timing, &node->event);
|
||||
}
|
||||
mTimingSchedule(&driver->p->p->timing, &node->event, 0);
|
||||
}
|
||||
value &= 0xFF83;
|
||||
value |= driver->p->siocnt & 0x00FC;
|
||||
} else if (address == GBA_REG_SIOMLT_SEND) {
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOMLT_SEND <- %04X", node->id, value);
|
||||
} else {
|
||||
mLOG(GBA_SIO, STUB, "Lockstep %i: Unknown reg %03X <- %04X", node->id, address, value);
|
||||
}
|
||||
value &= 0xFF83;
|
||||
value |= driver->p->siocnt & 0x00FC;
|
||||
|
||||
mLockstepUnlock(&node->p->d);
|
||||
|
||||
|
@ -525,62 +519,54 @@ static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* user,
|
|||
mLockstepUnlock(&node->p->d);
|
||||
}
|
||||
|
||||
static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
|
||||
static uint16_t GBASIOLockstepNodeNormalWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) {
|
||||
struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver;
|
||||
|
||||
mLockstepLock(&node->p->d);
|
||||
|
||||
if (address == GBA_REG_SIOCNT) {
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value);
|
||||
int attached;
|
||||
ATOMIC_LOAD(attached, node->p->attachedNormal);
|
||||
value &= 0xFF8B;
|
||||
if (node->id > 0) {
|
||||
value = GBASIONormalSetSi(value, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt));
|
||||
} else {
|
||||
value = GBASIONormalClearSi(value);
|
||||
}
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value);
|
||||
int attached;
|
||||
ATOMIC_LOAD(attached, node->p->attachedNormal);
|
||||
value &= 0xFF8B;
|
||||
if (node->id > 0) {
|
||||
value = GBASIONormalSetSi(value, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt));
|
||||
} else {
|
||||
value = GBASIONormalClearSi(value);
|
||||
}
|
||||
|
||||
enum mLockstepPhase transferActive;
|
||||
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
|
||||
if (node->id < 3 && attached > node->id + 1 && transferActive == TRANSFER_IDLE) {
|
||||
int try;
|
||||
for (try = 0; try < 3; ++try) {
|
||||
GBASIONormal nextSiocnct;
|
||||
ATOMIC_LOAD(nextSiocnct, node->p->players[node->id + 1]->d.p->siocnt);
|
||||
if (ATOMIC_CMPXCHG(node->p->players[node->id + 1]->d.p->siocnt, nextSiocnct, GBASIONormalSetSi(nextSiocnct, GBASIONormalGetIdleSo(value)))) {
|
||||
break;
|
||||
}
|
||||
enum mLockstepPhase transferActive;
|
||||
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
|
||||
if (node->id < 3 && attached > node->id + 1 && transferActive == TRANSFER_IDLE) {
|
||||
int try;
|
||||
for (try = 0; try < 3; ++try) {
|
||||
GBASIONormal nextSiocnct;
|
||||
ATOMIC_LOAD(nextSiocnct, node->p->players[node->id + 1]->d.p->siocnt);
|
||||
if (ATOMIC_CMPXCHG(node->p->players[node->id + 1]->d.p->siocnt, nextSiocnct, GBASIONormalSetSi(nextSiocnct, GBASIONormalGetIdleSo(value)))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((value & 0x0081) == 0x0081) {
|
||||
if (!node->id) {
|
||||
// Frequency
|
||||
int32_t cycles = GBASIOTransferCycles(node->d.p);
|
||||
}
|
||||
if ((value & 0x0081) == 0x0081) {
|
||||
if (!node->id) {
|
||||
// Frequency
|
||||
int32_t cycles = GBASIOTransferCycles(node->d.p);
|
||||
|
||||
if (transferActive == TRANSFER_IDLE) {
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id);
|
||||
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
|
||||
ATOMIC_STORE(node->p->d.transferCycles, cycles);
|
||||
if (transferActive == TRANSFER_IDLE) {
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id);
|
||||
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
|
||||
ATOMIC_STORE(node->p->d.transferCycles, cycles);
|
||||
|
||||
if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) {
|
||||
node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing);
|
||||
mTimingDeschedule(&driver->p->p->timing, &node->event);
|
||||
}
|
||||
mTimingSchedule(&driver->p->p->timing, &node->event, 0);
|
||||
} else {
|
||||
value &= ~0x0080;
|
||||
if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) {
|
||||
node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing);
|
||||
mTimingDeschedule(&driver->p->p->timing, &node->event);
|
||||
}
|
||||
mTimingSchedule(&driver->p->p->timing, &node->event, 0);
|
||||
} else {
|
||||
// TODO
|
||||
value &= ~0x0080;
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
} else if (address == GBA_REG_SIODATA32_LO) {
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_LO <- %04X", node->id, value);
|
||||
} else if (address == GBA_REG_SIODATA32_HI) {
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_HI <- %04X", node->id, value);
|
||||
} else if (address == GBA_REG_SIODATA8) {
|
||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA8 <- %02X", node->id, value);
|
||||
}
|
||||
|
||||
mLockstepUnlock(&node->p->d);
|
||||
|
|
Loading…
Reference in New Issue