diff --git a/config.def.h b/config.def.h index fed2f9895e..ad46235515 100644 --- a/config.def.h +++ b/config.def.h @@ -139,15 +139,7 @@ static const bool audio_sync = true; // How far an axis must be tilted to result in a button press #define AXIS_THRESHOLD 0.5 -#define AXIS_NEG(x) ((uint32_t)(x << 16) | 0xFFFF) -#define AXIS_POS(x) ((uint32_t)(x) | 0xFFFF0000U) -#define AXIS_NONE ((uint32_t)0xFFFFFFFFU) -#define NO_BTN 0xFFFF // I hope no joypad will ever have this many buttons ... ;) - // To figure out which joypad buttons to use, check jstest or similar. -// Axes are configured using the axis number for the positive (up, right) -// direction and the number's two's-complement (~) for negative directions. -// To use the axis, set the button to -1. // SDL sometimes reverses the axes for some odd reason, but hey. :D // Player 1 diff --git a/driver.h b/driver.h index 778bce9172..73ae142c48 100644 --- a/driver.h +++ b/driver.h @@ -64,9 +64,26 @@ typedef struct audio_driver const char *ident; } audio_driver_t; +#define AXIS_NEG(x) ((uint32_t)(x << 16) | 0xFFFF) +#define AXIS_POS(x) ((uint32_t)(x) | 0xFFFF0000U) +#define AXIS_NONE ((uint32_t)0xFFFFFFFFU) + #define AXIS_NEG_GET(x) ((x >> 16) & 0xFFFF) #define AXIS_POS_GET(x) (x & 0xFFFF) #define AXIS_NONE ((uint32_t)0xFFFFFFFFU) + +#define NO_BTN 0xFFFF // I hope no joypad will ever have this many buttons ... ;) + +#define HAT_UP_MASK (1 << 15) +#define HAT_DOWN_MASK (1 << 14) +#define HAT_LEFT_MASK (1 << 13) +#define HAT_RIGHT_MASK (1 << 12) +#define HAT_MAP(x, hat) ((x & ((1 << 12) - 1)) | hat) + +#define HAT_MASK (HAT_UP_MASK | HAT_DOWN_MASK | HAT_LEFT_MASK | HAT_RIGHT_MASK) +#define GET_HAT_DIR(x) (x & HAT_MASK) +#define GET_HAT(x) (x & (~HAT_MASK)) + typedef struct input_driver { void* (*init)(void); diff --git a/input/sdl.c b/input/sdl.c index b506a0d92d..8968862d32 100644 --- a/input/sdl.c +++ b/input/sdl.c @@ -24,6 +24,7 @@ #include #include #include "ssnes_sdl_input.h" +#include "config.def.h" static void* sdl_input_init(void) { @@ -52,13 +53,14 @@ static void* sdl_input_init(void) SSNES_LOG("Opened Joystick: %s\n", SDL_JoystickName(i)); sdl->num_axes[i] = SDL_JoystickNumAxes(sdl->joysticks[i]); sdl->num_buttons[i] = SDL_JoystickNumButtons(sdl->joysticks[i]); + sdl->num_hats[i] = SDL_JoystickNumHats(sdl->joysticks[i]); } return sdl; } -static bool sdl_key_pressed(void *data, int key) +static bool sdl_key_pressed(int key) { int num_keys; Uint8 *keymap = SDL_GetKeyState(&num_keys); @@ -69,27 +71,60 @@ static bool sdl_key_pressed(void *data, int key) return keymap[key]; } -static bool sdl_is_pressed(sdl_input_t *sdl, int port_num, const struct snes_keybind *key) +static bool sdl_joykey_pressed(sdl_input_t *sdl, int port_num, uint16_t joykey) { - if (sdl_key_pressed(sdl, key->key)) - return true; - if (port_num >= sdl->num_joysticks) - return false; - if (key->joykey < sdl->num_buttons[port_num] && SDL_JoystickGetButton(sdl->joysticks[port_num], key->joykey)) - return true; - - if (key->joyaxis != AXIS_NONE) + // Check hat. + if (GET_HAT_DIR(joykey)) { - if (AXIS_NEG_GET(key->joyaxis) < sdl->num_axes[port_num]) + int hat = GET_HAT(joykey); + if (hat < sdl->num_hats[port_num]) { - Sint16 val = SDL_JoystickGetAxis(sdl->joysticks[port_num], AXIS_NEG_GET(key->joyaxis)); + Uint8 dir = SDL_JoystickGetHat(sdl->joysticks[port_num], hat); + switch (GET_HAT_DIR(joykey)) + { + case HAT_UP_MASK: + if (dir == SDL_HAT_UP || dir == SDL_HAT_RIGHTUP || dir == SDL_HAT_LEFTUP) + return true; + break; + case HAT_DOWN_MASK: + if (dir == SDL_HAT_DOWN || dir == SDL_HAT_LEFTDOWN || dir == SDL_HAT_RIGHTDOWN) + return true; + break; + case HAT_LEFT_MASK: + if (dir == SDL_HAT_LEFT || dir == SDL_HAT_LEFTDOWN || dir == SDL_HAT_LEFTUP) + return true; + break; + case HAT_RIGHT_MASK: + if (dir == SDL_HAT_RIGHT || dir == SDL_HAT_RIGHTDOWN || dir == SDL_HAT_RIGHTUP) + return true; + break; + default: + break; + } + } + } + else // Check the button + { + if (joykey < sdl->num_buttons[port_num] && SDL_JoystickGetButton(sdl->joysticks[port_num], joykey)) + return true; + } + return false; +} + +static bool sdl_axis_pressed(sdl_input_t *sdl, int port_num, uint32_t joyaxis) +{ + if (joyaxis != AXIS_NONE) + { + if (AXIS_NEG_GET(joyaxis) < sdl->num_axes[port_num]) + { + Sint16 val = SDL_JoystickGetAxis(sdl->joysticks[port_num], AXIS_NEG_GET(joyaxis)); float scaled = (float)val / 0x8000; if (scaled < -g_settings.input.axis_threshold) return true; } - if (AXIS_POS_GET(key->joyaxis) < sdl->num_axes[port_num]) + if (AXIS_POS_GET(joyaxis) < sdl->num_axes[port_num]) { - Sint16 val = SDL_JoystickGetAxis(sdl->joysticks[port_num], AXIS_POS_GET(key->joyaxis)); + Sint16 val = SDL_JoystickGetAxis(sdl->joysticks[port_num], AXIS_POS_GET(joyaxis)); float scaled = (float)val / 0x8000; if (scaled > g_settings.input.axis_threshold) return true; @@ -99,8 +134,23 @@ static bool sdl_is_pressed(sdl_input_t *sdl, int port_num, const struct snes_key return false; } +static bool sdl_is_pressed(sdl_input_t *sdl, int port_num, const struct snes_keybind *key) +{ + if (sdl_key_pressed(key->key)) + return true; + if (port_num >= sdl->num_joysticks) + return false; + if (sdl_joykey_pressed(sdl, port_num, key->joykey)) + return true; + if (sdl_axis_pressed(sdl, port_num, key->joyaxis)) + return true; + + return false; +} + static bool sdl_bind_button_pressed(void *data, int key) { + // Only let player 1 use special binds called from main loop. const struct snes_keybind *binds = g_settings.input.binds[0]; for (int i = 0; binds[i].id != -1; i++) { diff --git a/input/ssnes_sdl_input.h b/input/ssnes_sdl_input.h index 5833396e3f..519477d64a 100644 --- a/input/ssnes_sdl_input.h +++ b/input/ssnes_sdl_input.h @@ -24,6 +24,7 @@ typedef struct sdl_input SDL_Joystick *joysticks[2]; unsigned num_axes[2]; unsigned num_buttons[2]; + unsigned num_hats[2]; unsigned num_joysticks; // A video driver could pre-init with the SDL driver and have it handle resizing events... diff --git a/settings.c b/settings.c index 8e352cea4b..219b77119d 100644 --- a/settings.c +++ b/settings.c @@ -17,10 +17,10 @@ #include "general.h" #include "conf/config_file.h" -#include "config.def.h" #include #include #include "hqflt/filters.h" +#include "config.def.h" #ifdef HAVE_CONFIG_H #include "config.h" @@ -422,7 +422,7 @@ static int find_sdlk_key(const char *str) static void read_keybinds(config_file_t *conf) { char *tmp_key = NULL; - int tmp_btn; + char *tmp_btn = NULL; char *tmp_axis = NULL; for (int j = 0; j < 1; j++) @@ -444,10 +444,35 @@ static void read_keybinds(config_file_t *conf) tmp_key = NULL; } - if (bind_maps[j][i].btn && config_get_int(conf, bind_maps[j][i].btn, &tmp_btn)) + if (bind_maps[j][i].btn && config_get_string(conf, bind_maps[j][i].btn, &tmp_btn)) { - if (tmp_btn >= 0) - bind->joykey = tmp_btn; + const char *btn = tmp_btn; + if (*btn++ == 'h') + { + if (isdigit(*btn)) + { + char *dir = NULL; + int hat = strtol(btn, &dir, 0); + int hat_dir = 0; + if (dir) + { + if (strcasecmp(dir, "up") == 0) + hat_dir = HAT_UP_MASK; + else if (strcasecmp(dir, "down") == 0) + hat_dir = HAT_DOWN_MASK; + else if (strcasecmp(dir, "left") == 0) + hat_dir = HAT_LEFT_MASK; + else if (strcasecmp(dir, "right") == 0) + hat_dir = HAT_RIGHT_MASK; + + if (hat_dir) + bind->joykey = HAT_MAP(hat, hat_dir); + } + } + } + else + bind->joykey = strtol(tmp_btn, NULL, 0); + free(tmp_btn); } if (bind_maps[j][i].axis && config_get_string(conf, bind_maps[j][i].axis, &tmp_axis))