changeset 398:c26e48a93fa3

Make keybindings data driven so they can be populated from a config file later
author Mike Pavone <pavone@retrodev.com>
date Fri, 14 Jun 2013 00:25:04 -0700
parents c20607e5b272
children acaae7c3d34c
files blastem.c blastem.h render.h render_sdl.c
diffstat 4 files changed, 199 insertions(+), 126 deletions(-) [+]
line wrap: on
line diff
--- a/blastem.c	Thu Jun 13 22:23:15 2013 -0700
+++ b/blastem.c	Fri Jun 14 00:25:04 2013 -0700
@@ -988,6 +988,174 @@
 	return context;
 }
 
+enum {
+	BIND_NONE,
+	BIND_GAMEPAD1,
+	BIND_GAMEPAD2,
+	BIND_UI
+};
+
+typedef enum {
+	UI_DEBUG_MODE_INC,
+	UI_DEBUG_PAL_INC,
+	UI_ENTER_DEBUGGER
+} ui_action;
+
+typedef struct {
+	uint8_t bind_type;
+	uint8_t subtype_a;
+	uint8_t subtype_b;
+	uint8_t value;
+} keybinding;
+
+keybinding * bindings[256];
+
+void bind_key(int keycode, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
+{
+	int bucket = keycode >> 8 & 0xFF;
+	if (!bindings[bucket]) {
+		bindings[bucket] = malloc(sizeof(keybinding) * 256);
+		memset(bindings[bucket], 0, sizeof(keybinding) * 256);
+	}
+	int idx = keycode & 0xFF;
+	bindings[bucket][idx].bind_type = bind_type;
+	bindings[bucket][idx].subtype_a = subtype_a;
+	bindings[bucket][idx].subtype_b = subtype_b;
+	bindings[bucket][idx].value = value;
+}
+
+#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)
+#define BUTTON_Z     GAMEPAD_BUTTON(GAMEPAD_EXTRA, GAMEPAD_NONE, 0x01)
+#define DPAD_DOWN    GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_TH1, 0x02)
+#define BUTTON_Y     GAMEPAD_BUTTON(GAMEPAD_EXTRA, GAMEPAD_NONE, 0x02)
+#define DPAD_LEFT    GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x04)
+#define BUTTON_X     GAMEPAD_BUTTON(GAMEPAD_EXTRA, GAMEPAD_NONE, 0x04)
+#define DPAD_RIGHT   GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x08)
+#define BUTTON_MODE  GAMEPAD_BUTTON(GAMEPAD_EXTRA, GAMEPAD_NONE, 0x08)
+#define BUTTON_A     GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_NONE, 0x10)
+#define BUTTON_B     GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x10)
+#define BUTTON_START GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_NONE, 0x20)
+#define BUTTON_C     GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x20)
+
+void bind_gamepad(int keycode, int gamepadnum, int button)
+{
+	
+	if (gamepadnum < 1 || gamepadnum > 2) {
+		return;
+	}
+	uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
+	bind_key(keycode, 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)
+{
+	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:
+		if (binding->subtype_a <= GAMEPAD_EXTRA) {
+			gamepad_1.input[binding->subtype_a] |= binding->value;
+		}
+		if (binding->subtype_b <= GAMEPAD_EXTRA) {
+			gamepad_1.input[binding->subtype_b] |= binding->value;
+		}
+		break;
+	case BIND_GAMEPAD2:
+		if (binding->subtype_a <= GAMEPAD_EXTRA) {
+			gamepad_2.input[binding->subtype_a] |= binding->value;
+		}
+		if (binding->subtype_b <= GAMEPAD_EXTRA) {
+			gamepad_2.input[binding->subtype_b] |= binding->value;
+		}
+		break;
+	}
+}
+
+uint8_t ui_debug_mode = 0;
+uint8_t ui_debug_pal = 0;
+
+void handle_keyup(int keycode)
+{
+	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:
+		if (binding->subtype_a <= GAMEPAD_EXTRA) {
+			gamepad_1.input[binding->subtype_a] &= ~binding->value;
+		}
+		if (binding->subtype_b <= GAMEPAD_EXTRA) {
+			gamepad_1.input[binding->subtype_b] &= ~binding->value;
+		}
+		break;
+	case BIND_GAMEPAD2:
+		if (binding->subtype_a <= GAMEPAD_EXTRA) {
+			gamepad_2.input[binding->subtype_a] &= ~binding->value;
+		}
+		if (binding->subtype_b <= GAMEPAD_EXTRA) {
+			gamepad_2.input[binding->subtype_b] &= ~binding->value;
+		}
+		break;
+	case BIND_UI:
+		switch (binding->subtype_a)
+		{
+		case UI_DEBUG_MODE_INC:
+			ui_debug_mode++;
+			if (ui_debug_mode == 4) {
+				ui_debug_mode = 0;
+			}
+			render_debug_mode(ui_debug_mode);
+			break;
+		case UI_DEBUG_PAL_INC:
+			ui_debug_pal++;
+			if (ui_debug_pal == 4) {
+				ui_debug_pal = 0;
+			}
+			render_debug_pal(ui_debug_pal);
+			break;
+		case UI_ENTER_DEBUGGER:
+			break_on_sync = 1;
+			break;
+		}
+		break;
+	}
+}
+
+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);
+}
+
 typedef struct bp_def {
 	struct bp_def * next;
 	uint32_t address;
@@ -2000,6 +2168,7 @@
 	if (i < 0) {
 		strcpy(sram_filename + fname_size, ".sram");
 	}
+	set_keybindings();
 	
 	init_run_cpu(&gen, debug, address_log);
 	return 0;
--- a/blastem.h	Thu Jun 13 22:23:15 2013 -0700
+++ b/blastem.h	Fri Jun 14 00:25:04 2013 -0700
@@ -35,6 +35,7 @@
 #define GAMEPAD_TH0 0
 #define GAMEPAD_TH1 1
 #define GAMEPAD_EXTRA 2
+#define GAMEPAD_NONE 0xF
 
 extern io_port gamepad_1;
 extern io_port gamepad_2;
@@ -42,6 +43,8 @@
 void io_adjust_cycles(io_port * pad, uint32_t current_cycle, uint32_t deduction);
 uint16_t read_dma_value(uint32_t address);
 m68k_context * debugger(m68k_context * context, uint32_t address);
+void handle_keydown(int keycode);
+void handle_keyup(int keycode);
 
 #endif //BLASTEM_H_
 
--- a/render.h	Thu Jun 13 22:23:15 2013 -0700
+++ b/render.h	Fri Jun 14 00:25:04 2013 -0700
@@ -1,5 +1,5 @@
-#ifndef RENDER_SDL_H_
-#define RENDER_SDL_H_
+#ifndef RENDER_H_
+#define RENDER_H_
 
 #include "vdp.h"
 #include "psg.h"
@@ -13,6 +13,15 @@
 void render_fps(uint32_t fps);
 uint32_t render_audio_buffer();
 uint32_t render_sample_rate();
+void render_debug_mode(uint8_t mode);
+void render_debug_pal(uint8_t pal);
 
-#endif //RENDER_SDL_H_
+//TODO: Throw an ifdef in here once there's more than one renderer
+#include <SDL.h>
+#define RENDERKEY_UP    SDLK_UP
+#define RENDERKEY_DOWN  SDLK_DOWN
+#define RENDERKEY_LEFT  SDLK_LEFT
+#define RENDERKEY_RIGHT SDLK_RIGHT
 
+#endif //RENDER_H_
+
--- a/render_sdl.c	Thu Jun 13 22:23:15 2013 -0700
+++ b/render_sdl.c	Fri Jun 14 00:25:04 2013 -0700
@@ -1,4 +1,3 @@
-#include <SDL.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include "render.h"
@@ -299,135 +298,28 @@
 	}
 }
 
