From de74f59932e94887debf30e5ec437d7f63591f74 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 23 Sep 2023 22:00:13 +0300 Subject: [PATCH] psxbios: experimental vsync HLE unsure how useful this is --- frontend/main.c | 1 + libpcsxcore/cdrom.c | 1 + libpcsxcore/cheat.c | 1 + libpcsxcore/misc.c | 43 +++++++++----- libpcsxcore/new_dynarec/emu_if.c | 1 + libpcsxcore/new_dynarec/events.c | 3 +- libpcsxcore/new_dynarec/events.h | 4 +- libpcsxcore/new_dynarec/linkage_offsets.h | 2 +- libpcsxcore/new_dynarec/new_dynarec.c | 31 +++++++--- libpcsxcore/ppf.c | 1 + libpcsxcore/psxbios.c | 71 +++++++++++++++++++++++ libpcsxcore/psxbios.h | 2 + libpcsxcore/r3000a.c | 3 + libpcsxcore/r3000a.h | 5 +- libpcsxcore/sio.c | 12 +--- libpcsxcore/sio.h | 2 - 16 files changed, 141 insertions(+), 42 deletions(-) diff --git a/frontend/main.c b/frontend/main.c index 092a844a..e2349903 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -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" diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 0ae2c50b..e232d05a 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -23,6 +23,7 @@ #include #include "cdrom.h" +#include "misc.h" #include "ppf.h" #include "psxdma.h" #include "arm_features.h" diff --git a/libpcsxcore/cheat.c b/libpcsxcore/cheat.c index 7e9dc240..e0cf411e 100644 --- a/libpcsxcore/cheat.c +++ b/libpcsxcore/cheat.c @@ -19,6 +19,7 @@ #include "psxcommon.h" #include "r3000a.h" #include "psxmem.h" +#include "misc.h" #include "cheat.h" diff --git a/libpcsxcore/misc.c b/libpcsxcore/misc.c index feabe15b..50caad42 100644 --- a/libpcsxcore/misc.c +++ b/libpcsxcore/misc.c @@ -28,6 +28,7 @@ #include "mdec.h" #include "gpu.h" #include "ppf.h" +#include "psxbios.h" #include "database.h" #include @@ -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); diff --git a/libpcsxcore/new_dynarec/emu_if.c b/libpcsxcore/new_dynarec/emu_if.c index e21003c0..9d8df341 100644 --- a/libpcsxcore/new_dynarec/emu_if.c +++ b/libpcsxcore/new_dynarec/emu_if.c @@ -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" diff --git a/libpcsxcore/new_dynarec/events.c b/libpcsxcore/new_dynarec/events.c index b1d427c9..2bc93326 100644 --- a/libpcsxcore/new_dynarec/events.c +++ b/libpcsxcore/new_dynarec/events.c @@ -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)(); diff --git a/libpcsxcore/new_dynarec/events.h b/libpcsxcore/new_dynarec/events.h index 919855cc..eeec289d 100644 --- a/libpcsxcore/new_dynarec/events.h +++ b/libpcsxcore/new_dynarec/events.h @@ -1,3 +1,5 @@ +#include "../psxcommon.h" + union psxCP0Regs_; -void schedule_timeslice(void); +u32 schedule_timeslice(void); void gen_interupt(union psxCP0Regs_ *cp0); diff --git a/libpcsxcore/new_dynarec/linkage_offsets.h b/libpcsxcore/new_dynarec/linkage_offsets.h index 23935b87..541325ac 100644 --- a/libpcsxcore/new_dynarec/linkage_offsets.h +++ b/libpcsxcore/new_dynarec/linkage_offsets.h @@ -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) diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 07cd6191..090165e6 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -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; diff --git a/libpcsxcore/ppf.c b/libpcsxcore/ppf.c index 2ce1a9d9..a7f6aefd 100644 --- a/libpcsxcore/ppf.c +++ b/libpcsxcore/ppf.c @@ -21,6 +21,7 @@ #include "psxcommon.h" #include "ppf.h" +#include "misc.h" #include "cdrom.h" typedef struct tagPPF_DATA { diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index b370966a..bad34578 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -36,6 +36,7 @@ #include "sio.h" #include "psxhle.h" #include "psxinterpreter.h" +#include "new_dynarec/events.h" #include #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); \ diff --git a/libpcsxcore/psxbios.h b/libpcsxcore/psxbios.h index 4ebbd2b6..c1368e67 100644 --- a/libpcsxcore/psxbios.h +++ b/libpcsxcore/psxbios.h @@ -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)(); diff --git a/libpcsxcore/r3000a.c b/libpcsxcore/r3000a.c index 69772d44..8035dfd1 100644 --- a/libpcsxcore/r3000a.c +++ b/libpcsxcore/r3000a.c @@ -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() { diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h index 3a903b1a..a8f39abb 100644 --- a/libpcsxcore/r3000a.h +++ b/libpcsxcore/r3000a.h @@ -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; diff --git a/libpcsxcore/sio.c b/libpcsxcore/sio.c index ab6baa12..5d5019d2 100644 --- a/libpcsxcore/sio.c +++ b/libpcsxcore/sio.c @@ -21,6 +21,8 @@ * SIO functions. */ +#include "misc.h" +#include "psxcounters.h" #include "sio.h" #include @@ -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); diff --git a/libpcsxcore/sio.h b/libpcsxcore/sio.h index a554c2bb..2dccdaea 100644 --- a/libpcsxcore/sio.h +++ b/libpcsxcore/sio.h @@ -48,8 +48,6 @@ unsigned short sioReadMode16(); unsigned short sioReadCtrl16(); unsigned short sioReadBaud16(); -void netError(); - void sioInterrupt(); int sioFreeze(void *f, int Mode); -- 2.39.2