Пример #1
0
		public void RegisterFunction(ScriptFunctionInfo func)
		{
			_functionLookupByOpcode[func.Opcode] = func;

			List<ScriptFunctionInfo> functions;
			if (!_functionLookupByName.TryGetValue(func.Name, out functions))
			{
				functions = new List<ScriptFunctionInfo>();
				_functionLookupByName[func.Name] = functions;
			}
			functions.Add(func);
		}
Пример #2
0
        public XMLOpcodeLookup(XDocument document)
        {
            XContainer root = document.Element("BlamScript");

            // Script execution types
            var scriptTypes = from element in root.Element("scriptTypes").Descendants("type")
                              select new
                              {
                                  Opcode = (ushort)XMLUtil.GetNumericAttribute(element, "opcode"),
                                  Name = XMLUtil.GetStringAttribute(element, "name")
                              };
            _scriptTypeNameLookup = scriptTypes.ToDictionary(t => t.Opcode, t => t.Name);
            _scriptTypeOpcodeLookup = scriptTypes.ToDictionary(t => t.Name, t => t.Opcode);

            // Value types
            var valueTypes = new List<ScriptValueType>();
            foreach (var element in root.Element("valueTypes").Descendants("type"))
            {
                var name = XMLUtil.GetStringAttribute(element, "name");
                var opcode = (ushort)XMLUtil.GetNumericAttribute(element, "opcode");
                var size = XMLUtil.GetNumericAttribute(element, "size");
                var quoted = XMLUtil.GetBoolAttribute(element, "quoted", false);
                var tag = XMLUtil.GetStringAttribute(element, "tag", null);

                valueTypes.Add(new ScriptValueType(name, opcode, size, quoted, tag));
            }
            _typeLookupByOpcode = valueTypes.ToDictionary(t => t.Opcode);
            _typeLookupByName = valueTypes.ToDictionary(t => t.Name);

            // Functions
            foreach (var element in root.Element("functions").Descendants("function"))
            {
                var name = XMLUtil.GetStringAttribute(element, "name");
                if (name == "")
                    continue;

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

                var info = new ScriptFunctionInfo(name, opcode, returnType, flags, parameterTypes);
                List<ScriptFunctionInfo> functions;
                if (!_functionLookupByName.TryGetValue(name, out functions))
                {
                    functions = new List<ScriptFunctionInfo>();
                    _functionLookupByName[name] = functions;
                }
                functions.Add(info);
                _functionLookupByOpcode[opcode] = info;
            }
        }
Пример #3
0
        public void RegisterFunction(ScriptFunctionInfo func)
        {
            _functionLookupByOpcode[func.Opcode] = func;

            List <ScriptFunctionInfo> functions;

            if (!_functionLookupByName.TryGetValue(func.Name, out functions))
            {
                functions = new List <ScriptFunctionInfo>();
                _functionLookupByName[func.Name] = functions;
            }
            functions.Add(func);
        }
Пример #4
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);
            }
        }
Пример #5
0
        private void GenerateCode(ScriptExpression expression, IndentedTextWriter output, bool firstrun = false)
        {
            int  firstIndentedArg = int.MaxValue;
            bool isFunctionCall   = false;

            if (expression.Type == ScriptExpressionType.Expression || expression.Type == ScriptExpressionType.Expression4)
            {
                ScriptValueType type = _opcodes.GetTypeInfo((ushort)expression.ReturnType);
                if (type.Name == "function_name")
                {
                    isFunctionCall = true;

                    if (!_nextFunctionIsScript)
                    {
                        ScriptFunctionInfo info = _opcodes.GetFunctionInfo(expression.Opcode);
                        if (info != null)
                        {
                            if (info.Name.StartsWith("begin"))
                            {
                                firstIndentedArg = 0;
                                if (expression.LineNumber > 0 && !_onNewLine)
                                {
                                    output.Indent++;
                                    output.WriteLine();
                                }
                            }
                            else if (info.Name == "if")
                            {
                                firstIndentedArg = 1;
                            }
                        }
                    }
                    if (expression.LineNumber > 0)
                    {
                        output.Write("(");
                    }
                }
            }



            bool wroteAnything = wroteAnything = HandleExpression(expression, output);
            int  startIndent   = output.Indent;

            int currentArg = 0;

            if (_h4 && firstrun)
            {
                firstIndentedArg = 0;
                currentArg       = 1;
                _h4 = false;
            }

            ScriptExpression sibling = expression.Next;

            while (sibling != null)
            {
                if (wroteAnything && !_nextExpressionIsVar)
                {
                    if (currentArg == firstIndentedArg)
                    {
                        output.Indent++;
                    }
                    if (currentArg >= firstIndentedArg)
                    {
                        output.WriteLine();
                        _onNewLine = true;
                    }
                    else if (output.Indent != startIndent)
                    {
                        output.WriteLine();
                        _onNewLine = true;
                    }
                    else
                    {
                        output.Write(" ");
                    }
                }

                if (!_nextExpressionIsVar)
                {
                    wroteAnything = HandleExpression(sibling, output);
                }
                else if ((_nextExpressionIsVar && sibling.Opcode != 0xFFFF))
                {
                    if (!_varTypeWritten)
                    {
                        ScriptValueType type = _opcodes.GetTypeInfo((ushort)sibling.ReturnType);
                        output.Write(type.Name + " var_" + localVarCounter.ToString() + " ");
                        _varTypeWritten = true;
                    }

                    wroteAnything = HandleExpression(sibling, output);
                }

                sibling = sibling.Next;
                currentArg++;
            }

            if (isFunctionCall && expression.LineNumber > 0)
            {
                if (output.Indent != startIndent)
                {
                    output.Indent = startIndent;
                    if (wroteAnything)
                    {
                        output.WriteLine();
                    }
                    output.Write(")");
                    _onNewLine = true;
                }
                else
                {
                    output.Write(")");
                }
            }
        }
