From 686ef22c4dcb60696edcc2814e46e60f04a54732 Mon Sep 17 00:00:00 2001 From: Hyper <34012267+hyperbx@users.noreply.github.com> Date: Thu, 23 Jan 2025 17:43:08 +0000 Subject: [PATCH] Implemented D-Pad support for the World Map, Gaia Colossus, Super Sonic and the Bobsleigh (#150) * Implemented D-Pad support for World Map, Super Sonic (WIP) and Bobsleigh * Implemented D-Pad support for Gaia Colossus and Super Sonic * Improved touchpad sensitivity --- UnleashedRecomp/api/SWA.h | 5 + .../api/SWA/Camera/CameraController.h | 17 + UnleashedRecomp/api/SWA/Menu/MenuWindowBase.h | 12 + .../GameMode/Title/TitleStateWorldMap.h | 14 + .../System/GameMode/WorldMap/WorldMapCamera.h | 26 ++ .../System/GameMode/WorldMap/WorldMapCursor.h | 24 ++ UnleashedRecomp/hid/driver/sdl_hid.cpp | 11 + UnleashedRecomp/hid/hid.cpp | 57 ++++ UnleashedRecomp/hid/hid.h | 20 ++ UnleashedRecomp/patches/input_patches.cpp | 321 +++++++++++++++++- UnleashedRecompLib/config/SWA.toml | 138 +++++++- 11 files changed, 623 insertions(+), 22 deletions(-) create mode 100644 UnleashedRecomp/api/SWA/Camera/CameraController.h create mode 100644 UnleashedRecomp/api/SWA/Menu/MenuWindowBase.h create mode 100644 UnleashedRecomp/api/SWA/System/GameMode/Title/TitleStateWorldMap.h create mode 100644 UnleashedRecomp/api/SWA/System/GameMode/WorldMap/WorldMapCamera.h create mode 100644 UnleashedRecomp/api/SWA/System/GameMode/WorldMap/WorldMapCursor.h diff --git a/UnleashedRecomp/api/SWA.h b/UnleashedRecomp/api/SWA.h index 1478fe2..01e0c61 100644 --- a/UnleashedRecomp/api/SWA.h +++ b/UnleashedRecomp/api/SWA.h @@ -59,6 +59,7 @@ #include "SWA/CSD/CsdTexListMirage.h" #include "SWA/CSD/GameObjectCSD.h" #include "SWA/Camera/Camera.h" +#include "SWA/Camera/CameraController.h" #include "SWA/CharacterUtility/CharacterProxy.h" #include "SWA/HUD/GeneralWindow/GeneralWindow.h" #include "SWA/HUD/Loading/Loading.h" @@ -74,6 +75,7 @@ #include "SWA/Inspire/InspireTextureAnimationInfo.h" #include "SWA/Inspire/InspireTextureOverlay.h" #include "SWA/Inspire/InspireTextureOverlayInfo.h" +#include "SWA/Menu/MenuWindowBase.h" #include "SWA/Movie/MovieDisplayer.h" #include "SWA/Movie/MovieManager.h" #include "SWA/Player/Character/EvilSonic/EvilSonic.h" @@ -98,6 +100,9 @@ #include "SWA/System/GameMode/Title/TitleMenu.h" #include "SWA/System/GameMode/Title/TitleStateBase.h" #include "SWA/System/GameMode/Title/TitleStateIntro.h" +#include "SWA/System/GameMode/Title/TitleStateWorldMap.h" +#include "SWA/System/GameMode/WorldMap/WorldMapCamera.h" +#include "SWA/System/GameMode/WorldMap/WorldMapCursor.h" #include "SWA/System/GameObject.h" #include "SWA/System/GameParameter.h" #include "SWA/System/GammaController.h" diff --git a/UnleashedRecomp/api/SWA/Camera/CameraController.h b/UnleashedRecomp/api/SWA/Camera/CameraController.h new file mode 100644 index 0000000..9262ed0 --- /dev/null +++ b/UnleashedRecomp/api/SWA/Camera/CameraController.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace SWA +{ + class CCameraController : public Hedgehog::Universe::CStateMachineBase::CStateBase + { + public: + SWA_INSERT_PADDING(0x04); + be m_FieldOfView; + SWA_INSERT_PADDING(0x68); + }; + + SWA_ASSERT_OFFSETOF(CCameraController, m_FieldOfView, 0x64); + SWA_ASSERT_SIZEOF(CCameraController, 0xD0); +} diff --git a/UnleashedRecomp/api/SWA/Menu/MenuWindowBase.h b/UnleashedRecomp/api/SWA/Menu/MenuWindowBase.h new file mode 100644 index 0000000..ccab2f6 --- /dev/null +++ b/UnleashedRecomp/api/SWA/Menu/MenuWindowBase.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace SWA +{ + class CMenuWindowBase + { + public: + SWA_INSERT_PADDING(0x10); + }; +} diff --git a/UnleashedRecomp/api/SWA/System/GameMode/Title/TitleStateWorldMap.h b/UnleashedRecomp/api/SWA/System/GameMode/Title/TitleStateWorldMap.h new file mode 100644 index 0000000..4934d74 --- /dev/null +++ b/UnleashedRecomp/api/SWA/System/GameMode/Title/TitleStateWorldMap.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +namespace SWA +{ + class CTitleStateWorldMap : public CTitleStateBase + { + public: + SWA_INSERT_PADDING(0x08); + xpointer m_pWorldMapCursor; + }; +} diff --git a/UnleashedRecomp/api/SWA/System/GameMode/WorldMap/WorldMapCamera.h b/UnleashedRecomp/api/SWA/System/GameMode/WorldMap/WorldMapCamera.h new file mode 100644 index 0000000..77c1ab3 --- /dev/null +++ b/UnleashedRecomp/api/SWA/System/GameMode/WorldMap/WorldMapCamera.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace SWA +{ + class CWorldMapCamera : public CCameraController + { + public: + be m_Pitch; + be m_Yaw; + be m_Distance; + be m_RotationSpeed; + SWA_INSERT_PADDING(0x08); + bool m_CanMove; + SWA_INSERT_PADDING(0x34); + be m_TiltToEarthTransitionSpeed; + }; + + SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_Pitch, 0xD0); + SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_Yaw, 0xD4); + SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_Distance, 0xD8); + SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_RotationSpeed, 0xDC); + SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_CanMove, 0xE8); + SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_TiltToEarthTransitionSpeed, 0x120); +} diff --git a/UnleashedRecomp/api/SWA/System/GameMode/WorldMap/WorldMapCursor.h b/UnleashedRecomp/api/SWA/System/GameMode/WorldMap/WorldMapCursor.h new file mode 100644 index 0000000..03ceb73 --- /dev/null +++ b/UnleashedRecomp/api/SWA/System/GameMode/WorldMap/WorldMapCursor.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace SWA +{ + class CWorldMapCursor : public CMenuWindowBase + { + public: + SWA_INSERT_PADDING(0x24); + be m_LeftStickVertical; + be m_LeftStickHorizontal; + bool m_IsCursorMoving; + SWA_INSERT_PADDING(0x07); + be m_CursorY; + be m_CursorX; + }; + + SWA_ASSERT_OFFSETOF(CWorldMapCursor, m_LeftStickVertical, 0x34); + SWA_ASSERT_OFFSETOF(CWorldMapCursor, m_LeftStickHorizontal, 0x38); + SWA_ASSERT_OFFSETOF(CWorldMapCursor, m_IsCursorMoving, 0x3C); + SWA_ASSERT_OFFSETOF(CWorldMapCursor, m_CursorY, 0x44); + SWA_ASSERT_OFFSETOF(CWorldMapCursor, m_CursorX, 0x48); +} diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 983eb85..5e21ada 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 07ca9c4..14ac803 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 d9bf21d..922c21c 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 fdddd61..7b9c2c4 100644 --- a/UnleashedRecomp/patches/input_patches.cpp +++ b/UnleashedRecomp/patches/input_patches.cpp @@ -1,28 +1,193 @@ #include +#include +#include +#include +#include -static void SetDPadAnalogDirectionX(PPCRegister& pPadState, PPCRegister& x, bool negate) +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; + +static float g_worldMapTouchVelocityX; +static float g_worldMapTouchVelocityY; + +class SDLEventListenerForInputPatches : public SDLEventListener +{ + static inline int ms_touchpadFingerCount; + + static inline float ms_touchpadX; + static inline float ms_touchpadY; + static inline float ms_touchpadDeltaX; + static inline float ms_touchpadDeltaY; + static inline float ms_touchpadPrevX; + static inline float ms_touchpadPrevY; + +public: + static void Update(float deltaTime) + { + /* NOTE (Hyper): this code was written at 144Hz and was + discovered later to be faulty at any other frame rate, + so this is here to account for that without changing + all the constants that I had tuned. */ + constexpr auto referenceDeltaTime = 1.0f / 144.0f; + + if (g_isTouchActive) + { + auto dxNorm = ms_touchpadDeltaX / referenceDeltaTime; + auto dyNorm = ms_touchpadDeltaY / referenceDeltaTime; + auto dxSens = dxNorm * g_worldMapTouchParams.SensitivityX; + auto dySens = dyNorm * g_worldMapTouchParams.SensitivityY; + + 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; + + auto flickThreshold = g_worldMapTouchParams.FlickThreshold; + + if (fabs(dxSens) > flickThreshold || fabs(dySens) > flickThreshold) + { + g_worldMapTouchVelocityX += dxNorm * g_worldMapTouchParams.FlickAccelX * (deltaTime / referenceDeltaTime); + g_worldMapTouchVelocityY += dyNorm * g_worldMapTouchParams.FlickAccelY * (deltaTime / referenceDeltaTime); + } + + 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(g_worldMapTouchParams.Damping, deltaTime / referenceDeltaTime); + + g_worldMapTouchVelocityX *= dampingFactor; + g_worldMapTouchVelocityY *= dampingFactor; + } + } + + void OnSDLEvent(SDL_Event* event) override + { + switch (event->type) + { + case SDL_CONTROLLERTOUCHPADMOTION: + { + g_isTouchActive = true; + + if (ms_touchpadFingerCount > 1) + { + g_isTouchActive = false; + break; + } + + ms_touchpadX = event->ctouchpad.x; + ms_touchpadY = event->ctouchpad.y; + ms_touchpadDeltaX = ms_touchpadX - ms_touchpadPrevX; + ms_touchpadDeltaY = ms_touchpadY - ms_touchpadPrevY; + ms_touchpadPrevX = ms_touchpadX; + ms_touchpadPrevY = ms_touchpadY; + + break; + } + + 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; + ms_touchpadFingerCount--; + break; + } + } +} +g_sdlEventListenerForInputPatches; + +// -------------- COMMON --------------- // + +static bool IsDPadActive(SWA::SPadState* pPadState) +{ + return pPadState->IsDown(SWA::eKeyState_DpadUp) || + pPadState->IsDown(SWA::eKeyState_DpadDown) || + pPadState->IsDown(SWA::eKeyState_DpadLeft) || + pPadState->IsDown(SWA::eKeyState_DpadRight); +} + +static void SetDPadAnalogDirectionX(PPCRegister& pPadState, PPCRegister& x, bool invert, float max = 1.0f) { auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); if (pGuestPadState->IsDown(SWA::eKeyState_DpadLeft)) - x.f64 = negate ? 1.0f : -1.0f; + x.f64 = invert ? max : -max; if (pGuestPadState->IsDown(SWA::eKeyState_DpadRight)) - x.f64 = negate ? -1.0f : 1.0f; + x.f64 = invert ? -max : max; } -static void SetDPadAnalogDirectionY(PPCRegister& pPadState, PPCRegister& y, bool negate) +static void SetDPadAnalogDirectionY(PPCRegister& pPadState, PPCRegister& y, bool invert, float max = 1.0f) { auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); if (pGuestPadState->IsDown(SWA::eKeyState_DpadUp)) - y.f64 = negate ? -1.0f : 1.0f; + y.f64 = invert ? -max : max; if (pGuestPadState->IsDown(SWA::eKeyState_DpadDown)) - y.f64 = negate ? 1.0f : -1.0f; + y.f64 = invert ? max : -max; } +// -------------- PLAYER --------------- // + void PostureDPadSupportMidAsmHook(PPCRegister& pPadState, PPCRegister& x, PPCRegister& y) +{ + SetDPadAnalogDirectionX(pPadState, x, false); + SetDPadAnalogDirectionY(pPadState, y, false); +} + +void PostureDPadSupportInvertYMidAsmHook(PPCRegister& pPadState, PPCRegister& x, PPCRegister& y) { SetDPadAnalogDirectionX(pPadState, x, false); SetDPadAnalogDirectionY(pPadState, y, true); @@ -38,8 +203,146 @@ void PostureDPadSupportYMidAsmHook(PPCRegister& pPadState, PPCRegister& y) SetDPadAnalogDirectionY(pPadState, y, false); } -void PostureDPadSupportPathLocalMidAsmHook(PPCRegister& pPadState, PPCRegister& x, PPCRegister& y) +void PostureSpaceHurrierDPadSupportXMidAsmHook(PPCRegister& pPadState, PPCVRegister& vector) { - SetDPadAnalogDirectionX(pPadState, x, false); - SetDPadAnalogDirectionY(pPadState, y, false); + auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); + + if (pGuestPadState->IsDown(SWA::eKeyState_DpadLeft)) + vector.f32[3] = -1.0f; + + if (pGuestPadState->IsDown(SWA::eKeyState_DpadRight)) + vector.f32[3] = 1.0f; +} + +void PostureSpaceHurrierDPadSupportYMidAsmHook(PPCRegister& pPadState, PPCVRegister& vector) +{ + auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); + + if (pGuestPadState->IsDown(SWA::eKeyState_DpadUp)) + vector.f32[3] = 1.0f; + + if (pGuestPadState->IsDown(SWA::eKeyState_DpadDown)) + vector.f32[3] = -1.0f; +} + +// ------------- WORLD MAP ------------- // + +bool WorldMapTouchSupportMidAsmHook() +{ + SDLEventListenerForInputPatches::Update(App::s_deltaTime); + + 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) +{ + return fabs(g_worldMapTouchVelocityX) > f0.f64 || fabs(g_worldMapTouchVelocityY) > f0.f64; +} + +void TouchAndDPadSupportWorldMapXMidAsmHook(PPCRegister& pPadState, PPCRegister& x) +{ + auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); + + if (fabs(pGuestPadState->LeftStickHorizontal) > g_worldMapTouchParams.CancelDeadzone || + fabs(pGuestPadState->LeftStickVertical) > g_worldMapTouchParams.CancelDeadzone) + { + g_worldMapTouchVelocityX = 0; + } + + if (IsDPadActive(pGuestPadState)) + { + g_worldMapTouchVelocityX = 0; + + SetDPadAnalogDirectionX(pPadState, x, false); + } + else + { + if (fabs(g_worldMapTouchVelocityX) > 0) + x.f64 = -g_worldMapTouchVelocityX; + } +} + +void TouchAndDPadSupportWorldMapYMidAsmHook(PPCRegister& pPadState, PPCRegister& y) +{ + auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); + + if (fabs(pGuestPadState->LeftStickHorizontal) > g_worldMapTouchParams.CancelDeadzone || + fabs(pGuestPadState->LeftStickVertical) > g_worldMapTouchParams.CancelDeadzone) + { + g_worldMapTouchVelocityY = 0; + } + + if (IsDPadActive(pGuestPadState)) + { + g_worldMapTouchVelocityY = 0; + + SetDPadAnalogDirectionY(pPadState, y, false); + } + else + { + if (fabs(g_worldMapTouchVelocityY) > 0) + y.f64 = g_worldMapTouchVelocityY; + } +} + +// SWA::CWorldMapCamera::Update +PPC_FUNC_IMPL(__imp__sub_82486968); +PPC_FUNC(sub_82486968) +{ + auto pWorldMapCamera = (SWA::CWorldMapCamera*)g_memory.Translate(ctx.r3.u32); + + // Reset vertical velocity if maximum pitch reached. + if (fabs(pWorldMapCamera->m_Pitch) >= 80.0f) + g_worldMapTouchVelocityY = 0; + + __imp__sub_82486968(ctx, base); +} + +// World Map cursor move hook. +PPC_FUNC(sub_8256C938) +{ + auto pWorldMapCursor = (SWA::CWorldMapCursor*)g_memory.Translate(ctx.r3.u32); + + pWorldMapCursor->m_IsCursorMoving = g_isTouchActive; + + if (ctx.r4.u8) + { + pWorldMapCursor->m_LeftStickVertical = 0; + pWorldMapCursor->m_LeftStickHorizontal = 0; + } + else if (auto pInputState = SWA::CInputState::GetInstance()) + { + auto& rPadState = pInputState->GetPadState(); + + pWorldMapCursor->m_LeftStickVertical = rPadState.LeftStickVertical; + pWorldMapCursor->m_LeftStickHorizontal = rPadState.LeftStickHorizontal; + + if (rPadState.IsDown(SWA::eKeyState_DpadUp)) + pWorldMapCursor->m_LeftStickVertical = 1.0f; + + if (rPadState.IsDown(SWA::eKeyState_DpadDown)) + pWorldMapCursor->m_LeftStickVertical = -1.0f; + + if (rPadState.IsDown(SWA::eKeyState_DpadLeft)) + pWorldMapCursor->m_LeftStickHorizontal = -1.0f; + + if (rPadState.IsDown(SWA::eKeyState_DpadRight)) + pWorldMapCursor->m_LeftStickHorizontal = 1.0f; + + if (sqrtf((pWorldMapCursor->m_LeftStickHorizontal * pWorldMapCursor->m_LeftStickHorizontal) + + (pWorldMapCursor->m_LeftStickVertical * pWorldMapCursor->m_LeftStickVertical)) > 0.7f) + { + pWorldMapCursor->m_IsCursorMoving = true; + } + } } diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index 70a9b67..e030ef1 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -548,41 +548,153 @@ jump_address = 0x82585480 name = "LoadingScreenControllerMidAsmHook" address = 0x824DC9D4 -# CPlayerSpeedPostureInputOnPath +# SWA::Player::CPlayerSpeedPostureInputOnPath [[midasm_hook]] -name = "PostureDPadSupportMidAsmHook" +name = "PostureDPadSupportInvertYMidAsmHook" address = 0x8234F194 registers = ["r31", "f13", "f0"] -# CPlayerSpeedPostureInputOnPathLocal +# SWA::Player::CPlayerSpeedPostureInputOnPathLocal [[midasm_hook]] -name = "PostureDPadSupportPathLocalMidAsmHook" +name = "PostureDPadSupportMidAsmHook" address = 0x8234F610 registers = ["r30", "f0", "f13"] -# CPlayerSpeedPostureInput3DStandard +# SWA::Player::CPlayerSpeedPostureInput3DStandard [[midasm_hook]] -name = "PostureDPadSupportMidAsmHook" +name = "PostureDPadSupportInvertYMidAsmHook" address = 0x8234EEE8 registers = ["r31", "f12", "f13"] -# CEvilPostureInputStandard +# SWA::Player::CEvilPostureInputStandard [[midasm_hook]] -name = "PostureDPadSupportMidAsmHook" +name = "PostureDPadSupportInvertYMidAsmHook" address = 0x823CDA60 registers = ["r3", "f11", "f12"] -# CEvilPostureInputStandard +# SWA::Player::CEvilPostureInputStandard [[midasm_hook]] name = "PostureDPadSupportXMidAsmHook" address = 0x823CDA74 registers = ["r3", "f0"] -# CEvilPostureInputStandard +# SWA::Player::CEvilPostureInputStandard [[midasm_hook]] -name = "PostureDPadSupportYMidAsmHook" -address = 0x823CDA88 -registers = ["r3", "f12"] +name = "PostureDPadSupportXMidAsmHook" +address = 0x823CDA74 +registers = ["r3", "f0"] + +# SWA::CObjBobsleigh::CStateMode3D +[[midasm_hook]] +name = "PostureDPadSupportXMidAsmHook" +address = 0x8266B5F0 +registers = ["r29", "f13"] + +# SWA::CObjBobsleigh::CStateMode3D +[[midasm_hook]] +name = "PostureDPadSupportXMidAsmHook" +address = 0x8266B8B4 +registers = ["r29", "f0"] + +# SWA::CObjBobsleigh::CStateMode3D +[[midasm_hook]] +name = "PostureDPadSupportXMidAsmHook" +address = 0x8266B618 +registers = ["r29", "f0"] + +# SWA::CObjBobsleigh::CStateMode3D +[[midasm_hook]] +name = "PostureDPadSupportXMidAsmHook" +address = 0x8266B6AC +registers = ["r29", "f0"] + +# SWA::Boss::Temple::CTemple (shared) +[[midasm_hook]] +name = "PostureDPadSupportMidAsmHook" +address = 0x82A77E68 +registers = ["r31", "f31", "f30"] + +# SWA::Boss::Temple::CTempleStateMove +[[midasm_hook]] +name = "PostureDPadSupportMidAsmHook" +address = 0x82A7B3CC +registers = ["r30", "f29", "f28"] + +# SWA::Boss::Temple::CTempleStateMove +[[midasm_hook]] +name = "PostureDPadSupportMidAsmHook" +address = 0x82A7B288 +registers = ["r30", "f13", "f10"] + +# SWA::Player::CSuperSonicPostureInputSpaceHurrier +[[midasm_hook]] +name = "PostureSpaceHurrierDPadSupportXMidAsmHook" +address = 0x82455DD8 +registers = ["r30", "v61"] + +# SWA::Player::CSuperSonicPostureInputSpaceHurrier +[[midasm_hook]] +name = "PostureSpaceHurrierDPadSupportYMidAsmHook" +address = 0x82455DC8 +registers = ["r30", "v63"] + +# SWA::Player::CSuperSonicPostureNights +[[midasm_hook]] +name = "PostureDPadSupportMidAsmHook" +address = 0x82454104 +registers = ["r29", "f28", "f27"] +after_instruction = true + +# SWA::CWorldMapCamera - disable rotation deadzone for touch +[[midasm_hook]] +name = "WorldMapTouchSupportMidAsmHook" +address = 0x824862EC +jump_address_on_true = 0x824862F0 + +# SWA::CWorldMapCamera - disable flag magnetism for touch +[[midasm_hook]] +name = "WorldMapTouchMagnetismSupportMidAsmHook" +address = 0x824866D4 +registers = ["f0"] +jump_address_on_true = 0x82486838 + +# SWA::CWorldMapCamera - touch and D-Pad support for camera adjustment threshold on the X axis +[[midasm_hook]] +name = "TouchAndDPadSupportWorldMapXMidAsmHook" +address = 0x824862D8 +registers = ["r30", "f12"] + +# SWA::CWorldMapCamera - touch and D-Pad support for adjusing camera yaw +[[midasm_hook]] +name = "TouchAndDPadSupportWorldMapXMidAsmHook" +address = 0x82486318 +registers = ["r30", "f12"] + +# SWA::CWorldMapCamera - touch and D-Pad support for camera adjustment threshold on the Y axis +[[midasm_hook]] +name = "TouchAndDPadSupportWorldMapYMidAsmHook" +address = 0x824862CC +registers = ["r30", "f0"] + +# SWA::CWorldMapCamera - touch and D-Pad support for adjusing camera pitch +[[midasm_hook]] +name = "TouchAndDPadSupportWorldMapYMidAsmHook" +address = 0x824862F4 +registers = ["r30", "f0"] + +# SWA::CWorldMapCamera - touch and D-Pad support for flag magnetism on the X axis +[[midasm_hook]] +name = "TouchAndDPadSupportWorldMapXMidAsmHook" +address = 0x8248665C +registers = ["r27", "f29"] +after_instruction = true + +# SWA::CWorldMapCamera - touch and D-Pad support for flag magnetism on the Y axis +[[midasm_hook]] +name = "TouchAndDPadSupportWorldMapYMidAsmHook" +address = 0x82486658 +registers = ["r27", "f28"] +after_instruction = true [[midasm_hook]] name = "LoadingUpdateMidAsmHook"