-Implemented GIF_MODE Masking fixed the All Star Pro Wrestling series slowness/hanging.

DMA: 
-Standardize the IPU and SIF dma's to use the standard chain handling in hw.c, fixed up some DMA resuming stuff in the forementioned units, VIF, GIF and SPR.

-Added some warnings for DMA stall control which isn't implemented, hopefully somebody will find a game that does it so we can add/test it :)

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5915 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction 2014-02-26 22:34:02 +00:00
parent e24f3585d4
commit 35b5e6a923
16 changed files with 336 additions and 376 deletions

View File

@ -547,6 +547,11 @@ static DMACh& vif1ch = (DMACh&)eeHw[0x9000];
static DMACh& gifch = (DMACh&)eeHw[0xA000];
static DMACh& spr0ch = (DMACh&)eeHw[0xD000];
static DMACh& spr1ch = (DMACh&)eeHw[0xD400];
static DMACh& ipu0ch = (DMACh&)eeHw[0xb000];
static DMACh& ipu1ch = (DMACh&)eeHw[0xb400];
static DMACh& sif0ch = (DMACh&)eeHw[0xc000];
static DMACh& sif1ch = (DMACh&)eeHw[0xc400];
static DMACh& sif2dma = (DMACh&)eeHw[0xc800];
extern void throwBusError(const char *s);
extern void setDmacStat(u32 num);

View File

@ -229,7 +229,7 @@ void GIFdma()
if (dmacRegs.ctrl.STD == STD_GIF)
{
// there are still bugs, need to also check if gifch.madr +16*qwc >= stadr, if not, stall
if (!gspath3done && ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR) && (ptag->ID == TAG_REFS))
if ((ptag->ID == TAG_REFS) && ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR))
{
// stalled.
// We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)
@ -246,6 +246,10 @@ void GIFdma()
checkTieBit(ptag);
}
else if (dmacRegs.ctrl.STD == STD_GIF && gifch.chcr.MOD == NORMAL_MODE)
{
Console.WriteLn("GIF DMA Stall in Normal mode not implemented - Report which game to PCSX2 Team");
}
clearFIFOstuff(true);
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
@ -296,7 +300,7 @@ void dmaGIF()
if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0) {
//DevCon.Warning(L"GIF QWC on Chain " + gifch.chcr.desc());
if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END)) {
if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END) || (gifch.chcr.tag().IRQ && gifch.chcr.TIE)) {
gspath3done = true;
}
}
@ -456,7 +460,10 @@ void mfifoGIFtransfer(int qwc)
ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr, gifqwc, spr0ch.madr);
gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
if (dmacRegs.ctrl.STD == STD_GIF && (ptag->ID == TAG_REFS))
{
Console.WriteLn("GIF MFIFO DMA Stall not implemented - Report which game to PCSX2 Team");
}
mfifoGifMaskMem(ptag->ID);
if(gspath3done == true) gifstate = GIF_STATE_DONE;

View File

@ -308,11 +308,15 @@ if this doesnt happen, which was the reasoning for the hacked up SPR timing we h
-Refraction
******************************/
void hwDmacSrcTadrInc(DMACh& dma)
inline void hwDmacSrcTadrInc(DMACh& dma)
{
//Don't touch it if in normal/interleave mode.
if (dma.chcr.STR == 0) return;
if (dma.chcr.MOD != 1) return;
u16 tagid = (dma.chcr.TAG >> 12) & 0x7;
if(tagid == TAG_CNT)
if (tagid == TAG_CNT)
{
dma.tadr = dma.madr;
}

View File

@ -102,8 +102,16 @@ void __fastcall _hwWrite32( u32 mem, u32 value )
icase(GIF_MODE)
{
// need to set GIF_MODE (hamster ball)
gifRegs.mode.write(value);
//Need to kickstart the GIF if the M3R mask comes off
if (gifRegs.stat.M3R == 1 && gifRegs.mode.M3R == 0 && gifch.chcr.STR)
{
DevCon.Warning("GIF Mode cancelling P3 Disable");
CPU_INT(DMAC_GIF, 8);
}
gifRegs.stat.M3R = gifRegs.mode.M3R;
gifRegs.stat.IMT = gifRegs.mode.IMT;
return;

View File

@ -61,7 +61,7 @@ void tIPU_cmd::clear()
__fi void IPUProcessInterrupt()
{
if (ipuRegs.ctrl.BUSY) // && (g_BP.FP || g_BP.IFC || (ipu1dma.chcr.STR && ipu1dma.qwc > 0)))
if (ipuRegs.ctrl.BUSY) // && (g_BP.FP || g_BP.IFC || (ipu1ch.chcr.STR && ipu1ch.qwc > 0)))
IPUWorker();
}
@ -873,7 +873,7 @@ __fi void IPUCMD_WRITE(u32 val)
case SCE_IPU_FDEC:
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, ipu1dma.chcr._u32);
val & 0x3f, g_BP.IFC, g_BP.BP, ipu1ch.chcr._u32);
g_BP.Advance(val & 0x3F);
ipuRegs.SetDataBusy();
@ -898,7 +898,7 @@ __fi void IPUCMD_WRITE(u32 val)
ipuRegs.ctrl.BUSY = 1;
//if(!ipu1dma.chcr.STR) hwIntcIrq(INTC_IPU);
//if(!ipu1ch.chcr.STR) hwIntcIrq(INTC_IPU);
}
__noinline void IPUWorker()
@ -922,7 +922,7 @@ __noinline void IPUWorker()
// CHECK!: IPU0dma remains when IDEC is done, so we need to clear it
// Check Mana Khemia 1 "off campus" to trigger a GUST IDEC messup.
// This hackfixes it :/
//if (ipu0dma.qwc > 0 && ipu0dma.chcr.STR) ipu0Interrupt();
//if (ipu0ch.qwc > 0 && ipu0ch.chcr.STR) ipu0Interrupt();
break;
case SCE_IPU_BDEC:

View File

