diff --git a/command.c b/command.c index 4d0b1044e8..17ebcc58d9 100644 --- a/command.c +++ b/command.c @@ -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: diff --git a/managers/state_manager.c b/managers/state_manager.c index 39a55c236f..8ab2563ae0 100644 --- a/managers/state_manager.c +++ b/managers/state_manager.c @@ -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. */ diff --git a/network/netplay/netplay.h b/network/netplay/netplay.h index 8a22bc12dd..38b04326ab 100644 --- a/network/netplay/netplay.h +++ b/network/netplay/netplay.h @@ -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, diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 1327354d13..0f0e941026 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -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; diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index fc4a7bd751..272c96cfae 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -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; diff --git a/network/netplay/netplay_sync.c b/network/netplay/netplay_sync.c index cf624c81de..bcaedb364e 100644 --- a/network/netplay/netplay_sync.c +++ b/network/netplay/netplay_sync.c @@ -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;