mirror of https://github.com/mgba-emu/mgba.git
GBA SIO: Attempt to clean up resyncing on disconnects
This commit is contained in:
parent
7089a5572b
commit
3f7cfb3e32
|
@ -115,6 +115,23 @@ static void _hardSync(struct GBASIOLockstepCoordinator*, struct GBASIOLockstepPl
|
||||||
|
|
||||||
static void _lockstepEvent(struct mTiming*, void* context, uint32_t cyclesLate);
|
static void _lockstepEvent(struct mTiming*, void* context, uint32_t cyclesLate);
|
||||||
|
|
||||||
|
static void _verifyAwake(struct GBASIOLockstepCoordinator* coordinator) {
|
||||||
|
#ifdef NDEBUG
|
||||||
|
UNUSED(coordinator);
|
||||||
|
#else
|
||||||
|
int i;
|
||||||
|
int asleep = 0;
|
||||||
|
for (i = 0; i < coordinator->nAttached; ++i) {
|
||||||
|
if (!coordinator->attachedPlayers[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, coordinator->attachedPlayers[i]);
|
||||||
|
asleep += player->asleep;
|
||||||
|
}
|
||||||
|
mASSERT_DEBUG(!asleep || asleep < coordinator->nAttached);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void GBASIOLockstepDriverCreate(struct GBASIOLockstepDriver* driver, struct mLockstepUser* user) {
|
void GBASIOLockstepDriverCreate(struct GBASIOLockstepDriver* driver, struct mLockstepUser* user) {
|
||||||
memset(driver, 0, sizeof(*driver));
|
memset(driver, 0, sizeof(*driver));
|
||||||
driver->d.init = GBASIOLockstepDriverInit;
|
driver->d.init = GBASIOLockstepDriverInit;
|
||||||
|
@ -189,8 +206,8 @@ static void GBASIOLockstepDriverReset(struct GBASIODriver* driver) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_reconfigPlayers(coordinator);
|
_reconfigPlayers(coordinator);
|
||||||
|
player->cycleOffset = mTimingCurrentTime(&driver->p->p->timing) - coordinator->cycle;
|
||||||
if (player->playerId != 0) {
|
if (player->playerId != 0) {
|
||||||
player->cycleOffset = mTimingCurrentTime(&driver->p->p->timing) - coordinator->cycle + LOCKSTEP_INTERVAL;
|
|
||||||
struct GBASIOLockstepEvent event = {
|
struct GBASIOLockstepEvent event = {
|
||||||
.type = SIO_EV_ATTACH,
|
.type = SIO_EV_ATTACH,
|
||||||
.playerId = player->playerId,
|
.playerId = player->playerId,
|
||||||
|
@ -200,9 +217,7 @@ static void GBASIOLockstepDriverReset(struct GBASIODriver* driver) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
player = TableLookup(&coordinator->players, lockstep->lockstepId);
|
player = TableLookup(&coordinator->players, lockstep->lockstepId);
|
||||||
if (player->playerId != 0) {
|
player->cycleOffset = mTimingCurrentTime(&driver->p->p->timing) - coordinator->cycle;
|
||||||
player->cycleOffset = mTimingCurrentTime(&driver->p->p->timing) - coordinator->cycle + LOCKSTEP_INTERVAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTimingIsScheduled(&lockstep->d.p->p->timing, &lockstep->event)) {
|
if (mTimingIsScheduled(&lockstep->d.p->p->timing, &lockstep->event)) {
|
||||||
|
@ -662,12 +677,18 @@ void _removePlayer(struct GBASIOLockstepCoordinator* coordinator, struct GBASIOL
|
||||||
.timestamp = GBASIOLockstepTime(player),
|
.timestamp = GBASIOLockstepTime(player),
|
||||||
};
|
};
|
||||||
_enqueueEvent(coordinator, &event, TARGET_ALL & ~TARGET(player->playerId));
|
_enqueueEvent(coordinator, &event, TARGET_ALL & ~TARGET(player->playerId));
|
||||||
GBASIOLockstepCoordinatorWakePlayers(coordinator);
|
|
||||||
if (player->playerId != 0) {
|
coordinator->waiting = 0;
|
||||||
GBASIOLockstepCoordinatorAckPlayer(coordinator, player);
|
coordinator->transferActive = false;
|
||||||
}
|
|
||||||
TableRemove(&coordinator->players, player->driver->lockstepId);
|
TableRemove(&coordinator->players, player->driver->lockstepId);
|
||||||
_reconfigPlayers(coordinator);
|
_reconfigPlayers(coordinator);
|
||||||
|
|
||||||
|
struct GBASIOLockstepPlayer* runner = TableLookup(&coordinator->players, coordinator->attachedPlayers[0]);
|
||||||
|
if (runner) {
|
||||||
|
GBASIOLockstepPlayerWake(runner);
|
||||||
|
}
|
||||||
|
_verifyAwake(coordinator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _reconfigPlayers(struct GBASIOLockstepCoordinator* coordinator) {
|
void _reconfigPlayers(struct GBASIOLockstepCoordinator* coordinator) {
|
||||||
|
@ -863,8 +884,10 @@ void _lockstepEvent(struct mTiming* timing, void* context, uint32_t cyclesLate)
|
||||||
player->queue->playerId, player->queue->timestamp);
|
player->queue->playerId, player->queue->timestamp);
|
||||||
wasDetach = true;
|
wasDetach = true;
|
||||||
}
|
}
|
||||||
if (player->playerId == 0) {
|
if (player->playerId == 0 && GBASIOLockstepTime(player) - coordinator->cycle >= 0) {
|
||||||
// We are the clock owner; advance the shared clock
|
// We are the clock owner; advance the shared clock. However, if we just became
|
||||||
|
// the clock owner (by the previous one disconnecting) we might be slightly
|
||||||
|
// behind the shared clock. We should wait a bit if needed in that case.
|
||||||
_advanceCycle(coordinator, player);
|
_advanceCycle(coordinator, player);
|
||||||
if (!coordinator->transferActive) {
|
if (!coordinator->transferActive) {
|
||||||
GBASIOLockstepCoordinatorWakePlayers(coordinator);
|
GBASIOLockstepCoordinatorWakePlayers(coordinator);
|
||||||
|
@ -949,6 +972,7 @@ void _lockstepEvent(struct mTiming* timing, void* context, uint32_t cyclesLate)
|
||||||
if (nextEvent < 4) {
|
if (nextEvent < 4) {
|
||||||
nextEvent = 4;
|
nextEvent = 4;
|
||||||
}
|
}
|
||||||
|
_verifyAwake(coordinator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MutexUnlock(&coordinator->mutex);
|
MutexUnlock(&coordinator->mutex);
|
||||||
|
@ -974,6 +998,8 @@ void GBASIOLockstepCoordinatorWaitOnPlayers(struct GBASIOLockstepCoordinator* co
|
||||||
coordinator->waiting = ((1 << coordinator->nAttached) - 1) & ~TARGET(player->playerId);
|
coordinator->waiting = ((1 << coordinator->nAttached) - 1) & ~TARGET(player->playerId);
|
||||||
GBASIOLockstepPlayerSleep(player);
|
GBASIOLockstepPlayerSleep(player);
|
||||||
GBASIOLockstepCoordinatorWakePlayers(coordinator);
|
GBASIOLockstepCoordinatorWakePlayers(coordinator);
|
||||||
|
|
||||||
|
_verifyAwake(coordinator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBASIOLockstepCoordinatorWakePlayers(struct GBASIOLockstepCoordinator* coordinator) {
|
void GBASIOLockstepCoordinatorWakePlayers(struct GBASIOLockstepCoordinator* coordinator) {
|
||||||
|
|
Loading…
Reference in New Issue