Config.Xa = Config.Cdda = 0;
Config.icache_emulation = 0;
Config.PsxAuto = 1;
+ Config.cycle_multiplier = CYCLE_MULT_DEFAULT;
pl_rearmed_cbs.thread_rendering = 0;
#endif
#endif
new_dynarec_hacks = 0;
- cycle_multiplier = 200;
in_type[0] = PSE_PAD_TYPE_STANDARD;
in_type[1] = PSE_PAD_TYPE_STANDARD;
Config.PsxAuto = 0;
Config.PsxType = region - 1;
}
- cycle_multiplier = 10000 / psx_clock;
+ Config.cycle_multiplier = 10000 / psx_clock;
switch (in_type_sel1) {
case 1: in_type[0] = PSE_PAD_TYPE_ANALOGPAD; break;
// ------------ adv options menu ------------
#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 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),
#endif
static const char h_cfg_shacks[] = "Breaks games but may give better performance";
static const char h_cfg_icache[] = "Support F1 games (only when dynarec is off)";
+static const char h_cfg_psxclk[] = "Over/under-clock the PSX, default is " DEFAULT_PSX_CLOCK_S "\n"
+ "(adjust this if the game is too slow/too fast/hangs)";
enum { AMO_XA, AMO_CDDA, AMO_IC, AMO_CPU };
#if !defined(DRC_DISABLE) || defined(LIGHTREC)
mee_onoff_h ("Disable dynarec (slow!)",0, menu_iopts[AMO_CPU], 1, h_cfg_nodrc),
#endif
+ mee_range_h ("PSX CPU clock, %", 0, psx_clock, 1, 500, h_cfg_psxclk),
mee_handler_h ("[Speed hacks]", menu_loop_speed_hacks, h_cfg_shacks),
mee_end,
};
psxCpu->Reset();
}
+ menu_sync_config();
psxCpu->ApplyConfig();
// core doesn't care about Config.Cdda changes,
if (Config.Cdda)
CDR_stop();
- menu_sync_config();
if (cpu_clock > 0)
plat_target_cpu_clock_set(cpu_clock);
const char * const id;
int mult;
}
-new_dynarec_clock_overrides[] =
+cycle_multiplier_overrides[] =
{
/* Internal Section - fussy about timings */
{ "SLPS01868", 202 },
* changing memcard settings is enough to break/unbreak it */
{ "SLPS02528", 190 },
{ "SLPS02636", 190 },
+#ifdef DRC_DISABLE /* new_dynarec has a hack for this game */
+ /* Parasite Eve II - internal timer checks */
+ { "SLUS01042", 125 },
+ { "SLUS01055", 125 },
+ { "SLES02558", 125 },
+ { "SLES12558", 125 },
+#endif
};
/* Function for automatic patching according to GameID. */
/* Dynarec game-specific hacks */
new_dynarec_hacks_pergame = 0;
- cycle_multiplier_override = 0;
+ Config.cycle_multiplier_override = 0;
- for (i = 0; i < ARRAY_SIZE(new_dynarec_clock_overrides); i++)
+ for (i = 0; i < ARRAY_SIZE(cycle_multiplier_overrides); i++)
{
- if (strcmp(CdromId, new_dynarec_clock_overrides[i].id) == 0)
+ if (strcmp(CdromId, cycle_multiplier_overrides[i].id) == 0)
{
- cycle_multiplier_override = new_dynarec_clock_overrides[i].mult;
+ Config.cycle_multiplier_override = cycle_multiplier_overrides[i].mult;
new_dynarec_hacks_pergame |= NDHACK_OVERRIDE_CYCLE_M;
- SysPrintf("using new_dynarec clock override: %d\n",
- cycle_multiplier_override);
+ SysPrintf("using cycle_multiplier_override: %d\n",
+ Config.cycle_multiplier_override);
break;
}
}
else
new_dynarec_hacks &= ~NDHACK_NO_STALLS;
- if (cycle_multiplier != cycle_multiplier_old
+ if (Config.cycle_multiplier != cycle_multiplier_old
|| new_dynarec_hacks != new_dynarec_hacks_old)
{
new_dynarec_clear_full();
int pending_exception, stop;
unsigned int next_interupt;
int new_dynarec_did_compile;
-int cycle_multiplier;
-int cycle_multiplier_override;
int cycle_multiplier_old;
int new_dynarec_hacks_pergame;
int new_dynarec_hacks_old;
#define NO_CYCLE_PENALTY_THR 12
-int cycle_multiplier = CYCLE_MULT_DEFAULT; // 100 for 1.0
-int cycle_multiplier_override;
int cycle_multiplier_old;
static int cycle_multiplier_active;
stat_clear(stat_blocks);
stat_clear(stat_links);
- cycle_multiplier_old = cycle_multiplier;
+ cycle_multiplier_old = Config.cycle_multiplier;
new_dynarec_hacks_old = new_dynarec_hacks;
}
#endif
#endif
out = ndrc->translation_cache;
- cycle_multiplier=200;
new_dynarec_clear_full();
#ifdef HOST_IMM8
// Copy this into local area so we don't have to put it in every literal pool
(0xbfc00000 <= addr && addr < 0xbfc80000)))
{
// 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
+ // but timings in PCSX are too tied to the interpreter's 2-per-insn assumption
if (!HACK_ENABLED(NDHACK_OVERRIDE_CYCLE_M))
cycle_multiplier_active = 200;
return 0;
}
- cycle_multiplier_active = cycle_multiplier_override && cycle_multiplier == CYCLE_MULT_DEFAULT
- ? cycle_multiplier_override : cycle_multiplier;
+ cycle_multiplier_active = Config.cycle_multiplier_override && Config.cycle_multiplier == CYCLE_MULT_DEFAULT
+ ? Config.cycle_multiplier_override : Config.cycle_multiplier;
source = get_source_start(start, &pagelimit);
if (source == NULL) {
extern int stop;
extern int new_dynarec_did_compile;
-#define CYCLE_MULT_DEFAULT 175
-extern int cycle_multiplier; // 100 for 1.0
-extern int cycle_multiplier_override;
extern int cycle_multiplier_old;
#define NDHACK_NO_SMC_CHECK (1<<0)
void __Log(char *fmt, ...);
+#define CYCLE_MULT_DEFAULT 175
+
typedef struct {
char Gpu[MAXPATHLEN];
char Spu[MAXPATHLEN];
char Pad1[MAXPATHLEN];
char Pad2[MAXPATHLEN];
char Net[MAXPATHLEN];
- char Sio1[MAXPATHLEN];
+ char Sio1[MAXPATHLEN];
char Mcd1[MAXPATHLEN];
char Mcd2[MAXPATHLEN];
char Bios[MAXPATHLEN];
boolean UseNet;
boolean icache_emulation;
boolean DisableStalls;
+ int cycle_multiplier; // 100 for 1.0
+ int cycle_multiplier_override;
u8 Cpu; // CPU_DYNAREC or CPU_INTERPRETER
u8 PsxType; // PSX_TYPE_NTSC or PSX_TYPE_PAL
#ifdef _WIN32
if (Mode == 0) SaveFuncs.read(f, ptr, size); \
}
-// Make the timing events trigger faster as we are currently assuming everything
-// takes one cycle, which is not the case on real hardware.
-// FIXME: Count the proper cycle and get rid of this
-#define BIAS 2
#define PSXCLK 33868800 /* 33.8688 MHz */
enum {
static u32 (INT_ATTR *fetch)(u8 **memRLUT, u32 pc) = fetchNoCache;
+// Make the timing events trigger faster as we are currently assuming everything
+// takes one cycle, which is not the case on real hardware.
+// FIXME: count cache misses, memory latencies, stalls to get rid of this
+static inline void addCycle(void)
+{
+ assert(psxRegs.subCycleStep >= 0x10000);
+ psxRegs.subCycle += psxRegs.subCycleStep;
+ psxRegs.cycle += psxRegs.subCycle >> 16;
+ psxRegs.subCycle &= 0xffff;
+}
+
static void delayRead(int reg, u32 bpc) {
u32 rold, rnew;
branch = 0;
psxRegs.pc = tar;
- psxRegs.cycle += BIAS;
+ addCycle();
psxBranchTest();
return 1;
}
return psxDelayBranchExec(tar2);
}
debugI();
- psxRegs.cycle += BIAS;
+ addCycle();
/*
* Got a branch at tar1:
return psxDelayBranchExec(tmp1);
}
debugI();
- psxRegs.cycle += BIAS;
+ addCycle();
/*
* Got a branch at tar2:
debugI();
psxRegs.pc += 4;
- psxRegs.cycle += BIAS;
+ addCycle();
// check for load delay
tmp = psxRegs.code >> 26;
if (Config.Debug) ProcessDebug();
regs_->pc += 4;
- regs_->cycle += BIAS;
+ addCycle();
psxBSC[regs_->code >> 26](regs_, regs_->code);
}
}
void intApplyConfig() {
+ int cycle_mult;
+
assert(psxBSC[18] == psxCOP2 || psxBSC[18] == psxCOP2_stall);
assert(psxBSC[50] == gteLWC2 || psxBSC[50] == gteLWC2_stall);
assert(psxBSC[58] == gteSWC2 || psxBSC[58] == gteSWC2_stall);
fetch = fetchNoCache;
else
fetch = fetchICache;
+
+ cycle_mult = Config.cycle_multiplier_override && Config.cycle_multiplier == CYCLE_MULT_DEFAULT
+ ? Config.cycle_multiplier_override : Config.cycle_multiplier;
+ psxRegs.subCycleStep = 0x10000 * cycle_mult / 100;
}
static void intShutdown() {
psxRegs.CP0.r[12] = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1
psxRegs.CP0.r[15] = 0x00000002; // PRevID = Revision ID, same as R3000A
+ psxCpu->ApplyConfig();
psxCpu->Reset();
psxHwReset();
struct { u32 sCycle, cycle; } intCycle[32];
u32 gteBusyCycle;
u32 muldivBusyCycle;
+ u32 subCycle; /* interpreter cycle counting */
+ u32 subCycleStep;
// warning: changing anything in psxRegisters requires update of all
- // asm in libpcsxcore/new_dynarec/, but this member can be replaced
- u32 reserved[2];
+ // asm in libpcsxcore/new_dynarec/
} psxRegisters;
extern boolean writeok;