public VifEmulator() { memory = new VuVector[1024]; for (int i = 0; i < memory.Length; ++i) { memory[i] = new VuVector(); } registers = new VifRegisters(); }
public static VuVector[] ReadBoundingBox(this BinaryReader br) { var box = new VuVector[8]; for (int i = 0; i < box.Length; ++i) { box[i] = br.ReadV4_32(); } return(box); }
void ProcessVifCodeUnpack(BinaryReader br) { var vifcode = (VifCodeUnpack)registers.Code; registers.Num = vifcode.Num; //Console.WriteLine($"VIFcode: {VifCodeCmd.Unpack} vn={vifcode.Vn} vl={vifcode.Vl} NUM={vifcode.Num} ADDR={vifcode.Address:x4} FLG={vifcode.Flag} USN={vifcode.Unsigned} m={vifcode.Mask}"); int addr = (int)((vifcode.Flag ? registers.TopS : 0) + vifcode.Address); int cycle = 0; bool isV4_5 = vifcode.Vn == VifUnpackVnType.V4 && vifcode.Vl == VifUnpackVlType.L_5; while (registers.Num > 0) { VuVector result = default; bool doSkip = false; bool doMode; bool doMask; if (registers.CycleCl >= registers.CycleWl) { doMode = true; doMask = false; // Skipping write if (cycle < registers.CycleWl) { // Write when under write limit result = br.ReadOneVifCodeUnpack(vifcode); } if (cycle == registers.CycleWl - 1) { doSkip = true; } } else { // Filling write throw new NotImplementedException("Filling write not implemented"); } // Write result result = ApplyMaskAndMode(result, doMode && !isV4_5, doMask); memory[addr++] = result; --registers.Num; // TODO: figure out the proper behavior for filling write if (doSkip) { addr += registers.CycleCl - registers.CycleWl; cycle = 0; } else { ++cycle; } } }
VuVector ApplyMaskAndMode(VuVector vector, bool doMode, bool doMask) { if (!doMode && !doMask) { return(vector); } uint x = vector.X.Packed; uint y = vector.Y.Packed; uint z = vector.Z.Packed; uint w = vector.W.Packed; if (doMask) { throw new NotImplementedException("Masking not implemented"); } if (doMode) { switch (registers.ModeMod) { case VifMode.None: break; default: throw new NotImplementedException("Addition decompression write not implemented"); } } return(new VuVector { X = new VuFloat { Packed = x }, Y = new VuFloat { Packed = y }, Z = new VuFloat { Packed = z }, W = new VuFloat { Packed = w }, }); }