diff --git a/pcsx2/Misc.h b/pcsx2/Misc.h index 71368d379f..012a355b93 100644 --- a/pcsx2/Misc.h +++ b/pcsx2/Misc.h @@ -70,6 +70,8 @@ #define CHECK_SLOWDVD (Config.GameFixes & 0x1) // Slow DVD access times, for games that are strict about them (Tales of the Abyss) #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_VUCLIPHACK (Config.GameFixes & 0x2) // Special Fix for GoW, updates the clipflag differently in recVUMI_CLIP() (note: turning this hack on, breaks Rockstar games) +#define CHECK_VUBRANCHHACK (Config.GameFixes & 0x8) // Special Fix for Magna Carta (note: Breaks Crash Bandicoot) + //------------ DEFAULT sseMXCSR VALUES!!! --------------- #define DEFAULT_sseMXCSR 0x9fc0 //disable all exception, round to 0, flush to 0 #define DEFAULT_sseVUMXCSR 0x7f80 //disable all exception diff --git a/pcsx2/windows/WinMain.c b/pcsx2/windows/WinMain.c index e20d8d6f61..c65d2830bb 100644 --- a/pcsx2/windows/WinMain.c +++ b/pcsx2/windows/WinMain.c @@ -728,6 +728,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) if(Config.GameFixes & 0x1) CheckDlgButton(hDlg, IDC_GAMEFIX1, TRUE); if(Config.GameFixes & 0x2) CheckDlgButton(hDlg, IDC_GAMEFIX2, TRUE); if(Config.GameFixes & 0x4) CheckDlgButton(hDlg, IDC_GAMEFIX3, TRUE); + if(Config.GameFixes & 0x8) CheckDlgButton(hDlg, IDC_GAMEFIX4, TRUE); return TRUE; case WM_COMMAND: @@ -737,6 +738,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) Config.GameFixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX1) ? 0x1 : 0; Config.GameFixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX2) ? 0x2 : 0; Config.GameFixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX3) ? 0x4 : 0; + Config.GameFixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX4) ? 0x8 : 0; SaveConfig(); diff --git a/pcsx2/windows/pcsx2.rc b/pcsx2/windows/pcsx2.rc index 7634fdbf4e..49888e56f8 100644 --- a/pcsx2/windows/pcsx2.rc +++ b/pcsx2/windows/pcsx2.rc @@ -90,6 +90,8 @@ BEGIN "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,58,253,10 CONTROL "Slow DVD access (fixes Tales of the Abyss)",IDC_GAMEFIX1, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,44,252,10 + CONTROL "VU Branch Hack - Special fix for Magna Carta; Breaks Crash Bandicoot!",IDC_GAMEFIX4, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,84,252,10 END diff --git a/pcsx2/windows/resource.h b/pcsx2/windows/resource.h index fe0d120dfd..0205425f91 100644 --- a/pcsx2/windows/resource.h +++ b/pcsx2/windows/resource.h @@ -626,6 +626,7 @@ #define IDC_FPUCLAMPHACK 1303 #define IDC_VU_CHECK2 1303 #define IDC_FPU_FLAGS 1303 +#define IDC_GAMEFIX4 1303 #define IDC_ROUNDMODE 1304 #define IDC_SOUNDHACK2 1304 #define IDC_ESCHACK 1304 diff --git a/pcsx2/x86/iVUzerorec.cpp b/pcsx2/x86/iVUzerorec.cpp index 1febb746fa..0df211ef07 100644 --- a/pcsx2/x86/iVUzerorec.cpp +++ b/pcsx2/x86/iVUzerorec.cpp @@ -93,10 +93,6 @@ using namespace std; #define SUPERVU_VIBRANCHDELAY // when integers are modified right before a branch that uses the integer, // the old integer value is used in the branch // fixes kh2 -#ifdef SUPERVU_VIBRANCHDELAY -//#define SUPERVU_VIBRANCHDELAY2 // stores the old integer value for SUPERVU_VIBRANCHDELAY into s_VIBranchDelay; when this is not-defined, we just return (uptr)&VU->VI[reg] instead. - // Note: this method breaks Magna Carta. -#endif #define SUPERVU_PROPAGATEFLAGS // the correct behavior of VUs, for some reason superman breaks gfx with it on... @@ -468,12 +464,8 @@ static u32 s_StatusRead = 0, s_MACRead = 0, s_ClipRead = 0; // read addrs static u32 s_PrevStatusWrite = 0, s_PrevMACWrite = 0, s_PrevClipWrite = 0, s_PrevIWrite = 0; static u32 s_WriteToReadQ = 0; -#ifdef SUPERVU_VIBRANCHDELAY2 -static u32 s_VIBranchDelay = 0; -//Value of register to use in a vi branch delayed situation -//If SUPERVU_VIBRANCHDELAY2 is not defined, we just return (uptr)&VU->VI[reg] -//Test this with Kingdom Hearts II and Magna Carta -#endif +static u32 s_VIBranchDelay = 0; //Value of register to use in a vi branch delayed situation + extern "C" { u32 s_TotalVUCycles; // total cycles since start of program execution @@ -515,14 +507,12 @@ u32 SuperVUGetVIAddr(int reg, int read) } #ifdef SUPERVU_VIBRANCHDELAY - if( read != 0 && (s_pCurInst->regs[0].pipe == VUPIPE_BRANCH) && s_pCurInst->vicached >= 0 && s_pCurInst->vicached == reg ) { - // test for branch delays -#ifdef SUPERVU_VIBRANCHDELAY2 - return (uptr)&s_VIBranchDelay; -#else - SysPrintf("VIBRANCHDELAY! Report if this breaks anything (rama)\n"); -#endif - } + if( (read != 0) && (s_pCurInst->regs[0].pipe == VUPIPE_BRANCH) && (s_pCurInst->vicached >= 0) && (s_pCurInst->vicached == reg) ) { + if (!CHECK_VUBRANCHHACK) { + return (uptr)&s_VIBranchDelay; // test for branch delays + } + else SysPrintf("VIBRANCHDELAY hack! Please report if this breaks anything (rama)\n"); + } #endif return (uptr)&VU->VI[reg]; @@ -3674,12 +3664,12 @@ void VuInstruction::Recompile(list::iterator& itinst, u32 vuxyz) if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; if( s_ScheduleXGKICK && s_XGKICKReg > 0 ) x86regs[s_XGKICKReg].needed = 1; -#ifdef SUPERVU_VIBRANCHDELAY2 - if( type & INST_CACHE_VI ) { - assert( vicached >= 0 ); - int cachedreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), vicached, MODE_READ); - MOV32RtoM((uptr)&s_VIBranchDelay, cachedreg); - } +#ifdef SUPERVU_VIBRANCHDELAY + if ( (!CHECK_VUBRANCHHACK) && (type & INST_CACHE_VI) ) { + assert( vicached >= 0 ); + int cachedreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), vicached, MODE_READ); + MOV32RtoM((uptr)&s_VIBranchDelay, cachedreg); + } #endif // check if inst before branch and the write is the same as the read in the branch (wipeout) diff --git a/pcsx2/x86/ix86-32/iR5900AritImm.c b/pcsx2/x86/ix86-32/iR5900AritImm.c index acf714ddcd..5e578a9b5e 100644 --- a/pcsx2/x86/ix86-32/iR5900AritImm.c +++ b/pcsx2/x86/ix86-32/iR5900AritImm.c @@ -65,39 +65,34 @@ void recADDI_(int info) EEINST_SETSIGNEXT(_Rt_); EEINST_SETSIGNEXT(_Rs_); - if( info & PROCESS_EE_MMX ) { - if( _Imm_ != 0 ) { + if ( info & PROCESS_EE_MMX ) { + if ( _Imm_ != 0 ) { u32* ptempmem = recAllocStackMem(8, 8); ptempmem[0] = (s32)_Imm_; ptempmem[1] = 0; - if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + if ( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); PADDDMtoR(EEREC_T, (u32)ptempmem); - if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(EEREC_T, _Rt_, 0); + if ( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(EEREC_T, _Rt_, 0); else EEINST_RESETHASLIVE1(_Rt_); } else { // just move and sign extend - if( !EEINST_HASLIVE1(_Rs_) ) { - - if( EEINST_ISLIVE1(_Rt_) ) - _signExtendGPRMMXtoMMX(EEREC_T, _Rt_, EEREC_S, _Rs_); - else - EEINST_RESETHASLIVE1(_Rt_); - } - else { - if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + if ( !EEINST_HASLIVE1(_Rs_) ) { + if ( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRMMXtoMMX(EEREC_T, _Rt_, EEREC_S, _Rs_); + else EEINST_RESETHASLIVE1(_Rt_); } + else if ( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); } return; } - if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && (_Rt_ != _Rs_) ) { + if ( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && (_Rt_ != _Rs_) ) { int rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); SetMMXstate(); - if( _Imm_ != 0 ) { + if ( _Imm_ != 0 ) { u32* ptempmem = recAllocStackMem(8, 8); ptempmem[0] = (s32)_Imm_; ptempmem[1] = 0; @@ -105,33 +100,31 @@ void recADDI_(int info) MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); PADDDMtoR(rtreg, (u32)ptempmem); - if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); + if ( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); else EEINST_RESETHASLIVE1(_Rt_); } else { // just move and sign extend - if( !EEINST_HASLIVE1(_Rs_) ) { + if ( !EEINST_HASLIVE1(_Rs_) ) { MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); - if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); + if ( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); else EEINST_RESETHASLIVE1(_Rt_); } - else { - MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); - } + else MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); } } else { - if( _Rt_ == _Rs_ ) { + if ( _Rt_ == _Rs_ ) { ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); - if( EEINST_ISLIVE1(_Rt_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + if ( EEINST_ISLIVE1(_Rt_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); else EEINST_RESETHASLIVE1(_Rt_); } else { MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); - if ( _Imm_ != 0 ) - ADD32ItoR( EAX, _Imm_ ); - if( EEINST_ISLIVE1(_Rt_) ) { + if ( _Imm_ != 0 ) ADD32ItoR( EAX, _Imm_ ); + + if ( EEINST_ISLIVE1(_Rt_) ) { CDQ( ); MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );