From 8a5cb7595479ab7dadea2ce8eef056fac76cc2fb Mon Sep 17 00:00:00 2001 From: somewhatlurker <52014015+somewhatlurker@users.noreply.github.com> Date: Wed, 12 Aug 2020 22:34:21 +1000 Subject: [PATCH] TLAC: proper raw input for PS4 controller slider --- .../Components/Input/TouchSliderEmulator.cpp | 51 +++++++++---------- .../Input/DirectInput/DirectInputDevice.cpp | 39 ++++++++++++++ .../Input/DirectInput/DirectInputDevice.h | 2 + .../TLAC/Input/DirectInput/Ds4/DualShock4.cpp | 19 +++++++ .../TLAC/Input/DirectInput/Ds4/DualShock4.h | 7 ++- 5 files changed, 89 insertions(+), 29 deletions(-) diff --git a/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.cpp b/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.cpp index 2581547..29d9591 100644 --- a/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.cpp +++ b/source-code/source/plugins/TLAC/Components/Input/TouchSliderEmulator.cpp @@ -59,8 +59,22 @@ namespace TLAC::Components usePs4OfficialSlider = configFile.GetBooleanValue("ps4_official_slider"); enableInMenus = configFile.GetBooleanValue("slider_in_menus"); - if (!usePs4OfficialSlider) + if (usePs4OfficialSlider) { + DualShock4* ds4 = DualShock4::GetInstance(); + if (ds4 == nullptr) + DualShock4::rawMode = true; // set raw mode for future instances if no current instance + else + ds4->SetRawMode(true); // if is a current instance, set raw mode on it (also sets for future instances) + } + else + { + DualShock4* ds4 = DualShock4::GetInstance(); + if (ds4 == nullptr) + DualShock4::rawMode = false; // set raw mode for future instances if no current instance + else + ds4->SetRawMode(false); // if is a current instance, set raw mode on it (also sets for future instances) + Config::BindConfigKeys(configFile.ConfigMap, "LEFT_SIDE_SLIDE_LEFT", *LeftSideSlideLeft, { "Q" }); Config::BindConfigKeys(configFile.ConfigMap, "LEFT_SIDE_SLIDE_RIGHT", *LeftSideSlideRight, { "E" }); @@ -93,33 +107,16 @@ namespace TLAC::Components Joystick ls = ds4->GetLeftStick(); Joystick rs = ds4->GetRightStick(); - // this looks bad because it is -- experimentally derived based on observed values - /* - 0: -1 - 63: -0.507805 - 65: -0.492210 - 126: -0.015640 - 127: -0.007828 - 128: -0.000015 - 129: 0.000015 - 130: 0.007950 - 131: 0.015885 - 192: 0.500023 - 255: 1 - */ uint32_t state = 0; - uint8_t read; - //printf("left stick: %8.6f, %8.6f, ", ls.XAxis, ls.YAxis); - read = ls.XAxis < 0 ? ((ls.XAxis + 1.001) * 128) : 255 - (uint8_t)((-ls.XAxis + 1.001) * 126); - //printf("%d, ", (int)read); - state |= read ^ 0b10000000; - read = ls.YAxis < 0 ? ((ls.YAxis + 1.001) * 128) : 255 - (uint8_t)((-ls.YAxis + 1.001) * 126); - //printf("%d\n", (int)read); - state |= (read ^ 0b10000000) << 8; - read = rs.XAxis < 0 ? ((rs.XAxis + 1.001) * 128) : 255 - (uint8_t)((-rs.XAxis + 1.001) * 126); - state |= (read ^ 0b10000000) << 16; - read = rs.YAxis < 0 ? ((rs.YAxis + 1.001) * 128) : 255 - (uint8_t)((-rs.YAxis + 1.001) * 126); - state |= (read ^ 0b10000000) << 24; + + // DualShock4 normalises sticks to floats -- this undoes that + //printf("left stick: %9.6f, %9.6f, ", ls.XAxis, ls.YAxis); + state |= (uint8_t)((ls.XAxis + 1.0 + 0.001) * 127.5) ^ 0b10000000; // 0.001 to prevent rounding errors + //printf("%d, ", (int)(state ^ 0b10000000)); + state |= ((uint8_t)((ls.YAxis + 1.0 + 0.001) * 127.5) ^ 0b10000000) << 8; + //printf("%d\n", (int)((state >> 8) ^ 0b10000000)); + state |= ((uint8_t)((rs.XAxis + 1.0 + 0.001) * 127.5) ^ 0b10000000) << 16; + state |= ((uint8_t)((rs.YAxis + 1.0 + 0.001) * 127.5) ^ 0b10000000) << 24; ApplyBitfieldState(state); } diff --git a/source-code/source/plugins/TLAC/Input/DirectInput/DirectInputDevice.cpp b/source-code/source/plugins/TLAC/Input/DirectInput/DirectInputDevice.cpp index 85dbd12..385ce57 100644 --- a/source-code/source/plugins/TLAC/Input/DirectInput/DirectInputDevice.cpp +++ b/source-code/source/plugins/TLAC/Input/DirectInput/DirectInputDevice.cpp @@ -53,6 +53,45 @@ namespace TLAC::Input return result; } + HRESULT DirectInputDevice::DI_SetRange(LONG min, LONG max) + { + DIPROPRANGE propData; + propData.lMin = min; + propData.lMax = max; + + propData.diph.dwSize = sizeof(DIPROPRANGE); + propData.diph.dwHeaderSize = sizeof(DIPROPHEADER); + propData.diph.dwHow = DIPH_DEVICE; + propData.diph.dwObj = 0; + + HRESULT result = directInputdevice->SetProperty(DIPROP_RANGE, &propData.diph); + return result; + } + + HRESULT DirectInputDevice::DI_SetRawMode(BOOL raw) + { + // extra unacquire/acquire logic so this can be called on an active device + BOOL wasAcquired = DI_Unacquire() == DI_OK; + + DIPROPDWORD propData; + propData.dwData = raw ? DIPROPCALIBRATIONMODE_RAW : DIPROPCALIBRATIONMODE_COOKED; + + propData.diph.dwSize = sizeof(DIPROPDWORD); + propData.diph.dwHeaderSize = sizeof(DIPROPHEADER); + propData.diph.dwHow = DIPH_DEVICE; + propData.diph.dwObj = 0; + + HRESULT result = NULL; + + if (FAILED(result = directInputdevice->SetProperty(DIPROP_CALIBRATIONMODE, &propData.diph))) + return result; + + if (wasAcquired) + result = DI_Acquire(); + + return result; + } + void DirectInputDevice::DI_Dispose() { if (directInputdevice == nullptr) diff --git a/source-code/source/plugins/TLAC/Input/DirectInput/DirectInputDevice.h b/source-code/source/plugins/TLAC/Input/DirectInput/DirectInputDevice.h index 1579413..ff9be40 100644 --- a/source-code/source/plugins/TLAC/Input/DirectInput/DirectInputDevice.h +++ b/source-code/source/plugins/TLAC/Input/DirectInput/DirectInputDevice.h @@ -16,6 +16,8 @@ namespace TLAC::Input HRESULT DI_Release(); HRESULT DI_Poll(); HRESULT DI_GetDeviceState(DWORD size, LPVOID data); + HRESULT DI_SetRange(LONG min, LONG max); + HRESULT DI_SetRawMode(BOOL raw); void DI_Dispose(); }; diff --git a/source-code/source/plugins/TLAC/Input/DirectInput/Ds4/DualShock4.cpp b/source-code/source/plugins/TLAC/Input/DirectInput/Ds4/DualShock4.cpp index 899f56c..2755edd 100644 --- a/source-code/source/plugins/TLAC/Input/DirectInput/Ds4/DualShock4.cpp +++ b/source-code/source/plugins/TLAC/Input/DirectInput/Ds4/DualShock4.cpp @@ -6,6 +6,7 @@ namespace TLAC::Input { DualShock4* DualShock4::instance; + bool DualShock4::rawMode = false; DualShock4::DualShock4() { @@ -53,11 +54,29 @@ namespace TLAC::Input if (FAILED(result = DI_SetDataFormat(&c_dfDIJoystick2))) return false; + if (FAILED(result = DI_SetRange(0, 255))) // use 8-bit data + return false; + + // set raw mode from previous instance + if (rawMode && FAILED(result = DI_SetRawMode(true))) + return false; + result = DI_Acquire(); return true; } + bool DualShock4::SetRawMode(bool raw) + { + HRESULT result = NULL; + if (FAILED(result = DI_SetRawMode(raw))) + return false; + + rawMode = raw; + + return true; + } + bool DualShock4::PollInput() { lastState = currentState; diff --git a/source-code/source/plugins/TLAC/Input/DirectInput/Ds4/DualShock4.h b/source-code/source/plugins/TLAC/Input/DirectInput/Ds4/DualShock4.h index 8245f7e..acdf4db 100644 --- a/source-code/source/plugins/TLAC/Input/DirectInput/Ds4/DualShock4.h +++ b/source-code/source/plugins/TLAC/Input/DirectInput/Ds4/DualShock4.h @@ -31,6 +31,7 @@ namespace TLAC::Input static bool TryInitializeInstance(); bool Initialize(); + bool SetRawMode(bool raw); bool PollInput() override; bool IsDown(Ds4Button button); @@ -48,6 +49,8 @@ namespace TLAC::Input static inline DualShock4* GetInstance() { return instance; }; static inline void DeleteInstance() { delete instance; instance = nullptr; }; + static bool rawMode; // kinda dodgy, used to set raw mode for all instances without waiting for a single one + private: static DualShock4* instance; @@ -58,8 +61,8 @@ namespace TLAC::Input const float joystickThreshold = 0.5f; const float dpadThreshold = 0.5f; - inline float NormalizeTrigger(long value) { return (float)value / USHRT_MAX; }; - inline float NormalizeStick(long value) { return (float)value / USHRT_MAX * 2.0f - 1.0f; }; + inline float NormalizeTrigger(long value) { return (float)value / UCHAR_MAX; }; + inline float NormalizeStick(long value) { return (float)value / UCHAR_MAX * 2.0f - 1.0f; }; inline Joystick NormalizeStick(long x, long y) { return Joystick(NormalizeStick(x), NormalizeStick(y)); }; void UpdateInternalDs4State(Ds4State &state);