diff --git a/bin/GameIndex.yaml b/bin/GameIndex.yaml index 4257382212..2787013240 100644 --- a/bin/GameIndex.yaml +++ b/bin/GameIndex.yaml @@ -15189,6 +15189,8 @@ SLES-54169: SLES-54170: name: "Jaws Unleashed" region: "PAL-M5" + gameFixes: + - XGKickHack # Fixes GS packet errors (and potential crash). SLES-54171: name: "Yakuza" region: "PAL-M5" @@ -36646,6 +36648,8 @@ SLUS-21062: name: "Jaws Unleashed" region: "NTSC-U" compat: 5 + gameFixes: + - XGKickHack # Fixes GS packet errors (and potential crash). SLUS-21063: name: "Shining Tears" region: "NTSC-U" diff --git a/pcsx2/VUops.cpp b/pcsx2/VUops.cpp index 818f0e729a..2e658b37ca 100644 --- a/pcsx2/VUops.cpp +++ b/pcsx2/VUops.cpp @@ -215,7 +215,7 @@ __fi void _vuTestPipes(VURegs* VU) { if (VU1.xgkickenable) { - _vuXGKICKTransfer((VU1.cycle - VU1.xgkicklastcycle), false); + _vuXGKICKTransfer((VU1.cycle - VU1.xgkicklastcycle) - 1, false); } } } @@ -2618,7 +2618,7 @@ static __ri void _vuXITOP(VURegs* VU) VU->VI[_It_].US[0] = VU->GetVifRegs().itop; } -void _vuXGKICKTransfer(u32 cycles, bool flush) +void _vuXGKICKTransfer(s32 cycles, bool flush) { if (!VU1.xgkickenable) return; diff --git a/pcsx2/VUops.h b/pcsx2/VUops.h index 6693a34a41..2b90e76bb6 100644 --- a/pcsx2/VUops.h +++ b/pcsx2/VUops.h @@ -59,4 +59,4 @@ extern void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn); extern void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn); extern void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn); extern void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn); -extern void _vuXGKICKTransfer(u32 cycles, bool flush); +extern void _vuXGKICKTransfer(s32 cycles, bool flush); diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 50fff17711..dd28730ea6 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -1634,15 +1634,19 @@ void __fastcall _vuXGKICKTransfermVU(bool flush) static __fi void mVU_XGKICK_SYNC(mV, bool flush) { + // Add the single cycle remainder after this instruction, some games do the store + // on the second instruction after the kick and that needs to go through first + // but that's VERY close.. xTEST(ptr32[&VU1.xgkickenable], 0x1); xForwardJZ32 skipxgkick; - xADD(ptr32[&VU1.xgkickcyclecount], mVUlow.kickcycles); + xADD(ptr32[&VU1.xgkickcyclecount], mVUlow.kickcycles-1); xCMP(ptr32[&VU1.xgkickcyclecount], 2); xForwardJL32 needcycles; mVUbackupRegs(mVU, true, true); xFastCall(_vuXGKICKTransfermVU, flush); mVUrestoreRegs(mVU, true, true); needcycles.SetTarget(); + xADD(ptr32[&VU1.xgkickcyclecount], 1); skipxgkick.SetTarget(); }