mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 22:20:21 +00:00
Adding savestate garbage collector for autoincrement stavestates
As some issues indicate (#6195 #10471 #11008 #6861) there's an issue with the autoincrement save slot feature: slot index will increase and very old saves won't be deleted. This commit adds support to delete old save states with a user defined save state limit (global). Instead of wrapping around the slot counter it will simply delete the oldest save, since it is simpler. For now there's a limit of one deletion per save, which ensures a user cannot delete many saves by accident if they set the limit too low.
This commit is contained in:
parent
865303c501
commit
1c5099051c
@ -1020,6 +1020,15 @@ static const unsigned netplay_share_analog = RARCH_NETPLAY_SHARE_ANALOG_NO_PREFE
|
||||
* to the highest existing value. */
|
||||
static const bool savestate_auto_index = false;
|
||||
|
||||
/* Specifies the maximum number of savestates to keep
|
||||
* when savestate auto index is enabled
|
||||
* > When limit is exceeded, savestate with the lowest
|
||||
* index will be deleted automatically when creating
|
||||
* a new savestate
|
||||
* > Setting value to zero disables the limit (no
|
||||
* savestates will be deleted in this case) */
|
||||
#define DEFAULT_SAVESTATE_MAX_KEEP 0
|
||||
|
||||
/* Automatically saves a savestate at the end of RetroArch's lifetime.
|
||||
* The path is $SRAM_PATH.auto.
|
||||
* RetroArch will automatically load any savestate with this path on
|
||||
|
@ -1878,6 +1878,7 @@ static struct config_uint_setting *populate_settings_uint(
|
||||
SETTING_UINT("rewind_granularity", &settings->uints.rewind_granularity, true, DEFAULT_REWIND_GRANULARITY, false);
|
||||
SETTING_UINT("rewind_buffer_size_step", &settings->uints.rewind_buffer_size_step, true, DEFAULT_REWIND_BUFFER_SIZE_STEP, false);
|
||||
SETTING_UINT("autosave_interval", &settings->uints.autosave_interval, true, DEFAULT_AUTOSAVE_INTERVAL, false);
|
||||
SETTING_UINT("savestate_max_keep", &settings->uints.savestate_max_keep, true, DEFAULT_SAVESTATE_MAX_KEEP, false);
|
||||
SETTING_UINT("frontend_log_level", &settings->uints.frontend_log_level, true, DEFAULT_FRONTEND_LOG_LEVEL, false);
|
||||
SETTING_UINT("libretro_log_level", &settings->uints.libretro_log_level, true, DEFAULT_LIBRETRO_LOG_LEVEL, false);
|
||||
SETTING_UINT("keyboard_gamepad_mapping_type",&settings->uints.input_keyboard_gamepad_mapping_type, true, 1, false);
|
||||
|
@ -170,6 +170,7 @@ typedef struct settings
|
||||
unsigned rewind_granularity;
|
||||
unsigned rewind_buffer_size_step;
|
||||
unsigned autosave_interval;
|
||||
unsigned savestate_max_keep;
|
||||
unsigned network_cmd_port;
|
||||
unsigned network_remote_base_port;
|
||||
unsigned keymapper_port;
|
||||
|
@ -2586,6 +2586,10 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_SAVESTATE_AUTO_SAVE,
|
||||
"savestate_auto_save"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_SAVESTATE_MAX_KEEP,
|
||||
"savestate_max_keep"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_SAVESTATE_DIRECTORY,
|
||||
"savestate_directory"
|
||||
|
@ -2962,6 +2962,14 @@ MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_INDEX,
|
||||
"Before making a save state, the save state index is automatically increased. When loading content, the index will be set to the highest existing index."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_SAVESTATE_MAX_KEEP,
|
||||
"Maximum Auto-Increment Save States to Keep"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_SAVESTATE_MAX_KEEP,
|
||||
"Limits the number of save states that will be created when 'Increment Save State Index Automatically' is enabled. If limit is exceeded when saving a new state, the existing state with the lowest index will be deleted. A value of '0' means unlimited states will be recorded."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_SAVE,
|
||||
"Auto Save State"
|
||||
|
@ -491,6 +491,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_savestate_auto_load, MENU_
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_savestate_thumbnail_enable, MENU_ENUM_SUBLABEL_SAVESTATE_THUMBNAIL_ENABLE)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_save_file_compression, MENU_ENUM_SUBLABEL_SAVE_FILE_COMPRESSION)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_savestate_file_compression, MENU_ENUM_SUBLABEL_SAVESTATE_FILE_COMPRESSION)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_savestate_max_keep, MENU_ENUM_SUBLABEL_SAVESTATE_MAX_KEEP)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_autosave_interval, MENU_ENUM_SUBLABEL_AUTOSAVE_INTERVAL)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_remap_binds_enable, MENU_ENUM_SUBLABEL_INPUT_REMAP_BINDS_ENABLE)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_autodetect_enable, MENU_ENUM_SUBLABEL_INPUT_AUTODETECT_ENABLE)
|
||||
@ -2876,6 +2877,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_AUTOSAVE_INTERVAL:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_autosave_interval);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_SAVESTATE_MAX_KEEP:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_savestate_max_keep);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_SAVESTATE_THUMBNAIL_ENABLE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_savestate_thumbnail_enable);
|
||||
break;
|
||||
|
@ -8052,31 +8052,48 @@ unsigned menu_displaylist_build_list(
|
||||
break;
|
||||
case DISPLAYLIST_SAVING_SETTINGS_LIST:
|
||||
{
|
||||
menu_displaylist_build_info_t build_list[] = {
|
||||
{MENU_ENUM_LABEL_SORT_SAVEFILES_ENABLE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SORT_SAVESTATES_ENABLE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SORT_SAVEFILES_BY_CONTENT_ENABLE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SORT_SAVESTATES_BY_CONTENT_ENABLE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_BLOCK_SRAM_OVERWRITE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_AUTOSAVE_INTERVAL, PARSE_ONLY_UINT},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_AUTO_INDEX, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_AUTO_SAVE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_AUTO_LOAD, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_THUMBNAIL_ENABLE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SAVE_FILE_COMPRESSION, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_FILE_COMPRESSION, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SORT_SCREENSHOTS_BY_CONTENT_ENABLE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SAVEFILES_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SAVESTATES_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SYSTEMFILES_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_SCREENSHOTS_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE, PARSE_ONLY_BOOL},
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool savestate_auto_index = settings->bools.savestate_auto_index;
|
||||
|
||||
menu_displaylist_build_info_selective_t build_list[] = {
|
||||
{MENU_ENUM_LABEL_SORT_SAVEFILES_ENABLE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SORT_SAVESTATES_ENABLE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SORT_SAVEFILES_BY_CONTENT_ENABLE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SORT_SAVESTATES_BY_CONTENT_ENABLE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_BLOCK_SRAM_OVERWRITE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_AUTOSAVE_INTERVAL, PARSE_ONLY_UINT, true},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_AUTO_INDEX, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_MAX_KEEP, PARSE_ONLY_UINT, false},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_AUTO_SAVE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_AUTO_LOAD, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_THUMBNAIL_ENABLE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SAVE_FILE_COMPRESSION, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SAVESTATE_FILE_COMPRESSION, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SORT_SCREENSHOTS_BY_CONTENT_ENABLE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SAVEFILES_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SAVESTATES_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SYSTEMFILES_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_SCREENSHOTS_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG, PARSE_ONLY_BOOL, true},
|
||||
{MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE, PARSE_ONLY_BOOL, true},
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(build_list); i++)
|
||||
{
|
||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||
switch (build_list[i].enum_idx)
|
||||
{
|
||||
case MENU_ENUM_LABEL_SAVESTATE_MAX_KEEP:
|
||||
build_list[i].checked = savestate_auto_index;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(build_list); i++)
|
||||
{
|
||||
if (build_list[i].checked &&
|
||||
MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||
build_list[i].enum_idx, build_list[i].parse_type,
|
||||
false) == 0)
|
||||
count++;
|
||||
|
@ -9317,7 +9317,7 @@ static bool setting_append_list(
|
||||
case SETTINGS_LIST_SAVING:
|
||||
{
|
||||
uint8_t i;
|
||||
struct bool_entry bool_entries[14];
|
||||
struct bool_entry bool_entries[13];
|
||||
|
||||
START_GROUP(list, list_info, &group_info, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVING_SETTINGS), parent_group);
|
||||
parent_group = msg_hash_to_str(MENU_ENUM_LABEL_SAVING_SETTINGS);
|
||||
@ -9361,54 +9361,48 @@ static bool setting_append_list(
|
||||
bool_entries[5].default_value = DEFAULT_BLOCK_SRAM_OVERWRITE;
|
||||
bool_entries[5].flags = SD_FLAG_NONE;
|
||||
|
||||
bool_entries[6].target = &settings->bools.savestate_auto_index;
|
||||
bool_entries[6].name_enum_idx = MENU_ENUM_LABEL_SAVESTATE_AUTO_INDEX;
|
||||
bool_entries[6].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_INDEX;
|
||||
bool_entries[6].default_value = savestate_auto_index;
|
||||
bool_entries[6].target = &settings->bools.savestate_auto_save;
|
||||
bool_entries[6].name_enum_idx = MENU_ENUM_LABEL_SAVESTATE_AUTO_SAVE;
|
||||
bool_entries[6].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_SAVE;
|
||||
bool_entries[6].default_value = savestate_auto_save;
|
||||
bool_entries[6].flags = SD_FLAG_NONE;
|
||||
|
||||
bool_entries[7].target = &settings->bools.savestate_auto_save;
|
||||
bool_entries[7].name_enum_idx = MENU_ENUM_LABEL_SAVESTATE_AUTO_SAVE;
|
||||
bool_entries[7].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_SAVE;
|
||||
bool_entries[7].default_value = savestate_auto_save;
|
||||
bool_entries[7].target = &settings->bools.savestate_auto_load;
|
||||
bool_entries[7].name_enum_idx = MENU_ENUM_LABEL_SAVESTATE_AUTO_LOAD;
|
||||
bool_entries[7].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_LOAD;
|
||||
bool_entries[7].default_value = savestate_auto_load;
|
||||
bool_entries[7].flags = SD_FLAG_NONE;
|
||||
|
||||
bool_entries[8].target = &settings->bools.savestate_auto_load;
|
||||
bool_entries[8].name_enum_idx = MENU_ENUM_LABEL_SAVESTATE_AUTO_LOAD;
|
||||
bool_entries[8].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_LOAD;
|
||||
bool_entries[8].default_value = savestate_auto_load;
|
||||
bool_entries[8].flags = SD_FLAG_NONE;
|
||||
bool_entries[8].target = &settings->bools.savestate_thumbnail_enable;
|
||||
bool_entries[8].name_enum_idx = MENU_ENUM_LABEL_SAVESTATE_THUMBNAIL_ENABLE;
|
||||
bool_entries[8].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVESTATE_THUMBNAIL_ENABLE;
|
||||
bool_entries[8].default_value = savestate_thumbnail_enable;
|
||||
bool_entries[8].flags = SD_FLAG_ADVANCED;
|
||||
|
||||
bool_entries[9].target = &settings->bools.savestate_thumbnail_enable;
|
||||
bool_entries[9].name_enum_idx = MENU_ENUM_LABEL_SAVESTATE_THUMBNAIL_ENABLE;
|
||||
bool_entries[9].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVESTATE_THUMBNAIL_ENABLE;
|
||||
bool_entries[9].default_value = savestate_thumbnail_enable;
|
||||
bool_entries[9].target = &settings->bools.savefiles_in_content_dir;
|
||||
bool_entries[9].name_enum_idx = MENU_ENUM_LABEL_SAVEFILES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[9].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVEFILES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[9].default_value = default_savefiles_in_content_dir;
|
||||
bool_entries[9].flags = SD_FLAG_ADVANCED;
|
||||
|
||||
bool_entries[10].target = &settings->bools.savefiles_in_content_dir;
|
||||
bool_entries[10].name_enum_idx = MENU_ENUM_LABEL_SAVEFILES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[10].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVEFILES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[10].default_value = default_savefiles_in_content_dir;
|
||||
bool_entries[10].target = &settings->bools.savestates_in_content_dir;
|
||||
bool_entries[10].name_enum_idx = MENU_ENUM_LABEL_SAVESTATES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[10].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVESTATES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[10].default_value = default_savestates_in_content_dir;
|
||||
bool_entries[10].flags = SD_FLAG_ADVANCED;
|
||||
|
||||
bool_entries[11].target = &settings->bools.savestates_in_content_dir;
|
||||
bool_entries[11].name_enum_idx = MENU_ENUM_LABEL_SAVESTATES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[11].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SAVESTATES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[11].default_value = default_savestates_in_content_dir;
|
||||
bool_entries[11].target = &settings->bools.systemfiles_in_content_dir;
|
||||
bool_entries[11].name_enum_idx = MENU_ENUM_LABEL_SYSTEMFILES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[11].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SYSTEMFILES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[11].default_value = default_systemfiles_in_content_dir;
|
||||
bool_entries[11].flags = SD_FLAG_ADVANCED;
|
||||
|
||||
bool_entries[12].target = &settings->bools.systemfiles_in_content_dir;
|
||||
bool_entries[12].name_enum_idx = MENU_ENUM_LABEL_SYSTEMFILES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[12].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SYSTEMFILES_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[12].default_value = default_systemfiles_in_content_dir;
|
||||
bool_entries[12].target = &settings->bools.screenshots_in_content_dir;
|
||||
bool_entries[12].name_enum_idx = MENU_ENUM_LABEL_SCREENSHOTS_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[12].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SCREENSHOTS_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[12].default_value = default_screenshots_in_content_dir;
|
||||
bool_entries[12].flags = SD_FLAG_ADVANCED;
|
||||
|
||||
bool_entries[13].target = &settings->bools.screenshots_in_content_dir;
|
||||
bool_entries[13].name_enum_idx = MENU_ENUM_LABEL_SCREENSHOTS_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[13].SHORT_enum_idx = MENU_ENUM_LABEL_VALUE_SCREENSHOTS_IN_CONTENT_DIR_ENABLE;
|
||||
bool_entries[13].default_value = default_screenshots_in_content_dir;
|
||||
bool_entries[13].flags = SD_FLAG_ADVANCED;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bool_entries); i++)
|
||||
{
|
||||
CONFIG_BOOL(
|
||||
@ -9446,6 +9440,37 @@ static bool setting_append_list(
|
||||
(*list)[list_info->index - 1].get_string_representation =
|
||||
&setting_get_string_representation_uint_autosave_interval;
|
||||
#endif
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.savestate_auto_index,
|
||||
MENU_ENUM_LABEL_SAVESTATE_AUTO_INDEX,
|
||||
MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_INDEX,
|
||||
savestate_auto_index,
|
||||
MENU_ENUM_LABEL_VALUE_OFF,
|
||||
MENU_ENUM_LABEL_VALUE_ON,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler,
|
||||
SD_FLAG_NONE);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_bool_action_left_with_refresh;
|
||||
(*list)[list_info->index - 1].action_left = &setting_bool_action_left_with_refresh;
|
||||
(*list)[list_info->index - 1].action_right = &setting_bool_action_right_with_refresh;
|
||||
|
||||
CONFIG_UINT(
|
||||
list, list_info,
|
||||
&settings->uints.savestate_max_keep,
|
||||
MENU_ENUM_LABEL_SAVESTATE_MAX_KEEP,
|
||||
MENU_ENUM_LABEL_VALUE_SAVESTATE_MAX_KEEP,
|
||||
DEFAULT_SAVESTATE_MAX_KEEP,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
menu_settings_list_current_add_range(list, list_info, 0, 999, 1, true, true);
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
|
@ -1736,6 +1736,7 @@ enum msg_hash_enums
|
||||
MENU_LABEL(CHEAT_DELETE_MATCH),
|
||||
MENU_LABEL(SCREEN_RESOLUTION),
|
||||
MENU_LABEL(SAVESTATE_AUTO_INDEX),
|
||||
MENU_LABEL(SAVESTATE_MAX_KEEP),
|
||||
MENU_LABEL(SAVESTATE_AUTO_SAVE),
|
||||
MENU_LABEL(SAVESTATE_AUTO_LOAD),
|
||||
MENU_LABEL(SAVESTATE_THUMBNAIL_ENABLE),
|
||||
|
111
retroarch.c
111
retroarch.c
@ -11982,7 +11982,7 @@ static void command_event_load_auto_state(
|
||||
|
||||
static void command_event_set_savestate_auto_index(
|
||||
settings_t *settings,
|
||||
global_t *global,
|
||||
const global_t *global,
|
||||
struct rarch_state *p_rarch)
|
||||
{
|
||||
size_t i;
|
||||
@ -12047,6 +12047,96 @@ static void command_event_set_savestate_auto_index(
|
||||
max_idx);
|
||||
}
|
||||
|
||||
static void command_event_set_savestate_garbage_collect(
|
||||
settings_t *settings,
|
||||
const global_t *global,
|
||||
struct rarch_state *p_rarch)
|
||||
{
|
||||
size_t i, cnt = 0;
|
||||
char state_dir[PATH_MAX_LENGTH];
|
||||
char state_base[PATH_MAX_LENGTH];
|
||||
|
||||
struct string_list *dir_list = NULL;
|
||||
unsigned min_idx = UINT_MAX;
|
||||
const char *oldest_save = NULL;
|
||||
unsigned max_to_keep = settings->uints.savestate_max_keep;
|
||||
bool show_hidden_files = settings->bools.show_hidden_files;
|
||||
|
||||
if (!global || (max_to_keep == 0))
|
||||
return;
|
||||
|
||||
state_dir[0] = '\0';
|
||||
state_base[0] = '\0';
|
||||
|
||||
/* Similar to command_event_set_savestate_auto_index(),
|
||||
* this will find the lowest numbered save-state */
|
||||
fill_pathname_basedir(state_dir, global->name.savestate,
|
||||
sizeof(state_dir));
|
||||
|
||||
dir_list = dir_list_new_special(state_dir, DIR_LIST_PLAIN, NULL,
|
||||
show_hidden_files);
|
||||
|
||||
if (!dir_list)
|
||||
return;
|
||||
|
||||
fill_pathname_base(state_base, global->name.savestate,
|
||||
sizeof(state_base));
|
||||
|
||||
for (i = 0; i < dir_list->size; i++)
|
||||
{
|
||||
unsigned idx;
|
||||
char elem_base[128];
|
||||
const char *end = NULL;
|
||||
const char *dir_elem = dir_list->elems[i].data;
|
||||
const char *ext = NULL;
|
||||
|
||||
elem_base[0] = '\0';
|
||||
|
||||
if (string_is_empty(dir_elem))
|
||||
continue;
|
||||
|
||||
fill_pathname_base(elem_base, dir_elem, sizeof(elem_base));
|
||||
|
||||
/* Only consider files with a '.state' extension
|
||||
* > i.e. Ignore '.state.auto', '.state.bak', etc. */
|
||||
ext = path_get_extension(elem_base);
|
||||
if (string_is_empty(ext) ||
|
||||
!string_starts_with_size(ext, "state", STRLEN_CONST("state")))
|
||||
continue;
|
||||
|
||||
/* Check whether this file is associated with
|
||||
* the current content */
|
||||
if (!string_starts_with(elem_base, state_base))
|
||||
continue;
|
||||
|
||||
/* This looks like a valid save */
|
||||
cnt++;
|
||||
|
||||
/* > Get index */
|
||||
end = dir_elem + strlen(dir_elem);
|
||||
while ((end > dir_elem) && ISDIGIT((int)end[-1]))
|
||||
end--;
|
||||
|
||||
idx = string_to_unsigned(end);
|
||||
|
||||
/* > Check if this is the lowest index so far */
|
||||
if (idx < min_idx)
|
||||
{
|
||||
min_idx = idx;
|
||||
oldest_save = dir_elem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only delete one save state per save action
|
||||
* > Conservative behaviour, designed to minimise
|
||||
* the risk of deleting multiple incorrect files
|
||||
* in case of accident */
|
||||
if (!string_is_empty(oldest_save) && (cnt > max_to_keep))
|
||||
filestream_delete(oldest_save);
|
||||
|
||||
dir_list_free(dir_list);
|
||||
}
|
||||
|
||||
static bool event_init_content(
|
||||
settings_t *settings,
|
||||
struct rarch_state *p_rarch)
|
||||
@ -12655,15 +12745,26 @@ static bool command_event_main_state(
|
||||
switch (cmd)
|
||||
{
|
||||
case CMD_EVENT_SAVE_STATE:
|
||||
content_save_state(state_path, true, false);
|
||||
{
|
||||
bool savestate_auto_index =
|
||||
settings->bools.savestate_auto_index;
|
||||
unsigned savestate_max_keep =
|
||||
settings->uints.savestate_max_keep;
|
||||
bool frame_time_counter_reset_after_save_state =
|
||||
settings->bools.frame_time_counter_reset_after_save_state;
|
||||
settings->bools.frame_time_counter_reset_after_save_state;
|
||||
|
||||
content_save_state(state_path, true, false);
|
||||
|
||||
/* Clean up excess savestates if necessary */
|
||||
if (savestate_auto_index && (savestate_max_keep > 0))
|
||||
command_event_set_savestate_garbage_collect(settings, global, p_rarch);
|
||||
|
||||
if (frame_time_counter_reset_after_save_state)
|
||||
p_rarch->video_driver_frame_time_count = 0;
|
||||
|
||||
ret = true;
|
||||
push_msg = false;
|
||||
}
|
||||
ret = true;
|
||||
push_msg = false;
|
||||
break;
|
||||
case CMD_EVENT_LOAD_STATE:
|
||||
if (content_load_state(state_path, false, false))
|
||||
|
Loading…
x
Reference in New Issue
Block a user