diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 983eb850..5e21adaa 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -170,6 +171,15 @@ static void SetControllerInputDevice(Controller* controller) hid::g_inputDevice = controller->GetInputDevice(); hid::g_inputDeviceController = hid::g_inputDevice; + + auto controllerType = (hid::EInputDeviceExplicit)controller->GetControllerType(); + + if (hid::g_inputDeviceExplicit != controllerType) + { + hid::g_inputDeviceExplicit = controllerType; + + LOGFN("Detected controller: {}", hid::GetInputDeviceName()); + } } int HID_OnSDLEvent(void*, SDL_Event* event) @@ -199,6 +209,7 @@ int HID_OnSDLEvent(void*, SDL_Event* event) case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONUP: case SDL_CONTROLLERAXISMOTION: + case SDL_CONTROLLERTOUCHPADDOWN: { auto* controller = FindController(event->cdevice.which); diff --git a/UnleashedRecomp/hid/hid.cpp b/UnleashedRecomp/hid/hid.cpp index 07ca9c45..14ac8030 100644 --- a/UnleashedRecomp/hid/hid.cpp +++ b/UnleashedRecomp/hid/hid.cpp @@ -2,6 +2,7 @@ hid::EInputDevice hid::g_inputDevice; hid::EInputDevice hid::g_inputDeviceController; +hid::EInputDeviceExplicit hid::g_inputDeviceExplicit; uint16_t hid::g_prohibitedButtons; @@ -15,3 +16,59 @@ bool hid::IsInputDeviceController() return hid::g_inputDevice != hid::EInputDevice::Keyboard && hid::g_inputDevice != hid::EInputDevice::Mouse; } + +std::string hid::GetInputDeviceName() +{ + switch (g_inputDevice) + { + case EInputDevice::Keyboard: + return "Keyboard"; + + case EInputDevice::Mouse: + return "Mouse"; + } + + switch (g_inputDeviceExplicit) + { + case EInputDeviceExplicit::Xbox360: + return "Xbox 360"; + + case EInputDeviceExplicit::XboxOne: + return "Xbox One"; + + case EInputDeviceExplicit::DualShock3: + return "DualShock 3"; + + case EInputDeviceExplicit::DualShock4: + return "DualShock 4"; + + case EInputDeviceExplicit::SwitchPro: + return "Nintendo Switch Pro"; + + case EInputDeviceExplicit::Virtual: + return "Virtual"; + + case EInputDeviceExplicit::DualSense: + return "DualSense"; + + case EInputDeviceExplicit::Luna: + return "Amazon Luna"; + + case EInputDeviceExplicit::Stadia: + return "Google Stadia"; + + case EInputDeviceExplicit::NvShield: + return "NVIDIA Shield"; + + case EInputDeviceExplicit::SwitchJCLeft: + return "Nintendo Switch Joy-Con (Left)"; + + case EInputDeviceExplicit::SwitchJCRight: + return "Nintendo Switch Joy-Con (Right)"; + + case EInputDeviceExplicit::SwitchJCPair: + return "Nintendo Switch Joy-Con (Pair)"; + } + + return "Unknown"; +} diff --git a/UnleashedRecomp/hid/hid.h b/UnleashedRecomp/hid/hid.h index d9bf21df..922c21cf 100644 --- a/UnleashedRecomp/hid/hid.h +++ b/UnleashedRecomp/hid/hid.h @@ -10,8 +10,27 @@ namespace hid PlayStation }; + enum class EInputDeviceExplicit + { + Unknown, + Xbox360, + XboxOne, + DualShock3, + DualShock4, + SwitchPro, + Virtual, + DualSense, + Luna, + Stadia, + NvShield, + SwitchJCLeft, + SwitchJCRight, + SwitchJCPair + }; + extern EInputDevice g_inputDevice; extern EInputDevice g_inputDeviceController; + extern EInputDeviceExplicit g_inputDeviceExplicit; extern uint16_t g_prohibitedButtons; @@ -23,4 +42,5 @@ namespace hid uint32_t GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps); bool IsInputDeviceController(); + std::string GetInputDeviceName(); } diff --git a/UnleashedRecomp/patches/input_patches.cpp b/UnleashedRecomp/patches/input_patches.cpp index 2ec1e49a..7b9c2c4f 100644 --- a/UnleashedRecomp/patches/input_patches.cpp +++ b/UnleashedRecomp/patches/input_patches.cpp @@ -1,16 +1,46 @@ #include +#include #include #include #include -constexpr float WORLD_MAP_TOUCH_CANCEL_DEADZONE = 0.31f; -constexpr float WORLD_MAP_TOUCH_DAMPING_FACTOR = 0.99f; -constexpr float WORLD_MAP_TOUCH_FLICK_ACCELERATION_X = 0.4f; -constexpr float WORLD_MAP_TOUCH_FLICK_ACCELERATION_Y = 0.2f; -constexpr float WORLD_MAP_TOUCH_FLICK_TERMINAL_VELOCITY = 40.0f; -constexpr float WORLD_MAP_TOUCH_FLICK_THRESHOLD = 2.25f; -constexpr float WORLD_MAP_TOUCH_SENSITIVITY_MULTIPLIER = 1.35f; -constexpr float WORLD_MAP_TOUCH_SMOOTHING_FACTOR = 0.8f; +class WorldMapTouchParams +{ +public: + float CancelDeadzone{ 0.31f }; + float Damping{ 0.99f }; + float FlickAccelX{ 0.25f }; + float FlickAccelY{ 0.1f }; + float FlickTerminalVelocity{ 40.0f }; + float FlickThreshold{ 2.25f }; + float SensitivityX{}; + float SensitivityY{}; + float Smoothing{ 0.8f }; +}; + +class WorldMapTouchParamsProspero : public WorldMapTouchParams +{ +public: + WorldMapTouchParamsProspero() + { + SensitivityX = 1.15f; + SensitivityY = 1.05f; + } +} +g_worldMapTouchParamsProspero; + +class WorldMapTouchParamsOrbis : public WorldMapTouchParams +{ +public: + WorldMapTouchParamsOrbis() + { + SensitivityX = 0.95f; + SensitivityY = 1.0f; + } +} +g_worldMapTouchParamsOrbis; + +WorldMapTouchParams g_worldMapTouchParams{}; static bool g_isTouchActive; @@ -39,37 +69,32 @@ public: if (g_isTouchActive) { - constexpr auto sensitivity = WORLD_MAP_TOUCH_SENSITIVITY_MULTIPLIER; - auto dxNorm = ms_touchpadDeltaX / referenceDeltaTime; auto dyNorm = ms_touchpadDeltaY / referenceDeltaTime; - auto dxSens = dxNorm * sensitivity; - auto dySens = dyNorm * sensitivity; + auto dxSens = dxNorm * g_worldMapTouchParams.SensitivityX; + auto dySens = dyNorm * g_worldMapTouchParams.SensitivityY; - auto smoothing = powf(WORLD_MAP_TOUCH_SMOOTHING_FACTOR, deltaTime / referenceDeltaTime); + auto smoothing = powf(g_worldMapTouchParams.Smoothing, deltaTime / referenceDeltaTime); g_worldMapTouchVelocityX = smoothing * g_worldMapTouchVelocityX + (1.0f - smoothing) * dxSens; g_worldMapTouchVelocityY = smoothing * g_worldMapTouchVelocityY + (1.0f - smoothing) * dySens; - constexpr auto flickThreshold = WORLD_MAP_TOUCH_FLICK_THRESHOLD; + auto flickThreshold = g_worldMapTouchParams.FlickThreshold; if (fabs(dxSens) > flickThreshold || fabs(dySens) > flickThreshold) { - constexpr auto flickAccelX = WORLD_MAP_TOUCH_FLICK_ACCELERATION_X; - constexpr auto flickAccelY = WORLD_MAP_TOUCH_FLICK_ACCELERATION_Y; - - g_worldMapTouchVelocityX += dxNorm * flickAccelX * (deltaTime / referenceDeltaTime); - g_worldMapTouchVelocityY += dyNorm * flickAccelY * (deltaTime / referenceDeltaTime); + g_worldMapTouchVelocityX += dxNorm * g_worldMapTouchParams.FlickAccelX * (deltaTime / referenceDeltaTime); + g_worldMapTouchVelocityY += dyNorm * g_worldMapTouchParams.FlickAccelY * (deltaTime / referenceDeltaTime); } - constexpr auto terminalVelocity = WORLD_MAP_TOUCH_FLICK_TERMINAL_VELOCITY; + auto terminalVelocity = g_worldMapTouchParams.FlickTerminalVelocity; g_worldMapTouchVelocityX = std::clamp(g_worldMapTouchVelocityX, -terminalVelocity, terminalVelocity); g_worldMapTouchVelocityY = std::clamp(g_worldMapTouchVelocityY, -terminalVelocity, terminalVelocity); } else { - auto dampingFactor = powf(WORLD_MAP_TOUCH_DAMPING_FACTOR, deltaTime / referenceDeltaTime); + auto dampingFactor = powf(g_worldMapTouchParams.Damping, deltaTime / referenceDeltaTime); g_worldMapTouchVelocityX *= dampingFactor; g_worldMapTouchVelocityY *= dampingFactor; @@ -101,10 +126,17 @@ public: } case SDL_CONTROLLERTOUCHPADDOWN: + { + g_worldMapTouchParams = hid::g_inputDeviceExplicit == hid::EInputDeviceExplicit::DualSense + ? (WorldMapTouchParams)g_worldMapTouchParamsProspero + : (WorldMapTouchParams)g_worldMapTouchParamsOrbis; + ms_touchpadFingerCount++; ms_touchpadPrevX = event->ctouchpad.x; ms_touchpadPrevY = event->ctouchpad.y; + break; + } case SDL_CONTROLLERTOUCHPADUP: g_isTouchActive = false; @@ -199,7 +231,17 @@ bool WorldMapTouchSupportMidAsmHook() { SDLEventListenerForInputPatches::Update(App::s_deltaTime); - return fabs(g_worldMapTouchVelocityX) > 0 || fabs(g_worldMapTouchVelocityY) > 0; + auto vxAbs = fabs(g_worldMapTouchVelocityX); + auto vyAbs = fabs(g_worldMapTouchVelocityY); + + /* Reduce touch noise if the player has + their finger resting on the touchpad, + but allow much precise values without + touch for proper interpolation to zero. */ + if (vxAbs < 0.05f || vyAbs < 0.05f) + return !g_isTouchActive; + + return vxAbs > 0 || vyAbs > 0; } bool WorldMapTouchMagnetismSupportMidAsmHook(PPCRegister& f0) @@ -211,8 +253,8 @@ void TouchAndDPadSupportWorldMapXMidAsmHook(PPCRegister& pPadState, PPCRegister& { auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); - if (fabs(pGuestPadState->LeftStickHorizontal) > WORLD_MAP_TOUCH_CANCEL_DEADZONE || - fabs(pGuestPadState->LeftStickVertical) > WORLD_MAP_TOUCH_CANCEL_DEADZONE) + if (fabs(pGuestPadState->LeftStickHorizontal) > g_worldMapTouchParams.CancelDeadzone || + fabs(pGuestPadState->LeftStickVertical) > g_worldMapTouchParams.CancelDeadzone) { g_worldMapTouchVelocityX = 0; } @@ -234,8 +276,8 @@ void TouchAndDPadSupportWorldMapYMidAsmHook(PPCRegister& pPadState, PPCRegister& { auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); - if (fabs(pGuestPadState->LeftStickHorizontal) > WORLD_MAP_TOUCH_CANCEL_DEADZONE || - fabs(pGuestPadState->LeftStickVertical) > WORLD_MAP_TOUCH_CANCEL_DEADZONE) + if (fabs(pGuestPadState->LeftStickHorizontal) > g_worldMapTouchParams.CancelDeadzone || + fabs(pGuestPadState->LeftStickVertical) > g_worldMapTouchParams.CancelDeadzone) { g_worldMapTouchVelocityY = 0; } diff --git a/tools/XenonRecomp b/tools/XenonRecomp index 3280a7cf..73b75e19 160000 --- a/tools/XenonRecomp +++ b/tools/XenonRecomp @@ -1 +1 @@ -Subproject commit 3280a7cf9f3be293ff051b9d56d5dccff79f45ba +Subproject commit 73b75e197a6b9e8c1ad693f926c044d0f8f23a0b