Replay rewind fix (#15079)

* Rewind during recording isn't visibly busted anymore but it doesn't rewind the replay properly during playback or record, inputs get clobbered; check frame pos/ptr stuff.

* Fix rewinding during movie recording and playback?
This commit is contained in:
Joe Osborn 2023-03-11 09:37:48 -08:00 committed by GitHub
parent 666fbdcb38
commit be5b198692
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 25 deletions

View file

@ -66,8 +66,11 @@ bool content_ram_state_pending(void);
/* Gets the number of bytes required to serialize the state. */
size_t content_get_serialized_size(void);
/* Serializes the current state. buffer must be at least content_get_serialized_size bytes */
bool content_serialize_state(void* buffer, size_t buffer_size);
/* Gets the number of bytes required to serialize the state for rewind. */
size_t content_get_serialized_size_rewind(void);
/* Serializes the current state for rewinding. buffer must be at least content_get_serialized_size bytes */
bool content_serialize_state_rewind(void* buffer, size_t buffer_size);
/* Deserializes the current state. */
bool content_deserialize_state(const void* serialized_data, size_t serialized_size);

View file

@ -4789,7 +4789,8 @@ void bsv_movie_next_frame(input_driver_state_t *input_st)
bsv_movie_t *handle = input_st->bsv_movie_state_handle;
if (!handle)
return;
handle->frame_pos[handle->frame_ptr] = intfstream_tell(handle->file);
if (state_manager_frame_is_reversed())
return;
if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_RECORDING)
{
int i;
@ -4901,6 +4902,7 @@ void bsv_movie_next_frame(input_driver_state_t *input_st)
}
}
}
handle->frame_pos[handle->frame_ptr] = intfstream_tell(handle->file);
}
size_t replay_get_serialize_size(void)
{

View file

@ -515,8 +515,10 @@ static void state_manager_push_do(state_manager_t *state)
const uint8_t *oldb, *newb;
uint8_t *compressed;
size_t headpos, tailpos, remaining;
if (state->capacity < sizeof(size_t) + state->maxcompsize)
if (state->capacity < sizeof(size_t) + state->maxcompsize) {
RARCH_ERR("State capacity insufficient\n");
return;
}
recheckcapacity:;
headpos = state->head - state->data;
@ -617,7 +619,7 @@ void state_manager_event_init(
return;
}
rewind_st->size = content_get_serialized_size();
rewind_st->size = content_get_serialized_size_rewind();
if (!rewind_st->size)
{
@ -638,7 +640,7 @@ void state_manager_event_init(
state_manager_push_where(rewind_st->state, &state);
content_serialize_state(state, rewind_st->size);
content_serialize_state_rewind(state, rewind_st->size);
state_manager_push_do(rewind_st->state);
}
@ -800,10 +802,9 @@ bool state_manager_check_rewind(
&& ((cnt == 0) || retroarch_ctl(RARCH_CTL_BSV_MOVIE_IS_INITED, NULL)))
{
void *state = NULL;
state_manager_push_where(rewind_st->state, &state);
content_serialize_state(state, rewind_st->size);
content_serialize_state_rewind(state, rewind_st->size);
state_manager_push_do(rewind_st->state);
}

View file

@ -620,7 +620,7 @@ static void task_save_handler_finished(retro_task_t *task,
/* Align to 8-byte boundary */
#define CONTENT_ALIGN_SIZE(size) ((((size) + 7) & ~7))
static size_t content_get_rastate_size(rastate_size_info_t* size)
static size_t content_get_rastate_size(rastate_size_info_t* size, bool rewind)
{
retro_ctx_size_info_t info;
core_serialize_size(&info);
@ -632,12 +632,18 @@ static size_t content_get_rastate_size(rastate_size_info_t* size)
#ifdef HAVE_CHEEVOS
/* 8-byte block header + content */
if ((size->cheevos_size = rcheevos_get_serialize_size()) > 0)
size->total_size += 8 + CONTENT_ALIGN_SIZE(size->cheevos_size);
size->total_size += 8 + CONTENT_ALIGN_SIZE(size->cheevos_size);
#endif
#ifdef HAVE_BSV_MOVIE
/* 8-byte block header + content */
if ((size->replay_size = replay_get_serialize_size()) > 0)
size->total_size += 8 + CONTENT_ALIGN_SIZE(size->replay_size);
if(!rewind)
{
size->replay_size = replay_get_serialize_size();
if(size->replay_size > 0)
size->total_size += 8 + CONTENT_ALIGN_SIZE(size->replay_size);
}
else
size->replay_size = 0;
#endif
return size->total_size;
}
@ -645,7 +651,12 @@ static size_t content_get_rastate_size(rastate_size_info_t* size)
size_t content_get_serialized_size(void)
{
rastate_size_info_t size;
return content_get_rastate_size(&size);
return content_get_rastate_size(&size, false);
}
size_t content_get_serialized_size_rewind(void)
{
rastate_size_info_t size;
return content_get_rastate_size(&size, true);
}
static void content_write_block_header(unsigned char* output, const char* header, size_t size)
@ -658,7 +669,8 @@ static void content_write_block_header(unsigned char* output, const char* header
}
static bool content_write_serialized_state(void* buffer,
rastate_size_info_t* size)
rastate_size_info_t* size,
bool rewind)
{
retro_ctx_serialize_info_t serial_info;
unsigned char* output = (unsigned char*)buffer;
@ -673,7 +685,7 @@ static bool content_write_serialized_state(void* buffer,
#ifdef HAVE_BSV_MOVIE
{
input_driver_state_t *input_st = input_state_get_ptr();
if (input_st->bsv_movie_state.flags & (BSV_FLAG_MOVIE_RECORDING | BSV_FLAG_MOVIE_PLAYBACK))
if (!rewind && input_st->bsv_movie_state.flags & (BSV_FLAG_MOVIE_RECORDING | BSV_FLAG_MOVIE_PLAYBACK) && !state_manager_frame_is_reversed())
{
content_write_block_header(output,
RASTATE_REPLAY_BLOCK, size->replay_size);
@ -710,13 +722,13 @@ static bool content_write_serialized_state(void* buffer,
return true;
}
bool content_serialize_state(void* buffer, size_t buffer_size)
bool content_serialize_state_rewind(void* buffer, size_t buffer_size)
{
rastate_size_info_t size;
size_t len = content_get_rastate_size(&size);
size_t len = content_get_rastate_size(&size, true);
if (len == 0 || len > buffer_size)
return false;
return content_write_serialized_state(buffer, &size);
return content_write_serialized_state(buffer, &size, true);
}
static void *content_get_serialized_data(size_t* serial_size)
@ -724,7 +736,7 @@ static void *content_get_serialized_data(size_t* serial_size)
size_t len;
void* data;
rastate_size_info_t size;
if ((len = content_get_rastate_size(&size)) == 0)
if ((len = content_get_rastate_size(&size, false)) == 0)
return NULL;
/* Ensure buffer is initialised to zero
@ -735,7 +747,7 @@ static void *content_get_serialized_data(size_t* serial_size)
if (!(data = calloc(len, 1)))
return NULL;
if (!content_write_serialized_state(data, &size))
if (!content_write_serialized_state(data, &size, false))
{
free(data);
return NULL;
@ -1116,13 +1128,13 @@ static bool content_load_rastate1(unsigned char* input, size_t size)
#ifdef HAVE_BSV_MOVIE
{
input_driver_state_t *input_st = input_state_get_ptr();
if (BSV_MOVIE_IS_RECORDING() && !seen_replay)
if (BSV_MOVIE_IS_RECORDING() && !seen_replay && !state_manager_frame_is_reversed())
{
/* TODO OSD message */
RARCH_ERR("[Replay] Can't load state without replay data during recording.\n");
return false;
}
if (BSV_MOVIE_IS_PLAYBACK_ON() && !seen_replay)
if (BSV_MOVIE_IS_PLAYBACK_ON() && !seen_replay && !state_manager_frame_is_reversed())
{
/* TODO OSD message */
RARCH_WARN("[Replay] Loading state without replay data during replay will cancel replay.\n");
@ -1145,7 +1157,8 @@ static bool content_load_rastate1(unsigned char* input, size_t size)
#ifdef HAVE_BSV_MOVIE
else if (memcmp(marker, RASTATE_REPLAY_BLOCK, 4) == 0)
{
if (replay_set_serialized_data((void*)input))
input_driver_state_t *input_st = input_state_get_ptr();
if (state_manager_frame_is_reversed() || replay_set_serialized_data((void*)input))
seen_replay = true;
else
return false;
@ -1167,7 +1180,7 @@ static bool content_load_rastate1(unsigned char* input, size_t size)
rcheevos_set_serialized_data(NULL);
#endif
#ifdef HAVE_BSV_MOVIE
if (!seen_replay)
if (!seen_replay && !state_manager_frame_is_reversed())
replay_set_serialized_data(NULL);
#endif
@ -1190,7 +1203,8 @@ bool content_deserialize_state(
rcheevos_set_serialized_data(NULL);
#endif
#ifdef HAVE_BSV_MOVIE
replay_set_serialized_data(NULL);
if(!state_manager_frame_is_reversed())
replay_set_serialized_data(NULL);
#endif
}
else