static void WriteCode(CodeGraph FuncCodeGraph, int Indent) { sWriter.Write(FuncCodeGraph.OutputCode(Indent)); }
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(); }