diff --git a/content.h b/content.h index f596ad8fe0..70da680aa8 100644 --- a/content.h +++ b/content.h @@ -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); diff --git a/input/input_driver.c b/input/input_driver.c index 716a0593a4..b207a1b631 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -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) { diff --git a/state_manager.c b/state_manager.c index 330cc326c2..238517cb43 100644 --- a/state_manager.c +++ b/state_manager.c @@ -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); } diff --git a/tasks/task_save.c b/tasks/task_save.c index 5b47f589c0..b082ef718c 100644 --- a/tasks/task_save.c +++ b/tasks/task_save.c @@ -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