From d465c182289a37112ef6d7902ecb6b5b5d5df448 Mon Sep 17 00:00:00 2001 From: refraction Date: Thu, 16 Aug 2012 23:03:27 +0000 Subject: [PATCH] More vif work to fix Shadowman 2 and improve the function of some parts. Gave vifstalled a more specific job and reasons for the stall. Also did some work with the irq offset, seperating it from the stalls. Savestate bump needed. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5380 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/FiFo.cpp | 4 ++-- pcsx2/SaveState.h | 2 +- pcsx2/Vif.cpp | 20 +++++++++++++------- pcsx2/Vif.h | 6 ++++++ pcsx2/Vif0_Dma.cpp | 43 ++++++++++++++++++++++++++---------------- pcsx2/Vif1_Dma.cpp | 40 +++++++++++++++++++++------------------ pcsx2/Vif1_MFIFO.cpp | 35 +++++++++++++++++++--------------- pcsx2/Vif_Codes.cpp | 32 +++++++++++++++---------------- pcsx2/Vif_Dma.h | 9 +++++++-- pcsx2/Vif_Transfer.cpp | 35 ++++++++++++++++++++-------------- 10 files changed, 135 insertions(+), 91 deletions(-) diff --git a/pcsx2/FiFo.cpp b/pcsx2/FiFo.cpp index 6c4d65cd0b..a4d57b0032 100644 --- a/pcsx2/FiFo.cpp +++ b/pcsx2/FiFo.cpp @@ -71,7 +71,7 @@ void __fastcall WriteFIFO_VIF0(const mem128_t *value) VIF_LOG("WriteFIFO/VIF0 <- %ls", value->ToString().c_str()); vif0ch.qwc += 1; - if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 FIFO start!"); + if(vif0.irqoffset.value != 0 && vif0.vifstalled.enabled == true) DevCon.Warning("Offset on VIF0 FIFO start!"); bool ret = VIF0transfer((u32*)value, 4); if (vif0.cmd) @@ -96,7 +96,7 @@ void __fastcall WriteFIFO_VIF1(const mem128_t *value) if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) ) { DevCon.Warning("writing to vif1 fifo when stalled"); } - if (vif1.irqoffset != 0 && vif1.vifstalled == true) { + if (vif1.irqoffset.value != 0 && vif1.vifstalled.enabled == true) { DevCon.Warning("Offset on VIF1 FIFO start!"); } diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index 7a8a0f5db9..d8d1545d21 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -24,7 +24,7 @@ // the lower 16 bit value. IF the change is breaking of all compatibility with old // states, increment the upper 16 bit value, and clear the lower 16 bits to 0. -static const u32 g_SaveVersion = (0x9A08 << 16) | 0x0000; +static const u32 g_SaveVersion = (0x9A09 << 16) | 0x0000; // this function is meant to be used in the place of GSfreeze, and provides a safe layer // between the GS saving function and the MTGS's needs. :) diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index 83d435b08e..0c023a9b14 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -97,7 +97,8 @@ __fi void vif0FBRST(u32 value) { cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's psHu64(VIF0_FIFO) = 0; psHu64(VIF0_FIFO + 8) = 0; - vif0.vifstalled = false; + vif0.vifstalled.enabled = false; + vif1.irqoffset.enabled = false; vif0.inprogress = 0; vif0.cmd = 0; vif0.done = true; @@ -123,7 +124,8 @@ __fi void vif0FBRST(u32 value) { // just stoppin the VIF (linuz). vif0Regs.stat.VSS = true; vif0Regs.stat.VPS = VPS_IDLE; - vif0.vifstalled = true; + vif0.vifstalled.enabled = true; + vif0.vifstalled.value = VIF_IRQ_STALL; } if (value & 0x8) // Cancel Vif Stall. @@ -138,8 +140,8 @@ __fi void vif0FBRST(u32 value) { VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1); if (cancel) { - if (vif0.vifstalled) - { + if (vif0.vifstalled.enabled && vif0.vifstalled.value == VIF_IRQ_STALL) + { g_vif0Cycles = 0; // loop necessary for spiderman @@ -192,7 +194,8 @@ __fi void vif1FBRST(u32 value) { vif1Regs.err.reset(); vif1.inprogress = 0; vif1.cmd = 0; - vif1.vifstalled = false; + vif1.vifstalled.enabled = false; + vif1.irqoffset.enabled = false; vif1Regs.stat.FQC = 0; vif1Regs.stat.clear_flags(VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS); } @@ -206,6 +209,8 @@ __fi void vif1FBRST(u32 value) { vif1Regs.stat.VFS = true; vif1Regs.stat.VPS = VPS_IDLE; cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's + vif1.vifstalled.enabled = true; + vif1.vifstalled.value = VIF_IRQ_STALL; Console.WriteLn("vif1 force break"); } @@ -216,7 +221,8 @@ __fi void vif1FBRST(u32 value) { vif1Regs.stat.VSS = true; vif1Regs.stat.VPS = VPS_IDLE; cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's - vif1.vifstalled = true; + vif1.vifstalled.enabled = true; + vif1.vifstalled.value = VIF_IRQ_STALL; } if (FBRST(value).STC) // Cancel Vif Stall. @@ -234,7 +240,7 @@ __fi void vif1FBRST(u32 value) { if (cancel) { - if (vif1.vifstalled) + if (vif1.vifstalled.enabled && vif1.vifstalled.value == VIF_IRQ_STALL) { g_vif1Cycles = 0; // loop necessary for spiderman diff --git a/pcsx2/Vif.h b/pcsx2/Vif.h index 4488efd8cd..235e232482 100644 --- a/pcsx2/Vif.h +++ b/pcsx2/Vif.h @@ -83,6 +83,12 @@ enum vif_status VPS_TRANSFERRING = 3 // And decompressing. }; +enum vif_stallreasons +{ + VIF_TIMING_BREAK = 1, + VIF_IRQ_STALL = 2 +}; + // // Bitfield Structure // diff --git a/pcsx2/Vif0_Dma.cpp b/pcsx2/Vif0_Dma.cpp index 85b720115d..559bb6727b 100644 --- a/pcsx2/Vif0_Dma.cpp +++ b/pcsx2/Vif0_Dma.cpp @@ -28,7 +28,8 @@ __fi void vif0FLUSH() if(vif0Regs.stat.VEW == true) { vif0.waitforvu = true; - vif0.vifstalled = true; + vif0.vifstalled.enabled = true; + vif0.vifstalled.value = VIF_TIMING_BREAK; } return; } @@ -55,8 +56,8 @@ bool _VIF0chain() 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); + if (vif0.irqoffset.enabled) + return VIF0transfer(pMem + vif0.irqoffset.value, vif0ch.qwc * 4 - vif0.irqoffset.value); else return VIF0transfer(pMem, vif0ch.qwc * 4); } @@ -101,21 +102,22 @@ __fi void vif0SetupTransfer() VIF_LOG("\tVIF0 SrcChain TTE=1, data = 0x%08x.%08x", masked_tag._u32[3], masked_tag._u32[2]); - if (vif0.vifstalled) + if (vif0.irqoffset.enabled) { - ret = VIF0transfer((u32*)&masked_tag + vif0.irqoffset, 4 - vif0.irqoffset, true); //Transfer Tag on stall + 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 = 2; + 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) + 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 @@ -123,7 +125,8 @@ __fi void vif0SetupTransfer() } } - vif0.irqoffset = 0; + vif0.irqoffset.value = 0; + vif0.irqoffset.enabled = false; vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID); if(vif0ch.qwc > 0) vif0.inprogress = 1; @@ -153,12 +156,13 @@ __fi void vif0VUFinish() return; } vif0Regs.stat.VEW = false; + VIF_LOG("VU0 finished"); if(vif0.waitforvu == true) { vif0.waitforvu = false; ExecuteVU(0); //Make sure VIF0 isnt already scheduled to spin. - if(!(cpuRegs.interrupt & 0x1)) + if(!(cpuRegs.interrupt & 0x1) && vif0ch.chcr.STR == true) vif0Interrupt(); } //DevCon.Warning("VU0 state cleared"); @@ -200,6 +204,9 @@ __fi void vif0Interrupt() //CPU_INT(DMAC_VIF0, 16); return; } + + vif0.vifstalled.enabled = false; + //Must go after the Stall, incase it's still in progress, GTC africa likes to see it still transferring. if (vif0.cmd) { @@ -233,9 +240,9 @@ __fi void vif0Interrupt() return; } - if (vif0.vifstalled && vif0.irq) + if (vif0.vifstalled.enabled && vif0.done) { - DevCon.WriteLn("VIF0 looping on stall\n"); + DevCon.WriteLn("VIF0 looping on stall at end\n"); CPU_INT(DMAC_VIF0, 0); return; //Dont want to end if vif is stalled. } @@ -246,6 +253,8 @@ __fi void vif0Interrupt() vif0ch.chcr.STR = false; vif0Regs.stat.FQC = min((u16)0x8, vif0ch.qwc); + vif0.vifstalled.enabled = false; + vif0.irqoffset.enabled = false; g_vif0Cycles = 0; hwDmacIrq(DMAC_VIF0); vif0Regs.stat.FQC = 0; @@ -260,16 +269,18 @@ void dmaVIF0() vif0ch.tadr, vif0ch.asr0, vif0ch.asr1); g_vif0Cycles = 0; - //if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 start! offset %x, Progress %x", vif0.irqoffset, vif0.vifstalled); - /*vif0.irqoffset = 0; - vif0.vifstalled = false; - vif0.inprogress = 0; - vif0.done = false;*/ + if ((vif0ch.chcr.MOD == NORMAL_MODE) || vif0ch.qwc > 0) // Normal Mode { vif0.dmamode = VIF_NORMAL_TO_MEM_MODE; + if(vif0.irqoffset.enabled == true && vif0.done == false) + { + 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 = false; if(vif0ch.chcr.MOD == CHAIN_MODE && vif0ch.qwc > 0) diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index ca479d8b41..db147b35be 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -28,7 +28,8 @@ __fi void vif1FLUSH() if(vif1Regs.stat.VEW == true) { vif1.waitforvu = true; - vif1.vifstalled = true; + vif1.vifstalled.enabled = true; + vif1.vifstalled.value = VIF_TIMING_BREAK; } } @@ -100,7 +101,8 @@ bool _VIF1chain() if (vif1ch.qwc == 0) { vif1.inprogress &= ~1; - vif1.irqoffset = 0; + vif1.irqoffset.value = 0; + vif1.irqoffset.enabled = false; return true; } @@ -124,8 +126,8 @@ bool _VIF1chain() VIF_LOG("VIF1chain size=%d, madr=%lx, tadr=%lx", vif1ch.qwc, vif1ch.madr, vif1ch.tadr); - if (vif1.vifstalled) - return VIF1transfer(pMem + vif1.irqoffset, vif1ch.qwc * 4 - vif1.irqoffset, false); + if (vif1.irqoffset.enabled) + return VIF1transfer(pMem + vif1.irqoffset.value, vif1ch.qwc * 4 - vif1.irqoffset.value, false); else return VIF1transfer(pMem, vif1ch.qwc * 4, false); } @@ -174,27 +176,29 @@ __fi void vif1SetupTransfer() VIF_LOG("\tVIF1 SrcChain TTE=1, data = 0x%08x.%08x", masked_tag._u32[3], masked_tag._u32[2]); - if (vif1.vifstalled) + if (vif1.irqoffset.enabled) { - ret = VIF1transfer((u32*)&masked_tag + vif1.irqoffset, 4 - vif1.irqoffset, true); //Transfer Tag on stall + 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 = 2; + 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) + 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 = 0; + vif1.irqoffset.value = 0; + vif1.irqoffset.enabled = false; vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID); @@ -225,6 +229,7 @@ __fi void vif1VUFinish() } vif1Regs.stat.VEW = false; + VIF_LOG("VU1 finished"); if(vif1.waitforvu == true) { vif1.waitforvu = false; @@ -303,6 +308,8 @@ __fi void vif1Interrupt() } } + vif1.vifstalled.enabled = false; + //Mirroring change to VIF0 if (vif1.cmd) { @@ -342,9 +349,9 @@ __fi void vif1Interrupt() return; } - if (vif1.vifstalled && vif1.irq) + if (vif1.vifstalled.enabled && vif1.done) { - DevCon.WriteLn("VIF1 looping on stall\n"); + DevCon.WriteLn("VIF1 looping on stall at end\n"); CPU_INT(DMAC_VIF1, 0); return; //Dont want to end if vif is stalled. } @@ -362,7 +369,8 @@ __fi void vif1Interrupt() if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16); vif1ch.chcr.STR = false; - vif1.vifstalled = false; + vif1.vifstalled.enabled = false; + vif1.irqoffset.enabled = false; g_vif1Cycles = 0; DMA_LOG("VIF1 DMA End"); hwDmacIrq(DMAC_VIF1); @@ -376,12 +384,6 @@ void dmaVIF1() vif1ch.chcr._u32, vif1ch.madr, vif1ch.qwc, vif1ch.tadr, vif1ch.asr0, vif1ch.asr1); -// vif1.done = false; - - //if(vif1.irqoffset != 0 && vif1.vifstalled == true) DevCon.Warning("Offset on VIF1 start! offset %x, Progress %x", vif1.irqoffset, vif1.vifstalled); - /*vif1.irqoffset = 0; - vif1.vifstalled = false; - vif1.inprogress = 0;*/ g_vif1Cycles = 0; #ifdef PCSX2_DEVBUILD @@ -419,6 +421,7 @@ void dmaVIF1() else vif1.dmamode = VIF_NORMAL_TO_MEM_MODE; + if(vif1.irqoffset.enabled == true && vif1.done == false) DevCon.Warning("Warning! VIF1 starting a Normal transfer with vif offset set (Possible force stop?)"); vif1.done = true; } @@ -426,6 +429,7 @@ void dmaVIF1() } else { + if(vif1.irqoffset.enabled == true && vif1.done == false) DevCon.Warning("Warning! VIF1 starting a new Chain transfer with vif offset set (Possible force stop?)"); vif1.dmamode = VIF_CHAIN_MODE; vif1.done = false; vif1.inprogress &= ~0x1; diff --git a/pcsx2/Vif1_MFIFO.cpp b/pcsx2/Vif1_MFIFO.cpp index b3dfbb6d01..5daa3ffaca 100644 --- a/pcsx2/Vif1_MFIFO.cpp +++ b/pcsx2/Vif1_MFIFO.cpp @@ -72,14 +72,14 @@ static __fi bool mfifoVIF1rbTransfer() src = (u32*)PSM(vif1ch.madr); if (src == NULL) return false; - if (vif1.vifstalled) - ret = VIF1transfer(src + vif1.irqoffset, s1 - vif1.irqoffset); + if (vif1.irqoffset.enabled) + ret = VIF1transfer(src + vif1.irqoffset.value, s1 - vif1.irqoffset.value); else ret = VIF1transfer(src, s1); if (ret) { - if(vif1.irqoffset != 0) DevCon.Warning("VIF1 MFIFO Offest != 0! vifoffset=%x", vif1.irqoffset); + if(vif1.irqoffset.value != 0) DevCon.Warning("VIF1 MFIFO Offest != 0! vifoffset=%x", vif1.irqoffset.value); /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ vif1ch.madr = maddr; @@ -97,8 +97,8 @@ static __fi bool mfifoVIF1rbTransfer() src = (u32*)PSM(vif1ch.madr); if (src == NULL) return false; - if (vif1.vifstalled) - ret = VIF1transfer(src + vif1.irqoffset, mfifoqwc * 4 - vif1.irqoffset); + if (vif1.irqoffset.enabled) + ret = VIF1transfer(src + vif1.irqoffset.value, mfifoqwc * 4 - vif1.irqoffset.value); else ret = VIF1transfer(src, mfifoqwc << 2); @@ -138,8 +138,8 @@ static __fi void mfifo_VIF1chain() if (pMem == NULL) return; - if (vif1.vifstalled) - VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch.qwc * 4 - vif1.irqoffset); + if (vif1.irqoffset.enabled) + VIF1transfer((u32*)pMem + vif1.irqoffset.value, vif1ch.qwc * 4 - vif1.irqoffset.value); else VIF1transfer((u32*)pMem, vif1ch.qwc << 2); } @@ -154,7 +154,7 @@ void mfifoVIF1transfer(int qwc) if (qwc > 0) { //vifqwc += qwc; - SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vif1ch.chcr._u32, vif1.vifstalled, vif1.done); + SPR_LOG("Added %x qw to mfifo,Vif CHCR %x Stalled %x done %x", qwc, vif1ch.chcr._u32, vif1.vifstalled.enabled, vif1.done); if (vif1.inprogress & 0x10) { if(vif1ch.chcr.STR == true && !(cpuRegs.interrupt & (1< (idx ? 0x3ffu : 0xffu)) { Console.WriteLn("VIF%d ITOP overrun! %x", idx, vifRegs.itops); @@ -76,12 +76,14 @@ static __fi void vuExecMicro(int idx, u32 addr) { if (!idx) vu0ExecMicro(addr); else vu1ExecMicro(addr); + ///NOTE: Shadowman 2 has SPS with this, uncommenting the correct code fixes it if (!idx) { startcycles = ((VU0.cycle-startcycles) + ( vif0ch.qwc - (vif0.vifpacketsize >> 2) )); CPU_INT(VIF_VU0_FINISH, 1/*startcycles * BIAS*/); } else { startcycles = ((VU1.cycle-startcycles) + ( vif1ch.qwc - (vif1.vifpacketsize >> 2) )); CPU_INT(VIF_VU1_FINISH, 1/*startcycles * BIAS*/); } //DevCon.Warning("Ran VU%x, VU0 Cycles %x, VU1 Cycles %x, start %x cycle %x", idx, g_vu0Cycles, g_vu1Cycles, startcycles, VU1.cycle); - GetVifX.vifstalled = true; + GetVifX.vifstalled.enabled = true; + GetVifX.vifstalled.value = VIF_TIMING_BREAK; } void ExecuteVU(int idx) @@ -135,7 +137,8 @@ template __fi int _vifCode_Direct(int pass, const u8* data, bool isDire if (size != ret) { // Stall if gif didn't process all the data (path2 queued) GUNIT_WARN("Vif %s: Stall! [size=%d][ret=%d]", name, size, ret); //gifUnit.PrintInfo(); - vif1.vifstalled = true; + vif1.vifstalled.enabled = true; + vif1.vifstalled.value = VIF_TIMING_BREAK; vif1Regs.stat.VGW = true; return 0; } @@ -168,7 +171,8 @@ vifOp(vifCode_Flush) { GUNIT_WARN("Vif Flush: Stall!"); //gifUnit.PrintInfo(); vif1Regs.stat.VGW = true; - vifX.vifstalled = true; + vifX.vifstalled.enabled = true; + vifX.vifstalled.value = VIF_TIMING_BREAK; return 0; } else vifX.cmd = 0; @@ -197,14 +201,7 @@ vifOp(vifCode_FlushA) { //p3.state= GIF_PATH_IDLE; // Does any game need this anymore? DevCon.Warning("Vif FlushA - path3 has no more data, but didn't EOP"); } - /*else { // Path 3 hasn't finished its current gs packet - if (gifUnit.stat.APATH != 3 && gifUnit.Path3Masked()) { - gifUnit.stat.APATH = 3; // Hack: Force path 3 to finish (persona 3 needs this) - //DevCon.Warning("Vif FlushA - Forcing path3 to finish current packet"); - } - gifInterrupt(); // Feed path3 some gif dma data - gifUnit.Execute(); // Execute path3 in-case gifInterrupt() didn't... - }*/ + if (p3.state != GIF_PATH_IDLE) { doStall = true; // If path3 still isn't finished... } @@ -213,7 +210,8 @@ vifOp(vifCode_FlushA) { } if (doStall) { vif1Regs.stat.VGW = true; - vifX.vifstalled = true; + vifX.vifstalled.enabled = true; + vifX.vifstalled.value = VIF_TIMING_BREAK; return 0; } else vifX.cmd = 0; @@ -274,7 +272,7 @@ vifOp(vifCode_MPG) { vifX.tag.addr = (u16)(vifXRegs.code << 3) & (idx ? 0x3fff : 0xfff); vifX.tag.size = vifNum ? (vifNum*2) : 512; vifFlush(idx); - if(vifX.vifstalled == true) return 0; + if(vifX.vifstalled.enabled == true) return 0; else { vifX.pass = 1; @@ -331,7 +329,8 @@ vifOp(vifCode_MSCALF) { if (u32 a = gifUnit.checkPaths(1,1,0)) { GUNIT_WARN("Vif MSCALF: Stall! [%d,%d]", !!(a&1), !!(a&2)); vif1Regs.stat.VGW = true; - vifX.vifstalled = true; + vifX.vifstalled.enabled = true; + vifX.vifstalled.value = VIF_TIMING_BREAK; } if(vifX.waitforvu == false) { @@ -396,7 +395,8 @@ vifOp(vifCode_Null) { if (!(vifXRegs.err.ME1)) { // Ignore vifcode and tag mismatch error Console.WriteLn("Vif%d: Unknown VifCmd! [%x]", idx, vifX.cmd); vifXRegs.stat.ER1 = true; - vifX.vifstalled = true; + vifX.vifstalled.enabled = true; + vifX.vifstalled.value = VIF_IRQ_STALL; //vifX.irq++; } vifX.cmd = 0; diff --git a/pcsx2/Vif_Dma.h b/pcsx2/Vif_Dma.h index 1adf48b298..18b314c896 100644 --- a/pcsx2/Vif_Dma.h +++ b/pcsx2/Vif_Dma.h @@ -54,6 +54,11 @@ union tTRXREG { }; }; +struct tVIF_CTRL { + bool enabled; + u32 value; +}; + // NOTE, if debugging vif stalls, use sega classics, spyro, gt4, and taito struct vifStruct { __aligned16 u128 MaskRow; @@ -71,7 +76,7 @@ struct vifStruct { int irq; bool done; - bool vifstalled; + tVIF_CTRL vifstalled; bool stallontag; bool waitforvu; @@ -81,7 +86,7 @@ struct vifStruct { tTRXREG TRXREG; u32 GSLastDownloadSize; - u8 irqoffset; // 32bit offset where next vif code is + tVIF_CTRL irqoffset; // 32bit offset where next vif code is u32 vifpacketsize; u8 inprogress; u8 dmamode; diff --git a/pcsx2/Vif_Transfer.cpp b/pcsx2/Vif_Transfer.cpp index 59bcbc7732..a5ed03ce47 100644 --- a/pcsx2/Vif_Transfer.cpp +++ b/pcsx2/Vif_Transfer.cpp @@ -32,8 +32,8 @@ _vifT void vifTransferLoop(u32* &data) { vifXRegs.stat.VPS |= VPS_TRANSFERRING; vifXRegs.stat.ER1 = false; - - while (pSize > 0 && !vifX.vifstalled) { + if(!idx)VIF_LOG("Starting VIF0 loop, pSize = %x, stalled = %x", pSize, vifX.vifstalled.enabled ); + while (pSize > 0 && !vifX.vifstalled.enabled) { if(!vifX.cmd) { // Get new VifCode @@ -66,11 +66,8 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) { vifStruct& vifX = GetVifX; // irqoffset necessary to add up the right qws, or else will spin (spiderman) - int transferred = vifX.irqoffset; - - vifX.irqoffset = 0; - vifX.vifstalled = false; - vifX.stallontag = false; + int transferred = vifX.irqoffset.enabled ? vifX.irqoffset.value : 0; + vifX.vifpacketsize = size; vifTransferLoop(data); @@ -81,15 +78,16 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) { if (!idx) g_vif0Cycles += max(1, (int)((transferred * BIAS) >> 2)); else g_vif1Cycles += max(1, (int)((transferred * BIAS) >> 2)); - vifX.irqoffset = transferred % 4; // cannot lose the offset - + vifX.irqoffset.value = transferred % 4; // cannot lose the offset + if (vifX.irq && vifX.cmd == 0) { //DevCon.WriteLn("Vif IRQ!"); if(((vifXRegs.code >> 24) & 0x7f) != 0x7) { vifXRegs.stat.VIS = true; // Note: commenting this out fixes WALL-E? } //Always needs to be set to return to the correct offset if there is data left. - vifX.vifstalled = true; + vifX.vifstalled.enabled = true; + vifX.vifstalled.value = VIF_IRQ_STALL; } if (!TTE) // *WARNING* - Tags CAN have interrupts! so lets just ignore the dma modifying stuffs (GT4) @@ -100,13 +98,22 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) { if (vifXch.chcr.STR) hwDmacSrcTadrInc(vifXch); - if(!vifXch.qwc) { + if(!vifXch.qwc) vifX.inprogress &= ~0x1; - vifX.vifstalled = false; - } + else if(vifX.irqoffset.value != 0) + vifX.irqoffset.enabled = true; + else + vifX.irqoffset.enabled = false; + } + else + { + if(vifX.irqoffset.value > 1) + vifX.irqoffset.enabled = true; + else + vifX.irqoffset.enabled = false; } - return !vifX.vifstalled; + return !vifX.vifstalled.enabled; } // When TTE is set to 1, MADR and QWC are not updated as part of the transfer.