Ultrawide patch for HUD 3D items.

This commit is contained in:
Skyth 2025-01-10 01:54:31 +03:00
parent f67895253e
commit c6e2dbcce0
4 changed files with 91 additions and 13 deletions

View file

@ -1,6 +1,7 @@
#include <api/SWA.h>
#include <ui/game_window.h>
#include <user/config.h>
#include "camera_patches.h"
static constexpr float ORIGINAL_ASPECT_RATIO = 4.0f / 3.0f;
static constexpr float ORIGINAL_WIDESCREEN_ASPECT_RATIO = 16.0f / 9.0f;
@ -15,23 +16,27 @@ void CameraAspectRatioMidAsmHook(PPCRegister& r30, PPCRegister& r31)
camera->m_HorzAspectRatio = float(GameWindow::s_width) / float(GameWindow::s_height);
}
float AdjustFieldOfView(float fieldOfView, float aspectRatio)
{
if (Config::AspectRatio == EAspectRatio::OriginalNarrow)
{
// Replicate the original incorrect field of view formula if requested.
fieldOfView *= ORIGINAL_ASPECT_RATIO;
}
else if (aspectRatio < ORIGINAL_WIDESCREEN_ASPECT_RATIO)
{
// Use proper VERT+ otherwise for narrow aspect ratios.
fieldOfView = 2.0 * atan(tan(0.5 * fieldOfView) / aspectRatio * ORIGINAL_WIDESCREEN_ASPECT_RATIO);
}
return fieldOfView;
}
void CameraFieldOfViewMidAsmHook(PPCRegister& r31, PPCRegister& f31)
{
auto camera = (SWA::CCamera*)g_memory.Translate(r31.u32);
// Replicate the original incorrect field of view formula if requested.
if (Config::AspectRatio == EAspectRatio::OriginalNarrow)
{
if (abs(camera->m_HorzAspectRatio - ORIGINAL_ASPECT_RATIO) < 0.001f)
{
f31.f64 *= ORIGINAL_ASPECT_RATIO;
}
}
// Use proper VERT+ otherwise for narrow aspect ratios.
else if (camera->m_HorzAspectRatio < ORIGINAL_WIDESCREEN_ASPECT_RATIO)
{
f31.f64 = 2.0 * atan(tan(0.5 * f31.f64) / camera->m_HorzAspectRatio * ORIGINAL_WIDESCREEN_ASPECT_RATIO);
}
f31.f64 = AdjustFieldOfView(f31.f64, camera->m_HorzAspectRatio);
}
PPC_FUNC_IMPL(__imp__sub_824697B0);

View file

@ -0,0 +1,3 @@
#pragma once
extern float AdjustFieldOfView(float fieldOfView, float aspectRatio);

View file

@ -5,6 +5,8 @@
#include <ui/sdl_listener.h>
#include <gpu/video.h>
#include "camera_patches.h"
// These are here for now to not recompile basically all of the project.
namespace Chao::CSD
{
@ -876,3 +878,66 @@ PPC_FUNC(sub_830D1EF0)
}
}
}
// Objects are pushed forward by 1m, so the coordinates need to compensate for it.
static const double OBJ_GET_ITEM_TANGENT = tan(M_PI / 8.0);
// Coordinates are in [-1, 1] range. Automatically fit and centered.
// The tangent is calculated incorrectly in game, causing distortion.
// This hook makes them move to the correct position regardless of FOV.
void ObjGetItemFieldOfViewMidAsmHook(PPCRegister& r1, PPCRegister& f1)
{
*reinterpret_cast<be<float>*>(g_memory.base + r1.u32 + 0x58) = tan(AdjustFieldOfView(f1.f64, g_aspectRatio) / 2.0) / OBJ_GET_ITEM_TANGENT;
}
// SWA::CObjGetItem::GetX
PPC_FUNC(sub_82690660)
{
uint32_t type = PPC_LOAD_U32(ctx.r3.u32 + 0xE8);
if (type >= 47) // Ring, Moon Medal, Sun Medal
{
double x;
if (type == 47) // Ring
x = 142.0;
else // Medal
x = 0.0; // TODO
x *= g_scale;
if (type != 47)
x += g_offsetX * 2.0 + (1280.0 * (1.0 - g_scale));
auto backBuffer = Video::GetBackBuffer();
ctx.f1.f64 = (x - (0.5 * backBuffer->width)) / (0.5 * backBuffer->height) * OBJ_GET_ITEM_TANGENT;
}
else
{
ctx.f1.f64 = 0.0;
}
}
// SWA::CObjGetItem::GetY
PPC_FUNC(sub_826906A8)
{
uint32_t type = PPC_LOAD_U32(ctx.r3.u32 + 0xE8);
if (type >= 47) // Ring, Moon Medal, Sun Medal
{
double y;
if (type == 47) // Ring
y = 642.0;
else // Medal
y = 0.0; // TODO
y *= g_scale;
y += g_offsetY * 2.0 + 720.0 * (1.0 - g_scale);
auto backBuffer = Video::GetBackBuffer();
ctx.f1.f64 = ((0.5 * backBuffer->height) - y) / (0.5 * backBuffer->height) * OBJ_GET_ITEM_TANGENT;
}
else
{
ctx.f1.f64 = 0.25;
}
}

View file

@ -623,3 +623,8 @@ registers = ["r4"]
name = "AddPrimitive2DMidAsmHook"
address = 0x824DB3E4
registers = ["r3"]
[[midasm_hook]]
name = "ObjGetItemFieldOfViewMidAsmHook"
address = 0x82692934
registers = ["r1", "f1"]