private void functionDecompile(LuaFile.LuaFunction function, int functionLevel, bool skipHeader = false) { // Check if we need to write the name of the function ( not with init ) if (!skipHeader) { writeWithTabs(functionLevel - 1, ""); // Check if we have a local function or global string funcName = function.getName(true).Substring(0, 4); if (funcName != "LUI." && funcName.Substring(0, 4) != "CoD.") { outputWriter.Write("local "); } // Write the function name outputWriter.Write("function " + function.getName(true) + "("); // Add all the arguments int index = 0, jj = 0; while (index < function.parameterCount) { if (function.UpvalsStrings.Contains("arg" + jj)) { jj++; continue; } function.Registers[index] = "arg" + jj; outputWriter.Write(((index > 0) ? ", " : "") + "arg" + jj++); index++; } if (function.usesVarArg) { if (function.parameterCount > 0) { outputWriter.Write(", "); } outputWriter.Write("..."); } outputWriter.Write(")\n"); } List <int> ifLevels = new List <int>(); List <int> elseLevels = new List <int>(); for (int i = 0; i < function.OPCodes.Count; i++) { DecompiledOPCode opcode = decompileOPCode(function, i, functionLevel); int skipLineAfter = 0; if (opcode.opcodeType == opCodeType.String) { writeWithTabs(functionLevel + ifLevels.Count, opcode.OpString + "\n"); } else if (opcode.opcodeType == opCodeType.FunctionClosure && function.getName() != "__INIT__" && function.lastFunctionClosure > -1) { functionDecompile(function.subFunctions[function.lastFunctionClosure], functionLevel + 1); } else if (opcode.opcodeType == opCodeType.skipLines || opcode.opcodeType == opCodeType.forEach) { writeWithTabs(functionLevel + ifLevels.Count, opcode.OpString + "\n"); ifLevels.Add(opcode.skipLines + 2); } else if (opcode.opcodeType == opCodeType.Else) { if (ifLevels.Count > 0) { ifLevels.RemoveAt(ifLevels.Count - 1); } ifLevels.Add(opcode.skipLines + 1 + opcode.elseLines); elseLevels.Add(opcode.skipLines); } else if (opcode.opcodeType == opCodeType.conditionToReg) { writeWithTabs(functionLevel + ifLevels.Count, opcode.OpString + "\n"); skipLineAfter += 3; } for (int k = 0; k < skipLineAfter + 1; k++) { if (k > 0) { i++; } for (int j = 0; j < ifLevels.Count; j++) { ifLevels[j]--; if (ifLevels[j] <= 0) { ifLevels.RemoveAt(j); writeWithTabs(functionLevel + ifLevels.Count, "end\n"); } } for (int j = 0; j < elseLevels.Count; j++) { elseLevels[j]--; if (elseLevels[j] <= 0) { elseLevels.RemoveAt(j); writeWithTabs(functionLevel + ifLevels.Count - 1, "else\n"); } } } } // Add the end of the function (not init) if (!skipHeader) { writeWithTabs(functionLevel - 1, "end\n"); } outputWriter.Write("\n"); // Print the other functions that are part of init if (function.getName() == "__INIT__") { for (int i = 0; i < function.subFunctions.Count; i++) { functionDecompile(function.subFunctions[i], functionLevel + 1); } } }
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); }