mirror of
https://github.com/libretro/RetroArch.git
synced 2024-10-08 07:03:30 +00:00
Add support for joypad "hats".
This commit is contained in:
parent
4b9c07428c
commit
a365989557
@ -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
|
||||
|
17
driver.h
17
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);
|
||||
|
78
input/sdl.c
78
input/sdl.c
@ -24,6 +24,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <libsnes.hpp>
|
||||
#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++)
|
||||
{
|
||||
|
@ -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...
|
||||
|
35
settings.c
35
settings.c
@ -17,10 +17,10 @@
|
||||
|
||||
#include "general.h"
|
||||
#include "conf/config_file.h"
|
||||
#include "config.def.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#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))
|
||||
|
Loading…
Reference in New Issue
Block a user