From 973ebd153d340a4d7035ba0237ca967c4d2219f4 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Tue, 8 Jun 2021 18:42:55 +0100 Subject: [PATCH] microVU: Consolidate I-bit hacks in to one generic one --- bin/GameIndex.yaml | 18 ++++++------- pcsx2/Config.h | 6 ++--- pcsx2/Pcsx2Config.cpp | 12 +++------ pcsx2/gui/Panels/GameFixesPanel.cpp | 6 +---- pcsx2/x86/microVU.cpp | 22 ++-------------- pcsx2/x86/microVU_Compile.inl | 39 ++++++++++++++++++----------- 6 files changed, 42 insertions(+), 61 deletions(-) diff --git a/bin/GameIndex.yaml b/bin/GameIndex.yaml index 9c5eaa5531..0643b3094d 100644 --- a/bin/GameIndex.yaml +++ b/bin/GameIndex.yaml @@ -12684,7 +12684,7 @@ SLES-53439: name: "Crash Tag Team Racing" region: "PAL-M6" gameFixes: - - CrashTagTeamRacingIbitHack # Fixes constant recompilation problems. + - IbitHack # Fixes constant recompilation problems. SLES-53441: name: "Heroes of the Pacific" region: "PAL-M5" @@ -14329,17 +14329,17 @@ SLES-54182: name: "Scarface - The World is Yours" region: "PAL-M4" gameFixes: - - ScarfaceIbitHack + - IbitHack SLES-54183: name: "Scarface - The World is Yours" region: "PAL-G" gameFixes: - - ScarfaceIbitHack + - IbitHack SLES-54184: name: "Scarface - The World is Yours" region: "PAL-R" gameFixes: - - ScarfaceIbitHack + - IbitHack SLES-54185: name: "Dirge of Cerberus - Final Fantasy VII" region: "PAL-M5" @@ -14509,7 +14509,7 @@ SLES-54271: name: "Scarface - The World is Yours" region: "PAL-E" gameFixes: - - ScarfaceIbitHack + - IbitHack SLES-54305: name: "Demon Chaos" region: "PAL-M5" @@ -15040,7 +15040,7 @@ SLES-54534: name: "Scarface - The World is Yours [Collector's Edition]" region: "PAL-E" gameFixes: - - ScarfaceIbitHack + - IbitHack SLES-54536: name: "Big Idea's VeggieTales - LarryBoy and the Bad Apple" region: "PAL-I" @@ -35827,7 +35827,7 @@ SLUS-21111: region: "NTSC-U" compat: 5 gameFixes: - - ScarfaceIbitHack + - IbitHack SLUS-21112: name: "L.A. Rush" region: "NTSC-U" @@ -36162,7 +36162,7 @@ SLUS-21191: region: "NTSC-U" compat: 5 gameFixes: - - CrashTagTeamRacingIbitHack # Fixes constant recompilation problems. + - IbitHack # Fixes constant recompilation problems. SLUS-21192: name: "Cabela's Outdoor Adventures 2006" region: "NTSC-U" @@ -37576,7 +37576,7 @@ SLUS-21492: region: "NTSC-U" compat: 5 gameFixes: - - ScarfaceIbitHack + - IbitHack SLUS-21493: name: "Need for Speed - Carbon" region: "NTSC-U" diff --git a/pcsx2/Config.h b/pcsx2/Config.h index c8c3c962ef..27f52a3d41 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -40,8 +40,7 @@ enum GamefixId Fix_VIF1Stall, Fix_GIFFIFO, Fix_GoemonTlbMiss, - Fix_ScarfaceIbit, - Fix_CrashTagTeamIbit, + Fix_Ibit, Fix_VU0Kickstart, GamefixId_COUNT @@ -350,8 +349,7 @@ struct Pcsx2Config VIF1StallHack : 1, // Like above, processes FIFO data before the stall is allowed (to make sure data goes over). GIFFIFOHack : 1, // Enabled the GIF FIFO (more correct but slower) GoemonTlbHack : 1, // Gomeon tlb miss hack. The game need to access unmapped virtual address. Instead to handle it as exception, tlb are preloaded at startup - ScarfaceIbit : 1, // Scarface I bit hack. Needed to stop constant VU recompilation - CrashTagTeamRacingIbit : 1, // Crash Tag Team Racing I bit hack. Needed to stop constant VU recompilation + IbitHack : 1, // I bit hack. Needed to stop constant VU recompilation in some games VU0KickstartHack : 1; // Speed up VU0 at start of program to avoid some VU1 sync issues BITFIELD_END diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index a2b11378ad..162f0b620b 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -285,8 +285,7 @@ const wxChar *const tbl_GamefixNames[] = L"VIF1Stall", L"GIFFIFO", L"GoemonTlb", - L"ScarfaceIbit", - L"CrashTagTeamRacingIbit", + L"Ibit", L"VU0Kickstart" }; @@ -347,8 +346,7 @@ void Pcsx2Config::GamefixOptions::Set( GamefixId id, bool enabled ) case Fix_VIF1Stall: VIF1StallHack = enabled; break; case Fix_GIFFIFO: GIFFIFOHack = enabled; break; case Fix_GoemonTlbMiss: GoemonTlbHack = enabled; break; - case Fix_ScarfaceIbit: ScarfaceIbit = enabled; break; - case Fix_CrashTagTeamIbit: CrashTagTeamRacingIbit = enabled; break; + case Fix_Ibit: IbitHack = enabled; break; case Fix_VU0Kickstart: VU0KickstartHack = enabled; break; jNO_DEFAULT; } @@ -372,8 +370,7 @@ bool Pcsx2Config::GamefixOptions::Get( GamefixId id ) const case Fix_VIF1Stall: return VIF1StallHack; case Fix_GIFFIFO: return GIFFIFOHack; case Fix_GoemonTlbMiss: return GoemonTlbHack; - case Fix_ScarfaceIbit: return ScarfaceIbit; - case Fix_CrashTagTeamIbit: return CrashTagTeamRacingIbit; + case Fix_Ibit: return IbitHack; case Fix_VU0Kickstart: return VU0KickstartHack; jNO_DEFAULT; } @@ -397,8 +394,7 @@ void Pcsx2Config::GamefixOptions::LoadSave( IniInterface& ini ) IniBitBool( VIF1StallHack ); IniBitBool( GIFFIFOHack ); IniBitBool( GoemonTlbHack ); - IniBitBool( ScarfaceIbit ); - IniBitBool( CrashTagTeamRacingIbit ); + IniBitBool( IbitHack ); IniBitBool( VU0KickstartHack ); } diff --git a/pcsx2/gui/Panels/GameFixesPanel.cpp b/pcsx2/gui/Panels/GameFixesPanel.cpp index 00eae4e797..3bcb286eb3 100644 --- a/pcsx2/gui/Panels/GameFixesPanel.cpp +++ b/pcsx2/gui/Panels/GameFixesPanel.cpp @@ -93,11 +93,7 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent ) wxEmptyString }, { - _("VU I bit Hack avoid constant recompilation (Scarface The World Is Yours)"), - wxEmptyString - }, - { - _("VU I bit Hack avoid constant recompilation (Crash Tag Team Racing)"), + _("VU I bit Hack avoid constant recompilation in some games (Scarface The World Is Yours, Crash Tag Team Racing)"), wxEmptyString }, { diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index f5db622152..a98c10727b 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -250,7 +250,7 @@ __fi bool mVUcmpProg(microVU& mVU, microProgram& prog, const bool cmpWholeProg) for (const auto& range : *prog.ranges) { auto cmpOffset = [&](void* x) { return (u8*)x + range.start; }; if ((range.start < 0) || (range.end < 0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU.index, range.start, range.end); } - if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU.regs().Micro), ((range.end+8) - range.start))) { + if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU.regs().Micro), (range.end - range.start))) { return false; } } @@ -271,25 +271,7 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) { std::deque::iterator it(list->begin()); for ( ; it != list->end(); ++it) { bool b = mVUcmpProg(mVU, *it[0], 0); - if (EmuConfig.Gamefixes.ScarfaceIbit) { - if (isVU1 && ((((u32*)mVU.regs().Micro)[startPC / 4 + 1]) == 0x80200118) && - ((((u32*)mVU.regs().Micro)[startPC / 4 + 3]) == 0x81000062)) { - b = true; - mVU.prog.cleared = 0; - mVU.prog.cur = it[0]; - mVU.prog.isSame = 1; - } - } else if (EmuConfig.Gamefixes.CrashTagTeamRacingIbit) { - // Crash tag team tends to make changes to the I register settings in the addresses 0x2bd0 - 0x3ff8 - // so detect when the code is only changed in this region and don't recompile. Use the same Scarface hack - // to access the new I regsiter settings (Look at doIbit() in microVU_Compile.inl - if (isVU1 && (memcmp_mmx((u8 *)(it[0]->data), (u8 *)(mVU.regs().Micro), 0x2bd0) == 0)) { - b = true; - mVU.prog.cleared = 0; - mVU.prog.cur = it[0]; - mVU.prog.isSame = 1; - } - } + if (b) { quick.block = it[0]->block[startPC/8]; quick.prog = it[0]; diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 42ec1cded3..aec138a0c8 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -44,19 +44,23 @@ __fi void mVUcheckIsSame(mV) { // Sets up microProgram PC ranges based on whats been recompiled void mVUsetupRange(microVU& mVU, s32 pc, bool isStartPC) { std::deque*& ranges = mVUcurProg.ranges; - pc &= mVU.microMemSize - 8; - + pxAssertDev(pc <= mVU.microMemSize, pxsFmt("microVU%d: PC outside of VU memory PC=0x%04x", mVU.index, pc)); if (isStartPC) { // Check if startPC is already within a block we've recompiled std::deque::const_iterator it(ranges->begin()); for ( ; it != ranges->end(); ++it) { if ((pc >= it[0].start) && (pc <= it[0].end)) { if (it[0].start != it[0].end) - return; // Last case makes sure its not a 1-opcode EvilBlock + { + microRange mRange = { it[0].start, it[0].end }; + ranges->erase(it); + ranges->push_front(mRange); + return; // new start PC is inside the range of another range + } } } } - else if (mVUrange.end != -1) { - // Above case was true + else if (mVUrange.end >= pc) { + // existing range covers more area than current PC so no need to process it return; } @@ -75,23 +79,22 @@ void mVUsetupRange(microVU& mVU, s32 pc, bool isStartPC) { std::deque::iterator it(ranges->begin()); for (++it; it != ranges->end(); ++it) { if((it[0].start >= rStart) && (it[0].start <= rEnd)) { // Starts after this prog but starts before the end of current prog - it[0].end = std::max(it[0].end, rEnd); // Extend the end of this prog to match this program + it[0].start = std::min(it[0].start, rStart); // Choose the earlier start mergedRange = true; } // Make sure we check both as the start on the other one may be later, we don't want to delete that if ((it[0].end >= rStart) && (it[0].end <= rEnd)) { // Ends after this prog starts but ends before this one ends - it[0].start = std::min(it[0].start, rStart); // Choose the earlier start + it[0].end = std::max(it[0].end, rEnd); // Extend the end of this prog to match this program mergedRange = true; } } if (mergedRange) { - //DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Merging", mVU.index); ranges->erase(ranges->begin()); } } else { - DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Wrap [%04x] [%d]", mVU.index, mVUrange.start, mVUrange.end); mVUrange.end = mVU.microMemSize; + DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Wrap [%04x] [%d]", mVU.index, mVUrange.start, mVUrange.end); microRange mRange = {0, pc}; ranges->push_front(mRange); } @@ -109,7 +112,7 @@ void doIbit(mV) { if (mVUup.iBit) { incPC(-1); mVU.regAlloc->clearRegVF(33); - if (EmuConfig.Gamefixes.ScarfaceIbit || EmuConfig.Gamefixes.CrashTagTeamRacingIbit) { + if (EmuConfig.Gamefixes.IbitHack) { xMOV(gprT1, ptr32[&curI]); xMOV(ptr32[&mVU.getVI(REG_I)], gprT1); } @@ -580,6 +583,11 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) if (curI & _Ibit_) { mVUlow.isNOP = true; mVUup.iBit = true; + if (EmuConfig.Gamefixes.IbitHack) { + mVUsetupRange(mVU, xPC, false); + if (branch < 2) + mVUsetupRange(mVU, xPC+8, true); // Ideally we'd do +4 but the mmx compare only works in 64bits, this should be fine + } } else { incPC(-1); @@ -675,8 +683,8 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) for (size_t i = 0; i < (sizeof(microRegInfo) - 4) / 4; i++, lpS++, cpS++) { xMOV(ptr32[lpS], cpS[0]); } - mVUsetupRange(mVU, xPC, false); incPC(2); + mVUsetupRange(mVU, xPC, false); mVUendProgram(mVU, &mFC, 0); normBranchCompile(mVU, xPC); incPC(-2); @@ -689,7 +697,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) } if (isEvilBlock) { - mVUsetupRange(mVU, xPC, false); + mVUsetupRange(mVU, xPC+8, false); normJumpCompile(mVU, mFC, true); goto perf_and_return; } @@ -697,15 +705,16 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) // Handle range wrapping if ((xPC + 8) == mVU.microMemSize) { - mVUsetupRange(mVU, xPC, false); + mVUsetupRange(mVU, xPC+8, false); mVUsetupRange(mVU, 0, 1); } incPC(1); } else { + incPC(1); mVUsetupRange(mVU, xPC, false); mVUdebugPrintBlocks(mVU, true); - incPC(-3); // Go back to branch opcode + incPC(-4); // Go back to branch opcode switch (mVUlow.branch) { case 1: // B/BAL @@ -742,7 +751,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) } // E-bit End - mVUsetupRange(mVU, xPC - 8, false); + mVUsetupRange(mVU, xPC, false); mVUendProgram(mVU, &mFC, 1); perf_and_return: