summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blastem.c7
-rw-r--r--config.c105
-rw-r--r--config.h3
-rw-r--r--paths.c2
-rw-r--r--paths.h2
5 files changed, 115 insertions, 4 deletions
diff --git a/blastem.c b/blastem.c
index 24c1ecd..09bcecb 100644
--- a/blastem.c
+++ b/blastem.c
@@ -286,6 +286,11 @@ void init_system_with_media(char *path, system_type force_stype)
update_title(info.name);
}
+static void save_config(void)
+{
+ persist_config(config);
+}
+
int main(int argc, char ** argv)
{
set_exe_str(argv[0]);
@@ -521,6 +526,8 @@ int main(int argc, char ** argv)
}
}
+ atexit(save_config);
+
#ifndef DISABLE_NUKLEAR
if (use_nuklear) {
blastem_nuklear_init(!menu);
diff --git a/config.c b/config.c
index 6b844ed..71a31f4 100644
--- a/config.c
+++ b/config.c
@@ -5,6 +5,7 @@
*/
#include "tern.h"
#include "util.h"
+#include "paths.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -36,7 +37,7 @@ char * strtok_r(char * input, char * sep, char ** state)
}
#endif
-tern_node * parse_config_int(char **state, int started, int *line)
+static tern_node * parse_config_int(char **state, int started, int *line)
{
char *config_data, *curline;
tern_node * head = NULL;
@@ -88,6 +89,80 @@ tern_node *parse_config(char * config_data)
return parse_config_int(&config_data, 0, &line);
}
+typedef struct {
+ char *buf;
+ uint32_t capacity;
+ uint32_t size;
+ uint32_t indent;
+} serialize_state;
+
+static void ensure_buf_capacity(uint32_t ensure, serialize_state *state)
+{
+ if (ensure + state->size > state->capacity) {
+ state->capacity = state->capacity * 2;
+ state->buf = realloc(state->buf, state->capacity);
+ }
+}
+
+static void indent(serialize_state *state)
+{
+ memset(state->buf + state->size, '\t', state->indent);
+ state->size += state->indent;
+}
+
+static void serialize_config_int(tern_node *config, serialize_state *state);
+
+static void serialize_iter(char *key, tern_val val, uint8_t valtype, void *data)
+{
+ serialize_state *state = data;
+ uint32_t keylen = strlen(key);
+ uint32_t vallen = 0;
+ if (valtype == TVAL_PTR) {
+ vallen = strlen(val.ptrval);
+ }
+ ensure_buf_capacity(state->indent + keylen + 2 + vallen, state);
+ state->buf[state->size++] = '\n';
+ indent(state);
+ memcpy(state->buf + state->size, key, keylen);
+ state->size += keylen;
+ state->buf[state->size++] = ' ';
+ if (valtype == TVAL_PTR) {
+ memcpy(state->buf + state->size, val.ptrval, vallen);
+ state->size += vallen;
+ } else {
+ serialize_config_int(val.ptrval, state);
+ }
+}
+
+static void serialize_config_int(tern_node *config, serialize_state *state)
+{
+ ensure_buf_capacity(1, state);
+ state->buf[state->size++] = '{';
+ state->indent++;
+
+ tern_foreach(config, serialize_iter, state);
+
+ --state->indent;
+ ensure_buf_capacity(2 + state->indent, state);
+ state->buf[state->size++] = '\n';
+ indent(state);
+ state->buf[state->size++] = '}';
+}
+
+char *serialize_config(tern_node *config, uint32_t *size_out)
+{
+ serialize_state state = {
+ .size = 0,
+ .capacity = 1024,
+ .indent = 0
+ };
+ state.buf = malloc(state.capacity);
+ tern_foreach(config, serialize_iter, &state);
+ //serialize_config_int(config, &state);
+ *size_out = state.size;
+ return state.buf;
+}
+
tern_node *parse_config_file(char *config_path)
{
tern_node * ret = NULL;
@@ -114,6 +189,19 @@ open_fail:
return ret;
}
+uint8_t serialize_config_file(tern_node *config, char *path)
+{
+ FILE *f = fopen(path, "w");
+ if (!f) {
+ return 0;
+ }
+ uint32_t buf_size;
+ char *buffer = serialize_config(config, &buf_size);
+ uint8_t ret = buf_size == fwrite(buffer, 1, buf_size, f);
+ fclose(f);
+ return ret;
+}
+
tern_node *parse_bundled_config(char *config_name)
{
uint32_t confsize;
@@ -133,7 +221,7 @@ tern_node *load_config()
char *confpath = NULL;
tern_node *ret;
if (confdir) {
- confpath = alloc_concat(confdir, "/blastem.cfg");
+ confpath = path_append(confdir, "blastem.cfg");
ret = parse_config_file(confpath);
if (ret) {
free(confpath);
@@ -156,6 +244,19 @@ tern_node *load_config()
return NULL;
}
+void persist_config(tern_node *config)
+{
+ char const *confdir = get_config_dir();
+ if (!confdir) {
+ fatal_error("Failed to locate config file directory\n");
+ }
+ char *confpath = path_append(confdir, "blastem.cfg");
+ if (!serialize_config_file(config, confpath)) {
+ fatal_error("Failed to write config to %s\n", confpath);
+ }
+ free(confpath);
+}
+
char **get_extension_list(tern_node *config, uint32_t *num_exts_out)
{
char *ext_filter = strdup(tern_find_path_default(config, "ui\0extensions\0", (tern_val){.ptrval = "bin gen md smd sms gg"}, TVAL_PTR).ptrval);
diff --git a/config.h b/config.h
index 9224606..5122577 100644
--- a/config.h
+++ b/config.h
@@ -10,6 +10,9 @@
tern_node *parse_config_file(char *config_path);
tern_node *parse_bundled_config(char *config_name);
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(tern_node *config);
char **get_extension_list(tern_node *config, uint32_t *num_exts_out);
#endif //CONFIG_H_
diff --git a/paths.c b/paths.c
index 9f7afbd..6f1cd5b 100644
--- a/paths.c
+++ b/paths.c
@@ -102,7 +102,7 @@ void get_initial_browse_path(char **dst)
tern_free(vars);
}
-char *path_append(char *base, char *suffix)
+char *path_append(const char *base, const char *suffix)
{
if (!strcmp(suffix, "..")) {
#ifdef _WIN32
diff --git a/paths.h b/paths.h
index da4b424..b084035 100644
--- a/paths.h
+++ b/paths.h
@@ -2,6 +2,6 @@
#define PATHS_H_
void get_initial_browse_path(char **dst);
-char *path_append(char *base, char *suffix);
+char *path_append(const char *base, const char *suffix);
#endif //PATHS_H_ \ No newline at end of file