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
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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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);