From 5f32e2495fb80fe33cde8dec3b617080575f0700 Mon Sep 17 00:00:00 2001 From: Hyper <34012267+hyperbx@users.noreply.github.com> Date: Tue, 18 Feb 2025 01:59:26 +0000 Subject: [PATCH] Switched to CFreeCamera instead of CReplayFreeCamera --- UnleashedRecomp/api/Hedgehog/Base/hhObject.h | 2 + .../api/Hedgehog/Base/hhObject.inl | 39 +++ UnleashedRecomp/api/Hedgehog/Math/Vector.h | 10 + .../api/Hedgehog/Universe/Engine/hhMessage.h | 19 ++ UnleashedRecomp/api/SWA.h | 11 +- .../api/SWA/Camera/CameraController.h | 17 - .../SWA/Camera/Controller/CameraController.h | 24 ++ .../api/SWA/Camera/Controller/FreeCamera.h | 16 + UnleashedRecomp/api/SWA/Globals.h | 4 + .../api/SWA/Message/MsgCameraPauseMove.h | 17 + .../api/SWA/Message/MsgPopCameraController.h | 32 ++ .../api/SWA/Message/MsgSetPosition.h | 18 ++ .../api/SWA/Message/MsgSetVelocity.h | 18 ++ .../SWA/Player/Character/Base/PlayerContext.h | 29 ++ .../Character/EvilSonic/EvilSonicContext.h | 15 +- .../Character/Speed/PlayerSpeedContext.h | 15 + .../Character/Speed/PlayerSpeedContext.inl | 7 + .../api/SWA/Replay/Camera/ReplayFreeCamera.h | 2 +- UnleashedRecomp/api/SWA/System/GameDocument.h | 5 +- .../SWA/Tool/FreeCameraTool/FreeCameraTool.h | 15 + UnleashedRecomp/app.cpp | 10 + UnleashedRecomp/app.h | 5 +- UnleashedRecomp/hid/driver/sdl_hid.cpp | 2 +- .../patches/free_camera_patches.cpp | 290 ++++++++++-------- UnleashedRecomp/patches/free_camera_patches.h | 2 + UnleashedRecomp/patches/inspire_patches.cpp | 2 +- UnleashedRecomp/patches/player_patches.cpp | 8 +- UnleashedRecomp/patches/resident_patches.cpp | 2 +- UnleashedRecompLib/config/SWA.toml | 43 +-- 29 files changed, 484 insertions(+), 195 deletions(-) create mode 100644 UnleashedRecomp/api/Hedgehog/Base/hhObject.inl create mode 100644 UnleashedRecomp/api/Hedgehog/Universe/Engine/hhMessage.h delete mode 100644 UnleashedRecomp/api/SWA/Camera/CameraController.h create mode 100644 UnleashedRecomp/api/SWA/Camera/Controller/CameraController.h create mode 100644 UnleashedRecomp/api/SWA/Camera/Controller/FreeCamera.h create mode 100644 UnleashedRecomp/api/SWA/Message/MsgCameraPauseMove.h create mode 100644 UnleashedRecomp/api/SWA/Message/MsgPopCameraController.h create mode 100644 UnleashedRecomp/api/SWA/Message/MsgSetPosition.h create mode 100644 UnleashedRecomp/api/SWA/Message/MsgSetVelocity.h create mode 100644 UnleashedRecomp/api/SWA/Player/Character/Base/PlayerContext.h create mode 100644 UnleashedRecomp/api/SWA/Player/Character/Speed/PlayerSpeedContext.h create mode 100644 UnleashedRecomp/api/SWA/Player/Character/Speed/PlayerSpeedContext.inl create mode 100644 UnleashedRecomp/api/SWA/Tool/FreeCameraTool/FreeCameraTool.h diff --git a/UnleashedRecomp/api/Hedgehog/Base/hhObject.h b/UnleashedRecomp/api/Hedgehog/Base/hhObject.h index 80723ee2..590aacb9 100644 --- a/UnleashedRecomp/api/Hedgehog/Base/hhObject.h +++ b/UnleashedRecomp/api/Hedgehog/Base/hhObject.h @@ -21,3 +21,5 @@ namespace Hedgehog::Base void operator delete(void* in_pMem, void* in_pObj); }; } + +#include "hhObject.inl" diff --git a/UnleashedRecomp/api/Hedgehog/Base/hhObject.inl b/UnleashedRecomp/api/Hedgehog/Base/hhObject.inl new file mode 100644 index 00000000..87f1b081 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Base/hhObject.inl @@ -0,0 +1,39 @@ +namespace Hedgehog::Base +{ + inline CObject::CObject() + { + } + + inline CObject::CObject(const swa_null_ctor&) + { + } + + inline void* CObject::operator new(const size_t in_Size) + { + return __HH_ALLOC(in_Size); + } + + // inline void* CObject::operator new(const size_t in_Size, const size_t in_Align) + // { + // return __HH_ALLOCALIGN(in_Size, in_Align); + // } + + inline void CObject::operator delete(void* in_pMem) + { + return __HH_FREE(in_pMem); + } + + inline void* CObject::operator new(const size_t in_Size, void* in_pObj) + { + return in_pObj; + } + + inline void* CObject::operator new(const size_t in_Size, const size_t in_Align, void* in_pObj) + { + return in_pObj; + } + + inline void CObject::operator delete(void* in_pMem, void* in_pObj) + { + } +} diff --git a/UnleashedRecomp/api/Hedgehog/Math/Vector.h b/UnleashedRecomp/api/Hedgehog/Math/Vector.h index 7ea0e382..fb81a1cb 100644 --- a/UnleashedRecomp/api/Hedgehog/Math/Vector.h +++ b/UnleashedRecomp/api/Hedgehog/Math/Vector.h @@ -18,6 +18,16 @@ namespace Hedgehog::Math be Y; be Z; be W; + + CVector operator*(const float& scalar) const + { + return { X * scalar, Y * scalar, Z * scalar }; + } + + CVector operator+(const CVector& v) const + { + return { X + v.X, Y + v.Y, Z + v.Z }; + } }; class CVector4 diff --git a/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhMessage.h b/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhMessage.h new file mode 100644 index 00000000..e08e7a82 --- /dev/null +++ b/UnleashedRecomp/api/Hedgehog/Universe/Engine/hhMessage.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include + +namespace Hedgehog::Universe +{ + class Message : public Base::CObject + { + public: + be m_pVftable; + be m_SenderActorID; + boost::shared_ptr m_spSelf; + }; + + class MessageTypeGet : public Message {}; + class MessageTypeSet : public Message {}; +} diff --git a/UnleashedRecomp/api/SWA.h b/UnleashedRecomp/api/SWA.h index 1779a7d7..ae1d1950 100644 --- a/UnleashedRecomp/api/SWA.h +++ b/UnleashedRecomp/api/SWA.h @@ -49,6 +49,7 @@ #include "Hedgehog/MirageCore/RenderData/hhVertexShaderData.h" #include "Hedgehog/MirageCore/Renderable/hhRenderable.h" #include "Hedgehog/Sparkle/hhParticleMaterial.h" +#include "Hedgehog/Universe/Engine/hhMessage.h" #include "Hedgehog/Universe/Engine/hhMessageActor.h" #include "Hedgehog/Universe/Engine/hhMessageProcess.h" #include "Hedgehog/Universe/Engine/hhStateMachineBase.h" @@ -65,7 +66,8 @@ #include "SWA/CSD/CsdTexListMirage.h" #include "SWA/CSD/GameObjectCSD.h" #include "SWA/Camera/Camera.h" -#include "SWA/Camera/CameraController.h" +#include "SWA/Camera/Controller/CameraController.h" +#include "SWA/Camera/Controller/FreeCamera.h" #include "SWA/CharacterUtility/CharacterProxy.h" #include "SWA/ExtraStage/Tails/Enemy/Boss/ExStageBoss.h" #include "SWA/ExtraStage/Tails/Enemy/Boss/State/StateBase.h" @@ -87,13 +89,19 @@ #include "SWA/Inspire/InspireTextureOverlay.h" #include "SWA/Inspire/InspireTextureOverlayInfo.h" #include "SWA/Menu/MenuWindowBase.h" +#include "SWA/Message/MsgCameraPauseMove.h" +#include "SWA/Message/MsgPopCameraController.h" +#include "SWA/Message/MsgSetPosition.h" +#include "SWA/Message/MsgSetVelocity.h" #include "SWA/Movie/MovieDisplayer.h" #include "SWA/Movie/MovieManager.h" #include "SWA/Object/Common/DashPanel/ObjDashPanel.h" #include "SWA/Object/SonicStage/EU/RollingBarrel/ObjRollingBarrel.h" +#include "SWA/Player/Character/Base/PlayerContext.h" #include "SWA/Player/Character/EvilSonic/EvilSonic.h" #include "SWA/Player/Character/EvilSonic/EvilSonicContext.h" #include "SWA/Player/Character/EvilSonic/Hud/EvilHudGuide.h" +#include "SWA/Player/Character/Speed/PlayerSpeedContext.h" #include "SWA/Replay/Camera/ReplayFreeCamera.h" #include "SWA/Sequence/Unit/SequenceUnitBase.h" #include "SWA/Sequence/Unit/SequenceUnitPlayMovie.h" @@ -125,5 +133,6 @@ #include "SWA/System/MatrixNodeTransform.h" #include "SWA/System/PadState.h" #include "SWA/System/World.h" +#include "SWA/Tool/FreeCameraTool/FreeCameraTool.h" #include "boost/smart_ptr/make_shared_object.h" #include "boost/smart_ptr/shared_ptr.h" diff --git a/UnleashedRecomp/api/SWA/Camera/CameraController.h b/UnleashedRecomp/api/SWA/Camera/CameraController.h deleted file mode 100644 index f7e7bb35..00000000 --- a/UnleashedRecomp/api/SWA/Camera/CameraController.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -namespace SWA -{ - class CCameraController - { - public: - SWA_INSERT_PADDING(0x64); - 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/Camera/Controller/CameraController.h b/UnleashedRecomp/api/SWA/Camera/Controller/CameraController.h new file mode 100644 index 00000000..1d71151a --- /dev/null +++ b/UnleashedRecomp/api/SWA/Camera/Controller/CameraController.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace SWA +{ + class CCameraController + { + public: + SWA_INSERT_PADDING(0x08); + xpointer m_pCamera; + SWA_INSERT_PADDING(0x58); + be m_FieldOfView; + SWA_INSERT_PADDING(0x08); + Hedgehog::Math::CVector m_Position; + Hedgehog::Math::CVector m_UpVector; + Hedgehog::Math::CQuaternion m_Rotation; + SWA_INSERT_PADDING(0x30); + }; + + SWA_ASSERT_OFFSETOF(CCameraController, m_pCamera, 0x08); + SWA_ASSERT_OFFSETOF(CCameraController, m_FieldOfView, 0x64); + SWA_ASSERT_SIZEOF(CCameraController, 0xD0); +} diff --git a/UnleashedRecomp/api/SWA/Camera/Controller/FreeCamera.h b/UnleashedRecomp/api/SWA/Camera/Controller/FreeCamera.h new file mode 100644 index 00000000..34fb774c --- /dev/null +++ b/UnleashedRecomp/api/SWA/Camera/Controller/FreeCamera.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include "SWA/Camera/Controller/CameraController.h" + +namespace SWA +{ + class CFreeCamera : public CCameraController + { + public: + SWA_INSERT_PADDING(0x10); + be m_Speed; + }; + + SWA_ASSERT_OFFSETOF(CFreeCamera, m_Speed, 0xE0); +} diff --git a/UnleashedRecomp/api/SWA/Globals.h b/UnleashedRecomp/api/SWA/Globals.h index c8a9ee3b..9652f04e 100644 --- a/UnleashedRecomp/api/SWA/Globals.h +++ b/UnleashedRecomp/api/SWA/Globals.h @@ -9,6 +9,9 @@ namespace SWA // ms_DrawLightFieldSamplingPoint: サンプリング点をデバッグ表示 static inline bool* ms_DrawLightFieldSamplingPoint; + // N/A + static inline be* ms_FreeCameraSpeed; + // N/A static inline bool* ms_IsAutoSaveWarningShown; @@ -60,6 +63,7 @@ namespace SWA static void Init() { ms_DrawLightFieldSamplingPoint = (bool*)MmGetHostAddress(0x83367BCE); + ms_FreeCameraSpeed = (be*)MmGetHostAddress(0x83366DF8); ms_IgnoreLightFieldData = (bool*)MmGetHostAddress(0x83367BCF); ms_IsAutoSaveWarningShown = (bool*)MmGetHostAddress(0x83367BC1); ms_IsCollisionRender = (bool*)MmGetHostAddress(0x833678A6); diff --git a/UnleashedRecomp/api/SWA/Message/MsgCameraPauseMove.h b/UnleashedRecomp/api/SWA/Message/MsgCameraPauseMove.h new file mode 100644 index 00000000..f128f3ea --- /dev/null +++ b/UnleashedRecomp/api/SWA/Message/MsgCameraPauseMove.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace SWA::Message +{ + class MsgCameraPauseMove : public Hedgehog::Universe::MessageTypeSet + { + public: + SWA_INSERT_PADDING(0x08); + bool m_isPaused; + + MsgCameraPauseMove(bool in_isPaused) : m_isPaused(in_isPaused) {} + }; + + SWA_ASSERT_OFFSETOF(MsgCameraPauseMove, m_isPaused, 0x18); +} diff --git a/UnleashedRecomp/api/SWA/Message/MsgPopCameraController.h b/UnleashedRecomp/api/SWA/Message/MsgPopCameraController.h new file mode 100644 index 00000000..0bfa428b --- /dev/null +++ b/UnleashedRecomp/api/SWA/Message/MsgPopCameraController.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +namespace SWA::Message +{ + class MsgPopCameraController : public Hedgehog::Universe::MessageTypeSet + { + public: + SWA_INSERT_PADDING(0x08); + xpointer m_pCameraController; + SWA_INSERT_PADDING(0x08); + xpointer m_pCameraName; + be m_InterpolateTime; + bool m_Field2C; + bool m_Field2D; + bool m_Field2E; + + MsgPopCameraController(CCameraController* in_pCameraController, float in_interpolateTime) + : m_pCameraController(in_pCameraController), m_InterpolateTime(in_interpolateTime) {} + + MsgPopCameraController(Hedgehog::Base::CSharedString* in_pCameraName, float in_interpolateTime) + : m_pCameraName(in_pCameraName), m_InterpolateTime(in_interpolateTime) {} + }; + + SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_pCameraController, 0x18); + SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_pCameraName, 0x24); + SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_InterpolateTime, 0x28); + SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_Field2C, 0x2C); + SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_Field2D, 0x2D); + SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_Field2E, 0x2E); +} diff --git a/UnleashedRecomp/api/SWA/Message/MsgSetPosition.h b/UnleashedRecomp/api/SWA/Message/MsgSetPosition.h new file mode 100644 index 00000000..c9316462 --- /dev/null +++ b/UnleashedRecomp/api/SWA/Message/MsgSetPosition.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace SWA::Message +{ + class MsgSetPosition : public Hedgehog::Universe::MessageTypeSet + { + public: + SWA_INSERT_PADDING(0x10); + Hedgehog::Math::CVector m_Position; + + MsgSetPosition(const Hedgehog::Math::CVector& in_rPosition) : m_Position(in_rPosition) {} + }; + + SWA_ASSERT_OFFSETOF(MsgSetPosition, m_Position, 0x20); + SWA_ASSERT_SIZEOF(MsgSetPosition, 0x30); +} diff --git a/UnleashedRecomp/api/SWA/Message/MsgSetVelocity.h b/UnleashedRecomp/api/SWA/Message/MsgSetVelocity.h new file mode 100644 index 00000000..c3e31cca --- /dev/null +++ b/UnleashedRecomp/api/SWA/Message/MsgSetVelocity.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace SWA::Message +{ + class MsgSetVelocity : public Hedgehog::Universe::MessageTypeSet + { + public: + SWA_INSERT_PADDING(0x10); + Hedgehog::Math::CVector m_Velocity; + + MsgSetVelocity(const Hedgehog::Math::CVector& in_rVelocity) : m_Velocity(in_rVelocity) {} + }; + + SWA_ASSERT_OFFSETOF(MsgSetVelocity, m_Velocity, 0x20); + SWA_ASSERT_SIZEOF(MsgSetVelocity, 0x30); +} diff --git a/UnleashedRecomp/api/SWA/Player/Character/Base/PlayerContext.h b/UnleashedRecomp/api/SWA/Player/Character/Base/PlayerContext.h new file mode 100644 index 00000000..e26b4950 --- /dev/null +++ b/UnleashedRecomp/api/SWA/Player/Character/Base/PlayerContext.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include "boost/smart_ptr/shared_ptr.h" + +namespace SWA::Player +{ + class CPlayer; + + class CPlayerContext + { + public: + SWA_INSERT_PADDING(0x10); + boost::shared_ptr m_spMatrixNode; + SWA_INSERT_PADDING(0x18); + boost::anonymous_shared_ptr m_spRayCastCollision; + SWA_INSERT_PADDING(0xC8); + xpointer m_pPlayer; + SWA_INSERT_PADDING(0xF8); + boost::shared_ptr m_spParameter; + SWA_INSERT_PADDING(0x0C); + }; + + SWA_ASSERT_OFFSETOF(CPlayerContext, m_spMatrixNode, 0x10); + SWA_ASSERT_OFFSETOF(CPlayerContext, m_spRayCastCollision, 0x30); + SWA_ASSERT_OFFSETOF(CPlayerContext, m_pPlayer, 0x100); + SWA_ASSERT_OFFSETOF(CPlayerContext, m_spParameter, 0x1FC); + SWA_ASSERT_SIZEOF(CPlayerContext, 0x210); +} diff --git a/UnleashedRecomp/api/SWA/Player/Character/EvilSonic/EvilSonicContext.h b/UnleashedRecomp/api/SWA/Player/Character/EvilSonic/EvilSonicContext.h index d8f38ae3..c410e3e8 100644 --- a/UnleashedRecomp/api/SWA/Player/Character/EvilSonic/EvilSonicContext.h +++ b/UnleashedRecomp/api/SWA/Player/Character/EvilSonic/EvilSonicContext.h @@ -5,19 +5,26 @@ namespace SWA::Player { - class CEvilSonicContext // : public CPlayerContext + class CEvilSonicContext : public CPlayerContext { public: - SWA_INSERT_PADDING(0x688); + SWA_INSERT_PADDING(0x478); be m_DarkGaiaEnergy; SWA_INSERT_PADDING(0x138); be m_AnimationID; SWA_INSERT_PADDING(0x38); - be m_UnkHudGuideF32; - be m_UnkHudGuideU32; + be m_Field800; // Related to EvilHudGuide + be m_Field804; // Related to EvilHudGuide SWA_INSERT_PADDING(0x18); be m_GuideType; SWA_INSERT_PADDING(0xA8); be m_OutOfControlCount; }; + + SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_DarkGaiaEnergy, 0x688); + SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_AnimationID, 0x7C4); + SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_Field800, 0x800); + SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_Field804, 0x804); + SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_GuideType, 0x820); + SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_OutOfControlCount, 0x8CC); } diff --git a/UnleashedRecomp/api/SWA/Player/Character/Speed/PlayerSpeedContext.h b/UnleashedRecomp/api/SWA/Player/Character/Speed/PlayerSpeedContext.h new file mode 100644 index 00000000..396743bb --- /dev/null +++ b/UnleashedRecomp/api/SWA/Player/Character/Speed/PlayerSpeedContext.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace SWA::Player +{ + class CPlayerSpeedContext : public CPlayerContext + { + public: + // TODO: Hedgehog::Base::TSynchronizedPtr + static CPlayerSpeedContext* GetInstance(); + }; +} + +#include "PlayerSpeedContext.inl" diff --git a/UnleashedRecomp/api/SWA/Player/Character/Speed/PlayerSpeedContext.inl b/UnleashedRecomp/api/SWA/Player/Character/Speed/PlayerSpeedContext.inl new file mode 100644 index 00000000..dd452f8d --- /dev/null +++ b/UnleashedRecomp/api/SWA/Player/Character/Speed/PlayerSpeedContext.inl @@ -0,0 +1,7 @@ +namespace SWA::Player +{ + inline CPlayerSpeedContext* CPlayerSpeedContext::GetInstance() + { + return *(xpointer*)MmGetHostAddress(0x83362F98); + } +} diff --git a/UnleashedRecomp/api/SWA/Replay/Camera/ReplayFreeCamera.h b/UnleashedRecomp/api/SWA/Replay/Camera/ReplayFreeCamera.h index a9ffd7ad..94f820a0 100644 --- a/UnleashedRecomp/api/SWA/Replay/Camera/ReplayFreeCamera.h +++ b/UnleashedRecomp/api/SWA/Replay/Camera/ReplayFreeCamera.h @@ -1,7 +1,7 @@ #pragma once #include -#include "SWA/Camera/CameraController.h" +#include "SWA/Camera/Controller/CameraController.h" namespace SWA { diff --git a/UnleashedRecomp/api/SWA/System/GameDocument.h b/UnleashedRecomp/api/SWA/System/GameDocument.h index d7013011..85854325 100644 --- a/UnleashedRecomp/api/SWA/System/GameDocument.h +++ b/UnleashedRecomp/api/SWA/System/GameDocument.h @@ -36,7 +36,9 @@ namespace SWA xpointer m_pSoundAdministrator; SWA_INSERT_PADDING(0x48); xpointer m_pGeneralWindow; - SWA_INSERT_PADDING(0xD8); + SWA_INSERT_PADDING(0xC0); + boost::anonymous_shared_ptr m_spPlayerSwitchManager; + SWA_INSERT_PADDING(0x10); SScoreInfo m_ScoreInfo; SWA_INSERT_PADDING(0x0C); }; @@ -63,6 +65,7 @@ namespace SWA SWA_ASSERT_OFFSETOF(CGameDocument::CMember, m_StageName, 0xAC); SWA_ASSERT_OFFSETOF(CGameDocument::CMember, m_pSoundAdministrator, 0xB0); SWA_ASSERT_OFFSETOF(CGameDocument::CMember, m_pGeneralWindow, 0xFC); + SWA_ASSERT_OFFSETOF(CGameDocument::CMember, m_spPlayerSwitchManager, 0x1C0); SWA_ASSERT_OFFSETOF(CGameDocument::CMember, m_ScoreInfo, 0x1D8); SWA_ASSERT_SIZEOF(CGameDocument::CMember, 0x230); diff --git a/UnleashedRecomp/api/SWA/Tool/FreeCameraTool/FreeCameraTool.h b/UnleashedRecomp/api/SWA/Tool/FreeCameraTool/FreeCameraTool.h new file mode 100644 index 00000000..f75886e7 --- /dev/null +++ b/UnleashedRecomp/api/SWA/Tool/FreeCameraTool/FreeCameraTool.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace SWA +{ + class CFreeCameraTool : public CGameObject + { + public: + SWA_INSERT_PADDING(0x04); + xpointer m_pFreeCamera; + }; + + SWA_ASSERT_OFFSETOF(CFreeCameraTool, m_pFreeCamera, 0xC0); +} diff --git a/UnleashedRecomp/app.cpp b/UnleashedRecomp/app.cpp index be696deb..16034196 100644 --- a/UnleashedRecomp/app.cpp +++ b/UnleashedRecomp/app.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,7 @@ PPC_FUNC(sub_822C1130) } AudioPatches::Update(App::s_deltaTime); + FreeCameraPatches::Update(); InspirePatches::Update(); // Apply subtitles option. @@ -94,3 +96,11 @@ PPC_FUNC(sub_822C1130) __imp__sub_822C1130(ctx, base); } +// SWA::CGameModeStage::CGameModeStage +PPC_FUNC_IMPL(__imp__sub_82541138); +PPC_FUNC(sub_82541138) +{ + App::s_pGameModeStage = (SWA::CGameModeStage*)g_memory.Translate(ctx.r3.u32); + + __imp__sub_82541138(ctx, base); +} diff --git a/UnleashedRecomp/app.h b/UnleashedRecomp/app.h index cc61bd0d..d12dbb74 100644 --- a/UnleashedRecomp/app.h +++ b/UnleashedRecomp/app.h @@ -1,5 +1,6 @@ #pragma once +#include #include class App @@ -8,9 +9,11 @@ public: static inline bool s_isInit; static inline bool s_isMissingDLC; static inline bool s_isLoading; - static inline bool s_isWerehog; static inline bool s_isSaveDataCorrupt; + static inline SWA::CGameModeStage* s_pGameModeStage; + static inline SWA::Player::CEvilSonicContext* s_pEvilSonicContext; + static inline ELanguage s_language; static inline double s_deltaTime; diff --git a/UnleashedRecomp/hid/driver/sdl_hid.cpp b/UnleashedRecomp/hid/driver/sdl_hid.cpp index 85e6793a..6aea5155 100644 --- a/UnleashedRecomp/hid/driver/sdl_hid.cpp +++ b/UnleashedRecomp/hid/driver/sdl_hid.cpp @@ -210,7 +210,7 @@ int HID_OnSDLEvent(void*, SDL_Event* event) g_controllers[freeIndex] = controller; - SetControllerTimeOfDayLED(controller, App::s_isWerehog); + SetControllerTimeOfDayLED(controller, App::s_pEvilSonicContext); } break; diff --git a/UnleashedRecomp/patches/free_camera_patches.cpp b/UnleashedRecomp/patches/free_camera_patches.cpp index 0cdb61cc..ef24c60e 100644 --- a/UnleashedRecomp/patches/free_camera_patches.cpp +++ b/UnleashedRecomp/patches/free_camera_patches.cpp @@ -8,19 +8,20 @@ #define DEGREES_TO_RADIANS(x) (float)(x / 180.0f * M_PI) #define RADIANS_TO_DEGREES(x) (float)(x / M_PI * 180.0f) -constexpr float DEFAULT_SPEED = 0.5f; -constexpr float DEFAULT_FOV = 45.0f; +constexpr float DEFAULT_SPEED = 1.0f; +constexpr float DEFAULT_FIELD_OF_VIEW = 45.0f; constexpr float MOVE_SPEED_SLOW = 0.075f; constexpr float MOVE_SPEED_FAST = 8.0f; constexpr float MOVE_SPEED_MODIFIER_RATIO = 0.02f; constexpr float FOV_MODIFIER_RATIO = 1.0f; static float g_baseSpeed = DEFAULT_SPEED; -static float g_baseFOV = DEFAULT_FOV; +static float g_baseFieldOfView = DEFAULT_FIELD_OF_VIEW; +static bool g_isDisablingFreeCamera; static bool g_isCameraLocked; static float g_speed; -static float g_fov; +static float g_fieldOfView; static void ResetParameters() { @@ -28,90 +29,22 @@ static void ResetParameters() g_speed = g_baseSpeed = DEFAULT_SPEED; *SWA::SGlobals::ms_IsRenderDepthOfField = true; - FreeCameraPatches::s_fieldOfView = g_fov = g_baseFOV = DEFAULT_FOV; + FreeCameraPatches::s_fieldOfView = g_fieldOfView = g_baseFieldOfView = DEFAULT_FIELD_OF_VIEW; } -bool EnableFreeCameraMidAsmHook() +bool FreeCameraActiveMidAsmHook() { - return Config::EnableFreeCamera; + return Config::EnableFreeCamera && FreeCameraPatches::s_isActive; } -bool FreeCameraNullInputMidAsmHook() -{ - return Config::EnableFreeCamera; -} - -// Original input: D-Pad Up -bool FreeCameraActivationInputMidAsmHook(PPCRegister& r11, PPCRegister& r27, PPCRegister& r28) +bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31, PPCRegister& r29, PPCRegister& f0) { if (!Config::EnableFreeCamera) return false; - static auto isChangedCameraMode = false; - - if ((r11.u32 & SWA::eKeyState_Select) != 0) - { - if (++r28.u32 >= 2) - r28.u32 = 0; - - isChangedCameraMode = true; - } - - FreeCameraPatches::s_isActive = r28.u32 > 0; - - if (isChangedCameraMode) - { - ResetParameters(); - - switch (r28.u32) - { - case 0: - LOGN("[Free Camera] Disabled"); - break; - - case 1: - LOGN("[Free Camera] Enabled"); - break; - } - - isChangedCameraMode = false; - - if (FreeCameraPatches::s_isActive && *SWA::SGlobals::ms_IsRenderHud) - { - *SWA::SGlobals::ms_IsRenderHud = false; - } - else - { - *SWA::SGlobals::ms_IsRenderHud = true; - } - } - - return true; -} - -// Original input: D-Pad Left -void FreeCameraTeleportToPlayerInputMidAsmHook(PPCRegister& r4) -{ - if (Config::EnableFreeCamera) - r4.u32 = SWA::eKeyState_RightStick; -} - -// Original inputs: X (Square) / Y (Triangle) -bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31) -{ - if (!Config::EnableFreeCamera) - return false; - - auto pCamera = (SWA::CReplayFreeCamera*)g_memory.Translate(r31.u32); - auto pInputState = SWA::CInputState::GetInstance(); - - if (!pInputState) - return false; - - auto& rPadState = pInputState->GetPadState(); - + auto pCamera = (SWA::CFreeCamera*)g_memory.Translate(r31.u32); + auto pPadState = (SWA::SPadState*)g_memory.Translate(r29.u32); auto factor = App::s_deltaTime / (1.0f / 60.0f); - auto aspectRatio = (float)GameWindow::s_width / (float)GameWindow::s_height; if (g_isCameraLocked) { @@ -122,7 +55,7 @@ bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31) static auto isLeftTriggerSpeedModifier = false; static auto isRightTriggerSpeedModifier = false; - if (rPadState.IsDown(SWA::eKeyState_LeftTrigger)) + if (pPadState->IsDown(SWA::eKeyState_LeftTrigger)) { g_speed = MOVE_SPEED_SLOW; isLeftTriggerSpeedModifier = true; @@ -133,7 +66,7 @@ bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31) isLeftTriggerSpeedModifier = false; } - if (rPadState.IsDown(SWA::eKeyState_RightTrigger)) + if (pPadState->IsDown(SWA::eKeyState_RightTrigger)) { g_speed = MOVE_SPEED_FAST; isRightTriggerSpeedModifier = true; @@ -147,10 +80,10 @@ bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31) if (isLeftTriggerSpeedModifier && isRightTriggerSpeedModifier) g_speed = MOVE_SPEED_FAST / 3; - if (rPadState.IsDown(SWA::eKeyState_A)) + if (pPadState->IsDown(SWA::eKeyState_A)) g_speed = g_baseSpeed = DEFAULT_SPEED; - if (rPadState.IsDown(SWA::eKeyState_B)) + if (pPadState->IsDown(SWA::eKeyState_B)) { g_baseSpeed -= MOVE_SPEED_MODIFIER_RATIO * factor; g_speed = g_baseSpeed; @@ -158,7 +91,7 @@ bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31) LOGFN("[Free Camera] Speed: {}", g_speed); } - if (rPadState.IsDown(SWA::eKeyState_X)) + if (pPadState->IsDown(SWA::eKeyState_X)) { g_baseSpeed += MOVE_SPEED_MODIFIER_RATIO * factor; g_speed = g_baseSpeed; @@ -166,57 +99,152 @@ bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31) LOGFN("[Free Camera] Speed: {}", g_speed); } - auto isResetFOV = rPadState.IsDown(SWA::eKeyState_Y); - auto isIncreaseFOV = rPadState.IsDown(SWA::eKeyState_DpadUp); - auto isDecreaseFOV = rPadState.IsDown(SWA::eKeyState_DpadDown); - - auto fovScaleFactor = 0.0f; - - if (isIncreaseFOV) - { - fovScaleFactor = FOV_MODIFIER_RATIO; - } - else if (isDecreaseFOV) - { - fovScaleFactor = -FOV_MODIFIER_RATIO; - } - g_speed = std::clamp(g_speed, 0.01f, 20.0f); - g_fov = fmodf(isResetFOV ? DEFAULT_FOV : g_fov + fovScaleFactor * App::s_deltaTime * 60.0f, 180.0f); } - if (rPadState.IsTapped(SWA::eKeyState_DpadLeft)) - { - g_isCameraLocked = !g_isCameraLocked; - g_speed = g_baseSpeed; - - if (g_isCameraLocked) - { - LOGN("[Free Camera] Locked"); - } - else - { - LOGN("[Free Camera] Unlocked"); - } - } - - if (rPadState.IsTapped(SWA::eKeyState_DpadRight)) - { - *SWA::SGlobals::ms_IsRenderDepthOfField = !*SWA::SGlobals::ms_IsRenderDepthOfField; - - if (*SWA::SGlobals::ms_IsRenderDepthOfField) - { - LOGN("[Free Camera] Depth of Field ON"); - } - else - { - LOGN("[Free Camera] Depth of Field OFF"); - } - } - - pCamera->m_Speed = g_speed; - - FreeCameraPatches::s_fieldOfView = 2.0f * atan(tan(DEGREES_TO_RADIANS(g_fov / 2.0f) * (16.0f / 9.0f / std::min(aspectRatio, 16.0f / 9.0f)))); + f0.f64 = g_speed; return true; } + +// SWA::CFreeCamera::Update +PPC_FUNC_IMPL(__imp__sub_82472A18); +PPC_FUNC(sub_82472A18) +{ + if (Config::EnableFreeCamera) + { + auto pCamera = (SWA::CFreeCamera*)g_memory.Translate(ctx.r3.u32); + auto aspectRatio = (float)GameWindow::s_width / (float)GameWindow::s_height; + + if (auto pInputState = SWA::CInputState::GetInstance()) + { + auto& rPadState = pInputState->GetPadState(); + + // Deactivate. + if (rPadState.IsTapped(SWA::eKeyState_Select)) + { + guest_stack_var msgPopCameraController(pCamera, 0.0f); + guest_stack_var msgCameraPauseMove(false); + + // Process SWA::Message::MsgPopCameraController. + GuestToHostFunction(sub_8246A840, pCamera->m_pCamera.get(), msgPopCameraController.get()); + + // Process SWA::Message::MsgFinishFreeCamera. + GuestToHostFunction(sub_8253ADB8, App::s_pGameModeStage); + + // Process SWA::Message::MsgCameraPauseMove. + GuestToHostFunction(sub_824679C0, pCamera->m_pCamera.get(), msgCameraPauseMove.get()); + + FreeCameraPatches::s_isActive = false; + *SWA::SGlobals::ms_IsRenderHud = true; + + LOGN("[Free Camera] Disabled"); + + g_isDisablingFreeCamera = true; + + return; + } + + // Teleport player to camera. + if (rPadState.IsTapped(SWA::eKeyState_LeftStick)) + { + guest_stack_var msgSetPosition(pCamera->m_Position); + guest_stack_var msgSetVelocity(Hedgehog::Math::CVector(0.0f, 0.0f, 0.0f)); + + if (auto pPlayerSpeedContext = SWA::Player::CPlayerSpeedContext::GetInstance()) + { + // Process SWA::Message::MsgSetPosition. + GuestToHostFunction(sub_82303100, pPlayerSpeedContext->m_pPlayer.get(), msgSetPosition.get()); + + // Process SWA::Message::MsgSetVelocity. + GuestToHostFunction(sub_82311820, pPlayerSpeedContext->m_pPlayer.get(), msgSetVelocity.get()); + } + else if (App::s_pEvilSonicContext) + { + // Process SWA::Message::MsgSetPosition. + GuestToHostFunction(sub_82303100, App::s_pEvilSonicContext->m_pPlayer.get(), msgSetPosition.get()); + } + } + + // Lock camera. + if (rPadState.IsTapped(SWA::eKeyState_DpadLeft)) + { + g_isCameraLocked = !g_isCameraLocked; + + if (g_isCameraLocked) + { + LOGN("[Free Camera] Locked"); + } + else + { + g_speed = g_baseSpeed; + + LOGN("[Free Camera] Unlocked"); + } + } + + // Toggle depth of field. + if (rPadState.IsTapped(SWA::eKeyState_DpadRight)) + { + *SWA::SGlobals::ms_IsRenderDepthOfField = !*SWA::SGlobals::ms_IsRenderDepthOfField; + + if (*SWA::SGlobals::ms_IsRenderDepthOfField) + { + LOGN("[Free Camera] Depth of Field ON"); + } + else + { + LOGN("[Free Camera] Depth of Field OFF"); + } + } + + auto isResetFOV = rPadState.IsDown(SWA::eKeyState_Y); + auto isIncreaseFOV = rPadState.IsDown(SWA::eKeyState_DpadUp); + auto isDecreaseFOV = rPadState.IsDown(SWA::eKeyState_DpadDown); + + auto fovScaleFactor = 0.0f; + + if (isIncreaseFOV) + { + fovScaleFactor = FOV_MODIFIER_RATIO; + } + else if (isDecreaseFOV) + { + fovScaleFactor = -FOV_MODIFIER_RATIO; + } + + g_fieldOfView = fmodf(isResetFOV ? DEFAULT_FIELD_OF_VIEW : g_fieldOfView + fovScaleFactor * App::s_deltaTime * 60.0f, 180.0f); + + FreeCameraPatches::s_fieldOfView = 2.0f * atan(tan(DEGREES_TO_RADIANS(g_fieldOfView / 2.0f) * (16.0f / 9.0f / std::min(aspectRatio, 16.0f / 9.0f)))); + } + } + + __imp__sub_82472A18(ctx, base); +} + +void FreeCameraPatches::Update() +{ + if (!Config::EnableFreeCamera || !App::s_pGameModeStage) + return; + + if (auto pInputState = SWA::CInputState::GetInstance()) + { + auto& rPadState = pInputState->GetPadState(); + + if (rPadState.IsTapped(SWA::eKeyState_Select) && !FreeCameraPatches::s_isActive && !g_isDisablingFreeCamera) + { + ResetParameters(); + + // Process SWA::Message::MsgStartFreeCamera. + GuestToHostFunction(sub_8253ACB8, App::s_pGameModeStage); + + FreeCameraPatches::s_isActive = true; + *SWA::SGlobals::ms_IsRenderHud = false; + + LOGN("[Free Camera] Enabled"); + } + + if (rPadState.IsReleased(SWA::eKeyState_Select) && !FreeCameraPatches::s_isActive) + g_isDisablingFreeCamera = false; + } +} diff --git a/UnleashedRecomp/patches/free_camera_patches.h b/UnleashedRecomp/patches/free_camera_patches.h index 77010e82..be1c99ff 100644 --- a/UnleashedRecomp/patches/free_camera_patches.h +++ b/UnleashedRecomp/patches/free_camera_patches.h @@ -6,4 +6,6 @@ public: static inline bool s_isActive; static inline float s_fieldOfView; + + static void Update(); }; diff --git a/UnleashedRecomp/patches/inspire_patches.cpp b/UnleashedRecomp/patches/inspire_patches.cpp index 4e493bce..72559383 100644 --- a/UnleashedRecomp/patches/inspire_patches.cpp +++ b/UnleashedRecomp/patches/inspire_patches.cpp @@ -57,7 +57,7 @@ PPC_FUNC(sub_82B98D30) g_pScene = nullptr; InspirePatches::s_sceneName.clear(); - SDL_User_EvilSonic(App::s_isWerehog); + SDL_User_EvilSonic(App::s_pEvilSonicContext); g_loadedMouthExplosionAnimation = false; g_hideMorphModels = false; diff --git a/UnleashedRecomp/patches/player_patches.cpp b/UnleashedRecomp/patches/player_patches.cpp index 3377c987..f57678fd 100644 --- a/UnleashedRecomp/patches/player_patches.cpp +++ b/UnleashedRecomp/patches/player_patches.cpp @@ -104,9 +104,9 @@ void SetXButtonHomingMidAsmHook(PPCRegister& r30) PPC_FUNC_IMPL(__imp__sub_823B49D8); PPC_FUNC(sub_823B49D8) { - __imp__sub_823B49D8(ctx, base); + App::s_pEvilSonicContext = (SWA::Player::CEvilSonicContext*)g_memory.Translate(ctx.r3.u32); - App::s_isWerehog = true; + __imp__sub_823B49D8(ctx, base); SDL_User_EvilSonic(true); } @@ -115,9 +115,9 @@ PPC_FUNC(sub_823B49D8) PPC_FUNC_IMPL(__imp__sub_823B4590); PPC_FUNC(sub_823B4590) { - __imp__sub_823B4590(ctx, base); + App::s_pEvilSonicContext = nullptr; - App::s_isWerehog = false; + __imp__sub_823B4590(ctx, base); SDL_User_EvilSonic(false); } diff --git a/UnleashedRecomp/patches/resident_patches.cpp b/UnleashedRecomp/patches/resident_patches.cpp index 791b4153..eadc0e61 100644 --- a/UnleashedRecomp/patches/resident_patches.cpp +++ b/UnleashedRecomp/patches/resident_patches.cpp @@ -20,7 +20,7 @@ PPC_FUNC(sub_824DCF38) if (Config::TimeOfDayTransition == ETimeOfDayTransition::PlayStation) { ctx.r4.u32 = SWA::eLoadingDisplayType_ChangeTimeOfDay; - pLoading->m_IsNightToDay = App::s_isWerehog; + pLoading->m_IsNightToDay = App::s_pEvilSonicContext; } if (Config::UseArrowsForTimeOfDayTransition) diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index 756d1daa..b0d4c4ec 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -1087,41 +1087,20 @@ name = "AnimationDataMakeMidAsmHook" address = 0x82BB38E4 registers = ["r31", "r29", "r28"] -[[midasm_hook]] -name = "EnableFreeCameraMidAsmHook" -address = 0x825389F0 -jump_address_on_true = 0x825389F4 - -[[midasm_hook]] -name = "EnableFreeCameraMidAsmHook" -address = 0x82538A18 -jump_address_on_true = 0x82538A1C - -[[midasm_hook]] -name = "FreeCameraActivationInputMidAsmHook" -address = 0x824569BC -registers = ["r11", "r27", "r28"] -jump_address_on_true = 0x824569D4 - -[[midasm_hook]] -name = "FreeCameraTeleportToPlayerInputMidAsmHook" -address = 0x8245C21C -registers = ["r4"] - [[midasm_hook]] name = "FreeCameraSpeedInputMidAsmHook" -address = 0x8245C318 -registers = ["r31"] -jump_address_on_true = 0x8245C38C +address = 0x82472A7C +registers = ["r31", "r29", "f0"] +jump_address_on_true = 0x82472AC4 -# Disable "change to free camera" input. +# Disable start/end tool input. [[midasm_hook]] -name = "FreeCameraNullInputMidAsmHook" -address = 0x8245BCE4 -jump_address_on_true = 0x8245BDB4 +name = "FreeCameraActiveMidAsmHook" +address = 0x825D7690 +jump_address_on_true = 0x825D7704 -# Disable "change to pan camera" input. +# Disable deactivation input. [[midasm_hook]] -name = "FreeCameraNullInputMidAsmHook" -address = 0x8245BDC4 -jump_address_on_true = 0x8245BEAC +name = "FreeCameraActiveMidAsmHook" +address = 0x825D745C +jump_address_on_true = 0x825D768C