changeset 1852:a4cae960fd08

Allow config file to be saved with executable for "portable" setups
author Michael Pavone <pavone@retrodev.com>
date Wed, 24 Apr 2019 19:08:49 -0700
parents 419b458f93cd
children 9b2acecf8124
files config.c config.h controller_info.c nuklear_ui/blastem_nuklear.c util.c util.h
diffstat 6 files changed, 65 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/config.c	Tue Apr 23 23:37:15 2019 -0700
+++ b/config.c	Wed Apr 24 19:08:49 2019 -0700
@@ -225,7 +225,7 @@
 	return ret;
 }
 
-tern_node *load_overrideable_config(char *name, char *bundled_name)
+tern_node *load_overrideable_config(char *name, char *bundled_name, uint8_t *used_config_dir)
 {
 	char const *confdir = get_config_dir();
 	char *confpath = NULL;
@@ -233,58 +233,60 @@
 	if (confdir) {
 		confpath = path_append(confdir, name);
 		ret = parse_config_file(confpath);
-		if (ret) {
-			free(confpath);
-			return ret;
+	}
+	free(confpath);
+	if (used_config_dir) {
+		*used_config_dir = ret != NULL;
+	}
+	
+	if (!ret) {
+		ret = parse_bundled_config(name);
+		if (!ret) {
+			ret = parse_bundled_config(bundled_name);
 		}
 	}
 
-	ret = parse_bundled_config(bundled_name);
-	if (ret) {
-		free(confpath);
-		return ret;
-	}
-	return NULL;
+	return ret;
 }
 
+static uint8_t app_config_in_config_dir;
 tern_node *load_config()
 {
-	char const *confdir = get_config_dir();
-	char *confpath = NULL;
-	tern_node *ret = load_overrideable_config("blastem.cfg", "default.cfg");
-	if (confdir) {
-		confpath = path_append(confdir, "blastem.cfg");
-		ret = parse_config_file(confpath);
-		if (ret) {
-			free(confpath);
-			return ret;
+	tern_node *ret = load_overrideable_config("blastem.cfg", "default.cfg", &app_config_in_config_dir);
+	
+	if (!ret) {
+		if (get_config_dir()) {
+			fatal_error("Failed to find a config file at %s or in the blastem executable directory\n", get_config_dir());
+		} else {
+			fatal_error("Failed to find a config file in the BlastEm executable directory and the config directory path could not be determined\n");
 		}
 	}
-
-	ret = parse_bundled_config("default.cfg");
-	if (ret) {
-		free(confpath);
-		return ret;
-	}
-
-	if (get_config_dir()) {
-		fatal_error("Failed to find a config file at %s or in the blastem executable directory\n", get_config_dir());
-	} else {
-		fatal_error("Failed to find a config file in the BlastEm executable directory and the config directory path could not be determined\n");
-	}
-	//this will never get reached, but the compiler doesn't know that. Let's make it happy
-	return NULL;
+	return ret;
 }
 
-void persist_config_at(tern_node *config, char *fname)
+void persist_config_at(tern_node *app_config, tern_node *to_save, char *fname)
 {
-	char const *confdir = get_config_dir();
-	if (!confdir) {
-		fatal_error("Failed to locate config file directory\n");
+	char*use_exe_dir = tern_find_path_default(app_config, "ui\0config_in_exe_dir\0", (tern_val){.ptrval = "off"}, TVAL_PTR).ptrval;
+	char *confpath;
+	if (!strcmp(use_exe_dir, "on")) {
+		confpath = path_append(get_exe_dir(), fname);
+		if (app_config == to_save && app_config_in_config_dir) {
+			//user switched to "portable" configs this session and there is an
+			//existing config file in the user-specific config directory
+			//delete it so we don't end up loading it next time
+			char *oldpath = path_append(get_config_dir(), fname);
+			delete_file(oldpath);
+			free(oldpath);
+		}
+	} else {
+		char const *confdir = get_config_dir();
+		if (!confdir) {
+			fatal_error("Failed to locate config file directory\n");
+		}
+		ensure_dir_exists(confdir);
+		confpath = path_append(confdir, fname);
 	}
-	ensure_dir_exists(confdir);
-	char *confpath = path_append(confdir, fname);
-	if (!serialize_config_file(config, confpath)) {
+	if (!serialize_config_file(to_save, confpath)) {
 		fatal_error("Failed to write config to %s\n", confpath);
 	}
 	free(confpath);
@@ -292,7 +294,7 @@
 
 void persist_config(tern_node *config)
 {
-	persist_config_at(config, "blastem.cfg");
+	persist_config_at(config, config, "blastem.cfg");
 }
 
 char **get_extension_list(tern_node *config, uint32_t *num_exts_out)
--- a/config.h	Tue Apr 23 23:37:15 2019 -0700
+++ b/config.h	Wed Apr 24 19:08:49 2019 -0700
@@ -9,11 +9,11 @@
 
 tern_node *parse_config_file(char *config_path);
 tern_node *parse_bundled_config(char *config_name);
-tern_node *load_overrideable_config(char *name, char *bundled_name);
+tern_node *load_overrideable_config(char *name, char *bundled_name, uint8_t *used_config_dir);
 tern_node *load_config();
 char *serialize_config(tern_node *config, uint32_t *size_out);
 uint8_t serialize_config_file(tern_node *config, char *path);
-void persist_config_at(tern_node *config, char *fname);
+void persist_config_at(tern_node *app_config, tern_node *to_save, char *fname);
 void persist_config(tern_node *config);
 char **get_extension_list(tern_node *config, uint32_t *num_exts_out);
 uint32_t get_lowpass_cutoff(tern_node *config);
--- a/controller_info.c	Tue Apr 23 23:37:15 2019 -0700
+++ b/controller_info.c	Wed Apr 24 19:08:49 2019 -0700
@@ -6,6 +6,7 @@
 #include "controller_info.h"
 #include "config.h"
 #include "util.h"
+#include "blastem.h"
 
 typedef struct {
 	char const      *name;
@@ -66,7 +67,7 @@
 static void load_ctype_config(void)
 {
 	if (!loaded) {
-		info_config = load_overrideable_config("controller_types.cfg", "controller_types.cfg");
+		info_config = load_overrideable_config("controller_types.cfg", "controller_types.cfg", NULL);
 		loaded = 1;
 	}
 }
@@ -197,7 +198,7 @@
 	existing = tern_insert_ptr(existing, "subtype", (void *)subtype_names[info->subtype]);
 	existing = tern_insert_ptr(existing, "variant",  (void *)variant_names[info->variant]);
 	info_config = tern_insert_node(info_config, guid_string, existing);
-	persist_config_at(info_config, "controller_types.cfg");
+	persist_config_at(config, info_config, "controller_types.cfg");
 #endif	
 }
 
@@ -209,7 +210,7 @@
 	tern_node *existing = tern_find_node(info_config, guid_string);
 	existing = tern_insert_ptr(existing, "mapping", mapping_string);
 	info_config = tern_insert_node(info_config, guid_string, existing);
-	persist_config_at(info_config, "controller_types.cfg");
+	persist_config_at(config, info_config, "controller_types.cfg");
 #endif
 }
 
--- a/nuklear_ui/blastem_nuklear.c	Tue Apr 23 23:37:15 2019 -0700
+++ b/nuklear_ui/blastem_nuklear.c	Wed Apr 24 19:08:49 2019 -0700
@@ -1827,6 +1827,7 @@
 		selected_sync = settings_dropdown(context, "Sync Source", sync_opts, num_sync_opts, selected_sync, "system\0sync_source\0");
 		settings_int_property(context, "68000 Clock Divider", "", "clocks\0m68k_divider\0", 7, 1, 53);
 		settings_toggle(context, "Remember ROM Path", "ui\0remember_path\0", 1);
+		settings_toggle(context, "Save config with EXE", "ui\0config_in_exe_dir\0", 0);
 		selected_region = settings_dropdown_ex(context, "Default Region", region_codes, regions, num_regions, selected_region, "system\0default_region\0");
 		selected_format = settings_dropdown(context, "Save State Format", formats, num_formats, selected_format, "ui\0state_format\0");
 		selected_init = settings_dropdown(context, "Initial RAM Value", ram_inits, num_inits, selected_init, "system\0ram_init\0");
--- a/util.c	Tue Apr 23 23:37:15 2019 -0700
+++ b/util.c	Wed Apr 24 19:08:49 2019 -0700
@@ -854,6 +854,16 @@
 	qsort(list, num_entries, sizeof(dir_entry), sort_dir_alpha);
 }
 
+uint8_t delete_file(char *path)
+{
+#ifdef _WIN32
+	//TODO: Call Unicode version and prepend special string to remove max path limitation
+	return 0 != DeleteFileA(path);
+#else
+	return 0 == unlink(path);
+#endif
+}
+
 #ifdef __ANDROID__
 
 #include <SDL.h>
@@ -943,7 +953,7 @@
 	fclose(f);
 	return ret;
 }
-#endif
+#endif //ISLIB
 
 #ifdef _WIN32
 char const *get_userdata_dir()
@@ -1000,8 +1010,6 @@
 }
 
 
-#endif
-
+#endif //_WIN32
+#endif //__ANDROID__
 
-
-#endif
--- a/util.h	Tue Apr 23 23:37:15 2019 -0700
+++ b/util.h	Wed Apr 24 19:08:49 2019 -0700
@@ -88,5 +88,7 @@
 void debug_message(char *format, ...);
 //Disables output of info and debug messages to stdout
 void disable_stdout_messages(void);
+//Deletes a file, returns true on success, false on failure
+uint8_t delete_file(char *path);
 
 #endif //UTIL_H_