diff options
author | Mike Pavone <pavone@retrodev.com> | 2013-06-23 22:27:12 -0700 |
---|---|---|
committer | Mike Pavone <pavone@retrodev.com> | 2013-06-23 22:27:12 -0700 |
commit | 3e393ab13479761a48120db84890c96c6ff5bed9 (patch) | |
tree | 3cc44beaa971aa2c00dea25b9ad42eac96475c90 | |
parent | 787f48aff2ba81c92b0fb1970f6fbacb43ba10d2 (diff) |
Implement basic joystick support
-rw-r--r-- | blastem.c | 150 | ||||
-rw-r--r-- | blastem.h | 3 | ||||
-rw-r--r-- | render.h | 16 | ||||
-rw-r--r-- | render_sdl.c | 42 |
4 files changed, 195 insertions, 16 deletions
@@ -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 { @@ -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_ @@ -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); |