More vif refactoring/cleanups.

There is a lot of code duplication in the vif0/vif1 files, I will probably work on getting them to use common functions.


git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2489 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2010-01-23 04:14:59 +00:00
parent 47d9ba5c7a
commit 92ddae17ce
18 changed files with 2354 additions and 2350 deletions

View File

@ -18,7 +18,7 @@
#include "GS.h" #include "GS.h"
#include "Gif.h" #include "Gif.h"
#include "VifDma.h" #include "Vif_Dma.h"
#include "iR5900.h" #include "iR5900.h"

View File

@ -25,6 +25,6 @@
#include "Gif.h" #include "Gif.h"
#include "Sif.h" #include "Sif.h"
#include "Vif.h" #include "Vif.h"
#include "VifDma.h" #include "Vif_Dma.h"
#endif #endif

View File

@ -13,296 +13,72 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h" #include "Common.h"
#include <cmath>
#include "Vif.h" #include "Vif.h"
#include "VifDma.h" #include "Vif_Dma.h"
VIFregisters *vifRegs; void vif0Init() { initNewVif(0); }
vifStruct *vif; void vif1Init() { initNewVif(1); }
u16 vifqwc = 0;
__aligned16 VifMaskTypes g_vifmask; void vif0Reset()
extern int g_vifCycles;
static __forceinline bool mfifoVIF1rbTransfer()
{ {
u32 maddr = dmacRegs->rbor.ADDR; /* Reset the whole VIF, meaning the internal pcsx2 vars and all the registers */
u32 msize = dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16; memzero(vif0);
u16 mfifoqwc = std::min(vif1ch->qwc, vifqwc); memzero(*vif0Regs);
u32 *src;
bool ret;
/* Check if the transfer should wrap around the ring buffer */ psHu64(VIF0_FIFO) = 0;
if ((vif1ch->madr + (mfifoqwc << 4)) > (msize)) psHu64(VIF0_FIFO + 8) = 0;
{
int s1 = ((msize) - vif1ch->madr) >> 2;
SPR_LOG("Split MFIFO"); vif0Regs->stat.VPS = VPS_IDLE;
vif0Regs->stat.FQC = 0;
/* it does, so first copy 's1' bytes from 'addr' to 'data' */ vif0.done = true;
src = (u32*)PSM(vif1ch->madr);
if (src == NULL) return false;
if (vif1.vifstalled) resetNewVif(0);
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() void vif1Reset()
{ {
bool ret; /* Reset the whole VIF, meaning the internal pcsx2 vars, and all the registers */
memzero(vif1);
memzero(*vif1Regs);
/* Is QWC = 0? if so there is nothing to transfer */ psHu64(VIF1_FIFO) = 0;
if ((vif1ch->qwc == 0) && (!vif1.vifstalled)) psHu64(VIF1_FIFO + 8) = 0;
{
vif1.inprogress &= ~1;
return true;
}
if (vif1ch->madr >= dmacRegs->rbor.ADDR && vif1Regs->stat.VPS = VPS_IDLE;
vif1ch->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK)) vif1Regs->stat.FQC = 0; // FQC=0
{
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; vif1.done = true;
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
if (vif1.vifstalled) resetNewVif(1);
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) 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; Freeze(g_vif1HasMask3); // Not Used Anymore
Freeze(g_vif1Masks); // Not Used Anymore
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;
} }

View File

@ -13,8 +13,7 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __VIF_H__ #pragma once
#define __VIF_H__
enum vif0_stat_flags 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 bool VIF1transfer(u32 *data, int size, bool istag);
extern void vifMFIFOInterrupt(); 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__ */

275
pcsx2/Vif0_Commands.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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
};

View File

@ -13,16 +13,14 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h" #include "Common.h"
#include "VifDma.h" #include "Vif_Dma.h"
#include "VUmicro.h" #include "VUmicro.h"
#include "newVif.h" #include "newVif.h"
extern int (__fastcall *Vif0TransTLB[128])(u32 *data); extern int (__fastcall *Vif0TransTLB[128])(u32 *data);
extern void (*Vif0CMDTLB[75])(); extern void (*Vif0CMDTLB[75])();
vifStruct vif0; vifStruct vif0;
__forceinline void vif0FLUSH() __forceinline void vif0FLUSH()
@ -36,11 +34,6 @@ __forceinline void vif0FLUSH()
g_vifCycles += (VU0.cycle - _cycles) * BIAS; g_vifCycles += (VU0.cycle - _cycles) * BIAS;
} }
void vif0Init()
{
initNewVif(0);
}
static __forceinline void vif0UNPACK(u32 *data) static __forceinline void vif0UNPACK(u32 *data)
{ {
int vifNum; int vifNum;
@ -77,229 +70,6 @@ static __forceinline void vif0UNPACK(u32 *data)
vif0Regs->offset = 0; 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) bool VIF0transfer(u32 *data, int size, bool istag)
{ {
int ret; int ret;
@ -535,42 +305,6 @@ void vif0Interrupt()
vif0Regs->stat.FQC = 0; 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() void dmaVIF0()
{ {
VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n" VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n"
@ -710,37 +444,3 @@ void vif0Write32(u32 mem, u32 value)
} }
/* Other registers are read-only so do nothing for them */ /* 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
}

425
pcsx2/Vif1_Commands.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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
};

View File

@ -13,10 +13,9 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h" #include "Common.h"
#include "VifDma.h" #include "Vif_Dma.h"
#include "GS.h" #include "GS.h"
#include "Gif.h" #include "Gif.h"
#include "VUmicro.h" #include "VUmicro.h"
@ -28,9 +27,6 @@ extern int (__fastcall *Vif1TransTLB[128])(u32 *data);
Path3Modes Path3progress = STOPPED_MODE; Path3Modes Path3progress = STOPPED_MODE;
vifStruct vif1; vifStruct vif1;
static __aligned16 u32 splittransfer[4];
static u32 splitptr = 0;
__forceinline void vif1FLUSH() __forceinline void vif1FLUSH()
{ {
int _cycles = VU1.cycle; int _cycles = VU1.cycle;
@ -50,12 +46,6 @@ __forceinline void vif1FLUSH()
} }
} }
void vif1Init()
{
initNewVif(1);
}
static __forceinline void vif1UNPACK(u32 *data) static __forceinline void vif1UNPACK(u32 *data)
{ {
int vifNum; int vifNum;
@ -99,424 +89,6 @@ static __forceinline void vif1UNPACK(u32 *data)
} }
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) bool VIF1transfer(u32 *data, int size, bool istag)
{ {
int ret; int ret;
@ -1110,31 +682,3 @@ void vif1Write32(u32 mem, u32 value)
/* Other registers are read-only so do nothing for them */ /* 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
}

305
pcsx2/Vif1_MFIFO.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "VifDma.h"

View File

@ -15,26 +15,16 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h" #include "Common.h"
#include "Vif_Dma.h"
#include "VifDma.h"
#include "VUmicro.h" #include "VUmicro.h"
int g_vifCycles = 0;
template void vuExecMicro<0>(u32 addr); template void vuExecMicro<0>(u32 addr);
template void vuExecMicro<1>(u32 addr); template void vuExecMicro<1>(u32 addr);
template<const u32 VIFdmanum> void vuExecMicro(u32 addr) template<const u32 VIFdmanum> void vuExecMicro(u32 addr)
{ {
VURegs * VU; VURegs * VU;
if (!VIFdmanum) { VU = &VU0; vif0FLUSH(); }
if (VIFdmanum == 0) { else { VU = &VU1; vif1FLUSH(); }
VU = &VU0;
vif0FLUSH();
}
else {
VU = &VU1;
vif1FLUSH();
}
if (VU->vifRegs->itops > (VIFdmanum ? 0x3ffu : 0xffu)) if (VU->vifRegs->itops > (VIFdmanum ? 0x3ffu : 0xffu))
Console.WriteLn("VIF%d ITOP overrun! %x", VIFdmanum, VU->vifRegs->itops); Console.WriteLn("VIF%d ITOP overrun! %x", VIFdmanum, VU->vifRegs->itops);
@ -43,17 +33,17 @@ template<const u32 VIFdmanum> void vuExecMicro(u32 addr)
if (VIFdmanum == 1) if (VIFdmanum == 1)
{ {
/* in case we're handling a VIF1 execMicro, set the top with the tops value */ // in case we're handling a VIF1 execMicro, set the top with the tops value
VU->vifRegs->top = VU->vifRegs->tops & 0x3ff; VU->vifRegs->top = VU->vifRegs->tops & 0x3ff;
/* is DBF flag set in VIF_STAT? */ // is DBF flag set in VIF_STAT?
if (VU->vifRegs->stat.DBF) { if (VU->vifRegs->stat.DBF) {
/* it is, so set tops with base, and clear the stat DBF flag */ // it is, so set tops with base, and clear the stat DBF flag
VU->vifRegs->tops = VU->vifRegs->base; VU->vifRegs->tops = VU->vifRegs->base;
VU->vifRegs->stat.DBF = false; VU->vifRegs->stat.DBF = false;
} }
else { else {
/* it is not, so set tops with base + offset, and set stat DBF flag */ // 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->tops = VU->vifRegs->base + VU->vifRegs->ofst;
VU->vifRegs->stat.DBF = true; VU->vifRegs->stat.DBF = true;
} }

View File

@ -82,3 +82,14 @@ template<const u32 VIFdmanum> void vuExecMicro(u32 addr);
extern void vif0FLUSH(); extern void vif0FLUSH();
extern void vif1FLUSH(); 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

View File

@ -16,7 +16,7 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h" #include "Common.h"
#include "Vif.h" #include "Vif.h"
#include "VifDma.h" #include "Vif_Dma.h"
enum UnpackOffset { enum UnpackOffset {
OFFSET_X = 0, OFFSET_X = 0,

View File

@ -17,7 +17,7 @@
#include "Common.h" #include "Common.h"
#include "GS.h" #include "GS.h"
#include "Gif.h" #include "Gif.h"
#include "VifDma.h" #include "Vif_Dma.h"
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// GIFpath -- the GIFtag Parser // GIFpath -- the GIFtag Parser

View File

@ -805,19 +805,31 @@
> >
</File> </File>
<File <File
RelativePath="..\..\Vif0Dma.cpp" RelativePath="..\..\Vif0_Commands.cpp"
> >
</File> </File>
<File <File
RelativePath="..\..\Vif1Dma.cpp" RelativePath="..\..\Vif0_Dma.cpp"
> >
</File> </File>
<File <File
RelativePath="..\..\VifDma.cpp" RelativePath="..\..\Vif1_Commands.cpp"
> >
</File> </File>
<File <File
RelativePath="..\..\VifDma.h" RelativePath="..\..\Vif1_Dma.cpp"
>
</File>
<File
RelativePath="..\..\Vif1_MFIFO.cpp"
>
</File>
<File
RelativePath="..\..\Vif_Commands.cpp"
>
</File>
<File
RelativePath="..\..\Vif_Dma.h"
> >
</File> </File>
<Filter <Filter

View File

@ -247,7 +247,7 @@ _f void dVifUnpack(int idx, u8 *data, u32 size, bool isFill) {
} }
return; return;
} }
DevCon.WriteLn("nVif%d: Recompiled Block! [%d]", idx, nVif[idx].numBlocks++); //DevCon.WriteLn("nVif%d: Recompiled Block! [%d]", idx, nVif[idx].numBlocks++);
//DevCon.WriteLn(L"[num=% 3d][upkType=0x%02x][scl=%d][cl=%d][wl=%d][mode=%d][m=%d][mask=%s]", //DevCon.WriteLn(L"[num=% 3d][upkType=0x%02x][scl=%d][cl=%d][wl=%d][mode=%d][m=%d][mask=%s]",
// _vBlock.num, _vBlock.upkType, _vBlock.scl, _vBlock.cl, _vBlock.wl, _vBlock.mode, // _vBlock.num, _vBlock.upkType, _vBlock.scl, _vBlock.cl, _vBlock.wl, _vBlock.mode,
// doMask >> 4, doMask ? wxsFormat( L"0x%08x", _vBlock.mask ).c_str() : L"ignored" // doMask >> 4, doMask ? wxsFormat( L"0x%08x", _vBlock.mask ).c_str() : L"ignored"

View File

@ -19,7 +19,7 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h" #include "Common.h"
#include "VifDma.h" #include "Vif_Dma.h"
#include "newVif.h" #include "newVif.h"
#include "Vif_Unpack.inl" #include "Vif_Unpack.inl"

View File

@ -16,7 +16,7 @@
#pragma once #pragma once
#include "Common.h" #include "Common.h"
#include "VifDma.h" #include "Vif_Dma.h"
#include "newVif.h" #include "newVif.h"
#include <xmmintrin.h> #include <xmmintrin.h>