From 0425dadee9bdb1eebaae80f523037fd62c39e004 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 26 May 2024 00:46:00 -0700 Subject: [PATCH] GBA SIO: Add RCNT bitfield --- include/mgba/internal/gba/sio.h | 9 +++++++++ src/gba/sio.c | 16 ++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/include/mgba/internal/gba/sio.h b/include/mgba/internal/gba/sio.h index 804f0f52a..bb7b2a78c 100644 --- a/include/mgba/internal/gba/sio.h +++ b/include/mgba/internal/gba/sio.h @@ -52,6 +52,15 @@ DECL_BITS(GBASIOMultiplayer, Id, 4, 2); DECL_BIT(GBASIOMultiplayer, Error, 6); DECL_BIT(GBASIOMultiplayer, Busy, 7); DECL_BIT(GBASIOMultiplayer, Irq, 14); +DECL_BITFIELD(GBASIORegisterRCNT, uint16_t); +DECL_BIT(GBASIORegisterRCNT, Sc, 0); +DECL_BIT(GBASIORegisterRCNT, Sd, 1); +DECL_BIT(GBASIORegisterRCNT, Si, 2); +DECL_BIT(GBASIORegisterRCNT, So, 3); +DECL_BIT(GBASIORegisterRCNT, ScDirection, 4); +DECL_BIT(GBASIORegisterRCNT, SdDirection, 5); +DECL_BIT(GBASIORegisterRCNT, SiDirection, 6); +DECL_BIT(GBASIORegisterRCNT, SoDirection, 7); struct GBASIODriverSet { struct GBASIODriver* normal; diff --git a/src/gba/sio.c b/src/gba/sio.c index 54fff7ea1..b10d2c257 100644 --- a/src/gba/sio.c +++ b/src/gba/sio.c @@ -86,11 +86,7 @@ static void _switchMode(struct GBASIO* sio) { if (sio->activeDriver && sio->activeDriver->deviceId) { id = sio->activeDriver->deviceId(sio->activeDriver); } - if (id) { - sio->rcnt |= 4; - } else { - sio->rcnt &= ~4; - } + sio->rcnt = GBASIORegisterRCNTSetSi(sio->rcnt, !!id); break; default: // TODO @@ -417,9 +413,17 @@ void GBASIOMultiplayerFinishTransfer(struct GBASIO* sio, uint16_t data[4], uint3 sio->p->memory.io[GBA_REG(SIOMULTI1)] = data[1]; sio->p->memory.io[GBA_REG(SIOMULTI2)] = data[2]; sio->p->memory.io[GBA_REG(SIOMULTI3)] = data[3]; - sio->rcnt |= 1; + sio->siocnt = GBASIOMultiplayerClearBusy(sio->siocnt); sio->siocnt = GBASIOMultiplayerSetId(sio->siocnt, id); + + // This SC level is actually a transient pulse, and probably a hardware glitch. + // Based on analog sampling it seems to just be a spike when the other lines deassert. + // It rapidly falls down to GND but it's high enough that it's read out as a 1 for + // several microseconds, likely around 300-500 cycles. I have not measured if and when + // it returns to 0 afterwards. + sio->rcnt = GBASIORegisterRCNTFillSc(sio->rcnt); + if (GBASIOMultiplayerIsIrq(sio->siocnt)) { GBARaiseIRQ(sio->p, GBA_IRQ_SIO, cyclesLate); }