diff --git a/pcsx2/IPU/IPU.cpp b/pcsx2/IPU/IPU.cpp index 45e9486e2b..7e965f5bae 100644 --- a/pcsx2/IPU/IPU.cpp +++ b/pcsx2/IPU/IPU.cpp @@ -296,7 +296,7 @@ void ipuSoftReset() ipu_cmd.clear(); ipuRegs.cmd.BUSY = 0; ipuRegs.cmd.DATA = 0; // required for Enthusia - Professional Racing after fix, or will freeze at start of next video. - + IPU1Status.DataRequested = true; memzero(g_BP); hwIntcIrq(INTC_IPU); // required for FightBox } @@ -363,14 +363,12 @@ __fi bool ipuWrite64(u32 mem, u64 value) static void ipuBCLR(u32 val) { - // The Input FIFO shouldn't be cleared when the DMA is running, however if it is the DMA should drain - // as it is constantly fighting it.... - while(ipu1ch.chcr.STR) - { - ipu_fifo.in.clear(); + if (ipu1ch.chcr.STR && g_BP.IFC < 8 && IPU1Status.DataRequested) ipu1Interrupt(); - } - + + if(!ipu1ch.chcr.STR) + psHu32(DMAC_STAT) &= ~(1 << DMAC_TO_IPU); + ipu_fifo.in.clear(); memzero(g_BP); @@ -878,6 +876,12 @@ __fi void IPUCMD_WRITE(u32 val) ipuBCLR(val); hwIntcIrq(INTC_IPU); //DMAC_TO_IPU ipuRegs.ctrl.BUSY = 0; + + IPU1Status.DataRequested = true; + if (ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999) + { + CPU_INT(DMAC_TO_IPU, 32); + } return; case SCE_IPU_SETTH: @@ -1005,10 +1009,4 @@ __noinline void IPUWorker() ipuRegs.ctrl.BUSY = 0; //ipu_cmd.current = 0xffffffff; hwIntcIrq(INTC_IPU); - - // Fill the FIFO ready for the next command - if (ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999) - { - CPU_INT(DMAC_TO_IPU, 32); - } } diff --git a/pcsx2/IPU/IPU.h b/pcsx2/IPU/IPU.h index 35673f271c..203318ca08 100644 --- a/pcsx2/IPU/IPU.h +++ b/pcsx2/IPU/IPU.h @@ -16,6 +16,7 @@ #pragma once #include "IPU_Fifo.h" +#include "IPUdma.h" #define ipumsk( src ) ( (src) & 0xff ) #define ipucase( src ) case ipumsk(src) diff --git a/pcsx2/IPU/IPU_Fifo.cpp b/pcsx2/IPU/IPU_Fifo.cpp index a43a49e5be..89ed049d62 100644 --- a/pcsx2/IPU/IPU_Fifo.cpp +++ b/pcsx2/IPU/IPU_Fifo.cpp @@ -85,11 +85,12 @@ int IPU_Fifo_Input::write(u32* pMem, int size) int IPU_Fifo_Input::read(void *value) { // wait until enough data to ensure proper streaming. - if (g_BP.IFC < 3) + if (g_BP.IFC <= 1) { // IPU FIFO is empty and DMA is waiting so lets tell the DMA we are ready to put data in the FIFO if(cpuRegs.eCycle[4] == 0x9999) { + IPU1Status.DataRequested = true; CPU_INT( DMAC_TO_IPU, 32 ); } diff --git a/pcsx2/IPU/IPUdma.cpp b/pcsx2/IPU/IPUdma.cpp index ee4bb9b311..3f96bb1d47 100644 --- a/pcsx2/IPU/IPUdma.cpp +++ b/pcsx2/IPU/IPUdma.cpp @@ -19,7 +19,7 @@ #include "IPU/IPUdma.h" #include "mpeg2lib/Mpeg.h" -static IPUStatus IPU1Status; +IPUStatus IPU1Status; static tIPU_DMA g_nDMATransfer; void ipuDmaReset() @@ -119,6 +119,13 @@ int IPU1dma() return 0; } + if (IPU1Status.DataRequested == false) + { + cpuRegs.eCycle[4] = 0x9999; + return 0; + } + + IPU_LOG("IPU1 DMA Called QWC %x Finished %d In Progress %d tadr %x", ipu1ch.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1ch.tadr); switch(IPU1Status.DMAMode) @@ -174,16 +181,27 @@ int IPU1dma() } //Do this here to prevent double settings on Chain DMA's - if(totalqwc > 0 || ipu1ch.qwc == 0) + if(totalqwc == 0 || (IPU1Status.DMAFinished && !IPU1Status.InProgress)) { - IPU_INT_TO(totalqwc * BIAS); - IPUProcessInterrupt(); + totalqwc = std::min(4, totalqwc); + IPU_INT_TO(4); } else { - cpuRegs.eCycle[4] = 0x9999;//IPU_INT_TO(2048); + + if (g_BP.IFC == 8) + { + IPU1Status.DataRequested = false; + cpuRegs.eCycle[4] = 0x9999;//IPU_INT_TO(2048); + } + else + { + IPU_INT_TO(totalqwc*BIAS); + } } + IPUProcessInterrupt(); + IPU_LOG("Completed Call IPU1 DMA QWC Remaining %x Finished %d In Progress %d tadr %x", ipu1ch.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1ch.tadr); return totalqwc; } @@ -296,7 +314,10 @@ __fi void dmaIPU1() // toIPU } IPU1Status.DMAMode = DMA_MODE_CHAIN; - IPU1dma(); + if(ipuRegs.ctrl.BUSY || IPU1Status.DataRequested) + IPU1dma(); + else + cpuRegs.eCycle[4] = 0x9999; } else //Normal Mode { @@ -304,7 +325,10 @@ __fi void dmaIPU1() // toIPU IPU1Status.InProgress = true; IPU1Status.DMAFinished = true; IPU1Status.DMAMode = DMA_MODE_NORMAL; - IPU1dma(); + if (ipuRegs.ctrl.BUSY || IPU1Status.DataRequested) + IPU1dma(); + else + cpuRegs.eCycle[4] = 0x9999; } } diff --git a/pcsx2/IPU/IPUdma.h b/pcsx2/IPU/IPUdma.h index 44a2dc0565..4be61e4261 100644 --- a/pcsx2/IPU/IPUdma.h +++ b/pcsx2/IPU/IPUdma.h @@ -29,6 +29,7 @@ struct IPUStatus { bool stalled; u8 ChainMode; u32 NextMem; + bool DataRequested; }; #define DMA_MODE_NORMAL 0 @@ -91,3 +92,4 @@ extern void IPU0dma(); extern int IPU1dma(); extern void ipuDmaReset(); +extern IPUStatus IPU1Status;