コード例 #1
0
ファイル: LegacyDmac.cpp プロジェクト: mauzus/progenitor
// Returns true if the DMA is enabled and executed successfully.  Returns false if execution
// was blocked (DMAE or master DMA enabler).
static bool QuickDmaExec( void (*func)(), u32 mem)
{
	bool ret = false;
    DMACh& reg = (DMACh&)psHu32(mem);

	if (reg.chcr.STR && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
	{
		func();
		ret = true;
	}

	return ret;
}
コード例 #2
0
ファイル: LegacyDmac.cpp プロジェクト: mauzus/progenitor
static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
{
	DMACh& reg = (DMACh&)psHu32(mem);
    tDMA_CHCR chcr(value);

	//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
	if (reg.chcr.STR)
	{
		const uint channel = ChannelNumber(mem);

		if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything
		{
			//If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.
			if(chcr.STR == 0)
			{
				//DevCon.Warning(L"32bit %s DMA Stopped on Suspend", ChcrName(mem));
				if(channel == 1)
				{
					cpuClearInt( 10 );
					QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
				}
				else if(channel == 2)
				{
					cpuClearInt( 11 );
					QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
				}
				
				cpuClearInt( channel );
				QueuedDMA._u16 &= ~(1 << channel); //Clear any queued DMA requests for this channel
			}
			//Sanity Check for possible future bug fix0rs ;p
			//Spams on Persona 4 opening.
			//if(reg.chcr.TAG != chcr.TAG) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Active", ChcrName(mem), chcr.TAG, reg.chcr.TAG, reg.qwc);
			//Here we update the LOWER CHCR, if a chain is stopped half way through, it can be manipulated in to a different mode
			//But we need to preserve the existing tag for now
			reg.chcr.set((reg.chcr.TAG << 16) | chcr.lower());
			return;
		}
		else //Else the DMA is running (Not Suspended), so we cant touch it!
		{
			//As the manual states "Fields other than STR can only be written to when the DMA is stopped"
			//Also "The DMA may not stop properly just by writing 0 to STR"
			//So the presumption is that STR can be written to (ala force stop the DMA) but nothing else

			if(chcr.STR == 0)
			{
				//DevCon.Warning(L"32bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg.chcr._u32, chcr._u32);
				reg.chcr.STR = 0;
				//We need to clear any existing DMA loops that are in progress else they will continue!

				if(channel == 1)
				{
					cpuClearInt( 10 );
					QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
				}
				else if(channel == 2)
				{
					cpuClearInt( 11 );
					QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
				}
				
				cpuClearInt( channel );
				QueuedDMA._u16 &= ~(1 << channel); //Clear any queued DMA requests for this channel
			}
			//else DevCon.Warning(L"32bit Attempted to change %s CHCR (Currently %x) with %x while DMA active, ignoring QWC = %x", ChcrName(mem), reg.chcr._u32, chcr._u32, reg.qwc);
			return;
		}

	}

	//if(reg.chcr.TAG != chcr.TAG && chcr.MOD == CHAIN_MODE) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Not Active", ChcrName(mem), chcr.TAG, reg.chcr.TAG, reg.qwc);

	reg.chcr.set(value);

	if (reg.chcr.STR && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
	{
		func();
	}
	else if(reg.chcr.STR)
	{
		//DevCon.Warning(L"32bit %s DMA Start while DMAC Disabled\n", ChcrName(mem));
		QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
	} //else QueuedDMA._u16 &~= (1 << ChannelNumber(mem)); //
}
コード例 #3
0
ファイル: LegacyDmac.cpp プロジェクト: AmbientMalice/pcsx2
static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
{
	DMACh& reg = (DMACh&)psHu32(mem);
    tDMA_CHCR chcr(value);

	//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
	if (reg.chcr.STR)
	{
		const uint channel = ChannelNumber(mem);

		//As the manual states "Fields other than STR can only be written to when the DMA is stopped"
		//Also "The DMA may not stop properly just by writing 0 to STR"
		//So the presumption is that STR can be written to (ala force stop the DMA) but nothing else
		//If the developer wishes to alter any of the other fields, it must be done AFTER the STR has been written,
		//it will not work before or during this event.
		if(chcr.STR == 0)
		{
			//DevCon.Warning(L"32bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg.chcr._u32, chcr._u32);
			reg.chcr.STR = 0;
			//We need to clear any existing DMA loops that are in progress else they will continue!

			if(channel == 1)
			{
				cpuClearInt( 10 );
				QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
			}
			else if(channel == 2)
			{
				cpuClearInt( 11 );
				QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
			}
				
			cpuClearInt( channel );
			QueuedDMA._u16 &= ~(1 << channel); //Clear any queued DMA requests for this channel
		}
		//else DevCon.Warning(L"32bit Attempted to change %s CHCR (Currently %x) with %x while DMA active, ignoring QWC = %x", ChcrName(mem), reg.chcr._u32, chcr._u32, reg.qwc);
		return;
	}

	//if(reg.chcr.TAG != chcr.TAG && chcr.MOD == CHAIN_MODE) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Not Active", ChcrName(mem), chcr.TAG, reg.chcr.TAG, reg.qwc);

	reg.chcr.set(value);

	//Final Fantasy XII sets the DMA Mode to 3 which doesn't exist. On some channels (like SPR) this will break logic completely. so lets assume they mean chain.
	if (reg.chcr.MOD == 0x3)
	{
		static bool warned; //Check if the warning has already been output to console, to prevent constant spam.
		if (!warned)
		{
			DevCon.Warning(L"%s CHCR.MOD set to 3, assuming 1 (chain)", ChcrName(mem));
			warned = true;
		}
		reg.chcr.MOD = 0x1;
	}
	if (reg.chcr.STR && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
	{
		func();
	}
	else if(reg.chcr.STR)
	{
		//DevCon.Warning(L"32bit %s DMA Start while DMAC Disabled\n", ChcrName(mem));
		QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
	} //else QueuedDMA._u16 &~= (1 << ChannelNumber(mem)); //
}