From 2405813165a8259d501406d91c3d3161972db9ec Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 29 Nov 2021 23:35:08 +0200 Subject: [PATCH] drc: rearrange hacks Also adds PE2 hack. PE2 probably checks if a frame didn't take too long to complete by comparing counter 2 to a hardcoded value. If it did exceed the limit it restarts all the processing, probably assuming that the GPU was busy that time and retrying on next frame would work out? Still it will hang if not enough cycles are available, regardless of how root counters are handled, and currently won't work on the interpreter even with root counter hack because of recently added stalls. PCSX's timing is just too wrong all over the place... --- frontend/menu.c | 13 +++-- libpcsxcore/database.c | 1 + libpcsxcore/new_dynarec/new_dynarec.c | 73 +++++++++++++++++---------- libpcsxcore/new_dynarec/new_dynarec.h | 1 + 4 files changed, 58 insertions(+), 30 deletions(-) diff --git a/frontend/menu.c b/frontend/menu.c index f5d035a0..85f7b7f9 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -1555,6 +1555,7 @@ static int menu_loop_plugin_options(int id, int keys) #ifndef DRC_DISABLE static const char h_cfg_psxclk[] = "Over/under-clock the PSX, default is " DEFAULT_PSX_CLOCK_S "\n" "(lower value - less work for the emu, may be faster)"; +static const char h_cfg_noch[] = "Disables game-specific compatibility hacks"; static const char h_cfg_nosmc[] = "Will cause crashes when loading, break memcards"; static const char h_cfg_gteunn[] = "May cause graphical glitches"; static const char h_cfg_gteflgs[] = "Will cause graphical glitches"; @@ -1565,6 +1566,7 @@ static menu_entry e_menu_speed_hacks[] = { #ifndef DRC_DISABLE mee_range_h ("PSX CPU clock, %%", 0, psx_clock, 1, 500, h_cfg_psxclk), + mee_onoff_h ("Disable compat hacks", 0, new_dynarec_hacks, NDHACK_NO_COMPAT_HACKS, h_cfg_noch), mee_onoff_h ("Disable SMC checks", 0, new_dynarec_hacks, NDHACK_NO_SMC_CHECK, h_cfg_nosmc), mee_onoff_h ("Assume GTE regs unneeded", 0, new_dynarec_hacks, NDHACK_GTE_UNNEEDED, h_cfg_gteunn), mee_onoff_h ("Disable GTE flags", 0, new_dynarec_hacks, NDHACK_GTE_NO_FLAGS, h_cfg_gteflgs), @@ -1589,11 +1591,12 @@ static const char h_cfg_cdda[] = "Disable CD Audio for a performance boost\n" "(proper .cue/.bin dump is needed otherwise)"; //static const char h_cfg_sio[] = "You should not need this, breaks games"; static const char h_cfg_spuirq[] = "Compatibility tweak; should be left off"; -//static const char h_cfg_rcnt1[] = "Parasite Eve 2, Vandal Hearts 1/2 Fix\n" -// "(timing hack, breaks other games)"; static const char h_cfg_rcnt2[] = "InuYasha Sengoku Battle Fix\n" "(timing hack, breaks other games)"; -#ifndef DRC_DISABLE +#ifdef DRC_DISABLE +static const char h_cfg_rcnt1[] = "Parasite Eve 2, Vandal Hearts 1/2 Fix\n" + "(timing hack, breaks other games)"; +#else static const char h_cfg_nodrc[] = "Disable dynamic recompiler and use interpreter\n" "Might be useful to overcome some dynarec bugs"; #endif @@ -1610,7 +1613,9 @@ static menu_entry e_menu_adv_options[] = //mee_onoff_h ("SIO IRQ Always Enabled", 0, Config.Sio, 1, h_cfg_sio), mee_onoff_h ("SPU IRQ Always Enabled", 0, Config.SpuIrq, 1, h_cfg_spuirq), mee_onoff_h ("ICache emulation", 0, Config.icache_emulation, 1, h_cfg_icache), - //mee_onoff_h ("Rootcounter hack", 0, Config.RCntFix, 1, h_cfg_rcnt1), +#ifdef DRC_DISABLE + mee_onoff_h ("Rootcounter hack", 0, Config.RCntFix, 1, h_cfg_rcnt1), +#endif mee_onoff_h ("Rootcounter hack 2", 0, Config.VSyncWA, 1, h_cfg_rcnt2), #ifndef DRC_DISABLE mee_onoff_h ("Disable dynarec (slow!)",0, Config.Cpu, 1, h_cfg_nodrc), diff --git a/libpcsxcore/database.c b/libpcsxcore/database.c index 4d4439ad..61312e09 100644 --- a/libpcsxcore/database.c +++ b/libpcsxcore/database.c @@ -36,6 +36,7 @@ void Apply_Hacks_Cdrom() /* Dynarec game-specific hacks */ new_dynarec_hacks_pergame = 0; + cycle_multiplier_override = 0; /* Internal Section is fussy about timings */ if (strcmp(CdromId, "SLPS01868") == 0) diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index f1005db8..27d9d469 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -121,8 +121,8 @@ struct regstat uint64_t wasdirty; uint64_t dirty; uint64_t u; - u_int wasconst; - u_int isconst; + u_int wasconst; // before; for example 'lw r2, (r2)' wasconst is true + u_int isconst; // ... but isconst is false when r2 is known u_int loadedconst; // host regs that have constants loaded u_int waswritten; // MIPS regs that were used as store base before }; @@ -468,12 +468,12 @@ static void do_clear_cache(void) int cycle_multiplier = CYCLE_MULT_DEFAULT; // 100 for 1.0 int cycle_multiplier_override; int cycle_multiplier_old; +static int cycle_multiplier_active; static int CLOCK_ADJUST(int x) { - int m = cycle_multiplier_override && cycle_multiplier == CYCLE_MULT_DEFAULT - ? cycle_multiplier_override : cycle_multiplier; - int s=(x>>31)|1; + int m = cycle_multiplier_active; + int s = (x >> 31) | 1; return (x * m + s * 50) / 100; } @@ -4122,6 +4122,7 @@ static int assemble(int i, const struct regstat *i_regs, int ccadj_) case SPAN: pagespan_assemble(i, i_regs); break; + case NOP: case OTHER: case NI: // not handled, just skip @@ -6906,9 +6907,6 @@ void new_dynarec_cleanup(void) static u_int *get_source_start(u_int addr, u_int *limit) { - if (!HACK_ENABLED(NDHACK_OVERRIDE_CYCLE_M)) - cycle_multiplier_override = 0; - if (addr < 0x00200000 || (0xa0000000 <= addr && addr < 0xa0200000)) { @@ -6923,7 +6921,7 @@ static u_int *get_source_start(u_int addr, u_int *limit) // BIOS. The multiplier should be much higher as it's uncached 8bit mem, // but timings in PCSX are too tied to the interpreter's BIAS if (!HACK_ENABLED(NDHACK_OVERRIDE_CYCLE_M)) - cycle_multiplier_override = 200; + cycle_multiplier_active = 200; *limit = (addr & 0xfff00000) | 0x80000; return (u_int *)((u_char *)psxR + (addr&0x7ffff)); @@ -7035,6 +7033,42 @@ void new_dynarec_load_blocks(const void *save, int size) memcpy(&psxRegs.GPR, regs_save, sizeof(regs_save)); } +static void apply_hacks(void) +{ + int i; + if (HACK_ENABLED(NDHACK_NO_COMPAT_HACKS)) + return; + /* special hack(s) */ + for (i = 0; i < slen - 4; i++) + { + // lui a4, 0xf200; jal ; addu a0, 2; slti v0, 28224 + if (source[i] == 0x3c04f200 && dops[i+1].itype == UJUMP + && source[i+2] == 0x34840002 && dops[i+3].opcode == 0x0a + && imm[i+3] == 0x6e40 && dops[i+3].rs1 == 2) + { + SysPrintf("PE2 hack @%08x\n", start + (i+3)*4); + dops[i + 3].itype = NOP; + } + } + i = slen; + if (i > 10 && source[i-1] == 0 && source[i-2] == 0x03e00008 + && source[i-4] == 0x8fbf0018 && source[i-6] == 0x00c0f809 + && dops[i-7].itype == STORE) + { + i = i-8; + if (dops[i].itype == IMM16) + i--; + // swl r2, 15(r6); swr r2, 12(r6); sw r6, *; jalr r6 + if (dops[i].itype == STORELR && dops[i].rs1 == 6 + && dops[i-1].itype == STORELR && dops[i-1].rs1 == 6) + { + SysPrintf("F1 hack from %08x\n", start); + if (f1_hack == 0) + f1_hack = ~0u; + } + } +} + int new_recompile_block(u_int addr) { u_int pagelimit = 0; @@ -7092,6 +7126,9 @@ int new_recompile_block(u_int addr) return 0; } + cycle_multiplier_active = cycle_multiplier_override && cycle_multiplier == CYCLE_MULT_DEFAULT + ? cycle_multiplier_override : cycle_multiplier; + source = get_source_start(start, &pagelimit); if (source == NULL) { SysPrintf("Compile at bogus memory address: %08x\n", addr); @@ -7613,23 +7650,7 @@ int new_recompile_block(u_int addr) } assert(slen>0); - /* spacial hack(s) */ - if (i > 10 && source[i-1] == 0 && source[i-2] == 0x03e00008 - && source[i-4] == 0x8fbf0018 && source[i-6] == 0x00c0f809 - && dops[i-7].itype == STORE) - { - i = i-8; - if (dops[i].itype == IMM16) - i--; - // swl r2, 15(r6); swr r2, 12(r6); sw r6, *; jalr r6 - if (dops[i].itype == STORELR && dops[i].rs1 == 6 - && dops[i-1].itype == STORELR && dops[i-1].rs1 == 6) - { - SysPrintf("F1 hack from %08x\n", start); - if (f1_hack == 0) - f1_hack = ~0u; - } - } + apply_hacks(); /* Pass 2 - Register dependencies and branch targets */ diff --git a/libpcsxcore/new_dynarec/new_dynarec.h b/libpcsxcore/new_dynarec/new_dynarec.h index f1464696..8991faca 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.h +++ b/libpcsxcore/new_dynarec/new_dynarec.h @@ -15,6 +15,7 @@ extern int cycle_multiplier_old; #define NDHACK_GTE_NO_FLAGS (1<<2) #define NDHACK_OVERRIDE_CYCLE_M (1<<3) #define NDHACK_NO_STALLS (1<<4) +#define NDHACK_NO_COMPAT_HACKS (1<<5) extern int new_dynarec_hacks; extern int new_dynarec_hacks_pergame; extern int new_dynarec_hacks_old; -- 2.39.2