diff blastem.c @ 418:dbf4e1c86f3c

Implement basic joystick support
author Mike Pavone <pavone@retrodev.com>
date Sun, 23 Jun 2013 22:27:12 -0700
parents c3abc4ada43d
children d0cacb4ade0b
line wrap: on
line diff
--- a/blastem.c	Sun Jun 23 12:27:11 2013 -0700
+++ b/blastem.c	Sun Jun 23 22:27:12 2013 -0700
@@ -866,7 +866,15 @@
 	uint8_t value;
 } keybinding;
 
+typedef struct {
+	keybinding bindings[4];
+	uint8_t    state;
+} joydpad;
+
 keybinding * bindings[256];
+keybinding * joybindings[MAX_JOYSTICKS];
+joydpad * joydpads[MAX_JOYSTICKS];
+const uint8_t dpadbits[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
 
 void bind_key(int keycode, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
 {
@@ -882,6 +890,49 @@
 	bindings[bucket][idx].value = value;
 }
 
+void bind_button(int joystick, int button, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
+{
+	if (joystick >= MAX_JOYSTICKS) {
+		return;
+	}
+	if (!joybindings[joystick]) {
+		int num = render_joystick_num_buttons(joystick);
+		if (!num) {
+			return;
+		}
+		joybindings[joystick] = malloc(sizeof(keybinding)*num);
+		memset(joybindings[joystick], 0, sizeof(keybinding)*num);
+	}
+	joybindings[joystick][button].bind_type = bind_type;
+	joybindings[joystick][button].subtype_a = subtype_a;
+	joybindings[joystick][button].subtype_b = subtype_b;
+	joybindings[joystick][button].value = value;
+}
+
+void bind_dpad(int joystick, int dpad, int direction, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
+{
+	if (joystick >= MAX_JOYSTICKS) {
+		return;
+	}
+	if (!joydpads[joystick]) {
+		int num = render_joystick_num_hats(joystick);
+		if (!num) {
+			return;
+		}
+		joydpads[joystick] = malloc(sizeof(joydpad)*num);
+		memset(joydpads[joystick], 0, sizeof(joydpad)*num);
+	}
+	for (int i = 0; i < 4; i ++) {
+		if (dpadbits[i] & direction) {
+			joydpads[joystick][dpad].bindings[i].bind_type = bind_type;
+			joydpads[joystick][dpad].bindings[i].subtype_a = subtype_a;
+			joydpads[joystick][dpad].bindings[i].subtype_b = subtype_b;
+			joydpads[joystick][dpad].bindings[i].value = value;
+			break;
+		}
+	}
+}
+
 #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)
@@ -907,19 +958,31 @@
 	bind_key(keycode, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
 }
 
+void bind_button_gamepad(int joystick, int joybutton, int gamepadnum, int padbutton)
+{
+	if (gamepadnum < 1 || gamepadnum > 2) {
+		return;
+	}
+	uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
+	bind_button(joystick, joybutton, bind_type, padbutton >> 12, padbutton >> 8 & 0xF, padbutton & 0xFF);
+}
+
+void bind_dpad_gamepad(int joystick, int dpad, uint8_t direction, int gamepadnum, int button)
+{
+	if (gamepadnum < 1 || gamepadnum > 2) {
+		return;
+	}
+	uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
+	bind_dpad(joystick, dpad, direction, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
+}
+
 void bind_ui(int keycode, ui_action action)
 {
 	bind_key(keycode, BIND_UI, action, 0, 0);
 }
 
-void handle_keydown(int keycode)
+void handle_binding_down(keybinding * binding)
 {
-	int bucket = keycode >> 8 & 0xFF;
-	if (!bindings[bucket]) {
-		return;
-	}
-	int idx = keycode & 0xFF;
-	keybinding * binding = bindings[bucket] + idx;
 	switch(binding->bind_type)
 	{
 	case BIND_GAMEPAD1:
@@ -941,10 +1004,7 @@
 	}
 }
 
-uint8_t ui_debug_mode = 0;
-uint8_t ui_debug_pal = 0;
-
-void handle_keyup(int keycode)
+void handle_keydown(int keycode)
 {
 	int bucket = keycode >> 8 & 0xFF;
 	if (!bindings[bucket]) {
@@ -952,6 +1012,23 @@
 	}
 	int idx = keycode & 0xFF;
 	keybinding * binding = bindings[bucket] + idx;
+	handle_binding_down(binding);
+}
+
+void handle_joydown(int joystick, int button)
+{
+	if (!joybindings[joystick]) {
+		return;
+	}
+	keybinding * binding = joybindings[joystick] + button;
+	handle_binding_down(binding);
+}
+
+uint8_t ui_debug_mode = 0;
+uint8_t ui_debug_pal = 0;
+
+void handle_binding_up(keybinding * binding)
+{
 	switch(binding->bind_type)
 	{
 	case BIND_GAMEPAD1:
@@ -995,6 +1072,44 @@
 	}
 }
 
+void handle_keyup(int keycode)
+{
+	int bucket = keycode >> 8 & 0xFF;
+	if (!bindings[bucket]) {
+		return;
+	}
+	int idx = keycode & 0xFF;
+	keybinding * binding = bindings[bucket] + idx;
+	handle_binding_up(binding);
+}
+
+void handle_joyup(int joystick, int button)
+{
+	if (!joybindings[joystick]) {
+		return;
+	}
+	keybinding * binding = joybindings[joystick] + button;
+	handle_binding_up(binding);
+}
+
+void handle_joy_dpad(int joystick, int dpadnum, uint8_t value)
+{
+	if (!joydpads[joystick]) {
+		return;
+	}
+	joydpad * dpad = joydpads[joystick] + dpadnum;
+	uint8_t newdown = (value ^ dpad->state) & value;
+	uint8_t newup = ((~value) ^ (~dpad->state)) & (~value);
+	dpad->state = value;
+	for (int i = 0; i < 4; i++) {
+		if (newdown & dpadbits[i]) {
+			handle_binding_down(dpad->bindings + i);
+		} else if(newup & dpadbits[i]) {
+			handle_binding_up(dpad->bindings + i);
+		}
+	}
+}
+
 void set_keybindings()
 {
 	bind_gamepad(RENDERKEY_UP, 1, DPAD_UP);
@@ -1012,6 +1127,19 @@
 	bind_ui('[', UI_DEBUG_MODE_INC);
 	bind_ui(']', UI_DEBUG_PAL_INC);
 	bind_ui('u', UI_ENTER_DEBUGGER);
+	
+	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);
 }
 
 typedef struct bp_def {