diff --git a/.gitignore b/.gitignore index a76dad1..a251088 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,11 @@ .vs/* packages/* + +[Bb]in/ +[Oo]bj/ + +.idea/ +*.user + +packages/ +*.nupkg diff --git a/LuaToolkit.sln b/LuaToolkit.sln index 72e39a2..3b8b742 100644 --- a/LuaToolkit.sln +++ b/LuaToolkit.sln @@ -17,54 +17,170 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Recompiler", "demo\Recompil EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "demo\LuaDecompiler-Web\Web.csproj", "{30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cli", "cli", "{342A349A-D343-8551-4064-2E2800C39E13}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaToolkit.Cli", "cli\LuaToolkit.Cli.csproj", "{BE269D79-DA30-4DBB-8C84-7D5978E70C0C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 TestDebug|Any CPU = TestDebug|Any CPU + TestDebug|x64 = TestDebug|x64 + TestDebug|x86 = TestDebug|x86 WebRelease|Any CPU = WebRelease|Any CPU + WebRelease|x64 = WebRelease|x64 + WebRelease|x86 = WebRelease|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {3C38C968-E485-4154-B6BD-E8446651307F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3C38C968-E485-4154-B6BD-E8446651307F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.Debug|x64.ActiveCfg = Debug|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.Debug|x64.Build.0 = Debug|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.Debug|x86.ActiveCfg = Debug|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.Debug|x86.Build.0 = Debug|Any CPU {3C38C968-E485-4154-B6BD-E8446651307F}.Release|Any CPU.ActiveCfg = Release|Any CPU {3C38C968-E485-4154-B6BD-E8446651307F}.Release|Any CPU.Build.0 = Release|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.Release|x64.ActiveCfg = Release|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.Release|x64.Build.0 = Release|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.Release|x86.ActiveCfg = Release|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.Release|x86.Build.0 = Release|Any CPU {3C38C968-E485-4154-B6BD-E8446651307F}.TestDebug|Any CPU.ActiveCfg = TestDebug|Any CPU {3C38C968-E485-4154-B6BD-E8446651307F}.TestDebug|Any CPU.Build.0 = TestDebug|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.TestDebug|x64.ActiveCfg = TestDebug|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.TestDebug|x64.Build.0 = TestDebug|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.TestDebug|x86.ActiveCfg = TestDebug|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.TestDebug|x86.Build.0 = TestDebug|Any CPU {3C38C968-E485-4154-B6BD-E8446651307F}.WebRelease|Any CPU.ActiveCfg = WebRelease|Any CPU {3C38C968-E485-4154-B6BD-E8446651307F}.WebRelease|Any CPU.Build.0 = WebRelease|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.WebRelease|x64.ActiveCfg = WebRelease|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.WebRelease|x64.Build.0 = WebRelease|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.WebRelease|x86.ActiveCfg = WebRelease|Any CPU + {3C38C968-E485-4154-B6BD-E8446651307F}.WebRelease|x86.Build.0 = WebRelease|Any CPU {9A45374E-5548-4C3A-AF06-C31A962295DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9A45374E-5548-4C3A-AF06-C31A962295DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.Debug|x64.ActiveCfg = Debug|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.Debug|x64.Build.0 = Debug|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.Debug|x86.ActiveCfg = Debug|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.Debug|x86.Build.0 = Debug|Any CPU {9A45374E-5548-4C3A-AF06-C31A962295DD}.Release|Any CPU.ActiveCfg = Release|Any CPU {9A45374E-5548-4C3A-AF06-C31A962295DD}.Release|Any CPU.Build.0 = Release|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.Release|x64.ActiveCfg = Release|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.Release|x64.Build.0 = Release|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.Release|x86.ActiveCfg = Release|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.Release|x86.Build.0 = Release|Any CPU {9A45374E-5548-4C3A-AF06-C31A962295DD}.TestDebug|Any CPU.ActiveCfg = TestDebug|Any CPU {9A45374E-5548-4C3A-AF06-C31A962295DD}.TestDebug|Any CPU.Build.0 = TestDebug|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.TestDebug|x64.ActiveCfg = TestDebug|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.TestDebug|x64.Build.0 = TestDebug|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.TestDebug|x86.ActiveCfg = TestDebug|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.TestDebug|x86.Build.0 = TestDebug|Any CPU {9A45374E-5548-4C3A-AF06-C31A962295DD}.WebRelease|Any CPU.ActiveCfg = WebRelease|Any CPU {9A45374E-5548-4C3A-AF06-C31A962295DD}.WebRelease|Any CPU.Build.0 = WebRelease|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.WebRelease|x64.ActiveCfg = WebRelease|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.WebRelease|x64.Build.0 = WebRelease|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.WebRelease|x86.ActiveCfg = WebRelease|Any CPU + {9A45374E-5548-4C3A-AF06-C31A962295DD}.WebRelease|x86.Build.0 = WebRelease|Any CPU {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Debug|x64.ActiveCfg = Debug|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Debug|x64.Build.0 = Debug|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Debug|x86.ActiveCfg = Debug|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Debug|x86.Build.0 = Debug|Any CPU {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Release|Any CPU.ActiveCfg = Release|Any CPU {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Release|Any CPU.Build.0 = Release|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Release|x64.ActiveCfg = Release|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Release|x64.Build.0 = Release|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Release|x86.ActiveCfg = Release|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.Release|x86.Build.0 = Release|Any CPU {C10726C0-8D2C-4F92-9961-5008D1B6940E}.TestDebug|Any CPU.ActiveCfg = TestDebug|Any CPU {C10726C0-8D2C-4F92-9961-5008D1B6940E}.TestDebug|Any CPU.Build.0 = TestDebug|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.TestDebug|x64.ActiveCfg = TestDebug|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.TestDebug|x64.Build.0 = TestDebug|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.TestDebug|x86.ActiveCfg = TestDebug|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.TestDebug|x86.Build.0 = TestDebug|Any CPU {C10726C0-8D2C-4F92-9961-5008D1B6940E}.WebRelease|Any CPU.ActiveCfg = WebRelease|Any CPU {C10726C0-8D2C-4F92-9961-5008D1B6940E}.WebRelease|Any CPU.Build.0 = WebRelease|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.WebRelease|x64.ActiveCfg = WebRelease|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.WebRelease|x64.Build.0 = WebRelease|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.WebRelease|x86.ActiveCfg = WebRelease|Any CPU + {C10726C0-8D2C-4F92-9961-5008D1B6940E}.WebRelease|x86.Build.0 = WebRelease|Any CPU {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Debug|x64.ActiveCfg = Debug|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Debug|x64.Build.0 = Debug|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Debug|x86.ActiveCfg = Debug|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Debug|x86.Build.0 = Debug|Any CPU {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Release|Any CPU.Build.0 = Release|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Release|x64.ActiveCfg = Release|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Release|x64.Build.0 = Release|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Release|x86.ActiveCfg = Release|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.Release|x86.Build.0 = Release|Any CPU {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.TestDebug|Any CPU.ActiveCfg = TestDebug|Any CPU {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.TestDebug|Any CPU.Build.0 = TestDebug|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.TestDebug|x64.ActiveCfg = TestDebug|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.TestDebug|x64.Build.0 = TestDebug|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.TestDebug|x86.ActiveCfg = TestDebug|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.TestDebug|x86.Build.0 = TestDebug|Any CPU {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.WebRelease|Any CPU.ActiveCfg = WebRelease|Any CPU {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.WebRelease|Any CPU.Build.0 = WebRelease|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.WebRelease|x64.ActiveCfg = WebRelease|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.WebRelease|x64.Build.0 = WebRelease|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.WebRelease|x86.ActiveCfg = WebRelease|Any CPU + {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB}.WebRelease|x86.Build.0 = WebRelease|Any CPU {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Debug|x64.ActiveCfg = Debug|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Debug|x64.Build.0 = Debug|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Debug|x86.ActiveCfg = Debug|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Debug|x86.Build.0 = Debug|Any CPU {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Release|Any CPU.ActiveCfg = Release|Any CPU {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Release|Any CPU.Build.0 = Release|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Release|x64.ActiveCfg = Release|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Release|x64.Build.0 = Release|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Release|x86.ActiveCfg = Release|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.Release|x86.Build.0 = Release|Any CPU {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.TestDebug|Any CPU.ActiveCfg = Debug|Any CPU {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.TestDebug|Any CPU.Build.0 = Debug|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.TestDebug|x64.ActiveCfg = TestDebug|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.TestDebug|x64.Build.0 = TestDebug|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.TestDebug|x86.ActiveCfg = TestDebug|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.TestDebug|x86.Build.0 = TestDebug|Any CPU {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.WebRelease|Any CPU.ActiveCfg = Release|Any CPU {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.WebRelease|Any CPU.Build.0 = Release|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.WebRelease|x64.ActiveCfg = WebRelease|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.WebRelease|x64.Build.0 = WebRelease|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.WebRelease|x86.ActiveCfg = WebRelease|Any CPU + {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77}.WebRelease|x86.Build.0 = WebRelease|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Debug|x64.ActiveCfg = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Debug|x64.Build.0 = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Debug|x86.ActiveCfg = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Debug|x86.Build.0 = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Release|Any CPU.Build.0 = Release|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Release|x64.ActiveCfg = Release|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Release|x64.Build.0 = Release|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Release|x86.ActiveCfg = Release|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.Release|x86.Build.0 = Release|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.TestDebug|Any CPU.ActiveCfg = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.TestDebug|Any CPU.Build.0 = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.TestDebug|x64.ActiveCfg = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.TestDebug|x64.Build.0 = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.TestDebug|x86.ActiveCfg = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.TestDebug|x86.Build.0 = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.WebRelease|Any CPU.ActiveCfg = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.WebRelease|Any CPU.Build.0 = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.WebRelease|x64.ActiveCfg = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.WebRelease|x64.Build.0 = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.WebRelease|x86.ActiveCfg = Debug|Any CPU + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C}.WebRelease|x86.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -75,6 +191,7 @@ Global {C10726C0-8D2C-4F92-9961-5008D1B6940E} = {6645C52B-19A3-4114-81F8-DEBA70779569} {CE7FDAB8-2F8A-4E39-AFC9-900D3458B9CB} = {6645C52B-19A3-4114-81F8-DEBA70779569} {30E34A9B-E065-4E33-BB4F-4F3B23C9DB77} = {6645C52B-19A3-4114-81F8-DEBA70779569} + {BE269D79-DA30-4DBB-8C84-7D5978E70C0C} = {342A349A-D343-8551-4064-2E2800C39E13} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {CA86C95D-BB88-475B-B999-4332121C087F} diff --git a/cli/.gitignore b/cli/.gitignore new file mode 100644 index 0000000..d45db4d --- /dev/null +++ b/cli/.gitignore @@ -0,0 +1,2 @@ +[Bb]in/ +[Oo]bj/ \ No newline at end of file diff --git a/cli/LuaToolkit.Cli.csproj b/cli/LuaToolkit.Cli.csproj new file mode 100644 index 0000000..68714e4 --- /dev/null +++ b/cli/LuaToolkit.Cli.csproj @@ -0,0 +1,12 @@ + + + Exe + net8.0 + LatestMajor + disable + luadec + + + + + \ No newline at end of file diff --git a/cli/Program.cs b/cli/Program.cs new file mode 100644 index 0000000..b9aed48 --- /dev/null +++ b/cli/Program.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; +using LuaToolkit.Core; +using LuaToolkit.Disassembler; +using LuaToolkit.Decompiler; + +namespace LuaToolkit.Cli +{ + class Program + { + static int Main(string[] args) + { + if (args.Length < 1) + { + Console.Error.WriteLine("usuage: luadec [more.luac ...]"); + Console.Error.WriteLine(" decompiles compiled Lua 5.1 (.luac) back to source code."); + return 1; + } + + foreach(var path in args) + { + if (!File.Exists(path)) + { + Console.Error.WriteLine($"[!] File not found: {path}"); + continue; + } + + var luac = new LuaCFile(File.ReadAllBytes(path)); + var decoder = new LuaDecoder(luac); + var decompiler = new LuaDecompiler(decoder); + Console.WriteLine(decompiler.LuaScript); + } + return 0; + } + } +} \ No newline at end of file diff --git a/src/Decompiler/LuaDecompiler.cs b/src/Decompiler/LuaDecompiler.cs index 16338a2..80f281c 100644 --- a/src/Decompiler/LuaDecompiler.cs +++ b/src/Decompiler/LuaDecompiler.cs @@ -28,12 +28,28 @@ public LuaDecompiler(LuaDecoder decoder) WriteFile(); } + private void ResClosureNames() + { + // walk every function we built and point each CLOSURE line at its child's name + // GetFunctionRef() got hooked up by the child in HandleUpvalues(), so by now its set + foreach (var f in this.LuaFunctions) + foreach (var line in f.GetLines()) + if (line.Instr != null && line.Instr.OpCode == LuaOpcode.CLOSURE && line.GetFunctionRef() != null) + line.Op3 = line.GetFunctionRef().ScriptFunction.Name; + } + private void WriteFile() { // create Script Functions this.Decoder.File.Function.Name = "CRoot"; // or main? WriteF(this.Decoder.File.Function); + // NOTE: closures point at child functions that didnt exist yet while + // building the parent lines, so UpdateClosures ran too early and left them as + // 'IDK_SHIT_WENT_MISSING_BRO' lol, now that every function is created we loop + // back over the closure lines and finally fill in their names + ResClosureNames(); + // NOTE: this is done on GetText //// allign/format/whatever each function //foreach (var f in this.LuaFunctions) @@ -45,14 +61,23 @@ private void WriteF(LuaFunction func) { CreateScripFunction(func); // root first and then inside ? // TODO: write functions on CLOSURE and not each list? + // for (int i = 0; i < func.Functions.Count; i++) + // { + // func.Functions[i].Name = func.Name + "_" + i; // set default name + // CreateScripFunction(func.Functions[i], func.ScriptFunction.Depth+1); + // foreach (var f in func.Functions[i].Functions) + // { + // WriteF(f); // children NOTE: write children in body of parent? + // } + // } + for (int i = 0; i < func.Functions.Count; i++) { func.Functions[i].Name = func.Name + "_" + i; // set default name - CreateScripFunction(func.Functions[i], func.ScriptFunction.Depth+1); - foreach (var f in func.Functions[i].Functions) - { - WriteF(f); // children NOTE: write children in body of parent? - } + // NOTE: recurse into the child itself so it (and any of ITS children) get + // created and named too. before this only the direct children were getting a name + // but grand children came out as "IDK_SHIT_WENT_MISSING_BRO" + WriteF(func.Functions[i]); } } diff --git a/src/Decompiler/LuaScriptLine.cs b/src/Decompiler/LuaScriptLine.cs index 05404e9..db733bf 100644 --- a/src/Decompiler/LuaScriptLine.cs +++ b/src/Decompiler/LuaScriptLine.cs @@ -92,14 +92,27 @@ public void SetMain(LuaInstruction Instr = null) } break; case LuaOpcode.GETUPVAL: - // NOTE: child get local from parent + // NOTE: R(A) = Upvalue[B], luac keeps the upvalue names in debug info, + // so grab that for real names instead of "unk" this.Op1 = WriteIndex(Instr.A); this.Op2 = " = "; - this.Op3 = WriteIndex(Instr.B); + + if (this.Func.DebugUpvalues.Count > Instr.B) + this.Op3 = this.Func.DebugUpvalues[Instr.B].TrimEnd('\0'); + else if (this.Func.Upvalues.Count > Instr.B) + this.Op3 = this.Func.Upvalues[Instr.B].ToString(); // if no debug info + else + this.Op3 = WriteIndex(Instr.B); + + + // NOTE: child get local from parent + // this.Op1 = WriteIndex(Instr.A); + // this.Op2 = " = "; + // this.Op3 = WriteIndex(Instr.B); // TODO: figure if an upvalue is a function or not? - if(this.Func.Upvalues.Count > Instr.B) - this.Op3 = this.Func.Upvalues[Instr.B].ToString(); + // if(this.Func.Upvalues.Count > Instr.B) + // this.Op3 = this.Func.Upvalues[Instr.B].ToString(); //this.Op3 = this.Func.Upvalues[Instr.B].ToString().Substring(1, this.Func.Upvalues[Instr.B].ToString().Length - 2); // this is legit for prototypes etc break; case LuaOpcode.GETGLOBAL: @@ -118,10 +131,20 @@ public void SetMain(LuaInstruction Instr = null) this.Op3 = $"var{Instr.A}"; break; case LuaOpcode.SETUPVAL: - // NOTE: child writes to parent locals - this.Op1 = $"{WriteIndex(Instr.B)}"; // no? + // NOTE: Upvalue[B] = R(A), the name lives in debug info, and + // the value is just whatever reg is in A (a read, so no local) + if (this.Func.DebugUpvalues.Count > Instr.B) + this.Op1 = this.Func.DebugUpvalues[Instr.B].TrimEnd('\0'); + else + this.Op1 = $"var{Instr.B}"; + this.Op2 = " = "; - this.Op3 = $"{GetConstant(Instr.A)}"; + this.Op3 = WriteIndex(Instr.A, false); + + // NOTE: child writes to parent locals + // this.Op1 = $"{WriteIndex(Instr.B)}"; // no? + // this.Op2 = " = "; + // this.Op3 = $"{GetConstant(Instr.A)}"; break; case LuaOpcode.SETTABLE: this.Op1 = $"{WriteIndex(Instr.A)}[{WriteIndex(Instr.B)}]"; @@ -268,31 +291,11 @@ public void SetMain(LuaInstruction Instr = null) this.Op2 = $"var{Instr.A}"; // func name only (used lateron) // Function Args - if(Instr.B == 0) - { - // func parms range from A+1 to B (B = top of stack) - this.Op3 = "("; - for (int i = Instr.A; i < Instr.B; i++) - //for (int i = Instr.A; i < Instr.A + Instr.B - 1; ++i) - { - this.Op3 += $"var{i + 1}"; - if (i < Instr.A + Instr.B - 2) - this.Op3 += ", "; - } - this.Op3 += ")"; - } - else - { - this.Op3 = "("; - for (int i = Instr.A; i < Instr.A + Instr.B - 1; i++) - //for (int i = Instr.A; i < Instr.A + Instr.B - 1; ++i) - { - this.Op3 += $"var{i + 1}"; - if (i < Instr.A + Instr.B - 2) - this.Op3 += ", "; - } - this.Op3 += ")"; - } + + // NOTE: B tells us how many args there are; B >= 1 means B-1 fixed args, + // but B==0 means "everything from A+1 up to the top of the stack" which + // some earlier VARARG/CALL pushed there, so we dig that top up. + this.Op3 = WriteArgs(Instr.A, Instr.B); break; case LuaOpcode.TAILCALL: // TODO: there is something off here? @@ -300,32 +303,9 @@ public void SetMain(LuaInstruction Instr = null) // Function Name this.Op1 = $"return var{Instr.A}"; // func name only (used lateron) //this.Op2 = $"({Instr.A+1}"; - // Function Args - if (Instr.B == 0) - { - // func parms range from A+1 to B (B = top of stack) - this.Op3 = $"("; - for (int i = Instr.A; i < Instr.B; i++) - //for (int i = Instr.A; i < Instr.A + Instr.B - 1; ++i) - { - this.Op3 += $"var{i + 1}"; - if (i < Instr.A + Instr.B - 2) - this.Op3 += ", "; - } - this.Op3 += ")"; - } - else - { - this.Op3 = $"("; - for (int i = Instr.A; i < Instr.A + Instr.B - 1; i++) - //for (int i = Instr.A; i < Instr.A + Instr.B - 1; ++i) - { - this.Op3 += $"var{i + 1}"; - if (i < Instr.A + Instr.B - 2) - this.Op3 += ", "; - } - this.Op3 += ")"; - } + + // Function Args (same B logic as CALL above) + this.Op3 = WriteArgs(Instr.A, Instr.B); break; case LuaOpcode.RETURN: // this gets overwritten by an 'end' afterwards in case its the last RETURN value of a func @@ -399,12 +379,19 @@ public void SetMain(LuaInstruction Instr = null) case LuaOpcode.VARARG: this.Func.ScriptFunction.HasVarargs = true; this.Op1 = "local "; - for (int i = Instr.A; i < Instr.A+Instr.B-1; i++) + int varargCount = Instr.B == 0 ? 1 : Instr.B - 1; + for (int i = 0; i < varargCount; i++) { - this.Op2 += $"var{i}"; - if (i < Instr.B - 2) + this.Op2 += $"var{Instr.A + i}"; + if (i < varargCount - 1) this.Op2 += ", "; } + // for (int i = Instr.A; i < Instr.A+Instr.B-1; i++) + // { + // this.Op2 += $"var{i}"; + // if (i < Instr.B - 2) // <-- bug #1: should be A+b-2, not B-2 + // this.Op2 += ", "; + // } this.Op2 += " = ..."; break; default: @@ -451,7 +438,7 @@ private string WriteConstant(int index, LuaFunction targetFunc = null) if (index > 255 && targetFunc.Constants[index - 256] != null) return targetFunc.Constants[index - 256].ToString(); else - return WriteIndex(index); + return WriteIndex(index, false); } public void SetFunctionRef(LuaFunction func) @@ -503,6 +490,46 @@ public string WriteIndex(int value, bool useLocalKeyword = true) } } + private string WriteArgs(int funcReg, int b) + { + int argCount; + + if (b == 0) + argCount = FindStackTop(funcReg) - funcReg; // A+1 .. top + else + argCount = b - 1; // exactly B-1 fixed args + + string result = "("; + for (int i = 0; i < argCount; i++) + { + result += $"var{funcReg + 1 + i}"; + if (i < argCount - 1) + result += ", "; + } + result += ")"; + return result; + } + + + // NOTE: when B/C == 0 the args reach up to the 'top' of the stack, which a + // preceding VARARG (B==0) or CALL (C==0) pushed there. Walk back to find it + // and return the register that top sits on + private int FindStackTop(int funcReg) + { + int idx = this.Func.Instructions.IndexOf(this.Instr); + for (int i = idx - 1; i >= 0; i--) + { + LuaInstruction prev = this.Func.Instructions[i]; + if (prev.A <= funcReg) + continue; // not part of this call's args + if (prev.OpCode == LuaOpcode.VARARG && prev.B == 0) + return prev.A; // varargs spill from here to top + if (prev.OpCode == LuaOpcode.CALL && prev.C == 0) + return prev.A; // call results spill from here to top + } + return funcReg; // nothing found, no args + } + public int ToIndex(int value, out bool isConstant) { // this is the logic from lua's source code (lopcodes.h)