diff --git a/network/netplay/netplay.c b/network/netplay/netplay.c index 85abe08dfa..06adae17cf 100644 --- a/network/netplay/netplay.c +++ b/network/netplay/netplay.c @@ -717,7 +717,8 @@ static bool netplay_get_cmd(netplay_t *netplay, case NETPLAY_CMD_REQUEST_SAVESTATE: /* Delay until next frame so we don't send the savestate after the * input */ - netplay->force_send_savestate = true; + connection->force_send_savestate = true; + netplay->force_send_savestate_one = true; break; case NETPLAY_CMD_LOAD_SAVESTATE: diff --git a/network/netplay/netplay_common.c b/network/netplay/netplay_common.c index 786d9db047..2d79c8d71d 100644 --- a/network/netplay/netplay_common.c +++ b/network/netplay/netplay_common.c @@ -267,7 +267,8 @@ static void netplay_handshake_ready(netplay_t *netplay, struct netplay_connectio /* Send them the savestate */ if (!(netplay->quirks & (NETPLAY_QUIRK_NO_SAVESTATES|NETPLAY_QUIRK_NO_TRANSMISSION))) { - netplay->force_send_savestate = true; + connection->force_send_savestate = true; + netplay->force_send_savestate_one = true; } } else diff --git a/network/netplay/netplay_net.c b/network/netplay/netplay_net.c index 0c9d858950..157eda9924 100644 --- a/network/netplay/netplay_net.c +++ b/network/netplay/netplay_net.c @@ -88,12 +88,14 @@ static bool netplay_net_pre_frame(netplay_t *netplay) } else if (!(netplay->quirks & NETPLAY_QUIRK_NO_SAVESTATES) && core_serialize(&serial_info)) { - if (netplay->force_send_savestate && !netplay->stall) + if ((netplay->force_send_savestate_all || netplay->force_send_savestate_one) && !netplay->stall) { /* Send this along to the other side */ serial_info.data_const = netplay->buffer[netplay->self_ptr].state; netplay_load_savestate(netplay, &serial_info, false); - netplay->force_send_savestate = false; + netplay->force_send_savestate_all = + netplay->force_send_savestate_one = false; + /* FIXME: Shouldn't send to everyone! */ } } else diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index 43b2818085..cd156e0fbe 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -246,6 +246,9 @@ struct netplay_connection /* Player # of connected player, or -1 if not a player */ int player; + + /* Force send a savestate, to this connection only */ + bool force_send_savestate; }; struct netplay @@ -299,16 +302,25 @@ struct netplay /* The size of our packet buffers */ size_t packet_buffer_size; - /* Pointer where we are now. */ + /* The current frame seen by the frontend */ size_t self_ptr; - /* Points to the last reliable state that self ever had. */ + uint32_t self_frame_count; + + /* The first frame at which some data might be unreliable */ size_t other_ptr; + uint32_t other_frame_count; + /* Pointer to where we are reading. - * Generally, other_ptr <= read_ptr <= self_ptr. */ + * Generally, other_ptr <= read_ptr <= self_ptr, but read_ptr can get ahead + * of self_ptr if the peer is running fast. */ size_t read_ptr; + uint32_t read_frame_count; + /* A pointer used temporarily for replay. */ size_t replay_ptr; + uint32_t replay_frame_count; + /* Size of savestates */ size_t state_size; /* Are we replaying old frames? */ @@ -324,9 +336,13 @@ struct netplay /* Quirks in the savestate implementation */ uint64_t quirks; - /* Force our state to be sent to the other side. Used when they request a - * savestate, to send at the next pre-frame. */ - bool force_send_savestate; + /* Force our state to be sent to all connections. Used when we explicitly + * load a state. */ + bool force_send_savestate_all; + + /* Set if there is at least one client which must be sent the state, usually + * because they've requested it or just connected. */ + bool force_send_savestate_one; /* Have we requested a savestate as a sync point? */ bool savestate_request_outstanding; @@ -334,12 +350,6 @@ struct netplay /* A buffer for outgoing input packets. */ uint32_t input_packet_buffer[2 + WORDS_PER_FRAME]; - /* All of our frame counts */ - uint32_t self_frame_count; - uint32_t read_frame_count; - uint32_t other_frame_count; - uint32_t replay_frame_count; - /* And socket info */ struct addrinfo *addr; struct sockaddr_storage their_addr;