diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index 58e53cbe73..1aff870d7d 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -36,6 +36,9 @@ __forceinline void vif1FLUSH() bool VIF1transfer(u32 *data, int size, bool istag) { + extern bool vif1Transfer_(u32 *data, int size, bool istag); + return vif1Transfer_(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) diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp new file mode 100644 index 0000000000..86d7185ba2 --- /dev/null +++ b/pcsx2/Vif_Codes.cpp @@ -0,0 +1,544 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2009 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#include "PrecompiledHeader.h" +#include "Common.h" +#include "GS.h" +#include "Gif.h" +#include "Vif_Dma.h" +#include "newVif.h" +#include "VUmicro.h" + +#define vifOp(vifCodeName) _vifT int __fastcall vifCodeName(int pass, u32 *data) +#define pass1 if (pass == 0) +#define pass2 if (pass == 1) +#define pass3 if (pass == 2) +#define vif1Only() { if (!idx) return vifCode_Null(pass, (u32*)data); } +vifOp(vifCode_Null); + +//------------------------------------------------------------------ +// Vif0/Vif1 Misc Functions +//------------------------------------------------------------------ + +_f void vifFlush(int idx) { + if (!idx) vif0FLUSH(); + else vif1FLUSH(); +} + +_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); +} + +//------------------------------------------------------------------ +// Vif0/Vif1 Code Implementations +//------------------------------------------------------------------ + +vifOp(vifCode_Base) { + vif1Only(); + pass1 { vif1Regs->base = vif1Regs->code & 0x3ff; vif1.cmd = 0; } + pass3 { DevCon.WriteLn("vifCode_Base"); } + return 0; +} + +template int __fastcall vifTrans_DirectHL(u32 *data); +template _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) { + pass1 { + vif1Only(); + int vifImm = (u16)vif1Regs->code; + vif1.tag.size = vifImm ? (vifImm*4) : (65536*4); + return 1; + } + pass2 { + vif1Only(); + //return vifTrans_DirectHL((u32*)data); + + if (isDirectHL) { + if (gif->chcr.STR && (!vif1Regs->mskpath3 && (Path3progress == IMAGE_MODE))) { + DevCon.WriteLn("DirectHL: Waiting for Path3 to finish!"); + vif1Regs->stat.VGW = true; // PATH3 is in image mode, so wait for end of transfer + vif1.vifstalled = true; + return 0; + } + } + + Registers::Freeze(); + nVifStruct& v = nVif[1]; + const int ret = aMin(vif1.vifpacketsize, vif1.tag.size); + s32 size = ret << 2; + + if (ret == v.vif->tag.size) { // Full Transfer + if (v.bSize) { // Last transfer was partial + memcpy_fast(&v.buffer[v.bSize], data, size); + v.bSize += size; + data = v.buffer; + size = v.bSize; + } + if (!size) { DevCon.WriteLn("Path2: No Data Transfer?"); } + const uint count = GetMTGS().PrepDataPacket(GIF_PATH_2, data, size >> 4); + memcpy_fast(GetMTGS().GetDataPacketPtr(), data, count << 4); + GetMTGS().SendDataPacket(); + vif1.tag.size = 0; + vif1.cmd = 0; + v.bSize = 0; + gifRegs->stat.clear_flags(GIF_STAT_APATH2 | GIF_STAT_OPH); + } + else { // Partial Transfer + DevCon.WriteLn("DirectHL: Partial Transfer1 [%d]", size); + gifRegs->stat.set_flags(GIF_STAT_APATH2 | GIF_STAT_OPH); + memcpy_fast(&v.buffer[v.bSize], data, size); + v.bSize += size; + vif1.tag.size -= ret; + } + + Registers::Freeze(); + return ret; + } + return 0; +} + +vifOp(vifCode_Direct) { + pass3 { DevCon.WriteLn("vifCode_Direct"); } + return _vifCode_Direct(pass, (u8*)data, 0); +} + +vifOp(vifCode_DirectHL) { + pass3 { DevCon.WriteLn("vifCode_DirectHL"); } + return _vifCode_Direct(pass, (u8*)data, 1); +} + +// ToDo: FixMe +vifOp(vifCode_Flush) { + vif1Only(); + pass1 { vifFlush(idx); vifX.cmd = 0; } + pass3 { DevCon.WriteLn("vifCode_Flush"); } + return 0; +} + +// ToDo: FixMe +vifOp(vifCode_FlushA) { + vif1Only(); + pass1 { + // 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); + } + vifFlush(idx); + vifX.cmd = 0; + } + pass3 { DevCon.WriteLn("vifCode_FlushA"); } + return 0; +} + +// ToDo: FixMe +vifOp(vifCode_FlushE) { + pass1 { vifFlush(idx); vifX.cmd = 0; } + pass3 { DevCon.WriteLn("vifCode_FlushE"); } + return 0; +} + +vifOp(vifCode_ITop) { + pass1 { vifXRegs->itops = vifXRegs->code & 0x3ff; vifX.cmd = 0; } + pass3 { DevCon.WriteLn("vifCode_ITop"); } + return 0; +} + +vifOp(vifCode_Mark) { + pass1 { + vifXRegs->mark = (u16)vifXRegs->code; + vifXRegs->stat.MRK = true; + vifX.cmd = 0; + } + pass3 { DevCon.WriteLn("vifCode_Mark"); } + return 0; +} + +_f void _vifCode_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); + } +} + +vifOp(vifCode_MPG) { + pass1 { + int vifNum = (u8)(vifXRegs->code >> 16); + vifX.tag.addr = (u16)(vifXRegs->code << 3) & (idx ? 0x3fff : 0xfff); + vifX.tag.size = vifNum ? (vifNum*2) : 512; + return 1; + } + pass2 { + vifFlush(idx); + if (vifX.vifpacketsize < vifX.tag.size) { // Partial Transfer + if((vifX.tag.addr + vifX.vifpacketsize) > (idx ? 0x4000 : 0x1000)) { + DevCon.Warning("Vif%d MPG Split Overflow", idx); + } + _vifCode_MPG(idx, vifX.tag.addr, data, vifX.vifpacketsize); + vifX.tag.addr += vifX.vifpacketsize << 2; + vifX.tag.size -= vifX.vifpacketsize; + return vifX.vifpacketsize; + } + else { // Full Transfer + if((vifX.tag.addr + vifX.tag.size) > (idx ? 0x4000 : 0x1000)) { + DevCon.Warning("Vif%d MPG Split Overflow", idx); + } + _vifCode_MPG(idx, vifX.tag.addr, data, vifX.tag.size); + int ret = vifX.tag.size; + vifX.tag.size = 0; + vifX.cmd = 0; + return ret; + } + } + pass3 { DevCon.WriteLn("vifCode_MPG"); } + return 0; +} + +vifOp(vifCode_MSCAL) { + pass1 { vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0; } + pass3 { DevCon.WriteLn("vifCode_MSCAL"); } + return 0; +} + +vifOp(vifCode_MSCALF) { + pass1 { vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0; } + pass3 { DevCon.WriteLn("vifCode_MSCALF"); } + return 0; +} + +vifOp(vifCode_MSCNT) { + pass1 { vuExecMicro(idx, -1); vifX.cmd = 0; } + pass3 { DevCon.WriteLn("vifCode_MSCNT"); } + return 0; +} + +// ToDo: FixMe +vifOp(vifCode_MskPath3) { + vif1Only(); + pass1 { + if (vif1ch->chcr.STR) { + schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1); + vif1.vifstalled = true; + } + else { + schedulepath3msk = (vif1Regs->code >> 15) & 0x1; + Vif1MskPath3(); + } + vifX.cmd = 0; + } + pass3 { DevCon.WriteLn("vifCode_MskPath3"); } + return 0; +} + +vifOp(vifCode_Nop) { + pass1 { vifX.cmd = 0; } + pass3 { DevCon.WriteLn("vifCode_Nop"); } + return 0; +} + +// ToDo: Review Flags +vifOp(vifCode_Null) { + pass1 { + // 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.vifstalled = true; + //vifX.irq++; + } + vifX.cmd = 0; + } + pass2 { Console.Error("Vif%d bad vifcode! [CMD = %x]", idx, vifX.cmd); } + pass3 { DevCon.WriteLn("vifCode_Null"); } + return 0; +} + +vifOp(vifCode_Offset) { + vif1Only(); + pass1 { + vif1Regs->stat.DBF = false; + vif1Regs->ofst = vif1Regs->code & 0x3ff; + vif1Regs->tops = vif1Regs->base; + vifX.cmd = 0; + } + pass3 { DevCon.WriteLn("vifCode_Offset"); } + return 0; +} + +template _f int _vifCode_STColRow(u32* data, u32* pmem1, u32* pmem2) { + int ret; + ret = min(4 - vifX.tag.addr, vifX.vifpacketsize); + pxAssume(vifX.tag.addr < 4); + pxAssume(ret > 0); + + switch (ret) { + case 4: + pmem1[12] = data[3]; + pmem2[3] = data[3]; + case 3: + pmem1[8] = data[2]; + pmem2[2] = data[2]; + case 2: + pmem1[4] = data[1]; + pmem2[1] = data[1]; + case 1: + pmem1[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; +} + +vifOp(vifCode_STCol) { + pass1 { + vifX.tag.addr = 0; + vifX.tag.size = 4; + return 1; + } + pass2 { + u32* cols = idx ? g_vifmask.Col1 : g_vifmask.Col0; + u32* pmem1 = &vifXRegs->c0 + (vifX.tag.addr << 2); + u32* pmem2 = cols + vifX.tag.addr; + return _vifCode_STColRow(data, pmem1, pmem2); + } + pass3 { DevCon.WriteLn("vifCode_STCol"); } + return 0; +} + +vifOp(vifCode_STRow) { + pass1 { + vifX.tag.addr = 0; + vifX.tag.size = 4; + return 1; + } + pass2 { + u32* rows = idx ? g_vifmask.Row1 : g_vifmask.Row0; + u32* pmem1 = &vifXRegs->r0 + (vifX.tag.addr << 2); + u32* pmem2 = rows + vifX.tag.addr; + return _vifCode_STColRow(data, pmem1, pmem2); + } + pass3 { DevCon.WriteLn("vifCode_STRow"); } + return 0; +} + +vifOp(vifCode_STCycl) { + pass1 { + vifXRegs->cycle.cl = (u8)(vifXRegs->code); + vifXRegs->cycle.wl = (u8)(vifXRegs->code >> 8); + vifX.cmd = 0; + } + pass3 { DevCon.WriteLn("vifCode_STCycl"); } + return 0; +} + +vifOp(vifCode_STMask) { + pass1 { vifX.tag.size = 1; } + pass2 { vifXRegs->mask = data[0]; vifX.cmd = 0; } + pass3 { DevCon.WriteLn("vifCode_STMask"); } + return 1; +} + +vifOp(vifCode_STMod) { + pass1 { vifXRegs->mode = vifXRegs->code & 0x3; vifX.cmd = 0; } + pass3 { DevCon.WriteLn("vifCode_STMod"); } + return 0; +} + +vifOp(vifCode_Unpack) { + pass1 { + if (!idx) vif0UnpackSetup(data); + else vif1UnpackSetup(data); + return 1; + } + pass2 { return nVifUnpack(idx, (u8*)data); } + pass3 { DevCon.WriteLn("vifCode_Unpack"); } + return 0; +} + +//------------------------------------------------------------------ +// Vif0/Vif1 Code Tables +//------------------------------------------------------------------ + +int (__fastcall *vif0Code[128])(int pass, u32 *data) = { + vifCode_Nop<0> , vifCode_STCycl<0> , vifCode_Offset<0> , vifCode_Base<0> , vifCode_ITop<0> , vifCode_STMod<0> , vifCode_MskPath3<0>, vifCode_Mark<0>, /*0x00*/ + vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0>, /*0x08*/ + vifCode_FlushE<0> , vifCode_Flush<0> , vifCode_Null<0> , vifCode_FlushA<0> , vifCode_MSCAL<0> , vifCode_MSCALF<0> , vifCode_Null<0> , vifCode_MSCNT<0>, /*0x10*/ + vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0>, /*0x18*/ + vifCode_STMask<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0>, /*0x20*/ + vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0>, /*0x28*/ + vifCode_STRow<0> , vifCode_STCol<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0>, /*0x30*/ + vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0>, /*0x38*/ + vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0>, /*0x40*/ + vifCode_Null<0> , vifCode_Null<0> , vifCode_MPG<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0>, /*0x48*/ + vifCode_Direct<0> , vifCode_DirectHL<0>, vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0>, /*0x50*/ + vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0> , vifCode_Null<0>, /*0x58*/ + vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Null<0>, /*0x60*/ + vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0>, /*0x68*/ + vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Null<0>, /*0x70*/ + vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Null<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> , vifCode_Unpack<0> /*0x78*/ +}; + +int (__fastcall *vif1Code[128])(int pass, u32 *data) = { + vifCode_Nop<1> , vifCode_STCycl<1> , vifCode_Offset<1> , vifCode_Base<1> , vifCode_ITop<1> , vifCode_STMod<1> , vifCode_MskPath3<1>, vifCode_Mark<1>, /*0x00*/ + vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1>, /*0x08*/ + vifCode_FlushE<1> , vifCode_Flush<1> , vifCode_Null<1> , vifCode_FlushA<1> , vifCode_MSCAL<1> , vifCode_MSCALF<1> , vifCode_Null<1> , vifCode_MSCNT<1>, /*0x10*/ + vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1>, /*0x18*/ + vifCode_STMask<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1>, /*0x20*/ + vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1>, /*0x28*/ + vifCode_STRow<1> , vifCode_STCol<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1>, /*0x30*/ + vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1>, /*0x38*/ + vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1>, /*0x40*/ + vifCode_Null<1> , vifCode_Null<1> , vifCode_MPG<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1>, /*0x48*/ + vifCode_Direct<1> , vifCode_DirectHL<1>, vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1>, /*0x50*/ + vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1> , vifCode_Null<1>, /*0x58*/ + vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1>, /*0x60*/ + vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1>, /*0x68*/ + 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 +void runMark(u32* &data) { + if (vif1.vifpacketsize && (((data[0]>>24)&0x7f)==7)) { + vif1.vifpacketsize--; + vif1Code[7](0, data++); + DevCon.WriteLn("Vif1: Running Mark on I-bit"); + } +} + +// Returns 1 if i-bit && finished vifcode && i-bit not masked && next vifcode != MARK +bool analyzeIbit(u32* &data, int iBit, bool isTag) { + if (iBit && !vif1.cmd && !vif1Regs->err.MII) { + //DevCon.WriteLn("Vif I-Bit IRQ"); + vif1.irq++; + if (isTag) { + DevCon.WriteLn("Vif isTag Hack!?"); + vif1.stallontag = true; + } + runMark(data); + return 1; + } + return 0; +} + +// Interprets packet +void vif1TransferLoop(u32* &data, bool isTag) { + u32& tSize = vif1.tag.size; + u32& pSize = vif1.vifpacketsize; + int iBit = vif1.cmd >> 7; + + vif1Regs->stat.VPS |= VPS_TRANSFERRING; + vif1Regs->stat.ER1 = false; + + while (pSize > 0 && !vif1.vifstalled) { + + if(!vif1.cmd) { // Get new VifCode + vif1Regs->code = data[0]; + vif1.cmd = data[0] >> 24; + iBit = data[0] >> 31; + + vif1Code[vif1.cmd & 0x7f](0, data); + data++; pSize--; + if (analyzeIbit(data, iBit, isTag)) break; + continue; + } + + int ret = vif1Code[vif1.cmd & 0x7f](1, data); + data += ret; + pSize -= ret; + if (analyzeIbit(data, iBit, isTag)) break; + } + if (vif1.cmd) vif1Regs->stat.VPS = VPS_WAITING; + else vif1Regs->stat.VPS = VPS_IDLE; +} + +bool vif1Transfer_(u32 *data, int size, bool istag) { + // irqoffset necessary to add up the right qws, or else will spin (spiderman) + int transferred = vif1.vifstalled ? vif1.irqoffset : 0; + + vif1.irqoffset = 0; + vif1.vifstalled = false; + vif1.stallontag = false; + vif1.vifpacketsize = size; + + vif1TransferLoop(data, istag); + + transferred += size - vif1.vifpacketsize; + g_vifCycles +=(transferred >> 2) * BIAS; /* guessing */ + vif1.irqoffset = transferred % 4; // cannot lose the offset + + if (!istag) { + transferred = transferred >> 2; + vif1ch->madr +=(transferred << 4); + vif1ch->qwc -= transferred; + } + + if (!vif1ch->qwc && (!vif1.irqoffset || istag)) vif1.inprogress &= ~0x1; + + if (vif1.irq && vif1.cmd == 0) { + //DevCon.WriteLn("Vif IRQ!"); + vif1.vifstalled = true; + vif1Regs->stat.VIS = true; // Note: commenting this out fixes WALL-E? + + // spiderman doesn't break on qw boundaries + if (istag) return false; + + if (!vif1ch->qwc && !vif1.irqoffset) vif1.inprogress = 0; + return false; + } + + return !vif1.vifstalled; +} diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index 904d70c63b..4210237212 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -1,7 +1,7 @@ + + diff --git a/pcsx2/x86/newVif.h b/pcsx2/x86/newVif.h index 247bb6c50b..9e60583c13 100644 --- a/pcsx2/x86/newVif.h +++ b/pcsx2/x86/newVif.h @@ -86,7 +86,7 @@ struct nVifStruct { u8* vuMemEnd; // End of VU Memory u32 vuMemLimit; // Use for fast AND u32 bSize; // Size of 'buffer' - u8 buffer[0x4000]; // Buffer for partial transfers + u8 buffer[_1mb]; // Buffer for partial transfers u8* recPtr; // Cur Pos to recompile to u8* recEnd; // End of Rec Cache BlockBuffer* vifCache; // Block Buffer diff --git a/pcsx2/x86/newVif_Unpack.cpp b/pcsx2/x86/newVif_Unpack.cpp index 4d81a77b3e..a2eda151f7 100644 --- a/pcsx2/x86/newVif_Unpack.cpp +++ b/pcsx2/x86/newVif_Unpack.cpp @@ -122,7 +122,7 @@ int nVifUnpack(int idx, u8* data) { if (ret == v.vif->tag.size) { // Full Transfer if (v.bSize) { // Last transfer was partial - memcpy(&v.buffer[v.bSize], data, size); + memcpy_fast(&v.buffer[v.bSize], data, size); v.bSize += size; data = v.buffer; size = v.bSize; @@ -136,7 +136,7 @@ int nVifUnpack(int idx, u8* data) { v.bSize = 0; } else { // Partial Transfer - memcpy(&v.buffer[v.bSize], data, size); + memcpy_fast(&v.buffer[v.bSize], data, size); v.bSize += size; vif->tag.size -= ret; }