IPU: Tidy up some DMA and FIFO behaviour

This commit is contained in:
refractionpcsx2 2021-12-22 10:40:08 +00:00
parent 8335b3ee77
commit 242655bac9
4 changed files with 19 additions and 27 deletions

View File

@ -296,7 +296,6 @@ void ipuSoftReset()
ipu_cmd.clear(); ipu_cmd.clear();
ipuRegs.cmd.BUSY = 0; ipuRegs.cmd.BUSY = 0;
ipuRegs.cmd.DATA = 0; // required for Enthusia - Professional Racing after fix, or will freeze at start of next video. 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); memzero(g_BP);
hwIntcIrq(INTC_IPU); // required for FightBox hwIntcIrq(INTC_IPU); // required for FightBox
} }
@ -370,11 +369,9 @@ static void ipuBCLR(u32 val)
psHu32(DMAC_STAT) &= ~(1 << DMAC_TO_IPU); psHu32(DMAC_STAT) &= ~(1 << DMAC_TO_IPU);
ipu_fifo.in.clear(); ipu_fifo.in.clear();
memzero(g_BP); memzero(g_BP);
g_BP.BP = val & 0x7F; g_BP.BP = val & 0x7F;
ipuRegs.ctrl.BUSY = 0;
ipuRegs.cmd.BUSY = 0; ipuRegs.cmd.BUSY = 0;
IPU_LOG("Clear IPU input FIFO. Set Bit offset=0x%X", g_BP.BP); IPU_LOG("Clear IPU input FIFO. Set Bit offset=0x%X", g_BP.BP);
} }
@ -876,12 +873,6 @@ __fi void IPUCMD_WRITE(u32 val)
ipuBCLR(val); ipuBCLR(val);
hwIntcIrq(INTC_IPU); //DMAC_TO_IPU hwIntcIrq(INTC_IPU); //DMAC_TO_IPU
ipuRegs.ctrl.BUSY = 0; ipuRegs.ctrl.BUSY = 0;
IPU1Status.DataRequested = true;
if (ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999)
{
CPU_INT(DMAC_TO_IPU, 32);
}
return; return;
case SCE_IPU_SETTH: case SCE_IPU_SETTH:
@ -890,8 +881,6 @@ __fi void IPUCMD_WRITE(u32 val)
ipuRegs.ctrl.BUSY = 0; ipuRegs.ctrl.BUSY = 0;
return; return;
case SCE_IPU_IDEC: case SCE_IPU_IDEC:
g_BP.Advance(val & 0x3F); g_BP.Advance(val & 0x3F);
ipuIDEC(val); ipuIDEC(val);
@ -912,7 +901,6 @@ __fi void IPUCMD_WRITE(u32 val)
case SCE_IPU_FDEC: case SCE_IPU_FDEC:
IPU_LOG("FDEC command. Skip 0x%X bits, FIFO 0x%X qwords, BP 0x%X, CHCR 0x%x", IPU_LOG("FDEC command. Skip 0x%X bits, FIFO 0x%X qwords, BP 0x%X, CHCR 0x%x",
val & 0x3f, g_BP.IFC, g_BP.BP, ipu1ch.chcr._u32); val & 0x3f, g_BP.IFC, g_BP.BP, ipu1ch.chcr._u32);
g_BP.Advance(val & 0x3F); g_BP.Advance(val & 0x3F);
ipuRegs.SetDataBusy(); ipuRegs.SetDataBusy();
break; break;

View File

