Add support for joypad "hats".

This commit is contained in:
Themaister 2011-01-08 22:15:02 +01:00
parent 4b9c07428c
commit a365989557
5 changed files with 112 additions and 27 deletions

View File

@ -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

View File

@ -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);

View File

@ -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++)
{

View File

@ -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...

View File

@ -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))