psxbios: experimental vsync HLE
authornotaz <notasas@gmail.com>
Sat, 23 Sep 2023 19:00:13 +0000 (22:00 +0300)
committernotaz <notasas@gmail.com>
Sat, 23 Sep 2023 21:24:07 +0000 (00:24 +0300)
unsure how useful this is

16 files changed:
frontend/main.c
libpcsxcore/cdrom.c
libpcsxcore/cheat.c
libpcsxcore/misc.c
libpcsxcore/new_dynarec/emu_if.c
libpcsxcore/new_dynarec/events.c
libpcsxcore/new_dynarec/events.h
libpcsxcore/new_dynarec/linkage_offsets.h
libpcsxcore/new_dynarec/new_dynarec.c
libpcsxcore/ppf.c
libpcsxcore/psxbios.c
libpcsxcore/psxbios.h
libpcsxcore/r3000a.c
libpcsxcore/r3000a.h
libpcsxcore/sio.c
libpcsxcore/sio.h

index 092a844..e234990 100644 (file)
@@ -23,6 +23,7 @@
 #include "plat.h"
 #include "../libpcsxcore/misc.h"
 #include "../libpcsxcore/cheat.h"
+#include "../libpcsxcore/sio.h"
 #include "../libpcsxcore/new_dynarec/new_dynarec.h"
 #include "../plugins/cdrcimg/cdrcimg.h"
 #include "../plugins/dfsound/spu_config.h"
index 0ae2c50..e232d05 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <assert.h>
 #include "cdrom.h"
+#include "misc.h"
 #include "ppf.h"
 #include "psxdma.h"
 #include "arm_features.h"
index 7e9dc24..e0cf411 100644 (file)
@@ -19,6 +19,7 @@
 #include "psxcommon.h"
 #include "r3000a.h"
 #include "psxmem.h"
+#include "misc.h"
 
 #include "cheat.h"
 
index feabe15..50caad4 100644 (file)
@@ -28,6 +28,7 @@
 #include "mdec.h"
 #include "gpu.h"
 #include "ppf.h"
+#include "psxbios.h"
 #include "database.h"
 #include <zlib.h>
 
