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. */ /* Gets the number of bytes required to serialize the state. */
size_t content_get_serialized_size(void); size_t content_get_serialized_size(void);
/* Serializes the current state. buffer must be at least content_get_serialized_size bytes */ /* Gets the number of bytes required to serialize the state for rewind. */
bool content_serialize_state(void* buffer, size_t buffer_size); 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. */ /* Deserializes the current state. */
bool content_deserialize_state(const void* serialized_data, size_t serialized_size); 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; bsv_movie_t *handle = input_st->bsv_movie_state_handle;
if (!handle) if (!handle)
return; 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) if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_RECORDING)
{ {
int i; 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) 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; const uint8_t *oldb, *newb;
uint8_t *compressed; uint8_t *compressed;
size_t headpos, tailpos, remaining; 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; return;
}
recheckcapacity:; recheckcapacity:;
headpos = state->head - state->data; headpos = state->head - state->data;
@ -617,7 +619,7 @@ void state_manager_event_init(
return; return;
} }
rewind_st->size = content_get_serialized_size(); rewind_st->size = content_get_serialized_size_rewind();
if (!rewind_st->size) if (!rewind_st->size)
{ {
@ -638,7 +640,7 @@ void state_manager_event_init(
state_manager_push_where(rewind_st->state, &state); 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); 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))) && ((cnt == 0) || retroarch_ctl(RARCH_CTL_BSV_MOVIE_IS_INITED, NULL)))
{ {
void *state = NULL; void *state = NULL;
state_manager_push_where(rewind_st->state, &state); 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); 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 */ /* Align to 8-byte boundary */
#define CONTENT_ALIGN_SIZE(size) ((((size) + 7) & ~7)) #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; retro_ctx_size_info_t info;
core_serialize_size(&info); core_serialize_size(&info);
@ -632,12 +632,18 @@ static size_t content_get_rastate_size(rastate_size_info_t* size)
#ifdef HAVE_CHEEVOS #ifdef HAVE_CHEEVOS
/* 8-byte block header + content */ /* 8-byte block header + content */
if ((size->cheevos_size = rcheevos_get_serialize_size()) > 0) 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 #endif
#ifdef HAVE_BSV_MOVIE #ifdef HAVE_BSV_MOVIE
/* 8-byte block header + content */ /* 8-byte block header + content */
if ((size->replay_size = replay_get_serialize_size()) > 0) if(!rewind)
size->total_size += 8 + CONTENT_ALIGN_SIZE(size->replay_size); {
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 #endif
return size->total_size; 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) size_t content_get_serialized_size(void)
{ {
rastate_size_info_t size; 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) 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, 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; retro_ctx_serialize_info_t serial_info;
unsigned char* output = (unsigned char*)buffer; unsigned char* output = (unsigned char*)buffer;
@ -673,7 +685,7 @@ static bool content_write_serialized_state(void* buffer,
#ifdef HAVE_BSV_MOVIE #ifdef HAVE_BSV_MOVIE
{ {
input_driver_state_t *input_st = input_state_get_ptr(); 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, content_write_block_header(output,
RASTATE_REPLAY_BLOCK, size->replay_size); RASTATE_REPLAY_BLOCK, size->replay_size);
@ -710,13 +722,13 @@ static bool content_write_serialized_state(void* buffer,
return true; 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; 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) if (len == 0 || len > buffer_size)
return false; 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) 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; size_t len;
void* data; void* data;
rastate_size_info_t size; rastate_size_info_t size;
if ((len = content_get_rastate_size(&size)) == 0) if ((len = content_get_rastate_size(&size, false)) == 0)
return NULL; return NULL;
/* Ensure buffer is initialised to zero /* 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))) if (!(data = calloc(len, 1)))
return NULL; return NULL;
if (!content_write_serialized_state(data, &size)) if (!content_write_serialized_state(data, &size, false))
{ {
free(data); free(data);
return NULL; return NULL;
@ -1116,13 +1128,13 @@ static bool content_load_rastate1(unsigned char* input, size_t size)
#ifdef HAVE_BSV_MOVIE #ifdef HAVE_BSV_MOVIE
{ {
input_driver_state_t *input_st = input_state_get_ptr(); 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 */ /* TODO OSD message */
RARCH_ERR("[Replay] Can't load state without replay data during recording.\n"); RARCH_ERR("[Replay] Can't load state without replay data during recording.\n");
return false; 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 */ /* TODO OSD message */
RARCH_WARN("[Replay] Loading state without replay data during replay will cancel replay.\n"); 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 #ifdef HAVE_BSV_MOVIE
else if (memcmp(marker, RASTATE_REPLAY_BLOCK, 4) == 0) 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; seen_replay = true;
else else
return false; return false;
@ -1167,7 +1180,7 @@ static bool content_load_rastate1(unsigned char* input, size_t size)
rcheevos_set_serialized_data(NULL); rcheevos_set_serialized_data(NULL);
#endif #endif
#ifdef HAVE_BSV_MOVIE #ifdef HAVE_BSV_MOVIE
if (!seen_replay) if (!seen_replay && !state_manager_frame_is_reversed())
replay_set_serialized_data(NULL); replay_set_serialized_data(NULL);
#endif #endif
@ -1190,7 +1203,8 @@ bool content_deserialize_state(
rcheevos_set_serialized_data(NULL); rcheevos_set_serialized_data(NULL);
#endif #endif
#ifdef HAVE_BSV_MOVIE #ifdef HAVE_BSV_MOVIE
replay_set_serialized_data(NULL); if(!state_manager_frame_is_reversed())
replay_set_serialized_data(NULL);
#endif #endif
} }
else else