Example #1
0
        public Instruction ParseSingle(ParseState ParseState)
        {
            var InstructionPosition = Stream.Position;
            var OpcodeNum           = BinaryReader.ReadUInt16();

            if (!Opcodes.ContainsKey(OpcodeNum))
            {
                throw(new NotImplementedException(String.Format("Unhandled opcode 0x{0:X2}", OpcodeNum)));
            }
            var Opcode = Opcodes[OpcodeNum];
            var Params = new List <object>();

            foreach (var FormatChar in Opcode.Format)
            {
                switch (FormatChar)
                {
                case '<': break;

                case 's': Params.Add(ReadString()); break;

                case 'S': Params.Add(ReadStringz()); break;

                case '1': Params.Add(BinaryReader.ReadByte()); break;

                case '7': Params.Add((AritmeticOps)BinaryReader.ReadByte()); break;

                case '9': Params.Add((ComparisionOps)BinaryReader.ReadByte()); break;

                case '2': Params.Add(BinaryReader.ReadInt16()); break;

                case 'v': Params.Add(new VariableReference()
                    {
                        Index = BinaryReader.ReadUInt16()
                    }); break;

                case '4': Params.Add(BinaryReader.ReadUInt32()); break;

                case 'L': Params.Add(new LabelReference()
                    {
                        Offset = BinaryReader.ReadUInt32()
                    }); break;

                case 'P':
                {
                    var    ParamType = BinaryReader.ReadByte();
                    object Value     = null;
                    switch (ParamType)
                    {
                    case 0x00: Value = BinaryReader.ReadSByte(); break;

                    case 0x10: Value = BinaryReader.ReadByte(); break;

                    case 0x20: Value = BinaryReader.ReadInt16(); break;

                    case 0x40: Value = BinaryReader.ReadInt32(); break;

                    case 0x01: Value = new VariableReference()
                    {
                            Index = BinaryReader.ReadUInt16()
                    }; break;

                    case 0x02: Value = new SpecialReference()
                    {
                            Index = BinaryReader.ReadUInt16()
                    }; break;

                    default: throw (new NotImplementedException(String.Format("Invalid param type {0}", ParamType)));
                    }

                    Params.Add(Value);
                }
                break;

                default:
                    throw(new NotImplementedException(String.Format("Invalid format '{0}'", FormatChar)));
                }
            }

            try
            {
                if (ParseState.Unindent.Contains((uint)InstructionPosition))
                {
                    ParseState.Indent--;
                }
                switch (Opcode.OpcodeName)
                {
                case "JUMP_ALWAYS":
                    ParseState.Indent--;
                    break;
                }

                return(new Instruction()
                {
                    Position = (uint)InstructionPosition,
                    Opcode = Opcode,
                    Parameters = Params.ToArray(),
                    Indent = ParseState.Indent,
                });
            }
            finally
            {
                switch (Opcode.OpcodeName)
                {
                //case "FUNCTION_DEF":
                case "JUMP_IF":
                    ParseState.Unindent.Add(((LabelReference)(Params.ToArray()[3])).Offset);
                    ParseState.Indent++;
                    break;

                case "JUMP_ALWAYS":
                    ParseState.Unindent.Add(((LabelReference)(Params.ToArray()[0])).Offset);
                    ParseState.Indent += 2;
                    break;
                }
            }
        }