mirror of
https://github.com/libretro/RetroArch
synced 2025-03-25 16:44:01 +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
|
#ifdef HAVE_CHEEVOS
|
||||||
settings_t *settings = config_get_ptr();
|
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)
|
if (settings->cheevos.hardcore_mode_enable)
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
@ -2041,13 +2035,8 @@ bool command_event(enum event_command cmd, void *data)
|
|||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_NETWORKING
|
if (settings->rewind_enable)
|
||||||
if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
|
state_manager_event_init((unsigned)settings->rewind_buffer_size);
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (settings->rewind_enable)
|
|
||||||
state_manager_event_init((unsigned)settings->rewind_buffer_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CMD_EVENT_REWIND_TOGGLE:
|
case CMD_EVENT_REWIND_TOGGLE:
|
||||||
|
@ -31,6 +31,10 @@
|
|||||||
#include "../verbosity.h"
|
#include "../verbosity.h"
|
||||||
#include "../audio/audio_driver.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. */
|
/* 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. */
|
/* Keep it off unless you're chasing a core bug, it slows things down. */
|
||||||
#define STRICT_BUF_SIZE 0
|
#define STRICT_BUF_SIZE 0
|
||||||
@ -687,9 +691,11 @@ bool state_manager_check_rewind(bool pressed,
|
|||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
static bool first = true;
|
static bool first = true;
|
||||||
|
bool was_reversed = false;
|
||||||
|
|
||||||
if (state_manager_frame_is_reversed())
|
if (state_manager_frame_is_reversed())
|
||||||
{
|
{
|
||||||
|
was_reversed = true;
|
||||||
audio_driver_frame_is_reverse();
|
audio_driver_frame_is_reverse();
|
||||||
state_manager_set_frame_is_reversed(false);
|
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;
|
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);
|
state_manager_set_frame_is_reversed(true);
|
||||||
|
|
||||||
audio_driver_setup_rewind();
|
audio_driver_setup_rewind();
|
||||||
@ -735,6 +749,14 @@ bool state_manager_check_rewind(bool pressed,
|
|||||||
serial_info.size = rewind_state.size;
|
serial_info.size = rewind_state.size;
|
||||||
core_unserialize(&serial_info);
|
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,
|
strlcpy(s,
|
||||||
msg_hash_to_str(MSG_REWIND_REACHED_END),
|
msg_hash_to_str(MSG_REWIND_REACHED_END),
|
||||||
len);
|
len);
|
||||||
@ -747,6 +769,14 @@ bool state_manager_check_rewind(bool pressed,
|
|||||||
{
|
{
|
||||||
static unsigned cnt = 0;
|
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 ?
|
cnt = (cnt + 1) % (rewind_granularity ?
|
||||||
rewind_granularity : 1); /* Avoid possible SIGFPE. */
|
rewind_granularity : 1); /* Avoid possible SIGFPE. */
|
||||||
|
|
||||||
|
@ -46,7 +46,9 @@ enum rarch_netplay_ctl_state
|
|||||||
RARCH_NETPLAY_CTL_LOAD_SAVESTATE,
|
RARCH_NETPLAY_CTL_LOAD_SAVESTATE,
|
||||||
RARCH_NETPLAY_CTL_RESET,
|
RARCH_NETPLAY_CTL_RESET,
|
||||||
RARCH_NETPLAY_CTL_DISCONNECT,
|
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,
|
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 we can't send it to the peer, loading a state was a bad idea */
|
||||||
if (netplay->quirks & (
|
if (netplay->quirks & (
|
||||||
NETPLAY_QUIRK_NO_SAVESTATES
|
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);
|
netplay_announce_nat_traversal(netplay_data);
|
||||||
#endif
|
#endif
|
||||||
goto done;
|
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:
|
default:
|
||||||
case RARCH_NETPLAY_CTL_NONE:
|
case RARCH_NETPLAY_CTL_NONE:
|
||||||
ret = false;
|
ret = false;
|
||||||
|
@ -354,6 +354,10 @@ struct netplay
|
|||||||
* connected_players) */
|
* connected_players) */
|
||||||
uint32_t connected_slaves;
|
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 */
|
/* Maximum player number */
|
||||||
uint32_t player_max;
|
uint32_t player_max;
|
||||||
|
|
||||||
|
@ -389,9 +389,10 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
|
|||||||
netplay->self_frame_count++;
|
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) ||
|
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_frame_count = netplay->self_frame_count;
|
||||||
netplay->other_ptr = netplay->self_ptr;
|
netplay->other_ptr = netplay->self_ptr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user