changeset 1608:419a0a133b5c

Allow a gamepad mapping to apply to all controllers, controllers of a particular type (i.e.e 6-button PS4 controllers) or specific controllers (based on SDL2 GUID) in addition to the controller in a certain slot
author Michael Pavone <pavone@retrodev.com>
date Fri, 03 Aug 2018 19:32:21 -0700
parents 0174759e559f
children 9c8f58740450
files bindings.c controller_info.c controller_info.h default.cfg render.h render_sdl.c
diffstat 6 files changed, 90 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/bindings.c	Thu Aug 02 19:06:57 2018 -0700
+++ b/bindings.c	Fri Aug 03 19:32:21 2018 -0700
@@ -8,6 +8,7 @@
 #include "genesis.h"
 #include "menu.h"
 #include "bindings.h"
+#include "controller_info.h"
 #ifndef DISABLE_NUKLEAR
 #include "nuklear_ui/blastem_nuklear.h"
 #endif
@@ -502,13 +503,13 @@
 	}
 }
 
-int parse_binding_target(char * target, tern_node * padbuttons, tern_node *mousebuttons, uint8_t * subtype_a, uint8_t * subtype_b)
+int parse_binding_target(int device_num, char * target, tern_node * padbuttons, tern_node *mousebuttons, uint8_t * subtype_a, uint8_t * subtype_b)
 {
 	const int gpadslen = strlen("gamepads.");
 	const int mouselen = strlen("mouse.");
 	if (!strncmp(target, "gamepads.", gpadslen)) {
-		if (target[gpadslen] >= '1' && target[gpadslen] <= '8') {
-			int padnum = target[gpadslen] - '0';
+		int padnum = target[gpadslen] == 'n' ? device_num + 1 : target[gpadslen] - '0';
+		if (padnum >= 1 && padnum <= 8) {
 			int button = tern_find_int(padbuttons, target + gpadslen + 1, 0);
 			if (button) {
 				*subtype_a = padnum;
@@ -525,8 +526,8 @@
 			warning("Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]);
 		}
 	} else if(!strncmp(target, "mouse.", mouselen)) {
-		if (target[mouselen] >= '1' && target[mouselen] <= '8') {
-			int mousenum = target[mouselen] - '0';
+		int mousenum = target[mouselen] == 'n' ? device_num + 1 : target[mouselen] - '0';
+		if (mousenum >= 1 && mousenum <= 8) {
 			int button = tern_find_int(mousebuttons, target + mouselen + 1, 0);
 			if (button) {
 				*subtype_a = mousenum;
@@ -615,7 +616,7 @@
 		}
 		char * target = cur->straight.value.ptrval;
 		uint8_t subtype_a = 0, subtype_b = 0;
-		int bindtype = parse_binding_target(target, padbuttons, mousebuttons, &subtype_a, &subtype_b);
+		int bindtype = parse_binding_target(0, target, padbuttons, mousebuttons, &subtype_a, &subtype_b);
 		bind_key(keycode, bindtype, subtype_a, subtype_b);
 	}
 	process_keys(cur->left, special, padbuttons, mousebuttons, prefix);
@@ -691,7 +692,7 @@
 	}
 	buttonnum--;
 	uint8_t subtype_a = 0, subtype_b = 0;
-	int bindtype = parse_binding_target(value.ptrval, state->padbuttons, state->mousebuttons, &subtype_a, &subtype_b);
+	int bindtype = parse_binding_target(state->mouseidx, value.ptrval, state->padbuttons, state->mousebuttons, &subtype_a, &subtype_b);
 	mice[state->mouseidx].buttons[buttonnum].bind_type = bindtype;
 	mice[state->mouseidx].buttons[buttonnum].subtype_a = subtype_a;
 	mice[state->mouseidx].buttons[buttonnum].subtype_b = subtype_b;
@@ -716,7 +717,7 @@
 	char *motion = tern_find_ptr(mousedef, "motion");
 	if (motion) {
 		uint8_t subtype_a = 0, subtype_b = 0;
-		int bindtype = parse_binding_target(motion, padbuttons, mousebuttons, &subtype_a, &subtype_b);
+		int bindtype = parse_binding_target(mouseidx, motion, padbuttons, mousebuttons, &subtype_a, &subtype_b);
 		mice[mouseidx].motion.bind_type = bindtype;
 		mice[mouseidx].motion.subtype_a = subtype_a;
 		mice[mouseidx].motion.subtype_b = subtype_b;
@@ -745,7 +746,7 @@
 		return;
 	}
 	uint8_t subtype_a = 0, subtype_b = 0;
-	int bindtype = parse_binding_target(val.ptrval, state->padbuttons, state->mousebuttons, &subtype_a, &subtype_b);
+	int bindtype = parse_binding_target(hostpadnum, val.ptrval, state->padbuttons, state->mousebuttons, &subtype_a, &subtype_b);
 	char *end;
 	long hostbutton = strtol(key, &end, 10);
 	if (*end) {
@@ -781,7 +782,7 @@
 		return;
 	}
 	uint8_t subtype_a = 0, subtype_b = 0;
-	int bindtype = parse_binding_target(val.ptrval, state->padbuttons, state->mousebuttons, &subtype_a, &subtype_b);
+	int bindtype = parse_binding_target(hostpadnum, val.ptrval, state->padbuttons, state->mousebuttons, &subtype_a, &subtype_b);
 	char *modifier = strchr(key, '.');
 	int positive = 1;
 	if (modifier) {
@@ -866,6 +867,20 @@
 		char numstr[11];
 		sprintf(numstr, "%d", joystick);
 		tern_node * pad = tern_find_node(pads, numstr);
+		if (!pad) {
+			char *type_id = render_joystick_type_id(joystick);
+			pad = tern_find_node(pads, type_id);
+			free(type_id);
+		}
+		if (!pad) {
+			controller_info info = get_controller_info(joystick);
+			char *key = make_controller_type_key(&info);
+			pad = tern_find_node(pads, key);
+			free(key);
+		}
+		if (!pad) {
+			pad = tern_find_node(pads, "default");
+		}
 		if (pad) {
 			tern_node * dpad_node = tern_find_node(pad, "dpads");
 			if (dpad_node) {
@@ -881,7 +896,7 @@
 						char * target = tern_find_ptr(pad_dpad, dirs[dir]);
 						if (target) {
 							uint8_t subtype_a = 0, subtype_b = 0;
-							int bindtype = parse_binding_target(target, get_pad_buttons(), get_mouse_buttons(), &subtype_a, &subtype_b);
+							int bindtype = parse_binding_target(joystick, target, get_pad_buttons(), get_mouse_buttons(), &subtype_a, &subtype_b);
 							bind_dpad(joystick, dpad, dirnums[dir], bindtype, subtype_a, subtype_b);
 						}
 					}
--- a/controller_info.c	Thu Aug 02 19:06:57 2018 -0700
+++ b/controller_info.c	Fri Aug 03 19:32:21 2018 -0700
@@ -261,3 +261,37 @@
 	}
 }
 
+char *make_controller_type_key(controller_info *info)
+{
+	const char *subtype;
+	if (info->subtype == SUBTYPE_UNKNOWN) {
+		switch(info->type)
+		{
+		case TYPE_XBOX:
+			subtype = subtype_names[SUBTYPE_X360];
+			break;
+		case TYPE_PSX:
+			subtype = subtype_names[SUBTYPE_PS4];
+			break;
+		case TYPE_NINTENDO:
+			subtype = subtype_names[SUBTYPE_SWITCH];
+			break;
+		default:
+			subtype = "unknown";
+		}
+	} else {
+		subtype = subtype_names[info->subtype];
+	}
+	const char *variant = variant_names[info->variant];
+	const char *parts[] = {subtype, "_", variant};
+	char *ret = alloc_concat_m(3, parts);
+	for (char *cur = ret; *cur; cur++)
+	{
+		if (*cur == ' ')
+		{
+			*cur = '_';
+		}
+	}
+	return ret;
+}
+
--- a/controller_info.h	Thu Aug 02 19:06:57 2018 -0700
+++ b/controller_info.h	Fri Aug 03 19:32:21 2018 -0700
@@ -46,5 +46,6 @@
 void save_controller_info(int joystick, controller_info *info);
 void save_controller_mapping(int joystick, char *mapping_string);
 void controller_add_mappings(void);
+char *make_controller_type_key(controller_info *info);
 
 #endif //CONTROLLER_INFO_H_
\ No newline at end of file
--- a/default.cfg	Thu Aug 02 19:06:57 2018 -0700
+++ b/default.cfg	Fri Aug 03 19:32:21 2018 -0700
@@ -38,67 +38,36 @@
 		rctrl ui.toggle_keyboard_captured
 	}
 	pads {
-		0 {
+		default {
 			dpads {
 				0 {
-					up gamepads.1.up
-					down gamepads.1.down
-					left gamepads.1.left
-					right gamepads.1.right
+					up gamepads.n.up
+					down gamepads.n.down
+					left gamepads.n.left
+					right gamepads.n.right
 				}
 			}
 			buttons {
-				a gamepads.1.a
-				b gamepads.1.b
-				rightshoulder gamepads.1.c
-				x gamepads.1.x
-				y gamepads.1.y
-				leftshoulder gamepads.1.z
-				back gamepads.1.mode
-				start gamepads.1.start
+				a gamepads.n.a
+				b gamepads.n.b
+				rightshoulder gamepads.n.c
+				x gamepads.n.x
+				y gamepads.n.y
+				leftshoulder gamepads.n.z
+				back gamepads.n.mode
+				start gamepads.n.start
 				guide ui.exit
 				leftstick ui.save_state
 			}
 			axes {
-				lefty.positive gamepads.1.down
-				lefty.negative gamepads.1.up
-				leftx.positive gamepads.1.right
-				leftx.negative gamepads.1.left
+				lefty.positive gamepads.n.down
+				lefty.negative gamepads.n.up
+				leftx.positive gamepads.n.right
+				leftx.negative gamepads.n.left
 				lefttrigger ui.prev_speed
 				righttrigger ui.next_speed
 			}
 		}
-		1 {
-			dpads {
-				0 {
-					up gamepads.2.up
-					down gamepads.2.down
-					left gamepads.2.left
-					right gamepads.2.right
-				}
-			}
-			buttons {
-				#this is exactly the same mapping as above, but with PS4 style names
-				cross gamepads.2.a
-				circle gamepads.2.b
-				r1 gamepads.2.c
-				square gamepads.2.x
-				triangle gamepads.2.y
-				l1 gamepads.2.z
-				share gamepads.2.mode
-				options gamepads.2.start
-				guide ui.exit
-				l3 ui.save_state
-			}
-			axes {
-				lefty.positive gamepads.2.down
-				lefty.negative gamepads.2.up
-				leftx.positive gamepads.2.right
-				leftx.negative gamepads.2.left
-				l2 ui.prev_speed
-				r2 ui.next_speed
-			}
-		}
 	}
 	mice {
 		0 {
--- a/render.h	Thu Aug 02 19:06:57 2018 -0700
+++ b/render.h	Fri Aug 03 19:32:21 2018 -0700
@@ -107,6 +107,7 @@
 int32_t render_dpad_part(int32_t input);
 int32_t render_axis_part(int32_t input);
 uint8_t render_direction_part(int32_t input);
+char* render_joystick_type_id(int index);
 void render_errorbox(char *title, char *message);
 void render_warnbox(char *title, char *message);
 void render_infobox(char *title, char *message);
--- a/render_sdl.c	Thu Aug 02 19:06:57 2018 -0700
+++ b/render_sdl.c	Fri Aug 03 19:32:21 2018 -0700
@@ -814,6 +814,17 @@
 	return joysticks[index];
 }
 
+char* render_joystick_type_id(int index)
+{
+	SDL_Joystick *stick = render_get_joystick(index);
+	if (!stick) {
+		return NULL;
+	}
+	char *guid_string = malloc(33);
+	SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(stick), guid_string, 33);
+	return guid_string;
+}
+
 SDL_GameController *render_get_controller(int index)
 {
 	if (index >= MAX_JOYSTICKS) {