mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
d49f177706
commit
58a48b7b3a
101
pcsx2/Counters.c
101
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,6 +453,12 @@ 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.
|
||||
|
@ -436,8 +469,7 @@ static __forceinline void vSync()
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
12
pcsx2/GS.cpp
12
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);
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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*/) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
180
pcsx2/R5900.c
180
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
|
||||
|
|
|
@ -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)
|
||||
|
|
16
pcsx2/SPR.c
16
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();
|
||||
}
|
||||
|
|
10
pcsx2/Sif.c
10
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -359,6 +359,7 @@
|
|||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableFiberSafeOptimizations="true"
|
||||
PreprocessorDefinitions="PCSX2_PUBLIC"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
/>
|
||||
<Tool
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue