changeset 431:440efd7d27a9

Read key bindings from config file
author Mike Pavone <pavone@retrodev.com>
date Wed, 10 Jul 2013 22:48:17 -0700
parents 7f84090ab1cd
children 18cde14e8c10
files config.c default.cfg io.c tern.c tern.h
diffstat 5 files changed, 109 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/config.c	Wed Jul 10 09:38:05 2013 -0700
+++ b/config.c	Wed Jul 10 22:48:17 2013 -0700
@@ -122,7 +122,7 @@
 				if (prefix) {
 					key = alloc_concat(prefix, key);
 				}
-				head = tern_insert_ptr(head, key, val);
+				head = tern_insert_ptr(head, key, strdup(val));
 				if (prefix) {
 					free(key);
 				}
--- a/default.cfg	Wed Jul 10 09:38:05 2013 -0700
+++ b/default.cfg	Wed Jul 10 22:48:17 2013 -0700
@@ -1,10 +1,10 @@
 
 bindings {
 	keys {
-		UP gamepads.1.up
-		DOWN gamepads.1.down
-		LEFT gamepads.1.left
-		RIGHT gamepads.1.right
+		up gamepads.1.up
+		down gamepads.1.down
+		left gamepads.1.left
+		right gamepads.1.right
 		a gamepads.1.a
 		s gamepads.1.b
 		d gamepads.1.c
@@ -12,7 +12,7 @@
 		w gamepads.1.y
 		e gamepads.1.z
 		f gamepads.1.mode
-		ENTER gamepads.1.start
+		enter gamepads.1.start
 		
 		[ ui.vdp_debug_mode
 		] ui.vdp_debug_pal
--- a/io.c	Wed Jul 10 09:38:05 2013 -0700
+++ b/io.c	Wed Jul 10 22:48:17 2013 -0700
@@ -252,23 +252,93 @@
 	}
 }
 
+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);
--- a/tern.c	Wed Jul 10 09:38:05 2013 -0700
+++ b/tern.c	Wed Jul 10 22:48:17 2013 -0700
@@ -63,6 +63,23 @@
 	return 0;
 }
 
+tern_node * tern_find_prefix(tern_node * head, char * key)
+{
+	tern_node * cur = head;
+	while (cur && *key)
+	{
+		if (cur->el == *key) {
+			cur = cur->straight.next;
+			key++;
+		} else if (*key < cur->el) {
+			cur = cur->left;
+		} else {
+			cur = cur->right;
+		}
+	}
+	return cur;
+}
+
 intptr_t tern_find_int(tern_node * head, char * key, intptr_t def)
 {
 	tern_val ret;
--- a/tern.h	Wed Jul 10 09:38:05 2013 -0700
+++ b/tern.h	Wed Jul 10 22:48:17 2013 -0700
@@ -20,6 +20,7 @@
 
 tern_node * tern_insert(tern_node * head, char * key, tern_val value);
 int tern_find(tern_node * head, char * key, tern_val *ret);
+tern_node * tern_find_prefix(tern_node * head, char * key);
 intptr_t tern_find_int(tern_node * head, char * key, intptr_t def);
 tern_node * tern_insert_int(tern_node * head, char * key, intptr_t value);
 void * tern_find_ptr(tern_node * head, char * key);