diff --git a/pcsx2/Interpreter.cpp b/pcsx2/Interpreter.cpp index fb163359ee..f4d9ac2ada 100644 --- a/pcsx2/Interpreter.cpp +++ b/pcsx2/Interpreter.cpp @@ -39,14 +39,32 @@ static fastjmp_buf intJmpBuf; static void intEventTest(); -u32 intGetCycles() +void intUpdateCPUCycles() { - return cpuBlockCycles; -} + const bool lowcycles = (cpuBlockCycles <= 40); + const s8 cyclerate = EmuConfig.Speedhacks.EECycleRate; + u32 scale_cycles = 0; -void intSetCycles(u32 cycles) -{ - cpuBlockCycles = cycles; + if (cyclerate == 0 || lowcycles || cyclerate < -99 || cyclerate > 3) + scale_cycles = cpuBlockCycles >> 3; + + else if (cyclerate > 1) + scale_cycles = cpuBlockCycles >> (2 + cyclerate); + + else if (cyclerate == 1) + scale_cycles = (cpuBlockCycles >> 3) / 1.3f; // Adds a mild 30% increase in clockspeed for value 1. + + else if (cyclerate == -1) // the mildest value which is also used by the "balanced" preset. + // These values were manually tuned to yield mild speedup with high compatibility + scale_cycles = (cpuBlockCycles <= 80 || cpuBlockCycles > 168 ? 5 : 7) * cpuBlockCycles / 32; + + else + scale_cycles = ((5 + (-2 * (cyclerate + 1))) * cpuBlockCycles) >> 5; + + // Ensure block cycle count is never less than 1. + cpuRegs.cycle += (scale_cycles < 1) ? 1 : scale_cycles; + + cpuBlockCycles &= (1 << 3) - 1; } // These macros are used to assemble the repassembler functions @@ -211,8 +229,7 @@ static __fi void _doBranch_shared(u32 tar) static void doBranch( u32 target ) { _doBranch_shared( target ); - cpuRegs.cycle += cpuBlockCycles >> 3; - cpuBlockCycles &= (1<<3)-1; + intUpdateCPUCycles(); intEventTest(); } @@ -223,8 +240,7 @@ void intDoBranch(u32 target) if( Cpu == &intCpu ) { - cpuRegs.cycle += cpuBlockCycles >> 3; - cpuBlockCycles &= (1<<3)-1; + intUpdateCPUCycles(); intEventTest(); } } diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index 41b3cd06bd..3bb8e29d61 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -220,8 +220,7 @@ alignas(16) extern tlbs tlb[48]; extern bool eeEventTestIsActive; -u32 intGetCycles(); -void intSetCycles(u32 cycles); +void intUpdateCPUCycles(); void intSetBranch(); // This is a special form of the interpreter's doBranch that is run from various diff --git a/pcsx2/VU0.cpp b/pcsx2/VU0.cpp index 66f20c42d3..6c1f77d3b5 100644 --- a/pcsx2/VU0.cpp +++ b/pcsx2/VU0.cpp @@ -66,13 +66,14 @@ __fi void _vu0run(bool breakOnMbit, bool addCycles, bool sync_only) { return; } + if(!EmuConfig.Cpu.Recompiler.EnableEE) + intUpdateCPUCycles(); + u32 startcycle = cpuRegs.cycle; s32 runCycles = 0x7fffffff; if (sync_only) { - cpuRegs.cycle += intGetCycles() >> 3; - intSetCycles(intGetCycles() & (1 << 3) - 1); runCycles = (s32)(cpuRegs.cycle - VU0.cycle); if (runCycles < 0) @@ -127,33 +128,36 @@ namespace OpcodeImpl void QMFC2() { + vu0Sync(); + if (cpuRegs.code & 1) { _vu0FinishMicro(); } - else - vu0Sync(); + if (_Rt_ == 0) return; cpuRegs.GPR.r[_Rt_].UD[0] = VU0.VF[_Fs_].UD[0]; cpuRegs.GPR.r[_Rt_].UD[1] = VU0.VF[_Fs_].UD[1]; } void QMTC2() { + vu0Sync(); + if (cpuRegs.code & 1) { _vu0WaitMicro(); } - else - vu0Sync(); + if (_Fs_ == 0) return; VU0.VF[_Fs_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; VU0.VF[_Fs_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; } void CFC2() { + vu0Sync(); + if (cpuRegs.code & 1) { _vu0FinishMicro(); } - else - vu0Sync(); + if (_Rt_ == 0) return; if (_Fs_ == REG_R) @@ -171,11 +175,12 @@ void CFC2() { } void CTC2() { + vu0Sync(); + if (cpuRegs.code & 1) { _vu0WaitMicro(); } - else - vu0Sync(); + if (_Fs_ == 0) return; switch(_Fs_) { diff --git a/pcsx2/VU0microInterp.cpp b/pcsx2/VU0microInterp.cpp index 9d1eac86ce..a080b13de2 100644 --- a/pcsx2/VU0microInterp.cpp +++ b/pcsx2/VU0microInterp.cpp @@ -286,6 +286,37 @@ void InterpVU0::Execute(u32 cycles) vu0Exec(&VU0); } VU0.VI[REG_TPC].UL >>= 3; - VU0.nextBlockCycles = (VU0.cycle - cpuRegs.cycle) + 1; + + if (EmuConfig.Speedhacks.EECycleRate != 0 && (!EmuConfig.Gamefixes.VUSyncHack || EmuConfig.Speedhacks.EECycleRate < 0)) + { + u32 cycle_change = VU0.cycle - startcycles; + VU0.cycle -= cycle_change; + switch (std::min(static_cast(EmuConfig.Speedhacks.EECycleRate), static_cast(cycle_change))) + { + case -3: // 50% + cycle_change *= 2.0f; + break; + case -2: // 60% + cycle_change *= 1.6666667f; + break; + case -1: // 75% + cycle_change *= 1.3333333f; + break; + case 1: // 130% + cycle_change /= 1.3f; + break; + case 2: // 180% + cycle_change /= 1.8f; + break; + case 3: // 300% + cycle_change /= 3.0f; + break; + default: + break; + } + VU0.cycle += cycle_change; + } fesetround(originalRounding); + + VU0.nextBlockCycles = (VU0.cycle - cpuRegs.cycle) + 1; }