- 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:
Jake.Stine 2008-10-31 20:32:12 +00:00 committed by Gregory Hainaut
parent 1bd9f54c9b
commit cd653603e5
5 changed files with 73 additions and 62 deletions

View File

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

View File

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

View File

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

View File

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

View File

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