diff --git a/content.h b/content.h index c54de0322a..db819002b9 100644 --- a/content.h +++ b/content.h @@ -60,6 +60,9 @@ bool content_load_state(const char* path, bool load_to_backup_buffer, bool autol /* Save a state from memory to disk. */ bool content_save_state(const char *path, bool save_to_disk, bool autosave); +/* Check a ram state write to disk. */ +bool content_ram_state_pending(void); + /* Gets the number of bytes required to serialize the state. */ size_t content_get_serialized_size(void); diff --git a/gfx/common/ctr_common.h b/gfx/common/ctr_common.h index 5a741cdc6d..970b7cfc2d 100644 --- a/gfx/common/ctr_common.h +++ b/gfx/common/ctr_common.h @@ -149,7 +149,6 @@ typedef struct ctr_video bool refresh_bottom_menu; bool render_font_bottom; bool render_state_from_png_file; - bool state_data_on_ram; bool state_data_exist; char state_date[CTR_STATE_DATE_SIZE]; int state_slot; diff --git a/gfx/drivers/ctr_gfx.c b/gfx/drivers/ctr_gfx.c index b7902abbdb..81179c0ff0 100644 --- a/gfx/drivers/ctr_gfx.c +++ b/gfx/drivers/ctr_gfx.c @@ -433,17 +433,7 @@ static void save_state_to_file(void *data) ctr_video_t *ctr = (ctr_video_t*)data; char state_path[PATH_MAX_LENGTH]; - global_t *global = global_get_ptr(); - const char *name_savestate = global->name.savestate; - - if (ctr->state_slot > 0) - snprintf(state_path, sizeof(state_path), "%s%d", name_savestate, - ctr->state_slot); - else if (ctr->state_slot < 0) - fill_pathname_join_delim(state_path, - name_savestate, "auto", '.', sizeof(state_path)); - else - strlcpy(state_path, name_savestate, sizeof(state_path)); + retroarch_get_current_savestate_path(state_path, sizeof(state_path)); command_event(CMD_EVENT_RAM_STATE_TO_FILE, state_path); } @@ -566,7 +556,6 @@ static void bottom_menu_control(void* data, bool lcd_bottom) ctr_state_thumbnail_geom(ctr); ctr->state_data_exist = true; - ctr->state_data_on_ram = true; ctr->render_state_from_png_file = false; ctr_update_state_date(ctr); @@ -592,9 +581,7 @@ static void bottom_menu_control(void* data, bool lcd_bottom) state_tmp_touch.py < 230 && ctr->state_data_exist) { - if (ctr->state_data_on_ram) - command_event(CMD_EVENT_LOAD_STATE_FROM_RAM, NULL); - else + if (!command_event(CMD_EVENT_LOAD_STATE_FROM_RAM, NULL)) command_event(CMD_EVENT_LOAD_STATE, NULL); BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE); } @@ -608,13 +595,10 @@ static void bottom_menu_control(void* data, bool lcd_bottom) !rarch_ctl(RARCH_CTL_CORE_IS_RUNNING, NULL)) return; + if (ctr->state_slot != config_slot) { - if (ctr->state_data_on_ram) - { - save_state_to_file(ctr); - ctr->state_data_on_ram = false; - } + save_state_to_file(ctr); ctr->state_slot = config_slot; @@ -944,11 +928,7 @@ static void ctr_lcd_aptHook(APT_HookType hook, void* param) { ctr_set_bottom_screen_enable(hook == APTHOOK_ONSUSPEND, ctr->bottom_is_idle); - if (ctr->state_data_on_ram) - { - save_state_to_file(ctr); - ctr->state_data_on_ram = false; - } + save_state_to_file(ctr); } if (menu_driver_is_alive()) @@ -1019,7 +999,6 @@ static void* ctr_init(const video_info_t* video, ctr->init_bottom_menu = false; ctr->state_data_exist = false; - ctr->state_data_on_ram = false; ctr->render_font_bottom = false; ctr->refresh_bottom_menu = true; ctr->render_state_from_png_file = false; @@ -1772,9 +1751,6 @@ static void ctr_free(void* data) if (!ctr) return; - if (ctr->state_data_on_ram) - save_state_to_file(ctr); - aptUnhook(&ctr->lcd_aptHook); gspSetEventCallback(GSPGPU_EVENT_VBlank0, NULL, NULL, true); shaderProgramFree(&ctr->shader); diff --git a/retroarch.c b/retroarch.c index fdfc5b4a6e..a33e36f0d7 100644 --- a/retroarch.c +++ b/retroarch.c @@ -7741,6 +7741,19 @@ static void path_clear_all(void) path_clear(RARCH_PATH_BASENAME); } +void ram_state_to_file(void) +{ + char state_path[PATH_MAX_LENGTH]; + + if (!content_ram_state_pending()) + return; + + state_path[0] = '\0'; + + if (retroarch_get_current_savestate_path(state_path, sizeof(state_path))) + command_event(CMD_EVENT_RAM_STATE_TO_FILE, state_path); +} + bool retroarch_get_current_savestate_path(char *path, size_t len) { struct rarch_state *p_rarch = &rarch_st; @@ -12107,6 +12120,10 @@ bool command_event(enum event_command cmd, void *data) runloop_state.core_running = false; + /* The platform that uses ram_state_save calls it when the content + * ends and writes it to a file */ + ram_state_to_file(); + /* Save last selected disk index, if required */ if (sys_info) disk_control_save_image_index(&sys_info->disk_control); @@ -12521,6 +12538,10 @@ bool command_event(enum event_command cmd, void *data) struct retro_hw_render_callback *hwr = NULL; rarch_system_info_t *sys_info = &runloop_state.system; + /* The platform that uses ram_state_save calls it when the content + * ends and writes it to a file */ + ram_state_to_file(); + /* Save last selected disk index, if required */ if (sys_info) disk_control_save_image_index(&sys_info->disk_control); diff --git a/tasks/task_save.c b/tasks/task_save.c index d2f85522b9..e7b763e70f 100644 --- a/tasks/task_save.c +++ b/tasks/task_save.c @@ -86,6 +86,12 @@ struct save_state_buf char path[PATH_MAX_LENGTH]; }; +struct ram_save_state_buf +{ + struct save_state_buf state_buf; + bool to_write_file; +}; + struct sram_block { void *data; @@ -153,7 +159,7 @@ static struct save_state_buf undo_load_buf; /* Buffer that stores state instead of file. * This is useful for devices with slow I/O. */ -static struct save_state_buf ram_buf; +static struct ram_save_state_buf ram_buf; #ifdef HAVE_THREADS /* TODO/FIXME - global state - perhaps move outside this file */ @@ -1550,6 +1556,17 @@ bool content_save_state(const char *path, bool save_to_disk, bool autosave) return true; } +/** + * content_ram_state_pending: + * Check a ram state write to disk. + * + * Returns: true if need to write, false otherwise. + **/ +bool content_ram_state_pending(void) +{ + return ram_buf.to_write_file; +} + static bool task_save_state_finder(retro_task_t *task, void *user_data) { if (!task) @@ -1673,14 +1690,15 @@ bool content_reset_savestate_backups(void) undo_load_buf.path[0] = '\0'; undo_load_buf.size = 0; - if (ram_buf.data) + if (ram_buf.state_buf.data) { - free(ram_buf.data); - ram_buf.data = NULL; + free(ram_buf.state_buf.data); + ram_buf.state_buf.data = NULL; } - ram_buf.path[0] = '\0'; - ram_buf.size = 0; + ram_buf.state_buf.path[0] = '\0'; + ram_buf.state_buf.size = 0; + ram_buf.to_write_file = false; return true; } @@ -1833,15 +1851,18 @@ bool content_load_state_from_ram(void) bool ret = false; void* temp_data = NULL; + if (!ram_buf.state_buf.data) + return false; + RARCH_LOG("[State]: %s, %u %s.\n", msg_hash_to_str(MSG_LOADING_STATE), - (unsigned)ram_buf.size, + (unsigned)ram_buf.state_buf.size, msg_hash_to_str(MSG_BYTES)); /* We need to make a temporary copy of the buffer, to allow the swap below */ - temp_data = malloc(ram_buf.size); - temp_data_size = ram_buf.size; - memcpy(temp_data, ram_buf.data, ram_buf.size); + temp_data = malloc(ram_buf.state_buf.size); + temp_data_size = ram_buf.state_buf.size; + memcpy(temp_data, ram_buf.state_buf.data, ram_buf.state_buf.size); /* Swap the current state with the backup state. This way, we can undo what we're undoing */ @@ -1908,22 +1929,23 @@ bool content_save_state_to_ram(void) } /* If we were holding onto an old state already, clean it up first */ - if (ram_buf.data) + if (ram_buf.state_buf.data) { - free(ram_buf.data); - ram_buf.data = NULL; + free(ram_buf.state_buf.data); + ram_buf.state_buf.data = NULL; } - ram_buf.data = malloc(serial_size); - if (!ram_buf.data) + ram_buf.state_buf.data = malloc(serial_size); + if (!ram_buf.state_buf.data) { free(data); return false; } - memcpy(ram_buf.data, data, serial_size); + memcpy(ram_buf.state_buf.data, data, serial_size); free(data); - ram_buf.size = serial_size; + ram_buf.state_buf.size = serial_size; + ram_buf.to_write_file = true; return true; } @@ -1948,17 +1970,23 @@ bool content_ram_state_to_file(const char *path) if (!path) return false; - if (!ram_buf.data) + if (!ram_buf.state_buf.data) + return false; + + if (!ram_buf.to_write_file) return false; #if defined(HAVE_ZLIB) if (compress_files) write_success = rzipstream_write_file( - path, ram_buf.data, ram_buf.size); + path, ram_buf.state_buf.data, ram_buf.state_buf.size); else #endif write_success = filestream_write_file( - path, ram_buf.data, ram_buf.size); + path, ram_buf.state_buf.data, ram_buf.state_buf.size); + + if (write_success) + ram_buf.to_write_file = false; return write_success; }