void psxCheckStartGate16(int i) { assert( i < 3 ); if(i == 0) // hSync counting... { // AlternateSource/scanline counters for Gates 1 and 3. // We count them here so that they stay nicely synced with the EE's hsync. const u32 altSourceCheck = IOPCNT_ALT_SOURCE | IOPCNT_ENABLE_GATE; const u32 stoppedGateCheck = (IOPCNT_STOPPED | altSourceCheck ); // count if alt source is enabled and either: // * the gate is enabled and not stopped. // * the gate is disabled. if( (psxCounters[1].mode & altSourceCheck) == IOPCNT_ALT_SOURCE || (psxCounters[1].mode & stoppedGateCheck ) == altSourceCheck ) { psxCounters[1].count++; _rcntTestTarget( 1 ); _rcntTestOverflow( 1 ); } if( (psxCounters[3].mode & altSourceCheck) == IOPCNT_ALT_SOURCE || (psxCounters[3].mode & stoppedGateCheck ) == altSourceCheck ) { psxCounters[3].count++; _rcntTestTarget( 3 ); _rcntTestOverflow( 3 ); } } _psxCheckStartGate( i ); }
void psxRcntUpdate() { int i; //u32 change = 0; for (i=0; i<=5; i++) { s32 change = psxRegs.cycle - psxCounters[i].sCycleT; // don't count disabled, gated, or hblank counters... // We can't check the ALTSOURCE flag because the PSXCLOCK source *should* // be counted here. if( psxCounters[i].mode & (IOPCNT_STOPPED | IOPCNT_ENABLE_GATE) ) continue; if( psxCounters[i].rate == PSXHBLANK ) continue; if( change <= 0 ) continue; psxCounters[i].count += change / psxCounters[i].rate; if(psxCounters[i].rate != 1) { change -= (change / psxCounters[i].rate) * psxCounters[i].rate; psxCounters[i].sCycleT = psxRegs.cycle - change; } else psxCounters[i].sCycleT = psxRegs.cycle; } // Do target/overflow testing // Optimization Note: This approach is very sound. Please do not try to unroll it // as the size of the Test functions will cause code cache clutter and slowness. for( i=0; i<6; i++ ) { // don't do target/oveflow checks for hblankers. Those // checks are done when the counters are updated. if( psxCounters[i].rate == PSXHBLANK ) continue; if( psxCounters[i].mode & IOPCNT_STOPPED ) continue; _rcntTestTarget( i ); _rcntTestOverflow( i ); // perform second target test because if we overflowed above it's possible we // already shot past our target if it was very near zero. //if( psxCounters[i].count >= psxCounters[i].target ) _rcntTestTarget( i ); } psxNextCounter = 0xffffff; psxNextsCounter = psxRegs.cycle; if(SPU2async) { const s32 difference = psxRegs.cycle - psxCounters[6].sCycleT; s32 c = psxCounters[6].CycleT; if(difference >= psxCounters[6].CycleT) { SPU2async(difference); psxCounters[6].sCycleT = psxRegs.cycle; psxCounters[6].CycleT = psxCounters[6].rate; } else c -= difference; psxNextCounter = c; } if(USBasync) { const s32 difference = psxRegs.cycle - psxCounters[7].sCycleT; s32 c = psxCounters[7].CycleT; if(difference >= psxCounters[7].CycleT) { USBasync(difference); psxCounters[7].sCycleT = psxRegs.cycle; psxCounters[7].CycleT = psxCounters[7].rate; } else c -= difference; if (c < psxNextCounter) psxNextCounter = c; } for (i=0; i<6; i++) _rcntSet( i ); }
void psxRcntUpdate() { int i; //u32 change = 0; g_iopNextEventCycle = psxRegs.cycle + 32; psxNextCounter = 0x7fffffff; psxNextsCounter = psxRegs.cycle; for (i=0; i<=5; i++) { s32 change = psxRegs.cycle - psxCounters[i].sCycleT; // don't count disabled or hblank counters... // We can't check the ALTSOURCE flag because the PSXCLOCK source *should* // be counted here. if( psxCounters[i].mode & IOPCNT_STOPPED ) continue; if ((psxCounters[i].mode & 0x40) && !(psxCounters[i].mode & 0x80)) { //Repeat IRQ mode Pulsed, resets a few cycles after the interrupt, this should do. psxCounters[i].mode |= 0x400; } if( psxCounters[i].rate == PSXHBLANK ) continue; if( change <= 0 ) continue; psxCounters[i].count += change / psxCounters[i].rate; if(psxCounters[i].rate != 1) { change -= (change / psxCounters[i].rate) * psxCounters[i].rate; psxCounters[i].sCycleT = psxRegs.cycle - change; } else psxCounters[i].sCycleT = psxRegs.cycle; } // Do target/overflow testing // Optimization Note: This approach is very sound. Please do not try to unroll it // as the size of the Test functions will cause code cache clutter and slowness. for( i=0; i<6; i++ ) { // don't do target/oveflow checks for hblankers. Those // checks are done when the counters are updated. if( psxCounters[i].rate == PSXHBLANK ) continue; if( psxCounters[i].mode & IOPCNT_STOPPED ) continue; _rcntTestTarget( i ); _rcntTestOverflow( i ); // perform second target test because if we overflowed above it's possible we // already shot past our target if it was very near zero. //if( psxCounters[i].count >= psxCounters[i].target ) _rcntTestTarget( i ); } if(SPU2async) { const s32 difference = psxRegs.cycle - psxCounters[6].sCycleT; s32 c = psxCounters[6].CycleT; if(difference >= psxCounters[6].CycleT) { SPU2async(difference); psxCounters[6].sCycleT = psxRegs.cycle; psxCounters[6].CycleT = psxCounters[6].rate; } else c -= difference; psxNextCounter = c; } if (DEV9async) { DEV9async(1); } if(USBasync) { const s32 difference = psxRegs.cycle - psxCounters[7].sCycleT; s32 c = psxCounters[7].CycleT; if(difference >= psxCounters[7].CycleT) { USBasync(difference); psxCounters[7].sCycleT = psxRegs.cycle; psxCounters[7].CycleT = psxCounters[7].rate; } else c -= difference; if (c < psxNextCounter) psxNextCounter = c; } #ifdef ENABLE_NEW_IOPDMA // New Iop DMA handler WIP { const s32 difference = psxRegs.cycle - psxCounters[8].sCycleT; s32 c = psxCounters[8].CycleT; if(difference >= psxCounters[8].CycleT) { psxCounters[8].sCycleT = psxRegs.cycle; psxCounters[8].CycleT = psxCounters[8].rate; IopDmaUpdate(difference); } else c -= difference; if (c < psxNextCounter) psxNextCounter = c; } #endif for (i=0; i<6; i++) _rcntSet( i ); }