mirror of
https://github.com/ZuneDev/ZuneUIXTools.git
synced 2026-07-27 13:11:59 -07:00
Add decompile command
This commit is contained in:
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,10 @@ internal class Program
|
||||
.WithAlias("c")
|
||||
.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
|
||||
config.PropagateExceptions();
|
||||
config.ValidateExamples();
|
||||
|
||||
@@ -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)),
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user