コード例 #1
0
ファイル: IopCounters.cpp プロジェクト: 0xZERO3/PCSX2-rr-lua
void psxRcnt0Wmode(u32 value)
{
	PSXCNT_LOG("IOP Counter[0] writeMode = %lx\n", value);

	psxCounters[0].mode = value;
	psxCounters[0].mode|= 0x0400;
	psxCounters[0].rate = 1;

	if(value & IOPCNT_ALT_SOURCE)
		psxCounters[0].rate = PSXPIXEL;
	
	if(psxCounters[0].mode & IOPCNT_ENABLE_GATE)
	{
		// gated counters are added up as per the h/vblank timers.
		PSXCNT_LOG("IOP Counter[0] Gate Check set, value = %x\n", value);
		psxhblankgate |= 1;
	}
	else psxhblankgate &= ~1;

	psxCounters[0].count = 0;
	psxCounters[0].sCycleT = psxRegs.cycle;
	psxCounters[0].target &= 0xffff;

	_rcntSet( 0 );
}
コード例 #2
0
ファイル: IopCounters.cpp プロジェクト: 0xZERO3/PCSX2-rr-lua
void psxRcnt5Wmode(u32 value)
{
	PSXCNT_LOG("IOP Counter[5] writeMode = %lx\n", value);

	psxCounters[5].mode = value;
	psxCounters[5].mode|= 0x0400;

	switch(value & 0x6000)
	{
		case 0x0000: psxCounters[5].rate = 1; break;
		case 0x2000: psxCounters[5].rate = 8; break;
		case 0x4000: psxCounters[5].rate = 16; break;
		case 0x6000: psxCounters[5].rate = 256; break;
	}
	// Need to set a rate and target
	if((psxCounters[5].mode & 0x7) == 0x7 || (psxCounters[5].mode & 0x7) == 0x1)
	{
		SysPrintf("Gate set on IOP C5, disabling\n");
		psxCounters[5].mode |= IOPCNT_STOPPED;
	}
	
	psxCounters[5].count = 0;
	psxCounters[5].sCycleT = psxRegs.cycle;
	psxCounters[5].target &= 0xffffffff;
	_rcntSet( 5 );
}
コード例 #3
0
ファイル: IopCounters.cpp プロジェクト: 0xZERO3/PCSX2-rr-lua
static void _psxCheckStartGate( int i )
{
	if(!(psxCounters[i].mode & IOPCNT_ENABLE_GATE)) return; //Ignore Gate

	switch((psxCounters[i].mode & 0x6) >> 1)
	{
		case 0x0: //GATE_ON_count - stop count on gate start:

			// get the current count at the time of stoppage:
			psxCounters[i].count = ( i < 3 ) ? 
				psxRcntRcount16( i ) : psxRcntRcount32( i );
			psxCounters[i].mode |= IOPCNT_STOPPED;
		return;

		case 0x1: //GATE_ON_ClearStart - count normally with resets after every end gate
			// do nothing - All counting will be done on a need-to-count basis.
		return;

		case 0x2: //GATE_ON_Clear_OFF_Start - start counting on gate start, stop on gate end
			psxCounters[i].count = 0;
			psxCounters[i].sCycleT = psxRegs.cycle;
			psxCounters[i].mode &= ~IOPCNT_STOPPED;
		break;

		case 0x3: //GATE_ON_Start - start and count normally on gate end (no restarts or stops or clears)
			// do nothing!
		return;
	}
	_rcntSet( i );
}
コード例 #4
0
ファイル: IopCounters.cpp プロジェクト: 0xZERO3/PCSX2-rr-lua
static void _psxCheckEndGate(int i)
{
	if(!(psxCounters[i].mode & IOPCNT_ENABLE_GATE)) return; //Ignore Gate

	switch((psxCounters[i].mode & 0x6) >> 1)
	{
		case 0x0: //GATE_ON_count - reset and start counting
		case 0x1: //GATE_ON_ClearStart - count normally with resets after every end gate
			psxCounters[i].count = 0;
			psxCounters[i].sCycleT = psxRegs.cycle;
			psxCounters[i].mode &= ~IOPCNT_STOPPED;
		break;

		case 0x2: //GATE_ON_Clear_OFF_Start - start counting on gate start, stop on gate end
			psxCounters[i].count = ( i < 3 ) ? 
				psxRcntRcount16( i ) : psxRcntRcount32( i );
			psxCounters[i].mode |= IOPCNT_STOPPED;
		return;	// do not set the counter

		case 0x3: //GATE_ON_Start - start and count normally (no restarts or stops or clears)
			if( psxCounters[i].mode & IOPCNT_STOPPED )
			{
				psxCounters[i].count = 0;
				psxCounters[i].sCycleT = psxRegs.cycle;
				psxCounters[i].mode &= ~IOPCNT_STOPPED;
			}
		break;
	}
	_rcntSet( i );
}
コード例 #5
0
ファイル: IopCounters.cpp プロジェクト: aerisarn/pcsx2
void psxRcntWcount32(int index, u32 value)
{
	u32 change;

	pxAssert( index >= 3 && index < 6 );
	PSXCNT_LOG("32bit IOP Counter[%d] writeCount32 = %x", index, value);

	if(psxCounters[index].rate != PSXHBLANK)
	{
		// Re-adjust the sCycleT to match where the counter is currently
		// (remainder of the rate divided into the time passed will do the trick)

		change = psxRegs.cycle - psxCounters[index].sCycleT;
		psxCounters[index].sCycleT = psxRegs.cycle - (change % psxCounters[index].rate);
	}

	psxCounters[index].count = value;
	if ((psxCounters[index].mode & 0x400) || (psxCounters[index].mode & 0x40)) { //IRQ not triggered (one shot) or toggle
		psxCounters[index].target &= 0xffffffff;
	}
	if (value > psxCounters[index].target) {//Count already higher than Target
		//DevCon.Warning("32bit Count already higher than target");
		psxCounters[index].target |= IOPCNT_FUTURE_TARGET;
	}
	_rcntSet( index );
}
コード例 #6
0
ファイル: IopCounters.cpp プロジェクト: Anoth3rone/pcsx2
__fi void psxRcntWmode16( int index, u32 value )
{
	PSXCNT_LOG( "IOP Counter[%d] writeMode = 0x%04X", index, value );

	pxAssume( index >= 0 && index < 3 );
	psxCounter& counter = psxCounters[index];

	counter.mode  = value;
	counter.mode |= 0x0400;

	if( index == 2 )
	{
		switch(value & 0x200)
		{
		case 0x000: psxCounters[2].rate = 1; break;
		case 0x200: psxCounters[2].rate = 8; break;
			jNO_DEFAULT;
		}

		if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
		{
			counter.mode |= IOPCNT_STOPPED;
		}
	}
	else
	{
		// Counters 0 and 1 can select PIXEL or HSYNC as an alternate source:
		counter.rate = 1;

		if(value & IOPCNT_ALT_SOURCE)
			counter.rate = (index==0) ? PSXPIXEL : PSXHBLANK;

		if(counter.mode & IOPCNT_ENABLE_GATE)
		{
			// gated counters are added up as per the h/vblank timers.
			// (the PIXEL alt source becomes a vsync gate)
			counter.mode |= IOPCNT_STOPPED;
			PSXCNT_LOG( "IOP Counter[%d] Gate Check set, value = 0x%04X", index, value );
			if( index == 0 )
				psxhblankgate |= 1;		// fixme: these gate flags should be one var >_<
			else
				psxvblankgate |= 1<<1;
		}
		else
		{
			if( index == 0 )
				psxhblankgate &= ~1;
			else
				psxvblankgate &= ~(1<<1);
		}
	}

	counter.count = 0;
	counter.sCycleT = psxRegs.cycle;
	counter.target &= 0xffff;

	_rcntSet( index );
}
コード例 #7
0
ファイル: IopCounters.cpp プロジェクト: 0xZERO3/PCSX2-rr-lua
void psxRcntWtarget16(int index, u32 value)
{
	assert( index < 3 );
	PSXCNT_LOG("IOP Counter[%d] writeTarget16 = %lx\n", index, value);
	psxCounters[index].target = value & 0xffff;

	// protect the target from an early arrival.
	// if the target is behind the current count, then set the target overflow
	// flag, so that the target won't be active until after the next overflow.
	
	if(psxCounters[index].target <= psxRcntCycles(index))
		psxCounters[index].target |= IOPCNT_FUTURE_TARGET;

	_rcntSet( index );
}
コード例 #8
0
ファイル: IopCounters.cpp プロジェクト: aerisarn/pcsx2
void psxRcntWtarget16(int index, u32 value)
{
	pxAssert( index < 3 );
	//DevCon.Warning("IOP Counter[%d] writeTarget16 = %lx", index, value);
	psxCounters[index].target = value & 0xffff;

	// protect the target from an early arrival.
	// if the target is behind the current count, then set the target overflow
	// flag, so that the target won't be active until after the next overflow.

	if(psxCounters[index].target <= psxRcntCycles(index) || ((psxCounters[index].mode & 0x400) == 0 && !(psxCounters[index].mode & 0x40)))
		psxCounters[index].target |= IOPCNT_FUTURE_TARGET;

	_rcntSet( index );
}
コード例 #9
0
ファイル: IopCounters.cpp プロジェクト: Anoth3rone/pcsx2
__fi void psxRcntWmode32( int index, u32 value )
{
	PSXCNT_LOG( "IOP Counter[%d] writeMode = 0x%04x", index, value );

	pxAssume( index >= 3 && index < 6 );
	psxCounter& counter = psxCounters[index];

	counter.mode  = value;
	counter.mode |= 0x0400;

	if( index == 3 )
	{
		// Counter 3 has the HBlank as an alternate source.
		counter.rate  = 1;
		if(value & IOPCNT_ALT_SOURCE)
			counter.rate = PSXHBLANK;

		if(counter.mode & IOPCNT_ENABLE_GATE)
		{
			PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value);
			counter.mode |= IOPCNT_STOPPED;
			psxvblankgate |= 1<<3;
		}
		else psxvblankgate &= ~(1<<3);
	}
	else
	{
		switch(value & 0x6000)
		{
		case 0x0000: counter.rate = 1;   break;
		case 0x2000: counter.rate = 8;   break;
		case 0x4000: counter.rate = 16;  break;
		case 0x6000: counter.rate = 256; break;
		}

		// Need to set a rate and target
		if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
		{
			Console.WriteLn( "Gate set on IOP Counter %d, disabling", index );
			counter.mode |= IOPCNT_STOPPED;
		}
	}

	counter.count = 0;
	counter.sCycleT = psxRegs.cycle;
	counter.target &= 0xffffffff;
	_rcntSet( index );
}
コード例 #10
0
ファイル: IopCounters.cpp プロジェクト: aerisarn/pcsx2
void psxRcntWtarget32(int index, u32 value)
{
	pxAssert( index >= 3 && index < 6);
	//DevCon.Warning("IOP Counter[%d] writeTarget32 = %lx mode %x", index, value, psxCounters[index].mode);

	psxCounters[index].target = value;
	if (!(psxCounters[index].mode & 0x80)) { //Toggle mode
		psxCounters[index].mode |= 0x0400; // Interrupt flag set low
	}
	// protect the target from an early arrival.
	// if the target is behind the current count, then set the target overflow
	// flag, so that the target won't be active until after the next overflow.

	if (psxCounters[index].target <= psxRcntCycles(index) || ((psxCounters[index].mode & 0x400) == 0 && !(psxCounters[index].mode & 0x40)))
		psxCounters[index].target |= IOPCNT_FUTURE_TARGET;

	_rcntSet( index );
}
コード例 #11
0
ファイル: IopCounters.cpp プロジェクト: 0xZERO3/PCSX2-rr-lua
void psxRcntWcount32(int index, u32 value)
{
	u32 change;

	assert( index >= 3 && index < 6 );
	PSXCNT_LOG("IOP Counter[%d] writeCount32 = %x\n", index, value);
	
	if(psxCounters[index].rate != PSXHBLANK)
	{
		// Re-adjust the sCycleT to match where the counter is currently
		// (remainder of the rate divided into the time passed will do the trick)

		change = psxRegs.cycle - psxCounters[index].sCycleT;
		psxCounters[index].sCycleT = psxRegs.cycle - (change % psxCounters[index].rate);
	}

	psxCounters[index].count = value & 0xffffffff;
	psxCounters[index].target &= 0xffffffff;	
	_rcntSet( index );
}
コード例 #12
0
ファイル: IopCounters.cpp プロジェクト: 0xZERO3/PCSX2-rr-lua
void psxRcnt3Wmode(u32 value)
{
	PSXCNT_LOG("IOP Counter[3] writeMode = %lx\n", value);

	psxCounters[3].mode = value;
	psxCounters[3].rate = 1;
	psxCounters[3].mode|= 0x0400;

	if(value & IOPCNT_ALT_SOURCE)
		psxCounters[3].rate = PSXHBLANK;
  
	if(psxCounters[3].mode & IOPCNT_ENABLE_GATE)
	{
		PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x\n", value);
		psxvblankgate |= 1<<3;
	}
	else psxvblankgate &= ~(1<<3);

	psxCounters[3].count = 0;
	psxCounters[3].sCycleT = psxRegs.cycle;
	psxCounters[3].target &= 0xffffffff;
	_rcntSet( 3 );
}
コード例 #13
0
ファイル: IopCounters.cpp プロジェクト: 0xZERO3/PCSX2-rr-lua
void psxRcnt2Wmode(u32 value)
{
	PSXCNT_LOG("IOP Counter[0] writeMode = %lx\n", value);

	psxCounters[2].mode = value;
	psxCounters[2].mode|= 0x0400;

	switch(value & 0x200)
	{
		case 0x200: psxCounters[2].rate = 8; break;
		case 0x000: psxCounters[2].rate = 1; break;
	}

	if((psxCounters[2].mode & 0x7) == 0x7 || (psxCounters[2].mode & 0x7) == 0x1)
	{
		//SysPrintf("Gate set on IOP C2, disabling\n");
		psxCounters[2].mode |= IOPCNT_STOPPED;
	}
	
	psxCounters[2].count = 0;
	psxCounters[2].sCycleT = psxRegs.cycle;
	psxCounters[2].target &= 0xffff;
	_rcntSet( 2 );
}
コード例 #14
0
ファイル: IopCounters.cpp プロジェクト: 0xZERO3/PCSX2-rr-lua
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 );
}
コード例 #15
0
ファイル: IopCounters.cpp プロジェクト: aerisarn/pcsx2
__fi void psxRcntWmode32( int index, u32 value )
{
	PSXCNT_LOG("32bit IOP Counter[%d] writeMode = 0x%04x", index, value );
	int irqmode = 0;
	pxAssume( index >= 3 && index < 6 );
	psxCounter& counter = psxCounters[index];

	counter.mode  = value;
	counter.mode |= 0x0400; //IRQ enable

	if (value & (1 << 4)) {
		irqmode += 1;
	}
	if (value & (1 << 5)) {
		irqmode += 2;
	}
	if (value & (1 << 7)) {
		PSXCNT_LOG("32 Counter %d Toggle IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow"));
	}
	else
	{
		PSXCNT_LOG("32 Counter %d Pulsed IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow"));
	}
	if (!(value & (1 << 6))) {
		PSXCNT_LOG("32 Counter %d One Shot", index);
	}
	else {
		PSXCNT_LOG("32 Counter %d Repeat", index);
	}
	if( index == 3 )
	{
		// Counter 3 has the HBlank as an alternate source.
		counter.rate  = 1;
		if(value & IOPCNT_ALT_SOURCE)
			counter.rate = PSXHBLANK;

		if(counter.mode & IOPCNT_ENABLE_GATE)
		{
			PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value);
			counter.mode |= IOPCNT_STOPPED;
			psxvblankgate |= 1<<3;
		}
		else psxvblankgate &= ~(1<<3);
	}
	else
	{
		switch(value & 0x6000)
		{
		case 0x0000: counter.rate = 1;   break;
		case 0x2000: counter.rate = 8;   break;
		case 0x4000: counter.rate = 16;  break;
		case 0x6000: counter.rate = 256; break;
		}

		// Need to set a rate and target
		if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
		{
			Console.WriteLn( "Gate set on IOP Counter %d, disabling", index );
			counter.mode |= IOPCNT_STOPPED;
		}
	}

	counter.count = 0;
	counter.sCycleT = psxRegs.cycle;
	counter.target &= 0xffffffff;
	_rcntSet( index );
}
コード例 #16
0
ファイル: IopCounters.cpp プロジェクト: aerisarn/pcsx2
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 );
}