diff options
| -rw-r--r-- | src/common/input.h | 7 | ||||
| -rw-r--r-- | src/core/hid/emulated_controller.cpp | 34 | ||||
| -rw-r--r-- | src/input_common/drivers/sdl_driver.cpp | 20 |
3 files changed, 48 insertions, 13 deletions
diff --git a/src/common/input.h b/src/common/input.h index 8871a9d07..cdacd4689 100644 --- a/src/common/input.h +++ b/src/common/input.h | |||
| @@ -60,6 +60,12 @@ enum class PollingError { | |||
| 60 | Unknown, | 60 | Unknown, |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | // Hint for amplification curve to be used | ||
| 64 | enum class VibrationAmplificationType { | ||
| 65 | Linear, | ||
| 66 | Exponential, | ||
| 67 | }; | ||
| 68 | |||
| 63 | struct AnalogProperties { | 69 | struct AnalogProperties { |
| 64 | float deadzone{}; | 70 | float deadzone{}; |
| 65 | float range{1.0f}; | 71 | float range{1.0f}; |
| @@ -126,6 +132,7 @@ struct VibrationStatus { | |||
| 126 | f32 low_frequency{}; | 132 | f32 low_frequency{}; |
| 127 | f32 high_amplitude{}; | 133 | f32 high_amplitude{}; |
| 128 | f32 high_frequency{}; | 134 | f32 high_frequency{}; |
| 135 | VibrationAmplificationType type; | ||
| 129 | }; | 136 | }; |
| 130 | 137 | ||
| 131 | struct LedStatus { | 138 | struct LedStatus { |
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index e102c9437..7b0c4a49b 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp | |||
| @@ -54,7 +54,6 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type | |||
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | void EmulatedController::ReloadFromSettings() { | 56 | void EmulatedController::ReloadFromSettings() { |
| 57 | //LOG_ERROR(Service_HID, "reload config from settings {}", NpadIdTypeToIndex(npad_id_type)); | ||
| 58 | const auto player_index = NpadIdTypeToIndex(npad_id_type); | 57 | const auto player_index = NpadIdTypeToIndex(npad_id_type); |
| 59 | const auto& player = Settings::values.players.GetValue()[player_index]; | 58 | const auto& player = Settings::values.players.GetValue()[player_index]; |
| 60 | 59 | ||
| @@ -92,7 +91,7 @@ void EmulatedController::ReloadFromSettings() { | |||
| 92 | } | 91 | } |
| 93 | 92 | ||
| 94 | void EmulatedController::ReloadInput() { | 93 | void EmulatedController::ReloadInput() { |
| 95 | //LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); | 94 | // LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); |
| 96 | // If you load any device here add the equivalent to the UnloadInput() function | 95 | // If you load any device here add the equivalent to the UnloadInput() function |
| 97 | const auto left_side = button_params[Settings::NativeButton::ZL]; | 96 | const auto left_side = button_params[Settings::NativeButton::ZL]; |
| 98 | const auto right_side = button_params[Settings::NativeButton::ZR]; | 97 | const auto right_side = button_params[Settings::NativeButton::ZR]; |
| @@ -640,12 +639,22 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v | |||
| 640 | if (!output_devices[device_index]) { | 639 | if (!output_devices[device_index]) { |
| 641 | return false; | 640 | return false; |
| 642 | } | 641 | } |
| 642 | const auto player_index = NpadIdTypeToIndex(npad_id_type); | ||
| 643 | const auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 644 | const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f; | ||
| 645 | |||
| 646 | // Exponential amplification is too strong at low amplitudes. Switch to a linear | ||
| 647 | // amplification if strength is set below 0.7f | ||
| 648 | const Input::VibrationAmplificationType type = | ||
| 649 | strength > 0.7f ? Input::VibrationAmplificationType::Exponential | ||
| 650 | : Input::VibrationAmplificationType::Linear; | ||
| 643 | 651 | ||
| 644 | const Input::VibrationStatus status = { | 652 | const Input::VibrationStatus status = { |
| 645 | .low_amplitude = vibration.high_amplitude, | 653 | .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f), |
| 646 | .low_frequency = vibration.high_amplitude, | 654 | .low_frequency = vibration.low_frequency, |
| 647 | .high_amplitude = vibration.high_amplitude, | 655 | .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f), |
| 648 | .high_frequency = vibration.high_amplitude, | 656 | .high_frequency = vibration.high_frequency, |
| 657 | .type = type, | ||
| 649 | }; | 658 | }; |
| 650 | return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; | 659 | return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; |
| 651 | } | 660 | } |
| @@ -661,6 +670,7 @@ bool EmulatedController::TestVibration(std::size_t device_index) { | |||
| 661 | .low_frequency = 160.0f, | 670 | .low_frequency = 160.0f, |
| 662 | .high_amplitude = 0.001f, | 671 | .high_amplitude = 0.001f, |
| 663 | .high_frequency = 320.0f, | 672 | .high_frequency = 320.0f, |
| 673 | .type = Input::VibrationAmplificationType::Linear, | ||
| 664 | }; | 674 | }; |
| 665 | return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; | 675 | return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; |
| 666 | } | 676 | } |
| @@ -687,7 +697,7 @@ void EmulatedController::Connect() { | |||
| 687 | std::lock_guard lock{mutex}; | 697 | std::lock_guard lock{mutex}; |
| 688 | if (is_configuring) { | 698 | if (is_configuring) { |
| 689 | temporary_is_connected = true; | 699 | temporary_is_connected = true; |
| 690 | TriggerOnChange(ControllerTriggerType::Connected,false); | 700 | TriggerOnChange(ControllerTriggerType::Connected, false); |
| 691 | return; | 701 | return; |
| 692 | } | 702 | } |
| 693 | 703 | ||
| @@ -697,7 +707,7 @@ void EmulatedController::Connect() { | |||
| 697 | is_connected = true; | 707 | is_connected = true; |
| 698 | } | 708 | } |
| 699 | LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type)); | 709 | LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type)); |
| 700 | TriggerOnChange(ControllerTriggerType::Connected,true); | 710 | TriggerOnChange(ControllerTriggerType::Connected, true); |
| 701 | } | 711 | } |
| 702 | 712 | ||
| 703 | void EmulatedController::Disconnect() { | 713 | void EmulatedController::Disconnect() { |
| @@ -707,7 +717,7 @@ void EmulatedController::Disconnect() { | |||
| 707 | temporary_is_connected = false; | 717 | temporary_is_connected = false; |
| 708 | LOG_ERROR(Service_HID, "Disconnected temporal controller {}", | 718 | LOG_ERROR(Service_HID, "Disconnected temporal controller {}", |
| 709 | NpadIdTypeToIndex(npad_id_type)); | 719 | NpadIdTypeToIndex(npad_id_type)); |
| 710 | TriggerOnChange(ControllerTriggerType::Disconnected,false); | 720 | TriggerOnChange(ControllerTriggerType::Disconnected, false); |
| 711 | return; | 721 | return; |
| 712 | } | 722 | } |
| 713 | 723 | ||
| @@ -717,7 +727,7 @@ void EmulatedController::Disconnect() { | |||
| 717 | is_connected = false; | 727 | is_connected = false; |
| 718 | } | 728 | } |
| 719 | LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type)); | 729 | LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type)); |
| 720 | TriggerOnChange(ControllerTriggerType::Disconnected,true); | 730 | TriggerOnChange(ControllerTriggerType::Disconnected, true); |
| 721 | } | 731 | } |
| 722 | 732 | ||
| 723 | bool EmulatedController::IsConnected(bool temporary) const { | 733 | bool EmulatedController::IsConnected(bool temporary) const { |
| @@ -751,7 +761,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { | |||
| 751 | return; | 761 | return; |
| 752 | } | 762 | } |
| 753 | temporary_npad_type = npad_type_; | 763 | temporary_npad_type = npad_type_; |
| 754 | TriggerOnChange(ControllerTriggerType::Type,false); | 764 | TriggerOnChange(ControllerTriggerType::Type, false); |
| 755 | return; | 765 | return; |
| 756 | } | 766 | } |
| 757 | 767 | ||
| @@ -764,7 +774,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { | |||
| 764 | } | 774 | } |
| 765 | npad_type = npad_type_; | 775 | npad_type = npad_type_; |
| 766 | } | 776 | } |
| 767 | TriggerOnChange(ControllerTriggerType::Type,true); | 777 | TriggerOnChange(ControllerTriggerType::Type, true); |
| 768 | } | 778 | } |
| 769 | 779 | ||
| 770 | LedPattern EmulatedController::GetLedPattern() const { | 780 | LedPattern EmulatedController::GetLedPattern() const { |
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index cee2d965f..d56351815 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp | |||
| @@ -107,6 +107,14 @@ public: | |||
| 107 | 107 | ||
| 108 | return false; | 108 | return false; |
| 109 | } | 109 | } |
| 110 | |||
| 111 | bool HasHDRumble() const { | ||
| 112 | if (sdl_controller) { | ||
| 113 | return (SDL_GameControllerGetType(sdl_controller.get()) == | ||
| 114 | SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO); | ||
| 115 | } | ||
| 116 | return false; | ||
| 117 | } | ||
| 110 | /** | 118 | /** |
| 111 | * The Pad identifier of the joystick | 119 | * The Pad identifier of the joystick |
| 112 | */ | 120 | */ |
| @@ -515,16 +523,26 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier, | |||
| 515 | const auto process_amplitude = [](f32 amplitude) { | 523 | const auto process_amplitude = [](f32 amplitude) { |
| 516 | return (amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF; | 524 | return (amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF; |
| 517 | }; | 525 | }; |
| 518 | const Input::VibrationStatus new_vibration{ | 526 | const Input::VibrationStatus exponential_vibration{ |
| 519 | .low_amplitude = process_amplitude(vibration.low_amplitude), | 527 | .low_amplitude = process_amplitude(vibration.low_amplitude), |
| 520 | .low_frequency = vibration.low_frequency, | 528 | .low_frequency = vibration.low_frequency, |
| 521 | .high_amplitude = process_amplitude(vibration.high_amplitude), | 529 | .high_amplitude = process_amplitude(vibration.high_amplitude), |
| 522 | .high_frequency = vibration.high_frequency, | 530 | .high_frequency = vibration.high_frequency, |
| 531 | .type = Input::VibrationAmplificationType::Exponential, | ||
| 523 | }; | 532 | }; |
| 524 | 533 | ||
| 534 | Input::VibrationStatus new_vibration{}; | ||
| 535 | |||
| 536 | if (vibration.type == Input::VibrationAmplificationType::Linear || joystick->HasHDRumble()) { | ||
| 537 | new_vibration = vibration; | ||
| 538 | } else { | ||
| 539 | new_vibration = exponential_vibration; | ||
| 540 | } | ||
| 541 | |||
| 525 | if (!joystick->RumblePlay(new_vibration)) { | 542 | if (!joystick->RumblePlay(new_vibration)) { |
| 526 | return Input::VibrationError::Unknown; | 543 | return Input::VibrationError::Unknown; |
| 527 | } | 544 | } |
| 545 | |||
| 528 | return Input::VibrationError::None; | 546 | return Input::VibrationError::None; |
| 529 | } | 547 | } |
| 530 | Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, | 548 | Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, |