From 713876918227367f8e8f336b84e5db1c4e3d52ee Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Sat, 12 Dec 2020 03:33:24 +0000 Subject: [PATCH] VU: Synchronise VU1, added speedhack for old behaviour --- bin/GameIndex.dbf | 36 ++++++++++++++++++++++++++ pcsx2/COP2.cpp | 4 +-- pcsx2/Config.h | 4 ++- pcsx2/Pcsx2Config.cpp | 2 ++ pcsx2/R5900.cpp | 2 +- pcsx2/VU0.cpp | 6 ++--- pcsx2/VU1micro.cpp | 20 +++++++++++--- pcsx2/VUmicro.cpp | 2 +- pcsx2/VUmicro.h | 2 +- pcsx2/Vif0_Dma.cpp | 5 ++-- pcsx2/Vif1_Dma.cpp | 12 +++++---- pcsx2/Vif1_MFIFO.cpp | 2 +- pcsx2/Vif_Codes.cpp | 26 +++++++------------ pcsx2/gui/AppConfig.cpp | 3 +++ pcsx2/gui/AppCoreThread.cpp | 8 ++++++ pcsx2/gui/Panels/ConfigurationPanels.h | 1 + pcsx2/gui/Panels/SpeedhacksPanel.cpp | 11 +++++++- pcsx2/x86/microVU_Branch.inl | 25 +++++++++++------- pcsx2/x86/microVU_Compile.inl | 2 -- pcsx2/x86/microVU_Macro.inl | 7 ++--- 20 files changed, 127 insertions(+), 53 deletions(-) diff --git a/bin/GameIndex.dbf b/bin/GameIndex.dbf index 3b95202ef5..67bdfde6fd 100644 --- a/bin/GameIndex.dbf +++ b/bin/GameIndex.dbf @@ -76,6 +76,7 @@ -- Speed Hacks (SpeedHackName = ) --------------------------------------------- -- mvuFlagSpeedHack = 1 or 0 // Katamari Damacy have weird speed bug when this speed hack is enabled (and it is by default) +-- InstantVU1SpeedHack = 1 or 0 // Games such as Parappa the Rapper 2 need VU1 to sync, so you can force disable the speedhack here --------------------------------------------- -- Memory Card Filter Override (MemCardFilter = s) @@ -1391,6 +1392,7 @@ Serial = SCES-50408 Name = PaRappa the Rapper 2 Region = PAL-M5 Compat = 5 +InstantVU1SpeedHack = 0 // Fixes noodles. --------------------------------------------- Serial = SCES-50409 Name = MotoGP 2 @@ -3550,6 +3552,7 @@ Region = NTSC-J Serial = SCPS-15017 Name = PaRappa the Rapper 2 Region = NTSC-J +InstantVU1SpeedHack = 0 // Fixes noodles. --------------------------------------------- Serial = SCPS-15018 Name = Train Simulator Real, The - Yamanote Sen @@ -4091,6 +4094,7 @@ Region = NTSC-J Serial = SCPS-19201 Name = PaRappa the Rapper 2 [PlayStation 2 The Best] Region = NTSC-J +InstantVU1SpeedHack = 0 // Fixes noodles. --------------------------------------------- Serial = SCPS-19202 Name = Extermination [PlayStation 2 The Best] @@ -4924,6 +4928,7 @@ Serial = SCUS-97167 Name = PaRappa the Rapper 2 Region = NTSC-U Compat = 5 +InstantVU1SpeedHack = 0 // Fixes noodles. --------------------------------------------- Serial = SCUS-97169 Name = Drakan - The Ancients' Gates [Demo] @@ -5080,6 +5085,7 @@ Region = NTSC-U Serial = SCUS-97208 Name = Hot Shots Golf 3 & PaRappa the Rapper 2 [Demo] Region = NTSC-U +InstantVU1SpeedHack = 0 // Fixes noodles on Parappa 2. --------------------------------------------- Serial = SCUS-97209 Name = Ratchet & Clank [E3 Demo] @@ -6772,6 +6778,7 @@ Region = PAL-M5 Serial = SLED-52488 Name = Suffering, The [Demo] Region = PAL-E +InstantVU1SpeedHack = 1 // Fixes SPS. --------------------------------------------- Serial = SLED-52597 Name = Burnout 3 - Takedown [Demo] @@ -7793,6 +7800,7 @@ Serial = SLES-50382 Name = Silent Hill 2 Region = PAL-M6 Compat = 5 +InstantVU1SpeedHack = 0 // Fixes hang on FMV's when CDVD timing is accurate. --------------------------------------------- Serial = SLES-50383 Name = Metal Gear Solid 2 - Sons of Liberty @@ -7961,6 +7969,7 @@ Serial = SLES-50446 Name = Shadow Man - 2econd Coming Region = PAL-M4 Compat = 4 +InstantVU1SpeedHack = 0 // Fixes SPS. --------------------------------------------- Serial = SLES-50447 Name = All-Star Baseball 2003 @@ -8292,6 +8301,7 @@ Region = PAL-M4 Serial = SLES-50608 Name = Shadow Man - 2econd Coming Region = PAL-G +InstantVU1SpeedHack = 0 // Fixes SPS. --------------------------------------------- Serial = SLES-50613 Name = Woody Woodpecker @@ -9614,6 +9624,7 @@ Serial = SLES-51144 Name = Shox - Rally Reinvented Region = PAL-M7 Compat = 5 +VU0KickstartHack = 1 // Fixes SPS. --------------------------------------------- Serial = SLES-51145 Name = Monopoly Party @@ -9642,6 +9653,7 @@ Serial = SLES-51156 Name = Silent Hill 2 - Director's Cut Region = PAL-M5 Compat = 5 +InstantVU1SpeedHack = 0 // Fixes hang on FMV's when CDVD timing is accurate. --------------------------------------------- Serial = SLES-51157 Name = Silent Scope 3 @@ -9863,10 +9875,12 @@ Serial = SLES-51250 Name = Shox - Rally Reinvented Region = PAL-E Compat = 5 +VU0KickstartHack = 1 // Fixes SPS. --------------------------------------------- Serial = SLES-51251 Name = Shox - Rally Reinvented Region = PAL-E +VU0KickstartHack = 1 // Fixes SPS. --------------------------------------------- Serial = SLES-51252 Name = Lord of the Rings, The - The Two Towers @@ -10797,6 +10811,7 @@ Region = PAL-S Serial = SLES-51693 Name = Suffering, The Region = PAL-E-F-G +InstantVU1SpeedHack = 1 // Fixes SPS. --------------------------------------------- Serial = SLES-51696 Name = Dragon's Lair 3D - Special Edition @@ -11584,6 +11599,7 @@ Serial = SLES-52001 Name = Mission Impossible - Operation Surma Region = PAL-M5 Compat = 5 +VU0KickstartHack = 1 // Fixes crashes and broken graphics. --------------------------------------------- Serial = SLES-52002 Name = Rogue Ops @@ -12439,6 +12455,7 @@ Serial = SLES-52439 Name = Suffering, The Region = PAL-E-I-S Compat = 5 +InstantVU1SpeedHack = 1 // Fixes SPS. --------------------------------------------- Serial = SLES-52440 Name = Harry Potter and the Prisoner of Azkaban @@ -12662,6 +12679,7 @@ Region = PAL-M4 // Nordic. Serial = SLES-52531 Name = Suffering, The Region = PAL-G +InstantVU1SpeedHack = 1 // Fixes SPS. --------------------------------------------- Serial = SLES-52532 Name = Aces of War @@ -15191,16 +15209,19 @@ Region = PAL-G Serial = SLES-53526 Name = Suffering, The - Ties that Bind Region = PAL-E-F +InstantVU1SpeedHack = 1 // Fixes SPS. MemCardFilter = SLES-53526/SLES-53527/SLES-53528/SLES-53626/SLES-51693/SLES-52439/SLES-52531 --------------------------------------------- Serial = SLES-53527 Name = Suffering, The - Ties that Bind Region = PAL-E-I-S +InstantVU1SpeedHack = 1 // Fixes SPS. MemCardFilter = SLES-53526/SLES-53527/SLES-53528/SLES-53626/SLES-51693/SLES-52439/SLES-52531 --------------------------------------------- Serial = SLES-53528 Name = Suffering, The - Ties that Bind Region = PAL-G +InstantVU1SpeedHack = 1 // Fixes SPS. MemCardFilter = SLES-53526/SLES-53527/SLES-53528/SLES-53626/SLES-51693/SLES-52439/SLES-52531 --------------------------------------------- Serial = SLES-53529 @@ -15509,6 +15530,7 @@ Compat = 5 Serial = SLES-53626 Name = Suffering, The - Ties that Bind Region = PAL-E-G +InstantVU1SpeedHack = 1 // Fixes SPS. MemCardFilter = SLES-53526/SLES-53527/SLES-53528/SLES-53626/SLES-51693/SLES-52439/SLES-52531 --------------------------------------------- Serial = SLES-53632 @@ -21725,6 +21747,7 @@ Region = NTSC-J Serial = SLPM-61009 Name = Silent Hill 2 (Red Ribbon) [Trial] Region = NTSC-J +InstantVU1SpeedHack = 0 // Fixes hang on FMV's when CDVD timing is accurate. --------------------------------------------- Serial = SLPM-61010 Name = Devil May Cry [Trial Version] @@ -21733,6 +21756,7 @@ Region = NTSC-J Serial = SLPM-61011 Name = Silent Hill 2 (Black Ribbon) [Video Trial] Region = NTSC-J +InstantVU1SpeedHack = 0 // Fixes hang on FMV's when CDVD timing is accurate. --------------------------------------------- Serial = SLPM-61051 Name = Dengeki PS2 D61 @@ -24098,6 +24122,7 @@ Region = NTSC-J Serial = SLPM-62737 Name = Rally Shox & Freestyle Motorcross [EA Best Hits] Region = NTSC-J +VU0KickstartHack = 1 // Fixes SPS. --------------------------------------------- Serial = SLPM-62739 Name = Suro Genjin @@ -24466,6 +24491,7 @@ Serial = SLPM-65051 Name = Silent Hill 2 Region = NTSC-J Compat = 5 +InstantVU1SpeedHack = 0 // Fixes hang on FMV's when CDVD timing is accurate. --------------------------------------------- Serial = SLPM-65052 Name = Guitar Freaks 4th Mix & Drummania 3rd Mix @@ -24627,6 +24653,7 @@ Serial = SLPM-65098 Name = Silent Hill 2 - Saigo no Uta Region = NTSC-J Compat = 5 +InstantVU1SpeedHack = 0 // Fixes hang on FMV's when CDVD timing is accurate. --------------------------------------------- Serial = SLPM-65100 Name = Onimusha 2 @@ -25437,6 +25464,7 @@ Region = NTSC-J Serial = SLPM-65341 Name = Silent Hill 2 - Saigo No Uta [Konami The Best] Region = NTSC-J +InstantVU1SpeedHack = 0 // Fixes hang on FMV's when CDVD timing is accurate. --------------------------------------------- Serial = SLPM-65342 Name = Kyoufu Shinbun (Heisei) Kaiki! Shinrei File @@ -26103,6 +26131,7 @@ Region = NTSC-J Serial = SLPM-65529 Name = Mission Impossible - Operation Surma Region = NTSC-J +VU0KickstartHack = 1 // Fixes crashes and broken graphics. --------------------------------------------- Serial = SLPM-65530 Name = J-League Pro Soccer Club - Tsukuku 2004 @@ -26495,6 +26524,7 @@ Region = NTSC-J Serial = SLPM-65631 Name = Silent Hill 2 [Konami The Best] Region = NTSC-J +InstantVU1SpeedHack = 0 // Fixes hang on FMV's when CDVD timing is accurate. --------------------------------------------- Serial = SLPM-65632 Name = Virtua Fighter Cyber Generation - Ambition of the Judgement Six @@ -38218,6 +38248,7 @@ Serial = SLUS-20228 Name = Silent Hill 2 Region = NTSC-U Compat = 5 +InstantVU1SpeedHack = 0 // Fixes hang on FMV's when CDVD timing is accurate. --------------------------------------------- Serial = SLUS-20229 Name = Jonny Moseley - Mad Trix @@ -39062,6 +39093,7 @@ Serial = SLUS-20400 Name = Mission Impossible - Operation Surma Region = NTSC-U Compat = 5 +VU0KickstartHack = 1 // Fixes crashes and broken graphics. --------------------------------------------- Serial = SLUS-20402 Name = Britney's Dance Beat @@ -39111,6 +39143,7 @@ Serial = SLUS-20413 Name = Shadow Man - 2econd Coming Region = NTSC-U Compat = 4 +InstantVU1SpeedHack = 0 // Fixes SPS. --------------------------------------------- Serial = SLUS-20414 Name = Legaia 2 - Duel Saga @@ -39690,6 +39723,7 @@ Serial = SLUS-20533 Name = Shox Region = NTSC-U Compat = 5 +VU0KickstartHack = 1 // Fixes SPS. --------------------------------------------- Serial = SLUS-20534 Name = Cabela's Big Game Hunter @@ -40177,6 +40211,7 @@ Serial = SLUS-20636 Name = Suffering, The Region = NTSC-U Compat = 5 +InstantVU1SpeedHack = 1 // Fixes SPS. --------------------------------------------- Serial = SLUS-20637 Name = Chessmaster (Online) @@ -42886,6 +42921,7 @@ Serial = SLUS-21189 Name = Suffering, The - Ties That Bind Region = NTSC-U Compat = 5 +InstantVU1SpeedHack = 1 // Fixes SPS. MemCardFilter = SLUS-21189/SLUS-20636 --------------------------------------------- Serial = SLUS-21190 diff --git a/pcsx2/COP2.cpp b/pcsx2/COP2.cpp index 9a566a133e..90bb21bc13 100644 --- a/pcsx2/COP2.cpp +++ b/pcsx2/COP2.cpp @@ -22,8 +22,8 @@ using namespace R5900; using namespace R5900::Interpreter; -//#define CP2COND (((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1)) -#define CP2COND (vif1Regs.stat.VEW) +#define CP2COND (((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1)) +//#define CP2COND (vif1Regs.stat.VEW) //Run the FINISH either side of the VCALL's as we have no control over it past here. void VCALLMS() { diff --git a/pcsx2/Config.h b/pcsx2/Config.h index 16e79ba5dc..2923450786 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -394,7 +394,8 @@ struct Pcsx2Config IntcStat :1, // tells Pcsx2 to fast-forward through intc_stat waits. WaitLoop :1, // enables constant loop detection and fast-forwarding vuFlagHack :1, // microVU specific flag hack - vuThread :1; // Enable Threaded VU1 + vuThread :1, // Enable Threaded VU1 + vu1Instant :1; // Enable Instant VU1 (Without MTVU only) BITFIELD_END s8 EECycleRate; // EE cycle rate selector (1.0, 1.5, 2.0) @@ -527,6 +528,7 @@ TraceLogFilters& SetTraceConfig(); // ------------ CPU / Recompiler Options --------------- #define THREAD_VU1 (EmuConfig.Cpu.Recompiler.UseMicroVU1 && EmuConfig.Speedhacks.vuThread) +#define INSTANT_VU1 (EmuConfig.Speedhacks.vu1Instant) #define CHECK_MICROVU0 (EmuConfig.Cpu.Recompiler.UseMicroVU0) #define CHECK_MICROVU1 (EmuConfig.Cpu.Recompiler.UseMicroVU1) #define CHECK_EEREC (EmuConfig.Cpu.Recompiler.EnableEE && GetCpuProviders().IsRecAvailable_EE()) diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index 5d30387ec9..ecafb42de4 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -43,6 +43,7 @@ Pcsx2Config::SpeedhackOptions::SpeedhackOptions() WaitLoop = true; IntcStat = true; vuFlagHack = true; + vu1Instant = true; } Pcsx2Config::SpeedhackOptions& Pcsx2Config::SpeedhackOptions::DisableAll() @@ -65,6 +66,7 @@ void Pcsx2Config::SpeedhackOptions::LoadSave( IniInterface& ini ) IniBitBool( WaitLoop ); IniBitBool( vuFlagHack ); IniBitBool( vuThread ); + IniBitBool( vu1Instant ); } void Pcsx2Config::ProfilerOptions::LoadSave( IniInterface& ini ) diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 681fe3a49a..54a2a7df9b 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -431,7 +431,7 @@ __fi void _cpuEventTest_Shared() // We're in a EventTest. All dynarec registers are flushed // so there is no need to freeze registers here. CpuVU0->ExecuteBlock(); - + CpuVU1->ExecuteBlock(); // Note: We don't update the VU1 here because it runs it's micro-programs in // one shot always. That is, when a program is executed the VU1 doesn't even // bother to return until the program is completely finished. diff --git a/pcsx2/VU0.cpp b/pcsx2/VU0.cpp index 8b0cbd585a..23bd56246b 100644 --- a/pcsx2/VU0.cpp +++ b/pcsx2/VU0.cpp @@ -170,10 +170,8 @@ void CTC2() { } break; case REG_CMSAR1: // REG_CMSAR1 - if (!(VU0.VI[REG_VPU_STAT].UL & 0x100) ) { - vu1ExecMicro(cpuRegs.GPR.r[_Rt_].US[0]); // Execute VU1 Micro SubRoutine - vif1VUFinish(); - } + vu1Finish(true); + vu1ExecMicro(cpuRegs.GPR.r[_Rt_].US[0]); // Execute VU1 Micro SubRoutine break; default: VU0.VI[_Fs_].UL = cpuRegs.GPR.r[_Rt_].UL[0]; diff --git a/pcsx2/VU1micro.cpp b/pcsx2/VU1micro.cpp index f987269c67..741cb4ee48 100644 --- a/pcsx2/VU1micro.cpp +++ b/pcsx2/VU1micro.cpp @@ -35,15 +35,24 @@ void vu1ResetRegs() vif1Regs.stat.VEW = false; } -void vu1Finish() { +void vu1Finish(bool add_cycles) { if (THREAD_VU1) { if (VU0.VI[REG_VPU_STAT].UL & 0x100) DevCon.Error("MTVU: VU0.VI[REG_VPU_STAT].UL & 0x100"); return; } - while (VU0.VI[REG_VPU_STAT].UL & 0x100) { + u32 vu1cycles = VU1.cycle; + if(VU0.VI[REG_VPU_STAT].UL & 0x100) { VUM_LOG("vu1ExecMicro > Stalling until current microprogram finishes"); CpuVU1->Execute(vu1RunCycles); } + if (VU0.VI[REG_VPU_STAT].UL & 0x100) { + DevCon.Warning("Force Stopping VU1, ran for too long"); + VU0.VI[REG_VPU_STAT].UL &= ~0x100; + } + if (add_cycles) + { + cpuRegs.cycle += VU1.cycle - vu1cycles; + } } void __fastcall vu1ExecMicro(u32 addr) @@ -54,7 +63,7 @@ void __fastcall vu1ExecMicro(u32 addr) return; } static int count = 0; - vu1Finish(); + vu1Finish(false); VUM_LOG("vu1ExecMicro %x (count=%d)", addr, count++); VU1.cycle = cpuRegs.cycle; @@ -64,5 +73,8 @@ void __fastcall vu1ExecMicro(u32 addr) CpuVU1->SetStartPC(VU1.VI[REG_TPC].UL << 3); _vuExecMicroDebug(VU1); - CpuVU1->Execute(vu1RunCycles); + if(!INSTANT_VU1) + CpuVU1->ExecuteBlock(1); + else + CpuVU1->Execute(vu1RunCycles); } diff --git a/pcsx2/VUmicro.cpp b/pcsx2/VUmicro.cpp index 22e51269f0..2827530e7c 100644 --- a/pcsx2/VUmicro.cpp +++ b/pcsx2/VUmicro.cpp @@ -21,7 +21,7 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp) { const u32& stat = VU0.VI[REG_VPU_STAT].UL; const int test = m_Idx ? 0x100 : 1; - const int s = EmuConfig.Gamefixes.VU0KickstartHack ? 16 : 0; // Kick Start Cycles (Jak needs at least 4, DT Racer needs 8192) + const int s = EmuConfig.Gamefixes.VU0KickstartHack ? 16 : 0; // Kick Start Cycles (Jak needs at least 4 due to writing values after they're read if (!(stat & test)) return; diff --git a/pcsx2/VUmicro.h b/pcsx2/VUmicro.h index b0f6a8dd1d..38e47ce8ca 100644 --- a/pcsx2/VUmicro.h +++ b/pcsx2/VUmicro.h @@ -264,7 +264,7 @@ extern void vu0Finish(); extern void iDumpVU0Registers(); // VU1 -extern void vu1Finish(); +extern void vu1Finish(bool add_cycles); extern void vu1ResetRegs(); extern void __fastcall vu1ExecMicro(u32 addr); extern void vu1Exec(VURegs* VU); diff --git a/pcsx2/Vif0_Dma.cpp b/pcsx2/Vif0_Dma.cpp index 5e0f6c451f..020cce9718 100644 --- a/pcsx2/Vif0_Dma.cpp +++ b/pcsx2/Vif0_Dma.cpp @@ -30,6 +30,7 @@ __fi void vif0FLUSH() vif0.waitforvu = true; vif0.vifstalled.enabled = VifStallEnable(vif0ch); vif0.vifstalled.value = VIF_TIMING_BREAK; + vif0Regs.stat.VEW = true; } return; } @@ -158,7 +159,7 @@ __fi void vif0VUFinish() vif0.waitforvu = false; ExecuteVU(0); //Make sure VIF0 isnt already scheduled to spin. - if(!(cpuRegs.interrupt & 0x1) && vif0ch.chcr.STR && !vif0Regs.stat.INT) + if(!(cpuRegs.interrupt & 0x1) && vif0ch.chcr.STR && !vif0Regs.stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS)) vif0Interrupt(); } //DevCon.Warning("VU0 state cleared"); @@ -176,7 +177,7 @@ __fi void vif0Interrupt() if(vif0.waitforvu) { - //CPU_INT(DMAC_VIF0, 16); + CPU_INT(VIF_VU0_FINISH, 16); return; } diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index bc97db5dc9..311c6067f3 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -30,6 +30,7 @@ __fi void vif1FLUSH() vif1.waitforvu = true; vif1.vifstalled.enabled = VifStallEnable(vif1ch); vif1.vifstalled.value = VIF_TIMING_BREAK; + vif1Regs.stat.VEW = true; } } @@ -236,13 +237,13 @@ __fi void vif1VUFinish() CPU_INT(VIF_VU1_FINISH, 128); return; } - + if (VU0.VI[REG_VPU_STAT].UL & 0x100) { - int _cycles = VU1.cycle; + u32 _cycles = VU1.cycle; //DevCon.Warning("Finishing VU1"); - vu1Finish(); - CPU_INT(VIF_VU1_FINISH, (VU1.cycle - _cycles) * BIAS); + vu1Finish(false); + CPU_INT(VIF_VU1_FINISH, VU1.cycle - _cycles); return; } @@ -267,7 +268,7 @@ __fi void vif1VUFinish() vif1.waitforvu = false; ExecuteVU(1); //Check if VIF is already scheduled to interrupt, if it's waiting, kick it :P - if((cpuRegs.interrupt & (1<> 2) )); CPU_INT(VIF_VU0_FINISH, 1/*startcycles * BIAS*/); } - else { startcycles = ((VU1.cycle-startcycles) + ( vif1ch.qwc - (vif1.vifpacketsize >> 2) )); CPU_INT(VIF_VU1_FINISH, 1/*startcycles * BIAS*/); } - - //DevCon.Warning("Ran VU%x, VU0 Cycles %x, VU1 Cycles %x, start %x cycle %x", idx, g_vu0Cycles, g_vu1Cycles, startcycles, VU1.cycle); - //GetVifX.vifstalled.enabled = VifStallEnable(vifXch); - //GetVifX.vifstalled.value = VIF_TIMING_BREAK; + // Hack for Wakeboarding Unleashed, game runs a VU program in parallel with a VIF unpack list. + // The start of the VU program clears the VU memory, while VIF populates it from behind, so we need to get the clear out of the way. + /*if (idx && !INSTANT_VU1) + { + VU1.cycle -= 256; + CpuVU1->ExecuteBlock(0); + }*/ } static __fi void vifFlush(int idx) { @@ -74,8 +69,6 @@ static __fi void vuExecMicro(int idx, u32 addr) { if(GetVifX.waitforvu) return; - vifRegs.stat.VEW = true; - if (vifRegs.itops > (idx ? 0x3ffu : 0xffu)) { Console.WriteLn("VIF%d ITOP overrun! %x", idx, vifRegs.itops); vifRegs.itops &= (idx ? 0x3ffu : 0xffu); @@ -103,6 +96,9 @@ static __fi void vuExecMicro(int idx, u32 addr) { GetVifX.queued_program = true; GetVifX.queued_pc = addr; GetVifX.unpackcalls = 0; + + if (!idx || (!THREAD_VU1 && !INSTANT_VU1)) + vifExecQueue(idx); } void ExecuteVU(int idx) @@ -271,8 +267,6 @@ static __fi void _vifCode_MPG(int idx, u32 addr, const u32 *data, int size) { return; } - - // Don't forget the Unsigned designator for these checks if((addr + size *4) > vuMemSize) { diff --git a/pcsx2/gui/AppConfig.cpp b/pcsx2/gui/AppConfig.cpp index 07af28781f..0d896e868d 100644 --- a/pcsx2/gui/AppConfig.cpp +++ b/pcsx2/gui/AppConfig.cpp @@ -1064,6 +1064,7 @@ bool AppConfig::IsOkApplyPreset(int n, bool ignoreMTVU) EmuOptions.Speedhacks = default_Pcsx2Config.Speedhacks; EmuOptions.Speedhacks.bitset = 0; //Turn off individual hacks to make it visually clear they're not used. EmuOptions.Speedhacks.vuThread = original_SpeedHacks.vuThread; + EmuOptions.Speedhacks.vu1Instant= original_SpeedHacks.vu1Instant; EnableSpeedHacks = true; // Actual application of current preset over the base settings which all presets use (mostly pcsx2's default values). @@ -1092,12 +1093,14 @@ bool AppConfig::IsOkApplyPreset(int n, bool ignoreMTVU) EmuOptions.Speedhacks.IntcStat = true; EmuOptions.Speedhacks.WaitLoop = true; EmuOptions.Speedhacks.vuFlagHack = true; + EmuOptions.Speedhacks.vu1Instant = true; // If waterfalling from > Safe, break to avoid MTVU disable. if (n > 1) break; [[fallthrough]]; case 0: // Safest + if(n == 0) EmuOptions.Speedhacks.vu1Instant = false; isMTVUSet ? 0 : (isMTVUSet = true, EmuOptions.Speedhacks.vuThread = false); // Disable MTVU break; diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index cfe8a4fc7d..f7f6f4005f 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -301,6 +301,14 @@ static int loadGameSettings(Pcsx2Config& dest, const Game_Data& game) gf++; } + if (game.keyExists("InstantVU1SpeedHack")) + { + bool vu1InstantHack = game.getInt("InstantVU1SpeedHack") ? 1 : 0; + PatchesCon->WriteLn("(GameDB) Changing Instant VU1 speedhack [mode=%d]", vu1InstantHack); + dest.Speedhacks.vu1Instant = vu1InstantHack; + gf++; + } + for (GamefixId id = GamefixId_FIRST; id < pxEnumEnd; ++id) { wxString key(EnumToString(id)); diff --git a/pcsx2/gui/Panels/ConfigurationPanels.h b/pcsx2/gui/Panels/ConfigurationPanels.h index f0866de7ad..2e5b01e6ba 100644 --- a/pcsx2/gui/Panels/ConfigurationPanels.h +++ b/pcsx2/gui/Panels/ConfigurationPanels.h @@ -342,6 +342,7 @@ namespace Panels pxCheckBox* m_check_fastCDVD; pxCheckBox* m_check_vuFlagHack; pxCheckBox* m_check_vuThread; + pxCheckBox* m_check_vu1Instant; public: virtual ~SpeedHacksPanel() = default; diff --git a/pcsx2/gui/Panels/SpeedhacksPanel.cpp b/pcsx2/gui/Panels/SpeedhacksPanel.cpp index f5e2df2e83..3090c46007 100644 --- a/pcsx2/gui/Panels/SpeedhacksPanel.cpp +++ b/pcsx2/gui/Panels/SpeedhacksPanel.cpp @@ -176,12 +176,18 @@ Panels::SpeedHacksPanel::SpeedHacksPanel( wxWindow* parent ) m_check_vuThread = new pxCheckBox( vuHacksPanel, _("MTVU (Multi-Threaded microVU1)"), _("Good Speedup and High Compatibility; may cause hanging... [Recommended if 3+ cores]") ); + m_check_vu1Instant = new pxCheckBox(vuHacksPanel, _("Instant VU1 (Without MTVU Only)"), + _("Good Speedup and High Compatibility; may cause some graphical errors")); + m_check_vuFlagHack->SetToolTip( pxEt( L"Updates Status Flags only on blocks which will read them, instead of all the time. This is safe most of the time." ) ); m_check_vuThread->SetToolTip( pxEt( L"Runs VU1 on its own thread (microVU1-only). Generally a speedup on CPUs with 3 or more cores. This is safe for most games, but a few games are incompatible and may hang. In the case of GS limited games, it may be a slowdown (especially on dual core CPUs)." ) ); + m_check_vu1Instant->SetToolTip(pxEt(L"Runs VU1 Instantly (When MTVU is disabled). Provides a modest speed improvement. This is safe for most games, but a few games may exhibit graphical errors." + )); + // ------------------------------------------------------------------------ // All other hacks Section: @@ -225,6 +231,7 @@ Panels::SpeedHacksPanel::SpeedHacksPanel( wxWindow* parent ) *vuHacksPanel += m_check_vuFlagHack | StdExpand(); *vuHacksPanel += m_check_vuThread | StdExpand(); + *vuHacksPanel += m_check_vu1Instant | StdExpand(); //*vuHacksPanel += 57; // Aligns left and right boxes in default language and font size *miscHacksPanel += m_check_intc | StdExpand(); @@ -281,6 +288,7 @@ void Panels::SpeedHacksPanel::EnableStuff( AppConfig* configToUse ) m_check_intc->Enable(HacksEnabledAndNoPreset); m_check_waitloop->Enable(HacksEnabledAndNoPreset); m_check_fastCDVD->Enable(HacksEnabledAndNoPreset); + m_check_vu1Instant->Enable(hacksEnabled); // Grayout MTVU on safest preset m_check_vuThread->Enable(hacksEnabled && (!hasPreset || configToUse->PresetIndex != 0)); @@ -315,7 +323,7 @@ void Panels::SpeedHacksPanel::ApplyConfigToGui( AppConfig& configToApply, int fl m_check_waitloop->SetValue(opts.WaitLoop); m_check_fastCDVD->SetValue(opts.fastCDVD); m_check_vuThread->SetValue(opts.vuThread); - + m_check_vu1Instant->SetValue(opts.vu1Instant); // Then, lock(gray out)/unlock the widgets as necessary. EnableStuff( &configToApply ); @@ -339,6 +347,7 @@ void Panels::SpeedHacksPanel::Apply() opts.IntcStat = m_check_intc->GetValue(); opts.vuFlagHack = m_check_vuFlagHack->GetValue(); opts.vuThread = m_check_vuThread->GetValue(); + opts.vu1Instant = m_check_vu1Instant->GetValue(); // If the user has a command line override specified, we need to disable it // so that their changes take effect diff --git a/pcsx2/x86/microVU_Branch.inl b/pcsx2/x86/microVU_Branch.inl index 83b4e6f064..6c47516081 100644 --- a/pcsx2/x86/microVU_Branch.inl +++ b/pcsx2/x86/microVU_Branch.inl @@ -63,11 +63,20 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { } // Save P/Q Regs - if (qInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xe5); } + if (qInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xe1); } xMOVSS(ptr32[&mVU.regs().VI[REG_Q].UL], xmmPQ); + xPSHUF.D(xmmPQ, xmmPQ, 0xe1); + xMOVSS(ptr32[&mVU.regs().pending_q], xmmPQ); + xPSHUF.D(xmmPQ, xmmPQ, 0xe1); + if (isVU1) { - xPSHUF.D(xmmPQ, xmmPQ, pInst ? 3 : 2); + xPSHUF.D(xmmPQ, xmmPQ, pInst ? 0x1b : 0x4e); xMOVSS(ptr32[&mVU.regs().VI[REG_P].UL], xmmPQ); + xPSHUF.D(xmmPQ, xmmPQ, pInst ? 0x1b : 0x4e); + + xPSHUF.D(xmmPQ, xmmPQ, 0x1b); + xMOVSS(ptr32[&mVU.regs().pending_p], xmmPQ); + xPSHUF.D(xmmPQ, xmmPQ, 0x1b); } // Save MAC, Status and CLIP Flag Instances @@ -102,10 +111,9 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { xMOVAPS(ptr128[&mVU.regs().micro_statusflags], xmmT1); } - if (isEbit || isVU1) { // Clear 'is busy' Flags + if (isEbit) { // Clear 'is busy' Flags if (!mVU.index || !THREAD_VU1) { xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag - xAND(ptr32[&mVU.getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif } } @@ -161,11 +169,11 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { xPSHUF.D(xmmPQ, xmmPQ, 0xe1); if (isVU1) { - xPSHUF.D(xmmPQ, xmmPQ, pInst ? 0x1b : 0x1e); + xPSHUF.D(xmmPQ, xmmPQ, pInst ? 0x1b : 0x4e); xMOVSS(ptr32[&mVU.regs().VI[REG_P].UL], xmmPQ); - xPSHUF.D(xmmPQ, xmmPQ, pInst ? 0x1b : 0x4b); + xPSHUF.D(xmmPQ, xmmPQ, pInst ? 0x1b : 0x4e); - xPSHUF.D(xmmPQ, xmmPQ, 0xe1); + xPSHUF.D(xmmPQ, xmmPQ, 0x1b); xMOVSS(ptr32[&mVU.regs().pending_p], xmmPQ); xPSHUF.D(xmmPQ, xmmPQ, 0x1b); } @@ -204,10 +212,9 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { } - if ((isEbit && isEbit != 3) || isVU1) { // Clear 'is busy' Flags + if ((isEbit && isEbit != 3)) { // Clear 'is busy' Flags if (!mVU.index || !THREAD_VU1) { xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag - //xAND(ptr32[&mVU.getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif } } diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index a0617cac57..b9580d449b 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -491,8 +491,6 @@ void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microF mVUsetFlags(mVU, mFC); // Sets Up Flag instances mVUoptimizePipeState(mVU); // Optimize the End Pipeline State for nicer Block Linking mVUdebugPrintBlocks(mVU, false); // Prints Start/End PC of blocks executed, for debugging... - - mVUtestCycles(mVU, mFC); // Update VU Cycles and Exit Early if Necessary // Second Pass iPC = startPC / 4; diff --git a/pcsx2/x86/microVU_Macro.inl b/pcsx2/x86/microVU_Macro.inl index a3f8df7c36..4521d47ab5 100644 --- a/pcsx2/x86/microVU_Macro.inl +++ b/pcsx2/x86/microVU_Macro.inl @@ -247,8 +247,8 @@ INTERPRETATE_COP2_FUNC(CALLMSR); void _setupBranchTest(u32*(jmpType)(u32), bool isLikely) { printCOP2("COP2 Branch"); _eeFlushAllUnused(); - xTEST(ptr32[&vif1Regs.stat._u32], 0x4); - //TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100); + //xTEST(ptr32[&vif1Regs.stat._u32], 0x4); + xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x100); recDoBranchImm(jmpType(0), isLikely); } @@ -397,12 +397,13 @@ static void recCTC2() { break; } case REG_CMSAR1: // Execute VU1 Micro SubRoutine + xMOV(ecx, 1); + xFastCall((void*)vu1Finish, ecx); if (_Rt_) { xMOV(ecx, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]); } else xXOR(ecx, ecx); xFastCall((void*)vu1ExecMicro, ecx); - xFastCall((void*)vif1VUFinish); break; case REG_FBRST: if (!_Rt_) {