DisassemblyState ReadInstruction(FileReader reader)
        {
            Assert.IsNotNull(reader, nameof(reader));

            var opcode = reader.ReadByte();
            var instructiondefinition = InstructionDefinitionMap[opcode];
            var instruction           = new Instruction(instructiondefinition);

            var state           = new DisassemblyState(reader, instruction, ReadExpression, ReadInstruction, ReadInstructionBlock);
            var builderfunction = instructiondefinition.DisassemblyFunction;

            builderfunction(state);

            return(state);
        }
        Expression ReadExpression(DisassemblyState state)
        {
            Assert.IsNotNull(state, nameof(state));

            var expression = new Expression();

            while (true)
            {
                var operationtype = (OperationType)state.Reader.ReadByte();
                var operation     = new Operation(operationtype);

                expression.Operations.Add(operation);

                if (operationtype == OperationType.PUSH_LONG)
                {
                    operation.Operands.Add(state.ReadOperand(OperandType.UInt32));
                }
                else if (operationtype == OperationType.EXEC_OP)
                {
                    operation.Operands.Add(state.ReadOperand(OperandType.Instruction));
                }
                else if (operationtype == OperationType.TEST_SCENA_FLAGS || operationtype == OperationType.GET_RESULT)
                {
                    operation.Operands.Add(state.ReadOperand(OperandType.UInt16));
                }
                else if (operationtype == OperationType.PUSH_VALUE_INDEX || operationtype == OperationType.UNKNOWN_23)
                {
                    operation.Operands.Add(state.ReadOperand(OperandType.Byte));
                }
                else if (operationtype == OperationType.GET_CHR_WORK)
                {
                    operation.Operands.Add(state.ReadOperand(OperandType.UInt16));
                    operation.Operands.Add(state.ReadOperand(OperandType.Byte));
                }
                else if (operationtype == OperationType.END)
                {
                    break;
                }
            }

            return(expression);
        }