diff --git a/core_impl.c b/core_impl.c index e0fc8633c8..eb4b2fffd0 100644 --- a/core_impl.c +++ b/core_impl.c @@ -43,6 +43,7 @@ #include "verbosity.h" #include "gfx/video_driver.h" #include "audio/audio_driver.h" +#include "tasks/tasks_internal.h" #ifdef HAVE_RUNAHEAD #include "runahead/copy_load_info.h" @@ -298,6 +299,7 @@ bool core_load_game(retro_ctx_load_content_info_t *load_info) #endif content_get_status(&contentless, &is_inited); + set_save_state_in_background(false); if (load_info && load_info->special) current_core.game_loaded = current_core.retro_load_game_special( diff --git a/dynamic.c b/dynamic.c index 4a91c2693b..6b35a0117d 100644 --- a/dynamic.c +++ b/dynamic.c @@ -1387,6 +1387,16 @@ bool rarch_environment_cb(unsigned cmd, void *data) break; } + case RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND: + { + bool state = *(const bool*)data; + RARCH_LOG("Environ SET_SAVE_STATE_IN_BACKGROUND: %s.\n", state ? "yes" : "no"); + + set_save_state_in_background(state) ; + + break; + } + case RETRO_ENVIRONMENT_GET_LIBRETRO_PATH: { const char **path = (const char**)data; diff --git a/retroarch.h b/retroarch.h index 46d882deed..dda1628c29 100644 --- a/retroarch.h +++ b/retroarch.h @@ -33,6 +33,8 @@ RETRO_BEGIN_DECLS +#define RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND RETRO_ENVIRONMENT_PRIVATE+1 + enum rarch_ctl_state { RARCH_CTL_NONE = 0, diff --git a/tasks/task_save.c b/tasks/task_save.c index 1b5d93be4e..650f88f2ce 100644 --- a/tasks/task_save.c +++ b/tasks/task_save.c @@ -56,6 +56,7 @@ #define SAVE_STATE_CHUNK 4096 +static bool save_state_in_background = false; static struct string_list *task_save_files = NULL; struct ram_type @@ -555,6 +556,33 @@ static void task_save_handler_finished(retro_task_t *task, free(state); } +void* get_serialized_data(const char *path, size_t serial_size) +{ + retro_ctx_serialize_info_t serial_info; + bool ret = false; + void *data = NULL; + + data = malloc(serial_size); + + if (!data) + return NULL; + + RARCH_LOG("%s: %d %s.\n", + msg_hash_to_str(MSG_STATE_SIZE), + (int)serial_size, + msg_hash_to_str(MSG_BYTES)); + + serial_info.data = data; + serial_info.size = serial_size; + ret = core_serialize(&serial_info); + if ( !ret ) + { + free(data) ; + return NULL ; + } + return data ; +} + /** * task_save_handler: * @task : the task being worked on @@ -576,9 +604,22 @@ static void task_save_handler(retro_task_t *task) return; } + if (!state->data) + { + state->data = get_serialized_data(state->path, state->size) ; + } + remaining = MIN(state->size - state->written, SAVE_STATE_CHUNK); - written = (int)intfstream_write(state->file, + + if ( state->data ) + { + written = (int)intfstream_write(state->file, (uint8_t*)state->data + state->written, remaining); + } + else + { + written = 0 ; + } state->written += written; @@ -1144,85 +1185,90 @@ error: **/ bool content_save_state(const char *path, bool save_to_disk, bool autosave) { - retro_ctx_serialize_info_t serial_info; retro_ctx_size_info_t info; bool ret = false; void *data = NULL; core_serialize_size(&info); - RARCH_LOG("%s: \"%s\".\n", - msg_hash_to_str(MSG_SAVING_STATE), - path); - if (info.size == 0) return false; - data = malloc(info.size); - - if (!data) - return false; - - RARCH_LOG("%s: %d %s.\n", - msg_hash_to_str(MSG_STATE_SIZE), - (int)info.size, - msg_hash_to_str(MSG_BYTES)); - - serial_info.data = data; - serial_info.size = info.size; - ret = core_serialize(&serial_info); - - if (ret) + if ( !save_state_in_background ) { - if (save_to_disk) - { - if (filestream_exists(path) && !autosave) - { - /* Before overwritting the savestate file, load it into a buffer - to allow undo_save_state() to work */ - /* TODO/FIXME - Use msg_hash_to_str here */ - RARCH_LOG("%s ...\n", - msg_hash_to_str(MSG_FILE_ALREADY_EXISTS_SAVING_TO_BACKUP_BUFFER)); + RARCH_LOG("%s: \"%s\".\n", + msg_hash_to_str(MSG_SAVING_STATE), + path); - task_push_load_and_save_state(path, data, info.size, true, autosave); - } - else - task_push_save_state(path, data, info.size, autosave); + data = get_serialized_data(path, info.size) ; + + + if (!data) + { + RARCH_ERR("%s \"%s\".\n", + msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO), + path); + return false; + } + + RARCH_LOG("%s: %d %s.\n", + msg_hash_to_str(MSG_STATE_SIZE), + (int)info.size, + msg_hash_to_str(MSG_BYTES)); + + } + + if (save_to_disk) + { + if (filestream_exists(path) && !autosave) + { + /* Before overwritting the savestate file, load it into a buffer + to allow undo_save_state() to work */ + /* TODO/FIXME - Use msg_hash_to_str here */ + RARCH_LOG("%s ...\n", + msg_hash_to_str(MSG_FILE_ALREADY_EXISTS_SAVING_TO_BACKUP_BUFFER)); + + task_push_load_and_save_state(path, data, info.size, true, autosave); } else - { - /* save_to_disk is false, which means we are saving the state - in undo_load_buf to allow content_undo_load_state() to restore it */ - - /* If we were holding onto an old state already, clean it up first */ - if (undo_load_buf.data) - { - free(undo_load_buf.data); - undo_load_buf.data = NULL; - } - - undo_load_buf.data = malloc(info.size); - if (!undo_load_buf.data) - { - free(data); - return false; - } - - memcpy(undo_load_buf.data, data, info.size); - free(data); - undo_load_buf.size = info.size; - strlcpy(undo_load_buf.path, path, sizeof(undo_load_buf.path)); - } + task_push_save_state(path, data, info.size, autosave); } else { + if ( data == NULL ) + data = get_serialized_data(path, info.size) ; + + if ( data == NULL ) + { + RARCH_ERR("%s \"%s\".\n", + msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO), + path); + return false ; + } + /* save_to_disk is false, which means we are saving the state + in undo_load_buf to allow content_undo_load_state() to restore it */ + + /* If we were holding onto an old state already, clean it up first */ + if (undo_load_buf.data) + { + free(undo_load_buf.data); + undo_load_buf.data = NULL; + } + + undo_load_buf.data = malloc(info.size); + if (!undo_load_buf.data) + { + free(data); + return false; + } + + memcpy(undo_load_buf.data, data, info.size); free(data); - RARCH_ERR("%s \"%s\".\n", - msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO), - path); + undo_load_buf.size = info.size; + strlcpy(undo_load_buf.path, path, sizeof(undo_load_buf.path)); } - return ret; + return true; } /** @@ -1546,3 +1592,8 @@ void *savefile_ptr_get(void) { return task_save_files; } + +void set_save_state_in_background(bool state) +{ + save_state_in_background = state ; +} diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index a2632e4ac8..4647a1dea1 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -267,6 +267,8 @@ bool task_push_audio_mixer_load( extern const char* const input_builtin_autoconfs[]; +void set_save_state_in_background(bool state) ; + RETRO_END_DECLS #endif