Fix ram states to file when core deinit (#12956)

* Fix ram states to file when core deinit

* Fix unterminated state_path
Call CMD_EVENT_RAM_STATE_TO_FILE when CMD_EVENT_UNLOAD_CORE too
This commit is contained in:
bulzipke 2021-09-09 01:01:07 +09:00 committed by GitHub
parent c9e587a5a7
commit 8018be5c9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 50 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;
}