Example #1
0
__fi void dmaIPU1() // toIPU
{
	IPU_LOG("IPU1DMAStart QWC %x, MADR %x, CHCR %x, TADR %x", ipu1ch.qwc, ipu1ch.madr, ipu1ch.chcr._u32, ipu1ch.tadr);

	if (ipu1ch.pad != 0)
	{
		// Note: pad is the padding right above qwc, so we're testing whether qwc
		// has overflowed into pad.
	    DevCon.Warning(L"IPU1dma's upper 16 bits set to %x\n", ipu1ch.pad);
		ipu1ch.qwc = ipu1ch.pad = 0;
		// If we are going to clear down IPU1, we should end it too.
		// Going to test this scenario on the PS2 mind - Refraction
		ipu1ch.chcr.STR = false;
		hwDmacIrq(DMAC_TO_IPU);
	}

	if (ipu1ch.chcr.MOD == NORMAL_MODE && ipu1ch.qwc == 0) //avoids freeze when IPU1 Normal error is triggered
	{
		/*ipu1ch.chcr.STR = false;
		// Hack to force stop IPU
		ipuRegs.cmd.BUSY = 0;
		ipuRegs.ctrl.BUSY = 0;
		ipuRegs.topbusy = 0;
		//
		hwDmacIrq(DMAC_TO_IPU);*/
		IPU_LOG("IPU1 Normal error fix");
		ipu1ch.qwc = 1;
	}

	if (ipu1ch.chcr.MOD == CHAIN_MODE)  //Chain Mode
	{
		IPU_LOG("Setting up IPU1 Chain mode");
		if(ipu1ch.qwc == 0)
		{
			IPU1Status.InProgress = false;
			IPU1Status.DMAFinished = false;
		}
		else
		{   //Attempting to continue a previous chain
			IPU_LOG("Resuming DMA TAG %x", (ipu1ch.chcr.TAG >> 12));
			//We MUST check the CHCR for the tag it last knew, it can be manipulated!
			IPU1Status.ChainMode = (ipu1ch.chcr.TAG >> 12) & 0x7;
			IPU1Status.InProgress = true;
			if ((ipu1ch.chcr.tag().ID == TAG_REFE) || (ipu1ch.chcr.tag().ID == TAG_END) || (ipu1ch.chcr.tag().IRQ && ipu1ch.chcr.TIE))
			{
				IPU1Status.DMAFinished = true;
			}
			else
			{
				IPU1Status.DMAFinished = false;
			}
		}

		IPU1Status.DMAMode = DMA_MODE_CHAIN;
		IPU1dma();
	}
Example #2
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);
}
Example #3
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");
}
Example #4
0
__fi void dmaIPU0() // fromIPU
{
	if (ipu0ch.pad != 0)
	{
		// Note: pad is the padding right above qwc, so we're testing whether qwc
		// has overflowed into pad.
	    DevCon.Warning(L"IPU0dma's upper 16 bits set to %x", ipu0ch.pad);
		ipu0ch.qwc = ipu0ch.pad = 0;
		//If we are going to clear down IPU0, we should end it too. Going to test this scenario on the PS2 mind - Refraction
		ipu0ch.chcr.STR = false;
		hwDmacIrq(DMAC_FROM_IPU);
	}
	//if (dmacRegs.ctrl.STS == STS_fromIPU) DevCon.Warning("DMA Stall enabled on IPU0");
	IPU_INT_FROM( 64 );


	
}
Example #5
0
__fi void dmaIPU1() // toIPU
{
	IPU_LOG("IPU1DMAStart QWC %x, MADR %x, CHCR %x, TADR %x", ipu1dma.qwc, ipu1dma.madr, ipu1dma.chcr._u32, ipu1dma.tadr);

	if (ipu1dma.pad != 0)
	{
		// Note: pad is the padding right above qwc, so we're testing whether qwc
		// has overflowed into pad.
	    DevCon.Warning(L"IPU1dma's upper 16 bits set to %x\n", ipu1dma.pad);
		ipu1dma.qwc = ipu1dma.pad = 0;
		// If we are going to clear down IPU1, we should end it too.
		// Going to test this scenario on the PS2 mind - Refraction
		ipu1dma.chcr.STR = false;
		hwDmacIrq(DMAC_TO_IPU);
	}

	if (ipu1dma.chcr.MOD == CHAIN_MODE)  //Chain Mode
	{
		IPU_LOG("Setting up IPU1 Chain mode");
		if(ipu1dma.qwc == 0)
		{
			IPU1Status.InProgress = false;
			IPU1Status.DMAFinished = false;
		}
		else
		{   //Attempting to continue a previous chain
			IPU_LOG("Resuming DMA TAG %x", (ipu1dma.chcr.TAG >> 12));
			//We MUST check the CHCR for the tag it last knew, it can be manipulated!
			IPU1Status.ChainMode = (ipu1dma.chcr.TAG >> 12) & 0x7;
			IPU1Status.InProgress = true;
			IPU1Status.DMAFinished = ((ipu1dma.chcr.TAG >> 15) && ipu1dma.chcr.TIE) ? true : false;
		}

		IPU1Status.DMAMode = DMA_MODE_CHAIN;
		IPU1dma();
	}
Example #6
0
__fi void  EEsif2Interrupt()
{
	hwDmacIrq(DMAC_SIF2);
	sif2dma.chcr.STR = false;
}
Example #7
0
File: Sif1.cpp Project: tsiru/pcsx2
__fi void  EEsif1Interrupt()
{
	hwDmacIrq(DMAC_SIF1);
	sif1dma.chcr.STR = false;
}
Example #8
0
void GIFdma()
{
	tDMA_TAG *ptag;
	gscycles = prevcycles;

	if (gifRegs.ctrl.PSE) { // temporarily stop
		Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)");
		GifDMAInt(16);
		return;
	}

	if ((dmacRegs.ctrl.STD == STD_GIF) && (prevcycles != 0)) {
		//Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gifch.madr, psHu32(DMAC_STADR));
		if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR) {
			GifDMAInt(4);
			gscycles = 0;
			return;
		}
		prevcycles = 0;
		gifch.qwc = 0;
	}

	if ((gifch.chcr.MOD == CHAIN_MODE) && (!gspath3done) && gifch.qwc == 0) // Chain Mode
	{
        ptag = ReadTag();
        if (ptag == NULL) return;
		//DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs.mskpath3);
		GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
		if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
		if (dmacRegs.ctrl.STD == STD_GIF)
		{
			// there are still bugs, need to also check if gifch.madr +16*qwc >= stadr, if not, stall
			if ((ptag->ID == TAG_REFS) && ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR))
			{
				// stalled.
				// We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)
				//Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gifch.madr, psHu32(DMAC_STADR));
				prevcycles = gscycles;
				gifch.tadr -= 16;
				gifch.qwc = 0;
				hwDmacIrq(DMAC_STALL_SIS);
				GifDMAInt(gscycles);
				gscycles = 0;
				return;
			}
		}

		checkTieBit(ptag);
	}
	else if (dmacRegs.ctrl.STD == STD_GIF && gifch.chcr.MOD == NORMAL_MODE)
	{
		Console.WriteLn("GIF DMA Stall in Normal mode not implemented - Report which game to PCSX2 Team");
	}


	if (!CHECK_GIFFIFOHACK) {
		gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
		clearFIFOstuff(true);
	}

	// Transfer Dn_QWC from Dn_MADR to GIF
	if (gifch.qwc > 0) // Normal Mode
	{
		if (CheckPaths() == false) return;

		GIFchain();	//Transfers the data set by the switch
		//if (gscycles < 8) DevCon.Warning("GSCycles = %d", gscycles);
		GifDMAInt(gscycles);
		return;
	} else if(!gspath3done) GIFdma(); //Loop round if there was a blank tag, causes hell otherwise with P3 masking games.

	//QWC == 0 && gspath3done == true - End of DMA
	prevcycles = 0;
	//if (gscycles < 8) DevCon.Warning("1 GSCycles = %d", gscycles);
	GifDMAInt(16);
}
Example #9
0
__fi void gifInterrupt()
{
	GIF_LOG("gifInterrupt caught!");
	gifCheckPathStatus();

	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.
			//This must trigger after VIF retriggers as VIf might instantly mask Path3
			if (!gifUnit.Path3Masked() || gifch.qwc == 0) {
				GifDMAInt(16);
			}
			return;
		}
		
	}

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

	if (CHECK_GIFFIFOHACK) {

		if (int amtRead = gif_fifo.read(true)) {

			if (!gifUnit.Path3Masked() || gifRegs.stat.FQC < 16) {
				GifDMAInt(amtRead * BIAS);
				return;
			}
		}
		else {

			if (!gifUnit.CanDoPath3() && gifRegs.stat.FQC == 16)
			{
				if (gifch.qwc > 0 || gspath3done == false) {
					if (!gifUnit.Path3Masked()) {
						GifDMAInt(128);
					}
					return;
				}
			}
		}
	}
	

	if (gifUnit.gsSIGNAL.queued) {
		GIF_LOG("Path 3 Paused");
		GifDMAInt(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
			GifDMAInt( 64 );
			return;
		}
		GIFdma();
		
		return;
	}

	//Double check as we might have read the fifo as it's ending the DMA
	gifCheckPathStatus();

	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);
			}
		}
	}
	if (!CHECK_GIFFIFOHACK)
	{
		gifRegs.stat.FQC = 0;
		clearFIFOstuff(false);
	}
	gscycles		 = 0;
	gspath3done		 = false;
	gifch.chcr.STR	 = false;

	hwDmacIrq(DMAC_GIF);
	GIF_LOG("GIF DMA End QWC in fifo %x APATH = %x OPH = %x state = %x", gifRegs.stat.FQC, gifRegs.stat.APATH, gifRegs.stat.OPH, gifUnit.gifPath[GIF_PATH_3].state);
}
Example #10
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");
}
Example #11
0
__fi void  EEsif0Interrupt()
{
	hwDmacIrq(DMAC_SIF0);
	sif0dma.chcr.STR = false;
}
Example #12
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);

}
Example #13
0
__fi void vif1SetupTransfer()
{
    tDMA_TAG *ptag;
	
	switch (vif1.dmamode)
	{
		case VIF_CHAIN_MODE:
			ptag = dmaGetAddr(vif1ch.tadr, false); //Set memory pointer to TADR

			if (!(vif1ch.transfer("Vif1 Tag", ptag))) return;

			vif1ch.madr = ptag[1]._u32;            //MADR = ADDR field + SPR
			g_vif1Cycles += 1; // Add 1 g_vifCycles from the QW read for the tag

			VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
			        ptag[1]._u32, ptag[0]._u32, vif1ch.qwc, ptag->ID, vif1ch.madr, vif1ch.tadr);

			if (!vif1.done && ((dmacRegs.ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS)))   // STD == VIF1
			{
				// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
				if ((vif1ch.madr + vif1ch.qwc * 16) >= dmacRegs.stadr.ADDR)
				{
					// stalled
					hwDmacIrq(DMAC_STALL_SIS);
					return;
				}
			}

			
			vif1.inprogress &= ~1;

			if (vif1ch.chcr.TTE)
			{
				// Transfer dma tag if tte is set

			    bool ret;

				static __aligned16 u128 masked_tag;
				
				masked_tag._u64[0] = 0;
				masked_tag._u64[1] = *((u64*)ptag + 1);

				VIF_LOG("\tVIF1 SrcChain TTE=1, data = 0x%08x.%08x", masked_tag._u32[3], masked_tag._u32[2]);

				if (vif1.irqoffset.enabled)
				{
					ret = VIF1transfer((u32*)&masked_tag + vif1.irqoffset.value, 4 - vif1.irqoffset.value, true);  //Transfer Tag on stall
					//ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset);  //Transfer Tag on stall
				}
				else
				{
					//Some games (like killzone) do Tags mid unpack, the nops will just write blank data
					//to the VU's, which breaks stuff, this is where the 128bit packet will fail, so we ignore the first 2 words
					vif1.irqoffset.value = 2;
					vif1.irqoffset.enabled = true;
					ret = VIF1transfer((u32*)&masked_tag + 2, 2, true);  //Transfer Tag
					//ret = VIF1transfer((u32*)ptag + 2, 2);  //Transfer Tag
				}
				
				if (!ret && vif1.irqoffset.enabled)
				{
					vif1.inprogress &= ~1; //Better clear this so it has to do it again (Jak 1)
					return;        //IRQ set by VIFTransfer
				}
			}
			vif1.irqoffset.value = 0;
			vif1.irqoffset.enabled = false;

			vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID);

			if(vif1ch.qwc > 0) vif1.inprogress |= 1;

			//Check TIE bit of CHCR and IRQ bit of tag
			if (vif1ch.chcr.TIE && ptag->IRQ)
			{
				VIF_LOG("dmaIrq Set");

                //End Transfer
				vif1.done = true;
				return;
			}
		break;
	}
}
Example #14
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");
}