From 122bf9de037f578cc4862b1dc775b6589d56057d Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Wed, 10 Jul 2013 22:48:17 -0700 Subject: Read key bindings from config file --- io.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 15 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index c951739..9fc3ad3 100644 --- a/io.c +++ b/io.c @@ -252,23 +252,93 @@ void handle_joy_dpad(int joystick, int dpadnum, uint8_t value) } } +void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, char * prefix) +{ + char * curstr; + int len; + if (!cur) { + return; + } + char onec[2]; + if (prefix) { + len = strlen(prefix); + curstr = malloc(len + 2); + memcpy(curstr, prefix, len); + } else { + curstr = onec; + len = 0; + } + curstr[len] = cur->el; + if (cur->el) { + curstr[len+1] = 0; + process_keys(cur->straight.next, special, padbuttons, curstr); + } else { + int keycode = tern_find_int(special, curstr, 0); + if (!keycode) { + keycode = curstr[0]; + if (curstr[1] != 0) { + fprintf(stderr, "%s is not recognized as a key identifier, truncating to %c\n", curstr, curstr[0]); + } + } + char * target = cur->straight.value.ptrval; + int gpadslen = strlen("gamepads."); + if (!memcmp(target, "gamepads.", gpadslen)) { + if (target[gpadslen] >= '1' && target[gpadslen] <= '8') { + int padnum = target[gpadslen] - '0'; + int button = tern_find_int(padbuttons, target + gpadslen + 1, 0); + if (button) { + bind_gamepad(keycode, padnum, button); + } else { + if (target[gpadslen+1]) { + fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid button '%s'\n", target, target + gpadslen + 1); + } else { + fprintf(stderr, "Gamepad mapping string '%s' has no button component\n", target); + } + } + } else { + fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]); + } + } else if(!memcmp(target, "ui.", strlen("ui."))) { + if (!strcmp(target + 3, "vdp_debug_mode")) { + bind_ui(keycode, UI_DEBUG_MODE_INC); + } else if(!strcmp(target + 3, "vdp_debug_pal")) { + bind_ui(keycode, UI_DEBUG_PAL_INC); + } else if(!strcmp(target + 3, "enter_debugger")) { + bind_ui(keycode, UI_ENTER_DEBUGGER); + } else { + fprintf(stderr, "Unreconized UI binding type %s for key %s\n", target, curstr); + } + } else { + fprintf(stderr, "Unrecognized binding type %s for key %s\n", target, curstr); + } + } + process_keys(cur->left, special, padbuttons, prefix); + process_keys(cur->right, special, padbuttons, prefix); +} + void set_keybindings() { - bind_gamepad(RENDERKEY_UP, 1, DPAD_UP); - bind_gamepad(RENDERKEY_DOWN, 1, DPAD_DOWN); - bind_gamepad(RENDERKEY_LEFT, 1, DPAD_LEFT); - bind_gamepad(RENDERKEY_RIGHT, 1, DPAD_RIGHT); - bind_gamepad('a', 1, BUTTON_A); - bind_gamepad('s', 1, BUTTON_B); - bind_gamepad('d', 1, BUTTON_C); - bind_gamepad('q', 1, BUTTON_X); - bind_gamepad('w', 1, BUTTON_Y); - bind_gamepad('e', 1, BUTTON_Z); - bind_gamepad('\r', 1, BUTTON_START); - bind_gamepad('f', 1, BUTTON_MODE); - bind_ui('[', UI_DEBUG_MODE_INC); - bind_ui(']', UI_DEBUG_PAL_INC); - bind_ui('u', UI_ENTER_DEBUGGER); + tern_node * special = tern_insert_int(NULL, "up", RENDERKEY_UP); + special = tern_insert_int(special, "down", RENDERKEY_DOWN); + special = tern_insert_int(special, "left", RENDERKEY_LEFT); + special = tern_insert_int(special, "right", RENDERKEY_RIGHT); + special = tern_insert_int(special, "enter", '\r'); + + tern_node * padbuttons = tern_insert_int(NULL, ".up", DPAD_UP); + padbuttons = tern_insert_int(padbuttons, ".down", DPAD_DOWN); + padbuttons = tern_insert_int(padbuttons, ".left", DPAD_LEFT); + padbuttons = tern_insert_int(padbuttons, ".right", DPAD_RIGHT); + padbuttons = tern_insert_int(padbuttons, ".a", BUTTON_A); + padbuttons = tern_insert_int(padbuttons, ".b", BUTTON_B); + padbuttons = tern_insert_int(padbuttons, ".c", BUTTON_C); + padbuttons = tern_insert_int(padbuttons, ".x", BUTTON_X); + padbuttons = tern_insert_int(padbuttons, ".y", BUTTON_Y); + padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z); + padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START); + padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE); + + tern_node * keys = tern_find_prefix(config, "bindingskeys"); + process_keys(keys, special, padbuttons, NULL); bind_dpad_gamepad(0, 0, RENDER_DPAD_UP, 2, DPAD_UP); bind_dpad_gamepad(0, 0, RENDER_DPAD_DOWN, 2, DPAD_DOWN); -- cgit v1.2.3 From 931a3998b096b27d881f4e4576759ef0e0bff4e1 Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Wed, 10 Jul 2013 23:47:48 -0700 Subject: Read joystick bindings from config file --- io.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 42 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 9fc3ad3..a8296df 100644 --- a/io.c +++ b/io.c @@ -252,6 +252,45 @@ void handle_joy_dpad(int joystick, int dpadnum, uint8_t value) } } +int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, int * padnum_out, int * padbutton_out) +{ + int gpadslen = strlen("gamepads."); + if (!memcmp(target, "gamepads.", gpadslen)) { + if (target[gpadslen] >= '1' && target[gpadslen] <= '8') { + int padnum = target[gpadslen] - '0'; + int button = tern_find_int(padbuttons, target + gpadslen + 1, 0); + if (button) { + *padnum_out = padnum; + *padbutton_out = button; + return 1; + } else { + if (target[gpadslen+1]) { + fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid button '%s'\n", target, target + gpadslen + 1); + } else { + fprintf(stderr, "Gamepad mapping string '%s' has no button component\n", target); + } + } + } else { + fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]); + } + } else if(!memcmp(target, "ui.", strlen("ui."))) { + if (!strcmp(target + 3, "vdp_debug_mode")) { + *ui_out = UI_DEBUG_MODE_INC; + } else if(!strcmp(target + 3, "vdp_debug_pal")) { + *ui_out = UI_DEBUG_PAL_INC; + } else if(!strcmp(target + 3, "enter_debugger")) { + *ui_out = UI_ENTER_DEBUGGER; + } else { + fprintf(stderr, "Unreconized UI binding type %s\n", target); + return 0; + } + return 2; + } else { + fprintf(stderr, "Unrecognized binding type %s\n", target); + } + return 0; +} + void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, char * prefix) { char * curstr; @@ -281,35 +320,12 @@ void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, } } char * target = cur->straight.value.ptrval; - int gpadslen = strlen("gamepads."); - if (!memcmp(target, "gamepads.", gpadslen)) { - if (target[gpadslen] >= '1' && target[gpadslen] <= '8') { - int padnum = target[gpadslen] - '0'; - int button = tern_find_int(padbuttons, target + gpadslen + 1, 0); - if (button) { - bind_gamepad(keycode, padnum, button); - } else { - if (target[gpadslen+1]) { - fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid button '%s'\n", target, target + gpadslen + 1); - } else { - fprintf(stderr, "Gamepad mapping string '%s' has no button component\n", target); - } - } - } else { - fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]); - } - } else if(!memcmp(target, "ui.", strlen("ui."))) { - if (!strcmp(target + 3, "vdp_debug_mode")) { - bind_ui(keycode, UI_DEBUG_MODE_INC); - } else if(!strcmp(target + 3, "vdp_debug_pal")) { - bind_ui(keycode, UI_DEBUG_PAL_INC); - } else if(!strcmp(target + 3, "enter_debugger")) { - bind_ui(keycode, UI_ENTER_DEBUGGER); - } else { - fprintf(stderr, "Unreconized UI binding type %s for key %s\n", target, curstr); - } - } else { - fprintf(stderr, "Unrecognized binding type %s for key %s\n", target, curstr); + int ui_func, padnum, button; + int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button); + if (bindtype == 1) { + bind_gamepad(keycode, padnum, button); + } else if(bindtype == 2) { + bind_ui(keycode, ui_func); } } process_keys(cur->left, special, padbuttons, prefix); @@ -339,19 +355,59 @@ void set_keybindings() tern_node * keys = tern_find_prefix(config, "bindingskeys"); process_keys(keys, special, padbuttons, NULL); - - bind_dpad_gamepad(0, 0, RENDER_DPAD_UP, 2, DPAD_UP); - bind_dpad_gamepad(0, 0, RENDER_DPAD_DOWN, 2, DPAD_DOWN); - bind_dpad_gamepad(0, 0, RENDER_DPAD_LEFT, 2, DPAD_LEFT); - bind_dpad_gamepad(0, 0, RENDER_DPAD_RIGHT, 2, DPAD_RIGHT); - bind_button_gamepad(0, 0, 2, BUTTON_A); - bind_button_gamepad(0, 1, 2, BUTTON_B); - bind_button_gamepad(0, 2, 2, BUTTON_C); - bind_button_gamepad(0, 3, 2, BUTTON_X); - bind_button_gamepad(0, 4, 2, BUTTON_Y); - bind_button_gamepad(0, 5, 2, BUTTON_Z); - bind_button_gamepad(0, 6, 2, BUTTON_START); - bind_button_gamepad(0, 7, 2, BUTTON_MODE); + char prefix[] = "bindingspads00"; + for (int i = 0; i < 100 && i < render_num_joysticks(); i++) + { + if (i < 10) { + prefix[strlen("bindingspads")] = i + '0'; + prefix[strlen("bindingspads")+1] = 0; + } else { + prefix[strlen("bindingspads")] = i/10 + '0'; + prefix[strlen("bindingspads")+1] = i%10 + '0'; + } + tern_node * pad = tern_find_prefix(config, prefix); + if (pad) { + char dprefix[] = "dpads0"; + for (int dpad = 0; dpad < 10 && dpad < render_joystick_num_hats(i); dpad++) + { + dprefix[strlen("dpads")] = dpad + '0'; + tern_node * pad_dpad = tern_find_prefix(pad, dprefix); + 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++) { + char * target = tern_find_ptr(pad_dpad, dirs[dir]); + if (target) { + int ui_func, padnum, button; + int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button); + if (bindtype == 1) { + bind_dpad_gamepad(i, dpad, dirnums[dir], padnum, button); + } + //TODO: Handle UI bindings + } + } + } + char bprefix[] = "buttons00"; + for (int but = 0; but < 100 && but < render_joystick_num_buttons(i); but++) + { + if (but < 10) { + bprefix[strlen("buttons")] = but + '0'; + bprefix[strlen("buttons")+1] = 0; + } else { + bprefix[strlen("buttons")] = but/10 + '0'; + bprefix[strlen("buttons")+1] = but%10 + '0'; + } + char * target = tern_find_ptr(pad, bprefix); + if (target) { + int ui_func, padnum, button; + int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button); + if (bindtype == 1) { + bind_button_gamepad(i, but, padnum, button); + } + //TODO: Handle UI bindings + } + } + } + } } #define TH 0x40 -- cgit v1.2.3 From de1c3145d57e6efc3022012d26744f7a79e3cde2 Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Mon, 15 Jul 2013 23:07:45 -0700 Subject: Restore one of the VDP debugging modes --- io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'io.c') diff --git a/io.c b/io.c index a8296df..fa9e2b2 100644 --- a/io.c +++ b/io.c @@ -197,7 +197,7 @@ void handle_binding_up(keybinding * binding) if (ui_debug_mode == 4) { ui_debug_mode = 0; } - render_debug_mode(ui_debug_mode); + genesis->vdp->debug = ui_debug_mode; break; case UI_DEBUG_PAL_INC: ui_debug_pal++; -- cgit v1.2.3 From b94c9fd1cd3731c9a0bdcabcb15e7bead85021dc Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Wed, 17 Jul 2013 22:26:11 -0700 Subject: Add fullscreen support and add a keybinding for exiting the emulator --- io.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'io.c') diff --git a/io.c b/io.c index fa9e2b2..b277c3c 100644 --- a/io.c +++ b/io.c @@ -12,7 +12,8 @@ enum { typedef enum { UI_DEBUG_MODE_INC, UI_DEBUG_PAL_INC, - UI_ENTER_DEBUGGER + UI_ENTER_DEBUGGER, + UI_EXIT } ui_action; typedef struct { @@ -209,6 +210,8 @@ void handle_binding_up(keybinding * binding) case UI_ENTER_DEBUGGER: break_on_sync = 1; break; + case UI_EXIT: + exit(0); } break; } @@ -280,6 +283,8 @@ int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, in *ui_out = UI_DEBUG_PAL_INC; } else if(!strcmp(target + 3, "enter_debugger")) { *ui_out = UI_ENTER_DEBUGGER; + } else if(!strcmp(target + 3, "exit")) { + *ui_out = UI_EXIT; } else { fprintf(stderr, "Unreconized UI binding type %s\n", target); return 0; @@ -339,6 +344,7 @@ void set_keybindings() special = tern_insert_int(special, "left", RENDERKEY_LEFT); special = tern_insert_int(special, "right", RENDERKEY_RIGHT); special = tern_insert_int(special, "enter", '\r'); + special = tern_insert_int(special, "esc", RENDERKEY_ESC); tern_node * padbuttons = tern_insert_int(NULL, ".up", DPAD_UP); padbuttons = tern_insert_int(padbuttons, ".down", DPAD_DOWN); -- cgit v1.2.3 From a75eb24bfbbf0dd3492c8414cfaafa0569a1539a Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Fri, 26 Jul 2013 19:55:04 -0700 Subject: Added support for saving savestates. Added gst savestate format test harness --- io.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index b277c3c..03875c5 100644 --- a/io.c +++ b/io.c @@ -13,6 +13,7 @@ typedef enum { UI_DEBUG_MODE_INC, UI_DEBUG_PAL_INC, UI_ENTER_DEBUGGER, + UI_SAVE_STATE, UI_EXIT } ui_action; @@ -107,7 +108,7 @@ void bind_dpad(int joystick, int dpad, int direction, uint8_t bind_type, uint8_t void bind_gamepad(int keycode, int gamepadnum, int button) { - + if (gamepadnum < 1 || gamepadnum > 2) { return; } @@ -210,6 +211,9 @@ void handle_binding_up(keybinding * binding) case UI_ENTER_DEBUGGER: break_on_sync = 1; break; + case UI_SAVE_STATE: + save_state = 1; + break; case UI_EXIT: exit(0); } @@ -283,6 +287,8 @@ int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, in *ui_out = UI_DEBUG_PAL_INC; } else if(!strcmp(target + 3, "enter_debugger")) { *ui_out = UI_ENTER_DEBUGGER; + } else if(!strcmp(target + 3, "save_state")) { + *ui_out = UI_SAVE_STATE; } else if(!strcmp(target + 3, "exit")) { *ui_out = UI_EXIT; } else { @@ -345,7 +351,7 @@ void set_keybindings() special = tern_insert_int(special, "right", RENDERKEY_RIGHT); special = tern_insert_int(special, "enter", '\r'); special = tern_insert_int(special, "esc", RENDERKEY_ESC); - + tern_node * padbuttons = tern_insert_int(NULL, ".up", DPAD_UP); padbuttons = tern_insert_int(padbuttons, ".down", DPAD_DOWN); padbuttons = tern_insert_int(padbuttons, ".left", DPAD_LEFT); @@ -358,7 +364,7 @@ void set_keybindings() padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z); padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START); padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE); - + tern_node * keys = tern_find_prefix(config, "bindingskeys"); process_keys(keys, special, padbuttons, NULL); char prefix[] = "bindingspads00"; -- cgit v1.2.3 From 2c302a78d201d9b594774cec505d14c22e03662c Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Tue, 10 Sep 2013 23:31:08 -0700 Subject: Added copyright notice to source files and added GPL license text in COPYING --- io.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'io.c') diff --git a/io.c b/io.c index 03875c5..b9e95c1 100644 --- a/io.c +++ b/io.c @@ -1,3 +1,8 @@ +/* + Copyright 2013 Michael Pavone + This file is part of BlastEm. + BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. +*/ #include "io.h" #include "blastem.h" #include "render.h" -- cgit v1.2.3 From c4e2e0114cdc1871e959c67d0f15be99bef3459c Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Tue, 1 Oct 2013 23:51:16 -0700 Subject: Implement turbo/slow motion feature that overclocks or underclocks the entire system at the push of a button --- io.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 106 insertions(+), 7 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index b9e95c1..c83f756 100644 --- a/io.c +++ b/io.c @@ -1,6 +1,6 @@ /* Copyright 2013 Michael Pavone - This file is part of BlastEm. + This file is part of BlastEm. BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. */ #include "io.h" @@ -18,7 +18,10 @@ typedef enum { UI_DEBUG_MODE_INC, UI_DEBUG_PAL_INC, UI_ENTER_DEBUGGER, - UI_SAVE_STATE, + UI_SAVE_STATE, + UI_SET_SPEED, + UI_NEXT_SPEED, + UI_PREV_SPEED, UI_EXIT } ui_action; @@ -139,9 +142,9 @@ void bind_dpad_gamepad(int joystick, int dpad, uint8_t direction, int gamepadnum bind_dpad(joystick, dpad, direction, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF); } -void bind_ui(int keycode, ui_action action) +void bind_ui(int keycode, ui_action action, uint8_t param) { - bind_key(keycode, BIND_UI, action, 0, 0); + bind_key(keycode, BIND_UI, action, 0, param); } void handle_binding_down(keybinding * binding) @@ -183,6 +186,10 @@ void handle_joydown(int joystick, int button) uint8_t ui_debug_mode = 0; uint8_t ui_debug_pal = 0; +int current_speed = 0; +int num_speeds = 1; +uint32_t * speeds = NULL; + void handle_binding_up(keybinding * binding) { switch(binding->bind_type) @@ -219,6 +226,32 @@ void handle_binding_up(keybinding * binding) case UI_SAVE_STATE: save_state = 1; break; + case UI_NEXT_SPEED: + current_speed++; + if (current_speed >= num_speeds) { + current_speed = 0; + } + printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]); + set_speed_percent(genesis, speeds[current_speed]); + break; + case UI_PREV_SPEED: + current_speed--; + if (current_speed < 0) { + current_speed = num_speeds - 1; + } + printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]); + set_speed_percent(genesis, speeds[current_speed]); + break; + case UI_SET_SPEED: + if (binding->value < num_speeds) { + current_speed = binding->value; + printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]); + set_speed_percent(genesis, speeds[current_speed]); + } else { + printf("Setting speed to %d\n", speeds[current_speed]); + set_speed_percent(genesis, binding->value); + } + break; case UI_EXIT: exit(0); } @@ -286,6 +319,7 @@ int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, in fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]); } } else if(!memcmp(target, "ui.", strlen("ui."))) { + *padbutton_out = 0; if (!strcmp(target + 3, "vdp_debug_mode")) { *ui_out = UI_DEBUG_MODE_INC; } else if(!strcmp(target + 3, "vdp_debug_pal")) { @@ -294,6 +328,13 @@ int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, in *ui_out = UI_ENTER_DEBUGGER; } else if(!strcmp(target + 3, "save_state")) { *ui_out = UI_SAVE_STATE; + } else if(!memcmp(target + 3, "set_speed.", strlen("set_speed."))) { + *ui_out = UI_SET_SPEED; + *padbutton_out = atoi(target + 3 + strlen("set_speed.")); + } else if(!strcmp(target + 3, "next_speed")) { + *ui_out = UI_NEXT_SPEED; + } else if(!strcmp(target + 3, "prev_speed")) { + *ui_out = UI_PREV_SPEED; } else if(!strcmp(target + 3, "exit")) { *ui_out = UI_EXIT; } else { @@ -309,7 +350,7 @@ int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, in void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, char * prefix) { - char * curstr; + char * curstr = NULL; int len; if (!cur) { return; @@ -324,8 +365,8 @@ void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, len = 0; } curstr[len] = cur->el; + curstr[len+1] = 0; if (cur->el) { - curstr[len+1] = 0; process_keys(cur->straight.next, special, padbuttons, curstr); } else { int keycode = tern_find_int(special, curstr, 0); @@ -341,11 +382,59 @@ void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, if (bindtype == 1) { bind_gamepad(keycode, padnum, button); } else if(bindtype == 2) { - bind_ui(keycode, ui_func); + bind_ui(keycode, ui_func, button); } } process_keys(cur->left, special, padbuttons, prefix); process_keys(cur->right, special, padbuttons, prefix); + if (curstr && len) { + free(curstr); + } +} + +void process_speeds(tern_node * cur, char * prefix) +{ + char * curstr = NULL; + int len; + if (!cur) { + return; + } + char onec[2]; + if (prefix) { + len = strlen(prefix); + curstr = malloc(len + 2); + memcpy(curstr, prefix, len); + } else { + curstr = onec; + len = 0; + } + curstr[len] = cur->el; + curstr[len+1] = 0; + if (cur->el) { + process_speeds(cur->straight.next, curstr); + } else { + int speed_index = atoi(curstr); + if (speed_index < 1) { + if (!strcmp(curstr, "0")) { + fputs("Speed index 0 cannot be set to a custom value\n", stderr); + } else { + fprintf(stderr, "%s is not a valid speed index", curstr); + } + } else { + if (speed_index >= num_speeds) { + speeds = realloc(speeds, sizeof(uint32_t) * (speed_index+1)); + for(; num_speeds < speed_index + 1; num_speeds++) { + speeds[num_speeds] = 0; + } + } + speeds[speed_index] = atoi(cur->straight.value.ptrval); + } + } + process_speeds(cur->left, prefix); + process_speeds(cur->right, prefix); + if (curstr && len) { + free(curstr); + } } void set_keybindings() @@ -425,6 +514,16 @@ void set_keybindings() } } } + tern_node * speed_nodes = tern_find_prefix(config, "clocksspeeds"); + speeds = malloc(sizeof(uint32_t)); + speeds[0] = 100; + process_speeds(speed_nodes, NULL); + for (int i = 0; i < num_speeds; i++) { + if (!speeds[i]) { + fprintf(stderr, "Speed index %d was not set to a valid percentage!", i); + speeds[i] = 100; + } + } } #define TH 0x40 -- cgit v1.2.3