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); SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx", chcr, madr, bcr, HW_DMA9_TADR);
sif0.iop.busy = true; sif0.iop.busy = true;
sif0.iop.end = false;
SIF0Dma(); 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); SIF_LOG("IOP: dmaSIF1 chcr = %lx, madr = %lx, bcr = %lx", chcr, madr, bcr);
sif1.iop.busy = true; sif1.iop.busy = true;
sif1.iop.end = false;
SIF1Dma(); SIF1Dma();
} }

View File

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

View File

@ -37,9 +37,9 @@ static __fi bool WriteEEtoFifo()
{ {
// There's some data ready to transfer into the fifo.. // 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);
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; tDMA_TAG *ptag;
ptag = sif1dma.getAddr(sif1dma.madr, DMAC_SIF1, false); ptag = sif1dma.getAddr(sif1dma.madr, DMAC_SIF1, false);
@ -55,7 +55,7 @@ static __fi bool WriteEEtoFifo()
hwDmacSrcTadrInc(sif1dma); hwDmacSrcTadrInc(sif1dma);
sif1.ee.cycles += writeSize; // fixme : BIAS is factored in above sif1.ee.cycles += writeSize; // fixme : BIAS is factored in above
sif1dma.qwc -= writeSize; sif1dma.qwc -= writeSize;
SIF_LOG("Ending FIFO Write, sif1 qwc = %x", sif1dma.qwc);
return true; return true;
} }
@ -166,7 +166,7 @@ static __fi void EndEE()
{ {
sif1.ee.end = false; sif1.ee.end = false;
sif1.ee.busy = 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 // 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. // 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. // Stop processing IOP, and signal an interrupt.
@ -314,12 +314,11 @@ __fi void SIF1Dma()
} }
} while (/*!done &&*/ BusyCheck > 0); } while (/*!done &&*/ BusyCheck > 0);
Sif1End();
} }
__fi void sif1Interrupt() __fi void sif1Interrupt()
{ {
Sif1End();
HW_DMA10_CHCR &= ~0x01000000; //reset TR flag HW_DMA10_CHCR &= ~0x01000000; //reset TR flag
psxDmaInterrupt2(3); psxDmaInterrupt2(3);
} }
@ -346,13 +345,20 @@ __fi void dmaSIF1()
psHu32(SBUS_F240) |= 0x4000; psHu32(SBUS_F240) |= 0x4000;
sif1.ee.busy = true; sif1.ee.busy = true;
// Okay, this here is needed currently (r3644). // Okay, this here is needed currently (r3644).
// FFX battles in the thunder plains map die otherwise, Phantasy Star 4 as well // 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, // 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. // 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. // Doing this DMA unfortunately brings back an old warning in Legend of Legaia though, but it still works.
if (sif1.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 :)
sif1.ee.end = false;
SIF1Dma(); SIF1Dma();
}
} }