From 7966c272466a3671f81b17b6b552ec0281d7563d Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Fri, 10 Sep 2021 10:26:25 +0100 Subject: [PATCH] GIF: Handle PATH2 ending when VIF not running --- pcsx2/Gif.cpp | 23 ++++++++++++++++++----- pcsx2/Gif_Unit.h | 30 ++++++++++++++++++++++++++---- pcsx2/Vif_Codes.cpp | 11 +++++++++-- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index 243b0e3cc3..e88792b990 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -108,11 +108,14 @@ int GIF_Fifo::write_fifo(u32* pMem, int size) int writePos = fifoSize * 4; - GIF_LOG("GIF FIFO Adding %d QW to GIF FIFO at offset %d FIFO now contains %d QW", transferSize, writePos, fifoSize); + memcpy(&data[writePos], pMem, transferSize * 16); fifoSize += transferSize; + + GIF_LOG("GIF FIFO Adding %d QW to GIF FIFO at offset %d FIFO now contains %d QW", transferSize, writePos, fifoSize); + gifRegs.stat.FQC = fifoSize; CalculateFIFOCSR(); @@ -185,6 +188,13 @@ void incGifChAddr(u32 qwc) __fi void gifCheckPathStatus(bool calledFromGIF) { + // If GIF is running on it's own, let it handle its own timing. + if (calledFromGIF && gifch.chcr.STR) + { + if(gif_fifo.fifoSize == 16) + GifDMAInt(16); + return; + } if (gifRegs.stat.APATH == 3) { gifRegs.stat.APATH = 0; @@ -222,7 +232,7 @@ __fi void gifCheckPathStatus(bool calledFromGIF) __fi void gifInterrupt() { - GIF_LOG("gifInterrupt caught qwc=%d fifo=%d apath=%d oph=%d state=%d!", gifch.qwc, gifRegs.stat.FQC, gifRegs.stat.APATH, gifRegs.stat.OPH, gifUnit.gifPath[GIF_PATH_3].state); + GIF_LOG("gifInterrupt caught qwc=%d fifo=%d(%d) apath=%d oph=%d state=%d!", gifch.qwc, gifRegs.stat.FQC, gif_fifo.fifoSize, gifRegs.stat.APATH, gifRegs.stat.OPH, gifUnit.gifPath[GIF_PATH_3].state); gifCheckPathStatus(false); if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE) @@ -280,8 +290,9 @@ __fi void gifInterrupt() } } } - - if (((gifch.qwc > 0) || (!gif.gspath3done)) && gif_fifo.fifoSize) + // If the dma has data waiting and there's something in the fifo, drain the fifo + // If the GIF is currently paused, check if the FIFO is full, otherwise fill it + if (((gifch.qwc > 0) || (!gif.gspath3done)) && (CheckPaths() || gif_fifo.fifoSize == 16 || readSize)) return; } @@ -791,7 +802,9 @@ void gifMFIFOInterrupt() } } - if (((gifch.qwc > 0) || (!gif.gspath3done)) && gif_fifo.fifoSize) + // If the dma has data waiting and there's something in the fifo, drain the fifo + // If the GIF is currently paused, check if the FIFO is full, otherwise fill it + if (((gifch.qwc > 0) || (!gif.gspath3done)) && (CheckPaths() || gif_fifo.fifoSize == 16 || readSize)) return; } diff --git a/pcsx2/Gif_Unit.h b/pcsx2/Gif_Unit.h index 24351dc01b..615375ab13 100644 --- a/pcsx2/Gif_Unit.h +++ b/pcsx2/Gif_Unit.h @@ -327,6 +327,7 @@ struct Gif_Path if (curOffset + 16 > curSize) { //GUNIT_LOG("Path Buffer: Not enough data for gif tag! [%d]", curSize-curOffset); + GUNIT_WARN("PATH %d not enough data pre tag, available %d wanted %d", gifRegs.stat.APATH, curSize - curOffset, 16); return gsPack; } @@ -339,11 +340,12 @@ struct Gif_Path gifTag.setTag(&buffer[curOffset], 1); state = (GIF_PATH_STATE)(gifTag.tag.FLG + 1); - + GUNIT_WARN("PATH %d New tag State %d FLG %d EOP %d NLOOP %d", gifRegs.stat.APATH, gifRegs.stat.APATH, state, gifTag.tag.FLG, gifTag.tag.EOP, gifTag.tag.NLOOP); // We don't have enough data for a complete GS packet if (!gifTag.hasAD && curOffset + 16 + gifTag.len > curSize) { gifTag.isValid = false; // So next time we test again + GUNIT_WARN("PATH %d not enough data, available %d wanted %d", gifRegs.stat.APATH, curSize - curOffset, 16 + gifTag.len); return gsPack; } @@ -357,7 +359,10 @@ struct Gif_Path while (gifTag.nLoop && !dblSIGNAL) { if (curOffset + 16 > curSize) + { + GUNIT_WARN("PATH %d not enough data AD, available %d wanted %d", gifRegs.stat.APATH, curSize - curOffset, 16); return gsPack; // Exit Early + } if (gifTag.curReg() == GIF_REG_A_D) { if (!isMTVU()) @@ -367,7 +372,10 @@ struct Gif_Path gifTag.packedStep(); } if (dblSIGNAL && !(gifTag.tag.EOP && !gifTag.nLoop)) + { + GUNIT_WARN("PATH %d early exit (double signal)", gifRegs.stat.APATH); return gsPack; // Exit Early + } } else incTag(curOffset, gsPack.size, gifTag.len); // Data length @@ -384,7 +392,7 @@ struct Gif_Path gsPack.Reset(); gsPack.offset = curOffset; - + GUNIT_WARN("EOP PATH %d", gifRegs.stat.APATH); //Path 3 Masking is timing sensitive, we need to simulate its length! (NFSU2/Outrun 2006) if ((gifRegs.stat.APATH - 1) == GIF_PATH_3) @@ -707,6 +715,7 @@ struct Gif_Unit return 0; } bool didPath3 = false; + bool path3Check = isPath3; int curPath = stat.APATH > 0 ? stat.APATH - 1 : 0; //Init to zero if no path is already set. gifPath[2].dmaRewind = 0; stat.OPH = 1; @@ -756,30 +765,43 @@ struct Gif_Unit } if (!gsSIGNAL.queued && !gifPath[0].isDone()) { + GUNIT_WARN("Swapping to PATH 1"); stat.APATH = 1; stat.P1Q = 0; curPath = 0; } else if (!gsSIGNAL.queued && !gifPath[1].isDone()) { + GUNIT_WARN("Swapping to PATH 2"); stat.APATH = 2; stat.P2Q = 0; curPath = 1; } else if (!gsSIGNAL.queued && !gifPath[2].isDone() && !Path3Masked()) { + GUNIT_WARN("Swapping to PATH 3"); stat.APATH = 3; stat.P3Q = 0; stat.IP3 = 0; curPath = 2; + path3Check = true; } else { + GUNIT_WARN("Finished Processing"); // If PATH3 was stalled due to another transfer but the DMA ended, it'll never check this // So lets quickly check if it's currently set to path3 - gifCheckPathStatus(true); - if (isResume || curPath == 0) + if (stat.APATH == 3 || path3Check) + gifCheckPathStatus(true); + else { + if (vif1Regs.stat.VGW) + { + // Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back. + if (!(cpuRegs.interrupt & (1 << DMAC_VIF1))) + CPU_INT(DMAC_VIF1, 1); + } + stat.APATH = 0; stat.OPH = 0; } diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index d8acda504a..fbb06fb939 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -230,8 +230,11 @@ vifOp(vifCode_Flush) vif1.vifstalled.value = VIF_TIMING_BREAK; return 0; } - else - vif1.cmd = 0; + + if (vif1.waitforvu) + return 0; + + vif1.cmd = 0; vif1.pass = 0; } pass3 { VifCodeLog("Flush"); } @@ -258,6 +261,10 @@ vifOp(vifCode_FlushA) vif1.vifstalled.value = VIF_TIMING_BREAK; return 0; } + + if (vif1.waitforvu) + return 0; + vif1.cmd = 0; vif1.pass = 0; }