diff --git a/pcsx2/Interpreter.cpp b/pcsx2/Interpreter.cpp index ab7e9a07a3..4dfc56b4ce 100644 --- a/pcsx2/Interpreter.cpp +++ b/pcsx2/Interpreter.cpp @@ -254,6 +254,11 @@ void J() void JAL() { + // 0x3563b8 is the start address of the function that invalidate entry in TLB cache + if (EmuConfig.Gamefixes.GoemonTlbHack) { + if (_JumpTarget_ == 0x3563b8) + GoemonUnloadTlb(cpuRegs.GPR.n.a0.UL[0]); + } _SetLink(31); doBranch(_JumpTarget_); } @@ -456,8 +461,9 @@ void BGEZALL() // Branch if Rs >= 0 and link void JR() { // 0x33ad48 is the return address of the function that populate the TLB cache - if (cpuRegs.GPR.r[_Rs_].UL[0] == 0x33ad48 && EmuConfig.Gamefixes.GoemonTlbHack) { - GoemonPreloadTlb(); + if (EmuConfig.Gamefixes.GoemonTlbHack) { + if (cpuRegs.GPR.r[_Rs_].UL[0] == 0x33ad48) + GoemonPreloadTlb(); } doBranch(cpuRegs.GPR.r[_Rs_].UL[0]); } diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index cd027895a2..1b8057e0a4 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -430,6 +430,7 @@ extern void cpuTlbMissW(u32 addr, u32 bd); extern void cpuTestHwInts(); extern void cpuClearInt(uint n); extern void __fastcall GoemonPreloadTlb(); +extern void __fastcall GoemonUnloadTlb(u32 key); extern void cpuSetNextEvent( u32 startCycle, s32 delta ); extern void cpuSetNextEventDelta( s32 delta ); diff --git a/pcsx2/vtlb.cpp b/pcsx2/vtlb.cpp index da746654b9..6c08b2e119 100644 --- a/pcsx2/vtlb.cpp +++ b/pcsx2/vtlb.cpp @@ -339,7 +339,7 @@ static void GoemonTlbMissDebug() for (u32 i = 0; i < 150; i++) { if (tlb[i].valid == 0x1 && tlb[i].low_add != tlb[i].high_add) - DevCon.WriteLn("Entry %d is valid. From V:0x%8.8x to V:0x%8.8x (P:0x%8.8x)", i, tlb[i].low_add, tlb[i].high_add, tlb[i].physical_add); + DevCon.WriteLn("GoemonTlbMissDebug: Entry %d is valid. Key %x. From V:0x%8.8x to V:0x%8.8x (P:0x%8.8x)", i, tlb[i].key, tlb[i].low_add, tlb[i].high_add, tlb[i].physical_add); } } @@ -356,7 +356,7 @@ void __fastcall GoemonPreloadTlb() u32 paddr = tlb[i].physical_add; if ((uptr)vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] == POINTER_SIGN_BIT) { - DevCon.WriteLn("Preload TLB[%d]: From V:0x%8.8x to P:0x%8.8x (%d pages)", i, vaddr, paddr, size >> VTLB_PAGE_BITS); + DevCon.WriteLn("GoemonPreloadTlb: Entry %d. Key %x. From V:0x%8.8x to P:0x%8.8x (%d pages)", i, tlb[i].key, vaddr, paddr, size >> VTLB_PAGE_BITS); vtlb_VMap( vaddr , paddr, size); vtlb_VMap(0x20000000|vaddr , paddr, size); } @@ -364,6 +364,33 @@ void __fastcall GoemonPreloadTlb() } } +void __fastcall GoemonUnloadTlb(u32 key) +{ + // 0x3d5580 is the address of the TLB cache table + GoemonTlb* tlb = (GoemonTlb*)&eeMem->Main[0x3d5580]; + for (u32 i = 0; i < 150; i++) { + if (tlb[i].key == key) { + if (tlb[i].valid == 0x1) { + DevCon.WriteLn("GoemonUnloadTlb: Entry %d. Key %x. From V:0x%8.8x to V:0x%8.8x (P:0x%8.8x)", i, tlb[i].key, tlb[i].low_add, tlb[i].high_add, tlb[i].physical_add); + u32 size = tlb[i].high_add - tlb[i].low_add; + u32 vaddr = tlb[i].low_add; + + vtlb_VMapUnmap( vaddr , size); + vtlb_VMapUnmap(0x20000000|vaddr , size); + + // Unmap the tlb in game cache table + // Note: Game copy FEFEFEFE for others data + tlb[i].valid = 0; + tlb[i].key = 0xFEFEFEFE; + tlb[i].low_add = 0xFEFEFEFE; + tlb[i].high_add = 0xFEFEFEFE; + } else { + DevCon.Error("GoemonUnloadTlb: Entry is not valid"); + } + } + } +} + // Generates a tlbMiss Exception static __ri void vtlb_Miss(u32 addr,u32 mode) { diff --git a/pcsx2/vtlb.h b/pcsx2/vtlb.h index 1e10a88103..13917b18cd 100644 --- a/pcsx2/vtlb.h +++ b/pcsx2/vtlb.h @@ -225,6 +225,6 @@ struct GoemonTlb { u32 physical_add; u32 unk3; // likely the size u32 high_add; - u32 unk4; + u32 key; // uniq number attached to an allocation u32 unk5; };