-#define DPAD_UP      0x01
-#define BUTTON_Z     0x01
-#define DPAD_DOWN    0x02
-#define BUTTON_Y     0x02
-#define DPAD_LEFT    0x04
-#define BUTTON_X     0x04
-#define DPAD_RIGHT   0x08
-#define BUTTON_MODE  0x08
-#define BUTTON_A     0x10
-#define BUTTON_B     0x10
-#define BUTTON_START 0x20
-#define BUTTON_C     0x20
+void render_debug_mode(uint8_t mode)
+{
+	if (mode < 4) {
+		render_dbg = mode;
+	}
+}
+
+void render_debug_pal(uint8_t pal)
+{
+	if (pal < 4) {
+		debug_pal = pal;
+	}
+}
 
 int32_t handle_event(SDL_Event *event)
 {
-	FILE * outfile;
 	switch (event->type) {
 	case SDL_KEYDOWN:
-		switch(event->key.keysym.sym)
-		{
-		case SDLK_LEFTBRACKET:
-			render_dbg++;
-			if (render_dbg == 4) {
-				render_dbg = 0;
-			}
-			break;
-		case SDLK_RIGHTBRACKET:
-			debug_pal++;
-			if (debug_pal == 4) {
-				debug_pal = 0;
-			}
-			break;
-		case SDLK_t:
-			/*outfile = fopen("state.gst", "wb");
-			fwrite("GST\0\0\0\xE0\x40", 1, 8, outfile);
-			vdp_save_state(context, outfile);
-			fclose(outfile);
-			puts("state saved to state.gst");*/
-			break;
-		case SDLK_u:
-			return 1;
-		case SDLK_RETURN:
-			gamepad_1.input[GAMEPAD_TH0] |= BUTTON_START;
-			break;
-		case SDLK_UP:
-			gamepad_1.input[GAMEPAD_TH0] |= DPAD_UP;
-			gamepad_1.input[GAMEPAD_TH1] |= DPAD_UP;
-			break;
-		case SDLK_DOWN:
-			gamepad_1.input[GAMEPAD_TH0] |= DPAD_DOWN;
-			gamepad_1.input[GAMEPAD_TH1] |= DPAD_DOWN;
-			break;
-		case SDLK_LEFT:
-			gamepad_1.input[GAMEPAD_TH1] |= DPAD_LEFT;
-			break;
-		case SDLK_RIGHT:
-			gamepad_1.input[GAMEPAD_TH1] |= DPAD_RIGHT;
-			break;
-		case SDLK_a:
-			gamepad_1.input[GAMEPAD_TH0] |= BUTTON_A;
-			//printf("BUTTON_A Dn | GAMEPAD_TH0: %X\n", gamepad_1.input[GAMEPAD_TH0]);
-			break;
-		case SDLK_s:
-			gamepad_1.input[GAMEPAD_TH1] |= BUTTON_B;
-			gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_B;
-			break;
-		case SDLK_d:
-			gamepad_1.input[GAMEPAD_TH1] |= BUTTON_C;
-			gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_C;
-			break;
-		case SDLK_q:
-			gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_X;
-			break;
-		case SDLK_w:
-			gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_Y;
-			break;
-		case SDLK_e:
-			gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_Z;
-			break;
-		case SDLK_f:
-			gamepad_1.input[GAMEPAD_EXTRA] |= BUTTON_MODE;
-			break;
-		}
+		handle_keydown(event->key.keysym.sym);
 		break;
 	case SDL_KEYUP:
-		switch(event->key.keysym.sym)
-		{
-		case SDLK_RETURN:
-			gamepad_1.input[GAMEPAD_TH0] &= ~BUTTON_START;
-			break;
-		case SDLK_UP:
-			gamepad_1.input[GAMEPAD_TH0] &= ~DPAD_UP;
-			gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_UP;
-			break;
-		case SDLK_DOWN:
-			gamepad_1.input[GAMEPAD_TH0] &= ~DPAD_DOWN;
-			gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_DOWN;
-			break;
-		case SDLK_LEFT:
-			gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_LEFT;
-			break;
-		case SDLK_RIGHT:
-			gamepad_1.input[GAMEPAD_TH1] &= ~DPAD_RIGHT;
-			break;
-		case SDLK_a:
-			gamepad_1.input[GAMEPAD_TH0] &= ~BUTTON_A;
-			//printf("BUTTON_A Up | GAMEPAD_TH0: %X\n", gamepad_1.input[GAMEPAD_TH0]);
-			break;
-		case SDLK_s:
-			gamepad_1.input[GAMEPAD_TH1] &= ~BUTTON_B;
-			gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_B;
-			break;
-		case SDLK_d:
-			gamepad_1.input[GAMEPAD_TH1] &= ~BUTTON_C;
-			gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_C;
-			break;
-		case SDLK_q:
-			gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_X;
-			break;
-		case SDLK_w:
-			gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_Y;
-			break;
-		case SDLK_e:
-			gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_Z;
-			break;
-		case SDLK_f:
-			gamepad_1.input[GAMEPAD_EXTRA] &= ~BUTTON_MODE;
-			break;
-		}
+		handle_keyup(event->key.keysym.sym);
 		break;
 	case SDL_QUIT:
 		puts("");