Пример #1
0
int  _SPR0chain()
{
	tDMA_TAG *pMem;
	int partialqwc = 0;
	if (spr0ch.qwc == 0) return 0;
	pMem = SPRdmaGetAddr(spr0ch.madr, true);
	if (pMem == NULL) return -1;

	switch (dmacRegs.ctrl.MFD)
	{
		case MFD_VIF1:
		case MFD_GIF:
			partialqwc = spr0ch.qwc;

			if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR)
				Console.WriteLn("SPR MFIFO Write outside MFIFO area");
			else
				mfifotransferred += partialqwc;

			hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), partialqwc);
			spr0ch.madr += partialqwc << 4;
			spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
			spr0ch.sadr += partialqwc << 4;
			spr0ch.qwc -= partialqwc;
			break;

		case NO_MFD:
		case MFD_RESERVED:
			
			//Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of
			//the cycle delay out of the way before the end.
			partialqwc = spr0ch.qwc;
			memcpy_qwc(pMem, &psSu128(spr0ch.sadr), partialqwc);

			// clear VU mem also!
			TestClearVUs(spr0ch.madr, partialqwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes)

			spr0ch.madr += partialqwc << 4;
			spr0ch.sadr += partialqwc << 4;
			spr0ch.qwc -= partialqwc;

			break;
	}

	

	return (partialqwc); // bus is 1/2 the ee speed
}
Пример #2
0
int  _SPR0chain()
{
	tDMA_TAG *pMem;
	int partialqwc = 0;
	if (spr0ch.qwc == 0) return 0;
	pMem = SPRdmaGetAddr(spr0ch.madr, true);
	if (pMem == NULL) return -1;

	if(spr0ch.madr >= dmacRegs.rbor.ADDR && spr0ch.madr < (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
	{
			partialqwc = spr0ch.qwc;

			if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR)
				Console.WriteLn("SPR MFIFO Write outside MFIFO area");
			else
				mfifotransferred += partialqwc;

			hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), partialqwc);
			spr0ch.madr += partialqwc << 4;
			spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
			spr0ch.sadr += partialqwc << 4;
			spr0ch.qwc -= partialqwc;
			
			spr0finished = true;
	}
	else
	{
			
			//Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of
			//the cycle delay out of the way before the end.
			partialqwc = spr0ch.qwc;
			memcpy_qwc(pMem, &psSu128(spr0ch.sadr), partialqwc);

			// clear VU mem also!
			TestClearVUs(spr0ch.madr, partialqwc);

			spr0ch.madr += partialqwc << 4;
			spr0ch.sadr += partialqwc << 4;
			spr0ch.qwc -= partialqwc;

	}

	

	return (partialqwc); // bus is 1/2 the ee speed
}
Пример #3
0
void _SPR0interleave()
{
	int qwc = spr0ch.qwc;
	int sqwc = dmacRegs.sqwc.SQWC;
	int tqwc = dmacRegs.sqwc.TQWC;
	tDMA_TAG *pMem;

	if (tqwc == 0) tqwc = qwc;
	//Console.WriteLn("dmaSPR0 interleave");
	SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
	        spr0ch.qwc, tqwc, sqwc, spr0ch.madr, spr0ch.sadr);

	CPU_INT(DMAC_FROM_SPR, qwc * BIAS);

	while (qwc > 0)
	{
		spr0ch.qwc = std::min(tqwc, qwc);
		qwc -= spr0ch.qwc;
		pMem = SPRdmaGetAddr(spr0ch.madr, true);

		switch (dmacRegs.ctrl.MFD)
 		{
			case MFD_VIF1:
			case MFD_GIF:
				hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), spr0ch.qwc);
				mfifotransferred += spr0ch.qwc;
				break;

			case NO_MFD:
			case MFD_RESERVED:
				// clear VU mem also!
				TestClearVUs(spr0ch.madr, spr0ch.qwc);
				memcpy_qwc(pMem, &psSu128(spr0ch.sadr), spr0ch.qwc);
				break;
 		}
		spr0ch.sadr += spr0ch.qwc * 16;
		spr0ch.madr += (sqwc + spr0ch.qwc) * 16;
	}

	spr0ch.qwc = 0;
}
Пример #4
0
int  _SPR1chain()
{
	tDMA_TAG *pMem;

	if (spr1ch.qwc == 0) return 0;

	pMem = SPRdmaGetAddr(spr1ch.madr, false);
	if (pMem == NULL) return -1;
	int partialqwc = 0;
	//Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of
	//the cycle delay out of the way before the end.
	partialqwc = spr1ch.qwc;

	SPR1transfer(pMem, partialqwc);
	spr1ch.madr += partialqwc * 16;
	spr1ch.qwc -= partialqwc;

	hwDmacSrcTadrInc(spr1ch);
	
	return (partialqwc);
}
Пример #5
0
void _SPR1interleave()
{
	int qwc = spr1ch.qwc;
	int sqwc = dmacRegs.sqwc.SQWC;
	int tqwc =  dmacRegs.sqwc.TQWC;
	tDMA_TAG *pMem;

	if (tqwc == 0) tqwc = qwc;
	SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
	        spr1ch.qwc, tqwc, sqwc, spr1ch.madr, spr1ch.sadr);
	CPU_INT(DMAC_TO_SPR, qwc * BIAS);
	while (qwc > 0)
	{
		spr1ch.qwc = std::min(tqwc, qwc);
		qwc -= spr1ch.qwc;
		pMem = SPRdmaGetAddr(spr1ch.madr, false);
		memcpy_qwc(&psSu128(spr1ch.sadr), pMem, spr1ch.qwc);
		spr1ch.sadr += spr1ch.qwc * 16;
		spr1ch.madr += (sqwc + spr1ch.qwc) * 16;
	}

	spr1ch.qwc = 0;
}
Пример #6
0
void _dmaSPR1()   // toSPR work function
{
	switch(spr1ch.chcr.MOD)
	{
		case NORMAL_MODE:
		{
			//int cycles = 0;
			// Transfer Dn_QWC from Dn_MADR to SPR1
			SPR1chain();
			spr1finished = true;
			return;
		}
		case CHAIN_MODE:
		{
			tDMA_TAG *ptag;
			bool done = false;

			if (spr1ch.qwc > 0)
			{
				SPR_LOG("spr1 Normal or in Progress size=%d, addr=%lx taddr=%lx saddr=%lx", spr1ch.qwc, spr1ch.madr, spr1ch.tadr, spr1ch.sadr);
				// Transfer Dn_QWC from Dn_MADR to SPR1
				SPR1chain();
				return;
			}
			// Chain Mode

			ptag = SPRdmaGetAddr(spr1ch.tadr, false);		//Set memory pointer to TADR

			if (!spr1ch.transfer("SPR1 Tag", ptag))
			{
				done = true;
				spr1finished = done;
			}

			spr1ch.madr = ptag[1]._u32;						//MADR = ADDR field + SPR

			// Transfer dma tag if tte is set
			if (spr1ch.chcr.TTE)
			{
				SPR_LOG("SPR TTE: %x_%x\n", ptag[3]._u32, ptag[2]._u32);
				SPR1transfer(ptag, 1);				//Transfer Tag
			}

			SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx taddr=%lx saddr=%lx",
				ptag[1]._u32, ptag[0]._u32, spr1ch.qwc, ptag->ID, spr1ch.madr, spr1ch.tadr, spr1ch.sadr);

			done = (hwDmacSrcChain(spr1ch, ptag->ID));
			SPR1chain();										//Transfers the data set by the switch

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

				//Console.WriteLn("SPR1 TIE");
				done = true;
			}

			spr1finished = done;
			break;
		}
		//case INTERLEAVE_MODE:
		default:
		{
			_SPR1interleave();
			spr1finished = true;
			break;
		}
	}
}