Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CoDLuaDecompiler.AssetExporter/AssetExport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Threading.Tasks;
using CoDLuaDecompiler.AssetExporter.Games;
using CoDLuaDecompiler.AssetExporter.Util;
using CoDLuaDecompiler.Common;
using CoDLuaDecompiler.Decompiler;
using CoDLuaDecompiler.Decompiler.LuaFile;
using CoDLuaDecompiler.HashResolver;
Expand All @@ -22,7 +23,7 @@ public class AssetExport : IAssetExport
public AssetExport(IDecompiler decompiler, IPackageIndex packageIndex)
{
_decompiler = decompiler;
_hashEntries = packageIndex.GetEntries();
_hashEntries = packageIndex.GetEntries(AppInfo.HashMask);
}

public static Dictionary<string, Tuple<IGame, bool>> Games = new Dictionary<string, Tuple<IGame, bool>>()
Expand Down
1 change: 1 addition & 0 deletions CoDLuaDecompiler.CLI/CoDLuaDecompiler.CLI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<ItemGroup>
<PackageReference Include="Autofac" Version="6.4.0" />
<PackageReference Include="GitHubUpdate" Version="1.2.0" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
</ItemGroup>

</Project>
125 changes: 106 additions & 19 deletions CoDLuaDecompiler.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.CommandLine;
using System.CommandLine.Invocation;
using CoDLuaDecompiler.AssetExporter;
using CoDLuaDecompiler.Decompiler;
using CoDLuaDecompiler.Decompiler.LuaFile;
using CoDLuaDecompiler.Common;
using System.Reflection;
using System.CommandLine.Parsing;

namespace CoDLuaDecompiler.CLI;

Expand Down Expand Up @@ -36,12 +40,22 @@ private void HandleFile(string filePath)
// decompile file
var output = _decompiler.Decompile(file);

// replace extension
var outFileName = Path.ChangeExtension(filePath, ".dec.lua");
string outFileName;
if (AppInfo.OutputDirectory is null)
{
// replace extension
outFileName = Path.ChangeExtension(filePath, ".dec.lua");
}
else
{
// get basename and join with specified output directory
string basename = Path.GetFileName(Path.ChangeExtension(filePath, ".dec.lua"));
outFileName = Path.Join(AppInfo.OutputDirectory, basename);
}

// save output
File.WriteAllText(outFileName, output);

Console.WriteLine($"Decompiled file: {filePath}");
}
catch (Exception e)
Expand All @@ -54,18 +68,13 @@ private static List<string> ParseFilesFromArgs(IEnumerable<string> args)
{
var files = new List<string>();

string luaExtension = "*.lua*";
if (args.Contains("--debug"))
{
UsesDebugInfo = true;
luaExtension = "*.luac";
}
string luaExtension = !UsesDebugInfo ? "*.lua*" : "*.luac";

foreach (var arg in args)
{
if (!File.Exists(arg) && !Directory.Exists(arg))
continue;

var attr = File.GetAttributes(arg);
// determine if we're a directory first
// if so only includes file that are of ".lua" or ".luac" extension
Expand All @@ -82,7 +91,7 @@ private static List<string> ParseFilesFromArgs(IEnumerable<string> args)
Console.WriteLine($"Invalid argument passed {arg} | {File.GetAttributes(arg)}!");
}
}

// make sure to remove duplicates
files = files.Distinct().ToList();

Expand All @@ -92,29 +101,107 @@ private static List<string> ParseFilesFromArgs(IEnumerable<string> args)

return files;
}

public void Main(string[] args)

public void Run(
string? outputDir,
bool showHashType,
bool doExport, bool doRawDump,
bool debug,
bool funcStats,
int bitsInHash,
IEnumerable<string> args)
{
if (args.Contains("--export"))
if (!(0 <= bitsInHash && bitsInHash <= 64))
{
Console.Error.WriteLine($"[!] --bits-in-hash arg must be a value 0-64. Got {bitsInHash}.");
return;
}

if (doExport)
{
Console.WriteLine("Starting asset export from memory.");
_assetExport.ExportAssets(args.Contains("--dump"));
_assetExport.ExportAssets(doRawDump);
}

if (args.Contains("--functionstats") || args.Contains("-fs"))
AppInfo.ShowFunctionData = funcStats;
AppInfo.ShowHashType = showHashType;
AppInfo.HashMask = ~0UL >> (64 - bitsInHash);
UsesDebugInfo = debug;

if (outputDir is not null)
{
AppInfo.ShowFunctionData = true;
if (!Directory.Exists(outputDir))
Directory.CreateDirectory(outputDir);

AppInfo.OutputDirectory = outputDir;
}

// parse files from arguments
var files = ParseFilesFromArgs(args);

Console.WriteLine($"Total of {files.Count} to process.");

#if DEBUG
files.ForEach(HandleFile);
files.ForEach(HandleFile);
#else
Parallel.ForEach(files, HandleFile);
#endif
}

