From 928816732b64a19c86dd0ad8b02c993295b08153 Mon Sep 17 00:00:00 2001 From: refraction Date: Fri, 26 Mar 2010 00:06:29 +0000 Subject: [PATCH] -Fixed a small bug in the unpack dynarec causing it to drop back to the interpreter (MGS3 - now about 10fps faster!) -Rewrote VIF0 DMA to work like VIF1, report any breakage from it. -Tweaked a couple of cycle bits when stalling VIF git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2766 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Vif.cpp | 11 +-- pcsx2/Vif0_Dma.cpp | 180 +++++++++++++++++++++-------------- pcsx2/Vif1_Dma.cpp | 1 + pcsx2/x86/newVif_Dynarec.cpp | 8 +- 4 files changed, 118 insertions(+), 82 deletions(-) diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index 12b3c49dc7..7fa267910b 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -143,13 +143,8 @@ _f void vif0FBRST(u32 value) { g_vifCycles = 0; // loop necessary for spiderman - if (vif0.stallontag) - _chainVIF0(); - else - _VIF0chain(); - vif0ch->chcr.STR = true; - CPU_INT(DMAC_VIF0, g_vifCycles); // Gets the timing right - Flatout + CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout } } } @@ -225,14 +220,14 @@ _f void vif1FBRST(u32 value) { { case MFD_VIF1: //Console.WriteLn("MFIFO Stall"); - CPU_INT(10, vif1ch->qwc * BIAS); + CPU_INT(10, 0); break; case NO_MFD: case MFD_RESERVED: case MFD_GIF: // Wonder if this should be with VIF? // Gets the timing right - Flatout - CPU_INT(DMAC_VIF1, vif1ch->qwc * BIAS); + CPU_INT(DMAC_VIF1, 0); break; } diff --git a/pcsx2/Vif0_Dma.cpp b/pcsx2/Vif0_Dma.cpp index 97553c39c1..4fe446f57a 100644 --- a/pcsx2/Vif0_Dma.cpp +++ b/pcsx2/Vif0_Dma.cpp @@ -29,11 +29,15 @@ __forceinline void vif0FLUSH() g_vifCycles += (VU0.cycle - _cycles) * BIAS; } -bool _VIF0chain() +bool _VIF0chain() { u32 *pMem; - if ((vif0ch->qwc == 0) && !vif0.vifstalled) return true; + if (vif0ch->qwc == 0) + { + vif0.inprogress = 0; + return true; + } pMem = (u32*)dmaGetAddr(vif0ch->madr); if (pMem == NULL) @@ -44,88 +48,115 @@ bool _VIF0chain() return true; } + VIF_LOG("VIF0chain size=%d, madr=%lx, tadr=%lx", + vif0ch->qwc, vif0ch->madr, vif0ch->tadr); + if (vif0.vifstalled) return VIF0transfer(pMem + vif0.irqoffset, vif0ch->qwc * 4 - vif0.irqoffset, false); else return VIF0transfer(pMem, vif0ch->qwc * 4, false); } -bool _chainVIF0() +__forceinline void vif0SetupTransfer() { tDMA_TAG *ptag; - ptag = dmaGetAddr(vif0ch->tadr); //Set memory pointer to TADR - - if (!(vif0ch->transfer("Vif0 Tag", ptag))) return false; - - vif0ch->madr = ptag[1]._u32; // MADR = ADDR field + SPR - g_vifCycles += 1; // Increase the QW read for the tag - - VIF_LOG("dmaChain %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); - - // Transfer dma tag if tte is set - if (vif0ch->chcr.TTE) + switch (vif0.dmamode) { - bool ret; + case VIF_NORMAL_TO_MEM_MODE: + vif0.inprogress = 1; + vif0.done = true; + g_vifCycles = 2; + break; - if (vif0.vifstalled) - ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset, true); //Transfer Tag on stall - else - ret = VIF0transfer((u32*)ptag + 2, 2, true); //Transfer Tag + case VIF_CHAIN_MODE: + ptag = dmaGetAddr(vif0ch->tadr); //Set memory pointer to TADR - if (!(ret)) return false; //IRQ set by VIFTransfer + if (!(vif0ch->transfer("vif0 Tag", ptag))) return; + + vif0ch->madr = ptag[1]._u32; //MADR = ADDR field + SPR + g_vifCycles += 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\n", + ptag[1]._u32, ptag[0]._u32, vif0ch->qwc, ptag->ID, vif0ch->madr, vif0ch->tadr); + + vif0.inprogress = 1; + + if (vif0ch->chcr.TTE) + { + bool ret; + + if (vif0.vifstalled) + ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset, true); //Transfer Tag on stall + else + ret = VIF0transfer((u32*)ptag + 2, 2, true); //Transfer Tag + + if ((ret == false) && vif0.irqoffset < 2) + { + vif0.inprogress = 0; //Better clear this so it has to do it again (Jak 1) + return; //There has been an error or an interrupt + } + } + + vif0.irqoffset = 0; + vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID); + + //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; } - - vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID); - - VIF_LOG("dmaChain %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); - - _VIF0chain(); //Transfers the data set by the switch - - if (vif0ch->chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag - { - VIF_LOG("dmaIrq Set\n"); - vif0.done = true; //End Transfer - } - - return vif0.done; } -void vif0Interrupt() +__forceinline void vif0Interrupt() { - g_vifCycles = 0; //Reset the cycle count, Wouldn't reset on stall if put lower down. VIF_LOG("vif0Interrupt: %8.8x", cpuRegs.cycle); - if (vif0.irq && (vif0.tag.size == 0)) + g_vifCycles = 0; + + if (!(vif0ch->chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch->chcr._u32); + + if (vif0.irq && vif0.tag.size == 0) { vif0Regs->stat.INT = true; hwIntcIrq(VIF0intc); --vif0.irq; - if (vif0Regs->stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS)) { vif0Regs->stat.FQC = 0; + + // One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho vif0ch->chcr.STR = false; return; } - - if (vif0ch->qwc > 0 || vif0.irqoffset > 0) + else if ((vif0ch->qwc > 0) || (vif0.irqoffset > 0)) { if (vif0.stallontag) - _chainVIF0(); + vif0SetupTransfer(); else - _VIF0chain(); - - CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo); - return; + _VIF0chain();//CPU_INT(DMAC_STALL_SIS, vif0ch->qwc * BIAS); } } - if (!vif0ch->chcr.STR) Console.WriteLn("Vif0 running when CHCR = %x", vif0ch->chcr._u32); + if (vif0.inprogress & 0x1) + { + _VIF0chain(); + // VIF_NORMAL_FROM_MEM_MODE is a very slow operation. + // Timesplitters 2 depends on this beeing a bit higher than 128. + if (vif0.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF0, 1024); + else CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo); + return; + } - if ((vif0ch->chcr.MOD == CHAIN_MODE) && (!vif0.done)) + if (!vif0.done) { if (!(dmacRegs->ctrl.DMAE)) @@ -134,19 +165,26 @@ void vif0Interrupt() return; } - if (vif0ch->qwc > 0) - _VIF0chain(); - else - _chainVIF0(); + if ((vif0.inprogress & 0x1) == 0) vif0SetupTransfer(); CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo); return; } - if (vif0ch->qwc > 0) Console.WriteLn("VIF0 Ending with QWC left"); - if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x", vif0.cmd); + if (vif0.vifstalled && vif0.irq) + { + DevCon.WriteLn("VIF0 looping on stall\n"); + CPU_INT(DMAC_VIF0, 0); + 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 (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size); +#endif + vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands; vif0ch->chcr.STR = false; + g_vifCycles = 0; hwDmacIrq(DMAC_VIF0); vif0Regs->stat.FQC = 0; } @@ -154,30 +192,28 @@ void vif0Interrupt() void dmaVIF0() { VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n" - " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + " tadr = %lx, asr0 = %lx, asr1 = %lx", vif0ch->chcr._u32, vif0ch->madr, vif0ch->qwc, vif0ch->tadr, vif0ch->asr0, vif0ch->asr1); g_vifCycles = 0; + vif0.inprogress = 0; - vif0Regs->stat.FQC = 0x8; // FQC=8 - - if (!(vif0ch->chcr.MOD & 0x1) || vif0ch->qwc > 0) // Normal Mode + if ((vif0ch->chcr.MOD == NORMAL_MODE) || vif0ch->qwc > 0) // Normal Mode { - if (!_VIF0chain()) - { - Console.WriteLn(L"Stall on normal vif0 " + vif0Regs->stat.desc()); - - vif0.vifstalled = true; - return; - } - - vif0.done = true; - CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo); - return; + vif0.dmamode = VIF_NORMAL_TO_MEM_MODE; } + else + { + vif0.dmamode = VIF_CHAIN_MODE; + } + + if (vif0.dmamode != VIF_NORMAL_FROM_MEM_MODE) + vif0Regs->stat.FQC = 0x8; + else + vif0Regs->stat.FQC = min((u16)0x8, vif0ch->qwc); // Chain Mode vif0.done = false; - CPU_INT(DMAC_VIF0, 0); -} + vif0Interrupt(); +} \ No newline at end of file diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index 57ec483fec..b167be4573 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -262,6 +262,7 @@ __forceinline void vif1Interrupt() if (vif1.vifstalled && vif1.irq) { + DevCon.WriteLn("VIF1 looping on stall\n"); CPU_INT(DMAC_VIF1, 0); return; //Dont want to end if vif is stalled. } diff --git a/pcsx2/x86/newVif_Dynarec.cpp b/pcsx2/x86/newVif_Dynarec.cpp index 3d59bf36e0..7d790e8546 100644 --- a/pcsx2/x86/newVif_Dynarec.cpp +++ b/pcsx2/x86/newVif_Dynarec.cpp @@ -186,12 +186,16 @@ static _f u8* dVifsetVUptr(const nVifStruct& v, int cl, int wl, bool isFill) { if (!isFill) { // Account for skip-cycles int skipSize = cl - wl; int blocks = _vBlock.num / wl; - int skips = (blocks * skipSize + _vBlock.num) * 16; + int skips = (blocks * skipSize + _vBlock.num) * 16; + + //We must do skips - 1 here else skip calculation adds an extra skip which can overflow + //causing the emu to drop back to the interpreter (do not need to skip on last block write) - Refraction + if(skipSize > 0) skips -= skipSize * 16; endPtr = ptr + skips; } else endPtr = ptr + (_vBlock.num * 16); if ( endPtr > v.vuMemEnd ) { - DevCon.WriteLn("nVif - VU Mem Ptr Overflow; falling back to interpreter."); + DevCon.WriteLn("nVif%x - VU Mem Ptr Overflow; falling back to interpreter. Start = %x End = %x num = %x, wl = %x, cl = %x", v.idx, v.vif->tag.addr, v.vif->tag.addr + (_vBlock.num * 16), _vBlock.num, wl, cl); ptr = NULL; // Fall Back to Interpreters which have wrap-around logic } return ptr;