diff --git a/BurnOutSharp.Builders/Nitro.cs b/BurnOutSharp.Builders/Nitro.cs index 242a81d2..f397b066 100644 --- a/BurnOutSharp.Builders/Nitro.cs +++ b/BurnOutSharp.Builders/Nitro.cs @@ -82,6 +82,9 @@ namespace BurnOutSharp.Builders #endregion + // TODO: Read and optionally parse out the other areas + // Look for offsets and lengths in the header pieces + return cart; } @@ -97,12 +100,12 @@ namespace BurnOutSharp.Builders byte[] gameTitle = data.ReadBytes(0x0C); header.GameTitle = Encoding.ASCII.GetString(gameTitle); - header.Gamecode = data.ReadUInt32(); + header.GameCode = data.ReadUInt32(); byte[] makerCode = data.ReadBytes(2); - header.Makercode = Encoding.ASCII.GetString(bytes: makerCode); - header.Unitcode = (Unitcode)data.ReadByteValue(); + header.MakerCode = Encoding.ASCII.GetString(bytes: makerCode); + header.UnitCode = (Unitcode)data.ReadByteValue(); header.EncryptionSeedSelect = data.ReadByteValue(); - header.Devicecapacity = data.ReadByteValue(); + header.DeviceCapacity = data.ReadByteValue(); header.Reserved1 = data.ReadBytes(7); header.GameRevision = data.ReadUInt16(); header.RomVersion = data.ReadByteValue(); @@ -123,31 +126,51 @@ namespace BurnOutSharp.Builders header.ARM9OverlayLength = data.ReadUInt32(); header.ARM7OverlayOffset = data.ReadUInt32(); header.ARM7OverlayLength = data.ReadUInt32(); + header.NormalCardControlRegisterSettings = data.ReadUInt32(); + header.SecureCardControlRegisterSettings = data.ReadUInt32(); + header.IconBannerOffset = data.ReadUInt32(); + header.SecureAreaCRC = data.ReadUInt16(); + header.SecureTransferTimeout = data.ReadUInt16(); + header.ARM9Autoload = data.ReadUInt32(); + header.ARM7Autoload = data.ReadUInt32(); header.SecureDisable = data.ReadBytes(8); header.NTRRegionRomSize = data.ReadUInt32(); header.HeaderSize = data.ReadUInt32(); header.Reserved2 = data.ReadBytes(56); header.NintendoLogo = data.ReadBytes(156); header.NintendoLogoCRC = data.ReadUInt16(); + header.HeaderCRC = data.ReadUInt16(); header.DebuggerReserved = data.ReadBytes(0x20); // If we have a DSi compatible title - if (header.Unitcode == Unitcode.NDSPlusDSi || header.Unitcode == Unitcode.DSi) + if (header.UnitCode == Unitcode.NDSPlusDSi || header.UnitCode == Unitcode.DSi) { - header.GlobalMBK15Settings = data.ReadBytes(20); - header.LocalMBK68SettingsARM9 = data.ReadBytes(12); - header.LocalMBK68SettingsARM7 = data.ReadBytes(12); - header.GlobalMBK9Setting = data.ReadBytes(4); - header.RegionFlags = data.ReadBytes(4); - header.AccessControl = data.ReadBytes(4); - header.ARM7SCFGEXTMask = data.ReadBytes(4); - header.ReservedFlags = data.ReadBytes(4); + header.GlobalMBK15Settings = new uint[5]; + for (int i = 0; i < 5; i++) + { + header.GlobalMBK15Settings[i] = data.ReadUInt32(); + } + header.LocalMBK68SettingsARM9 = new uint[3]; + for (int i = 0; i < 3; i++) + { + header.LocalMBK68SettingsARM9[i] = data.ReadUInt32(); + } + header.LocalMBK68SettingsARM7 = new uint[3]; + for (int i = 0; i < 3; i++) + { + header.LocalMBK68SettingsARM7[i] = data.ReadUInt32(); + } + header.GlobalMBK9Setting = data.ReadUInt32(); + header.RegionFlags = data.ReadUInt32(); + header.AccessControl = data.ReadUInt32(); + header.ARM7SCFGEXTMask = data.ReadUInt32(); + header.ReservedFlags = data.ReadUInt32(); header.ARM9iRomOffset = data.ReadUInt32(); - header.Reserved3 = data.ReadBytes(4); + header.Reserved3 = data.ReadUInt32(); header.ARM9iLoadAddress = data.ReadUInt32(); header.ARM9iSize = data.ReadUInt32(); header.ARM7iRomOffset = data.ReadUInt32(); - header.Reserved4 = data.ReadBytes(4); + header.Reserved4 = data.ReadUInt32(); header.ARM7iLoadAddress = data.ReadUInt32(); header.ARM7iSize = data.ReadUInt32(); header.DigestNTRRegionOffset = data.ReadUInt32(); @@ -161,7 +184,7 @@ namespace BurnOutSharp.Builders header.DigestSectorSize = data.ReadUInt32(); header.DigestBlockSectorCount = data.ReadUInt32(); header.IconBannerSize = data.ReadUInt32(); - header.Unknown1 = data.ReadBytes(4); + header.Unknown1 = data.ReadUInt32(); header.ModcryptArea1Offset = data.ReadUInt32(); header.ModcryptArea1Size = data.ReadUInt32(); header.ModcryptArea2Offset = data.ReadUInt32(); diff --git a/BurnOutSharp.Models/Nitro/Header.cs b/BurnOutSharp.Models/Nitro/Header.cs index 7e73dda3..4ddbfe4c 100644 --- a/BurnOutSharp.Models/Nitro/Header.cs +++ b/BurnOutSharp.Models/Nitro/Header.cs @@ -16,17 +16,17 @@ namespace BurnOutSharp.Models.Nitro /// /// Gamecode /// - public uint Gamecode; + public uint GameCode; /// /// Makercode /// - public string Makercode; + public string MakerCode; /// /// Unitcode /// - public Unitcode Unitcode; + public Unitcode UnitCode; /// /// Encryption seed select (device code. 0 = normal) @@ -36,7 +36,7 @@ namespace BurnOutSharp.Models.Nitro /// /// Devicecapacity /// - public byte Devicecapacity; + public byte DeviceCapacity; /// /// Reserved @@ -141,12 +141,12 @@ namespace BurnOutSharp.Models.Nitro /// /// Normal card control register settings (0x00416657 for OneTimePROM) /// - public byte[] NormalCardControlRegisterSettings; + public uint NormalCardControlRegisterSettings; /// /// Secure card control register settings (0x081808F8 for OneTimePROM) /// - public byte[] SecureCardControlRegisterSettings; + public uint SecureCardControlRegisterSettings; /// /// Icon Banner offset (NDSi same as NDS, but with new extra entries) @@ -166,12 +166,12 @@ namespace BurnOutSharp.Models.Nitro /// /// ARM9 autoload /// - public byte[] ARM9Autoload; + public uint ARM9Autoload; /// /// ARM7 autoload /// - public byte[] ARM7Autoload; + public uint ARM7Autoload; /// /// Secure disable @@ -215,47 +215,48 @@ namespace BurnOutSharp.Models.Nitro #endregion + // TODO: Should this be separated into a distinct file? #region Extended DSi /// /// Global MBK1..MBK5 Settings /// - public byte[] GlobalMBK15Settings; + public uint[] GlobalMBK15Settings; /// /// Local MBK6..MBK8 Settings for ARM9 /// - public byte[] LocalMBK68SettingsARM9; + public uint[] LocalMBK68SettingsARM9; /// /// Local MBK6..MBK8 Settings for ARM7 /// - public byte[] LocalMBK68SettingsARM7; + public uint[] LocalMBK68SettingsARM7; /// /// Global MBK9 Setting /// - public byte[] GlobalMBK9Setting; + public uint GlobalMBK9Setting; /// - /// + /// Region Flags /// - public byte[] RegionFlags; + public uint RegionFlags; /// /// Access control /// - public byte[] AccessControl; + public uint AccessControl; /// /// ARM7 SCFG EXT mask (controls which devices to enable) /// - public byte[] ARM7SCFGEXTMask; + public uint ARM7SCFGEXTMask; /// /// Reserved/flags? When bit2 of byte 0x1bf is set, usage of banner.sav from the title data dir is enabled.(additional banner data) /// - public byte[] ReservedFlags; + public uint ReservedFlags; /// /// ARM9i rom offset @@ -265,7 +266,7 @@ namespace BurnOutSharp.Models.Nitro /// /// Reserved /// - public byte[] Reserved3; + public uint Reserved3; /// /// ARM9i load address @@ -285,7 +286,7 @@ namespace BurnOutSharp.Models.Nitro /// /// Pointer to base address where various structures and parameters are passed to the title - what is that??? /// - public byte[] Reserved4; + public uint Reserved4; /// /// ARM7i load address @@ -355,7 +356,7 @@ namespace BurnOutSharp.Models.Nitro /// /// Unknown (used by DSi) /// - public byte[] Unknown1; + public uint Unknown1; /// /// NTR+TWL region ROM size (total size including DSi area) diff --git a/BurnOutSharp.Wrappers/Nitro.cs b/BurnOutSharp.Wrappers/Nitro.cs new file mode 100644 index 00000000..b8f012fc --- /dev/null +++ b/BurnOutSharp.Wrappers/Nitro.cs @@ -0,0 +1,506 @@ +using System; +using System.IO; + +namespace BurnOutSharp.Wrappers +{ + public class Nitro : WrapperBase + { + #region Pass-Through Properties + + #region Header + + #region Common + + /// + public string GameTitle => _cart.Header.GameTitle; + + /// + public uint GameCode => _cart.Header.GameCode; + + /// + public string MakerCode => _cart.Header.MakerCode; + + /// + public Models.Nitro.Unitcode UnitCode => _cart.Header.UnitCode; + + /// + public byte EncryptionSeedSelect => _cart.Header.EncryptionSeedSelect; + + /// + public byte DeviceCapacity => _cart.Header.DeviceCapacity; + + /// + public byte[] Reserved1 => _cart.Header.Reserved1; + + /// + public ushort GameRevision => _cart.Header.GameRevision; + + /// + public byte RomVersion => _cart.Header.RomVersion; + + /// + public byte InternalFlags => _cart.Header.InternalFlags; + + /// + public uint ARM9RomOffset => _cart.Header.ARM9RomOffset; + + /// + public uint ARM9EntryAddress => _cart.Header.ARM9EntryAddress; + + /// + public uint ARM9LoadAddress => _cart.Header.ARM9LoadAddress; + + /// + public uint ARM9Size => _cart.Header.ARM9Size; + + /// + public uint ARM7RomOffset => _cart.Header.ARM7RomOffset; + + /// + public uint ARM7EntryAddress => _cart.Header.ARM7EntryAddress; + + /// + public uint ARM7LoadAddress => _cart.Header.ARM7LoadAddress; + + /// + public uint ARM7Size => _cart.Header.ARM7Size; + + /// + public uint FileNameTableOffset => _cart.Header.FileNameTableOffset; + + /// + public uint FileNameTableLength => _cart.Header.FileNameTableLength; + + /// + public uint FileAllocationTableOffset => _cart.Header.FileAllocationTableOffset; + + /// + public uint FileAllocationTableLength => _cart.Header.FileAllocationTableLength; + + /// + public uint ARM9OverlayOffset => _cart.Header.ARM9OverlayOffset; + + /// + public uint ARM9OverlayLength => _cart.Header.ARM9OverlayLength; + + /// + public uint ARM7OverlayOffset => _cart.Header.ARM7OverlayOffset; + + /// + public uint ARM7OverlayLength => _cart.Header.ARM7OverlayLength; + + /// + public uint NormalCardControlRegisterSettings => _cart.Header.NormalCardControlRegisterSettings; + + /// + public uint SecureCardControlRegisterSettings => _cart.Header.SecureCardControlRegisterSettings; + + /// + public uint IconBannerOffset => _cart.Header.IconBannerOffset; + + /// + public ushort SecureAreaCRC => _cart.Header.SecureAreaCRC; + + /// + public ushort SecureTransferTimeout => _cart.Header.SecureTransferTimeout; + + /// + public uint ARM9Autoload => _cart.Header.ARM9Autoload; + + /// + public uint ARM7Autoload => _cart.Header.ARM7Autoload; + + /// + public byte[] SecureDisable => _cart.Header.SecureDisable; + + /// + public uint NTRRegionRomSize => _cart.Header.NTRRegionRomSize; + + /// + public uint HeaderSize => _cart.Header.HeaderSize; + + /// + public byte[] Reserved2 => _cart.Header.Reserved2; + + /// + public byte[] NintendoLogo => _cart.Header.NintendoLogo; + + /// + public ushort NintendoLogoCRC => _cart.Header.NintendoLogoCRC; + + /// + public ushort HeaderCRC => _cart.Header.HeaderCRC; + + /// + public byte[] DebuggerReserved => _cart.Header.DebuggerReserved; + + #endregion + + #region Extended DSi + + /// + public uint[] GlobalMBK15Settings => _cart.Header.GlobalMBK15Settings; + + /// + public uint[] LocalMBK68SettingsARM9 => _cart.Header.LocalMBK68SettingsARM9; + + /// + public uint[] LocalMBK68SettingsARM7 => _cart.Header.LocalMBK68SettingsARM7; + + /// + public uint GlobalMBK9Setting => _cart.Header.GlobalMBK9Setting; + + /// + public uint RegionFlags => _cart.Header.RegionFlags; + + /// + public uint AccessControl => _cart.Header.AccessControl; + + /// + public uint ARM7SCFGEXTMask => _cart.Header.ARM7SCFGEXTMask; + + /// + public uint ReservedFlags => _cart.Header.ReservedFlags; + + /// + public uint ARM9iRomOffset => _cart.Header.ARM9iRomOffset; + + /// + public uint Reserved3 => _cart.Header.Reserved3; + + /// + public uint ARM9iLoadAddress => _cart.Header.ARM9iLoadAddress; + + /// + public uint ARM9iSize => _cart.Header.ARM9iSize; + + /// + public uint ARM7iRomOffset => _cart.Header.ARM7iRomOffset; + + /// + public uint Reserved4 => _cart.Header.Reserved4; + + /// + public uint ARM7iLoadAddress => _cart.Header.ARM7iLoadAddress; + + /// + public uint ARM7iSize => _cart.Header.ARM7iSize; + + /// + public uint DigestNTRRegionOffset => _cart.Header.DigestNTRRegionOffset; + + /// + public uint DigestNTRRegionLength => _cart.Header.DigestNTRRegionLength; + + /// + public uint DigestTWLRegionOffset => _cart.Header.DigestTWLRegionOffset; + + /// + public uint DigestTWLRegionLength => _cart.Header.DigestTWLRegionLength; + + /// + public uint DigestSectorHashtableRegionOffset => _cart.Header.DigestSectorHashtableRegionOffset; + + /// + public uint DigestSectorHashtableRegionLength => _cart.Header.DigestSectorHashtableRegionLength; + + /// + public uint DigestBlockHashtableRegionOffset => _cart.Header.DigestBlockHashtableRegionOffset; + + /// + public uint DigestBlockHashtableRegionLength => _cart.Header.DigestBlockHashtableRegionLength; + + /// + public uint DigestSectorSize => _cart.Header.DigestSectorSize; + + /// + public uint DigestBlockSectorCount => _cart.Header.DigestBlockSectorCount; + + /// + public uint IconBannerSize => _cart.Header.IconBannerSize; + + /// + public uint Unknown1 => _cart.Header.Unknown1; + + /// + public uint ModcryptArea1Offset => _cart.Header.ModcryptArea1Offset; + + /// + public uint ModcryptArea1Size => _cart.Header.ModcryptArea1Size; + + /// + public uint ModcryptArea2Offset => _cart.Header.ModcryptArea2Offset; + + /// + public uint ModcryptArea2Size => _cart.Header.ModcryptArea2Size; + + /// + public byte[] TitleID => _cart.Header.TitleID; + + /// + public uint DSiWarePublicSavSize => _cart.Header.DSiWarePublicSavSize; + + /// + public uint DSiWarePrivateSavSize => _cart.Header.DSiWarePrivateSavSize; + + /// + public byte[] ReservedZero => _cart.Header.ReservedZero; + + /// + public byte[] Unknown2 => _cart.Header.Unknown2; + + /// + public byte[] ARM9WithSecureAreaSHA1HMACHash => _cart.Header.ARM9WithSecureAreaSHA1HMACHash; + + /// + public byte[] ARM7SHA1HMACHash => _cart.Header.ARM7SHA1HMACHash; + + /// + public byte[] DigestMasterSHA1HMACHash => _cart.Header.DigestMasterSHA1HMACHash; + + /// + public byte[] BannerSHA1HMACHash => _cart.Header.BannerSHA1HMACHash; + + /// + public byte[] ARM9iDecryptedSHA1HMACHash => _cart.Header.ARM9iDecryptedSHA1HMACHash; + + /// + public byte[] ARM7iDecryptedSHA1HMACHash => _cart.Header.ARM7iDecryptedSHA1HMACHash; + + /// + public byte[] Reserved5 => _cart.Header.Reserved5; + + /// + public byte[] ARM9NoSecureAreaSHA1HMACHash => _cart.Header.ARM9NoSecureAreaSHA1HMACHash; + + /// + public byte[] Reserved6 => _cart.Header.Reserved6; + + /// + public byte[] ReservedAndUnchecked => _cart.Header.ReservedAndUnchecked; + + /// + public byte[] RSASignature => _cart.Header.RSASignature; + + #endregion + + #endregion + + #region Secure Area + + /// + public byte[] SecureArea => _cart.SecureArea; + + #endregion + + #endregion + + #region Instance Variables + + /// + /// Internal representation of the cart + /// + private Models.Nitro.Cart _cart; + + #endregion + + #region Constructors + + /// + /// Private constructor + /// + private Nitro() { } + + /// + /// Create a NDS cart image from a byte array and offset + /// + /// Byte array representing the archive + /// Offset within the array to parse + /// A NDS cart image wrapper on success, null on failure + public static Nitro Create(byte[] data, int offset) + { + // If the data is invalid + if (data == null) + return null; + + // If the offset is out of bounds + if (offset < 0 || offset >= data.Length) + return null; + + // Create a memory stream and use that + MemoryStream dataStream = new MemoryStream(data, offset, data.Length - offset); + return Create(dataStream); + } + + /// + /// Create a NDS cart image from a Stream + /// + /// Stream representing the archive + /// A NDS cart image wrapper on success, null on failure + public static Nitro Create(Stream data) + { + // If the data is invalid + if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) + return null; + + var archive = Builders.Nitro.ParseCart(data); + if (archive == null) + return null; + + var wrapper = new Nitro + { + _cart = archive, + _dataSource = DataSource.Stream, + _streamData = data, + }; + return wrapper; + } + + #endregion + + #region Printing + + /// + public override void Print() + { + Console.WriteLine("NDS Cart Information:"); + Console.WriteLine("-------------------------"); + Console.WriteLine(); + + PrintCommonHeader(); + PrintDSiHeader(); + PrintSecureArea(); + } + + /// + /// Print common header information + /// + private void PrintCommonHeader() + { + Console.WriteLine(" Common Header Information:"); + Console.WriteLine(" -------------------------"); + Console.WriteLine($" Game title: {GameTitle ?? "[NULL]"}"); + Console.WriteLine($" Game code: {GameCode}"); + Console.WriteLine($" Maker code: {MakerCode ?? "[NULL]"}"); + Console.WriteLine($" Unit code: {UnitCode}"); + Console.WriteLine($" Encryption seed select: {EncryptionSeedSelect}"); + Console.WriteLine($" Device capacity: {DeviceCapacity}"); + Console.WriteLine($" Reserved 1: {BitConverter.ToString(Reserved1).Replace('-', ' ')}"); + Console.WriteLine($" Game revision: {GameRevision}"); + Console.WriteLine($" Rom version: {RomVersion}"); + Console.WriteLine($" ARM9 rom offset: {ARM9RomOffset}"); + Console.WriteLine($" ARM9 entry address: {ARM9EntryAddress}"); + Console.WriteLine($" ARM9 load address: {ARM9LoadAddress}"); + Console.WriteLine($" ARM9 size: {ARM9Size}"); + Console.WriteLine($" ARM7 rom offset: {ARM7RomOffset}"); + Console.WriteLine($" ARM7 entry address: {ARM7EntryAddress}"); + Console.WriteLine($" ARM7 load address: {ARM7LoadAddress}"); + Console.WriteLine($" ARM7 size: {ARM7Size}"); + Console.WriteLine($" File name table offset: {FileNameTableOffset}"); + Console.WriteLine($" File name table length: {FileNameTableLength}"); + Console.WriteLine($" File allocation table offset: {FileAllocationTableOffset}"); + Console.WriteLine($" File allocation table length: {FileAllocationTableLength}"); + Console.WriteLine($" ARM9 overlay offset: {ARM9OverlayOffset}"); + Console.WriteLine($" ARM9 overlay length: {ARM9OverlayLength}"); + Console.WriteLine($" ARM7 overlay offset: {ARM7OverlayOffset}"); + Console.WriteLine($" ARM7 overlay length: {ARM7OverlayLength}"); + Console.WriteLine($" Normal card control register settings: {NormalCardControlRegisterSettings}"); + Console.WriteLine($" Secure card control register settings: {SecureCardControlRegisterSettings}"); + Console.WriteLine($" Icon banner offset: {IconBannerOffset}"); + Console.WriteLine($" Secure area CRC: {SecureAreaCRC}"); + Console.WriteLine($" Secure transfer timeout: {SecureTransferTimeout}"); + Console.WriteLine($" ARM9 autoload: {ARM9Autoload}"); + Console.WriteLine($" ARM7 autoload: {ARM7Autoload}"); + Console.WriteLine($" Secure disable: {SecureDisable}"); + Console.WriteLine($" NTR region rom size: {NTRRegionRomSize}"); + Console.WriteLine($" Header size: {HeaderSize}"); + Console.WriteLine($" Reserved 2: {BitConverter.ToString(Reserved2).Replace('-', ' ')}"); + Console.WriteLine($" Nintendo logo: {BitConverter.ToString(NintendoLogo).Replace('-', ' ')}"); + Console.WriteLine($" Nintendo logo CRC: {NintendoLogoCRC}"); + Console.WriteLine($" Header CRC: {HeaderCRC}"); + Console.WriteLine($" Debugger reserved: {BitConverter.ToString(DebuggerReserved).Replace('-', ' ')}"); + Console.WriteLine(); + } + + /// + /// Print DSi header information + /// + private void PrintDSiHeader() + { + Console.WriteLine(" DSi Header Information:"); + Console.WriteLine(" -------------------------"); + if (UnitCode == Models.Nitro.Unitcode.NDSPlusDSi || UnitCode == Models.Nitro.Unitcode.DSi) + { + Console.WriteLine(" No DSi header"); + } + else + { + Console.WriteLine($" Global MBK1..MBK5 settings: {string.Join(", ", GlobalMBK15Settings)}"); + Console.WriteLine($" Local MBK6..MBK8 settings for ARM9: {string.Join(", ", LocalMBK68SettingsARM9)}"); + Console.WriteLine($" Local MBK6..MBK8 settings for ARM7: {string.Join(", ", LocalMBK68SettingsARM7)}"); + Console.WriteLine($" Global MBK9 setting: {GlobalMBK9Setting}"); + Console.WriteLine($" Region flags: {RegionFlags}"); + Console.WriteLine($" Access control: {AccessControl}"); + Console.WriteLine($" ARM7 SCFG EXT mask: {ARM7SCFGEXTMask}"); + Console.WriteLine($" Reserved/flags?: {ReservedFlags}"); + Console.WriteLine($" ARM9i rom offset: {ARM9iRomOffset}"); + Console.WriteLine($" Reserved 3: {Reserved3}"); + Console.WriteLine($" ARM9i load address: {ARM9iLoadAddress}"); + Console.WriteLine($" ARM9i size: {ARM9iSize}"); + Console.WriteLine($" ARM7i rom offset: {ARM7iRomOffset}"); + Console.WriteLine($" Reserved 4: {Reserved4}"); + Console.WriteLine($" ARM7i load address: {ARM7iLoadAddress}"); + Console.WriteLine($" ARM7i size: {ARM7iSize}"); + Console.WriteLine($" Digest NTR region offset: {DigestNTRRegionOffset}"); + Console.WriteLine($" Digest NTR region length: {DigestNTRRegionLength}"); + Console.WriteLine($" Digest TWL region offset: {DigestTWLRegionOffset}"); + Console.WriteLine($" Digest TWL region length: {DigestTWLRegionLength}"); + Console.WriteLine($" Digest sector hashtable region offset: {DigestSectorHashtableRegionOffset}"); + Console.WriteLine($" Digest sector hashtable region length: {DigestSectorHashtableRegionLength}"); + Console.WriteLine($" Digest block hashtable region offset: {DigestBlockHashtableRegionOffset}"); + Console.WriteLine($" Digest block hashtable region length: {DigestBlockHashtableRegionLength}"); + Console.WriteLine($" Digest sector size: {DigestSectorSize}"); + Console.WriteLine($" Digest block sector count: {DigestBlockSectorCount}"); + Console.WriteLine($" Icon banner size: {IconBannerSize}"); + Console.WriteLine($" Unknown 1: {Unknown1}"); + Console.WriteLine($" Modcrypt area 1 offset: {ModcryptArea1Offset}"); + Console.WriteLine($" Modcrypt area 1 size: {ModcryptArea1Size}"); + Console.WriteLine($" Modcrypt area 2 offset: {ModcryptArea2Offset}"); + Console.WriteLine($" Modcrypt area 2 size: {ModcryptArea2Size}"); + Console.WriteLine($" Title ID: {BitConverter.ToString(TitleID).Replace('-', ' ')}"); + Console.WriteLine($" DSiWare 'public.sav' size: {DSiWarePublicSavSize}"); + Console.WriteLine($" DSiWare 'private.sav' size: {DSiWarePrivateSavSize}"); + Console.WriteLine($" Reserved (zero): {BitConverter.ToString(ReservedZero).Replace('-', ' ')}"); + Console.WriteLine($" Unknown 2: {BitConverter.ToString(Unknown2).Replace('-', ' ')}"); + Console.WriteLine($" ARM9 (with encrypted secure area) SHA1 HMAC hash: {BitConverter.ToString(ARM9WithSecureAreaSHA1HMACHash).Replace('-', ' ')}"); + Console.WriteLine($" ARM7 SHA1 HMAC hash: {BitConverter.ToString(ARM7SHA1HMACHash).Replace('-', ' ')}"); + Console.WriteLine($" Digest master SHA1 HMAC hash: {BitConverter.ToString(DigestMasterSHA1HMACHash).Replace('-', ' ')}"); + Console.WriteLine($" Banner SHA1 HMAC hash: {BitConverter.ToString(BannerSHA1HMACHash).Replace('-', ' ')}"); + Console.WriteLine($" ARM9i (decrypted) SHA1 HMAC hash: {BitConverter.ToString(ARM9iDecryptedSHA1HMACHash).Replace('-', ' ')}"); + Console.WriteLine($" ARM7i (decrypted) SHA1 HMAC hash: {BitConverter.ToString(ARM7iDecryptedSHA1HMACHash).Replace('-', ' ')}"); + Console.WriteLine($" Reserved 5: {BitConverter.ToString(Reserved5).Replace('-', ' ')}"); + Console.WriteLine($" ARM9 (without secure area) SHA1 HMAC hash: {BitConverter.ToString(ARM9NoSecureAreaSHA1HMACHash).Replace('-', ' ')}"); + Console.WriteLine($" Reserved 6: {BitConverter.ToString(Reserved6).Replace('-', ' ')}"); + Console.WriteLine($" Reserved and unchecked region: {BitConverter.ToString(ReservedAndUnchecked).Replace('-', ' ')}"); + Console.WriteLine($" RSA signature: {BitConverter.ToString(RSASignature).Replace('-', ' ')}"); + } + Console.WriteLine(); + } + + /// + /// Print secure area information + /// + private void PrintSecureArea() + { + Console.WriteLine(" Secure Area Information:"); + Console.WriteLine(" -------------------------"); + if (SecureArea == null || SecureArea.Length == 0) + Console.WriteLine(" No secure area"); + else + Console.WriteLine($" {BitConverter.ToString(SecureArea).Replace('-', ' ')}"); + Console.WriteLine(); + } + + #endregion + } +} \ No newline at end of file