Add decompile command

This commit is contained in:
Yoshi Askharoun
2024-02-22 11:13:31 -06:00
parent 02078f1793
commit acd127c3a1
3 changed files with 137 additions and 0 deletions
+113
View File
@@ -0,0 +1,113 @@
using Microsoft.Iris.Asm;
using Microsoft.Iris.Debug;
using Microsoft.Iris.Markup;
using Spectre.Console;
using Spectre.Console.Cli;
using System.ComponentModel;
namespace UIXC.Commands;
public class DecompileCommand : Command<DecompileCommand.Settings>
{
public override int Execute(CommandContext context, Settings settings)
{
if (settings.Inputs is null || settings.Inputs.Length <= 0)
{
AnsiConsole.MarkupLine("[red]Missing arguments: must specify a UIB file to decompile.[/]");
return -1;
}
if (settings.Verbose)
{
// Configure error and warning messages
TraceSettings.Current.SetCategoryLevel(TraceCategory.Markup, byte.MaxValue);
TraceSettings.Current.SetCategoryLevel(TraceCategory.MarkupCompiler, byte.MaxValue);
TraceSettings.Current.SetCategoryLevel(TraceCategory.MarkupDebug, byte.MaxValue);
TraceSettings.Current.OnWriteLine += (line) =>
{
AnsiConsole.MarkupLineInterpolated($"[grey]{line}[/]");
};
}
MarkupSystem.Startup(true);
bool success = false;
if (settings.Language == SourceLanguage.Asm)
{
foreach (var input in settings.Inputs)
{
try
{
var uibLoadResult = MarkupSystem.Load($"file://{input}", (uint)Random.Shared.Next());
uibLoadResult.FullLoad();
if (uibLoadResult.Status != LoadResultStatus.Success)
throw new Exception($"Failed to load UIB source ({uibLoadResult.ErrorContextUri})");
var disassembler = Disassembler.Load(uibLoadResult as MarkupLoadResult);
var asm = disassembler.Write();
File.WriteAllText(GetOutputPath(settings, input), asm);
success = true;
}
catch (Exception ex)
{
AnsiConsole.WriteException(ex);
success = false;
}
}
}
else if (settings.Language == SourceLanguage.Xml)
{
AnsiConsole.MarkupLine("[red]UIX XML is not currently a supported decompilation target.[/]");
}
else
{
AnsiConsole.MarkupLine($"[red]{settings.Language} is not currently a supported decompilation target.[/]");
}
if (!success)
{
AnsiConsole.MarkupLine("[red]Decompilation failed.[/]");
return -1;
}
else
{
AnsiConsole.MarkupLine("[green]Decompilation finished.[/]");
return 0;
}
}
private static string GetOutputPath(Settings settings, string inputFilePath)
{
var outputDir = settings.OutputDir ?? Environment.CurrentDirectory;
return Path.Combine(outputDir, Path.ChangeExtension(inputFilePath, settings.Language.GetExtension()));
}
public sealed class Settings : CommandSettings
{
[Description("The UIB files to decompile.")]
[CommandArgument(0, "[inputs]")]
public required string[] Inputs { get; init; }
[Description("Directories to search for imported files in.")]
[CommandOption("-I <VALUES>")]
public required string[] IncludeDirectories { get; init; }
[Description("A shared binary data table to decompile with.")]
[CommandOption("-t|--dataTable")]
public string? DataTable { get; init; }
[Description("The directory to output to.")]
[CommandOption("-o|--output <outputDir>")]
public string? OutputDir { get; init; }
// TODO: Enum options
[Description("The language to decompile to.")]
[CommandOption("-l|--lang <lang>")]
public SourceLanguage Language { get; init; } = SourceLanguage.Asm;
[CommandOption("--verbose")]
[DefaultValue(false)]
public bool Verbose { get; init; }
}
}
+4
View File
@@ -15,6 +15,10 @@ internal class Program
.WithAlias("c") .WithAlias("c")
.WithDescription("Compiles the given source to UIB."); .WithDescription("Compiles the given source to UIB.");
config.AddCommand<DecompileCommand>("decompile")
.WithAlias("d")
.WithDescription("Decompiles the given compiled UIX to a source langauge.");
#if DEBUG #if DEBUG
config.PropagateExceptions(); config.PropagateExceptions();
config.ValidateExamples(); config.ValidateExamples();
+20
View File
@@ -0,0 +1,20 @@
namespace UIXC;
public enum SourceLanguage
{
Xml, Asm
}
public static class SourceLanguageEx
{
public static string GetExtension(this SourceLanguage sourceLanguage)
{
return sourceLanguage switch
{
SourceLanguage.Xml => ".uix",
SourceLanguage.Asm => ".uixa",
_ => throw new ArgumentException("Invalid source langauge", nameof(sourceLanguage)),
};
}
}