diff --git a/pcsx2/Misc.h b/pcsx2/Misc.h index 847d85d625..e200beb0db 100644 --- a/pcsx2/Misc.h +++ b/pcsx2/Misc.h @@ -82,23 +82,23 @@ extern SessionOverrideFlags g_Session; #define CHECK_MULTIGS (Config.Options&PCSX2_GSMULTITHREAD) #define CHECK_EEREC (!g_Session.ForceDisableEErec && Config.Options&PCSX2_EEREC) //------------ SPEED/MISC HACKS!!! --------------- -#define CHECK_EE_CYCLERATE (Config.Hacks & 0x03) -#define CHECK_IOP_CYCLERATE (Config.Hacks & (1<<3)) -#define CHECK_WAITCYCLE_HACK (Config.Hacks & (1<<4)) -#define CHECK_INTC_STAT_HACK (Config.Hacks & (1<<5)) -#define CHECK_ESCAPE_HACK (Config.Hacks & 0x400) +#define CHECK_EE_CYCLERATE (Config.Hacks & 0x03) +#define CHECK_IOP_CYCLERATE (Config.Hacks & 0x08) +#define CHECK_WAITCYCLE_HACK (Config.Hacks & 0x10) +#define CHECK_INTC_STAT_HACK (Config.Hacks & 0x20) +#define CHECK_ESCAPE_HACK (Config.Hacks & 0x400) //------------ SPECIAL GAME FIXES!!! --------------- -#define CHECK_VUADDSUBHACK (Config.GameFixes & 0x1) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate. -#define CHECK_FPUCLAMPHACK (Config.GameFixes & 0x4) // Special Fix for Tekken 5, different clamping for FPU (sets NaN to zero; doesn't clamp infinities) -#define CHECK_FCORHACK (Config.GameFixes & 0x8) // Special Fix for ICO, cures SPS due to some misscalculation of the clip flag. +#define CHECK_VUADDSUBHACK (Config.GameFixes & 0x1) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate. +#define CHECK_FPUCOMPAREHACK (Config.GameFixes & 0x4) // Special Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu. +#define CHECK_FCORHACK (Config.GameFixes & 0x8) // Special Fix for ICO, cures SPS due to some misscalculation of the clip flag. //------------ Advanced Options!!! --------------- -#define CHECK_VU_OVERFLOW (Config.vuOptions & 0x1) -#define CHECK_VU_EXTRA_OVERFLOW (Config.vuOptions & 0x2) // If enabled, Operands are clamped before being used in the VU recs -#define CHECK_VU_SIGN_OVERFLOW (Config.vuOptions & 0x4) -#define CHECK_VU_UNDERFLOW (Config.vuOptions & 0x8) +#define CHECK_VU_OVERFLOW (Config.vuOptions & 0x1) +#define CHECK_VU_EXTRA_OVERFLOW (Config.vuOptions & 0x2) // If enabled, Operands are clamped before being used in the VU recs +#define CHECK_VU_SIGN_OVERFLOW (Config.vuOptions & 0x4) +#define CHECK_VU_UNDERFLOW (Config.vuOptions & 0x8) #define CHECK_VU_EXTRA_FLAGS 0 // Always disabled now // Sets correct flags in the VU recs -#define CHECK_FPU_OVERFLOW (Config.eeOptions & 0x1) -#define CHECK_FPU_EXTRA_OVERFLOW (Config.eeOptions & 0x2) // If enabled, Operands are checked for infinities before being used in the FPU recs +#define CHECK_FPU_OVERFLOW (Config.eeOptions & 0x1) +#define CHECK_FPU_EXTRA_OVERFLOW (Config.eeOptions & 0x2) // If enabled, Operands are checked for infinities before being used in the FPU recs #define CHECK_FPU_EXTRA_FLAGS 1 // Always enabled now // Sets D/I flags on FPU instructions #define DEFAULT_eeOptions 0x01 #define DEFAULT_vuOptions 0x01 diff --git a/pcsx2/windows/pcsx2.rc b/pcsx2/windows/pcsx2.rc index 9b2a242d83..151680a281 100644 --- a/pcsx2/windows/pcsx2.rc +++ b/pcsx2/windows/pcsx2.rc @@ -8,7 +8,6 @@ // Generated from the TEXTINCLUDE 2 resource. // #include "afxresmw.h" - ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -84,11 +83,12 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,139,99,50,14 CTEXT "Some games need special settings.\nConfigure them here.",IDC_STATIC,7,7,264,17 GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,31,264,89 - CONTROL "FPU Clamp Hack - Special fix for Tekken 5.",IDC_GAMEFIX3, + CONTROL "FPU Compare Hack - Special fix for Digimon Rumble Arena 2.",IDC_GAMEFIX3, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,51,249,10 CONTROL "VU Add / Sub Hack - Special fix for Tri-Ace games!",IDC_GAMEFIX2, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,65,252,10 - CONTROL "VU FCOR Hack - Fixes ICO SPS",IDC_GAMEFIX7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,79,252,10 + CONTROL "VU FCOR Hack - Special Fix for ICO SPS.",IDC_GAMEFIX7, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,79,252,10 END @@ -1388,7 +1388,7 @@ END 2 TEXTINCLUDE BEGIN - "#include ""afxresmw.h\0" + "#include ""afxresmw.h""\0" END 3 TEXTINCLUDE diff --git a/pcsx2/x86/iFPU.cpp b/pcsx2/x86/iFPU.cpp index b0a202a705..65a3150bd0 100644 --- a/pcsx2/x86/iFPU.cpp +++ b/pcsx2/x86/iFPU.cpp @@ -371,70 +371,61 @@ REC_FPUFUNC(RSQRT_S); //------------------------------------------------------------------ // Clamp Functions (Converts NaN's and Infinities to Normal Numbers) //------------------------------------------------------------------ -void fpuFloat(int regd) { // +/-NaN -> +fMax, +Inf -> +fMax, -Inf -> -fMax - if (CHECK_FPU_OVERFLOW && !CHECK_FPUCLAMPHACK) { // Tekken 5 doesn't like clamping infinities. + +PCSX2_ALIGNED16(u64 FPU_FLOAT_TEMP[2]); +__forceinline void fpuFloat4(int regd) { // +NaN -> +fMax, -NaN -> -fMax, +Inf -> +fMax, -Inf -> -fMax + int t1reg = _allocTempXMMreg(XMMT_FPS, -1); + if (t1reg >= 0) { + SSE_MOVSS_XMM_to_XMM(t1reg, regd); + SSE_ANDPS_M128_to_XMM(t1reg, (uptr)&s_neg[0]); + SSE_MINSS_M32_to_XMM(regd, (uptr)&g_maxvals[0]); + SSE_MAXSS_M32_to_XMM(regd, (uptr)&g_minvals[0]); + SSE_ORPS_XMM_to_XMM(regd, t1reg); + _freeXMMreg(t1reg); + } + else { + Console::Error("fpuFloat2() allocation error"); + t1reg = (regd == 0) ? 1 : 0; // get a temp reg thats not regd + SSE_MOVAPS_XMM_to_M128( (uptr)&FPU_FLOAT_TEMP[0], t1reg ); // backup data in t1reg to a temp address + SSE_MOVSS_XMM_to_XMM(t1reg, regd); + SSE_ANDPS_M128_to_XMM(t1reg, (uptr)&s_neg[0]); + SSE_MINSS_M32_to_XMM(regd, (uptr)&g_maxvals[0]); + SSE_MAXSS_M32_to_XMM(regd, (uptr)&g_minvals[0]); + SSE_ORPS_XMM_to_XMM(regd, t1reg); + SSE_MOVAPS_M128_to_XMM( t1reg, (uptr)&FPU_FLOAT_TEMP[0] ); // restore t1reg data + } +} + +__forceinline void fpuFloat(int regd) { // +/-NaN -> +fMax, +Inf -> +fMax, -Inf -> -fMax + if (CHECK_FPU_OVERFLOW) { SSE_MINSS_M32_to_XMM(regd, (uptr)&g_maxvals[0]); // MIN() must be before MAX()! So that NaN's become +Maximum SSE_MAXSS_M32_to_XMM(regd, (uptr)&g_minvals[0]); } } -PCSX2_ALIGNED16(u64 FPU_FLOAT_TEMP[2]); -void fpuFloat2(int regd) { // +NaN -> +fMax, -NaN -> -fMax, +Inf -> +fMax, -Inf -> -fMax - if (CHECK_FPU_OVERFLOW && !CHECK_FPUCLAMPHACK) { // Tekken 5 doesn't like clamping infinities. - int t1reg = _allocTempXMMreg(XMMT_FPS, -1); - if (t1reg >= 0) { - SSE_MOVSS_XMM_to_XMM(t1reg, regd); - SSE_ANDPS_M128_to_XMM(t1reg, (uptr)&s_neg[0]); - SSE_MINSS_M32_to_XMM(regd, (uptr)&g_maxvals[0]); - SSE_MAXSS_M32_to_XMM(regd, (uptr)&g_minvals[0]); - SSE_ORPS_XMM_to_XMM(regd, t1reg); - _freeXMMreg(t1reg); - } - else { - Console::Error("fpuFloat2() allocation error"); - t1reg = (regd == 0) ? 1 : 0; // get a temp reg thats not regd - SSE_MOVAPS_XMM_to_M128( (uptr)&FPU_FLOAT_TEMP[0], t1reg ); // backup data in t1reg to a temp address - SSE_MOVSS_XMM_to_XMM(t1reg, regd); - SSE_ANDPS_M128_to_XMM(t1reg, (uptr)&s_neg[0]); - SSE_MINSS_M32_to_XMM(regd, (uptr)&g_maxvals[0]); - SSE_MAXSS_M32_to_XMM(regd, (uptr)&g_minvals[0]); - SSE_ORPS_XMM_to_XMM(regd, t1reg); - SSE_MOVAPS_M128_to_XMM( t1reg, (uptr)&FPU_FLOAT_TEMP[0] ); // restore t1reg data - } +__forceinline void fpuFloat2(int regd) { // +NaN -> +fMax, -NaN -> -fMax, +Inf -> +fMax, -Inf -> -fMax + if (CHECK_FPU_OVERFLOW) { + fpuFloat4(regd); } } __forceinline void fpuFloat3(int regd) { - // This clamp function used in the recC_xx opcodes + // This clamp function is used in the recC_xx opcodes // Rule of Rose needs clamping or else it crashes (minss or maxss both fix the crash) + // Tekken 5 has disappearing characters unless preserving NaN sign (fpuFloat4() preserves NaN sign). // Digimon Rumble Arena 2 needs MAXSS clamping (if you only use minss, it spins on the intro-menus; - // it also doesn't like preserving NaN sign with fpuFloat2, so the only way to make Digimon work + // it also doesn't like preserving NaN sign with fpuFloat4, so the only way to make Digimon work // is by calling MAXSS first) - SSE_MAXSS_M32_to_XMM(regd, (uptr)&g_minvals[0]); - //SSE_MINSS_M32_to_XMM(regd, (uptr)&g_maxvals[0]); + if (CHECK_FPUCOMPAREHACK) { + //SSE_MINSS_M32_to_XMM(regd, (uptr)&g_maxvals[0]); + SSE_MAXSS_M32_to_XMM(regd, (uptr)&g_minvals[0]); + } + else fpuFloat4(regd); } void ClampValues(int regd) { fpuFloat(regd); } - -void ClampValues2(int regd) { - if (CHECK_FPUCLAMPHACK) { // Fixes Tekken 5 ( Makes NaN equal 0, infinities stay the same ) - int t5reg = _allocTempXMMreg(XMMT_FPS, -1); - - SSE_XORPS_XMM_to_XMM(t5reg, t5reg); - SSE_CMPORDSS_XMM_to_XMM(t5reg, regd); - - SSE_ANDPS_XMM_to_XMM(regd, t5reg); - - /* --- Its odd but tekken dosn't like Infinities to be clamped. --- */ - //SSE_MINSS_M32_to_XMM(regd, (uptr)&g_maxvals[0]); - //SSE_MAXSS_M32_to_XMM(regd, (uptr)&g_minvals[0]); - - _freeXMMreg(t5reg); - } - else fpuFloat(regd); -} //------------------------------------------------------------------ @@ -639,7 +630,7 @@ int recCommutativeOp(int info, int regd, int op) void recADD_S_xmm(int info) { //AND32ItoM((uptr)&fpuRegs.fprc[31], ~(FPUflagO|FPUflagU)); // Clear O and U flags - ClampValues2(recCommutativeOp(info, EEREC_D, 0)); + ClampValues(recCommutativeOp(info, EEREC_D, 0)); //REC_FPUOP(ADD_S); } @@ -1561,7 +1552,7 @@ void recSUBop(int info, int regd) break; } - ClampValues2(regd); + ClampValues(regd); _freeXMMreg(t0reg); } diff --git a/pcsx2/x86/iVUmicroLower.cpp b/pcsx2/x86/iVUmicroLower.cpp index 3717902f32..e1a1f0432c 100644 --- a/pcsx2/x86/iVUmicroLower.cpp +++ b/pcsx2/x86/iVUmicroLower.cpp @@ -1364,7 +1364,7 @@ void recVUMI_FMEQ( VURegs *VU, int info ) if ( _Ft_ == 0 ) return; //SysPrintf("recVUMI_FMEQ \n"); if( _Ft_ == _Fs_ ) { - ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ);//|MODE_8BITREG); + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ|MODE_8BITREG); CMP16MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); SETE8R(EAX); @@ -1397,7 +1397,7 @@ void recVUMI_FMOR( VURegs *VU, int info ) MOVZX32M16toR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1) ); } else if( _Ft_ == _Fs_ ) { - ftreg = ALLOCVI(_Ft_, MODE_WRITE);//|MODE_READ|MODE_8BITREG); + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ);//|MODE_8BITREG); OR16MtoR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1) ); } else { @@ -1453,18 +1453,20 @@ void recVUMI_FCEQ( VURegs *VU, int info ) //------------------------------------------------------------------ void recVUMI_FCOR( VURegs *VU, int info ) { - int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); - //SysPrintf("recVUMI_FCOR \n"); - MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1) ); - XOR32RtoR( ftreg, ftreg ); - OR32ItoR( EAX, VU->code ); - AND32ItoR( EAX, 0xffffff ); - CMP32ItoR( EAX, 0xffffff ); - - if(CHECK_FCORHACK) //ICO Misscalculated CLIP flag (bits missing id guess) - SETNZ8R(ftreg); - else - SETZ8R(ftreg); + int ftreg; + //SysPrintf("recVUMI_FCOR\n"); + if(CHECK_FCORHACK) {//ICO Miss-calculated CLIP flag so always set to true (probably a zerorec pipeline problem) + ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + MOV32ItoR( ftreg, 1 ); + } + else { + ftreg = ALLOCVI(1, MODE_WRITE); + MOV32MtoR( ftreg, VU_VI_ADDR(REG_CLIP_FLAG, 1) ); + OR32ItoR ( ftreg, VU->code ); + AND32ItoR( ftreg, 0xffffff ); + ADD32ItoR( ftreg, 1 ); // If 24 1's will make 25th bit 1, else 0 + SHR32ItoR( ftreg, 24 ); // Get the 25th bit (also clears the rest of the garbage in the reg) + } } //------------------------------------------------------------------