From ad4aeca3ad1af47d848611df5130b91bec729b12 Mon Sep 17 00:00:00 2001 From: refraction Date: Tue, 23 Aug 2011 18:30:40 +0000 Subject: [PATCH] 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 --- pcsx2/IopDma.cpp | 2 ++ pcsx2/Sif0.cpp | 18 ++++++++++++------ pcsx2/Sif1.cpp | 32 +++++++++++++++++++------------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/pcsx2/IopDma.cpp b/pcsx2/IopDma.cpp index 5df826c1d..07d267647 100644 --- a/pcsx2/IopDma.cpp +++ b/pcsx2/IopDma.cpp @@ -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(); } diff --git a/pcsx2/Sif0.cpp b/pcsx2/Sif0.cpp index ccd472c27..d0301962c 100644 --- a/pcsx2/Sif0.cpp +++ b/pcsx2/Sif0.cpp @@ -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(); - } + } diff --git a/pcsx2/Sif1.cpp b/pcsx2/Sif1.cpp index a43eb474e..b03eb228d 100644 --- a/pcsx2/Sif1.cpp +++ b/pcsx2/Sif1.cpp @@ -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(); + }