#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"
#include <assert.h>
#include "cdrom.h"
+#include "misc.h"
#include "ppf.h"
#include "psxdma.h"
#include "arm_features.h"
#include "psxcommon.h"
#include "r3000a.h"
#include "psxmem.h"
+#include "misc.h"
#include "cheat.h"
#include "mdec.h"
#include "gpu.h"
#include "ppf.h"
+#include "psxbios.h"
#include "database.h"
#include <zlib.h>
}
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];
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?
}
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;
}
}
int LoadState(const char *file) {
+ u32 biosBranchCheckOld = psxRegs.biosBranchCheck;
void *f;
GPUFreeze_t *gpufP = NULL;
SPUFreeze_t *spufP = NULL;
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);
mdecFreeze(f, 0);
new_dyna_freeze(f, 0);
+ if (Config.HLE)
+ psxBiosCheckExe(biosBranchCheckOld, 0x60);
+
result = 0;
cleanup:
SaveFuncs.close(f);
#include "events.h"
#include "../psxhle.h"
#include "../psxinterpreter.h"
+#include "../psxcounters.h"
#include "../r3000a.h"
#include "../gte_arm.h"
#include "../gte_neon.h"
u32 event_cycles[PSXINT_COUNT];
-void schedule_timeslice(void)
+u32 schedule_timeslice(void)
{
u32 i, c = psxRegs.cycle;
u32 irqs = psxRegs.interrupt;
min = dif;
}
next_interupt = c + min;
+ return next_interupt;
}
typedef void (irq_func)();
+#include "../psxcommon.h"
+
union psxCP0Regs_;
-void schedule_timeslice(void);
+u32 schedule_timeslice(void);
void gen_interupt(union psxCP0Regs_ *cp0);
#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)
#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"
#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;
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;
}
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;
#include "psxcommon.h"
#include "ppf.h"
+#include "misc.h"
#include "cdrom.h"
typedef struct tagPPF_DATA {
#include "sio.h"
#include "psxhle.h"
#include "psxinterpreter.h"
+#include "new_dynarec/events.h"
#include <zlib.h>
#ifndef PSXBIOS_LOG
int i;
uLongf len;
+ psxRegs.biosBranchCheck = ~0;
+
memset(psxM, 0, 0x10000);
for(i = 0; i < 256; i++) {
biosA0[i] = NULL;
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); \
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)();
#include "mdec.h"
#include "gte.h"
#include "psxinterpreter.h"
+#include "psxbios.h"
#include "../include/compiler_features.h"
R3000Acpu *psxCpu = NULL;
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() {
#endif
#include "psxcommon.h"
-#include "psxmem.h"
-#include "psxcounters.h"
-#include "psxbios.h"
enum R3000Aexception {
R3000E_Int = 0, // Interrupt
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;
* SIO functions.
*/
+#include "misc.h"
+#include "psxcounters.h"
#include "sio.h"
#include <sys/stat.h>
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);
unsigned short sioReadCtrl16();
unsigned short sioReadBaud16();
-void netError();
-
void sioInterrupt();
int sioFreeze(void *f, int Mode);