diff --git a/SabreTools.Serialization/Printer.cs b/SabreTools.Serialization/Printer.cs
index c6fea58d..48c3a5f6 100644
--- a/SabreTools.Serialization/Printer.cs
+++ b/SabreTools.Serialization/Printer.cs
@@ -54,6 +54,7 @@ namespace SabreTools.Serialization
Wrapper.PAK item => item.PrettyPrint(),
Wrapper.PFF item => item.PrettyPrint(),
Wrapper.PIC item => item.PrettyPrint(),
+ Wrapper.PKZIP item => item.PrettyPrint(),
Wrapper.PlayJAudioFile item => item.PrettyPrint(),
Wrapper.PlayJPlaylist item => item.PrettyPrint(),
Wrapper.PortableExecutable item => item.PrettyPrint(),
@@ -97,6 +98,7 @@ namespace SabreTools.Serialization
Wrapper.PAK item => item.ExportJSON(),
Wrapper.PFF item => item.ExportJSON(),
Wrapper.PIC item => item.ExportJSON(),
+ Wrapper.PKZIP item => item.ExportJSON(),
Wrapper.PlayJAudioFile item => item.ExportJSON(),
Wrapper.PlayJPlaylist item => item.ExportJSON(),
Wrapper.PortableExecutable item => item.ExportJSON(),
@@ -314,6 +316,16 @@ namespace SabreTools.Serialization
PIC.Print(builder, item.Model);
return builder;
}
+
+ ///
+ /// Export the item information as pretty-printed text
+ ///
+ private static StringBuilder PrettyPrint(this Wrapper.PKZIP item)
+ {
+ var builder = new StringBuilder();
+ PKZIP.Print(builder, item.Model);
+ return builder;
+ }
///
/// Export the item information as pretty-printed text
diff --git a/SabreTools.Serialization/Printers/PKZIP.cs b/SabreTools.Serialization/Printers/PKZIP.cs
new file mode 100644
index 00000000..c001c36c
--- /dev/null
+++ b/SabreTools.Serialization/Printers/PKZIP.cs
@@ -0,0 +1,279 @@
+using System.Text;
+using SabreTools.Models.PKZIP;
+using SabreTools.Serialization.Interfaces;
+
+namespace SabreTools.Serialization.Printers
+{
+ public class PKZIP : IPrinter
+ {
+ ///
+ public void PrintInformation(StringBuilder builder, Archive model)
+ => Print(builder, model);
+
+ public static void Print(StringBuilder builder, Archive archive)
+ {
+ builder.AppendLine("PKZIP Archive (or Derived Format) Information:");
+ builder.AppendLine("-------------------------");
+ builder.AppendLine();
+
+ Print(builder, archive.EndOfCentralDirectoryRecord);
+ Print(builder, archive.ZIP64EndOfCentralDirectoryLocator);
+ Print(builder, archive.ZIP64EndOfCentralDirectoryRecord);
+ Print(builder, archive.CentralDirectoryHeaders);
+ Print(builder, archive.ArchiveExtraDataRecord);
+ Print(builder,
+ archive.LocalFileHeaders,
+ archive.EncryptionHeaders,
+ archive.FileData,
+ archive.DataDescriptors,
+ archive.ZIP64DataDescriptors);
+ }
+
+ private static void Print(StringBuilder builder, EndOfCentralDirectoryRecord? record)
+ {
+ builder.AppendLine(" End of Central Directory Record Information:");
+ builder.AppendLine(" -------------------------");
+ if (record == null)
+ {
+ builder.AppendLine(" No end of central directory record");
+ builder.AppendLine();
+ return;
+ }
+
+ builder.AppendLine(record.Signature, " Signature");
+ builder.AppendLine(record.DiskNumber, " Disk number");
+ builder.AppendLine(record.StartDiskNumber, " Start disk number");
+ builder.AppendLine(record.TotalEntriesOnDisk, " Total entries on disk");
+ builder.AppendLine(record.TotalEntries, " Total entries");
+ builder.AppendLine(record.CentralDirectorySize, " Central directory size");
+ builder.AppendLine(record.CentralDirectoryOffset, " Central directory offset");
+ builder.AppendLine(record.FileCommentLength, " File comment length");
+ builder.AppendLine(record.FileComment, " File comment");
+ builder.AppendLine();
+ }
+
+ private static void Print(StringBuilder builder, EndOfCentralDirectoryLocator64? locator)
+ {
+ builder.AppendLine(" ZIP64 End of Central Directory Locator Information:");
+ builder.AppendLine(" -------------------------");
+ if (locator == null)
+ {
+ builder.AppendLine(" No ZIP64 end of central directory locator");
+ builder.AppendLine();
+ return;
+ }
+
+ builder.AppendLine(locator.Signature, " Signature");
+ builder.AppendLine(locator.StartDiskNumber, " Start disk number");
+ builder.AppendLine(locator.CentralDirectoryOffset, " Central directory offset");
+ builder.AppendLine(locator.TotalDisks, " Total disks");
+ builder.AppendLine();
+ }
+
+ private static void Print(StringBuilder builder, EndOfCentralDirectoryRecord64? record)
+ {
+ builder.AppendLine(" ZIP64 End of Central Directory Record Information:");
+ builder.AppendLine(" -------------------------");
+ if (record == null)
+ {
+ builder.AppendLine(" No ZIP64 end of central directory record");
+ builder.AppendLine();
+ return;
+ }
+
+ builder.AppendLine(record.Signature, " Signature");
+ builder.AppendLine(record.DirectoryRecordSize, " Directory record size");
+ builder.AppendLine($" Host system: {record.HostSystem} (0x{record.HostSystem:X})");
+ builder.AppendLine(record.VersionMadeBy, " Version made by");
+ builder.AppendLine(record.VersionNeededToExtract, " Version needed to extract");
+ builder.AppendLine(record.DiskNumber, " Disk number");
+ builder.AppendLine(record.StartDiskNumber, " Start disk number");
+ builder.AppendLine(record.TotalEntriesOnDisk, " Total entries on disk");
+ builder.AppendLine(record.TotalEntries, " Total entries");
+ builder.AppendLine(record.CentralDirectorySize, " Central directory size");
+ builder.AppendLine(record.CentralDirectoryOffset, " Central directory offset");
+ //builder.AppendLine(record.ExtensibleDataSector, " Extensible data sector");
+ builder.AppendLine();
+ }
+
+ private static void Print(StringBuilder builder, CentralDirectoryFileHeader?[]? headers)
+ {
+ builder.AppendLine(" Central Directory File Headers Information:");
+ builder.AppendLine(" -------------------------");
+ if (headers == null || headers.Length == 0)
+ {
+ builder.AppendLine(" No central directory file headers");
+ builder.AppendLine();
+ return;
+ }
+
+ for (int i = 0; i < headers.Length; i++)
+ {
+ var record = headers[i];
+ Print(builder, record, i);
+ }
+ builder.AppendLine();
+ }
+
+ private static void Print(StringBuilder builder, CentralDirectoryFileHeader? header, int index)
+ {
+ builder.AppendLine($" Central Directory File Header Entry {index}");
+ if (header == null)
+ {
+ builder.AppendLine(" [NULL]");
+ return;
+ }
+
+ builder.AppendLine(header.Signature, " Signature");
+ builder.AppendLine($" Host system: {header.HostSystem} (0x{header.HostSystem:X})");
+ builder.AppendLine(header.VersionMadeBy, " Version made by");
+ builder.AppendLine(header.VersionNeededToExtract, " Version needed to extract");
+ builder.AppendLine($" Flags: {header.Flags} (0x{header.Flags:X})");
+ builder.AppendLine($" Compression method: {header.CompressionMethod} (0x{header.CompressionMethod:X})");
+ builder.AppendLine(header.LastModifedFileTime, " Last modified file time"); // TODO: Parse from MS-DOS
+ builder.AppendLine(header.LastModifiedFileDate, " Last modified file date"); // TODO: Parse from MS-DOS
+ builder.AppendLine(header.CRC32, " CRC-32");
+ builder.AppendLine(header.CompressedSize, " Compressed size");
+ builder.AppendLine(header.UncompressedSize, " Uncompressed size");
+ builder.AppendLine(header.FileNameLength, " File name length");
+ builder.AppendLine(header.ExtraFieldLength, " Extra field length");
+ builder.AppendLine(header.FileCommentLength, " File comment length");
+ builder.AppendLine(header.DiskNumberStart, " Disk number start");
+ builder.AppendLine($" Internal file attributes: {header.InternalFileAttributes} (0x{header.InternalFileAttributes:X})");
+ builder.AppendLine(header.ExternalFileAttributes, " External file attributes");
+ builder.AppendLine(header.RelativeOffsetOfLocalHeader, " Relative offset of local header");
+ builder.AppendLine(header.FileName, " File name");
+ builder.AppendLine(header.ExtraField, " Extra field");
+ builder.AppendLine(header.FileComment, " File comment");
+ }
+
+ private static void Print(StringBuilder builder, ArchiveExtraDataRecord? record)
+ {
+ builder.AppendLine(" Archive Extra Data Record Information:");
+ builder.AppendLine(" -------------------------");
+ if (record == null)
+ {
+ builder.AppendLine(" No archive extra data record");
+ builder.AppendLine();
+ return;
+ }
+
+ builder.AppendLine(record.Signature, " Signature");
+ builder.AppendLine(record.ExtraFieldLength, " Extra field length");
+ builder.AppendLine(record.ExtraFieldData, " Extra field data");
+ builder.AppendLine();
+ }
+
+ private static void Print(StringBuilder builder,
+ LocalFileHeader[]? localFileHeaders,
+ byte[]?[]? encryptionHeaders,
+ byte[][]? fileData,
+ DataDescriptor?[]? dataDescriptors,
+ DataDescriptor64?[]? zip64DataDescriptors)
+ {
+ builder.AppendLine(" Local File Information:");
+ builder.AppendLine(" -------------------------");
+ if (localFileHeaders == null || localFileHeaders.Length == 0)
+ {
+ builder.AppendLine(" No local files");
+ builder.AppendLine();
+ return;
+ }
+
+ if (encryptionHeaders == null || localFileHeaders.Length > encryptionHeaders.Length
+ || fileData == null || localFileHeaders.Length > fileData.Length
+ || dataDescriptors == null || localFileHeaders.Length > dataDescriptors.Length
+ || zip64DataDescriptors == null || localFileHeaders.Length > zip64DataDescriptors.Length)
+ {
+ builder.AppendLine(" Mismatch in local file array values");
+ builder.AppendLine();
+ }
+
+ for (int i = 0; i < localFileHeaders.Length; i++)
+ {
+ var localFileHeader = localFileHeaders[i];
+ var encryptionHeader = encryptionHeaders != null && i < encryptionHeaders.Length - 1 ? encryptionHeaders[i] : null;
+ var fileDatum = fileData != null && i < fileData.Length - 1 ? fileData[i] : null;
+ var dataDescriptor = dataDescriptors != null && i < dataDescriptors.Length - 1 ? dataDescriptors[i] : null;
+ var zip64DataDescriptor = zip64DataDescriptors != null && i < zip64DataDescriptors.Length - 1 ? zip64DataDescriptors[i] : null;
+
+ Print(builder, localFileHeader, encryptionHeader, fileDatum, dataDescriptor, zip64DataDescriptor, i);
+ }
+ builder.AppendLine();
+ }
+
+ private static void Print(StringBuilder builder,
+ LocalFileHeader localFileHeader,
+ byte[]? encryptionHeader,
+ byte[]? fileData,
+ DataDescriptor? dataDescriptor,
+ DataDescriptor64? zip64DataDescriptor,
+ int index)
+ {
+ builder.AppendLine($" Local File Entry {index}");
+ if (localFileHeader == null)
+ {
+ builder.AppendLine(" [NULL]");
+ return;
+ }
+
+ builder.AppendLine(localFileHeader.Signature, " [Local File Header] Signature");
+ builder.AppendLine(localFileHeader.Version, " [Local File Header] Version");
+ builder.AppendLine($" [Local File Header] Flags: {localFileHeader.Flags} (0x{localFileHeader.Flags:X})");
+ builder.AppendLine($" [Local File Header] Compression method: {localFileHeader.CompressionMethod} (0x{localFileHeader.CompressionMethod:X})");
+ builder.AppendLine(localFileHeader.LastModifedFileTime, " [Local File Header] Last modified file time"); // TODO: Parse from MS-DOS
+ builder.AppendLine(localFileHeader.LastModifiedFileDate, " [Local File Header] Last modified file date"); // TODO: Parse from MS-DOS
+ builder.AppendLine(localFileHeader.CRC32, " [Local File Header] CRC-32");
+ builder.AppendLine(localFileHeader.CompressedSize, " [Local File Header] Compressed size");
+ builder.AppendLine(localFileHeader.UncompressedSize, " [Local File Header] Uncompressed size");
+ builder.AppendLine(localFileHeader.FileNameLength, " [Local File Header] File name length");
+ builder.AppendLine(localFileHeader.ExtraFieldLength, " [Local File Header] Extra field length");
+ builder.AppendLine(localFileHeader.FileName, " [Local File Header] File name");
+ builder.AppendLine(localFileHeader.ExtraField, " [Local File Header] Extra field");
+
+ if (encryptionHeader == null)
+ {
+ builder.AppendLine(" [Encryption Header]: [NULL]");
+ }
+ else
+ {
+ builder.AppendLine(encryptionHeader.Length, " [Encryption Header] Length");
+ builder.AppendLine(encryptionHeader, " [Encryption Header] Data");
+ }
+
+ if (fileData == null)
+ {
+ builder.AppendLine(" [File Data]: [NULL]");
+ }
+ else
+ {
+ builder.AppendLine(fileData.Length, " [File Data] Length");
+ //builder.AppendLine(fileData, " [File Data] Data");
+ }
+
+ if (dataDescriptor == null)
+ {
+ builder.AppendLine(" [Data Descriptor]: [NULL]");
+ }
+ else
+ {
+ builder.AppendLine(dataDescriptor.Signature, " [Data Descriptor] Signature");
+ builder.AppendLine(dataDescriptor.CRC32, " [Data Descriptor] CRC-32");
+ builder.AppendLine(dataDescriptor.CompressedSize, " [Data Descriptor] Compressed size");
+ builder.AppendLine(dataDescriptor.UncompressedSize, " [Data Descriptor] Uncompressed size");
+ }
+
+ if (zip64DataDescriptor == null)
+ {
+ builder.AppendLine(" [ZIP64 Data Descriptor]: [NULL]");
+ }
+ else
+ {
+ builder.AppendLine(zip64DataDescriptor.Signature, " [ZIP64 Data Descriptor] Signature");
+ builder.AppendLine(zip64DataDescriptor.CRC32, " [ZIP64 Data Descriptor] CRC-32");
+ builder.AppendLine(zip64DataDescriptor.CompressedSize, " [ZIP64 Data Descriptor] Compressed size");
+ builder.AppendLine(zip64DataDescriptor.UncompressedSize, " [ZIP64 Data Descriptor] Uncompressed size");
+ }
+ }
+ }
+}
\ No newline at end of file