mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-09-22 23:05:03 +00:00
Fix DS/3DS sttuff, add 3DS wrapper/printing
This commit is contained in:
@@ -56,7 +56,7 @@ namespace BurnOutSharp.Builders
|
||||
// Create a new cart image to fill
|
||||
var cart = new Cart();
|
||||
|
||||
#region Header
|
||||
#region NCSD Header
|
||||
|
||||
// Try to parse the header
|
||||
var header = ParseNCSDHeader(data);
|
||||
@@ -68,6 +68,34 @@ namespace BurnOutSharp.Builders
|
||||
|
||||
#endregion
|
||||
|
||||
#region Card Info Header
|
||||
|
||||
// Try to parse the card info header
|
||||
var cardInfoHeader = ParseCardInfoHeader(data);
|
||||
if (cardInfoHeader == null)
|
||||
return null;
|
||||
|
||||
// Set the card info header
|
||||
cart.CardInfoHeader = cardInfoHeader;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Development Card Info Header
|
||||
|
||||
// TODO: Hook up a builder flag to enable development parsing
|
||||
if (false)
|
||||
{
|
||||
// Try to parse the development card info header
|
||||
var developmentCardInfoHeader = ParseDevelopmentCardInfoHeader(data);
|
||||
if (developmentCardInfoHeader == null)
|
||||
return null;
|
||||
|
||||
// Set the development card info header
|
||||
cart.DevelopmentCardInfoHeader = developmentCardInfoHeader;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Partitions
|
||||
|
||||
// Create the partition table
|
||||
@@ -88,16 +116,15 @@ namespace BurnOutSharp.Builders
|
||||
/// Parse a Stream into an NCSD header
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="development">Indicates if the cart is development or not</param>
|
||||
/// <returns>Filled NCSD header on success, null on error</returns>
|
||||
private static NCSDHeader ParseNCSDHeader(Stream data, bool development = false)
|
||||
private static NCSDHeader ParseNCSDHeader(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
NCSDHeader header = new NCSDHeader();
|
||||
|
||||
header.RSA2048Signature = data.ReadBytes(0x100);
|
||||
byte[] magicNumber = data.ReadBytes(4);
|
||||
header.MagicNumber = Encoding.ASCII.GetString(magicNumber);
|
||||
header.MagicNumber = Encoding.ASCII.GetString(magicNumber).TrimEnd('\0');;
|
||||
if (header.MagicNumber != NCSDMagicNumber)
|
||||
return null;
|
||||
|
||||
@@ -119,36 +146,16 @@ namespace BurnOutSharp.Builders
|
||||
header.SectorZeroOffset = data.ReadUInt32();
|
||||
header.PartitionFlags = data.ReadBytes(8);
|
||||
|
||||
header.PartitionIdTable = new byte[8][];
|
||||
header.PartitionIdTable = new ulong[8];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
header.PartitionIdTable[i] = data.ReadBytes(8);
|
||||
header.PartitionIdTable[i] = data.ReadUInt64();
|
||||
}
|
||||
|
||||
header.Reserved1 = data.ReadBytes(0x20);
|
||||
header.Reserved2 = data.ReadBytes(0xE);
|
||||
header.Reserved2 = data.ReadBytes(0x0E);
|
||||
header.FirmUpdateByte1 = data.ReadByteValue();
|
||||
header.FirmUpdateByte2 = data.ReadByteValue();
|
||||
|
||||
header.CARD2WritableAddressMediaUnits = data.ReadBytes(4);
|
||||
header.CardInfoBytemask = data.ReadBytes(4);
|
||||
header.Reserved3 = data.ReadBytes(0x108);
|
||||
header.TitleVersion = data.ReadUInt16();
|
||||
header.CardRevision = data.ReadUInt16();
|
||||
header.Reserved4 = data.ReadBytes(0xCEC); // Incorrectly documented as 0xCEE
|
||||
header.CardSeedKeyY = data.ReadBytes(0x10);
|
||||
header.EncryptedCardSeed = data.ReadBytes(0x10);
|
||||
header.CardSeedAESMAC = data.ReadBytes(0x10);
|
||||
header.CardSeedNonce = data.ReadBytes(0xC);
|
||||
header.Reserved5 = data.ReadBytes(0xC4);
|
||||
header.BackupHeader = ParseNCCHHeader(data, true);
|
||||
|
||||
if (development)
|
||||
{
|
||||
header.CardDeviceReserved1 = data.ReadBytes(0x200);
|
||||
header.TitleKey = data.ReadBytes(0x10);
|
||||
header.CardDeviceReserved2 = data.ReadBytes(0xF0);
|
||||
}
|
||||
}
|
||||
else if (header.PartitionsFSType == FilesystemType.FIRM)
|
||||
{
|
||||
@@ -175,6 +182,78 @@ namespace BurnOutSharp.Builders
|
||||
return partitionTableEntry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a card info header
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled card info header on success, null on error</returns>
|
||||
private static CardInfoHeader ParseCardInfoHeader(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
CardInfoHeader cardInfoHeader = new CardInfoHeader();
|
||||
|
||||
cardInfoHeader.WritableAddressMediaUnits = data.ReadUInt32();
|
||||
cardInfoHeader.CardInfoBitmask = data.ReadUInt32();
|
||||
cardInfoHeader.Reserved1 = data.ReadBytes(0xF8);
|
||||
cardInfoHeader.FilledSize = data.ReadUInt32();
|
||||
cardInfoHeader.Reserved2 = data.ReadBytes(0x0C);
|
||||
cardInfoHeader.TitleVersion = data.ReadUInt16();
|
||||
cardInfoHeader.CardRevision = data.ReadUInt16();
|
||||
cardInfoHeader.Reserved3 = data.ReadBytes(0x0C);
|
||||
cardInfoHeader.CVerTitleID = data.ReadBytes(8);
|
||||
cardInfoHeader.CVerVersionNumber = data.ReadUInt16();
|
||||
cardInfoHeader.Reserved4 = data.ReadBytes(0xCD6);
|
||||
|
||||
return cardInfoHeader;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a development card info header
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled development card info header on success, null on error</returns>
|
||||
private static DevelopmentCardInfoHeader ParseDevelopmentCardInfoHeader(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
DevelopmentCardInfoHeader developmentCardInfoHeader = new DevelopmentCardInfoHeader();
|
||||
|
||||
developmentCardInfoHeader.InitialData = ParseInitialData(data);
|
||||
if (developmentCardInfoHeader.InitialData == null)
|
||||
return null;
|
||||
|
||||
developmentCardInfoHeader.CardDeviceReserved1 = data.ReadBytes(0x200);
|
||||
developmentCardInfoHeader.TitleKey = data.ReadBytes(0x10);
|
||||
developmentCardInfoHeader.CardDeviceReserved2 = data.ReadBytes(0x1BF0);
|
||||
|
||||
developmentCardInfoHeader.TestData = ParseTestData(data);
|
||||
if (developmentCardInfoHeader.TestData == null)
|
||||
return null;
|
||||
|
||||
return developmentCardInfoHeader;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into an initial data
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled initial data on success, null on error</returns>
|
||||
private static InitialData ParseInitialData(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
InitialData initialData = new InitialData();
|
||||
|
||||
initialData.CardSeedKeyY = data.ReadBytes(0x10);
|
||||
initialData.EncryptedCardSeed = data.ReadBytes(0x10);
|
||||
initialData.CardSeedAESMAC = data.ReadBytes(0x10);
|
||||
initialData.CardSeedNonce = data.ReadBytes(0xC);
|
||||
initialData.Reserved = data.ReadBytes(0xC4);
|
||||
initialData.BackupHeader = ParseNCCHHeader(data, true);
|
||||
if (initialData.BackupHeader == null)
|
||||
return null;
|
||||
|
||||
return initialData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into an NCCH header
|
||||
/// </summary>
|
||||
@@ -190,7 +269,7 @@ namespace BurnOutSharp.Builders
|
||||
header.RSA2048Signature = data.ReadBytes(0x100);
|
||||
|
||||
byte[] magicId = data.ReadBytes(4);
|
||||
header.MagicID = Encoding.ASCII.GetString(magicId);
|
||||
header.MagicID = Encoding.ASCII.GetString(magicId).TrimEnd('\0');;
|
||||
if (header.MagicID != NCCHMagicNumber)
|
||||
return null;
|
||||
|
||||
@@ -247,6 +326,31 @@ namespace BurnOutSharp.Builders
|
||||
return headerFlags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into an initial data
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled initial data on success, null on error</returns>
|
||||
private static TestData ParseTestData(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
TestData testData = new TestData();
|
||||
|
||||
// TODO: Validate some of the values
|
||||
testData.Signature = data.ReadBytes(8);
|
||||
testData.AscendingByteSequence = data.ReadBytes(0x1F8);
|
||||
testData.DescendingByteSequence = data.ReadBytes(0x200);
|
||||
testData.Filled00 = data.ReadBytes(0x200);
|
||||
testData.FilledFF = data.ReadBytes(0x200);
|
||||
testData.Filled0F = data.ReadBytes(0x200);
|
||||
testData.FilledF0 = data.ReadBytes(0x200);
|
||||
testData.Filled55 = data.ReadBytes(0x200);
|
||||
testData.FilledAA = data.ReadBytes(0x1FF);
|
||||
testData.FinalByte = data.ReadByteValue();
|
||||
|
||||
return testData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,10 +113,10 @@ namespace BurnOutSharp.Builders
|
||||
CommonHeader commonHeader = new CommonHeader();
|
||||
|
||||
byte[] gameTitle = data.ReadBytes(0x0C);
|
||||
commonHeader.GameTitle = Encoding.ASCII.GetString(gameTitle);
|
||||
commonHeader.GameTitle = Encoding.ASCII.GetString(gameTitle).TrimEnd('\0');
|
||||
commonHeader.GameCode = data.ReadUInt32();
|
||||
byte[] makerCode = data.ReadBytes(2);
|
||||
commonHeader.MakerCode = Encoding.ASCII.GetString(bytes: makerCode);
|
||||
commonHeader.MakerCode = Encoding.ASCII.GetString(bytes: makerCode).TrimEnd('\0');
|
||||
commonHeader.UnitCode = (Unitcode)data.ReadByteValue();
|
||||
commonHeader.EncryptionSeedSelect = data.ReadByteValue();
|
||||
commonHeader.DeviceCapacity = data.ReadByteValue();
|
||||
|
||||
61
BurnOutSharp.Models/N3DS/CardInfoHeader.cs
Normal file
61
BurnOutSharp.Models/N3DS/CardInfoHeader.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
namespace BurnOutSharp.Models.N3DS
|
||||
{
|
||||
/// <see href="https://www.3dbrew.org/wiki/NCSD#Card_Info_Header"/>
|
||||
public sealed class CardInfoHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// CARD2: Writable Address In Media Units (For 'On-Chip' Savedata). CARD1: Always 0xFFFFFFFF.
|
||||
/// </summary>
|
||||
public uint WritableAddressMediaUnits;
|
||||
|
||||
/// <summary>
|
||||
/// Card Info Bitmask
|
||||
/// </summary>
|
||||
public uint CardInfoBitmask;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte[] Reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// Filled size of cartridge
|
||||
/// </summary>
|
||||
public uint FilledSize;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte[] Reserved2;
|
||||
|
||||
/// <summary>
|
||||
/// Title version
|
||||
/// </summary>
|
||||
public ushort TitleVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Card revision
|
||||
/// </summary>
|
||||
public ushort CardRevision;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte[] Reserved3;
|
||||
|
||||
/// <summary>
|
||||
/// Title ID of CVer in included update partition
|
||||
/// </summary>
|
||||
public byte[] CVerTitleID;
|
||||
|
||||
/// <summary>
|
||||
/// Version number of CVer in included update partition
|
||||
/// </summary>
|
||||
public ushort CVerVersionNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte[] Reserved4;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,16 @@ namespace BurnOutSharp.Models.N3DS
|
||||
/// </summary>
|
||||
public NCSDHeader Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 3DS card info header
|
||||
/// </summary>
|
||||
public CardInfoHeader CardInfoHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 3DS development card info header
|
||||
/// </summary>
|
||||
public DevelopmentCardInfoHeader DevelopmentCardInfoHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// NCCH partitions
|
||||
/// </summary>
|
||||
|
||||
31
BurnOutSharp.Models/N3DS/DevelopmentCardInfoHeader.cs
Normal file
31
BurnOutSharp.Models/N3DS/DevelopmentCardInfoHeader.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
namespace BurnOutSharp.Models.N3DS
|
||||
{
|
||||
/// <see href="https://www.3dbrew.org/wiki/NCSD#Development_Card_Info_Header_Extension"/>
|
||||
public sealed class DevelopmentCardInfoHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// InitialData
|
||||
/// </summary>
|
||||
public InitialData InitialData;
|
||||
|
||||
/// <summary>
|
||||
/// CardDeviceReserved1
|
||||
/// </summary>
|
||||
public byte[] CardDeviceReserved1;
|
||||
|
||||
/// <summary>
|
||||
/// TitleKey
|
||||
/// </summary>
|
||||
public byte[] TitleKey;
|
||||
|
||||
/// <summary>
|
||||
/// CardDeviceReserved2
|
||||
/// </summary>
|
||||
public byte[] CardDeviceReserved2;
|
||||
|
||||
/// <summary>
|
||||
/// TestData
|
||||
/// </summary>
|
||||
public TestData TestData;
|
||||
}
|
||||
}
|
||||
35
BurnOutSharp.Models/N3DS/InitialData.cs
Normal file
35
BurnOutSharp.Models/N3DS/InitialData.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
namespace BurnOutSharp.Models.N3DS
|
||||
{
|
||||
/// <see href="https://www.3dbrew.org/wiki/NCSD#InitialData"/>
|
||||
public sealed class InitialData
|
||||
{
|
||||
/// <summary>
|
||||
/// Card seed keyY (first u64 is Media ID (same as first NCCH partitionId))
|
||||
/// </summary>
|
||||
public byte[] CardSeedKeyY;
|
||||
|
||||
/// <summary>
|
||||
/// Encrypted card seed (AES-CCM, keyslot 0x3B for retail cards, see CTRCARD_SECSEED) /// </summary>
|
||||
public byte[] EncryptedCardSeed;
|
||||
|
||||
/// <summary>
|
||||
/// Card seed AES-MAC
|
||||
/// </summary>
|
||||
public byte[] CardSeedAESMAC;
|
||||
|
||||
/// <summary>
|
||||
/// Card seed nonce
|
||||
/// </summary>
|
||||
public byte[] CardSeedNonce;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved3
|
||||
/// </summary>
|
||||
public byte[] Reserved;
|
||||
|
||||
/// <summary>
|
||||
/// Copy of first NCCH header (excluding RSA signature)
|
||||
/// </summary>
|
||||
public NCCHHeader BackupHeader;
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@
|
||||
/// <summary>
|
||||
/// Partition ID table
|
||||
/// </summary>
|
||||
public byte[][] PartitionIdTable;
|
||||
public ulong[] PartitionIdTable;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
@@ -115,87 +115,5 @@
|
||||
public byte[] EncryptedMBR;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Card Info Header
|
||||
|
||||
/// <summary>
|
||||
/// CARD2: Writable Address In Media Units (For 'On-Chip' Savedata). CARD1: Always 0xFFFFFFFF.
|
||||
/// </summary>
|
||||
public byte[] CARD2WritableAddressMediaUnits;
|
||||
|
||||
/// <summary>
|
||||
/// Card Info Bitmask
|
||||
/// </summary>
|
||||
public byte[] CardInfoBytemask;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved1
|
||||
/// </summary>
|
||||
public byte[] Reserved3;
|
||||
|
||||
/// <summary>
|
||||
/// Title version
|
||||
/// </summary>
|
||||
public ushort TitleVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Card revision
|
||||
/// </summary>
|
||||
public ushort CardRevision;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved2
|
||||
/// </summary>
|
||||
public byte[] Reserved4;
|
||||
|
||||
/// <summary>
|
||||
/// Card seed keyY (first u64 is Media ID (same as first NCCH partitionId))
|
||||
/// </summary>
|
||||
public byte[] CardSeedKeyY;
|
||||
|
||||
/// <summary>
|
||||
/// Encrypted card seed (AES-CCM, keyslot 0x3B for retail cards, see CTRCARD_SECSEED) /// </summary>
|
||||
public byte[] EncryptedCardSeed;
|
||||
|
||||
/// <summary>
|
||||
/// Card seed AES-MAC
|
||||
/// </summary>
|
||||
public byte[] CardSeedAESMAC;
|
||||
|
||||
/// <summary>
|
||||
/// Card seed nonce
|
||||
/// </summary>
|
||||
public byte[] CardSeedNonce;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved3
|
||||
/// </summary>
|
||||
public byte[] Reserved5;
|
||||
|
||||
/// <summary>
|
||||
/// Copy of first NCCH header (excluding RSA signature)
|
||||
/// </summary>
|
||||
public NCCHHeader BackupHeader;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Development Card Info Header Extension
|
||||
|
||||
/// <summary>
|
||||
/// CardDeviceReserved1
|
||||
/// </summary>
|
||||
public byte[] CardDeviceReserved1;
|
||||
|
||||
/// <summary>
|
||||
/// TitleKey
|
||||
/// </summary>
|
||||
public byte[] TitleKey;
|
||||
|
||||
/// <summary>
|
||||
/// CardDeviceReserved2
|
||||
/// </summary>
|
||||
public byte[] CardDeviceReserved2;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
59
BurnOutSharp.Models/N3DS/TestData.cs
Normal file
59
BurnOutSharp.Models/N3DS/TestData.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
namespace BurnOutSharp.Models.N3DS
|
||||
{
|
||||
/// <summary>
|
||||
/// The test data is the same one encountered in development DS/DSi cartridges.
|
||||
/// </summary>
|
||||
/// <see href="https://www.3dbrew.org/wiki/NCSD#TestData"/>
|
||||
public sealed class TestData
|
||||
{
|
||||
/// <summary>
|
||||
/// The bytes FF 00 FF 00 AA 55 AA 55.
|
||||
/// </summary>
|
||||
public byte[] Signature;
|
||||
|
||||
/// <summary>
|
||||
/// An ascending byte sequence equal to the offset mod 256 (08 09 0A ... FE FF 00 01 ... FF).
|
||||
/// </summary>
|
||||
public byte[] AscendingByteSequence;
|
||||
|
||||
/// <summary>
|
||||
/// A descending byte sequence equal to 255 minus the offset mod 256 (FF FE FD ... 00 FF DE ... 00).
|
||||
/// </summary>
|
||||
public byte[] DescendingByteSequence;
|
||||
|
||||
/// <summary>
|
||||
/// Filled with 00 (0b00000000) bytes.
|
||||
/// </summary>
|
||||
public byte[] Filled00;
|
||||
|
||||
/// <summary>
|
||||
/// Filled with FF (0b11111111) bytes.
|
||||
/// </summary>
|
||||
public byte[] FilledFF;
|
||||
|
||||
/// <summary>
|
||||
/// Filled with 0F (0b00001111) bytes.
|
||||
/// </summary>
|
||||
public byte[] Filled0F;
|
||||
|
||||
/// <summary>
|
||||
/// Filled with F0 (0b11110000) bytes.
|
||||
/// </summary>
|
||||
public byte[] FilledF0;
|
||||
|
||||
/// <summary>
|
||||
/// Filled with 55 (0b01010101) bytes.
|
||||
/// </summary>
|
||||
public byte[] Filled55;
|
||||
|
||||
/// <summary>
|
||||
/// Filled with AA (0b10101010) bytes.
|
||||
/// </summary>
|
||||
public byte[] FilledAA;
|
||||
|
||||
/// <summary>
|
||||
/// The final byte is 00 (0b00000000).
|
||||
/// </summary>
|
||||
public byte FinalByte;
|
||||
}
|
||||
}
|
||||
452
BurnOutSharp.Wrappers/N3DS.cs
Normal file
452
BurnOutSharp.Wrappers/N3DS.cs
Normal file
@@ -0,0 +1,452 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp.Wrappers
|
||||
{
|
||||
public class N3DS : WrapperBase
|
||||
{
|
||||
#region Pass-Through Properties
|
||||
|
||||
#region Header
|
||||
|
||||
#region Common to all NCSD files
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.RSA2048Signature"/>
|
||||
public byte[] RSA2048Signature => _cart.Header.RSA2048Signature;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.MagicNumber"/>
|
||||
public string MagicNumber => _cart.Header.MagicNumber;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.ImageSizeInMediaUnits"/>
|
||||
public uint ImageSizeInMediaUnits => _cart.Header.ImageSizeInMediaUnits;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.MediaId"/>
|
||||
public byte[] MediaId => _cart.Header.MediaId;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.PartitionsFSType"/>
|
||||
public Models.N3DS.FilesystemType PartitionsFSType => _cart.Header.PartitionsFSType;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.PartitionsCryptType"/>
|
||||
public byte[] PartitionsCryptType => _cart.Header.PartitionsCryptType;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.PartitionsTable"/>
|
||||
public Models.N3DS.PartitionTableEntry[] PartitionsTable => _cart.Header.PartitionsTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region CTR Cart Image (CCI) Specific
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.ExheaderHash"/>
|
||||
public byte[] ExheaderHash => _cart.Header.ExheaderHash;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.AdditionalHeaderSize"/>
|
||||
public uint AdditionalHeaderSize => _cart.Header.AdditionalHeaderSize;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.SectorZeroOffset"/>
|
||||
public uint SectorZeroOffset => _cart.Header.SectorZeroOffset;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.PartitionFlags"/>
|
||||
public byte[] PartitionFlags => _cart.Header.PartitionFlags;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.PartitionIdTable"/>
|
||||
public ulong[] PartitionIdTable => _cart.Header.PartitionIdTable;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.Reserved1"/>
|
||||
public byte[] Reserved1 => _cart.Header.Reserved1;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.Reserved2"/>
|
||||
public byte[] Reserved2 => _cart.Header.Reserved2;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.FirmUpdateByte1"/>
|
||||
public byte FirmUpdateByte1 => _cart.Header.FirmUpdateByte1;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.FirmUpdateByte2"/>
|
||||
public byte FirmUpdateByte2 => _cart.Header.FirmUpdateByte2;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Raw NAND Format Specific
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.Unknown"/>
|
||||
public byte[] Unknown => _cart.Header.Unknown;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.NCSDHeader.EncryptedMBR"/>
|
||||
public byte[] EncryptedMBR => _cart.Header.EncryptedMBR;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Card Info Header
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.WritableAddressMediaUnits"/>
|
||||
public uint CIH_WritableAddressMediaUnits => _cart.CardInfoHeader.WritableAddressMediaUnits;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.CardInfoBitmask"/>
|
||||
public uint CIH_CardInfoBitmask => _cart.CardInfoHeader.CardInfoBitmask;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.Reserved1"/>
|
||||
public byte[] CIH_Reserved1 => _cart.CardInfoHeader.Reserved1;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.FilledSize"/>
|
||||
public uint CIH_FilledSize => _cart.CardInfoHeader.FilledSize;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.Reserved2"/>
|
||||
public byte[] CIH_Reserved2 => _cart.CardInfoHeader.Reserved2;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.TitleVersion"/>
|
||||
public ushort CIH_TitleVersion => _cart.CardInfoHeader.TitleVersion;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.CardRevision"/>
|
||||
public ushort CIH_CardRevision => _cart.CardInfoHeader.CardRevision;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.Reserved3"/>
|
||||
public byte[] CIH_Reserved3 => _cart.CardInfoHeader.Reserved3;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.CVerTitleID"/>
|
||||
public byte[] CIH_CVerTitleID => _cart.CardInfoHeader.CVerTitleID;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.CVerVersionNumber"/>
|
||||
public ushort CIH_CVerVersionNumber => _cart.CardInfoHeader.CVerVersionNumber;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.CardInfoHeader.Reserved4"/>
|
||||
public byte[] CIH_Reserved4 => _cart.CardInfoHeader.Reserved4;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Development Card Info Header
|
||||
|
||||
#region Initial Data
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.InitialData.CardSeedKeyY"/>
|
||||
public byte[] DCIH_ID_CardSeedKeyY => _cart.DevelopmentCardInfoHeader?.InitialData?.CardSeedKeyY;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.InitialData.EncryptedCardSeed"/>
|
||||
public byte[] DCIH_ID_EncryptedCardSeed => _cart.DevelopmentCardInfoHeader?.InitialData?.EncryptedCardSeed;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.InitialData.CardSeedAESMAC"/>
|
||||
public byte[] DCIH_ID_CardSeedAESMAC => _cart.DevelopmentCardInfoHeader?.InitialData?.CardSeedAESMAC;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.InitialData.CardSeedNonce"/>
|
||||
public byte[] DCIH_ID_CardSeedNonce => _cart.DevelopmentCardInfoHeader?.InitialData?.CardSeedNonce;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.InitialData.Reserved3"/>
|
||||
public byte[] DCIH_ID_Reserved => _cart.DevelopmentCardInfoHeader?.InitialData?.Reserved;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.InitialData.BackupHeader"/>
|
||||
public Models.N3DS.NCCHHeader DCIH_ID_BackupHeader => _cart.DevelopmentCardInfoHeader?.InitialData?.BackupHeader;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.DevelopmentCardInfoHeader.CardDeviceReserved1"/>
|
||||
public byte[] DCIH_CardDeviceReserved1 => _cart.DevelopmentCardInfoHeader?.CardDeviceReserved1;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.DevelopmentCardInfoHeader.TitleKey"/>
|
||||
public byte[] DCIH_TitleKey => _cart.DevelopmentCardInfoHeader?.TitleKey;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.DevelopmentCardInfoHeader.CardDeviceReserved2"/>
|
||||
public byte[] DCIH_CardDeviceReserved2 => _cart.DevelopmentCardInfoHeader?.CardDeviceReserved2;
|
||||
|
||||
#region Test Data
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.TestData.Signature"/>
|
||||
public byte[] DCIH_TD_Signature => _cart.DevelopmentCardInfoHeader?.TestData?.Signature;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.TestData.AscendingByteSequence"/>
|
||||
public byte[] DCIH_TD_AscendingByteSequence => _cart.DevelopmentCardInfoHeader?.TestData?.AscendingByteSequence;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.TestData.DescendingByteSequence"/>
|
||||
public byte[] DCIH_TD_DescendingByteSequence => _cart.DevelopmentCardInfoHeader?.TestData?.DescendingByteSequence;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.TestData.Filled00"/>
|
||||
public byte[] DCIH_TD_Filled00 => _cart.DevelopmentCardInfoHeader?.TestData?.Filled00;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.TestData.FilledFF"/>
|
||||
public byte[] DCIH_TD_FilledFF => _cart.DevelopmentCardInfoHeader?.TestData?.FilledFF;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.TestData.Filled0F"/>
|
||||
public byte[] DCIH_TD_Filled0F => _cart.DevelopmentCardInfoHeader?.TestData?.Filled0F;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.TestData.FilledF0"/>
|
||||
public byte[] DCIH_TD_FilledF0 => _cart.DevelopmentCardInfoHeader?.TestData?.FilledF0;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.TestData.Filled55"/>
|
||||
public byte[] DCIH_TD_Filled55 => _cart.DevelopmentCardInfoHeader?.TestData?.Filled55;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.TestData.FilledAA"/>
|
||||
public byte[] DCIH_TD_FilledAA => _cart.DevelopmentCardInfoHeader?.TestData?.FilledAA;
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.TestData.FinalByte"/>
|
||||
public byte? DCIH_TD_FinalByte => _cart.DevelopmentCardInfoHeader?.TestData?.FinalByte;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Partitions
|
||||
|
||||
/// <inheritdoc cref="Models.N3DS.Cart.Partitions"/>
|
||||
public Models.N3DS.NCCHHeader[] Partitions => _cart.Partitions;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Variables
|
||||
|
||||
/// <summary>
|
||||
/// Internal representation of the cart
|
||||
/// </summary>
|
||||
private Models.N3DS.Cart _cart;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Private constructor
|
||||
/// </summary>
|
||||
private N3DS() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a 3DS cart image from a byte array and offset
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the archive</param>
|
||||
/// <param name="offset">Offset within the array to parse</param>
|
||||
/// <returns>A 3DS cart image wrapper on success, null on failure</returns>
|
||||
public static N3DS 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a 3DS cart image from a Stream
|
||||
/// </summary>
|
||||
/// <param name="data">Stream representing the archive</param>
|
||||
/// <returns>A 3DS cart image wrapper on success, null on failure</returns>
|
||||
public static N3DS Create(Stream data)
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead)
|
||||
return null;
|
||||
|
||||
var archive = Builders.N3DS.ParseCart(data);
|
||||
if (archive == null)
|
||||
return null;
|
||||
|
||||
var wrapper = new N3DS
|
||||
{
|
||||
_cart = archive,
|
||||
_dataSource = DataSource.Stream,
|
||||
_streamData = data,
|
||||
};
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Printing
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Print()
|
||||
{
|
||||
Console.WriteLine("3DS Cart Information:");
|
||||
Console.WriteLine("-------------------------");
|
||||
Console.WriteLine();
|
||||
|
||||
PrintNCSDHeader();
|
||||
PrintCardInfoHeader();
|
||||
PrintDevelopmentCardInfoHeader();
|
||||
PrintPartitions();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Print NCSD header information
|
||||
/// </summary>
|
||||
private void PrintNCSDHeader()
|
||||
{
|
||||
Console.WriteLine(" NCSD Header Information:");
|
||||
Console.WriteLine(" -------------------------");
|
||||
Console.WriteLine($" RSA-2048 SHA-256 signature: {BitConverter.ToString(RSA2048Signature).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Magic number: {MagicNumber}");
|
||||
Console.WriteLine($" Image size in media units: {ImageSizeInMediaUnits}");
|
||||
Console.WriteLine($" Media ID: {BitConverter.ToString(MediaId).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Partitions filesystem type: {PartitionsFSType}");
|
||||
Console.WriteLine($" Partitions crypt type: {BitConverter.ToString(PartitionsCryptType).Replace('-', ' ')}");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine($" Partition table:");
|
||||
Console.WriteLine(" -------------------------");
|
||||
for (int i = 0; i < PartitionsTable.Length; i++)
|
||||
{
|
||||
var partitionTableEntry = PartitionsTable[i];
|
||||
Console.WriteLine($" Partition table entry {i}");
|
||||
Console.WriteLine($" Offset: {partitionTableEntry.Offset}");
|
||||
Console.WriteLine($" Length: {partitionTableEntry.Length}");
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
// If we have a cart image
|
||||
if (PartitionsFSType == Models.N3DS.FilesystemType.Normal || PartitionsFSType == Models.N3DS.FilesystemType.None)
|
||||
{
|
||||
Console.WriteLine($" Exheader SHA-256 hash: {BitConverter.ToString(ExheaderHash).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Additional header size: {AdditionalHeaderSize}");
|
||||
Console.WriteLine($" Sector zero offset: {SectorZeroOffset}");
|
||||
Console.WriteLine($" Partition flags: {BitConverter.ToString(PartitionFlags).Replace('-', ' ')}");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine($" Partition ID table:");
|
||||
Console.WriteLine(" -------------------------");
|
||||
for (int i = 0; i < PartitionIdTable.Length; i++)
|
||||
{
|
||||
Console.WriteLine($" Partition {i} ID: {PartitionIdTable[i]}");
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine($" Reserved 1: {BitConverter.ToString(Reserved1).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Reserved 2: {BitConverter.ToString(Reserved2).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Firmware update byte 1: {FirmUpdateByte1}");
|
||||
Console.WriteLine($" Firmware update byte 2: {FirmUpdateByte2}");
|
||||
}
|
||||
|
||||
// If we have a firmware image
|
||||
else if (PartitionsFSType == Models.N3DS.FilesystemType.FIRM)
|
||||
{
|
||||
Console.WriteLine($" Unknown: {BitConverter.ToString(Unknown).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Encrypted MBR: {BitConverter.ToString(EncryptedMBR).Replace('-', ' ')}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Print card info header information
|
||||
/// </summary>
|
||||
private void PrintCardInfoHeader()
|
||||
{
|
||||
Console.WriteLine(" Card Info Header Information:");
|
||||
Console.WriteLine(" -------------------------");
|
||||
Console.WriteLine($" Writable address in media units: {CIH_WritableAddressMediaUnits}");
|
||||
Console.WriteLine($" Card info bitmask: {CIH_CardInfoBitmask}");
|
||||
Console.WriteLine($" Reserved 1: {BitConverter.ToString(CIH_Reserved1).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Filled size of cartridge: {CIH_FilledSize}");
|
||||
Console.WriteLine($" Reserved 2: {BitConverter.ToString(CIH_Reserved2).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Title version: {CIH_TitleVersion}");
|
||||
Console.WriteLine($" Card revision: {CIH_CardRevision}");
|
||||
Console.WriteLine($" Reserved 3: {BitConverter.ToString(CIH_Reserved3).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Title ID of CVer in included update partition: {BitConverter.ToString(CIH_CVerTitleID).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Version number of CVer in included update partition: {CIH_CVerVersionNumber}");
|
||||
Console.WriteLine($" Reserved 4: {BitConverter.ToString(CIH_Reserved4).Replace('-', ' ')}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Print development card info header information
|
||||
/// </summary>
|
||||
private void PrintDevelopmentCardInfoHeader()
|
||||
{
|
||||
Console.WriteLine(" Development Card Info Header Information:");
|
||||
Console.WriteLine(" -------------------------");
|
||||
if (_cart.DevelopmentCardInfoHeader == null)
|
||||
{
|
||||
Console.WriteLine(" No development card info header");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(" Initial Data:");
|
||||
Console.WriteLine(" -------------------------");
|
||||
Console.WriteLine($" Card seed keyY: {BitConverter.ToString(DCIH_ID_CardSeedKeyY).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Encrypted card seed: {BitConverter.ToString(DCIH_ID_EncryptedCardSeed).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Card seed AES-MAC: {BitConverter.ToString(DCIH_ID_CardSeedAESMAC).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Card seed nonce: {BitConverter.ToString(DCIH_ID_CardSeedNonce).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Reserved: {BitConverter.ToString(DCIH_ID_Reserved).Replace('-', ' ')}");
|
||||
// TODO: Print Backup Header?
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine($" Card device reserved 1: {BitConverter.ToString(DCIH_CardDeviceReserved1).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Title key: {BitConverter.ToString(DCIH_TitleKey).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Card device reserved 2: {BitConverter.ToString(DCIH_CardDeviceReserved2).Replace('-', ' ')}");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine(" Test Data:");
|
||||
Console.WriteLine(" -------------------------");
|
||||
Console.WriteLine($" Signature: {BitConverter.ToString(DCIH_TD_Signature).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Ascending byte sequence: {BitConverter.ToString(DCIH_TD_AscendingByteSequence).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Descending byte sequence: {BitConverter.ToString(DCIH_TD_DescendingByteSequence).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Filled with 00: {BitConverter.ToString(DCIH_TD_Filled00).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Filled with FF: {BitConverter.ToString(DCIH_TD_FilledFF).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Filled with 0F: {BitConverter.ToString(DCIH_TD_Filled0F).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Filled with F0: {BitConverter.ToString(DCIH_TD_FilledF0).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Filled with 55: {BitConverter.ToString(DCIH_TD_Filled55).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Filled with AA: {BitConverter.ToString(DCIH_TD_FilledAA).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Final byte: {DCIH_TD_FinalByte}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Print NCCH partition header information
|
||||
/// </summary>
|
||||
private void PrintPartitions()
|
||||
{
|
||||
Console.WriteLine(" NCCH Partition Header Information:");
|
||||
Console.WriteLine(" -------------------------");
|
||||
if (Partitions == null || Partitions.Length == 0)
|
||||
{
|
||||
Console.WriteLine(" No NCCH partition headers");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < Partitions.Length; i++)
|
||||
{
|
||||
var partitionHeader = Partitions[i];
|
||||
Console.WriteLine($" NCCH Partition Header {i}");
|
||||
Console.WriteLine($" RSA-2048 SHA-256 signature: {BitConverter.ToString(partitionHeader.RSA2048Signature).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Magic ID: {partitionHeader.MagicID}");
|
||||
Console.WriteLine($" Content size in media units: {partitionHeader.ContentSizeInMediaUnits}");
|
||||
Console.WriteLine($" Partition ID: {partitionHeader.PartitionId}");
|
||||
Console.WriteLine($" Maker code: {partitionHeader.MakerCode}");
|
||||
Console.WriteLine($" Version: {partitionHeader.Version}");
|
||||
Console.WriteLine($" Verification hash: {partitionHeader.VerificationHash}");
|
||||
Console.WriteLine($" Program ID: {BitConverter.ToString(partitionHeader.ProgramId).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Reserved 1: {BitConverter.ToString(partitionHeader.Reserved1).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Logo region SHA-256 hash: {BitConverter.ToString(partitionHeader.LogoRegionHash).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Product code: {BitConverter.ToString(partitionHeader.ProductCode).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Extended header SHA-256 hash: {BitConverter.ToString(partitionHeader.ExtendedHeaderHash).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Extended header size in bytes: {partitionHeader.ExtendedHeaderSizeInBytes}");
|
||||
Console.WriteLine($" Reserved 2: {BitConverter.ToString(partitionHeader.Reserved2).Replace('-', ' ')}");
|
||||
Console.WriteLine($" Flags: {partitionHeader.Flags}");
|
||||
Console.WriteLine($" Plain region offset, in media units: {partitionHeader.PlainRegionOffsetInMediaUnits}");
|
||||
Console.WriteLine($" Plain region size, in media units: {partitionHeader.PlainRegionSizeInMediaUnits}");
|
||||
Console.WriteLine($" Logo region offset, in media units: {partitionHeader.LogoRegionOffsetInMediaUnits}");
|
||||
Console.WriteLine($" Logo region size, in media units: {partitionHeader.LogoRegionSizeInMediaUnits}");
|
||||
Console.WriteLine($" ExeFS offset, in media units: {partitionHeader.ExeFSOffsetInMediaUnits}");
|
||||
Console.WriteLine($" ExeFS size, in media units: {partitionHeader.ExeFSSizeInMediaUnits}");
|
||||
Console.WriteLine($" ExeFS hash region size, in media units: {partitionHeader.ExeFSHashRegionSizeInMediaUnits}");
|
||||
Console.WriteLine($" Reserved 3: {BitConverter.ToString(partitionHeader.Reserved3).Replace('-', ' ')}");
|
||||
Console.WriteLine($" RomFS offset, in media units: {partitionHeader.RomFSOffsetInMediaUnits}");
|
||||
Console.WriteLine($" RomFS size, in media units: {partitionHeader.RomFSSizeInMediaUnits}");
|
||||
Console.WriteLine($" RomFS hash region size, in media units: {partitionHeader.RomFSHashRegionSizeInMediaUnits}");
|
||||
Console.WriteLine($" Reserved 4: {BitConverter.ToString(partitionHeader.Reserved4).Replace('-', ' ')}");
|
||||
Console.WriteLine($" ExeFS superblock SHA-256 hash: {BitConverter.ToString(partitionHeader.ExeFSSuperblockHash).Replace('-', ' ')}");
|
||||
Console.WriteLine($" RomFS superblock SHA-256 hash: {BitConverter.ToString(partitionHeader.RomFSSuperblockHash).Replace('-', ' ')}");
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user