mirror of
https://github.com/libretro/RetroArch
synced 2024-12-26 21:29:08 +00:00
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:
parent
c9e587a5a7
commit
8018be5c9b
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
21
retroarch.c
21
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user