public static void Return(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode, int index) { if (index > 0) { if (function.OPCodes[index - 1].OPCode == 0x16) { opCode.B = 1; } } if (opCode.B > 1) { string registers = opCode.A.ToString(); string returns = function.Registers[opCode.A]; for (int i = opCode.A + 1; i <= opCode.A + opCode.B - 2; i++) { registers += ", " + i; returns += ", " + function.Registers[i]; } function.DisassembleStrings.Add(String.Format("return r({0}) // {1}", registers, returns)); } else { function.DisassembleStrings.Add("return"); } }
public static void VarArg(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.Registers[opCode.A] = "..."; function.DisassembleStrings.Add(String.Format("r({0}) = VarArg // {1} ", opCode.A, function.Registers[opCode.A])); }
public static void DoOperator(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode, string Operator) { if (opCode.C > 255) { function.DisassembleStrings.Add(String.Format("r({0}) = c[{1}] {6} r({2}) // {3} = {4} {6} {5}", opCode.A, opCode.C - 256, opCode.B, "returnval" + function.returnValCount, function.Strings[opCode.C - 256].String, function.Registers[opCode.B], Operator)); } else { function.DisassembleStrings.Add(String.Format("r({0}) = r({1}) {6} r({2}) // {3} = {4} {6} {5}", opCode.A, opCode.C, opCode.B, "returnval" + function.returnValCount, function.Registers[opCode.C], function.Registers[opCode.B], Operator)); } function.Registers[opCode.A] = function.getNewReturnVal(); }
public static void SkipLines(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode, int index) { string suffix = ""; if (opCode.B == 0) { if (function.OPCodes[index + opCode.C + 2].OPCode == 0xE && !function.foreachPositions.Contains(index + opCode.C + 2)) { int baseVal = function.OPCodes[index + opCode.C + 2].A + 3; function.Registers[baseVal] = "index" + ((function.forLoopCount > 0) ? function.forLoopCount.ToString() : ""); function.Registers[baseVal + 1] = "value" + ((function.forLoopCount > 0) ? function.forLoopCount.ToString() : ""); function.forLoopCount++; suffix = " + start of foreach loop"; function.foreachPositions.Add(index + opCode.C + 2); } function.DisassembleStrings.Add(String.Format("skip the next [{0}] opcodes // advance {0} lines{1}", opCode.C + 1, suffix)); } else { if (function.OPCodes[index + opCode.sBx + 1].OPCode == 0xE && !function.foreachPositions.Contains(index + opCode.sBx + 1)) { int baseVal = function.OPCodes[index + opCode.sBx + 1].A + 3; function.Registers[baseVal] = "index" + ((function.forLoopCount > 0) ? function.forLoopCount.ToString() : ""); function.Registers[baseVal + 1] = "value" + ((function.forLoopCount > 0) ? function.forLoopCount.ToString() : ""); function.forLoopCount++; suffix = " + start of foreach loop"; function.foreachPositions.Add(index + opCode.sBx + 1); } function.DisassembleStrings.Add(String.Format("skip the next [{0}] opcodes // advance {0} lines", opCode.sBx)); } }
public static void SetList(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { string tableString = "{"; string tableRegisters = ""; if (opCode.B > 0) { tableString += function.Registers[opCode.A + 1]; tableRegisters += opCode.A + 1; if (opCode.B > 1) { for (int j = opCode.A + 2; j <= opCode.A + opCode.B; j++) { tableString += ", " + function.Registers[j]; tableRegisters += ", " + j; } } } tableString += "}"; function.Registers[opCode.A] = function.Registers[opCode.A]; function.DisassembleStrings.Add(String.Format("r({0}) = r({1}) // {2} = {3}", opCode.A, tableRegisters, function.Registers[opCode.A], tableString)); }
public static void IfIsTrueFalse(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.DisassembleStrings.Add(String.Format("if r({0}) == {1}, skip next opcode // if {2}{3} then skip next line", opCode.A, (opCode.C == 1) ? "false" : "true", (opCode.C == 1) ? "not " : "", function.Registers[opCode.A])); }
public static void GetUpValue(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.Registers[opCode.A] = function.UpvalsStrings[opCode.B]; function.DisassembleStrings.Add(String.Format("r({0}) = upval({1}) // {2}", opCode.A, opCode.B, function.UpvalsStrings[opCode.B])); }
/// <summary> /// Puts a register value in another register /// </summary> /// <param name="function"></param> /// <param name="opCode"></param> public static void RegisterToRegister(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.Registers[opCode.A] = function.Registers[opCode.B]; function.DisassembleStrings.Add(String.Format("r({0}) = r({1}) // {2}", opCode.A, opCode.B, function.Registers[opCode.A])); }
public static void GlobalRegisterToRegister(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.Registers[opCode.A] = function.Strings[opCode.Bx].String; function.DisassembleStrings.Add(String.Format("r({0}) = g[{1}] // {2}", opCode.A, opCode.Bx, function.Strings[opCode.Bx].getString())); }
public static void RegisterToGlobal(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.DisassembleStrings.Add(String.Format("g[c[{0}]] = r({1}) // {2} = {3}", opCode.Bx, opCode.A, function.Strings[opCode.Bx].String, function.Registers[opCode.A])); }
public static void Length(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.Registers[opCode.A] = "#" + function.Registers[opCode.B]; function.DisassembleStrings.Add(String.Format("r({0}) = len(r({1})) // {2}", opCode.A, opCode.B, function.Registers[opCode.B])); }
public static void LocalConstantToRegister(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.Registers[opCode.A] = function.Strings[opCode.Bx].getString(); function.DisassembleStrings.Add(String.Format("r({0}) = c[{1}] // {2}", opCode.A, opCode.Bx, function.Registers[opCode.A])); }
public static void StartForEachLoop(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.DisassembleStrings.Add(String.Format("Start a foreach loop with val r({0}), stop: r({1}), inc: r({2}) // use these values: {3} and {4}", opCode.A, opCode.A + 1, opCode.A + 2, function.Registers[opCode.A + 3], function.Registers[opCode.A + 4])); }
/// <summary> /// Connects a register value and a constant value with a . /// </summary> /// <param name="function"></param> /// <param name="opCode"></param> public static void ConnectWithDot(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.Registers[opCode.A] = function.Registers[opCode.B] + "." + function.Strings[opCode.C].String; function.DisassembleStrings.Add(String.Format("r({0}) = r({1}).field({2}) // {3}", opCode.A, opCode.B, opCode.C, function.Registers[opCode.A])); }
public static void Not(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.DisassembleStrings.Add(String.Format("r({0}) = not r({1}) // {2} = not {3}", opCode.A, opCode.B, "returnval" + function.returnValCount, function.Registers[opCode.B])); function.Registers[opCode.A] = function.getNewReturnVal(); }
public static void EmptyTable(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.Registers[opCode.A] = "table" + function.tableCount; function.tableCount++; function.DisassembleStrings.Add(String.Format("r({0}) = {4} // {3} = {4} Index: {2} Hash: {1}", opCode.A, opCode.C, opCode.B, function.Registers[opCode.A], "{}")); }
public static void Closure(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.Registers[opCode.A] = String.Format("__FUNC_{0:X}_", function.subFunctions[opCode.Bx].beginPosition); function.doingUpvals = opCode.A; function.lastFunctionClosure = opCode.Bx; function.DisassembleStrings.Add(String.Format("r({0}) = closure({1}) // {2}", opCode.A, opCode.Bx, function.Registers[opCode.A])); }
public static void StartForLoop(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.Registers[opCode.A + 3] = "index" + ((function.forLoopCount > 0) ? function.forLoopCount.ToString() : ""); function.forLoopCount++; function.DisassembleStrings.Add(String.Format("for {6}=r({0}), {6} < r({1}), r({2}) do // for {6}={3}, {4}, {5} do", opCode.A, opCode.A + 1, opCode.A + 2, function.Registers[opCode.A], function.Registers[opCode.A + 1], function.Registers[opCode.A + 2], function.Registers[opCode.A + 3])); }
public static void DoOperatorBackWards(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode, string Operator) { function.DisassembleStrings.Add(String.Format("r({0}) = c({2}) {6} r({1}) // {3} = {5} {6} {4}", opCode.A, opCode.C, opCode.B, "returnval" + function.returnValCount, function.Registers[opCode.C], function.Strings[opCode.B].String, Operator)); function.Registers[opCode.A] = function.getNewReturnVal(); }
public static void EndForLoop(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode, int index) { if (opCode.B == 0) { function.DisassembleStrings.Add(String.Format("skip the next [{0}] opcodes // advance {0} lines", opCode.C + 1)); } else { function.DisassembleStrings.Add(String.Format("skip the next [{0}] opcodes // advance {0} lines", opCode.sBx)); } }
public static void NilToRegister(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { for (int i = opCode.A; i <= (opCode.B); i++) { function.Registers[i] = "nil"; } if ((opCode.B) > opCode.A) { function.DisassembleStrings.Add(String.Format("r({0} to {1}) inclusive = nil", opCode.A, opCode.B)); } else { function.DisassembleStrings.Add(String.Format("r({0}) = nil", opCode.A)); } }
public static void BooleanToRegister(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { if (opCode.B == 0) { function.Registers[opCode.A] = "false"; } else { function.Registers[opCode.A] = "true"; } function.DisassembleStrings.Add(String.Format("r({0}) = {1}{2}", opCode.A, function.Registers[opCode.A], (opCode.C == 1) ? " // skip next opcode" : "")); }
/// <summary> /// Connects 2 register values with a double . /// </summary> /// <param name="function"></param> /// <param name="opCode"></param> public static void ConnectWithDoubleDot(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { string output = "(" + function.Registers[opCode.B]; string registers = "r(" + opCode.B + ")"; for (int i = opCode.B + 1; i <= opCode.C; i++) { output += " .. " + function.Registers[i]; registers += "..r(" + i + ")"; } output += ")"; function.Registers[opCode.A] = output; function.DisassembleStrings.Add(String.Format("r({0}) = {1} // {2}", opCode.A, registers, function.Registers[opCode.A])); }
public static void GetIndex(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { if (opCode.C > 255) { function.Registers[opCode.A] = function.Registers[opCode.B] + "[" + function.Strings[opCode.C - 256].String + "]"; function.DisassembleStrings.Add(String.Format("r({0}) = r({1})[c[{2}]] // {3}", opCode.A, opCode.B, opCode.C - 256, function.Registers[opCode.A])); } else { function.Registers[opCode.A] = function.Registers[opCode.B] + "[" + function.Registers[opCode.C] + "]"; function.DisassembleStrings.Add(String.Format("r({0}) = r({1})[r({2})] // {3}", opCode.A, opCode.B, opCode.C, function.Registers[opCode.A])); } }
public static void LargerThan(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { if (opCode.C > 255) { function.DisassembleStrings.Add(String.Format("if {4}r({0}) > c[{1}], skip next opcode // if {4}{2} > {3} then skip next line", opCode.B, opCode.C - 256, function.Registers[opCode.B], function.Strings[opCode.C - 256].getString(), (opCode.A == 1) ? "not " : "")); } else { function.DisassembleStrings.Add(String.Format("if {4}r({0}) > r({1}), skip next opcode // if {4}{2} > {3} then skip next line", opCode.B, opCode.C, function.Registers[opCode.B], function.Registers[opCode.C], (opCode.A == 0) ? "not " : "")); } }
/// <summary> /// Connects a register value and a constant value with a : /// </summary> /// <param name="function"></param> /// <param name="opCode"></param> public static void ConnectWithColon(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { if (opCode.C > 255) { function.Registers[opCode.A] = function.Registers[opCode.B] + ":" + function.Strings[opCode.C - 256].String; function.DisassembleStrings.Add(String.Format("r({0}) = r({1}):c[{2}] // {3}", opCode.A, opCode.B, opCode.C - 256, function.Registers[opCode.A])); } else { function.Registers[opCode.A] = function.Registers[opCode.B] + ":" + function.Registers[opCode.C]; function.DisassembleStrings.Add(String.Format("r({0}) = r({1}):r({2}) // {3}", opCode.A, opCode.B, opCode.C, function.Registers[opCode.A])); } }
public static void SetField(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode, int index, bool isString = false) { if (opCode.C > 255) { if (function.Strings[opCode.C - 256].StringType == LuaFile.StringType.String) { isString = true; } function.DisassembleStrings.Add(String.Format("r({0}).field(c[{1}]) = c[{2}] // {3}.{4} = {5}", opCode.A, opCode.B, opCode.C - 256, function.Registers[opCode.A], function.Strings[opCode.B].String, function.Strings[opCode.C - 256].getString())); } else { if (function.Registers[opCode.C].Contains("__FUNC") && (function.OPCodes[index - 1].OPCode == 0x4A || function.OPCodes[index - 1].OPCode == 0x54) && (function.Registers[opCode.A].Substring(0, 3) == "CoD" || function.Registers[opCode.A].Substring(0, 3) == "LUI")) { for (int i = index; i > 0; i--) { if (function.OPCodes[i].OPCode == 0x4A) { function.subFunctions[function.OPCodes[i].Bx].functionName = function.Registers[opCode.A] + "." + function.Strings[opCode.B].String; break; } } } function.DisassembleStrings.Add(String.Format("r({0}).field(c[{1}]) = r({2}) // {3}.{4} = {5}", opCode.A, opCode.B, opCode.C, function.Registers[opCode.A], function.Strings[opCode.B].String, (isString) ? "\"" + function.Registers[opCode.C] + "\"" : function.Registers[opCode.C])); } }
public static void SetTableBackwards(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { if (opCode.C > 255) { function.DisassembleStrings.Add(String.Format("r({0})[c[{1}]] = c[{2}] // {3}[{4}] = {5}", opCode.A, opCode.B, opCode.C - 256, function.Registers[opCode.A], function.Strings[opCode.B].getString(), function.Strings[opCode.C - 256].getString())); } else { function.DisassembleStrings.Add(String.Format("r({0})[c[{1}]] = r({2}) // {3}[{4}] = {5}", opCode.A, opCode.B, opCode.C, function.Registers[opCode.A], function.Strings[opCode.B].getString(), function.Registers[opCode.C])); } }
public static void IfIsEqualBackwards(LuaFile.LuaFunction function, LuaFile.LuaOPCode opCode) { function.DisassembleStrings.Add("; Unhandled OP: (OPCODE_EQ_BK)"); }
private DecompiledOPCode decompileOPCode(LuaFile.LuaFunction function, int index, int functionLevel) { DecompiledOPCode DecompileString = new DecompiledOPCode(opCodeType.empty, ""); LuaFile.LuaOPCode opCode = function.OPCodes[index]; try { switch (opCode.OPCode) { case 0x0: LuaDecompile.LuaStrings.ConnectWithDot(function, opCode); break; case 0x1: DecompileString = LuaDecompile.LuaConditions.IfIsTrueFalse(function, opCode, index); break; case 0x2: case 0x4C: DecompileString = LuaDecompile.LuaFunctions.CallFunctionWithParameters(function, opCode, index); break; case 0x16: DecompileString = LuaDecompile.LuaFunctions.CallFunctionWithParameters(function, opCode, index, true); break; case 0x4: DecompileString = LuaDecompile.LuaConditions.IfIsEqual(function, opCode, index); break; case 0x5: DecompileString = LuaDecompile.LuaConditions.IfIsEqualBackwards(function, opCode, index); break; case 0x6: LuaDecompile.LuaRegisters.GlobalRegisterToRegister(function, opCode); break; case 0x7: LuaDecompile.LuaRegisters.RegisterToRegister(function, opCode); break; case 0x8: LuaDecompile.LuaStrings.ConnectWithColon(function, opCode); break; case 0x9: DecompileString = LuaDecompile.LuaOperators.Return(function, opCode, index); break; case 0xA: LuaDecompile.LuaTables.GetIndex(function, opCode); break; case 0xD: LuaDecompile.LuaRegisters.BooleanToRegister(function, opCode, index); break; //case 0xE: Console.WriteLine("Foreach"); break; case 0xF: DecompileString = LuaDecompile.LuaStrings.SetField(function, opCode, index); break; case 0x10: DecompileString = LuaDecompile.LuaTables.SetTable(function, opCode); break; case 0x11: DecompileString = LuaDecompile.LuaTables.SetTableBackwards(function, opCode); break; case 0x19: LuaDecompile.LuaRegisters.LocalConstantToRegister(function, opCode); break; case 0x1A: LuaDecompile.LuaRegisters.NilToRegister(function, opCode); break; case 0x1B: DecompileString = LuaDecompile.LuaRegisters.RegisterToGlobal(function, opCode); break; case 0x1C: DecompileString = LuaDecompile.LuaConditions.SkipLines(function, opCode, index); break; case 0x26: LuaDecompile.LuaFunctions.GetUpValue(function, opCode); break; case 0x27: DecompileString = LuaDecompile.LuaOperators.SetupVal(function, opCode); break; case 0x28: DecompileString = LuaDecompile.LuaOperators.Add(function, opCode); break; case 0x29: DecompileString = LuaDecompile.LuaOperators.AddBackWards(function, opCode); break; case 0x2A: DecompileString = LuaDecompile.LuaOperators.Subtract(function, opCode); break; case 0x2B: DecompileString = LuaDecompile.LuaOperators.SubtractBackWards(function, opCode); break; case 0x2C: DecompileString = LuaDecompile.LuaOperators.Multiply(function, opCode); break; case 0x2D: DecompileString = LuaDecompile.LuaOperators.MultiplyBackWards(function, opCode); break; case 0x2E: DecompileString = LuaDecompile.LuaOperators.Divide(function, opCode); break; case 0x2F: DecompileString = LuaDecompile.LuaOperators.DivideBackWards(function, opCode); break; case 0x30: DecompileString = LuaDecompile.LuaOperators.Modulo(function, opCode); break; case 0x31: DecompileString = LuaDecompile.LuaOperators.ModuloBackWards(function, opCode); break; case 0x32: DecompileString = LuaDecompile.LuaOperators.Power(function, opCode); break; case 0x33: DecompileString = LuaDecompile.LuaOperators.PowerBackWards(function, opCode); break; case 0x34: DecompileString = LuaDecompile.LuaTables.EmptyTable(function, opCode); break; case 0x35: LuaDecompile.LuaOperators.UnaryMinus(function, opCode); break; case 0x36: DecompileString = LuaDecompile.LuaConditions.Not(function, opCode); break; case 0x37: LuaDecompile.LuaOperators.Length(function, opCode); break; case 0x38: DecompileString = LuaDecompile.LuaConditions.LessThan(function, opCode, index); break; case 0x39: DecompileString = LuaDecompile.LuaConditions.LessThanBackwards(function, opCode, index); break; case 0x3A: DecompileString = LuaDecompile.LuaConditions.LessOrEqualThan(function, opCode, index); break; case 0x3B: DecompileString = LuaDecompile.LuaConditions.LessOrEqualThanBackwards(function, opCode, index); break; case 0x3C: DecompileString = LuaDecompile.LuaOperators.ShiftLeft(function, opCode); break; case 0x3D: DecompileString = LuaDecompile.LuaOperators.ShiftLeftBackwards(function, opCode); break; case 0x40: DecompileString = LuaDecompile.LuaOperators.BinaryAnd(function, opCode); break; case 0x42: DecompileString = LuaDecompile.LuaOperators.BinaryOr(function, opCode); break; case 0x44: LuaDecompile.LuaStrings.ConnectWithDoubleDot(function, opCode); break; case 0x45: DecompileString = LuaDecompile.LuaOperators.TestSet(function, opCode); break; case 0x46: DecompileString = LuaDecompile.LuaLoops.StartForLoop(function, opCode); break; case 0x48: DecompileString = LuaDecompile.LuaTables.SetList(function, opCode); break; case 0x49: LuaDecompile.LuaOperators.Close(function, opCode); break; case 0x4A: LuaDecompile.LuaFunctions.Closure(function, opCode, index, functionLevel, this); break; case 0x4B: LuaDecompile.LuaOperators.VarArg(function, opCode); break; case 0x4D: DecompileString = LuaDecompile.LuaFunctions.CallFunctionWithoutParameters(function, opCode, index); break; case 0x4F: DecompileString = LuaDecompile.LuaConditions.IfIsTrueFalse(function, opCode, index); break; case 0x50: DecompileString = LuaDecompile.LuaOperators.NotR1(function, opCode); break; case 0x51: LuaDecompile.LuaStrings.ConnectWithDot(function, opCode); break; case 0x52: DecompileString = LuaDecompile.LuaStrings.SetField(function, opCode, index); break; case 0x54: if (function.doingUpvals >= 0) { if (opCode.A == 1) { function.DisassembleStrings.Add(String.Format("r({0}).upval({1}) = r({2}) // {3}", function.doingUpvals, function.subFunctions[function.lastFunctionClosure].UpvalsStrings.Count, opCode.C, function.Registers[opCode.C])); } else if (opCode.A == 2) { function.DisassembleStrings.Add(String.Format("r({0}).upval({1}) = upval({2}) // {3}", function.doingUpvals, function.subFunctions[function.lastFunctionClosure].UpvalsStrings.Count, opCode.C, function.UpvalsStrings[opCode.C])); } else { Console.WriteLine("Trying to get to do upvalue on level " + opCode.A); } } else { function.DisassembleStrings.Add(String.Format("data({0}, {1}, {2}, {3})", opCode.A, opCode.C, opCode.B, opCode.OPCode)); } break; } if (opCode.OPCode == 0xF && function.getName() == "__INIT__") { if (luaFile.game == LuaFile.Game.BlackOps4 && function.Registers[opCode.A].Length > 3) { if ((function.Registers[opCode.A].Substring(0, 4) == "CoD." || function.Registers[opCode.A].Substring(0, 4) == "LUI.") && function.Strings[opCode.B].String == "new") { luaFile.fakeName = function.Registers[opCode.A].Substring(4); } } } if (function.doingUpvals >= 0) { if (opCode.OPCode != 0x4A) { if (opCode.OPCode == 0x54) { if (opCode.A == 1) { function.subFunctions[function.lastFunctionClosure].UpvalsStrings.Add(function.Registers[opCode.C]); } else if (opCode.A == 2) { function.subFunctions[function.lastFunctionClosure].UpvalsStrings.Add(function.UpvalsStrings[opCode.C]); } if (function.OPCodes[index + 1].OPCode != 0x54 && function.getName() != "__INIT__") { doFunctionClosure(function, functionLevel); } } else { function.doingUpvals = -1; } } } } catch { Console.WriteLine("Error occured while disassembling A: {3}, B: {4}, C: {5} OPcode: {0:X} at line {1} in function {2}", opCode.OPCode, index, function.getName(), opCode.A, opCode.B, opCode.C); } return(DecompileString); }