2020-12-05 13:08:24 +01:00
# include "stdafx.h"
2017-12-23 22:25:51 +01:00
# include "PadHandler.h"
2021-04-21 22:12:21 +02:00
# include "Emu/system_utils.hpp"
2023-05-18 17:17:30 +02:00
# include "Emu/system_config.h"
2019-12-22 17:39:42 +01:00
# include "Input/pad_thread.h"
2020-04-25 02:12:19 +02:00
# include "Input/product_info.h"
2017-12-23 22:25:51 +01:00
cfg_input g_cfg_input ;
PadHandlerBase : : PadHandlerBase ( pad_handler type ) : m_type ( type )
{
}
2023-06-13 01:19:32 +02:00
std : : set < u32 > PadHandlerBase : : narrow_set ( const std : : set < u64 > & src )
2017-12-23 22:25:51 +01:00
{
2023-06-13 01:19:32 +02:00
if ( src . empty ( ) )
return { } ;
2017-12-23 22:25:51 +01:00
2023-06-13 01:19:32 +02:00
std : : set < u32 > dst ;
for ( const u64 & s : src )
2017-12-23 22:25:51 +01:00
{
2023-06-13 01:19:32 +02:00
dst . insert ( : : narrow < u32 > ( s ) ) ;
2017-12-23 22:25:51 +01:00
}
2023-06-13 01:19:32 +02:00
return dst ;
2017-12-23 22:25:51 +01:00
}
2021-12-16 23:19:09 +01:00
// Get new multiplied value based on the multiplier
s32 PadHandlerBase : : MultipliedInput ( s32 raw_value , s32 multiplier )
{
return ( multiplier * raw_value ) / 100 ;
}
2017-12-23 22:25:51 +01:00
// Get new scaled value between 0 and 255 based on its minimum and maximum
2022-08-13 09:56:04 +02:00
f32 PadHandlerBase : : ScaledInput ( s32 raw_value , int minimum , int maximum , f32 range )
2017-12-23 22:25:51 +01:00
{
// value based on max range converted to [0, 1]
2022-08-13 09:56:04 +02:00
const f32 val = static_cast < f32 > ( std : : clamp ( raw_value , minimum , maximum ) - minimum ) / ( abs ( maximum ) + abs ( minimum ) ) ;
return range * val ;
2017-12-23 22:25:51 +01:00
}
// Get new scaled value between -255 and 255 based on its minimum and maximum
2022-08-13 09:56:04 +02:00
f32 PadHandlerBase : : ScaledInput2 ( s32 raw_value , int minimum , int maximum , f32 range )
2017-12-23 22:25:51 +01:00
{
// value based on max range converted to [0, 1]
2022-08-13 09:56:04 +02:00
const f32 val = static_cast < f32 > ( std : : clamp ( raw_value , minimum , maximum ) - minimum ) / ( abs ( maximum ) + abs ( minimum ) ) ;
return ( 2.0f * range * val ) - range ;
2017-12-23 22:25:51 +01:00
}
// Get normalized trigger value based on the range defined by a threshold
2021-04-09 21:12:47 +02:00
u16 PadHandlerBase : : NormalizeTriggerInput ( u16 value , int threshold ) const
2017-12-23 22:25:51 +01:00
{
if ( value < = threshold | | threshold > = trigger_max )
{
return static_cast < u16 > ( 0 ) ;
}
else if ( threshold < = trigger_min )
{
2020-05-04 16:15:43 +02:00
return static_cast < u16 > ( ScaledInput ( value , trigger_min , trigger_max ) ) ;
2017-12-23 22:25:51 +01:00
}
else
{
2022-08-13 09:56:04 +02:00
const s32 val = static_cast < s32 > ( static_cast < f32 > ( trigger_max ) * ( value - threshold ) / ( trigger_max - threshold ) ) ;
2020-05-04 16:15:43 +02:00
return static_cast < u16 > ( ScaledInput ( val , trigger_min , trigger_max ) ) ;
2017-12-23 22:25:51 +01:00
}
}
// normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions
// the input values must lie in 0+
2020-07-03 21:16:01 +02:00
u16 PadHandlerBase : : NormalizeDirectedInput ( s32 raw_value , s32 threshold , s32 maximum ) const
2017-12-23 22:25:51 +01:00
{
if ( threshold > = maximum | | maximum < = 0 )
{
return static_cast < u16 > ( 0 ) ;
}
2022-08-13 09:56:04 +02:00
const f32 val = static_cast < f32 > ( std : : clamp ( raw_value , 0 , maximum ) ) / maximum ; // value based on max range converted to [0, 1]
2017-12-23 22:25:51 +01:00
if ( threshold < = 0 )
{
return static_cast < u16 > ( 255.0f * val ) ;
}
else
{
2022-08-13 09:56:04 +02:00
const f32 thresh = static_cast < f32 > ( threshold ) / maximum ; // threshold converted to [0, 1]
2017-12-23 22:25:51 +01:00
return static_cast < u16 > ( 255.0f * std : : min ( 1.0f , ( val - thresh ) / ( 1.0f - thresh ) ) ) ;
}
}
2020-07-03 21:16:01 +02:00
u16 PadHandlerBase : : NormalizeStickInput ( u16 raw_value , int threshold , int multiplier , bool ignore_threshold ) const
2017-12-23 22:25:51 +01:00
{
2021-12-16 23:19:09 +01:00
const s32 scaled_value = MultipliedInput ( raw_value , multiplier ) ;
2019-05-16 21:14:33 +02:00
2017-12-23 22:25:51 +01:00
if ( ignore_threshold )
{
2020-05-04 16:02:43 +02:00
return static_cast < u16 > ( ScaledInput ( scaled_value , 0 , thumb_max ) ) ;
2017-12-23 22:25:51 +01:00
}
else
{
2019-05-16 21:14:33 +02:00
return NormalizeDirectedInput ( scaled_value , threshold , thumb_max ) ;
2017-12-23 22:25:51 +01:00
}
}
// This function normalizes stick deadzone based on the DS3's deadzone, which is ~13%
// X and Y is expected to be in (-255) to 255 range, deadzone should be in terms of thumb stick range
// return is new x and y values in 0-255 range
2020-07-12 19:30:45 +02:00
std : : tuple < u16 , u16 > PadHandlerBase : : NormalizeStickDeadzone ( s32 inX , s32 inY , u32 deadzone ) const
2017-12-23 22:25:51 +01:00
{
2022-08-13 09:56:04 +02:00
const f32 dz_range = deadzone / static_cast < f32 > ( std : : abs ( thumb_max ) ) ; // NOTE: thumb_max should be positive anyway
2017-12-23 22:25:51 +01:00
2022-08-13 09:56:04 +02:00
f32 X = inX / 255.0f ;
f32 Y = inY / 255.0f ;
2017-12-23 22:25:51 +01:00
2020-05-04 16:31:08 +02:00
if ( dz_range > 0.f )
2017-12-23 22:25:51 +01:00
{
2022-08-13 09:56:04 +02:00
const f32 mag = std : : min ( sqrtf ( X * X + Y * Y ) , 1.f ) ;
2017-12-23 22:25:51 +01:00
if ( mag < = 0 )
{
return std : : tuple < u16 , u16 > ( ConvertAxis ( X ) , ConvertAxis ( Y ) ) ;
}
2020-05-04 16:31:08 +02:00
if ( mag > dz_range )
2020-02-23 11:32:32 +01:00
{
2022-08-13 09:56:04 +02:00
const f32 pos = std : : lerp ( 0.13f , 1.f , ( mag - dz_range ) / ( 1 - dz_range ) ) ;
const f32 scale = pos / mag ;
2017-12-23 22:25:51 +01:00
X = X * scale ;
Y = Y * scale ;
}
2020-02-23 11:32:32 +01:00
else
{
2022-08-13 09:56:04 +02:00
const f32 pos = std : : lerp ( 0.f , 0.13f , mag / dz_range ) ;
const f32 scale = pos / mag ;
2017-12-23 22:25:51 +01:00
X = X * scale ;
Y = Y * scale ;
}
}
return std : : tuple < u16 , u16 > ( ConvertAxis ( X ) , ConvertAxis ( Y ) ) ;
}
// get clamped value between 0 and 255
u16 PadHandlerBase : : Clamp0To255 ( f32 input )
{
2018-09-05 22:52:30 +02:00
return static_cast < u16 > ( std : : clamp ( input , 0.0f , 255.0f ) ) ;
2017-12-23 22:25:51 +01:00
}
// get clamped value between 0 and 1023
u16 PadHandlerBase : : Clamp0To1023 ( f32 input )
{
2018-09-05 22:52:30 +02:00
return static_cast < u16 > ( std : : clamp ( input , 0.0f , 1023.0f ) ) ;
2017-12-23 22:25:51 +01:00
}
// input has to be [-1,1]. result will be [0,255]
2022-08-13 09:56:04 +02:00
u16 PadHandlerBase : : ConvertAxis ( f32 value )
2017-12-23 22:25:51 +01:00
{
2022-10-15 12:10:40 +02:00
return static_cast < u16 > ( ( value + 1.0 ) * ( 255.0 / 2.0 ) ) ;
2017-12-23 22:25:51 +01:00
}
// The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle
// using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange
// this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000
// This function assumes inX and inY is already in 0-255
std : : tuple < u16 , u16 > PadHandlerBase : : ConvertToSquirclePoint ( u16 inX , u16 inY , int squircle_factor )
{
// convert inX and Y to a (-1, 1) vector;
2019-12-02 22:31:34 +01:00
const f32 x = ( inX - 127.5f ) / 127.5f ;
const f32 y = ( inY - 127.5f ) / 127.5f ;
2017-12-23 22:25:51 +01:00
// compute angle and len of given point to be used for squircle radius
const f32 angle = std : : atan2 ( y , x ) ;
const f32 r = std : : sqrt ( std : : pow ( x , 2.f ) + std : : pow ( y , 2.f ) ) ;
// now find len/point on the given squircle from our current angle and radius in polar coords
// https://thatsmaths.com/2016/07/14/squircles/
2019-12-02 22:31:34 +01:00
const f32 newLen = ( 1 + std : : pow ( std : : sin ( 2 * angle ) , 2.f ) / ( squircle_factor / 1000.f ) ) * r ;
2017-12-23 22:25:51 +01:00
2018-04-29 08:41:51 +02:00
// we now have len and angle, convert to cartesian
2023-04-15 11:13:31 +02:00
const int newX = Clamp0To255 ( std : : round ( ( ( newLen * std : : cos ( angle ) ) + 1 ) * 127.5f ) ) ;
const int newY = Clamp0To255 ( std : : round ( ( ( newLen * std : : sin ( angle ) ) + 1 ) * 127.5f ) ) ;
2017-12-23 22:25:51 +01:00
return std : : tuple < u16 , u16 > ( newX , newY ) ;
}
2020-02-23 11:32:32 +01:00
std : : string PadHandlerBase : : name_string ( ) const
2018-01-17 02:23:50 +01:00
{
return m_name_string ;
}
2020-12-18 08:39:54 +01:00
usz PadHandlerBase : : max_devices ( ) const
2018-01-16 14:07:57 +01:00
{
return m_max_devices ;
}
2020-02-23 11:32:32 +01:00
bool PadHandlerBase : : has_config ( ) const
2017-12-23 22:25:51 +01:00
{
return b_has_config ;
}
2020-02-23 11:32:32 +01:00
bool PadHandlerBase : : has_rumble ( ) const
2017-12-23 22:25:51 +01:00
{
return b_has_rumble ;
}
2022-08-13 09:56:04 +02:00
bool PadHandlerBase : : has_motion ( ) const
{
return b_has_motion ;
}
2020-02-23 11:32:32 +01:00
bool PadHandlerBase : : has_deadzones ( ) const
2017-12-23 22:25:51 +01:00
{
return b_has_deadzones ;
}
2020-02-23 11:32:32 +01:00
bool PadHandlerBase : : has_led ( ) const
2019-05-09 21:31:43 +02:00
{
return b_has_led ;
}
2021-02-28 04:50:23 +01:00
bool PadHandlerBase : : has_rgb ( ) const
{
return b_has_rgb ;
}
2022-10-19 21:47:18 +02:00
bool PadHandlerBase : : has_player_led ( ) const
{
return b_has_player_led ;
}
2020-03-05 19:02:28 +01:00
bool PadHandlerBase : : has_battery ( ) const
{
return b_has_battery ;
}
2021-08-06 02:08:18 +02:00
bool PadHandlerBase : : has_pressure_intensity_button ( ) const
{
return b_has_pressure_intensity_button ;
}
2017-12-23 22:25:51 +01:00
void PadHandlerBase : : init_configs ( )
{
2020-02-19 18:03:59 +01:00
for ( u32 i = 0 ; i < MAX_GAMEPADS ; i + + )
2017-12-23 22:25:51 +01:00
{
2021-08-10 21:45:26 +02:00
init_config ( & m_pad_configs [ i ] ) ;
2017-12-23 22:25:51 +01:00
}
}
2019-09-20 16:28:55 +02:00
2023-01-17 01:28:54 +01:00
cfg_pad * PadHandlerBase : : get_config ( const std : : string & pad_id )
{
int index = 0 ;
for ( uint i = 0 ; i < MAX_GAMEPADS ; i + + )
{
if ( g_cfg_input . player [ i ] - > handler = = m_type )
{
if ( g_cfg_input . player [ i ] - > device . to_string ( ) = = pad_id )
{
m_pad_configs [ index ] . from_string ( g_cfg_input . player [ i ] - > config . to_string ( ) ) ;
return & m_pad_configs [ index ] ;
}
index + + ;
}
}
return nullptr ;
}
2022-10-21 22:55:31 +02:00
PadHandlerBase : : connection PadHandlerBase : : get_next_button_press ( const std : : string & pad_id , const pad_callback & callback , const pad_fail_callback & fail_callback , bool get_blacklist , const std : : vector < std : : string > & /*buttons*/ )
2019-09-20 16:28:55 +02:00
{
if ( get_blacklist )
blacklist . clear ( ) ;
auto device = get_device ( pad_id ) ;
2023-06-13 01:19:32 +02:00
const connection status = update_connection ( device ) ;
2019-09-20 16:28:55 +02:00
if ( status = = connection : : disconnected )
2020-07-04 13:18:45 +02:00
{
if ( fail_callback )
fail_callback ( pad_id ) ;
2022-10-21 22:55:31 +02:00
return status ;
2020-07-04 13:18:45 +02:00
}
2022-06-05 15:58:05 +02:00
if ( status = = connection : : no_data )
{
2022-10-21 22:55:31 +02:00
return status ;
2022-06-05 15:58:05 +02:00
}
2019-09-20 16:28:55 +02:00
// Get the current button values
auto data = get_button_values ( device ) ;
// Check for each button in our list if its corresponding (maybe remapped) button or axis was pressed.
// Return the new value if the button was pressed (aka. its value was bigger than 0 or the defined threshold)
2022-08-13 09:56:04 +02:00
// Get all the legally pressed buttons and use the one with highest value (prioritize first)
struct
{
u16 value = 0 ;
std : : string name ;
} pressed_button { } ;
2022-06-05 15:58:05 +02:00
for ( const auto & [ keycode , name ] : button_list )
2019-09-20 16:28:55 +02:00
{
2022-06-05 15:58:05 +02:00
const u16 & value = data [ keycode ] ;
2019-09-20 16:28:55 +02:00
2023-06-14 20:57:30 +02:00
if ( ! get_blacklist & & blacklist . contains ( keycode ) )
2019-09-20 16:28:55 +02:00
continue ;
2022-10-15 12:41:21 +02:00
const bool is_trigger = get_is_left_trigger ( device , keycode ) | | get_is_right_trigger ( device , keycode ) ;
const bool is_stick = ! is_trigger & & ( get_is_left_stick ( device , keycode ) | | get_is_right_stick ( device , keycode ) ) ;
2019-09-20 16:28:55 +02:00
const bool is_button = ! is_trigger & & ! is_stick ;
if ( ( is_trigger & & ( value > m_trigger_threshold ) ) | | ( is_stick & & ( value > m_thumb_threshold ) ) | | ( is_button & & ( value > 0 ) ) )
{
if ( get_blacklist )
{
2023-06-14 20:57:30 +02:00
blacklist . insert ( keycode ) ;
2022-06-05 15:58:05 +02:00
input_log . error ( " %s Calibration: Added key [ %d = %s ] to blacklist. Value = %d " , m_type , keycode , name , value ) ;
2019-09-20 16:28:55 +02:00
}
2022-08-13 09:56:04 +02:00
else if ( value > pressed_button . value )
{
pressed_button = { . value = value , . name = name } ;
}
2019-09-20 16:28:55 +02:00
}
}
if ( get_blacklist )
{
if ( blacklist . empty ( ) )
2020-02-01 09:23:50 +01:00
input_log . success ( " %s Calibration: Blacklist is clear. No input spam detected " , m_type ) ;
2022-10-21 22:55:31 +02:00
return status ;
2019-09-20 16:28:55 +02:00
}
2020-07-04 13:18:45 +02:00
if ( callback )
{
2022-10-21 22:55:31 +02:00
const pad_preview_values preview_values = get_preview_values ( data ) ;
const u32 battery_level = get_battery_level ( pad_id ) ;
2022-08-13 09:56:04 +02:00
if ( pressed_button . value > 0 )
2022-10-21 22:55:31 +02:00
callback ( pressed_button . value , pressed_button . name , pad_id , battery_level , preview_values ) ;
2020-07-04 13:18:45 +02:00
else
2022-10-21 22:55:31 +02:00
callback ( 0 , " " , pad_id , battery_level , preview_values ) ;
2020-07-04 13:18:45 +02:00
}
2022-10-21 22:55:31 +02:00
return status ;
2022-08-13 09:56:04 +02:00
}
2019-09-20 16:28:55 +02:00
2022-08-13 09:56:04 +02:00
void PadHandlerBase : : get_motion_sensors ( const std : : string & pad_id , const motion_callback & callback , const motion_fail_callback & fail_callback , motion_preview_values preview_values , const std : : array < AnalogSensor , 4 > & /*sensors*/ )
{
if ( ! b_has_motion )
{
return ;
}
// Reset sensors
auto device = get_device ( pad_id ) ;
2023-06-13 01:19:32 +02:00
const connection status = update_connection ( device ) ;
2022-08-13 09:56:04 +02:00
if ( status = = connection : : disconnected )
{
if ( fail_callback )
fail_callback ( pad_id , std : : move ( preview_values ) ) ;
return ;
}
if ( status = = connection : : no_data | | ! callback )
{
return ;
}
// Get the current motion values
std : : shared_ptr < Pad > pad = std : : make_shared < Pad > ( m_type , 0 , 0 , 0 ) ;
pad - > m_sensors . resize ( preview_values . size ( ) , AnalogSensor ( 0 , 0 , 0 , 0 , 0 ) ) ;
pad_ensemble binding { pad , device , nullptr } ;
get_extended_info ( binding ) ;
for ( usz i = 0 ; i < preview_values . size ( ) ; i + + )
{
preview_values [ i ] = pad - > m_sensors [ i ] . m_value ;
}
callback ( pad_id , std : : move ( preview_values ) ) ;
2019-09-20 16:28:55 +02:00
}
2020-07-12 19:30:45 +02:00
void PadHandlerBase : : convert_stick_values ( u16 & x_out , u16 & y_out , const s32 & x_in , const s32 & y_in , const s32 & deadzone , const s32 & padsquircling ) const
{
// Normalize our stick axis based on the deadzone
std : : tie ( x_out , y_out ) = NormalizeStickDeadzone ( x_in , y_in , deadzone ) ;
// Apply pad squircling if necessary
if ( padsquircling ! = 0 )
{
std : : tie ( x_out , y_out ) = ConvertToSquirclePoint ( x_out , y_out , padsquircling ) ;
}
}
2019-09-20 16:28:55 +02:00
// Update the pad button values based on their type and thresholds. With this you can use axis or triggers as buttons or vice versa
void PadHandlerBase : : TranslateButtonPress ( const std : : shared_ptr < PadDevice > & device , u64 keyCode , bool & pressed , u16 & val , bool ignore_stick_threshold , bool ignore_trigger_threshold )
{
if ( ! device | | ! device - > config )
{
return ;
}
2022-10-15 12:41:21 +02:00
if ( get_is_left_trigger ( device , keyCode ) )
2019-09-20 16:28:55 +02:00
{
pressed = val > ( ignore_trigger_threshold ? 0 : device - > config - > ltriggerthreshold ) ;
val = pressed ? NormalizeTriggerInput ( val , device - > config - > ltriggerthreshold ) : 0 ;
}
2022-10-15 12:41:21 +02:00
else if ( get_is_right_trigger ( device , keyCode ) )
2019-09-20 16:28:55 +02:00
{
pressed = val > ( ignore_trigger_threshold ? 0 : device - > config - > rtriggerthreshold ) ;
val = pressed ? NormalizeTriggerInput ( val , device - > config - > rtriggerthreshold ) : 0 ;
}
2022-10-15 12:41:21 +02:00
else if ( get_is_left_stick ( device , keyCode ) )
2019-09-20 16:28:55 +02:00
{
pressed = val > ( ignore_stick_threshold ? 0 : device - > config - > lstickdeadzone ) ;
val = pressed ? NormalizeStickInput ( val , device - > config - > lstickdeadzone , device - > config - > lstickmultiplier , ignore_stick_threshold ) : 0 ;
}
2022-10-15 12:41:21 +02:00
else if ( get_is_right_stick ( device , keyCode ) )
2019-09-20 16:28:55 +02:00
{
pressed = val > ( ignore_stick_threshold ? 0 : device - > config - > rstickdeadzone ) ;
val = pressed ? NormalizeStickInput ( val , device - > config - > rstickdeadzone , device - > config - > rstickmultiplier , ignore_stick_threshold ) : 0 ;
}
else // normal button (should in theory also support sensitive buttons)
{
pressed = val > 0 ;
val = pressed ? val : 0 ;
}
}
2022-08-13 09:56:04 +02:00
bool PadHandlerBase : : bindPadToDevice ( std : : shared_ptr < Pad > pad , u8 player_id )
2019-09-20 16:28:55 +02:00
{
2022-08-13 09:56:04 +02:00
if ( ! pad | | player_id > = g_cfg_input . player . size ( ) )
2022-01-27 21:06:37 +01:00
{
return false ;
}
2022-08-13 09:56:04 +02:00
const cfg_player * player_config = g_cfg_input . player [ player_id ] ;
if ( ! player_config )
{
return false ;
}
std : : shared_ptr < PadDevice > pad_device = get_device ( player_config - > device ) ;
2019-09-20 16:28:55 +02:00
if ( ! pad_device )
2020-10-25 20:59:03 +01:00
{
2022-08-13 09:56:04 +02:00
input_log . error ( " PadHandlerBase::bindPadToDevice: no PadDevice found for device '%s' " , player_config - > device . to_string ( ) ) ;
2019-09-20 16:28:55 +02:00
return false ;
2020-10-25 20:59:03 +01:00
}
2019-09-20 16:28:55 +02:00
2022-08-13 09:56:04 +02:00
m_pad_configs [ player_id ] . from_string ( player_config - > config . to_string ( ) ) ;
2021-08-10 21:45:26 +02:00
pad_device - > config = & m_pad_configs [ player_id ] ;
2021-08-09 23:41:49 +02:00
pad_device - > player_id = player_id ;
2021-08-10 21:45:26 +02:00
cfg_pad * config = pad_device - > config ;
if ( config = = nullptr )
2020-10-25 20:59:03 +01:00
{
2022-08-13 09:56:04 +02:00
input_log . error ( " PadHandlerBase::bindPadToDevice: no profile found for device %d '%s' " , m_bindings . size ( ) , player_config - > device . to_string ( ) ) ;
2019-09-20 16:28:55 +02:00
return false ;
2020-10-25 20:59:03 +01:00
}
2019-09-20 16:28:55 +02:00
2023-06-13 01:19:32 +02:00
std : : array < std : : set < u32 > , button : : button_count > mapping = get_mapped_key_codes ( pad_device , config ) ;
2019-09-20 16:28:55 +02:00
2020-04-25 02:12:19 +02:00
u32 pclass_profile = 0x0 ;
2023-06-13 01:19:32 +02:00
for ( const input : : product_info & product : input : : get_products_by_class ( config - > device_class_type ) )
2020-04-25 02:12:19 +02:00
{
2021-08-10 21:45:26 +02:00
if ( product . vendor_id = = config - > vendor_id & & product . product_id = = config - > product_id )
2020-04-25 02:12:19 +02:00
{
pclass_profile = product . pclass_profile ;
}
}
2019-09-20 16:28:55 +02:00
pad - > Init
(
CELL_PAD_STATUS_DISCONNECTED ,
CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE ,
CELL_PAD_DEV_TYPE_STANDARD ,
2021-08-10 21:45:26 +02:00
config - > device_class_type ,
2020-04-25 02:12:19 +02:00
pclass_profile ,
2021-08-10 21:45:26 +02:00
config - > vendor_id ,
config - > product_id ,
config - > pressure_intensity
2019-09-20 16:28:55 +02:00
) ;
2021-08-06 02:08:18 +02:00
pad - > m_buttons . emplace_back ( special_button_offset , mapping [ button : : pressure_intensity_button ] , special_button_value : : pressure_intensity ) ;
2021-08-15 18:43:48 +02:00
pad - > m_pressure_intensity_button_index = static_cast < s32 > ( pad - > m_buttons . size ( ) ) - 1 ;
2021-08-06 02:08:18 +02:00
2019-09-20 16:28:55 +02:00
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL1 , mapping [ button : : up ] , CELL_PAD_CTRL_UP ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL1 , mapping [ button : : down ] , CELL_PAD_CTRL_DOWN ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL1 , mapping [ button : : left ] , CELL_PAD_CTRL_LEFT ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL1 , mapping [ button : : right ] , CELL_PAD_CTRL_RIGHT ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL2 , mapping [ button : : cross ] , CELL_PAD_CTRL_CROSS ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL2 , mapping [ button : : square ] , CELL_PAD_CTRL_SQUARE ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL2 , mapping [ button : : circle ] , CELL_PAD_CTRL_CIRCLE ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL2 , mapping [ button : : triangle ] , CELL_PAD_CTRL_TRIANGLE ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL2 , mapping [ button : : l1 ] , CELL_PAD_CTRL_L1 ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL2 , mapping [ button : : l2 ] , CELL_PAD_CTRL_L2 ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL1 , mapping [ button : : l3 ] , CELL_PAD_CTRL_L3 ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL2 , mapping [ button : : r1 ] , CELL_PAD_CTRL_R1 ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL2 , mapping [ button : : r2 ] , CELL_PAD_CTRL_R2 ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL1 , mapping [ button : : r3 ] , CELL_PAD_CTRL_R3 ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL1 , mapping [ button : : start ] , CELL_PAD_CTRL_START ) ;
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL1 , mapping [ button : : select ] , CELL_PAD_CTRL_SELECT ) ;
2023-02-10 03:53:10 +01:00
pad - > m_buttons . emplace_back ( CELL_PAD_BTN_OFFSET_DIGITAL1 , mapping [ button : : ps ] , CELL_PAD_CTRL_PS ) ;
2019-09-20 16:28:55 +02:00
pad - > m_sticks . emplace_back ( CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X , mapping [ button : : ls_left ] , mapping [ button : : ls_right ] ) ;
pad - > m_sticks . emplace_back ( CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y , mapping [ button : : ls_down ] , mapping [ button : : ls_up ] ) ;
pad - > m_sticks . emplace_back ( CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X , mapping [ button : : rs_left ] , mapping [ button : : rs_right ] ) ;
pad - > m_sticks . emplace_back ( CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y , mapping [ button : : rs_down ] , mapping [ button : : rs_up ] ) ;
2022-08-13 09:56:04 +02:00
pad - > m_sensors . emplace_back ( CELL_PAD_BTN_OFFSET_SENSOR_X , 0 , 0 , 0 , DEFAULT_MOTION_X ) ;
pad - > m_sensors . emplace_back ( CELL_PAD_BTN_OFFSET_SENSOR_Y , 0 , 0 , 0 , DEFAULT_MOTION_Y ) ;
pad - > m_sensors . emplace_back ( CELL_PAD_BTN_OFFSET_SENSOR_Z , 0 , 0 , 0 , DEFAULT_MOTION_Z ) ;
pad - > m_sensors . emplace_back ( CELL_PAD_BTN_OFFSET_SENSOR_G , 0 , 0 , 0 , DEFAULT_MOTION_G ) ;
2019-09-20 16:28:55 +02:00
pad - > m_vibrateMotors . emplace_back ( true , 0 ) ;
pad - > m_vibrateMotors . emplace_back ( false , 0 ) ;
2022-08-13 09:56:04 +02:00
m_bindings . emplace_back ( pad , pad_device , nullptr ) ;
2019-09-20 16:28:55 +02:00
return true ;
}
2023-06-13 01:19:32 +02:00
std : : array < std : : set < u32 > , PadHandlerBase : : button : : button_count > PadHandlerBase : : get_mapped_key_codes ( const std : : shared_ptr < PadDevice > & device , const cfg_pad * cfg )
2021-08-10 21:45:26 +02:00
{
2023-06-13 01:19:32 +02:00
std : : array < std : : set < u32 > , button : : button_count > mapping { } ;
2022-10-15 12:41:21 +02:00
if ( ! device | | ! cfg )
2021-08-10 21:45:26 +02:00
return mapping ;
2023-06-13 01:19:32 +02:00
device - > trigger_code_left = FindKeyCodes < u32 , u64 > ( button_list , cfg - > l2 ) ;
device - > trigger_code_right = FindKeyCodes < u32 , u64 > ( button_list , cfg - > r2 ) ;
device - > axis_code_left [ 0 ] = FindKeyCodes < u32 , u64 > ( button_list , cfg - > ls_left ) ;
device - > axis_code_left [ 1 ] = FindKeyCodes < u32 , u64 > ( button_list , cfg - > ls_right ) ;
device - > axis_code_left [ 2 ] = FindKeyCodes < u32 , u64 > ( button_list , cfg - > ls_down ) ;
device - > axis_code_left [ 3 ] = FindKeyCodes < u32 , u64 > ( button_list , cfg - > ls_up ) ;
device - > axis_code_right [ 0 ] = FindKeyCodes < u32 , u64 > ( button_list , cfg - > rs_left ) ;
device - > axis_code_right [ 1 ] = FindKeyCodes < u32 , u64 > ( button_list , cfg - > rs_right ) ;
device - > axis_code_right [ 2 ] = FindKeyCodes < u32 , u64 > ( button_list , cfg - > rs_down ) ;
device - > axis_code_right [ 3 ] = FindKeyCodes < u32 , u64 > ( button_list , cfg - > rs_up ) ;
mapping [ button : : up ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > up ) ;
mapping [ button : : down ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > down ) ;
mapping [ button : : left ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > left ) ;
mapping [ button : : right ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > right ) ;
mapping [ button : : cross ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > cross ) ;
mapping [ button : : square ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > square ) ;
mapping [ button : : circle ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > circle ) ;
mapping [ button : : triangle ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > triangle ) ;
mapping [ button : : start ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > start ) ;
mapping [ button : : select ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > select ) ;
mapping [ button : : l1 ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > l1 ) ;
mapping [ button : : l2 ] = narrow_set ( device - > trigger_code_left ) ;
mapping [ button : : l3 ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > l3 ) ;
mapping [ button : : r1 ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > r1 ) ;
mapping [ button : : r2 ] = narrow_set ( device - > trigger_code_right ) ;
mapping [ button : : r3 ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > r3 ) ;
mapping [ button : : ls_left ] = narrow_set ( device - > axis_code_left [ 0 ] ) ;
mapping [ button : : ls_right ] = narrow_set ( device - > axis_code_left [ 1 ] ) ;
mapping [ button : : ls_down ] = narrow_set ( device - > axis_code_left [ 2 ] ) ;
mapping [ button : : ls_up ] = narrow_set ( device - > axis_code_left [ 3 ] ) ;
mapping [ button : : rs_left ] = narrow_set ( device - > axis_code_right [ 0 ] ) ;
mapping [ button : : rs_right ] = narrow_set ( device - > axis_code_right [ 1 ] ) ;
mapping [ button : : rs_down ] = narrow_set ( device - > axis_code_right [ 2 ] ) ;
mapping [ button : : rs_up ] = narrow_set ( device - > axis_code_right [ 3 ] ) ;
mapping [ button : : ps ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > ps ) ;
mapping [ button : : pressure_intensity_button ] = FindKeyCodes < u32 , u32 > ( button_list , cfg - > pressure_intensity_button ) ;
2021-08-06 02:08:18 +02:00
2019-09-20 16:28:55 +02:00
return mapping ;
}
2022-08-13 09:56:04 +02:00
void PadHandlerBase : : get_mapping ( const pad_ensemble & binding )
2019-09-20 16:28:55 +02:00
{
2022-08-13 09:56:04 +02:00
const auto & device = binding . device ;
const auto & pad = binding . pad ;
2019-09-20 16:28:55 +02:00
if ( ! device | | ! pad )
return ;
2023-06-13 01:19:32 +02:00
const cfg_pad * cfg = device - > config ;
2023-06-14 20:57:30 +02:00
if ( ! cfg )
return ;
2019-09-20 16:28:55 +02:00
auto button_values = get_button_values ( device ) ;
2021-08-29 09:08:31 +02:00
// Find out if special buttons are pressed (introduced by RPCS3).
// These buttons will have a delay of one cycle, but whatever.
2023-06-05 21:56:01 +02:00
const bool adjust_pressure = pad - > get_pressure_intensity_enabled ( cfg - > pressure_intensity_toggle_mode . get ( ) ) ;
2021-08-29 09:08:31 +02:00
2019-09-20 16:28:55 +02:00
// Translate any corresponding keycodes to our normal DS3 buttons and triggers
2023-06-14 20:57:30 +02:00
for ( Button & button : pad - > m_buttons )
2019-09-20 16:28:55 +02:00
{
2023-06-13 01:19:32 +02:00
bool pressed { } ;
u16 value { } ;
2021-08-29 09:08:31 +02:00
2023-06-14 20:57:30 +02:00
for ( u32 code : button . m_key_codes )
2021-08-29 09:08:31 +02:00
{
2023-06-13 01:19:32 +02:00
bool press { } ;
u16 val = button_values [ code ] ;
TranslateButtonPress ( device , code , press , val ) ;
if ( press )
{
// Modify pressure if necessary if the button was pressed
if ( adjust_pressure )
{
val = pad - > m_pressure_intensity ;
}
value = std : : max ( value , val ) ;
pressed = true ;
}
2021-08-29 09:08:31 +02:00
}
2023-06-14 20:57:30 +02:00
button . m_value = value ;
button . m_pressed = pressed ;
2019-09-20 16:28:55 +02:00
}
// used to get the absolute value of an axis
2023-06-13 01:19:32 +02:00
s32 stick_val [ 4 ] { } ;
2019-09-20 16:28:55 +02:00
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
for ( int i = 0 ; i < static_cast < int > ( pad - > m_sticks . size ( ) ) ; i + + )
{
2023-06-13 01:19:32 +02:00
bool pressed { } ;
u16 val_min { } ;
u16 val_max { } ;
// m_key_codes_min are the mapped keys for left or down
for ( u32 key_min : pad - > m_sticks [ i ] . m_key_codes_min )
{
u16 val = button_values [ key_min ] ;
TranslateButtonPress ( device , key_min , pressed , val , true ) ;
2019-09-20 16:28:55 +02:00
2023-06-13 01:19:32 +02:00
if ( pressed )
{
val_min = std : : max ( val_min , val ) ;
}
}
2019-09-20 16:28:55 +02:00
2023-06-13 01:19:32 +02:00
// m_key_codes_max are the mapped keys for right or up
for ( u32 key_max : pad - > m_sticks [ i ] . m_key_codes_max )
{
u16 val = button_values [ key_max ] ;
TranslateButtonPress ( device , key_max , pressed , val , true ) ;
if ( pressed )
{
val_max = std : : max ( val_max , val ) ;
}
}
2019-09-20 16:28:55 +02:00
// cancel out opposing values and get the resulting difference
stick_val [ i ] = val_max - val_min ;
}
u16 lx , ly , rx , ry ;
2020-07-12 19:30:45 +02:00
// Normalize and apply pad squircling
2021-08-29 08:39:16 +02:00
convert_stick_values ( lx , ly , stick_val [ 0 ] , stick_val [ 1 ] , cfg - > lstickdeadzone , cfg - > lpadsquircling ) ;
convert_stick_values ( rx , ry , stick_val [ 2 ] , stick_val [ 3 ] , cfg - > rstickdeadzone , cfg - > rpadsquircling ) ;
2019-09-20 16:28:55 +02:00
if ( m_type = = pad_handler : : ds4 )
{
ly = 255 - ly ;
ry = 255 - ry ;
// these are added with previous value and divided to 'smooth' out the readings
// the ds4 seems to rapidly flicker sometimes between two values and this seems to stop that
pad - > m_sticks [ 0 ] . m_value = ( lx + pad - > m_sticks [ 0 ] . m_value ) / 2 ; // LX
pad - > m_sticks [ 1 ] . m_value = ( ly + pad - > m_sticks [ 1 ] . m_value ) / 2 ; // LY
pad - > m_sticks [ 2 ] . m_value = ( rx + pad - > m_sticks [ 2 ] . m_value ) / 2 ; // RX
pad - > m_sticks [ 3 ] . m_value = ( ry + pad - > m_sticks [ 3 ] . m_value ) / 2 ; // RY
}
else
{
pad - > m_sticks [ 0 ] . m_value = lx ;
pad - > m_sticks [ 1 ] . m_value = 255 - ly ;
pad - > m_sticks [ 2 ] . m_value = rx ;
pad - > m_sticks [ 3 ] . m_value = 255 - ry ;
}
}
2022-10-21 22:48:38 +02:00
void PadHandlerBase : : process ( )
2019-09-20 16:28:55 +02:00
{
2022-08-13 09:56:04 +02:00
for ( usz i = 0 ; i < m_bindings . size ( ) ; + + i )
2019-09-20 16:28:55 +02:00
{
2022-08-13 09:56:04 +02:00
auto & device = m_bindings [ i ] . device ;
auto & pad = m_bindings [ i ] . pad ;
2019-09-20 16:28:55 +02:00
if ( ! device | | ! pad )
continue ;
2023-06-13 01:19:32 +02:00
const connection status = update_connection ( device ) ;
2019-09-20 16:28:55 +02:00
switch ( status )
{
case connection : : no_data :
case connection : : connected :
{
if ( ! last_connection_status [ i ] )
{
2020-02-01 09:23:50 +01:00
input_log . success ( " %s device %d connected " , m_type , i ) ;
2019-09-20 16:28:55 +02:00
pad - > m_port_status | = CELL_PAD_STATUS_CONNECTED ;
pad - > m_port_status | = CELL_PAD_STATUS_ASSIGN_CHANGES ;
last_connection_status [ i ] = true ;
connected_devices + + ;
}
if ( status = = connection : : no_data )
2022-08-13 09:56:04 +02:00
{
// TODO: don't skip entirely if buddy device has data
2023-06-14 20:57:30 +02:00
apply_pad_data ( m_bindings [ i ] ) ;
2019-09-20 16:28:55 +02:00
continue ;
2022-08-13 09:56:04 +02:00
}
2019-09-20 16:28:55 +02:00
break ;
}
case connection : : disconnected :
{
2023-05-18 17:17:30 +02:00
if ( g_cfg . io . keep_pads_connected )
{
if ( ! last_connection_status [ i ] )
{
input_log . success ( " %s device %d connected by force " , m_type , i ) ;
pad - > m_port_status | = CELL_PAD_STATUS_CONNECTED ;
pad - > m_port_status | = CELL_PAD_STATUS_ASSIGN_CHANGES ;
last_connection_status [ i ] = true ;
connected_devices + + ;
}
continue ;
}
2019-09-20 16:28:55 +02:00
if ( last_connection_status [ i ] )
{
2020-02-01 09:23:50 +01:00
input_log . error ( " %s device %d disconnected " , m_type , i ) ;
2019-09-20 16:28:55 +02:00
pad - > m_port_status & = ~ CELL_PAD_STATUS_CONNECTED ;
pad - > m_port_status | = CELL_PAD_STATUS_ASSIGN_CHANGES ;
last_connection_status [ i ] = false ;
connected_devices - - ;
}
continue ;
}
}
2022-08-13 09:56:04 +02:00
get_mapping ( m_bindings [ i ] ) ;
get_extended_info ( m_bindings [ i ] ) ;
apply_pad_data ( m_bindings [ i ] ) ;
2019-09-20 16:28:55 +02:00
}
}