private string FormatCode() { UDecompilingState.AddTabs(1); string locals = FormatLocals(); if (locals != String.Empty) { locals += "\r\n"; } string code; try { code = DecompileScript(); } catch (Exception e) { code = e.Message; } finally { UDecompilingState.RemoveTabs(1); } // Empty function! if (String.IsNullOrEmpty(locals) && String.IsNullOrEmpty(code)) { return(String.Empty); } return(UnrealConfig.PrintBeginBracket() + "\r\n" + locals + code + UnrealConfig.PrintEndBracket()); }
public string FormatDefaultProperties() { if (Default != null && Default != this) { Default.BeginDeserializing(); } if (Properties == null || !Properties.Any()) { return(String.Empty); } string output = String.Empty; string innerOutput; if (IsClassType("Class")) { output += "\r\ndefaultproperties\r\n{\r\n"; } else { output += "\r\n" + UDecompilingState.Tabs + "structdefaultproperties\r\n" + UDecompilingState.Tabs + "{\r\n"; } UDecompilingState.AddTabs(1); try { innerOutput = DecompileProperties(); } catch (Exception e) { innerOutput = String.Format ( "{0}// {1} occurred while decompiling properties!\r\n", UDecompilingState.Tabs, e.GetType().Name ); } finally { UDecompilingState.RemoveTabs(1); } if (Name.StartsWith("Seq")) { innerOutput += $"\tObjCategory=\"{Package.FullPackageName}\"\r\n"; } return(output + innerOutput + UDecompilingState.Tabs + "}"); }
public virtual string Decompile() { try { UDecompilingState.ResetTabs(); return(Object.Decompile()); } catch (Exception e) { return(String.Format ( "An exception of type \"{0}\" occurred while decompiling {1}.\r\nDetails:\r\n{2}", e.GetType().Name, Text, e )); } }
private string FormatNames() { string output = String.Empty; UDecompilingState.AddTabs(1); for (int index = 0; index < Names.Count; index++) { var enumName = Names[index]; output += "\r\n" + UDecompilingState.Tabs + enumName; if (index != Names.Count - 1) { output += ","; } } UDecompilingState.RemoveTabs(1); return(output); }
/// <summary> /// Decompiles this Object into human-readable code /// </summary> public virtual string Decompile() { if (ShouldDeserializeOnDemand) { BeginDeserializing(); } string output = String.Format("begin object name={0} class={1}\r\n", Name, Class.Name); UDecompilingState.AddTabs(1); try { output += DecompileProperties(); } finally { UDecompilingState.RemoveTabs(1); } return(output + String.Format("{0}object end\r\n{0}// Reference: {1}'{2}'", UDecompilingState.Tabs, Class.Name, GetOuterGroup())); }
/// <summary> /// Decompiles this Object into human-readable code /// </summary> public virtual string Decompile() { if (ShouldDeserializeOnDemand) { BeginDeserializing(); } string output = $"{{\r\n\"Name\":\"{Name}\",\r\n\"Class\":\"{Class.Name}\",\r\n"; UDecompilingState.AddTabs(1); try { output += DecompileProperties(); } finally { UDecompilingState.RemoveTabs(1); } return($"{output}{UDecompilingState.Tabs}\r\n}}\r\n{UDecompilingState.Tabs}"); }
/// <summary> /// Decompiles this object into a text format of: /// /// [FLAGS] state[()] NAME [extends NAME] /// { /// [ignores Name[,Name];] /// /// [FUNCTIONS] /// /// [STATE CODE] /// }; /// </summary> /// <returns></returns> public override string Decompile() { string content = FormatHeader() + UnrealConfig.PrintBeginBracket(); UDecompilingState.AddTabs(1); var locals = FormatLocals(); if (locals != String.Empty) { content += "\r\n" + locals; } content += FormatIgnores() + FormatConstants() + FormatFunctions() + DecompileScript(); UDecompilingState.RemoveTabs(1); content += UnrealConfig.PrintEndBracket(); return(content); }
/// <summary> /// Decompiles this object into a text format of: /// /// struct [FLAGS] NAME [extends NAME] /// { /// [STRUCTCPPTEXT] /// /// [CONSTS] /// /// [ENUMS] /// /// [STRUCTS] /// /// [VARIABLES] /// /// [STRUCTDEFAULTPROPERTIES] /// }; /// </summary> /// <returns></returns> public override string Decompile() { string content = UDecompilingState.Tabs + FormatHeader() + UnrealConfig.PrintBeginBracket(); UDecompilingState.AddTabs(1); string cpptext = FormatCPPText(); string props = FormatProperties(); string defProps = FormatDefaultProperties(); if (defProps.Length != 0) { defProps += "\r\n"; } UDecompilingState.RemoveTabs(1); content += cpptext + props + defProps; if (content.EndsWith("\r\n")) { content = content.TrimEnd('\r', '\n'); } return(content + UnrealConfig.PrintEndBracket() + ";"); }
public string FormatReplication() { if (DataScriptSize <= 0) { return(string.Empty); } var replicatedObjects = new List <IUnrealNetObject>(); if (Variables != null) { replicatedObjects.AddRange(Variables.Where(prop => prop.HasPropertyFlag(Flags.PropertyFlagsLO.Net) && prop.RepOffset != ushort.MaxValue)); } if (Package.Version < VReliableDeprecation && Functions != null) { replicatedObjects.AddRange(Functions.Where(func => func.HasFunctionFlag(Flags.FunctionFlags.Net) && func.RepOffset != ushort.MaxValue)); } if (replicatedObjects.Count == 0) { return(string.Empty); } var statements = new Dictionary <uint, List <IUnrealNetObject> >(); replicatedObjects.Sort((ro, ro2) => ro.RepKey.CompareTo(ro2.RepKey)); for (int netIndex = 0; netIndex < replicatedObjects.Count; ++netIndex) { var firstObject = replicatedObjects[netIndex]; var netObjects = new List <IUnrealNetObject> { firstObject }; for (int nextIndex = netIndex + 1; nextIndex < replicatedObjects.Count; ++nextIndex) { var nextObject = replicatedObjects[nextIndex]; if (nextObject.RepOffset != firstObject.RepOffset || nextObject.RepReliable != firstObject.RepReliable ) { netIndex = nextIndex - 1; break; } netObjects.Add(nextObject); } netObjects.Sort((o, o2) => string.Compare(o.Name, o2.Name, StringComparison.Ordinal)); if (!statements.ContainsKey(firstObject.RepKey)) { statements.Add(firstObject.RepKey, netObjects); } } replicatedObjects.Clear(); var output = new StringBuilder("\r\n" + "replication" + UnrealConfig.PrintBeginBracket()); UDecompilingState.AddTab(); foreach (var statement in statements) { try { var pos = (ushort)(statement.Key & 0x0000FFFF); var rel = Convert.ToBoolean(statement.Key & 0xFFFF0000); output.Append("\r\n" + UDecompilingState.Tabs); if (!UnrealConfig.SuppressComments) { output.AppendFormat("// Pos:0x{0:X3}\r\n{1}", pos, UDecompilingState.Tabs); } ByteCodeManager.Deserialize(); ByteCodeManager.JumpTo(pos); string statementCode; try { statementCode = ByteCodeManager.CurrentToken.Decompile(); } catch (Exception e) { statementCode = string.Format("/* An exception occurred while decompiling condition ({0}) */", e); } var statementType = Package.Version < VReliableDeprecation ? rel ? "reliable" : "unreliable" : string.Empty; var statementFormat = string.Format("{0} if({1})", statementType, statementCode); output.Append(statementFormat); UDecompilingState.AddTab(); // NetObjects for (int i = 0; i < statement.Value.Count; ++i) { var shouldSplit = i % 2 == 0; if (shouldSplit) { output.Append("\r\n" + UDecompilingState.Tabs); } var netObject = statement.Value[i]; output.Append(netObject.Name); var isNotLast = i != statement.Value.Count - 1; output.Append(isNotLast ? ", " : ";"); } UDecompilingState.RemoveTab(); // IsNotLast if (statements.Last().Key != statement.Key) { output.Append("\r\n"); } } catch (Exception e) { output.AppendFormat("/* An exception occurred while decompiling a statement! ({0}) */", e); } } UDecompilingState.RemoveTab(); output.Append(UnrealConfig.PrintEndBracket() + "\r\n"); return(output.ToString()); }
/// <summary> /// FORMATION ISSUESSES: /// 1:(-> Logic remains the same) Continue's are decompiled as Else's statements e.g. /// -> Original /// if( continueCondition ) /// { /// continue; /// } /// /// // Actual code /// /// -> Decompiled /// if( continueCodition ) /// { /// } /// else /// { /// // Actual code /// } /// /// /// 2:(-> ...) ... /// -> Original /// ... /// -> Decompiled /// ... /// /// </summary> public override string Decompile() { // Break offset! if (CodeOffset >= Position) { //==================We're inside a Case and at the end of it! if (Decompiler.IsInNest(NestManager.Nest.NestType.Case) != null) { //Decompiler._Nester.AddNestEnd( NestManager.Nest.NestType.Case, Position ); NoJumpLabel(); Commentize(); Decompiler._CanAddSemicolon = true; return("break"); } //==================We're inside a Default and at the end of it! if (Decompiler.IsInNest(NestManager.Nest.NestType.Default) != null) { NoJumpLabel(); Commentize(); Decompiler._Nester.AddNestEnd(NestManager.Nest.NestType.Default, Position); Decompiler._Nester.AddNestEnd(NestManager.Nest.NestType.Switch, Position); Decompiler._CanAddSemicolon = true; return("break"); } var nest = Decompiler.IsWithinNest(NestManager.Nest.NestType.ForEach); if (nest != null) { var dest = Decompiler.TokenAt(CodeOffset); if (dest != null) { if (dest is IteratorPopToken) { if (Decompiler.PreviousToken is IteratorNextToken) { NoJumpLabel(); return(String.Empty); } NoJumpLabel(); Commentize(); Decompiler._CanAddSemicolon = true; return("break"); } if (dest is IteratorNextToken) { NoJumpLabel(); Commentize(); Decompiler._CanAddSemicolon = true; return("continue"); } } } nest = Decompiler.IsWithinNest(NestManager.Nest.NestType.Loop); if (nest != null) { var dest = nest.Creator as JumpToken; if (dest != null) { if (CodeOffset + 10 == dest.CodeOffset) { CommentStatement("Explicit Continue"); goto gotoJump; } if (CodeOffset == dest.CodeOffset) { CommentStatement("Explicit Break"); goto gotoJump; } } } nest = Decompiler.IsInNest(NestManager.Nest.NestType.If); //==================We're inside a If and at the end of it! if (nest != null) { // We're inside a If however the kind of jump could range from: continue; break; goto; else var nestEnd = Decompiler.CurNestEnd(); if (nestEnd != null) { // Else, Req:In If nest, nestends > 0, curendnest position == Position if (nestEnd.Position - Size == Position) { // HACK: This should be handled by UByteCodeDecompiler.Decompile() UDecompilingState.RemoveTabs(1); Decompiler._NestChain.RemoveAt(Decompiler._NestChain.Count - 1); Decompiler._Nester.Nests.Remove(nestEnd); Decompiler._Nester.AddNest(NestManager.Nest.NestType.Else, Position, CodeOffset); NoJumpLabel(); // HACK: This should be handled by UByteCodeDecompiler.Decompile() return("}" + "\r\n" + (UnrealConfig.SuppressComments ? UDecompilingState.Tabs + "else" : UDecompilingState.Tabs + String.Format("// End:0x{0:X2}", CodeOffset) + "\r\n" + UDecompilingState.Tabs + "else")); } } } } if (CodeOffset < Position) { CommentStatement("Loop Continue"); } gotoJump: // This is an implicit GoToToken. Decompiler._CanAddSemicolon = true; return(String.Format("goto J0x{0:X2}", CodeOffset)); }