@ -121,15 +121,16 @@ struct alignas(16) tIPU_BP {
__fi bool FillBuffer(u32 bits) __fi bool FillBuffer(u32 bits)
{ {
while (FP <= ((BP + bits) / 128)) while ((FP * 128) < (BP + bits))
{ {
if (ipu_fifo.in.read(&internal_qwc[FP]) == 0) if (ipu_fifo.in.read(&internal_qwc[FP]) == 0)
{ {
// Here we *try* to fill the entire internal QWC buffer; however that may not necessarily // Here we *try* to fill the entire internal QWC buffer; however that may not necessarily
// be possible -- so if the fill fails we'll only return 0 if we don't have enough // be possible -- so if the fill fails we'll only return 0 if we don't have enough
// remaining bits in the FIFO to fill the request. // remaining bits in the FIFO to fill the request.
// Used to do ((FP!=0) && (BP + bits) <= 128) if we get here there's defo not enough data now though
return ((FP!=0) && (BP + bits) <= 128); return false;
} }
++FP; ++FP;

View File

@ -38,6 +38,13 @@ void IPU_Fifo_Input::clear()
ipuRegs.ctrl.IFC = 0; ipuRegs.ctrl.IFC = 0;
readpos = 0; readpos = 0;
writepos = 0; writepos = 0;
// Because the FIFO is drained it will request more data immediately
IPU1Status.DataRequested = true;
if (ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999)
{
CPU_INT(DMAC_TO_IPU, 32);
}
} }
void IPU_Fifo_Output::clear() void IPU_Fifo_Output::clear()
@ -88,9 +95,10 @@ int IPU_Fifo_Input::read(void *value)
if (g_BP.IFC <= 1) 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 // 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;
if(ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999)
{ {
IPU1Status.DataRequested = true;
CPU_INT( DMAC_TO_IPU, 32 ); CPU_INT( DMAC_TO_IPU, 32 );
} }

View File

@ -260,15 +260,8 @@ void IPU0dma()
break; break;
} }
} }
//Fixme ( voodoocycles ):
//This was IPU_INT_FROM(readsize*BIAS );
//This broke vids in Digital Devil Saga
//Note that interrupting based on totalsize is just guessing..
IPU_INT_FROM( readsize * BIAS ); IPU_INT_FROM( readsize * BIAS );
if (ipuRegs.ctrl.IFC > 0) { IPUProcessInterrupt(); }
//return readsize;
} }
__fi void dmaIPU0() // fromIPU __fi void dmaIPU0() // fromIPU
@ -282,7 +275,9 @@ __fi void dmaIPU0() // fromIPU
// This is because the game sends bad DMA information, starts an IDEC, then sets it to the correct values // This is because the game sends bad DMA information, starts an IDEC, then sets it to the correct values
// but because our IPU is too quick, it messes up the sync between the DMA and IPU. // but because our IPU is too quick, it messes up the sync between the DMA and IPU.
// So this will do until (if) we sort the timing out of IPU, shouldn't cause any problems for games for now. // So this will do until (if) we sort the timing out of IPU, shouldn't cause any problems for games for now.
IPU_INT_FROM( 160 ); //IPU_INT_FROM( 160 );
// Update 22/12/2021 - Doesn't seem to need this now after fixing some FIFO/DMA behaviour
IPU0dma();
} }
__fi void dmaIPU1() // toIPU __fi void dmaIPU1() // toIPU
@ -314,7 +309,7 @@ __fi void dmaIPU1() // toIPU
} }
IPU1Status.DMAMode = DMA_MODE_CHAIN; IPU1Status.DMAMode = DMA_MODE_CHAIN;
if(ipuRegs.ctrl.BUSY || IPU1Status.DataRequested) if(IPU1Status.DataRequested)
IPU1dma(); IPU1dma();
else else
cpuRegs.eCycle[4] = 0x9999; cpuRegs.eCycle[4] = 0x9999;
@ -325,7 +320,7 @@ __fi void dmaIPU1() // toIPU
IPU1Status.InProgress = true; IPU1Status.InProgress = true;
IPU1Status.DMAFinished = true; IPU1Status.DMAFinished = true;
IPU1Status.DMAMode = DMA_MODE_NORMAL; IPU1Status.DMAMode = DMA_MODE_NORMAL;
if (ipuRegs.ctrl.BUSY || IPU1Status.DataRequested) if (IPU1Status.DataRequested)
IPU1dma(); IPU1dma();
else else
cpuRegs.eCycle[4] = 0x9999; cpuRegs.eCycle[4] = 0x9999;