示例#1
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);
        }
示例#2
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);
        }
示例#3
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));
            }
        }
示例#4
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(); }));
        }
示例#5
0
        private void CompareNormalExpressions(ScriptExpression origExp, ScriptExpression modExp)
        {
            ExpressionValueComparer valComparer = new ExpressionValueComparer();
            bool areEqual = true;

            // the opcodes always have to match.
            areEqual = areEqual && (origExp.Opcode == modExp.Opcode);
            areEqual = areEqual && (origExp.ReturnType == modExp.ReturnType);

            // An expression's opcode determines its actual value type. The value type is used for casting. Function names are an exception.
            string valueType = _op.GetTypeInfo(origExp.ReturnType).Name == "function_name" ? "function_name" : _op.GetTypeInfo(origExp.Opcode).Name;

            switch (valueType)
            {
            case "void":
            case "boolean":
            case "long":
            case "short":
                // ignore random strings.
                areEqual = areEqual && valComparer.Equals(origExp.Value, modExp.Value);
                break;

            case "real":
                byte[] b1  = BitConverter.GetBytes(origExp.Value.UintValue);
                byte[] b2  = BitConverter.GetBytes(modExp.Value.UintValue);
                float  fl1 = BitConverter.ToSingle(b1, 0);
                float  fl2 = BitConverter.ToSingle(b2, 0);
                if ((fl1 != 0.0 || fl2 != -0.0) && (fl1 != -0.0 || fl2 != 0.0))
                {
                    areEqual = areEqual && valComparer.Equals(origExp.Value, modExp.Value);
                }
                break;

            case "string":
            case "string_id":
            case "function_name":
                areEqual = areEqual && (origExp.StringValue == modExp.StringValue);
                break;

            case "sound":
            case "effect":
            case "damage":
            case "looping_sound":
            case "animation_graph":
            case "damage_effect":
            case "object_definition":
            case "bitmap":
            case "shader":
            case "render_model":
            case "structure_definition":
            case "lightmap_definition":
            case "cinematic_definition":
            case "cinematic_scene_definition":
            case "cinematic_transition_definition":
            case "bink_definition":
            case "cui_screen_definition":
            case "any_tag":
            case "any_tag_not_resolving":
            case "ai_line":
            case "unit_seat_mapping":
                areEqual = areEqual && valComparer.Equals(origExp.Value, modExp.Value);
                // ignore missing tags, ai lines and unit seat mappings
                if (!origExp.Value.IsNull)
                {
                    areEqual = areEqual && (origExp.StringValue == modExp.StringValue);
                }
                break;

            default:
                areEqual = areEqual && valComparer.Equals(origExp.Value, modExp.Value);
                // Ignore enum values, where a space char was replaced with an underscore.
                if (origExp.StringValue != modExp.StringValue && (!_op.GetTypeInfo(valueType).IsEnum || origExp.StringValue.Replace(' ', '_') != modExp.StringValue))
                {
                    areEqual = false;
                }
                break;
            }

            if (!areEqual)
            {
                WriteScriptObject();

                _output.WriteLine("Unequal Expressions!");
                _output.WriteLine("### Original ###");
                _output.WriteLine(ExpressionToString(origExp));
                _output.WriteLine("### Modified ###");
                _output.WriteLine(ExpressionToString(modExp));
                _output.WriteLine();
            }
        }
示例#6
0
        /// <summary>
        /// Processes script declarations. Opens a datum. 
        /// Creates the script node and the initial "begin" expression.
        /// Generates the variable lookup. Pushes return types.
        /// </summary>
        /// <param name="context"></param>
        public override void EnterScriptDeclaration(HS_Gen1Parser.ScriptDeclarationContext context)
        {
            if(_debug)
            {
                _logger.Script(context, CompilerContextAction.Enter);
            }

            // Create new script object and add it to the table.
            Script script = ScriptObjectCreation.GetScriptFromContext(context, _currentIndex, _opcodes);
            _scripts.Add(script);

            // Generate the parameter lookup.
            for(ushort i = 0; i < script.Parameters.Count; i++)
            {
                ScriptParameter parameter = script.Parameters[i];
                var info = new ParameterInfo(parameter.Name, _opcodes.GetTypeInfo(parameter.Type).Name, i);
                _parameterLookup.Add(info.Name, info);
            }

            string returnType = context.VALUETYPE().GetTextSanitized();
            int expressionCount = context.expression().Count();

            // The final expression must match the return type of this script.
            _expectedTypes.PushType(returnType);
            // The other expressions can be of any type.
            if (expressionCount > 1)
            {
                _expectedTypes.PushTypes("void", expressionCount - 1);
            }

            CreateInitialBegin(returnType, context.GetCorrectTextPosition(_missingCarriageReturnPositions));
        }