microVU: Consolidate I-bit hacks in to one generic one

This commit is contained in:
refractionpcsx2 2021-06-08 18:42:55 +01:00
parent 4116aed738
commit 973ebd153d
6 changed files with 42 additions and 61 deletions

View File

@ -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"

View File

@ -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

View File

@ -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 );
}

View File

@ -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
},
{

View File

@ -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<microProgram*>::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];

View File

@ -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<microRange>*& 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<microRange>::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<microRange>::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: