public static ScriptingAssembly Decompile(byte[] scriptNodeData, ScriptEngineDefinition engineDefinition, string[] tagList, ScenarioBase scnr)
        {
            s_nodeDataReader = new BinaryReader(new MemoryStream(scriptNodeData, 56, scriptNodeData.Length - 56, false));
            s_globals        = new List <NodeBase>();
            s_scripts        = new List <NodeBase>();

            s_engineDefinition = engineDefinition;
            s_tagList          = tagList;
            s_scnr             = scnr;

            ScenarioScriptGlobal[] scnrGlobals = s_scnr.GetScriptGlobals();
            ScenarioScript[]       scnrScripts = s_scnr.GetScripts();

            foreach (ScenarioScriptGlobal g in scnrGlobals)
            {
                CompiledScriptNode cnode = new CompiledScriptNode(g.InitialisationExpressionIndex, s_nodeDataReader);
                s_globals.Add(new VariableNode(g.Name, g.Type, DecompileNode(cnode)));
            }

            foreach (ScenarioScript s in scnrScripts)
            {
                CompiledScriptNode cnode = new CompiledScriptNode(s.RootExpressionIndex, s_nodeDataReader);
                s_scripts.Add(new ScriptNode(s.Name, (ScriptType)s.ScriptType, s.ReturnType, DecompileNode(cnode).Children));
            }

            ScriptingAssembly assembly = new ScriptingAssembly(s_engineDefinition, s_globals, s_scripts);

            s_nodeDataReader   = null;
            s_globals          = null;
            s_scripts          = null;
            s_engineDefinition = null;
            s_tagList          = null;
            s_scnr             = null;

            return(assembly);
        }
        // handle null nodes
        private static NodeBase DecompileNode(CompiledScriptNode node)
        {
            switch (node.NodeType)
            {
            case CompiledNodeType.FunctionCall:
            {
                List <NodeBase> parameters = new List <NodeBase>();

                CompiledScriptNode firstChild = new CompiledScriptNode(BitConverter.ToInt16(node.ValueData, 0), s_nodeDataReader);
                short childIndex = firstChild.NextSiblingIndex;
                while (childIndex != -1)
                {
                    CompiledScriptNode child = new CompiledScriptNode(childIndex, s_nodeDataReader);
                    parameters.Add(DecompileNode(child));
                    childIndex = child.NextSiblingIndex;
                }

                /*if (node.OpCode == 0) // Begin
                 *      return new GroupingNode(parameters);*/

                return(new BslFunctionCallNode(node.OpCode, parameters));
            }

            case CompiledNodeType.ScriptCall:
            {
                List <NodeBase> parameters = new List <NodeBase>();

                CompiledScriptNode firstChild = new CompiledScriptNode(BitConverter.ToInt16(node.ValueData, 0), s_nodeDataReader);
                short childIndex = firstChild.NextSiblingIndex;
                while (childIndex != -1)
                {
                    CompiledScriptNode child = new CompiledScriptNode(childIndex, s_nodeDataReader);
                    parameters.Add(DecompileNode(child));
                    childIndex = child.NextSiblingIndex;
                }

                return(new ScriptCallNode(s_scripts[node.OpCode] as ScriptNode, parameters));
            }

            case CompiledNodeType.GlobalReference:
            {
                uint index = BitConverter.ToUInt32(node.ValueData, 0);

                if (index >= 0xFFFF8000)
                {
                    return(new BslGameGlobalReferenceNode((short)(index - 0xFFFF8000), node.ValueType));
                }
                else
                {
                    return(new VariableReferenceValueNode(s_globals[(short)index] as VariableNode, node.ValueType));
                }
            }

            case CompiledNodeType.Value:
            {
                switch ((IntegralValueType)node.ValueType)
                {
                case IntegralValueType.Bool:
                    return(new BoolValueNode(BitConverter.ToBoolean(node.ValueData, 0)));

                case IntegralValueType.Real:
                    return(new RealValueNode(BitConverter.ToSingle(node.ValueData, 0)));

                case IntegralValueType.Short:
                    return(new ShortValueNode(BitConverter.ToInt16(node.ValueData, 0)));

                case IntegralValueType.Long:
                    return(new LongValueNode(BitConverter.ToInt32(node.ValueData, 0)));

                case IntegralValueType.String:
                    return(new StringValueNode(s_scnr.GetScriptString(node.StringTableOffset)));

                case IntegralValueType.Script:
                    return(new ScriptReferenceValueNode(s_scripts[BitConverter.ToInt16(node.ValueData, 0)] as ScriptNode));
                }

                ExtendedTypeBase type = s_engineDefinition.ExtendedTypes[node.ValueType - ExtendedTypeBase.FirstTypeIndex];

                if (type is EnumerationType)
                {
                    return(new EnumerationValueNode(type as EnumerationType, BitConverter.ToInt16(node.ValueData, 0)));
                }
                if (type is BlockReferenceType)
                {
                    return
                        (new BlockReferenceValueNode(type as BlockReferenceType,
                                                     s_scnr.GetBlockStringForScriptingReferenceType(
                                                         BitConverter.ToInt16(node.ValueData, 0), type.TypeIndex)));
                }
                if (type is TagReferenceType)
                {
                    return(new TagReferenceValueNode(type as TagReferenceType, s_tagList[BitConverter.ToInt16(node.ValueData, 0)]));
                }

                throw new OnlyForDebuggingException("N.B. :(");
            }
            }

            throw new OnlyForDebuggingException("N.B. :X");
        }