mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-10-30 07:11:05 +00:00
134 lines
4.4 KiB
C++
134 lines
4.4 KiB
C++
#include <api/SWA.h>
|
|
#include <user/config.h>
|
|
#include <hid/hid.h>
|
|
#include <app.h>
|
|
|
|
// SWA::CObjFlame::CObjFlame
|
|
// A field is not zero initialized,
|
|
// causing collisions to constantly get created
|
|
// and slow down the game.
|
|
PPC_FUNC_IMPL(__imp__sub_82608E60);
|
|
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);
|
|
}
|
|
|
|
// SWA::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;
|
|
}
|
|
}
|
|
|
|
// SWA::CExBullet::AddCallback
|
|
// Tornado Defense bullet particles are colored by the button prompt, which differs on PlayStation 3.
|
|
// Luckily, the PS3 particles are left in the files, and they get spawned by name when a bullet gets created.
|
|
PPC_FUNC_IMPL(__imp__sub_82B14CC0);
|
|
PPC_FUNC(sub_82B14CC0)
|
|
{
|
|
auto isPlayStation = Config::ControllerIcons == EControllerIcons::PlayStation;
|
|
|
|
if (Config::ControllerIcons == EControllerIcons::Auto)
|
|
isPlayStation = hid::g_inputDeviceController == hid::EInputDevice::PlayStation;
|
|
|
|
if (isPlayStation)
|
|
{
|
|
PPC_STORE_U8(0x820C2A0B, 'b'); // Cross
|
|
PPC_STORE_U8(0x820C29C3, 'r'); // Circle
|
|
PPC_STORE_U8(0x820C29DB, 'p'); // Square
|
|
PPC_STORE_U8(0x820C29F3, 'g'); // Triangle
|
|
}
|
|
else
|
|
{
|
|
PPC_STORE_U8(0x820C2A0B, 'g'); // A
|
|
PPC_STORE_U8(0x820C29C3, 'r'); // B
|
|
PPC_STORE_U8(0x820C29DB, 'b'); // X
|
|
PPC_STORE_U8(0x820C29F3, 'o'); // Y
|
|
}
|
|
|
|
__imp__sub_82B14CC0(ctx, base);
|
|
}
|
|
|
|
// CObjGrindDashPanel is particularly egregious when it comes to overlapping sounds at HFR
|
|
// due to the character proxy sending the hit message multiple times in a frame. This is a
|
|
// quick workaround to limit the message process function to occur at a 30 FPS time step.
|
|
static constexpr size_t OBJ_GRIND_DASH_PANEL_SIZE = 0x160;
|
|
|
|
void ObjGrindDashPanelAllocMidAsmHook(PPCRegister& r3)
|
|
{
|
|
r3.u32 += sizeof(std::chrono::steady_clock::time_point);
|
|
}
|
|
|
|
// SWA::CObjGrindDashPanel::CObjGrindDashPanel
|
|
PPC_FUNC_IMPL(__imp__sub_82614228);
|
|
PPC_FUNC(sub_82614228)
|
|
{
|
|
new (base + ctx.r3.u32 + OBJ_GRIND_DASH_PANEL_SIZE) std::chrono::steady_clock::time_point();
|
|
__imp__sub_82614228(ctx, base);
|
|
}
|
|
|
|
// SWA::CObjGrindDashPanel::MsgHitEventCollision::Impl
|
|
PPC_FUNC_IMPL(__imp__sub_826145D8);
|
|
PPC_FUNC(sub_826145D8)
|
|
{
|
|
auto pLastHitTime = (std::chrono::steady_clock::time_point*)g_memory.Translate(ctx.r3.u32 + OBJ_GRIND_DASH_PANEL_SIZE);
|
|
auto now = std::chrono::steady_clock::now();
|
|
auto deltaTime = std::min(std::chrono::duration<double>(now - *pLastHitTime).count(), 1.0 / 15.0);
|
|
|
|
*pLastHitTime = now;
|
|
|
|
if (deltaTime < 1.0 / 30.0)
|
|
return;
|
|
|
|
__imp__sub_826145D8(ctx, base);
|
|
}
|