From c6e2dbcce0760ed03c41335b45c04330c12433e5 Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Fri, 10 Jan 2025 01:54:31 +0300 Subject: [PATCH] Ultrawide patch for HUD 3D items. --- UnleashedRecomp/patches/camera_patches.cpp | 31 ++++++----- UnleashedRecomp/patches/camera_patches.h | 3 + UnleashedRecomp/patches/csd_patches.cpp | 65 ++++++++++++++++++++++ UnleashedRecompLib/config/SWA.toml | 5 ++ 4 files changed, 91 insertions(+), 13 deletions(-) create mode 100644 UnleashedRecomp/patches/camera_patches.h diff --git a/UnleashedRecomp/patches/camera_patches.cpp b/UnleashedRecomp/patches/camera_patches.cpp index a88b5037..215f4227 100644 --- a/UnleashedRecomp/patches/camera_patches.cpp +++ b/UnleashedRecomp/patches/camera_patches.cpp @@ -1,6 +1,7 @@ #include #include #include +#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); diff --git a/UnleashedRecomp/patches/camera_patches.h b/UnleashedRecomp/patches/camera_patches.h new file mode 100644 index 00000000..949a2ddc --- /dev/null +++ b/UnleashedRecomp/patches/camera_patches.h @@ -0,0 +1,3 @@ +#pragma once + +extern float AdjustFieldOfView(float fieldOfView, float aspectRatio); diff --git a/UnleashedRecomp/patches/csd_patches.cpp b/UnleashedRecomp/patches/csd_patches.cpp index 5d512671..e5202a4d 100644 --- a/UnleashedRecomp/patches/csd_patches.cpp +++ b/UnleashedRecomp/patches/csd_patches.cpp @@ -5,6 +5,8 @@ #include #include +#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*>(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; + } +} diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index a644146b..a39470f2 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -623,3 +623,8 @@ registers = ["r4"] name = "AddPrimitive2DMidAsmHook" address = 0x824DB3E4 registers = ["r3"] + +[[midasm_hook]] +name = "ObjGetItemFieldOfViewMidAsmHook" +address = 0x82692934 +registers = ["r1", "f1"]