mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-02-04 05:36:12 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e78eecb40 | ||
|
|
3626faea60 | ||
|
|
a0177f1174 | ||
|
|
db5fe4a2cd |
@@ -21,7 +21,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
return null;
|
||||
|
||||
// Cache the current offset
|
||||
int initialOffset = (int)data.Position;
|
||||
long initialOffset = data.Position;
|
||||
|
||||
// Create a new cart image to fill
|
||||
var cart = new Cart();
|
||||
@@ -62,118 +62,72 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Partitions
|
||||
|
||||
// Create the partition table
|
||||
cart.Partitions = new NCCHHeader[8];
|
||||
|
||||
// Iterate and build the partitions
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
cart.Partitions[i] = ParseNCCHHeader(data);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Cache the media unit size for further use
|
||||
long mediaUnitSize = 0;
|
||||
if (header.PartitionFlags != null)
|
||||
mediaUnitSize = (uint)(0x200 * Math.Pow(2, header.PartitionFlags[(int)NCSDFlags.MediaUnitSize]));
|
||||
|
||||
#region Extended Headers
|
||||
#region Partitions
|
||||
|
||||
// Create the extended header table
|
||||
// Create the tables
|
||||
cart.Partitions = new NCCHHeader[8];
|
||||
cart.ExtendedHeaders = new NCCHExtendedHeader?[8];
|
||||
|
||||
// Iterate and build the extended headers
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
// If we have an encrypted or invalid partition
|
||||
if (cart.Partitions[i]!.MagicID != NCCHMagicNumber)
|
||||
continue;
|
||||
|
||||
// If we have no partitions table
|
||||
if (cart.Header!.PartitionsTable == null)
|
||||
continue;
|
||||
|
||||
// Get the extended header offset
|
||||
long offset = (cart.Header.PartitionsTable[i]!.Offset * mediaUnitSize) + 0x200;
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
continue;
|
||||
|
||||
// Seek to the extended header
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Parse the extended header
|
||||
var extendedHeader = ParseNCCHExtendedHeader(data);
|
||||
if (extendedHeader != null)
|
||||
cart.ExtendedHeaders[i] = extendedHeader;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ExeFS Headers
|
||||
|
||||
// Create the ExeFS header table
|
||||
cart.ExeFSHeaders = new ExeFSHeader?[8];
|
||||
|
||||
// Iterate and build the ExeFS headers
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
// If we have an encrypted or invalid partition
|
||||
if (cart.Partitions[i]!.MagicID != NCCHMagicNumber)
|
||||
continue;
|
||||
|
||||
// If we have no partitions table
|
||||
if (cart.Header!.PartitionsTable == null)
|
||||
continue;
|
||||
|
||||
// Get the ExeFS header offset
|
||||
long offset = (cart.Header.PartitionsTable[i]!.Offset + cart.Partitions[i]!.ExeFSOffsetInMediaUnits) * mediaUnitSize;
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
continue;
|
||||
|
||||
// Seek to the ExeFS header
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Parse the ExeFS header
|
||||
var exeFsHeader = ParseExeFSHeader(data);
|
||||
if (exeFsHeader == null)
|
||||
return null;
|
||||
|
||||
cart.ExeFSHeaders[i] = exeFsHeader;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RomFS Headers
|
||||
|
||||
// Create the RomFS header table
|
||||
cart.RomFSHeaders = new RomFSHeader?[8];
|
||||
|
||||
// Iterate and build the RomFS headers
|
||||
// Iterate and build the partitions
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
// If we have an encrypted or invalid partition
|
||||
if (cart.Partitions[i]!.MagicID != NCCHMagicNumber)
|
||||
// Cache the offset of the partition
|
||||
initialOffset = data.Position;
|
||||
|
||||
// Handle the normal header
|
||||
var partition = ParseNCCHHeader(data);
|
||||
if (partition == null || partition.MagicID != NCCHMagicNumber)
|
||||
continue;
|
||||
|
||||
// If we have no partitions table
|
||||
if (cart.Header!.PartitionsTable == null)
|
||||
continue;
|
||||
// Set the normal header
|
||||
cart.Partitions[i] = partition;
|
||||
|
||||
// Get the RomFS header offset
|
||||
long offset = (cart.Header.PartitionsTable[i]!.Offset + cart.Partitions[i]!.RomFSOffsetInMediaUnits) * mediaUnitSize;
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
continue;
|
||||
// Handle the extended header, if it exists
|
||||
if (partition.ExtendedHeaderSizeInBytes > 0)
|
||||
{
|
||||
var extendedHeader = ParseNCCHExtendedHeader(data);
|
||||
if (extendedHeader != null)
|
||||
cart.ExtendedHeaders[i] = extendedHeader;
|
||||
}
|
||||
|
||||
// Seek to the RomFS header
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
// Handle the ExeFS, if it exists
|
||||
if (partition.ExeFSSizeInMediaUnits > 0)
|
||||
{
|
||||
long offset = partition.ExeFSOffsetInMediaUnits * mediaUnitSize;
|
||||
data.Seek(initialOffset + offset, SeekOrigin.Begin);
|
||||
|
||||
var exeFsHeader = ParseExeFSHeader(data);
|
||||
if (exeFsHeader == null)
|
||||
return null;
|
||||
|
||||
cart.ExeFSHeaders[i] = exeFsHeader;
|
||||
}
|
||||
|
||||
// Handle the RomFS, if it exists
|
||||
if (partition.RomFSSizeInMediaUnits > 0)
|
||||
{
|
||||
long offset = partition.RomFSOffsetInMediaUnits * mediaUnitSize;
|
||||
data.Seek(initialOffset + offset, SeekOrigin.Begin);
|
||||
|
||||
var romFsHeader = ParseRomFSHeader(data);
|
||||
if (romFsHeader == null)
|
||||
continue;
|
||||
else if (romFsHeader.MagicString != RomFSMagicNumber || romFsHeader.MagicNumber != RomFSSecondMagicNumber)
|
||||
continue;
|
||||
|
||||
// Parse the RomFS header
|
||||
var romFsHeader = ParseRomFSHeader(data);
|
||||
if (romFsHeader != null)
|
||||
cart.RomFSHeaders[i] = romFsHeader;
|
||||
}
|
||||
|
||||
// Skip past other data
|
||||
long partitionSize = partition.ContentSizeInMediaUnits * mediaUnitSize;
|
||||
data.Seek(initialOffset + partitionSize, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>1.7.1</Version>
|
||||
<Version>1.7.2</Version>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
|
||||
@@ -16,6 +16,11 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#region Extension Properties
|
||||
|
||||
/// <summary>
|
||||
/// Backup header
|
||||
/// </summary>
|
||||
public NCCHHeader? BackupHeader => Model.CardInfoHeader?.InitialData?.BackupHeader;
|
||||
|
||||
/// <summary>
|
||||
/// Backup Write Wait Time (The time to wait to write save to backup after the card is recognized (0-255
|
||||
/// seconds)). NATIVE_FIRM loads this flag from the gamecard NCSD header starting with 6.0.0-11.
|
||||
@@ -243,6 +248,23 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#region Data
|
||||
|
||||
/// <summary>
|
||||
/// Get the bit masks for a partition
|
||||
/// </summary>
|
||||
public BitMasks GetBitMasks(int partitionIndex)
|
||||
{
|
||||
if (Model.Partitions == null)
|
||||
return 0;
|
||||
if (partitionIndex < 0 || partitionIndex >= Model.Partitions.Length)
|
||||
return 0;
|
||||
|
||||
var partition = Model.Partitions[partitionIndex];
|
||||
if (partition?.Flags == null)
|
||||
return 0;
|
||||
|
||||
return partition.Flags.BitMasks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a file header represents a CODE block
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user