From cd653603e534faba76e879e287cb530cc6958dc9 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Fri, 31 Oct 2008 20:32:12 +0000 Subject: [PATCH] - Better IOP synchronization when using the X2 and X3 IOP hacks. Still not perfect, though (music may run a little behind or ahead of the games). I'll look into it tomorrow first thing. - IOP Counter optimizations. The IOP counter code now only updates counters actually being modified instead of blindly updating all counters. git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@259 a6443dda-0b58-4228-96e9-037be469359c --- pcsx2/PsxCounters.c | 112 ++++++++++++++++++++++-------------------- pcsx2/PsxDma.c | 1 - pcsx2/R3000A.c | 9 ++-- pcsx2/R5900.c | 6 +++ pcsx2/x86/iR3000A.cpp | 7 +-- 5 files changed, 73 insertions(+), 62 deletions(-) diff --git a/pcsx2/PsxCounters.c b/pcsx2/PsxCounters.c index 162752894f..ad305b4c37 100644 --- a/pcsx2/PsxCounters.c +++ b/pcsx2/PsxCounters.c @@ -48,54 +48,58 @@ static void psxRcntReset32(u32 index) { psxRcntUpd32(index); } -static void psxRcntSet() { +__forceinline static void _rcntSet( int i, int bitwise ) +{ + // thanks to being forceinline'd, this conditional will always be optimized + // to a constant by VC (confirmed via disassembler): + + u64 overflowCap = (bitwise==32) ? 0x100000000 : 0x10000; u64 c; + +#ifdef _DEBUG + if(bitwise == 32) + assert( (i < 6) && (i >= 3) ); + else + assert( i < 3 ); +#endif + + if(psxCounters[i].rate == PSXHBLANK) return; + + c = (u64)((overflowCap - psxCounters[i].count) * psxCounters[i].rate) - (psxRegs.cycle - psxCounters[i].sCycleT); + if (c < psxNextCounter) psxNextCounter = (u32)c; + + //if((psxCounters[i].mode & 0x10) == 0 || psxCounters[i].target > 0xffff) continue; + + c = (u64)((psxCounters[i].target - psxCounters[i].count) * psxCounters[i].rate) - (psxRegs.cycle - psxCounters[i].sCycleT); + if (c < psxNextCounter) psxNextCounter = (u32)c; +} + +static void psxRcntSet() { int i; psxNextCounter = 0xffffffff; psxNextsCounter = psxRegs.cycle; for (i=0; i<3; i++) { - if(psxCounters[i].rate == PSXHBLANK) continue; - c = (u64)((0x10000 - psxCounters[i].count) * psxCounters[i].rate) - (psxRegs.cycle - psxCounters[i].sCycleT); - if (c < psxNextCounter) { - psxNextCounter = (u32)c; - } - //if((psxCounters[i].mode & 0x10) == 0 || psxCounters[i].target > 0xffff) continue; - c = (u64)((psxCounters[i].target - psxCounters[i].count) * psxCounters[i].rate) - (psxRegs.cycle - psxCounters[i].sCycleT); - if (c < psxNextCounter) { - psxNextCounter = (u32)c; - } - + _rcntSet( i, 16 ); } for (i=3; i<6; i++) { - if(psxCounters[i].rate == PSXHBLANK) continue; - c = (u64)((0x100000000 - psxCounters[i].count) * psxCounters[i].rate) - (psxRegs.cycle - psxCounters[i].sCycleT); - if (c < psxNextCounter) { - psxNextCounter = (u32)c; - } - - //if((psxCounters[i].mode & 0x10) == 0 || psxCounters[i].target > 0xffffffff) continue; - c = (u64)((psxCounters[i].target - psxCounters[i].count) * psxCounters[i].rate) - (psxRegs.cycle - psxCounters[i].sCycleT); - if (c < psxNextCounter) { - psxNextCounter = (u32)c; - } - + _rcntSet( i, 32 ); } if(SPU2async) { - c = (u32)(psxCounters[6].CycleT - (psxRegs.cycle - psxCounters[6].sCycleT)) ; - if (c < psxNextCounter) { - psxNextCounter = (u32)c; - } + u32 c = (psxCounters[6].CycleT - (psxRegs.cycle - psxCounters[6].sCycleT)) ; + if (c < psxNextCounter) { + psxNextCounter = c; + } } if(USBasync) { - c = (u32)(psxCounters[7].CycleT - (psxRegs.cycle - psxCounters[7].sCycleT)) ; - if (c < psxNextCounter) { - psxNextCounter = (u32)c; - } + u32 c = (psxCounters[7].CycleT - (psxRegs.cycle - psxCounters[7].sCycleT)) ; + if (c < psxNextCounter) { + psxNextCounter = c; + } } } @@ -223,9 +227,10 @@ void psxCheckStartGate(int counter) { //Check Gate events when Vsync Starts psxCounters[6].sCycleT = psxRegs.cycle; }*/ } - + + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + if(counter < 3){ //Gates for 16bit counters - if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate //SysPrintf("PSX Gate %x\n", i); switch((psxCounters[i].mode & 0x6) >> 1) { case 0x0: //GATE_ON_count @@ -250,7 +255,6 @@ void psxCheckStartGate(int counter) { //Check Gate events when Vsync Starts } if(counter >= 3){ //Gates for 32bit counters - if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate //SysPrintf("PSX Gate %x\n", i); switch((psxCounters[i].mode & 0x6) >> 1) { case 0x0: //GATE_ON_count @@ -411,7 +415,6 @@ void _testRcnt32(int i) { } -extern int spu2interrupts[2]; void psxRcntUpdate() { int i; u32 change = 0; @@ -440,13 +443,14 @@ void psxRcntUpdate() { if(SPU2async) - { - if((psxRegs.cycle - psxCounters[6].sCycleT) >= psxCounters[6].CycleT){ - SPU2async(psxRegs.cycle - psxCounters[6].sCycleT); - //SysPrintf("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT); - psxCounters[6].sCycleT = psxRegs.cycle; - psxCounters[6].CycleT = ((Config.Hacks & 0x4) ? 768 : 9216); - } + { + if((psxRegs.cycle - psxCounters[6].sCycleT) >= psxCounters[6].CycleT) + { + SPU2async(psxRegs.cycle - psxCounters[6].sCycleT); + //SysPrintf("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT); + psxCounters[6].sCycleT = psxRegs.cycle; + psxCounters[6].CycleT = ((Config.Hacks & 0x4) ? 768 : 9216); + } } if(USBasync) @@ -480,7 +484,7 @@ void psxRcntWcount16(int index, u32 value) { } if(psxCounters[index].rate == PSXHBLANK)SysPrintf("Whoops 16 IOP\n"); psxRcntUpd16(index); - psxRcntSet(); + _rcntSet( index, 16 ); } void psxRcntWcount32(int index, u32 value) { @@ -503,7 +507,7 @@ void psxRcntWcount32(int index, u32 value) { } if(psxCounters[index].rate == PSXHBLANK)SysPrintf("Whoops 32 IOP\n"); //psxRcntUpd32(index); - psxRcntSet(); + _rcntSet( index, 32 ); } void psxRcnt0Wmode(u32 value) { @@ -511,9 +515,11 @@ void psxRcnt0Wmode(u32 value) { PSXCNT_LOG("IOP writeCmode[0] = %lx\n", value); #endif +#if 0 if (value & 0x1c00) { SysPrintf("Counter 0 Value write %x\n", value & 0x1c00); } +#endif psxCounters[0].mode = value; psxCounters[0].mode|= 0x0400; @@ -537,7 +543,7 @@ void psxRcnt0Wmode(u32 value) { //SysPrintf("IOP 16 Correcting target 0 after mode write\n"); psxCounters[0].target &= 0xffff; } - psxRcntSet(); + _rcntSet( 0, 16 ); //} } @@ -572,7 +578,7 @@ void psxRcnt1Wmode(u32 value) { //SysPrintf("IOP 16 Correcting target 1 after mode write\n"); psxCounters[1].target &= 0xffff; } - psxRcntSet(); + _rcntSet( 1, 16 ); //} } @@ -610,7 +616,7 @@ void psxRcnt2Wmode(u32 value) { //SysPrintf("IOP 16 Correcting target 2 after mode write\n"); psxCounters[2].target &= 0xffff; } - psxRcntSet(); + _rcntSet( 2, 16 ); } void psxRcnt3Wmode(u32 value) { @@ -644,7 +650,7 @@ void psxRcnt3Wmode(u32 value) { //SysPrintf("IOP 32 Correcting target 3 after mode write\n"); psxCounters[3].target &= 0xffffffff; } - psxRcntSet(); + _rcntSet( 3, 32 ); //} } @@ -689,7 +695,7 @@ void psxRcnt4Wmode(u32 value) { //SysPrintf("IOP 32 Correcting target 4 after mode write\n"); psxCounters[4].target &= 0xffffffff; } - psxRcntSet(); + _rcntSet( 4, 32 ); } void psxRcnt5Wmode(u32 value) { @@ -733,7 +739,7 @@ void psxRcnt5Wmode(u32 value) { //SysPrintf("IOP 32 Correcting target 5 after mode write\n"); psxCounters[5].target &= 0xffffffff; } - psxRcntSet(); + _rcntSet( 5, 32 ); } void psxRcntWtarget16(int index, u32 value) { @@ -746,7 +752,7 @@ void psxRcntWtarget16(int index, u32 value) { psxCounters[index].target += 0x1000000000; } - psxRcntSet(); + _rcntSet( index, 16 ); } void psxRcntWtarget32(int index, u32 value) { @@ -761,7 +767,7 @@ void psxRcntWtarget32(int index, u32 value) { psxCounters[index].target += 0x1000000000; } - psxRcntSet(); + _rcntSet( index, 32 ); } u16 psxRcntRcount16(int index) { diff --git a/pcsx2/PsxDma.c b/pcsx2/PsxDma.c index bcfb913643..b6a6fe51e8 100644 --- a/pcsx2/PsxDma.c +++ b/pcsx2/PsxDma.c @@ -25,7 +25,6 @@ // Dma8 in PsxSpd.c // Dma11/12 in PsxSio2.c //static int spudmaenable[2]; -int spu2interrupts[2]; int iopsifbusy[2] = { 0, 0 }; void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU int size; diff --git a/pcsx2/R3000A.c b/pcsx2/R3000A.c index 08b849385c..1cc8944f62 100644 --- a/pcsx2/R3000A.c +++ b/pcsx2/R3000A.c @@ -161,13 +161,16 @@ static void _psxTestInterrupts() { PSX_TESTINT(21, usbInterrupt); } -#define IOP_WAIT_CYCLE 256 // was (and is again!) 64 +// Higher Wait cycle values should, in theory, reduce IOP overhead without much +// drawback. The IOP is almost always forced to perform branch tests at import- +// ant intervals regardless of this value (such as counter or irq events, hsyncs, +// etc.) +#define IOP_WAIT_CYCLE 256 void psxBranchTest() { - // g_psxNextBranchCycle is initialized for us by iPsxBranchTest. g_psxNextBranchCycle = psxRegs.cycle; - if( EEsCycle >= 0 ) g_psxNextBranchCycle += IOP_WAIT_CYCLE; + //if( EEsCycle >= 0 ) g_psxNextBranchCycle += IOP_WAIT_CYCLE; if ((int)(psxRegs.cycle - psxNextsCounter) >= psxNextCounter) psxRcntUpdate(); diff --git a/pcsx2/R5900.c b/pcsx2/R5900.c index 1db5fdf4da..e6985edd5e 100644 --- a/pcsx2/R5900.c +++ b/pcsx2/R5900.c @@ -435,6 +435,12 @@ void cpuBranchTest() //#endif _cpuTestTIMR(); + // 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. Otherwise things won't be anywhere near "in sync." + + psxBranchTest(); + EEsCycle += cpuRegs.cycle - EEoCycle; EEoCycle = cpuRegs.cycle; diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp index 62f94c23a0..ed625fac81 100644 --- a/pcsx2/x86/iR3000A.cpp +++ b/pcsx2/x86/iR3000A.cpp @@ -987,19 +987,16 @@ static void iPsxBranchTest(u32 newpc, u32 cpuBranch) MOV32RtoM((uptr)&psxRegs.cycle, ECX); // update cycles } else { - SUB32ItoM((uptr)&EEsCycle, s_psxBlockCycles*PSXCYCLE_MULT*8); // 8 EE clocks for every IOP clock. + SUB32ItoM((uptr)&EEsCycle, ((u32)(s_psxBlockCycles*PSXCYCLE_MULT))*8); // 8 EE clocks for every IOP clock. ADD32ItoM((uptr)&psxRegs.cycle, s_psxBlockCycles*PSXCYCLE_MULT); return; } // check if we've caught up with the EE - SUB32ItoM((uptr)&EEsCycle, s_psxBlockCycles*PSXCYCLE_MULT*8); // 8 EE clocks for every IOP clock. + SUB32ItoM((uptr)&EEsCycle, ((u32)(s_psxBlockCycles*PSXCYCLE_MULT))*8); // 8 EE clocks for every IOP clock. j8Ptr[2] = JGE8(0); // Break the Block-execute Loop here. - // (but not without running another branch test! And do it regardless - // because the EE needs at least one IOP branch test or else bad things happen) - CALLFunc((uptr)psxBranchTest); if( REC_INC_STACK ) ADD64ItoR(ESP, REC_INC_STACK);