Spectator and slave mode are rewind-free

This commit makes spectator mode and slave mode in netplay always stay
ahead of the input, thereby avoiding rewinds, which is sort of the
point. This also changes catch-up detection to be a bit less eager, so
that they hopefully don't flap between stalling for server input and
catching up with that input.
This commit is contained in:
Gregor Richards 2017-02-23 19:05:43 -05:00
parent e495671563
commit 3ff9a43b7d
3 changed files with 47 additions and 9 deletions

View File

@ -247,7 +247,7 @@ bool netplay_send_cur_input(netplay_t *netplay,
{ {
if (!send_input_frame(netplay, connection, NULL, if (!send_input_frame(netplay, connection, NULL,
netplay->self_frame_count, netplay->self_frame_count,
(netplay->is_server ? NETPLAY_CMD_INPUT_BIT_SERVER : 0) | netplay->self_player, (netplay->is_server ? NETPLAY_CMD_INPUT_BIT_SERVER : 0) | netplay->self_player,
dframe->self_state)) dframe->self_state))
return false; return false;
} }

View File

@ -42,6 +42,7 @@
#define MAX_SERVER_STALL_TIME_USEC (5*1000*1000) #define MAX_SERVER_STALL_TIME_USEC (5*1000*1000)
#define MAX_CLIENT_STALL_TIME_USEC (10*1000*1000) #define MAX_CLIENT_STALL_TIME_USEC (10*1000*1000)
#define CATCH_UP_CHECK_TIME_USEC (500*1000)
#define MAX_RETRIES 16 #define MAX_RETRIES 16
#define RETRY_MS 500 #define RETRY_MS 500
@ -479,6 +480,12 @@ struct netplay
/* Opposite of stalling, should we be catching up? */ /* Opposite of stalling, should we be catching up? */
bool catch_up; bool catch_up;
/* When did we start falling behind? */
retro_time_t catch_up_time;
/* How far behind did we fall? */
uint32_t catch_up_behind;
/* Frequency with which to check CRCs */ /* Frequency with which to check CRCs */
int check_frames; int check_frames;

View File

@ -555,7 +555,7 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
if (netplay->catch_up) if (netplay->catch_up)
{ {
/* Are we caught up? */ /* Are we caught up? */
if (netplay->self_frame_count >= lo_frame_count) if (netplay->self_frame_count + 1 >= lo_frame_count)
{ {
netplay->catch_up = false; netplay->catch_up = false;
input_driver_unset_nonblock_state(); input_driver_unset_nonblock_state();
@ -565,17 +565,44 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
} }
else if (!stalled) else if (!stalled)
{ {
if (netplay->self_frame_count + 2 < lo_frame_count) if (netplay->self_frame_count + 3 < lo_frame_count)
{ {
/* Are we falling behind? */ retro_time_t cur_time = cpu_features_get_time_usec();
netplay->catch_up = true; uint32_t cur_behind = lo_frame_count - netplay->self_frame_count;
input_driver_set_nonblock_state();
driver_set_nonblock_state(); /* We're behind, but we'll only try to catch up if we're actually
* falling behind, i.e. if we're more behind after some time */
if (netplay->catch_up_time == 0)
{
/* Record our current time to check for catch-up later */
netplay->catch_up_time = cur_time;
netplay->catch_up_behind = cur_behind;
}
else if (cur_time - netplay->catch_up_time > CATCH_UP_CHECK_TIME_USEC)
{
/* Time to check how far behind we are */
if (netplay->catch_up_behind <= cur_behind)
{
/* We're definitely falling behind! */
netplay->catch_up = true;
netplay->catch_up_time = 0;
input_driver_set_nonblock_state();
driver_set_nonblock_state();
}
else
{
/* Check again in another period */
netplay->catch_up_time = cur_time;
netplay->catch_up_behind = cur_behind;
}
}
} }
else if (netplay->self_frame_count + 2 < hi_frame_count) else if (netplay->self_frame_count + 3 < hi_frame_count)
{ {
size_t i; size_t i;
netplay->catch_up_time = 0;
/* We're falling behind some clients but not others, so request that /* We're falling behind some clients but not others, so request that
* clients ahead of us stall */ * clients ahead of us stall */
@ -589,7 +616,7 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
player = connection->player; player = connection->player;
/* Are they ahead? */ /* Are they ahead? */
if (netplay->self_frame_count + 2 < netplay->read_frame_count[player]) if (netplay->self_frame_count + 3 < netplay->read_frame_count[player])
{ {
/* Tell them to stall */ /* Tell them to stall */
if (connection->stall_frame + NETPLAY_MAX_REQ_STALL_FREQUENCY < if (connection->stall_frame + NETPLAY_MAX_REQ_STALL_FREQUENCY <
@ -603,5 +630,9 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
} }
} }
} }
else
netplay->catch_up_time = 0;
} }
else
netplay->catch_up_time = 0;
} }