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 :)
This commit is contained in:
refractionpcsx2 2016-01-25 21:43:53 +00:00
parent 393e56a604
commit 0147e6cb8d
5 changed files with 18 additions and 28 deletions

View File

@ -40,7 +40,8 @@ enum MTVU_EVENT {
// Calls the vif unpack functions from the MTVU thread // Calls the vif unpack functions from the MTVU thread
static void MTVU_Unpack(void* data, VIFregisters& vifRegs) 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); if (newVifDynaRec) dVifUnpack<1>((u8*)data, isFill);
else _nVifUnpack(1, (u8*)data, vifRegs.mode, isFill); else _nVifUnpack(1, (u8*)data, vifRegs.mode, isFill);
} }

View File

@ -188,11 +188,6 @@ _vifT void vifUnpackSetup(const u32 *data) {
vifStruct& vifX = GetVifX; 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++; GetVifX.unpackcalls++;
if (GetVifX.unpackcalls > 3) if (GetVifX.unpackcalls > 3)
@ -216,12 +211,14 @@ _vifT void vifUnpackSetup(const u32 *data) {
const u8& gsize = nVifT[vifX.cmd & 0x0f]; 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; vifX.tag.size = ((vifNum * gsize) + 3) / 4;
} }
else { else { //Filling write
int n = vifXRegs.cycle.cl * (vifNum / vifXRegs.cycle.wl) + int n = vifXRegs.cycle.cl * (vifNum / wl) +
_limit(vifNum % vifXRegs.cycle.wl, vifXRegs.cycle.cl); _limit(vifNum % wl, vifXRegs.cycle.cl);
vifX.tag.size = ((n * gsize) + 3) >> 2; vifX.tag.size = ((n * gsize) + 3) >> 2;
} }

View File

@ -61,9 +61,9 @@ struct __aligned16 nVifBlock {
u8 num; // [00] Num Field u8 num; // [00] Num Field
u8 upkType; // [01] Unpack Type [usn*1:mask*1:upk*4] u8 upkType; // [01] Unpack Type [usn*1:mask*1:upk*4]
u8 mode; // [02] Mode Field u8 mode; // [02] Mode Field
u8 cl; // [03] CL Field u16 cl; // [03] CL Field
u32 mask; // [04] Mask Field u32 mask; // [04] Mask Field
u8 wl; // [08] WL Field u16 wl; // [08] WL Field
u8 aligned; // [09] Packet Alignment u8 aligned; // [09] Packet Alignment
u8 padding[2];// [10] through [11] u8 padding[2];// [10] through [11]
uptr startPtr; // [12] Start Ptr of RecGen Code uptr startPtr; // [12] Start Ptr of RecGen Code

View File

@ -236,11 +236,6 @@ void VifUnpackSSE_Dynarec::CompileRoutine() {
else { else {
dstIndirect += (16 * skipSize); dstIndirect += (16 * skipSize);
vCL = 0; 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; vifStruct& vif = MTVU_VifX;
const VURegs& VU = vuRegs[idx]; const VURegs& VU = vuRegs[idx];
const uint vuMemLimit = idx ? 0x4000 : 0x1000; const uint vuMemLimit = idx ? 0x4000 : 0x1000;
u8* startmem = VU.Mem + (vif.tag.addr & (vuMemLimit-0x10)); u8* startmem = VU.Mem + (vif.tag.addr & (vuMemLimit-0x10));
u8* endmem = VU.Mem + vuMemLimit; u8* endmem = VU.Mem + vuMemLimit;
uint length = (v.block.num > 0) ? (v.block.num * 16) : 4096; // 0 = 256 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) { 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 skipSize = (cl - wl) * 16;
uint blocks = v.block.num / wl; uint blocks = v.block.num / wl;
length += (blocks-1) * skipSize; 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.num = (u8&)vifRegs.num;
v.block.mode = (u8&)vifRegs.mode; v.block.mode = (u8&)vifRegs.mode;
v.block.cl = vifRegs.cycle.cl; 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! v.block.aligned = vif.start_aligned; //MTVU doesn't have a packet size!
if ((upkType & 0xf) != 9) if ((upkType & 0xf) != 9)

View File

@ -111,10 +111,11 @@ _vifT int nVifUnpack(const u8* data) {
vifStruct& vif = GetVifX; vifStruct& vif = GetVifX;
VIFregisters& vifRegs = vifXRegs; VIFregisters& vifRegs = vifXRegs;
const uint wl = vifRegs.cycle.wl ? vifRegs.cycle.wl : 256;
const uint ret = aMin(vif.vifpacketsize, vif.tag.size); 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; s32 size = ret << 2;
if (ret == vif.tag.size) { // Full Transfer if (ret == vif.tag.size) { // Full Transfer
if (v.bSize) { // Last transfer was partial if (v.bSize) { // Last transfer was partial
memcpy(&v.buffer[v.bSize], data, size); 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) ]; const UNPACKFUNCTYPE ft = VIFfuncTable[idx][doMode ? vifRegs.mode : 0][ ((usn*2*16) + upkNum) ];
pxAssume (vif.cl == 0); pxAssume (vif.cl == 0);
pxAssume (vifRegs.cycle.wl > 0); //pxAssume (vifRegs.cycle.wl > 0);
do { do {
u8* dest = getVUptr(idx, vif.tag.addr); u8* dest = getVUptr(idx, vif.tag.addr);