summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blastem.c8
-rw-r--r--genesis.c10
-rw-r--r--io.c68
-rw-r--r--menu.c2
-rwxr-xr-xrender_sdl.c30
-rw-r--r--romdb.c40
-rw-r--r--sms.c2
-rw-r--r--tern.c63
-rw-r--r--tern.h20
9 files changed, 138 insertions, 105 deletions
diff --git a/blastem.c b/blastem.c
index 1b12ca4..da1149d 100644
--- a/blastem.c
+++ b/blastem.c
@@ -140,7 +140,7 @@ void update_title(char *rom_name)
void setup_saves(char *fname, rom_info *info, system_header *context)
{
static uint8_t persist_save_registered;
- char *savedir_template = tern_find_path(config, "ui\0save_path\0").ptrval;
+ char *savedir_template = tern_find_path(config, "ui\0save_path\0", TVAL_PTR).ptrval;
if (!savedir_template) {
savedir_template = "$USERDATA/blastem/$ROMNAME";
}
@@ -322,7 +322,7 @@ int main(int argc, char ** argv)
uint8_t menu = !loaded;
if (!loaded) {
//load menu
- romfname = tern_find_path(config, "ui\0rom\0").ptrval;
+ romfname = tern_find_path(config, "ui\0rom\0", TVAL_PTR).ptrval;
if (!romfname) {
romfname = "menu.bin";
}
@@ -349,7 +349,7 @@ int main(int argc, char ** argv)
}
int def_width = 0;
- char *config_width = tern_find_path(config, "video\0width\0").ptrval;
+ char *config_width = tern_find_path(config, "video\0width\0", TVAL_PTR).ptrval;
if (config_width) {
def_width = atoi(config_width);
}
@@ -359,7 +359,7 @@ int main(int argc, char ** argv)
width = width < 320 ? def_width : width;
height = height < 240 ? (width/320) * 240 : height;
- char *config_fullscreen = tern_find_path(config, "video\0fullscreen\0").ptrval;
+ char *config_fullscreen = tern_find_path(config, "video\0fullscreen\0", TVAL_PTR).ptrval;
if (config_fullscreen && !strcmp("on", config_fullscreen)) {
fullscreen = !fullscreen;
}
diff --git a/genesis.c b/genesis.c
index 1773f40..8c69117 100644
--- a/genesis.c
+++ b/genesis.c
@@ -822,7 +822,7 @@ static void set_speed_percent(system_header * system, uint32_t percent)
void set_region(genesis_context *gen, rom_info *info, uint8_t region)
{
if (!region) {
- char * def_region = tern_find_path_default(config, "system\0default_region\0", (tern_val){.ptrval = "U"}).ptrval;
+ char * def_region = tern_find_path_default(config, "system\0default_region\0", (tern_val){.ptrval = "U"}, TVAL_PTR).ptrval;
if (!info->regions || (info->regions & translate_region_char(toupper(*def_region)))) {
region = translate_region_char(toupper(*def_region));
} else {
@@ -1001,10 +1001,10 @@ genesis_context *alloc_init_genesis(rom_info *rom, void *main_rom, void *lock_on
init_vdp_context(gen->vdp, gen->version_reg & 0x40);
gen->vdp->system = &gen->header;
gen->frame_end = vdp_cycles_to_frame_end(gen->vdp);
- char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0").ptrval;
+ char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval;
gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL;
- char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0").ptrval;
+ char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0", TVAL_PTR).ptrval;
uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : DEFAULT_LOWPASS_CUTOFF;
gen->ym = malloc(sizeof(ym2612_context));
@@ -1032,7 +1032,7 @@ genesis_context *alloc_init_genesis(rom_info *rom, void *main_rom, void *lock_on
gen->cart = main_rom;
gen->lock_on = lock_on;
gen->work_ram = calloc(2, RAM_WORDS);
- if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}).ptrval))
+ if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval))
{
srand(time(NULL));
for (int i = 0; i < RAM_WORDS; i++)
@@ -1124,7 +1124,7 @@ genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_o
byteswap_rom(lock_on_size, lock_on);
}
#endif
- char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0").ptrval;
+ char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0", TVAL_PTR).ptrval;
if (!m68k_divider) {
m68k_divider = "7";
}
diff --git a/io.c b/io.c
index d60a587..3769ac8 100644
--- a/io.c
+++ b/io.c
@@ -494,7 +494,7 @@ void handle_binding_up(keybinding * binding)
current_system->soft_reset(current_system);
break;
case UI_SCREENSHOT: {
- char *screenshot_base = tern_find_path(config, "ui\0screenshot_path\0").ptrval;
+ char *screenshot_base = tern_find_path(config, "ui\0screenshot_path\0", TVAL_PTR).ptrval;
if (!screenshot_base) {
screenshot_base = "$HOME";
}
@@ -505,7 +505,7 @@ void handle_binding_up(keybinding * binding)
time_t now = time(NULL);
struct tm local_store;
char fname_part[256];
- char *template = tern_find_path(config, "ui\0screenshot_template\0").ptrval;
+ char *template = tern_find_path(config, "ui\0screenshot_template\0", TVAL_PTR).ptrval;
if (!template) {
template = "blastem_%c.ppm";
}
@@ -876,10 +876,10 @@ void setup_io_devices(tern_node * config, rom_info *rom, sega_io *io)
{
current_io = io;
io_port * ports = current_io->ports;
- tern_node *io_nodes = tern_get_node(tern_find_path(config, "io\0devices\0"));
- char * io_1 = rom->port1_override ? rom->port1_override : tern_find_ptr(io_nodes, "1");
- char * io_2 = rom->port2_override ? rom->port2_override : tern_find_ptr(io_nodes, "2");
- char * io_ext = rom->ext_override ? rom->ext_override : tern_find_ptr(io_nodes, "ext");
+ tern_node *io_nodes = tern_find_path(config, "io\0devices\0", TVAL_NODE).ptrval;
+ char * io_1 = rom->port1_override ? rom->port1_override : io_nodes ? tern_find_ptr(io_nodes, "1") : NULL;
+ char * io_2 = rom->port2_override ? rom->port2_override : io_nodes ? tern_find_ptr(io_nodes, "2") : NULL;
+ char * io_ext = rom->ext_override ? rom->ext_override : io_nodes ? tern_find_ptr(io_nodes, "ext") : NULL;
process_device(io_1, ports);
process_device(io_2, ports+1);
@@ -901,7 +901,7 @@ void setup_io_devices(tern_node * config, rom_info *rom, sega_io *io)
#ifndef _WIN32
if (ports[i].device_type == IO_SEGA_PARALLEL)
{
- char *pipe_name = tern_find_path(config, "io\0parallel_pipe\0").ptrval;
+ char *pipe_name = tern_find_path(config, "io\0parallel_pipe\0", TVAL_PTR).ptrval;
if (!pipe_name)
{
warning("IO port %s is configured to use the sega parallel board, but no paralell_pipe is set!\n", io_name(i));
@@ -927,7 +927,7 @@ void setup_io_devices(tern_node * config, rom_info *rom, sega_io *io)
}
}
} else if (ports[i].device_type == IO_GENERIC) {
- char *sock_name = tern_find_path(config, "io\0socket\0").ptrval;
+ char *sock_name = tern_find_path(config, "io\0socket\0", TVAL_PTR).ptrval;
if (!sock_name)
{
warning("IO port %s is configured to use generic IO, but no socket is set!\n", io_name(i));
@@ -1013,7 +1013,7 @@ typedef struct {
int mouseidx;
} pmb_state;
-void process_mouse_button(char *buttonstr, tern_val value, void *data)
+void process_mouse_button(char *buttonstr, tern_val value, uint8_t valtype, void *data)
{
pmb_state *state = data;
int buttonnum = atoi(buttonstr);
@@ -1021,6 +1021,10 @@ void process_mouse_button(char *buttonstr, tern_val value, void *data)
warning("Mouse button %s is out of the supported range of 1-8\n", buttonstr);
return;
}
+ if (valtype != TVAL_PTR) {
+ warning("Mouse button %s is not a scalar value!\n", buttonstr);
+ return;
+ }
buttonnum--;
int ui_func, devicenum, button;
int bindtype = parse_binding_target(value.ptrval, state->padbuttons, state->mousebuttons, &ui_func, &devicenum, &button);
@@ -1045,17 +1049,17 @@ void process_mouse_button(char *buttonstr, tern_val value, void *data)
}
-void process_mouse(char *mousenum, tern_val value, void *data)
+void process_mouse(char *mousenum, tern_val value, uint8_t valtype, void *data)
{
tern_node **buttonmaps = data;
- tern_node *mousedef = tern_get_node(value);
- tern_node *padbuttons = buttonmaps[0];
- tern_node *mousebuttons = buttonmaps[1];
-
- if (!mousedef) {
+ if (valtype != TVAL_NODE) {
warning("Binding for mouse %s is a scalar!\n", mousenum);
return;
}
+ tern_node *mousedef = value.ptrval;
+ tern_node *padbuttons = buttonmaps[0];
+ tern_node *mousebuttons = buttonmaps[1];
+
int mouseidx = atoi(mousenum);
if (mouseidx < 0 || mouseidx >= MAX_MICE) {
warning("Mouse numbers must be between 0 and %d, but %d is not\n", MAX_MICE, mouseidx);
@@ -1074,7 +1078,7 @@ void process_mouse(char *mousenum, tern_val value, void *data)
warning("Mouse motion can't be bound to target %s\n", motion);
}
}
- tern_node *buttons = tern_get_node(tern_find_path(mousedef, "buttons\0\0"));
+ tern_node *buttons = tern_find_path(mousedef, "buttons\0\0", TVAL_NODE).ptrval;
if (buttons) {
pmb_state state = {padbuttons, mousebuttons, mouseidx};
tern_foreach(buttons, process_mouse_button, &state);
@@ -1087,11 +1091,15 @@ typedef struct {
tern_node *mousebuttons;
} pad_button_state;
-void process_pad_button(char *key, tern_val val, void *data)
+void process_pad_button(char *key, tern_val val, uint8_t valtype, void *data)
{
pad_button_state *state = data;
int hostpadnum = state->padnum;
int ui_func, padnum, button;
+ if (valtype != TVAL_PTR) {
+ warning("Pad button %s has a non-scalar value\n", key);
+ return;
+ }
int bindtype = parse_binding_target(val.ptrval, state->padbuttons, state->mousebuttons, &ui_func, &padnum, &button);
char *end;
long hostbutton = strtol(key, &end, 10);
@@ -1129,12 +1137,16 @@ void process_pad_button(char *key, tern_val val, void *data)
}
}
-void process_pad_axis(char *key, tern_val val, void *data)
+void process_pad_axis(char *key, tern_val val, uint8_t valtype, void *data)
{
key = strdup(key);
pad_button_state *state = data;
int hostpadnum = state->padnum;
int ui_func, padnum, button;
+ if (valtype != TVAL_PTR) {
+ warning("Mapping for axis %s has a non-scalar value", key);
+ return;
+ }
int bindtype = parse_binding_target(val.ptrval, state->padbuttons, state->mousebuttons, &ui_func, &padnum, &button);
char *modifier = strchr(key, '.');
int positive = 1;
@@ -1226,19 +1238,19 @@ void handle_joy_added(int joystick)
if (joystick > MAX_JOYSTICKS) {
return;
}
- tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0"));
+ tern_node * pads = tern_find_path(config, "bindings\0pads\0", TVAL_NODE).ptrval;
if (pads) {
char numstr[11];
sprintf(numstr, "%d", joystick);
- tern_node * pad = tern_find_ptr(pads, numstr);
+ tern_node * pad = tern_find_node(pads, numstr);
if (pad) {
- tern_node * dpad_node = tern_find_ptr(pad, "dpads");
+ tern_node * dpad_node = tern_find_node(pad, "dpads");
if (dpad_node) {
for (int dpad = 0; dpad < 10; dpad++)
{
numstr[0] = dpad + '0';
numstr[1] = 0;
- tern_node * pad_dpad = tern_find_ptr(dpad_node, numstr);
+ tern_node * pad_dpad = tern_find_node(dpad_node, numstr);
char * dirs[] = {"up", "down", "left", "right"};
int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) {
@@ -1255,7 +1267,7 @@ void handle_joy_added(int joystick)
}
}
}
- tern_node *button_node = tern_find_ptr(pad, "buttons");
+ tern_node *button_node = tern_find_node(pad, "buttons");
if (button_node) {
pad_button_state state = {
.padnum = joystick,
@@ -1264,7 +1276,7 @@ void handle_joy_added(int joystick)
};
tern_foreach(button_node, process_pad_button, &state);
}
- tern_node *axes_node = tern_find_ptr(pad, "axes");
+ tern_node *axes_node = tern_find_node(pad, "axes");
if (axes_node) {
pad_button_state state = {
.padnum = joystick,
@@ -1347,10 +1359,10 @@ void set_keybindings(sega_io *io)
tern_node *mousebuttons = get_mouse_buttons();
- tern_node * keys = tern_get_node(tern_find_path(config, "bindings\0keys\0"));
+ tern_node * keys = tern_find_path(config, "bindings\0keys\0", TVAL_NODE).ptrval;
process_keys(keys, special, padbuttons, mousebuttons, NULL);
char numstr[] = "00";
- tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0"));
+ tern_node * pads = tern_find_path(config, "bindings\0pads\0", TVAL_NODE).ptrval;
if (pads) {
for (int i = 0; i < MAX_JOYSTICKS; i++)
{
@@ -1366,12 +1378,12 @@ void set_keybindings(sega_io *io)
}
}
memset(mice, 0, sizeof(mice));
- tern_node * mice = tern_get_node(tern_find_path(config, "bindings\0mice\0"));
+ tern_node * mice = tern_find_path(config, "bindings\0mice\0", TVAL_NODE).ptrval;
if (mice) {
tern_node *buttonmaps[2] = {padbuttons, mousebuttons};
tern_foreach(mice, process_mouse, buttonmaps);
}
- tern_node * speed_nodes = tern_get_node(tern_find_path(config, "clocks\0speeds\0"));
+ tern_node * speed_nodes = tern_find_path(config, "clocks\0speeds\0", TVAL_NODE).ptrval;
speeds = malloc(sizeof(uint32_t));
speeds[0] = 100;
process_speeds(speed_nodes, NULL);
diff --git a/menu.c b/menu.c
index cd5cf0c..97eba82 100644
--- a/menu.c
+++ b/menu.c
@@ -166,7 +166,7 @@ void * menu_write_w(uint32_t address, void * context, uint16_t value)
menu_context *menu = gen->extra;
if (!menu) {
gen->extra = menu = calloc(1, sizeof(menu_context));
- menu->curpath = tern_find_path(config, "ui\0initial_path\0").ptrval;
+ menu->curpath = tern_find_path(config, "ui\0initial_path\0", TVAL_PTR).ptrval;
if (!menu->curpath){
#ifdef __ANDROID__
menu->curpath = get_external_storage_path();
diff --git a/render_sdl.c b/render_sdl.c
index c69d1ec..5e4d4c7 100755
--- a/render_sdl.c
+++ b/render_sdl.c
@@ -217,9 +217,9 @@ static void gl_setup()
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW);
tern_val def = {.ptrval = "default.v.glsl"};
- vshader = load_shader(tern_find_path_default(config, "video\0vertex_shader\0", def).ptrval, GL_VERTEX_SHADER);
+ vshader = load_shader(tern_find_path_default(config, "video\0vertex_shader\0", def, TVAL_PTR).ptrval, GL_VERTEX_SHADER);
def.ptrval = "default.f.glsl";
- fshader = load_shader(tern_find_path_default(config, "video\0fragment_shader\0", def).ptrval, GL_FRAGMENT_SHADER);
+ fshader = load_shader(tern_find_path_default(config, "video\0fragment_shader\0", def, TVAL_PTR).ptrval, GL_FRAGMENT_SHADER);
program = glCreateProgram();
glAttachShader(program, vshader);
glAttachShader(program, fshader);
@@ -284,7 +284,7 @@ static void update_aspect()
main_clip.h = main_height;
main_clip.x = main_clip.y = 0;
//calculate configured aspect ratio
- char *config_aspect = tern_find_path_default(config, "video\0aspect\0", (tern_val){.ptrval = "4:3"}).ptrval;
+ char *config_aspect = tern_find_path_default(config, "video\0aspect\0", (tern_val){.ptrval = "4:3"}, TVAL_PTR).ptrval;
if (strcmp("stretch", config_aspect)) {
float src_aspect = 4.0f/3.0f;
char *end;
@@ -356,32 +356,28 @@ void render_init(int width, int height, char * title, uint8_t fullscreen)
render_gl = 0;
tern_val def = {.ptrval = "off"};
- char *vsync = tern_find_path_default(config, "video\0vsync\0", def).ptrval;
+ char *vsync = tern_find_path_default(config, "video\0vsync\0", def, TVAL_PTR).ptrval;
- tern_val video_node = {.ptrval = NULL};
- tern_find(config, "video", &video_node);
- tern_node *video = tern_get_node(video_node);
+ tern_node *video = tern_find_node(config, "video");
if (video)
{
for (int i = 0; i < NUM_VID_STD; i++)
{
- video_node.ptrval = NULL;
- tern_find(video, vid_std_names[i], &video_node);
- tern_node *std_settings = tern_get_node(video_node);
+ tern_node *std_settings = tern_find_node(video, vid_std_names[i]);
if (std_settings) {
- char *val = tern_find_path_default(std_settings, "overscan\0top\0", (tern_val){.ptrval = NULL}).ptrval;
+ char *val = tern_find_path_default(std_settings, "overscan\0top\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
if (val) {
overscan_top[i] = atoi(val);
}
- val = tern_find_path_default(std_settings, "overscan\0bottom\0", (tern_val){.ptrval = NULL}).ptrval;
+ val = tern_find_path_default(std_settings, "overscan\0bottom\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
if (val) {
overscan_bot[i] = atoi(val);
}
- val = tern_find_path_default(std_settings, "overscan\0left\0", (tern_val){.ptrval = NULL}).ptrval;
+ val = tern_find_path_default(std_settings, "overscan\0left\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
if (val) {
overscan_left[i] = atoi(val);
}
- val = tern_find_path_default(std_settings, "overscan\0right\0", (tern_val){.ptrval = NULL}).ptrval;
+ val = tern_find_path_default(std_settings, "overscan\0right\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
if (val) {
overscan_right[i] = atoi(val);
}
@@ -447,7 +443,7 @@ void render_init(int width, int height, char * title, uint8_t fullscreen)
update_aspect();
render_alloc_surfaces();
def.ptrval = "off";
- scanlines = !strcmp(tern_find_path_default(config, "video\0scanlines\0", def).ptrval, "on");
+ scanlines = !strcmp(tern_find_path_default(config, "video\0scanlines\0", def, TVAL_PTR).ptrval, "on");
caption = title;
@@ -457,7 +453,7 @@ void render_init(int width, int height, char * title, uint8_t fullscreen)
audio_ready = SDL_CreateCond();
SDL_AudioSpec desired, actual;
- char * rate_str = tern_find_path(config, "audio\0rate\0").ptrval;
+ char * rate_str = tern_find_path(config, "audio\0rate\0", TVAL_PTR).ptrval;
int rate = rate_str ? atoi(rate_str) : 0;
if (!rate) {
rate = 48000;
@@ -465,7 +461,7 @@ void render_init(int width, int height, char * title, uint8_t fullscreen)
desired.freq = rate;
desired.format = AUDIO_S16SYS;
desired.channels = 2;
- char * samples_str = tern_find_path(config, "audio\0buffer\0").ptrval;
+ char * samples_str = tern_find_path(config, "audio\0buffer\0", TVAL_PTR).ptrval;
int samples = samples_str ? atoi(samples_str) : 0;
if (!samples) {
samples = 512;
diff --git a/romdb.c b/romdb.c
index c603521..ea23a2c 100644
--- a/romdb.c
+++ b/romdb.c
@@ -643,13 +643,17 @@ typedef struct {
uint16_t ptr_index;
} map_iter_state;
-void eeprom_read_fun(char *key, tern_val val, void *data)
+void eeprom_read_fun(char *key, tern_val val, uint8_t valtype, void *data)
{
int bit = atoi(key);
if (bit < 0 || bit > 15) {
fprintf(stderr, "bit %s is out of range", key);
return;
}
+ if (valtype != TVAL_PTR) {
+ fprintf(stderr, "bit %s has a non-scalar value", key);
+ return;
+ }
char *pin = val.ptrval;
if (strcmp(pin, "sda")) {
fprintf(stderr, "bit %s is connected to unrecognized read pin %s", key, pin);
@@ -659,13 +663,17 @@ void eeprom_read_fun(char *key, tern_val val, void *data)
map->sda_read_bit = bit;
}
-void eeprom_write_fun(char *key, tern_val val, void *data)
+void eeprom_write_fun(char *key, tern_val val, uint8_t valtype, void *data)
{
int bit = atoi(key);
if (bit < 0 || bit > 15) {
fprintf(stderr, "bit %s is out of range", key);
return;
}
+ if (valtype != TVAL_PTR) {
+ fprintf(stderr, "bit %s has a non-scalar value", key);
+ return;
+ }
char *pin = val.ptrval;
eeprom_map *map = data;
if (!strcmp(pin, "sda")) {
@@ -682,7 +690,7 @@ void eeprom_write_fun(char *key, tern_val val, void *data)
void process_sram_def(char *key, map_iter_state *state)
{
if (!state->info->save_size) {
- char * size = tern_find_path(state->root, "SRAM\0size\0").ptrval;
+ char * size = tern_find_path(state->root, "SRAM\0size\0", TVAL_PTR).ptrval;
if (!size) {
fatal_error("ROM DB map entry %d with address %s has device type SRAM, but the SRAM size is not defined\n", state->index, key);
}
@@ -693,7 +701,7 @@ void process_sram_def(char *key, map_iter_state *state)
state->info->save_mask = nearest_pow2(state->info->save_size)-1;
state->info->save_buffer = malloc(state->info->save_size);
memset(state->info->save_buffer, 0, state->info->save_size);
- char *bus = tern_find_path(state->root, "SRAM\0bus\0").ptrval;
+ char *bus = tern_find_path(state->root, "SRAM\0bus\0", TVAL_PTR).ptrval;
if (!strcmp(bus, "odd")) {
state->info->save_type = RAM_FLAG_ODD;
} else if(!strcmp(bus, "even")) {
@@ -707,7 +715,7 @@ void process_sram_def(char *key, map_iter_state *state)
void process_eeprom_def(char * key, map_iter_state *state)
{
if (!state->info->save_size) {
- char * size = tern_find_path(state->root, "EEPROM\0size\0").ptrval;
+ char * size = tern_find_path(state->root, "EEPROM\0size\0", TVAL_PTR).ptrval;
if (!size) {
fatal_error("ROM DB map entry %d with address %s has device type EEPROM, but the EEPROM size is not defined\n", state->index, key);
}
@@ -715,7 +723,7 @@ void process_eeprom_def(char * key, map_iter_state *state)
if (!state->info->save_size) {
fatal_error("EEPROM size %s is invalid\n", size);
}
- char *etype = tern_find_path(state->root, "EEPROM\0type\0").ptrval;
+ char *etype = tern_find_path(state->root, "EEPROM\0type\0", TVAL_PTR).ptrval;
if (!etype) {
etype = "i2c";
}
@@ -737,11 +745,11 @@ void add_eeprom_map(tern_node *node, uint32_t start, uint32_t end, map_iter_stat
eep_map->start = start;
eep_map->end = end;
eep_map->sda_read_bit = 0xFF;
- tern_node * bits_read = tern_find_ptr(node, "bits_read");
+ tern_node * bits_read = tern_find_node(node, "bits_read");
if (bits_read) {
tern_foreach(bits_read, eeprom_read_fun, eep_map);
}
- tern_node * bits_write = tern_find_ptr(node, "bits_write");
+ tern_node * bits_write = tern_find_node(node, "bits_write");
if (bits_write) {
tern_foreach(bits_write, eeprom_write_fun, eep_map);
}
@@ -749,13 +757,13 @@ void add_eeprom_map(tern_node *node, uint32_t start, uint32_t end, map_iter_stat
state->info->num_eeprom++;
}
-void map_iter_fun(char *key, tern_val val, void *data)
+void map_iter_fun(char *key, tern_val val, uint8_t valtype, void *data)
{
map_iter_state *state = data;
- tern_node *node = tern_get_node(val);
- if (!node) {
+ if (valtype != TVAL_NODE) {
fatal_error("ROM DB map entry %d with address %s is not a node\n", state->index, key);
}
+ tern_node *node = val.ptrval;
uint32_t start = strtol(key, NULL, 16);
uint32_t end = strtol(tern_find_ptr_default(node, "last", "0"), NULL, 16);
if (!end || end < start) {
@@ -819,7 +827,7 @@ void map_iter_fun(char *key, tern_val val, void *data)
state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
memset(state->info->map + state->info->map_chunks - 7, 0, sizeof(memmap_chunk) * 7);
map = state->info->map + state->index;
- char *save_device = tern_find_path(node, "save\0device\0").ptrval;
+ char *save_device = tern_find_path(node, "save\0device\0", TVAL_PTR).ptrval;
if (save_device && !strcmp(save_device, "EEPROM")) {
process_eeprom_def(key, state);
add_eeprom_map(node, start & map->mask, end & map->mask, state);
@@ -892,9 +900,9 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *l
uint8_t hex_hash[41];
bin_to_hex(hex_hash, raw_hash, 20);
printf("SHA1: %s\n", hex_hash);
- tern_node * entry = tern_find_ptr(rom_db, hex_hash);
+ tern_node * entry = tern_find_node(rom_db, hex_hash);
if (!entry) {
- entry = tern_find_ptr(rom_db, product_id);
+ entry = tern_find_node(rom_db, product_id);
}
if (!entry) {
puts("Not found in ROM DB, examining header\n");
@@ -927,7 +935,7 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *l
info.regions = get_header_regions(rom);
}
- tern_node *map = tern_find_ptr(entry, "map");
+ tern_node *map = tern_find_node(entry, "map");
if (map) {
info.save_type = SAVE_NONE;
info.map_chunks = tern_count(map);
@@ -959,7 +967,7 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *l
add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
}
- tern_node *device_overrides = tern_find_ptr(entry, "device_overrides");
+ tern_node *device_overrides = tern_find_node(entry, "device_overrides");
if (device_overrides) {
info.port1_override = tern_find_ptr(device_overrides, "1");
info.port2_override = tern_find_ptr(device_overrides, "2");
diff --git a/sms.c b/sms.c
index 0ccac57..6993095 100644
--- a/sms.c
+++ b/sms.c
@@ -324,7 +324,7 @@ sms_context *alloc_configure_sms(system_media *media, uint32_t opts, uint8_t for
sms->bank_regs[3] = 0x8000 >> 14;
}
- char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0").ptrval;
+ char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0", TVAL_PTR).ptrval;
uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : 3390;
//TODO: Detect region and pick master clock based off of that
diff --git a/tern.c b/tern.c
index 2036b64..7b4cb5f 100644
--- a/tern.c
+++ b/tern.c
@@ -10,7 +10,7 @@
#include <stdio.h>
#include "util.h"
-tern_node * tern_insert(tern_node * head, char const * key, tern_val value)
+tern_node * tern_insert(tern_node * head, char const * key, tern_val value, uint8_t valtype)
{
tern_node ** cur = &head;
while(*key)
@@ -31,6 +31,7 @@ tern_node * tern_insert(tern_node * head, char const * key, tern_val value)
(*cur)->right = NULL;
(*cur)->straight.next = NULL;
(*cur)->el = *key;
+ (*cur)->valtype = TVAL_NONE;
}
cur = &((*cur)->straight.next);
key++;
@@ -46,10 +47,11 @@ tern_node * tern_insert(tern_node * head, char const * key, tern_val value)
(*cur)->el = 0;
}
(*cur)->straight.value = value;
+ (*cur)->valtype = valtype;
return head;
}
-int tern_find(tern_node * head, char const * key, tern_val *ret)
+uint8_t tern_find(tern_node * head, char const * key, tern_val *ret)
{
tern_node * cur = head;
while (cur)
@@ -60,7 +62,7 @@ int tern_find(tern_node * head, char const * key, tern_val *ret)
key++;
} else {
*ret = cur->straight.value;
- return 1;
+ return cur->valtype;
}
} else if (*key < cur->el) {
cur = cur->left;
@@ -68,7 +70,7 @@ int tern_find(tern_node * head, char const * key, tern_val *ret)
cur = cur->right;
}
}
- return 0;
+ return TVAL_NONE;
}
tern_node * tern_find_prefix(tern_node * head, char const * key)
@@ -91,7 +93,8 @@ tern_node * tern_find_prefix(tern_node * head, char const * key)
intptr_t tern_find_int(tern_node * head, char const * key, intptr_t def)
{
tern_val ret;
- if (tern_find(head, key, &ret)) {
+ uint8_t valtype = tern_find(head, key, &ret);
+ if (valtype == TVAL_INT) {
return ret.intval;
}
return def;
@@ -101,18 +104,15 @@ tern_node * tern_insert_int(tern_node * head, char const * key, intptr_t value)
{
tern_val val;
val.intval = value;
- return tern_insert(head, key, val);
+ return tern_insert(head, key, val, TVAL_INT);
}
void * tern_find_ptr_default(tern_node * head, char const * key, void * def)
{
tern_val ret;
- if (tern_find(head, key, &ret)) {
- if (ret.intval & 1) {
- return (void *)(ret.intval & ~1);
- } else {
- return ret.ptrval;
- }
+ uint8_t valtype = tern_find(head, key, &ret);
+ if (valtype == TVAL_PTR) {
+ return ret.ptrval;
}
return def;
}
@@ -122,44 +122,57 @@ void * tern_find_ptr(tern_node * head, char const * key)
return tern_find_ptr_default(head, key, NULL);
}
-tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def)
+tern_node *tern_find_node(tern_node *head, char const *key)
+{
+ tern_val ret;
+ uint8_t valtype = tern_find(head, key, &ret);
+ if (valtype == TVAL_NODE) {
+ return ret.ptrval;
+ }
+ return NULL;
+}
+
+tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def, uint8_t req_valtype)
{
tern_val ret;
while (*key)
{
- if (!tern_find(head, key, &ret)) {
+ uint8_t valtype = tern_find(head, key, &ret);
+ if (!valtype) {
return def;
}
key = key + strlen(key) + 1;
if (*key) {
- head = tern_get_node(ret);
- if (!head) {
+ if (valtype != TVAL_NODE) {
return def;
}
+ head = ret.ptrval;
+ } else if (req_valtype && req_valtype != valtype) {
+ return def;
}
}
return ret;
}
-tern_val tern_find_path(tern_node *head, char const *key)
+tern_val tern_find_path(tern_node *head, char const *key, uint8_t valtype)
{
tern_val def;
def.ptrval = NULL;
- return tern_find_path_default(head, key, def);
+ return tern_find_path_default(head, key, def, valtype);
}
tern_node * tern_insert_ptr(tern_node * head, char const * key, void * value)
{
tern_val val;
val.ptrval = value;
- return tern_insert(head, key, val);
+ return tern_insert(head, key, val, TVAL_PTR);
}
tern_node * tern_insert_node(tern_node *head, char const *key, tern_node *value)
{
tern_val val;
- val.intval = ((intptr_t)value) | 1;
- return tern_insert(head, key, val);
+ val.ptrval = value;
+ return tern_insert(head, key, val, TVAL_NODE);
}
uint32_t tern_count(tern_node *head)
@@ -184,7 +197,7 @@ void tern_foreach_int(tern_node *head, iter_fun fun, void *data, char *keybuf, i
{
if (!head->el) {
keybuf[pos] = 0;
- fun(keybuf, head->straight.value, data);
+ fun(keybuf, head->straight.value, head->valtype, data);
}
if (head->left) {
tern_foreach_int(head->left, fun, data, keybuf, pos);
@@ -220,11 +233,6 @@ char * tern_int_key(uint32_t key, char * buf)
return buf;
}
-tern_node * tern_get_node(tern_val value)
-{
- return value.intval & 1 ? (tern_node *)(value.intval & ~1) : NULL;
-}
-
void tern_free(tern_node *head)
{
if (head->left) {
@@ -236,4 +244,5 @@ void tern_free(tern_node *head)
if (head->el) {
tern_free(head->straight.next);
}
+ free(head);
}
diff --git a/tern.h b/tern.h
index e3a2db6..57c62ff 100644
--- a/tern.h
+++ b/tern.h
@@ -23,25 +23,33 @@ typedef struct tern_node {
} straight;
struct tern_node *right;
char el;
+ uint8_t valtype;
} tern_node;
-typedef void (*iter_fun)(char *key, tern_val val, void *data);
+enum {
+ TVAL_NONE=0,
+ TVAL_INT,
+ TVAL_PTR,
+ TVAL_NODE
+};
-tern_node * tern_insert(tern_node * head, char const * key, tern_val value);
-int tern_find(tern_node * head, char const * key, tern_val *ret);
+typedef void (*iter_fun)(char *key, tern_val val, uint8_t valtype, void *data);
+
+tern_node * tern_insert(tern_node * head, char const * key, tern_val value, uint8_t valtype);
+uint8_t tern_find(tern_node * head, char const * key, tern_val *ret);
tern_node * tern_find_prefix(tern_node * head, char const * key);
intptr_t tern_find_int(tern_node * head, char const * key, intptr_t def);
tern_node * tern_insert_int(tern_node * head, char const * key, intptr_t value);
void * tern_find_ptr_default(tern_node * head, char const * key, void * def);
void * tern_find_ptr(tern_node * head, char const * key);
-tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def);
-tern_val tern_find_path(tern_node *head, char const *key);
+tern_node *tern_find_node(tern_node *head, char const *key);
+tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def, uint8_t req_valtype);
+tern_val tern_find_path(tern_node *head, char const *key, uint8_t valtype);
tern_node * tern_insert_ptr(tern_node * head, char const * key, void * value);
tern_node * tern_insert_node(tern_node *head, char const *key, tern_node *value);
uint32_t tern_count(tern_node *head);
void tern_foreach(tern_node *head, iter_fun fun, void *data);
char * tern_int_key(uint32_t key, char * buf);
-tern_node * tern_get_node(tern_val value);
void tern_free(tern_node *head);
#endif //TERN_H_