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); } }
private uint GetValue(ScriptExpression expression, ScriptValueType type) { //var valBytes = new byte[4]; uint newVal = 0; byte[] valBytes = new byte[4]; switch(type.Size) { case 1: valBytes[0] = 0; valBytes[1] = 0; valBytes[2] = 0; valBytes[3] = (byte)(expression.Value); break; case 2: valBytes[0] = 0; valBytes[1] = 0; valBytes[2] = (byte)(expression.Value); valBytes[3] = (byte)(expression.Value >> 8); break; default: case 4: valBytes[0] = (byte)(expression.Value); valBytes[1] = (byte)(expression.Value >> 8); valBytes[2] = (byte)(expression.Value >> 16); valBytes[3] = (byte)(expression.Value >> 24); break; } newVal = BitConverter.ToUInt32(valBytes, 0); return newVal >> (32 - (type.Size * 8)); //return expression.Value >> (32 - (type.Size*8)); }
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(")"); } } }
public void RegisterValueType(ScriptValueType type) { _typeLookupByName[type.Name] = type; _typeLookupByOpcode[type.Opcode] = type; }
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); }
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(")"); } } }
private uint GetValue(ScriptExpression expression, ScriptValueType type) { return expression.Value >> (32 - (type.Size*8)); }
/// <summary> /// The decompiler generates a literal (expression) on an expression. /// </summary> /// <param name="output">The output.</param> /// <param name="expression">The expression.</param> /// <param name="newLine">Indicates whether the expressions of the branch start on a new line.</param> /// <returns>Returns true if code was generated.</returns> private bool GenerateExpression(IndentedTextWriter output, ScriptExpression expression, bool newLine) { ScriptValueType type = _opcodes.GetTypeInfo(expression.ReturnType); ScriptValueType actualType = type; // Check if a typecast is occurring if (expression.Opcode != 0xFFFF) { actualType = _opcodes.GetTypeInfo(expression.Opcode); // Simply write the string for quoted expressions. if (actualType.Quoted) { // Don't quote the keyword none. if (expression.Value.IsNull || expression.StringValue == "none") { output.Write("none"); } else { output.Write("\"{0}\"", ScriptStringHelpers.Escape(expression.StringValue)); } return(false); } } uint value = GetValue(expression, actualType); byte[] val = BitConverter.GetBytes(value); string text; switch (actualType.Name) { case "void": text = ""; break; case "ai_command_script": case "script": short index = BitConverter.ToInt16(val, 0); text = _scripts.Scripts[index].Name; break; case "boolean": text = BitConverter.ToBoolean(val, 0) ? "true" : "false"; break; case "short": text = BitConverter.ToInt16(val, 0).ToString(); break; case "long": // Signed integer int signed = (int)value; text = signed.ToString(); break; case "real": float fl = BitConverter.ToSingle(val, 0); text = fl.ToString("0.0#######", CultureInfo.InvariantCulture); break; case "ai_line": text = expression.StringValue == "" ? "\"\"" : expression.StringValue; break; case "unit_seat_mapping": text = expression.Value.IsNull ? "none" : expression.StringValue; break; default: if (expression.Value.IsNull) { text = "none"; } else if (actualType.IsEnum) { string enumValue = actualType.GetEnumValue(value); if (enumValue != null) { text = enumValue; } else { throw new NotImplementedException("Unknown Enum Value."); } } else { //throw new NotImplementedException($"Unhandled Return Type: \"{actualType.Name}\"."); text = expression.StringValue; } break; } output.Write(text); HandleNewLine(output, newLine); return(false); }
private uint GetValue(ScriptExpression expression, ScriptValueType type) { return(expression.Value >> (32 - (type.Size * 8))); }