diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp
index 01475d2ee7..d79bb5966f 100644
--- a/pcsx2/Gif.cpp
+++ b/pcsx2/Gif.cpp
@@ -18,7 +18,7 @@
#include "GS.h"
#include "Gif.h"
-#include "VifDma.h"
+#include "Vif_Dma.h"
#include "iR5900.h"
diff --git a/pcsx2/Hardware.h b/pcsx2/Hardware.h
index e4edff6056..4cbe475839 100644
--- a/pcsx2/Hardware.h
+++ b/pcsx2/Hardware.h
@@ -25,6 +25,6 @@
#include "Gif.h"
#include "Sif.h"
#include "Vif.h"
-#include "VifDma.h"
+#include "Vif_Dma.h"
#endif
diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp
index df428f4d0d..49c48aefda 100644
--- a/pcsx2/Vif.cpp
+++ b/pcsx2/Vif.cpp
@@ -13,296 +13,72 @@
* If not, see .
*/
-
#include "PrecompiledHeader.h"
#include "Common.h"
-
-#include
-
#include "Vif.h"
-#include "VifDma.h"
+#include "Vif_Dma.h"
-VIFregisters *vifRegs;
-vifStruct *vif;
-u16 vifqwc = 0;
+void vif0Init() { initNewVif(0); }
+void vif1Init() { initNewVif(1); }
-__aligned16 VifMaskTypes g_vifmask;
-
-extern int g_vifCycles;
-
-static __forceinline bool mfifoVIF1rbTransfer()
+void vif0Reset()
{
- u32 maddr = dmacRegs->rbor.ADDR;
- u32 msize = dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16;
- u16 mfifoqwc = std::min(vif1ch->qwc, vifqwc);
- u32 *src;
- bool ret;
+ /* Reset the whole VIF, meaning the internal pcsx2 vars and all the registers */
+ memzero(vif0);
+ memzero(*vif0Regs);
- /* Check if the transfer should wrap around the ring buffer */
- if ((vif1ch->madr + (mfifoqwc << 4)) > (msize))
- {
- int s1 = ((msize) - vif1ch->madr) >> 2;
+ psHu64(VIF0_FIFO) = 0;
+ psHu64(VIF0_FIFO + 8) = 0;
+
+ vif0Regs->stat.VPS = VPS_IDLE;
+ vif0Regs->stat.FQC = 0;
- SPR_LOG("Split MFIFO");
+ vif0.done = true;
- /* it does, so first copy 's1' bytes from 'addr' to 'data' */
- src = (u32*)PSM(vif1ch->madr);
- if (src == NULL) return false;
-
- if (vif1.vifstalled)
- ret = VIF1transfer(src + vif1.irqoffset, s1 - vif1.irqoffset, false);
- else
- ret = VIF1transfer(src, s1, false);
-
- if (ret)
- {
- /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
- vif1ch->madr = maddr;
-
- src = (u32*)PSM(maddr);
- if (src == NULL) return false;
- VIF1transfer(src, ((mfifoqwc << 2) - s1), false);
- }
- }
- else
- {
- SPR_LOG("Direct MFIFO");
-
- /* it doesn't, so just transfer 'qwc*4' words */
- src = (u32*)PSM(vif1ch->madr);
- if (src == NULL) return false;
-
- if (vif1.vifstalled)
- ret = VIF1transfer(src + vif1.irqoffset, mfifoqwc * 4 - vif1.irqoffset, false);
- else
- ret = VIF1transfer(src, mfifoqwc << 2, false);
- }
- return ret;
+ resetNewVif(0);
}
-static __forceinline bool mfifo_VIF1chain()
+void vif1Reset()
{
- bool ret;
-
- /* Is QWC = 0? if so there is nothing to transfer */
- if ((vif1ch->qwc == 0) && (!vif1.vifstalled))
- {
- vif1.inprogress &= ~1;
- return true;
- }
+ /* Reset the whole VIF, meaning the internal pcsx2 vars, and all the registers */
+ memzero(vif1);
+ memzero(*vif1Regs);
- if (vif1ch->madr >= dmacRegs->rbor.ADDR &&
- vif1ch->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK))
- {
- u16 startqwc = vif1ch->qwc;
- ret = mfifoVIF1rbTransfer();
- vifqwc -= startqwc - vif1ch->qwc;
- }
- else
- {
- tDMA_TAG *pMem = dmaGetAddr(vif1ch->madr);
- SPR_LOG("Non-MFIFO Location");
+ psHu64(VIF1_FIFO) = 0;
+ psHu64(VIF1_FIFO + 8) = 0;
- if (pMem == NULL) return false;
+ vif1Regs->stat.VPS = VPS_IDLE;
+ vif1Regs->stat.FQC = 0; // FQC=0
- if (vif1.vifstalled)
- ret = VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset, false);
- else
- ret = VIF1transfer((u32*)pMem, vif1ch->qwc << 2, false);
- }
- return ret;
+ vif1.done = true;
+ cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
+
+ resetNewVif(1);
}
-static u32 qwctag(u32 mask)
+void SaveStateBase::vif0Freeze()
{
- return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK));
+ static u32 g_vif0Masks[64]; // Dummy Var for saved state compatibility
+ static u32 g_vif0HasMask3[4]; // Dummy Var for saved state compatibility
+ FreezeTag("VIFdma");
+
+ // Dunno if this one is needed, but whatever, it's small. :)
+ Freeze(g_vifCycles);
+
+ // mask settings for VIF0 and VIF1
+ Freeze(g_vifmask);
+
+ Freeze(vif0);
+ Freeze(g_vif0HasMask3); // Not Used Anymore
+ Freeze(g_vif0Masks); // Not Used Anymore
}
-void mfifoVIF1transfer(int qwc)
+void SaveStateBase::vif1Freeze()
{
- tDMA_TAG *ptag;
+ static u32 g_vif1Masks[64]; // Dummy Var for saved state compatibility
+ static u32 g_vif1HasMask3[4]; // Dummy Var for saved state compatibility
+ Freeze(vif1);
- g_vifCycles = 0;
-
- if (qwc > 0)
- {
- vifqwc += qwc;
- SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch->chcr._u32, vif1.vifstalled, vif1.done);
- if (vif1.inprogress & 0x10)
- {
- if (vif1ch->madr >= dmacRegs->rbor.ADDR && vif1ch->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK))
- CPU_INT(10, 0);
- else
- CPU_INT(10, vif1ch->qwc * BIAS);
-
- vif1Regs->stat.FQC = 0x10; // FQC=16
- }
- vif1.inprogress &= ~0x10;
-
- return;
- }
-
- if (vif1ch->qwc == 0 && vifqwc > 0)
- {
- ptag = dmaGetAddr(vif1ch->tadr);
-
- if (vif1ch->chcr.TTE)
- {
- bool ret;
-
- if (vif1.stallontag)
- ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, true); //Transfer Tag on Stall
- else
- ret = VIF1transfer((u32*)ptag + 2, 2, true); //Transfer Tag
-
- if (!(ret))
- {
- VIF_LOG("MFIFO Stall on tag");
- vif1.stallontag = true;
- return; //IRQ set by VIFTransfer
- }
- }
-
- vif1ch->unsafeTransfer(ptag);
-
- vif1ch->madr = ptag[1]._u32;
- vifqwc--;
-
- SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
- ptag[1]._u32, ptag[0]._u32, vif1ch->qwc, ptag->ID, vif1ch->madr, vif1ch->tadr, vifqwc, spr0->madr);
-
- switch (ptag->ID)
- {
- case TAG_REFE: // Refe - Transfer Packet According to ADDR field
- vif1ch->tadr = qwctag(vif1ch->tadr + 16);
- vif1.done = true; //End Transfer
- break;
-
- case TAG_CNT: // CNT - Transfer QWC following the tag.
- vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to QW after Tag
- vif1ch->tadr = qwctag(vif1ch->madr + (vif1ch->qwc << 4)); //Set TADR to QW following the data
- vif1.done = false;
- break;
-
- case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
- {
- int temp = vif1ch->madr; //Temporarily Store ADDR
- vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to QW following the tag
- vif1ch->tadr = temp; //Copy temporarily stored ADDR to Tag
- if ((temp & dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("Next tag = %x outside ring %x size %x", temp, psHu32(DMAC_RBOR), psHu32(DMAC_RBSR));
- vif1.done = false;
- break;
- }
-
- case TAG_REF: // Ref - Transfer QWC from ADDR field
- case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
- vif1ch->tadr = qwctag(vif1ch->tadr + 16); //Set TADR to next tag
- vif1.done = false;
- break;
-
- case TAG_END: // End - Transfer QWC following the tag
- vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to data following the tag
- vif1ch->tadr = qwctag(vif1ch->madr + (vif1ch->qwc << 4)); //Set TADR to QW following the data
- vif1.done = true; //End Transfer
- break;
- }
-
- if (vif1ch->chcr.TIE && ptag->IRQ)
- {
- VIF_LOG("dmaIrq Set");
- vif1.done = true;
- }
- }
-
- vif1.inprogress |= 1;
-
- SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr, vifqwc);
-}
-
-void vifMFIFOInterrupt()
-{
- g_vifCycles = 0;
-
- if (schedulepath3msk) Vif1MskPath3();
-
- if ((vif1Regs->stat.VGW))
- {
- if (gif->chcr.STR)
- {
- CPU_INT(10, 16);
- return;
- }
- else
- {
- vif1Regs->stat.VGW = false;
- }
-
- }
-
- if ((spr0->chcr.STR) && (spr0->qwc == 0))
- {
- spr0->chcr.STR = false;
- hwDmacIrq(DMAC_FROM_SPR);
- }
-
- if (vif1.irq && vif1.tag.size == 0)
- {
- vif1Regs->stat.INT = true;
- hwIntcIrq(INTC_VIF1);
- --vif1.irq;
-
- if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
- {
- vif1Regs->stat.FQC = 0; // FQC=0
- vif1ch->chcr.STR = false;
- return;
- }
- }
-
- if (vif1.done == false || vif1ch->qwc)
- {
- switch(vif1.inprogress & 1)
- {
- case 0: //Set up transfer
- if (vif1ch->tadr == spr0->madr)
- {
- // Console.WriteLn("Empty 1");
- vifqwc = 0;
- vif1.inprogress |= 0x10;
- vif1Regs->stat.FQC = 0;
- hwDmacIrq(DMAC_MFIFO_EMPTY);
- return;
- }
-
- mfifoVIF1transfer(0);
- if ((vif1ch->madr >= dmacRegs->rbor.ADDR) && (vif1ch->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK)))
- CPU_INT(10, 0);
- else
- CPU_INT(10, vif1ch->qwc * BIAS);
-
- return;
-
- case 1: //Transfer data
- mfifo_VIF1chain();
- CPU_INT(10, 0);
- return;
- }
- return;
- }
-
- /*if (vifqwc <= 0)
- {
- //Console.WriteLn("Empty 2");
- //vif1.inprogress |= 0x10;
- vif1Regs->stat.FQC = 0; // FQC=0
- hwDmacIrq(DMAC_MFIFO_EMPTY);
- }*/
-
- vif1.done = 1;
- g_vifCycles = 0;
- vif1ch->chcr.STR = false;
- hwDmacIrq(DMAC_VIF1);
- VIF_LOG("vif mfifo dma end");
-
- vif1Regs->stat.FQC = 0;
+ Freeze(g_vif1HasMask3); // Not Used Anymore
+ Freeze(g_vif1Masks); // Not Used Anymore
}
diff --git a/pcsx2/Vif.h b/pcsx2/Vif.h
index 26e7df1c96..ac0203705c 100644
--- a/pcsx2/Vif.h
+++ b/pcsx2/Vif.h
@@ -13,8 +13,7 @@
* If not, see .
*/
-#ifndef __VIF_H__
-#define __VIF_H__
+#pragma once
enum vif0_stat_flags
{
@@ -225,16 +224,3 @@ extern bool VIF0transfer(u32 *data, int size, bool istag);
extern bool VIF1transfer(u32 *data, int size, bool istag);
extern void vifMFIFOInterrupt();
-// --------------------------------------------------------------------------------------
-// newVif SSE-optimized Row/Col Structs
-// --------------------------------------------------------------------------------------
-
-struct VifMaskTypes
-{
- u32 Row0[4], Col0[4];
- u32 Row1[4], Col1[4];
-};
-
-extern __aligned16 VifMaskTypes g_vifmask; // This struct is used by newVif
-
-#endif /* __VIF_H__ */
diff --git a/pcsx2/Vif0_Commands.cpp b/pcsx2/Vif0_Commands.cpp
new file mode 100644
index 0000000000..e5d852609a
--- /dev/null
+++ b/pcsx2/Vif0_Commands.cpp
@@ -0,0 +1,275 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+#include "Common.h"
+#include "Vif_Dma.h"
+#include "VUmicro.h"
+
+//------------------------------------------------------------------
+// Vif0 Data Transfer Commands
+//------------------------------------------------------------------
+
+static int __fastcall Vif0TransNull(u32 *data) // Shouldnt go here
+{
+ Console.WriteLn("VIF0 Shouldn't go here CMD = %x", vif0Regs->code);
+ vif0.cmd = 0;
+ return 0;
+}
+
+static int __fastcall Vif0TransSTMask(u32 *data) // STMASK
+{
+ vif0Regs->mask = data[0];
+ VIF_LOG("STMASK == %x", vif0Regs->mask);
+
+ vif0.tag.size = 0;
+ vif0.cmd = 0;
+ return 1;
+}
+
+static int __fastcall Vif0TransSTRow(u32 *data) // STROW
+{
+ int ret;
+
+ u32* pmem = &vif0Regs->r0 + (vif0.tag.addr << 2);
+ u32* pmem2 = g_vifmask.Row0 + vif0.tag.addr;
+ pxAssume(vif0.tag.addr < 4);
+ ret = min(4 - vif0.tag.addr, vif0.vifpacketsize);
+ pxAssume(ret > 0);
+
+ switch (ret)
+ {
+ case 4:
+ pmem[12] = data[3];
+ pmem2[3] = data[3];
+ case 3:
+ pmem[8] = data[2];
+ pmem2[2] = data[2];
+ case 2:
+ pmem[4] = data[1];
+ pmem2[1] = data[1];
+ case 1:
+ pmem[0] = data[0];
+ pmem2[0] = data[0];
+ break;
+
+ jNO_DEFAULT
+ }
+
+ vif0.tag.addr += ret;
+ vif0.tag.size -= ret;
+ if (vif0.tag.size == 0) vif0.cmd = 0;
+
+ return ret;
+}
+
+static int __fastcall Vif0TransSTCol(u32 *data) // STCOL
+{
+ int ret;
+
+ u32* pmem = &vif0Regs->c0 + (vif0.tag.addr << 2);
+ u32* pmem2 = g_vifmask.Col0 + vif0.tag.addr;
+ ret = min(4 - vif0.tag.addr, vif0.vifpacketsize);
+
+ switch (ret)
+ {
+ case 4:
+ pmem[12] = data[3];
+ pmem2[3] = data[3];
+ case 3:
+ pmem[8] = data[2];
+ pmem2[2] = data[2];
+ case 2:
+ pmem[4] = data[1];
+ pmem2[1] = data[1];
+ case 1:
+ pmem[0] = data[0];
+ pmem2[0] = data[0];
+ break;
+
+ jNO_DEFAULT
+ }
+
+ vif0.tag.addr += ret;
+ vif0.tag.size -= ret;
+ if (vif0.tag.size == 0) vif0.cmd = 0;
+ return ret;
+}
+
+static __forceinline void vif0mpgTransfer(u32 addr, u32 *data, int size)
+{
+ if (memcmp(VU0.Micro + addr, data, size << 2))
+ {
+ CpuVU0->Clear(addr, size << 2); // Clear before writing! :/ (cottonvibes)
+ memcpy_fast(VU0.Micro + addr, data, size << 2);
+ }
+}
+
+static int __fastcall Vif0TransMPG(u32 *data) // MPG
+{
+ if (vif0.vifpacketsize < vif0.tag.size)
+ {
+ if((vif0.tag.addr + vif0.vifpacketsize) > 0x1000) DevCon.Warning("Vif0 MPG Split Overflow");
+
+ vif0mpgTransfer(vif0.tag.addr, data, vif0.vifpacketsize);
+ vif0.tag.addr += vif0.vifpacketsize << 2;
+ vif0.tag.size -= vif0.vifpacketsize;
+
+ return vif0.vifpacketsize;
+ }
+ else
+ {
+ int ret;
+
+ if((vif0.tag.addr + vif0.tag.size) > 0x1000) DevCon.Warning("Vif0 MPG Overflow");
+
+ vif0mpgTransfer(vif0.tag.addr, data, vif0.tag.size);
+ ret = vif0.tag.size;
+ vif0.tag.size = 0;
+ vif0.cmd = 0;
+
+ return ret;
+ }
+}
+
+static int __fastcall Vif0TransUnpack(u32 *data) // UNPACK
+{
+ return nVifUnpack(0, (u8*)data);
+}
+
+//------------------------------------------------------------------
+// Vif0 CMD Base Commands
+//------------------------------------------------------------------
+
+static void Vif0CMDNop() // NOP
+{
+ vif0.cmd &= ~0x7f;
+}
+
+static void Vif0CMDSTCycl() // STCYCL
+{
+ vif0Regs->cycle.cl = (u8)vif0Regs->code;
+ vif0Regs->cycle.wl = (u8)(vif0Regs->code >> 8);
+ vif0.cmd &= ~0x7f;
+}
+
+static void Vif0CMDITop() // ITOP
+{
+ vif0Regs->itops = vif0Regs->code & 0x3ff;
+ vif0.cmd &= ~0x7f;
+}
+
+static void Vif0CMDSTMod() // STMOD
+{
+ vif0Regs->mode = vif0Regs->code & 0x3;
+ vif0.cmd &= ~0x7f;
+}
+
+static void Vif0CMDMark() // MARK
+{
+ vif0Regs->mark = (u16)vif0Regs->code;
+ vif0Regs->stat.MRK = true;
+ vif0.cmd &= ~0x7f;
+}
+
+static void Vif0CMDFlushE() // FLUSHE
+{
+ vif0FLUSH();
+ vif0.cmd &= ~0x7f;
+}
+
+static void Vif0CMDMSCALF() //MSCAL/F
+{
+ vuExecMicro<0>((u16)(vif0Regs->code) << 3);
+ vif0.cmd &= ~0x7f;
+}
+
+static void Vif0CMDMSCNT() // MSCNT
+{
+ vuExecMicro<0>(-1);
+ vif0.cmd &= ~0x7f;
+}
+
+static void Vif0CMDSTMask() // STMASK
+{
+ vif0.tag.size = 1;
+}
+
+static void Vif0CMDSTRowCol() // STROW / STCOL
+{
+ vif0.tag.addr = 0;
+ vif0.tag.size = 4;
+}
+
+static void Vif0CMDMPGTransfer() // MPG
+{
+ int vifNum;
+ vif0FLUSH();
+ vifNum = (u8)(vif0Regs->code >> 16);
+ if (vifNum == 0) vifNum = 256;
+ vif0.tag.addr = (u16)((vif0Regs->code) << 3) & 0xfff;
+ vif0.tag.size = vifNum * 2;
+}
+
+static void Vif0CMDNull() // invalid opcode
+{
+ // if ME1, then force the vif to interrupt
+ if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
+ {
+ Console.WriteLn("UNKNOWN VifCmd: %x", vif0.cmd);
+ vif0Regs->stat.ER1 = true;
+ vif0.irq++;
+ }
+ vif0.cmd &= ~0x7f;
+}
+
+
+//------------------------------------------------------------------
+// Vif0 Data Transfer / Vif0 CMD Tables
+//------------------------------------------------------------------
+
+int (__fastcall *Vif0TransTLB[128])(u32 *data) =
+{
+ Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x7*/
+ Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0xF*/
+ Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x17*/
+ Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x1F*/
+ Vif0TransSTMask , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x27*/
+ Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x2F*/
+ Vif0TransSTRow , Vif0TransSTCol , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x37*/
+ Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x3F*/
+ Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x47*/
+ Vif0TransNull , Vif0TransNull , Vif0TransMPG , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x4F*/
+ Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x57*/
+ Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x5F*/
+ Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , /*0x67*/
+ Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , /*0x6F*/
+ Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , /*0x77*/
+ Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack /*0x7F*/
+};
+
+void (*Vif0CMDTLB[75])() =
+{
+ Vif0CMDNop , Vif0CMDSTCycl , Vif0CMDNull , Vif0CMDNull , Vif0CMDITop , Vif0CMDSTMod , Vif0CMDNull, Vif0CMDMark , /*0x7*/
+ Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0xF*/
+ Vif0CMDFlushE , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull, Vif0CMDMSCALF, Vif0CMDMSCALF, Vif0CMDNull , Vif0CMDMSCNT, /*0x17*/
+ Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x1F*/
+ Vif0CMDSTMask , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x27*/
+ Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x2F*/
+ Vif0CMDSTRowCol, Vif0CMDSTRowCol, Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x37*/
+ Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x3F*/
+ Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x47*/
+ Vif0CMDNull , Vif0CMDNull , Vif0CMDMPGTransfer
+};
diff --git a/pcsx2/Vif0Dma.cpp b/pcsx2/Vif0_Dma.cpp
similarity index 54%
rename from pcsx2/Vif0Dma.cpp
rename to pcsx2/Vif0_Dma.cpp
index 6f3d882412..eb1b701df9 100644
--- a/pcsx2/Vif0Dma.cpp
+++ b/pcsx2/Vif0_Dma.cpp
@@ -1,746 +1,446 @@
-/* PCSX2 - PS2 Emulator for PCs
- * Copyright (C) 2002-2009 PCSX2 Dev Team
- *
- * PCSX2 is free software: you can redistribute it and/or modify it under the terms
- * of the GNU Lesser General Public License as published by the Free Software Found-
- * ation, either version 3 of the License, or (at your option) any later version.
- *
- * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with PCSX2.
- * If not, see .
- */
-
-
-#include "PrecompiledHeader.h"
-#include "Common.h"
-#include "VifDma.h"
-#include "VUmicro.h"
-#include "newVif.h"
-
-extern int (__fastcall *Vif0TransTLB[128])(u32 *data);
-extern void (*Vif0CMDTLB[75])();
-
-vifStruct vif0;
-
-__forceinline void vif0FLUSH()
-{
- int _cycles = VU0.cycle;
-
- // fixme: this code should call _vu0WaitMicro instead? I'm not sure if
- // it's purposefully ignoring ee cycles or not (see below for more)
-
- vu0Finish();
- g_vifCycles += (VU0.cycle - _cycles) * BIAS;
-}
-
-void vif0Init()
-{
- initNewVif(0);
-}
-
-static __forceinline void vif0UNPACK(u32 *data)
-{
- int vifNum;
-
- if ((vif0Regs->cycle.wl == 0) && (vif0Regs->cycle.wl < vif0Regs->cycle.cl))
- {
- Console.WriteLn("Vif0 CL %d, WL %d", vif0Regs->cycle.cl, vif0Regs->cycle.wl);
- vif0.cmd &= ~0x7f;
- return;
- }
-
- vif0FLUSH();
-
- vif0.tag.addr = (vif0Regs->code & 0xff) << 4;
- vif0.usn = (vif0Regs->code >> 14) & 0x1;
- vifNum = (vif0Regs->code >> 16) & 0xff;
- if (vifNum == 0) vifNum = 256;
- vif0Regs->num = vifNum;
-
- if (vif0Regs->cycle.wl <= vif0Regs->cycle.cl)
- {
- vif0.tag.size = ((vifNum * VIFfuncTable[ vif0.cmd & 0xf ].gsize) + 3) >> 2;
- }
- else
- {
- int n = vif0Regs->cycle.cl * (vifNum / vif0Regs->cycle.wl) +
- _limit(vifNum % vif0Regs->cycle.wl, vif0Regs->cycle.cl);
-
- vif0.tag.size = ((n * VIFfuncTable[ vif0.cmd & 0xf ].gsize) + 3) >> 2;
- }
-
- vif0.cl = 0;
- vif0.tag.cmd = vif0.cmd;
- vif0Regs->offset = 0;
-}
-
-static __forceinline void vif0mpgTransfer(u32 addr, u32 *data, int size)
-{
- /* Console.WriteLn("vif0mpgTransfer addr=%x; size=%x", addr, size);
- {
- FILE *f = fopen("vu1.raw", "wb");
- fwrite(data, 1, size*4, f);
- fclose(f);
- }*/
- if (memcmp(VU0.Micro + addr, data, size << 2))
- {
- CpuVU0->Clear(addr, size << 2); // Clear before writing! :/ (cottonvibes)
- memcpy_fast(VU0.Micro + addr, data, size << 2);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Vif0 Data Transfer Commands
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-static int __fastcall Vif0TransNull(u32 *data) // Shouldnt go here
-{
- Console.WriteLn("VIF0 Shouldn't go here CMD = %x", vif0Regs->code);
- vif0.cmd = 0;
- return 0;
-}
-
-static int __fastcall Vif0TransSTMask(u32 *data) // STMASK
-{
- vif0Regs->mask = data[0];
- VIF_LOG("STMASK == %x", vif0Regs->mask);
-
- vif0.tag.size = 0;
- vif0.cmd = 0;
- return 1;
-}
-
-static int __fastcall Vif0TransSTRow(u32 *data) // STROW
-{
- int ret;
-
- u32* pmem = &vif0Regs->r0 + (vif0.tag.addr << 2);
- u32* pmem2 = g_vifmask.Row0 + vif0.tag.addr;
- pxAssume(vif0.tag.addr < 4);
- ret = min(4 - vif0.tag.addr, vif0.vifpacketsize);
- pxAssume(ret > 0);
-
- switch (ret)
- {
- case 4:
- pmem[12] = data[3];
- pmem2[3] = data[3];
- case 3:
- pmem[8] = data[2];
- pmem2[2] = data[2];
- case 2:
- pmem[4] = data[1];
- pmem2[1] = data[1];
- case 1:
- pmem[0] = data[0];
- pmem2[0] = data[0];
- break;
-
- jNO_DEFAULT
- }
-
- vif0.tag.addr += ret;
- vif0.tag.size -= ret;
- if (vif0.tag.size == 0) vif0.cmd = 0;
-
- return ret;
-}
-
-static int __fastcall Vif0TransSTCol(u32 *data) // STCOL
-{
- int ret;
-
- u32* pmem = &vif0Regs->c0 + (vif0.tag.addr << 2);
- u32* pmem2 = g_vifmask.Col0 + vif0.tag.addr;
- ret = min(4 - vif0.tag.addr, vif0.vifpacketsize);
-
- switch (ret)
- {
- case 4:
- pmem[12] = data[3];
- pmem2[3] = data[3];
- case 3:
- pmem[8] = data[2];
- pmem2[2] = data[2];
- case 2:
- pmem[4] = data[1];
- pmem2[1] = data[1];
- case 1:
- pmem[0] = data[0];
- pmem2[0] = data[0];
- break;
-
- jNO_DEFAULT
- }
-
- vif0.tag.addr += ret;
- vif0.tag.size -= ret;
- if (vif0.tag.size == 0) vif0.cmd = 0;
- return ret;
-}
-
-static int __fastcall Vif0TransMPG(u32 *data) // MPG
-{
- if (vif0.vifpacketsize < vif0.tag.size)
- {
- if((vif0.tag.addr + vif0.vifpacketsize) > 0x1000) DevCon.Warning("Vif0 MPG Split Overflow");
-
- vif0mpgTransfer(vif0.tag.addr, data, vif0.vifpacketsize);
- vif0.tag.addr += vif0.vifpacketsize << 2;
- vif0.tag.size -= vif0.vifpacketsize;
-
- return vif0.vifpacketsize;
- }
- else
- {
- int ret;
-
- if((vif0.tag.addr + vif0.tag.size) > 0x1000) DevCon.Warning("Vif0 MPG Overflow");
-
- vif0mpgTransfer(vif0.tag.addr, data, vif0.tag.size);
- ret = vif0.tag.size;
- vif0.tag.size = 0;
- vif0.cmd = 0;
-
- return ret;
- }
-}
-
-static int __fastcall Vif0TransUnpack(u32 *data) // UNPACK
-{
- return nVifUnpack(0, (u8*)data);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Vif0 CMD Base Commands
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-static void Vif0CMDNop() // NOP
-{
- vif0.cmd &= ~0x7f;
-}
-
-static void Vif0CMDSTCycl() // STCYCL
-{
- vif0Regs->cycle.cl = (u8)vif0Regs->code;
- vif0Regs->cycle.wl = (u8)(vif0Regs->code >> 8);
- vif0.cmd &= ~0x7f;
-}
-
-static void Vif0CMDITop() // ITOP
-{
- vif0Regs->itops = vif0Regs->code & 0x3ff;
- vif0.cmd &= ~0x7f;
-}
-
-static void Vif0CMDSTMod() // STMOD
-{
- vif0Regs->mode = vif0Regs->code & 0x3;
- vif0.cmd &= ~0x7f;
-}
-
-static void Vif0CMDMark() // MARK
-{
- vif0Regs->mark = (u16)vif0Regs->code;
- vif0Regs->stat.MRK = true;
- vif0.cmd &= ~0x7f;
-}
-
-static void Vif0CMDFlushE() // FLUSHE
-{
- vif0FLUSH();
- vif0.cmd &= ~0x7f;
-}
-
-static void Vif0CMDMSCALF() //MSCAL/F
-{
- vuExecMicro<0>((u16)(vif0Regs->code) << 3);
- vif0.cmd &= ~0x7f;
-}
-
-static void Vif0CMDMSCNT() // MSCNT
-{
- vuExecMicro<0>(-1);
- vif0.cmd &= ~0x7f;
-}
-
-static void Vif0CMDSTMask() // STMASK
-{
- vif0.tag.size = 1;
-}
-
-static void Vif0CMDSTRowCol() // STROW / STCOL
-{
- vif0.tag.addr = 0;
- vif0.tag.size = 4;
-}
-
-static void Vif0CMDMPGTransfer() // MPG
-{
- int vifNum;
- vif0FLUSH();
- vifNum = (u8)(vif0Regs->code >> 16);
- if (vifNum == 0) vifNum = 256;
- vif0.tag.addr = (u16)((vif0Regs->code) << 3) & 0xfff;
- vif0.tag.size = vifNum * 2;
-}
-
-static void Vif0CMDNull() // invalid opcode
-{
- // if ME1, then force the vif to interrupt
- if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
- {
- Console.WriteLn("UNKNOWN VifCmd: %x", vif0.cmd);
- vif0Regs->stat.ER1 = true;
- vif0.irq++;
- }
- vif0.cmd &= ~0x7f;
-}
-
-bool VIF0transfer(u32 *data, int size, bool istag)
-{
- int ret;
- int transferred = vif0.vifstalled ? vif0.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman)
- VIF_LOG("VIF0transfer: size %x (vif0.cmd %x)", size, vif0.cmd);
-
- vif0.stallontag = false;
- vif0.vifstalled = false;
- vif0.vifpacketsize = size;
-
- while (vif0.vifpacketsize > 0)
- {
- if (vif0.cmd)
- {
- vif0Regs->stat.VPS = VPS_TRANSFERRING; //Decompression has started
-
- ret = Vif0TransTLB[(vif0.cmd & 0x7f)](data);
- data += ret;
- vif0.vifpacketsize -= ret;
- if (vif0.cmd == 0) vif0Regs->stat.VPS = VPS_IDLE; //We are once again waiting for a new vifcode as the command has cleared
- continue;
- }
-
- if (vif0.tag.size != 0) Console.WriteLn("no vif0 cmd but tag size is left last cmd read %x", vif0Regs->code);
-
- // if interrupt and new cmd is NOT MARK
- if (vif0.irq) break;
-
- vif0.cmd = (data[0] >> 24);
- vif0Regs->code = data[0];
-
- vif0Regs->stat.VPS |= VPS_DECODING; //We need to set these (Onimusha needs it)
-
- if ((vif0.cmd & 0x60) == 0x60)
- {
- vif0UNPACK(data);
- }
- else
- {
- VIF_LOG("VIFtransfer: cmd %x, num %x, imm %x, size %x", vif0.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size);
-
- if ((vif0.cmd & 0x7f) > 0x4A)
- {
- if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
- {
- Console.WriteLn("UNKNOWN VifCmd: %x", vif0.cmd);
- vif0Regs->stat.ER1 = true;
- vif0.irq++;
- }
- vif0.cmd = 0;
- }
- else
- {
- Vif0CMDTLB[(vif0.cmd & 0x7f)]();
- }
- }
- ++data;
- --vif0.vifpacketsize;
-
- if ((vif0.cmd & 0x80))
- {
- vif0.cmd &= 0x7f;
-
- if (!(vif0Regs->err.MII)) //i bit on vifcode and not masked by VIF0_ERR
- {
- VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif0.cmd, psHu32(INTC_MASK));
-
- ++vif0.irq;
-
- if (istag && vif0.tag.size <= vif0.vifpacketsize) vif0.stallontag = true;
-
- if (vif0.tag.size == 0) break;
- }
- }
- } //End of Transfer loop
-
- transferred += size - vif0.vifpacketsize;
- g_vifCycles += (transferred >> 2) * BIAS; /* guessing */
- // use tag.size because some game doesn't like .cmd
-
- if (vif0.irq && (vif0.tag.size == 0))
- {
- vif0.vifstalled = true;
-
- if (((vif0Regs->code >> 24) & 0x7f) != 0x7) vif0Regs->stat.VIS = true;
- //else Console.WriteLn("VIF0 IRQ on MARK");
-
- // spiderman doesn't break on qw boundaries
- vif0.irqoffset = transferred % 4; // cannot lose the offset
-
- if (!istag)
- {
- transferred = transferred >> 2;
- vif0ch->madr += (transferred << 4);
- vif0ch->qwc -= transferred;
- }
- //else Console.WriteLn("Stall on vif0, FromSPR = %x, Vif0MADR = %x Sif0MADR = %x STADR = %x", psHu32(0x1000d010), vif0ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR));
- return false;
- }
-
- vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
- if (vif0.cmd) vif0Regs->stat.VPS |= VPS_WAITING; //Otherwise we wait for the data
-
- if (!istag)
- {
- transferred = transferred >> 2;
- vif0ch->madr += (transferred << 4);
- vif0ch->qwc -= transferred;
- }
-
- return true;
-}
-
-bool _VIF0chain()
-{
- u32 *pMem;
-
- if ((vif0ch->qwc == 0) && !vif0.vifstalled) return true;
-
- pMem = (u32*)dmaGetAddr(vif0ch->madr);
- if (pMem == NULL)
- {
- vif0.cmd = 0;
- vif0.tag.size = 0;
- vif0ch->qwc = 0;
- return true;
- }
-
- if (vif0.vifstalled)
- return VIF0transfer(pMem + vif0.irqoffset, vif0ch->qwc * 4 - vif0.irqoffset, false);
- else
- return VIF0transfer(pMem, vif0ch->qwc * 4, false);
-}
-
-bool _chainVIF0()
-{
- 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)
- {
- 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)) return false; //IRQ set by VIFTransfer
- }
-
- 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()
-{
- 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))
- {
- 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;
- vif0ch->chcr.STR = false;
- return;
- }
-
- if (vif0ch->qwc > 0 || vif0.irqoffset > 0)
- {
- if (vif0.stallontag)
- _chainVIF0();
- else
- _VIF0chain();
-
- CPU_INT(0, /*g_vifCycles*/ VifCycleVoodoo);
- return;
- }
- }
-
- if (!vif0ch->chcr.STR) Console.WriteLn("Vif0 running when CHCR = %x", vif0ch->chcr._u32);
-
- if ((vif0ch->chcr.MOD == CHAIN_MODE) && (!vif0.done) && (!vif0.vifstalled))
- {
-
- if (!(dmacRegs->ctrl.DMAE))
- {
- Console.WriteLn("vif0 dma masked");
- return;
- }
-
- if (vif0ch->qwc > 0)
- _VIF0chain();
- else
- _chainVIF0();
-
- CPU_INT(0, /*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);
-
- vif0ch->chcr.STR = false;
- hwDmacIrq(DMAC_VIF0);
- vif0Regs->stat.FQC = 0;
-}
-
-// Vif0 Data Transfer Table
-int (__fastcall *Vif0TransTLB[128])(u32 *data) =
-{
- Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x7*/
- Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0xF*/
- Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x17*/
- Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x1F*/
- Vif0TransSTMask , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x27*/
- Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x2F*/
- Vif0TransSTRow , Vif0TransSTCol , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x37*/
- Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x3F*/
- Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x47*/
- Vif0TransNull , Vif0TransNull , Vif0TransMPG , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x4F*/
- Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x57*/
- Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x5F*/
- Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , /*0x67*/
- Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , /*0x6F*/
- Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , /*0x77*/
- Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack /*0x7F*/
-};
-
-// Vif0 CMD Table
-void (*Vif0CMDTLB[75])() =
-{
- Vif0CMDNop , Vif0CMDSTCycl , Vif0CMDNull , Vif0CMDNull , Vif0CMDITop , Vif0CMDSTMod , Vif0CMDNull, Vif0CMDMark , /*0x7*/
- Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0xF*/
- Vif0CMDFlushE , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull, Vif0CMDMSCALF, Vif0CMDMSCALF, Vif0CMDNull , Vif0CMDMSCNT, /*0x17*/
- Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x1F*/
- Vif0CMDSTMask , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x27*/
- Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x2F*/
- Vif0CMDSTRowCol, Vif0CMDSTRowCol, Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x37*/
- Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x3F*/
- Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x47*/
- Vif0CMDNull , Vif0CMDNull , Vif0CMDMPGTransfer
-};
-
-void dmaVIF0()
-{
- VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n"
- " tadr = %lx, asr0 = %lx, asr1 = %lx\n",
- vif0ch->chcr._u32, vif0ch->madr, vif0ch->qwc,
- vif0ch->tadr, vif0ch->asr0, vif0ch->asr1);
-
- g_vifCycles = 0;
-
- vif0Regs->stat.FQC = 0x8; // FQC=8
-
- if (!(vif0ch->chcr.MOD & 0x1) || 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(0, /*g_vifCycles*/ VifCycleVoodoo);
- return;
- }
-
- // Chain Mode
- vif0.done = false;
- CPU_INT(0, 0);
-}
-
-void vif0Write32(u32 mem, u32 value)
-{
- switch (mem)
- {
- case VIF0_MARK:
- VIF_LOG("VIF0_MARK write32 0x%8.8x", value);
-
- /* Clear mark flag in VIF0_STAT and set mark with 'value' */
- vif0Regs->stat.MRK = false;
- vif0Regs->mark = value;
- break;
-
- case VIF0_FBRST:
- VIF_LOG("VIF0_FBRST write32 0x%8.8x", value);
-
- if (value & 0x1) // Reset Vif.
- {
- //Console.WriteLn("Vif0 Reset %x", vif0Regs->stat._u32);
-
- memzero(vif0);
- vif0ch->qwc = 0; //?
- cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
- psHu64(VIF0_FIFO) = 0;
- psHu64(VIF0_FIFO + 8) = 0;
- vif0.done = true;
- vif0Regs->err.reset();
- vif0Regs->stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0
- }
-
- if (value & 0x2) // Forcebreak Vif,
- {
- /* I guess we should stop the VIF dma here, but not 100% sure (linuz) */
- cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
- vif0Regs->stat.VFS = true;
- vif0Regs->stat.VPS = VPS_IDLE;
- vif0.vifstalled = true;
- Console.WriteLn("vif0 force break");
- }
-
- if (value & 0x4) // Stop Vif.
- {
- // Not completely sure about this, can't remember what game, used this, but 'draining' the VIF helped it, instead of
- // just stoppin the VIF (linuz).
- vif0Regs->stat.VSS = true;
- vif0Regs->stat.VPS = VPS_IDLE;
- vif0.vifstalled = true;
- }
-
- if (value & 0x8) // Cancel Vif Stall.
- {
- bool cancel = false;
-
- /* Cancel stall, first check if there is a stall to cancel, and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */
- if (vif0Regs->stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
- cancel = true;
-
- vif0Regs->stat.clear_flags(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS |
- VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1);
- if (cancel)
- {
- if (vif0.vifstalled)
- {
- g_vifCycles = 0;
-
- // loop necessary for spiderman
- if (vif0.stallontag)
- _chainVIF0();
- else
- _VIF0chain();
-
- vif0ch->chcr.STR = true;
- CPU_INT(0, g_vifCycles); // Gets the timing right - Flatout
- }
- }
- }
- break;
-
- case VIF0_ERR:
- // ERR
- VIF_LOG("VIF0_ERR write32 0x%8.8x", value);
-
- /* Set VIF0_ERR with 'value' */
- vif0Regs->err.write(value);
- break;
-
- case VIF0_R0:
- case VIF0_R1:
- case VIF0_R2:
- case VIF0_R3:
- pxAssume((mem&0xf) == 0);
- g_vifmask.Row0[(mem>>4) & 3] = value;
- break;
-
- case VIF0_C0:
- case VIF0_C1:
- case VIF0_C2:
- case VIF0_C3:
- pxAssume((mem&0xf) == 0);
- g_vifmask.Col0[(mem>>4) & 3] = value;
- break;
-
- default:
- Console.WriteLn("Unknown Vif0 write to %x", mem);
- psHu32(mem) = value;
- break;
- }
- /* Other registers are read-only so do nothing for them */
-}
-
-void vif0Reset()
-{
- /* Reset the whole VIF, meaning the internal pcsx2 vars and all the registers */
- memzero(vif0);
- memzero(*vif0Regs);
-
- psHu64(VIF0_FIFO) = 0;
- psHu64(VIF0_FIFO + 8) = 0;
-
- vif0Regs->stat.VPS = VPS_IDLE;
- vif0Regs->stat.FQC = 0;
-
- vif0.done = true;
-
- resetNewVif(0);
-}
-
-void SaveStateBase::vif0Freeze()
-{
- static u32 g_vif0Masks[64]; // Dummy Var for saved state compatibility
- static u32 g_vif0HasMask3[4]; // Dummy Var for saved state compatibility
- FreezeTag("VIFdma");
-
- // Dunno if this one is needed, but whatever, it's small. :)
- Freeze(g_vifCycles);
-
- // mask settings for VIF0 and VIF1
- Freeze(g_vifmask);
-
- Freeze(vif0);
- Freeze(g_vif0HasMask3); // Not Used Anymore
- Freeze(g_vif0Masks); // Not Used Anymore
-}
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+#include "Common.h"
+#include "Vif_Dma.h"
+#include "VUmicro.h"
+#include "newVif.h"
+
+extern int (__fastcall *Vif0TransTLB[128])(u32 *data);
+extern void (*Vif0CMDTLB[75])();
+vifStruct vif0;
+
+__forceinline void vif0FLUSH()
+{
+ int _cycles = VU0.cycle;
+
+ // fixme: this code should call _vu0WaitMicro instead? I'm not sure if
+ // it's purposefully ignoring ee cycles or not (see below for more)
+
+ vu0Finish();
+ g_vifCycles += (VU0.cycle - _cycles) * BIAS;
+}
+
+static __forceinline void vif0UNPACK(u32 *data)
+{
+ int vifNum;
+
+ if ((vif0Regs->cycle.wl == 0) && (vif0Regs->cycle.wl < vif0Regs->cycle.cl))
+ {
+ Console.WriteLn("Vif0 CL %d, WL %d", vif0Regs->cycle.cl, vif0Regs->cycle.wl);
+ vif0.cmd &= ~0x7f;
+ return;
+ }
+
+ vif0FLUSH();
+
+ vif0.tag.addr = (vif0Regs->code & 0xff) << 4;
+ vif0.usn = (vif0Regs->code >> 14) & 0x1;
+ vifNum = (vif0Regs->code >> 16) & 0xff;
+ if (vifNum == 0) vifNum = 256;
+ vif0Regs->num = vifNum;
+
+ if (vif0Regs->cycle.wl <= vif0Regs->cycle.cl)
+ {
+ vif0.tag.size = ((vifNum * VIFfuncTable[ vif0.cmd & 0xf ].gsize) + 3) >> 2;
+ }
+ else
+ {
+ int n = vif0Regs->cycle.cl * (vifNum / vif0Regs->cycle.wl) +
+ _limit(vifNum % vif0Regs->cycle.wl, vif0Regs->cycle.cl);
+
+ vif0.tag.size = ((n * VIFfuncTable[ vif0.cmd & 0xf ].gsize) + 3) >> 2;
+ }
+
+ vif0.cl = 0;
+ vif0.tag.cmd = vif0.cmd;
+ vif0Regs->offset = 0;
+}
+
+bool VIF0transfer(u32 *data, int size, bool istag)
+{
+ int ret;
+ int transferred = vif0.vifstalled ? vif0.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman)
+ VIF_LOG("VIF0transfer: size %x (vif0.cmd %x)", size, vif0.cmd);
+
+ vif0.stallontag = false;
+ vif0.vifstalled = false;
+ vif0.vifpacketsize = size;
+
+ while (vif0.vifpacketsize > 0)
+ {
+ if (vif0.cmd)
+ {
+ vif0Regs->stat.VPS = VPS_TRANSFERRING; //Decompression has started
+
+ ret = Vif0TransTLB[(vif0.cmd & 0x7f)](data);
+ data += ret;
+ vif0.vifpacketsize -= ret;
+ if (vif0.cmd == 0) vif0Regs->stat.VPS = VPS_IDLE; //We are once again waiting for a new vifcode as the command has cleared
+ continue;
+ }
+
+ if (vif0.tag.size != 0) Console.WriteLn("no vif0 cmd but tag size is left last cmd read %x", vif0Regs->code);
+
+ // if interrupt and new cmd is NOT MARK
+ if (vif0.irq) break;
+
+ vif0.cmd = (data[0] >> 24);
+ vif0Regs->code = data[0];
+
+ vif0Regs->stat.VPS |= VPS_DECODING; //We need to set these (Onimusha needs it)
+
+ if ((vif0.cmd & 0x60) == 0x60)
+ {
+ vif0UNPACK(data);
+ }
+ else
+ {
+ VIF_LOG("VIFtransfer: cmd %x, num %x, imm %x, size %x", vif0.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size);
+
+ if ((vif0.cmd & 0x7f) > 0x4A)
+ {
+ if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
+ {
+ Console.WriteLn("UNKNOWN VifCmd: %x", vif0.cmd);
+ vif0Regs->stat.ER1 = true;
+ vif0.irq++;
+ }
+ vif0.cmd = 0;
+ }
+ else
+ {
+ Vif0CMDTLB[(vif0.cmd & 0x7f)]();
+ }
+ }
+ ++data;
+ --vif0.vifpacketsize;
+
+ if ((vif0.cmd & 0x80))
+ {
+ vif0.cmd &= 0x7f;
+
+ if (!(vif0Regs->err.MII)) //i bit on vifcode and not masked by VIF0_ERR
+ {
+ VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif0.cmd, psHu32(INTC_MASK));
+
+ ++vif0.irq;
+
+ if (istag && vif0.tag.size <= vif0.vifpacketsize) vif0.stallontag = true;
+
+ if (vif0.tag.size == 0) break;
+ }
+ }
+ } //End of Transfer loop
+
+ transferred += size - vif0.vifpacketsize;
+ g_vifCycles += (transferred >> 2) * BIAS; /* guessing */
+ // use tag.size because some game doesn't like .cmd
+
+ if (vif0.irq && (vif0.tag.size == 0))
+ {
+ vif0.vifstalled = true;
+
+ if (((vif0Regs->code >> 24) & 0x7f) != 0x7) vif0Regs->stat.VIS = true;
+ //else Console.WriteLn("VIF0 IRQ on MARK");
+
+ // spiderman doesn't break on qw boundaries
+ vif0.irqoffset = transferred % 4; // cannot lose the offset
+
+ if (!istag)
+ {
+ transferred = transferred >> 2;
+ vif0ch->madr += (transferred << 4);
+ vif0ch->qwc -= transferred;
+ }
+ //else Console.WriteLn("Stall on vif0, FromSPR = %x, Vif0MADR = %x Sif0MADR = %x STADR = %x", psHu32(0x1000d010), vif0ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR));
+ return false;
+ }
+
+ vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
+ if (vif0.cmd) vif0Regs->stat.VPS |= VPS_WAITING; //Otherwise we wait for the data
+
+ if (!istag)
+ {
+ transferred = transferred >> 2;
+ vif0ch->madr += (transferred << 4);
+ vif0ch->qwc -= transferred;
+ }
+
+ return true;
+}
+
+bool _VIF0chain()
+{
+ u32 *pMem;
+
+ if ((vif0ch->qwc == 0) && !vif0.vifstalled) return true;
+
+ pMem = (u32*)dmaGetAddr(vif0ch->madr);
+ if (pMem == NULL)
+ {
+ vif0.cmd = 0;
+ vif0.tag.size = 0;
+ vif0ch->qwc = 0;
+ return true;
+ }
+
+ if (vif0.vifstalled)
+ return VIF0transfer(pMem + vif0.irqoffset, vif0ch->qwc * 4 - vif0.irqoffset, false);
+ else
+ return VIF0transfer(pMem, vif0ch->qwc * 4, false);
+}
+
+bool _chainVIF0()
+{
+ 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)
+ {
+ 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)) return false; //IRQ set by VIFTransfer
+ }
+
+ 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()
+{
+ 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))
+ {
+ 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;
+ vif0ch->chcr.STR = false;
+ return;
+ }
+
+ if (vif0ch->qwc > 0 || vif0.irqoffset > 0)
+ {
+ if (vif0.stallontag)
+ _chainVIF0();
+ else
+ _VIF0chain();
+
+ CPU_INT(0, /*g_vifCycles*/ VifCycleVoodoo);
+ return;
+ }
+ }
+
+ if (!vif0ch->chcr.STR) Console.WriteLn("Vif0 running when CHCR = %x", vif0ch->chcr._u32);
+
+ if ((vif0ch->chcr.MOD == CHAIN_MODE) && (!vif0.done) && (!vif0.vifstalled))
+ {
+
+ if (!(dmacRegs->ctrl.DMAE))
+ {
+ Console.WriteLn("vif0 dma masked");
+ return;
+ }
+
+ if (vif0ch->qwc > 0)
+ _VIF0chain();
+ else
+ _chainVIF0();
+
+ CPU_INT(0, /*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);
+
+ vif0ch->chcr.STR = false;
+ hwDmacIrq(DMAC_VIF0);
+ vif0Regs->stat.FQC = 0;
+}
+
+void dmaVIF0()
+{
+ VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n"
+ " tadr = %lx, asr0 = %lx, asr1 = %lx\n",
+ vif0ch->chcr._u32, vif0ch->madr, vif0ch->qwc,
+ vif0ch->tadr, vif0ch->asr0, vif0ch->asr1);
+
+ g_vifCycles = 0;
+
+ vif0Regs->stat.FQC = 0x8; // FQC=8
+
+ if (!(vif0ch->chcr.MOD & 0x1) || 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(0, /*g_vifCycles*/ VifCycleVoodoo);
+ return;
+ }
+
+ // Chain Mode
+ vif0.done = false;
+ CPU_INT(0, 0);
+}
+
+void vif0Write32(u32 mem, u32 value)
+{
+ switch (mem)
+ {
+ case VIF0_MARK:
+ VIF_LOG("VIF0_MARK write32 0x%8.8x", value);
+
+ /* Clear mark flag in VIF0_STAT and set mark with 'value' */
+ vif0Regs->stat.MRK = false;
+ vif0Regs->mark = value;
+ break;
+
+ case VIF0_FBRST:
+ VIF_LOG("VIF0_FBRST write32 0x%8.8x", value);
+
+ if (value & 0x1) // Reset Vif.
+ {
+ //Console.WriteLn("Vif0 Reset %x", vif0Regs->stat._u32);
+
+ memzero(vif0);
+ vif0ch->qwc = 0; //?
+ cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
+ psHu64(VIF0_FIFO) = 0;
+ psHu64(VIF0_FIFO + 8) = 0;
+ vif0.done = true;
+ vif0Regs->err.reset();
+ vif0Regs->stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0
+ }
+
+ if (value & 0x2) // Forcebreak Vif,
+ {
+ /* I guess we should stop the VIF dma here, but not 100% sure (linuz) */
+ cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
+ vif0Regs->stat.VFS = true;
+ vif0Regs->stat.VPS = VPS_IDLE;
+ vif0.vifstalled = true;
+ Console.WriteLn("vif0 force break");
+ }
+
+ if (value & 0x4) // Stop Vif.
+ {
+ // Not completely sure about this, can't remember what game, used this, but 'draining' the VIF helped it, instead of
+ // just stoppin the VIF (linuz).
+ vif0Regs->stat.VSS = true;
+ vif0Regs->stat.VPS = VPS_IDLE;
+ vif0.vifstalled = true;
+ }
+
+ if (value & 0x8) // Cancel Vif Stall.
+ {
+ bool cancel = false;
+
+ /* Cancel stall, first check if there is a stall to cancel, and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */
+ if (vif0Regs->stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
+ cancel = true;
+
+ vif0Regs->stat.clear_flags(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS |
+ VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1);
+ if (cancel)
+ {
+ if (vif0.vifstalled)
+ {
+ g_vifCycles = 0;
+
+ // loop necessary for spiderman
+ if (vif0.stallontag)
+ _chainVIF0();
+ else
+ _VIF0chain();
+
+ vif0ch->chcr.STR = true;
+ CPU_INT(0, g_vifCycles); // Gets the timing right - Flatout
+ }
+ }
+ }
+ break;
+
+ case VIF0_ERR:
+ // ERR
+ VIF_LOG("VIF0_ERR write32 0x%8.8x", value);
+
+ /* Set VIF0_ERR with 'value' */
+ vif0Regs->err.write(value);
+ break;
+
+ case VIF0_R0:
+ case VIF0_R1:
+ case VIF0_R2:
+ case VIF0_R3:
+ pxAssume((mem&0xf) == 0);
+ g_vifmask.Row0[(mem>>4) & 3] = value;
+ break;
+
+ case VIF0_C0:
+ case VIF0_C1:
+ case VIF0_C2:
+ case VIF0_C3:
+ pxAssume((mem&0xf) == 0);
+ g_vifmask.Col0[(mem>>4) & 3] = value;
+ break;
+
+ default:
+ Console.WriteLn("Unknown Vif0 write to %x", mem);
+ psHu32(mem) = value;
+ break;
+ }
+ /* Other registers are read-only so do nothing for them */
+}
diff --git a/pcsx2/Vif1_Commands.cpp b/pcsx2/Vif1_Commands.cpp
new file mode 100644
index 0000000000..157b87c08e
--- /dev/null
+++ b/pcsx2/Vif1_Commands.cpp
@@ -0,0 +1,425 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+#include "Common.h"
+#include "Vif_Dma.h"
+#include "GS.h"
+#include "Gif.h"
+#include "VUmicro.h"
+
+//------------------------------------------------------------------
+// Vif1 Data Transfer Commands
+//------------------------------------------------------------------
+
+static int __fastcall Vif1TransNull(u32 *data) // Shouldnt go here
+{
+ Console.WriteLn("VIF1 Shouldn't go here CMD = %x", vif1Regs->code);
+ vif1.cmd = 0;
+ return 0;
+}
+
+static int __fastcall Vif1TransSTMask(u32 *data) // STMASK
+{
+ vif1Regs->mask = data[0];
+ VIF_LOG("STMASK == %x", vif1Regs->mask);
+
+ vif1.tag.size = 0;
+ vif1.cmd = 0;
+ return 1;
+}
+
+static int __fastcall Vif1TransSTRow(u32 *data) // STROW
+{
+ int ret;
+
+ u32* pmem = &vif1Regs->r0 + (vif1.tag.addr << 2);
+ u32* pmem2 = g_vifmask.Row1 + vif1.tag.addr;
+ pxAssume(vif1.tag.addr < 4);
+ ret = min(4 - vif1.tag.addr, vif1.vifpacketsize);
+ pxAssume(ret > 0);
+
+ switch (ret)
+ {
+ case 4:
+ pmem[12] = data[3];
+ pmem2[3] = data[3];
+ case 3:
+ pmem[8] = data[2];
+ pmem2[2] = data[2];
+ case 2:
+ pmem[4] = data[1];
+ pmem2[1] = data[1];
+ case 1:
+ pmem[0] = data[0];
+ pmem2[0] = data[0];
+ break;
+ jNO_DEFAULT;
+ }
+
+ vif1.tag.addr += ret;
+ vif1.tag.size -= ret;
+ if (vif1.tag.size == 0) vif1.cmd = 0;
+
+ return ret;
+}
+
+static int __fastcall Vif1TransSTCol(u32 *data)
+{
+ int ret;
+
+ u32* pmem = &vif1Regs->c0 + (vif1.tag.addr << 2);
+ u32* pmem2 = g_vifmask.Col1 + vif1.tag.addr;
+ ret = min(4 - vif1.tag.addr, vif1.vifpacketsize);
+ switch (ret)
+ {
+ case 4:
+ pmem[12] = data[3];
+ pmem2[3] = data[3];
+ case 3:
+ pmem[8] = data[2];
+ pmem2[2] = data[2];
+ case 2:
+ pmem[4] = data[1];
+ pmem2[1] = data[1];
+ case 1:
+ pmem[0] = data[0];
+ pmem2[0] = data[0];
+ break;
+ jNO_DEFAULT;
+ }
+ vif1.tag.addr += ret;
+ vif1.tag.size -= ret;
+ if (vif1.tag.size == 0) vif1.cmd = 0;
+ return ret;
+}
+
+static __forceinline void vif1mpgTransfer(u32 addr, u32 *data, int size)
+{
+ pxAssume(VU1.Micro > 0);
+ if (memcmp(VU1.Micro + addr, data, size << 2))
+ {
+ CpuVU1->Clear(addr, size << 2); // Clear before writing! :/
+ memcpy_fast(VU1.Micro + addr, data, size << 2);
+ }
+}
+
+static int __fastcall Vif1TransMPG(u32 *data)
+{
+ if (vif1.vifpacketsize < vif1.tag.size)
+ {
+ if((vif1.tag.addr + vif1.vifpacketsize) > 0x4000) DevCon.Warning("Vif1 MPG Split Overflow");
+ vif1mpgTransfer(vif1.tag.addr, data, vif1.vifpacketsize);
+ vif1.tag.addr += vif1.vifpacketsize << 2;
+ vif1.tag.size -= vif1.vifpacketsize;
+ return vif1.vifpacketsize;
+ }
+ else
+ {
+ int ret;
+ if((vif1.tag.addr + vif1.tag.size) > 0x4000) DevCon.Warning("Vif1 MPG Overflow");
+ vif1mpgTransfer(vif1.tag.addr, data, vif1.tag.size);
+ ret = vif1.tag.size;
+ vif1.tag.size = 0;
+ vif1.cmd = 0;
+ return ret;
+ }
+}
+
+// Dummy GIF-TAG Packet to Guarantee Count = 1
+extern __aligned16 u32 nloop0_packet[4];
+static __aligned16 u32 splittransfer[4];
+static u32 splitptr = 0;
+
+static int __fastcall Vif1TransDirectHL(u32 *data)
+{
+ int ret = 0;
+
+ if ((vif1.cmd & 0x7f) == 0x51)
+ {
+ if (gif->chcr.STR && (!vif1Regs->mskpath3 && (Path3progress == IMAGE_MODE))) //PATH3 is in image mode, so wait for end of transfer
+ {
+ vif1Regs->stat.VGW = true;
+ return 0;
+ }
+ }
+
+ gifRegs->stat.APATH |= GIF_APATH2;
+ gifRegs->stat.OPH = true;
+
+ if (splitptr > 0) //Leftover data from the last packet, filling the rest and sending to the GS
+ {
+ if ((splitptr < 4) && (vif1.vifpacketsize >= (4 - splitptr)))
+ {
+ while (splitptr < 4)
+ {
+ splittransfer[splitptr++] = (u32)data++;
+ ret++;
+ vif1.tag.size--;
+ }
+ }
+
+ Registers::Freeze();
+ // copy 16 bytes the fast way:
+ const u64* src = (u64*)splittransfer[0];
+ GetMTGS().PrepDataPacket(GIF_PATH_2, nloop0_packet, 1);
+ u64* dst = (u64*)GetMTGS().GetDataPacketPtr();
+ dst[0] = src[0];
+ dst[1] = src[1];
+
+ GetMTGS().SendDataPacket();
+ Registers::Thaw();
+
+ if (vif1.tag.size == 0) vif1.cmd = 0;
+ splitptr = 0;
+ return ret;
+ }
+
+ if (vif1.vifpacketsize < vif1.tag.size)
+ {
+ if (vif1.vifpacketsize < 4 && splitptr != 4) //Not a full QW left in the buffer, saving left over data
+ {
+ ret = vif1.vifpacketsize;
+ while (ret > 0)
+ {
+ splittransfer[splitptr++] = (u32)data++;
+ vif1.tag.size--;
+ ret--;
+ }
+ return vif1.vifpacketsize;
+ }
+ vif1.tag.size -= vif1.vifpacketsize;
+ ret = vif1.vifpacketsize;
+ }
+ else
+ {
+ gifRegs->stat.clear_flags(GIF_STAT_APATH2 | GIF_STAT_OPH);
+ ret = vif1.tag.size;
+ vif1.tag.size = 0;
+ vif1.cmd = 0;
+ }
+
+ //TODO: ret is guaranteed to be qword aligned ?
+
+ Registers::Freeze();
+
+ // Round ret up, just in case it's not 128bit aligned.
+ const uint count = GetMTGS().PrepDataPacket(GIF_PATH_2, data, (ret + 3) >> 2);
+ memcpy_fast(GetMTGS().GetDataPacketPtr(), data, count << 4);
+ GetMTGS().SendDataPacket();
+
+ Registers::Thaw();
+
+ return ret;
+}
+static int __fastcall Vif1TransUnpack(u32 *data)
+{
+ return nVifUnpack(1, (u8*)data);
+}
+
+//------------------------------------------------------------------
+// Vif1 CMD Base Commands
+//------------------------------------------------------------------
+
+static void Vif1CMDNop() // NOP
+{
+ vif1.cmd &= ~0x7f;
+}
+
+static void Vif1CMDSTCycl() // STCYCL
+{
+ vif1Regs->cycle.cl = (u8)vif1Regs->code;
+ vif1Regs->cycle.wl = (u8)(vif1Regs->code >> 8);
+ vif1.cmd &= ~0x7f;
+}
+
+static void Vif1CMDOffset() // OFFSET
+{
+ vif1Regs->ofst = vif1Regs->code & 0x3ff;
+ vif1Regs->stat.DBF = false;
+ vif1Regs->tops = vif1Regs->base;
+ vif1.cmd &= ~0x7f;
+}
+
+static void Vif1CMDBase() // BASE
+{
+ vif1Regs->base = vif1Regs->code & 0x3ff;
+ vif1.cmd &= ~0x7f;
+}
+
+static void Vif1CMDITop() // ITOP
+{
+ vif1Regs->itops = vif1Regs->code & 0x3ff;
+ vif1.cmd &= ~0x7f;
+}
+
+static void Vif1CMDSTMod() // STMOD
+{
+ vif1Regs->mode = vif1Regs->code & 0x3;
+ vif1.cmd &= ~0x7f;
+}
+
+u8 schedulepath3msk = 0;
+
+void Vif1MskPath3() // MSKPATH3
+{
+ vif1Regs->mskpath3 = schedulepath3msk & 0x1;
+ //Console.WriteLn("VIF MSKPATH3 %x", vif1Regs->mskpath3);
+
+ if (vif1Regs->mskpath3)
+ {
+ gifRegs->stat.M3P = true;
+ }
+ else
+ {
+ //Let the Gif know it can transfer again (making sure any vif stall isnt unset prematurely)
+ Path3progress = TRANSFER_MODE;
+ gifRegs->stat.IMT = false;
+ CPU_INT(2, 4);
+ }
+
+ schedulepath3msk = 0;
+}
+static void Vif1CMDMskPath3() // MSKPATH3
+{
+ if (vif1ch->chcr.STR)
+ {
+ schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1);
+ vif1.vifstalled = true;
+ }
+ else
+ {
+ schedulepath3msk = (vif1Regs->code >> 15) & 0x1;
+ Vif1MskPath3();
+ }
+ vif1.cmd &= ~0x7f;
+}
+
+
+static void Vif1CMDMark() // MARK
+{
+ vif1Regs->mark = (u16)vif1Regs->code;
+ vif1Regs->stat.MRK = true;
+ vif1.cmd &= ~0x7f;
+}
+
+static void Vif1CMDFlush() // FLUSH/E/A
+{
+ vif1FLUSH();
+
+ if ((vif1.cmd & 0x7f) == 0x13)
+ {
+ // Gif is already transferring so wait for it.
+ if (((Path3progress != STOPPED_MODE) || !vif1Regs->mskpath3) && gif->chcr.STR)
+ {
+ vif1Regs->stat.VGW = true;
+ CPU_INT(2, 4);
+ }
+ }
+
+ vif1.cmd &= ~0x7f;
+}
+
+static void Vif1CMDMSCALF() //MSCAL/F
+{
+ vif1FLUSH();
+ vuExecMicro<1>((u16)(vif1Regs->code) << 3);
+ vif1.cmd &= ~0x7f;
+}
+
+static void Vif1CMDMSCNT() // MSCNT
+{
+ vuExecMicro<1>(-1);
+ vif1.cmd &= ~0x7f;
+}
+
+static void Vif1CMDSTMask() // STMASK
+{
+ vif1.tag.size = 1;
+}
+
+static void Vif1CMDSTRowCol() // STROW / STCOL
+{
+ vif1.tag.addr = 0;
+ vif1.tag.size = 4;
+}
+
+static void Vif1CMDMPGTransfer() // MPG
+{
+ int vifNum = (u8)(vif1Regs->code >> 16);
+ if(!vifNum) vifNum = 256;
+
+ vif1.tag.addr = (u16)((vif1Regs->code) << 3) & 0x3fff;
+ vif1.tag.size = vifNum * 2;
+}
+
+static void Vif1CMDDirectHL() // DIRECT/HL
+{
+ int vifImm = (u16)vif1Regs->code;
+ if(!vifImm) vif1.tag.size = 65536 << 2;
+ else vif1.tag.size = vifImm << 2;
+}
+
+static void Vif1CMDNull() // invalid opcode
+{
+ // if ME1, then force the vif to interrupt
+
+ if (!(vif1Regs->err.ME1)) //Ignore vifcode and tag mismatch error
+ {
+ Console.WriteLn("UNKNOWN VifCmd: %x\n", vif1.cmd);
+ vif1Regs->stat.ER1 = true;
+ vif1.irq++;
+ }
+ vif1.cmd = 0;
+}
+
+//------------------------------------------------------------------
+// Vif1 Data Transfer / Vif1 CMD Tables
+//------------------------------------------------------------------
+
+int (__fastcall *Vif1TransTLB[128])(u32 *data) =
+{
+ Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x7*/
+ Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0xF*/
+ Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x17*/
+ Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x1F*/
+ Vif1TransSTMask , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x27*/
+ Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x2F*/
+ Vif1TransSTRow , Vif1TransSTCol , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x37*/
+ Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x3F*/
+ Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x47*/
+ Vif1TransNull , Vif1TransNull , Vif1TransMPG , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x4F*/
+ Vif1TransDirectHL, Vif1TransDirectHL, Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x57*/
+ Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x5F*/
+ Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , /*0x67*/
+ Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , /*0x6F*/
+ Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , /*0x77*/
+ Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack /*0x7F*/
+};
+
+void (*Vif1CMDTLB[82])() =
+{
+ Vif1CMDNop , Vif1CMDSTCycl , Vif1CMDOffset , Vif1CMDBase , Vif1CMDITop , Vif1CMDSTMod , Vif1CMDMskPath3, Vif1CMDMark , /*0x7*/
+ Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0xF*/
+ Vif1CMDFlush , Vif1CMDFlush , Vif1CMDNull , Vif1CMDFlush, Vif1CMDMSCALF, Vif1CMDMSCALF, Vif1CMDNull , Vif1CMDMSCNT, /*0x17*/
+ Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x1F*/
+ Vif1CMDSTMask , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x27*/
+ Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x2F*/
+ Vif1CMDSTRowCol, Vif1CMDSTRowCol, Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x37*/
+ Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x3F*/
+ Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x47*/
+ Vif1CMDNull , Vif1CMDNull , Vif1CMDMPGTransfer, Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x4F*/
+ Vif1CMDDirectHL, Vif1CMDDirectHL
+};
diff --git a/pcsx2/Vif1Dma.cpp b/pcsx2/Vif1_Dma.cpp
similarity index 56%
rename from pcsx2/Vif1Dma.cpp
rename to pcsx2/Vif1_Dma.cpp
index bca9ebd154..2b41921431 100644
--- a/pcsx2/Vif1Dma.cpp
+++ b/pcsx2/Vif1_Dma.cpp
@@ -1,1140 +1,684 @@
-/* PCSX2 - PS2 Emulator for PCs
- * Copyright (C) 2002-2009 PCSX2 Dev Team
- *
- * PCSX2 is free software: you can redistribute it and/or modify it under the terms
- * of the GNU Lesser General Public License as published by the Free Software Found-
- * ation, either version 3 of the License, or (at your option) any later version.
- *
- * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with PCSX2.
- * If not, see .
- */
-
-
-#include "PrecompiledHeader.h"
-#include "Common.h"
-#include "VifDma.h"
-#include "GS.h"
-#include "Gif.h"
-#include "VUmicro.h"
-#include "newVif.h"
-
-extern void (*Vif1CMDTLB[82])();
-extern int (__fastcall *Vif1TransTLB[128])(u32 *data);
-
-Path3Modes Path3progress = STOPPED_MODE;
-vifStruct vif1;
-
-static __aligned16 u32 splittransfer[4];
-static u32 splitptr = 0;
-
-__forceinline void vif1FLUSH()
-{
- int _cycles = VU1.cycle;
-
- // fixme: Same as above, is this a "stalling" offense? I think the cycles should
- // be added to cpuRegs.cycle instead of g_vifCycles, but not sure (air)
-
- if (VU0.VI[REG_VPU_STAT].UL & 0x100)
- {
- do
- {
- CpuVU1->ExecuteBlock();
- }
- while (VU0.VI[REG_VPU_STAT].UL & 0x100);
-
- g_vifCycles += (VU1.cycle - _cycles) * BIAS;
- }
-}
-
-
-void vif1Init()
-{
- initNewVif(1);
-}
-
-static __forceinline void vif1UNPACK(u32 *data)
-{
- int vifNum;
-
- if ((vif1Regs->cycle.wl == 0) && (vif1Regs->cycle.wl < vif1Regs->cycle.cl))
- {
- Console.WriteLn("Vif1 CL %d, WL %d", vif1Regs->cycle.cl, vif1Regs->cycle.wl);
- vif1.cmd &= ~0x7f;
- return;
- }
-
- //vif1FLUSH();
-
- vif1.usn = (vif1Regs->code >> 14) & 0x1;
- vifNum = (vif1Regs->code >> 16) & 0xff;
-
- if (vifNum == 0) vifNum = 256;
- vif1Regs->num = vifNum;
-
- if (vif1Regs->cycle.wl <= vif1Regs->cycle.cl)
- {
- vif1.tag.size = ((vifNum * VIFfuncTable[ vif1.cmd & 0xf ].gsize) + 3) >> 2;
- }
- else
- {
- int n = vif1Regs->cycle.cl * (vifNum / vif1Regs->cycle.wl) +
- _limit(vifNum % vif1Regs->cycle.wl, vif1Regs->cycle.cl);
-
- vif1.tag.size = ((n * VIFfuncTable[ vif1.cmd & 0xf ].gsize) + 3) >> 2;
- }
-
- if ((vif1Regs->code >> 15) & 0x1)
- vif1.tag.addr = (vif1Regs->code + vif1Regs->tops) & 0x3ff;
- else
- vif1.tag.addr = vif1Regs->code & 0x3ff;
-
- vif1Regs->offset = 0;
- vif1.cl = 0;
- vif1.tag.addr <<= 4;
- vif1.tag.cmd = vif1.cmd;
-
-}
-
-static __forceinline void vif1mpgTransfer(u32 addr, u32 *data, int size)
-{
- /* Console.WriteLn("vif1mpgTransfer addr=%x; size=%x", addr, size);
- {
- FILE *f = fopen("vu1.raw", "wb");
- fwrite(data, 1, size*4, f);
- fclose(f);
- }*/
- pxAssume(VU1.Micro > 0);
- if (memcmp(VU1.Micro + addr, data, size << 2))
- {
- CpuVU1->Clear(addr, size << 2); // Clear before writing! :/
- memcpy_fast(VU1.Micro + addr, data, size << 2);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Vif1 Data Transfer Commands
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-static int __fastcall Vif1TransNull(u32 *data) // Shouldnt go here
-{
- Console.WriteLn("VIF1 Shouldn't go here CMD = %x", vif1Regs->code);
- vif1.cmd = 0;
- return 0;
-}
-
-static int __fastcall Vif1TransSTMask(u32 *data) // STMASK
-{
- vif1Regs->mask = data[0];
- VIF_LOG("STMASK == %x", vif1Regs->mask);
-
- vif1.tag.size = 0;
- vif1.cmd = 0;
- return 1;
-}
-
-static int __fastcall Vif1TransSTRow(u32 *data) // STROW
-{
- int ret;
-
- u32* pmem = &vif1Regs->r0 + (vif1.tag.addr << 2);
- u32* pmem2 = g_vifmask.Row1 + vif1.tag.addr;
- pxAssume(vif1.tag.addr < 4);
- ret = min(4 - vif1.tag.addr, vif1.vifpacketsize);
- pxAssume(ret > 0);
-
- switch (ret)
- {
- case 4:
- pmem[12] = data[3];
- pmem2[3] = data[3];
- case 3:
- pmem[8] = data[2];
- pmem2[2] = data[2];
- case 2:
- pmem[4] = data[1];
- pmem2[1] = data[1];
- case 1:
- pmem[0] = data[0];
- pmem2[0] = data[0];
- break;
- jNO_DEFAULT;
- }
-
- vif1.tag.addr += ret;
- vif1.tag.size -= ret;
- if (vif1.tag.size == 0) vif1.cmd = 0;
-
- return ret;
-}
-
-static int __fastcall Vif1TransSTCol(u32 *data)
-{
- int ret;
-
- u32* pmem = &vif1Regs->c0 + (vif1.tag.addr << 2);
- u32* pmem2 = g_vifmask.Col1 + vif1.tag.addr;
- ret = min(4 - vif1.tag.addr, vif1.vifpacketsize);
- switch (ret)
- {
- case 4:
- pmem[12] = data[3];
- pmem2[3] = data[3];
- case 3:
- pmem[8] = data[2];
- pmem2[2] = data[2];
- case 2:
- pmem[4] = data[1];
- pmem2[1] = data[1];
- case 1:
- pmem[0] = data[0];
- pmem2[0] = data[0];
- break;
- jNO_DEFAULT;
- }
- vif1.tag.addr += ret;
- vif1.tag.size -= ret;
- if (vif1.tag.size == 0) vif1.cmd = 0;
- return ret;
-}
-
-static int __fastcall Vif1TransMPG(u32 *data)
-{
- if (vif1.vifpacketsize < vif1.tag.size)
- {
- if((vif1.tag.addr + vif1.vifpacketsize) > 0x4000) DevCon.Warning("Vif1 MPG Split Overflow");
- vif1mpgTransfer(vif1.tag.addr, data, vif1.vifpacketsize);
- vif1.tag.addr += vif1.vifpacketsize << 2;
- vif1.tag.size -= vif1.vifpacketsize;
- return vif1.vifpacketsize;
- }
- else
- {
- int ret;
- if((vif1.tag.addr + vif1.tag.size) > 0x4000) DevCon.Warning("Vif1 MPG Overflow");
- vif1mpgTransfer(vif1.tag.addr, data, vif1.tag.size);
- ret = vif1.tag.size;
- vif1.tag.size = 0;
- vif1.cmd = 0;
- return ret;
- }
-}
-
-// Dummy GIF-TAG Packet to Guarantee Count = 1
-extern __aligned16 u32 nloop0_packet[4];
-
-static int __fastcall Vif1TransDirectHL(u32 *data)
-{
- int ret = 0;
-
- if ((vif1.cmd & 0x7f) == 0x51)
- {
- if (gif->chcr.STR && (!vif1Regs->mskpath3 && (Path3progress == IMAGE_MODE))) //PATH3 is in image mode, so wait for end of transfer
- {
- vif1Regs->stat.VGW = true;
- return 0;
- }
- }
-
- gifRegs->stat.APATH |= GIF_APATH2;
- gifRegs->stat.OPH = true;
-
- if (splitptr > 0) //Leftover data from the last packet, filling the rest and sending to the GS
- {
- if ((splitptr < 4) && (vif1.vifpacketsize >= (4 - splitptr)))
- {
- while (splitptr < 4)
- {
- splittransfer[splitptr++] = (u32)data++;
- ret++;
- vif1.tag.size--;
- }
- }
-
- Registers::Freeze();
- // copy 16 bytes the fast way:
- const u64* src = (u64*)splittransfer[0];
- GetMTGS().PrepDataPacket(GIF_PATH_2, nloop0_packet, 1);
- u64* dst = (u64*)GetMTGS().GetDataPacketPtr();
- dst[0] = src[0];
- dst[1] = src[1];
-
- GetMTGS().SendDataPacket();
- Registers::Thaw();
-
- if (vif1.tag.size == 0) vif1.cmd = 0;
- splitptr = 0;
- return ret;
- }
-
- if (vif1.vifpacketsize < vif1.tag.size)
- {
- if (vif1.vifpacketsize < 4 && splitptr != 4) //Not a full QW left in the buffer, saving left over data
- {
- ret = vif1.vifpacketsize;
- while (ret > 0)
- {
- splittransfer[splitptr++] = (u32)data++;
- vif1.tag.size--;
- ret--;
- }
- return vif1.vifpacketsize;
- }
- vif1.tag.size -= vif1.vifpacketsize;
- ret = vif1.vifpacketsize;
- }
- else
- {
- gifRegs->stat.clear_flags(GIF_STAT_APATH2 | GIF_STAT_OPH);
- ret = vif1.tag.size;
- vif1.tag.size = 0;
- vif1.cmd = 0;
- }
-
- //TODO: ret is guaranteed to be qword aligned ?
-
- Registers::Freeze();
-
- // Round ret up, just in case it's not 128bit aligned.
- const uint count = GetMTGS().PrepDataPacket(GIF_PATH_2, data, (ret + 3) >> 2);
- memcpy_fast(GetMTGS().GetDataPacketPtr(), data, count << 4);
- GetMTGS().SendDataPacket();
-
- Registers::Thaw();
-
- return ret;
-}
-static int __fastcall Vif1TransUnpack(u32 *data)
-{
- return nVifUnpack(1, (u8*)data);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Vif1 CMD Base Commands
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-static void Vif1CMDNop() // NOP
-{
- vif1.cmd &= ~0x7f;
-}
-
-static void Vif1CMDSTCycl() // STCYCL
-{
- vif1Regs->cycle.cl = (u8)vif1Regs->code;
- vif1Regs->cycle.wl = (u8)(vif1Regs->code >> 8);
- vif1.cmd &= ~0x7f;
-}
-
-static void Vif1CMDOffset() // OFFSET
-{
- vif1Regs->ofst = vif1Regs->code & 0x3ff;
- vif1Regs->stat.DBF = false;
- vif1Regs->tops = vif1Regs->base;
- vif1.cmd &= ~0x7f;
-}
-
-static void Vif1CMDBase() // BASE
-{
- vif1Regs->base = vif1Regs->code & 0x3ff;
- vif1.cmd &= ~0x7f;
-}
-
-static void Vif1CMDITop() // ITOP
-{
- vif1Regs->itops = vif1Regs->code & 0x3ff;
- vif1.cmd &= ~0x7f;
-}
-
-static void Vif1CMDSTMod() // STMOD
-{
- vif1Regs->mode = vif1Regs->code & 0x3;
- vif1.cmd &= ~0x7f;
-}
-
-u8 schedulepath3msk = 0;
-
-void Vif1MskPath3() // MSKPATH3
-{
- vif1Regs->mskpath3 = schedulepath3msk & 0x1;
- //Console.WriteLn("VIF MSKPATH3 %x", vif1Regs->mskpath3);
-
- if (vif1Regs->mskpath3)
- {
- gifRegs->stat.M3P = true;
- }
- else
- {
- //Let the Gif know it can transfer again (making sure any vif stall isnt unset prematurely)
- Path3progress = TRANSFER_MODE;
- gifRegs->stat.IMT = false;
- CPU_INT(2, 4);
- }
-
- schedulepath3msk = 0;
-}
-static void Vif1CMDMskPath3() // MSKPATH3
-{
- if (vif1ch->chcr.STR)
- {
- schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1);
- vif1.vifstalled = true;
- }
- else
- {
- schedulepath3msk = (vif1Regs->code >> 15) & 0x1;
- Vif1MskPath3();
- }
- vif1.cmd &= ~0x7f;
-}
-
-
-static void Vif1CMDMark() // MARK
-{
- vif1Regs->mark = (u16)vif1Regs->code;
- vif1Regs->stat.MRK = true;
- vif1.cmd &= ~0x7f;
-}
-
-static void Vif1CMDFlush() // FLUSH/E/A
-{
- vif1FLUSH();
-
- if ((vif1.cmd & 0x7f) == 0x13)
- {
- // Gif is already transferring so wait for it.
- if (((Path3progress != STOPPED_MODE) || !vif1Regs->mskpath3) && gif->chcr.STR)
- {
- vif1Regs->stat.VGW = true;
- CPU_INT(2, 4);
- }
- }
-
- vif1.cmd &= ~0x7f;
-}
-
-static void Vif1CMDMSCALF() //MSCAL/F
-{
- vif1FLUSH();
- vuExecMicro<1>((u16)(vif1Regs->code) << 3);
- vif1.cmd &= ~0x7f;
-}
-
-static void Vif1CMDMSCNT() // MSCNT
-{
- vuExecMicro<1>(-1);
- vif1.cmd &= ~0x7f;
-}
-
-static void Vif1CMDSTMask() // STMASK
-{
- vif1.tag.size = 1;
-}
-
-static void Vif1CMDSTRowCol() // STROW / STCOL
-{
- vif1.tag.addr = 0;
- vif1.tag.size = 4;
-}
-
-static void Vif1CMDMPGTransfer() // MPG
-{
- int vifNum;
- //vif1FLUSH();
- vifNum = (u8)(vif1Regs->code >> 16);
-
- if (vifNum == 0) vifNum = 256;
-
- vif1.tag.addr = (u16)((vif1Regs->code) << 3) & 0x3fff;
- vif1.tag.size = vifNum * 2;
-}
-
-static void Vif1CMDDirectHL() // DIRECT/HL
-{
- int vifImm;
- vifImm = (u16)vif1Regs->code;
-
- if (vifImm == 0)
- vif1.tag.size = 65536 << 2;
- else
- vif1.tag.size = vifImm << 2;
-}
-
-static void Vif1CMDNull() // invalid opcode
-{
- // if ME1, then force the vif to interrupt
-
- if (!(vif1Regs->err.ME1)) //Ignore vifcode and tag mismatch error
- {
- Console.WriteLn("UNKNOWN VifCmd: %x\n", vif1.cmd);
- vif1Regs->stat.ER1 = true;
- vif1.irq++;
- }
- vif1.cmd = 0;
-}
-
-// Vif1 Data Transfer Table
-
-int (__fastcall *Vif1TransTLB[128])(u32 *data) =
-{
- Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x7*/
- Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0xF*/
- Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x17*/
- Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x1F*/
- Vif1TransSTMask , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x27*/
- Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x2F*/
- Vif1TransSTRow , Vif1TransSTCol , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x37*/
- Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x3F*/
- Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x47*/
- Vif1TransNull , Vif1TransNull , Vif1TransMPG , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x4F*/
- Vif1TransDirectHL, Vif1TransDirectHL, Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x57*/
- Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x5F*/
- Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , /*0x67*/
- Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , /*0x6F*/
- Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , /*0x77*/
- Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack /*0x7F*/
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Vif1 CMD Table
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void (*Vif1CMDTLB[82])() =
-{
- Vif1CMDNop , Vif1CMDSTCycl , Vif1CMDOffset , Vif1CMDBase , Vif1CMDITop , Vif1CMDSTMod , Vif1CMDMskPath3, Vif1CMDMark , /*0x7*/
- Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0xF*/
- Vif1CMDFlush , Vif1CMDFlush , Vif1CMDNull , Vif1CMDFlush, Vif1CMDMSCALF, Vif1CMDMSCALF, Vif1CMDNull , Vif1CMDMSCNT, /*0x17*/
- Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x1F*/
- Vif1CMDSTMask , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x27*/
- Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x2F*/
- Vif1CMDSTRowCol, Vif1CMDSTRowCol, Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x37*/
- Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x3F*/
- Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x47*/
- Vif1CMDNull , Vif1CMDNull , Vif1CMDMPGTransfer, Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x4F*/
- Vif1CMDDirectHL, Vif1CMDDirectHL
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-bool VIF1transfer(u32 *data, int size, bool istag)
-{
- int ret;
- int transferred = vif1.vifstalled ? vif1.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman)
-
- VIF_LOG("VIF1transfer: size %x (vif1.cmd %x)", size, vif1.cmd);
-
- vif1.irqoffset = 0;
- vif1.vifstalled = false;
- vif1.stallontag = false;
- vif1.vifpacketsize = size;
-
- while (vif1.vifpacketsize > 0)
- {
- if(vif1Regs->stat.VGW) break;
-
- if (vif1.cmd)
- {
- vif1Regs->stat.VPS = VPS_TRANSFERRING; //Decompression has started
-
- ret = Vif1TransTLB[vif1.cmd](data);
- data += ret;
- vif1.vifpacketsize -= ret;
-
- //We are once again waiting for a new vifcode as the command has cleared
- if (vif1.cmd == 0) vif1Regs->stat.VPS = VPS_IDLE;
- continue;
- }
-
- if (vif1.tag.size != 0) DevCon.Error("no vif1 cmd but tag size is left last cmd read %x", vif1Regs->code);
-
- if (vif1.irq) break;
-
- vif1.cmd = (data[0] >> 24);
- vif1Regs->code = data[0];
- vif1Regs->stat.VPS |= VPS_DECODING;
-
- if ((vif1.cmd & 0x60) == 0x60)
- {
- vif1UNPACK(data);
- }
- else
- {
- VIF_LOG("VIFtransfer: cmd %x, num %x, imm %x, size %x", vif1.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, vif1.vifpacketsize);
-
- if ((vif1.cmd & 0x7f) > 0x51)
- {
- if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
- {
- Console.WriteLn("UNKNOWN VifCmd: %x", vif1.cmd);
- vif1Regs->stat.ER1 = true;
- vif1.irq++;
- }
- vif1.cmd = 0;
- }
- else Vif1CMDTLB[(vif1.cmd & 0x7f)]();
- }
-
- ++data;
- --vif1.vifpacketsize;
-
- if ((vif1.cmd & 0x80))
- {
- vif1.cmd &= 0x7f;
-
- if (!(vif1Regs->err.MII)) //i bit on vifcode and not masked by VIF1_ERR
- {
- VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif1.cmd, psHu32(INTC_MASK));
-
- ++vif1.irq;
-
- if (istag && vif1.tag.size <= vif1.vifpacketsize) vif1.stallontag = true;
-
- if (vif1.tag.size == 0) break;
- }
- }
-
- if(!vif1.cmd) vif1Regs->stat.VPS = VPS_IDLE;
-
- if((vif1Regs->stat.VGW) || vif1.vifstalled == true) break;
- } // End of Transfer loop
-
- transferred += size - vif1.vifpacketsize;
- g_vifCycles += (transferred >> 2) * BIAS; /* guessing */
- vif1.irqoffset = transferred % 4; // cannot lose the offset
-
- if (vif1.irq && vif1.cmd == 0)
- {
- vif1.vifstalled = true;
-
- if (((vif1Regs->code >> 24) & 0x7f) != 0x7) vif1Regs->stat.VIS = true; // Note: commenting this out fixes WALL-E
-
- if (vif1ch->qwc == 0 && (vif1.irqoffset == 0 || istag == 1)) vif1.inprogress &= ~0x1;
-
- // spiderman doesn't break on qw boundaries
- if (istag) return false;
-
- transferred = transferred >> 2;
- vif1ch->madr += (transferred << 4);
- vif1ch->qwc -= transferred;
-
- if ((vif1ch->qwc == 0) && (vif1.irqoffset == 0)) vif1.inprogress = 0;
- //Console.WriteLn("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR));
- return false;
- }
-
- vif1Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
- if (vif1.cmd) vif1Regs->stat.VPS = VPS_WAITING; //Otherwise we wait for the data
-
- if (!istag)
- {
- transferred = transferred >> 2;
- vif1ch->madr += (transferred << 4);
- vif1ch->qwc -= transferred;
- }
-
- if (vif1Regs->stat.VGW) vif1.vifstalled = true;
-
- if (vif1ch->qwc == 0 && (vif1.irqoffset == 0 || istag == 1)) vif1.inprogress &= ~0x1;
-
- return (!(vif1.vifstalled));
-}
-
-void vif1TransferFromMemory()
-{
- int size;
- u64* pMem = (u64*)dmaGetAddr(vif1ch->madr);
-
- // VIF from gsMemory
- if (pMem == NULL) //Is vif0ptag empty?
- {
- Console.WriteLn("Vif1 Tag BUSERR");
- dmacRegs->stat.BEIS = true; //Bus Error
- vif1Regs->stat.FQC = 0;
-
- vif1ch->qwc = 0;
- vif1.done = true;
- CPU_INT(1, 0);
- return; //An error has occurred.
- }
-
- // MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading
- // stuff from the GS. The *only* way to handle this case safely is to flush the GS
- // completely and execute the transfer there-after.
-
- XMMRegisters::Freeze();
-
- if (GSreadFIFO2 == NULL)
- {
- for (size = vif1ch->qwc; size > 0; --size)
- {
- if (size > 1)
- {
- GetMTGS().WaitGS();
- GSreadFIFO(&psHu64(VIF1_FIFO));
- }
- pMem[0] = psHu64(VIF1_FIFO);
- pMem[1] = psHu64(VIF1_FIFO + 8);
- pMem += 2;
- }
- }
- else
- {
- GetMTGS().WaitGS();
- GSreadFIFO2(pMem, vif1ch->qwc);
-
- // set incase read
- psHu64(VIF1_FIFO) = pMem[2*vif1ch->qwc-2];
- psHu64(VIF1_FIFO + 8) = pMem[2*vif1ch->qwc-1];
- }
-
- XMMRegisters::Thaw();
-
- g_vifCycles += vif1ch->qwc * 2;
- vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
- vif1ch->qwc = 0;
-}
-
-bool _VIF1chain()
-{
- u32 *pMem;
-
- if (vif1ch->qwc == 0)
- {
- vif1.inprogress = 0;
- return true;
- }
-
- if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE)
- {
- vif1TransferFromMemory();
- vif1.inprogress = 0;
- return true;
- }
-
- pMem = (u32*)dmaGetAddr(vif1ch->madr);
- if (pMem == NULL)
- {
- vif1.cmd = 0;
- vif1.tag.size = 0;
- vif1ch->qwc = 0;
- return true;
- }
-
- 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);
- else
- return VIF1transfer(pMem, vif1ch->qwc * 4, false);
-}
-
-bool _chainVIF1()
-{
- return vif1.done; // Return Done
-}
-
-__forceinline void vif1SetupTransfer()
-{
- tDMA_TAG *ptag;
-
- switch (vif1.dmamode)
- {
- case VIF_NORMAL_TO_MEM_MODE:
- case VIF_NORMAL_FROM_MEM_MODE:
- vif1.inprogress = 1;
- vif1.done = true;
- g_vifCycles = 2;
- break;
-
- case VIF_CHAIN_MODE:
- ptag = dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR
-
- if (!(vif1ch->transfer("Vif1 Tag", ptag))) return;
-
- vif1ch->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("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n",
- 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;
- }
- }
-
- vif1.inprogress = 1;
-
- if (vif1ch->chcr.TTE)
- {
- bool ret;
-
- if (vif1.vifstalled)
- ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, true); //Transfer Tag on stall
- else
- ret = VIF1transfer((u32*)ptag + 2, 2, true); //Transfer Tag
-
- if ((ret == false) && vif1.irqoffset < 2)
- {
- vif1.inprogress = 0; //Better clear this so it has to do it again (Jak 1)
- return; //There has been an error or an interrupt
- }
- }
-
- vif1.irqoffset = 0;
- vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID);
-
- //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;
- }
-}
-
-__forceinline void vif1Interrupt()
-{
- VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle);
-
- g_vifCycles = 0;
-
- if (schedulepath3msk) Vif1MskPath3();
-
- if ((vif1Regs->stat.VGW))
- {
- if (gif->chcr.STR)
- {
- CPU_INT(1, gif->qwc * BIAS);
- return;
- }
- else
- {
- vif1Regs->stat.VGW = false;
- }
- }
-
- if (!(vif1ch->chcr.STR)) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch->chcr._u32);
-
- if (vif1.irq && vif1.tag.size == 0)
- {
- vif1Regs->stat.INT = true;
- hwIntcIrq(VIF1intc);
- --vif1.irq;
- if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
- {
- vif1Regs->stat.FQC = 0;
-
- // One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
- vif1ch->chcr.STR = false;
- return;
- }
- else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0))
- {
- if (vif1.stallontag)
- vif1SetupTransfer();
- else
- _VIF1chain();//CPU_INT(13, vif1ch->qwc * BIAS);
- }
- }
-
- if (vif1.inprogress & 0x1)
- {
- _VIF1chain();
- CPU_INT(1, /*g_vifCycles*/ VifCycleVoodoo);
- return;
- }
-
- if (!vif1.done)
- {
-
- if (!(dmacRegs->ctrl.DMAE))
- {
- Console.WriteLn("vif1 dma masked");
- return;
- }
-
- if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
-
- CPU_INT(1, /*g_vifCycles*/ VifCycleVoodoo);
- return;
- }
-
- if (vif1.vifstalled && vif1.irq)
- {
- CPU_INT(1, 0);
- return; //Dont want to end if vif is stalled.
- }
-#ifdef PCSX2_DEVBUILD
- if (vif1ch->qwc > 0) Console.WriteLn("VIF1 Ending with %x QWC left");
- if (vif1.cmd != 0) Console.WriteLn("vif1.cmd still set %x tag size %x", vif1.cmd, vif1.tag.size);
-#endif
-
- vif1Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
- vif1ch->chcr.STR = false;
- g_vifCycles = 0;
- hwDmacIrq(DMAC_VIF1);
-
- //Im not totally sure why Path3 Masking makes it want to see stuff in the fifo
- //Games effected by setting, Fatal Frame, KH2, Shox, Crash N Burn, GT3/4 possibly
- //Im guessing due to the full gs fifo before the reverse? (Refraction)
- //Note also this is only the condition for reverse fifo mode, normal direction clears it as normal
- if (!vif1Regs->mskpath3 || vif1ch->chcr.DIR) vif1Regs->stat.FQC = 0;
-}
-
-void dmaVIF1()
-{
- VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n"
- " tadr = %lx, asr0 = %lx, asr1 = %lx",
- vif1ch->chcr._u32, vif1ch->madr, vif1ch->qwc,
- vif1ch->tadr, vif1ch->asr0, vif1ch->asr1);
-
- g_vifCycles = 0;
- vif1.inprogress = 0;
-
- if (dmacRegs->ctrl.MFD == MFD_VIF1) // VIF MFIFO
- {
- //Console.WriteLn("VIFMFIFO\n");
- // Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw.
- if (vif1ch->chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch->chcr._u32);
- vifMFIFOInterrupt();
- return;
- }
-
-#ifdef PCSX2_DEVBUILD
- if (dmacRegs->ctrl.STD == STD_VIF1)
- {
- //DevCon.WriteLn("VIF Stall Control Source = %x, Drain = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3);
- }
-#endif
-
- if ((vif1ch->chcr.MOD == NORMAL_MODE) || vif1ch->qwc > 0) // Normal Mode
- {
-
- if (dmacRegs->ctrl.STD == STD_VIF1)
- Console.WriteLn("DMA Stall Control on VIF1 normal");
-
- if (vif1ch->chcr.DIR) // to Memory
- vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
- else
- vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
- }
- else
- {
- vif1.dmamode = VIF_CHAIN_MODE;
- }
-
- if (vif1.dmamode != VIF_NORMAL_FROM_MEM_MODE)
- vif1Regs->stat.FQC = 0x10;
- else
- vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
-
- // Chain Mode
- vif1.done = false;
- vif1Interrupt();
-}
-
-void vif1Write32(u32 mem, u32 value)
-{
- switch (mem)
- {
- case VIF1_MARK:
- VIF_LOG("VIF1_MARK write32 0x%8.8x", value);
-
- /* Clear mark flag in VIF1_STAT and set mark with 'value' */
- vif1Regs->stat.MRK = false;
- vif1Regs->mark = value;
- break;
-
- case VIF1_FBRST: // FBRST
- VIF_LOG("VIF1_FBRST write32 0x%8.8x", value);
-
- if (FBRST(value).RST) // Reset Vif.
- {
- memzero(vif1);
- cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
- vif1ch->qwc = 0; //?
- psHu64(VIF1_FIFO) = 0;
- psHu64(VIF1_FIFO + 8) = 0;
- vif1.done = true;
-
- if(vif1Regs->mskpath3)
- {
- vif1Regs->mskpath3 = 0;
- gifRegs->stat.IMT = false;
- if (gif->chcr.STR) CPU_INT(2, 4);
- }
-
- vif1Regs->err.reset();
- vif1.inprogress = 0;
- 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);
- }
-
- if (FBRST(value).FBK) // Forcebreak Vif.
- {
- /* I guess we should stop the VIF dma here, but not 100% sure (linuz) */
- vif1Regs->stat.VFS = true;
- vif1Regs->stat.VPS = VPS_IDLE;
- cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
- vif1.vifstalled = true;
- Console.WriteLn("vif1 force break");
- }
-
- if (FBRST(value).STP) // Stop Vif.
- {
- // Not completely sure about this, can't remember what game used this, but 'draining' the VIF helped it, instead of
- // just stoppin the VIF (linuz).
- vif1Regs->stat.VSS = true;
- vif1Regs->stat.VPS = VPS_IDLE;
- cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
- vif1.vifstalled = true;
- }
-
- if (FBRST(value).STC) // Cancel Vif Stall.
- {
- bool cancel = false;
-
- /* Cancel stall, first check if there is a stall to cancel, and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */
- if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
- {
- cancel = true;
- }
-
- vif1Regs->stat.clear_flags(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS |
- VIF1_STAT_INT | VIF1_STAT_ER0 | VIF1_STAT_ER1);
-
- if (cancel)
- {
- if (vif1.vifstalled)
- {
- g_vifCycles = 0;
- // loop necessary for spiderman
- switch(dmacRegs->ctrl.MFD)
- {
- case MFD_VIF1:
- //Console.WriteLn("MFIFO Stall");
- CPU_INT(10, vif1ch->qwc * BIAS);
- break;
-
- case NO_MFD:
- case MFD_RESERVED:
- case MFD_GIF: // Wonder if this should be with VIF?
- // Gets the timing right - Flatout
- CPU_INT(1, vif1ch->qwc * BIAS);
- break;
- }
-
- vif1ch->chcr.STR = true;
- }
- }
- }
- break;
-
- case VIF1_ERR: // ERR
- VIF_LOG("VIF1_ERR write32 0x%8.8x", value);
-
- /* Set VIF1_ERR with 'value' */
- vif1Regs->err.write(value);
- break;
-
- case VIF1_STAT: // STAT
- VIF_LOG("VIF1_STAT write32 0x%8.8x", value);
-
-#ifdef PCSX2_DEVBUILD
- /* Only FDR bit is writable, so mask the rest */
- if ((vif1Regs->stat.FDR) ^ ((tVIF_STAT&)value).FDR)
- {
- // different so can't be stalled
- if (vif1Regs->stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
- {
- DevCon.WriteLn("changing dir when vif1 fifo stalled");
- }
- }
-#endif
-
- vif1Regs->stat.FDR = VIF_STAT(value).FDR;
-
- if (vif1Regs->stat.FDR) // Vif transferring to memory.
- {
- // Hack but it checks this is true before transfer? (fatal frame)
- vif1Regs->stat.FQC = 0x1;
- }
- else // Memory transferring to Vif.
- {
- vif1ch->qwc = 0;
- vif1.vifstalled = false;
- vif1.done = true;
- vif1Regs->stat.FQC = 0;
- }
- break;
-
- case VIF1_MODE:
- vif1Regs->mode = value;
- break;
-
- case VIF1_R0:
- case VIF1_R1:
- case VIF1_R2:
- case VIF1_R3:
- pxAssume((mem&0xf) == 0);
- g_vifmask.Row1[(mem>>4) & 3] = value;
- break;
-
- case VIF1_C0:
- case VIF1_C1:
- case VIF1_C2:
- case VIF1_C3:
- pxAssume((mem&0xf) == 0);
- g_vifmask.Col1[(mem>>4) & 3] = value;
- break;
-
- default:
- Console.WriteLn("Unknown Vif1 write to %x", mem);
- psHu32(mem) = value;
- break;
- }
-
- /* Other registers are read-only so do nothing for them */
-}
-
-void vif1Reset()
-{
- /* Reset the whole VIF, meaning the internal pcsx2 vars, and all the registers */
- memzero(vif1);
- memzero(*vif1Regs);
-
- psHu64(VIF1_FIFO) = 0;
- psHu64(VIF1_FIFO + 8) = 0;
-
- vif1Regs->stat.VPS = VPS_IDLE;
- vif1Regs->stat.FQC = 0; // FQC=0
-
- vif1.done = true;
- cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
-
- resetNewVif(1);
-}
-
-void SaveStateBase::vif1Freeze()
-{
- static u32 g_vif1Masks[64]; // Dummy Var for saved state compatibility
- static u32 g_vif1HasMask3[4]; // Dummy Var for saved state compatibility
- Freeze(vif1);
-
- Freeze(g_vif1HasMask3); // Not Used Anymore
- Freeze(g_vif1Masks); // Not Used Anymore
-}
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+#include "Common.h"
+#include "Vif_Dma.h"
+#include "GS.h"
+#include "Gif.h"
+#include "VUmicro.h"
+#include "newVif.h"
+
+extern void (*Vif1CMDTLB[82])();
+extern int (__fastcall *Vif1TransTLB[128])(u32 *data);
+
+Path3Modes Path3progress = STOPPED_MODE;
+vifStruct vif1;
+
+__forceinline void vif1FLUSH()
+{
+ int _cycles = VU1.cycle;
+
+ // fixme: Same as above, is this a "stalling" offense? I think the cycles should
+ // be added to cpuRegs.cycle instead of g_vifCycles, but not sure (air)
+
+ if (VU0.VI[REG_VPU_STAT].UL & 0x100)
+ {
+ do
+ {
+ CpuVU1->ExecuteBlock();
+ }
+ while (VU0.VI[REG_VPU_STAT].UL & 0x100);
+
+ g_vifCycles += (VU1.cycle - _cycles) * BIAS;
+ }
+}
+
+static __forceinline void vif1UNPACK(u32 *data)
+{
+ int vifNum;
+
+ if ((vif1Regs->cycle.wl == 0) && (vif1Regs->cycle.wl < vif1Regs->cycle.cl))
+ {
+ Console.WriteLn("Vif1 CL %d, WL %d", vif1Regs->cycle.cl, vif1Regs->cycle.wl);
+ vif1.cmd &= ~0x7f;
+ return;
+ }
+
+ //vif1FLUSH();
+
+ vif1.usn = (vif1Regs->code >> 14) & 0x1;
+ vifNum = (vif1Regs->code >> 16) & 0xff;
+
+ if (vifNum == 0) vifNum = 256;
+ vif1Regs->num = vifNum;
+
+ if (vif1Regs->cycle.wl <= vif1Regs->cycle.cl)
+ {
+ vif1.tag.size = ((vifNum * VIFfuncTable[ vif1.cmd & 0xf ].gsize) + 3) >> 2;
+ }
+ else
+ {
+ int n = vif1Regs->cycle.cl * (vifNum / vif1Regs->cycle.wl) +
+ _limit(vifNum % vif1Regs->cycle.wl, vif1Regs->cycle.cl);
+
+ vif1.tag.size = ((n * VIFfuncTable[ vif1.cmd & 0xf ].gsize) + 3) >> 2;
+ }
+
+ if ((vif1Regs->code >> 15) & 0x1)
+ vif1.tag.addr = (vif1Regs->code + vif1Regs->tops) & 0x3ff;
+ else
+ vif1.tag.addr = vif1Regs->code & 0x3ff;
+
+ vif1Regs->offset = 0;
+ vif1.cl = 0;
+ vif1.tag.addr <<= 4;
+ vif1.tag.cmd = vif1.cmd;
+
+}
+
+bool VIF1transfer(u32 *data, int size, bool istag)
+{
+ int ret;
+ int transferred = vif1.vifstalled ? vif1.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman)
+
+ VIF_LOG("VIF1transfer: size %x (vif1.cmd %x)", size, vif1.cmd);
+
+ vif1.irqoffset = 0;
+ vif1.vifstalled = false;
+ vif1.stallontag = false;
+ vif1.vifpacketsize = size;
+
+ while (vif1.vifpacketsize > 0)
+ {
+ if(vif1Regs->stat.VGW) break;
+
+ if (vif1.cmd)
+ {
+ vif1Regs->stat.VPS = VPS_TRANSFERRING; //Decompression has started
+
+ ret = Vif1TransTLB[vif1.cmd](data);
+ data += ret;
+ vif1.vifpacketsize -= ret;
+
+ //We are once again waiting for a new vifcode as the command has cleared
+ if (vif1.cmd == 0) vif1Regs->stat.VPS = VPS_IDLE;
+ continue;
+ }
+
+ if (vif1.tag.size != 0) DevCon.Error("no vif1 cmd but tag size is left last cmd read %x", vif1Regs->code);
+
+ if (vif1.irq) break;
+
+ vif1.cmd = (data[0] >> 24);
+ vif1Regs->code = data[0];
+ vif1Regs->stat.VPS |= VPS_DECODING;
+
+ if ((vif1.cmd & 0x60) == 0x60)
+ {
+ vif1UNPACK(data);
+ }
+ else
+ {
+ VIF_LOG("VIFtransfer: cmd %x, num %x, imm %x, size %x", vif1.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, vif1.vifpacketsize);
+
+ if ((vif1.cmd & 0x7f) > 0x51)
+ {
+ if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
+ {
+ Console.WriteLn("UNKNOWN VifCmd: %x", vif1.cmd);
+ vif1Regs->stat.ER1 = true;
+ vif1.irq++;
+ }
+ vif1.cmd = 0;
+ }
+ else Vif1CMDTLB[(vif1.cmd & 0x7f)]();
+ }
+
+ ++data;
+ --vif1.vifpacketsize;
+
+ if ((vif1.cmd & 0x80))
+ {
+ vif1.cmd &= 0x7f;
+
+ if (!(vif1Regs->err.MII)) //i bit on vifcode and not masked by VIF1_ERR
+ {
+ VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif1.cmd, psHu32(INTC_MASK));
+
+ ++vif1.irq;
+
+ if (istag && vif1.tag.size <= vif1.vifpacketsize) vif1.stallontag = true;
+
+ if (vif1.tag.size == 0) break;
+ }
+ }
+
+ if(!vif1.cmd) vif1Regs->stat.VPS = VPS_IDLE;
+
+ if((vif1Regs->stat.VGW) || vif1.vifstalled == true) break;
+ } // End of Transfer loop
+
+ transferred += size - vif1.vifpacketsize;
+ g_vifCycles += (transferred >> 2) * BIAS; /* guessing */
+ vif1.irqoffset = transferred % 4; // cannot lose the offset
+
+ if (vif1.irq && vif1.cmd == 0)
+ {
+ vif1.vifstalled = true;
+
+ if (((vif1Regs->code >> 24) & 0x7f) != 0x7) vif1Regs->stat.VIS = true; // Note: commenting this out fixes WALL-E
+
+ if (vif1ch->qwc == 0 && (vif1.irqoffset == 0 || istag == 1)) vif1.inprogress &= ~0x1;
+
+ // spiderman doesn't break on qw boundaries
+ if (istag) return false;
+
+ transferred = transferred >> 2;
+ vif1ch->madr += (transferred << 4);
+ vif1ch->qwc -= transferred;
+
+ if ((vif1ch->qwc == 0) && (vif1.irqoffset == 0)) vif1.inprogress = 0;
+ //Console.WriteLn("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR));
+ return false;
+ }
+
+ vif1Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
+ if (vif1.cmd) vif1Regs->stat.VPS = VPS_WAITING; //Otherwise we wait for the data
+
+ if (!istag)
+ {
+ transferred = transferred >> 2;
+ vif1ch->madr += (transferred << 4);
+ vif1ch->qwc -= transferred;
+ }
+
+ if (vif1Regs->stat.VGW) vif1.vifstalled = true;
+
+ if (vif1ch->qwc == 0 && (vif1.irqoffset == 0 || istag == 1)) vif1.inprogress &= ~0x1;
+
+ return (!(vif1.vifstalled));
+}
+
+void vif1TransferFromMemory()
+{
+ int size;
+ u64* pMem = (u64*)dmaGetAddr(vif1ch->madr);
+
+ // VIF from gsMemory
+ if (pMem == NULL) //Is vif0ptag empty?
+ {
+ Console.WriteLn("Vif1 Tag BUSERR");
+ dmacRegs->stat.BEIS = true; //Bus Error
+ vif1Regs->stat.FQC = 0;
+
+ vif1ch->qwc = 0;
+ vif1.done = true;
+ CPU_INT(1, 0);
+ return; //An error has occurred.
+ }
+
+ // MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading
+ // stuff from the GS. The *only* way to handle this case safely is to flush the GS
+ // completely and execute the transfer there-after.
+
+ XMMRegisters::Freeze();
+
+ if (GSreadFIFO2 == NULL)
+ {
+ for (size = vif1ch->qwc; size > 0; --size)
+ {
+ if (size > 1)
+ {
+ GetMTGS().WaitGS();
+ GSreadFIFO(&psHu64(VIF1_FIFO));
+ }
+ pMem[0] = psHu64(VIF1_FIFO);
+ pMem[1] = psHu64(VIF1_FIFO + 8);
+ pMem += 2;
+ }
+ }
+ else
+ {
+ GetMTGS().WaitGS();
+ GSreadFIFO2(pMem, vif1ch->qwc);
+
+ // set incase read
+ psHu64(VIF1_FIFO) = pMem[2*vif1ch->qwc-2];
+ psHu64(VIF1_FIFO + 8) = pMem[2*vif1ch->qwc-1];
+ }
+
+ XMMRegisters::Thaw();
+
+ g_vifCycles += vif1ch->qwc * 2;
+ vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
+ vif1ch->qwc = 0;
+}
+
+bool _VIF1chain()
+{
+ u32 *pMem;
+
+ if (vif1ch->qwc == 0)
+ {
+ vif1.inprogress = 0;
+ return true;
+ }
+
+ if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE)
+ {
+ vif1TransferFromMemory();
+ vif1.inprogress = 0;
+ return true;
+ }
+
+ pMem = (u32*)dmaGetAddr(vif1ch->madr);
+ if (pMem == NULL)
+ {
+ vif1.cmd = 0;
+ vif1.tag.size = 0;
+ vif1ch->qwc = 0;
+ return true;
+ }
+
+ 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);
+ else
+ return VIF1transfer(pMem, vif1ch->qwc * 4, false);
+}
+
+bool _chainVIF1()
+{
+ return vif1.done; // Return Done
+}
+
+__forceinline void vif1SetupTransfer()
+{
+ tDMA_TAG *ptag;
+
+ switch (vif1.dmamode)
+ {
+ case VIF_NORMAL_TO_MEM_MODE:
+ case VIF_NORMAL_FROM_MEM_MODE:
+ vif1.inprogress = 1;
+ vif1.done = true;
+ g_vifCycles = 2;
+ break;
+
+ case VIF_CHAIN_MODE:
+ ptag = dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR
+
+ if (!(vif1ch->transfer("Vif1 Tag", ptag))) return;
+
+ vif1ch->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("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n",
+ 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;
+ }
+ }
+
+ vif1.inprogress = 1;
+
+ if (vif1ch->chcr.TTE)
+ {
+ bool ret;
+
+ if (vif1.vifstalled)
+ ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, true); //Transfer Tag on stall
+ else
+ ret = VIF1transfer((u32*)ptag + 2, 2, true); //Transfer Tag
+
+ if ((ret == false) && vif1.irqoffset < 2)
+ {
+ vif1.inprogress = 0; //Better clear this so it has to do it again (Jak 1)
+ return; //There has been an error or an interrupt
+ }
+ }
+
+ vif1.irqoffset = 0;
+ vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID);
+
+ //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;
+ }
+}
+
+__forceinline void vif1Interrupt()
+{
+ VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle);
+
+ g_vifCycles = 0;
+
+ if (schedulepath3msk) Vif1MskPath3();
+
+ if ((vif1Regs->stat.VGW))
+ {
+ if (gif->chcr.STR)
+ {
+ CPU_INT(1, gif->qwc * BIAS);
+ return;
+ }
+ else
+ {
+ vif1Regs->stat.VGW = false;
+ }
+ }
+
+ if (!(vif1ch->chcr.STR)) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch->chcr._u32);
+
+ if (vif1.irq && vif1.tag.size == 0)
+ {
+ vif1Regs->stat.INT = true;
+ hwIntcIrq(VIF1intc);
+ --vif1.irq;
+ if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
+ {
+ vif1Regs->stat.FQC = 0;
+
+ // One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
+ vif1ch->chcr.STR = false;
+ return;
+ }
+ else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0))
+ {
+ if (vif1.stallontag)
+ vif1SetupTransfer();
+ else
+ _VIF1chain();//CPU_INT(13, vif1ch->qwc * BIAS);
+ }
+ }
+
+ if (vif1.inprogress & 0x1)
+ {
+ _VIF1chain();
+ CPU_INT(1, /*g_vifCycles*/ VifCycleVoodoo);
+ return;
+ }
+
+ if (!vif1.done)
+ {
+
+ if (!(dmacRegs->ctrl.DMAE))
+ {
+ Console.WriteLn("vif1 dma masked");
+ return;
+ }
+
+ if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
+
+ CPU_INT(1, /*g_vifCycles*/ VifCycleVoodoo);
+ return;
+ }
+
+ if (vif1.vifstalled && vif1.irq)
+ {
+ CPU_INT(1, 0);
+ return; //Dont want to end if vif is stalled.
+ }
+#ifdef PCSX2_DEVBUILD
+ if (vif1ch->qwc > 0) Console.WriteLn("VIF1 Ending with %x QWC left");
+ if (vif1.cmd != 0) Console.WriteLn("vif1.cmd still set %x tag size %x", vif1.cmd, vif1.tag.size);
+#endif
+
+ vif1Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
+ vif1ch->chcr.STR = false;
+ g_vifCycles = 0;
+ hwDmacIrq(DMAC_VIF1);
+
+ //Im not totally sure why Path3 Masking makes it want to see stuff in the fifo
+ //Games effected by setting, Fatal Frame, KH2, Shox, Crash N Burn, GT3/4 possibly
+ //Im guessing due to the full gs fifo before the reverse? (Refraction)
+ //Note also this is only the condition for reverse fifo mode, normal direction clears it as normal
+ if (!vif1Regs->mskpath3 || vif1ch->chcr.DIR) vif1Regs->stat.FQC = 0;
+}
+
+void dmaVIF1()
+{
+ VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n"
+ " tadr = %lx, asr0 = %lx, asr1 = %lx",
+ vif1ch->chcr._u32, vif1ch->madr, vif1ch->qwc,
+ vif1ch->tadr, vif1ch->asr0, vif1ch->asr1);
+
+ g_vifCycles = 0;
+ vif1.inprogress = 0;
+
+ if (dmacRegs->ctrl.MFD == MFD_VIF1) // VIF MFIFO
+ {
+ //Console.WriteLn("VIFMFIFO\n");
+ // Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw.
+ if (vif1ch->chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch->chcr._u32);
+ vifMFIFOInterrupt();
+ return;
+ }
+
+#ifdef PCSX2_DEVBUILD
+ if (dmacRegs->ctrl.STD == STD_VIF1)
+ {
+ //DevCon.WriteLn("VIF Stall Control Source = %x, Drain = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3);
+ }
+#endif
+
+ if ((vif1ch->chcr.MOD == NORMAL_MODE) || vif1ch->qwc > 0) // Normal Mode
+ {
+
+ if (dmacRegs->ctrl.STD == STD_VIF1)
+ Console.WriteLn("DMA Stall Control on VIF1 normal");
+
+ if (vif1ch->chcr.DIR) // to Memory
+ vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
+ else
+ vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
+ }
+ else
+ {
+ vif1.dmamode = VIF_CHAIN_MODE;
+ }
+
+ if (vif1.dmamode != VIF_NORMAL_FROM_MEM_MODE)
+ vif1Regs->stat.FQC = 0x10;
+ else
+ vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
+
+ // Chain Mode
+ vif1.done = false;
+ vif1Interrupt();
+}
+
+void vif1Write32(u32 mem, u32 value)
+{
+ switch (mem)
+ {
+ case VIF1_MARK:
+ VIF_LOG("VIF1_MARK write32 0x%8.8x", value);
+
+ /* Clear mark flag in VIF1_STAT and set mark with 'value' */
+ vif1Regs->stat.MRK = false;
+ vif1Regs->mark = value;
+ break;
+
+ case VIF1_FBRST: // FBRST
+ VIF_LOG("VIF1_FBRST write32 0x%8.8x", value);
+
+ if (FBRST(value).RST) // Reset Vif.
+ {
+ memzero(vif1);
+ cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
+ vif1ch->qwc = 0; //?
+ psHu64(VIF1_FIFO) = 0;
+ psHu64(VIF1_FIFO + 8) = 0;
+ vif1.done = true;
+
+ if(vif1Regs->mskpath3)
+ {
+ vif1Regs->mskpath3 = 0;
+ gifRegs->stat.IMT = false;
+ if (gif->chcr.STR) CPU_INT(2, 4);
+ }
+
+ vif1Regs->err.reset();
+ vif1.inprogress = 0;
+ 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);
+ }
+
+ if (FBRST(value).FBK) // Forcebreak Vif.
+ {
+ /* I guess we should stop the VIF dma here, but not 100% sure (linuz) */
+ vif1Regs->stat.VFS = true;
+ vif1Regs->stat.VPS = VPS_IDLE;
+ cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
+ vif1.vifstalled = true;
+ Console.WriteLn("vif1 force break");
+ }
+
+ if (FBRST(value).STP) // Stop Vif.
+ {
+ // Not completely sure about this, can't remember what game used this, but 'draining' the VIF helped it, instead of
+ // just stoppin the VIF (linuz).
+ vif1Regs->stat.VSS = true;
+ vif1Regs->stat.VPS = VPS_IDLE;
+ cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
+ vif1.vifstalled = true;
+ }
+
+ if (FBRST(value).STC) // Cancel Vif Stall.
+ {
+ bool cancel = false;
+
+ /* Cancel stall, first check if there is a stall to cancel, and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */
+ if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
+ {
+ cancel = true;
+ }
+
+ vif1Regs->stat.clear_flags(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS |
+ VIF1_STAT_INT | VIF1_STAT_ER0 | VIF1_STAT_ER1);
+
+ if (cancel)
+ {
+ if (vif1.vifstalled)
+ {
+ g_vifCycles = 0;
+ // loop necessary for spiderman
+ switch(dmacRegs->ctrl.MFD)
+ {
+ case MFD_VIF1:
+ //Console.WriteLn("MFIFO Stall");
+ CPU_INT(10, vif1ch->qwc * BIAS);
+ break;
+
+ case NO_MFD:
+ case MFD_RESERVED:
+ case MFD_GIF: // Wonder if this should be with VIF?
+ // Gets the timing right - Flatout
+ CPU_INT(1, vif1ch->qwc * BIAS);
+ break;
+ }
+
+ vif1ch->chcr.STR = true;
+ }
+ }
+ }
+ break;
+
+ case VIF1_ERR: // ERR
+ VIF_LOG("VIF1_ERR write32 0x%8.8x", value);
+
+ /* Set VIF1_ERR with 'value' */
+ vif1Regs->err.write(value);
+ break;
+
+ case VIF1_STAT: // STAT
+ VIF_LOG("VIF1_STAT write32 0x%8.8x", value);
+
+#ifdef PCSX2_DEVBUILD
+ /* Only FDR bit is writable, so mask the rest */
+ if ((vif1Regs->stat.FDR) ^ ((tVIF_STAT&)value).FDR)
+ {
+ // different so can't be stalled
+ if (vif1Regs->stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
+ {
+ DevCon.WriteLn("changing dir when vif1 fifo stalled");
+ }
+ }
+#endif
+
+ vif1Regs->stat.FDR = VIF_STAT(value).FDR;
+
+ if (vif1Regs->stat.FDR) // Vif transferring to memory.
+ {
+ // Hack but it checks this is true before transfer? (fatal frame)
+ vif1Regs->stat.FQC = 0x1;
+ }
+ else // Memory transferring to Vif.
+ {
+ vif1ch->qwc = 0;
+ vif1.vifstalled = false;
+ vif1.done = true;
+ vif1Regs->stat.FQC = 0;
+ }
+ break;
+
+ case VIF1_MODE:
+ vif1Regs->mode = value;
+ break;
+
+ case VIF1_R0:
+ case VIF1_R1:
+ case VIF1_R2:
+ case VIF1_R3:
+ pxAssume((mem&0xf) == 0);
+ g_vifmask.Row1[(mem>>4) & 3] = value;
+ break;
+
+ case VIF1_C0:
+ case VIF1_C1:
+ case VIF1_C2:
+ case VIF1_C3:
+ pxAssume((mem&0xf) == 0);
+ g_vifmask.Col1[(mem>>4) & 3] = value;
+ break;
+
+ default:
+ Console.WriteLn("Unknown Vif1 write to %x", mem);
+ psHu32(mem) = value;
+ break;
+ }
+
+ /* Other registers are read-only so do nothing for them */
+}
diff --git a/pcsx2/Vif1_MFIFO.cpp b/pcsx2/Vif1_MFIFO.cpp
new file mode 100644
index 0000000000..23e2bf4c97
--- /dev/null
+++ b/pcsx2/Vif1_MFIFO.cpp
@@ -0,0 +1,305 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+#include "Common.h"
+#include "Vif.h"
+#include "Vif_Dma.h"
+
+VIFregisters *vifRegs;
+vifStruct *vif;
+u16 vifqwc = 0;
+int g_vifCycles = 0;
+
+__aligned16 VifMaskTypes g_vifmask;
+
+extern int g_vifCycles;
+
+static __forceinline bool mfifoVIF1rbTransfer()
+{
+ u32 maddr = dmacRegs->rbor.ADDR;
+ u32 msize = dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16;
+ u16 mfifoqwc = std::min(vif1ch->qwc, vifqwc);
+ u32 *src;
+ bool ret;
+
+ /* Check if the transfer should wrap around the ring buffer */
+ if ((vif1ch->madr + (mfifoqwc << 4)) > (msize))
+ {
+ int s1 = ((msize) - vif1ch->madr) >> 2;
+
+ SPR_LOG("Split MFIFO");
+
+ /* it does, so first copy 's1' bytes from 'addr' to 'data' */
+ src = (u32*)PSM(vif1ch->madr);
+ if (src == NULL) return false;
+
+ if (vif1.vifstalled)
+ ret = VIF1transfer(src + vif1.irqoffset, s1 - vif1.irqoffset, false);
+ else
+ ret = VIF1transfer(src, s1, false);
+
+ if (ret)
+ {
+ /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
+ vif1ch->madr = maddr;
+
+ src = (u32*)PSM(maddr);
+ if (src == NULL) return false;
+ VIF1transfer(src, ((mfifoqwc << 2) - s1), false);
+ }
+ }
+ else
+ {
+ SPR_LOG("Direct MFIFO");
+
+ /* it doesn't, so just transfer 'qwc*4' words */
+ src = (u32*)PSM(vif1ch->madr);
+ if (src == NULL) return false;
+
+ if (vif1.vifstalled)
+ ret = VIF1transfer(src + vif1.irqoffset, mfifoqwc * 4 - vif1.irqoffset, false);
+ else
+ ret = VIF1transfer(src, mfifoqwc << 2, false);
+ }
+ return ret;
+}
+
+static __forceinline bool mfifo_VIF1chain()
+{
+ bool ret;
+
+ /* Is QWC = 0? if so there is nothing to transfer */
+ if ((vif1ch->qwc == 0) && (!vif1.vifstalled))
+ {
+ vif1.inprogress &= ~1;
+ return true;
+ }
+
+ if (vif1ch->madr >= dmacRegs->rbor.ADDR &&
+ vif1ch->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK))
+ {
+ u16 startqwc = vif1ch->qwc;
+ ret = mfifoVIF1rbTransfer();
+ vifqwc -= startqwc - vif1ch->qwc;
+ }
+ else
+ {
+ tDMA_TAG *pMem = dmaGetAddr(vif1ch->madr);
+ SPR_LOG("Non-MFIFO Location");
+
+ if (pMem == NULL) return false;
+
+ if (vif1.vifstalled)
+ ret = VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset, false);
+ else
+ ret = VIF1transfer((u32*)pMem, vif1ch->qwc << 2, false);
+ }
+ return ret;
+}
+
+static u32 qwctag(u32 mask)
+{
+ return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK));
+}
+
+void mfifoVIF1transfer(int qwc)
+{
+ tDMA_TAG *ptag;
+
+ g_vifCycles = 0;
+
+ if (qwc > 0)
+ {
+ vifqwc += qwc;
+ SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch->chcr._u32, vif1.vifstalled, vif1.done);
+ if (vif1.inprogress & 0x10)
+ {
+ if (vif1ch->madr >= dmacRegs->rbor.ADDR && vif1ch->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK))
+ CPU_INT(10, 0);
+ else
+ CPU_INT(10, vif1ch->qwc * BIAS);
+
+ vif1Regs->stat.FQC = 0x10; // FQC=16
+ }
+ vif1.inprogress &= ~0x10;
+
+ return;
+ }
+
+ if (vif1ch->qwc == 0 && vifqwc > 0)
+ {
+ ptag = dmaGetAddr(vif1ch->tadr);
+
+ if (vif1ch->chcr.TTE)
+ {
+ bool ret;
+
+ if (vif1.stallontag)
+ ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, true); //Transfer Tag on Stall
+ else
+ ret = VIF1transfer((u32*)ptag + 2, 2, true); //Transfer Tag
+
+ if (!(ret))
+ {
+ VIF_LOG("MFIFO Stall on tag");
+ vif1.stallontag = true;
+ return; //IRQ set by VIFTransfer
+ }
+ }
+
+ vif1ch->unsafeTransfer(ptag);
+
+ vif1ch->madr = ptag[1]._u32;
+ vifqwc--;
+
+ SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
+ ptag[1]._u32, ptag[0]._u32, vif1ch->qwc, ptag->ID, vif1ch->madr, vif1ch->tadr, vifqwc, spr0->madr);
+
+ switch (ptag->ID)
+ {
+ case TAG_REFE: // Refe - Transfer Packet According to ADDR field
+ vif1ch->tadr = qwctag(vif1ch->tadr + 16);
+ vif1.done = true; //End Transfer
+ break;
+
+ case TAG_CNT: // CNT - Transfer QWC following the tag.
+ vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to QW after Tag
+ vif1ch->tadr = qwctag(vif1ch->madr + (vif1ch->qwc << 4)); //Set TADR to QW following the data
+ vif1.done = false;
+ break;
+
+ case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
+ {
+ int temp = vif1ch->madr; //Temporarily Store ADDR
+ vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to QW following the tag
+ vif1ch->tadr = temp; //Copy temporarily stored ADDR to Tag
+ if ((temp & dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("Next tag = %x outside ring %x size %x", temp, psHu32(DMAC_RBOR), psHu32(DMAC_RBSR));
+ vif1.done = false;
+ break;
+ }
+
+ case TAG_REF: // Ref - Transfer QWC from ADDR field
+ case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
+ vif1ch->tadr = qwctag(vif1ch->tadr + 16); //Set TADR to next tag
+ vif1.done = false;
+ break;
+
+ case TAG_END: // End - Transfer QWC following the tag
+ vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to data following the tag
+ vif1ch->tadr = qwctag(vif1ch->madr + (vif1ch->qwc << 4)); //Set TADR to QW following the data
+ vif1.done = true; //End Transfer
+ break;
+ }
+
+ if (vif1ch->chcr.TIE && ptag->IRQ)
+ {
+ VIF_LOG("dmaIrq Set");
+ vif1.done = true;
+ }
+ }
+
+ vif1.inprogress |= 1;
+
+ SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr, vifqwc);
+}
+
+void vifMFIFOInterrupt()
+{
+ g_vifCycles = 0;
+
+ if (schedulepath3msk) Vif1MskPath3();
+
+ if ((vif1Regs->stat.VGW))
+ {
+ if (gif->chcr.STR)
+ {
+ CPU_INT(10, 16);
+ return;
+ }
+ else
+ {
+ vif1Regs->stat.VGW = false;
+ }
+
+ }
+
+ if ((spr0->chcr.STR) && (spr0->qwc == 0))
+ {
+ spr0->chcr.STR = false;
+ hwDmacIrq(DMAC_FROM_SPR);
+ }
+
+ if (vif1.irq && vif1.tag.size == 0)
+ {
+ vif1Regs->stat.INT = true;
+ hwIntcIrq(INTC_VIF1);
+ --vif1.irq;
+
+ if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
+ {
+ vif1Regs->stat.FQC = 0; // FQC=0
+ vif1ch->chcr.STR = false;
+ return;
+ }
+ }
+
+ if (vif1.done == false || vif1ch->qwc)
+ {
+ switch(vif1.inprogress & 1)
+ {
+ case 0: //Set up transfer
+ if (vif1ch->tadr == spr0->madr)
+ {
+ // Console.WriteLn("Empty 1");
+ vifqwc = 0;
+ vif1.inprogress |= 0x10;
+ vif1Regs->stat.FQC = 0;
+ hwDmacIrq(DMAC_MFIFO_EMPTY);
+ return;
+ }
+
+ mfifoVIF1transfer(0);
+ if ((vif1ch->madr >= dmacRegs->rbor.ADDR) && (vif1ch->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK)))
+ CPU_INT(10, 0);
+ else
+ CPU_INT(10, vif1ch->qwc * BIAS);
+
+ return;
+
+ case 1: //Transfer data
+ mfifo_VIF1chain();
+ CPU_INT(10, 0);
+ return;
+ }
+ return;
+ }
+
+ /*if (vifqwc <= 0)
+ {
+ //Console.WriteLn("Empty 2");
+ //vif1.inprogress |= 0x10;
+ vif1Regs->stat.FQC = 0; // FQC=0
+ hwDmacIrq(DMAC_MFIFO_EMPTY);
+ }*/
+
+ vif1.done = 1;
+ g_vifCycles = 0;
+ vif1ch->chcr.STR = false;
+ hwDmacIrq(DMAC_VIF1);
+ VIF_LOG("vif mfifo dma end");
+
+ vif1Regs->stat.FQC = 0;
+}
diff --git a/pcsx2/VifDma_internal.h b/pcsx2/VifDma_internal.h
deleted file mode 100644
index 4e7157cb19..0000000000
--- a/pcsx2/VifDma_internal.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* PCSX2 - PS2 Emulator for PCs
- * Copyright (C) 2002-2009 PCSX2 Dev Team
- *
- * PCSX2 is free software: you can redistribute it and/or modify it under the terms
- * of the GNU Lesser General Public License as published by the Free Software Found-
- * ation, either version 3 of the License, or (at your option) any later version.
- *
- * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with PCSX2.
- * If not, see .
- */
-
-#pragma once
-
-#include "VifDma.h"
-
-
diff --git a/pcsx2/VifDma.cpp b/pcsx2/Vif_Commands.cpp
similarity index 78%
rename from pcsx2/VifDma.cpp
rename to pcsx2/Vif_Commands.cpp
index e20c720f93..09c3dc0961 100644
--- a/pcsx2/VifDma.cpp
+++ b/pcsx2/Vif_Commands.cpp
@@ -1,64 +1,54 @@
-/* PCSX2 - PS2 Emulator for PCs
- * Copyright (C) 2002-2009 PCSX2 Dev Team
- *
- * PCSX2 is free software: you can redistribute it and/or modify it under the terms
- * of the GNU Lesser General Public License as published by the Free Software Found-
- * ation, either version 3 of the License, or (at your option) any later version.
- *
- * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with PCSX2.
- * If not, see .
- */
-
-#include "PrecompiledHeader.h"
-#include "Common.h"
-
-#include "VifDma.h"
-#include "VUmicro.h"
-
-int g_vifCycles = 0;
-
-template void vuExecMicro<0>(u32 addr);
-template void vuExecMicro<1>(u32 addr);
-template void vuExecMicro(u32 addr)
-{
- VURegs * VU;
-
- if (VIFdmanum == 0) {
- VU = &VU0;
- vif0FLUSH();
- }
- else {
- VU = &VU1;
- vif1FLUSH();
- }
-
- if (VU->vifRegs->itops > (VIFdmanum ? 0x3ffu : 0xffu))
- Console.WriteLn("VIF%d ITOP overrun! %x", VIFdmanum, VU->vifRegs->itops);
-
- VU->vifRegs->itop = VU->vifRegs->itops;
-
- if (VIFdmanum == 1)
- {
- /* in case we're handling a VIF1 execMicro, set the top with the tops value */
- VU->vifRegs->top = VU->vifRegs->tops & 0x3ff;
-
- /* is DBF flag set in VIF_STAT? */
- if (VU->vifRegs->stat.DBF) {
- /* it is, so set tops with base, and clear the stat DBF flag */
- VU->vifRegs->tops = VU->vifRegs->base;
- VU->vifRegs->stat.DBF = false;
- }
- else {
- /* it is not, so set tops with base + offset, and set stat DBF flag */
- VU->vifRegs->tops = VU->vifRegs->base + VU->vifRegs->ofst;
- VU->vifRegs->stat.DBF = true;
- }
- }
-
- if (!VIFdmanum) vu0ExecMicro(addr);
- else vu1ExecMicro(addr);
-}
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+#include "Common.h"
+#include "Vif_Dma.h"
+#include "VUmicro.h"
+
+template void vuExecMicro<0>(u32 addr);
+template void vuExecMicro<1>(u32 addr);
+template void vuExecMicro(u32 addr)
+{
+ VURegs * VU;
+ if (!VIFdmanum) { VU = &VU0; vif0FLUSH(); }
+ else { VU = &VU1; vif1FLUSH(); }
+
+ if (VU->vifRegs->itops > (VIFdmanum ? 0x3ffu : 0xffu))
+ Console.WriteLn("VIF%d ITOP overrun! %x", VIFdmanum, VU->vifRegs->itops);
+
+ VU->vifRegs->itop = VU->vifRegs->itops;
+
+ if (VIFdmanum == 1)
+ {
+ // in case we're handling a VIF1 execMicro, set the top with the tops value
+ VU->vifRegs->top = VU->vifRegs->tops & 0x3ff;
+
+ // is DBF flag set in VIF_STAT?
+ if (VU->vifRegs->stat.DBF) {
+ // it is, so set tops with base, and clear the stat DBF flag
+ VU->vifRegs->tops = VU->vifRegs->base;
+ VU->vifRegs->stat.DBF = false;
+ }
+ else {
+ // it is not, so set tops with base + offset, and set stat DBF flag
+ VU->vifRegs->tops = VU->vifRegs->base + VU->vifRegs->ofst;
+ VU->vifRegs->stat.DBF = true;
+ }
+ }
+
+ if (!VIFdmanum) vu0ExecMicro(addr);
+ else vu1ExecMicro(addr);
+}
diff --git a/pcsx2/VifDma.h b/pcsx2/Vif_Dma.h
similarity index 82%
rename from pcsx2/VifDma.h
rename to pcsx2/Vif_Dma.h
index d82d6d7c86..1c14c8ed2a 100644
--- a/pcsx2/VifDma.h
+++ b/pcsx2/Vif_Dma.h
@@ -1,84 +1,95 @@
-/* PCSX2 - PS2 Emulator for PCs
- * Copyright (C) 2002-2009 PCSX2 Dev Team
- *
- * PCSX2 is free software: you can redistribute it and/or modify it under the terms
- * of the GNU Lesser General Public License as published by the Free Software Found-
- * ation, either version 3 of the License, or (at your option) any later version.
- *
- * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with PCSX2.
- * If not, see .
- */
-
-#pragma once
-#include "Vif_Unpack.h"
-
-struct vifCode {
- u32 addr;
- u32 size;
- u32 cmd;
- u16 wl;
- u16 cl;
-};
-
-// NOTE, if debugging vif stalls, use sega classics, spyro, gt4, and taito
-struct vifStruct {
- vifCode tag;
- int cmd;
- int irq;
- int cl;
- int qwcalign;
- u8 usn;
-
- bool done;
- bool vifstalled;
- bool stallontag;
-
- u8 irqoffset; // 32bit offset where next vif code is
- u32 savedtag; // need this for backwards compat with save states
- u32 vifpacketsize;
- u8 inprogress;
- u8 dmamode;
-};
-
-extern vifStruct* vif;
-extern vifStruct vif0, vif1;
-extern u8 schedulepath3msk;
-static const int VifCycleVoodoo = 4;
-
-extern void vif0Init();
-extern void vif0Interrupt();
-extern void vif0Write32(u32 mem, u32 value);
-extern void vif0Reset();
-
-extern void vif1Interrupt();
-extern void vif1Init();
-extern void Vif1MskPath3();
-extern void vif1Write32(u32 mem, u32 value);
-extern void vif1Reset();
-
-__forceinline static int _limit(int a, int max)
-{
- return ((a > max) ? max : a);
-}
-
-enum VifModes
-{
- VIF_NORMAL_TO_MEM_MODE = 0,
- VIF_NORMAL_FROM_MEM_MODE = 1,
- VIF_CHAIN_MODE = 2
-};
-
-// Generic constants
-static const unsigned int VIF0intc = 4;
-static const unsigned int VIF1intc = 5;
-
-extern int g_vifCycles;
-
-template void vuExecMicro(u32 addr);
-extern void vif0FLUSH();
-extern void vif1FLUSH();
-
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#pragma once
+#include "Vif_Unpack.h"
+
+struct vifCode {
+ u32 addr;
+ u32 size;
+ u32 cmd;
+ u16 wl;
+ u16 cl;
+};
+
+// NOTE, if debugging vif stalls, use sega classics, spyro, gt4, and taito
+struct vifStruct {
+ vifCode tag;
+ int cmd;
+ int irq;
+ int cl;
+ int qwcalign;
+ u8 usn;
+
+ bool done;
+ bool vifstalled;
+ bool stallontag;
+
+ u8 irqoffset; // 32bit offset where next vif code is
+ u32 savedtag; // need this for backwards compat with save states
+ u32 vifpacketsize;
+ u8 inprogress;
+ u8 dmamode;
+};
+
+extern vifStruct* vif;
+extern vifStruct vif0, vif1;
+extern u8 schedulepath3msk;
+static const int VifCycleVoodoo = 4;
+
+extern void vif0Init();
+extern void vif0Interrupt();
+extern void vif0Write32(u32 mem, u32 value);
+extern void vif0Reset();
+
+extern void vif1Interrupt();
+extern void vif1Init();
+extern void Vif1MskPath3();
+extern void vif1Write32(u32 mem, u32 value);
+extern void vif1Reset();
+
+__forceinline static int _limit(int a, int max)
+{
+ return ((a > max) ? max : a);
+}
+
+enum VifModes
+{
+ VIF_NORMAL_TO_MEM_MODE = 0,
+ VIF_NORMAL_FROM_MEM_MODE = 1,
+ VIF_CHAIN_MODE = 2
+};
+
+// Generic constants
+static const unsigned int VIF0intc = 4;
+static const unsigned int VIF1intc = 5;
+
+extern int g_vifCycles;
+
+template void vuExecMicro(u32 addr);
+extern void vif0FLUSH();
+extern void vif1FLUSH();
+
+//------------------------------------------------------------------
+// newVif SSE-optimized Row/Col Structs
+//------------------------------------------------------------------
+
+struct VifMaskTypes
+{
+ u32 Row0[4], Col0[4];
+ u32 Row1[4], Col1[4];
+};
+
+extern __aligned16 VifMaskTypes g_vifmask; // This struct is used by newVif
diff --git a/pcsx2/Vif_Unpack.cpp b/pcsx2/Vif_Unpack.cpp
index f66a545aca..f4eb7e9e97 100644
--- a/pcsx2/Vif_Unpack.cpp
+++ b/pcsx2/Vif_Unpack.cpp
@@ -16,7 +16,7 @@
#include "PrecompiledHeader.h"
#include "Common.h"
#include "Vif.h"
-#include "VifDma.h"
+#include "Vif_Dma.h"
enum UnpackOffset {
OFFSET_X = 0,
diff --git a/pcsx2/ps2/GIFpath.cpp b/pcsx2/ps2/GIFpath.cpp
index be749e0986..d320fa2739 100644
--- a/pcsx2/ps2/GIFpath.cpp
+++ b/pcsx2/ps2/GIFpath.cpp
@@ -17,7 +17,7 @@
#include "Common.h"
#include "GS.h"
#include "Gif.h"
-#include "VifDma.h"
+#include "Vif_Dma.h"
// --------------------------------------------------------------------------------------
// GIFpath -- the GIFtag Parser
diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index d505395ccb..5720935adc 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -805,19 +805,31 @@
>
+
+
+
+
+
+
> 4, doMask ? wxsFormat( L"0x%08x", _vBlock.mask ).c_str() : L"ignored"
diff --git a/pcsx2/x86/newVif_Unpack.cpp b/pcsx2/x86/newVif_Unpack.cpp
index 64e81fbd10..247f49aa97 100644
--- a/pcsx2/x86/newVif_Unpack.cpp
+++ b/pcsx2/x86/newVif_Unpack.cpp
@@ -19,7 +19,7 @@
#include "PrecompiledHeader.h"
#include "Common.h"
-#include "VifDma.h"
+#include "Vif_Dma.h"
#include "newVif.h"
#include "Vif_Unpack.inl"
diff --git a/pcsx2/x86/newVif_UnpackSSE.h b/pcsx2/x86/newVif_UnpackSSE.h
index 4da4454a5e..01629630c4 100644
--- a/pcsx2/x86/newVif_UnpackSSE.h
+++ b/pcsx2/x86/newVif_UnpackSSE.h
@@ -16,7 +16,7 @@
#pragma once
#include "Common.h"
-#include "VifDma.h"
+#include "Vif_Dma.h"
#include "newVif.h"
#include