mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
47d9ba5c7a
commit
92ddae17ce
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include "GS.h"
|
||||
#include "Gif.h"
|
||||
#include "VifDma.h"
|
||||
#include "Vif_Dma.h"
|
||||
|
||||
#include "iR5900.h"
|
||||
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
#include "Gif.h"
|
||||
#include "Sif.h"
|
||||
#include "Vif.h"
|
||||
#include "VifDma.h"
|
||||
#include "Vif_Dma.h"
|
||||
|
||||
#endif
|
||||
|
|
310
pcsx2/Vif.cpp
310
pcsx2/Vif.cpp
|
@ -13,296 +13,72 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#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;
|
||||
|
||||
SPR_LOG("Split MFIFO");
|
||||
vif0Regs->stat.VPS = VPS_IDLE;
|
||||
vif0Regs->stat.FQC = 0;
|
||||
|
||||
/* it does, so first copy 's1' bytes from 'addr' to 'data' */
|
||||
src = (u32*)PSM(vif1ch->madr);
|
||||
if (src == NULL) return false;
|
||||
vif0.done = true;
|
||||
|
||||
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;
|
||||
/* 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 */
|
||||
if ((vif1ch->qwc == 0) && (!vif1.vifstalled))
|
||||
{
|
||||
vif1.inprogress &= ~1;
|
||||
return true;
|
||||
}
|
||||
psHu64(VIF1_FIFO) = 0;
|
||||
psHu64(VIF1_FIFO + 8) = 0;
|
||||
|
||||
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");
|
||||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
vif1Regs->stat.FQC = 0; // FQC=0
|
||||
|
||||
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;
|
||||
}
|
||||
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
|
||||
|
||||
resetNewVif(1);
|
||||
}
|
||||
|
||||
vif1.inprogress |= 1;
|
||||
|
||||
SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr, vifqwc);
|
||||
}
|
||||
|
||||
void vifMFIFOInterrupt()
|
||||
void SaveStateBase::vif0Freeze()
|
||||
{
|
||||
g_vifCycles = 0;
|
||||
static u32 g_vif0Masks[64]; // Dummy Var for saved state compatibility
|
||||
static u32 g_vif0HasMask3[4]; // Dummy Var for saved state compatibility
|
||||
FreezeTag("VIFdma");
|
||||
|
||||
if (schedulepath3msk) Vif1MskPath3();
|
||||
// Dunno if this one is needed, but whatever, it's small. :)
|
||||
Freeze(g_vifCycles);
|
||||
|
||||
if ((vif1Regs->stat.VGW))
|
||||
{
|
||||
if (gif->chcr.STR)
|
||||
{
|
||||
CPU_INT(10, 16);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
// mask settings for VIF0 and VIF1
|
||||
Freeze(g_vifmask);
|
||||
|
||||
Freeze(vif0);
|
||||
Freeze(g_vif0HasMask3); // Not Used Anymore
|
||||
Freeze(g_vif0Masks); // Not Used Anymore
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((spr0->chcr.STR) && (spr0->qwc == 0))
|
||||
void SaveStateBase::vif1Freeze()
|
||||
{
|
||||
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;
|
||||
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
|
||||
}
|
||||
|
|
16
pcsx2/Vif.h
16
pcsx2/Vif.h
|
@ -13,8 +13,7 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
|
|
|
@ -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
|
||||
};
|
|
@ -13,16 +13,14 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
#include "VifDma.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()
|
||||
|
@ -36,11 +34,6 @@ __forceinline void vif0FLUSH()
|
|||
g_vifCycles += (VU0.cycle - _cycles) * BIAS;
|
||||
}
|
||||
|
||||
void vif0Init()
|
||||
{
|
||||
initNewVif(0);
|
||||
}
|
||||
|
||||
static __forceinline void vif0UNPACK(u32 *data)
|
||||
{
|
||||
int vifNum;
|
||||
|
@ -77,229 +70,6 @@ static __forceinline void vif0UNPACK(u32 *data)
|
|||
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;
|
||||
|
@ -535,42 +305,6 @@ void vif0Interrupt()
|
|||
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"
|
||||
|
@ -710,37 +444,3 @@ void vif0Write32(u32 mem, u32 value)
|
|||
}
|
||||
/* 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
|
||||
}
|
|
@ -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
|
||||
};
|
|
@ -13,10 +13,9 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
#include "VifDma.h"
|
||||
#include "Vif_Dma.h"
|
||||
#include "GS.h"
|
||||
#include "Gif.h"
|
||||
#include "VUmicro.h"
|
||||
|
@ -28,9 +27,6 @@ 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;
|
||||
|
@ -50,12 +46,6 @@ __forceinline void vif1FLUSH()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void vif1Init()
|
||||
{
|
||||
initNewVif(1);
|
||||
}
|
||||
|
||||
static __forceinline void vif1UNPACK(u32 *data)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
|
@ -1110,31 +682,3 @@ void vif1Write32(u32 mem, u32 value)
|
|||
|
||||
/* 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
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
|
||||
|
|
@ -15,26 +15,16 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
|
||||
#include "VifDma.h"
|
||||
#include "Vif_Dma.h"
|
||||
#include "VUmicro.h"
|
||||
|
||||
int g_vifCycles = 0;
|
||||
|
||||
template void vuExecMicro<0>(u32 addr);
|
||||
template void vuExecMicro<1>(u32 addr);
|
||||
template<const u32 VIFdmanum> void vuExecMicro(u32 addr)
|
||||
{
|
||||
VURegs * VU;
|
||||
|
||||
if (VIFdmanum == 0) {
|
||||
VU = &VU0;
|
||||
vif0FLUSH();
|
||||
}
|
||||
else {
|
||||
VU = &VU1;
|
||||
vif1FLUSH();
|
||||
}
|
||||
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);
|
||||
|
@ -43,17 +33,17 @@ template<const u32 VIFdmanum> void vuExecMicro(u32 addr)
|
|||
|
||||
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;
|
||||
|
||||
/* is DBF flag set in VIF_STAT? */
|
||||
// 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 */
|
||||
// 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 */
|
||||
// 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;
|
||||
}
|
|
@ -82,3 +82,14 @@ template<const u32 VIFdmanum> 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
|
|
@ -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,
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "Common.h"
|
||||
#include "GS.h"
|
||||
#include "Gif.h"
|
||||
#include "VifDma.h"
|
||||
#include "Vif_Dma.h"
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// GIFpath -- the GIFtag Parser
|
||||
|
|
|
@ -805,19 +805,31 @@
|
|||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\Vif0Dma.cpp"
|
||||
RelativePath="..\..\Vif0_Commands.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\Vif1Dma.cpp"
|
||||
RelativePath="..\..\Vif0_Dma.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\VifDma.cpp"
|
||||
RelativePath="..\..\Vif1_Commands.cpp"
|
||||
>
|
||||
</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>
|
||||
<Filter
|
||||
|
|
|
@ -247,7 +247,7 @@ _f void dVifUnpack(int idx, u8 *data, u32 size, bool isFill) {
|
|||
}
|
||||
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]",
|
||||
// _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"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
#include "VifDma.h"
|
||||
#include "Vif_Dma.h"
|
||||
#include "newVif.h"
|
||||
#include "Vif_Unpack.inl"
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include "VifDma.h"
|
||||
#include "Vif_Dma.h"
|
||||
#include "newVif.h"
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
|
Loading…
Reference in New Issue