Exemple #1
0
static void StartQueuedDMA()
{
	if (QueuedDMA.VIF0) { DMA_LOG("Resuming DMA for VIF0"); QueuedDMA.VIF0 = !QuickDmaExec(dmaVIF0, D0_CHCR); }
	if (QueuedDMA.VIF1) { DMA_LOG("Resuming DMA for VIF1"); QueuedDMA.VIF1 = !QuickDmaExec(dmaVIF1, D1_CHCR); }
	if (QueuedDMA.GIF ) { DMA_LOG("Resuming DMA for GIF" ); QueuedDMA.GIF  = !QuickDmaExec(dmaGIF , D2_CHCR); }
	if (QueuedDMA.IPU0) { DMA_LOG("Resuming DMA for IPU0"); QueuedDMA.IPU0 = !QuickDmaExec(dmaIPU0, D3_CHCR); }
	if (QueuedDMA.IPU1) { DMA_LOG("Resuming DMA for IPU1"); QueuedDMA.IPU1 = !QuickDmaExec(dmaIPU1, D4_CHCR); }
	if (QueuedDMA.SIF0) { DMA_LOG("Resuming DMA for SIF0"); QueuedDMA.SIF0 = !QuickDmaExec(dmaSIF0, D5_CHCR); }
	if (QueuedDMA.SIF1) { DMA_LOG("Resuming DMA for SIF1"); QueuedDMA.SIF1 = !QuickDmaExec(dmaSIF1, D6_CHCR); }
	if (QueuedDMA.SIF2) { DMA_LOG("Resuming DMA for SIF2"); QueuedDMA.SIF2 = !QuickDmaExec(dmaSIF2, D7_CHCR); }
	if (QueuedDMA.SPR0) { DMA_LOG("Resuming DMA for SPR0"); QueuedDMA.SPR0 = !QuickDmaExec(dmaSPR0, D8_CHCR); }
	if (QueuedDMA.SPR1) { DMA_LOG("Resuming DMA for SPR1"); QueuedDMA.SPR1 = !QuickDmaExec(dmaSPR1, D9_CHCR); }
}
Exemple #2
0
static __fi void Sif2End()
{
	psHu32(SBUS_F240) &= ~0x80;
	psHu32(SBUS_F240) &= ~0x8000;

	DMA_LOG("SIF2 DMA End");
}
Exemple #3
0
static __fi void Sif1End()
{
	psHu32(SBUS_F240) &= ~0x40;
	psHu32(SBUS_F240) &= ~0x4000;

	DMA_LOG("SIF1 DMA End");
}
Exemple #4
0
static __fi void Sif0End()
{
	psHu32(SBUS_F240) &= ~0x20;
	psHu32(SBUS_F240) &= ~0x2000;

	DMA_LOG("SIF0 DMA End");
}
Exemple #5
0
void SPRTOinterrupt()
{
	SPR_LOG("SPR1 Interrupt");
	if (!spr1finished || spr1ch.qwc > 0)
	{
		_dmaSPR1();
		return;
	}

	DMA_LOG("SPR1 DMA End");
	spr1ch.chcr.STR = false;
	spr1lastqwc = false;
	hwDmacIrq(DMAC_TO_SPR);
}
Exemple #6
0
void SPRFROMinterrupt()
{
	
	if (!spr0finished || spr0ch.qwc > 0) 
	{
		_dmaSPR0();

		//the qwc check is simply because having data still to transfer from the packet can freak games out if they do a d.tadr == s.madr check
		//and there is still data to come over (FF12 ingame menu)
		if(mfifotransferred != 0 && spr0ch.qwc == 0)
		{
			switch (dmacRegs.ctrl.MFD)
			{
				case MFD_VIF1: // Most common case.
				{
					if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("VIF MFIFO Write outside MFIFO area");
					spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
					//Console.WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", vif1ch.chcr._u32, vif1ch.madr, vif1ch.tadr);
					mfifoVIF1transfer(mfifotransferred);
					mfifotransferred = 0;
					break;
				}
				case MFD_GIF:
				{
					if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("GIF MFIFO Write outside MFIFO area");
					spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
					//Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
					mfifoGIFtransfer(mfifotransferred);
					mfifotransferred = 0;
					break;
				}
				default:
					break;
			}
		}
		
		return;
	}


	spr0lastqwc = false;
	spr0ch.chcr.STR = false;
	hwDmacIrq(DMAC_FROM_SPR);
	DMA_LOG("SPR0 DMA End");
}
Exemple #7
0
__fi void gifInterrupt()
{
	GIF_LOG("gifInterrupt caught!");
	if( gifRegs.stat.APATH == 3 )
	{
		gifRegs.stat.APATH = 0;
		gifRegs.stat.OPH = 0;
		if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT) 
		{
			if(gifUnit.checkPaths(1,1,0)) gifUnit.Execute(false, true);
		}

	}

	//Required for Path3 Masking timing!
	if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
			gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE;

	if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
	{
		if(vif1Regs.stat.VGW)
		{
			//Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back.
			if(!(cpuRegs.interrupt & (1<<DMAC_VIF1)))
				CPU_INT(DMAC_VIF1, 1);

			//Make sure it loops if the GIF packet is empty to prepare for the next packet
			//or end if it was the end of a packet.
			if(!gifUnit.Path3Masked() || gifch.qwc == 0) 
				CPU_INT(DMAC_GIF, 16);
			return;
		}
		
	}

	if (dmacRegs.ctrl.MFD == MFD_GIF) { // GIF MFIFO
		//Console.WriteLn("GIF MFIFO");
		gifMFIFOInterrupt();
		return;
	}	

	if (gifUnit.gsSIGNAL.queued) {
		//DevCon.WriteLn("Path 3 Paused");
		CPU_INT(DMAC_GIF, 128);
		return;
	}
	
	if (!(gifch.chcr.STR)) return;

	if ((gifch.qwc > 0) || (!gspath3done)) {
		if (!dmacRegs.ctrl.DMAE) {
			Console.Warning("gs dma masked, re-scheduling...");
			// re-raise the int shortly in the future
			CPU_INT( DMAC_GIF, 64 );
			return;
		}
		GIFdma();
		return;
	}

	gifRegs.stat.FQC = 0;
	gscycles		 = 0;
	gspath3done		 = false;
	gifch.chcr.STR	 = false;
	clearFIFOstuff(false);
	hwDmacIrq(DMAC_GIF);
	DMA_LOG("GIF DMA End");
}
Exemple #8
0
__fi void vif1Interrupt()
{
	VIF_LOG("vif1Interrupt: %8.8x chcr %x, done %x, qwc %x", cpuRegs.cycle, vif1ch.chcr._u32, vif1.done, vif1ch.qwc);

	g_vif1Cycles = 0;

	if( gifRegs.stat.APATH == 2  && gifUnit.gifPath[GIF_PATH_2].isDone())
	{
		gifRegs.stat.APATH = 0;
		gifRegs.stat.OPH = 0;
		vif1Regs.stat.VGW = false; //Let vif continue if it's stuck on a flush

		if(gifUnit.checkPaths(1,0,1)) gifUnit.Execute(false, true);
	}
	//Some games (Fahrenheit being one) start vif first, let it loop through blankness while it sets MFIFO mode, so we need to check it here.
	if (dmacRegs.ctrl.MFD == MFD_VIF1) {
		//Console.WriteLn("VIFMFIFO\n");
		// Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw.
		if (vif1ch.chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch.chcr._u32);
		vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);
		vifMFIFOInterrupt();
		return;
	}

	// We need to check the direction, if it is downloading
	// from the GS then we handle that separately (KH2 for testing)
	if (vif1ch.chcr.DIR) {
		bool isDirect   = (vif1.cmd & 0x7f) == 0x50;
		bool isDirectHL = (vif1.cmd & 0x7f) == 0x51;
		if((isDirect   && !gifUnit.CanDoPath2())
		|| (isDirectHL && !gifUnit.CanDoPath2HL())) {
			GUNIT_WARN("vif1Interrupt() - Waiting for Path 2 to be ready");
			CPU_INT(DMAC_VIF1, 128);
			if(gifRegs.stat.APATH == 3) vif1Regs.stat.VGW = 1; //We're waiting for path 3. Gunslinger II
			return;
		}
		vif1Regs.stat.VGW = 0; //Path 3 isn't busy so we don't need to wait for it.
		vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
		//Simulated GS transfer time done, clear the flags
	}
	
	if(vif1.waitforvu == true)
	{
		//DevCon.Warning("Waiting on VU1");
		//CPU_INT(DMAC_VIF1, 16);
		return;
	}
	if (!vif1ch.chcr.STR) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch.chcr._u32);

	if (vif1.irq && vif1.tag.size == 0 &&vif1.cmd == 0)
	{
		VIF_LOG("VIF IRQ Firing");
		vif1Regs.stat.INT = true;
		hwIntcIrq(VIF1intc);
		--vif1.irq;
		if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
		{
			//vif1Regs.stat.FQC = 0;

			//NFSHPS stalls when the whole packet has gone across (it stalls in the last 32bit cmd)
			//In this case VIF will end
			vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);
			if((vif1ch.qwc > 0 || !vif1.done) && !CHECK_VIF1STALLHACK)	
			{
				VIF_LOG("VIF1 Stalled");
				return;
			}
		}
	}

	vif1.vifstalled.enabled = false;

	//Mirroring change to VIF0
	if (vif1.cmd) 
	{
		if (vif1.done && (vif1ch.qwc == 0)) vif1Regs.stat.VPS = VPS_WAITING;
	}
	else		 
	{
		vif1Regs.stat.VPS = VPS_IDLE;
	}
	
	if (vif1.inprogress & 0x1)
    {
            _VIF1chain();
            // VIF_NORMAL_FROM_MEM_MODE is a very slow operation.
            // Timesplitters 2 depends on this beeing a bit higher than 128.
            if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
		
			if(!(vif1Regs.stat.VGW && gifUnit.gifPath[GIF_PATH_3].state != GIF_PATH_IDLE)) //If we're waiting on GIF, stop looping, (can be over 1000 loops!)
				CPU_INT(DMAC_VIF1, g_vif1Cycles);
            return;
    }

    if (!vif1.done)
    {

            if (!(dmacRegs.ctrl.DMAE))
            {
                    Console.WriteLn("vif1 dma masked");
                    return;
            }

            if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
            if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);

			if(!(vif1Regs.stat.VGW && gifUnit.gifPath[GIF_PATH_3].state != GIF_PATH_IDLE)) //If we're waiting on GIF, stop looping, (can be over 1000 loops!)
	            CPU_INT(DMAC_VIF1, g_vif1Cycles);
            return;
	}

	if (vif1.vifstalled.enabled && vif1.done)
	{
		DevCon.WriteLn("VIF1 looping on stall at end\n");
		CPU_INT(DMAC_VIF1, 0);
		return; //Dont want to end if vif is stalled.
	}
