drc: add a hack for f1 games
authornotaz <notasas@gmail.com>
Wed, 24 Nov 2021 19:17:47 +0000 (21:17 +0200)
committernotaz <notasas@gmail.com>
Wed, 24 Nov 2021 19:17:47 +0000 (21:17 +0200)
Quite fragile but maybe good enough.

What the games do seems to be deliberate to break emulators. It takes
the address of some internal function (let's call it f1) and calculates
an address add2 in such a way that f1 can't evict code at addr2. It then
writes a 4 instruction code piece f2 that just loads an address from
stack (which happens to be stacked ra) and jumps to it. f1 then gets
called, loads data (?) and overwrites f2 doing it and returns. Right
after that f2 gets called again.

libpcsxcore/new_dynarec/assem_arm.c
libpcsxcore/new_dynarec/assem_arm64.c
libpcsxcore/new_dynarec/linkage_arm64.S
libpcsxcore/new_dynarec/new_dynarec.c

index 4ff1afd..c7bd5cc 100644 (file)
@@ -441,6 +441,13 @@ static void emit_add(int rs1,int rs2,int rt)
   output_w32(0xe0800000|rd_rn_rm(rt,rs1,rs2));
 }
 
+static void emit_adds(int rs1,int rs2,int rt)
+{
+  assem_debug("adds %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  output_w32(0xe0900000|rd_rn_rm(rt,rs1,rs2));
+}
+#define emit_adds_ptr emit_adds
+
 static void emit_adcs(int rs1,int rs2,int rt)
 {
   assem_debug("adcs %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
@@ -1160,6 +1167,13 @@ static void emit_readword_dualindexedx4(int rs1, int rs2, int rt)
   assem_debug("ldr %s,%s,%s lsl #2\n",regname[rt],regname[rs1],regname[rs2]);
   output_w32(0xe7900000|rd_rn_rm(rt,rs1,rs2)|0x100);
 }
+#define emit_readptr_dualindexedx_ptrlen emit_readword_dualindexedx4
+
+static void emit_ldr_dualindexed(int rs1, int rs2, int rt)
+{
+  assem_debug("ldr %s,%s,%s\n",regname[rt],regname[rs1],regname[rs2]);
+  output_w32(0xe7900000|rd_rn_rm(rt,rs1,rs2));
+}
 
 static void emit_ldrcc_dualindexed(int rs1, int rs2, int rt)
 {
@@ -1253,6 +1267,7 @@ static void emit_readword(void *addr, int rt)
   assem_debug("ldr %s,fp+%d\n",regname[rt],offset);
   output_w32(0xe5900000|rd_rn_rm(rt,FP,0)|offset);
 }
+#define emit_readptr emit_readword
 
 static void emit_writeword_indexed(int rt, int offset, int rs)
 {
index ea1b8a3..63c6866 100644 (file)
@@ -330,6 +330,7 @@ static void emit_adds64(u_int rs1, u_int rs2, u_int rt)
   assem_debug("adds %s,%s,%s\n",regname64[rt],regname64[rs1],regname64[rs2]);
   output_w32(0xab000000 | rm_rn_rd(rs2, rs1, rt));
 }
+#define emit_adds_ptr emit_adds64
 
 static void emit_neg(u_int rs, u_int rt)
 {
@@ -434,6 +435,7 @@ static void emit_readdword(void *addr, u_int rt)
   else
     abort();
 }
+#define emit_readptr emit_readdword
 
 static void emit_readshword(void *addr, u_int rt)
 {
@@ -1047,6 +1049,7 @@ static void emit_readdword_dualindexedx8(u_int rs1, u_int rs2, u_int rt)
   assem_debug("ldr %s, [%s,%s, uxtw #3]\n",regname64[rt],regname64[rs1],regname[rs2]);
   output_w32(0xf8605800 | rm_rn_rd(rs2, rs1, rt));
 }
+#define emit_readptr_dualindexedx_ptrlen emit_readdword_dualindexedx8
 
 static void emit_ldrb_dualindexed(u_int rs1, u_int rs2, u_int rt)
 {
index 249fecb..6f32fa3 100644 (file)
 #include "assem_arm64.h"
 #include "linkage_offsets.h"
 
+#if (LO_mem_wtab & 7)
+#error misligned pointers
+#endif
+
 .bss
        .align  4
        .global dynarec_local
index 7e9fa1e..a8fdf47 100644 (file)
@@ -225,6 +225,7 @@ static struct decoded_insn
   static void *copy;
   static int expirep;
   static u_int stop_after_jal;
+  static u_int f1_hack; // 0 - off, ~0 - capture address, else addr
 #ifndef RAM_FIXED
   static uintptr_t ram_offset;
 #else
@@ -6700,6 +6701,7 @@ void new_dynarec_clear_full(void)
   literalcount=0;
   stop_after_jal=0;
   inv_code_start=inv_code_end=~0;
+  f1_hack=0;
   // TLB
   for(n=0;n<4096;n++) ll_clear(jump_in+n);
   for(n=0;n<4096;n++) ll_clear(jump_out+n);
@@ -6945,6 +6947,27 @@ int new_recompile_block(u_int addr)
     ll_add_flags(jump_in+page,start,state_rflags,(void *)beginning);
     return 0;
   }
+  else if (f1_hack == ~0u || (f1_hack != 0 && start == f1_hack)) {
+    void *beginning = start_block();
+    u_int page = get_page(start);
+    emit_readword(&psxRegs.GPR.n.sp, 0);
+    emit_readptr(&mem_rtab, 1);
+    emit_shrimm(0, 12, 2);
+    emit_readptr_dualindexedx_ptrlen(1, 2, 1);
+    emit_addimm(0, 0x18, 0);
+    emit_adds_ptr(1, 1, 1);
+    emit_ldr_dualindexed(1, 0, 0);
+    emit_writeword(0, &psxRegs.GPR.r[26]); // lw k0, 0x18(sp)
+    emit_far_call(get_addr_ht);
+    emit_jmpreg(0); // jr k0
+    literal_pool(0);
+    end_block(beginning);
+
+    ll_add_flags(jump_in + page, start, state_rflags, beginning);
+    SysPrintf("F1 hack to   %08x\n", start);
+    f1_hack = start;
+    return 0;
+  }
 
   source = get_source_start(start, &pagelimit);
   if (source == NULL) {
@@ -7465,6 +7488,23 @@ 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);
+      f1_hack = ~0u;
+    }
+  }
+
   /* Pass 2 - Register dependencies and branch targets */
 
   unneeded_registers(0,slen-1,0);