public async Task<int> Main(string[] args)
{
var outDirOption = new Option<string?>(
aliases: new string[] { "--output-dir", "-o" },
description: "Specify the directory to output decompiled lua files. If none is provided, " +
"it will write to the same location as the input lua file.");

var doExport = new Option<bool>(
name: "--export",
description: "Export luas from a running game's memory (only for older titles).",
getDefaultValue: () => false);

var doRawDump = new Option<bool>(
name: "--dump",
description: "If --export is enabled, then enabling this will export the raw lua files along with the decompiled lua files.",
getDefaultValue: () => false);

var debug = new Option<bool>(
name: "--debug",
description: "Will extract debug information from T7 luas. Will change the extension to look for from *.lua to *.luac.",
getDefaultValue: () => false);

var hashType = new Option<bool>(
aliases: new string[] { "--hash-type", "-ht" },
description: "If enabled, will prefix all hash values with `{HashType}#` to indicate what type of hash it is.",
getDefaultValue: () => false);

var funcStats = new Option<bool>(
aliases: new string[] { "--functionstats", "-fs" },
description: "Prepends function information to decompiled functions.",
getDefaultValue: () => false);

var bitsHash = new Option<int>(
aliases: new string[] { "--bits-in-hash", "-bh" },
description: "The number of bits in a hash. Affects the output of hashes and hashes that are searched for in wni files. Max value is 64.",
getDefaultValue: () => 64);

var luasPath = new Argument<IEnumerable<string>>(
name: "paths",
description: "A list of 1 or more paths to a directory of luas or a single lua file.");

var rootCommand = new RootCommand($"Lua decompiler for Call of Duty games. Version {AppInfo.Version}");
rootCommand.AddOption(outDirOption);
rootCommand.AddOption(funcStats);
rootCommand.AddOption(hashType);
rootCommand.AddOption(bitsHash);
rootCommand.AddOption(doExport);
rootCommand.AddOption(doRawDump);
rootCommand.AddOption(debug);
rootCommand.AddArgument(luasPath);

rootCommand.SetHandler(Run,
outDirOption, hashType, doExport, doRawDump, debug, funcStats, bitsHash, luasPath);

return await rootCommand.InvokeAsync(args);
}
}
2 changes: 1 addition & 1 deletion CoDLuaDecompiler.CLI/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ private static async Task Main(string[] args)

var container = builder.Build();
var updateTask = container.Resolve<GithubUpdateChecker>().CheckForUpdate();
container.Resolve<Program>().Main(args);
await container.Resolve<Program>().Main(args);
await updateTask;

Console.WriteLine("Press enter to exit");
Expand Down
5 changes: 4 additions & 1 deletion CoDLuaDecompiler.Common/AppInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

public static class AppInfo
{
public static string Version { get; } = "2.4.2";
public static string Version { get; } = "2.4.3";
public static bool ShowFunctionData { get; set; } = false;
public static bool ShowHashType { get; set; } = false;
public static string? OutputDirectory { get; set; } = null;
public static ulong HashMask { get; set; } = ~0UL;
}
3 changes: 2 additions & 1 deletion CoDLuaDecompiler.Decompiler/Decompiler.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.IO;
using CoDLuaDecompiler.Common;
using CoDLuaDecompiler.Decompiler.Analyzers;
using CoDLuaDecompiler.Decompiler.IR;
using CoDLuaDecompiler.Decompiler.IR.Functions;
Expand All @@ -15,7 +16,7 @@ public class Decompiler : IDecompiler

public Decompiler(IPackageIndex packageIndex)
{
HashEntries = packageIndex.GetEntries();
HashEntries = packageIndex.GetEntries(AppInfo.HashMask);
}

public Function GetDecompiledFile(ILuaFile luaFile)
Expand Down
13 changes: 12 additions & 1 deletion CoDLuaDecompiler.Decompiler/IR/Expression/Constant.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using CoDLuaDecompiler.Common;
using CoDLuaDecompiler.Decompiler.IR.Identifiers;
using System.Text;
using System.Text.RegularExpressions;
Expand All @@ -11,6 +12,7 @@ public class Constant : IExpression
public string String { get; set; }
public bool Boolean { get; set; }
public ulong Hash { get; set; }
public int? HashType { get; set; }

