Fix for Eternal Poison video (really this time :P)

There is a current issue with IPU causing videos to cut short, going to need to spend some time checking this

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2863 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction 2010-04-16 01:27:03 +00:00
parent 6382f6811b
commit d4d4d78c39
2 changed files with 57 additions and 32 deletions

View File

@ -62,9 +62,10 @@ static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
tDMA_CHCR chcr(value);
//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
if (chcr.STR && reg->chcr.STR && dmacRegs->ctrl.DMAE) {
if((reg->chcr._u32 & 0xff) == (chcr._u32 & 0xff) && psHu8(DMAC_ENABLER+2) == 0) //Tried to start another DMA in the same mode
DevCon.Warning(L"DMAExec32 Attempt to run DMA while one is already active in %s(%x)", ChcrName(mem), mem);
DevCon.Warning(L"DMAExec16 Attempt to run DMA while one is already active in %s(%x)", ChcrName(mem), mem);
else //Just trying to change mode without stopping the DMA, so we dont care really :P
{
HW_LOG("Attempted to change modes while DMA active, ignoring");
@ -76,6 +77,19 @@ static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
}
}
//This should be more correct, but the FFX video does some WIERD stuff and tries to stop and restart the IPU without suspending
/*if (reg->chcr.STR) {
if(psHu8(DMAC_ENABLER+2) == 0) // DMA Not in suspend mode
{
DevCon.Warning(L"DMAExec16 Attempt to alter DMA While not Suspended %s(%x) Current Val %x New Val %x", ChcrName(mem), mem, reg->chcr._u32, value);
// When DMA is active only STR field is writable, so we just
// call the dma transfer function w/o modifying CHCR contents...
//func();
Registers::Thaw();
return; // Test with Gust games and fatal frame
}
}*/
// Note: pad is the padding right above qwc, so we're testing whether qwc
// has overflowed into pad.
// Note2: May be only needed for IPU which has this handling in IPU.cpp now. (Fixes GS transfers)
@ -117,6 +131,19 @@ static void DmaExec( void (*func)(), u32 mem, u32 value )
}
}
//This should be more correct, but the FFX video does some WIERD stuff and tries to stop and restart the IPU without suspending
/*if (reg->chcr.STR) {
if(psHu8(DMAC_ENABLER+2) == 0) // DMA Not in suspend mode
{
DevCon.Warning(L"DMAExec32 Attempt to alter DMA While not Suspended %s(%x) Current Val %x New Val %x", ChcrName(mem), mem, reg->chcr._u32, value);
// When DMA is active only STR field is writable, so we just
// call the dma transfer function w/o modifying CHCR contents...
//func();
Registers::Thaw();
return; // Test with Gust games and fatal frame
}
}*/
// Note: pad is the padding right above qwc, so we're testing whether qwc
// has overflowed into pad.
// Note2: May be only needed for IPU which has this handling in IPU.cpp now. (Fixes GS transfers)

View File

