From ca6b42e20eb3b8931ab36765595b56633c8719b0 Mon Sep 17 00:00:00 2001 From: "Skyth (Asilkan)" <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Thu, 23 Jan 2025 19:41:15 +0300 Subject: [PATCH] Interpolate barrels in Spagonia Night to fix softlock at high frame rates. (#153) --- UnleashedRecomp/api/Hedgehog/Math/Vector.h | 1 + UnleashedRecomp/api/SWA.h | 1 + .../api/SWA/CharacterUtility/CharacterProxy.h | 14 +++++ UnleashedRecomp/patches/object_patches.cpp | 59 +++++++++++++++++++ UnleashedRecompLib/config/SWA.toml | 10 ++++ 5 files changed, 85 insertions(+) create mode 100644 UnleashedRecomp/api/SWA/CharacterUtility/CharacterProxy.h diff --git a/UnleashedRecomp/api/Hedgehog/Math/Vector.h b/UnleashedRecomp/api/Hedgehog/Math/Vector.h index b1c0f3d..7ea0e38 100644 --- a/UnleashedRecomp/api/Hedgehog/Math/Vector.h +++ b/UnleashedRecomp/api/Hedgehog/Math/Vector.h @@ -17,6 +17,7 @@ namespace Hedgehog::Math be X; be Y; be Z; + be W; }; class CVector4 diff --git a/UnleashedRecomp/api/SWA.h b/UnleashedRecomp/api/SWA.h index e2a846e..1478fe2 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/CharacterUtility/CharacterProxy.h" #include "SWA/HUD/GeneralWindow/GeneralWindow.h" #include "SWA/HUD/Loading/Loading.h" #include "SWA/HUD/Pause/HudPause.h" diff --git a/UnleashedRecomp/api/SWA/CharacterUtility/CharacterProxy.h b/UnleashedRecomp/api/SWA/CharacterUtility/CharacterProxy.h new file mode 100644 index 0000000..4032727 --- /dev/null +++ b/UnleashedRecomp/api/SWA/CharacterUtility/CharacterProxy.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace SWA +{ + class CCharacterProxy + { + public: + SWA_INSERT_PADDING(0x120); + Hedgehog::Math::CVector m_Position; + Hedgehog::Math::CVector m_Velocity; + }; +} diff --git a/UnleashedRecomp/patches/object_patches.cpp b/UnleashedRecomp/patches/object_patches.cpp index b7ebe36..54c391b 100644 --- a/UnleashedRecomp/patches/object_patches.cpp +++ b/UnleashedRecomp/patches/object_patches.cpp @@ -1,3 +1,6 @@ +#include +#include + // CObjFlame::CObjFlame // A field is not zero initialized, // causing collisions to constantly get created @@ -8,3 +11,59 @@ PPC_FUNC(sub_82608E60) memset(base + ctx.r3.u32, 0, 0x154); __imp__sub_82608E60(ctx, base); } + +// The barrel gets stuck at a slope at high frame rates and softlocks the player. +// We can update the character proxy at 30 FPS, and interpolate the visuals to work around this issue. +static constexpr size_t OBJ_BIG_BARREL_SIZE = 0x1A0; + +struct ObjBigBarrelEx +{ + float elapsedTime{}; + bool interpolate{}; +}; + +void ObjBigBarrelAllocMidAsmHook(PPCRegister& r3) +{ + r3.u32 += sizeof(ObjBigBarrelEx); +} + +// CObjBigBarrel::CObjBigBarrel +PPC_FUNC_IMPL(__imp__sub_8271AC08); +PPC_FUNC(sub_8271AC08) +{ + new (base + ctx.r3.u32 + OBJ_BIG_BARREL_SIZE) ObjBigBarrelEx(); + __imp__sub_8271AC08(ctx, base); +} + +// CObjBigBarrel::Integrate +PPC_FUNC_IMPL(__imp__sub_8271AA30); +PPC_FUNC(sub_8271AA30) +{ + auto objBigBarrelEx = reinterpret_cast(base + ctx.r3.u32 + OBJ_BIG_BARREL_SIZE); + objBigBarrelEx->interpolate = ctx.f1.f64 < (1.0 / 30.0); + objBigBarrelEx->elapsedTime += ctx.f1.f64; + + if (!objBigBarrelEx->interpolate || objBigBarrelEx->elapsedTime >= (1.0f / 30.0f)) + { + ctx.f1.f64 = objBigBarrelEx->elapsedTime; + __imp__sub_8271AA30(ctx, base); + objBigBarrelEx->elapsedTime = 0.0f; + } +} + +void ObjBigBarrelSetPositionMidAsmHook(PPCRegister& r3, PPCRegister& r4) +{ + uint8_t* base = g_memory.base; + auto objBigBarrelEx = reinterpret_cast(base + r3.u32 + OBJ_BIG_BARREL_SIZE); + + if (objBigBarrelEx->interpolate) + { + auto characterProxy = reinterpret_cast(base + PPC_LOAD_U32(r3.u32 + 0x100)); + auto position = reinterpret_cast(base + r4.u32); + + float factor = (1.0f / 30.0f) - objBigBarrelEx->elapsedTime; + position->X = position->X - characterProxy->m_Velocity.X * factor; + position->Y = position->Y - characterProxy->m_Velocity.Y * factor; + position->Z = position->Z - characterProxy->m_Velocity.Z * factor; + } +} diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index cbb8971..70a9b67 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -680,3 +680,13 @@ registers = ["r3"] name = "TitleMenuRemoveContinueOnCorruptSaveMidAsmHook" address = 0x82585470 registers = ["r3"] + +[[midasm_hook]] +name = "ObjBigBarrelAllocMidAsmHook" +address = 0x8271B778 +registers = ["r3"] + +[[midasm_hook]] +name = "ObjBigBarrelSetPositionMidAsmHook" +address = 0x8271B5C8 +registers = ["r3", "r4"]