diff --git a/src/gba/sio/dolphin.c b/src/gba/sio/dolphin.c index 51afb1b76..48c5176de 100644 --- a/src/gba/sio/dolphin.c +++ b/src/gba/sio/dolphin.c @@ -7,8 +7,8 @@ #include "gba/io.h" -#define CLOCK_GRAIN 2048 #define CYCLES_PER_BIT 75 +#define CLOCK_GRAIN (CYCLES_PER_BIT * 8) const uint16_t DOLPHIN_CLOCK_PORT = 49420; const uint16_t DOLPHIN_DATA_PORT = 54970; @@ -18,15 +18,16 @@ enum { CMD_POLL = 0x00, CMD_TRANS = 0x14, CMD_RECV = 0x15, + + CMD_NONE = 0x80 }; -// static bool GBASIODolphinInit(struct GBASIODriver* driver); -// static void GBASIODolphinDeinit(struct GBASIODriver* driver); static bool GBASIODolphinLoad(struct GBASIODriver* driver); -// static bool GBASIODolphinUnload(struct GBASIODriver* driver); static uint16_t GBASIODolphinWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); static int32_t GBASIODolphinProcessEvents(struct GBASIODriver* driver, int32_t cycles); +static int32_t _processCommand(struct GBASIODolphin* dol, uint8_t command); + void GBASIODolphinCreate(struct GBASIODolphin* dol) { dol->d.init = 0; dol->d.deinit = 0; @@ -75,18 +76,21 @@ bool GBASIODolphinConnect(struct GBASIODolphin* dol, const struct Address* addre dol->clock = SocketConnectTCP(clockPort, address); if (SOCKET_FAILED(dol->clock)) { - SocketClose(dol->clock); + SocketClose(dol->data); + dol->data = INVALID_SOCKET; return false; } SocketSetBlocking(dol->data, false); SocketSetBlocking(dol->clock, false); + SocketSetTCPPush(dol->data, true); return true; } static bool GBASIODolphinLoad(struct GBASIODriver* driver) { struct GBASIODolphin* dol = (struct GBASIODolphin*) driver; dol->nextEvent = 0; + dol->clockSlice = 0; return true; } @@ -108,63 +112,76 @@ uint16_t GBASIODolphinWriteRegister(struct GBASIODriver* driver, uint32_t addres int32_t GBASIODolphinProcessEvents(struct GBASIODriver* driver, int32_t cycles) { struct GBASIODolphin* dol = (struct GBASIODolphin*) driver; dol->nextEvent -= cycles; + dol->clockSlice -= cycles; if (dol->nextEvent <= 0) { uint8_t command; - int32_t nextEvent = CLOCK_GRAIN; - uint32_t clocks = 0; - uint32_t clockSlice; - while (SocketRecv(dol->clock, &clockSlice, 4) == 4) { - clocks += ntohl(clockSlice); - } - while (SocketRecv(dol->data, &command, 1) == 1) { - int bitsOnLine = 8 + 1; - uint8_t buffer[5]; - - switch (command) { - case CMD_RESET: - dol->d.p->p->memory.io[REG_JOYCNT >> 1] |= 1; - if (dol->d.p->p->memory.io[REG_JOYCNT >> 1] & 0x40) { - GBARaiseIRQ(dol->d.p->p, IRQ_SIO); - } - // Fall through - case CMD_POLL: - buffer[0] = 0x00; - buffer[1] = 0x04; - buffer[2] = dol->d.p->p->memory.io[REG_JOYSTAT >> 1]; - SocketSend(dol->data, buffer, 3); - bitsOnLine += 24 + 1; - break; - case CMD_RECV: - dol->d.p->p->memory.io[REG_JOYCNT >> 1] |= 2; - dol->d.p->p->memory.io[REG_JOYSTAT >> 1] |= 2; - SocketRecv(dol->data, &buffer, 4); - dol->d.p->p->memory.io[REG_JOY_RECV_LO >> 1] = buffer[0] | (buffer[1] << 8); - dol->d.p->p->memory.io[REG_JOY_RECV_HI >> 1] = buffer[2] | (buffer[3] << 8); - buffer[0] = dol->d.p->p->memory.io[REG_JOYSTAT >> 1]; - SocketSend(dol->data, buffer, 1); - if (dol->d.p->p->memory.io[REG_JOYCNT >> 1] & 0x40) { - GBARaiseIRQ(dol->d.p->p, IRQ_SIO); - } - bitsOnLine += 40 + 1; - break; - case CMD_TRANS: - dol->d.p->p->memory.io[REG_JOYCNT >> 1] |= 4; - dol->d.p->p->memory.io[REG_JOYSTAT >> 1] &= ~8; - buffer[0] = dol->d.p->p->memory.io[REG_JOY_TRANS_LO >> 1]; - buffer[1] = dol->d.p->p->memory.io[REG_JOY_TRANS_LO >> 1] >> 8; - buffer[2] = dol->d.p->p->memory.io[REG_JOY_TRANS_HI >> 1]; - buffer[3] = dol->d.p->p->memory.io[REG_JOY_TRANS_HI >> 1] >> 8; - buffer[4] = dol->d.p->p->memory.io[REG_JOYSTAT >> 1]; - SocketSend(dol->data, buffer, 5); - if (dol->d.p->p->memory.io[REG_JOYCNT >> 1] & 0x40) { - GBARaiseIRQ(dol->d.p->p, IRQ_SIO); - } - bitsOnLine += 40 + 1; - break; + int32_t clockSlice = 0; + if (dol->clockSlice <= 0) { + Socket r = dol->clock; + if (SocketPoll(1, &r, 0, 0, 1) == 1 && SocketRecv(dol->clock, &clockSlice, 4) == 4) { + clockSlice = ntohl(clockSlice); + dol->clockSlice += clockSlice; } - nextEvent = bitsOnLine * CYCLES_PER_BIT; } - dol->nextEvent += nextEvent; + + if (SocketRecv(dol->data, &command, 1) == 1) { + dol->nextEvent += _processCommand(dol, command); + } else { + dol->nextEvent += CLOCK_GRAIN; + } + + if (dol->nextEvent > dol->clockSlice) { + dol->nextEvent = dol->clockSlice; + } } return dol->nextEvent; } + +int32_t _processCommand(struct GBASIODolphin* dol, uint8_t command) { + int bitsOnLine = 8 + 1; + uint8_t buffer[5]; + + switch (command) { + case CMD_RESET: + dol->d.p->p->memory.io[REG_JOYCNT >> 1] |= 1; + if (dol->d.p->p->memory.io[REG_JOYCNT >> 1] & 0x40) { + GBARaiseIRQ(dol->d.p->p, IRQ_SIO); + } + // Fall through + case CMD_POLL: + buffer[0] = 0x00; + buffer[1] = 0x04; + buffer[2] = dol->d.p->p->memory.io[REG_JOYSTAT >> 1]; + SocketSend(dol->data, buffer, 3); + bitsOnLine += 24 + 1; + break; + case CMD_RECV: + dol->d.p->p->memory.io[REG_JOYCNT >> 1] |= 2; + dol->d.p->p->memory.io[REG_JOYSTAT >> 1] |= 2; + SocketRecv(dol->data, &buffer, 4); + dol->d.p->p->memory.io[REG_JOY_RECV_LO >> 1] = buffer[0] | (buffer[1] << 8); + dol->d.p->p->memory.io[REG_JOY_RECV_HI >> 1] = buffer[2] | (buffer[3] << 8); + buffer[0] = dol->d.p->p->memory.io[REG_JOYSTAT >> 1]; + SocketSend(dol->data, buffer, 1); + if (dol->d.p->p->memory.io[REG_JOYCNT >> 1] & 0x40) { + GBARaiseIRQ(dol->d.p->p, IRQ_SIO); + } + bitsOnLine += 40 + 1; + break; + case CMD_TRANS: + dol->d.p->p->memory.io[REG_JOYCNT >> 1] |= 4; + dol->d.p->p->memory.io[REG_JOYSTAT >> 1] &= ~8; + buffer[0] = dol->d.p->p->memory.io[REG_JOY_TRANS_LO >> 1]; + buffer[1] = dol->d.p->p->memory.io[REG_JOY_TRANS_LO >> 1] >> 8; + buffer[2] = dol->d.p->p->memory.io[REG_JOY_TRANS_HI >> 1]; + buffer[3] = dol->d.p->p->memory.io[REG_JOY_TRANS_HI >> 1] >> 8; + buffer[4] = dol->d.p->p->memory.io[REG_JOYSTAT >> 1]; + SocketSend(dol->data, buffer, 5); + if (dol->d.p->p->memory.io[REG_JOYCNT >> 1] & 0x40) { + GBARaiseIRQ(dol->d.p->p, IRQ_SIO); + } + bitsOnLine += 40 + 1; + break; + } + return bitsOnLine * CYCLES_PER_BIT; +} diff --git a/src/gba/sio/dolphin.h b/src/gba/sio/dolphin.h index 2ba4e53b6..5d09a6a7e 100644 --- a/src/gba/sio/dolphin.h +++ b/src/gba/sio/dolphin.h @@ -20,6 +20,7 @@ struct GBASIODolphin { Socket clock; int32_t nextEvent; + int32_t clockSlice; }; void GBASIODolphinCreate(struct GBASIODolphin*);