diff --git a/README.md b/README.md index 35e0dfc4..daabd543 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,8 @@ These are miscellaneous controller-specific settings etc. - `dualsense_lightbar_brightness` Set LED lightbar brightness for Sony Dualsense controllers. Valid range [0-9] where 0=off, 1=min, 2-9=12.5-100% in 12.5% increments. - `dualsense_enable_player_leds` Enable/disable the white player indicator LEDs below the Dualsense touchpad. - `dualsense_vibration_intensity` Set Dualsense vibration intensity, 12.5% per increment. Valid range [1-8] where 1=12.5%, 8=100%. + - `dualsense_enable_adaptive_triggers` Enable/disable adaptive triggers for Dualsense. + - `dualsense_adaptive_triggers_resistance` Set Dualsense adaptive triggers resistance. Valid range [0-9] where 0=light, 9=heavy. ### Removal diff --git a/mc_mitm/config.ini b/mc_mitm/config.ini index ad0c02f9..fc250786 100644 --- a/mc_mitm/config.ini +++ b/mc_mitm/config.ini @@ -26,3 +26,7 @@ ;dualsense_enable_player_leds=false ; Set Dualsense vibration intensity, 12.5% per increment. Valid range [1-8] where 1=12.5%, 8=100% [default 4(50%)] ;dualsense_vibration_intensity=4 +; Enable adaptive triggers [default true] +;dualsense_enable_adaptive_triggers=true +; Set resistance of the DualSense adaptive triggers. Valid range [0-9] where 0=light, 9=heavy [default 0(light)] +;dualsense_adaptive_triggers_resistance=0 diff --git a/mc_mitm/source/controllers/dualsense_controller.cpp b/mc_mitm/source/controllers/dualsense_controller.cpp index 90c648a3..49029a98 100644 --- a/mc_mitm/source/controllers/dualsense_controller.cpp +++ b/mc_mitm/source/controllers/dualsense_controller.cpp @@ -156,8 +156,8 @@ namespace ams::controller { this->MapButtons(&src->input0x01.buttons); - m_buttons.ZR = src->input0x01.right_trigger > (m_trigger_threshold * UINT8_MAX); - m_buttons.ZL = src->input0x01.left_trigger > (m_trigger_threshold * UINT8_MAX); + m_buttons.ZR = src->input0x01.right_trigger > (std::min(m_trigger_threshold * UINT8_MAX, UINT8_MAX - 1.0f)); + m_buttons.ZL = src->input0x01.left_trigger > (std::min(m_trigger_threshold * UINT8_MAX, UINT8_MAX - 1.0f)); } void DualsenseController::MapInputReport0x31(const DualsenseReportData *src) { @@ -190,8 +190,8 @@ namespace ams::controller { this->MapButtons(&src->input0x31.buttons); - m_buttons.ZR = src->input0x31.right_trigger > (m_trigger_threshold * UINT8_MAX); - m_buttons.ZL = src->input0x31.left_trigger > (m_trigger_threshold * UINT8_MAX); + m_buttons.ZR = src->input0x31.right_trigger > (std::min(m_trigger_threshold * UINT8_MAX, UINT8_MAX - 1.0f)); + m_buttons.ZL = src->input0x31.left_trigger > (std::min(m_trigger_threshold * UINT8_MAX, UINT8_MAX - 1.0f)); if (src->input0x31.buttons.touchpad) { for (int i = 0; i < 2; ++i) { @@ -310,6 +310,131 @@ namespace ams::controller { report.output0x31.data[2] = 0x54; report.output0x31.data[3] = m_rumble_state.amp_motor_right; report.output0x31.data[4] = m_rumble_state.amp_motor_left; + + if (config->misc.dualsense_enable_adaptive_triggers) { + // Magic numbers that work best after some trial & error + float trigger_threshold = (std::min(m_trigger_threshold * UINT8_MAX, UINT8_MAX - 1.0f)); + float adaptive_trigger_threshold_end = (std::max(trigger_threshold - 80.0f, 0.0f)); + float adaptive_trigger_threshold_start = (std::max(adaptive_trigger_threshold_end - 10.0f, 0.0f)); + + u8 force1 = static_cast(adaptive_trigger_threshold_start); + u8 force2 = static_cast(adaptive_trigger_threshold_end); + + u8 force3 = static_cast(config->misc.dualsense_adaptive_triggers_resistance / 9.0f * 255.0f); + + // --- Control flags --- + report.output0x31.data[1] = 0x01 | 0x02 | 0x04 | 0x08; + report.output0x31.data[2] = 0x01 | 0x04 | 0x10 | 0x40; + + // --- Right trigger --- + + // [Mode] + // 0x00 = Off + // 0x01 = Rigid + // 0x02 = Pulse + // 0x20 = Extra A + // 0x04 = Extra B + // 0xFC = Calibration + report.output0x31.data[11] = 0x02; + + // [Force 1] + // Start of resistance section + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[12] = force1; + + // [Force 2] + // (Mode Rigid = Amount of force exerted) + // (Mode Pulse = End of resistance section) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[13] = force2; + + // [Force 3] + // (Mode Pulse = Force exerted in range) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[14] = force3; + + // [Force 4] + // (Mode Extra A & Extra B = Strength of effect near release state) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[15] = 0x00; + + // [Force 5] + // (Mode Extra A & Extra B = Strength of effect near middle) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[16] = 0x00; + + // [Force 6] + // (Mode Extra A & Extra B = Strength of effect at pressed state) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[17] = 0x00; + + // [Force 7] + // (Mode Extra A & Extra B = Effect actuation frequency in Hz) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[20] = 0x00; + + // --- Left trigger --- + + // [Mode] + // 0x00 = Off + // 0x01 = Rigid + // 0x02 = Pulse + // 0x20 = Extra A + // 0x04 = Extra B + // 0xFC = Calibration + report.output0x31.data[22] = 0x02; + + // [Force 1] + // Start of resistance section + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[23] = force1; + + // [Force 2] + // (Mode Rigid = Amount of force exerted) + // (Mode Pulse = End of resistance section) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[24] = force2; + + // [Force 3] + // (Mode Pulse = Force exerted in range) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[25] = force3; + + // [Force 4] + // (Mode Extra A & Extra B = Strength of effect near release state) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[26] = 0x00; + + // [Force 5] + // (Mode Extra A & Extra B = Strength of effect near middle) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[27] = 0x00; + + // [Force 6] + // (Mode Extra A & Extra B = Strength of effect at pressed state) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[28] = 0x00; + + // [Force 7] + // (Mode Extra A & Extra B = Effect actuation frequency in Hz) + // 0x00 = 0% + // 0xFF = 100% + report.output0x31.data[31] = 0x00; + } + report.output0x31.data[37] = 0x08 - config->misc.dualsense_vibration_intensity; // User setting is inverse of how the controller sets intensity report.output0x31.data[39] = 0x02 | 0x01; report.output0x31.data[42] = 0x02; diff --git a/mc_mitm/source/mcmitm_config.cpp b/mc_mitm/source/mcmitm_config.cpp index 41b9e5f8..5c391848 100644 --- a/mc_mitm/source/mcmitm_config.cpp +++ b/mc_mitm/source/mcmitm_config.cpp @@ -36,7 +36,9 @@ namespace ams::mitm { .dualshock4_lightbar_brightness = 5, .dualsense_lightbar_brightness = 5, .dualsense_enable_player_leds = true, - .dualsense_vibration_intensity = 4 + .dualsense_vibration_intensity = 4, + .dualsense_enable_adaptive_triggers = true, + .dualsense_adaptive_triggers_resistance = 0 } }; @@ -107,6 +109,10 @@ namespace ams::mitm { ParseBoolean(value, &config->misc.dualsense_enable_player_leds); } else if (strcasecmp(name, "dualsense_vibration_intensity") == 0) { ParseInt(value, &config->misc.dualsense_vibration_intensity, 1, 8); + } else if (strcasecmp(name, "dualsense_enable_adaptive_triggers") == 0) { + ParseBoolean(value, &config->misc.dualsense_enable_adaptive_triggers); + } else if (strcasecmp(name, "dualsense_adaptive_triggers_resistance") == 0) { + ParseInt(value, &config->misc.dualsense_adaptive_triggers_resistance, 0, 9); } } else { return 0; diff --git a/mc_mitm/source/mcmitm_config.hpp b/mc_mitm/source/mcmitm_config.hpp index a38ecf61..f68b06ff 100644 --- a/mc_mitm/source/mcmitm_config.hpp +++ b/mc_mitm/source/mcmitm_config.hpp @@ -36,6 +36,8 @@ namespace ams::mitm { int dualsense_lightbar_brightness; bool dualsense_enable_player_leds; int dualsense_vibration_intensity; + bool dualsense_enable_adaptive_triggers; + int dualsense_adaptive_triggers_resistance; } misc; };