Пример #6
0
        private bool GenerateExpressionCode(ScriptExpression expression, IndentedTextWriter output)
        {
            if (expression.LineNumber == 0)
            {
                return(false);
            }

            _onNewLine = false;
            ScriptValueType type       = _opcodes.GetTypeInfo((ushort)expression.ReturnType);
            ScriptValueType actualType = type;

            if (type.Name != "function_name")
            {
                // Check if a typecast is occurring

                if (expression.Opcode != 0xFFFF)
                {
                    actualType = _opcodes.GetTypeInfo(expression.Opcode);

                    if (actualType.Quoted)
                    {
                        if (expression.Value != 0xFFFFFFFF)
                        {
                            output.Write("\"{0}\"", expression.StringValue);
                        }
                        else
                        {
                            output.Write("none");
                        }
                        return(true);
                    }
                }
            }

            uint value = GetValue(expression, type, _endian);

            byte[] val = BitConverter.GetBytes(value);

            switch (type.Name)
            {
            case "void":
                return(false);

            case "boolean":
                if (BitConverter.ToBoolean(val, 0))
                {
                    output.Write("true");
                }
                else
                {
                    output.Write("false");
                }
                break;

            case "short":
                output.Write(BitConverter.ToInt16(val, 0));
                break;

            case "long":
                // Signed integer
                output.Write((int)value);
                break;

            case "real":
                // Eww
                //var floatBytes = new byte[4];
                //floatBytes[0] = (byte) (value & 0xFF);
                //floatBytes[1] = (byte) ((value >> 8) & 0xFF);
                //floatBytes[2] = (byte) ((value >> 16) & 0xFF);
                //floatBytes[3] = (byte) ((value >> 24) & 0xFF);
                output.Write(BitConverter.ToSingle(val, 0));
                break;

            case "function_name":
                if (_nextFunctionIsScript)
                {
                    if (expression.Opcode >= _scripts.Scripts.Count)
                    {
                        output.Write("import#" + expression.StringValue);
                    }
                    else
                    {
                        output.Write(expression.StringValue);                                 // todo: there are cases (h3 xbox mainmenu's campaign_cam specifically) where the function_name expression's opcode value is +1 from what it should be, and the expression prior has the right index.
                    }
                    // the current state of this script code doesnt seem to be good enough to step back so here is the hacky fix implemented in the HO fork.

                    //output.Write(_scripts.Scripts[expression.Opcode].Name);

                    _nextFunctionIsScript = false;
                }
                else
                {
                    ScriptFunctionInfo info = _opcodes.GetFunctionInfo(expression.Opcode);
                    if (info == null)
                    {
                        output.Write("UNNAMED_OPCODE_" + expression.Opcode.ToString("X4") + "#" + expression.StringValue);
                    }
                    else
                    {
                        output.Write(info.Name);
                    }
                    //throw new InvalidOperationException("Unrecognized function opcode 0x" + expression.Opcode.ToString("X"));
                }
                break;

            case "unit_seat_mapping":
                // This isn't the technical way of doing this,
                // but since seat mapping names aren't stored anywhere,
                // it would be tricky to resolve them unless we just use an index for now
                if (expression.Value != 0xFFFFFFFF)
                {
                    output.Write(expression.Value & 0xFFFF);
                }
                else
                {
                    output.Write("none");
                }
                break;

            case "unparsed":
                break;

            default:
                string enumValue = actualType.GetEnumValue(value);
                if (enumValue != null)
                {
                    output.Write(enumValue);
                }
                else if (expression.Value == 0xFFFFFFFF)
                {
                    output.Write("none");
                }
                else
                {
                    enumValue = expression.StringValue;
                    if (enumValue != null)
                    {
                        output.Write(enumValue);
                    }
                    else
                    {
                        output.Write("0x{0:X}", value);
                    }
                }
                break;
            }
            return(true);
        }
        private void GenerateCode(ScriptExpression expression, IndentedTextWriter output)
        {
            int  firstIndentedArg = int.MaxValue;
            bool isFunctionCall   = false;

            if (expression.Type == ScriptExpressionType.Expression)
            {
                ScriptValueType type = _opcodes.GetTypeInfo((ushort)expression.ReturnType);
                if (type.Name == "function_name")
                {
                    isFunctionCall = true;

                    if (!_nextFunctionIsScript)
                    {
                        ScriptFunctionInfo info = _opcodes.GetFunctionInfo(expression.Opcode);
                        if (info != null)
                        {
                            if (info.Name.StartsWith("begin"))
                            {
                                firstIndentedArg = 0;
                                if (expression.LineNumber > 0 && !_onNewLine)
                                {
                                    output.Indent++;
                                    output.WriteLine();
                                }
                            }
                            else if (info.Name == "if")
                            {
                                firstIndentedArg = 1;
                            }
                        }
                    }
                    if (expression.LineNumber > 0)
                    {
                        output.Write("(");
                    }
                }
            }

            bool wroteAnything = HandleExpression(expression, output);
            int  startIndent   = output.Indent;

            int currentArg           = 0;
            ScriptExpression sibling = expression.Next;

            while (sibling != null)
            {
                if (wroteAnything)
                {
                    if (currentArg == firstIndentedArg)
                    {
                        output.Indent++;
                    }
                    if (currentArg >= firstIndentedArg || output.Indent != startIndent)
                    {
                        output.WriteLine();
                        _onNewLine = true;
                    }
                    else
                    {
                        output.Write(" ");
                    }
                }

                wroteAnything = HandleExpression(sibling, output);
                sibling       = sibling.Next;
                currentArg++;
            }

            if (isFunctionCall && expression.LineNumber > 0)
            {
                if (output.Indent != startIndent)
                {
                    output.Indent = startIndent;
                    if (wroteAnything)
                    {
                        output.WriteLine();
                    }
                    output.Write(")");
                    _onNewLine = true;
                }
                else
                {
                    output.Write(")");
                }
            }
        }
        private bool GenerateExpressionCode(ScriptExpression expression, IndentedTextWriter output)
        {
            if (expression.LineNumber == 0)
            {
                return(false);
            }

            _onNewLine = false;
            ScriptValueType type       = _opcodes.GetTypeInfo((ushort)expression.ReturnType);
            ScriptValueType actualType = type;

            if (type.Name != "function_name")
            {
                // Check if a typecast is occurring
                actualType = _opcodes.GetTypeInfo(expression.Opcode);

                if (actualType.Quoted)
                {
                    if (expression.Value != 0xFFFFFFFF)
                    {
                        output.Write("\"{0}\"", expression.StringValue);
                    }
                    else
                    {
                        output.Write("none");
                    }
                    return(true);
                }
            }

            uint value = GetValue(expression, type);

            switch (type.Name)
            {
            case "void":
                return(false);

            case "boolean":
                if (value > 0)
                {
                    output.Write("true");
                }
                else
                {
                    output.Write("false");
                }
                break;

            case "short":
            case "long":
                // Signed integer
                output.Write((int)value);
                break;

            case "real":
                // Eww
                var floatBytes = new byte[4];
                floatBytes[0] = (byte)(value & 0xFF);
                floatBytes[1] = (byte)((value >> 8) & 0xFF);
                floatBytes[2] = (byte)((value >> 16) & 0xFF);
                floatBytes[3] = (byte)((value >> 24) & 0xFF);
                output.Write(BitConverter.ToSingle(floatBytes, 0));
                break;

            case "function_name":
                if (_nextFunctionIsScript)
                {
                    output.Write(expression.StringValue);                             // halo online seems weird in that the "opcode" value that is actually a script index in this case is greater than the number of scripts
                    //output.Write(_scripts.Scripts[expression.Opcode].Name);
                    _nextFunctionIsScript = false;
                }
                else
                {
                    ScriptFunctionInfo info = _opcodes.GetFunctionInfo(expression.Opcode);
                    if (info == null)
                    {
                        output.Write("unknown_" + expression.Opcode.ToString("X") + "(" + expression.StringValue + ")");                          //throw new InvalidOperationException("Unrecognized function opcode 0x" + expression.Opcode.ToString("X"));
                    }
                    else
                    {
                        output.Write(info.Name);
                    }
                }
                break;

            case "unit_seat_mapping":
                // This isn't the technical way of doing this,
                // but since seat mapping names aren't stored anywhere,
                // it would be tricky to resolve them unless we just use an index for now
                if (expression.Value != 0xFFFFFFFF)
                {
                    output.Write(expression.Value & 0xFFFF);
                }
                else
                {
                    output.Write("none");
                }
                break;

            default:
                string enumValue = actualType.GetEnumValue(value);
                if (enumValue != null)
                {
                    output.Write(enumValue);
                }
                else if (expression.Value == 0xFFFFFFFF)
                {
                    output.Write("none");
                }
                else
                {
                    enumValue = expression.StringValue;
                    if (enumValue != null)
                    {
                        output.Write(enumValue);
                    }
                    else
                    {
                        output.Write("0x{0:X}", value);
                    }
                }
                break;
            }
            return(true);
        }