private void ReadBytecode(Stream input, FunctionDefinition funcDef) { funcDef.Instructions = new List <IInstruction>(); funcDef.InstructionOffsets = new List <int>(); var unencodedByteCodeLength = input.ReadValueEncodedS32(); int read; for (read = 0; read < unencodedByteCodeLength;) { funcDef.InstructionOffsets.Add(read); var op = input.ReadValueU8(); var opcode = (Script.Opcode)op; read++; Script.IInstruction instruction = null; switch (opcode) { case Script.Opcode.OP_Target: { instruction = new Target(); break; } case Script.Opcode.OP_ShortConst: { instruction = new ShortConst(); break; } case Script.Opcode.OP_IntConst: { instruction = new IntConst(); break; } case Script.Opcode.OP_FloatConst: { instruction = new FloatConst(); break; } case Script.Opcode.OP_StringConst: { instruction = new StringConst(this); break; } case Script.Opcode.OP_VirtualFunc: { instruction = new VirtualFunc(this); break; } case Script.Opcode.OP_Context: case Script.Opcode.OP_SwitchLabel: { instruction = new U16U16(opcode); break; } case Script.Opcode.OP_Assign: case Script.Opcode.OP_JumpIfFalse: case Script.Opcode.OP_Jump: case Script.Opcode.OP_Skip: { instruction = new U16(opcode); break; } case Script.Opcode.OP_LocalVar: case Script.Opcode.OP_ObjectVar: case Script.Opcode.OP_ParamVar: case Script.Opcode.OP_StructMember: { instruction = new TypeMember(opcode, this); break; } case Script.Opcode.OP_Switch: { instruction = new Switch(); break; } case Script.Opcode.OP_Constructor: { instruction = new Constructor(this); break; } case Script.Opcode.OP_TestEqual: case Script.Opcode.OP_EnumToInt: case Script.Opcode.OP_ArrayPushBack: case Script.Opcode.OP_ArraySize: case Script.Opcode.OP_ArrayElement: case Script.Opcode.OP_New: case Script.Opcode.OP_ArrayClear: case Script.Opcode.OP_DynamicCast: case Script.Opcode.OP_ArrayContainsFast: case Script.Opcode.OP_ArrayRemoveFast: case Script.Opcode.OP_TestNotEqual: case Script.Opcode.OP_ArrayErase: case Script.Opcode.OP_EnumToString: case Script.Opcode.OP_ArrayContains: case Script.Opcode.OP_ArrayResize: case Script.Opcode.OP_ArrayInsert: case Script.Opcode.OP_ArrayGrow: case Script.Opcode.OP_ArrayFindFirstFast: case Script.Opcode.OP_ArrayLast: case Script.Opcode.OP_ArrayRemove: case Script.Opcode.OP_SaveValue: { instruction = new TypeRef(opcode, this); break; } case Script.Opcode.OP_NameConst: { instruction = new NameConst(Strings); break; } case Script.Opcode.OP_FinalFunc: { instruction = new FinalFunc(this); break; } case Script.Opcode.OP_EntryFunc: case Script.Opcode.OP_SavePoint: { instruction = new U16S32(opcode, this); break; } case Script.Opcode.OP_Nop: case Script.Opcode.OP_ParamEnd: case Script.Opcode.OP_IntZero: case Script.Opcode.OP_IntOne: case Script.Opcode.OP_BoolFalse: case Script.Opcode.OP_BoolTrue: case Script.Opcode.OP_Return: case Script.Opcode.OP_GetServer: case Script.Opcode.OP_GetCamera: case Script.Opcode.OP_NameToString: case Script.Opcode.OP_GetPlayer: case Script.Opcode.OP_IntToFloat: case Script.Opcode.OP_This: case Script.Opcode.OP_Null: case Script.Opcode.OP_GetGame: case Script.Opcode.OP_ObjectToBool: case Script.Opcode.OP_IntToString: case Script.Opcode.OP_FloatToString: case Script.Opcode.OP_IntToByte: case Script.Opcode.OP_ObjectToString: case Script.Opcode.OP_SwitchDefault: case Script.Opcode.OP_BoolToString: case Script.Opcode.OP_GetHud: case Script.Opcode.OP_FloatToInt: case Script.Opcode.OP_NameToBool: case Script.Opcode.OP_Parent: case Script.Opcode.OP_IntToBool: case Script.Opcode.OP_ByteToInt: case Script.Opcode.OP_FloatToBool: case Script.Opcode.OP_ByteToFloat: case Script.Opcode.OP_StringToBool: case Script.Opcode.OP_SavePointEnd: case Script.Opcode.OP_StringToInt: case Script.Opcode.OP_GetSound: { instruction = new Simple(opcode); break; } default: { throw new NotImplementedException("unhandled " + opcode.ToString()); } } read += instruction.Deserialize(input); funcDef.Instructions.Add(instruction); } if (read != unencodedByteCodeLength) { throw new InvalidOperationException(); } }