summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2013-06-23 22:27:12 -0700
committerMike Pavone <pavone@retrodev.com>2013-06-23 22:27:12 -0700
commit3e393ab13479761a48120db84890c96c6ff5bed9 (patch)
tree3cc44beaa971aa2c00dea25b9ad42eac96475c90
parent787f48aff2ba81c92b0fb1970f6fbacb43ba10d2 (diff)
Implement basic joystick support
-rw-r--r--blastem.c150
-rw-r--r--blastem.h3
-rw-r--r--render.h16
-rw-r--r--render_sdl.c42
4 files changed, 195 insertions, 16 deletions
diff --git a/blastem.c b/blastem.c
index 7262591..01be7db 100644
--- a/blastem.c
+++ b/blastem.c
@@ -866,7 +866,15 @@ typedef struct {
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 @@ void bind_key(int keycode, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype
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 @@ void bind_gamepad(int keycode, int gamepadnum, int button)
bind_key(keycode, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
}
-void bind_ui(int keycode, ui_action action)
+void bind_button_gamepad(int joystick, int joybutton, int gamepadnum, int padbutton)
{
- bind_key(keycode, BIND_UI, action, 0, 0);
+ 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 handle_keydown(int keycode)
+void bind_dpad_gamepad(int joystick, int dpad, uint8_t direction, int gamepadnum, int button)
{
- int bucket = keycode >> 8 & 0xFF;
- if (!bindings[bucket]) {
+ if (gamepadnum < 1 || gamepadnum > 2) {
return;
}
- int idx = keycode & 0xFF;
- keybinding * binding = bindings[bucket] + idx;
+ 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_binding_down(keybinding * binding)
+{
switch(binding->bind_type)
{
case BIND_GAMEPAD1:
@@ -941,10 +1004,7 @@ void handle_keydown(int keycode)
}
}
-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 @@ void handle_keyup(int keycode)
}
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)
}
}
+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 @@ void set_keybindings()
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 {
diff --git a/blastem.h b/blastem.h
index fce42a4..3688ea9 100644
--- a/blastem.h
+++ b/blastem.h
@@ -45,6 +45,9 @@ 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);
+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);
#endif //BLASTEM_H_
diff --git a/render.h b/render.h
index 5fb9818..80823dc 100644
--- a/render.h
+++ b/render.h
@@ -16,13 +16,21 @@ uint32_t render_sample_rate();
void render_debug_mode(uint8_t mode);
void render_debug_pal(uint8_t pal);
void process_events();
+int render_joystick_num_buttons(int joystick);
+int render_joystick_num_hats(int joystick);
//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
+#define RENDERKEY_UP SDLK_UP
+#define RENDERKEY_DOWN SDLK_DOWN
+#define RENDERKEY_LEFT SDLK_LEFT
+#define RENDERKEY_RIGHT SDLK_RIGHT
+#define RENDER_DPAD_UP SDL_HAT_UP
+#define RENDER_DPAD_DOWN SDL_HAT_DOWN
+#define RENDER_DPAD_LEFT SDL_HAT_LEFT
+#define RENDER_DPAD_RIGHT SDL_HAT_RIGHT
+
+#define MAX_JOYSTICKS 8
#endif //RENDER_H_
diff --git a/render_sdl.c b/render_sdl.c
index 298c944..5306ef0 100644
--- a/render_sdl.c
+++ b/render_sdl.c
@@ -72,9 +72,12 @@ void render_close_audio()
SDL_CloseAudio();
}
+SDL_Joystick * joysticks[MAX_JOYSTICKS];
+int num_joysticks;
+
void render_init(int width, int height, char * title, uint32_t fps)
{
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) {
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
exit(1);
}
@@ -145,6 +148,18 @@ void render_init(int width, int height, char * title, uint32_t fps)
sample_rate = actual.freq;
printf("Initialized audio at frequency %d with a %d sample buffer\n", actual.freq, actual.samples);
SDL_PauseAudio(0);
+ num_joysticks = SDL_NumJoysticks();
+ if (num_joysticks > MAX_JOYSTICKS) {
+ num_joysticks = MAX_JOYSTICKS;
+ }
+ for (int i = 0; i < num_joysticks; i++) {
+ printf("Joystick %d: %s\n", i, SDL_JoystickName(i));
+ SDL_Joystick * joy = joysticks[i] = SDL_JoystickOpen(i);
+ if (joy) {
+ printf("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy));
+ }
+ }
+ SDL_JoystickEventState(SDL_ENABLE);
}
uint16_t blankbuf[320*240];
@@ -281,6 +296,22 @@ void render_context(vdp_context * context)
}
}
+int render_joystick_num_buttons(int joystick)
+{
+ if (joystick >= num_joysticks) {
+ return 0;
+ }
+ return SDL_JoystickNumButtons(joysticks[joystick]);
+}
+
+int render_joystick_num_hats(int joystick)
+{
+ if (joystick >= num_joysticks) {
+ return 0;
+ }
+ return SDL_JoystickNumHats(joysticks[joystick]);
+}
+
void render_wait_quit(vdp_context * context)
{
SDL_Event event;
@@ -329,6 +360,15 @@ int32_t handle_event(SDL_Event *event)
case SDL_KEYUP:
handle_keyup(event->key.keysym.sym);
break;
+ case SDL_JOYBUTTONDOWN:
+ handle_joydown(event->jbutton.which, event->jbutton.button);
+ break;
+ case SDL_JOYBUTTONUP:
+ handle_joyup(event->jbutton.which, event->jbutton.button);
+ break;
+ case SDL_JOYHATMOTION:
+ handle_joy_dpad(event->jbutton.which, event->jhat.hat, event->jhat.value);
+ break;
case SDL_QUIT:
puts("");
exit(0);