GBA SIO: Fix Dolphin connection when driver is inactive

This commit is contained in:
Vicki Pfau 2021-03-27 16:47:29 -07:00
parent b2fdb22cd7
commit a5890bfea5
2 changed files with 36 additions and 4 deletions

View File

@ -27,6 +27,7 @@ struct GBASIODolphin {
int32_t clockSlice; int32_t clockSlice;
int state; int state;
bool active;
}; };
void GBASIODolphinCreate(struct GBASIODolphin*); void GBASIODolphinCreate(struct GBASIODolphin*);

View File

@ -22,14 +22,19 @@ enum {
WAIT_FOR_COMMAND, WAIT_FOR_COMMAND,
}; };
static bool GBASIODolphinInit(struct GBASIODriver* driver);
static bool GBASIODolphinLoad(struct GBASIODriver* driver); static bool GBASIODolphinLoad(struct GBASIODriver* driver);
static bool GBASIODolphinUnload(struct GBASIODriver* driver);
static void GBASIODolphinProcessEvents(struct mTiming* timing, void* context, uint32_t cyclesLate); static void GBASIODolphinProcessEvents(struct mTiming* timing, void* context, uint32_t cyclesLate);
static int32_t _processCommand(struct GBASIODolphin* dol, uint32_t cyclesLate); static int32_t _processCommand(struct GBASIODolphin* dol, uint32_t cyclesLate);
static void _flush(struct GBASIODolphin* dol);
void GBASIODolphinCreate(struct GBASIODolphin* dol) { void GBASIODolphinCreate(struct GBASIODolphin* dol) {
GBASIOJOYCreate(&dol->d); GBASIOJOYCreate(&dol->d);
dol->d.init = GBASIODolphinInit;
dol->d.load = GBASIODolphinLoad; dol->d.load = GBASIODolphinLoad;
dol->d.unload = GBASIODolphinUnload;
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;
@ -37,6 +42,7 @@ void GBASIODolphinCreate(struct GBASIODolphin* dol) {
dol->data = INVALID_SOCKET; dol->data = INVALID_SOCKET;
dol->clock = INVALID_SOCKET; dol->clock = INVALID_SOCKET;
dol->active = false;
} }
void GBASIODolphinDestroy(struct GBASIODolphin* dol) { void GBASIODolphinDestroy(struct GBASIODolphin* dol) {
@ -86,15 +92,30 @@ bool GBASIODolphinConnect(struct GBASIODolphin* dol, const struct Address* addre
return true; return true;
} }
static bool GBASIODolphinLoad(struct GBASIODriver* driver) { static bool GBASIODolphinInit(struct GBASIODriver* driver) {
struct GBASIODolphin* dol = (struct GBASIODolphin*) driver; struct GBASIODolphin* dol = (struct GBASIODolphin*) driver;
dol->active = false;
dol->clockSlice = 0; dol->clockSlice = 0;
dol->state = WAIT_FOR_FIRST_CLOCK; dol->state = WAIT_FOR_FIRST_CLOCK;
_flush(dol);
return true;
}
static bool GBASIODolphinLoad(struct GBASIODriver* driver) {
struct GBASIODolphin* dol = (struct GBASIODolphin*) driver;
dol->active = true;
_flush(dol);
mTimingDeschedule(&dol->d.p->p->timing, &dol->event); mTimingDeschedule(&dol->d.p->p->timing, &dol->event);
mTimingSchedule(&dol->d.p->p->timing, &dol->event, 0); mTimingSchedule(&dol->d.p->p->timing, &dol->event, 0);
return true; return true;
} }
static bool GBASIODolphinUnload(struct GBASIODriver* driver) {
struct GBASIODolphin* dol = (struct GBASIODolphin*) driver;
dol->active = false;
return true;
}
void GBASIODolphinProcessEvents(struct mTiming* timing, void* context, uint32_t cyclesLate) { void GBASIODolphinProcessEvents(struct mTiming* timing, void* context, uint32_t cyclesLate) {
struct GBASIODolphin* dol = context; struct GBASIODolphin* dol = context;
if (SOCKET_FAILED(dol->data)) { if (SOCKET_FAILED(dol->data)) {
@ -127,7 +148,7 @@ void GBASIODolphinProcessEvents(struct mTiming* timing, void* context, uint32_t
Socket r = dol->data; Socket r = dol->data;
SocketPoll(1, &r, 0, 0, CLOCK_WAIT); SocketPoll(1, &r, 0, 0, CLOCK_WAIT);
} }
if (_processCommand(dol, cyclesLate)) { if (_processCommand(dol, cyclesLate) >= 0) {
dol->state = WAIT_FOR_CLOCK; dol->state = WAIT_FOR_CLOCK;
nextEvent = CLOCK_GRAIN; nextEvent = CLOCK_GRAIN;
} }
@ -138,13 +159,19 @@ void GBASIODolphinProcessEvents(struct mTiming* timing, void* context, uint32_t
mTimingSchedule(timing, &dol->event, nextEvent); mTimingSchedule(timing, &dol->event, nextEvent);
} }
void _flush(struct GBASIODolphin* dol) {
uint8_t buffer[32];
while (SocketRecv(dol->clock, buffer, sizeof(buffer)) == sizeof(buffer));
while (SocketRecv(dol->data, buffer, sizeof(buffer)) == sizeof(buffer));
}
int32_t _processCommand(struct GBASIODolphin* dol, uint32_t cyclesLate) { int32_t _processCommand(struct GBASIODolphin* dol, uint32_t cyclesLate) {
// This does not include the stop bits due to compatibility reasons // This does not include the stop bits due to compatibility reasons
int bitsOnLine = 8; int bitsOnLine = 8;
uint8_t buffer[6]; uint8_t buffer[6];
int gotten = SocketRecv(dol->data, buffer, 1); int gotten = SocketRecv(dol->data, buffer, 1);
if (gotten < 1) { if (gotten < 1) {
return 0; return -1;
} }
switch (buffer[0]) { switch (buffer[0]) {
@ -155,7 +182,7 @@ int32_t _processCommand(struct GBASIODolphin* dol, uint32_t cyclesLate) {
case JOY_RECV: case JOY_RECV:
gotten = SocketRecv(dol->data, &buffer[1], 4); gotten = SocketRecv(dol->data, &buffer[1], 4);
if (gotten < 4) { if (gotten < 4) {
return 0; return -1;
} }
mLOG(GBA_SIO, DEBUG, "DOL recv: %02X%02X%02X%02X", buffer[1], buffer[2], buffer[3], buffer[4]); mLOG(GBA_SIO, DEBUG, "DOL recv: %02X%02X%02X%02X", buffer[1], buffer[2], buffer[3], buffer[4]);
// Fall through // Fall through
@ -164,6 +191,10 @@ int32_t _processCommand(struct GBASIODolphin* dol, uint32_t cyclesLate) {
break; break;
} }
if (!dol->active) {
return 0;
}
int sent = GBASIOJOYSendCommand(&dol->d, buffer[0], &buffer[1]); int sent = GBASIOJOYSendCommand(&dol->d, buffer[0], &buffer[1]);
SocketSend(dol->data, &buffer[1], sent); SocketSend(dol->data, &buffer[1], sent);