diff --git a/source-code/data/plugins/config.ini b/source-code/data/plugins/config.ini index ca3a630..bd6a8f8 100644 --- a/source-code/data/plugins/config.ini +++ b/source-code/data/plugins/config.ini @@ -80,6 +80,8 @@ No_Timer_Sprite=1 Unlock_Pseudo=0 #Enable the card menu (incomplete, it doesn't bypass the card prompt) Card=0 +#Allow using a real arcade slider attached to COM11 (or PS4 official FT controller) +Hardware_Slider=0 #Enable custom patches Custom_Patches=1 #Prevent data deletion diff --git a/source-code/data/plugins/keyconfig.ini b/source-code/data/plugins/keyconfig.ini index 64226b3..e4a7ca4 100644 --- a/source-code/data/plugins/keyconfig.ini +++ b/source-code/data/plugins/keyconfig.ini @@ -30,6 +30,7 @@ autopause =true slider_in_menus =false # Use the hardware slider from HORI FT official controller (PS4 version) +# Requires enabling hardware slider support. # Warning: alpha feature, may not work properly # Recommended to remove Ds4_L_Stick_* and Ds4_R_Stick_* from button bindings (JVS_LEFT, JVS_RIGHT, MENU_L, MENU_R). ps4_official_slider =false diff --git a/source-code/source/plugins/Launcher/framework.h b/source-code/source/plugins/Launcher/framework.h index a023bce..8b5d168 100644 --- a/source-code/source/plugins/Launcher/framework.h +++ b/source-code/source/plugins/Launcher/framework.h @@ -223,6 +223,9 @@ ConfigOptionBase* optionsArray[] = { new NumericOption(L"xinput_preferred", KEYCONFIG_SECTION, KEYCONFIG_FILE, L"XInput Controller Num:", L"Sets the preferred XInput controller.\nIf unavailable, the next connected controller is used.", 0, 0, 3), new OptionMetaSpacer(8), + new BooleanOption(L"hardware_slider", PATCHES_SECTION, CONFIG_FILE, L"Use Hardware Slider", L"Enable this if using a real arcade slider.\n(set the slider to port COM11)", false, false), + new OptionMetaSpacer(8), + new BooleanOption(L"opengl_patch_a", LAUNCHER_SECTION, CONFIG_FILE, L"OpenGL Patch A", L"Ignores some OpenGL-related errors. Don't use both patches at the same time unless you're know what you're doing.", false, false), new BooleanOption(L"opengl_patch_b", LAUNCHER_SECTION, CONFIG_FILE, L"OpenGL Patch B", L"Ignores some OpenGL-related errors. Don't use both patches at the same time unless you're know what you're doing.", false, false), new OptionMetaSpacer(8), diff --git a/source-code/source/plugins/Patches/dllmain.cpp b/source-code/source/plugins/Patches/dllmain.cpp index 127ec3e..f92f23f 100644 --- a/source-code/source/plugins/Patches/dllmain.cpp +++ b/source-code/source/plugins/Patches/dllmain.cpp @@ -787,6 +787,12 @@ void ApplyPatches() { { InjectCode((void*)0x0000000140565E6B, { 0x90, 0x90 }); } + // The original slider update needs to run for hardware sliders to work -- only patch it when using emulation + if (!nHardwareSlider) + { + // Don't update the touch slider state so we can write our own + InjectCode((void*)0x000000014061579B, { 0x90, 0x90, 0x90, 0x8B, 0x42, 0xE0, 0x90, 0x90, 0x90 }); + } // Quick start { if (nQuickStart == 1) // skip the card/guest screen diff --git a/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.cpp b/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.cpp index 29d9591..4c7a47a 100644 --- a/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.cpp +++ b/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.cpp @@ -129,18 +129,22 @@ namespace TLAC::Components EmulateSliderInput(LeftSideSlideLeft, LeftSideSlideRight, ContactPoints[0], 0.0f, 0.5f); EmulateSliderInput(RightSideSlideLeft, RightSideSlideRight, ContactPoints[1], 0.5f + sensorStep, 1.0f + sensorStep); - sliderState->ResetSensors(); + sliderState->ResetSensors(TouchSliderState::SENSOR_SET_MODE_SECTIONS); for (int i = 0; i < CONTACT_POINTS; i++) - ApplyContactPoint(ContactPoints[i]); + ApplyContactPoint(ContactPoints[i], i); } } void TouchSliderEmulator::OnFocusLost() { - sliderState->ResetSensors(); + if (usePs4OfficialSlider) + sliderState->ResetSensors(TouchSliderState::SENSOR_SET_MODE_RAW); + else + sliderState->ResetSensors(TouchSliderState::SENSOR_SET_MODE_SECTIONS); } + // EmulateSliderInput and ApplyContactPoint are used for analog stick/button slider emulation void TouchSliderEmulator::EmulateSliderInput(Binding *leftBinding, Binding *rightBinding, ContactPoint &contactPoint, float start, float end) { bool leftDown = leftBinding->AnyDown(); @@ -166,25 +170,35 @@ namespace TLAC::Components contactPoint.InContact = leftDown || rightDown; } - void TouchSliderEmulator::ApplyContactPoint(ContactPoint& contactPoint) + void TouchSliderEmulator::ApplyContactPoint(ContactPoint& contactPoint, int section) { + sliderState->SectionTouched[section] = contactPoint.InContact; + + int pressure = contactPoint.InContact ? FULL_PRESSURE : NO_PRESSURE; + float position = std::clamp(contactPoint.Position, 0.0f, 1.0f); + if (contactPoint.InContact) { - float position = std::clamp(contactPoint.Position, 0.0f, 1.0f); int sensor = (int)(position * (SLIDER_SENSORS - 1)); - sliderState->SetSensor(sensor, FULL_PRESSURE); + sliderState->SetSensor(sensor, pressure, TouchSliderState::SENSOR_SET_MODE_SECTIONS); } + + constexpr float startRange = -1.0f; + constexpr float endRange = +1.0f; + + sliderState->SectionPositions[section] = contactPoint.InContact ? (ConvertRange(0.0f, 1.0f, startRange, endRange, position)) : 0.0f; } + // ApplyBitfieldState is used for setting raw slider data void TouchSliderEmulator::ApplyBitfieldState(uint32_t state) { for (int i = 0; i < 32; i++) { if (state & (1 << (31 - i))) - sliderState->SetSensor(i, FULL_PRESSURE); + sliderState->SetSensor(i, FULL_PRESSURE, TouchSliderState::SENSOR_SET_MODE_RAW); else - sliderState->SetSensor(i, NO_PRESSURE); + sliderState->SetSensor(i, NO_PRESSURE, TouchSliderState::SENSOR_SET_MODE_RAW); } } } \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.h b/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.h index 9c90b1b..126210d 100644 --- a/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.h +++ b/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.h @@ -57,7 +57,7 @@ namespace TLAC::Components ContactPoint ContactPoints[CONTACT_POINTS]; void EmulateSliderInput(Input::Binding *leftBinding, Input::Binding *rightBinding, ContactPoint &contactPoint, float start, float end); - void ApplyContactPoint(ContactPoint &contactPoint); + void ApplyContactPoint(ContactPoint &contactPoint, int section); void ApplyBitfieldState(uint32_t state); }; } diff --git a/source-code/source/plugins/TLAC/Components/Input/TouchSliderState.cpp b/source-code/source/plugins/TLAC/Components/Input/TouchSliderState.cpp index dbee5db..b97359d 100644 --- a/source-code/source/plugins/TLAC/Components/Input/TouchSliderState.cpp +++ b/source-code/source/plugins/TLAC/Components/Input/TouchSliderState.cpp @@ -2,28 +2,36 @@ namespace TLAC::Components { - void TouchSliderState::SetSensor(int index, int value) + void TouchSliderState::SetSensor(int index, int value, SliderSensorSetMode mode) { if (index < 0 || index >= SLIDER_SENSORS) return; - - if (SerialState == nullptr) - return; - uint32_t* ph = SerialState->sliderSerialResponse.sensors[index].pressureHistory; - ph[3] = ph[2]; - ph[2] = ph[1]; - ph[1] = ph[0]; - ph[0] = value; + if (mode == SENSOR_SET_MODE_RAW) + { + if (SerialState == nullptr) + return; - SerialState->sliderSerialResponse.scanMode = 1; - SerialState->sliderSerialResponse.scanCount = 1; - SerialState->sliderResponseCnt = 1; + uint32_t* ph = SerialState->sliderSerialResponse.sensors[index].pressureHistory; + ph[3] = ph[2]; + ph[2] = ph[1]; + ph[1] = ph[0]; + ph[0] = value; + + SerialState->sliderSerialResponse.scanMode = 1; + SerialState->sliderSerialResponse.scanCount = 1; + SerialState->sliderResponseCnt = 1; + } + else + { + SensorPressureLevels[index] = value; + SensorTouched[index].IsTouched = value > 0; + } } - void TouchSliderState::ResetSensors() + void TouchSliderState::ResetSensors(SliderSensorSetMode mode) { for (int i = 0; i < SLIDER_SENSORS; i++) - SetSensor(i, NO_PRESSURE); + SetSensor(i, NO_PRESSURE, mode); } } \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/Components/Input/TouchSliderState.h b/source-code/source/plugins/TLAC/Components/Input/TouchSliderState.h index 8aeaefb..026c282 100644 --- a/source-code/source/plugins/TLAC/Components/Input/TouchSliderState.h +++ b/source-code/source/plugins/TLAC/Components/Input/TouchSliderState.h @@ -8,6 +8,7 @@ #define NO_PRESSURE 0 #define FULL_PRESSURE 180 + namespace TLAC::Components { struct TouchSliderSerialState @@ -64,8 +65,17 @@ namespace TLAC::Components uint8_t Padding[45]; } SensorTouched[SLIDER_SENSORS]; - void SetSensor(int index, int value); - void ResetSensors(); + + // two different places to be set depending on operation mode now + // stick/button based emulation directly controls sections and raw slider emulation controls fake serial inputs + enum SliderSensorSetMode + { + SENSOR_SET_MODE_SECTIONS, + SENSOR_SET_MODE_RAW + }; + + void SetSensor(int index, int value, SliderSensorSetMode mode); + void ResetSensors(SliderSensorSetMode mode); }; } diff --git a/source-code/source/plugins/TLAC/Components/Pause.cpp b/source-code/source/plugins/TLAC/Components/Pause.cpp index 98e8b58..4563e07 100644 --- a/source-code/source/plugins/TLAC/Components/Pause.cpp +++ b/source-code/source/plugins/TLAC/Components/Pause.cpp @@ -265,7 +265,8 @@ namespace TLAC::Components // no slider while paused // this is simpler than buttons because slider doesn't trigger on press, it triggers on movement // (therefore per-button blocking isn't needed) - sliderState->ResetSensors(); + // SENSOR_SET_MODE_SECTIONS matches old behaviour + sliderState->ResetSensors(TouchSliderState::SENSOR_SET_MODE_SECTIONS); } else {