diff --git a/input/input_driver.c b/input/input_driver.c index c28b4d42da..a4af4525cb 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -1609,53 +1609,99 @@ int16_t input_joypad_analog(const input_device_driver_t *drv, unsigned port, unsigned idx, unsigned ident, const struct retro_keybind *binds) { - uint32_t axis_minus, axis_plus; - int16_t pressed_minus, pressed_plus, res; - unsigned ident_minus = 0; - unsigned ident_plus = 0; - const struct retro_keybind *bind_minus = NULL; - const struct retro_keybind *bind_plus = NULL; + int16_t res; - input_conv_analog_id_to_bind_id(idx, ident, &ident_minus, &ident_plus); + if ( idx == RETRO_DEVICE_INDEX_ANALOG_BUTTON ) + { + /* A RETRO_DEVICE_JOYPAD button? */ + if ( ident < RARCH_FIRST_CUSTOM_BIND ) + { + uint32_t axis = 0; + const struct retro_keybind *bind = NULL; - bind_minus = &binds[ident_minus]; - bind_plus = &binds[ident_plus]; + bind = &binds[ ident ]; + if (!bind->valid) + return 0; - if (!bind_minus->valid || !bind_plus->valid) - return 0; + axis = bind->joyaxis; + if ( axis == AXIS_NONE ) + axis = joypad_info.auto_binds[ ident ].joyaxis; - axis_minus = bind_minus->joyaxis; - axis_plus = bind_plus->joyaxis; + /* Analog button. */ + res = abs( drv->axis( joypad_info.joy_idx, axis ) ); - if (axis_minus == AXIS_NONE) - axis_minus = joypad_info.auto_binds[ident_minus].joyaxis; - if (axis_plus == AXIS_NONE) - axis_plus = joypad_info.auto_binds[ident_plus].joyaxis; + /* If the result is zero, it's got a digital button attached to it */ + if ( res == 0 ) + { + uint64_t key = bind->joykey; - pressed_minus = abs(drv->axis(joypad_info.joy_idx, axis_minus)); - pressed_plus = abs(drv->axis(joypad_info.joy_idx, axis_plus)); - res = pressed_plus - pressed_minus; + if ( key == NO_BTN ) + key = joypad_info.auto_binds[ ident ].joykey; - if (res == 0) - { - int16_t digital_left = 0; - int16_t digital_right = 0; - uint64_t key_minus = bind_minus->joykey; - uint64_t key_plus = bind_plus->joykey; + if ( drv->button(joypad_info.joy_idx, (uint16_t)key)) + res = 0x7fff; + } + } + else + { + /* not a suitable button */ + res = 0; + } + } + else + { + /* Analog sticks. Either RETRO_DEVICE_INDEX_ANALOG_LEFT + * or RETRO_DEVICE_INDEX_ANALOG_RIGHT */ - if (key_minus == NO_BTN) - key_minus = joypad_info.auto_binds[ident_minus].joykey; - if (key_plus == NO_BTN) - key_plus = joypad_info.auto_binds[ident_plus].joykey; + uint32_t axis_minus, axis_plus; + int16_t pressed_minus, pressed_plus; + unsigned ident_minus = 0; + unsigned ident_plus = 0; + const struct retro_keybind *bind_minus = NULL; + const struct retro_keybind *bind_plus = NULL; - if (drv->button(joypad_info.joy_idx, (uint16_t)key_minus)) - digital_left = -0x7fff; - if (drv->button(joypad_info.joy_idx, (uint16_t)key_plus)) - digital_right = 0x7fff; - return digital_right + digital_left; - } + input_conv_analog_id_to_bind_id(idx, ident, &ident_minus, &ident_plus); - return res; + bind_minus = &binds[ident_minus]; + bind_plus = &binds[ident_plus]; + + if (!bind_minus->valid || !bind_plus->valid) + return 0; + + axis_minus = bind_minus->joyaxis; + axis_plus = bind_plus->joyaxis; + + if (axis_minus == AXIS_NONE) + axis_minus = joypad_info.auto_binds[ident_minus].joyaxis; + if (axis_plus == AXIS_NONE) + axis_plus = joypad_info.auto_binds[ident_plus].joyaxis; + + pressed_minus = abs(drv->axis(joypad_info.joy_idx, axis_minus)); + pressed_plus = abs(drv->axis(joypad_info.joy_idx, axis_plus)); + res = pressed_plus - pressed_minus; + + if (res == 0) + { + int16_t digital_left = 0; + int16_t digital_right = 0; + uint64_t key_minus = bind_minus->joykey; + uint64_t key_plus = bind_plus->joykey; + + if (key_minus == NO_BTN) + key_minus = joypad_info.auto_binds[ident_minus].joykey; + if (key_plus == NO_BTN) + key_plus = joypad_info.auto_binds[ident_plus].joykey; + + if (drv->button(joypad_info.joy_idx, (uint16_t)key_minus)) + digital_left = -0x7fff; + if (drv->button(joypad_info.joy_idx, (uint16_t)key_plus)) + digital_right = 0x7fff; + + return digital_right + digital_left; + } + } + + return res; } /** diff --git a/input/input_driver.h b/input/input_driver.h index 17d135402d..3267efeacd 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -520,6 +520,7 @@ static INLINE bool input_joypad_pressed( * E.g.: * - RETRO_DEVICE_INDEX_ANALOG_LEFT * - RETRO_DEVICE_INDEX_ANALOG_RIGHT + * - RETRO_DEVICE_INDEX_ANALOG_BUTTON * @ident : Analog key identifier. * E.g.: * - RETRO_DEVICE_ID_ANALOG_X diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index 4d35ac7b41..27b61b70b7 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -131,11 +131,12 @@ extern "C" { #define RETRO_DEVICE_LIGHTGUN 4 /* The ANALOG device is an extension to JOYPAD (RetroPad). - * Similar to DualShock it adds two analog sticks. - * This is treated as a separate device type as it returns values in the - * full analog range of [-0x8000, 0x7fff]. Positive X axis is right. - * Positive Y axis is down. - * Only use ANALOG type when polling for analog values of the axes. + * Similar to DualShock2 it adds two analog sticks and all buttons can + * be analog. This is treated as a separate device type as it returns + * axis values in the full analog range of [-0x8000, 0x7fff]. + * Positive X axis is right. Positive Y axis is down. + * Buttons are returned in the range [0, 0x7fff]. + * Only use ANALOG type when polling for analog values. */ #define RETRO_DEVICE_ANALOG 5 @@ -174,7 +175,8 @@ extern "C" { /* Buttons for the RetroPad (JOYPAD). * The placement of these is equivalent to placements on the * Super Nintendo controller. - * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. */ + * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. + * Also used as id values for RETRO_DEVICE_INDEX_ANALOG_BUTTON */ #define RETRO_DEVICE_ID_JOYPAD_B 0 #define RETRO_DEVICE_ID_JOYPAD_Y 1 #define RETRO_DEVICE_ID_JOYPAD_SELECT 2 @@ -193,10 +195,11 @@ extern "C" { #define RETRO_DEVICE_ID_JOYPAD_R3 15 /* Index / Id values for ANALOG device. */ -#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 -#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 -#define RETRO_DEVICE_ID_ANALOG_X 0 -#define RETRO_DEVICE_ID_ANALOG_Y 1 +#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 +#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 +#define RETRO_DEVICE_INDEX_ANALOG_BUTTON 2 +#define RETRO_DEVICE_ID_ANALOG_X 0 +#define RETRO_DEVICE_ID_ANALOG_Y 1 /* Id values for MOUSE. */ #define RETRO_DEVICE_ID_MOUSE_X 0