diff --git a/network/netplay/netplay_delta.c b/network/netplay/netplay_delta.c index 2309d4b78d..ac9677093e 100644 --- a/network/netplay/netplay_delta.c +++ b/network/netplay/netplay_delta.c @@ -59,9 +59,9 @@ bool netplay_delta_frame_ready(netplay_t *netplay, struct delta_frame *delta, delta->crc = 0; for (i = 0; i < MAX_INPUT_DEVICES; i++) { - clear_input(delta->resolved_input[i]); - clear_input(delta->real_input[i]); - clear_input(delta->simulated_input[i]); + clear_input(delta->resolved_input1[i]); + clear_input(delta->real_input1[i]); + clear_input(delta->simulated_input1[i]); } delta->have_local = false; for (i = 0; i < MAX_CLIENTS; i++) @@ -117,9 +117,9 @@ void netplay_delta_frame_free(struct delta_frame *delta) for (i = 0; i < MAX_INPUT_DEVICES; i++) { - free_input_state(&delta->resolved_input[i]); - free_input_state(&delta->real_input[i]); - free_input_state(&delta->simulated_input[i]); + free_input_state(&delta->resolved_input1[i]); + free_input_state(&delta->real_input1[i]); + free_input_state(&delta->simulated_input1[i]); } } @@ -129,13 +129,13 @@ void netplay_delta_frame_free(struct delta_frame *delta) * Get an input state for a particular client */ netplay_input_state_t netplay_input_state_for(netplay_input_state_t *list, - uint32_t client_num, size_t size, bool must_create) + uint32_t client_num, size_t size, bool must_create, bool must_not_create) { netplay_input_state_t ret; while (*list) { ret = *list; - if (!ret->used && ret->size == size) + if (!ret->used && !must_not_create && ret->size == size) { ret->client_num = client_num; ret->used = true; @@ -151,6 +151,9 @@ netplay_input_state_t netplay_input_state_for(netplay_input_state_t *list, list = &(ret->next); } + if (must_not_create) + return NULL; + /* Couldn't find a slot, allocate a fresh one */ ret = calloc(1, sizeof(struct netplay_input_state) + (size-1) * sizeof(uint32_t)); if (!ret) diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 8196e58650..efac48fa41 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -135,8 +135,8 @@ static bool get_self_input_state(netplay_t *netplay) if (!(devices & (1<real_input[devi], - netplay->self_client_num, 3 /* FIXME */, true); + istate = netplay_input_state_for(&ptr->real_input1[devi], + netplay->self_client_num, 3 /* FIXME */, true, false); if (!istate) continue; /* FIXME: More severe? */ @@ -501,11 +501,9 @@ static int16_t netplay_input_state(netplay_t *netplay, /* FIXME: Mixing */ delta = &netplay->buffer[ptr]; - istate = delta->real_input[port]; + istate = delta->resolved_input1[port]; if (istate && istate->used) delta->used_real[port] = true; - else - istate = delta->simulated_input[port]; if (!istate) return 0; diff --git a/network/netplay/netplay_io.c b/network/netplay/netplay_io.c index b54f40f225..043cdcb52b 100644 --- a/network/netplay/netplay_io.c +++ b/network/netplay/netplay_io.c @@ -225,7 +225,7 @@ static bool send_input_frame(netplay_t *netplay, struct delta_frame *dframe, netplay_input_state_t istate; if (!(devices & (1<real_input[device]; + istate = dframe->real_input1[device]; while (istate && istate->client_num != client_num) istate = istate->next; if (!istate) @@ -633,8 +633,13 @@ static bool netplay_get_cmd(netplay_t *netplay, continue; dsize = netplay_expected_input_size(1 << device); - istate = netplay_input_state_for(&dframe->real_input[device], - client_num, dsize, true); + istate = netplay_input_state_for(&dframe->real_input1[device], + client_num, dsize, true, false); + if (!istate) + { + /* Catastrophe! */ + return netplay_cmd_nak(netplay, connection); + } RECV(istate->data, dsize*sizeof(uint32_t)) return false; for (di = 0; di < dsize; di++) @@ -1002,7 +1007,9 @@ static bool netplay_get_cmd(netplay_t *netplay, for (device = 0; device < MAX_INPUT_DEVICES; device++) { if (!(devices & (1<real_input[device], client_num, 3 /* FIXME */, true); + netplay_input_state_t istate = netplay_input_state_for( + &dframe->real_input1[device], client_num, + 3 /* FIXME */, true, false); memset(istate->data, 0, istate->size*sizeof(uint32_t)); } dframe->have_local = true; @@ -1653,13 +1660,13 @@ void netplay_handle_slaves(netplay_t *netplay) netplay_input_state_t istate_out, istate_in; if (!(devices & (1<real_input[device]; + istate_in = oframe->real_input1[device]; while (istate_in && istate_in->client_num != client_num) istate_in = istate_in->next; if (!istate_in) continue; - istate_out = netplay_input_state_for(&frame->real_input[device], - client_num, istate_in->size, true); + istate_out = netplay_input_state_for(&frame->real_input1[device], + client_num, istate_in->size, true, false); memcpy(istate_out->data, istate_in->data, istate_in->size * sizeof(uint32_t)); } diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index d59ba73d32..7fe863d518 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -278,14 +278,14 @@ struct delta_frame /* The resolved input, i.e., what's actually going to the core. One input * per device. */ - netplay_input_state_t resolved_input[MAX_INPUT_DEVICES]; + netplay_input_state_t resolved_input1[MAX_INPUT_DEVICES]; /* The real input */ - netplay_input_state_t real_input[MAX_INPUT_DEVICES]; + netplay_input_state_t real_input1[MAX_INPUT_DEVICES]; /* The simulated input. is_real here means the simulation is done, i.e., * it's a real simulation, not real input. */ - netplay_input_state_t simulated_input[MAX_INPUT_DEVICES]; + netplay_input_state_t simulated_input1[MAX_INPUT_DEVICES]; /* Have we read local input? */ bool have_local; @@ -656,7 +656,7 @@ void netplay_delta_frame_free(struct delta_frame *delta); * Get an input state for a particular client */ netplay_input_state_t netplay_input_state_for(netplay_input_state_t *list, - uint32_t client_num, size_t size, bool must_create); + uint32_t client_num, size_t size, bool must_create, bool must_not_create); /** * netplay_expected_input_size diff --git a/network/netplay/netplay_sync.c b/network/netplay/netplay_sync.c index 5414b5a889..9fb7295746 100644 --- a/network/netplay/netplay_sync.c +++ b/network/netplay/netplay_sync.c @@ -98,68 +98,79 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) uint32_t client; size_t prev; struct delta_frame *simframe, *pframe; - netplay_input_state_t simstate, pstate; + netplay_input_state_t simstate, resstate, pstate; uint32_t devices, device; - bool ret = false; + bool ret = false, simulated; simframe = &netplay->buffer[sim_ptr]; for (client = 0; client < MAX_CLIENTS; client++) { if (!(netplay->connected_players1 & (1<have_real[client]) continue; devices = netplay->client_devices[client]; for (device = 0; device < MAX_INPUT_DEVICES; device++) { - if (!(devices & device)) continue; + if (!(devices & (1<simulated_input[device], client, 3 /* FIXME */, false); + simulated = false; + simstate = netplay_input_state_for(&simframe->real_input1[device], client, 3 /* FIXME */, false, true); if (!simstate) - continue; - - prev = PREV_PTR(netplay->read_ptr1[client]); - pframe = &netplay->buffer[prev]; - pstate = netplay_input_state_for(&pframe->real_input[device], client, 3 /* FIXME */, false); - if (!pstate) - continue; - - if (resim) { - /* In resimulation mode, we only copy the buttons. The reason for this - * is nonobvious: - * - * If we resimulated nothing, then the /duration/ with which any input - * was pressed would be approximately correct, since the original - * simulation came in as the input came in, but the /number of times/ - * the input was pressed would be wrong, as there would be an - * advancing wavefront of real data overtaking the simulated data - * (which is really just real data offset by some frames). - * - * That's acceptable for arrows in most situations, since the amount - * you move is tied to the duration, but unacceptable for buttons, - * which will seem to jerkily be pressed numerous times with those - * wavefronts. - */ - const uint32_t keep = (1U<data[0]; - simstate->data[0] &= keep; - simstate->data[0] |= pstate->data[0] & ~keep; - if (prev != simstate->data[0]) - ret = true; - } - else - { - if (memcmp(simstate->data, pstate->data, simstate->size * sizeof(uint32_t))) - ret = true; - memcpy(simstate->data, pstate->data, - simstate->size * sizeof(uint32_t)); + /* Don't already have this input, so must simulate */ + simulated = true; + simstate = netplay_input_state_for(&simframe->simulated_input1[device], client, 3 /* FIXME */, false, false); + if (!simstate) + continue; + + prev = PREV_PTR(netplay->read_ptr1[client]); + pframe = &netplay->buffer[prev]; + pstate = netplay_input_state_for(&pframe->real_input1[device], client, 3 /* FIXME */, false, true); + if (!pstate) + continue; + + if (resim) + { + /* In resimulation mode, we only copy the buttons. The reason for this + * is nonobvious: + * + * If we resimulated nothing, then the /duration/ with which any input + * was pressed would be approximately correct, since the original + * simulation came in as the input came in, but the /number of times/ + * the input was pressed would be wrong, as there would be an + * advancing wavefront of real data overtaking the simulated data + * (which is really just real data offset by some frames). + * + * That's acceptable for arrows in most situations, since the amount + * you move is tied to the duration, but unacceptable for buttons, + * which will seem to jerkily be pressed numerous times with those + * wavefronts. + */ + const uint32_t keep = (1U<data[0]; + simstate->data[0] &= keep; + simstate->data[0] |= pstate->data[0] & ~keep; + } + else + { + memcpy(simstate->data, pstate->data, + simstate->size * sizeof(uint32_t)); + } } + + /* Now we copy the state, whether real or simulated, out into the resolved state (FIXME: Merging) */ + resstate = netplay_input_state_for(&simframe->resolved_input1[device], 0, 3 /* FIXME */, false, false); + if (!resstate) + continue; + resstate->used = !simulated; /* We reuse "used" to mean "real" */ + if (memcmp(resstate->data, simstate->data, resstate->size * sizeof(uint32_t))) + ret = true; + memcpy(resstate->data, simstate->data, resstate->size * sizeof(uint32_t)); } } @@ -440,7 +451,6 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled) } #ifndef DEBUG_NONDETERMINISTIC_CORES -#if 0 /* FIXME: netplay_resolve_input is broken */ if (!netplay->force_rewind) { /* Skip ahead if we predicted correctly. @@ -460,7 +470,6 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled) netplay->other_frame_count++; } } -#endif #endif /* Now replay the real input if we've gotten ahead of it */