@ -1251,42 +1251,40 @@ static __forceinline void ipuDmacSrcChain()
{
case 0x0: // refe
//if(IPU1Status.InProgress == false) ipu1dma->tadr += 16;
if(ipu1dma->qwc == 0) IPU1Status.DMAFinished = true;
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = true;
break;
case 0x1: // cnt
// Set the taddr to the next tag
ipu1dma->tadr = ipu1dma->madr;
if(ipu1dma->qwc == 0) IPU1Status.DMAFinished = false;
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
break;
case 0x2: // next
ipu1dma->tadr = IPU1Status.NextMem;
if(ipu1dma->qwc == 0) IPU1Status.DMAFinished = false;
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
break;
case 0x3: // ref
//if(IPU1Status.InProgress == false)ipu1dma->tadr += 16;
if(ipu1dma->qwc == 0) IPU1Status.DMAFinished = false;
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
break;
case 0x7: // end
ipu1dma->tadr = ipu1dma->madr;
if(ipu1dma->qwc == 0) IPU1Status.DMAFinished = true;
if(ipu1dma->qwc == 0 && IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = true;
break;
}
}
static __forceinline bool WaitGSPaths()
{
if (dmacRegs->ctrl.STD != STD_GIF || (gif->madr + (gif->qwc * 16)) < dmacRegs->stadr.ADDR)
if(GSTransferStatus.PTH3 < STOPPED_MODE)
{
if(gif->chcr.STR && (vif1Regs->mskpath3 == 0) && GSTransferStatus.PTH3 != STOPPED_MODE)
{
GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr._u32, gif->tadr, gif->madr, gif->qwc);
//DevCon.WriteLn("Waiting for GIF");
return false;
}
//GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr._u32, gif->tadr, gif->madr, gif->qwc);
//DevCon.WriteLn("Waiting for GIF");
return false;
}
if(GSTransferStatus.PTH2 != STOPPED_MODE)
{
//DevCon.WriteLn("Waiting for VIF");
@ -1344,7 +1342,7 @@ static __forceinline int IPU1chain() {
// if (GSTransferStatus._u32 != 0x2a)
// {
// if(GSTransferStatus.PTH3 != STOPPED_MODE && vif1Regs->mskpath3) return true;
// DMA_LOG("Waiting for GS transfers to finish %x", GSTransferStatus._u32);
// IPU_LOG("Waiting for GS transfers to finish %x", GSTransferStatus._u32);
// IPU_INT_TO(4);
// return false;
// }
@ -1364,7 +1362,7 @@ int IPU1dma()
DMA_LOG("IPU1 DMA Called QWC %x Finished %d In Progress %d tadr %x", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1dma->tadr);
IPU_LOG("IPU1 DMA Called QWC %x Finished %d In Progress %d tadr %x", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1dma->tadr);
switch(IPU1Status.DMAMode)
{
@ -1375,7 +1373,7 @@ int IPU1dma()
IPU_INT_TO(4); //Give it a short wait.
return totalqwc;
}
DMA_LOG("Processing Normal QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
IPU_LOG("Processing Normal QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
if(IPU1Status.InProgress == true) totalqwc += IPU1chain();
}
break;
@ -1389,7 +1387,7 @@ int IPU1dma()
IPU_INT_TO(4); //Give it a short wait.
return totalqwc;
}
DMA_LOG("Processing Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
IPU_LOG("Processing Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
totalqwc += IPU1chain();
//Set the TADR forward
ipuDmacSrcChain();
@ -1425,13 +1423,13 @@ int IPU1dma()
//ipu1dma->tadr += 16;
ipu1dma->tadr += 16;
ipu1dma->madr = ptag[1];
DMA_LOG("Tag should end on %x", ipu1dma->tadr);
IPU_LOG("Tag should end on %x", ipu1dma->tadr);
break;
case 0x1: // cnt
ipu1dma->madr = ipu1dma->tadr + 16;
DMA_LOG("Tag should end on %x", ipu1dma->madr + ipu1dma->qwc * 16);
IPU_LOG("Tag should end on %x", ipu1dma->madr + ipu1dma->qwc * 16);
//ipu1dma->tadr = ipu1dma->madr + (ipu1dma->qwc * 16);
// Set the taddr to the next tag
//IPU1Status.DMAFinished = false;
@ -1440,14 +1438,14 @@ int IPU1dma()
case 0x2: // next
ipu1dma->madr = ipu1dma->tadr + 16;
IPU1Status.NextMem = ptag[1];
DMA_LOG("Tag should end on %x", IPU1Status.NextMem);
IPU_LOG("Tag should end on %x", IPU1Status.NextMem);
//IPU1Status.DMAFinished = false;
break;
case 0x3: // ref
ipu1dma->madr = ptag[1];
ipu1dma->tadr += 16;
DMA_LOG("Tag should end on %x", ipu1dma->tadr);
IPU_LOG("Tag should end on %x", ipu1dma->tadr);
//IPU1Status.DMAFinished = false;
break;
@ -1455,7 +1453,7 @@ int IPU1dma()
// do not change tadr
ipu1dma->madr = ipu1dma->tadr + 16;
ipu1dma->tadr += 16;
DMA_LOG("Tag should end on %x", ipu1dma->madr + ipu1dma->qwc * 16);
IPU_LOG("Tag should end on %x", ipu1dma->madr + ipu1dma->qwc * 16);
break;
@ -1466,10 +1464,10 @@ int IPU1dma()
//if(ipu1dma->qwc == 0) Console.Warning("Blank QWC!");
if(ipu1dma->qwc > 0) IPU1Status.InProgress = true;
DMA_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x",
IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x",
ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC);
if ((ipu1dma->chcr._u32 & 0x80) && ptag[0] & 0x80000000) //Tag Interrupt is set, so schedule the end/interrupt
if (ipu1dma->chcr.TIE && (ptag[0] & 0x80000000)) //Tag Interrupt is set, so schedule the end/interrupt
IPU1Status.DMAFinished = true;
@ -1478,7 +1476,7 @@ int IPU1dma()
IPU_INT_TO(4); //Give it a short wait.
return totalqwc;
}
DMA_LOG("Processing Start Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
IPU_LOG("Processing Start Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
totalqwc += IPU1chain();
//Set the TADR forward
ipuDmacSrcChain();
@ -1567,10 +1565,10 @@ __forceinline void dmaIPU0() // fromIPU
__forceinline void dmaIPU1() // toIPU
{
IPU_LOG("IPU1DMAStart QWC %x, MADR %x, CHCR %x, TADR %x", ipu1dma->qwc, ipu1dma->madr, ipu1dma->chcr._u32, ipu1dma->tadr);
if(ipu1dma->chcr.MOD == 1) //Chain Mode
{
DMA_LOG("Setting up IPU1 Chain mode");
IPU_LOG("Setting up IPU1 Chain mode");
if(ipu1dma->qwc == 0)
{
IPU1Status.InProgress = false;
@ -1603,7 +1601,7 @@ __forceinline void dmaIPU1() // toIPU
}
else
{
DMA_LOG("Setting up IPU1 Normal mode");
IPU_LOG("Setting up IPU1 Normal mode");
IPU1Status.InProgress = true;
IPU1Status.DMAFinished = true;
IPU1Status.DMAMode = DMA_MODE_NORMAL;
@ -1628,6 +1626,7 @@ void ipu0Interrupt()
if (g_nDMATransfer.GIFSTALL)
{
// gif
Console.Warning("IPU GIF Stall");
g_nDMATransfer.GIFSTALL = false;
//if (gif->chcr.STR) GIFdma();
}
@ -1635,6 +1634,7 @@ void ipu0Interrupt()
if (g_nDMATransfer.VIFSTALL)
{
// vif
Console.Warning("IPU VIF Stall");
g_nDMATransfer.VIFSTALL = false;
if (vif1ch->chcr.STR) dmaVIF1();
}
@ -1642,6 +1642,7 @@ void ipu0Interrupt()
if (g_nDMATransfer.SIFSTALL)
{
// sif
Console.Warning("IPU SIF Stall");
g_nDMATransfer.SIFSTALL = false;
// Not totally sure whether this needs to be done or not, so I'm
@ -1660,7 +1661,7 @@ void ipu0Interrupt()
IPU_FORCEINLINE void ipu1Interrupt()
{
DMA_LOG("ipu1Interrupt %x:", cpuRegs.cycle);
IPU_LOG("ipu1Interrupt %x:", cpuRegs.cycle);
if(IPU1Status.DMAFinished == false || IPU1Status.InProgress == true) //Sanity Check
{
@ -1670,9 +1671,6 @@ IPU_FORCEINLINE void ipu1Interrupt()
return;
}
//Console.Warning("Whoops");
ipu1dma->chcr.STR = false;
hwDmacIrq(DMAC_TO_IPU);
}