#ifdef PCSX2_DEVBUILD
	if (vif1ch.qwc > 0) Console.WriteLn("VIF1 Ending with %x QWC left", vif1ch.qwc);
	if (vif1.cmd != 0) Console.WriteLn("vif1.cmd still set %x tag size %x", vif1.cmd, vif1.tag.size);
#endif

	if((vif1ch.chcr.DIR == VIF_NORMAL_TO_MEM_MODE) && vif1.GSLastDownloadSize <= 16)
	{
		//Reverse fifo has finished and nothing is left, so lets clear the outputting flag
		gifRegs.stat.OPH = false;
	}

	if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);

	vif1ch.chcr.STR = false;
	vif1.vifstalled.enabled = false;
	vif1.irqoffset.enabled = false;
	if(vif1.queued_program == true) vifExecQueue(1);
	g_vif1Cycles = 0;
	DMA_LOG("VIF1 DMA End");
	hwDmacIrq(DMAC_VIF1);

}
Exemple #9
0
__fi void vif0Interrupt()
{
	VIF_LOG("vif0Interrupt: %8.8x", cpuRegs.cycle);

	g_vif0Cycles = 0;

	vif0Regs.stat.FQC = min(vif0ch.qwc, (u16)8);

	if (!(vif0ch.chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch.chcr._u32);

	if (vif0.irq && vif0.tag.size == 0 && vif0.cmd == 0)
	{
		vif0Regs.stat.INT = true;
		hwIntcIrq(VIF0intc);
		--vif0.irq;
		if (vif0Regs.stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
		{
			//vif0Regs.stat.FQC = 0;

			// One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
			//vif0ch.chcr.STR = false;
			vif0Regs.stat.FQC = min((u16)0x8, vif0ch.qwc);
			if(vif0ch.qwc > 0 || !vif0.done)	
			{
				VIF_LOG("VIF0 Stalled");
				return;
			}
		}
	}

	if(vif0.waitforvu == true)
	{
		//DevCon.Warning("Waiting on VU0");
		//CPU_INT(DMAC_VIF0, 16);
		return;
	}

	vif0.vifstalled.enabled = false;

	//Must go after the Stall, incase it's still in progress, GTC africa likes to see it still transferring.
	if (vif0.cmd) 
	{
		if(vif0.done == true && vif0ch.qwc == 0)	vif0Regs.stat.VPS = VPS_WAITING;
	}
	else		 
	{
		vif0Regs.stat.VPS = VPS_IDLE;
	}

	if (vif0.inprogress & 0x1)
	{
		_VIF0chain();
		vif0Regs.stat.FQC = min(vif0ch.qwc, (u16)8);
		CPU_INT(DMAC_VIF0, g_vif0Cycles);
		return;
	}

	if (!vif0.done)
	{

		if (!(dmacRegs.ctrl.DMAE))
		{
			Console.WriteLn("vif0 dma masked");
			return;
		}

		if ((vif0.inprogress & 0x1) == 0) vif0SetupTransfer();
		vif0Regs.stat.FQC = min(vif0ch.qwc, (u16)8);
		CPU_INT(DMAC_VIF0, g_vif0Cycles);
		return;
	}

	if (vif0.vifstalled.enabled && vif0.done)
	{
		DevCon.WriteLn("VIF0 looping on stall at end\n");
		CPU_INT(DMAC_VIF0, 0);
		return; //Dont want to end if vif is stalled.
	}
#ifdef PCSX2_DEVBUILD
	if (vif0ch.qwc > 0) Console.WriteLn("vif0 Ending with %x QWC left");
	if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size);
#endif

	vif0ch.chcr.STR = false;
	vif0Regs.stat.FQC = min((u16)0x8, vif0ch.qwc);
	vif0.vifstalled.enabled = false;
	vif0.irqoffset.enabled = false;
	if(vif0.queued_program == true) vifExecQueue(0);
	g_vif0Cycles = 0;
	hwDmacIrq(DMAC_VIF0);
	vif0Regs.stat.FQC = 0;
	DMA_LOG("VIF0 DMA End");
}