diff --git a/Il2CppInspector.Redux.CLI/CliClient.cs b/Il2CppInspector.Redux.CLI/CliClient.cs index b88f5fa..66c8df8 100644 --- a/Il2CppInspector.Redux.CLI/CliClient.cs +++ b/Il2CppInspector.Redux.CLI/CliClient.cs @@ -61,6 +61,11 @@ public class CliClient : IDisposable public async ValueTask GetInspectorVersion(CancellationToken cancellationToken = default) => await _connection.InvokeAsync(nameof(Il2CppHub.GetInspectorVersion), cancellationToken); + public async ValueTask SetSettings(InspectorSettings settings, CancellationToken cancellationToken = default) + { + await _connection.InvokeAsync(nameof(Il2CppHub.SetSettings), settings, cancellationToken); + } + public async ValueTask WaitForLoadingToFinishAsync(CancellationToken cancellationToken = default) { var currentLoadingCount = _finishedLoadingCount; diff --git a/Il2CppInspector.Redux.CLI/Commands/InteractiveCommand.cs b/Il2CppInspector.Redux.CLI/Commands/InteractiveCommand.cs index e61447a..0ec1f14 100644 --- a/Il2CppInspector.Redux.CLI/Commands/InteractiveCommand.cs +++ b/Il2CppInspector.Redux.CLI/Commands/InteractiveCommand.cs @@ -1,14 +1,13 @@ -using Microsoft.AspNetCore.SignalR.Client; -using Spectre.Console; +using Spectre.Console; using Spectre.Console.Cli; namespace Il2CppInspector.Redux.CLI.Commands; -internal class InteractiveCommand(PortProvider portProvider) : BaseCommand(portProvider) +internal sealed class InteractiveCommand(PortProvider portProvider) : BaseCommand(portProvider) { - public class Options : CommandSettings; + public sealed class Settings : CommandSettings; - protected override async Task ExecuteAsync(CliClient client, Options settings) + protected override async Task ExecuteAsync(CliClient client, Settings settings) { await Task.Delay(1000); await AnsiConsole.AskAsync("meow?"); diff --git a/Il2CppInspector.Redux.CLI/Commands/ManualCommand.cs b/Il2CppInspector.Redux.CLI/Commands/ManualCommand.cs index 7bc888e..3048b95 100644 --- a/Il2CppInspector.Redux.CLI/Commands/ManualCommand.cs +++ b/Il2CppInspector.Redux.CLI/Commands/ManualCommand.cs @@ -3,7 +3,7 @@ using Spectre.Console.Cli; namespace Il2CppInspector.Redux.CLI.Commands; -internal abstract class ManualCommand(PortProvider portProvider) : BaseCommand(portProvider) where T : ManualCommandOptions +internal abstract class ManualCommand(PortProvider portProvider) : BaseCommand(portProvider) where T : ManualCommandSettings { public override ValidationResult Validate(CommandContext context, T settings) { diff --git a/Il2CppInspector.Redux.CLI/Commands/ManualCommandOptions.cs b/Il2CppInspector.Redux.CLI/Commands/ManualCommandSettings.cs similarity index 88% rename from Il2CppInspector.Redux.CLI/Commands/ManualCommandOptions.cs rename to Il2CppInspector.Redux.CLI/Commands/ManualCommandSettings.cs index b8902c8..7fc5944 100644 --- a/Il2CppInspector.Redux.CLI/Commands/ManualCommandOptions.cs +++ b/Il2CppInspector.Redux.CLI/Commands/ManualCommandSettings.cs @@ -3,7 +3,7 @@ using Spectre.Console.Cli; namespace Il2CppInspector.Redux.CLI.Commands; -internal class ManualCommandOptions : CommandSettings +internal class ManualCommandSettings : CommandSettings { [CommandArgument(0, "")] [Description("Paths to the input files. Will be subsequently loaded until binary and metadata were found.")] diff --git a/Il2CppInspector.Redux.CLI/Commands/ProcessCommand.cs b/Il2CppInspector.Redux.CLI/Commands/ProcessCommand.cs index cd325d2..43018e4 100644 --- a/Il2CppInspector.Redux.CLI/Commands/ProcessCommand.cs +++ b/Il2CppInspector.Redux.CLI/Commands/ProcessCommand.cs @@ -1,16 +1,18 @@ -using Il2CppInspector.Cpp; +using System.Globalization; +using Il2CppInspector.Cpp; +using Il2CppInspector.Redux.FrontendCore; using Il2CppInspector.Redux.FrontendCore.Outputs; using Spectre.Console; using Spectre.Console.Cli; namespace Il2CppInspector.Redux.CLI.Commands; -internal class ProcessCommand(PortProvider portProvider) : ManualCommand(portProvider) +internal sealed class ProcessCommand(PortProvider portProvider) : ManualCommand(portProvider) { // NOTE: There might be a better option than replicating all available flags here (and in the TS UI). // Investigate this in the future. - public class Option : ManualCommandOptions + public sealed class Settings : ManualCommandSettings { // C++ Scaffolding [CommandOption("--output-cpp-scaffolding")] @@ -67,13 +69,27 @@ internal class ProcessCommand(PortProvider portProvider) : ManualCommand ExecuteAsync(CliClient client, Option settings) + protected override async Task ExecuteAsync(CliClient client, Settings settings) { var inspectorVersion = await client.GetInspectorVersion(); AnsiConsole.MarkupLineInterpolated($"Using inspector [gray]{inspectorVersion}[/]"); + if (settings.ImageBase != null) + { + var imageBase = ulong.Parse(settings.ImageBase, + settings.ImageBase.StartsWith("0x") + ? NumberStyles.HexNumber + : NumberStyles.Integer); + + AnsiConsole.MarkupLineInterpolated($"Setting image base to [white]0x{imageBase:x}[/]"); + await client.SetSettings(new InspectorSettings(imageBase)); + } + await client.SubmitInputFiles(settings.InputPaths.ToList()); await client.WaitForLoadingToFinishAsync(); if (!client.ImportCompleted) @@ -148,7 +164,7 @@ internal class ProcessCommand(PortProvider portProvider) : ManualCommand inputFiles) { - await State.LoadInputFiles(Client, inputFiles); + await State.LoadInputFilesAsync(Client, inputFiles); } public async Task QueueExport(string exportTypeId, string outputDirectory, Dictionary settings) { - await State.QueueExport(Client, exportTypeId, outputDirectory, settings); + await State.QueueExportAsync(Client, exportTypeId, outputDirectory, settings); } public async Task StartExport() { - await State.StartExport(Client); + await State.StartExportAsync(Client); } public async Task> GetPotentialUnityVersions() { - return await State.GetPotentialUnityVersions(); + return await State.GetPotentialUnityVersionsAsync(); } public async Task ExportIl2CppFiles(string outputDirectory) { - await State.ExportIl2CppFiles(Client, outputDirectory); + await State.ExportIl2CppFilesAsync(Client, outputDirectory); } public async Task GetInspectorVersion() { - return await UiContext.GetInspectorVersion(); + return await UiContext.GetInspectorVersionAsync(); + } + + public async Task SetSettings(InspectorSettings settings) + { + await State.SetSettingsAsync(Client, settings); } } \ No newline at end of file diff --git a/Il2CppInspector.Redux.FrontendCore/InspectorSettings.cs b/Il2CppInspector.Redux.FrontendCore/InspectorSettings.cs new file mode 100644 index 0000000..6104c36 --- /dev/null +++ b/Il2CppInspector.Redux.FrontendCore/InspectorSettings.cs @@ -0,0 +1,3 @@ +namespace Il2CppInspector.Redux.FrontendCore; + +public sealed record InspectorSettings(ulong ImageBase); \ No newline at end of file diff --git a/Il2CppInspector.Redux.FrontendCore/UiContext.cs b/Il2CppInspector.Redux.FrontendCore/UiContext.cs index 44eca27..7f84454 100644 --- a/Il2CppInspector.Redux.FrontendCore/UiContext.cs +++ b/Il2CppInspector.Redux.FrontendCore/UiContext.cs @@ -26,7 +26,7 @@ public class UiContext private readonly List<(string FormatId, string OutputDirectory, Dictionary Settings)> _queuedExports = []; - private async Task TryLoadMetadataFromStream(UiClient client, MemoryStream stream) + private async Task TryLoadMetadataFromStreamAsync(UiClient client, MemoryStream stream) { try { @@ -41,7 +41,7 @@ public class UiContext return false; } - private async Task TryLoadBinaryFromStream(UiClient client, MemoryStream stream) + private async Task TryLoadBinaryFromStreamAsync(UiClient client, MemoryStream stream) { await client.ShowLogMessage("Processing binary"); @@ -64,7 +64,7 @@ public class UiContext return false; } - private async Task TryInitializeInspector(UiClient client) + private async Task TryInitializeInspectorAsync(UiClient client) { Debug.Assert(_binary != null); Debug.Assert(_metadata != null); @@ -117,12 +117,12 @@ public class UiContext return true; } - public async Task Initialize(UiClient client, CancellationToken cancellationToken = default) + public async Task InitializeAsync(UiClient client, CancellationToken cancellationToken = default) { await client.ShowSuccessToast("SignalR initialized!", cancellationToken); } - public async Task LoadInputFiles(UiClient client, List inputFiles, + public async Task LoadInputFilesAsync(UiClient client, List inputFiles, CancellationToken cancellationToken = default) { await using (await LoadingSession.Start(client)) @@ -132,10 +132,10 @@ public class UiContext { // The input files contained a package that provides the metadata and binary. // Use these instead of parsing all files individually. - if (!await TryLoadMetadataFromStream(client, streams.Value.Metadata)) + if (!await TryLoadMetadataFromStreamAsync(client, streams.Value.Metadata)) return; - if (!await TryLoadBinaryFromStream(client, streams.Value.Binary)) + if (!await TryLoadBinaryFromStreamAsync(client, streams.Value.Binary)) return; } else @@ -152,7 +152,7 @@ public class UiContext if ( _metadata == null && PathHeuristics.IsMetadataPath(inputFile)) { - if (await TryLoadMetadataFromStream(client, stream)) + if (await TryLoadMetadataFromStreamAsync(client, stream)) { await client.ShowSuccessToast($"Loaded metadata (v{_metadata!.Version}) from {inputFile}", cancellationToken); } @@ -162,7 +162,7 @@ public class UiContext stream.Position = 0; _loadOptions.BinaryFilePath = inputFile; - if (await TryLoadBinaryFromStream(client, stream)) + if (await TryLoadBinaryFromStreamAsync(client, stream)) { await client.ShowSuccessToast($"Loaded binary from {inputFile}", cancellationToken); } @@ -172,7 +172,7 @@ public class UiContext if (_metadata != null && _binary != null) { - if (await TryInitializeInspector(client)) + if (await TryInitializeInspectorAsync(client)) { await client.ShowSuccessToast($"Successfully loaded IL2CPP (v{_appModels[0].Package.Version}) data!", cancellationToken); await client.OnImportCompleted(cancellationToken); @@ -181,14 +181,14 @@ public class UiContext } } - public Task QueueExport(UiClient client, string exportFormatId, string outputDirectory, + public Task QueueExportAsync(UiClient client, string exportFormatId, string outputDirectory, Dictionary settings, CancellationToken cancellationToken = default) { _queuedExports.Add((exportFormatId, outputDirectory, settings)); return Task.CompletedTask; } - public async Task StartExport(UiClient client, CancellationToken cancellationToken = default) + public async Task StartExportAsync(UiClient client, CancellationToken cancellationToken = default) { // todo: support different app model selection (when loading packages) Debug.Assert(_appModels.Count > 0); @@ -217,12 +217,12 @@ public class UiContext await client.ShowSuccessToast("Export finished", cancellationToken); } - public Task> GetPotentialUnityVersions() + public Task> GetPotentialUnityVersionsAsync() { return Task.FromResult(_potentialUnityVersions.Select(x => x.VersionRange.Min.ToString()).ToList()); } - public async Task ExportIl2CppFiles(UiClient client, string outputDirectory, CancellationToken cancellationToken = default) + public async Task ExportIl2CppFilesAsync(UiClient client, string outputDirectory, CancellationToken cancellationToken = default) { Debug.Assert(_appModels.Count > 0); var pkg = _appModels[0].Package; @@ -244,8 +244,14 @@ public class UiContext } } - public static Task GetInspectorVersion() + public static Task GetInspectorVersionAsync() { return Task.FromResult(typeof(UiContext).Assembly.GetAssemblyVersion() ?? ""); } + + public Task SetSettingsAsync(UiClient client, InspectorSettings settings) + { + _loadOptions.ImageBase = settings.ImageBase; + return Task.CompletedTask; + } } \ No newline at end of file