示例#1
0
 public ScriptWalker(ScriptTable orig, ScriptTable mod, IndentedTextWriter output, EngineDescription desc)
 {
     _orig   = orig;
     _mod    = mod;
     _output = output;
     _op     = desc.ScriptInfo;
 }
示例#2
0
        private static void UpdateXshdWithScriptInfo(XDocument doc, OpcodeLookup opcodes)
        {
            XNamespace df                = doc.Root.Name.Namespace;
            var        keyWords          = doc.Root.Descendants(df + "Keywords");
            XElement   scriptTypeElement = keyWords.Where(x => x.Attribute("color")?.Value == "ScriptType")?.First();
            XElement   valueTypeElement  = keyWords.Where(x => x.Attribute("color")?.Value == "ValueType")?.First();
            XElement   functionElement   = keyWords.Where(x => x.Attribute("color")?.Value == "Function")?.First();

            foreach (string scriptType in opcodes.GetAllScriptTypeNames())
            {
                XElement element = StringToWordElement(scriptType, df);
                scriptTypeElement.Add(element);
            }

            foreach (string type in opcodes.GetAllValueTypeNames())
            {
                XElement element = StringToWordElement(type, df);
                valueTypeElement.Add(element);
            }

            foreach (string function in opcodes.GetAllUniqueFunctionNames())
            {
                XElement element = StringToWordElement(function, df);
                functionElement.Add(element);
            }
        }
示例#3
0
        private void RegisterTypeCasts(XContainer root, OpcodeLookup lookup)
        {
            List <TempTypeCast>           info  = new List <TempTypeCast>();
            Dictionary <string, string[]> casts = new Dictionary <string, string[]>();

            // Load type casting information.
            foreach (XElement element in root.Element("typecasting").Elements("to"))
            {
                TempTypeCast temp = new TempTypeCast()
                {
                    Name     = XMLUtil.GetStringAttribute(element, "name"),
                    CastOnly = XMLUtil.GetBoolAttribute(element, "castOnly", false),
                    Types    = element.Elements("from").Select(e => e.Value)
                };
                info.Add(temp);
                casts[temp.Name] = temp.Types.ToArray();
            }

            bool itemsAdded = true;

            while (itemsAdded)
            {
                itemsAdded = false;
                // Iterate over all casts.
                foreach (var i in info)
                {
                    string[] newPredecessors = casts[i.Name];
                    // Iterate over all predecessors of the cast.
                    foreach (string type in casts[i.Name])
                    {
                        // Check if the predecessor supports casting.
                        if (casts.TryGetValue(type, out string[] predecessors))
示例#4
0
 private void RegisterExecutionTypes(XContainer root, OpcodeLookup lookup)
 {
     foreach (XElement element in root.Element("scriptTypes").Descendants("type"))
     {
         var    opcode = (ushort)XMLUtil.GetNumericAttribute(element, "opcode");
         string name   = XMLUtil.GetStringAttribute(element, "name");
         lookup.RegisterScriptType(name, opcode);
     }
 }
示例#5
0
        public ScriptEditor(EngineDescription buildInfo, IScriptFile scriptFile, IStreamManager streamManager, ICacheFile casheFile, Endian endian)
        {
            _endian        = endian;
            _buildInfo     = buildInfo;
            _opcodes       = _buildInfo.ScriptInfo;
            _scriptFile    = scriptFile;
            _streamManager = streamManager;
            _cashefile     = casheFile;

            // If a game contains hsdt tags, it uses a newer Blam Script syntax. Currently the compiler only supports the old syntax.
            _hasNewSyntax = _buildInfo.Layouts.HasLayout("hsdt");

            InitializeComponent();

            // Disable user input. Enable it again when all background tasks have been completed.
            txtScript.IsReadOnly = true;

            // Enable code completion only if the compiler supports this game.
            if (!_hasNewSyntax)
            {
                txtScript.TextArea.GotFocus         += EditorGotFocus;
                txtScript.TextArea.LostFocus        += EditorLostFocus;
                txtScript.TextArea.TextEntering     += EditorTextEntering;
                txtScript.TextArea.TextEntered      += EditorTextEntered;
                txtScript.TextArea.Document.Changed += EditorTextChanged;
            }

            App.AssemblyStorage.AssemblySettings.PropertyChanged += Settings_SettingsChanged;
            SetHighlightColor();
            SearchPanel srch     = SearchPanel.Install(txtScript);
            var         bconv    = new System.Windows.Media.BrushConverter();
            var         srchbrsh = (System.Windows.Media.Brush)bconv.ConvertFromString("#40F0F0F0");

            srch.MarkerBrush = srchbrsh;

            txtScript.SyntaxHighlighting = LoadSyntaxHighlighting();

            // With syntax highlighting and HTML formatting, copying text takes ages. Disable the HTML formatting for copied text.
            DataObject.AddSettingDataHandler(txtScript, onTextViewSettingDataHandler);

            _progress = new Progress <int>(i =>
            {
                progressBar.Value = i;
            });

            itemShowInformation.IsChecked = App.AssemblyStorage.AssemblySettings.ShowScriptInfo;
            itemDebugData.IsChecked       = App.AssemblyStorage.AssemblySettings.OutputCompilerDebugData;

            // Enable compilation only for supported games.
            if (_buildInfo.Name.Contains("Reach") || _buildInfo.Name.Contains("Halo 3") && _buildInfo.HeaderSize != 0x800 && !_buildInfo.Name.Contains("ODST"))
            {
                compileButton.Visibility    = Visibility.Visible;
                progressReporter.Visibility = Visibility.Visible;
            }
        }
示例#6
0
        /// <summary>
        ///     Loads setting data from a path.
        /// </summary>
        /// <param name="path">The path to load from.</param>
        /// <returns>
        ///     The loaded setting data.
        /// </returns>
        public object LoadSetting(string path)
        {
            XDocument document = XDocument.Load(path);
            var       result   = new OpcodeLookup();
            XElement  root     = document.Element("BlamScript");

            RegisterExecutionTypes(root, result);
            RegisterValueTypes(root, result);
            RegisterFunctions(root, result);

            return(result);
        }
示例#7
0
        public static bool IsObject(string type, OpcodeLookup op)
        {
            CastInfo info = op.GetTypeCast("object");

            if (info is null)
            {
                return(false);
            }
            else
            {
                return(info.From.Contains(type));
            }
        }
示例#8
0
 private void RegisterValueTypes(XContainer root, OpcodeLookup lookup)
 {
     foreach (XElement element in root.Element("valueTypes").Descendants("type"))
     {
         string name      = XMLUtil.GetStringAttribute(element, "name");
         var    opcode    = (ushort)XMLUtil.GetNumericAttribute(element, "opcode");
         int    size      = XMLUtil.GetNumericAttribute(element, "size");
         bool   quoted    = XMLUtil.GetBoolAttribute(element, "quoted", false);
         string tag       = XMLUtil.GetStringAttribute(element, "tag", null);
         var    valueType = new ScriptValueType(name, opcode, size, quoted, tag);
         lookup.RegisterValueType(valueType);
     }
 }
示例#9
0
        public ScriptCompiler(ICacheFile casheFile, EngineDescription buildInfo, OpcodeLookup opCodes, ScriptingContextCollection context, IProgress<int> progress, ScriptCompilerLogger logger, bool debug)
        {
            _buildInfo = buildInfo;
            _progress = progress;
            _cacheFile = casheFile;
            _scriptingContext = context;
            _opcodes = opCodes;
            _logger = logger;
            _debug = debug;
            _expectedTypes = new TypeStack(logger, _debug);

            ushort intialSalt = SaltGenerator.GetSalt("script node");
            _currentIndex = new DatumIndex(intialSalt, 0);
        }
示例#10
0
        private string DecompileScnrScripts()
        {
            using (IReader reader = _streamManager.OpenRead())
            {
                ScriptTable scripts = _scriptFile.LoadScripts(reader);
                if (scripts is null)
                {
                    return("");
                }

                OpcodeLookup opcodes    = _buildInfo.ScriptInfo;
                var          decompiler = new BlamScriptDecompiler(scripts, opcodes, _endian);
                return(decompiler.DecompileAll(_scriptFile.Name, App.AssemblyStorage.AssemblySettings.ShowScriptInfo, true));
            }
        }
示例#11
0
        private void RegisterGlobals(XContainer root, OpcodeLookup lookup)
        {
            foreach (XElement element in root.Element("globals").Descendants("global"))
            {
                string name = XMLUtil.GetStringAttribute(element, "name");
                if (name == "")
                {
                    continue;
                }

                ushort opcode     = (ushort)XMLUtil.GetNumericAttribute(element, "opcode");
                string returnType = XMLUtil.GetStringAttribute(element, "type");
                bool   isNull     = XMLUtil.GetBoolAttribute(element, "null", false);

                var info = new GlobalInfo(name, opcode, returnType, !isNull);
                lookup.RegisterGlobal(info);
            }
        }
示例#12
0
        //public static bool CanBeCasted(string from, string to, OpcodeLookup op)
        //{
        //    if ((IsNumType(from) && IsNumType(to)) || (op.GetTypeInfo(from).IsObject && op.GetTypeInfo(to).IsObject))
        //    {
        //        return true;
        //    }

        //    // Check if this type supports casting
        //    CastInfo info = op.GetTypeCast(to);
        //    if (info != null)
        //    {
        //        List<string> casts = new List<string>();
        //        List<string> processedTypes = new List<string>();
        //        int addedTypes = info.From.Count;
        //        casts.AddRange(info.From);

        //        // Generate a list of all possible casts.
        //        while (addedTypes > 0)
        //        {
        //            int added = 0;
        //            string[] difference = casts.Except(processedTypes).ToArray();
        //            foreach (string cast in difference)
        //            {
        //                info = op.GetTypeCast(cast);
        //                if (info != null)
        //                {
        //                    foreach (var type in info.From)
        //                    {
        //                        if (!casts.Contains(type))
        //                        {
        //                            casts.Add(type);
        //                            added++;
        //                        }
        //                    }
        //                }
        //                processedTypes.Add(cast);
        //            }
        //            addedTypes = added;
        //        }
        //        // Check if this generated list contains this cast.
        //        return casts.Contains(from);
        //    }
        //    else
        //    {
        //        return false;
        //    }
        //}

        public static bool CanBeCasted(string from, string to, OpcodeLookup op)
        {
            if ((IsNumType(from) && IsNumType(to)) || (op.GetTypeInfo(from).IsObject&& op.GetTypeInfo(to).IsObject))
            {
                return(true);
            }

            CastInfo info = op.GetTypeCast(to);

            if (info is null)
            {
                return(false);
            }
            else
            {
                return(info.From.Contains(from));
            }
        }
示例#13
0
        private void RegisterFunctions(XContainer root, OpcodeLookup lookup)
        {
            foreach (XElement element in root.Element("functions").Descendants("function"))
            {
                string name = XMLUtil.GetStringAttribute(element, "name");
                if (name == "")
                {
                    continue;
                }

                var      opcode         = (ushort)XMLUtil.GetNumericAttribute(element, "opcode");
                string   returnType     = XMLUtil.GetStringAttribute(element, "returnType", "void");
                var      flags          = (uint)XMLUtil.GetNumericAttribute(element, "flags", 0);
                string[] parameterTypes = element.Descendants("arg").Select(e => XMLUtil.GetStringAttribute(e, "type")).ToArray();

                var info = new ScriptFunctionInfo(name, opcode, returnType, flags, parameterTypes);
                lookup.RegisterFunction(info);
            }
        }
示例#14
0
        public static Script GetScriptFromContext(HS_Gen1Parser.ScriptDeclarationContext context, DatumIndex rootExpressionIndex, OpcodeLookup opcodes)
        {
            // Create a new Script.
            Script script = new Script
            {
                Name                = context.scriptID().GetTextSanitized(),
                ExecutionType       = (short)opcodes.GetScriptTypeOpcode(context.SCRIPTTYPE().GetTextSanitized()),
                ReturnType          = (short)opcodes.GetTypeInfo(context.VALUETYPE().GetTextSanitized()).Opcode,
                RootExpressionIndex = rootExpressionIndex
            };
            // Handle scripts with parameters.
            var parameterContext = context.scriptParameters();

            if (parameterContext != null)
            {
                var parameters = parameterContext.parameter();
                for (ushort i = 0; i < parameters.Length; i++)
                {
                    string name          = parameters[i].ID().GetTextSanitized();
                    var    valueTypeNode = parameters[i].VALUETYPE();
                    string valueType     = valueTypeNode is null ? "script" : valueTypeNode.GetTextSanitized();

                    // Add the parameter to the script object.
                    ScriptParameter parameter = new ScriptParameter
                    {
                        Name = name,
                        Type = opcodes.GetTypeInfo(valueType).Opcode
                    };
                    script.Parameters.Add(parameter);
                }
            }
            return(script);
        }
示例#15
0
        private void DecompileScripts(object streamManager)
        {
            DateTime startTime = DateTime.Now;

            ScriptTable scripts;

            using (IReader reader = ((IStreamManager)streamManager).OpenRead())
            {
                scripts = _scriptFile.LoadScripts(reader);
                if (scripts == null)
                {
                    return;
                }
            }

            OpcodeLookup opcodes   = _buildInfo.ScriptInfo;
            var          generator = new BlamScriptGenerator(scripts, opcodes, _endian);
            var          code      = new IndentedTextWriter(new StringWriter());

            generator.WriteComment("Decompiled with Assembly", code);
            generator.WriteComment("", code);
            generator.WriteComment("Source file: " + _scriptFile.Name, code);
            generator.WriteComment("Start time: " + startTime, code);
            generator.WriteComment("", code);
            generator.WriteComment("Remember that all script code is property of Bungie/343 Industries.", code);
            generator.WriteComment("You have no rights. Play nice.", code);
            code.WriteLine();

            int counter = 0;

            if (scripts.Variables != null)
            {
                generator.WriteComment("VARIABLES", code);
                foreach (ScriptGlobal variable in scripts.Variables)
                {
                    code.Write("(variable {0} {1} ", opcodes.GetTypeInfo((ushort)variable.Type).Name, variable.Name);
                    generator.WriteExpression(variable.ExpressionIndex, code);
                    if (_showInfo)
                    {
                        code.WriteLine(")\t\t; Index: {0}, Expression Index: {1}", counter.ToString(), variable.ExpressionIndex.Index.ToString());
                    }
                    else
                    {
                        code.WriteLine(")");
                    }
                    counter++;
                }
                code.WriteLine();
                counter = 0;
            }

            generator.WriteComment("GLOBALS", code);
            foreach (ScriptGlobal global in scripts.Globals)
            {
                code.Write("(global {0} {1} ", opcodes.GetTypeInfo((ushort)global.Type).Name, global.Name);
                generator.WriteExpression(global.ExpressionIndex, code);
                if (_showInfo)
                {
                    code.WriteLine(")\t\t; Index: {0}, Expression Index: {1}", counter.ToString(), global.ExpressionIndex.Index.ToString());
                }
                else
                {
                    code.WriteLine(")");
                }
                counter++;
            }
            code.WriteLine();
            counter = 0;

            generator.WriteComment("SCRIPTS", code);
            foreach (Script script in scripts.Scripts)
            {
                if (_showInfo)
                {
                    generator.WriteComment(string.Format("Index: {0}, Expression Index: {1}", counter.ToString(), script.RootExpressionIndex.Index.ToString()), code);
                }

                code.Write("(script {0} {1} ", opcodes.GetScriptTypeName((ushort)script.ExecutionType),
                           opcodes.GetTypeInfo((ushort)script.ReturnType).Name);

                if (script.Parameters != null && script.Parameters.Count > 0)
                {
                    code.Write("({0} (", script.Name);

                    bool firstParam = true;
                    foreach (ScriptParameter param in script.Parameters)
                    {
                        if (!firstParam)
                        {
                            code.Write(", ");
                        }
                        code.Write("{1} {0}", param.Name, opcodes.GetTypeInfo((ushort)param.Type).Name);
                        firstParam = false;
                    }

                    code.Write("))");
                }
                else
                {
                    code.Write(script.Name);
                }

                code.Indent++;
                code.WriteLine();
                generator.WriteExpression(script.RootExpressionIndex, code, _buildInfo.HeaderSize == 0x1E000);
                code.Indent--;

                code.WriteLine();
                code.WriteLine(")");
                code.WriteLine();
                counter++;
            }

            DateTime endTime  = DateTime.Now;
            TimeSpan duration = endTime.Subtract(startTime);

            generator.WriteComment("Decompilation finished in ~" + duration.TotalSeconds + "s", code);

            Dispatcher.Invoke(new Action(delegate { txtScript.Text = code.InnerWriter.ToString(); }));
        }
示例#16
0
        public static IHighlightingDefinition LoadEmbeddedBlamScriptDefinition(string filename, OpcodeLookup lookup)
        {
            // Embedded resources are prefixed with their namespace name
            string ns           = typeof(HighlightLoader).Namespace;
            string resourcePath = ns + '.' + filename;

            // Read it from the assembly this class is embedded in.
            System.Reflection.Assembly assembly = typeof(HighlightLoader).Assembly;
            using (Stream s = assembly.GetManifestResourceStream(resourcePath))
            {
                if (s != null)
                {
                    XDocument doc = XDocument.Load(s);
                    UpdateXshdWithScriptInfo(doc, lookup);

                    // We can't write the updated definition to the resource stream. Therefore we have to create a new stream.
                    using (var destinationStream = new MemoryStream())
                    {
                        // Save and rewind the stream.
                        doc.Save(destinationStream);
                        destinationStream.Seek(0, SeekOrigin.Begin);

                        using (var reader = new XmlTextReader(destinationStream))
                        {
                            // Don't cache the definition, since keywords vary between games.
                            return(HighlightingLoader.Load(reader, HighlightingManager.Instance));
                        }
                    }
                }
                else
                {
                    throw new FileNotFoundException($"An embedded highlighting definition file with the name {filename} could not be found.");
                }
            }
        }
示例#17
0
        /// <summary>
        ///     Extracts all unique unit seat mappings from the script expressions of a scnr based script file.
        /// </summary>
        /// <param name="scnr">The scnr based script file.</param>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="op">A lookup containing script type information.</param>
        /// <returns>All unique unit seat mappings contained in the script expressions.</returns>
        public static IEnumerable <UnitSeatMapping> ExtractScnrSeatMappings(ScnrScriptFile scnr, IReader reader, OpcodeLookup op)
        {
            ScriptTable     scripts  = scnr.LoadScripts(reader);
            ScriptValueType typeInfo = op.GetTypeInfo("unit_seat_mapping");

            // find all unique mappings
            SortedDictionary <uint, UnitSeatMapping> uniqueMappings = new SortedDictionary <uint, UnitSeatMapping>();

            foreach (var exp in scripts.Expressions)
            {
                if (exp.Opcode == typeInfo.Opcode && exp.ReturnType == typeInfo.Opcode && !exp.Value.IsNull)
                {
                    // Calculate the index and only add it if it doesn't exist yet.
                    uint index = exp.Value.UintValue & 0xFFFF;
                    if (!uniqueMappings.ContainsKey(index))
                    {
                        uint            count   = (exp.Value.UintValue & 0xFFFF0000) >> 16;
                        string          name    = exp.StringValue;
                        UnitSeatMapping mapping = new UnitSeatMapping((short)index, (short)count, name);
                        uniqueMappings.Add(index, mapping);
                    }
                }
            }
            return(uniqueMappings.Values);
        }