Example #1
0
// Read Fifo into an ee tag, transfer it to sif2dma, and process it.
static __fi bool ProcessEETag()
{
	static __aligned16 u32 tag[4];
	tDMA_TAG& ptag(*(tDMA_TAG*)tag);

	sif2.fifo.read((u32*)&tag[0], 4); // Tag
	SIF_LOG("SIF2 EE read tag: %x %x %x %x", tag[0], tag[1], tag[2], tag[3]);

	sif2dma.unsafeTransfer(&ptag);
	sif2dma.madr = tag[1];

	SIF_LOG("SIF2 EE dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)",
		sif2dma.madr, sif2dma.qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);

	if (sif2dma.chcr.TIE && ptag.IRQ)
	{
		//Console.WriteLn("SIF2 TIE");
		sif2.ee.end = true;
	}

	switch (ptag.ID)
	{
	case TAG_CNT:	break;

	case TAG_CNTS:
		break;

	case TAG_END:
		sif2.ee.end = true;
		break;
	}
	return true;
}
Example #2
0
__fi void dmaSIF2()
{
	DevCon.Warning("SIF2 EE CHCR %x", sif2dma.chcr._u32);
	SIF_LOG(wxString(L"dmaSIF2" + sif2dma.cmqt_to_str()).To8BitData());

	if (sif2.fifo.readPos != sif2.fifo.writePos)
	{
		SIF_LOG("warning, sif2.fifoReadPos != sif2.fifoWritePos");
	}

	//if(sif2dma.chcr.MOD == CHAIN_MODE && sif2dma.qwc > 0) DevCon.Warning(L"SIF2 QWC on Chain CHCR " + sif2dma.chcr.desc());
	psHu32(SBUS_F240) |= 0x8000;
	sif2.ee.busy = true;

	// Okay, this here is needed currently (r3644). 
	// FFX battles in the thunder plains map die otherwise, Phantasy Star 4 as well
	// These 2 games could be made playable again by increasing the time the EE or the IOP run,
	// showing that this is very timing sensible.
	// Doing this DMA unfortunately brings back an old warning in Legend of Legaia though, but it still works.

	//Updated 23/08/2011: The hangs are caused by the EE suspending SIF1 DMA and restarting it when in the middle 
	//of processing a "REFE" tag, so the hangs can be solved by forcing the ee.end to be false
	// (as it should always be at the beginning of a DMA).  using "if iop is busy" flags breaks Tom Clancy Rainbow Six.
	// Legend of Legaia doesn't throw a warning either :)
	//sif2.ee.end = false;
	
	SIF2Dma();

}
Example #3
0
// Read Fifo into an ee tag, transfer it to sif0ch, and process it.
static __fi bool ProcessEETag()
{
	static __aligned16 u32 tag[4];
	tDMA_TAG& ptag(*(tDMA_TAG*)tag);

	sif0.fifo.read((u32*)&tag[0], 4); // Tag
	SIF_LOG("SIF0 EE read tag: %x %x %x %x", tag[0], tag[1], tag[2], tag[3]);

	sif0ch.unsafeTransfer(&ptag);
	sif0ch.madr = tag[1];

	SIF_LOG("SIF0 EE dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)",
		sif0ch.madr, sif0ch.qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);

	if (sif0ch.chcr.TIE && ptag.IRQ)
	{
		//Console.WriteLn("SIF0 TIE");
		sif0.ee.end = true;
	}

	switch (ptag.ID)
	{
		case TAG_CNT:	break;

		case TAG_CNTS:
			if (dmacRegs.ctrl.STS == STS_SIF0)
				dmacRegs.stadr.ADDR = sif0ch.madr + (sif0ch.qwc * 16);
			break;

		case TAG_END:
			sif0.ee.end = true;
			break;
	}
	return true;
}
Example #4
0
void FinalizeEERead()
{
	SIF_LOG("Sif0: End EE");
	sif0.ee.end = false;
	sif0.ee.busy = false;
	SIF_LOG("CPU INT FIRED SIF0");
	CPU_INT(DMAC_SIF0, 16);
}
Example #5
0
s32 PrepareEERead()
{
	static __aligned16 u32 tag[4];

	// Process DMA tag at hw_dma9.tadr
	sif0.iop.data = *(sifData *)iopPhysMem(hw_dma9.tadr);
	sif0.iop.data.words = (sif0.iop.data.words + 3) & 0xfffffffc; // Round up to nearest 4.
	memcpy(tag, (u32*)iopPhysMem(hw_dma9.tadr + 8), 16);

	hw_dma9.tadr += 16; ///hw_dma9.madr + 16 + sif0.sifData.words << 2;

	// We're only copying the first 24 bits.
	hw_dma9.madr = sif0data & 0xFFFFFF;
	sif0.iop.counter = sif0words;

	if (sif0tag.IRQ  || (sif0tag.ID & 4)) sif0.iop.end = true;
	SIF_LOG("SIF0 IOP to EE Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)"
		"\n\tread tag: %x %x %x %x", hw_dma9.madr, hw_dma9.tadr, sif0.iop.counter, sif0words, sif0data,
		tag[0], tag[1], tag[2], tag[3]);

	sif0ch.unsafeTransfer(((tDMA_TAG*)(tag)));
	sif0ch.madr = tag[1];
	tDMA_TAG ptag(tag[0]);

	SIF_LOG("SIF0 EE dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)",
		sif0ch.madr, sif0ch.qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);

	if (sif0ch.chcr.TIE && ptag.IRQ)
	{
		//Console.WriteLn("SIF0 TIE");
		sif0.ee.end = true;
	}

	switch (ptag.ID)
	{
	case TAG_REFE:
		sif0.ee.end = true;
		if (dmacRegs.ctrl.STS != NO_STS)
			dmacRegs.stadr.ADDR = sif0ch.madr + (sif0ch.qwc * 16);
		break;

	case TAG_REFS:
		if (dmacRegs.ctrl.STS != NO_STS)
			dmacRegs.stadr.ADDR = sif0ch.madr + (sif0ch.qwc * 16);
		break;

	case TAG_END:
		sif0.ee.end = true;
		break;
	}
	return true;
}
Example #6
0
// Stop transferring ee, and signal an interrupt.
static __fi void EndEE()
{
	SIF_LOG("Sif2: End EE");
	sif2.ee.end = false;
	sif2.ee.busy = false;
	if (sif2.ee.cycles == 0)
	{
		SIF_LOG("SIF2 EE: cycles = 0");
		sif2.ee.cycles = 1;
	}

	CPU_INT(DMAC_SIF2, sif2.ee.cycles*BIAS);
}
Example #7
0
static __fi void Sif2Init()
{
	SIF_LOG("SIF2 DMA start... free %x iop busy %x", sif2.fifo.sif_free(), sif2.iop.busy);
	done = false;
	sif2.ee.cycles = 0;
	sif2.iop.cycles = 0;
}
Example #8
0
s32 DoSifRead(u32 iopAvailable)
{
	u32 eeAvailable = PrepareEERead();

	u32 transferSizeBytes = min(min(iopAvailable,eeAvailable),fifoSize);
	u32 transferSizeWords = transferSizeBytes >> 2;
	u32 transferSizeQWords = transferSizeBytes >> 4;

	SIF_LOG("Write IOP to EE: +++++++++++ %lX of %lX", transferSizeWords, sif0.iop.counter);

	tDMA_TAG *ptag = sif0ch.getAddr(sif0ch.madr, DMAC_SIF0, true);
	if (ptag == NULL)
	{
		DevCon.Warning("Write IOP to EE: ptag == NULL");
		return false;
	}

	memcpy((u32*)ptag, (u32*)iopPhysMem(hw_dma9.madr), transferSizeBytes);

	// Clearing handled by vtlb memory protection and manual blocks.
	//Cpu->Clear(sif0ch.madr, readSize*4);

	sif0ch.madr += transferSizeBytes;
	sif0.ee.cycles += transferSizeQWords * 2;
	sif0ch.qwc -= transferSizeQWords;

	return transferSizeBytes;
}
Example #9
0
// Read Fifo into an iop tag, and transfer it to hw_dma9. And presumably process it.
static __fi bool ProcessIOPTag()
{
	// Process DMA tag at hw_dma9.tadr
	sif0.iop.data = *(sifData *)iopPhysMem(hw_dma9.tadr);
	sif0.iop.data.words = (sif0.iop.data.words + 3) & 0xfffffffc; // Round up to nearest 4.

	// send the EE's side of the DMAtag.  The tag is only 64 bits, with the upper 64 bits
	// ignored by the EE.

	sif0.fifo.write((u32*)iopPhysMem(hw_dma9.tadr + 8), 2);
	sif0.fifo.writePos = (sif0.fifo.writePos + 2) & (FIFO_SIF_W - 1);		// iggy on the upper 64.
	sif0.fifo.size += 2;

	hw_dma9.tadr += 16; ///hw_dma9.madr + 16 + sif0.sifData.words << 2;

	// We're only copying the first 24 bits.  Bits 30 and 31 (checked below) are Stop/IRQ bits.
	hw_dma9.madr = sif0data & 0xFFFFFF;
	sif0.iop.counter = sif0words;

	// IOP tags have an IRQ bit and an End of Transfer bit:
	if (sif0tag.IRQ  || (sif0tag.ID & 4)) sif0.iop.end = true;
	SIF_LOG("SIF0 IOP Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)", hw_dma9.madr, hw_dma9.tadr, sif0.iop.counter, sif0words, sif0data);

	return true;
}
Example #10
0
// Write from Fifo to EE.
static __fi bool WriteFifoToEE()
{
	const int readSize = std::min((s32)sif2dma.qwc, sif2.fifo.size >> 2);

	tDMA_TAG *ptag;

	//SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif2dma.madr);
	SIF_LOG("Write Fifo to EE: ----------- %lX of %lX", readSize << 2, sif2dma.qwc << 2);

	ptag = sif2dma.getAddr(sif2dma.madr, DMAC_SIF2, true);
	if (ptag == NULL)
	{
		DevCon.Warning("Write Fifo to EE: ptag == NULL");
		return false;
	}

	sif2.fifo.read((u32*)ptag, readSize << 2);

	// Clearing handled by vtlb memory protection and manual blocks.
	//Cpu->Clear(sif2dma.madr, readSize*4);

	sif2dma.madr += readSize << 4;
	sif2.ee.cycles += readSize;	// fixme : BIAS is factored in above
	sif2dma.qwc -= readSize;
	
	return true;
}
Example #11
0
File: Sif1.cpp Project: tsiru/pcsx2
// Write from the EE to Fifo.
static __fi bool WriteEEtoFifo()
{
	// There's some data ready to transfer into the fifo..

	SIF_LOG("Sif 1: Write EE to Fifo");
	const int writeSize = min((s32)sif1dma.qwc, sif1.fifo.sif_free() >> 2);

	tDMA_TAG *ptag;

	ptag = sif1dma.getAddr(sif1dma.madr, DMAC_SIF1, false);
	if (ptag == NULL)
	{
		DevCon.Warning("Write EE to Fifo: ptag == NULL");
		return false;
	}

	sif1.fifo.write((u32*)ptag, writeSize << 2);

	sif1dma.madr += writeSize << 4;
	hwDmacSrcTadrInc(sif1dma);
	sif1.ee.cycles += writeSize;		// fixme : BIAS is factored in above
	sif1dma.qwc -= writeSize;

	return true;
}
Example #12
0
File: Sif1.cpp Project: tsiru/pcsx2
static __fi void Sif1Init()
{
	SIF_LOG("SIF1 DMA start...");
	done = false;
	sif1.ee.cycles = 0;
	sif1.iop.cycles = 0;
}
Example #13
0
File: Sif1.cpp Project: tsiru/pcsx2
// Read from the fifo and write to IOP
static __fi bool WriteFifoToIOP()
{
	// If we're reading something, continue to do so.

	SIF_LOG("Sif1: Write Fifo to IOP");
	const int readSize = min (sif1.iop.counter, sif1.fifo.size);

	SIF_LOG("Sif 1 IOP doing transfer %04X to %08X", readSize, HW_DMA10_MADR);

	sif1.fifo.read((u32*)iopPhysMem(hw_dma10.madr), readSize);
	psxCpu->Clear(hw_dma10.madr, readSize);
	hw_dma10.madr += readSize << 2;
	sif1.iop.cycles += readSize >> 2;		// fixme: should be >> 4
	sif1.iop.counter -= readSize;

	return true;
}
Example #14
0
File: Sif1.cpp Project: tsiru/pcsx2
// Stop processing EE, and signal an interrupt.
static __fi void EndEE()
{
	sif1.ee.end = false;
	sif1.ee.busy = false;
	SIF_LOG("Sif 1: End EE");

	// Voodoocycles : Okami wants around 100 cycles when booting up
	// Other games reach like 50k cycles here, but the EE will long have given up by then and just retry.
	// (Cause of double interrupts on the EE)
	if (sif1.ee.cycles == 0)
	{
		SIF_LOG("SIF1 EE: cycles = 0");
		sif1.ee.cycles = 1;
	}


	CPU_INT(DMAC_SIF1, /*min((int)(*/sif1.ee.cycles*BIAS/*), 384)*/);
}
Example #15
0
__fi bool WriteFifoSingleWord()
{
	// There's some data ready to transfer into the fifo..

	SIF_LOG("Write Single word to SIF2 Fifo");
	
	sif2.fifo.write((u32*)&psxHu32(HW_PS1_GPU_DATA), 1);
	if (sif2.fifo.size > 0) psxHu32(0x1000f300) &= ~0x4000000;
	return true;
}
Example #16
0
__fi void  sif2Interrupt()
{
	if (!sif2.iop.end || sif2.iop.counter > 0)
	{
		SIF2Dma();
		return;
	}
	
	SIF_LOG("SIF2 IOP Intr end");
	HW_DMA2_CHCR &= ~0x01000000;
	psxDmaInterrupt2(2);
}
Example #17
0
__fi bool ReadFifoSingleWord()
{
	u32 ptag[4];

	//SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif2dma.madr);
	SIF_LOG("Read Fifo SIF2 Single Word IOP Busy %x Fifo Size %x SIF2 CHCR %x", sif2.iop.busy, sif2.fifo.size, HW_DMA2_CHCR);


	sif2.fifo.read((u32*)&ptag[0], 1);
	psHu32(0x1000f3e0) = ptag[0];
	if (sif2.fifo.size == 0) psxHu32(0x1000f300) |= 0x4000000;
	if (sif2.iop.busy && sif2.fifo.size <= 8)SIF2Dma();
	return true;
}
Example #18
0
File: Sif1.cpp Project: tsiru/pcsx2
// Write fifo to data, and put it in IOP.
static __fi bool SIFIOPReadTag()
{
	// Read a tag.
	sif1.fifo.read((u32*)&sif1.iop.data, 4);
	//sif1words = (sif1words + 3) & 0xfffffffc; // Round up to nearest 4.
	SIF_LOG("SIF 1 IOP: dest chain tag madr:%08X wc:%04X id:%X irq:%d",
		sif1data & 0xffffff, sif1words, sif1tag.ID, sif1tag.IRQ);

	// Only use the first 24 bits.
	hw_dma10.madr = sif1data & 0xffffff;

	sif1.iop.counter = sif1words;
	if (sif1tag.IRQ  || (sif1tag.ID & 4)) sif1.iop.end = true;

	return true;
}
Example #19
0
// Write IOP to Fifo.
static __fi bool WriteIOPtoFifo()
{
	// There's some data ready to transfer into the fifo..
	const int writeSize = min(sif0.iop.counter, sif0.fifo.sif_free());

	SIF_LOG("Write IOP to Fifo: +++++++++++ %lX of %lX", writeSize, sif0.iop.counter);

	sif0.fifo.write((u32*)iopPhysMem(hw_dma9.madr), writeSize);
	hw_dma9.madr += writeSize << 2;

	// iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords).
	sif0.iop.cycles += (writeSize >> 2)/* * BIAS*/;		// fixme : should be >> 4
	sif0.iop.counter -= writeSize;

	return true;
}
Example #20
0
// Stop transferring iop, and signal an interrupt.
static __fi void EndIOP()
{
	SIF_LOG("Sif2: End IOP");
	sif2data = 0;
	//sif2.iop.end = false;
	sif2.iop.busy = false;

	if (sif2.iop.cycles == 0)
	{
		DevCon.Warning("SIF2 IOP: cycles = 0");
		sif2.iop.cycles = 1;
	}
	// iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords)
	// So when we're all done, the equation looks like thus:
	//PSX_INT(IopEvt_SIF2, ( ( sif2.iop.cycles*BIAS ) / 4 ) / 8);
	PSX_INT(IopEvt_SIF2, sif2.iop.cycles);
}
Example #21
0
// Write IOP to Fifo.
static __fi bool WriteIOPtoFifo()
{
	// There's some data ready to transfer into the fifo..
	const int writeSize = std::min(sif2.iop.counter, sif2.fifo.sif_free());

	SIF_LOG("Write IOP to Fifo: +++++++++++ %lX of %lX", writeSize, sif2.iop.counter);
	
	sif2.fifo.write((u32*)iopPhysMem(hw_dma2.madr), writeSize);
	hw_dma2.madr += writeSize << 2;

	// iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords).
	sif2.iop.cycles += (writeSize >> 2)/* * BIAS*/;		// fixme : should be >> 4
	sif2.iop.counter -= writeSize;
	//PSX_INT(IopEvt_SIF2, sif2.iop.cycles);
	if (sif2.iop.counter == 0) hw_dma2.madr = sif2data & 0xffffff;
	if (sif2.fifo.size > 0) psxHu32(0x1000f300) &= ~0x4000000;
	return true;
}
Example #22
0
File: Sif1.cpp Project: tsiru/pcsx2
// Stop processing IOP, and signal an interrupt.
static __fi void EndIOP()
{
	sif1data = 0;
	sif1.iop.end = false;
	sif1.iop.busy = false;
	SIF_LOG("Sif 1: End IOP");

	//Fixme ( voodoocycles ):
	//The *24 are needed for ecco the dolphin (CDVD hangs) and silver surfer (Pad not detected)
	//Greater than *35 break rebooting when trying to play Tekken5 arcade history
	//Total cycles over 1024 makes SIF too slow to keep up the sound stream in so3...
	if (sif1.iop.cycles == 0)
	{
		DevCon.Warning("SIF1 IOP: cycles = 0");
		sif1.iop.cycles = 1;
	}
	// iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords)
	PSX_INT(IopEvt_SIF1, /*min((*/sif1.iop.cycles/* * 26*//*), 1024)*/);
}
Example #23
0
File: Sif1.cpp Project: tsiru/pcsx2
// Get a tag and process it.
static __fi bool ProcessEETag()
{
	// Chain mode
	tDMA_TAG *ptag;
	SIF_LOG("Sif1: ProcessEETag");

	// Process DMA tag at sif1dma.tadr
	ptag = sif1dma.DMAtransfer(sif1dma.tadr, DMAC_SIF1);
	if (ptag == NULL)
	{
		Console.WriteLn("Sif1 ProcessEETag: ptag = NULL");
		return false;
	}

	if (sif1dma.chcr.TTE)
	{
		Console.WriteLn("SIF1 TTE");
		sif1.fifo.write((u32*)ptag + 2, 2);
	}

	if (sif1dma.chcr.TIE && ptag->IRQ)
	{
		Console.WriteLn("SIF1 TIE");
		sif1.ee.end = true;
	}

	SIF_LOG(wxString(ptag->tag_to_str()).To8BitData());
	switch (ptag->ID)
	{
		case TAG_REFE:
			sif1.ee.end = true;
			sif1dma.madr = ptag[1]._u32;
			sif1dma.tadr += 16;
			break;

		case TAG_CNT:
			sif1dma.tadr += 16;
			sif1dma.madr = sif1dma.tadr;
			break;

		case TAG_NEXT:
			sif1dma.madr = sif1dma.tadr + 16;
			sif1dma.tadr = ptag[1]._u32;
			break;

		case TAG_REF:
		case TAG_REFS:
			if(ptag->ID == TAG_REFS && dmacRegs.ctrl.STD == STD_SIF1) DevCon.Warning("SIF1 Drain Stall Control not implemented");
			sif1dma.madr = ptag[1]._u32;
			sif1dma.tadr += 16;
			break;

		case TAG_END:
			sif1.ee.end = true;
			sif1dma.madr = sif1dma.tadr + 16;
			//sif1dma.tadr = sif1dma.madr + (sif1dma.qwc << 4);
			break;

		default:
			Console.WriteLn("Bad addr1 source chain");
	}
	return true;
}