mirror of
https://github.com/libretro/RetroArch
synced 2025-03-03 04:14:00 +00:00
Add support for RETRO_DEVICE_ANALOG.
This commit is contained in:
parent
32383f168b
commit
c440c7a50a
18
config.def.h
18
config.def.h
@ -329,6 +329,15 @@ static const struct snes_keybind snes_keybinds_1[] = {
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_L3, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_R3, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
|
||||
{ true, RARCH_ANALOG_LEFT_X_PLUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_LEFT_X_MINUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_LEFT_Y_PLUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_LEFT_Y_MINUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_RIGHT_X_PLUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_RIGHT_X_MINUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_RIGHT_Y_PLUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_RIGHT_Y_MINUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
|
||||
{ true, RARCH_FAST_FORWARD_KEY, SK_SPACE, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_FAST_FORWARD_HOLD_KEY, SK_l, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_LOAD_STATE_KEY, SK_F4, NO_BTN, AXIS_NONE },
|
||||
@ -374,6 +383,15 @@ static const struct snes_keybind snes_keybinds_rest[] = {
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_R2, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_L3, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_R3, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
|
||||
{ true, RARCH_ANALOG_LEFT_X_PLUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_LEFT_X_MINUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_LEFT_Y_PLUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_LEFT_Y_MINUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_RIGHT_X_PLUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_RIGHT_X_MINUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_RIGHT_Y_PLUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_ANALOG_RIGHT_Y_MINUS, SK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
};
|
||||
|
||||
#endif
|
||||
|
23
driver.h
23
driver.h
@ -37,10 +37,27 @@
|
||||
#define AUDIO_MAX_RATIO 16
|
||||
|
||||
// libretro has 16 buttons from 0-15 (libretro.h)
|
||||
#define RARCH_FIRST_META_KEY 16
|
||||
enum
|
||||
// Analog binds use RETRO_DEVICE_ANALOG, but we follow the same scheme internally
|
||||
// in RetroArch for simplicity,
|
||||
// so they are mapped into [16, 23].
|
||||
#define RARCH_FIRST_ANALOG_BIND 16
|
||||
#define RARCH_FIRST_META_KEY RARCH_ANALOG_BIND_LIST_END
|
||||
enum // RetroArch specific bind IDs.
|
||||
{
|
||||
RARCH_FAST_FORWARD_KEY = RARCH_FIRST_META_KEY,
|
||||
// Analogs (RETRO_DEVICE_ANALOG)
|
||||
RARCH_ANALOG_LEFT_X_PLUS = RARCH_FIRST_ANALOG_BIND,
|
||||
RARCH_ANALOG_LEFT_X_MINUS,
|
||||
RARCH_ANALOG_LEFT_Y_PLUS,
|
||||
RARCH_ANALOG_LEFT_Y_MINUS,
|
||||
RARCH_ANALOG_RIGHT_X_PLUS,
|
||||
RARCH_ANALOG_RIGHT_X_MINUS,
|
||||
RARCH_ANALOG_RIGHT_Y_PLUS,
|
||||
RARCH_ANALOG_RIGHT_Y_MINUS,
|
||||
|
||||
RARCH_ANALOG_BIND_LIST_END,
|
||||
|
||||
// Command binds.
|
||||
RARCH_FAST_FORWARD_KEY = RARCH_ANALOG_BIND_LIST_END,
|
||||
RARCH_FAST_FORWARD_HOLD_KEY,
|
||||
RARCH_LOAD_STATE_KEY,
|
||||
RARCH_SAVE_STATE_KEY,
|
||||
|
@ -190,47 +190,60 @@ static bool dinput_joykey_pressed(sdl_dinput_t *di, unsigned port_num, uint16_t
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool dinput_joyaxis_pressed(sdl_dinput_t *di, unsigned port_num, uint32_t joyaxis)
|
||||
int16_t sdl_dinput_axis(sdl_dinput_t *di, unsigned port_num, const struct snes_keybind *key)
|
||||
{
|
||||
uint32_t joyaxis = key->joyaxis;
|
||||
|
||||
if (joyaxis == AXIS_NONE)
|
||||
return 0;
|
||||
|
||||
int val = 0;
|
||||
|
||||
int axis = -1;
|
||||
bool is_neg = false;
|
||||
bool is_pos = false;
|
||||
|
||||
if (AXIS_NEG_GET(joyaxis) <= 5)
|
||||
{
|
||||
axis = AXIS_NEG_GET(joyaxis);
|
||||
is_neg = true;
|
||||
}
|
||||
else if (AXIS_POS_GET(joyaxis) <= 5)
|
||||
{
|
||||
axis = AXIS_POS_GET(joyaxis);
|
||||
is_pos = true;
|
||||
}
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case 0: val = di->joy_state[port_num].lX; break;
|
||||
case 1: val = di->joy_state[port_num].lY; break;
|
||||
case 2: val = di->joy_state[port_num].lZ; break;
|
||||
case 3: val = di->joy_state[port_num].lRx; break;
|
||||
case 4: val = di->joy_state[port_num].lRy; break;
|
||||
case 5: val = di->joy_state[port_num].lRz; break;
|
||||
}
|
||||
|
||||
if (val < -0x7fff) // So abs() of -0x8000 can't mess us up.
|
||||
val = -0x7fff;
|
||||
|
||||
if (is_neg && val > 0)
|
||||
val = 0;
|
||||
else if (is_pos && val < 0)
|
||||
val = 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static bool dinput_joyaxis_pressed(sdl_dinput_t *di, unsigned port_num, const struct snes_keybind *key)
|
||||
{
|
||||
if (key->joyaxis == AXIS_NONE)
|
||||
return false;
|
||||
|
||||
int min = -32678 * g_settings.input.axis_threshold;
|
||||
int max = 32677 * g_settings.input.axis_threshold;
|
||||
int min = 0x7fff * g_settings.input.axis_threshold;
|
||||
|
||||
switch (AXIS_NEG_GET(joyaxis))
|
||||
{
|
||||
case 0:
|
||||
return di->joy_state[port_num].lX <= min;
|
||||
case 1:
|
||||
return di->joy_state[port_num].lY <= min;
|
||||
case 2:
|
||||
return di->joy_state[port_num].lZ <= min;
|
||||
case 3:
|
||||
return di->joy_state[port_num].lRx <= min;
|
||||
case 4:
|
||||
return di->joy_state[port_num].lRy <= min;
|
||||
case 5:
|
||||
return di->joy_state[port_num].lRz <= min;
|
||||
}
|
||||
|
||||
switch (AXIS_POS_GET(joyaxis))
|
||||
{
|
||||
case 0:
|
||||
return di->joy_state[port_num].lX >= max;
|
||||
case 1:
|
||||
return di->joy_state[port_num].lY >= max;
|
||||
case 2:
|
||||
return di->joy_state[port_num].lZ >= max;
|
||||
case 3:
|
||||
return di->joy_state[port_num].lRx >= max;
|
||||
case 4:
|
||||
return di->joy_state[port_num].lRy >= max;
|
||||
case 5:
|
||||
return di->joy_state[port_num].lRz >= max;
|
||||
}
|
||||
|
||||
return false;
|
||||
int16_t val = sdl_dinput_axis(di, port_num, key);
|
||||
return abs(val) > min;
|
||||
}
|
||||
|
||||
bool sdl_dinput_pressed(sdl_dinput_t *di, unsigned port_num, const struct snes_keybind *key)
|
||||
@ -239,7 +252,7 @@ bool sdl_dinput_pressed(sdl_dinput_t *di, unsigned port_num, const struct snes_k
|
||||
return false;
|
||||
if (dinput_joykey_pressed(di, port_num, key->joykey))
|
||||
return true;
|
||||
if (dinput_joyaxis_pressed(di, port_num, key->joyaxis))
|
||||
if (dinput_joyaxis_pressed(di, port_num, key))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -40,6 +40,9 @@ void sdl_dinput_free(sdl_dinput_t *di);
|
||||
bool sdl_dinput_pressed(sdl_dinput_t *di, unsigned port_num,
|
||||
const struct snes_keybind *key);
|
||||
|
||||
int16_t sdl_dinput_axis(sdl_dinput_t *di, unsigned port_num,
|
||||
const struct snes_keybind *key);
|
||||
|
||||
void sdl_dinput_poll(sdl_dinput_t *di);
|
||||
|
||||
|
||||
|
@ -223,27 +223,38 @@ static bool sdl_joykey_pressed(sdl_input_t *sdl, int port_num, uint16_t joykey)
|
||||
}
|
||||
}
|
||||
|
||||
static bool sdl_axis_pressed(sdl_input_t *sdl, int port_num, uint32_t joyaxis)
|
||||
static int16_t sdl_axis_analog(sdl_input_t *sdl, unsigned port_num, uint32_t joyaxis)
|
||||
{
|
||||
if (joyaxis == AXIS_NONE)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
Sint16 val = 0;
|
||||
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;
|
||||
val = SDL_JoystickGetAxis(sdl->joysticks[port_num], AXIS_NEG_GET(joyaxis));
|
||||
|
||||
if (val > 0)
|
||||
val = 0;
|
||||
else if (val < -0x8000) // -0x8000 can cause trouble if we later abs() it.
|
||||
val = -0x7fff;
|
||||
}
|
||||
if (AXIS_POS_GET(joyaxis) < sdl->num_axes[port_num])
|
||||
else if (AXIS_POS_GET(joyaxis) < sdl->num_axes[port_num])
|
||||
{
|
||||
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;
|
||||
val = SDL_JoystickGetAxis(sdl->joysticks[port_num], AXIS_POS_GET(joyaxis));
|
||||
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
return val;
|
||||
}
|
||||
|
||||
static bool sdl_axis_pressed(sdl_input_t *sdl, unsigned port_num, uint32_t joyaxis)
|
||||
{
|
||||
int16_t val = sdl_axis_analog(sdl, port_num, joyaxis);
|
||||
|
||||
float scaled = (float)abs(val) / 0x8000;
|
||||
return scaled > g_settings.input.axis_threshold;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -291,6 +302,69 @@ static int16_t sdl_joypad_device_state(sdl_input_t *sdl, const struct snes_keybi
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void conv_analog_id_to_bind_id(unsigned index, unsigned id,
|
||||
unsigned *id_minus, unsigned *id_plus)
|
||||
{
|
||||
switch ((index << 1) | id)
|
||||
{
|
||||
case (RETRO_DEVICE_INDEX_ANALOG_LEFT << 1) | RETRO_DEVICE_ID_ANALOG_X:
|
||||
*id_minus = RARCH_ANALOG_LEFT_X_MINUS;
|
||||
*id_plus = RARCH_ANALOG_LEFT_X_PLUS;
|
||||
break;
|
||||
|
||||
case (RETRO_DEVICE_INDEX_ANALOG_LEFT << 1) | RETRO_DEVICE_ID_ANALOG_Y:
|
||||
*id_minus = RARCH_ANALOG_LEFT_Y_MINUS;
|
||||
*id_plus = RARCH_ANALOG_LEFT_Y_PLUS;
|
||||
break;
|
||||
|
||||
case (RETRO_DEVICE_INDEX_ANALOG_RIGHT << 1) | RETRO_DEVICE_ID_ANALOG_X:
|
||||
*id_minus = RARCH_ANALOG_RIGHT_X_MINUS;
|
||||
*id_plus = RARCH_ANALOG_RIGHT_X_PLUS;
|
||||
break;
|
||||
|
||||
case (RETRO_DEVICE_INDEX_ANALOG_RIGHT << 1) | RETRO_DEVICE_ID_ANALOG_Y:
|
||||
*id_minus = RARCH_ANALOG_RIGHT_Y_MINUS;
|
||||
*id_plus = RARCH_ANALOG_RIGHT_Y_PLUS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t sdl_analog_device_state(sdl_input_t *sdl, const struct snes_keybind **binds_,
|
||||
unsigned port_num, unsigned index, unsigned id)
|
||||
{
|
||||
const struct snes_keybind *binds = binds_[port_num];
|
||||
if (id >= RARCH_BIND_LIST_END)
|
||||
return 0;
|
||||
|
||||
unsigned id_minus = 0;
|
||||
unsigned id_plus = 0;
|
||||
conv_analog_id_to_bind_id(index, id, &id_minus, &id_plus);
|
||||
|
||||
const struct snes_keybind *bind_minus = &binds[id_minus];
|
||||
const struct snes_keybind *bind_plus = &binds[id_plus];
|
||||
if (!bind_minus->valid || !bind_plus->valid)
|
||||
return 0;
|
||||
|
||||
// A user might have bound minus axis to positive axis in SDL.
|
||||
#ifdef HAVE_DINPUT
|
||||
int16_t pressed_minus = abs(sdl_dinput_axis(sdl->di, port_num, bind_minus));
|
||||
int16_t pressed_plus = abs(sdl_dinput_axis(sdl->di, port_num, bind_plus));
|
||||
#else
|
||||
int16_t pressed_minus = abs(sdl_axis_analog(sdl, port_num, bind_minus->joyaxis));
|
||||
int16_t pressed_plus = abs(sdl_axis_analog(sdl, port_num, bind_plus->joyaxis));
|
||||
#endif
|
||||
|
||||
int16_t res = pressed_plus - pressed_minus;
|
||||
|
||||
// TODO: Does it make sense to use axis thresholding here?
|
||||
if (res != 0)
|
||||
return res;
|
||||
|
||||
int16_t digital_left = sdl_is_pressed(sdl, port_num, bind_minus) ? -0x7fff : 0;
|
||||
int16_t digital_right = sdl_is_pressed(sdl, port_num, bind_plus) ? 0x7fff : 0;
|
||||
return digital_right + digital_left;
|
||||
}
|
||||
|
||||
static int16_t sdl_mouse_device_state(sdl_input_t *sdl, unsigned id)
|
||||
{
|
||||
switch (id)
|
||||
@ -338,6 +412,8 @@ static int16_t sdl_input_state(void *data_, const struct snes_keybind **binds, u
|
||||
{
|
||||
case RETRO_DEVICE_JOYPAD:
|
||||
return sdl_joypad_device_state(data, binds, port, id);
|
||||
case RETRO_DEVICE_ANALOG:
|
||||
return sdl_analog_device_state(data, binds, port, index, id);
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
return sdl_mouse_device_state(data, id);
|
||||
case RETRO_DEVICE_LIGHTGUN:
|
||||
|
@ -197,6 +197,9 @@ static int16_t x_input_state(void *data, const struct snes_keybind **binds, unsi
|
||||
return x_is_pressed(x11, binds[port], id) ||
|
||||
input_sdl.input_state(x11->sdl, binds, port, device, index, id);
|
||||
|
||||
case RETRO_DEVICE_ANALOG:
|
||||
return input_sdl.input_state(x11->sdl, binds, port, device, index, id);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -115,6 +115,11 @@ static void update_input(void)
|
||||
if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT))
|
||||
dir_x++;
|
||||
|
||||
dir_x += input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 2000;
|
||||
dir_y += input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 2000;
|
||||
//dir_x += input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / 2000;
|
||||
//dir_y += input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) / 2000;
|
||||
|
||||
x_coord = (x_coord + dir_x) & 31;
|
||||
y_coord = (y_coord + dir_y) & 31;
|
||||
}
|
||||
|
@ -203,6 +203,19 @@
|
||||
# input_player1_l3 =
|
||||
# input_player1_r3 =
|
||||
|
||||
# Two analog sticks (DualShock-esque).
|
||||
# Bound as usual, however, if a real analog axis is bound,
|
||||
# it can be read as a true analog.
|
||||
# Positive X axis is right, Positive Y axis is down.
|
||||
# input_player1_l_x_plus =
|
||||
# input_player1_l_x_minus =
|
||||
# input_player1_l_y_plus =
|
||||
# input_player1_l_y_minus =
|
||||
# input_player1_r_x_plus =
|
||||
# input_player1_r_x_minus =
|
||||
# input_player1_r_y_plus =
|
||||
# input_player1_r_y_minus =
|
||||
|
||||
# If desired, it is possible to override which joypads are being used for player 1 through 5. First joypad available is 0.
|
||||
# input_player1_joypad_index = 0
|
||||
# input_player2_joypad_index = 1
|
||||
|
73
settings.c
73
settings.c
@ -527,44 +527,35 @@ struct bind_map
|
||||
|
||||
#define DECLARE_BIND(x, bind) { true, "input_" #x, "input_" #x "_btn", "input_" #x "_axis", bind }
|
||||
#define DECL_PLAYER(P) \
|
||||
{ \
|
||||
DECLARE_BIND(player##P##_b, RETRO_DEVICE_ID_JOYPAD_B), \
|
||||
DECLARE_BIND(player##P##_y, RETRO_DEVICE_ID_JOYPAD_Y), \
|
||||
DECLARE_BIND(player##P##_select, RETRO_DEVICE_ID_JOYPAD_SELECT), \
|
||||
DECLARE_BIND(player##P##_start, RETRO_DEVICE_ID_JOYPAD_START), \
|
||||
DECLARE_BIND(player##P##_up, RETRO_DEVICE_ID_JOYPAD_UP), \
|
||||
DECLARE_BIND(player##P##_down, RETRO_DEVICE_ID_JOYPAD_DOWN), \
|
||||
DECLARE_BIND(player##P##_left, RETRO_DEVICE_ID_JOYPAD_LEFT), \
|
||||
DECLARE_BIND(player##P##_right, RETRO_DEVICE_ID_JOYPAD_RIGHT), \
|
||||
DECLARE_BIND(player##P##_a, RETRO_DEVICE_ID_JOYPAD_A), \
|
||||
DECLARE_BIND(player##P##_x, RETRO_DEVICE_ID_JOYPAD_X), \
|
||||
DECLARE_BIND(player##P##_l, RETRO_DEVICE_ID_JOYPAD_L), \
|
||||
DECLARE_BIND(player##P##_r, RETRO_DEVICE_ID_JOYPAD_R), \
|
||||
DECLARE_BIND(player##P##_l2, RETRO_DEVICE_ID_JOYPAD_L2), \
|
||||
DECLARE_BIND(player##P##_r2, RETRO_DEVICE_ID_JOYPAD_R2), \
|
||||
DECLARE_BIND(player##P##_l3, RETRO_DEVICE_ID_JOYPAD_L3), \
|
||||
DECLARE_BIND(player##P##_r3, RETRO_DEVICE_ID_JOYPAD_R3), \
|
||||
}
|
||||
DECLARE_BIND(player##P##_b, RETRO_DEVICE_ID_JOYPAD_B), \
|
||||
DECLARE_BIND(player##P##_y, RETRO_DEVICE_ID_JOYPAD_Y), \
|
||||
DECLARE_BIND(player##P##_select, RETRO_DEVICE_ID_JOYPAD_SELECT), \
|
||||
DECLARE_BIND(player##P##_start, RETRO_DEVICE_ID_JOYPAD_START), \
|
||||
DECLARE_BIND(player##P##_up, RETRO_DEVICE_ID_JOYPAD_UP), \
|
||||
DECLARE_BIND(player##P##_down, RETRO_DEVICE_ID_JOYPAD_DOWN), \
|
||||
DECLARE_BIND(player##P##_left, RETRO_DEVICE_ID_JOYPAD_LEFT), \
|
||||
DECLARE_BIND(player##P##_right, RETRO_DEVICE_ID_JOYPAD_RIGHT), \
|
||||
DECLARE_BIND(player##P##_a, RETRO_DEVICE_ID_JOYPAD_A), \
|
||||
DECLARE_BIND(player##P##_x, RETRO_DEVICE_ID_JOYPAD_X), \
|
||||
DECLARE_BIND(player##P##_l, RETRO_DEVICE_ID_JOYPAD_L), \
|
||||
DECLARE_BIND(player##P##_r, RETRO_DEVICE_ID_JOYPAD_R), \
|
||||
DECLARE_BIND(player##P##_l2, RETRO_DEVICE_ID_JOYPAD_L2), \
|
||||
DECLARE_BIND(player##P##_r2, RETRO_DEVICE_ID_JOYPAD_R2), \
|
||||
DECLARE_BIND(player##P##_l3, RETRO_DEVICE_ID_JOYPAD_L3), \
|
||||
DECLARE_BIND(player##P##_r3, RETRO_DEVICE_ID_JOYPAD_R3), \
|
||||
DECLARE_BIND(player##P##_l_x_plus, RARCH_ANALOG_LEFT_X_PLUS), \
|
||||
DECLARE_BIND(player##P##_l_x_minus, RARCH_ANALOG_LEFT_X_MINUS), \
|
||||
DECLARE_BIND(player##P##_l_y_plus, RARCH_ANALOG_LEFT_Y_PLUS), \
|
||||
DECLARE_BIND(player##P##_l_y_minus, RARCH_ANALOG_LEFT_Y_MINUS), \
|
||||
DECLARE_BIND(player##P##_r_x_plus, RARCH_ANALOG_RIGHT_X_PLUS), \
|
||||
DECLARE_BIND(player##P##_r_x_minus, RARCH_ANALOG_RIGHT_X_MINUS), \
|
||||
DECLARE_BIND(player##P##_r_y_plus, RARCH_ANALOG_RIGHT_Y_PLUS), \
|
||||
DECLARE_BIND(player##P##_r_y_minus, RARCH_ANALOG_RIGHT_Y_MINUS)
|
||||
|
||||
// Big and nasty bind map... :)
|
||||
static const struct bind_map bind_maps[MAX_PLAYERS][RARCH_BIND_LIST_END_NULL] = {
|
||||
{
|
||||
DECLARE_BIND(player1_b, RETRO_DEVICE_ID_JOYPAD_B),
|
||||
DECLARE_BIND(player1_y, RETRO_DEVICE_ID_JOYPAD_Y),
|
||||
DECLARE_BIND(player1_select, RETRO_DEVICE_ID_JOYPAD_SELECT),
|
||||
DECLARE_BIND(player1_start, RETRO_DEVICE_ID_JOYPAD_START),
|
||||
DECLARE_BIND(player1_up, RETRO_DEVICE_ID_JOYPAD_UP),
|
||||
DECLARE_BIND(player1_down, RETRO_DEVICE_ID_JOYPAD_DOWN),
|
||||
DECLARE_BIND(player1_left, RETRO_DEVICE_ID_JOYPAD_LEFT),
|
||||
DECLARE_BIND(player1_right, RETRO_DEVICE_ID_JOYPAD_RIGHT),
|
||||
DECLARE_BIND(player1_a, RETRO_DEVICE_ID_JOYPAD_A),
|
||||
DECLARE_BIND(player1_x, RETRO_DEVICE_ID_JOYPAD_X),
|
||||
DECLARE_BIND(player1_l, RETRO_DEVICE_ID_JOYPAD_L),
|
||||
DECLARE_BIND(player1_r, RETRO_DEVICE_ID_JOYPAD_R),
|
||||
DECLARE_BIND(player1_l2, RETRO_DEVICE_ID_JOYPAD_L2),
|
||||
DECLARE_BIND(player1_r2, RETRO_DEVICE_ID_JOYPAD_R2),
|
||||
DECLARE_BIND(player1_l3, RETRO_DEVICE_ID_JOYPAD_L3),
|
||||
DECLARE_BIND(player1_r3, RETRO_DEVICE_ID_JOYPAD_R3),
|
||||
DECL_PLAYER(1),
|
||||
|
||||
DECLARE_BIND(toggle_fast_forward, RARCH_FAST_FORWARD_KEY),
|
||||
DECLARE_BIND(hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY),
|
||||
@ -593,13 +584,13 @@ static const struct bind_map bind_maps[MAX_PLAYERS][RARCH_BIND_LIST_END_NULL] =
|
||||
DECLARE_BIND(slowmotion, RARCH_SLOWMOTION),
|
||||
},
|
||||
|
||||
DECL_PLAYER(2),
|
||||
DECL_PLAYER(3),
|
||||
DECL_PLAYER(4),
|
||||
DECL_PLAYER(5),
|
||||
DECL_PLAYER(6),
|
||||
DECL_PLAYER(7),
|
||||
DECL_PLAYER(8),
|
||||
{ DECL_PLAYER(2) },
|
||||
{ DECL_PLAYER(3) },
|
||||
{ DECL_PLAYER(4) },
|
||||
{ DECL_PLAYER(5) },
|
||||
{ DECL_PLAYER(6) },
|
||||
{ DECL_PLAYER(7) },
|
||||
{ DECL_PLAYER(8) },
|
||||
};
|
||||
|
||||
struct key_map
|
||||
|
@ -60,53 +60,62 @@ struct bind
|
||||
bool is_misc;
|
||||
};
|
||||
|
||||
#define BIND(x, k) { x, { "input_player1_" #k "_btn", "input_player2_" #k "_btn", "input_player3_" #k "_btn", "input_player4_" #k "_btn", "input_player5_" #k "_btn" }, {"input_player1_" #k "_axis", "input_player2_" #k "_axis", "input_player3_" #k "_axis", "input_player4_" #k "_axis", "input_player5_" #k "_axis"}, false},
|
||||
#define BIND(x, k) { x, { "input_player1_" #k "_btn", "input_player2_" #k "_btn", "input_player3_" #k "_btn", "input_player4_" #k "_btn", "input_player5_" #k "_btn" }, {"input_player1_" #k "_axis", "input_player2_" #k "_axis", "input_player3_" #k "_axis", "input_player4_" #k "_axis", "input_player5_" #k "_axis"}, false}
|
||||
|
||||
#define MISC_BIND(x, k) { x, { "input_" #k "_btn" }, { "input_" #k "_axis" }, true},
|
||||
#define MISC_BIND(x, k) { x, { "input_" #k "_btn" }, { "input_" #k "_axis" }, true}
|
||||
|
||||
static struct bind binds[] = {
|
||||
BIND("A button (right)", a)
|
||||
BIND("B button (down)", b)
|
||||
BIND("X button (top)", x)
|
||||
BIND("Y button (left)", y)
|
||||
BIND("L button (left shoulder)", l)
|
||||
BIND("R button (right shoulder)", r)
|
||||
BIND("L2 button (left shoulder #2)", l2)
|
||||
BIND("R2 button (right shoulder #2)", r2)
|
||||
BIND("L3 button (left analog button)", l3)
|
||||
BIND("R3 button (right analog button)", r3)
|
||||
BIND("Start button", start)
|
||||
BIND("Select button", select)
|
||||
BIND("Left D-pad", left)
|
||||
BIND("Up D-pad", up)
|
||||
BIND("Right D-pad", right)
|
||||
BIND("Down D-pad", down)
|
||||
BIND("A button (right)", a),
|
||||
BIND("B button (down)", b),
|
||||
BIND("X button (top)", x),
|
||||
BIND("Y button (left)", y),
|
||||
BIND("L button (left shoulder)", l),
|
||||
BIND("R button (right shoulder)", r),
|
||||
BIND("L2 button (left shoulder #2)", l2),
|
||||
BIND("R2 button (right shoulder #2)", r2),
|
||||
BIND("L3 button (left analog button)", l3),
|
||||
BIND("R3 button (right analog button)", r3),
|
||||
BIND("Start button", start),
|
||||
BIND("Select button", select),
|
||||
BIND("Left D-pad", left),
|
||||
BIND("Up D-pad", up),
|
||||
BIND("Right D-pad", right),
|
||||
BIND("Down D-pad", down),
|
||||
|
||||
MISC_BIND("Save state", save_state)
|
||||
MISC_BIND("Load state", load_state)
|
||||
MISC_BIND("Exit emulator", exit_emulator)
|
||||
MISC_BIND("Toggle fullscreen", toggle_fullscreen)
|
||||
MISC_BIND("Save state slot increase", state_slot_increase)
|
||||
MISC_BIND("Save state slot decrease", state_slot_decrease)
|
||||
MISC_BIND("Toggle fast forward", toggle_fast_forward)
|
||||
MISC_BIND("Hold fast forward", hold_fast_forward)
|
||||
MISC_BIND("Audio input rate step up", rate_step_up)
|
||||
MISC_BIND("Audio input rate step down", rate_step_down)
|
||||
MISC_BIND("Rewind", rewind)
|
||||
MISC_BIND("Movie recording toggle", movie_record_toggle)
|
||||
MISC_BIND("Pause", pause_toggle)
|
||||
MISC_BIND("Frame advance", frame_advance)
|
||||
MISC_BIND("Reset", reset)
|
||||
MISC_BIND("Next shader", shader_next)
|
||||
MISC_BIND("Previous shader", shader_prev)
|
||||
MISC_BIND("Toggle cheat on/off", cheat_toggle)
|
||||
MISC_BIND("Cheat index plus", cheat_index_plus)
|
||||
MISC_BIND("Cheat index minus", cheat_index_minus)
|
||||
MISC_BIND("Screenshot", screenshot)
|
||||
MISC_BIND("DSP config", dsp_config)
|
||||
MISC_BIND("Audio mute/unmute", audio_mute)
|
||||
MISC_BIND("Netplay player flip", netplay_flip_players)
|
||||
MISC_BIND("Slow motion", slowmotion)
|
||||
BIND("Left analog X+ (right)", l_x_plus),
|
||||
BIND("Left analog Y+ (down)", l_y_plus),
|
||||
BIND("Left analog X- (left)", l_x_minus),
|
||||
BIND("Left analog Y- (up)", l_y_minus),
|
||||
BIND("Right analog X+ (right)", r_x_plus),
|
||||
BIND("Right analog Y+ (down)", r_y_plus),
|
||||
BIND("Right analog X- (left)", r_x_minus),
|
||||
BIND("Right analog Y- (up)", r_y_minus),
|
||||
|
||||
MISC_BIND("Save state", save_state),
|
||||
MISC_BIND("Load state", load_state),
|
||||
MISC_BIND("Exit emulator", exit_emulator),
|
||||
MISC_BIND("Toggle fullscreen", toggle_fullscreen),
|
||||
MISC_BIND("Save state slot increase", state_slot_increase),
|
||||
MISC_BIND("Save state slot decrease", state_slot_decrease),
|
||||
MISC_BIND("Toggle fast forward", toggle_fast_forward),
|
||||
MISC_BIND("Hold fast forward", hold_fast_forward),
|
||||
MISC_BIND("Audio input rate step up", rate_step_up),
|
||||
MISC_BIND("Audio input rate step down", rate_step_down),
|
||||
MISC_BIND("Rewind", rewind),
|
||||
MISC_BIND("Movie recording toggle", movie_record_toggle),
|
||||
MISC_BIND("Pause", pause_toggle),
|
||||
MISC_BIND("Frame advance", frame_advance),
|
||||
MISC_BIND("Reset", reset),
|
||||
MISC_BIND("Next shader", shader_next),
|
||||
MISC_BIND("Previous shader", shader_prev),
|
||||
MISC_BIND("Toggle cheat on/off", cheat_toggle),
|
||||
MISC_BIND("Cheat index plus", cheat_index_plus),
|
||||
MISC_BIND("Cheat index minus", cheat_index_minus),
|
||||
MISC_BIND("Screenshot", screenshot),
|
||||
MISC_BIND("DSP config", dsp_config),
|
||||
MISC_BIND("Audio mute/unmute", audio_mute),
|
||||
MISC_BIND("Netplay player flip", netplay_flip_players),
|
||||
MISC_BIND("Slow motion", slowmotion),
|
||||
};
|
||||
|
||||
static void get_binds(config_file_t *conf, int player, int joypad)
|
||||
@ -116,6 +125,7 @@ static void get_binds(config_file_t *conf, int player, int joypad)
|
||||
fprintf(stderr, "Failed to init joystick subsystem.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SDL_Joystick *joystick;
|
||||
int num = SDL_NumJoysticks();
|
||||
if (joypad >= num)
|
||||
@ -131,8 +141,9 @@ static void get_binds(config_file_t *conf, int player, int joypad)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int last_axis = 0xFF;
|
||||
int last_pos = 0;
|
||||
int last_axis = -1;
|
||||
bool block_axis = false;
|
||||
|
||||
int num_axes = SDL_JoystickNumAxes(joystick);
|
||||
int *initial_axes = (int*)calloc(num_axes, sizeof(int));
|
||||
assert(initial_axes);
|
||||
@ -140,7 +151,20 @@ static void get_binds(config_file_t *conf, int player, int joypad)
|
||||
SDL_PumpEvents();
|
||||
SDL_JoystickUpdate();
|
||||
for (int i = 0; i < num_axes; i++)
|
||||
initial_axes[i] = SDL_JoystickGetAxis(joystick, i);
|
||||
{
|
||||
Sint16 initial = SDL_JoystickGetAxis(joystick, i);
|
||||
if (abs(initial) < 20000)
|
||||
initial = 0;
|
||||
|
||||
// Certain joypads (such as XBox360 controller on Linux) has a default negative axis for shoulder triggers,
|
||||
// which makes configuration very awkward.
|
||||
// If default negative, we can't trigger on the negative axis, and similar with defaulted positive axes.
|
||||
|
||||
if (initial)
|
||||
fprintf(stderr, "Axis %d is defaulted to %s axis value of %d\n", i, initial > 0 ? "positive" : "negative", (int)initial);
|
||||
|
||||
initial_axes[i] = initial;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Configuring binds for player #%d on joypad #%d (%s)\n",
|
||||
player + 1, joypad, SDL_JoystickName(joypad));
|
||||
@ -168,27 +192,44 @@ static void get_binds(config_file_t *conf, int player, int joypad)
|
||||
break;
|
||||
|
||||
case SDL_JOYAXISMOTION:
|
||||
if ( // This is starting to look like Lisp. :D
|
||||
(abs((int)event.jaxis.value - initial_axes[event.jaxis.axis]) > 20000) &&
|
||||
(
|
||||
(event.jaxis.axis != last_axis) ||
|
||||
(
|
||||
(abs(event.jaxis.value) > 20000) &&
|
||||
(abs((int)event.jaxis.value - last_pos) > 20000)
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
bool same_axis = last_axis == event.jaxis.axis;
|
||||
bool require_negative = initial_axes[event.jaxis.axis] > 0;
|
||||
bool require_positive = initial_axes[event.jaxis.axis] < 0;
|
||||
|
||||
// Block the axis config until we're sure axes have returned to their neutral state.
|
||||
if (same_axis)
|
||||
{
|
||||
if (abs(event.jaxis.value) < 10000 ||
|
||||
(require_positive && event.jaxis.value < 0) ||
|
||||
(require_negative && event.jaxis.value > 0))
|
||||
block_axis = false;
|
||||
}
|
||||
|
||||
// If axes are in their neutral state, we can't allow it.
|
||||
if (require_negative && event.jaxis.value >= 0)
|
||||
break;
|
||||
if (require_positive && event.jaxis.value <= 0)
|
||||
break;
|
||||
|
||||
if (block_axis)
|
||||
break;
|
||||
|
||||
if (abs(event.jaxis.value) > 20000)
|
||||
{
|
||||
last_axis = event.jaxis.axis;
|
||||
last_pos = event.jaxis.value;
|
||||
fprintf(stderr, "\tJoyaxis moved: Axis %d, Value %d\n", (int)event.jaxis.axis, (int)event.jaxis.value);
|
||||
done = true;
|
||||
|
||||
done = true;
|
||||
block_axis = true;
|
||||
|
||||
char buf[8];
|
||||
snprintf(buf, sizeof(buf), event.jaxis.value > 0 ? "+%d" : "-%d", event.jaxis.axis);
|
||||
config_set_string(conf, binds[i].confaxis[player_index], buf);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
fprintf(stderr, ":V\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user