From 459c574d2469a41bd8df339f30bf15c3d00972be Mon Sep 17 00:00:00 2001 From: GitHubProUser67 <127040195+GitHubProUser67@users.noreply.github.com> Date: Tue, 28 Jan 2025 22:14:48 +0100 Subject: [PATCH] [Soft-Float] - Implements accurate VU clip. Improves performance of clip, while being accurate. Test Ratchet Gladiator to verify this commit (game needs this alongside accurate Mul support on the COP2 to fix some physics behaviours). --- pcsx2/PS2Float.cpp | 34 ++++++++++++++++++++++++++++++++++ pcsx2/PS2Float.h | 2 ++ pcsx2/VUops.cpp | 21 ++++++++++++++------- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/pcsx2/PS2Float.cpp b/pcsx2/PS2Float.cpp index eef9c61833..64bdc38503 100644 --- a/pcsx2/PS2Float.cpp +++ b/pcsx2/PS2Float.cpp @@ -540,6 +540,40 @@ s32 PS2Float::Ftoi(s32 complement, u32 f1) return (s32)result; } +u8 PS2Float::Clip(u32 f1, u32 f2, bool& cplus, bool& cminus) +{ + bool resultPlus = false; + bool resultMinus = false; + u32 a; + + if ((f1 & 0x7F800000) == 0) + { + f1 &= 0xFF800000; + } + + a = f1; + + if ((f2 & 0x7F800000) == 0) + { + f2 &= 0xFF800000; + } + + f1 = f1 & MAX_FLOATING_POINT_VALUE; + f2 = f2 & MAX_FLOATING_POINT_VALUE; + + if ((-1 < (int)a) && (f2 < f1)) + resultPlus = true; + + cplus = resultPlus; + + if (((int)a < 0) && (f2 < f1)) + resultMinus = true; + + cminus = resultMinus; + + return 0; +} + bool PS2Float::DetermineMultiplicationDivisionOperationSign(PS2Float a, PS2Float b) { return a.Sign() ^ b.Sign(); diff --git a/pcsx2/PS2Float.h b/pcsx2/PS2Float.h index 9e68425be7..dfffd40eb9 100644 --- a/pcsx2/PS2Float.h +++ b/pcsx2/PS2Float.h @@ -72,6 +72,8 @@ public: static s32 Ftoi(s32 complement, u32 f1); + static u8 Clip(u32 f1, u32 f2, bool& cplus, bool& cminus); + PS2Float Add(PS2Float addend); PS2Float Sub(PS2Float subtrahend); diff --git a/pcsx2/VUops.cpp b/pcsx2/VUops.cpp index 0beb19d1b8..ca27cfdc85 100644 --- a/pcsx2/VUops.cpp +++ b/pcsx2/VUops.cpp @@ -1805,15 +1805,22 @@ static __fi void _vuCLIP(VURegs* VU) { if (CHECK_VU_SOFT_ADDSUB((VU == &VU1) ? 1 : 0) || CHECK_VU_SOFT_MULDIV((VU == &VU1) ? 1 : 0) || CHECK_VU_SOFT_SQRT((VU == &VU1) ? 1 : 0)) { - double value = PS2Float(PS2Float(VU->VF[_Ft_].i.w).Abs()).ToDouble(); + bool cplus = false; + bool cminus = false; + u32 value = PS2Float(VU->VF[_Ft_].i.w).Abs(); VU->clipflag <<= 6; - if (PS2Float(VU->VF[_Fs_].i.x).ToDouble() > +value) VU->clipflag |= 0x01; - if (PS2Float(VU->VF[_Fs_].i.x).ToDouble() < -value) VU->clipflag |= 0x02; - if (PS2Float(VU->VF[_Fs_].i.y).ToDouble() > +value) VU->clipflag |= 0x04; - if (PS2Float(VU->VF[_Fs_].i.y).ToDouble() < -value) VU->clipflag |= 0x08; - if (PS2Float(VU->VF[_Fs_].i.z).ToDouble() > +value) VU->clipflag |= 0x10; - if (PS2Float(VU->VF[_Fs_].i.z).ToDouble() < -value) VU->clipflag |= 0x20; + PS2Float::Clip(VU->VF[_Fs_].i.x, value, cplus, cminus); + if (cplus) VU->clipflag |= 0x01; + if (cminus) VU->clipflag |= 0x02; + + PS2Float::Clip(VU->VF[_Fs_].i.y, value, cplus, cminus); + if (cplus) VU->clipflag |= 0x04; + if (cminus) VU->clipflag |= 0x08; + + PS2Float::Clip(VU->VF[_Fs_].i.z, value, cplus, cminus); + if (cplus) VU->clipflag |= 0x10; + if (cminus) VU->clipflag |= 0x20; } else {