Skip to content

Commit

Permalink
add ICache
Browse files Browse the repository at this point in the history
Xenogears: fixes memory card access.
Need more test determine whether it has an impact on other games
  • Loading branch information
xjsxjs197 committed Oct 16, 2022
1 parent 27c4bd1 commit 109c5c1
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 8 deletions.
2 changes: 2 additions & 0 deletions misc.c
Expand Up @@ -290,6 +290,8 @@ int LoadCdromFile(char *filename, EXE_HEADER *head) {

psxCpu->Clear(addr, size / 4);

psxRegs.ICache_valid = FALSE;

while (size & ~2047) {
incTime();
READTRACK();
Expand Down
13 changes: 11 additions & 2 deletions ppc/pR3000A.c
Expand Up @@ -1090,12 +1090,21 @@ __inline static void execute() {
char *p;

p = (char*)PC_REC(psxRegs.pc);
/*if (p != NULL)*/ recFunc = (void (**)()) (u32)p;
/*if (p != NULL)*/
/*else { recError(); return; }*/

if (*recFunc == 0) {
if (*p == 0) {
recRecompile();
}
else if (psxRegs.ICache_valid == FALSE) { // Xenogears: fixes memory card access with original BIOS (0a_44_FlushCache issue)
//psxCpu->Clear(0x0, 0x20000);
memset(recRAM, 0, 0x200000);
recRecompile();
p = (char*)PC_REC(psxRegs.pc);
psxRegs.ICache_valid = TRUE;
}
recFunc = (void (**)()) (u32)p;

recRun(*recFunc, (u32)&psxRegs, (u32)&psxM);
}

Expand Down
1 change: 1 addition & 0 deletions psxbios.c
Expand Up @@ -1322,6 +1322,7 @@ void psxBios_FlushCache() { // 44
#ifdef PSXBIOS_LOG
PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
#endif
psxRegs.ICache_valid = FALSE;

pc0 = ra;
}
Expand Down
15 changes: 10 additions & 5 deletions psxinterpreter.c
Expand Up @@ -267,7 +267,9 @@ void psxDelayTest(int reg, u32 bpc) {
u32 *code;
u32 tmp;

code = (u32 *)PSXM(bpc);
// Don't execute yet - just peek
code = Read_ICache(bpc, TRUE);

tmp = ((code == NULL) ? 0 : SWAP32(*code));
branch = 1;

Expand All @@ -291,7 +293,7 @@ __inline u32 psxBranchNoDelay(void) {
u32 *code;
u32 temp;

code = (u32 *)PSXM(psxRegs.pc);
code = Read_ICache(psxRegs.pc, TRUE);
psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
switch (_Op_) {
case 0x00: // SPECIAL
Expand Down Expand Up @@ -416,11 +418,13 @@ __inline void doBranch(u32 tar) {
branch2 = branch = 1;
branchPC = tar;

// check for branch in delay slot
// notaz: check for branch in delay slot
if (psxDelayBranchTest(tar))
return;

code = (u32 *)PSXM(psxRegs.pc);
// branch delay slot
code = Read_ICache(psxRegs.pc, TRUE);

psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));

debugI();
Expand Down Expand Up @@ -920,6 +924,7 @@ static int intInit() {
}

static void intReset() {
psxRegs.ICache_valid = FALSE;
}

static void intExecute() {
Expand Down Expand Up @@ -950,7 +955,7 @@ static void intShutdown() {

// interpreter execution
inline void execI() {
u32 *code = (u32 *)PSXM(psxRegs.pc);
u32 *code = Read_ICache(psxRegs.pc, FALSE);
psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));

debugI();
Expand Down
2 changes: 2 additions & 0 deletions psxmem.c
Expand Up @@ -363,6 +363,8 @@ void psxMemWrite32(u32 mem, u32 value) {
memset(psxMemWLUT + 0x0000, 0, 0x80 * sizeof(void *));
memset(psxMemWLUT + 0x8000, 0, 0x80 * sizeof(void *));
memset(psxMemWLUT + 0xa000, 0, 0x80 * sizeof(void *));

psxRegs.ICache_valid = FALSE;
break;
case 0x00: case 0x1e988:
if (writeok == 1) break;
Expand Down
9 changes: 8 additions & 1 deletion r3000a.c
Expand Up @@ -253,11 +253,18 @@ inline void psxTestHWInts() {
if (*((u32*)psxHAddr(0x1070)) & *((u32*)psxHAddr(0x1074))) {
// upd xjsxjs197 end
if ((psxRegs.CP0.n.Status & 0x401) == 0x401) {
u32 opcode;

// Crash Bandicoot 2: Don't run exceptions when GTE in pipeline
opcode = SWAP32(*Read_ICache(psxRegs.pc, TRUE));
if( ((opcode >> 24) & 0xfe) != 0x4a ) {
psxException(0x400, 0);
}
#ifdef PSXCPU_LOG
PSXCPU_LOG("Interrupt: %x %x\n", psxHu32(0x1070), psxHu32(0x1074));
#endif
// SysPrintf("Interrupt (%x): %x %x\n", psxRegs.cycle, psxHu32(0x1070), psxHu32(0x1074));
psxException(0x400, 0);
//psxException(0x400, 0);
}
}
}
Expand Down
77 changes: 77 additions & 0 deletions r3000a.h
Expand Up @@ -135,10 +135,87 @@ typedef struct {
u32 interrupt;
//u32 intCycle[32];
struct { u32 sCycle, cycle; } intCycle[32];
u8 ICache_Addr[0x1000];
u8 ICache_Code[0x1000];
bool ICache_valid;
} psxRegisters;

extern psxRegisters psxRegs;

/*
Formula One 2001
- Use old CPU cache code when the RAM location is
updated with new code (affects in-game racing)
TODO:
- I-cache / D-cache swapping
- Isolate D-cache from RAM
*/

static inline u32 *Read_ICache(u32 pc, bool isolate) {
u32 pc_bank, pc_offset, pc_cache;
u8 *IAddr, *ICode;

pc_bank = pc >> 24;
pc_offset = pc & 0xffffff;
pc_cache = pc & 0xfff;

IAddr = psxRegs.ICache_Addr;
ICode = psxRegs.ICache_Code;

// clear I-cache
if (!psxRegs.ICache_valid) {
memset(psxRegs.ICache_Addr, 0xff, sizeof(psxRegs.ICache_Addr));
memset(psxRegs.ICache_Code, 0xff, sizeof(psxRegs.ICache_Code));

psxRegs.ICache_valid = TRUE;
}

// uncached
if (pc_bank >= 0xa0)
return (u32 *)PSXM(pc);

// cached - RAM
if (pc_bank == 0x80 || pc_bank == 0x00) {
if (SWAP32(*(u32 *)(IAddr + pc_cache)) == pc_offset) {
// Cache hit - return last opcode used
return (u32 *)(ICode + pc_cache);
} else {
// Cache miss - addresses don't match
// - default: 0xffffffff (not init)

if (!isolate) {
// cache line is 4 bytes wide
pc_offset &= ~0xf;
pc_cache &= ~0xf;

// address line
*(u32 *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0);
*(u32 *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4);
*(u32 *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8);
*(u32 *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc);

// opcode line
pc_offset = pc & ~0xf;
*(u32 *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0);
*(u32 *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4);
*(u32 *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8);
*(u32 *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc);
}

// normal code
return (u32 *)PSXM(pc);
}
}

/*
TODO: Probably should add cached BIOS
*/

// default
return (u32 *)PSXM(pc);
}

enum {
PSXINT_SIO = 0,
PSXINT_CDR,
Expand Down

0 comments on commit 109c5c1

Please sign in to comment.