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;
int state;
bool active;
};
void GBASIODolphinCreate(struct GBASIODolphin*);

View File

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