Skip to content

Commit fa42321

Browse files
authored
Seek backwards/forwards in replays by checkpoint (#18238)
* Add save checkpoint, prev/next checkpoint commands and hotkeys * Fix copy paste error in meta binds * Implement save_replay_checkpoint command * Implement prev/next checkpoint commands * Update per @Jamiras review * add command to seek to a specific frame number * Add message queue toasts for seek forward/back * Fix basis for seek, produce full message on reply * fix bugs seeking back during record * Tidy up * Allow back and forwards seeking of recording replays while paused * Update changelog
1 parent 3d7d6c9 commit fa42321

17 files changed

Lines changed: 693 additions & 172 deletions

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
- INPUT/BSV/REPLAY: Add checkpoint and initial savestate compression, following the `savestate_file_compression` config boolean. Use zstd if available, or fall back to zlib.
3737
- INPUT/BSV/REPLAY: Add incremental checkpoints based on statestreams (depending on `HAVE_STATESTREAM` compile time flag). As an example, 60 `pcsx_rearmed` savestates would take 267MB uncompressed; with incremental encoding this is reduced to 77MB. Compressing the result can reduce the size to just 4MB.
3838
- INPUT/BSV/REPLAY: Checkpoint compression and encoding can be combined. For example, 60 `pcsx_rearmed` checkpoints can take up just 15MB if each state is incremental and compressed. This is not as optimal as using incremental states without save state compression followed by offline compression, but is a good compromise in many use cases.
39+
- INPUT/BSV/REPLAY: Add hotkeys and text commands to force a checkpoint insertion into the currently recording replay, and to seek backwards to the previous checkpoint and forwards to the next checkpoint.
40+
- INPUT/BSV/REPLAY: Add a text command to seek to a specific frame of the currently playing/recording replay; it will return via the command replier the actual seeked-to frame (right now it only supports seeking to checkpoints).
3941
- INTL: Add Irish Gaelic to selectable languages
4042
- IOS: Fix crash on iOS9 when fetching refresh rate
4143
- LINUX: Add full complement of key/value pairs to desktop entry

Makefile.common

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ ifeq ($(HAVE_SAPI), 1)
2525
LIBS += sapi.dll
2626
endif
2727

28-
ifeq ($(HAVE_STATESTREAM), 1)
29-
DEF_FLAGS += -DHAVE_STATESTREAM
30-
endif
31-
3228
ifeq ($(HAVE_GL_CONTEXT),)
3329
HAVE_GL_CONTEXT = 0
3430
HAVE_GL_MODERN = 0
@@ -455,8 +451,12 @@ endif
455451

456452
ifeq ($(HAVE_BSV_MOVIE), 1)
457453
DEFINES += -DHAVE_BSV_MOVIE
458-
OBJ += input/bsv/bsvmovie.o \
459-
input/bsv/uint32s_index.o
454+
OBJ += input/bsv/bsvmovie.o
455+
endif
456+
457+
ifeq ($(HAVE_STATESTREAM), 1)
458+
DEFINES += -DHAVE_STATESTREAM
459+
OBJ += input/bsv/uint32s_index.o
460460
endif
461461

462462
ifeq ($(HAVE_RUNAHEAD), 1)

command.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* If not, see <http://www.gnu.org/licenses/>.
1616
*/
1717

18+
#include "input/input_driver.h"
1819
#include <stdio.h>
1920
#include <stdlib.h>
2021
#include <stddef.h>
@@ -802,6 +803,42 @@ bool command_play_replay_slot(command_t *cmd, const char *arg)
802803
#endif
803804
}
804805

