From bcae973d82c2c1987bb9358446e30e866bf85739 Mon Sep 17 00:00:00 2001 From: Themaister Date: Tue, 27 Sep 2011 15:31:25 +0200 Subject: [PATCH] Savestate auto indexing support. --- config.def.h | 4 ++++ file.c | 8 ++++++-- file.h | 2 ++ general.h | 1 + settings.c | 2 ++ ssnes.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++-- ssnes.cfg | 7 +++++++ 7 files changed, 76 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index 1860369a7d..3f32d4cd3b 100644 --- a/config.def.h +++ b/config.def.h @@ -216,6 +216,10 @@ static const bool netplay_client_swap_input = true; // This could potentially lead to buggy games. static const bool block_sram_overwrite = false; +// When saving savestates, state index is automatically incremented before saving. +// When the ROM is loaded, state index will be set to the highest existing value. +static const bool savestate_auto_index = false; + //////////////////// // Keybinds, Joypad diff --git a/file.c b/file.c index 57285c21b0..a9798f6a28 100644 --- a/file.c +++ b/file.c @@ -818,8 +818,12 @@ char** dir_list_new(const char *dir, const char *ext) goto error; if (strlcat(utf8_buf, "/*", sizeof(utf8_buf)) >= sizeof(utf8_buf)) goto error; - if (strlcat(utf8_buf, ext, sizeof(utf8_buf)) >= sizeof(utf8_buf)) - goto error; + + if (ext) + { + if (strlcat(utf8_buf, ext, sizeof(utf8_buf)) >= sizeof(utf8_buf)) + goto error; + } if (MultiByteToWideChar(CP_UTF8, 0, utf8_buf, -1, wchar_buf, MAXPATHLEN) == 0) goto error; diff --git a/file.h b/file.h index c7948cd6ab..12abc13b60 100644 --- a/file.h +++ b/file.h @@ -37,6 +37,8 @@ void save_ram_file(const char *path, int type); bool init_rom_file(enum ssnes_game_type type); // Returns a NULL-terminated list of files in a directory with full paths. +// If ext is NULL, any file will be picked. +// If non-NULL, only files with extension ext are added. char** dir_list_new(const char *dir, const char *ext); void dir_list_free(char **dir_list); diff --git a/general.h b/general.h index 8464233f49..18242433ee 100644 --- a/general.h +++ b/general.h @@ -150,6 +150,7 @@ struct settings unsigned autosave_interval; bool block_sram_overwrite; + bool savestate_auto_index; }; enum ssnes_game_type diff --git a/settings.c b/settings.c index 5776884a13..8d1bd4b0ff 100644 --- a/settings.c +++ b/settings.c @@ -172,6 +172,7 @@ static void set_defaults(void) g_settings.autosave_interval = autosave_interval; g_settings.block_sram_overwrite = block_sram_overwrite; + g_settings.savestate_auto_index = savestate_auto_index; assert(sizeof(g_settings.input.binds[0]) >= sizeof(snes_keybinds_1)); assert(sizeof(g_settings.input.binds[1]) >= sizeof(snes_keybinds_rest)); @@ -421,6 +422,7 @@ static void parse_config_file(void) CONFIG_GET_STRING(cheat_settings_path, "cheat_settings_path"); CONFIG_GET_BOOL(block_sram_overwrite, "block_sram_overwrite"); + CONFIG_GET_BOOL(savestate_auto_index, "savestate_auto_index"); if (!g_extern.has_set_save_path && config_get_array(conf, "savefile_directory", tmp_str, sizeof(tmp_str))) { diff --git a/ssnes.c b/ssnes.c index dd236d164c..8880e4e347 100644 --- a/ssnes.c +++ b/ssnes.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include "driver.h" @@ -1070,6 +1071,53 @@ static void deinit_autosave(void) } } +static void set_savestate_auto_index(void) +{ + if (!g_settings.savestate_auto_index) + return; + + char state_path[MAXPATHLEN]; + strlcpy(state_path, g_extern.savestate_name, sizeof(state_path)); + + char *split = strrchr(state_path, '/'); + if (!split) + split = strrchr(state_path, '\\'); + + const char *base = state_path; + const char *dir = state_path; + if (split) + { + *split = '\0'; + base = split + 1; + } + + unsigned max_index = 0; + + char **dir_list = dir_list_new(dir, NULL); + if (!dir_list) + return; + + unsigned index = 0; + const char *dir_elem; + while ((dir_elem = dir_list[index++])) + { + if (!strstr(dir_elem, base)) + continue; + + const char *end = dir_elem + strlen(dir_elem); + while ((end != dir_elem) && isdigit(end[-1])) end--; + + unsigned index = strtoul(end, NULL, 0); + if (index > max_index) + max_index = index; + } + + dir_list_free(dir_list); + + g_extern.state_slot = max_index; + SSNES_LOG("Found last state slot: #%u\n", g_extern.state_slot); +} + static void fill_pathnames(void) { switch (g_extern.game_type) @@ -1127,6 +1175,9 @@ static void check_savestates(void) bool should_savestate = driver.input->key_pressed(driver.input_data, SSNES_SAVE_STATE_KEY); if (should_savestate && !old_should_savestate) { + if (g_settings.savestate_auto_index) + g_extern.state_slot++; + char save_path[MAXPATHLEN]; if (g_extern.state_slot > 0) @@ -1134,7 +1185,7 @@ static void check_savestates(void) else snprintf(save_path, sizeof(save_path), "%s", g_extern.savestate_name); - if(!save_state(save_path)) + if (!save_state(save_path)) { msg_queue_clear(g_extern.msg_queue); char msg[512]; @@ -1160,7 +1211,7 @@ static void check_savestates(void) else snprintf(load_path, sizeof(load_path), "%s", g_extern.savestate_name); - if(!load_state(load_path)) + if (!load_state(load_path)) { msg_queue_clear(g_extern.msg_queue); char msg[512]; @@ -1574,6 +1625,7 @@ int main(int argc, char *argv[]) SSNES_LOG("Version of libsnes API: %u.%u\n", psnes_library_revision_major(), psnes_library_revision_minor()); fill_pathnames(); + set_savestate_auto_index(); if (!init_rom_file(g_extern.game_type)) goto error; diff --git a/ssnes.cfg b/ssnes.cfg index e052762a27..acfef1b0a0 100644 --- a/ssnes.cfg +++ b/ssnes.cfg @@ -320,3 +320,10 @@ # Block SRAM from being overwritten when loading save states. # Might potentially lead to buggy games. # block_sram_overwrite = false + +# When saving a savestate, save state index is automatically increased before +# it is saved. +# Also, when loading a ROM, the index will be set to the highest existing index. +# There is no upper bound on the index. +# savestate_auto_index = false +