Mercurial > repos > blastem
diff config.c @ 1648:b7ecd0d6a77b mame_interp
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 25 Dec 2018 11:12:26 -0800 |
parents | 1fc61c844ec5 |
children | ba3fb7a3be6b |
line wrap: on
line diff
--- a/config.c Sun Dec 31 10:11:16 2017 -0800 +++ b/config.c Tue Dec 25 11:12:26 2018 -0800 @@ -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 @@ } #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 @@ 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,20 @@ 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); + free(buffer); + fclose(f); + return ret; +} + tern_node *parse_bundled_config(char *config_name) { uint32_t confsize; @@ -127,13 +216,35 @@ return ret; } -tern_node *load_config() +tern_node *load_overrideable_config(char *name, char *bundled_name) { char const *confdir = get_config_dir(); char *confpath = NULL; tern_node *ret; if (confdir) { - confpath = alloc_concat(confdir, "/blastem.cfg"); + confpath = path_append(confdir, name); + ret = parse_config_file(confpath); + if (ret) { + free(confpath); + return ret; + } + } + + ret = parse_bundled_config(bundled_name); + if (ret) { + free(confpath); + return ret; + } + return NULL; +} + +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); @@ -147,11 +258,56 @@ return ret; } - if (confpath) { - fatal_error("Failed to find a config file at %s or in the blastem executable directory\n", confpath); + 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; } + +void persist_config_at(tern_node *config, char *fname) +{ + char const *confdir = get_config_dir(); + if (!confdir) { + fatal_error("Failed to locate config file directory\n"); + } + ensure_dir_exists(confdir); + char *confpath = path_append(confdir, fname); + if (!serialize_config_file(config, confpath)) { + fatal_error("Failed to write config to %s\n", confpath); + } + free(confpath); +} + +void persist_config(tern_node *config) +{ + persist_config_at(config, "blastem.cfg"); +} + +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); + uint32_t num_exts = 0, ext_storage = 5; + char **ext_list = malloc(sizeof(char *) * ext_storage); + char *cur_filter = ext_filter; + while (*cur_filter) + { + if (num_exts == ext_storage) { + ext_storage *= 2; + ext_list = realloc(ext_list, sizeof(char *) * ext_storage); + } + ext_list[num_exts++] = cur_filter; + cur_filter = split_keyval(cur_filter); + } + *num_exts_out = num_exts; + return ext_list; +} + +#define DEFAULT_LOWPASS_CUTOFF 3390 +uint32_t get_lowpass_cutoff(tern_node *config) +{ + char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0", TVAL_PTR).ptrval; + return lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : DEFAULT_LOWPASS_CUTOFF; +}