806+
bool command_seek_replay(command_t *cmd, const char *arg)
807+
{
808+
#ifdef HAVE_BSV_MOVIE
809+
char reply[32];
810+
bool ret = true;
811+
char *endptr;
812+
size_t _len;
813+
int64_t frame = strtoll(arg, &endptr, 10), target_frame;
814+
input_driver_state_t *input_st = input_state_get_ptr();
815+
if (!endptr)
816+
ret = false;
817+
if (!(input_st->bsv_movie_state.flags & (BSV_FLAG_MOVIE_PLAYBACK | BSV_FLAG_MOVIE_RECORDING)))
818+
ret = false;
819+
#ifdef HAVE_CHEEVOS
820+
ret = !rcheevos_hardcore_active();
821+
#endif
822+
if (ret)
823+
ret = movie_seek_to_frame(input_st, frame);
824+
if (ret)
825+
{
826+
_len = strlcpy(reply, "OK ", sizeof(reply));
827+
_len += snprintf(reply+_len, sizeof(reply)-_len,
828+
"%ld", input_st->bsv_movie_state.seek_target_frame);
829+
}
830+
else
831+
_len = strlcpy(reply, "NO", sizeof(reply));
832+
reply[_len] = '\n';
833+
reply[++_len] = '\0';
834+
cmd->replier(cmd, reply, _len);
835+
return ret;
836+
#else
837+
cmd->replier(cmd, "NO\n", 4);
838+
return false;
839+
#endif
840+
}
841+
805842
bool command_save_savefiles(command_t *cmd, const char* arg)
806843
{
807844
char reply[4];

command.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ enum event_command
6969
CMD_EVENT_PLAY_REPLAY,
7070
CMD_EVENT_RECORD_REPLAY,
7171
CMD_EVENT_HALT_REPLAY,
72+
CMD_EVENT_SAVE_REPLAY_CHECKPOINT,
73+
CMD_EVENT_PREV_REPLAY_CHECKPOINT,
74+
CMD_EVENT_NEXT_REPLAY_CHECKPOINT,
7275
CMD_EVENT_REPLAY_DECREMENT,
7376
CMD_EVENT_REPLAY_INCREMENT,
7477
/* Save state actions. */
@@ -421,6 +424,7 @@ bool command_get_config_param(command_t *cmd, const char* arg);
421424
bool command_show_osd_msg(command_t *cmd, const char* arg);
422425
bool command_load_state_slot(command_t *cmd, const char* arg);
423426
bool command_play_replay_slot(command_t *cmd, const char* arg);
427+
bool command_seek_replay(command_t *cmd, const char *arg);
424428
bool command_save_savefiles(command_t *cmd, const char* arg);
425429
bool command_load_savefiles(command_t *cmd, const char* arg);
426430
#ifdef HAVE_CHEEVOS
@@ -449,6 +453,7 @@ static const struct cmd_action_map action_map[] = {
449453

450454
{ "LOAD_STATE_SLOT",command_load_state_slot, "<slot number>"},
451455
{ "PLAY_REPLAY_SLOT",command_play_replay_slot, "<slot number>"},
456+
{ "SEEK_REPLAY",command_seek_replay, "<frame number>"},
452457

453458
{ "SAVE_FILES", command_save_savefiles, "No argument"},
454459
{ "LOAD_FILES", command_load_savefiles, "No argument"},
@@ -480,6 +485,9 @@ static const struct cmd_map map[] = {
480485
{ "PLAY_REPLAY", RARCH_PLAY_REPLAY_KEY },
481486
{ "RECORD_REPLAY", RARCH_RECORD_REPLAY_KEY },
482487
{ "HALT_REPLAY", RARCH_HALT_REPLAY_KEY },
488+
{ "SAVE_REPLAY_CHECKPOINT", RARCH_SAVE_REPLAY_CHECKPOINT_KEY },
489+
{ "PREV_REPLAY_CHECKPOINT", RARCH_PREV_REPLAY_CHECKPOINT_KEY },
490+
{ "NEXT_REPLAY_CHECKPOINT", RARCH_NEXT_REPLAY_CHECKPOINT_KEY },
483491
{ "REPLAY_SLOT_PLUS", RARCH_REPLAY_SLOT_PLUS },
484492
{ "REPLAY_SLOT_MINUS", RARCH_REPLAY_SLOT_MINUS },
485493

config.def.keybinds.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,27 @@ static const struct retro_keybind retro_keybinds_1[] = {
430430
RARCH_HALT_REPLAY_KEY, NO_BTN, NO_BTN, 0,
431431
true
432432
},
433+
{
434+
NULL, NULL,
435+
AXIS_NONE, AXIS_NONE,
436+
MENU_ENUM_LABEL_VALUE_INPUT_META_SAVE_REPLAY_CHECKPOINT_KEY, RETROK_UNKNOWN,
437+
RARCH_SAVE_REPLAY_CHECKPOINT_KEY, NO_BTN, NO_BTN, 0,
438+
true
439+
},
440+
{
441+
NULL, NULL,
442+
AXIS_NONE, AXIS_NONE,
443+
MENU_ENUM_LABEL_VALUE_INPUT_META_PREV_REPLAY_CHECKPOINT_KEY, RETROK_UNKNOWN,
444+
RARCH_PREV_REPLAY_CHECKPOINT_KEY, NO_BTN, NO_BTN, 0,
445+
true
446+
},
447+
{
448+
NULL, NULL,
449+
AXIS_NONE, AXIS_NONE,
450+
MENU_ENUM_LABEL_VALUE_INPUT_META_NEXT_REPLAY_CHECKPOINT_KEY, RETROK_UNKNOWN,
451+
RARCH_NEXT_REPLAY_CHECKPOINT_KEY, NO_BTN, NO_BTN, 0,
452+
true
453+
},
433454
{
434455
NULL, NULL,
435456
AXIS_NONE, AXIS_NONE,

configuration.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,9 @@ const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = {
366366
DECLARE_META_BIND(1, play_replay, RARCH_PLAY_REPLAY_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_PLAY_REPLAY_KEY),
367367
DECLARE_META_BIND(1, record_replay, RARCH_RECORD_REPLAY_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_RECORD_REPLAY_KEY),
368368
DECLARE_META_BIND(1, halt_replay, RARCH_HALT_REPLAY_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_HALT_REPLAY_KEY),
369+
DECLARE_META_BIND(1, save_replay_checkpoint,RARCH_SAVE_REPLAY_CHECKPOINT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SAVE_REPLAY_CHECKPOINT_KEY),
370+
DECLARE_META_BIND(1, prev_replay_checkpoint,RARCH_PREV_REPLAY_CHECKPOINT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_PREV_REPLAY_CHECKPOINT_KEY),
371+
DECLARE_META_BIND(1, next_replay_checkpoint,RARCH_NEXT_REPLAY_CHECKPOINT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_NEXT_REPLAY_CHECKPOINT_KEY),
369372
DECLARE_META_BIND(2, replay_slot_increase, RARCH_REPLAY_SLOT_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_META_REPLAY_SLOT_PLUS),
370373
DECLARE_META_BIND(2, replay_slot_decrease, RARCH_REPLAY_SLOT_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_META_REPLAY_SLOT_MINUS),
371374

0 commit comments

Comments
 (0)