- Deleted old vif transfer code.
- Deleted Vif_Commands.cpp
- Added Vif_Transfer.cpp


git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2622 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2010-02-22 02:04:55 +00:00
parent a7507d6e4a
commit c144913ede
8 changed files with 145 additions and 878 deletions

View File

@ -230,6 +230,3 @@ extern void mfifoVIF1transfer(int qwc);
extern bool VIF0transfer(u32 *data, int size, bool istag);
extern bool VIF1transfer(u32 *data, int size, bool istag);
extern void vifMFIFOInterrupt();
extern bool vifTransfer0(u32 *data, int size, bool isTag);
extern bool vifTransfer1(u32 *data, int size, bool isTag);

View File

@ -28,120 +28,6 @@ __forceinline void vif0FLUSH()
g_vifCycles += (VU0.cycle - _cycles) * BIAS;
}
bool VIF0transfer(u32 *data, int size, bool istag)
{
return vifTransfer0(data, size, istag);
int ret;
int transferred = vif0.vifstalled ? vif0.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman)
VIF_LOG("VIF0transfer: size %x (vif0.cmd %x)", size, vif0.cmd);
vif0.stallontag = false;
vif0.vifstalled = false;
vif0.vifpacketsize = size;
while (vif0.vifpacketsize > 0)
{
if (vif0.cmd)
{
vif0Regs->stat.VPS = VPS_TRANSFERRING; //Decompression has started
ret = Vif0TransTLB[(vif0.cmd & 0x7f)](data);
data += ret;
vif0.vifpacketsize -= ret;
if (vif0.cmd == 0) vif0Regs->stat.VPS = VPS_IDLE; //We are once again waiting for a new vifcode as the command has cleared
continue;
}
if (vif0.tag.size != 0) Console.WriteLn("no vif0 cmd but tag size is left last cmd read %x", vif0Regs->code);
// if interrupt and new cmd is NOT MARK
if (vif0.irq) break;
vif0.cmd = (data[0] >> 24);
vif0Regs->code = data[0];
vif0Regs->stat.VPS |= VPS_DECODING; //We need to set these (Onimusha needs it)
if ((vif0.cmd & 0x60) == 0x60)
{
vif0UnpackSetup(data);
}
else
{
VIF_LOG("VIFtransfer: cmd %x, num %x, imm %x, size %x", vif0.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size);
if ((vif0.cmd & 0x7f) > 0x4A)
{
if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
{
Console.WriteLn("UNKNOWN VifCmd: %x", vif0.cmd);
vif0Regs->stat.ER1 = true;
vif0.irq++;
}
vif0.cmd = 0;
}
else
{
Vif0CMDTLB[(vif0.cmd & 0x7f)]();
}
}
++data;
--vif0.vifpacketsize;
if ((vif0.cmd & 0x80))
{
vif0.cmd &= 0x7f;
if (!(vif0Regs->err.MII)) //i bit on vifcode and not masked by VIF0_ERR
{
VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif0.cmd, psHu32(INTC_MASK));
++vif0.irq;
if (istag && vif0.tag.size <= vif0.vifpacketsize) vif0.stallontag = true;
if (vif0.tag.size == 0) break;
}
}
} //End of Transfer loop
transferred += size - vif0.vifpacketsize;
g_vifCycles += (transferred >> 2) * BIAS; /* guessing */
// use tag.size because some game doesn't like .cmd
if (vif0.irq && (vif0.tag.size == 0))
{
vif0.vifstalled = true;
if (((vif0Regs->code >> 24) & 0x7f) != 0x7) vif0Regs->stat.VIS = true;
//else Console.WriteLn("VIF0 IRQ on MARK");
// spiderman doesn't break on qw boundaries
vif0.irqoffset = transferred % 4; // cannot lose the offset
if (!istag)
{
transferred = transferred >> 2;
vif0ch->madr += (transferred << 4);
vif0ch->qwc -= transferred;
}
//else Console.WriteLn("Stall on vif0, FromSPR = %x, Vif0MADR = %x Sif0MADR = %x STADR = %x", psHu32(0x1000d010), vif0ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR));
return false;
}
vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
if (vif0.cmd) vif0Regs->stat.VPS |= VPS_WAITING; //Otherwise we wait for the data
if (!istag)
{
transferred = transferred >> 2;
vif0ch->madr +=(transferred << 4);
vif0ch->qwc -= transferred;
}
return true;
}
bool _VIF0chain()
{
u32 *pMem;

View File

@ -34,137 +34,6 @@ __forceinline void vif1FLUSH()
}
}
bool VIF1transfer(u32 *data, int size, bool istag)
{
return vifTransfer1(data, size, istag);
int ret;
int transferred = vif1.vifstalled ? vif1.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman)
// Fixme:
// VIF1 chain mode seems to be pretty buggy. Keep it in synch with a INTC (page 28, ee user manual) fixes Transformers.
// Test chain mode with Harry Potter, Def Jam Fight for New York (+many others, look for flickering graphics).
// Mentioned games break by doing this, but they barely work anyway
// if ( vif1.vifstalled ) hwIntcIrq(VIF1intc);
VIF_LOG("VIF1transfer: size %x (vif1.cmd %x)", size, vif1.cmd);
vif1.irqoffset = 0;
vif1.vifstalled = false;
vif1.stallontag = false;
vif1.vifpacketsize = size;
while (vif1.vifpacketsize > 0)
{
if(vif1Regs->stat.VGW) break;
if (vif1.cmd)
{
vif1Regs->stat.VPS = VPS_TRANSFERRING; //Decompression has started
ret = Vif1TransTLB[vif1.cmd](data);
data += ret;
vif1.vifpacketsize -= ret;
//We are once again waiting for a new vifcode as the command has cleared
if (vif1.cmd == 0) vif1Regs->stat.VPS = VPS_IDLE;
continue;
}
if (vif1.tag.size != 0) DevCon.Error("no vif1 cmd but tag size is left last cmd read %x", vif1Regs->code);
if (vif1.irq) break;
vif1.cmd = (data[0] >> 24);
vif1Regs->code = data[0];
vif1Regs->stat.VPS |= VPS_DECODING;
if ((vif1.cmd & 0x60) == 0x60)
{
vif1UnpackSetup(data);
}
else
{
VIF_LOG("VIFtransfer: cmd %x, num %x, imm %x, size %x", vif1.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, vif1.vifpacketsize);
if ((vif1.cmd & 0x7f) > 0x51)
{
if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
{
Console.WriteLn("UNKNOWN VifCmd: %x", vif1.cmd);
vif1Regs->stat.ER1 = true;
vif1.irq++;
}
vif1.cmd = 0;
}
else Vif1CMDTLB[(vif1.cmd & 0x7f)]();
}
++data;
--vif1.vifpacketsize;
if ((vif1.cmd & 0x80))
{
vif1.cmd &= 0x7f;
if (!(vif1Regs->err.MII)) //i bit on vifcode and not masked by VIF1_ERR
{
// Fixme: This seems to be an important part of the VIF1 chain mode issue (see Fixme above :p )
//Console.Warning("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif1.cmd, psHu32(INTC_MASK));
VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif1.cmd, psHu32(INTC_MASK));
++vif1.irq;
if (istag && vif1.tag.size <= vif1.vifpacketsize) vif1.stallontag = true;
if (vif1.tag.size == 0) break;
}
}
if(!vif1.cmd) vif1Regs->stat.VPS = VPS_IDLE;
if((vif1Regs->stat.VGW) || vif1.vifstalled == true) break;
} // End of Transfer loop
transferred += size - vif1.vifpacketsize;
g_vifCycles += (transferred >> 2) * BIAS; /* guessing */
vif1.irqoffset = transferred % 4; // cannot lose the offset
if (vif1.irq && vif1.cmd == 0)
{
vif1.vifstalled = true;
if (((vif1Regs->code >> 24) & 0x7f) != 0x7) vif1Regs->stat.VIS = true; // Note: commenting this out fixes WALL-E
if (vif1ch->qwc == 0 && (vif1.irqoffset == 0 || istag == 1)) vif1.inprogress &= ~0x1;
// spiderman doesn't break on qw boundaries
if (istag) return false;
transferred = transferred >> 2;
vif1ch->madr += (transferred << 4);
vif1ch->qwc -= transferred;
if ((vif1ch->qwc == 0) && (vif1.irqoffset == 0)) vif1.inprogress = 0;
//Console.WriteLn("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR));
return false;
}
vif1Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
if (vif1.cmd) vif1Regs->stat.VPS = VPS_WAITING; //Otherwise we wait for the data
if (!istag)
{
transferred = transferred >> 2;
vif1ch->madr +=(transferred << 4);
vif1ch->qwc -= transferred;
}
if (vif1Regs->stat.VGW) vif1.vifstalled = true;
if (vif1ch->qwc == 0 && (vif1.irqoffset == 0 || istag == 1)) vif1.inprogress &= ~0x1;
return (!(vif1.vifstalled));
}
void vif1TransferFromMemory()
{
int size;
@ -255,11 +124,6 @@ bool _VIF1chain()
return VIF1transfer(pMem, vif1ch->qwc * 4, false);
}
bool _chainVIF1()
{
return vif1.done; // Return Done
}
__forceinline void vif1SetupTransfer()
{
tDMA_TAG *ptag;

View File

@ -69,6 +69,24 @@ static _f void vuExecMicro(int idx, u32 addr) {
else vu1ExecMicro(addr);
}
u8 schedulepath3msk = 0;
void Vif1MskPath3() {
vif1Regs->mskpath3 = schedulepath3msk & 0x1;
//Console.WriteLn("VIF MSKPATH3 %x", vif1Regs->mskpath3);
if (!vif1Regs->mskpath3) {
//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(DMAC_GIF, 4);
}
else gifRegs->stat.M3P = true;
schedulepath3msk = 0;
}
//------------------------------------------------------------------
// Vif0/Vif1 Code Implementations
//------------------------------------------------------------------
@ -80,7 +98,6 @@ vifOp(vifCode_Base) {
return 0;
}
template<int idx> int __fastcall vifTrans_DirectHL(u32 *data);
template<int idx> _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) {
pass1 {
vif1Only();
@ -447,107 +464,3 @@ int (__fastcall *vif1Code[128])(int pass, u32 *data) = {
vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1>, /*0x70*/
vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> /*0x78*/
};
//------------------------------------------------------------------
// Vif0/Vif1 Code Transfer Interpreter
//------------------------------------------------------------------
// Runs the next vifCode if its the Mark command
_vifT void runMark(u32* &data) {
if (vifX.vifpacketsize && (((data[0]>>24)&0x7f)==7)) {
vifX.vifpacketsize--;
vifXCode[7](0, data++);
DevCon.WriteLn("Vif%d: Running Mark on I-bit", idx);
}
}
// Returns 1 if i-bit && finished vifcode && i-bit not masked && next vifcode != MARK
_vifT bool analyzeIbit(u32* &data, int iBit, bool isTag) {
if (iBit && !vifX.cmd && !vifXRegs->err.MII) {
//DevCon.WriteLn("Vif I-Bit IRQ");
vifX.irq++;
if (isTag) {
//DevCon.WriteLn("Vif isTag Hack!?");
vifX.stallontag = true;
}
runMark<idx>(data);
return 1;
}
return 0;
}
// Interprets packet
_vifT void vifTransferLoop(u32* &data, bool isTag) {
u32& tSize = vifX.tag.size;
u32& pSize = vifX.vifpacketsize;
int iBit = vifX.cmd >> 7;
vifXRegs->stat.VPS |= VPS_TRANSFERRING;
vifXRegs->stat.ER1 = false;
while (pSize > 0 && !vifX.vifstalled) {
if(!vifX.cmd) { // Get new VifCode
vifXRegs->code = data[0];
vifX.cmd = data[0] >> 24;
iBit = data[0] >> 31;
vifXCode[vifX.cmd & 0x7f](0, data);
data++; pSize--;
if (analyzeIbit<idx>(data, iBit, isTag)) break;
continue;
}
int ret = vifXCode[vifX.cmd & 0x7f](1, data);
data += ret;
pSize -= ret;
if (analyzeIbit<idx>(data, iBit, isTag)) break;
}
if (vifX.cmd) vifXRegs->stat.VPS = VPS_WAITING;
else vifXRegs->stat.VPS = VPS_IDLE;
}
_vifT _f bool vifTransfer(u32 *data, int size, bool isTag) {
// irqoffset necessary to add up the right qws, or else will spin (spiderman)
int transferred = vifX.vifstalled ? vifX.irqoffset : 0;
vifX.irqoffset = 0;
vifX.vifstalled = false;
vifX.stallontag = false;
vifX.vifpacketsize = size;
vifTransferLoop<idx>(data, isTag);
transferred += size - vifX.vifpacketsize;
g_vifCycles +=(transferred >> 2) * BIAS; /* guessing */
vifX.irqoffset = transferred % 4; // cannot lose the offset
if (!isTag) {
transferred = transferred >> 2;
vifXch->madr +=(transferred << 4);
vifXch->qwc -= transferred;
}
if (!vifXch->qwc && (!vifX.irqoffset || isTag)) vifX.inprogress &= ~0x1;
if (vifX.irq && vifX.cmd == 0) {
//DevCon.WriteLn("Vif IRQ!");
vifX.vifstalled = true;
vifXRegs->stat.VIS = true; // Note: commenting this out fixes WALL-E?
// spiderman doesn't break on qw boundaries
if (isTag) return false;
if (!vifXch->qwc && !vifX.irqoffset) vifX.inprogress = 0;
return false;
}
return !vifX.vifstalled;
}
bool vifTransfer0(u32 *data, int size, bool isTag) {
return vifTransfer<0>(data, size, isTag);
}
bool vifTransfer1(u32 *data, int size, bool isTag) {
return vifTransfer<1>(data, size, isTag);
}

View File

@ -1,514 +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/>.
*/
#include "PrecompiledHeader.h"
#include "Common.h"
#include "GS.h"
#include "Gif.h"
#include "Vif_Dma.h"
#include "newVif.h"
#include "VUmicro.h"
#define vif1Only() { if (!idx) { vifCMD_Null<idx>(); return; } }
#define vif1Only_() { if (!idx) { return vifTrans_Null<idx>(NULL); } }
_vifT void vifCMD_Null();
//------------------------------------------------------------------
// Vif0/Vif1 Misc Functions
//------------------------------------------------------------------
static _f void vifFlush(int idx) {
if (!idx) vif0FLUSH();
else vif1FLUSH();
}
static _f void vuExecMicro(int idx, u32 addr) {
VURegs* VU = nVif[idx].VU;
vifFlush(idx);
if (VU->vifRegs->itops > (idx ? 0x3ffu : 0xffu)) {
Console.WriteLn("VIF%d ITOP overrun! %x", idx, VU->vifRegs->itops);
VU->vifRegs->itops &= (idx ? 0x3ffu : 0xffu);
}
VU->vifRegs->itop = VU->vifRegs->itops;
if (idx) {
// in case we're handling a VIF1 execMicro, set the top with the tops value
VU->vifRegs->top = VU->vifRegs->tops & 0x3ff;
// is DBF flag set in VIF_STAT?
if (VU->vifRegs->stat.DBF) {
// it is, so set tops with base, and clear the stat DBF flag
VU->vifRegs->tops = VU->vifRegs->base;
VU->vifRegs->stat.DBF = false;
}
else {
// it is not, so set tops with base + offset, and set stat DBF flag
VU->vifRegs->tops = VU->vifRegs->base + VU->vifRegs->ofst;
VU->vifRegs->stat.DBF = true;
}
}
if (!idx) vu0ExecMicro(addr);
else vu1ExecMicro(addr);
}
u8 schedulepath3msk = 0;
void Vif1MskPath3() {
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(DMAC_GIF, 4);
}
schedulepath3msk = 0;
}
//------------------------------------------------------------------
// Vif0/Vif1 Data Transfer Commands
//------------------------------------------------------------------
_vifT int __fastcall vifTrans_Null(u32 *data)
{
Console.WriteLn("VIF%d Shouldn't go here CMD = %x", idx, vifXRegs->code);
vifX.cmd = 0;
return 0;
}
_vifT int __fastcall vifTrans_STMask(u32 *data)
{
vifXRegs->mask = data[0];
VIF_LOG("STMASK == %x", vifXRegs->mask);
vifX.tag.size = 0;
vifX.cmd = 0;
return 1;
}
_vifT int __fastcall vifTrans_STRow(u32 *data)
{
int ret;
u32* rows = idx ? g_vifmask.Row1 : g_vifmask.Row0;
u32* pmem = &vifXRegs->r0 + (vifX.tag.addr << 2);
u32* pmem2 = rows + vifX.tag.addr;
ret = min(4 - vifX.tag.addr, vifX.vifpacketsize);
pxAssume(vifX.tag.addr < 4);
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
}
vifX.tag.addr += ret;
vifX.tag.size -= ret;
if (!vifX.tag.size) vifX.cmd = 0;
return ret;
}
_vifT int __fastcall vifTrans_STCol(u32 *data)
{
int ret;
u32* cols = idx ? g_vifmask.Col1 : g_vifmask.Col0;
u32* pmem = &vifXRegs->c0 + (vifX.tag.addr << 2);
u32* pmem2 = cols + vifX.tag.addr;
ret = min(4 - vifX.tag.addr, vifX.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
}
vifX.tag.addr += ret;
vifX.tag.size -= ret;
if (!vifX.tag.size) vifX.cmd = 0;
return ret;
}
_f void _vifTrans_MPG(int idx, u32 addr, u32 *data, int size)
{
VURegs& VUx = idx ? VU1 : VU0;
pxAssume(VUx.Micro > 0);
if (memcmp(VUx.Micro + addr, data, size << 2)) {
if (!idx) CpuVU0->Clear(addr, size << 2); // Clear before writing!
else CpuVU1->Clear(addr, size << 2); // Clear before writing!
memcpy_fast(VUx.Micro + addr, data, size << 2);
}
}
_vifT int __fastcall vifTrans_MPG(u32 *data)
{
if (vifX.vifpacketsize < vifX.tag.size) {
if((vifX.tag.addr + vifX.vifpacketsize) > (idx ? 0x4000 : 0x1000)) {
DevCon.Warning("Vif%d MPG Split Overflow", idx);
}
_vifTrans_MPG(idx, vifX.tag.addr, data, vifX.vifpacketsize);
vifX.tag.addr += vifX.vifpacketsize << 2;
vifX.tag.size -= vifX.vifpacketsize;
return vifX.vifpacketsize;
}
else {
int ret;
if((vifX.tag.addr + vifX.tag.size) > (idx ? 0x4000 : 0x1000)) {
DevCon.Warning("Vif%d MPG Split Overflow", idx);
}
_vifTrans_MPG(idx, vifX.tag.addr, data, vifX.tag.size);
ret = vifX.tag.size;
vifX.tag.size = 0;
vifX.cmd = 0;
return ret;
}
}
_vifT int __fastcall vifTrans_Unpack(u32 *data)
{
return nVifUnpack(idx, (u8*)data);
}
// Dummy GIF-TAG Packet to Guarantee Count = 1
extern __aligned16 u32 nloop0_packet[4];
static __aligned16 u32 splittransfer[4];
static u32 splitptr = 0;
_vifT int __fastcall vifTrans_DirectHL(u32 *data)
{
vif1Only_();
int ret = 0;
if ((vif1.cmd & 0x7f) == 0x51) {
if (gif->chcr.STR && (!vif1Regs->mskpath3 && (Path3progress == IMAGE_MODE))) {
vif1Regs->stat.VGW = true; // PATH3 is in image mode, so wait for end of transfer
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) {
ret = vif1.vifpacketsize;
while (ret > 0) { // Not a full QW left in the buffer, saving left over data
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;
}
//------------------------------------------------------------------
// Vif0/Vif1 Commands (VifCodes)
//------------------------------------------------------------------
_vifT void vifCMD_Base()
{
vif1Only();
vif1Regs->base = vif1Regs->code & 0x3ff;
vif1.cmd &= ~0x7f;
}
_vifT void vifCMD_DirectHL()
{
vif1Only();
int vifImm = (u16)vif1Regs->code;
if(!vifImm) vif1.tag.size = 65536 << 2;
else vif1.tag.size = vifImm << 2;
}
_vifT void vifCMD_FlushE()
{
vifFlush(idx);
vifX.cmd &= ~0x7f;
}
_vifT void vifCMD_Flush()
{
vif1Only();
vifFlush(idx);
vifX.cmd &= ~0x7f;
}
_vifT void vifCMD_FlushA()
{
vif1Only();
vifFlush(idx);
// Gif is already transferring so wait for it.
if (((Path3progress != STOPPED_MODE) || !vif1Regs->mskpath3) && gif->chcr.STR) {
vif1Regs->stat.VGW = true;
CPU_INT(DMAC_GIF, 4);
}
vifX.cmd &= ~0x7f;
}
_vifT void vifCMD_ITop()
{
vifXRegs->itops = vifXRegs->code & 0x3ff;
vifX.cmd &= ~0x7f;
}
_vifT void vifCMD_Mark()
{
vifXRegs->mark = (u16)vifXRegs->code;
vifXRegs->stat.MRK = true;
vifX.cmd &= ~0x7f;
}
_vifT void vifCMD_MPG()
{
vifFlush(idx);
int vifNum = (u8)(vifXRegs->code >> 16);
if(!vifNum) vifNum = 256;
vifX.tag.addr = (u16)((vifXRegs->code) << 3) & (idx ? 0x3fff : 0xfff);
vifX.tag.size = vifNum * 2;
}
_vifT void vifCMD_MSCALF()
{
vuExecMicro(idx, (u16)(vifXRegs->code) << 3);
vifX.cmd &= ~0x7f;
}
_vifT void vifCMD_MSCNT()
{
vuExecMicro(idx, -1);
vifX.cmd &= ~0x7f;
}
_vifT void vifCMD_MskPath3()
{
vif1Only();
if (vif1ch->chcr.STR) {
schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1);
vif1.vifstalled = true;
}
else {
schedulepath3msk = (vif1Regs->code >> 15) & 0x1;
Vif1MskPath3();
}
vif1.cmd &= ~0x7f;
}
_vifT void vifCMD_Nop()
{
vifX.cmd &= ~0x7f;
}
_vifT void vifCMD_Null() // invalid opcode
{
// if ME1, then force the vif to interrupt
if (!(vifXRegs->err.ME1)) //Ignore vifcode and tag mismatch error
{
Console.WriteLn("Vif%d: Unknown VifCmd! [%x]", idx, vifX.cmd);
vifXRegs->stat.ER1 = true;
vifX.irq++;
}
if (!idx) vifX.cmd &= ~0x7f; // FixMe: vif0/vif1 should do the same thing!?
else vifX.cmd = 0;
}
_vifT void vifCMD_Offset()
{
vif1Only();
vif1Regs->stat.DBF = false;
vif1Regs->ofst = vif1Regs->code & 0x3ff;
vif1Regs->tops = vif1Regs->base;
vif1.cmd &= ~0x7f;
}
_vifT void vifCMD_STCycl()
{
vifXRegs->cycle.cl = (u8)(vifXRegs->code);
vifXRegs->cycle.wl = (u8)(vifXRegs->code >> 8);
vifX.cmd &= ~0x7f;
}
_vifT void vifCMD_STMask()
{
vifX.tag.size = 1;
}
_vifT void vifCMD_STMod()
{
vifXRegs->mode = vifXRegs->code & 0x3;
vifX.cmd &= ~0x7f;
}
_vifT void vifCMD_STRowCol() // STROW / STCOL
{
vifX.tag.addr = 0;
vifX.tag.size = 4;
}
//------------------------------------------------------------------
// Vif0/Vif1 Data Transfer Tables
//------------------------------------------------------------------
int (__fastcall *Vif0TransTLB[128])(u32 *data) = {
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x00*/
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x08*/
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x10*/
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x18*/
vifTrans_STMask<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x20*/
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x28*/
vifTrans_STRow<0> , vifTrans_STCol<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x30*/
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x38*/
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x40*/
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_MPG<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x48*/
vifTrans_DirectHL<0>, vifTrans_DirectHL<0>, vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x50*/
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x58*/
vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Null<0>, /*0x60*/
vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0>, /*0x68*/
vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Null<0>, /*0x70*/
vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Null<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> /*0x78*/
};
int (__fastcall *Vif1TransTLB[128])(u32 *data) = {
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x00*/
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x08*/
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x10*/
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x18*/
vifTrans_STMask<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x20*/
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x28*/
vifTrans_STRow<1> , vifTrans_STCol<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x30*/
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x38*/
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x40*/
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_MPG<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x48*/
vifTrans_DirectHL<1>, vifTrans_DirectHL<1>, vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x50*/
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x58*/
vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Null<1>, /*0x60*/
vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1>, /*0x68*/
vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Null<1>, /*0x70*/
vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Null<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> /*0x78*/
};
//------------------------------------------------------------------
// Vif0/Vif1 CMD Tables
//------------------------------------------------------------------
void (*Vif0CMDTLB[82])() = {
vifCMD_Nop<0> , vifCMD_STCycl<0> , vifCMD_Offset<0>, vifCMD_Base<0> , vifCMD_ITop<0> , vifCMD_STMod<0> , vifCMD_MskPath3<0>, vifCMD_Mark<0> , /*0x00*/
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x08*/
vifCMD_FlushE<0> , vifCMD_Flush<0> , vifCMD_Null<0> , vifCMD_FlushA<0>, vifCMD_MSCALF<0>, vifCMD_MSCALF<0>, vifCMD_Null<0> , vifCMD_MSCNT<0>, /*0x10*/
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x18*/
vifCMD_STMask<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x20*/
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x28*/
vifCMD_STRowCol<0>, vifCMD_STRowCol<0>, vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x30*/
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x38*/
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x40*/
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_MPG<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x48*/
vifCMD_DirectHL<0>, vifCMD_DirectHL<0>
};
void (*Vif1CMDTLB[82])() = {
vifCMD_Nop<1> , vifCMD_STCycl<1> , vifCMD_Offset<1>, vifCMD_Base<1> , vifCMD_ITop<1> , vifCMD_STMod<1> , vifCMD_MskPath3<1>, vifCMD_Mark<1> , /*0x00*/
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x08*/
vifCMD_FlushE<1> , vifCMD_Flush<1> , vifCMD_Null<1> , vifCMD_FlushA<1>, vifCMD_MSCALF<1>, vifCMD_MSCALF<1>, vifCMD_Null<1> , vifCMD_MSCNT<1>, /*0x10*/
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x18*/
vifCMD_STMask<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x20*/
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x28*/
vifCMD_STRowCol<1>, vifCMD_STRowCol<1>, vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x30*/
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x38*/
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x40*/
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_MPG<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x48*/
vifCMD_DirectHL<1>, vifCMD_DirectHL<1>
};

View File

@ -60,10 +60,8 @@ extern void Vif1MskPath3();
extern void vif1Write32(u32 mem, u32 value);
extern void vif1Reset();
extern void (*Vif0CMDTLB[82])();
extern void (*Vif1CMDTLB[82])();
extern int (__fastcall *Vif0TransTLB[128])(u32 *data);
extern int (__fastcall *Vif1TransTLB[128])(u32 *data);
extern int (__fastcall *vif0Code[128])(int pass, u32 *data);
extern int (__fastcall *vif1Code[128])(int pass, u32 *data);
__forceinline static int _limit(int a, int max)
{

123
pcsx2/Vif_Transfer.cpp Normal file
View File

@ -0,0 +1,123 @@
/* 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 "newVif.h"
//------------------------------------------------------------------
// VifCode Transfer Interpreter (Vif0/Vif1)
//------------------------------------------------------------------
// Runs the next vifCode if its the Mark command
_vifT void runMark(u32* &data) {
if (vifX.vifpacketsize && (((data[0]>>24)&0x7f)==7)) {
vifX.vifpacketsize--;
vifXCode[7](0, data++);
DevCon.WriteLn("Vif%d: Running Mark on I-bit", idx);
}
}
// Returns 1 if i-bit && finished vifcode && i-bit not masked && next vifcode != MARK
_vifT bool analyzeIbit(u32* &data, int iBit, bool isTag) {
if (iBit && !vifX.cmd && !vifXRegs->err.MII) {
//DevCon.WriteLn("Vif I-Bit IRQ");
vifX.irq++;
if (isTag) {
//DevCon.WriteLn("Vif isTag Hack!?");
vifX.stallontag = true;
}
runMark<idx>(data);
return 1;
}
return 0;
}
// Interprets packet
_vifT void vifTransferLoop(u32* &data, bool isTag) {
u32& tSize = vifX.tag.size;
u32& pSize = vifX.vifpacketsize;
int iBit = vifX.cmd >> 7;
vifXRegs->stat.VPS |= VPS_TRANSFERRING;
vifXRegs->stat.ER1 = false;
while (pSize > 0 && !vifX.vifstalled) {
if(!vifX.cmd) { // Get new VifCode
vifXRegs->code = data[0];
vifX.cmd = data[0] >> 24;
iBit = data[0] >> 31;
vifXCode[vifX.cmd & 0x7f](0, data);
data++; pSize--;
if (analyzeIbit<idx>(data, iBit, isTag)) break;
continue;
}
int ret = vifXCode[vifX.cmd & 0x7f](1, data);
data += ret;
pSize -= ret;
if (analyzeIbit<idx>(data, iBit, isTag)) break;
}
if (vifX.cmd) vifXRegs->stat.VPS = VPS_WAITING;
else vifXRegs->stat.VPS = VPS_IDLE;
}
_vifT _f bool vifTransfer(u32 *data, int size, bool isTag) {
// irqoffset necessary to add up the right qws, or else will spin (spiderman)
int transferred = vifX.vifstalled ? vifX.irqoffset : 0;
vifX.irqoffset = 0;
vifX.vifstalled = false;
vifX.stallontag = false;
vifX.vifpacketsize = size;
vifTransferLoop<idx>(data, isTag);
transferred += size - vifX.vifpacketsize;
g_vifCycles +=(transferred >> 2) * BIAS; /* guessing */
vifX.irqoffset = transferred % 4; // cannot lose the offset
if (!isTag) {
transferred = transferred >> 2;
vifXch->madr +=(transferred << 4);
vifXch->qwc -= transferred;
}
if (!vifXch->qwc && (!vifX.irqoffset || isTag)) vifX.inprogress &= ~0x1;
if (vifX.irq && vifX.cmd == 0) {
//DevCon.WriteLn("Vif IRQ!");
vifX.vifstalled = true;
vifXRegs->stat.VIS = true; // Note: commenting this out fixes WALL-E?
// spiderman doesn't break on qw boundaries
if (isTag) return false;
if (!vifXch->qwc && !vifX.irqoffset) vifX.inprogress = 0;
return false;
}
return !vifX.vifstalled;
}
bool VIF0transfer(u32 *data, int size, bool istag) {
return vifTransfer<0>(data, size, istag);
}
bool VIF1transfer(u32 *data, int size, bool istag) {
return vifTransfer<1>(data, size, istag);
}

View File

@ -829,11 +829,11 @@
>
</File>
<File
RelativePath="..\..\Vif_Commands.cpp"
RelativePath="..\..\Vif_Dma.h"
>
</File>
<File
RelativePath="..\..\Vif_Dma.h"
RelativePath="..\..\Vif_Transfer.cpp"
>
</File>
<Filter