SIF: Better fix in place for random hangs, Tom Clancy Rainbow Six Lockdown now Playable.

Hangs also related to Phantasy Star 4 and FFX Thunder Plains, which are both still ok with this. Also the sif dma errors in Legends of Legaia should be gone again!

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4874 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction 2011-08-23 18:30:40 +00:00
parent 783f600711
commit ad4aeca3ad
3 changed files with 33 additions and 19 deletions

View File

@ -195,6 +195,7 @@ void psxDma9(u32 madr, u32 bcr, u32 chcr)
SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx", chcr, madr, bcr, HW_DMA9_TADR);
sif0.iop.busy = true;
sif0.iop.end = false;
SIF0Dma();
}
@ -204,6 +205,7 @@ void psxDma10(u32 madr, u32 bcr, u32 chcr)
SIF_LOG("IOP: dmaSIF1 chcr = %lx, madr = %lx, bcr = %lx", chcr, madr, bcr);
sif1.iop.busy = true;
sif1.iop.end = false;
SIF1Dma();
}

View File

@ -286,7 +286,7 @@ static __fi void HandleIOPTransfer()
static __fi void Sif0End()
{
psHu32(SBUS_F240) &= ~0x20;
psHu32(SBUS_F240) &= ~0x2000;
//psHu32(SBUS_F240) &= ~0x2000;
DMA_LOG("SIF0 DMA End");
}
@ -320,7 +320,7 @@ __fi void SIF0Dma()
}
} while (/*!done && */BusyCheck > 0); // Substituting (sif0.ee.busy || sif0.iop.busy) breaks things.
Sif0End();
}
__fi void sif0Interrupt()
@ -331,12 +331,14 @@ __fi void sif0Interrupt()
__fi void EEsif0Interrupt()
{
Sif0End();
hwDmacIrq(DMAC_SIF0);
sif0dma.chcr.STR = false;
}
__fi void dmaSIF0()
{
if(sif0.ee.end == true) DevCon.Warning("Happened on SIF0 :(");
SIF_LOG(wxString(L"dmaSIF0" + sif0dma.cmqt_to_str()).To8BitData());
if (sif0.fifo.readPos != sif0.fifo.writePos)
@ -345,7 +347,7 @@ __fi void dmaSIF0()
}
//if(sif0dma.chcr.MOD == CHAIN_MODE && sif0dma.qwc > 0) DevCon.Warning(L"SIF0 QWC on Chain CHCR " + sif0dma.chcr.desc());
psHu32(SBUS_F240) |= 0x2000;
//psHu32(SBUS_F240) |= 0x2000;
sif0.ee.busy = true;
// Okay, this here is needed currently (r3644).
@ -353,9 +355,13 @@ __fi void dmaSIF0()
// 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.
if (sif0.iop.busy)
{
//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 :)
sif0.ee.end = false;
//hwIntcIrq(INTC_SBUS); // not sure, so let's not
SIF0Dma();
}
}

View File

@ -37,9 +37,9 @@ 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);
SIF_LOG("Sif 1: Write EE QWC %x to Fifo Size %x", sif1dma.qwc, writeSize);
tDMA_TAG *ptag;
ptag = sif1dma.getAddr(sif1dma.madr, DMAC_SIF1, false);
@ -55,7 +55,7 @@ static __fi bool WriteEEtoFifo()
hwDmacSrcTadrInc(sif1dma);
sif1.ee.cycles += writeSize; // fixme : BIAS is factored in above
sif1dma.qwc -= writeSize;
SIF_LOG("Ending FIFO Write, sif1 qwc = %x", sif1dma.qwc);
return true;
}
@ -166,7 +166,7 @@ static __fi void EndEE()
{
sif1.ee.end = false;
sif1.ee.busy = false;
SIF_LOG("Sif 1: End EE");
SIF_LOG("Sif 1: End EE %x", sif1dma.qwc);
// 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.
@ -178,7 +178,7 @@ static __fi void EndEE()
}
CPU_INT(DMAC_SIF1, /*min((int)(*/sif1.ee.cycles*BIAS/*), 384)*/);
CPU_INT(DMAC_SIF1, /*min((int)(*/sif1.ee.cycles*8/*), 384)*/);
}
// Stop processing IOP, and signal an interrupt.
@ -280,7 +280,7 @@ static __fi void Sif1End()
{
psHu32(SBUS_F240) &= ~0x40;
psHu32(SBUS_F240) &= ~0x4000;
DMA_LOG("SIF1 DMA End");
}
@ -313,13 +313,12 @@ __fi void SIF1Dma()
}
}
} while (/*!done &&*/ BusyCheck > 0);
Sif1End();
} while (/*!done &&*/ BusyCheck > 0);
}
__fi void sif1Interrupt()
{
Sif1End();
HW_DMA10_CHCR &= ~0x01000000; //reset TR flag
psxDmaInterrupt2(3);
}
@ -346,13 +345,20 @@ __fi void dmaSIF1()
psHu32(SBUS_F240) |= 0x4000;
sif1.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.
if (sif1.iop.busy)
{
SIF1Dma();
}
//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 :)
sif1.ee.end = false;
SIF1Dma();
}