diff --git a/network/netplay/netplay_delta.c b/network/netplay/netplay_delta.c index a759d68f52..7828cb9f9a 100644 --- a/network/netplay/netplay_delta.c +++ b/network/netplay/netplay_delta.c @@ -65,10 +65,7 @@ bool netplay_delta_frame_ready(netplay_t *netplay, struct delta_frame *delta, } delta->have_local = false; for (i = 0; i < MAX_CLIENTS; i++) - { delta->have_real[i] = false; - delta->used_real[i] = false; - } return true; } diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index a731874eeb..d0058029ce 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -496,11 +496,8 @@ static int16_t netplay_input_state(netplay_t *netplay, return 0; } - /* FIXME: Mixing */ delta = &netplay->buffer[ptr]; istate = delta->resolved_input[port]; - if (istate && istate->used) - delta->used_real[port] = true; if (!istate) return 0; @@ -1253,23 +1250,23 @@ static void netplay_toggle_play_spectate(netplay_t *netplay) } else { - uint32_t cmd; + enum rarch_netplay_connection_mode mode; if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING || netplay->self_mode == NETPLAY_CONNECTION_SLAVE) { /* Switch to spectator mode immediately */ netplay->self_mode = NETPLAY_CONNECTION_SPECTATING; - cmd = NETPLAY_CMD_SPECTATE; + mode = NETPLAY_CONNECTION_SPECTATING; } else if (netplay->self_mode == NETPLAY_CONNECTION_SPECTATING) { /* Switch only after getting permission */ - cmd = NETPLAY_CMD_PLAY; + mode = NETPLAY_CONNECTION_PLAYING; } else return; - netplay_send_raw_cmd_all(netplay, NULL, cmd, NULL, 0); + netplay_cmd_mode(netplay, &netplay->one_connection, mode); } } diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index 446828d7eb..982ce5ddcf 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -318,9 +318,6 @@ struct delta_frame /* Have we read the real (remote) input? */ bool have_real[MAX_CLIENTS]; - - /* Is the current state as of self_frame_count using the real (remote) data? */ - bool used_real[MAX_CLIENTS]; }; struct socket_buffer diff --git a/network/netplay/netplay_sync.c b/network/netplay/netplay_sync.c index 9d5608427f..f85312082e 100644 --- a/network/netplay/netplay_sync.c +++ b/network/netplay/netplay_sync.c @@ -88,21 +88,21 @@ struct vote_count { /** * netplay_device_client_state - * @resstate : state being resolved + * @netplay : pointer to netplay object * @simframe : frame in which merging is being performed * @device : device being merged * @client : client to find state for */ -netplay_input_state_t netplay_device_client_state( - netplay_input_state_t resstate, struct delta_frame *simframe, - uint32_t device, uint32_t client) +netplay_input_state_t netplay_device_client_state(netplay_t *netplay, + struct delta_frame *simframe, uint32_t device, uint32_t client) { netplay_input_state_t simstate = netplay_input_state_for( &simframe->real_input[device], client, 3 /* FIXME */, false, true); if (!simstate) { - resstate->used = false; + if (netplay->read_frame_count1[client] > simframe->frame) + return NULL; simstate = netplay_input_state_for(&simframe->simlated_input[device], client, 3 /* FIXME */, false, true); } @@ -125,6 +125,14 @@ static void netplay_merge_digital(netplay_t *netplay, netplay_input_state_t simstate; uint32_t word, bit, client; uint8_t share_mode = netplay->device_share_modes[device] & NETPLAY_SHARE_DIGITAL_BITS; + + /* Make sure all real clients are accounted for */ + for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next) + { + if (!simstate->used || simstate->size != 3 /* FIXME */) continue; + clients |= 1<client_num; + } + if (share_mode == NETPLAY_SHARE_DIGITAL_VOTE) { /* Vote mode requires counting all the bits */ @@ -133,9 +141,9 @@ static void netplay_merge_digital(netplay_t *netplay, for (client = 0; client < MAX_CLIENTS; client++) { if (!(clients & (1<device_share_modes[device] & NETPLAY_SHARE_ANALOG_BITS; int32_t value = 0, new_value; + /* Make sure all real clients are accounted for */ + for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next) + { + if (!simstate->used || simstate->size != 3 /* FIXME */) continue; + clients |= 1<client_num; + } + for (client = 0; client < MAX_CLIENTS; client++) { if (!(clients & (1<data[word]>>bit) & 0xFFFF); switch (share_mode) { @@ -279,31 +294,36 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) { size_t prev; struct delta_frame *simframe, *pframe; - netplay_input_state_t simstate, resstate, oldresstate, pstate; + netplay_input_state_t simstate, client_state = NULL, resstate, oldresstate, pstate; uint32_t clients, client, client_count; uint32_t device; - bool ret = false, simulated; + bool ret = false; simframe = &netplay->buffer[sim_ptr]; for (device = 0; device < MAX_INPUT_DEVICES; device++) { clients = netplay->device_clients[device]; - if (!clients) continue; client_count = 0; + /* Make sure all real clients are accounted for */ + for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next) + { + if (!simstate->used || simstate->size != 3 /* FIXME */) continue; + clients |= 1<client_num; + } + for (client = 0; client < MAX_CLIENTS; client++) { if (!(clients & (1<real_input[device], client, 3 /* FIXME */, false, true); if (!simstate) { - /* Don't already have this input, so must simulate */ - simulated = true; + /* Don't already have this input, so must simulate if we're supposed to have it at all */ + if (netplay->read_frame_count1[client] > simframe->frame) + continue; simstate = netplay_input_state_for(&simframe->simlated_input[device], client, 3 /* FIXME */, false, false); if (!simstate) continue; @@ -345,6 +365,9 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) simstate->size * sizeof(uint32_t)); } } + + client_state = simstate; + client_count++; } /* Now we copy the state, whether real or simulated, out into the resolved state */ @@ -355,12 +378,24 @@ bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim) if (client_count == 1) { /* Trivial in the common 1-client case */ - resstate->used = !simulated; /* We reuse "used" to mean "real" */ - if (memcmp(resstate->data, simstate->data, resstate->size * sizeof(uint32_t))) + if (memcmp(resstate->data, client_state->data, resstate->size * sizeof(uint32_t))) ret = true; - memcpy(resstate->data, simstate->data, resstate->size * sizeof(uint32_t)); + memcpy(resstate->data, client_state->data, resstate->size * sizeof(uint32_t)); - } else { + } + else if (client_count == 0) + { + uint32_t word; + for (word = 0; word < resstate->size; word++) + { + if (resstate->data[word]) + ret = true; + resstate->data[word] = 0; + } + + } + else + { /* Merge them */ static const uint32_t digital[3] = {-1, 0, 0}; oldresstate = netplay_input_state_for(&simframe->resolved_input[device], 1, 3 /* FIXME */, false, false);