public VifUnpacker(byte[] code) { _code = code; _programCounter = 0; _vifnMask = new VIFn_Mask(0); _vifnCol = new uint[4]; _vifnRow = new uint[4]; _readSigned = new Func <uint>[] { ReadInt32, ReadInt16, ReadInt8, ReadInt16, }; _readUnsigned = new Func <uint>[] { ReadUInt32, ReadUInt16, ReadUInt8, ReadUInt16 }; _unpacker = new Action <Func <uint> >[] { UnpackSingle, UnpackVector2, UnpackVector3, UnpackVector4, }; }
private State Step() { if (_programCounter >= _code.Length) { return(State.End); } var opcode = new Opcode(ReadUInt32()); if (opcode.IsUnpack) { Unpack(opcode); } else { switch (opcode.Cmd) { case CmdNop: break; case CmdStcycl: // KH2 is not really using it.. so we are going to to the same. _vifnCycle = new VIFn_Cycle(opcode.Immediate); break; case CmdMscal: // opcode.Immediate needs to be used as execution address for the microprogram. return(State.Microprogram); case CmdMscnt: // The difference with Mscal is that the execution address will be the // most recent end of the previous microcode execution. return(State.Microprogram); case CmdStmask: _vifnMask = new VIFn_Mask(ReadUInt32()); break; case CmdStrow: _vifnRow[0] = ReadUInt32(); _vifnRow[1] = ReadUInt32(); _vifnRow[2] = ReadUInt32(); _vifnRow[3] = ReadUInt32(); break; case CmdStcol: _vifnCol[0] = ReadUInt32(); _vifnCol[1] = ReadUInt32(); _vifnCol[2] = ReadUInt32(); _vifnCol[3] = ReadUInt32(); break; default: throw new Exception($"VIF1 cmd {opcode.Cmd:X02}@{_programCounter:X} not implemented!"); } } return(State.Run); }