mirror of
https://github.com/libretro/RetroArch
synced 2025-03-21 13:20:52 +00:00
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:
parent
7104d329fd
commit
fbb508ab5e
15
command.c
15
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:
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user