From 49f6704694a08ce2018419a30620cf67e030a090 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 30 Sep 2025 14:05:34 -0400 Subject: [PATCH] Add initial XZ printer --- SabreTools.Serialization/Printer.cs | 12 +++ SabreTools.Serialization/Printers/XZ.cs | 109 ++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 SabreTools.Serialization/Printers/XZ.cs diff --git a/SabreTools.Serialization/Printer.cs b/SabreTools.Serialization/Printer.cs index 2287912c..ea14ee45 100644 --- a/SabreTools.Serialization/Printer.cs +++ b/SabreTools.Serialization/Printer.cs @@ -75,6 +75,7 @@ namespace SabreTools.Serialization Wrapper.WiseSectionHeader item => item.PrettyPrint(), Wrapper.XeMID item => item.PrettyPrint(), Wrapper.XMID item => item.PrettyPrint(), + Wrapper.XZ item => item.PrettyPrint(), Wrapper.XZP item => item.PrettyPrint(), _ => null, }; @@ -130,6 +131,7 @@ namespace SabreTools.Serialization Wrapper.WiseSectionHeader item => item.ExportJSON(), Wrapper.XeMID item => item.ExportJSON(), Wrapper.XMID item => item.ExportJSON(), + Wrapper.XZ item => item.ExportJSON(), Wrapper.XZP item => item.ExportJSON(), _ => string.Empty, }; @@ -558,6 +560,16 @@ namespace SabreTools.Serialization return builder; } + /// + /// Export the item information as pretty-printed text + /// + private static StringBuilder PrettyPrint(this Wrapper.XZ item) + { + var builder = new StringBuilder(); + XZ.Print(builder, item.Model); + return builder; + } + /// /// Export the item information as pretty-printed text /// diff --git a/SabreTools.Serialization/Printers/XZ.cs b/SabreTools.Serialization/Printers/XZ.cs new file mode 100644 index 00000000..6deabdb9 --- /dev/null +++ b/SabreTools.Serialization/Printers/XZ.cs @@ -0,0 +1,109 @@ +using System.Text; +using SabreTools.Data.Models.XZ; + +namespace SabreTools.Data.Printers +{ + public class XZ : IPrinter + { + /// + public void PrintInformation(StringBuilder builder, Archive model) + => Print(builder, model); + + public static void Print(StringBuilder builder, Archive archive) + { + builder.AppendLine("xz Information:"); + builder.AppendLine("-------------------------"); + builder.AppendLine(); + + Print(builder, archive.Header); + Print(builder, archive.Blocks); + Print(builder, archive.Index); + Print(builder, archive.Footer); + } + + private static void Print(StringBuilder builder, Header? header) + { + builder.AppendLine(" Header Information:"); + builder.AppendLine(" -------------------------"); + if (header == null) + { + builder.AppendLine(" No header"); + builder.AppendLine(); + return; + } + + builder.AppendLine(header.Signature, " Signature"); + builder.AppendLine($" Flags: {header.Flags} (0x{(ushort)header.Flags:X4})"); + builder.AppendLine(header.Crc32, " CRC-32"); + builder.AppendLine(); + } + + private static void Print(StringBuilder builder, Block[]? blocks) + { + builder.AppendLine(" Blocks Information:"); + builder.AppendLine(" -------------------------"); + if (blocks == null || blocks.Length == 0) + { + builder.AppendLine(" No blocks"); + builder.AppendLine(); + return; + } + + for (int i = 0; i < blocks.Length; i++) + { + var block = blocks[i]; + + builder.AppendLine($" Block {i}:"); + builder.AppendLine(block.HeaderSize, " Header size"); + builder.AppendLine($" Flags: {block.Flags} (0x{(byte)block.Flags:X2})"); + builder.AppendLine(block.CompressedSize, " Compressed size"); + builder.AppendLine(block.UncompressedSize, " Uncompressed size"); + // TODO: Print filter flags + builder.AppendLine(block.HeaderPadding, " Header padding"); + builder.AppendLine(block.Crc32, " CRC-32"); + // TODO: Print the actual compressed data length + builder.AppendLine(block.BlockPadding, " Block padding"); + builder.AppendLine(block.Check, " Check"); + } + + builder.AppendLine(); + } + + private static void Print(StringBuilder builder, Index? index) + { + builder.AppendLine(" Index Information:"); + builder.AppendLine(" -------------------------"); + if (index == null) + { + builder.AppendLine(" No index"); + builder.AppendLine(); + return; + } + + builder.AppendLine(index.IndexIndicator, " Index indicator"); + builder.AppendLine(index.NumberOfRecords, " Number of records"); + // TODO: Print records + builder.AppendLine(index.Padding, " Padding"); + builder.AppendLine(index.Crc32, " CRC-32"); + builder.AppendLine(); + } + + private static void Print(StringBuilder builder, Footer? footer) + { + builder.AppendLine(" Footer Information:"); + builder.AppendLine(" -------------------------"); + if (footer == null) + { + builder.AppendLine(" No footer"); + builder.AppendLine(); + return; + } + + builder.AppendLine(footer.Crc32, " CRC-32"); + builder.AppendLine(footer.BackwardSize, " Backward size"); + builder.AppendLine($" Flags: {footer.Flags} (0x{(ushort)footer.Flags:X4})"); + builder.AppendLine(footer.Signature, " Signature"); + builder.AppendLine(); + } + } +}