Interpolate barrels in Spagonia Night to fix softlock at high frame rates. (#153)

This commit is contained in:
Skyth (Asilkan) 2025-01-23 19:41:15 +03:00 committed by GitHub
parent 372c04fedd
commit ca6b42e20e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 85 additions and 0 deletions

View file

@ -17,6 +17,7 @@ namespace Hedgehog::Math
be<float> X;
be<float> Y;
be<float> Z;
be<float> W;
};
class CVector4

View file

@ -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"

View file

@ -0,0 +1,14 @@
#pragma once
#include <Hedgehog/Math/Vector.h>
namespace SWA
{
class CCharacterProxy
{
public:
SWA_INSERT_PADDING(0x120);
Hedgehog::Math::CVector m_Position;
Hedgehog::Math::CVector m_Velocity;
};
}

View file

@ -1,3 +1,6 @@
#include <user/config.h>
#include <SWA/CharacterUtility/CharacterProxy.h>
// 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<ObjBigBarrelEx*>(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<ObjBigBarrelEx*>(base + r3.u32 + OBJ_BIG_BARREL_SIZE);
if (objBigBarrelEx->interpolate)
{
auto characterProxy = reinterpret_cast<SWA::CCharacterProxy*>(base + PPC_LOAD_U32(r3.u32 + 0x100));
auto position = reinterpret_cast<Hedgehog::Math::CVector*>(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;
}
}

View file

@ -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"]