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
2 changes: 1 addition & 1 deletion Cpp2IL.Core/Cpp2IlRuntimeArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class Cpp2IlRuntimeArgs
public List<Cpp2IlProcessingLayer> ProcessingLayersToRun = [];
public readonly Dictionary<string, string> ProcessingLayerConfigurationOptions = new();

public Cpp2IlOutputFormat? OutputFormat;
public IEnumerable<Cpp2IlOutputFormat>? OutputFormats;
public string OutputRootDirectory = null!;

public bool LowMemoryMode;
Expand Down
3 changes: 1 addition & 2 deletions Cpp2IL/CommandLineArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ public class CommandLineArgs
[Option("list-output-formats", HelpText = "List the available output formats and exit.")]
public bool ListOutputFormats { get; set; }

//FUTURE: Allow multiple of these?
[Option("output-as", HelpText = "Specify the ID of the output format you wish to use.")]
public string? OutputFormatId { get; set; }
public IEnumerable<string> OutputFormatIds { get; set; } = new List<string>();

[Option("output-to", HelpText = "Root directory to output to. Defaults to cpp2il_out in the current working directory.")]
public string OutputRootDir { get; set; } = Path.GetFullPath("cpp2il_out");
Expand Down
39 changes: 26 additions & 13 deletions Cpp2IL/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,12 @@ private static void HandleIpa(string gamePath, ref Cpp2IlRuntimeArgs args)
#endif
private static Cpp2IlRuntimeArgs GetRuntimeOptionsFromCommandLine(string[] commandLine)
{
var parserResult = Parser.Default.ParseArguments<CommandLineArgs>(commandLine);
var parserResult = new Parser(settings =>
{
settings.AllowMultiInstance = true;
settings.HelpWriter = Console.Out;
})
.ParseArguments<CommandLineArgs>(commandLine);

if (parserResult is NotParsed<CommandLineArgs> notParsed && notParsed.Errors.Count() == 1 && notParsed.Errors.All(e => e.Tag is ErrorType.VersionRequestedError or ErrorType.HelpRequestedError))
//Version or help requested
Expand Down Expand Up @@ -530,7 +535,7 @@ private static Cpp2IlRuntimeArgs GetRuntimeOptionsFromCommandLine(string[] comma
if (options.GamePath != null && options.GamePath.StartsWith("~"))
options.GamePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + options.GamePath[1..];
#endif

ResolvePathsFromCommandLine(options.GamePath, options.ExeName, ref result);
}
else
Expand All @@ -555,12 +560,12 @@ private static Cpp2IlRuntimeArgs GetRuntimeOptionsFromCommandLine(string[] comma

// if(string.IsNullOrEmpty(options.OutputFormatId)) // throw new SoftException("No output format specified, so nothing to do!");

if (!string.IsNullOrEmpty(options.OutputFormatId))
if (options.OutputFormatIds.Any() == true)
{
try
{
result.OutputFormat = OutputFormatRegistry.GetFormat(options.OutputFormatId!);
Logger.VerboseNewline($"Selected output format: {result.OutputFormat.OutputFormatName}");
result.OutputFormats = options.OutputFormatIds.Select(OutputFormatRegistry.GetFormat).ToList();
Logger.VerboseNewline($"Selected output formats: [{string.Join(", ", options.OutputFormatIds)}]");
}
catch (Exception e)
{
Expand Down Expand Up @@ -647,7 +652,13 @@ public static int MainWithArgs(Cpp2IlRuntimeArgs runtimeArgs)

var executionStart = DateTime.Now;

runtimeArgs.OutputFormat?.OnOutputFormatSelected();
if (runtimeArgs.OutputFormats != null)
{
foreach (Cpp2IlOutputFormat format in runtimeArgs.OutputFormats)
{
format.OnOutputFormatSelected();
}
}

GCSettings.LatencyMode = runtimeArgs.LowMemoryMode ? GCLatencyMode.Interactive : GCLatencyMode.SustainedLowLatency;

Expand Down Expand Up @@ -687,14 +698,16 @@ public static int MainWithArgs(Cpp2IlRuntimeArgs runtimeArgs)

var outputStart = DateTime.Now;

if (runtimeArgs.OutputFormat != null)
if (runtimeArgs.OutputFormats != null)
{
if (runtimeArgs.LowMemoryMode)
GC.Collect();

Logger.InfoNewline($"Outputting as {runtimeArgs.OutputFormat.OutputFormatName} to {runtimeArgs.OutputRootDirectory}...");
runtimeArgs.OutputFormat.DoOutput(Cpp2IlApi.CurrentAppContext, runtimeArgs.OutputRootDirectory);
Logger.InfoNewline($"Finished outputting in {(DateTime.Now - outputStart).TotalMilliseconds}ms");
foreach (Cpp2IlOutputFormat format in runtimeArgs.OutputFormats)
{
if (runtimeArgs.LowMemoryMode)
GC.Collect();
Logger.InfoNewline($"Outputting as {format.OutputFormatName} to {runtimeArgs.OutputRootDirectory}...");
format.DoOutput(Cpp2IlApi.CurrentAppContext, runtimeArgs.OutputRootDirectory);
Logger.InfoNewline($"Finished outputting in {(DateTime.Now - outputStart).TotalMilliseconds}ms");
}
}
else
{
Expand Down
64 changes: 44 additions & 20 deletions LibCpp2IL/BinarySearcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,34 +169,58 @@ internal ulong FindCodeRegistrationPost2019(Il2CppMetadata metadata)
pSomewhereInCodegenModules = pSomewhereInCodegenModules.Select(va => va - ptrSize * (ulong)initialBacktrack);

//Slightly experimental, but we're gonna try backtracking most of the way through the number of modules. Not all the way because we don't want to overshoot.
int backtrack;
for (backtrack = initialBacktrack; backtrack < sanityCheckNumberOfModules && (pCodegenModules?.Count() ?? 0) != 1; backtrack++)
{
pCodegenModules = FindAllMappedWords(pSomewhereInCodegenModules).ToList();

//Sanity check the count, which is one pointer back
if (pCodegenModules.Count == 1)
List<ulong> FindCodegenModules(int initialBacktrackParam)
{
List<ulong> foundModules = [];

for (int backtrack = initialBacktrackParam; backtrack < sanityCheckNumberOfModules && foundModules.Count != 1; backtrack++)
{
binary.Reader.Position = binary.MapVirtualAddressToRaw(pCodegenModules.First() - ptrSize);
var moduleCount = binary.Reader.ReadInt32();
foundModules = FindAllMappedWords(pSomewhereInCodegenModules).ToList();

if (moduleCount < 0 || moduleCount > sanityCheckNumberOfModules)
pCodegenModules = [];
else
LibLogger.VerboseNewline($"\t\t\tFound valid address for pCodegenModules after a backtrack of {backtrack}, module count is {LibCpp2IlMain.TheMetadata!.imageDefinitions.Length}");
//Sanity check the count, which is one pointer back
if (foundModules.Count == 1)
{
if (foundModules.Any())
{
binary.Reader.Position = binary.MapVirtualAddressToRaw(foundModules.First() - ptrSize);
var moduleCount = binary.Reader.ReadInt32();

if (moduleCount < 0 || moduleCount > sanityCheckNumberOfModules)
foundModules = [];
else
LibLogger.VerboseNewline($"\t\t\tFound valid address for pCodegenModules after a backtrack of {backtrack}/{LibCpp2IlMain.TheMetadata!.imageDefinitions.Length}: {foundModules[0]:X}");
}
}
else if (foundModules.Count > 1)
{
LibLogger.VerboseNewline($"\t\t\tFound {foundModules.Count} potential pCodegenModules addresses after a backtrack of {backtrack}, which is too many (> 1). Will try backtracking further.");
}
pSomewhereInCodegenModules = pSomewhereInCodegenModules.Select(va => va - ptrSize);
}
else if (pCodegenModules.Count > 1)

return foundModules;
}

var backtrackedModules = FindCodegenModules(initialBacktrack);
if (backtrackedModules.Count < 1)
{
LibLogger.WarnNewline($"Hit backtrack limit of {sanityCheckNumberOfModules} modules and still didn't find a valid pCodegenModules pointer. Switching to the fallback non-backtracked search");
pSomewhereInCodegenModules = pMscorlibCodegenEntryInCodegenModulesList.AsEnumerable();
var unbacktrackedModules = FindCodegenModules(0);
if (unbacktrackedModules.Count < 1)
{
LibLogger.VerboseNewline($"\t\t\tFound {pCodegenModules.Count} potential pCodegenModules addresses after a backtrack of {backtrack}, which is too many (> 1). Will try backtracking further.");
LibLogger.WarnNewline("Fallback search failed to find a valid pCodegen modules pointer.");
return 0;
}
else
{
pCodegenModules = unbacktrackedModules;
}

pSomewhereInCodegenModules = pSomewhereInCodegenModules.Select(va => va - ptrSize);
}

if (backtrack == sanityCheckNumberOfModules && (pCodegenModules?.Count() ?? 0) != 1)
else
{
LibLogger.WarnNewline($"Hit backtrack limit of {backtrack} modules and still didn't find a valid pCodegenModules pointer.");
return 0;
pCodegenModules = backtrackedModules;
}

if (pCodegenModules?.Any() != true)
Expand Down