public int Id { get; set; }

Expand Down Expand Up @@ -55,6 +57,15 @@ public Constant(ulong h, int id)
{
Type = Identifiers.ValueType.Hash;
Hash = h;
HashType = null;
Id = id;
}

public Constant(ulong h, int? htype, int id)
{
Type = Identifiers.ValueType.Hash;
Hash = h;
HashType = htype;
Id = id;
}

Expand Down Expand Up @@ -85,7 +96,7 @@ public override string ToString()
case Identifiers.ValueType.Boolean:
return Boolean ? "true" : "false";
case Identifiers.ValueType.Hash:
return $"0x{Hash & 0xFFFFFFFFFFFFFFF:X}";
return (!AppInfo.ShowHashType || HashType is null) ? $"0x{Hash:X016}" : $"{HashType!}#0x{Hash:X016}";
case Identifiers.ValueType.Table:
return "{}";
case Identifiers.ValueType.VarArgs:
Expand Down
7 changes: 4 additions & 3 deletions CoDLuaDecompiler.Decompiler/IR/SymbolTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ public Identifier GetNewRegister()
{
// Get the highest regs
var newRegNum = ScopeStack.Peek()
.Select(st => st.Key.StartsWith("REG") ? int.Parse(st.Key.Substring(3)) : -1)
.Where(reg => reg != -1)
.Max() + 1;
.Select(st => st.Key.StartsWith("REG") && int.TryParse(st.Key.AsSpan(3), out int r) ? r : -1)
.Where(reg => reg != -1)
.Max() + 1;

Identifier id = new Identifier
{
IdentifierType = IdentifierType.Register,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ private IExpression ConvertLuaJitConstant(ILuaJitConstant con, int id)
if (con.Type == LuaJitConstantType.Boolean)
return new Constant(con.BoolValue, id);
if (con.Type == LuaJitConstantType.Hash)
return new Constant(con.HashValue, id);
return new Constant(con.HashValue, con.HashType, id);
if (con.Type == LuaJitConstantType.Function)
{
foreach (var upvalueReference in con.Function.UpvalueReferences)
Expand Down Expand Up @@ -392,6 +392,18 @@ public void Convert(Function function, ILuaFunction luaFunc)
_symbolTable.GetGlobal(luaFunction.Constants[(int) i.CD].ToString(), (int)i.CD),
new IdentifierReference(_symbolTable.GetRegister(i.A))));
break;
case "HGGET": // BO7 specific
instrs.Add(new Assignment(
_symbolTable.GetRegister(i.A),
new IdentifierReference(_symbolTable.GetGlobal("_G", (int)i.A), ConvertLuaJitConstant(luaFunction.Constants[(int)i.CD], -1))
));
break;
case "HGSET": // BO7 specific
instrs.Add(new Assignment(
new IdentifierReference(_symbolTable.GetGlobal("_G", (int)i.CD), ConvertLuaJitConstant(luaFunction.Constants[(int)i.CD], -1)),
new IdentifierReference(_symbolTable.GetRegister(i.A))
));
break;
case "TGETV":
instrs.Add(new Assignment(
RegisterReference(i.A),
Expand Down
2 changes: 2 additions & 0 deletions CoDLuaDecompiler.Decompiler/LuaFile/LuaFileFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public static ILuaFile Create(BinaryReader reader, string filePath, bool useDebu
return new LuaJitFileBocw(reader);
if (bytes[3] == 0x83)
return new LuaJitFileMw2(reader);
if (bytes[3] == 0x84)
return new LuaJitFileBO6(reader);
}

if (bytes[0] != 0x1B || bytes[1] != 0x4C || bytes[2] != 0x75 || bytes[3] != 0x61)
Expand Down
17 changes: 17 additions & 0 deletions CoDLuaDecompiler.Decompiler/LuaFile/LuaJit/LuaJitFileBO6.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.IO;
using CoDLuaDecompiler.Decompiler.LuaFile.Structures.LuaFunction.LuaJit;

namespace CoDLuaDecompiler.Decompiler.LuaFile.LuaJit
{
public class LuaJitFileBO6 : LuaJitFile
{
public LuaJitFileBO6(BinaryReader reader) : base(reader)
{
}

protected override LuaJitFunction ReadFunction()
{
return new LuaJitFunctionBO6(this, Reader);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ public abstract class ILuaJitConstant
public LuaJitTable Table { get; set; }
public bool BoolValue { get; protected set; }
public ulong HashValue { get; protected set; }
public int? HashType { get; protected set; }
}
}
Loading