From 74ea6e6002120ac87e6bff430e6bea87a5b4cf22 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Thu, 14 Sep 2023 23:36:29 -0400 Subject: [PATCH] Port N3DS to new printing --- BinaryObjectScanner.Printing/N3DS.cs | 669 +++++++++++++++++++++++++++ BinaryObjectScanner.Wrappers/N3DS.cs | 637 +------------------------ 2 files changed, 670 insertions(+), 636 deletions(-) create mode 100644 BinaryObjectScanner.Printing/N3DS.cs diff --git a/BinaryObjectScanner.Printing/N3DS.cs b/BinaryObjectScanner.Printing/N3DS.cs new file mode 100644 index 00000000..250e263e --- /dev/null +++ b/BinaryObjectScanner.Printing/N3DS.cs @@ -0,0 +1,669 @@ +using System.Text; +using SabreTools.Models.N3DS; + +namespace BinaryObjectScanner.Printing +{ + public static class N3DS + { + public static void Print(StringBuilder builder, Cart cart) + { + builder.AppendLine("3DS Cart Information:"); + builder.AppendLine("-------------------------"); + builder.AppendLine(); + + Print(builder, cart.Header); + Print(builder, cart.CardInfoHeader); + Print(builder, cart.DevelopmentCardInfoHeader); + Print(builder, cart.Partitions); + Print(builder, cart.ExtendedHeaders); + Print(builder, cart.ExeFSHeaders); + Print(builder, cart.RomFSHeaders); + } + +#if NET48 + private static void Print(StringBuilder builder, NCSDHeader header) +#else + private static void Print(StringBuilder builder, NCSDHeader? header) +#endif + { + builder.AppendLine(" NCSD Header Information:"); + builder.AppendLine(" -------------------------"); + if (header == null) + { + builder.AppendLine(" No NCSD header"); + builder.AppendLine(); + return; + } + + builder.AppendLine(header.RSA2048Signature, " RSA-2048 SHA-256 signature"); + builder.AppendLine(header.MagicNumber, " Magic number"); + builder.AppendLine(header.ImageSizeInMediaUnits, " Image size in media units"); + builder.AppendLine(header.MediaId, " Media ID"); + builder.AppendLine($" Partitions filesystem type: {header.PartitionsFSType} (0x{header.PartitionsFSType:X})"); + builder.AppendLine(header.PartitionsCryptType, " Partitions crypt type"); + builder.AppendLine(); + + builder.AppendLine(" Partition table:"); + builder.AppendLine(" -------------------------"); + if (header.PartitionsTable == null || header.PartitionsTable.Length == 0) + { + builder.AppendLine(" No partition table entries"); + } + else + { + for (int i = 0; i < header.PartitionsTable.Length; i++) + { + var partitionTableEntry = header.PartitionsTable[i]; + builder.AppendLine($" Partition table entry {i}"); + if (partitionTableEntry == null) + { + builder.AppendLine(" [NULL]"); + continue; + } + + builder.AppendLine(partitionTableEntry.Offset, " Offset"); + builder.AppendLine(partitionTableEntry.Length, " Length"); + } + } + builder.AppendLine(); + + // If we have a cart image + if (header.PartitionsFSType == FilesystemType.Normal || header.PartitionsFSType == FilesystemType.None) + { + builder.AppendLine(header.ExheaderHash, " Exheader SHA-256 hash"); + builder.AppendLine(header.AdditionalHeaderSize, " Additional header size"); + builder.AppendLine(header.SectorZeroOffset, " Sector zero offset"); + builder.AppendLine(header.PartitionFlags, " Partition flags"); + builder.AppendLine(); + + builder.AppendLine(" Partition ID table:"); + builder.AppendLine(" -------------------------"); + if (header.PartitionIdTable == null || header.PartitionIdTable.Length == 0) + { + builder.AppendLine(" No partition ID table entries"); + } + else + { + for (int i = 0; i < header.PartitionIdTable.Length; i++) + { + builder.AppendLine(header.PartitionIdTable[i], $" Partition {i} ID"); + } + } + builder.AppendLine(); + + builder.AppendLine(header.Reserved1, " Reserved 1"); + builder.AppendLine(header.Reserved2, " Reserved 2"); + builder.AppendLine(header.FirmUpdateByte1, " Firmware update byte 1"); + builder.AppendLine(header.FirmUpdateByte2, " Firmware update byte 2"); + } + + // If we have a firmware image + else if (header.PartitionsFSType == FilesystemType.FIRM) + { + builder.AppendLine(header.Unknown, " Unknown"); + builder.AppendLine(header.EncryptedMBR, " Encrypted MBR"); + } + + builder.AppendLine(); + } + +#if NET48 + private static void Print(StringBuilder builder, CardInfoHeader header) +#else + private static void Print(StringBuilder builder, CardInfoHeader? header) +#endif + { + builder.AppendLine(" Card Info Header Information:"); + builder.AppendLine(" -------------------------"); + if (header == null) + { + builder.AppendLine(" No card info header"); + builder.AppendLine(); + return; + } + + builder.AppendLine(header.WritableAddressMediaUnits, " Writable address in media units"); + builder.AppendLine(header.CardInfoBitmask, " Card info bitmask"); + builder.AppendLine(header.Reserved1, " Reserved 1"); + builder.AppendLine(header.FilledSize, " Filled size of cartridge"); + builder.AppendLine(header.Reserved2, " Reserved 2"); + builder.AppendLine(header.TitleVersion, " Title version"); + builder.AppendLine(header.CardRevision, " Card revision"); + builder.AppendLine(header.Reserved3, " Reserved 3"); + builder.AppendLine(header.CVerTitleID, " Title ID of CVer in included update partition"); + builder.AppendLine(header.CVerVersionNumber, " Version number of CVer in included update partition"); + builder.AppendLine(header.Reserved4, " Reserved 4"); + builder.AppendLine(); + } + +#if NET48 + private static void Print(StringBuilder builder, DevelopmentCardInfoHeader header) +#else + private static void Print(StringBuilder builder, DevelopmentCardInfoHeader? header) +#endif + { + builder.AppendLine(" Development Card Info Header Information:"); + builder.AppendLine(" -------------------------"); + if (header == null) + { + builder.AppendLine(" No development card info header"); + builder.AppendLine(); + return; + } + + builder.AppendLine(); + builder.AppendLine(" Initial Data:"); + builder.AppendLine(" -------------------------"); + if (header.InitialData == null) + { + builder.AppendLine(" No initial data"); + } + else + { + builder.AppendLine(header.InitialData.CardSeedKeyY, " Card seed keyY"); + builder.AppendLine(header.InitialData.EncryptedCardSeed, " Encrypted card seed"); + builder.AppendLine(header.InitialData.CardSeedAESMAC, " Card seed AES-MAC"); + builder.AppendLine(header.InitialData.CardSeedNonce, " Card seed nonce"); + builder.AppendLine(header.InitialData.Reserved, " Reserved"); + } + builder.AppendLine(); + + builder.AppendLine(" Backup Header:"); + builder.AppendLine(" -------------------------"); + if (header.InitialData.BackupHeader == null) + { + builder.AppendLine(" No backup header"); + } + else + { + builder.AppendLine(header.InitialData.BackupHeader.MagicID, " Magic ID"); + builder.AppendLine(header.InitialData.BackupHeader.ContentSizeInMediaUnits, " Content size in media units"); + builder.AppendLine(header.InitialData.BackupHeader.PartitionId, " Partition ID"); + builder.AppendLine(header.InitialData.BackupHeader.MakerCode, " Maker code"); + builder.AppendLine(header.InitialData.BackupHeader.Version, " Version"); + builder.AppendLine(header.InitialData.BackupHeader.VerificationHash, " Verification hash"); + builder.AppendLine(header.InitialData.BackupHeader.ProgramId, " Program ID"); + builder.AppendLine(header.InitialData.BackupHeader.Reserved1, " Reserved 1"); + builder.AppendLine(header.InitialData.BackupHeader.LogoRegionHash, " Logo region SHA-256 hash"); + builder.AppendLine(header.InitialData.BackupHeader.ProductCode, " Product code"); + builder.AppendLine(header.InitialData.BackupHeader.ExtendedHeaderHash, " Extended header SHA-256 hash"); + builder.AppendLine(header.InitialData.BackupHeader.ExtendedHeaderSizeInBytes, " Extended header size in bytes"); + builder.AppendLine(header.InitialData.BackupHeader.Reserved2, " Reserved 2"); + builder.AppendLine($" Flags: {header.InitialData.BackupHeader.Flags} (0x{header.InitialData.BackupHeader.Flags:X})"); + builder.AppendLine(header.InitialData.BackupHeader.PlainRegionOffsetInMediaUnits, " Plain region offset, in media units"); + builder.AppendLine(header.InitialData.BackupHeader.PlainRegionSizeInMediaUnits, " Plain region size, in media units"); + builder.AppendLine(header.InitialData.BackupHeader.LogoRegionOffsetInMediaUnits, " Logo region offset, in media units"); + builder.AppendLine(header.InitialData.BackupHeader.LogoRegionSizeInMediaUnits, " Logo region size, in media units"); + builder.AppendLine(header.InitialData.BackupHeader.ExeFSOffsetInMediaUnits, " ExeFS offset, in media units"); + builder.AppendLine(header.InitialData.BackupHeader.ExeFSSizeInMediaUnits, " ExeFS size, in media units"); + builder.AppendLine(header.InitialData.BackupHeader.ExeFSHashRegionSizeInMediaUnits, " ExeFS hash region size, in media units"); + builder.AppendLine(header.InitialData.BackupHeader.Reserved3, " Reserved 3"); + builder.AppendLine(header.InitialData.BackupHeader.RomFSOffsetInMediaUnits, " RomFS offset, in media units"); + builder.AppendLine(header.InitialData.BackupHeader.RomFSSizeInMediaUnits, " RomFS size, in media units"); + builder.AppendLine(header.InitialData.BackupHeader.RomFSHashRegionSizeInMediaUnits, " RomFS hash region size, in media units"); + builder.AppendLine(header.InitialData.BackupHeader.Reserved4, " Reserved 4"); + builder.AppendLine(header.InitialData.BackupHeader.ExeFSSuperblockHash, " ExeFS superblock SHA-256 hash"); + builder.AppendLine(header.InitialData.BackupHeader.RomFSSuperblockHash, " RomFS superblock SHA-256 hash"); + } + builder.AppendLine(); + + builder.AppendLine(header.CardDeviceReserved1, " Card device reserved 1"); + builder.AppendLine(header.TitleKey, " Title key"); + builder.AppendLine(header.CardDeviceReserved2, " Card device reserved 2"); + builder.AppendLine(); + + builder.AppendLine(" Test Data:"); + builder.AppendLine(" -------------------------"); + if (header.TestData == null) + { + builder.AppendLine(" No test data"); + } + else + { + builder.AppendLine(header.TestData.Signature, " Signature"); + builder.AppendLine(header.TestData.AscendingByteSequence, " Ascending byte sequence"); + builder.AppendLine(header.TestData.DescendingByteSequence, " Descending byte sequence"); + builder.AppendLine(header.TestData.Filled00, " Filled with 00"); + builder.AppendLine(header.TestData.FilledFF, " Filled with FF"); + builder.AppendLine(header.TestData.Filled0F, " Filled with 0F"); + builder.AppendLine(header.TestData.FilledF0, " Filled with F0"); + builder.AppendLine(header.TestData.Filled55, " Filled with 55"); + builder.AppendLine(header.TestData.FilledAA, " Filled with AA"); + builder.AppendLine(header.TestData.FinalByte, " Final byte"); + } + builder.AppendLine(); + } + +#if NET48 + private static void Print(StringBuilder builder, NCCHHeader[] entries) +#else + private static void Print(StringBuilder builder, NCCHHeader?[]? entries) +#endif + { + builder.AppendLine(" NCCH Partition Header Information:"); + builder.AppendLine(" -------------------------"); + if (entries == null || entries.Length == 0) + { + builder.AppendLine(" No NCCH partition headers"); + builder.AppendLine(); + return; + } + + for (int i = 0; i < entries.Length; i++) + { + var entry = entries[i]; + builder.AppendLine($" NCCH Partition Header {i}"); + if (entry == null) + { + builder.AppendLine(" [NULL]"); + continue; + } + + if (entry.MagicID == string.Empty) + { + builder.AppendLine(" Empty partition, no data can be parsed"); + } + else if (entry.MagicID != Constants.NCCHMagicNumber) + { + builder.AppendLine(" Unrecognized partition data, no data can be parsed"); + } + else + { + builder.AppendLine(entry.RSA2048Signature, " RSA-2048 SHA-256 signature"); + builder.AppendLine(entry.MagicID, " Magic ID"); + builder.AppendLine(entry.ContentSizeInMediaUnits, " Content size in media units"); + builder.AppendLine(entry.PartitionId, " Partition ID"); + builder.AppendLine(entry.MakerCode, " Maker code"); + builder.AppendLine(entry.Version, " Version"); + builder.AppendLine(entry.VerificationHash, " Verification hash"); + builder.AppendLine(entry.ProgramId, " Program ID"); + builder.AppendLine(entry.Reserved1, " Reserved 1"); + builder.AppendLine(entry.LogoRegionHash, " Logo region SHA-256 hash"); + builder.AppendLine(entry.ProductCode, " Product code"); + builder.AppendLine(entry.ExtendedHeaderHash, " Extended header SHA-256 hash"); + builder.AppendLine(entry.ExtendedHeaderSizeInBytes, " Extended header size in bytes"); + builder.AppendLine(entry.Reserved2, " Reserved 2"); + builder.AppendLine(" Flags:"); + if (entry.Flags == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.Flags.Reserved0, " Reserved 0"); + builder.AppendLine(entry.Flags.Reserved1, " Reserved 1"); + builder.AppendLine(entry.Flags.Reserved2, " Reserved 2"); + builder.AppendLine($" Crypto method: {entry.Flags.CryptoMethod} (0x{entry.Flags.CryptoMethod:X})"); + builder.AppendLine($" Content platform: {entry.Flags.ContentPlatform} (0x{entry.Flags.ContentPlatform:X})"); + builder.AppendLine($" Content type: {entry.Flags.MediaPlatformIndex} (0x{entry.Flags.MediaPlatformIndex:X})"); + builder.AppendLine(entry.Flags.ContentUnitSize, " Content unit size"); + builder.AppendLine($" Bitmasks: {entry.Flags.BitMasks} (0x{entry.Flags.BitMasks:X})"); + } + builder.AppendLine(entry.PlainRegionOffsetInMediaUnits, " Plain region offset, in media units"); + builder.AppendLine(entry.PlainRegionSizeInMediaUnits, " Plain region size, in media units"); + builder.AppendLine(entry.LogoRegionOffsetInMediaUnits, " Logo region offset, in media units"); + builder.AppendLine(entry.LogoRegionSizeInMediaUnits, " Logo region size, in media units"); + builder.AppendLine(entry.ExeFSOffsetInMediaUnits, " ExeFS offset, in media units"); + builder.AppendLine(entry.ExeFSSizeInMediaUnits, " ExeFS size, in media units"); + builder.AppendLine(entry.ExeFSHashRegionSizeInMediaUnits, " ExeFS hash region size, in media units"); + builder.AppendLine(entry.Reserved3, " Reserved 3"); + builder.AppendLine(entry.RomFSOffsetInMediaUnits, " RomFS offset, in media units"); + builder.AppendLine(entry.RomFSSizeInMediaUnits, " RomFS size, in media units"); + builder.AppendLine(entry.RomFSHashRegionSizeInMediaUnits, " RomFS hash region size, in media units"); + builder.AppendLine(entry.Reserved4, " Reserved 4"); + builder.AppendLine(entry.ExeFSSuperblockHash, " ExeFS superblock SHA-256 hash"); + builder.AppendLine(entry.RomFSSuperblockHash, " RomFS superblock SHA-256 hash"); + } + } + builder.AppendLine(); + } + +#if NET48 + private static void Print(StringBuilder builder, NCCHExtendedHeader[] entries) +#else + private static void Print(StringBuilder builder, NCCHExtendedHeader?[]? entries) +#endif + { + builder.AppendLine(" NCCH Extended Header Information:"); + builder.AppendLine(" -------------------------"); + if (entries == null || entries.Length == 0) + { + builder.AppendLine(" No NCCH extended headers"); + builder.AppendLine(); + return; + } + + for (int i = 0; i < entries.Length; i++) + { + var entry = entries[i]; + builder.AppendLine($" NCCH Extended Header {i}"); + if (entry == null) + { + builder.AppendLine(" Unrecognized partition data, no data can be parsed"); + continue; + } + + builder.AppendLine(" System control info:"); + if (entry.SCI == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.SCI.ApplicationTitle, " Application title"); + builder.AppendLine(entry.SCI.Reserved1, " Reserved 1"); + builder.AppendLine(entry.SCI.Flag, " Flag"); + builder.AppendLine(entry.SCI.RemasterVersion, " Remaster version"); + + builder.AppendLine(" Text code set info:"); + if (entry.SCI.TextCodeSetInfo == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.SCI.TextCodeSetInfo.Address, " Address"); + builder.AppendLine(entry.SCI.TextCodeSetInfo.PhysicalRegionSizeInPages, " Physical region size (in page-multiples)"); + builder.AppendLine(entry.SCI.TextCodeSetInfo.SizeInBytes, " Size (in bytes)"); + } + + builder.AppendLine(entry.SCI.StackSize, " Stack size"); + + builder.AppendLine(" Read-only code set info:"); + if (entry.SCI.ReadOnlyCodeSetInfo == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.SCI.ReadOnlyCodeSetInfo.Address, " Address"); + builder.AppendLine(entry.SCI.ReadOnlyCodeSetInfo.PhysicalRegionSizeInPages, " Physical region size (in page-multiples)"); + builder.AppendLine(entry.SCI.ReadOnlyCodeSetInfo.SizeInBytes, " Size (in bytes)"); + } + + builder.AppendLine(entry.SCI.Reserved2, " Reserved 2"); + + builder.AppendLine(" Data code set info:"); + if (entry.SCI.DataCodeSetInfo == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.SCI.DataCodeSetInfo.Address, " Address"); + builder.AppendLine(entry.SCI.DataCodeSetInfo.PhysicalRegionSizeInPages, " Physical region size (in page-multiples)"); + builder.AppendLine(entry.SCI.DataCodeSetInfo.SizeInBytes, " Size (in bytes)"); + } + + builder.AppendLine(entry.SCI.BSSSize, " BSS size"); + builder.AppendLine(entry.SCI.DependencyModuleList, " Dependency module list"); + + builder.AppendLine(" System info:"); + if (entry.SCI.SystemInfo == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.SCI.SystemInfo.SaveDataSize, " SaveData size"); + builder.AppendLine(entry.SCI.SystemInfo.JumpID, " Jump ID"); + builder.AppendLine(entry.SCI.SystemInfo.Reserved, " Reserved"); + } + } + + builder.AppendLine(" Access control info:"); + if (entry.ACI == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(" ARM11 local system capabilities:"); + if (entry.ACI.ARM11LocalSystemCapabilities == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.ProgramID, " Program ID"); + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.CoreVersion, " Core version"); + builder.AppendLine($" Flag 1: {entry.ACI.ARM11LocalSystemCapabilities.Flag1} (0x{entry.ACI.ARM11LocalSystemCapabilities.Flag1:X})"); + builder.AppendLine($" Flag 2: {entry.ACI.ARM11LocalSystemCapabilities.Flag2} (0x{entry.ACI.ARM11LocalSystemCapabilities.Flag2:X})"); + builder.AppendLine($" Flag 0: {entry.ACI.ARM11LocalSystemCapabilities.Flag0} (0x{entry.ACI.ARM11LocalSystemCapabilities.Flag0:X})"); + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.Priority, " Priority"); + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.ResourceLimitDescriptors, " Resource limit descriptors"); + builder.AppendLine(" Storage info:"); + if (entry.ACI.ARM11LocalSystemCapabilities.StorageInfo == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID, " Extdata ID"); + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs, " System savedata IDs"); + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs, " Storage accessible unique IDs"); + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo, " File system access info"); + builder.AppendLine($" Other attributes: {entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes} (0x{entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes:X})"); + } + + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.ServiceAccessControl, " Service access control"); + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl, " Extended service access control"); + builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.Reserved, " Reserved"); + builder.AppendLine($" Resource limit cateogry: {entry.ACI.ARM11LocalSystemCapabilities.ResourceLimitCategory} (0x{entry.ACI.ARM11LocalSystemCapabilities.ResourceLimitCategory:X})"); + } + + builder.AppendLine(" ARM11 kernel capabilities:"); + if (entry.ACI.ARM11KernelCapabilities == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.ACI.ARM11KernelCapabilities.Descriptors, " Descriptors"); + builder.AppendLine(entry.ACI.ARM11KernelCapabilities.Reserved, " Reserved"); + } + + builder.AppendLine(" ARM9 access control:"); + if (entry.ACI.ARM9AccessControl == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.ACI.ARM9AccessControl.Descriptors, " Descriptors"); + builder.AppendLine(entry.ACI.ARM9AccessControl.DescriptorVersion, " Descriptor version"); + } + + builder.AppendLine(entry.AccessDescSignature, " AccessDec signature (RSA-2048-SHA256)"); + builder.AppendLine(entry.NCCHHDRPublicKey, " NCCH HDR RSA-2048 public key"); + } + + builder.AppendLine(" Access control info (for limitations of first ACI):"); + if (entry.ACIForLimitations == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(" ARM11 local system capabilities:"); + if (entry.ACIForLimitations.ARM11LocalSystemCapabilities == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.ProgramID, " Program ID"); + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.CoreVersion, " Core version"); + builder.AppendLine($" Flag 1: {entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag1} (0x{entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag1:X})"); + builder.AppendLine($" Flag 2: {entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag2} (0x{entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag2:X})"); + builder.AppendLine($" Flag 0: {entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag0} (0x{entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag0:X})"); + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.Priority, " Priority"); + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitDescriptors, " Resource limit descriptors"); + + builder.AppendLine(" Storage info:"); + if (entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID, " Extdata ID"); + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs, " System savedata IDs"); + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs, " Storage accessible unique IDs"); + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo, " File system access info"); + builder.AppendLine($" Other attributes: {entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes} (0x{entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes:X})"); + } + + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.ServiceAccessControl, " Service access control"); + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl, " Extended service access control"); + builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.Reserved, " Reserved"); + builder.AppendLine($" Resource limit cateogry: {entry.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitCategory} (0x{entry.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitCategory:X})"); + } + + builder.AppendLine(" ARM11 kernel capabilities:"); + if (entry.ACIForLimitations.ARM11KernelCapabilities == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.ACIForLimitations.ARM11KernelCapabilities.Descriptors, " Descriptors"); + builder.AppendLine(entry.ACIForLimitations.ARM11KernelCapabilities.Reserved, " Reserved"); + } + + builder.AppendLine(" ARM9 access control:"); + if (entry.ACIForLimitations.ARM9AccessControl == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine(entry.ACIForLimitations.ARM9AccessControl.Descriptors, " Descriptors"); + builder.AppendLine(entry.ACIForLimitations.ARM9AccessControl.DescriptorVersion, " Descriptor version"); + } + } + } + builder.AppendLine(); + } + +#if NET48 + private static void Print(StringBuilder builder, ExeFSHeader[] entries) +#else + private static void Print(StringBuilder builder, ExeFSHeader?[]? entries) +#endif + { + builder.AppendLine(" ExeFS Header Information:"); + builder.AppendLine(" -------------------------"); + if (entries == null || entries.Length == 0) + { + builder.AppendLine(" No ExeFS headers"); + builder.AppendLine(); + return; + } + + for (int i = 0; i < entries.Length; i++) + { + var entry = entries[i]; + builder.AppendLine($" ExeFS Header {i}"); + if (entry == null) + { + builder.AppendLine(" Unrecognized partition data, no data can be parsed"); + continue; + } + + builder.AppendLine(" File headers:"); + if (entry.FileHeaders == null || entry.FileHeaders.Length == 0) + { + builder.AppendLine(" No file headers"); + } + else + { + for (int j = 0; j < entry.FileHeaders.Length; j++) + { + var fileHeader = entry.FileHeaders[j]; + builder.AppendLine($" File Header {j}"); + if (fileHeader == null) + { + builder.AppendLine(" [NULL]"); + continue; + } + + builder.AppendLine(fileHeader.FileName, " File name"); + builder.AppendLine(fileHeader.FileOffset, " File offset"); + builder.AppendLine(fileHeader.FileSize, " File size"); + } + } + + builder.AppendLine(entry.Reserved, " Reserved"); + + builder.AppendLine(" File hashes:"); + if (entry.FileHashes == null || entry.FileHashes.Length == 0) + { + builder.AppendLine(" No file hashes"); + } + else + { + for (int j = 0; j < entry.FileHashes.Length; j++) + { + var fileHash = entry.FileHashes[j]; + builder.AppendLine($" File Hash {j}"); + if (fileHash == null) + { + builder.AppendLine(" [NULL]"); + continue; + } + + builder.AppendLine(fileHash, " SHA-256"); + } + } + } + builder.AppendLine(); + } + +#if NET48 + private static void Print(StringBuilder builder, RomFSHeader[] entries) +#else + private static void Print(StringBuilder builder, RomFSHeader?[]? entries) +#endif + { + builder.AppendLine(" RomFS Header Information:"); + builder.AppendLine(" -------------------------"); + if (entries == null || entries.Length == 0) + { + builder.AppendLine(" No RomFS headers"); + builder.AppendLine(); + return; + } + + for (int i = 0; i < entries.Length; i++) + { + var romFSHeader = entries[i]; + builder.AppendLine($" RomFS Header {i}"); + if (romFSHeader == null) + { + builder.AppendLine(" Unrecognized RomFS data, no data can be parsed"); + continue; + } + + builder.AppendLine(romFSHeader.MagicString, " Magic string"); + builder.AppendLine(romFSHeader.MagicNumber, " Magic number"); + builder.AppendLine(romFSHeader.MasterHashSize, " Master hash size"); + builder.AppendLine(romFSHeader.Level1LogicalOffset, " Level 1 logical offset"); + builder.AppendLine(romFSHeader.Level1HashdataSize, " Level 1 hashdata size"); + builder.AppendLine(romFSHeader.Level1BlockSizeLog2, " Level 1 block size"); + builder.AppendLine(romFSHeader.Reserved1, " Reserved 1"); + builder.AppendLine(romFSHeader.Level2LogicalOffset, " Level 2 logical offset"); + builder.AppendLine(romFSHeader.Level2HashdataSize, " Level 2 hashdata size"); + builder.AppendLine(romFSHeader.Level2BlockSizeLog2, " Level 2 block size"); + builder.AppendLine(romFSHeader.Reserved2, " Reserved 2"); + builder.AppendLine(romFSHeader.Level3LogicalOffset, " Level 3 logical offset"); + builder.AppendLine(romFSHeader.Level3HashdataSize, " Level 3 hashdata size"); + builder.AppendLine(romFSHeader.Level3BlockSizeLog2, " Level 3 block size"); + builder.AppendLine(romFSHeader.Reserved3, " Reserved 3"); + builder.AppendLine(romFSHeader.Reserved4, " Reserved 4"); + builder.AppendLine(romFSHeader.OptionalInfoSize, " Optional info size"); + } + builder.AppendLine(); + } + } +} \ No newline at end of file diff --git a/BinaryObjectScanner.Wrappers/N3DS.cs b/BinaryObjectScanner.Wrappers/N3DS.cs index 5eb6d588..0a11765c 100644 --- a/BinaryObjectScanner.Wrappers/N3DS.cs +++ b/BinaryObjectScanner.Wrappers/N3DS.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Text; @@ -511,644 +510,10 @@ namespace BinaryObjectScanner.Wrappers public override StringBuilder PrettyPrint() { StringBuilder builder = new StringBuilder(); - - builder.AppendLine("3DS Cart Information:"); - builder.AppendLine("-------------------------"); - builder.AppendLine(); - - PrintNCSDHeader(builder); - PrintCardInfoHeader(builder); - PrintDevelopmentCardInfoHeader(builder); - PrintPartitions(builder); - PrintExtendedHeaders(builder); - PrintExeFSHeaders(builder); - PrintRomFSHeaders(builder); - + Printing.N3DS.Print(builder, _model); return builder; } - /// - /// Print NCSD header information - /// - /// StringBuilder to append information to - private void PrintNCSDHeader(StringBuilder builder) - { - builder.AppendLine(" NCSD Header Information:"); - builder.AppendLine(" -------------------------"); - builder.AppendLine($" RSA-2048 SHA-256 signature: {(RSA2048Signature == null ? "[NULL]" : BitConverter.ToString(RSA2048Signature).Replace('-', ' '))}"); - builder.AppendLine($" Magic number: {MagicNumber} (0x{MagicNumber:X})"); - builder.AppendLine($" Image size in media units: {ImageSizeInMediaUnits} (0x{ImageSizeInMediaUnits:X})"); - builder.AppendLine($" Media ID: {(MediaId == null ? "[NULL]" : BitConverter.ToString(MediaId).Replace('-', ' '))}"); - builder.AppendLine($" Partitions filesystem type: {PartitionsFSType} (0x{PartitionsFSType:X})"); - builder.AppendLine($" Partitions crypt type: {(PartitionsCryptType == null ? "[NULL]" : BitConverter.ToString(PartitionsCryptType).Replace('-', ' '))}"); - builder.AppendLine(); - - builder.AppendLine($" Partition table:"); - builder.AppendLine(" -------------------------"); - if (PartitionsTable == null || PartitionsTable.Length == 0) - { - builder.AppendLine(" No partition table entries"); - } - else - { - for (int i = 0; i < PartitionsTable.Length; i++) - { - var partitionTableEntry = PartitionsTable[i]; - builder.AppendLine($" Partition table entry {i}"); - if (partitionTableEntry == null) - { - builder.AppendLine(" [NULL]"); - continue; - } - - builder.AppendLine($" Offset: {partitionTableEntry.Offset} (0x{partitionTableEntry.Offset:X})"); - builder.AppendLine($" Length: {partitionTableEntry.Length} (0x{partitionTableEntry.Length:X})"); - } - } - builder.AppendLine(); - - // If we have a cart image - if (PartitionsFSType == SabreTools.Models.N3DS.FilesystemType.Normal || PartitionsFSType == SabreTools.Models.N3DS.FilesystemType.None) - { - builder.AppendLine($" Exheader SHA-256 hash: {(ExheaderHash == null ? "[NULL]" : BitConverter.ToString(ExheaderHash).Replace('-', ' '))}"); - builder.AppendLine($" Additional header size: {AdditionalHeaderSize} (0x{AdditionalHeaderSize:X})"); - builder.AppendLine($" Sector zero offset: {SectorZeroOffset} (0x{SectorZeroOffset:X})"); - builder.AppendLine($" Partition flags: {(PartitionFlags == null ? "[NULL]" : BitConverter.ToString(PartitionFlags).Replace('-', ' '))}"); - builder.AppendLine(); - - builder.AppendLine($" Partition ID table:"); - builder.AppendLine(" -------------------------"); - if (PartitionIdTable == null || PartitionIdTable.Length == 0) - { - builder.AppendLine(" No partition ID table entries"); - } - else - { - for (int i = 0; i < PartitionIdTable.Length; i++) - { - builder.AppendLine($" Partition {i} ID: {PartitionIdTable[i]} (0x{PartitionIdTable[i]:X})"); - } - } - builder.AppendLine(); - - builder.AppendLine($" Reserved 1: {(Reserved1 == null ? "[NULL]" : BitConverter.ToString(Reserved1).Replace('-', ' '))}"); - builder.AppendLine($" Reserved 2: {(Reserved2 == null ? "[NULL]" : BitConverter.ToString(Reserved2).Replace('-', ' '))}"); - builder.AppendLine($" Firmware update byte 1: {FirmUpdateByte1} (0x{FirmUpdateByte1:X})"); - builder.AppendLine($" Firmware update byte 2: {FirmUpdateByte2} (0x{FirmUpdateByte2:X})"); - } - - // If we have a firmware image - else if (PartitionsFSType == SabreTools.Models.N3DS.FilesystemType.FIRM) - { - builder.AppendLine($" Unknown: {(Unknown == null ? "[NULL]" : BitConverter.ToString(Unknown).Replace('-', ' '))}"); - builder.AppendLine($" Encrypted MBR: {(EncryptedMBR == null ? "[NULL]" : BitConverter.ToString(EncryptedMBR).Replace('-', ' '))}"); - } - - builder.AppendLine(); - } - - /// - /// Print card info header information - /// - /// StringBuilder to append information to - private void PrintCardInfoHeader(StringBuilder builder) - { - builder.AppendLine(" Card Info Header Information:"); - builder.AppendLine(" -------------------------"); - builder.AppendLine($" Writable address in media units: {CIH_WritableAddressMediaUnits} (0x{CIH_WritableAddressMediaUnits:X})"); - builder.AppendLine($" Card info bitmask: {CIH_CardInfoBitmask} (0x{CIH_CardInfoBitmask:X})"); - builder.AppendLine($" Reserved 1: {(CIH_Reserved1 == null ? "[NULL]" : BitConverter.ToString(CIH_Reserved1).Replace('-', ' '))}"); - builder.AppendLine($" Filled size of cartridge: {CIH_FilledSize} (0x{CIH_FilledSize:X})"); - builder.AppendLine($" Reserved 2: {(CIH_Reserved2 == null ? "[NULL]" : BitConverter.ToString(CIH_Reserved2).Replace('-', ' '))}"); - builder.AppendLine($" Title version: {CIH_TitleVersion} (0x{CIH_TitleVersion:X})"); - builder.AppendLine($" Card revision: {CIH_CardRevision} (0x{CIH_CardRevision:X})"); - builder.AppendLine($" Reserved 3: {(CIH_Reserved3 == null ? "[NULL]" : BitConverter.ToString(CIH_Reserved3).Replace('-', ' '))}"); - builder.AppendLine($" Title ID of CVer in included update partition: {(CIH_CVerTitleID == null ? "[NULL]" : BitConverter.ToString(CIH_CVerTitleID).Replace('-', ' '))}"); - builder.AppendLine($" Version number of CVer in included update partition: {CIH_CVerVersionNumber} (0x{CIH_CVerVersionNumber:X})"); - builder.AppendLine($" Reserved 4: {(CIH_Reserved4 == null ? "[NULL]" : BitConverter.ToString(CIH_Reserved4).Replace('-', ' '))}"); - builder.AppendLine(); - } - - /// - /// Print development card info header information - /// - /// StringBuilder to append information to - private void PrintDevelopmentCardInfoHeader(StringBuilder builder) - { - builder.AppendLine(" Development Card Info Header Information:"); - builder.AppendLine(" -------------------------"); - if (_model.DevelopmentCardInfoHeader == null) - { - builder.AppendLine(" No development card info header"); - } - else - { - builder.AppendLine(); - builder.AppendLine(" Initial Data:"); - builder.AppendLine(" -------------------------"); - builder.AppendLine($" Card seed keyY: {(DCIH_ID_CardSeedKeyY == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_CardSeedKeyY).Replace('-', ' '))}"); - builder.AppendLine($" Encrypted card seed: {(DCIH_ID_EncryptedCardSeed == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_EncryptedCardSeed).Replace('-', ' '))}"); - builder.AppendLine($" Card seed AES-MAC: {(DCIH_ID_CardSeedAESMAC == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_CardSeedAESMAC).Replace('-', ' '))}"); - builder.AppendLine($" Card seed nonce: {(DCIH_ID_CardSeedNonce == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_CardSeedNonce).Replace('-', ' '))}"); - builder.AppendLine($" Reserved: {(DCIH_ID_Reserved == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_Reserved).Replace('-', ' '))}"); - builder.AppendLine(); - - builder.AppendLine(" Backup Header:"); - builder.AppendLine(" -------------------------"); - if (DCIH_ID_BackupHeader == null) - { - builder.AppendLine(" No backup header"); - } - else - { - builder.AppendLine($" Magic ID: {DCIH_ID_BackupHeader.MagicID} (0x{DCIH_ID_BackupHeader.MagicID:X})"); - builder.AppendLine($" Content size in media units: {DCIH_ID_BackupHeader.ContentSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.ContentSizeInMediaUnits:X})"); - builder.AppendLine($" Partition ID: {DCIH_ID_BackupHeader.PartitionId} (0x{DCIH_ID_BackupHeader.PartitionId:X})"); - builder.AppendLine($" Maker code: {DCIH_ID_BackupHeader.MakerCode} (0x{DCIH_ID_BackupHeader.MakerCode:X})"); - builder.AppendLine($" Version: {DCIH_ID_BackupHeader.Version} (0x{DCIH_ID_BackupHeader.Version:X})"); - builder.AppendLine($" Verification hash: {DCIH_ID_BackupHeader.VerificationHash} (0x{DCIH_ID_BackupHeader.VerificationHash:X})"); - builder.AppendLine($" Program ID: {(DCIH_ID_BackupHeader.ProgramId == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.ProgramId).Replace('-', ' '))}"); - builder.AppendLine($" Reserved 1: {(DCIH_ID_BackupHeader.Reserved1 == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.Reserved1).Replace('-', ' '))}"); - builder.AppendLine($" Logo region SHA-256 hash: {(DCIH_ID_BackupHeader.LogoRegionHash == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.LogoRegionHash).Replace('-', ' '))}"); - builder.AppendLine($" Product code: {DCIH_ID_BackupHeader.ProductCode} (0x{DCIH_ID_BackupHeader.ProductCode:X})"); - builder.AppendLine($" Extended header SHA-256 hash: {(DCIH_ID_BackupHeader.ExtendedHeaderHash == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.ExtendedHeaderHash).Replace('-', ' '))}"); - builder.AppendLine($" Extended header size in bytes: {DCIH_ID_BackupHeader.ExtendedHeaderSizeInBytes} (0x{DCIH_ID_BackupHeader.ExtendedHeaderSizeInBytes:X})"); - builder.AppendLine($" Reserved 2: {(DCIH_ID_BackupHeader.Reserved2 == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.Reserved2).Replace('-', ' '))}"); - builder.AppendLine($" Flags: {DCIH_ID_BackupHeader.Flags} (0x{DCIH_ID_BackupHeader.Flags:X})"); - builder.AppendLine($" Plain region offset, in media units: {DCIH_ID_BackupHeader.PlainRegionOffsetInMediaUnits} (0x{DCIH_ID_BackupHeader.PlainRegionOffsetInMediaUnits:X})"); - builder.AppendLine($" Plain region size, in media units: {DCIH_ID_BackupHeader.PlainRegionSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.PlainRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Logo region offset, in media units: {DCIH_ID_BackupHeader.LogoRegionOffsetInMediaUnits} (0x{DCIH_ID_BackupHeader.LogoRegionOffsetInMediaUnits:X})"); - builder.AppendLine($" Logo region size, in media units: {DCIH_ID_BackupHeader.LogoRegionSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.LogoRegionSizeInMediaUnits:X})"); - builder.AppendLine($" ExeFS offset, in media units: {DCIH_ID_BackupHeader.ExeFSOffsetInMediaUnits} (0x{DCIH_ID_BackupHeader.ExeFSOffsetInMediaUnits:X})"); - builder.AppendLine($" ExeFS size, in media units: {DCIH_ID_BackupHeader.ExeFSSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.ExeFSSizeInMediaUnits:X})"); - builder.AppendLine($" ExeFS hash region size, in media units: {DCIH_ID_BackupHeader.ExeFSHashRegionSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.ExeFSHashRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Reserved 3: {(DCIH_ID_BackupHeader.Reserved3 == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.Reserved3).Replace('-', ' '))}"); - builder.AppendLine($" RomFS offset, in media units: {DCIH_ID_BackupHeader.RomFSOffsetInMediaUnits} (0x{DCIH_ID_BackupHeader.RomFSOffsetInMediaUnits:X})"); - builder.AppendLine($" RomFS size, in media units: {DCIH_ID_BackupHeader.RomFSSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.RomFSSizeInMediaUnits:X})"); - builder.AppendLine($" RomFS hash region size, in media units: {DCIH_ID_BackupHeader.RomFSHashRegionSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.RomFSHashRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Reserved 4: {(DCIH_ID_BackupHeader.Reserved4 == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.Reserved4).Replace('-', ' '))}"); - builder.AppendLine($" ExeFS superblock SHA-256 hash: {(DCIH_ID_BackupHeader.ExeFSSuperblockHash == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.ExeFSSuperblockHash).Replace('-', ' '))}"); - builder.AppendLine($" RomFS superblock SHA-256 hash: {(DCIH_ID_BackupHeader.RomFSSuperblockHash == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.RomFSSuperblockHash).Replace('-', ' '))}"); - } - builder.AppendLine(); - - builder.AppendLine($" Card device reserved 1: {(DCIH_CardDeviceReserved1 == null ? "[NULL]" : BitConverter.ToString(DCIH_CardDeviceReserved1).Replace('-', ' '))}"); - builder.AppendLine($" Title key: {(DCIH_TitleKey == null ? "[NULL]" : BitConverter.ToString(DCIH_TitleKey).Replace('-', ' '))}"); - builder.AppendLine($" Card device reserved 2: {(DCIH_CardDeviceReserved2 == null ? "[NULL]" : BitConverter.ToString(DCIH_CardDeviceReserved2).Replace('-', ' '))}"); - builder.AppendLine(); - - builder.AppendLine(" Test Data:"); - builder.AppendLine(" -------------------------"); - builder.AppendLine($" Signature: {(DCIH_TD_Signature == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_Signature).Replace('-', ' '))}"); - builder.AppendLine($" Ascending byte sequence: {(DCIH_TD_AscendingByteSequence == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_AscendingByteSequence).Replace('-', ' '))}"); - builder.AppendLine($" Descending byte sequence: {(DCIH_TD_DescendingByteSequence == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_DescendingByteSequence).Replace('-', ' '))}"); - builder.AppendLine($" Filled with 00: {(DCIH_TD_Filled00 == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_Filled00).Replace('-', ' '))}"); - builder.AppendLine($" Filled with FF: {(DCIH_TD_FilledFF == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_FilledFF).Replace('-', ' '))}"); - builder.AppendLine($" Filled with 0F: {(DCIH_TD_Filled0F == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_Filled0F).Replace('-', ' '))}"); - builder.AppendLine($" Filled with F0: {(DCIH_TD_FilledF0 == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_FilledF0).Replace('-', ' '))}"); - builder.AppendLine($" Filled with 55: {(DCIH_TD_Filled55 == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_Filled55).Replace('-', ' '))}"); - builder.AppendLine($" Filled with AA: {(DCIH_TD_FilledAA == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_FilledAA).Replace('-', ' '))}"); - builder.AppendLine($" Final byte: {DCIH_TD_FinalByte}"); - } - - builder.AppendLine(); - } - - /// - /// Print NCCH partition header information - /// - /// StringBuilder to append information to - private void PrintPartitions(StringBuilder builder) - { - builder.AppendLine(" NCCH Partition Header Information:"); - builder.AppendLine(" -------------------------"); - if (Partitions == null || Partitions.Length == 0) - { - builder.AppendLine(" No NCCH partition headers"); - } - else - { - for (int i = 0; i < Partitions.Length; i++) - { - var partitionHeader = Partitions[i]; - builder.AppendLine($" NCCH Partition Header {i}"); - if (partitionHeader == null) - { - builder.AppendLine($" [NULL]"); - continue; - } - - if (partitionHeader.MagicID == string.Empty) - { - builder.AppendLine($" Empty partition, no data can be parsed"); - } - else if (partitionHeader.MagicID != SabreTools.Models.N3DS.Constants.NCCHMagicNumber) - { - builder.AppendLine($" Unrecognized partition data, no data can be parsed"); - } - else - { - builder.AppendLine($" RSA-2048 SHA-256 signature: {(partitionHeader.RSA2048Signature == null ? "[NULL]" : BitConverter.ToString(partitionHeader.RSA2048Signature).Replace('-', ' '))}"); - builder.AppendLine($" Magic ID: {partitionHeader.MagicID} (0x{partitionHeader.MagicID:X})"); - builder.AppendLine($" Content size in media units: {partitionHeader.ContentSizeInMediaUnits} (0x{partitionHeader.ContentSizeInMediaUnits:X})"); - builder.AppendLine($" Partition ID: {partitionHeader.PartitionId} (0x{partitionHeader.PartitionId:X})"); - builder.AppendLine($" Maker code: {partitionHeader.MakerCode} (0x{partitionHeader.MakerCode:X})"); - builder.AppendLine($" Version: {partitionHeader.Version} (0x{partitionHeader.Version:X})"); - builder.AppendLine($" Verification hash: {partitionHeader.VerificationHash} (0x{partitionHeader.VerificationHash:X})"); - builder.AppendLine($" Program ID: {(partitionHeader.ProgramId == null ? "[NULL]" : BitConverter.ToString(partitionHeader.ProgramId).Replace('-', ' '))}"); - builder.AppendLine($" Reserved 1: {(partitionHeader.Reserved1 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved1).Replace('-', ' '))}"); - builder.AppendLine($" Logo region SHA-256 hash: {(partitionHeader.LogoRegionHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.LogoRegionHash).Replace('-', ' '))}"); - builder.AppendLine($" Product code: {partitionHeader.ProductCode} (0x{partitionHeader.ProductCode:X})"); - builder.AppendLine($" Extended header SHA-256 hash: {(partitionHeader.ExtendedHeaderHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.ExtendedHeaderHash).Replace('-', ' '))}"); - builder.AppendLine($" Extended header size in bytes: {partitionHeader.ExtendedHeaderSizeInBytes} (0x{partitionHeader.ExtendedHeaderSizeInBytes:X})"); - builder.AppendLine($" Reserved 2: {(partitionHeader.Reserved2 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved2).Replace('-', ' '))}"); - builder.AppendLine(" Flags:"); - if (partitionHeader.Flags == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Reserved 0: {partitionHeader.Flags.Reserved0} (0x{partitionHeader.Flags.Reserved0:X})"); - builder.AppendLine($" Reserved 1: {partitionHeader.Flags.Reserved1} (0x{partitionHeader.Flags.Reserved1:X})"); - builder.AppendLine($" Reserved 2: {partitionHeader.Flags.Reserved2} (0x{partitionHeader.Flags.Reserved2:X})"); - builder.AppendLine($" Crypto method: {partitionHeader.Flags.CryptoMethod} (0x{partitionHeader.Flags.CryptoMethod:X})"); - builder.AppendLine($" Content platform: {partitionHeader.Flags.ContentPlatform} (0x{partitionHeader.Flags.ContentPlatform:X})"); - builder.AppendLine($" Content type: {partitionHeader.Flags.MediaPlatformIndex} (0x{partitionHeader.Flags.MediaPlatformIndex:X})"); - builder.AppendLine($" Content unit size: {partitionHeader.Flags.ContentUnitSize} (0x{partitionHeader.Flags.ContentUnitSize:X})"); - builder.AppendLine($" Bitmasks: {partitionHeader.Flags.BitMasks} (0x{partitionHeader.Flags.BitMasks:X})"); - } - builder.AppendLine($" Plain region offset, in media units: {partitionHeader.PlainRegionOffsetInMediaUnits} (0x{partitionHeader.PlainRegionOffsetInMediaUnits:X})"); - builder.AppendLine($" Plain region size, in media units: {partitionHeader.PlainRegionSizeInMediaUnits} (0x{partitionHeader.PlainRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Logo region offset, in media units: {partitionHeader.LogoRegionOffsetInMediaUnits} (0x{partitionHeader.LogoRegionOffsetInMediaUnits:X})"); - builder.AppendLine($" Logo region size, in media units: {partitionHeader.LogoRegionSizeInMediaUnits} (0x{partitionHeader.LogoRegionSizeInMediaUnits:X})"); - builder.AppendLine($" ExeFS offset, in media units: {partitionHeader.ExeFSOffsetInMediaUnits} (0x{partitionHeader.ExeFSOffsetInMediaUnits:X})"); - builder.AppendLine($" ExeFS size, in media units: {partitionHeader.ExeFSSizeInMediaUnits} (0x{partitionHeader.ExeFSSizeInMediaUnits:X})"); - builder.AppendLine($" ExeFS hash region size, in media units: {partitionHeader.ExeFSHashRegionSizeInMediaUnits} (0x{partitionHeader.ExeFSHashRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Reserved 3: {(partitionHeader.Reserved3 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved3).Replace('-', ' '))}"); - builder.AppendLine($" RomFS offset, in media units: {partitionHeader.RomFSOffsetInMediaUnits} (0x{partitionHeader.RomFSOffsetInMediaUnits:X})"); - builder.AppendLine($" RomFS size, in media units: {partitionHeader.RomFSSizeInMediaUnits} (0x{partitionHeader.RomFSSizeInMediaUnits:X})"); - builder.AppendLine($" RomFS hash region size, in media units: {partitionHeader.RomFSHashRegionSizeInMediaUnits} (0x{partitionHeader.RomFSHashRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Reserved 4: {(partitionHeader.Reserved4 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved4).Replace('-', ' '))}"); - builder.AppendLine($" ExeFS superblock SHA-256 hash: {(partitionHeader.ExeFSSuperblockHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.ExeFSSuperblockHash).Replace('-', ' '))}"); - builder.AppendLine($" RomFS superblock SHA-256 hash: {(partitionHeader.RomFSSuperblockHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.RomFSSuperblockHash).Replace('-', ' '))}"); - } - } - } - builder.AppendLine(); - } - - /// - /// Print NCCH extended header information - /// - /// StringBuilder to append information to - private void PrintExtendedHeaders(StringBuilder builder) - { - builder.AppendLine(" NCCH Extended Header Information:"); - builder.AppendLine(" -------------------------"); - if (ExtendedHeaders == null || ExtendedHeaders.Length == 0) - { - builder.AppendLine(" No NCCH extended headers"); - } - else - { - for (int i = 0; i < ExtendedHeaders.Length; i++) - { - var extendedHeader = ExtendedHeaders[i]; - builder.AppendLine($" NCCH Extended Header {i}"); - if (extendedHeader == null) - { - builder.AppendLine($" Unrecognized partition data, no data can be parsed"); - } - else - { - builder.AppendLine($" System control info:"); - if (extendedHeader.SCI == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Application title: {extendedHeader.SCI.ApplicationTitle}"); - builder.AppendLine($" Reserved 1: {(extendedHeader.SCI.Reserved1 == null ? "[NULL]" : BitConverter.ToString(extendedHeader.SCI.Reserved1).Replace('-', ' '))}"); - builder.AppendLine($" Flag: {extendedHeader.SCI.Flag} (0x{extendedHeader.SCI.Flag:X})"); - builder.AppendLine($" Remaster version: {extendedHeader.SCI.RemasterVersion} (0x{extendedHeader.SCI.RemasterVersion:X})"); - - builder.AppendLine($" Text code set info:"); - if (extendedHeader.SCI.TextCodeSetInfo == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Address: {extendedHeader.SCI.TextCodeSetInfo.Address} (0x{extendedHeader.SCI.TextCodeSetInfo.Address:X})"); - builder.AppendLine($" Physical region size (in page-multiples): {extendedHeader.SCI.TextCodeSetInfo.PhysicalRegionSizeInPages} (0x{extendedHeader.SCI.TextCodeSetInfo.PhysicalRegionSizeInPages:X})"); - builder.AppendLine($" Size (in bytes): {extendedHeader.SCI.TextCodeSetInfo.SizeInBytes} (0x{extendedHeader.SCI.TextCodeSetInfo.SizeInBytes:X})"); - } - - builder.AppendLine($" Stack size: {extendedHeader.SCI.StackSize} (0x{extendedHeader.SCI.StackSize:X})"); - - builder.AppendLine($" Read-only code set info:"); - if (extendedHeader.SCI.ReadOnlyCodeSetInfo == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Address: {extendedHeader.SCI.ReadOnlyCodeSetInfo.Address} (0x{extendedHeader.SCI.ReadOnlyCodeSetInfo.Address:X})"); - builder.AppendLine($" Physical region size (in page-multiples): {extendedHeader.SCI.ReadOnlyCodeSetInfo.PhysicalRegionSizeInPages} (0x{extendedHeader.SCI.ReadOnlyCodeSetInfo.PhysicalRegionSizeInPages:X})"); - builder.AppendLine($" Size (in bytes): {extendedHeader.SCI.ReadOnlyCodeSetInfo.SizeInBytes} (0x{extendedHeader.SCI.ReadOnlyCodeSetInfo.SizeInBytes:X})"); - } - - builder.AppendLine($" Reserved 2: {(extendedHeader.SCI.Reserved2 == null ? "[NULL]" : BitConverter.ToString(extendedHeader.SCI.Reserved2).Replace('-', ' '))}"); - - builder.AppendLine($" Data code set info:"); - if (extendedHeader.SCI.DataCodeSetInfo == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Address: {extendedHeader.SCI.DataCodeSetInfo.Address} (0x{extendedHeader.SCI.DataCodeSetInfo.Address:X})"); - builder.AppendLine($" Physical region size (in page-multiples): {extendedHeader.SCI.DataCodeSetInfo.PhysicalRegionSizeInPages} (0x{extendedHeader.SCI.DataCodeSetInfo.PhysicalRegionSizeInPages:X})"); - builder.AppendLine($" Size (in bytes): {extendedHeader.SCI.DataCodeSetInfo.SizeInBytes} (0x{extendedHeader.SCI.DataCodeSetInfo.SizeInBytes:X})"); - } - - builder.AppendLine($" BSS size: {extendedHeader.SCI.BSSSize} (0x{extendedHeader.SCI.BSSSize:X})"); - builder.AppendLine($" Dependency module list: {(extendedHeader.SCI.DependencyModuleList == null ? "[NULL]" : string.Join(", ", extendedHeader.SCI.DependencyModuleList))}"); - - builder.AppendLine($" System info:"); - if (extendedHeader.SCI.SystemInfo == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" SaveData size: {extendedHeader.SCI.SystemInfo.SaveDataSize} (0x{extendedHeader.SCI.SystemInfo.SaveDataSize:X})"); - builder.AppendLine($" Jump ID: {extendedHeader.SCI.SystemInfo.JumpID} (0x{extendedHeader.SCI.SystemInfo.JumpID:X})"); - builder.AppendLine($" Reserved: {(extendedHeader.SCI.SystemInfo.Reserved == null ? "[NULL]" : BitConverter.ToString(extendedHeader.SCI.SystemInfo.Reserved).Replace('-', ' '))}"); - } - } - - builder.AppendLine($" Access control info:"); - if (extendedHeader.ACI == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" ARM11 local system capabilities:"); - if (extendedHeader.ACI.ARM11LocalSystemCapabilities == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Program ID: {extendedHeader.ACI.ARM11LocalSystemCapabilities.ProgramID} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.ProgramID:X})"); - builder.AppendLine($" Core version: {extendedHeader.ACI.ARM11LocalSystemCapabilities.CoreVersion} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.CoreVersion:X})"); - builder.AppendLine($" Flag 1: {extendedHeader.ACI.ARM11LocalSystemCapabilities.Flag1} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.Flag1:X})"); - builder.AppendLine($" Flag 2: {extendedHeader.ACI.ARM11LocalSystemCapabilities.Flag2} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.Flag2:X})"); - builder.AppendLine($" Flag 0: {extendedHeader.ACI.ARM11LocalSystemCapabilities.Flag0} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.Flag0:X})"); - builder.AppendLine($" Priority: {extendedHeader.ACI.ARM11LocalSystemCapabilities.Priority} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.Priority:X})"); - builder.AppendLine($" Resource limit descriptors: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.ResourceLimitDescriptors == null ? "[NULL]" : string.Join(", ", extendedHeader.ACI.ARM11LocalSystemCapabilities.ResourceLimitDescriptors))}"); - builder.AppendLine($" Storage info:"); - if (extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Extdata ID: {extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID:X})"); - builder.AppendLine($" System savedata IDs: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs).Replace('-', ' '))}"); - builder.AppendLine($" Storage accessible unique IDs: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs).Replace('-', ' '))}"); - builder.AppendLine($" File system access info: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo).Replace('-', ' '))}"); - builder.AppendLine($" Other attributes: {extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes:X})"); - } - - builder.AppendLine($" Service access control: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.ServiceAccessControl == null ? "[NULL]" : string.Join(", ", extendedHeader.ACI.ARM11LocalSystemCapabilities.ServiceAccessControl))}"); - builder.AppendLine($" Extended service access control: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl == null ? "[NULL]" : string.Join(", ", extendedHeader.ACI.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl))}"); - builder.AppendLine($" Reserved: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.Reserved == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.Reserved).Replace('-', ' '))}"); - builder.AppendLine($" Resource limit cateogry: {extendedHeader.ACI.ARM11LocalSystemCapabilities.ResourceLimitCategory} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.ResourceLimitCategory:X})"); - } - - builder.AppendLine($" ARM11 kernel capabilities:"); - if (extendedHeader.ACI.ARM11KernelCapabilities == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Descriptors: {(extendedHeader.ACI.ARM11KernelCapabilities.Descriptors == null ? "[NULL]" : string.Join(", ", extendedHeader.ACI.ARM11KernelCapabilities.Descriptors))}"); - builder.AppendLine($" Reserved: {(extendedHeader.ACI.ARM11KernelCapabilities.Reserved == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM11KernelCapabilities.Reserved).Replace('-', ' '))}"); - } - - builder.AppendLine($" ARM9 access control:"); - if (extendedHeader.ACI.ARM9AccessControl == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Descriptors: {(extendedHeader.ACI.ARM9AccessControl.Descriptors == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM9AccessControl.Descriptors).Replace('-', ' '))}"); - builder.AppendLine($" Descriptor version: {extendedHeader.ACI.ARM9AccessControl.DescriptorVersion} (0x{extendedHeader.ACI.ARM9AccessControl.DescriptorVersion:X})"); - } - - builder.AppendLine($" AccessDec signature (RSA-2048-SHA256): {(extendedHeader.AccessDescSignature == null ? "[NULL]" : BitConverter.ToString(extendedHeader.AccessDescSignature).Replace('-', ' '))}"); - builder.AppendLine($" NCCH HDR RSA-2048 public key: {(extendedHeader.NCCHHDRPublicKey == null ? "[NULL]" : BitConverter.ToString(extendedHeader.NCCHHDRPublicKey).Replace('-', ' '))}"); - } - - builder.AppendLine($" Access control info (for limitations of first ACI):"); - if (extendedHeader.ACIForLimitations == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" ARM11 local system capabilities:"); - if (extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Program ID: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ProgramID} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ProgramID:X})"); - builder.AppendLine($" Core version: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.CoreVersion} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.CoreVersion:X})"); - builder.AppendLine($" Flag 1: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Flag1} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Flag1:X})"); - builder.AppendLine($" Flag 2: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Flag2} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Flag2:X})"); - builder.AppendLine($" Flag 0: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Flag0} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Flag0:X})"); - builder.AppendLine($" Priority: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Priority} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Priority:X})"); - builder.AppendLine($" Resource limit descriptors: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitDescriptors == null ? "[NULL]" : string.Join(", ", extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitDescriptors))}"); - - builder.AppendLine($" Storage info:"); - if (extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Extdata ID: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID:X})"); - builder.AppendLine($" System savedata IDs: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs).Replace('-', ' '))}"); - builder.AppendLine($" Storage accessible unique IDs: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs).Replace('-', ' '))}"); - builder.AppendLine($" File system access info: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo).Replace('-', ' '))}"); - builder.AppendLine($" Other attributes: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes:X})"); - } - - builder.AppendLine($" Service access control: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ServiceAccessControl == null ? "[NULL]" : string.Join(", ", extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ServiceAccessControl))}"); - builder.AppendLine($" Extended service access control: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl == null ? "[NULL]" : string.Join(", ", extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl))}"); - builder.AppendLine($" Reserved: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Reserved == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Reserved).Replace('-', ' '))}"); - builder.AppendLine($" Resource limit cateogry: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitCategory} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitCategory:X})"); - } - - builder.AppendLine($" ARM11 kernel capabilities:"); - if (extendedHeader.ACIForLimitations.ARM11KernelCapabilities == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Descriptors: {(extendedHeader.ACIForLimitations.ARM11KernelCapabilities.Descriptors == null ? "[NULL]" : string.Join(", ", extendedHeader.ACIForLimitations.ARM11KernelCapabilities.Descriptors))}"); - builder.AppendLine($" Reserved: {(extendedHeader.ACIForLimitations.ARM11KernelCapabilities.Reserved == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11KernelCapabilities.Reserved).Replace('-', ' '))}"); - } - - builder.AppendLine($" ARM9 access control:"); - if (extendedHeader.ACIForLimitations.ARM9AccessControl == null) - { - builder.AppendLine(" [NULL]"); - } - else - { - builder.AppendLine($" Descriptors: {(extendedHeader.ACIForLimitations.ARM9AccessControl.Descriptors == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM9AccessControl.Descriptors).Replace('-', ' '))}"); - builder.AppendLine($" Descriptor version: {extendedHeader.ACIForLimitations.ARM9AccessControl.DescriptorVersion} (0x{extendedHeader.ACIForLimitations.ARM9AccessControl.DescriptorVersion:X})"); - } - } - } - } - } - builder.AppendLine(); - } - - /// - /// Print ExeFS header information - /// - /// StringBuilder to append information to - private void PrintExeFSHeaders(StringBuilder builder) - { - builder.AppendLine(" ExeFS Header Information:"); - builder.AppendLine(" -------------------------"); - if (ExeFSHeaders == null || ExeFSHeaders.Length == 0) - { - builder.AppendLine(" No ExeFS headers"); - } - else - { - for (int i = 0; i < ExeFSHeaders.Length; i++) - { - var exeFSHeader = ExeFSHeaders[i]; - builder.AppendLine($" ExeFS Header {i}"); - if (exeFSHeader == null) - { - builder.AppendLine($" Unrecognized partition data, no data can be parsed"); - } - else - { - builder.AppendLine($" File headers:"); - if (exeFSHeader.FileHeaders == null || exeFSHeader.FileHeaders.Length == 0) - { - builder.AppendLine(" No file headers"); - } - else - { - for (int j = 0; j < exeFSHeader.FileHeaders.Length; j++) - { - var fileHeader = exeFSHeader.FileHeaders[j]; - builder.AppendLine($" File Header {j}"); - if (fileHeader == null) - { - builder.AppendLine(" [NULL]"); - continue; - } - - builder.AppendLine($" File name: {fileHeader.FileName}"); - builder.AppendLine($" File offset: {fileHeader.FileOffset} (0x{fileHeader.FileOffset:X})"); - builder.AppendLine($" File size: {fileHeader.FileSize} (0x{fileHeader.FileSize:X})"); - } - } - - builder.AppendLine($" Reserved: {(exeFSHeader.Reserved == null ? "[NULL]" : BitConverter.ToString(exeFSHeader.Reserved).Replace('-', ' '))}"); - - builder.AppendLine($" File hashes:"); - if (exeFSHeader.FileHashes == null || exeFSHeader.FileHashes.Length == 0) - { - builder.AppendLine(" No file hashes"); - } - else - { - for (int j = 0; j < exeFSHeader.FileHashes.Length; j++) - { - var fileHash = exeFSHeader.FileHashes[j]; - builder.AppendLine($" File Hash {j}"); - if (fileHash == null) - { - builder.AppendLine(" [NULL]"); - continue; - } - - builder.AppendLine($" SHA-256: {(fileHash == null ? "[NULL]" : BitConverter.ToString(fileHash).Replace('-', ' '))}"); - } - } - } - } - } - builder.AppendLine(); - } - - /// - /// Print RomFS header information - /// - /// StringBuilder to append information to - private void PrintRomFSHeaders(StringBuilder builder) - { - builder.AppendLine(" RomFS Header Information:"); - builder.AppendLine(" -------------------------"); - if (RomFSHeaders == null || RomFSHeaders.Length == 0) - { - builder.AppendLine(" No RomFS headers"); - } - else - { - for (int i = 0; i < RomFSHeaders.Length; i++) - { - var romFSHeader = RomFSHeaders[i]; - builder.AppendLine($" RomFS Header {i}"); - if (romFSHeader == null) - { - builder.AppendLine($" Unrecognized RomFS data, no data can be parsed"); - } - else - { - builder.AppendLine($" Magic string: {romFSHeader.MagicString}"); - builder.AppendLine($" Magic number: {romFSHeader.MagicNumber} (0x{romFSHeader.MagicNumber:X})"); - builder.AppendLine($" Master hash size: {romFSHeader.MasterHashSize} (0x{romFSHeader.MasterHashSize:X})"); - builder.AppendLine($" Level 1 logical offset: {romFSHeader.Level1LogicalOffset} (0x{romFSHeader.Level1LogicalOffset:X})"); - builder.AppendLine($" Level 1 hashdata size: {romFSHeader.Level1HashdataSize} (0x{romFSHeader.Level1HashdataSize:X})"); - builder.AppendLine($" Level 1 block size: {romFSHeader.Level1BlockSizeLog2} (0x{romFSHeader.Level1BlockSizeLog2:X})"); - builder.AppendLine($" Reserved 1: {(romFSHeader.Reserved1 == null ? "[NULL]" : BitConverter.ToString(romFSHeader.Reserved1).Replace('-', ' '))}"); - builder.AppendLine($" Level 2 logical offset: {romFSHeader.Level2LogicalOffset} (0x{romFSHeader.Level2LogicalOffset:X})"); - builder.AppendLine($" Level 2 hashdata size: {romFSHeader.Level2HashdataSize} (0x{romFSHeader.Level2HashdataSize:X})"); - builder.AppendLine($" Level 2 block size: {romFSHeader.Level2BlockSizeLog2} (0x{romFSHeader.Level2BlockSizeLog2:X})"); - builder.AppendLine($" Reserved 2: {(romFSHeader.Reserved2 == null ? "[NULL]" : BitConverter.ToString(romFSHeader.Reserved2).Replace('-', ' '))}"); - builder.AppendLine($" Level 3 logical offset: {romFSHeader.Level3LogicalOffset} (0x{romFSHeader.Level3LogicalOffset:X})"); - builder.AppendLine($" Level 3 hashdata size: {romFSHeader.Level3HashdataSize} (0x{romFSHeader.Level3HashdataSize:X})"); - builder.AppendLine($" Level 3 block size: {romFSHeader.Level3BlockSizeLog2} (0x{romFSHeader.Level3BlockSizeLog2:X})"); - builder.AppendLine($" Reserved 3: {(romFSHeader.Reserved3 == null ? "[NULL]" : BitConverter.ToString(romFSHeader.Reserved3).Replace('-', ' '))}"); - builder.AppendLine($" Reserved 4: {(romFSHeader.Reserved4 == null ? "[NULL]" : BitConverter.ToString(romFSHeader.Reserved4).Replace('-', ' '))}"); - builder.AppendLine($" Optional info size: {romFSHeader.OptionalInfoSize} (0x{romFSHeader.OptionalInfoSize:X})"); - } - } - } - builder.AppendLine(); - } - #if NET6_0_OR_GREATER ///