@@ -178,7 +179,10 @@ static void getFromCnf(char *buf, const char *key, u32 *val)
 }
 
 int LoadCdrom() {
-       EXE_HEADER tmpHead;
+       union {
+               EXE_HEADER h;
+               u32 d[sizeof(EXE_HEADER) / sizeof(u32)];
+       } tmpHead;
        struct iso_directory_record *dir;
        u8 time[4], *buf;
        u8 mdir[4096];
@@ -186,8 +190,10 @@ int LoadCdrom() {
        u32 cnf_tcb = 4;
        u32 cnf_event = 16;
        u32 cnf_stack = 0;
+       u32 t_addr;
+       u32 t_size;
        u32 sp = 0;
-       int ret;
+       int i, ret;
 
        if (!Config.HLE) {
                if (psxRegs.pc != 0x80030000) // BiosBootBypass'ed or custom BIOS?
@@ -250,32 +256,34 @@ int LoadCdrom() {
        }
 
        memcpy(&tmpHead, buf + 12, sizeof(EXE_HEADER));
+       for (i = 2; i < sizeof(tmpHead.d) / sizeof(tmpHead.d[0]); i++)
+               tmpHead.d[i] = SWAP32(tmpHead.d[i]);
 
-       SysPrintf("manual booting '%s' pc=%x\n", exename, SWAP32(tmpHead.pc0));
-       sp = SWAP32(tmpHead.s_addr);
+       SysPrintf("manual booting '%s' pc=%x\n", exename, tmpHead.h.pc0);
+       sp = tmpHead.h.s_addr;
        if (cnf_stack)
                sp = cnf_stack;
-       SetBootRegs(SWAP32(tmpHead.pc0), SWAP32(tmpHead.gp0), sp);
-
-       tmpHead.t_size = SWAP32(tmpHead.t_size);
-       tmpHead.t_addr = SWAP32(tmpHead.t_addr);
-
-       psxCpu->Clear(tmpHead.t_addr, tmpHead.t_size / 4);
-       //psxCpu->Reset();
+       SetBootRegs(tmpHead.h.pc0, tmpHead.h.gp0, sp);
 
        // Read the rest of the main executable
-       while (tmpHead.t_size & ~2047) {
-               void *ptr = (void *)PSXM(tmpHead.t_addr);
+       for (t_addr = tmpHead.h.t_addr, t_size = tmpHead.h.t_size; t_size & ~2047; ) {
+               void *ptr = (void *)PSXM(t_addr);
 
                incTime();
                READTRACK();
 
                if (ptr != INVALID_PTR) memcpy(ptr, buf+12, 2048);
 
-               tmpHead.t_size -= 2048;
-               tmpHead.t_addr += 2048;
+               t_addr += 2048;
+               t_size -= 2048;
        }
 
+       psxCpu->Clear(tmpHead.h.t_addr, tmpHead.h.t_size / 4);
+       //psxCpu->Reset();
+
+       if (Config.HLE)
+               psxBiosCheckExe(tmpHead.h.t_addr, tmpHead.h.t_size);
+
        return 0;
 }
 
@@ -690,6 +698,7 @@ cleanup:
 }
 
 int LoadState(const char *file) {
+       u32 biosBranchCheckOld = psxRegs.biosBranchCheck;
        void *f;
        GPUFreeze_t *gpufP = NULL;
        SPUFreeze_t *spufP = NULL;
@@ -721,6 +730,7 @@ int LoadState(const char *file) {
        SaveFuncs.read(f, psxH, 0x00010000);
        SaveFuncs.read(f, &psxRegs, offsetof(psxRegisters, gteBusyCycle));
        psxRegs.gteBusyCycle = psxRegs.cycle;
+       psxRegs.biosBranchCheck = ~0;
 
        psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
 
@@ -751,6 +761,9 @@ int LoadState(const char *file) {
        mdecFreeze(f, 0);
        new_dyna_freeze(f, 0);
 
+       if (Config.HLE)
+               psxBiosCheckExe(biosBranchCheckOld, 0x60);
+
        result = 0;
 cleanup:
        SaveFuncs.close(f);
index e21003c..9d8df34 100644 (file)
@@ -12,6 +12,7 @@
 #include "events.h"
 #include "../psxhle.h"
 #include "../psxinterpreter.h"
+#include "../psxcounters.h"
 #include "../r3000a.h"
 #include "../gte_arm.h"
 #include "../gte_neon.h"
index b1d427c..2bc9332 100644 (file)
@@ -12,7 +12,7 @@ extern int pending_exception;
 
 u32 event_cycles[PSXINT_COUNT];
 
-void schedule_timeslice(void)
+u32 schedule_timeslice(void)
 {
        u32 i, c = psxRegs.cycle;
        u32 irqs = psxRegs.interrupt;
@@ -28,6 +28,7 @@ void schedule_timeslice(void)
                        min = dif;
        }
        next_interupt = c + min;
+       return next_interupt;
 }
 
 typedef void (irq_func)();
index 919855c..eeec289 100644 (file)
@@ -1,3 +1,5 @@
+#include "../psxcommon.h"
+
 union psxCP0Regs_;
-void schedule_timeslice(void);
+u32  schedule_timeslice(void);
 void gen_interupt(union psxCP0Regs_ *cp0);
index 23935b8..541325a 100644 (file)
@@ -27,7 +27,7 @@
 #define LO_psxRegs_subCycle    (LO_muldivBusyCycle + 4)
 #define LO_psxRegs_biuReg      (LO_psxRegs_subCycle + 4*2)
 #define LO_psxRegs_reserved    (LO_psxRegs_biuReg + 4)
-#define LO_psxRegs_end         (LO_psxRegs_reserved + 4*3)
+#define LO_psxRegs_end         (LO_psxRegs_reserved + 4*7)
 #define LO_rcnts               (LO_psxRegs_end)
 #define LO_rcnts_end           (LO_rcnts + 7*4*4)
 #define LO_inv_code_start      (LO_rcnts_end)
index 07cd619..090165e 100644 (file)
@@ -37,6 +37,7 @@ static Jit g_jit;
 #include "new_dynarec_config.h"
 #include "../psxhle.h"
 #include "../psxinterpreter.h"
+#include "../psxcounters.h"
 #include "../gte.h"
 #include "emu_if.h" // emulator interface
 #include "linkage_offsets.h"
@@ -6500,6 +6501,15 @@ void new_dynarec_print_stats(void)
 #endif
 }
 
+static void force_intcall(int i)
+{
+  memset(&dops[i], 0, sizeof(dops[i]));
+  dops[i].itype = INTCALL;
+  dops[i].rs1 = CCREG;
+  dops[i].is_exception = 1;
+  cinfo[i].ba = -1;
+}
+
 static int apply_hacks(void)
 {
   int i;
@@ -6534,6 +6544,18 @@ static int apply_hacks(void)
       return 1;
     }
   }
+  if (Config.HLE)
+  {
+    if (start <= psxRegs.biosBranchCheck && psxRegs.biosBranchCheck < start + i*4)
+    {
+      i = (psxRegs.biosBranchCheck - start) / 4u + 23;
+      if (dops[i].is_jump && !dops[i+1].bt)
+      {
+        force_intcall(i);
+        dops[i+1].is_ds = 0;
+      }
+    }
+  }
   return 0;
 }
 
@@ -6547,15 +6569,6 @@ static int is_ld_use_hazard(const struct decoded_insn *op_ld,
   return op->itype != CJUMP && op->itype != SJUMP;
 }
 
-static void force_intcall(int i)
-{
-  memset(&dops[i], 0, sizeof(dops[i]));
-  dops[i].itype = INTCALL;
-  dops[i].rs1 = CCREG;
-  dops[i].is_exception = 1;
-  cinfo[i].ba = -1;
-}
-
 static void disassemble_one(int i, u_int src)
 {
     unsigned int type, op, op2, op3;
index 2ce1a9d..a7f6aef 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "psxcommon.h"
 #include "ppf.h"
+#include "misc.h"
 #include "cdrom.h"
 
 typedef struct tagPPF_DATA {
index b370966..bad3457 100644 (file)
@@ -36,6 +36,7 @@
 #include "sio.h"
 #include "psxhle.h"
 #include "psxinterpreter.h"
+#include "new_dynarec/events.h"
 #include <zlib.h>
 
 #ifndef PSXBIOS_LOG
@@ -3330,6 +3331,8 @@ void psxBiosInit() {
        int i;
        uLongf len;
 
+       psxRegs.biosBranchCheck = ~0;
+
        memset(psxM, 0, 0x10000);
        for(i = 0; i < 256; i++) {
                biosA0[i] = NULL;
@@ -4172,6 +4175,74 @@ void (* const psxHLEt[24])() = {
        hleExcPadCard1, hleExcPadCard2,
 };
 
+void psxBiosCheckExe(u32 t_addr, u32 t_size)
+{
+       // lw      $v0, 0x10($sp)
+       // nop
+       // addiu   $v0, -1
+       // sw      $v0, 0x10($sp)
+       // lw      $v0, 0x10($sp)
+       // nop
+       // bne     $v0, $v1, not_timeout
+       // nop
+       // lui     $a0, ...
+       static const u8 pattern[] = {
+               0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
+               0xFF, 0xFF, 0x42, 0x24, 0x10, 0x00, 0xA2, 0xAF,
+               0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
+               0x0C, 0x00, 0x43, 0x14, 0x00, 0x00, 0x00, 0x00,
+       };
+       u32 start = t_addr & 0x1ffffc;
+       u32 end = (start + t_size) & 0x1ffffc;
+       u32 buf[sizeof(pattern) / sizeof(u32)];
+       const u32 *r32 = (u32 *)(psxM + start);
+       u32 i, j;
+
+       if (end <= start)
+               return;
+       if (!Config.HLE)
+               return;
+
+       memcpy(buf, pattern, sizeof(buf));
+       for (i = 0; i < t_size / 4; i += j + 1) {
+               for (j = 0; j < sizeof(buf) / sizeof(buf[0]); j++)
+                       if (r32[i + j] != buf[j])
+                               break;
+               if (j != sizeof(buf) / sizeof(buf[0]))
+                       continue;
+
+               if ((SWAP32(r32[i + j]) >> 16) != 0x3c04) // lui
+                       continue;
+               SysPrintf("HLE vsync @%08x\n", start + i * 4);
+               psxRegs.biosBranchCheck = (t_addr & 0xa01ffffc) + i * 4;
+       }
+}
+
+void psxBiosCheckBranch(void)
+{
+#if 1
+       // vsync HLE hack
+       static u32 cycles_prev, v0_prev;
+       u32 cycles_passed, waste_cycles;
+       u32 loops, v0_expect = v0_prev - 1;
+       if (v0 != 1)
+               return;
+       execI(&psxRegs);
+       cycles_passed = psxRegs.cycle - cycles_prev;
+       cycles_prev = psxRegs.cycle;
+       v0_prev = v0;
+       if (cycles_passed < 10 || cycles_passed > 50 || v0 != v0_expect)
+               return;
+
+       waste_cycles = schedule_timeslice() - psxRegs.cycle;
+       loops = waste_cycles / cycles_passed;
+       if (loops > v0)
+               loops = v0;
+       v0 -= loops;
+       psxRegs.cycle += loops * cycles_passed;
+       //printf("c %4u %d\n", loops, cycles_passed);
+#endif
+}
 
 #define bfreeze(ptr, size) { \
        if (Mode == 1) memcpy(&psxR[base], ptr, size); \
index 4ebbd2b..c1368e6 100644 (file)
@@ -40,6 +40,8 @@ void psxBiosException();
 void psxBiosFreeze(int Mode);
 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 sp);
 void psxBiosSetupBootState(void);
+void psxBiosCheckExe(u32 t_addr, u32 t_size);
+void psxBiosCheckBranch(void);
 
 extern void (*biosA0[256])();
 extern void (**biosB0)();
index 69772d4..8035dfd 100644 (file)
@@ -26,6 +26,7 @@
 #include "mdec.h"
 #include "gte.h"
 #include "psxinterpreter.h"
+#include "psxbios.h"
 #include "../include/compiler_features.h"
 
 R3000Acpu *psxCpu = NULL;
@@ -210,6 +211,8 @@ void psxBranchTest() {
                psxRegs.CP0.n.Cause |= 0x400;
        if (((psxRegs.CP0.n.Cause | 1) & psxRegs.CP0.n.SR & 0x401) == 0x401)
                psxException(0, 0, &psxRegs.CP0);
+       else if (unlikely(psxRegs.pc == psxRegs.biosBranchCheck))
+               psxBiosCheckBranch();
 }
 
 void psxJumpTest() {
index 3a903b1..a8f39ab 100644 (file)
@@ -25,9 +25,6 @@ extern "C" {
 #endif
 
 #include "psxcommon.h"
-#include "psxmem.h"
-#include "psxcounters.h"
-#include "psxbios.h"
 
 enum R3000Aexception {
        R3000E_Int = 0,      // Interrupt
@@ -224,6 +221,8 @@ typedef struct {
        u8  dloadSel;       /* interp. delay load state */
        u8  dloadReg[2];
        u32 dloadVal[2];
+       u32 biosBranchCheck;
+       u32 reserved[3];
        // warning: changing anything in psxRegisters requires update of all
        // asm in libpcsxcore/new_dynarec/
 } psxRegisters;
index ab6baa1..5d5019d 100644 (file)
@@ -21,6 +21,8 @@
 * SIO functions.
 */
 
+#include "misc.h"
+#include "psxcounters.h"
 #include "sio.h"
 #include <sys/stat.h>
 
@@ -325,16 +327,6 @@ unsigned short sioReadBaud16() {
        return BaudReg;
 }
 
-void netError() {
-       ClosePlugins();
-       SysMessage(_("Connection closed!\n"));
-
-       CdromId[0] = '\0';
-       CdromLabel[0] = '\0';
-
-       SysRunGui();
-}
-
 void sioInterrupt() {
 #ifdef PAD_LOG
        PAD_LOG("Sio Interrupt (CP0.Status = %x)\n", psxRegs.CP0.n.Status);
index a554c2b..2dccdae 100644 (file)
@@ -48,8 +48,6 @@ unsigned short sioReadMode16();
 unsigned short sioReadCtrl16();
 unsigned short sioReadBaud16();
 
-void netError();
-
 void sioInterrupt();
 int sioFreeze(void *f, int Mode);