/* PCSX2 - PS2 Emulator for PCs * Copyright (C) 2002-2010 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 . */ #pragma once // Old Vif Unpack Code // Only here for testing/reference template void VIFunpack(u32 *data, vifCode *v, u32 size) { //if (!VIFdmanum) DevCon.WriteLn("vif#%d, size = %d [%x]", VIFdmanum, size, data); VURegs * VU; u8 *cdata = (u8*)data; u32 tempsize = 0; const u32 memlimit = (VIFdmanum == 0) ? 0x1000 : 0x4000; if (VIFdmanum == 0) { VU = &VU0; vifRegs = vif0Regs; vif = &vif0; } else { VU = &VU1; vifRegs = vif1Regs; vif = &vif1; } u32 *dest = (u32*)(VU->Mem + v->addr); const VIFUnpackFuncTable& ft( VIFfuncTable[ v->cmd & 0x1f ] ); UNPACKFUNCTYPE func = vif->usn ? ft.funcU : ft.funcS; size <<= 2; if (vifRegs->cycle.cl >= vifRegs->cycle.wl) { // skipping write if (v->addr >= memlimit) { DevCon.Warning("Overflown at the start"); v->addr &= (memlimit - 1); dest = (u32*)(VU->Mem + v->addr); } size = std::min(size, vifRegs->num * ft.gsize); //size will always be the same or smaller tempsize = v->addr + ((((vifRegs->num-1) / vifRegs->cycle.wl) * (vifRegs->cycle.cl - vifRegs->cycle.wl)) * 16) + (vifRegs->num * 16); //Sanity Check (memory overflow) if (tempsize > memlimit) { if (((vifRegs->cycle.cl != vifRegs->cycle.wl) && ((memlimit + (vifRegs->cycle.cl - vifRegs->cycle.wl) * 16) == tempsize))) { //It's a red herring, so ignore it! SSE unpacks will be much quicker. DevCon.WriteLn("what!!!!!!!!!"); //tempsize = 0; tempsize = size; size = 0; } else { DevCon.Warning("VIF%x Unpack ending %x > %x", VIFdmanum, tempsize, VIFdmanum ? 0x4000 : 0x1000); tempsize = size; size = 0; } } else { tempsize = size; size = 0; } if (tempsize) { int incdest = ((vifRegs->cycle.cl - vifRegs->cycle.wl) << 2) + 4; size = 0; int addrstart = v->addr; //if((tempsize >> 2) != v->size) DevCon.Warning("split when size != tagsize"); VIFUNPACK_LOG("sorting tempsize :p, size %d, vifnum %d, addr %x", tempsize, vifRegs->num, v->addr); while ((tempsize >= ft.gsize) && (vifRegs->num > 0)) { if(v->addr >= memlimit) { DevCon.Warning("Mem limit overflow"); v->addr &= (memlimit - 1); dest = (u32*)(VU->Mem + v->addr); } func(dest, (u32*)cdata); cdata += ft.gsize; tempsize -= ft.gsize; vifRegs->num--; vif->cl++; if (vif->cl == vifRegs->cycle.wl) { dest += incdest; v->addr +=(incdest * 4); vif->cl = 0; } else { dest += 4; v->addr += 16; } } if (v->addr >= memlimit) { v->addr &=(memlimit - 1); dest = (u32*)(VU->Mem + v->addr); } v->addr = addrstart; if(tempsize > 0) size = tempsize; } if (size >= ft.dsize && vifRegs->num > 0) { //Else write what we do have DevCon.Warning("huh!!!!!!!!!!!!!!!!!!!!!!"); VIF_LOG("warning, end with size = %d", size); // unpack one qword //v->addr += (size / ft.dsize) * 4; (vif->usn ? ft.oddU : ft.oddS)(dest, (u32*)cdata, size / ft.dsize); size = 0; VIFUNPACK_LOG("leftover done, size %d, vifnum %d, addr %x", size, vifRegs->num, v->addr); } } else { // filling write if(vifRegs->cycle.cl > 0) // Quicker and avoids zero division :P if((u32)(((size / ft.gsize) / vifRegs->cycle.cl) * vifRegs->cycle.wl) < vifRegs->num) DevCon.Warning("Filling write warning! %x < %x and CL = %x WL = %x", (size / ft.gsize), vifRegs->num, vifRegs->cycle.cl, vifRegs->cycle.wl); DevCon.Warning("filling write %d cl %d, wl %d mask %x mode %x unpacktype %x addr %x", vifRegs->num, vifRegs->cycle.cl, vifRegs->cycle.wl, vifRegs->mask, vifRegs->mode, v->cmd & 0xf, vif->tag.addr); while (vifRegs->num > 0) { if (vif->cl == vifRegs->cycle.wl) { vif->cl = 0; } // unpack one qword if (vif->cl < vifRegs->cycle.cl) { if(size < ft.gsize) { DevCon.WriteLn("Out of Filling write data!"); break; } func(dest, (u32*)cdata); cdata += ft.gsize; size -= ft.gsize; vif->cl++; vifRegs->num--; if (vif->cl == vifRegs->cycle.wl) { vif->cl = 0; } } else { func(dest, (u32*)cdata); v->addr += 16; vifRegs->num--; vif->cl++; } dest += 4; if (vifRegs->num == 0) break; } } }