diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp index 086a341854..8d717ab87f 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -86,6 +86,8 @@ void show_debug_overlay(const CellPadData& data, const Pad& pad, const pad_info& "> Digital: %5s %5s\n" "> Press: %5s %5s\n" "> Sensor: %5s %5s\n" + "> Large Motor: %5d %5d\n" + "> Small Motor: %5d %5d\n" ">\n" "> Digital 1: 0x%04x 0x%04x\n" "> Digital 2: 0x%04x 0x%04x\n" @@ -126,6 +128,8 @@ void show_debug_overlay(const CellPadData& data, const Pad& pad, const pad_info& "on", data.len >= CELL_PAD_LEN_CHANGE_DEFAULT ? "on" : "off", (setting & CELL_PAD_SETTING_PRESS_ON) ? "on" : "off", data.len >= CELL_PAD_LEN_CHANGE_PRESS_ON ? "on" : "off", (setting & CELL_PAD_SETTING_SENSOR_ON) ? "on" : "off", data.len >= CELL_PAD_LEN_CHANGE_SENSOR_ON ? "on" : "off", + pad.m_vibrateMotors[0].m_value, pad.m_vibrateMotors[0].m_adjusted_value, + pad.m_vibrateMotors[1].m_value, pad.m_vibrateMotors[1].m_adjusted_value, pad.m_digital_1, d1, pad.m_digital_2, d2, pad.m_press_up, !!(d1 & CELL_PAD_CTRL_UP), data.button[CELL_PAD_BTN_OFFSET_PRESS_UP], diff --git a/rpcs3/Emu/Io/PadHandler.cpp b/rpcs3/Emu/Io/PadHandler.cpp index 19b9347da6..561c9b15d3 100644 --- a/rpcs3/Emu/Io/PadHandler.cpp +++ b/rpcs3/Emu/Io/PadHandler.cpp @@ -40,7 +40,7 @@ f32 PadHandlerBase::ScaledInput(f32 raw_value, f32 minimum, f32 maximum, f32 dea } // convert [min, max] to [0, 1] - const f32 val = static_cast(std::clamp(raw_value, minimum, maximum) - minimum) / (maximum - minimum); + const f32 val = static_cast(std::max(minimum, std::min(raw_value, maximum)) - minimum) / (maximum - minimum); // convert [0, 1] to [0, range] return range * val; @@ -50,7 +50,7 @@ f32 PadHandlerBase::ScaledInput(f32 raw_value, f32 minimum, f32 maximum, f32 dea f32 PadHandlerBase::ScaledAxisInput(f32 raw_value, f32 minimum, f32 maximum, f32 deadzone, f32 range) { // convert [min, max] to [0, 1] - f32 val = static_cast(std::clamp(raw_value, minimum, maximum) - minimum) / (maximum - minimum); + f32 val = static_cast(std::max(minimum, std::min(raw_value, maximum)) - minimum) / (maximum - minimum); if (deadzone > 0) { @@ -762,6 +762,7 @@ void PadHandlerBase::process() for (VibrateMotor& motor : pad->m_vibrateMotors) { motor.m_value = 0; + motor.m_adjusted_value = 0; } pad->m_last_rumble_time_us = 0; diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index 99c085b015..b10df8ebdb 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -255,15 +255,6 @@ protected: return {}; } - // Get new multiplied value based on the multiplier - static s32 MultipliedInput(s32 raw_value, s32 multiplier); - - // Get new scaled value between 0 and 255 based on its minimum and maximum - static f32 ScaledInput(f32 raw_value, f32 minimum, f32 maximum, f32 deadzone, f32 range = 255.0f); - - // Get new scaled value between -255 and 255 based on its minimum and maximum - static f32 ScaledAxisInput(f32 raw_value, f32 minimum, f32 maximum, f32 deadzone, f32 range = 255.0f); - // Get normalized trigger value based on the range defined by a threshold u16 NormalizeTriggerInput(u16 value, u32 threshold) const; @@ -276,6 +267,17 @@ protected: // return is new x and y values in 0-255 range std::tuple NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone, u32 anti_deadzone) const; +public: + + // Get new multiplied value based on the multiplier + static s32 MultipliedInput(s32 raw_value, s32 multiplier); + + // Get new scaled value between 0 and 255 based on its minimum and maximum + static f32 ScaledInput(f32 raw_value, f32 minimum, f32 maximum, f32 deadzone, f32 range = 255.0f); + + // Get new scaled value between -255 and 255 based on its minimum and maximum + static f32 ScaledAxisInput(f32 raw_value, f32 minimum, f32 maximum, f32 deadzone, f32 range = 255.0f); + // get clamped value between 0 and 255 static u16 Clamp0To255(f32 input); @@ -291,7 +293,6 @@ protected: // This function assumes inX and inY is already in 0-255 static void ConvertToSquirclePoint(u16& inX, u16& inY, u32 squircle_factor); -public: // u32 thumb_min = 0; // Unused. Make sure all handlers report 0+ values for sticks in get_button_values. u32 thumb_max = 255; u32 trigger_min = 0; diff --git a/rpcs3/Emu/Io/pad_config.cpp b/rpcs3/Emu/Io/pad_config.cpp index fb0b140aeb..8d1ec42953 100644 --- a/rpcs3/Emu/Io/pad_config.cpp +++ b/rpcs3/Emu/Io/pad_config.cpp @@ -1,8 +1,7 @@ #include "stdafx.h" #include "pad_config.h" #include "Emu/system_utils.hpp" - -LOG_CHANNEL(input_log, "Input"); +#include "Emu/Io/PadHandler.h" extern std::string g_input_config_override; @@ -32,18 +31,30 @@ std::string cfg_pad::get_buttons(std::vector vec) return fmt::merge(vec, ","); } -u8 cfg_pad::get_large_motor_speed(const std::array& motor_speed) const +u8 cfg_pad::get_large_motor_speed(std::array& motors) const { - const u8 idx = switch_vibration_motors ? 1 : 0; + VibrateMotor& motor = motors[switch_vibration_motors ? 1 : 0]; const f32 multiplier = multiplier_vibration_motor_large / 100.0f; - return static_cast(std::clamp(motor_speed[idx].m_value * multiplier, 0.0f, 255.0f)); + + // Ignore lower range. Scale remaining range to full range. + const f32 adjusted = PadHandlerBase::ScaledInput(motor.m_value, static_cast(vibration_threshold.get()), 255.0f, 0.0f, 255.0f); + + // Apply multiplier + motor.m_adjusted_value = static_cast(std::clamp(adjusted * multiplier, 0.0f, 255.0f)); + return motor.m_adjusted_value; } -u8 cfg_pad::get_small_motor_speed(const std::array& motor_speed) const +u8 cfg_pad::get_small_motor_speed(std::array& motors) const { - const u8 idx = switch_vibration_motors ? 0 : 1; + VibrateMotor& motor = motors[switch_vibration_motors ? 0 : 1]; const f32 multiplier = multiplier_vibration_motor_small / 100.0f; - return static_cast(std::clamp(motor_speed[idx].m_value * multiplier, 0.0f, 255.0f)); + + // Ignore lower range. Scale remaining range to full range. + const f32 adjusted = PadHandlerBase::ScaledInput(motor.m_value, static_cast(vibration_threshold.get()), 255.0f, 0.0f, 255.0f); + + // Apply multiplier + motor.m_adjusted_value = static_cast(std::clamp(adjusted * multiplier, 0.0f, 255.0f)); + return motor.m_adjusted_value; } bool cfg_input::load(const std::string& title_id, const std::string& config_file, bool strict) diff --git a/rpcs3/Emu/Io/pad_config.h b/rpcs3/Emu/Io/pad_config.h index 7c39a79411..7f5aa1081d 100644 --- a/rpcs3/Emu/Io/pad_config.h +++ b/rpcs3/Emu/Io/pad_config.h @@ -28,8 +28,8 @@ struct cfg_pad final : cfg::node static std::vector get_buttons(const std::string& str); static std::string get_buttons(std::vector vec); - u8 get_large_motor_speed(const std::array& motor_speed) const; - u8 get_small_motor_speed(const std::array& motor_speed) const; + u8 get_large_motor_speed(std::array& motors) const; + u8 get_small_motor_speed(std::array& motors) const; cfg::string ls_left{ this, "Left Stick Left", "" }; cfg::string ls_down{ this, "Left Stick Down", "" }; @@ -102,6 +102,7 @@ struct cfg_pad final : cfg::node cfg::uint<0, 200> multiplier_vibration_motor_large{ this, "Large Vibration Motor Multiplier", 100 }; cfg::uint<0, 200> multiplier_vibration_motor_small{ this, "Small Vibration Motor Multiplier", 100 }; cfg::_bool switch_vibration_motors{ this, "Switch Vibration Motors", false }; + cfg::uint<0, 255> vibration_threshold{ this, "Vibration Threshold", MOTOR_THRESHOLD }; cfg::_enum mouse_move_mode{ this, "Mouse Movement Mode", mouse_movement_mode::relative }; cfg::uint<0, 255> mouse_deadzone_x{ this, "Mouse Deadzone X Axis", 60 }; diff --git a/rpcs3/Emu/Io/pad_types.h b/rpcs3/Emu/Io/pad_types.h index ecbadff3bf..45790f5a00 100644 --- a/rpcs3/Emu/Io/pad_types.h +++ b/rpcs3/Emu/Io/pad_types.h @@ -344,6 +344,8 @@ struct CellPadData be_t button[CELL_PAD_MAX_CODES]; }; +static constexpr u8 MOTOR_THRESHOLD = 63; // The DS3 does not seem to respond to values <= 63. So we should ignore those in other handlers as well. + static constexpr u16 MOTION_ONE_G = 113; static constexpr u16 DEFAULT_MOTION_X = 512; static constexpr u16 DEFAULT_MOTION_Y = 399; // 512 - 113 (113 is 1G gravity) @@ -459,6 +461,7 @@ struct VibrateMotor { bool m_is_large_motor = false; u8 m_value = 0; + u8 m_adjusted_value = 0; VibrateMotor() {} VibrateMotor(bool is_large_motor, u8 value) diff --git a/rpcs3/Input/ds3_pad_handler.cpp b/rpcs3/Input/ds3_pad_handler.cpp index 2bc41ccead..00501b81c4 100644 --- a/rpcs3/Input/ds3_pad_handler.cpp +++ b/rpcs3/Input/ds3_pad_handler.cpp @@ -209,6 +209,7 @@ void ds3_pad_handler::init_config(cfg_pad* cfg) cfg->rtriggerthreshold.def = 0; // between 0 and 255 cfg->lpadsquircling.def = 0; cfg->rpadsquircling.def = 0; + cfg->vibration_threshold.def = 0; // Set default LED options cfg->led_battery_indicator.def = false;