mirror of https://github.com/PCSX2/pcsx2.git
pcsx2: tlb: goemon implement a preload hack tlb
Tlb mapping is stored @0x3d5580 (GoemonTlb[150]) The function that will populate the tlb is around pc = 0x356250, ra = 0x33ad48 The idea is to add a callback on 0x33ad48 block that will populate the tlb based on ee mem content. Note: The hack is based on previous Virtual PS2 => Physical PS2 LUT
This commit is contained in:
parent
9452444a9f
commit
a00b8ecc55
|
@ -345,6 +345,10 @@ 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();
|
||||
}
|
||||
doBranch(cpuRegs.GPR.r[_Rs_].UL[0]);
|
||||
}
|
||||
|
||||
|
|
|
@ -423,6 +423,7 @@ extern void cpuTlbMissR(u32 addr, u32 bd);
|
|||
extern void cpuTlbMissW(u32 addr, u32 bd);
|
||||
extern void cpuTestHwInts();
|
||||
extern void cpuClearInt(uint n);
|
||||
extern __fastcall void GoemonPreloadTlb();
|
||||
|
||||
extern void cpuSetNextEvent( u32 startCycle, s32 delta );
|
||||
extern void cpuSetNextEventDelta( s32 delta );
|
||||
|
|
|
@ -43,6 +43,7 @@ static void PostLoadPrep()
|
|||
memzero(pCache);
|
||||
// WriteCP0Status(cpuRegs.CP0.n.Status.val);
|
||||
for(int i=0; i<48; i++) MapTLB(i);
|
||||
if (EmuConfig.Gamefixes.GoemonTlbHack) GoemonPreloadTlb();
|
||||
|
||||
UpdateVSyncRate();
|
||||
}
|
||||
|
|
|
@ -331,9 +331,45 @@ template void vtlb_memWrite<mem32_t>(u32 mem, mem32_t data);
|
|||
// Important recompiler note: Mid-block Exception handling isn't reliable *yet* because
|
||||
// memory ops don't flush the PC prior to invoking the indirect handlers.
|
||||
|
||||
|
||||
static void GoemonTlbMissDebug()
|
||||
{
|
||||
// 0x3d5580 is the address of the TLB cache
|
||||
GoemonTlb* tlb = (GoemonTlb*)&eeMem->Main[0x3d5580];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall GoemonPreloadTlb()
|
||||
{
|
||||
// 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].valid == 0x1 && tlb[i].low_add != tlb[i].high_add) {
|
||||
|
||||
u32 size = tlb[i].high_add - tlb[i].low_add;
|
||||
u32 vaddr = tlb[i].low_add;
|
||||
u32 paddr = tlb[i].physical_add;
|
||||
|
||||
if ((u32)vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] == 0x80000000u) {
|
||||
DevCon.WriteLn("Preload TLB[%d]: From V:0x%8.8x to P:0x%8.8x (%d pages)", i, vaddr, paddr, size >> VTLB_PAGE_BITS);
|
||||
vtlb_VMap( vaddr , paddr, size);
|
||||
vtlb_VMap(0x20000000|vaddr , paddr, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates a tlbMiss Exception
|
||||
static __ri void vtlb_Miss(u32 addr,u32 mode)
|
||||
{
|
||||
if (EmuConfig.Gamefixes.GoemonTlbHack)
|
||||
GoemonTlbMissDebug();
|
||||
|
||||
// Hack to handle expected tlb miss by some games.
|
||||
if (Cpu == &intCpu) {
|
||||
if (mode)
|
||||
|
|
15
pcsx2/vtlb.h
15
pcsx2/vtlb.h
|
@ -211,3 +211,18 @@ namespace vtlb_private
|
|||
|
||||
extern __aligned(64) MapData vtlbdata;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Goemon game fix
|
||||
// --------------------------------------------------------------------------------------
|
||||
struct GoemonTlb {
|
||||
u32 valid;
|
||||
u32 unk1; // could be physical address also
|
||||
u32 unk2;
|
||||
u32 low_add;
|
||||
u32 physical_add;
|
||||
u32 unk3; // likely the size
|
||||
u32 high_add;
|
||||
u32 unk4;
|
||||
u32 unk5;
|
||||
};
|
||||
|
|
|
@ -971,6 +971,12 @@ void SetBranchReg( u32 reg )
|
|||
_allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
|
||||
_eeMoveGPRtoR(ESI, reg);
|
||||
|
||||
if (EmuConfig.Gamefixes.GoemonTlbHack) {
|
||||
xMOV(ecx, esi);
|
||||
vtlb_DynV2P();
|
||||
xMOV(esi, eax);
|
||||
}
|
||||
|
||||
recompileNextInstruction(1);
|
||||
|
||||
if( x86regs[ESI].inuse ) {
|
||||
|
@ -1516,7 +1522,6 @@ void encodeMemcheck()
|
|||
|
||||
}
|
||||
|
||||
|
||||
void recompileNextInstruction(int delayslot)
|
||||
{
|
||||
static u8 s_bFlushReg = 1;
|
||||
|
@ -1862,6 +1867,11 @@ static void __fastcall recRecompile( const u32 startpc )
|
|||
xCALL(PreBlockCheck);
|
||||
}
|
||||
|
||||
// 0x33ad48 is the return address of the function that populate the TLB cache
|
||||
if (pc == 0x33ad48 && EmuConfig.Gamefixes.GoemonTlbHack) {
|
||||
xCALL(GoemonPreloadTlb);
|
||||
}
|
||||
|
||||
// go until the next branch
|
||||
i = startpc;
|
||||
s_nEndBlock = 0xffffffff;
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "R5900OpcodeTables.h"
|
||||
#include "iR5900.h"
|
||||
|
||||
using namespace x86Emitter;
|
||||
|
||||
namespace R5900 {
|
||||
namespace Dynarec {
|
||||
namespace OpcodeImpl
|
||||
|
@ -48,7 +50,10 @@ void recJ( void )
|
|||
// SET_FPUSTATE;
|
||||
u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 );
|
||||
recompileNextInstruction(1);
|
||||
SetBranchImm(newpc);
|
||||
if (EmuConfig.Gamefixes.GoemonTlbHack)
|
||||
SetBranchImm(vtlb_V2P(newpc));
|
||||
else
|
||||
SetBranchImm(newpc);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -69,7 +74,10 @@ void recJAL( void )
|
|||
}
|
||||
|
||||
recompileNextInstruction(1);
|
||||
SetBranchImm(newpc);
|
||||
if (EmuConfig.Gamefixes.GoemonTlbHack)
|
||||
SetBranchImm(vtlb_V2P(newpc));
|
||||
else
|
||||
SetBranchImm(newpc);
|
||||
}
|
||||
|
||||
/*********************************************************
|
||||
|
@ -89,6 +97,12 @@ void recJALR( void )
|
|||
int newpc = pc + 4;
|
||||
_allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
|
||||
_eeMoveGPRtoR(ESI, _Rs_);
|
||||
|
||||
if (EmuConfig.Gamefixes.GoemonTlbHack) {
|
||||
xMOV(ecx, esi);
|
||||
vtlb_DynV2P();
|
||||
xMOV(esi, eax);
|
||||
}
|
||||
// uncomment when there are NO instructions that need to call interpreter
|
||||
// int mmreg;
|
||||
// if( GPR_IS_CONST1(_Rs_) )
|
||||
|
|
Loading…
Reference in New Issue