Make rewind compatible with netplay.

This commit adds support for temporary desync in netplay. When frontend
features that can't be truly synced, in particular rewind, are used,
netplay is momentarily disabled. As soon as the feature finished, e.g. a
rewind ending, netplay resumes with a state load. For rewind, netplay
peers won't actually experience the effect of rewind, but they will load
the rewound state.
This commit is contained in:
Gregor Richards 2017-04-18 15:25:58 -04:00
parent 7104d329fd
commit fbb508ab5e
6 changed files with 57 additions and 16 deletions

View File

@ -2020,12 +2020,6 @@ bool command_event(enum event_command cmd, void *data)
{
#ifdef HAVE_CHEEVOS
settings_t *settings = config_get_ptr();
#endif
#ifdef HAVE_NETWORKING
if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
return false;
#endif
#ifdef HAVE_CHEEVOS
if (settings->cheevos.hardcore_mode_enable)
return false;
#endif
@ -2041,13 +2035,8 @@ bool command_event(enum event_command cmd, void *data)
return false;
#endif
#ifdef HAVE_NETWORKING
if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
#endif
{
if (settings->rewind_enable)
state_manager_event_init((unsigned)settings->rewind_buffer_size);
}
if (settings->rewind_enable)
state_manager_event_init((unsigned)settings->rewind_buffer_size);
}
break;
case CMD_EVENT_REWIND_TOGGLE:

View File

@ -31,6 +31,10 @@
#include "../verbosity.h"
#include "../audio/audio_driver.h"
#ifdef HAVE_NETWORKING
#include "../network/netplay/netplay.h"
#endif
/* This makes Valgrind throw errors if a core overflows its savestate size. */
/* Keep it off unless you're chasing a core bug, it slows things down. */
#define STRICT_BUF_SIZE 0
@ -687,9 +691,11 @@ bool state_manager_check_rewind(bool pressed,
{
bool ret = false;
static bool first = true;
bool was_reversed = false;
if (state_manager_frame_is_reversed())
{
was_reversed = true;
audio_driver_frame_is_reverse();
state_manager_set_frame_is_reversed(false);
}
@ -711,6 +717,14 @@ bool state_manager_check_rewind(bool pressed,
{
retro_ctx_serialize_info_t serial_info;
#ifdef HAVE_NETWORKING
if (!was_reversed)
{
/* Make sure netplay isn't confused */
netplay_driver_ctl(RARCH_NETPLAY_CTL_DESYNC_PUSH, NULL);
}
#endif
state_manager_set_frame_is_reversed(true);
audio_driver_setup_rewind();
@ -735,6 +749,14 @@ bool state_manager_check_rewind(bool pressed,
serial_info.size = rewind_state.size;
core_unserialize(&serial_info);
#ifdef HAVE_NETWORKING
if (was_reversed)
{
/* Tell netplay we're done */
netplay_driver_ctl(RARCH_NETPLAY_CTL_DESYNC_POP, NULL);
}
#endif
strlcpy(s,
msg_hash_to_str(MSG_REWIND_REACHED_END),
len);
@ -747,6 +769,14 @@ bool state_manager_check_rewind(bool pressed,
{
static unsigned cnt = 0;
#ifdef HAVE_NETWORKING
if (was_reversed)
{
/* Tell netplay we're done */
netplay_driver_ctl(RARCH_NETPLAY_CTL_DESYNC_POP, NULL);
}
#endif
cnt = (cnt + 1) % (rewind_granularity ?
rewind_granularity : 1); /* Avoid possible SIGFPE. */

View File

@ -46,7 +46,9 @@ enum rarch_netplay_ctl_state
RARCH_NETPLAY_CTL_LOAD_SAVESTATE,
RARCH_NETPLAY_CTL_RESET,
RARCH_NETPLAY_CTL_DISCONNECT,
RARCH_NETPLAY_CTL_FINISHED_NAT_TRAVERSAL
RARCH_NETPLAY_CTL_FINISHED_NAT_TRAVERSAL,
RARCH_NETPLAY_CTL_DESYNC_PUSH,
RARCH_NETPLAY_CTL_DESYNC_POP
};
int16_t input_state_net(unsigned port, unsigned device,

View File

@ -996,6 +996,10 @@ void netplay_load_savestate(netplay_t *netplay,
}
}
/* Don't send it if we're expected to be desynced */
if (netplay->desync)
return;
/* If we can't send it to the peer, loading a state was a bad idea */
if (netplay->quirks & (
NETPLAY_QUIRK_NO_SAVESTATES
@ -1319,6 +1323,17 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data)
netplay_announce_nat_traversal(netplay_data);
#endif
goto done;
case RARCH_NETPLAY_CTL_DESYNC_PUSH:
netplay_data->desync++;
break;
case RARCH_NETPLAY_CTL_DESYNC_POP:
if (netplay_data->desync)
{
netplay_data->desync--;
if (!netplay_data->desync)
netplay_load_savestate(netplay_data, NULL, true);
}
break;
default:
case RARCH_NETPLAY_CTL_NONE:
ret = false;

View File

@ -354,6 +354,10 @@ struct netplay
* connected_players) */
uint32_t connected_slaves;
/* Number of desync operations we're currently performing. If set, we don't
* attempt to stay in sync. */
uint32_t desync;
/* Maximum player number */
uint32_t player_max;

View File

@ -389,9 +389,10 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
netplay->self_frame_count++;
}
/* Only relevant if we're connected */
/* Only relevant if we're connected and not in a desynching operation */
if ((netplay->is_server && !netplay->connected_players) ||
(netplay->self_mode < NETPLAY_CONNECTION_CONNECTED))
(netplay->self_mode < NETPLAY_CONNECTION_CONNECTED) ||
(netplay->desync))
{
netplay->other_frame_count = netplay->self_frame_count;
netplay->other_ptr = netplay->self_ptr;