diff --git a/pcsx2/Counters.c b/pcsx2/Counters.c
index 28fb0f0953..3f000f2397 100644
--- a/pcsx2/Counters.c
+++ b/pcsx2/Counters.c
@@ -75,7 +75,16 @@ static __forceinline void _rcntSet( int i )
static __forceinline void cpuRcntSet() {
int i;
- nextCounter = (counters[4].CycleT < counters[5].CycleT) ? counters[4].CycleT : counters[5].CycleT;
+ // Calculate our target cycle deltas.
+ // This must be done regardless of if the hblank/vblank counters updated since
+ // cpuRegs.cycle changes, even if sCycle hasn't!
+
+ u32 counter4CycleT = ( counters[4].mode == MODE_HBLANK ) ? HBLANK_TIME_ : HRENDER_TIME_;
+ u32 counter5CycleT = VSYNC_HALF_ - (cpuRegs.cycle - counters[5].sCycle);
+ counter4CycleT -= (cpuRegs.cycle - counters[4].sCycle);
+
+ nextCounter = (counter4CycleT < counter5CycleT) ? counter4CycleT : counter5CycleT;
+
nextsCounter = cpuRegs.cycle;
for (i = 0; i < 4; i++)
@@ -384,24 +393,38 @@ static __forceinline void VSyncEnd(u32 sCycle) // VSync End
frameLimit(); // limit FPS (also handles frameskip and VUskip)
}
-#define hScanlineNextCycle(diff, cyclesAmount) { \
- u32 compareValue = (SCANLINE_ + cyclesAmount); \
- if (diff >= compareValue) { \
- u32 increment = (diff / compareValue); \
- /*SysPrintf("Counters Optimization\n");*/ \
- /* if counter's count increases on hblank gate's off signal OR if counter increases every hblank, THEN add to the counter */ \
- if ( (!(counters[0].mode & 0x30) && (gates & (1<<0))) || (((counters[0].mode & 0x83) == 0x83) && !(gates & (1<<0))) ) counters[0].count += (increment * HBLANK_COUNTER_SPEED); \
- if ( (!(counters[1].mode & 0x30) && (gates & (1<<1))) || (((counters[1].mode & 0x83) == 0x83) && !(gates & (1<<1))) ) counters[1].count += (increment * HBLANK_COUNTER_SPEED); \
- if ( (!(counters[2].mode & 0x30) && (gates & (1<<2))) || (((counters[2].mode & 0x83) == 0x83) && !(gates & (1<<2))) ) counters[2].count += (increment * HBLANK_COUNTER_SPEED); \
- if ( (!(counters[3].mode & 0x30) && (gates & (1<<3))) || (((counters[3].mode & 0x83) == 0x83) && !(gates & (1<<3))) ) counters[3].count += (increment * HBLANK_COUNTER_SPEED); \
- counters[4].sCycle += (increment * compareValue); \
- } \
- else counters[4].sCycle += cyclesAmount; \
- counters[4].CycleT = (s32)(cyclesAmount - (cpuRegs.cycle - counters[4].sCycle)); \
- if ((s32)counters[4].CycleT < 0) { \
- counters[4].sCycle += (((s32)counters[4].CycleT) * -1); \
- counters[4].CycleT = 0; \
- } \
+static __forceinline void hScanlineNextCycle( u32 diff, u32 cyclesAmount )
+{
+ // This function: Now Unneeded?
+ // This code doesn't appear to be run anymore after fixing the CycleT bug
+ // and fixing the EE/IOP code execution sync issues (tested on 6 games,
+ // with EEx3 hack too).
+
+ // And it makes sense -- bad behavior by the counters would have led
+ // to cpuBranchTest being delayed beyond the span of a full hsync.
+ // It could still happen in some isolated part of some particular game,
+ // but probably we're better off letting that game lose a couple hsyncs
+ // once in a while rather than slow everyone else down needlessly.
+
+ u32 scanlineCycles = SCANLINE_;
+ diff -= cyclesAmount;
+ if (diff >= scanlineCycles)
+ {
+ u32 increment = diff / scanlineCycles;
+
+ // Counter Optimization:
+ // If the time passed is beyond a single scanline, then increment all scanline
+ // counters as a set here.
+
+ SysPrintf("Counters Optimization %d\n", diff / scanlineCycles);
+
+ /* if counter's count increases on hblank gate's off signal OR if counter increases every hblank, THEN add to the counter */
+ if ( (!(counters[0].mode & 0x30) && (gates & (1<<0))) || (((counters[0].mode & 0x83) == 0x83) && !(gates & (1<<0))) ) counters[0].count += (increment * HBLANK_COUNTER_SPEED);
+ if ( (!(counters[1].mode & 0x30) && (gates & (1<<1))) || (((counters[1].mode & 0x83) == 0x83) && !(gates & (1<<1))) ) counters[1].count += (increment * HBLANK_COUNTER_SPEED);
+ if ( (!(counters[2].mode & 0x30) && (gates & (1<<2))) || (((counters[2].mode & 0x83) == 0x83) && !(gates & (1<<2))) ) counters[2].count += (increment * HBLANK_COUNTER_SPEED);
+ if ( (!(counters[3].mode & 0x30) && (gates & (1<<3))) || (((counters[3].mode & 0x83) == 0x83) && !(gates & (1<<3))) ) counters[3].count += (increment * HBLANK_COUNTER_SPEED);
+ counters[4].sCycle += (increment * scanlineCycles);
+ }
}
static __forceinline void hScanline()
@@ -409,16 +432,20 @@ static __forceinline void hScanline()
u32 difference = (cpuRegs.cycle - counters[4].sCycle);
if (counters[4].mode & MODE_HBLANK) { //HBLANK Start
- if (difference >= HBLANK_TIME_ ) {
- hScanlineNextCycle(difference, HBLANK_TIME_);
+ const u32 modeCycles = HBLANK_TIME_;
+ if (difference >= modeCycles ) {
+ //hScanlineNextCycle(difference, modeCycles);
+ counters[4].sCycle += modeCycles;
rcntStartGate(0, counters[4].sCycle);
psxCheckStartGate16(0);
counters[4].mode = MODE_HRENDER;
}
}
else { //HBLANK END / HRENDER Begin
- if (difference >= (HRENDER_TIME_)) {
- hScanlineNextCycle(difference, HRENDER_TIME_);
+ const u32 modeCycles = HRENDER_TIME_;
+ if (difference >= modeCycles) {
+ //hScanlineNextCycle(difference, modeCycles);
+ counters[4].sCycle += modeCycles;
if (CSRw & 0x4) GSCSRr |= 4; // signal
if (!(GSIMR&0x400)) gsIrq();
if (gates) rcntEndGate(0, counters[4].sCycle);
@@ -426,18 +453,23 @@ static __forceinline void hScanline()
counters[4].mode = MODE_HBLANK;
}
}
+
+ /*if(counters[4].CycleT < 0) {
+ counters[4].sCycle += -counters[4].CycleT;
+ counters[4].CycleT = 0;
+ }*/
+
}
// Only called from one place so might as well inline it.
-static __forceinline void vSync()
+static __forceinline void vSync()
{
u32 diff = (cpuRegs.cycle - counters[5].sCycle);
hScanline();
if (diff >= (VSYNC_HALF_)) {
- counters[5].sCycle += (VSYNC_HALF_ * (u32)(diff / VSYNC_HALF_));
- counters[5].CycleT = VSYNC_HALF_ - (cpuRegs.cycle - counters[5].sCycle);
+ counters[5].sCycle += VSYNC_HALF_; // * (u32)(diff / VSYNC_HALF_));
if (counters[5].mode == MODE_VSYNC) {
VSyncEnd(counters[5].sCycle);
@@ -446,7 +478,16 @@ static __forceinline void vSync()
else {
VSyncStart(counters[5].sCycle);
counters[5].mode = MODE_VSYNC;
+
+ // Accumulate hsync rounding errors:
+ counters[4].sCycle += HSYNC_ERROR;
+
+ // Tighten up EE/IOP responsiveness for a wee bit.
+ // Games are usually most sensitive to vSync sessions since that's
+ // when the hard thinking usually occurs.
+ g_eeTightenSync += 2;
}
+ g_nextBranchCycle = cpuRegs.cycle + 384;
}
}
@@ -680,6 +721,16 @@ int rcntFreeze(gzFile f, int Mode) {
gzfreeze(&nextCounter, sizeof(nextCounter));
gzfreeze(&nextsCounter, sizeof(nextsCounter));
+ if( Mode == 0 )
+ {
+ // Sanity check for loading older savestates:
+ if( counters[4].sCycle == 0 )
+ counters[4].sCycle = cpuRegs.cycle;
+
+ if( counters[5].sCycle == 0 )
+ counters[5].sCycle = cpuRegs.cycle;
+ }
+
return 0;
}
diff --git a/pcsx2/Counters.h b/pcsx2/Counters.h
index 2c928b8bb9..23ecd5a8ff 100644
--- a/pcsx2/Counters.h
+++ b/pcsx2/Counters.h
@@ -47,6 +47,8 @@ typedef struct {
#define SCANLINES_VBLANK1_NTSC 19 // scanlines used for vblank1 (even interlace)
#define SCANLINES_VBLANK2_NTSC 20 // scanlines used for vblank2 (odd interlace)
+#define HSYNC_ERROR_NTSC ((s32)VSYNC_NTSC - (s32)(((HRENDER_TIME_NTSC+HBLANK_TIME_NTSC) * SCANLINES_TOTAL_NTSC)/2) )
+
//------------------------------------------------------------------
// PAL Timing Information!!! (some scanline info is guessed)
//------------------------------------------------------------------
@@ -62,6 +64,8 @@ typedef struct {
#define SCANLINES_VBLANK1_PAL 19 // scanlines used for vblank1 (even interlace)
#define SCANLINES_VBLANK2_PAL 20 // scanlines used for vblank2 (odd interlace)
+#define HSYNC_ERROR_PAL ((s32)VSYNC_PAL - (s32)((SCANLINE_PAL * SCANLINES_TOTAL_PAL) / 2))
+
//------------------------------------------------------------------
// Timing (PAL/NTSC) Information!!!
//------------------------------------------------------------------
@@ -71,6 +75,8 @@ typedef struct {
#define VSYNC_ ((Config.PsxType&1) ? VSYNC_PAL : VSYNC_NTSC)
#define VSYNC_HALF_ ((Config.PsxType&1) ? VSYNC_HALF_PAL : VSYNC_HALF_NTSC)
+#define HSYNC_ERROR ((Config.PsxType&1) ? HSYNC_ERROR_PAL : HSYNC_ERROR_NTSC)
+
#define SCANLINES_TOTAL_ ((Config.PsxType&1) ? SCANLINES_TOTAL_PAL : SCANLINES_TOTAL_NTSC)
#define SCANLINES_VSYNC_ ((Config.PsxType&1) ? SCANLINES_VSYNC_PAL : SCANLINES_VSYNC_NTSC)
#define SCANLINES_VRENDER_ ((Config.PsxType&1) ? SCANLINES_VRENDER_PAL : SCANLINES_VRENDER_NTSC)
diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp
index db37d9cd02..6193b72f99 100644
--- a/pcsx2/GS.cpp
+++ b/pcsx2/GS.cpp
@@ -1054,7 +1054,7 @@ void GIFdma()
SysPrintf("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gif->madr, psHu32(DMAC_STADR));
if( gif->madr + (gif->qwc * 16) > psHu32(DMAC_STADR) ) {
- INT(2, gscycles);
+ CPU_INT(2, gscycles);
gscycles = 0;
return;
}
@@ -1165,7 +1165,7 @@ void GIFdma()
prevcycles = gscycles;
gif->tadr -= 16;
hwDmacIrq(13);
- INT(2, gscycles);
+ CPU_INT(2, gscycles);
gscycles = 0;
return;
}
@@ -1187,14 +1187,14 @@ void GIFdma()
prevtag = NULL;
prevcycles = 0;
if (!(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1))) {
- INT(2, gscycles);
+ CPU_INT(2, gscycles);
gscycles = 0;
}
}
void dmaGIF() {
//if(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1)){
- // INT(2, 48); //Wait time for the buffer to fill, fixes some timing problems in path 3 masking
+ // CPU_INT(2, 48); //Wait time for the buffer to fill, fixes some timing problems in path 3 masking
//} //It takes the time of 24 QW for the BUS to become ready - The Punisher, And1 Streetball
//else
gspath3done = 0; // For some reason this doesnt clear? So when the system starts the thread, we will clear it :)
@@ -1373,7 +1373,7 @@ void mfifoGIFtransfer(int qwc) {
if(gif->qwc == 0 && gifdone == 2) gifdone = 1;
- INT(11,mfifocycles);
+ CPU_INT(11,mfifocycles);
#ifdef SPR_LOG
SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x\n", gif->chcr, gif->madr, gif->tadr);
@@ -1599,7 +1599,7 @@ void* GSThreadProc(void* lpParam)
vif1ch->madr += vif1ch->qwc * 16;
if(vif1Regs->mskpath3 == 0)vif1Regs->stat&= ~0x1f000000;
- INT(1, 0); // since gs thread always lags real thread
+ CPU_INT(1, 0); // since gs thread always lags real thread
vif1ch->qwc = 0;
InterlockedExchangeAdd((long*)&g_pGSRingPos, 16);
diff --git a/pcsx2/Hw.h b/pcsx2/Hw.h
index 25e8db51a9..1c4b115435 100644
--- a/pcsx2/Hw.h
+++ b/pcsx2/Hw.h
@@ -39,13 +39,7 @@ extern u64 *psHD;
#define psHu64(mem) (*(u64*)&PS2MEM_HW[(mem) & 0xffff])
extern u32 g_nextBranchCycle;
-
-#define INT(n, ecycle) { \
- g_nextBranchCycle = min(g_nextBranchCycle, cpuRegs.cycle+ecycle); \
- cpuRegs.interrupt|= 1 << n; \
- cpuRegs.sCycle[n] = cpuRegs.cycle; \
- cpuRegs.eCycle[n] = ecycle; \
-}
+extern void CPU_INT( u32 n, u32 ecycle );
// VIF0 -- 0x10004000 -- psH[0x4000]
// VIF1 -- 0x10005000 -- psH[0x5000]
diff --git a/pcsx2/IPU/IPU.c b/pcsx2/IPU/IPU.c
index 8d49752039..252cbd5058 100644
--- a/pcsx2/IPU/IPU.c
+++ b/pcsx2/IPU/IPU.c
@@ -1032,7 +1032,7 @@ void IPUCMD_WRITE(u32 val) {
g_nCmdIndex = 0;
if( ipuCSC(ipuRegs->cmd.DATA) ) {
- if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0);
+ if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) CPU_INT(DMAC_FROM_IPU,0);
return;
}
@@ -1051,7 +1051,7 @@ void IPUCMD_WRITE(u32 val) {
case SCE_IPU_IDEC:
if( ipuIDEC(val) ) {
// idec done, ipu0 done too
- if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0);
+ if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) CPU_INT(DMAC_FROM_IPU,0);
return;
}
@@ -1064,7 +1064,7 @@ void IPUCMD_WRITE(u32 val) {
case SCE_IPU_BDEC:
if( ipuBDEC(val)) {
- if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0);
+ if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) CPU_INT(DMAC_FROM_IPU,0);
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD)
hwIntcIrq(INTC_IPU);
@@ -1136,7 +1136,7 @@ void IPUWorker()
return;
}
- if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0);
+ if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) CPU_INT(DMAC_FROM_IPU,0);
break;
case SCE_IPU_PACK:
if( !ipuPACK(ipuRegs->cmd.DATA) )
@@ -1161,7 +1161,7 @@ void IPUWorker()
ipuCurCmd = 0xffffffff;
// CHECK!: IPU0dma remains when IDEC is done, so we need to clear it
if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100))
- INT(DMAC_FROM_IPU,0);
+ CPU_INT(DMAC_FROM_IPU,0);
s_routine = NULL;
break;
@@ -1177,7 +1177,7 @@ void IPUWorker()
ipuRegs->topbusy = 0;
ipuRegs->cmd.BUSY = 0;
ipuCurCmd = 0xffffffff;
- if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0);
+ if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) CPU_INT(DMAC_FROM_IPU,0);
s_routine = NULL;
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD)
hwIntcIrq(INTC_IPU);
@@ -1642,7 +1642,7 @@ int IPU1dma()
if ((ipu1dma->chcr & 0x80) && (g_nDMATransfer&IPU_DMA_DOTIE1)) { //Check TIE bit of CHCR and IRQ bit of tag
SysPrintf("IPU1 TIE\n");
- INT(DMAC_TO_IPU, totalqwc*BIAS);
+ CPU_INT(DMAC_TO_IPU, totalqwc*BIAS);
g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1);
g_nDMATransfer |= IPU_DMA_TIE1;
return totalqwc;
@@ -1651,7 +1651,7 @@ int IPU1dma()
g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1);
if( (ipu1dma->chcr&0xc) == 0 ) {
- INT(DMAC_TO_IPU, totalqwc*BIAS);
+ CPU_INT(DMAC_TO_IPU, totalqwc*BIAS);
return totalqwc;
}
else {
@@ -1667,7 +1667,7 @@ int IPU1dma()
ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ( (*ptag) & 0xFFFF0000 );
IPU_LOG("IPU dmaIrq Set\n");
- INT(DMAC_TO_IPU, totalqwc*BIAS);
+ CPU_INT(DMAC_TO_IPU, totalqwc*BIAS);
g_nDMATransfer |= IPU_DMA_TIE1;
return totalqwc;
}
@@ -1676,12 +1676,12 @@ int IPU1dma()
{
case 0x00000000:
ipu1dma->tadr += 16;
- INT(DMAC_TO_IPU, (1+totalqwc)*BIAS);
+ CPU_INT(DMAC_TO_IPU, (1+totalqwc)*BIAS);
return totalqwc;
case 0x70000000:
ipu1dma->tadr = ipu1dma->madr;
- INT(DMAC_TO_IPU, (1+totalqwc)*BIAS);
+ CPU_INT(DMAC_TO_IPU, (1+totalqwc)*BIAS);
return totalqwc;
}
}
@@ -1698,7 +1698,7 @@ int IPU1dma()
IPU_LOG("dmaIPU1 Normal size=%d, addr=%lx, fifosize=%x\n",
ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC);
IPU1chain();
- INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS);
+ CPU_INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS);
return totalqwc;
}
else
@@ -1780,7 +1780,7 @@ int IPU1dma()
ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ( (*ptag) & 0xFFFF0000 );
}
- INT(DMAC_TO_IPU, ipu1cycles+totalqwc*BIAS);
+ CPU_INT(DMAC_TO_IPU, ipu1cycles+totalqwc*BIAS);
g_nDMATransfer |= IPU_DMA_TIE1;
return totalqwc;
}
@@ -1791,18 +1791,18 @@ int IPU1dma()
{
case 0x00000000:
ipu1dma->tadr += 16;
- INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS);
+ CPU_INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS);
return totalqwc;
case 0x70000000:
ipu1dma->tadr = ipu1dma->madr;
- INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS);
+ CPU_INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS);
return totalqwc;
}
}
}
- INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS);
+ CPU_INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS);
return totalqwc;
}
@@ -1912,7 +1912,7 @@ int IPU0dma()
break;
}
}
- INT(DMAC_FROM_IPU,readsize*BIAS);
+ CPU_INT(DMAC_FROM_IPU,readsize*BIAS);
}
diff --git a/pcsx2/Misc.c b/pcsx2/Misc.c
index a35172029b..91614a6ff0 100644
--- a/pcsx2/Misc.c
+++ b/pcsx2/Misc.c
@@ -405,6 +405,7 @@ void __Log(const char *fmt, ...) {
SysPrintf(tmp);
} else if( emuLog != NULL ) {
vfprintf(emuLog, fmt, list);
+ fflush( emuLog );
}
#else //i assume that this will not be used (Florin)
vsprintf(tmp, fmt, list);
diff --git a/pcsx2/PsxCounters.c b/pcsx2/PsxCounters.c
index 7192593c4f..9f189d8f81 100644
--- a/pcsx2/PsxCounters.c
+++ b/pcsx2/PsxCounters.c
@@ -294,9 +294,7 @@ void psxCheckStartGate32(int i)
void _testRcnt16target(int i) {
-#ifdef PSXCNT_LOG
PSXCNT_LOG("[%d] target %x >= %x (CycleT); count=%I64x, target=%I64x, mode=%I64x\n", i, (psxRegs.cycle - psxCounters[i].sCycleT), psxCounters[i].CycleT, psxCounters[i].count, psxCounters[i].target, psxCounters[i].mode);
-#endif
if(psxCounters[i].target > 0xffff) {
psxCounters[i].target &= 0xffff;
@@ -327,10 +325,7 @@ void _testRcnt16target(int i) {
void _testRcnt16overflow(int i) {
-#ifdef PSXCNT_LOG
- PSXCNT_LOG("[%d] overflow 0x%x >= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle) / psxCounters[i].rate, psxCounters[i].Cycle, psxRcntRcount16(i), psxCounters[i].count);
-#endif
-
+ PSXCNT_LOG("[%d] overflow 0x%x >= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle) / psxCounters[i].rate, psxCounters[i].Cycle, psxRcntRcount16(i), psxCounters[i].count);
if (psxCounters[i].mode & 0x0020) { // Overflow interrupt
psxHu32(0x1070)|= psxCounters[i].interrupt;
@@ -352,9 +347,7 @@ void _testRcnt16overflow(int i) {
void _testRcnt32target(int i) {
-#ifdef PSXCNT_LOG
PSXCNT_LOG("[%d] target %x >= %x (CycleT); count=%I64x, target=%I64x, mode=%I64x\n", i, (psxRegs.cycle - psxCounters[i].sCycleT), psxCounters[i].CycleT, psxCounters[i].count, psxCounters[i].target, psxCounters[i].mode);
-#endif
if(psxCounters[i].target > 0xffffffff) {
//SysPrintf("IOP 32 Correcting target on target reset\n");
psxCounters[i].target &= 0xffffffff;
@@ -388,9 +381,7 @@ void _testRcnt32target(int i) {
void _testRcnt32overflow(int i) {
-#ifdef PSXCNT_LOG
PSXCNT_LOG("[%d] overflow 0x%x >= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle), psxCounters[i].Cycle, psxRcntRcount32(i), psxCounters[i].count);
-#endif
//SysPrintf("Overflow 32\n");
if (psxCounters[i].mode & 0x0020) { // Overflow interrupt
psxHu32(0x1070)|= psxCounters[i].interrupt;
@@ -401,11 +392,13 @@ void _testRcnt32overflow(int i) {
}
}
psxCounters[i].count -= 0x100000000ULL;
- if(psxCounters[i].target > 0xffffffff) {
+ if(psxCounters[i].target > 0xffffffff)
+ {
//SysPrintf("IOP 32 Correcting target on overflow\n");
- if((psxCounters[i].mode & 0x50) <= 0x40 && (psxCounters[i].mode & 0x50) != 0) SysPrintf("Counter %x overflowing, no repeat interrupt mode = %x\n", i, psxCounters[i].mode);
+ if((psxCounters[i].mode & 0x50) <= 0x40 && (psxCounters[i].mode & 0x50) != 0)
+ SysPrintf("Counter %x overflowing, no repeat interrupt mode = %x\n", i, psxCounters[i].mode);
psxCounters[i].target &= 0xffffffff;
- }
+ }
}
@@ -479,9 +472,7 @@ void psxRcntUpdate() {
void psxRcntWcount16(int index, u32 value) {
u32 change = 0;
-#ifdef PSXCNT_LOG
PSXCNT_LOG("writeCcount[%d] = %x\n", index, value);
-#endif
change = psxRegs.cycle - psxCounters[index].sCycleT;
//psxCounters[i].count += change / psxCounters[i].rate;
@@ -524,9 +515,7 @@ void psxRcntWcount32(int index, u32 value) {
}
void psxRcnt0Wmode(u32 value) {
-#ifdef PSXCNT_LOG
PSXCNT_LOG("IOP writeCmode[0] = %lx\n", value);
-#endif
#if 0
if (value & 0x1c00) {
@@ -561,9 +550,7 @@ void psxRcnt0Wmode(u32 value) {
}
void psxRcnt1Wmode(u32 value) {
-#ifdef PSXCNT_LOG
PSXCNT_LOG("IOP writeCmode[1] = %lx\n", value);
-#endif
if (value & 0x1c00) {
SysPrintf("Counter 1 Value write %x\n", value & 0x1c00);
@@ -596,9 +583,7 @@ void psxRcnt1Wmode(u32 value) {
}
void psxRcnt2Wmode(u32 value) {
-#ifdef PSXCNT_LOG
PSXCNT_LOG("IOP writeCmode[2] = %lx\n", value);
-#endif
if (value & 0x1c00) {
SysPrintf("Counter 2 Value write %x\n", value & 0x1c00);
@@ -633,9 +618,7 @@ void psxRcnt2Wmode(u32 value) {
}
void psxRcnt3Wmode(u32 value) {
-#ifdef PSXCNT_LOG
PSXCNT_LOG("IOP writeCmode[3] = %lx\n", value);
-#endif
if (value & 0x1c00) {
SysPrintf("Counter 3 Value write %x\n", value & 0x1c00);
@@ -668,9 +651,7 @@ void psxRcnt3Wmode(u32 value) {
}
void psxRcnt4Wmode(u32 value) {
-#ifdef PSXCNT_LOG
PSXCNT_LOG("IOP writeCmode[4] = %lx\n", value);
-#endif
if (value & 0x1c00) {
SysPrintf("Counter 4 Value write %x\n", value & 0x1c00);
@@ -712,9 +693,7 @@ void psxRcnt4Wmode(u32 value) {
}
void psxRcnt5Wmode(u32 value) {
-#ifdef PSXCNT_LOG
PSXCNT_LOG("IOP writeCmode[5] = %lx\n", value);
-#endif
if (value & 0x1c00) {
SysPrintf("Counter 5 Value write %x\n", value & 0x1c00);
@@ -756,9 +735,7 @@ void psxRcnt5Wmode(u32 value) {
}
void psxRcntWtarget16(int index, u32 value) {
-#ifdef PSXCNT_LOG
PSXCNT_LOG("writeCtarget16[%ld] = %lx\n", index, value);
-#endif
psxCounters[index].target = value & 0xffff;
if(psxCounters[index].target <= psxRcntCycles(index)/* && psxCounters[index].target != 0*/) {
//SysPrintf("IOP 16 Saving %x target from early trigger target = %x, count = %I64x\n", index, psxCounters[index].target, psxRcntCycles(index));
@@ -769,10 +746,8 @@ void psxRcntWtarget16(int index, u32 value) {
}
void psxRcntWtarget32(int index, u32 value) {
-#ifdef PSXCNT_LOG
- PSXCNT_LOG("writeCtarget32[%ld] = %lx (count=%lx) ; sCycleT: %x CycleT: %x psxRegscycle %x\n",
- index, value, psxCounters[index].count, psxCounters[index].sCycleT, psxCounters[index].CycleT, psxRegs.cycle);
-#endif
+ PSXCNT_LOG("writeCtarget32[%ld] = %lx (count=%lx) ; sCycleT: %x CycleT: %x psxRegscycle %x\n",
+ index, value, psxCounters[index].count, psxCounters[index].sCycleT, psxCounters[index].CycleT, psxRegs.cycle);
psxCounters[index].target = value;
if(psxCounters[index].target <= psxRcntCycles(index)/* && psxCounters[index].target != 0*/) {
diff --git a/pcsx2/PsxHw.h b/pcsx2/PsxHw.h
index 1878073bff..92ddf83113 100644
--- a/pcsx2/PsxHw.h
+++ b/pcsx2/PsxHw.h
@@ -78,12 +78,7 @@
#define HW_DMA_PCR2 (psxHu32(0x1570))
#define HW_DMA_ICR2 (psxHu32(0x1574))
-#define PSX_INT(n, ecycle) \
- psxRegs.interrupt|= 1 << n; \
- g_psxNextBranchCycle = min(g_psxNextBranchCycle, psxRegs.cycle+ecycle); \
- psxRegs.sCycle[n] = psxRegs.cycle; \
- psxRegs.eCycle[n] = ecycle;
-
+extern void PSX_INT( int n, u32 ecycle);
void psxHwReset();
u8 psxHwRead8 (u32 add);
diff --git a/pcsx2/PsxInterpreter.c b/pcsx2/PsxInterpreter.c
index 69431e84a7..32f399ee16 100644
--- a/pcsx2/PsxInterpreter.c
+++ b/pcsx2/PsxInterpreter.c
@@ -270,7 +270,7 @@ void zeroEx() {
}
}
-#ifdef PSXBIOS_LOG
+#ifdef PCSX2_DEVBUILD
{char libz[9]; memcpy(libz, lib, 8); libz[8]=0;
PSXBIOS_LOG("%s: %s (%x)"
" (%x, %x, %x, %x)" //comment this line to disable param showing
@@ -316,7 +316,7 @@ void zeroEx() {
SysPrintf("sifcmd sceSifRegisterRpc (%x): rpc_id %x\n", psxRegs.pc, psxRegs.GPR.n.a1);
}
-#ifdef PSXBIOS_LOG
+#ifdef PCSX2_DEVBUILD
if (!strncmp(lib, "sysclib", 8)) {
switch (code) {
case 0x16: // strcmp
@@ -330,7 +330,7 @@ void zeroEx() {
}
#endif
-#ifdef PSXBIOS_LOG
+#ifdef PCSX2_DEVBUILD
if (varLog & 0x00800000) EMU_LOG("\n");
#endif
@@ -387,7 +387,7 @@ void spyFunctions(){
* Format: OP rt, rs, immediate *
*********************************************************/
void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
-void psxADDIU() { if (!_Rt_) { zeroEx(); return; } _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
+void psxADDIU() { if (!_Rt_) { g_eeTightenSync+=3; zeroEx(); return; } _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
@@ -774,7 +774,10 @@ extern void iDumpPsxRegisters(u32,u32);
#endif
static void intExecuteBlock() {
- while (EEsCycle > 0){
+ psxBreak = 0;
+ psxCycleEE = EEsCycle;
+
+ while (psxCycleEE >= 0){
branch2 = 0;
while (!branch2) {
execI();
@@ -786,6 +789,7 @@ static void intExecuteBlock() {
#endif
}
}
+ EEsCycle = psxBreak + psxCycleEE;
}
static void intClear(u32 Addr, u32 Size) {
diff --git a/pcsx2/R3000A.c b/pcsx2/R3000A.c
index 3a3067210a..4bb0732ee1 100644
--- a/pcsx2/R3000A.c
+++ b/pcsx2/R3000A.c
@@ -29,6 +29,17 @@ u32 g_psxConstRegs[32];
u32 g_psxHasConstReg, g_psxFlushedConstReg;
u32 g_psxNextBranchCycle = 0;
+// This value is used when the IOP execution is broken to return contorl to the EE.
+// (which happens when the IOP throws EE-bound interrupts). It holds the value of
+// psxCycleEE (which is set to zero to facilitate the code break), so that the unrun
+// cycles can be accounted for later.
+s32 psxBreak = 0;
+
+// tracks the IOP's current sync status with the EE. When it dips below zero,
+// control is returned to the EE.
+s32 psxCycleEE = -1;
+
+
PCSX2_ALIGNED16(psxRegisters psxRegs);
int psxInit()
@@ -134,6 +145,36 @@ void psxException(u32 code, u32 bd) {
}*/
}
+__forceinline void PSX_INT( int n, u32 ecycle )
+{
+ psxRegs.interrupt |= 1 << n;
+
+ psxRegs.sCycle[n] = psxRegs.cycle;
+ psxRegs.eCycle[n] = ecycle;
+
+ if( (g_psxNextBranchCycle - psxRegs.sCycle[n]) <= psxRegs.eCycle[n] ) return;
+
+ // Interrupt is happening soon: make sure everyone is aware (includeing the EE!)
+ g_psxNextBranchCycle = psxRegs.sCycle[n] + psxRegs.eCycle[n];
+
+ if( psxCycleEE < 0 )
+ {
+ // The EE called this int, so inform it to branch as needed:
+
+ u32 iopDelta = (g_psxNextBranchCycle-psxRegs.cycle)*8;
+ if( g_nextBranchCycle - cpuRegs.cycle > iopDelta )
+ {
+ // Optimization note: This method inlines witn 'n' as a constant, so the
+ // following conditionals will optimize nicely.
+
+ g_nextBranchCycle = cpuRegs.cycle + iopDelta;
+ if( n > 12 ) g_eeTightenSync += 5;
+ if( n >= 19 ) g_eeTightenSync += 2;
+ }
+ }
+}
+
+
#define PSX_TESTINT(n, callback) \
if (psxRegs.interrupt & (1 << n)) { \
if ((int)(psxRegs.cycle - psxRegs.sCycle[n]) >= psxRegs.eCycle[n]) { \
@@ -143,46 +184,45 @@ void psxException(u32 code, u32 bd) {
g_psxNextBranchCycle = psxRegs.sCycle[n] + psxRegs.eCycle[n]; \
}
-static void _psxTestInterrupts() {
+static __forceinline void _psxTestInterrupts()
+{
PSX_TESTINT(9, sif0Interrupt); // SIF0
PSX_TESTINT(10, sif1Interrupt); // SIF1
- PSX_TESTINT(11, psxDMA11Interrupt); // SIO2
- PSX_TESTINT(12, psxDMA12Interrupt); // SIO2
PSX_TESTINT(16, sioInterrupt);
- PSX_TESTINT(17, cdrInterrupt);
- PSX_TESTINT(18, cdrReadInterrupt);
PSX_TESTINT(19, cdvdReadInterrupt);
- PSX_TESTINT(20, dev9Interrupt);
- PSX_TESTINT(21, usbInterrupt);
+
+ // Profile-guided Optimization (sorta)
+ // The following ints are rarely called. Encasing them in a conditional
+ // as follows helps speed up most games.
+
+ if( psxRegs.interrupt & ( (3ul<<11) | (3ul<<20) | (3ul<<17) ) )
+ {
+ PSX_TESTINT(17, cdrInterrupt);
+ PSX_TESTINT(18, cdrReadInterrupt);
+ PSX_TESTINT(11, psxDMA11Interrupt); // SIO2
+ PSX_TESTINT(12, psxDMA12Interrupt); // SIO2
+ PSX_TESTINT(20, dev9Interrupt);
+ PSX_TESTINT(21, usbInterrupt);
+ }
}
-
-// IOP Wait cycles are still required to be a low number for maximum compatibility.
-// Some games like to freeze up if the BranchTest isn't called at fairly regular
-// intervals. ([TODO]: figure out why?)
-#define IOP_WAIT_CYCLE 64
-
void psxBranchTest()
{
- g_psxNextBranchCycle = psxRegs.cycle + IOP_WAIT_CYCLE;
-
- if ((int)(psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
+ if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
psxRcntUpdate();
- if (psxRegs.interrupt) {
- _psxTestInterrupts();
- }
+ // start the next branch at the next counter event by default
+ // the int code below will assign nearer branches if needed.
+ g_psxNextBranchCycle = psxNextsCounter+psxNextCounter;
- if( (int)(g_psxNextBranchCycle-psxNextsCounter) >= (u32)psxNextCounter )
- g_psxNextBranchCycle = (u32)psxNextsCounter+(u32)psxNextCounter;
+ if (psxRegs.interrupt) _psxTestInterrupts();
if (psxHu32(0x1078)) {
if(psxHu32(0x1070) & psxHu32(0x1074)){
- if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401) {
-//#ifdef PSXCPU_LOG
-// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074));
-//#endif
+ if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401)
+ {
+// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074));
psxException(0, 0);
}
}
diff --git a/pcsx2/R3000A.h b/pcsx2/R3000A.h
index 579fa1f858..e9b3065035 100644
--- a/pcsx2/R3000A.h
+++ b/pcsx2/R3000A.h
@@ -151,6 +151,9 @@ extern PCSX2_ALIGNED16_DECL(psxRegisters psxRegs);
extern u32 g_psxConstRegs[32];
extern u32 g_psxHasConstReg, g_psxFlushedConstReg;
+extern s32 psxBreak; // used when the IOP execution is broken and control returned to the EE
+extern s32 psxCycleEE; // tracks IOP's current sych status with the EE
+
#ifndef _PC_
#define _i32(x) (s32)x
@@ -197,7 +200,7 @@ extern u32 g_psxHasConstReg, g_psxFlushedConstReg;
#define _SetLink(x) psxRegs.GPR.r[x] = _PC_ + 4; // Sets the return address in the link register
-extern int EEsCycle;
+extern s32 EEsCycle;
extern u32 EEoCycle;
#endif
diff --git a/pcsx2/R5900.c b/pcsx2/R5900.c
index c62c3cf8e3..5c98b49fb0 100644
--- a/pcsx2/R5900.c
+++ b/pcsx2/R5900.c
@@ -39,7 +39,7 @@ PCSX2_ALIGNED16(GPR_reg64 g_cpuConstRegs[32]) = {0};
u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0;
R5900cpu *Cpu;
-int EEsCycle; // used to sync the IOP to the EE
+s32 EEsCycle; // used to sync the IOP to the EE
u32 EEoCycle;
u32 bExecBIOS = 0; // set if the BIOS has already been executed
@@ -325,34 +325,43 @@ void cpuTestMissingHwInts() {
}
}
-#define TESTINT(n, callback) { \
- if ( (cpuRegs.interrupt & (1 << n)) ) { \
- if( ((int)(cpuRegs.cycle - cpuRegs.sCycle[n]) >= cpuRegs.eCycle[n]) ) { \
- callback(); \
- } \
- else if( (int)(g_nextBranchCycle - cpuRegs.sCycle[n]) > cpuRegs.eCycle[n] ) { \
- g_nextBranchCycle = cpuRegs.sCycle[n] + cpuRegs.eCycle[n]; \
- } \
- } \
-} \
+static __forceinline void TESTINT( u8 n, void (*callback)() )
+{
+ if( !(cpuRegs.interrupt & (1 << n)) ) return;
-void _cpuTestInterrupts() {
+ if( (cpuRegs.cycle - cpuRegs.sCycle[n]) >= cpuRegs.eCycle[n] )
+ {
+ callback();
+ }
+ else if( (g_nextBranchCycle - cpuRegs.sCycle[n]) > cpuRegs.eCycle[n] )
+ g_nextBranchCycle = cpuRegs.sCycle[n] + cpuRegs.eCycle[n];
+}
- inter = cpuRegs.interrupt;
+static __forceinline void _cpuTestInterrupts()
+{
/* These are 'pcsx2 interrupts', they handle asynchronous stuff
that depends on the cycle timings */
- TESTINT(0, vif0Interrupt);
- TESTINT(10, vifMFIFOInterrupt);
TESTINT(1, vif1Interrupt);
- TESTINT(11, gifMFIFOInterrupt);
TESTINT(2, gsInterrupt);
- TESTINT(3, ipu0Interrupt);
- TESTINT(4, ipu1Interrupt);
TESTINT(5, EEsif0Interrupt);
TESTINT(6, EEsif1Interrupt);
- TESTINT(8, SPRFROMinterrupt);
- TESTINT(9, SPRTOinterrupt);
+
+ // Profile-guided Optimization (sorta)
+ // The following ints are rarely called. Encasing them in a conditional
+ // as follows helps speed up most games.
+
+ if( cpuRegs.interrupt & ( 1 | (3 << 3) | (3<<8) | (3<<10)) )
+ {
+ TESTINT(0, vif0Interrupt);
+ TESTINT(3, ipu0Interrupt);
+ TESTINT(4, ipu1Interrupt);
+ TESTINT(8, SPRFROMinterrupt);
+ TESTINT(9, SPRTOinterrupt);
+
+ TESTINT(10, vifMFIFOInterrupt);
+ TESTINT(11, gifMFIFOInterrupt);
+ }
if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return;
TESTINT(30, intcInterrupt);
@@ -362,10 +371,17 @@ void _cpuTestInterrupts() {
u32 s_iLastCOP0Cycle = 0;
u32 s_iLastPERFCycle[2] = {0,0};
-_inline static void _cpuTestTIMR() {
+static __forceinline void _cpuTestTIMR()
+{
cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle;
s_iLastCOP0Cycle = cpuRegs.cycle;
+ // [Air] : Are these necessary? The recompiler and interpreter code both appear
+ // to recalculate them whenever they're read. (although if they were not read
+ // for a long time they could overflow). Maybe these checks could be moved to
+ // the Ints or Counters so they they get called less frequently, but still get
+ // called enough to avoid overflows.
+
if((cpuRegs.PERF.n.pccr & 0x800003E0) == 0x80000020) {
cpuRegs.PERF.n.pcr0 += cpuRegs.cycle-s_iLastPERFCycle[0];
s_iLastPERFCycle[0] = cpuRegs.cycle;
@@ -382,41 +398,71 @@ _inline static void _cpuTestTIMR() {
}
}
+// maximum wait between branches. Lower values provide a tighter synchronization between
+// the EE and the IOP, but incur more execution overhead.
#define EE_WAIT_CYCLE 2048
+// maximum wait between branches when EE/IOP sync is tightened via g_eeTightenSync.
+// Lower values don't always make games better, since places where this value is set
+// will have to use higher numbers to achieve the same cycle count.
+#define EE_ACTIVE_CYCLE 192
+#define EE_ACTIVE_CYCLE_SUB (EE_WAIT_CYCLE - EE_ACTIVE_CYCLE)
+
+
// if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates
u32 g_nextBranchCycle = 0;
-u32 s_lastvsync[2];
+
+// if non-zero, the EE uses a shorter wait cycle (effectively tightening EE/IOP code
+// synchronization). Value decremented each branch test.
+u32 g_eeTightenSync = 0;
+
+#if !defined( PCSX2_NORECBUILD ) && !defined( PCSX2_PUBLIC )
extern u8 g_globalXMMSaved;
X86_32CODE(extern u8 g_globalMMXSaved;)
+#endif
-u32 loaded = 0;
u32 g_MTGSVifStart = 0, g_MTGSVifCount=0;
extern void gsWaitGS();
void cpuBranchTest()
{
#ifndef PCSX2_NORECBUILD
+#ifndef PCSX2_PUBLIC
// dont' remove this check unless doing an official release
if( g_globalXMMSaved X86_32CODE(|| g_globalMMXSaved) )
SysPrintf("frozen regs have not been restored!!!\n");
assert( !g_globalXMMSaved X86_32CODE(&& !g_globalMMXSaved) );
+#endif
g_EEFreezeRegs = 0;
#endif
-// if( !loaded && cpuRegs.cycle > 0x20000000 ) {
-// char strstate[255];
-// sprintf(strstate, SSTATES_DIR "/%8.8X.000", ElfCRC);
-// LoadState(strstate);
-// loaded = 1;
-// }
-
g_nextBranchCycle = cpuRegs.cycle + EE_WAIT_CYCLE;
+ if( g_eeTightenSync != 0 )
+ {
+ // This means we're running "sync-sensitive" code.
+ // tighten up the EE's cycle rate to ensure a more responsive
+ // EE/IOP operation:
- if ((int)(cpuRegs.cycle - nextsCounter) >= nextCounter)
+ g_eeTightenSync--;
+ g_nextBranchCycle -= EE_ACTIVE_CYCLE_SUB;
+ }
+
+ // ---- Counters -------------
+
+ if( (cpuRegs.cycle - nextsCounter) >= nextCounter )
rcntUpdate();
- // stall mtgs if it is taking too long
+ if( (g_nextBranchCycle-nextsCounter) >= nextCounter )
+ g_nextBranchCycle = nextsCounter+nextCounter;
+
+ // ---- Interrupts -------------
+
+ if( cpuRegs.interrupt )
+ _cpuTestInterrupts();
+
+ // ---- MTGS -------------
+ // stall mtgs if it is taking too long
+
if( g_MTGSVifCount > 0 ) {
if( cpuRegs.cycle-g_MTGSVifStart > g_MTGSVifCount ) {
gsWaitGS();
@@ -424,25 +470,17 @@ void cpuBranchTest()
}
}
- if (cpuRegs.interrupt)
- _cpuTestInterrupts();
-
- if( (int)(g_nextBranchCycle-nextsCounter) >= nextCounter )
- g_nextBranchCycle = nextsCounter+nextCounter;
-
//#ifdef CPU_LOG
// cpuTestMissingHwInts();
//#endif
_cpuTestTIMR();
// ---- IOP -------------
-
// Signal for an immediate branch test! This is important! The IOP must
// be able to act on the state the EE has given it before executing any
- // additional code. Doing this actually fixes some games that used to crash
- // when trying to boot them through the BIOS.
+ // additional code.
- //psxBranchTest();
+ psxBranchTest();
EEsCycle += cpuRegs.cycle - EEoCycle;
EEoCycle = cpuRegs.cycle;
@@ -461,30 +499,56 @@ void cpuBranchTest()
// ---- VU0 -------------
- if (VU0.VI[REG_VPU_STAT].UL & 0x1) {
+ if (VU0.VI[REG_VPU_STAT].UL & 0x1)
+ {
FreezeXMMRegs(1);
Cpu->ExecuteVU0Block();
FreezeXMMRegs(0);
}
- // [Air] dead code? There shouldn't be any reason to bother checking
- // for g_nextBranchCycle being behind cpuRegs.cycle, since the branch code will
- // just do the same check after the next block.
-
- //if( (int)cpuRegs.cycle-(int)g_nextBranchCycle > 0 )
- // g_nextBranchCycle = cpuRegs.cycle+1;
-
#ifndef PCSX2_NORECBUILD
+#ifndef PCSX2_PUBLIC
assert( !g_globalXMMSaved X86_32CODE(&& !g_globalMMXSaved) );
+#endif
g_EEFreezeRegs = 1;
#endif
}
+__forceinline void CPU_INT( u32 n, u32 ecycle)
+{
+ cpuRegs.interrupt|= 1 << n;
+ cpuRegs.sCycle[n] = cpuRegs.cycle;
+ cpuRegs.eCycle[n] = ecycle;
+
+ if( (g_nextBranchCycle - cpuRegs.sCycle[n]) <= cpuRegs.eCycle[n] ) return;
+
+ // Interrupt is happening soon: make sure everyone's aware!
+ g_nextBranchCycle = cpuRegs.sCycle[n] + cpuRegs.eCycle[n];
+
+ // Optimization note: this method inlines nicely since 'n' is almost always a
+ // constant. The following conditional optimizes to virtually nothing in most
+ // cases.
+
+ if( ( n == 3 || n == 4 || n == 30 || n == 31 ) &&
+ ecycle <= 28 && psxCycleEE > 0 )
+ {
+ // If running in the IOP, force it to break immediately into the EE.
+ // the EE's branch test is due to run.
+
+ psxBreak += psxCycleEE; // number of cycles we didn't run.
+ psxCycleEE = 0;
+ if( n == 3 || n == 4 )
+ g_eeTightenSync += 1; // only tighten IPU a bit, otherwise it's too slow!
+ else
+ g_eeTightenSync += 4;
+ }
+}
+
static void _cpuTestINTC() {
if ((cpuRegs.CP0.n.Status.val & 0x10407) == 0x10401){
if (psHu32(INTC_STAT) & psHu32(INTC_MASK)) {
if ((cpuRegs.interrupt & (1 << 30)) == 0) {
- INT(30,4);
+ CPU_INT(30,4);
}
}
}
@@ -495,7 +559,7 @@ static void _cpuTestDMAC() {
if (psHu16(0xe012) & psHu16(0xe010) ||
psHu16(0xe010) & 0x8000) {
if ( (cpuRegs.interrupt & (1 << 31)) == 0) {
- INT(31, 4);
+ CPU_INT(31, 4);
}
}
}
@@ -623,15 +687,16 @@ void IntcpuBranchTest()
g_EEFreezeRegs = 0;
#endif
- g_nextBranchCycle = cpuRegs.cycle + EE_WAIT_CYCLE;
+ // Interpreter uses a high-resolution wait cycle all the time:
+ g_nextBranchCycle = cpuRegs.cycle + 256;
- if ((int)(cpuRegs.cycle - nextsCounter) >= nextCounter)
+ if ((cpuRegs.cycle - nextsCounter) >= nextCounter)
rcntUpdate();
if (cpuRegs.interrupt)
_cpuTestInterrupts();
- if( (int)(g_nextBranchCycle-nextsCounter) >= nextCounter )
+ if( (g_nextBranchCycle-nextsCounter) >= nextCounter )
g_nextBranchCycle = nextsCounter+nextCounter;
//#ifdef CPU_LOG
@@ -639,6 +704,8 @@ void IntcpuBranchTest()
//#endif
_cpuTestTIMR();
+ psxBranchTest();
+
EEsCycle += cpuRegs.cycle - EEoCycle;
EEoCycle = cpuRegs.cycle;
@@ -651,9 +718,6 @@ void IntcpuBranchTest()
Cpu->ExecuteVU1Block();
}
- if( (int)cpuRegs.cycle-(int)g_nextBranchCycle > 0 )
- g_nextBranchCycle = cpuRegs.cycle+1;
-
#ifndef PCSX2_NORECBUILD
g_EEFreezeRegs = 1;
#endif
diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h
index f620944b25..5911189bdc 100644
--- a/pcsx2/R5900.h
+++ b/pcsx2/R5900.h
@@ -125,7 +125,7 @@ typedef struct {
u32 tempcycles;
} cpuRegisters;
-extern int EEsCycle;
+extern s32 EEsCycle;
extern u32 EEoCycle;
extern PCSX2_ALIGNED16_DECL(cpuRegisters cpuRegs);
@@ -236,7 +236,6 @@ void cpuTestHwInts();
void cpuTestINTCInts();
void cpuTestDMACInts();
void cpuTestTIMRInts();
-void _cpuTestInterrupts();
void cpuExecuteBios();
void cpuRestartCPU();
@@ -252,6 +251,7 @@ void JumpCheckSym(u32 addr, u32 pc);
void JumpCheckSymRet(u32 addr);
extern u32 g_EEFreezeRegs;
+extern u32 g_eeTightenSync; // non-zero values tighten EE/IOP code synchronization for short periods.
//exception code
#define EXC_CODE(x) ((x)<<2)
diff --git a/pcsx2/SPR.c b/pcsx2/SPR.c
index db1cfdfcc7..7d4d6c61f9 100644
--- a/pcsx2/SPR.c
+++ b/pcsx2/SPR.c
@@ -127,7 +127,7 @@ void _SPR0interleave() {
}
spr0->qwc = 0;
- INT(8, cycles);
+ CPU_INT(8, cycles);
}
void _dmaSPR0() {
@@ -146,7 +146,7 @@ void _dmaSPR0() {
if ((spr0->chcr & 0xc) == 0x0) { // Normal Mode
int cycles = 0;
SPR0chain();
- INT(8, cycles);
+ CPU_INT(8, cycles);
return;
} else if ((spr0->chcr & 0xc) == 0x4) {
@@ -157,7 +157,7 @@ void _dmaSPR0() {
if(spr0->qwc > 0){
SPR0chain();
- INT(8, cycles);
+ CPU_INT(8, cycles);
return;
}
@@ -214,7 +214,7 @@ void _dmaSPR0() {
return;
}*/
}
- INT(8, cycles);
+ CPU_INT(8, cycles);
} else { // Interleave Mode
_SPR0interleave();
}
@@ -314,7 +314,7 @@ void _SPR1interleave() {
}
spr1->qwc = 0;
- INT(9, cycles);
+ CPU_INT(9, cycles);
}
@@ -337,7 +337,7 @@ void dmaSPR1() { // toSPR
//if(spr1->qwc == 0 && (spr1->chcr & 0xc) == 1) spr1->qwc = 0xffff;
// Transfer Dn_QWC from Dn_MADR to SPR1
SPR1chain();
- INT(9, cycles);
+ CPU_INT(9, cycles);
FreezeMMXRegs(0);
return;
} else if ((spr1->chcr & 0xc) == 0x4){
@@ -350,7 +350,7 @@ void dmaSPR1() { // toSPR
//if(spr1->qwc == 0 && (spr1->chcr & 0xc) == 1) spr1->qwc = 0xffff;
// Transfer Dn_QWC from Dn_MADR to SPR1
SPR1chain();
- INT(9, cycles);
+ CPU_INT(9, cycles);
FreezeMMXRegs(0);
return;
}
@@ -399,7 +399,7 @@ void dmaSPR1() { // toSPR
break;
}
}
- INT(9, cycles);
+ CPU_INT(9, cycles);
} else { // Interleave Mode
_SPR1interleave();
}
diff --git a/pcsx2/Sif.c b/pcsx2/Sif.c
index 1723d8d5c0..5515eab67f 100644
--- a/pcsx2/Sif.c
+++ b/pcsx2/Sif.c
@@ -277,7 +277,7 @@ _inline void SIF0Dma()
//sif0dma->chcr &= ~0x100;
eesifbusy[0] = 0;
- INT(5, cycles*BIAS);
+ CPU_INT(5, cycles*BIAS);
//hwDmacIrq(5);
notDone = 0;
}
@@ -289,7 +289,7 @@ _inline void SIF0Dma()
//sif0dma->chcr &= ~0x100;
//hwDmacIrq(5);
eesifbusy[0] = 0;
- INT(5, cycles*BIAS);
+ CPU_INT(5, cycles*BIAS);
notDone = 0;
}
else if(sif0.fifoSize >= 4) // Read a tag
@@ -344,7 +344,7 @@ _inline void SIF1Dma()
SIF_LOG("EE SIF1 End %x\n", sif1.end);
eesifbusy[1] = 0;
notDone = 0;
- INT(6, cycles*BIAS);
+ CPU_INT(6, cycles*BIAS);
sif1.chain = 0;
sif1.end = 0;
}
@@ -519,7 +519,7 @@ _inline void sif1Interrupt() {
_inline void EEsif0Interrupt() {
/*if (psHu32(DMAC_STAT) & (1<<5)) {
- INT(5, 0x800);
+ CPU_INT(5, 0x800);
return 0;
}*/
sif0dma->chcr &= ~0x100;
@@ -531,7 +531,7 @@ _inline void EEsif0Interrupt() {
_inline void EEsif1Interrupt() {
/*if (psHu32(DMAC_STAT) & (1<<6)) {
- INT(6, 0x800);
+ CPU_INT(6, 0x800);
return 0;
}*/
hwDmacIrq(6);
diff --git a/pcsx2/Vif.c b/pcsx2/Vif.c
index 2d614804f8..7917df1815 100644
--- a/pcsx2/Vif.c
+++ b/pcsx2/Vif.c
@@ -521,7 +521,7 @@ void mfifoVIF1transfer(int qwc) {
VIF_LOG("MFIFO Stallon tag\n");
#endif
vif1.stallontag = 1;
- INT(10,cycles+g_vifCycles);
+ CPU_INT(10,cycles+g_vifCycles);
return; //IRQ set by VIFTransfer
}
}
@@ -584,20 +584,20 @@ void mfifoVIF1transfer(int qwc) {
SysPrintf("VIF dmaChain error size=%d, madr=%lx, tadr=%lx\n",
vif1ch->qwc, vif1ch->madr, vif1ch->tadr);
vif1.done = 1;
- INT(10,g_vifCycles);
+ CPU_INT(10,g_vifCycles);
}
if(ret == -2){
#ifdef VIF_LOG
VIF_LOG("MFIFO Stall\n");
#endif
- INT(10,g_vifCycles);
+ CPU_INT(10,g_vifCycles);
return;
}
if(vif1.done == 2 && vif1ch->qwc == 0) vif1.done = 1;
- INT(10,g_vifCycles);
+ CPU_INT(10,g_vifCycles);
#ifdef SPR_LOG
SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x\n", vif1ch->chcr, vif1ch->madr, vif1ch->tadr, vifqwc);
diff --git a/pcsx2/VifDma.c b/pcsx2/VifDma.c
index 028e5d3f0f..f37c100f82 100644
--- a/pcsx2/VifDma.c
+++ b/pcsx2/VifDma.c
@@ -1293,7 +1293,7 @@ void vif0Interrupt() {
_chainVIF0();
}
else _VIF0chain();
- INT(0, g_vifCycles);
+ CPU_INT(0, g_vifCycles);
return;
}
}
@@ -1318,7 +1318,7 @@ void vif0Interrupt() {
if(vif0ch->qwc > 0) _VIF0chain();
ret = _chainVIF0();
- INT(0, g_vifCycles);
+ CPU_INT(0, g_vifCycles);
return;
//if(ret!=2)
/*else*/ //return 1;
@@ -1387,7 +1387,7 @@ void dmaVIF0() {
}*/
// if(vif0ch->qwc > 0) {
// _VIF0chain();
-// INT(0, g_vifCycles);
+// CPU_INT(0, g_vifCycles);
// }
g_vifCycles = 0;
@@ -1401,17 +1401,17 @@ void dmaVIF0() {
return;
}
vif0.done = 1;
- INT(0, g_vifCycles);
+ CPU_INT(0, g_vifCycles);
return;
}
/* if (_VIF0chain() != 0) {
- INT(0, g_vifCycles);
+ CPU_INT(0, g_vifCycles);
return;
}*/
// Chain Mode
vif0.done = 0;
- INT(0, g_vifCycles);
+ CPU_INT(0, g_vifCycles);
}
@@ -1477,7 +1477,7 @@ void vif0Write32(u32 mem, u32 value) {
} else _VIF0chain();
vif0ch->chcr |= 0x100;
- INT(0, g_vifCycles); // Gets the timing right - Flatout
+ CPU_INT(0, g_vifCycles); // Gets the timing right - Flatout
}
}
}
@@ -1839,7 +1839,7 @@ static void Vif1CMDMskPath3(){ // MSKPATH3
//while(gif->chcr & 0x100) gsInterrupt(); // Finish the transfer first
psHu32(GIF_STAT) |= 0x2;
} else {
- if(gif->chcr & 0x100) INT(2, (transferred>>2) * BIAS); // Restart Path3 on its own, time it right!
+ if(gif->chcr & 0x100) CPU_INT(2, (transferred>>2) * BIAS); // Restart Path3 on its own, time it right!
psHu32(GIF_STAT) &= ~0x2;
}
#else
@@ -2230,7 +2230,7 @@ void vif1Interrupt() {
_chainVIF1();
}
else _VIF1chain();
- INT(1, g_vifCycles);
+ CPU_INT(1, g_vifCycles);
return;
}
}
@@ -2249,7 +2249,7 @@ void vif1Interrupt() {
}
/*if(vif1ch->qwc > 0){
_VIF1chain();
- INT(1, g_vifCycles);
+ CPU_INT(1, g_vifCycles);
return 0;
}*/
if ((vif1ch->chcr & 0x104) == 0x104 && vif1.done == 0) {
@@ -2260,7 +2260,7 @@ void vif1Interrupt() {
}
_chainVIF1();
- INT(1, g_vifCycles);
+ CPU_INT(1, g_vifCycles);
return;
}
@@ -2302,7 +2302,7 @@ void dmaVIF1()
}*/
// if(vif1ch->qwc > 0) {
// _VIF1chain();
-// INT(1, g_vifCycles);
+// CPU_INT(1, g_vifCycles);
// }
vif1.done = 0;
g_vifCycles = 0;
@@ -2321,11 +2321,11 @@ void dmaVIF1()
VIF_LOG("dmaIrq Set\n");
#endif
vif1.done = 1;
- INT(1, g_vifCycles);
+ CPU_INT(1, g_vifCycles);
return;
}
//vif1.done = 1;
- INT(1, g_vifCycles);
+ CPU_INT(1, g_vifCycles);
return;
}*/
@@ -2356,7 +2356,7 @@ void dmaVIF1()
vif1.vifstalled = 1;
return;
}
- INT(1, g_vifCycles);
+ CPU_INT(1, g_vifCycles);
} else { // from Memory
@@ -2401,7 +2401,7 @@ void dmaVIF1()
vif1.done = 1;
vif1Regs->stat&= ~0x1f000000;
vif1ch->qwc = 0;
- INT(1, g_vifCycles);
+ CPU_INT(1, g_vifCycles);
return; //Return -1 as an error has occurred
}
@@ -2427,7 +2427,7 @@ void dmaVIF1()
g_vifCycles += vif1ch->qwc * 2;
vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
vif1ch->qwc = 0;
- INT(1, g_vifCycles);
+ CPU_INT(1, g_vifCycles);
}
}
@@ -2437,13 +2437,13 @@ void dmaVIF1()
}
/* if (_VIF1chain() != 0) {
- INT(1, g_vifCycles);
+ CPU_INT(1, g_vifCycles);
return;
}*/
// Chain Mode
vif1.done = 0;
- INT(1, g_vifCycles);
+ CPU_INT(1, g_vifCycles);
}
@@ -2509,14 +2509,14 @@ void vif1Write32(u32 mem, u32 value) {
if((psHu32(DMAC_CTRL) & 0xC) == 0x8){
//vif1.vifstalled = 0;
//SysPrintf("MFIFO Stall\n");
- INT(10, 0);
+ CPU_INT(10, 0);
}else {
if(vif1.stallontag == 1){
//SysPrintf("Sorting VIF Stall on tag\n");
_chainVIF1();
} else _VIF1chain();
//vif1.vifstalled = 0'
- INT(1, g_vifCycles); // Gets the timing right - Flatout
+ CPU_INT(1, g_vifCycles); // Gets the timing right - Flatout
}
vif1ch->chcr |= 0x100;
}
diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index 508406ad1a..f8d9ea6828 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -359,6 +359,7 @@
GameFixes = strtoul(szValue, NULL, 0);
+ // Remove Fast Branches hack for now:
+ Conf->Hacks &= ~0x80;
+
#ifdef ENABLE_NLS
{
char text[256];
diff --git a/pcsx2/windows/pcsx2.rc b/pcsx2/windows/pcsx2.rc
index 87f56aab46..79789d198d 100644
--- a/pcsx2/windows/pcsx2.rc
+++ b/pcsx2/windows/pcsx2.rc
@@ -1058,7 +1058,7 @@ BEGIN
CONTROL "Disable FPU Overflow Checks - *Checked = Disables overflow checks. ( Speedup! ) *Greyed = Extra overflow checks. ( Helps SPS, Slow! )",IDC_FPU_OVERFLOWHACK,
"Button",BS_AUTO3STATE | WS_TABSTOP,15,63,483,10
CONTROL "EE/IOP Fast Branches - Quick branching ( Very small speedup; Not Recommended! )",IDC_FASTBRANCHES,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,231,423,10
+ "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,15,231,423,10
CTEXT "If you have problems, disable all these and try again!",IDC_STATIC,7,22,497,8
GROUPBOX "Overflow and Underflow",IDC_STATIC,7,36,497,58
CONTROL "Disable Underflow Checks - *Checked = Disables underflow checks. ( Speedup! )",IDC_DENORMALS,
diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp
index d96fea6494..e9dd16aac9 100644
--- a/pcsx2/x86/iR3000A.cpp
+++ b/pcsx2/x86/iR3000A.cpp
@@ -445,20 +445,26 @@ void psxRecompileCodeConst0(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode,
}
extern "C" void zeroEx();
+extern "C" u32 g_eeTightenSync;
// rt = rs op imm16
void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode)
{
if ( ! _Rt_ ) {
-#ifdef _DEBUG
if( (psxRegs.code>>26) == 9 ) {
//ADDIU, call bios
+#ifdef _DEBUG
MOV32ItoM( (uptr)&psxRegs.code, psxRegs.code );
MOV32ItoM( (uptr)&psxRegs.pc, psxpc );
_psxFlushCall(FLUSH_NODESTROY);
CALLFunc((uptr)zeroEx);
- }
#endif
+ // Tighten up the EE/IOP sync (helps prevent crashes)
+ // [TODO] should probably invoke a branch test or EE code control break here,
+ // but it would require the use of registers and I have no eff'ing idea how
+ // the register allocation stuff works in the recompiler. :/
+ ADD32ItoM( (uptr)&g_eeTightenSync, 3 );
+ }
return;
}
@@ -618,7 +624,7 @@ static void recShutdown() {
#if !defined(__x86_64__)
static u32 s_uSaveESP = 0;
-static void R3000AExecute()
+static __forceinline void R3000AExecute()
{
#ifdef _DEBUG
u8* fnptr;
@@ -629,7 +635,8 @@ static void R3000AExecute()
BASEBLOCK* pblock;
- while (EEsCycle > 0) {
+ //while (EEsCycle > 0)
+ {
pblock = PSX_GETBLOCK(psxRegs.pc);
if ( !pblock->pFnptr || (pblock->startpc&PSX_MEMMASK) != (psxRegs.pc&PSX_MEMMASK) ) {
@@ -983,9 +990,6 @@ void psxSetBranchImm( u32 imm )
#define USE_FAST_BRANCHES CHECK_FASTBRANCHES
-// Important! The following macro makes sure the rounding error of both the psxRegs.cycle
-// modifier and EEsCycle modifier are consistent (in case you wonder why it's got a u32 typecast)
-
//fixme : this is all a huge hack, we base the counter advancements on the average an opcode should take (wtf?)
// If that wasn't bad enough we have default values like 9/8 which will get cast to int later
// (yeah, that means all sync code couldn't have worked to beginn with)
@@ -1000,29 +1004,35 @@ static u32 psxScaleBlockCycles()
(CHECK_IOPSYNC_HACK ? (CHECK_EE_IOP_EXTRA ? 3 : 2) : 1 );
}
+extern "C" s32 psxScaleWaitCycles()
+{
+ return -40 *
+ (CHECK_IOPSYNC_HACK ? (CHECK_EE_IOP_EXTRA ? 3.1875 : 2.125) : (17/16));
+}
+
+
static void iPsxBranchTest(u32 newpc, u32 cpuBranch)
{
u32 blockCycles = psxScaleBlockCycles();
if( USE_FAST_BRANCHES && cpuBranch == 0 )
{
- SUB32ItoM((uptr)&EEsCycle, blockCycles*8 );
+ SUB32ItoM((uptr)&psxCycleEE, blockCycles*8 );
ADD32ItoM((uptr)&psxRegs.cycle, blockCycles);
return;
}
MOV32MtoR(ECX, (uptr)&psxRegs.cycle);
- ADD32ItoR(ECX, blockCycles); // greater mult factor causes nfsmw to crash
+ MOV32MtoR(EAX, (uptr)&psxCycleEE);
+ ADD32ItoR(ECX, blockCycles);
+ SUB32ItoR(EAX, blockCycles*8);
MOV32RtoM((uptr)&psxRegs.cycle, ECX); // update cycles
+ MOV32RtoM((uptr)&psxCycleEE, EAX);
- // check if we've caught up with the EE
- SUB32ItoM((uptr)&EEsCycle, blockCycles*8 );
- j8Ptr[2] = JGE8(0);
-
- // Break the Block-execute Loop here.
+ j8Ptr[2] = JNS8( 0 ); // jump if no, on (psxCycleEE - blockCycles*8) < 0
if( REC_INC_STACK )
ADD64ItoR(ESP, REC_INC_STACK);
- RET2();
+ RET2(); // returns control to the EE
// Continue onward with branching here:
x86SetJ8( j8Ptr[2] );
@@ -1033,7 +1043,8 @@ static void iPsxBranchTest(u32 newpc, u32 cpuBranch)
CALLFunc((uptr)psxBranchTest);
- if( newpc != 0xffffffff ) {
+ if( newpc != 0xffffffff )
+ {
CMP32ItoM((uptr)&psxRegs.pc, newpc);
JNE32((uptr)psxDispatcherReg - ( (uptr)x86Ptr + 6 ));
}
@@ -1069,7 +1080,7 @@ void rpsxSYSCALL()
CMP32ItoM((uptr)&psxRegs.pc, psxpc-4);
j8Ptr[0] = JE8(0);
ADD32ItoM((uptr)&psxRegs.cycle, psxScaleBlockCycles() );
- SUB32ItoM((uptr)&EEsCycle, psxScaleBlockCycles()*8 );
+ SUB32ItoM((uptr)&psxCycleEE, psxScaleBlockCycles()*8 );
JMP32((uptr)psxDispatcherReg - ( (uptr)x86Ptr + 5 ));
x86SetJ8(j8Ptr[0]);
@@ -1088,7 +1099,7 @@ void rpsxBREAK()
CMP32ItoM((uptr)&psxRegs.pc, psxpc-4);
j8Ptr[0] = JE8(0);
ADD32ItoM((uptr)&psxRegs.cycle, psxScaleBlockCycles() );
- SUB32ItoM((uptr)&EEsCycle, psxScaleBlockCycles()*8 );
+ SUB32ItoM((uptr)&psxCycleEE, psxScaleBlockCycles()*8 );
JMP32((uptr)psxDispatcherReg - ( (uptr)x86Ptr + 5 ));
x86SetJ8(j8Ptr[0]);
@@ -1113,6 +1124,9 @@ void psxRecompileNextInstruction(int delayslot)
BASEBLOCK* pblock = PSX_GETBLOCK(psxpc);
+ //if( psxpc == 0x5264 )
+ // SysPrintf( "Woot!" );
+
// need *ppblock != s_pCurBlock because of branches
if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) {
@@ -1200,8 +1214,12 @@ static void recExecute() {
for (;;) R3000AExecute();
}
-static void recExecuteBlock() {
+static void recExecuteBlock()
+{
+ psxBreak = 0;
+ psxCycleEE = EEsCycle;
R3000AExecute();
+ EEsCycle = psxBreak + psxCycleEE;
}
#include "PsxHw.h"
@@ -1511,7 +1529,7 @@ StartRecomp:
else
{
ADD32ItoM((uptr)&psxRegs.cycle, psxScaleBlockCycles() );
- SUB32ItoM((uptr)&EEsCycle, psxScaleBlockCycles()*8 );
+ SUB32ItoM((uptr)&psxCycleEE, psxScaleBlockCycles()*8 );
}
if( willbranch3 ) {
diff --git a/pcsx2/x86/ix86-32/iR5900-32.c b/pcsx2/x86/ix86-32/iR5900-32.c
index ebbb24a00c..05dc252cb3 100644
--- a/pcsx2/x86/ix86-32/iR5900-32.c
+++ b/pcsx2/x86/ix86-32/iR5900-32.c
@@ -2258,7 +2258,6 @@ void iFlushCall(int flushtype)
// So for now these are new settings that work. I would've set 1 for default but that seemed too low
// (rama)
-//#define EECYCLE_MULT (CHECK_EESYNC_HACK ? (CHECK_EE_IOP_EXTRA ? 3.375 : 2.25) : (9/8))
#define EECYCLE_MULT (CHECK_EESYNC_HACK ? (CHECK_EE_IOP_EXTRA ? 3 : 2) : (1.2))
static void iBranchTest(u32 newpc, u32 cpuBranch)
@@ -2274,26 +2273,26 @@ static void iBranchTest(u32 newpc, u32 cpuBranch)
//CALLFunc((uptr)testfpu);
#endif
- if( !USE_FAST_BRANCHES || cpuBranch ) {
- MOV32MtoR(ECX, (int)&cpuRegs.cycle);
- ADD32ItoR(ECX, s_nBlockCycles*EECYCLE_MULT); // NOTE: mulitply cycles here, 6/5 ratio stops pal ffx from randomly crashing, but crashes jakI
- MOV32RtoM((int)&cpuRegs.cycle, ECX); // update cycles
- }
- else {
- ADD32ItoM((int)&cpuRegs.cycle, s_nBlockCycles*EECYCLE_MULT);
+ if( USE_FAST_BRANCHES && (cpuBranch==0) )
+ {
+ ADD32ItoM((uptr)&cpuRegs.cycle, s_nBlockCycles*EECYCLE_MULT);
return;
}
- SUB32MtoR(ECX, (int)&g_nextBranchCycle);
+ MOV32MtoR(ECX, (uptr)&cpuRegs.cycle);
+ ADD32ItoR(ECX, s_nBlockCycles*EECYCLE_MULT);
+ MOV32RtoM((uptr)&cpuRegs.cycle, ECX); // update cycles
+ SUB32MtoR(ECX, (uptr)&g_nextBranchCycle);
// check if should branch
j8Ptr[0] = JS8( 0 );
// has to be in the middle of Save/LoadBranchState
- CALLFunc( (int)cpuBranchTest );
+ CALLFunc( (uptr)cpuBranchTest );
- if( newpc != 0xffffffff ) {
- CMP32ItoM((int)&cpuRegs.pc, newpc);
+ if( newpc != 0xffffffff )
+ {
+ CMP32ItoM((uptr)&cpuRegs.pc, newpc);
JNE32((u32)DispatcherReg - ( (u32)x86Ptr + 6 ));
}
@@ -2325,9 +2324,9 @@ void recSYSCALL( void ) {
iFlushCall(FLUSH_NODESTROY);
CALLFunc( (uptr)SYSCALL );
- CMP32ItoM((int)&cpuRegs.pc, pc);
+ CMP32ItoM((uptr)&cpuRegs.pc, pc);
j8Ptr[0] = JE8(0);
- ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles*EECYCLE_MULT);
+ ADD32ItoM((uptr)&cpuRegs.cycle, s_nBlockCycles*EECYCLE_MULT);
JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 ));
x86SetJ8(j8Ptr[0]);
//branch = 2;
@@ -2340,7 +2339,7 @@ void recBREAK( void ) {
iFlushCall(FLUSH_EVERYTHING);
CALLFunc( (uptr)BREAK );
- CMP32ItoM((int)&cpuRegs.pc, pc);
+ CMP32ItoM((uptr)&cpuRegs.pc, pc);
j8Ptr[0] = JE8(0);
ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles*EECYCLE_MULT);
RET();