public string OutputCode(int IndentL) { for (int i = 0; i < Graph.Count; i++) { if (Graph[i].Type == VertexType.Branch) { int BranchIndex = IndexFromAddr(Graph[i].BranchTo); if (BranchIndex == -1) { Graph[i].Code = "break " + Graph[i].BranchTo.ToString() + ";";//Branch to label long EndAddr = Graph[Graph.Count - 1].Addr; CodeVertex Label = new CodeVertex(VertexType.Label, -1, Graph[i].BranchTo.ToString() + ":", EndAddr + 1); Graph.Add(Label); } else { VertexType DestType = Graph[BranchIndex].Type; if (DestType == VertexType.CodeBlock || DestType == VertexType.Branch) { Graph[i].Code = "break " + Graph[i].BranchTo.ToString() + ";";//Branch to label CodeVertex NewLine = new CodeVertex(VertexType.Label, -1, Graph[i].BranchTo.ToString() + ":", Graph[i].BranchTo); Graph.Insert(BranchIndex, NewLine); if (BranchIndex <= i) { i++; } } else if (DestType == VertexType.Label) { string LabelName = Graph[BranchIndex].Code.Replace(':', ' '); Graph[i].Code = "break " + LabelName + ";";//Branch to label } else if (DestType == VertexType.ConditionalBranch) { //While Loop Detected Graph[BranchIndex].Code = "while(" + Graph[BranchIndex].Code + ")" + Environment.NewLine + "{";//Put while loop int ClosingIndex = IndexFromAddr(Graph[BranchIndex].BranchTo); if (ClosingIndex == -1) { CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "}", Graph[BranchIndex].BranchTo); Graph.Add(NewLine); } else { CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "}", Graph[BranchIndex].BranchTo); Graph.Insert(ClosingIndex, NewLine); if (ClosingIndex <= i) { i++; } } } } } } for (int i = 0; i < Graph.Count; i++) { if (Graph[i].Type == VertexType.ConditionalBranch && !Graph[i].Code.StartsWith("while")) { if (Graph[i].Addr < Graph[i].BranchTo) { //If Statement Detected Graph[i].Code = "if(" + Graph[i].Code + ")" + Environment.NewLine + "{";//Put if int ClosingIndex = IndexFromAddr(Graph[i].BranchTo); if (ClosingIndex == -1) { CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "}", Graph[i].BranchTo); Graph.Add(NewLine); } else { CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "}", Graph[i].BranchTo); Graph.Insert(ClosingIndex, NewLine); if (ClosingIndex <= i) { i++; } } } else { //Do loop detected Graph[i].Code = "} while(" + Graph[i].Code + ")";//Put do loop int ClosingIndex = IndexFromAddr(Graph[i].BranchTo); CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "do" + Environment.NewLine + "{", Graph[i].BranchTo); Graph.Insert(ClosingIndex, NewLine); if (ClosingIndex <= i) { i++; } } } } string DecompiledCode = ""; for (int i = 0; i < Graph.Count; i++) { DecompiledCode = DecompiledCode + Environment.NewLine + Graph[i].Code; } string[] lines = DecompiledCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); DecompiledCode = ""; int IndentLevel = IndentL; for (int i = 0; i < lines.Length; i++) { if (lines[i] == "") { continue; } string IndentedString = new String(' ', IndentLevel * 4) + lines[i]; if (lines[i].Contains("{")) { IndentLevel++; } else if (lines[i].Contains("}")) { IndentLevel = System.Math.Max(0, IndentLevel - 1); IndentedString = new String(' ', IndentLevel * 4) + lines[i]; } if (DecompiledCode == "") { DecompiledCode = IndentedString; } else { DecompiledCode = DecompiledCode + Environment.NewLine + IndentedString; } } return(DecompiledCode); }
static void DecompFunction(uint ofs, int IndentL) { byte command; sReader.Keep(); sReader.Goto(sTextOffset + ofs); var maxofs = 0u; Stack <string> Stack = new Stack <string>(); CodeGraph FuncCodeGraph = new CodeGraph(); do { var pos = sReader.Position - sTextOffset; command = sReader.Read8(); var nextofs = 0u; switch (command) { case 0x00: //int { Stack.Push(sReader.ReadS32().ToString()); break; } case 0x01: //flt { Stack.Push(sReader.ReadF32().ToString()); break; } case 0x02: //str { var data = sReader.ReadS32(); var value = FetchDataValue(data); Stack.Push("\"" + value + "\""); break; } case 0x03: //adr { Stack.Push(sReader.ReadS32().ToString("X8")); break; } case 0x04: //var { var display = sReader.ReadS32(); var data = sReader.ReadS32(); switch (display) { case 0: Stack.Push(FetchSymbolName(FetchSymbol(i => i.Type == SymbolType.Variable && i.Data == data))); break; case 1: Stack.Push("local" + data.ToString()); break; } break; } case 0x06: //inc { string Op = Stack.Pop(); Stack.Push("(" + Op + "+1)"); break; } case 0x07: //dec { string Op = Stack.Pop(); Stack.Push("(" + Op + "-1)"); break; } case 0x08: //add { string Op2 = Stack.Pop(); string Op1 = Stack.Pop(); Stack.Push("(" + Op1 + " + " + Op2 + ")"); break; } case 0x09: //sub { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " - " + Op2 + ")"); break; } case 0x0A: //mul { string Op2 = Stack.Pop(); string Op1 = Stack.Pop(); Stack.Push("(" + Op1 + " * " + Op2 + ")"); break; } case 0x0B: //div { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " / " + Op2 + ")"); break; } case 0x0C: //mod { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " % " + Op2 + ")"); break; } case 0x0D: //ass { sReader.Read8(); //Ignore this byte var display = sReader.ReadS32(); var data = sReader.ReadS32(); string VariableName = ""; switch (display) { case 0: VariableName = FetchSymbolName(FetchSymbol(i => i.Type == SymbolType.Variable && i.Data == data)); break; case 1: VariableName = "local" + data.ToString(); break; } CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, VariableName + " = " + Stack.Pop() + ";", pos); FuncCodeGraph.AddVertex(NewLine); break; } case 0x0E: //eq { string Op2 = Stack.Pop(); string Op1 = Stack.Pop(); Stack.Push("(" + Op1 + " == " + Op2 + ")"); break; } case 0x0F: //ne { string Op2 = Stack.Pop(); string Op1 = Stack.Pop(); Stack.Push("(" + Op1 + " != " + Op2 + ")"); break; } case 0x10: //gt { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " > " + Op2 + ")"); break; } case 0x11: //lt { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " < " + Op2 + ")"); break; } case 0x12: //ge { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " >= " + Op2 + ")"); break; } case 0x13: //le { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " <= " + Op2 + ")"); break; } case 0x14: //neg { string Op1 = Stack.Pop(); Stack.Push("-(" + Op1 + ")"); break; } case 0x15: //not { string Op1 = Stack.Pop(); Stack.Push("!(" + Op1 + ")"); break; } case 0x16: //and { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " && " + Op2 + ")"); break; } case 0x17: //or { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " || " + Op2 + ")"); break; } case 0x18: //band { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " & " + Op2 + ")"); break; } case 0x19: //bor { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " ^ " + Op2 + ")"); break; } case 0x1A: //shl { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " << " + Op2 + ")"); break; } case 0x1B: //shr { string Op1 = Stack.Pop(); string Op2 = Stack.Pop(); Stack.Push("(" + Op1 + " >> " + Op2 + ")"); break; } case 0x1C: //call { var dest = sReader.Read32(); var args = sReader.ReadS32(); var symbol = FetchSymbol(i => i.Data == dest); string FuncName = ""; if (symbol != null) { FuncName = FetchSymbolName(symbol); } else { FuncName = dest.ToString("X8"); } string FuncInput = ""; for (int i = 0; i < args; i++) { string Op = Stack.Pop(); if (i != 0) { FuncInput = Op + "," + FuncInput; } else { FuncInput = Op; } } Stack.Push(FuncName + "(" + FuncInput + ")"); break; } case 0x1D: //func { string FuncName = FetchSymbolName(FetchSymbol(sReader.ReadS32())); var args = sReader.ReadS32(); string FuncInput = ""; for (int i = 0; i < args; i++) { string Op = Stack.Pop(); if (i != 0) { FuncInput = Op + "," + FuncInput; } else { FuncInput = Op; } } Stack.Push(FuncName + "(" + FuncInput + ")"); break; } case 0x1E: sReader.ReadS32(); break; case 0x1F: sReader.ReadS32(); break; case 0x20: //ret { string Op = Stack.Pop(); CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "return " + Op + ";", pos); FuncCodeGraph.AddVertex(NewLine); break; } case 0x21: //ret0 { CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "return 0;", pos); FuncCodeGraph.AddVertex(NewLine); break; } case 0x22: //jne { var dest = sReader.Read32(); nextofs = dest; string Op = Stack.Pop(); CodeVertex NewLine = new CodeVertex(VertexType.ConditionalBranch, dest, Op, pos); FuncCodeGraph.AddVertex(NewLine); break; } case 0x23: //jmp { var dest = sReader.Read32(); nextofs = dest; CodeVertex NewLine = new CodeVertex(VertexType.Branch, dest, "", pos); FuncCodeGraph.AddVertex(NewLine); break; } case 0x24: //pop { string Op = Stack.Pop(); CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, Op + ";", pos); FuncCodeGraph.AddVertex(NewLine); break; } case 0x25: //int0 { Stack.Push("0"); break; } case 0x26: //int1 { Stack.Push("1"); break; } } if (nextofs > maxofs) { maxofs = nextofs; } } while (!IsReturnCommand(command) || sReader.Position <= sTextOffset + maxofs); WriteCode(FuncCodeGraph, IndentL); sWriter.WriteLine(); sReader.Back(); }
public void AddVertex(CodeVertex NewVertex)//Adds a vertex { Graph.Add(NewVertex); }