From 0147e6cb8da9c43640218689b190b838addecc10 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Mon, 25 Jan 2016 21:43:53 +0000 Subject: [PATCH] Vif: Fix for Unpacks when WL = 0. (KH2 + Tests) Removes a long standing hack. Note: CL = 0 behaviour is still not completely accurate, the first vector is incorrect, but will look at that another day, need a game that does it first really so we can see if it helps :) --- pcsx2/MTVU.cpp | 3 ++- pcsx2/Vif_Unpack.cpp | 15 ++++++--------- pcsx2/x86/newVif.h | 4 ++-- pcsx2/x86/newVif_Dynarec.cpp | 17 ++++------------- pcsx2/x86/newVif_Unpack.cpp | 7 ++++--- 5 files changed, 18 insertions(+), 28 deletions(-) diff --git a/pcsx2/MTVU.cpp b/pcsx2/MTVU.cpp index 58d958e9e5..b77b37224f 100644 --- a/pcsx2/MTVU.cpp +++ b/pcsx2/MTVU.cpp @@ -40,7 +40,8 @@ enum MTVU_EVENT { // Calls the vif unpack functions from the MTVU thread static void MTVU_Unpack(void* data, VIFregisters& vifRegs) { - bool isFill = vifRegs.cycle.cl < vifRegs.cycle.wl; + u16 wl = vifRegs.cycle.wl > 0 ? vifRegs.cycle.wl : 256; + bool isFill = vifRegs.cycle.cl < wl; if (newVifDynaRec) dVifUnpack<1>((u8*)data, isFill); else _nVifUnpack(1, (u8*)data, vifRegs.mode, isFill); } diff --git a/pcsx2/Vif_Unpack.cpp b/pcsx2/Vif_Unpack.cpp index 122054d26e..e57aac40f8 100644 --- a/pcsx2/Vif_Unpack.cpp +++ b/pcsx2/Vif_Unpack.cpp @@ -188,11 +188,6 @@ _vifT void vifUnpackSetup(const u32 *data) { vifStruct& vifX = GetVifX; - if ((vifXRegs.cycle.wl == 0) && (vifXRegs.cycle.wl < vifXRegs.cycle.cl)) { - //DevCon.WriteLn("Vif%d CL %d, WL %d Mode %x Mask %x Num %x", idx, vifXRegs.cycle.cl, vifXRegs.cycle.wl, vifXRegs.mode, vifXRegs.mask, (vifXRegs.code >> 16) & 0xff); - vifX.cmd = 0; - return; // Skipping write and 0 write-cycles, so do nothing! - } GetVifX.unpackcalls++; if (GetVifX.unpackcalls > 3) @@ -216,12 +211,14 @@ _vifT void vifUnpackSetup(const u32 *data) { const u8& gsize = nVifT[vifX.cmd & 0x0f]; - if (vifXRegs.cycle.wl <= vifXRegs.cycle.cl) { + uint wl = vifXRegs.cycle.wl ? vifXRegs.cycle.wl : 256; + + if (wl <= vifXRegs.cycle.cl) { //Skipping write vifX.tag.size = ((vifNum * gsize) + 3) / 4; } - else { - int n = vifXRegs.cycle.cl * (vifNum / vifXRegs.cycle.wl) + - _limit(vifNum % vifXRegs.cycle.wl, vifXRegs.cycle.cl); + else { //Filling write + int n = vifXRegs.cycle.cl * (vifNum / wl) + + _limit(vifNum % wl, vifXRegs.cycle.cl); vifX.tag.size = ((n * gsize) + 3) >> 2; } diff --git a/pcsx2/x86/newVif.h b/pcsx2/x86/newVif.h index 37df6737cc..4d67d25ca5 100644 --- a/pcsx2/x86/newVif.h +++ b/pcsx2/x86/newVif.h @@ -61,9 +61,9 @@ struct __aligned16 nVifBlock { u8 num; // [00] Num Field u8 upkType; // [01] Unpack Type [usn*1:mask*1:upk*4] u8 mode; // [02] Mode Field - u8 cl; // [03] CL Field + u16 cl; // [03] CL Field u32 mask; // [04] Mask Field - u8 wl; // [08] WL Field + u16 wl; // [08] WL Field u8 aligned; // [09] Packet Alignment u8 padding[2];// [10] through [11] uptr startPtr; // [12] Start Ptr of RecGen Code diff --git a/pcsx2/x86/newVif_Dynarec.cpp b/pcsx2/x86/newVif_Dynarec.cpp index 64ddcad737..fe1c2093bf 100644 --- a/pcsx2/x86/newVif_Dynarec.cpp +++ b/pcsx2/x86/newVif_Dynarec.cpp @@ -236,11 +236,6 @@ void VifUnpackSSE_Dynarec::CompileRoutine() { else { dstIndirect += (16 * skipSize); vCL = 0; - // FIXME - // temporary code to avoid an infinite loop until the code is correctly fixed - if (blockSize == cycleSize && cycleSize == 0) - break; - // END FIXME } } @@ -253,18 +248,14 @@ _vifT static __fi u8* dVifsetVUptr(uint cl, uint wl, bool isFill) { vifStruct& vif = MTVU_VifX; const VURegs& VU = vuRegs[idx]; const uint vuMemLimit = idx ? 0x4000 : 0x1000; - + u8* startmem = VU.Mem + (vif.tag.addr & (vuMemLimit-0x10)); u8* endmem = VU.Mem + vuMemLimit; uint length = (v.block.num > 0) ? (v.block.num * 16) : 4096; // 0 = 256 + //wl = wl ? wl : 256; //0 is taken as 256 (KH2) + //if (wl == 256) isFill = true; if (!isFill) { - // Accounting for skipping mode: Subtract the last skip cycle, since the skipped part of the run - // shouldn't count as wrapped data. Otherwise, a trailing skip can cause the emu to drop back - // to the interpreter. -- Refraction (test with MGS3) - // FIXME temporary solution to avoid a crash - if (wl == 0) wl = 1; - // END FIXME uint skipSize = (cl - wl) * 16; uint blocks = v.block.num / wl; length += (blocks-1) * skipSize; @@ -321,7 +312,7 @@ _vifT __fi void dVifUnpack(const u8* data, bool isFill) { v.block.num = (u8&)vifRegs.num; v.block.mode = (u8&)vifRegs.mode; v.block.cl = vifRegs.cycle.cl; - v.block.wl = vifRegs.cycle.wl; + v.block.wl = vifRegs.cycle.wl ? vifRegs.cycle.wl : 256; v.block.aligned = vif.start_aligned; //MTVU doesn't have a packet size! if ((upkType & 0xf) != 9) diff --git a/pcsx2/x86/newVif_Unpack.cpp b/pcsx2/x86/newVif_Unpack.cpp index 4359904b87..0886bcf0b1 100644 --- a/pcsx2/x86/newVif_Unpack.cpp +++ b/pcsx2/x86/newVif_Unpack.cpp @@ -111,10 +111,11 @@ _vifT int nVifUnpack(const u8* data) { vifStruct& vif = GetVifX; VIFregisters& vifRegs = vifXRegs; + const uint wl = vifRegs.cycle.wl ? vifRegs.cycle.wl : 256; const uint ret = aMin(vif.vifpacketsize, vif.tag.size); - const bool isFill = (vifRegs.cycle.cl < vifRegs.cycle.wl); + const bool isFill = (vifRegs.cycle.cl < wl); s32 size = ret << 2; - + if (ret == vif.tag.size) { // Full Transfer if (v.bSize) { // Last transfer was partial memcpy(&v.buffer[v.bSize], data, size); @@ -252,7 +253,7 @@ __ri void __fastcall _nVifUnpackLoop(const u8* data) { const UNPACKFUNCTYPE ft = VIFfuncTable[idx][doMode ? vifRegs.mode : 0][ ((usn*2*16) + upkNum) ]; pxAssume (vif.cl == 0); - pxAssume (vifRegs.cycle.wl > 0); + //pxAssume (vifRegs.cycle.wl > 0); do { u8* dest = getVUptr(idx, vif.tag.addr);