@ -47,28 +47,28 @@ static __fi void ipuDmacSrcChain()
switch (IPU1Status.ChainMode)
{
case TAG_REFE: // refe
//if(IPU1Status.InProgress == false) ipu1dma.tadr += 16;
//if(IPU1Status.InProgress == false) ipu1ch.tadr += 16;
IPU1Status.DMAFinished = true;
break;
case TAG_CNT: // cnt
// Set the taddr to the next tag
ipu1dma.tadr = ipu1dma.madr;
ipu1ch.tadr = ipu1ch.madr;
//if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
break;
case TAG_NEXT: // next
ipu1dma.tadr = IPU1Status.NextMem;
ipu1ch.tadr = IPU1Status.NextMem;
//if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
break;
case TAG_REF: // ref
//if(IPU1Status.InProgress == false)ipu1dma.tadr += 16;
//if(IPU1Status.InProgress == false)ipu1ch.tadr += 16;
//if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
break;
case TAG_END: // end
//ipu1dma.tadr = ipu1dma.madr;
IPU1Status.DMAFinished = true;
//ipu1ch.tadr = ipu1ch.madr;
//IPU1Status.DMAFinished = true;
break;
}
}
@ -77,12 +77,12 @@ static __fi int IPU1chain() {
int totalqwc = 0;
if (ipu1dma.qwc > 0 && IPU1Status.InProgress == true)
if (ipu1ch.qwc > 0 && IPU1Status.InProgress == true)
{
int qwc = ipu1dma.qwc;
int qwc = ipu1ch.qwc;
u32 *pMem;
pMem = (u32*)dmaGetAddr(ipu1dma.madr, false);
pMem = (u32*)dmaGetAddr(ipu1ch.madr, false);
if (pMem == NULL)
{
@ -92,15 +92,16 @@ static __fi int IPU1chain() {
//Write our data to the fifo
qwc = ipu_fifo.in.write(pMem, qwc);
ipu1dma.madr += qwc << 4;
ipu1dma.qwc -= qwc;
ipu1ch.madr += qwc << 4;
ipu1ch.qwc -= qwc;
totalqwc += qwc;
}
//Update TADR etc
if(IPU1Status.DMAMode == DMA_MODE_CHAIN) ipuDmacSrcChain();
if( ipu1dma.qwc == 0)
hwDmacSrcTadrInc(ipu1ch);
if( ipu1ch.qwc == 0)
IPU1Status.InProgress = false;
return totalqwc;
@ -113,22 +114,22 @@ int IPU1dma()
//We need to make sure GIF has flushed before sending IPU data, it seems to REALLY screw FFX videos
if(ipu1dma.chcr.STR == false || IPU1Status.DMAMode == 2)
if(ipu1ch.chcr.STR == false || IPU1Status.DMAMode == 2)
{
//We MUST stop the IPU from trying to fill the FIFO with more data if the DMA has been suspended
//if we don't, we risk causing the data to go out of sync with the fifo and we end up losing some!
//This is true for Dragons Quest 8 and probably others which suspend the DMA.
DevCon.Warning("IPU1 running when IPU1 DMA disabled! CHCR %x QWC %x", ipu1dma.chcr._u32, ipu1dma.qwc);
DevCon.Warning("IPU1 running when IPU1 DMA disabled! CHCR %x QWC %x", ipu1ch.chcr._u32, ipu1ch.qwc);
return 0;
}
IPU_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", ipu1ch.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1ch.tadr);
switch(IPU1Status.DMAMode)
{
case DMA_MODE_NORMAL:
{
IPU_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", ipu1ch.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
if(IPU1Status.InProgress == true) totalqwc += IPU1chain();
}
break;
@ -137,82 +138,37 @@ int IPU1dma()
{
if(IPU1Status.InProgress == true) //No transfer is ready to go so we need to set one up
{
IPU_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", ipu1ch.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
totalqwc += IPU1chain();
//Set the TADR forward
}
if(IPU1Status.InProgress == false && IPU1Status.DMAFinished == false) //No transfer is ready to go so we need to set one up
{
tDMA_TAG* ptag = dmaGetAddr(ipu1dma.tadr, false); //Set memory pointer to TADR
tDMA_TAG* ptag = dmaGetAddr(ipu1ch.tadr, false); //Set memory pointer to TADR
if (!ipu1dma.transfer("IPU1", ptag))
if (!ipu1ch.transfer("IPU1", ptag))
{
return totalqwc;
}
ipu1ch.madr = ptag[1]._u32;
ipu1cycles += 1; // Add 1 cycles from the QW read for the tag
IPU1Status.ChainMode = ptag->ID;
if(ipu1dma.chcr.TTE) DevCon.Warning("TTE?");
if(ipu1ch.chcr.TTE) DevCon.Warning("TTE?");
IPU1Status.DMAFinished = hwDmacSrcChain(ipu1ch, ptag->ID);
switch (IPU1Status.ChainMode)
{
case TAG_REFE: // refe
// do not change tadr
//ipu1dma.tadr += 16;
ipu1dma.tadr += 16;
ipu1dma.madr = ptag[1]._u32;
IPU_LOG("Tag should end on %x", ipu1dma.tadr);
break;
case TAG_CNT: // cnt
ipu1dma.tadr += 16;
ipu1dma.madr = ipu1dma.tadr;
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;
break;
case TAG_NEXT: // next
ipu1dma.madr = ipu1dma.tadr + 16;
IPU1Status.NextMem = ptag[1]._u32;
IPU_LOG("Tag should end on %x", IPU1Status.NextMem);
//IPU1Status.DMAFinished = false;
break;
case TAG_REF: // ref
ipu1dma.madr = ptag[1]._u32;
ipu1dma.tadr += 16;
IPU_LOG("Tag should end on %x", ipu1dma.tadr);
//IPU1Status.DMAFinished = false;
break;
case TAG_END: // end
// do not change tadr
ipu1dma.madr = ipu1dma.tadr + 16;
//ipu1dma.tadr += 16;
IPU_LOG("Tag should end on %x", ipu1dma.madr + ipu1dma.qwc * 16);
break;
default:
DevCon.Error("IPU ERROR: different transfer mode!, Please report to PCSX2 Team");
break;
}
//if(ipu1dma.qwc == 0) Console.Warning("Blank QWC!");
if(ipu1dma.qwc > 0) IPU1Status.InProgress = true;
if(ipu1ch.qwc > 0) IPU1Status.InProgress = true;
IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x",
ptag[1]._u32, ptag[0]._u32, ipu1dma.qwc, ipu1dma.madr, 8 - g_BP.IFC);
ptag[1]._u32, ptag[0]._u32, ipu1ch.qwc, ipu1ch.madr, 8 - g_BP.IFC);
if (ipu1dma.chcr.TIE && ptag->IRQ) //Tag Interrupt is set, so schedule the end/interrupt
if (ipu1ch.chcr.TIE && ptag->IRQ) //Tag Interrupt is set, so schedule the end/interrupt
IPU1Status.DMAFinished = true;
IPU_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", ipu1ch.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
totalqwc += IPU1chain();
//Set the TADR forward
}
@ -222,7 +178,7 @@ int IPU1dma()
}
//Do this here to prevent double settings on Chain DMA's
if(totalqwc > 0 || ipu1dma.qwc == 0)
if(totalqwc > 0 || ipu1ch.qwc == 0)
{
IPU_INT_TO(totalqwc * BIAS);
IPUProcessInterrupt();
@ -232,7 +188,7 @@ int IPU1dma()
cpuRegs.eCycle[4] = 0x9999;//IPU_INT_TO(2048);
}
IPU_LOG("Completed Call IPU1 DMA QWC Remaining %x Finished %d In Progress %d tadr %x", ipu1dma.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1dma.tadr);
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;
}
@ -248,46 +204,45 @@ void IPU0dma()
int readsize;
tDMA_TAG* pMem;
if ((!(ipu0dma.chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma.qwc == 0))
if ((!(ipu0ch.chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0ch.qwc == 0))
{
DevCon.Warning("How??");
return;
}
pxAssert(!(ipu0dma.chcr.TTE));
pxAssert(!(ipu0ch.chcr.TTE));
IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx",
ipu0dma.chcr._u32, ipu0dma.madr, ipu0dma.qwc);
ipu0ch.chcr._u32, ipu0ch.madr, ipu0ch.qwc);
pxAssert(ipu0dma.chcr.MOD == NORMAL_MODE);
pxAssert(ipu0ch.chcr.MOD == NORMAL_MODE);
pMem = dmaGetAddr(ipu0dma.madr, true);
pMem = dmaGetAddr(ipu0ch.madr, true);
readsize = min(ipu0dma.qwc, (u16)ipuRegs.ctrl.OFC);
readsize = min(ipu0ch.qwc, (u16)ipuRegs.ctrl.OFC);
ipu_fifo.out.read(pMem, readsize);
ipu0dma.madr += readsize << 4;
ipu0dma.qwc -= readsize; // note: qwc is u16
ipu0ch.madr += readsize << 4;
ipu0ch.qwc -= readsize; // note: qwc is u16
if (ipu0dma.qwc == 0)
{
if (dmacRegs.ctrl.STS == STS_fromIPU) // STS == fromIPU
{
dmacRegs.stadr.ADDR = ipu0dma.madr;
dmacRegs.stadr.ADDR = ipu0ch.madr;
switch (dmacRegs.ctrl.STD)
{
case NO_STD:
break;
case STD_GIF: // GIF
DevCon.Warning("GIFSTALL");
//DevCon.Warning("GIFSTALL");
g_nDMATransfer.GIFSTALL = true;
break;
case STD_VIF1: // VIF
DevCon.Warning("VIFSTALL");
//DevCon.Warning("VIFSTALL");
g_nDMATransfer.VIFSTALL = true;
break;
case STD_SIF1:
DevCon.Warning("SIFSTALL");
// DevCon.Warning("SIFSTALL");
g_nDMATransfer.SIFSTALL = true;
break;
}
@ -296,7 +251,7 @@ void IPU0dma()
//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 );
if(ipuRegs.ctrl.IFC > 0) IPUProcessInterrupt();
@ -305,17 +260,17 @@ void IPU0dma()
__fi void dmaIPU0() // fromIPU
{
if (ipu0dma.pad != 0)
if (ipu0ch.pad != 0)
{
// Note: pad is the padding right above qwc, so we're testing whether qwc
// has overflowed into pad.
DevCon.Warning(L"IPU0dma's upper 16 bits set to %x", ipu0dma.pad);
ipu0dma.qwc = ipu0dma.pad = 0;
DevCon.Warning(L"IPU0dma's upper 16 bits set to %x", ipu0ch.pad);
ipu0ch.qwc = ipu0ch.pad = 0;
//If we are going to clear down IPU0, we should end it too. Going to test this scenario on the PS2 mind - Refraction
ipu0dma.chcr.STR = false;
ipu0ch.chcr.STR = false;
hwDmacIrq(DMAC_FROM_IPU);
}
//if (dmacRegs.ctrl.STS == STS_fromIPU) DevCon.Warning("DMA Stall enabled on IPU0");
IPU_INT_FROM( 64 );
@ -324,35 +279,42 @@ __fi void dmaIPU0() // fromIPU
__fi void dmaIPU1() // toIPU
{
IPU_LOG("IPU1DMAStart QWC %x, MADR %x, CHCR %x, TADR %x", ipu1dma.qwc, ipu1dma.madr, ipu1dma.chcr._u32, ipu1dma.tadr);
IPU_LOG("IPU1DMAStart QWC %x, MADR %x, CHCR %x, TADR %x", ipu1ch.qwc, ipu1ch.madr, ipu1ch.chcr._u32, ipu1ch.tadr);
if (ipu1dma.pad != 0)
if (ipu1ch.pad != 0)
{
// Note: pad is the padding right above qwc, so we're testing whether qwc
// has overflowed into pad.
DevCon.Warning(L"IPU1dma's upper 16 bits set to %x\n", ipu1dma.pad);
ipu1dma.qwc = ipu1dma.pad = 0;
DevCon.Warning(L"IPU1dma's upper 16 bits set to %x\n", ipu1ch.pad);
ipu1ch.qwc = ipu1ch.pad = 0;
// If we are going to clear down IPU1, we should end it too.
// Going to test this scenario on the PS2 mind - Refraction
ipu1dma.chcr.STR = false;
ipu1ch.chcr.STR = false;
hwDmacIrq(DMAC_TO_IPU);
}
if (ipu1dma.chcr.MOD == CHAIN_MODE) //Chain Mode
if (ipu1ch.chcr.MOD == CHAIN_MODE) //Chain Mode
{
IPU_LOG("Setting up IPU1 Chain mode");
if(ipu1dma.qwc == 0)
if(ipu1ch.qwc == 0)
{
IPU1Status.InProgress = false;
IPU1Status.DMAFinished = false;
}
else
{ //Attempting to continue a previous chain
IPU_LOG("Resuming DMA TAG %x", (ipu1dma.chcr.TAG >> 12));
IPU_LOG("Resuming DMA TAG %x", (ipu1ch.chcr.TAG >> 12));
//We MUST check the CHCR for the tag it last knew, it can be manipulated!
IPU1Status.ChainMode = (ipu1dma.chcr.TAG >> 12) & 0x7;
IPU1Status.ChainMode = (ipu1ch.chcr.TAG >> 12) & 0x7;
IPU1Status.InProgress = true;
IPU1Status.DMAFinished = ((ipu1dma.chcr.TAG >> 15) && ipu1dma.chcr.TIE) ? true : false;
if ((ipu1ch.chcr.tag().ID == TAG_REFE) || (ipu1ch.chcr.tag().ID == TAG_END) || (ipu1ch.chcr.tag().IRQ && ipu1ch.chcr.TIE))
{
IPU1Status.DMAFinished = true;
}
else
{
IPU1Status.DMAFinished = false;
}
}
IPU1Status.DMAMode = DMA_MODE_CHAIN;
@ -360,9 +322,9 @@ __fi void dmaIPU1() // toIPU
}
else //Normal Mode
{
if(ipu1dma.qwc == 0)
if(ipu1ch.qwc == 0)
{
ipu1dma.chcr.STR = false;
ipu1ch.chcr.STR = false;
// Hack to force stop IPU
ipuRegs.cmd.BUSY = 0;
ipuRegs.ctrl.BUSY = 0;
@ -388,7 +350,7 @@ void ipu0Interrupt()
{
IPU_LOG("ipu0Interrupt: %x", cpuRegs.cycle);
if(ipu0dma.qwc > 0)
if(ipu0ch.qwc > 0)
{
IPU0dma();
return;
@ -402,7 +364,7 @@ void ipu0Interrupt()
if (g_nDMATransfer.GIFSTALL)
{
// gif
DevCon.Warning("IPU GIF Stall");
//DevCon.Warning("IPU GIF Stall");
g_nDMATransfer.GIFSTALL = false;
//if (gif->chcr.STR) GIFdma();
}
@ -410,7 +372,7 @@ void ipu0Interrupt()
if (g_nDMATransfer.VIFSTALL)
{
// vif
DevCon.Warning("IPU VIF Stall");
//DevCon.Warning("IPU VIF Stall");
g_nDMATransfer.VIFSTALL = false;
//if (vif1ch.chcr.STR) dmaVIF1();
}
@ -418,12 +380,12 @@ void ipu0Interrupt()
if (g_nDMATransfer.SIFSTALL)
{
// sif
DevCon.Warning("IPU SIF Stall");
//DevCon.Warning("IPU SIF Stall");
g_nDMATransfer.SIFSTALL = false;
// Not totally sure whether this needs to be done or not, so I'm
// leaving it commented out for the moment.
//if (sif1dma.chcr.STR) SIF1Dma();
//if (sif1ch.chcr.STR) SIF1Dma();
}
if (g_nDMATransfer.TIE0)
@ -431,7 +393,7 @@ void ipu0Interrupt()
g_nDMATransfer.TIE0 = false;
}
ipu0dma.chcr.STR = false;
ipu0ch.chcr.STR = false;
hwDmacIrq(DMAC_FROM_IPU);
DMA_LOG("IPU0 DMA End");
}
@ -447,7 +409,7 @@ IPU_FORCEINLINE void ipu1Interrupt()
}
DMA_LOG("IPU1 DMA End");
ipu1dma.chcr.STR = false;
ipu1ch.chcr.STR = false;
IPU1Status.DMAMode = 2;
hwDmacIrq(DMAC_TO_IPU);
}

View File

@ -17,8 +17,7 @@
#include "IPU.h"
static DMACh& ipu0dma = (DMACh&)eeHw[0xb000];
static DMACh& ipu1dma = (DMACh&)eeHw[0xb400];
struct IPUStatus {
bool InProgress;

View File

@ -120,7 +120,7 @@ int _SPR0chain()
__fi void SPR0chain()
{
int cycles = 0;
cycles = _SPR0chain() * BIAS;
cycles = _SPR0chain() / BIAS;
CPU_INT(DMAC_FROM_SPR, cycles);
}
@ -136,7 +136,7 @@ void _SPR0interleave()
SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
spr0ch.qwc, tqwc, sqwc, spr0ch.madr, spr0ch.sadr);
CPU_INT(DMAC_FROM_SPR, qwc * BIAS);
CPU_INT(DMAC_FROM_SPR, qwc / BIAS);
while (qwc > 0)
{
@ -178,6 +178,10 @@ static __fi void _dmaSPR0()
{
case NORMAL_MODE:
{
if (dmacRegs.ctrl.STS == STS_fromSPR) // STS == fromSPR
{
Console.WriteLn("SPR stall control Normal not implemented");
}
SPR0chain();
spr0finished = true;
return;
@ -239,6 +243,10 @@ static __fi void _dmaSPR0()
//case INTERLEAVE_MODE:
default:
{
if (dmacRegs.ctrl.STS == STS_fromSPR) // STS == fromSPR
{
Console.WriteLn("SPR stall control interleave not implemented");
}
_SPR0interleave();
spr0finished = true;
break;
@ -352,7 +360,7 @@ __fi void SPR1chain()
int cycles = 0;
if(!CHECK_IPUWAITHACK)
{
cycles = _SPR1chain() * BIAS;
cycles = _SPR1chain() / BIAS;
CPU_INT(DMAC_TO_SPR, cycles);
}
else
@ -372,7 +380,7 @@ void _SPR1interleave()
if (tqwc == 0) tqwc = qwc;
SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
spr1ch.qwc, tqwc, sqwc, spr1ch.madr, spr1ch.sadr);
CPU_INT(DMAC_TO_SPR, qwc * BIAS);
CPU_INT(DMAC_TO_SPR, qwc / BIAS);
while (qwc > 0)
{
spr1ch.qwc = std::min(tqwc, qwc);
@ -432,7 +440,7 @@ void _dmaSPR1() // toSPR work function
SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx taddr=%lx saddr=%lx",
ptag[1]._u32, ptag[0]._u32, spr1ch.qwc, ptag->ID, spr1ch.madr, spr1ch.tadr, spr1ch.sadr);
done = (hwDmacSrcChain(spr1ch, ptag->ID));
done = hwDmacSrcChain(spr1ch, ptag->ID);
SPR1chain(); //Transfers the data set by the switch
if (spr1ch.chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag
@ -468,7 +476,7 @@ void dmaSPR1() // toSPR
if(spr1ch.chcr.MOD == CHAIN_MODE && spr1ch.qwc > 0)
{
//DevCon.Warning(L"SPR1 QWC on Chain " + spr1ch.chcr.desc());
if ((spr1ch.chcr.tag().ID == TAG_END) || (spr1ch.chcr.tag().ID == TAG_REFE))
if ((spr1ch.chcr.tag().ID == TAG_END) || (spr1ch.chcr.tag().ID == TAG_REFE) || (spr1ch.chcr.tag().IRQ && spr1ch.chcr.TIE))
{
spr1finished = true;
}

View File

@ -18,10 +18,6 @@
static const int FIFO_SIF_W = 128;
static DMACh& sif0dma = (DMACh&)eeHw[0xc000];
static DMACh& sif1dma = (DMACh&)eeHw[0xc400];
static DMACh& sif2dma = (DMACh&)eeHw[0xc800];
// Despite its name, this is actually the IOP's DMAtag, which itself also contains
// the EE's DMAtag in its upper 64 bits. Note that only the lower 24 bits of 'data' is
// the IOP's chain transfer address (loaded into MADR). Bits 30 and 31 are transfer stop

View File

@ -35,14 +35,14 @@ static __fi void Sif0Init()
// Write from Fifo to EE.
static __fi bool WriteFifoToEE()
{
const int readSize = min((s32)sif0dma.qwc, sif0.fifo.size >> 2);
const int readSize = min((s32)sif0ch.qwc, sif0.fifo.size >> 2);
tDMA_TAG *ptag;
//SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma.madr);
SIF_LOG("Write Fifo to EE: ----------- %lX of %lX", readSize << 2, sif0dma.qwc << 2);
//SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0ch.madr);
SIF_LOG("Write Fifo to EE: ----------- %lX of %lX", readSize << 2, sif0ch.qwc << 2);
ptag = sif0dma.getAddr(sif0dma.madr, DMAC_SIF0, true);
ptag = sif0ch.getAddr(sif0ch.madr, DMAC_SIF0, true);
if (ptag == NULL)
{
DevCon.Warning("Write Fifo to EE: ptag == NULL");
@ -52,11 +52,11 @@ static __fi bool WriteFifoToEE()
sif0.fifo.read((u32*)ptag, readSize << 2);
// Clearing handled by vtlb memory protection and manual blocks.
//Cpu->Clear(sif0dma.madr, readSize*4);
//Cpu->Clear(sif0ch.madr, readSize*4);
sif0dma.madr += readSize << 4;
sif0ch.madr += readSize << 4;
sif0.ee.cycles += readSize; // fixme : BIAS is factored in above
sif0dma.qwc -= readSize;
sif0ch.qwc -= readSize;
return true;
}
@ -79,7 +79,7 @@ static __fi bool WriteIOPtoFifo()
return true;
}
// Read Fifo into an ee tag, transfer it to sif0dma, and process it.
// Read Fifo into an ee tag, transfer it to sif0ch, and process it.
static __fi bool ProcessEETag()
{
static __aligned16 u32 tag[4];
@ -88,13 +88,13 @@ static __fi bool ProcessEETag()
sif0.fifo.read((u32*)&tag[0], 4); // Tag
SIF_LOG("SIF0 EE read tag: %x %x %x %x", tag[0], tag[1], tag[2], tag[3]);
sif0dma.unsafeTransfer(&ptag);
sif0dma.madr = tag[1];
sif0ch.unsafeTransfer(&ptag);
sif0ch.madr = tag[1];
SIF_LOG("SIF0 EE dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)",
sif0dma.madr, sif0dma.qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);
sif0ch.madr, sif0ch.qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);
if (sif0dma.chcr.TIE && ptag.IRQ)
if (sif0ch.chcr.TIE && ptag.IRQ)
{
//Console.WriteLn("SIF0 TIE");
sif0.ee.end = true;
@ -106,7 +106,7 @@ static __fi bool ProcessEETag()
case TAG_CNTS:
if (dmacRegs.ctrl.STS == STS_SIF0)
dmacRegs.stadr.ADDR = sif0dma.madr + (sif0dma.qwc * 16);
dmacRegs.stadr.ADDR = sif0ch.madr + (sif0ch.qwc * 16);
break;
case TAG_END:
@ -180,7 +180,7 @@ static __fi void EndIOP()
// Handle the EE transfer.
static __fi void HandleEETransfer()
{
if(sif0dma.chcr.STR == false)
if(sif0ch.chcr.STR == false)
{
//DevCon.Warning("Replacement for irq prevention hack EE SIF0");
sif0.ee.end = false;
@ -190,20 +190,20 @@ static __fi void HandleEETransfer()
if (dmacRegs.ctrl.STS == STS_SIF0)
{
DevCon.Warning("SIF0 stall control");
DevCon.Warning("SIF0 stall control not properly implemented");
}
/*if (sif0dma.qwc == 0)
if (sif0dma.chcr.MOD == NORMAL_MODE)
/*if (sif0ch.qwc == 0)
if (sif0ch.chcr.MOD == NORMAL_MODE)
if (!sif0.ee.end){
DevCon.Warning("sif0 irq prevented");
done = true;
return;
}*/
if (sif0dma.qwc <= 0)
if (sif0ch.qwc <= 0)
{
if ((sif0dma.chcr.MOD == NORMAL_MODE) || sif0.ee.end)
if ((sif0ch.chcr.MOD == NORMAL_MODE) || sif0.ee.end)
{
// Stop transferring ee, and signal an interrupt.
done = true;
@ -211,13 +211,13 @@ static __fi void HandleEETransfer()
}
else if (sif0.fifo.size >= 4) // Read a tag
{
// Read Fifo into an ee tag, transfer it to sif0dma
// Read Fifo into an ee tag, transfer it to sif0ch
// and process it.
ProcessEETag();
}
}
if (sif0dma.qwc > 0) // If we're writing something, continue to do so.
if (sif0ch.qwc > 0) // If we're writing something, continue to do so.
{
// Write from Fifo to EE.
if (sif0.fifo.size > 0)
@ -312,7 +312,7 @@ __fi void SIF0Dma()
}
if (sif0.ee.busy)
{
if(sif0.fifo.size >= 4 || (sif0.ee.end == true && sif0dma.qwc == 0))
if(sif0.fifo.size >= 4 || (sif0.ee.end == true && sif0ch.qwc == 0))
{
BusyCheck++;
HandleEETransfer();
@ -332,19 +332,19 @@ __fi void sif0Interrupt()
__fi void EEsif0Interrupt()
{
hwDmacIrq(DMAC_SIF0);
sif0dma.chcr.STR = false;
sif0ch.chcr.STR = false;
}
__fi void dmaSIF0()
{
SIF_LOG(wxString(L"dmaSIF0" + sif0dma.cmqt_to_str()).To8BitData());
SIF_LOG(wxString(L"dmaSIF0" + sif0ch.cmqt_to_str()).To8BitData());
if (sif0.fifo.readPos != sif0.fifo.writePos)
{
SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos");
}
//if(sif0dma.chcr.MOD == CHAIN_MODE && sif0dma.qwc > 0) DevCon.Warning(L"SIF0 QWC on Chain CHCR " + sif0dma.chcr.desc());
//if(sif0ch.chcr.MOD == CHAIN_MODE && sif0ch.qwc > 0) DevCon.Warning(L"SIF0 QWC on Chain CHCR " + sif0ch.chcr.desc());
psHu32(SBUS_F240) |= 0x2000;
sif0.ee.busy = true;

View File

@ -38,11 +38,11 @@ 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);
const int writeSize = min((s32)sif1ch.qwc, sif1.fifo.sif_free() >> 2);
tDMA_TAG *ptag;
ptag = sif1dma.getAddr(sif1dma.madr, DMAC_SIF1, false);
ptag = sif1ch.getAddr(sif1ch.madr, DMAC_SIF1, false);
if (ptag == NULL)
{
DevCon.Warning("Write EE to Fifo: ptag == NULL");
@ -51,10 +51,10 @@ static __fi bool WriteEEtoFifo()
sif1.fifo.write((u32*)ptag, writeSize << 2);
sif1dma.madr += writeSize << 4;
hwDmacSrcTadrInc(sif1dma);
sif1ch.madr += writeSize << 4;
hwDmacSrcTadrInc(sif1ch);
sif1.ee.cycles += writeSize; // fixme : BIAS is factored in above
sif1dma.qwc -= writeSize;
sif1ch.qwc -= writeSize;
return true;
}
@ -85,61 +85,31 @@ static __fi bool ProcessEETag()
tDMA_TAG *ptag;
SIF_LOG("Sif1: ProcessEETag");
// Process DMA tag at sif1dma.tadr
ptag = sif1dma.DMAtransfer(sif1dma.tadr, DMAC_SIF1);
// Process DMA tag at sif1ch.tadr
ptag = sif1ch.DMAtransfer(sif1ch.tadr, DMAC_SIF1);
if (ptag == NULL)
{
Console.WriteLn("Sif1 ProcessEETag: ptag = NULL");
return false;
}
if (sif1dma.chcr.TTE)
if (sif1ch.chcr.TTE)
{
Console.WriteLn("SIF1 TTE");
sif1.fifo.write((u32*)ptag + 2, 2);
}
if (sif1dma.chcr.TIE && ptag->IRQ)
if (sif1ch.chcr.TIE && ptag->IRQ)
{
Console.WriteLn("SIF1 TIE");
sif1.ee.end = true;
}
SIF_LOG(wxString(ptag->tag_to_str()).To8BitData());
switch (ptag->ID)
{
case TAG_REFE:
sif1.ee.end = true;
sif1dma.madr = ptag[1]._u32;
sif1dma.tadr += 16;
break;
sif1ch.madr = ptag[1]._u32;
case TAG_CNT:
sif1dma.tadr += 16;
sif1dma.madr = sif1dma.tadr;
break;
sif1.ee.end = hwDmacSrcChain(sif1ch, ptag->ID);
case TAG_NEXT:
sif1dma.madr = sif1dma.tadr + 16;
sif1dma.tadr = ptag[1]._u32;
break;
case TAG_REF:
case TAG_REFS:
if(ptag->ID == TAG_REFS && dmacRegs.ctrl.STD == STD_SIF1) DevCon.Warning("SIF1 Drain Stall Control not implemented");
sif1dma.madr = ptag[1]._u32;
sif1dma.tadr += 16;
break;
case TAG_END:
sif1.ee.end = true;
sif1dma.madr = sif1dma.tadr + 16;
//sif1dma.tadr = sif1dma.madr + (sif1dma.qwc << 4);
break;
default:
Console.WriteLn("Bad addr1 source chain");
}
return true;
}
@ -205,7 +175,7 @@ static __fi void EndIOP()
// Handle the EE transfer.
static __fi void HandleEETransfer()
{
if(sif1dma.chcr.STR == false)
if(sif1ch.chcr.STR == false)
{
//DevCon.Warning("Replacement for irq prevention hack EE SIF1");
sif1.ee.end = false;
@ -214,22 +184,22 @@ static __fi void HandleEETransfer()
}
if (dmacRegs.ctrl.STD == STD_SIF1)
{
DevCon.Warning("SIF1 stall control"); // STD == fromSIF1
DevCon.Warning("SIF1 stall control Not Implemented"); // STD == fromSIF1
}
/*if (sif1dma.qwc == 0)
if (sif1dma.chcr.MOD == NORMAL_MODE)
/*if (sif1ch.qwc == 0)
if (sif1ch.chcr.MOD == NORMAL_MODE)
if (!sif1.ee.end){
DevCon.Warning("sif1 irq prevented CHCR %x QWC %x", sif1dma.chcr, sif1dma.qwc);
DevCon.Warning("sif1 irq prevented CHCR %x QWC %x", sif1ch.chcr, sif1ch.qwc);
done = true;
return;
}*/
// If there's no more to transfer.
if (sif1dma.qwc <= 0)
if (sif1ch.qwc <= 0)
{
// If NORMAL mode or end of CHAIN then stop DMA.
if ((sif1dma.chcr.MOD == NORMAL_MODE) || sif1.ee.end)
if ((sif1ch.chcr.MOD == NORMAL_MODE) || sif1.ee.end)
{
done = true;
EndEE();
@ -297,7 +267,7 @@ __fi void SIF1Dma()
if (sif1.ee.busy)
{
if(sif1.fifo.sif_free() > 0 || (sif1.ee.end == true && sif1dma.qwc == 0))
if(sif1.fifo.sif_free() > 0 || (sif1.ee.end == true && sif1ch.qwc == 0))
{
BusyCheck++;
HandleEETransfer();
@ -327,37 +297,44 @@ __fi void sif1Interrupt()
__fi void EEsif1Interrupt()
{
hwDmacIrq(DMAC_SIF1);
sif1dma.chcr.STR = false;
sif1ch.chcr.STR = false;
}
// Do almost exactly the same thing as psxDma10 in IopDma.cpp.
// Main difference is this checks for iop, where psxDma10 checks for ee.
__fi void dmaSIF1()
{
SIF_LOG(wxString(L"dmaSIF1" + sif1dma.cmqt_to_str()).To8BitData());
SIF_LOG(wxString(L"dmaSIF1" + sif1ch.cmqt_to_str()).To8BitData());
if (sif1.fifo.readPos != sif1.fifo.writePos)
{
SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos");
}
//if(sif1dma.chcr.MOD == CHAIN_MODE && sif1dma.qwc > 0) DevCon.Warning(L"SIF1 QWC on Chain CHCR " + sif1dma.chcr.desc());
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.
//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;
if (sif1ch.chcr.MOD == CHAIN_MODE && sif1ch.qwc > 0)
{
if ((sif1ch.chcr.tag().ID == TAG_REFE) || (sif1ch.chcr.tag().ID == TAG_END) || (sif1ch.chcr.tag().IRQ && vif1ch.chcr.TIE))
{
sif1.ee.end = true;
}
}
SIF1Dma();
}

View File

@ -66,80 +66,69 @@ __fi void vif0SetupTransfer()
{
tDMA_TAG *ptag;
switch (vif0.dmamode)
ptag = dmaGetAddr(vif0ch.tadr, false); //Set memory pointer to TADR
if (!(vif0ch.transfer("vif0 Tag", ptag))) return;
vif0ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
g_vif0Cycles += 1; // Add 1 g_vifCycles from the QW read for the tag
// Transfer dma tag if tte is set
VIF_LOG("vif0 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
ptag[1]._u32, ptag[0]._u32, vif0ch.qwc, ptag->ID, vif0ch.madr, vif0ch.tadr);
vif0.inprogress = 0;
if (vif0ch.chcr.TTE)
{
case VIF_NORMAL_TO_MEM_MODE:
vif0.inprogress = 1;
vif0.done = true;
g_vif0Cycles = 2;
break;
// Transfer dma tag if tte is set
case VIF_CHAIN_MODE:
ptag = dmaGetAddr(vif0ch.tadr, false); //Set memory pointer to TADR
bool ret;
if (!(vif0ch.transfer("vif0 Tag", ptag))) return;
static __aligned16 u128 masked_tag;
vif0ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
g_vif0Cycles += 1; // Add 1 g_vifCycles from the QW read for the tag
masked_tag._u64[0] = 0;
masked_tag._u64[1] = *((u64*)ptag + 1);
// Transfer dma tag if tte is set
VIF_LOG("\tVIF0 SrcChain TTE=1, data = 0x%08x.%08x", masked_tag._u32[3], masked_tag._u32[2]);
VIF_LOG("vif0 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
ptag[1]._u32, ptag[0]._u32, vif0ch.qwc, ptag->ID, vif0ch.madr, vif0ch.tadr);
vif0.inprogress = 0;
if (vif0ch.chcr.TTE)
{
// Transfer dma tag if tte is set
bool ret;
static __aligned16 u128 masked_tag;
masked_tag._u64[0] = 0;
masked_tag._u64[1] = *((u64*)ptag + 1);
VIF_LOG("\tVIF0 SrcChain TTE=1, data = 0x%08x.%08x", masked_tag._u32[3], masked_tag._u32[2]);
if (vif0.irqoffset.enabled)
{
ret = VIF0transfer((u32*)&masked_tag + vif0.irqoffset.value, 4 - vif0.irqoffset.value, true); //Transfer Tag on stall
//ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset); //Transfer Tag on stall
}
else
{
//Some games (like killzone) do Tags mid unpack, the nops will just write blank data
//to the VU's, which breaks stuff, this is where the 128bit packet will fail, so we ignore the first 2 words
vif0.irqoffset.value = 2;
vif0.irqoffset.enabled = true;
ret = VIF0transfer((u32*)&masked_tag + 2, 2, true); //Transfer Tag
//ret = VIF0transfer((u32*)ptag + 2, 2); //Transfer Tag
}
if (vif0.irqoffset.enabled)
{
ret = VIF0transfer((u32*)&masked_tag + vif0.irqoffset.value, 4 - vif0.irqoffset.value, true); //Transfer Tag on stall
//ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset); //Transfer Tag on stall
}
else
{
//Some games (like killzone) do Tags mid unpack, the nops will just write blank data
//to the VU's, which breaks stuff, this is where the 128bit packet will fail, so we ignore the first 2 words
vif0.irqoffset.value = 2;
vif0.irqoffset.enabled = true;
ret = VIF0transfer((u32*)&masked_tag + 2, 2, true); //Transfer Tag
//ret = VIF0transfer((u32*)ptag + 2, 2); //Transfer Tag
}
if (!ret && vif0.irqoffset.enabled)
{
vif0.inprogress = 0; //Better clear this so it has to do it again (Jak 1)
return; //IRQ set by VIFTransfer
if (!ret && vif0.irqoffset.enabled)
{
vif0.inprogress = 0; //Better clear this so it has to do it again (Jak 1)
return; //IRQ set by VIFTransfer
}
}
}
}
vif0.irqoffset.value = 0;
vif0.irqoffset.enabled = false;
vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID);
vif0.irqoffset.value = 0;
vif0.irqoffset.enabled = false;
vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID);
if(vif0ch.qwc > 0) vif0.inprogress = 1;
//Check TIE bit of CHCR and IRQ bit of tag
if (vif0ch.chcr.TIE && ptag->IRQ)
{
VIF_LOG("dmaIrq Set");
if(vif0ch.qwc > 0) vif0.inprogress = 1;
//Check TIE bit of CHCR and IRQ bit of tag
if (vif0ch.chcr.TIE && ptag->IRQ)
{
VIF_LOG("dmaIrq Set");
//End Transfer
vif0.done = true;
return;
}
break;
//End Transfer
vif0.done = true;
return;
}
}
@ -254,7 +243,7 @@ __fi void vif0Interrupt()
return; //Dont want to end if vif is stalled.
}
#ifdef PCSX2_DEVBUILD
if (vif0ch.qwc > 0) Console.WriteLn("vif0 Ending with %x QWC left");
if (vif0ch.qwc > 0) Console.WriteLn("vif0 Ending with %x QWC left", vif0ch.qwc);
if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size);
#endif
@ -278,34 +267,37 @@ void dmaVIF0()
g_vif0Cycles = 0;
if ((vif0ch.chcr.MOD == NORMAL_MODE) || vif0ch.qwc > 0) // Normal Mode
if (vif0ch.qwc > 0) // Normal Mode
{
vif0.dmamode = VIF_NORMAL_TO_MEM_MODE;
if (vif0ch.chcr.MOD == CHAIN_MODE)
{
vif0.dmamode = VIF_CHAIN_MODE;
if(vif0.irqoffset.enabled == true && vif0.done == false)
if ((vif0ch.chcr.tag().ID == TAG_REFE) || (vif0ch.chcr.tag().ID == TAG_END) || (vif0ch.chcr.tag().IRQ && vif0ch.chcr.TIE))
{
if(vif0ch.chcr.MOD == NORMAL_MODE)DevCon.Warning("Warning! VIF0 starting a new Normal transfer with vif offset set (Possible force stop?)");
else if(vif0ch.qwc == 0) DevCon.Warning("Warning! VIF0 starting a new Chain transfer with vif offset set (Possible force stop?)");
vif0.done = true;
}
vif0.done = false;
if(vif0ch.chcr.MOD == CHAIN_MODE && vif0ch.qwc > 0)
else
{
vif0.dmamode = VIF_CHAIN_MODE;
DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch.chcr.desc());
if ((vif0ch.chcr.tag().ID == TAG_REFE) || (vif0ch.chcr.tag().ID == TAG_END))
{
vif0.done = true;
}
vif0.done = false;
}
}
else //Assume Normal mode.
{
vif0.dmamode = VIF_NORMAL_FROM_MEM_MODE;
if (vif0.irqoffset.enabled == true && vif0.done == false) DevCon.Warning("Warning! VIF0 starting a Normal transfer with vif offset set (Possible force stop?)");
vif0.done = true;
}
vif0.inprogress |= 1;
}
else
{
if (vif0.irqoffset.enabled == true && vif0.done == false) DevCon.Warning("Warning! VIF0 starting a new Chain transfer with vif offset set (Possible force stop?)");
vif0.dmamode = VIF_CHAIN_MODE;
vif0.done = false;
vif0.inprogress &= ~0x1;
}
vif0Regs.stat.FQC = min((u16)0x8, vif0ch.qwc);

View File

@ -136,84 +136,81 @@ __fi void vif1SetupTransfer()
{
tDMA_TAG *ptag;
switch (vif1.dmamode)
ptag = dmaGetAddr(vif1ch.tadr, false); //Set memory pointer to TADR
if (!(vif1ch.transfer("Vif1 Tag", ptag))) return;
vif1ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
g_vif1Cycles += 1; // Add 1 g_vifCycles from the QW read for the tag
vif1.inprogress &= ~1;
VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
ptag[1]._u32, ptag[0]._u32, vif1ch.qwc, ptag->ID, vif1ch.madr, vif1ch.tadr);
if (!vif1.done && ((dmacRegs.ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS))) // STD == VIF1
{
case VIF_CHAIN_MODE:
ptag = dmaGetAddr(vif1ch.tadr, false); //Set memory pointer to TADR
if (!(vif1ch.transfer("Vif1 Tag", ptag))) return;
vif1ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
g_vif1Cycles += 1; // Add 1 g_vifCycles from the QW read for the tag
VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
ptag[1]._u32, ptag[0]._u32, vif1ch.qwc, ptag->ID, vif1ch.madr, vif1ch.tadr);
if (!vif1.done && ((dmacRegs.ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS))) // STD == VIF1
{
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
if ((vif1ch.madr + vif1ch.qwc * 16) >= dmacRegs.stadr.ADDR)
{
// stalled
hwDmacIrq(DMAC_STALL_SIS);
return;
}
}
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
if ((vif1ch.madr + vif1ch.qwc * 16) >= dmacRegs.stadr.ADDR)
{
//DevCon.Warning("VIF1 DMA Stall");
// stalled
hwDmacIrq(DMAC_STALL_SIS);
return;
}
}
vif1.inprogress &= ~1;
if (vif1ch.chcr.TTE)
{
// Transfer dma tag if tte is set
if (vif1ch.chcr.TTE)
{
// Transfer dma tag if tte is set
bool ret;
bool ret;
static __aligned16 u128 masked_tag;
static __aligned16 u128 masked_tag;
masked_tag._u64[0] = 0;
masked_tag._u64[1] = *((u64*)ptag + 1);
masked_tag._u64[0] = 0;
masked_tag._u64[1] = *((u64*)ptag + 1);
VIF_LOG("\tVIF1 SrcChain TTE=1, data = 0x%08x.%08x", masked_tag._u32[3], masked_tag._u32[2]);
VIF_LOG("\tVIF1 SrcChain TTE=1, data = 0x%08x.%08x", masked_tag._u32[3], masked_tag._u32[2]);
if (vif1.irqoffset.enabled)
{
ret = VIF1transfer((u32*)&masked_tag + vif1.irqoffset.value, 4 - vif1.irqoffset.value, true); //Transfer Tag on stall
//ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset); //Transfer Tag on stall
}
else
{
//Some games (like killzone) do Tags mid unpack, the nops will just write blank data
//to the VU's, which breaks stuff, this is where the 128bit packet will fail, so we ignore the first 2 words
vif1.irqoffset.value = 2;
vif1.irqoffset.enabled = true;
ret = VIF1transfer((u32*)&masked_tag + 2, 2, true); //Transfer Tag
//ret = VIF1transfer((u32*)ptag + 2, 2); //Transfer Tag
}
if (vif1.irqoffset.enabled)
{
ret = VIF1transfer((u32*)&masked_tag + vif1.irqoffset.value, 4 - vif1.irqoffset.value, true); //Transfer Tag on stall
//ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset); //Transfer Tag on stall
}
else
{
//Some games (like killzone) do Tags mid unpack, the nops will just write blank data
//to the VU's, which breaks stuff, this is where the 128bit packet will fail, so we ignore the first 2 words
vif1.irqoffset.value = 2;
vif1.irqoffset.enabled = true;
ret = VIF1transfer((u32*)&masked_tag + 2, 2, true); //Transfer Tag
//ret = VIF1transfer((u32*)ptag + 2, 2); //Transfer Tag
}
if (!ret && vif1.irqoffset.enabled)
{
vif1.inprogress &= ~1; //Better clear this so it has to do it again (Jak 1)
return; //IRQ set by VIFTransfer
}
}
vif1.irqoffset.value = 0;
vif1.irqoffset.enabled = false;
if (!ret && vif1.irqoffset.enabled)
{
vif1.inprogress &= ~1; //Better clear this so it has to do it again (Jak 1)
return; //IRQ set by VIFTransfer
}
}
vif1.irqoffset.value = 0;
vif1.irqoffset.enabled = false;
vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID);
vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID);
if(vif1ch.qwc > 0) vif1.inprogress |= 1;
if(vif1ch.qwc > 0) vif1.inprogress |= 1;
//Check TIE bit of CHCR and IRQ bit of tag
if (vif1ch.chcr.TIE && ptag->IRQ)
{
VIF_LOG("dmaIrq Set");
//Check TIE bit of CHCR and IRQ bit of tag
if (vif1ch.chcr.TIE && ptag->IRQ)
{
VIF_LOG("dmaIrq Set");
//End Transfer
vif1.done = true;
return;
}
break;
//End Transfer
vif1.done = true;
return;
}
}
@ -433,7 +430,7 @@ void dmaVIF1()
vif1.dmamode = VIF_CHAIN_MODE;
//DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch.chcr.desc());
if ((vif1ch.chcr.tag().ID == TAG_REFE) || (vif1ch.chcr.tag().ID == TAG_END))
if ((vif1ch.chcr.tag().ID == TAG_REFE) || (vif1ch.chcr.tag().ID == TAG_END) || (vif1ch.chcr.tag().IRQ && vif1ch.chcr.TIE))
{
vif1.done = true;
}
@ -445,9 +442,9 @@ void dmaVIF1()
else //Assume normal mode for reverse FIFO and Normal.
{
if (dmacRegs.ctrl.STD == STD_VIF1)
Console.WriteLn("DMA Stall Control on VIF1 normal");
Console.WriteLn("DMA Stall Control on VIF1 normal not implemented - Report which game to PCSX2 Team");
if (vif1ch.chcr.DIR) // to Memory
if (vif1ch.chcr.DIR) // from Memory
vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
else
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;

View File

@ -202,6 +202,11 @@ void mfifoVIF1transfer(int qwc)
vif1ch.tadr = qwctag(vif1ch.tadr);
ptag = dmaGetAddr(vif1ch.tadr, false);
if (dmacRegs.ctrl.STD == STD_VIF1 && (ptag->ID == TAG_REFS))
{
Console.WriteLn("VIF MFIFO DMA Stall not implemented - Report which game to PCSX2 Team");
}
if (vif1ch.chcr.TTE)
{
bool ret;

View File

@ -93,7 +93,7 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) {
vifXch.madr +=(transferred << 4);
vifXch.qwc -= transferred;
if (vifXch.chcr.STR) hwDmacSrcTadrInc(vifXch);
hwDmacSrcTadrInc(vifXch);
vifX.irqoffset.enabled = false;

View File

@ -33,14 +33,14 @@ s32 PrepareEERead()
"\n\tread tag: %x %x %x %x", hw_dma9.madr, hw_dma9.tadr, sif0.iop.counter, sif0words, sif0data,
tag[0], tag[1], tag[2], tag[3]);
sif0dma.unsafeTransfer(((tDMA_TAG*)(tag)));
sif0dma.madr = tag[1];
sif0ch.unsafeTransfer(((tDMA_TAG*)(tag)));
sif0ch.madr = tag[1];
tDMA_TAG ptag(tag[0]);
SIF_LOG("SIF0 EE dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)",
sif0dma.madr, sif0dma.qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);
sif0ch.madr, sif0ch.qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);
if (sif0dma.chcr.TIE && ptag.IRQ)
if (sif0ch.chcr.TIE && ptag.IRQ)
{
//Console.WriteLn("SIF0 TIE");
sif0.ee.end = true;
@ -51,12 +51,12 @@ s32 PrepareEERead()
case TAG_REFE:
sif0.ee.end = true;
if (dmacRegs.ctrl.STS != NO_STS)
dmacRegs.stadr.ADDR = sif0dma.madr + (sif0dma.qwc * 16);
dmacRegs.stadr.ADDR = sif0ch.madr + (sif0ch.qwc * 16);
break;
case TAG_REFS:
if (dmacRegs.ctrl.STS != NO_STS)
dmacRegs.stadr.ADDR = sif0dma.madr + (sif0dma.qwc * 16);
dmacRegs.stadr.ADDR = sif0ch.madr + (sif0ch.qwc * 16);
break;
case TAG_END:
@ -91,7 +91,7 @@ s32 DoSifRead(u32 iopAvailable)
SIF_LOG("Write IOP to EE: +++++++++++ %lX of %lX", transferSizeWords, sif0.iop.counter);
tDMA_TAG *ptag = sif0dma.getAddr(sif0dma.madr, DMAC_SIF0, true);
tDMA_TAG *ptag = sif0ch.getAddr(sif0ch.madr, DMAC_SIF0, true);
if (ptag == NULL)
{
DevCon.Warning("Write IOP to EE: ptag == NULL");
@ -101,11 +101,11 @@ s32 DoSifRead(u32 iopAvailable)
memcpy((u32*)ptag, (u32*)iopPhysMem(hw_dma9.madr), transferSizeBytes);
// Clearing handled by vtlb memory protection and manual blocks.
//Cpu->Clear(sif0dma.madr, readSize*4);
//Cpu->Clear(sif0ch.madr, readSize*4);
sif0dma.madr += transferSizeBytes;
sif0ch.madr += transferSizeBytes;
sif0.ee.cycles += transferSizeQWords * 2;
sif0dma.qwc -= transferSizeQWords;
sif0ch.qwc -= transferSizeQWords;
return transferSizeBytes;
}