mirror of https://github.com/PCSX2/pcsx2.git
- 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
This commit is contained in:
parent
1bd9f54c9b
commit
cd653603e5
|
@ -48,53 +48,57 @@ 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)) ;
|
||||
u32 c = (psxCounters[6].CycleT - (psxRegs.cycle - psxCounters[6].sCycleT)) ;
|
||||
if (c < psxNextCounter) {
|
||||
psxNextCounter = (u32)c;
|
||||
psxNextCounter = c;
|
||||
}
|
||||
}
|
||||
if(USBasync)
|
||||
{
|
||||
c = (u32)(psxCounters[7].CycleT - (psxRegs.cycle - psxCounters[7].sCycleT)) ;
|
||||
u32 c = (psxCounters[7].CycleT - (psxRegs.cycle - psxCounters[7].sCycleT)) ;
|
||||
if (c < psxNextCounter) {
|
||||
psxNextCounter = (u32)c;
|
||||
psxNextCounter = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,8 +228,9 @@ void psxCheckStartGate(int counter) { //Check Gate events when Vsync Starts
|
|||
}*/
|
||||
}
|
||||
|
||||
if(counter < 3){ //Gates for 16bit counters
|
||||
if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate
|
||||
|
||||
if(counter < 3){ //Gates for 16bit counters
|
||||
//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;
|
||||
|
@ -441,7 +444,8 @@ void psxRcntUpdate() {
|
|||
|
||||
if(SPU2async)
|
||||
{
|
||||
if((psxRegs.cycle - psxCounters[6].sCycleT) >= psxCounters[6].CycleT){
|
||||
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;
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue