changeset 1194:1ad0ec7e3939

Make gamepad "semantic" mapping play nice with hotplug support
author Michael Pavone <pavone@retrodev.com>
date Tue, 24 Jan 2017 20:53:10 -0800
parents 0e69409634f3
children b8ba086b96ed
files io.c io.h render_sdl.c
diffstat 3 files changed, 119 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/io.c	Tue Jan 24 18:53:55 2017 -0800
+++ b/io.c	Tue Jan 24 20:53:10 2017 -0800
@@ -175,6 +175,28 @@
 	}
 }
 
+void reset_joystick_bindings(int joystick)
+{
+	if (joystick >= MAX_JOYSTICKS) {
+		return;
+	}
+	if (joysticks[joystick].buttons) {
+		for (int i = 0; i < joysticks[joystick].num_buttons; i++)
+		{
+			joysticks[joystick].buttons[i].bind_type = BIND_NONE;
+		}
+	}
+	if (joysticks[joystick].dpads) {
+		for (int i = 0; i < joysticks[joystick].num_dpads; i++)
+		{
+			for (int dir = 0; dir < 4; dir++)
+			{
+				joysticks[joystick].dpads[i].bindings[dir].bind_type = BIND_NONE;
+			}
+		}
+	}
+}
+
 #define GAMEPAD_BUTTON(PRI_SLOT, SEC_SLOT, VALUE)  (PRI_SLOT << 12 | SEC_SLOT << 8 | VALUE)
 
 #define DPAD_UP      GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_TH1, 0x01)
@@ -966,6 +988,98 @@
 	}
 }
 
+static tern_node *get_pad_buttons()
+{
+	static tern_node *padbuttons;
+	if (!padbuttons) {
+		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);
+	}
+	return padbuttons;
+}
+
+static tern_node *get_mouse_buttons()
+{
+	static tern_node *mousebuttons;
+	if (!mousebuttons) {
+		mousebuttons = tern_insert_int(NULL, ".left", MOUSE_LEFT);
+		mousebuttons = tern_insert_int(mousebuttons, ".middle", MOUSE_MIDDLE);
+		mousebuttons = tern_insert_int(mousebuttons, ".right", MOUSE_RIGHT);
+		mousebuttons = tern_insert_int(mousebuttons, ".start", MOUSE_START);
+		mousebuttons = tern_insert_int(mousebuttons, ".motion", PSEUDO_BUTTON_MOTION);
+	}
+	return mousebuttons;
+}
+
+void handle_joy_added(int joystick)
+{
+	if (joystick > MAX_JOYSTICKS) {
+		return;
+	}
+	tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0"));
+	if (pads) {
+		char numstr[11];
+		sprintf(numstr, "%d", joystick);
+		tern_node * pad = tern_find_ptr(pads, numstr);
+		if (pad) {
+			tern_node * dpad_node = tern_find_ptr(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);
+					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, get_pad_buttons(), get_mouse_buttons(), &ui_func, &padnum, &button);
+							if (bindtype == BIND_GAMEPAD1) {
+								bind_dpad_gamepad(joystick, dpad, dirnums[dir], padnum, button);
+							} else if (bindtype == BIND_UI) {
+								bind_dpad_ui(joystick, dpad, dirnums[dir], ui_func, button);
+							}
+						}
+					}
+				}
+			}
+			tern_node *button_node = tern_find_ptr(pad, "buttons");
+			if (button_node) {
+				pad_button_state state = {
+					.padnum = joystick,
+					.padbuttons = get_pad_buttons(),
+					.mousebuttons = get_mouse_buttons()
+				};
+				tern_foreach(button_node, process_pad_button, &state);
+			}
+			if (current_io) {
+				if (joysticks[joystick].buttons) {
+					map_bindings(current_io->ports, joysticks[joystick].buttons, joysticks[joystick].num_buttons);
+				}
+				if (joysticks[joystick].dpads)
+				{
+					for (uint32_t i = 0; i < joysticks[joystick].num_dpads; i++) {
+						map_bindings(current_io->ports, joysticks[joystick].dpads[i].bindings, 4);
+					}
+				}
+			}
+		}
+	}
+	
+}
+
 void set_keybindings(sega_io *io)
 {
 	static uint8_t already_done;
@@ -1012,27 +1126,9 @@
 	special = tern_insert_int(special, "search", RENDERKEY_SEARCH);
 	special = tern_insert_int(special, "back", RENDERKEY_BACK);
 
-	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 *padbuttons = get_pad_buttons();
 
-	tern_node *mousebuttons = tern_insert_int(NULL, ".left", MOUSE_LEFT);
-	mousebuttons = tern_insert_int(mousebuttons, ".middle", MOUSE_MIDDLE);
-	mousebuttons = tern_insert_int(mousebuttons, ".right", MOUSE_RIGHT);
-	mousebuttons = tern_insert_int(mousebuttons, ".start", MOUSE_START);
-	mousebuttons = tern_insert_int(mousebuttons, ".motion", PSEUDO_BUTTON_MOTION);
-
-	//pump event loop, so initial joystick insertion events are processed
-	process_events();
+	tern_node *mousebuttons = get_mouse_buttons();
 	
 	tern_node * keys = tern_get_node(tern_find_path(config, "bindings\0keys\0"));
 	process_keys(keys, special, padbuttons, mousebuttons, NULL);
@@ -1049,42 +1145,7 @@
 				numstr[0] = i/10 + '0';
 				numstr[1] = i%10 + '0';
 			}
-			tern_node * pad = tern_find_ptr(pads, numstr);
-			if (pad) {
-				tern_node * dpad_node = tern_find_ptr(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);
-						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, mousebuttons, &ui_func, &padnum, &button);
-								if (bindtype == BIND_GAMEPAD1) {
-									bind_dpad_gamepad(i, dpad, dirnums[dir], padnum, button);
-								} else if (bindtype == BIND_UI) {
-									bind_dpad_ui(i, dpad, dirnums[dir], ui_func, button);
-								}
-							}
-						}
-					}
-				}
-				tern_node *button_node = tern_find_ptr(pad, "buttons");
-				if (button_node) {
-					pad_button_state state = {
-						.padnum = i,
-						.padbuttons = padbuttons,
-						.mousebuttons = mousebuttons
-					};
-					tern_foreach(button_node, process_pad_button, &state);
-					
-				}
-			}
+			
 		}
 	}
 	memset(mice, 0, sizeof(mice));
--- a/io.h	Tue Jan 24 18:53:55 2017 -0800
+++ b/io.h	Tue Jan 24 20:53:10 2017 -0800
@@ -95,6 +95,7 @@
 void handle_joydown(int joystick, int button);
 void handle_joyup(int joystick, int button);
 void handle_joy_dpad(int joystick, int dpad, uint8_t state);
+void handle_joy_added(int joystick);
 void handle_mouse_moved(int mouse, uint16_t x, uint16_t y, int16_t deltax, int16_t deltay);
 void handle_mousedown(int mouse, int button);
 void handle_mouseup(int mouse, int button);
--- a/render_sdl.c	Tue Jan 24 18:53:55 2017 -0800
+++ b/render_sdl.c	Tue Jan 24 20:53:10 2017 -0800
@@ -818,6 +818,7 @@
 				if (joy) {
 					printf("Joystick %d added: %s\n", index, SDL_JoystickName(joy));
 					printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy));
+					handle_joy_added(index);
 				}
 			}
 		}