Big update; should fix most or all of the problems introduced in recent revisions. Extended summary follows:

New EE/IOP sync method: The EE can now "throttle" itself between high and low resolution wait cycles.  High res cycles are engaged when certain time-critical ints and BIOS calls are done.  Meanwhile, low-res mode uses much less cpu.

vs2008 project: Added a "PUBLIC" define to the 'Release (to Public)' build type.  It can be used to ifdef code that should only be excluded when creating official builds and releases.

Renamed INT() macro into CPU_INT() function.  INT() is also a Win32 define so renaming helps alleviate confusion and lets VS IDE's code database browser work better when trying to list references of the function.

Fixed some lingering inaccuracies in the EE h/vsync counters introduced at r246.

Removed the Use Fast Branches option (for now) as it's not compatible with the new EE/IOP sync (yet).

Added fflush() to the emu log so that it doesn't get cut off prematurely if the emulator crashes.

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@317 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
Jake.Stine 2008-11-12 01:47:43 +00:00 committed by Gregory Hainaut
parent d49f177706
commit 58a48b7b3a
23 changed files with 418 additions and 264 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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);

View File

@ -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]

View File

@ -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);
}

View File

@ -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);

View File

@ -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*/) {

View File

@ -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);

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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();
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -359,6 +359,7 @@
<Tool
Name="VCCLCompilerTool"
EnableFiberSafeOptimizations="true"
PreprocessorDefinitions="PCSX2_PUBLIC"
EnableEnhancedInstructionSet="0"
/>
<Tool

View File

@ -909,7 +909,7 @@ static void HacksInit( HWND hDlg )
if(Config.Hacks & 0x10) CheckDlgButton(hDlg, IDC_SYNCHACK2, TRUE);
if(Config.Hacks & 0x20) CheckDlgButton(hDlg, IDC_SYNCHACK3, TRUE);
if(Config.Hacks & 0x40) CheckDlgButton(hDlg, IDC_VU_OVERFLOWHACK, 2);
if(Config.Hacks & 0x80) CheckDlgButton(hDlg, IDC_FASTBRANCHES, TRUE);
//if(Config.Hacks & 0x80) CheckDlgButton(hDlg, IDC_FASTBRANCHES, TRUE);
if(Config.Hacks & 0x100) CheckDlgButton(hDlg, IDC_VU_FLAGS, TRUE);
if(Config.Hacks & 0x200) CheckDlgButton(hDlg, IDC_FPU_FLAGS, TRUE);
if(Config.Hacks & 0x400) CheckDlgButton(hDlg, IDC_ESCHACK, TRUE);
@ -927,7 +927,7 @@ static void HacksChecked( HWND hDlg )
Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_DENORMALS) ? 0x8 : 0;
Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_SYNCHACK2) ? 0x10 : 0;
Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_SYNCHACK3) ? 0x20 : 0;
Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_FASTBRANCHES) ? 0x80 : 0;
//Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_FASTBRANCHES) ? 0x80 : 0;
Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_VU_FLAGS) ? 0x100 : 0;
Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_FPU_FLAGS) ? 0x200 : 0;
Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_ESCHACK) ? 0x400 : 0;
@ -963,7 +963,7 @@ BOOL APIENTRY HacksProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
CheckDlgButton(hDlg, IDC_SYNCHACK, FALSE);
CheckDlgButton(hDlg, IDC_SYNCHACK2, FALSE);
CheckDlgButton(hDlg, IDC_SYNCHACK3, FALSE);
CheckDlgButton(hDlg, IDC_FASTBRANCHES, FALSE);
//CheckDlgButton(hDlg, IDC_FASTBRANCHES, FALSE);
//CheckDlgButton(hDlg, IDC_SOUNDHACK, TRUE);
//CheckDlgButton(hDlg, IDC_ESCHACK, TRUE);
@ -980,7 +980,7 @@ BOOL APIENTRY HacksProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
CheckDlgButton(hDlg, IDC_SYNCHACK, TRUE);
CheckDlgButton(hDlg, IDC_SYNCHACK2, TRUE);
CheckDlgButton(hDlg, IDC_SYNCHACK3, TRUE);
CheckDlgButton(hDlg, IDC_FASTBRANCHES, FALSE);
//CheckDlgButton(hDlg, IDC_FASTBRANCHES, FALSE);
CheckDlgButton(hDlg, IDC_SOUNDHACK, FALSE);
//CheckDlgButton(hDlg, IDC_ESCHACK, TRUE);

View File

@ -152,6 +152,9 @@ int LoadConfig()
GetPrivateProfileString("Misc", "GameFixes", NULL, szValue, 20, szIniFile);
Conf->GameFixes = strtoul(szValue, NULL, 0);
// Remove Fast Branches hack for now:
Conf->Hacks &= ~0x80;
#ifdef ENABLE_NLS
{
char text[256];

View File

@ -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,

View File

@ -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 ) {

View File

@ -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();