/// <summary> /// Read from a stream and get an NCCH header, if possible /// </summary> /// <param name="reader">BinaryReader representing the input stream</param> /// <param name="readSignature">True if the RSA signature is read, false otherwise</param> /// <returns>NCCH header object, null on error</returns> public static NCCHHeader Read(BinaryReader reader, bool readSignature) { NCCHHeader header = new NCCHHeader(); try { if (readSignature) { header.RSA2048Signature = reader.ReadBytes(0x100); } if (new string(reader.ReadChars(4)) != NCCHMagicNumber) { return(null); } header.ContentSizeInMediaUnits = reader.ReadUInt32(); header.PartitionId = reader.ReadBytes(8).Reverse().ToArray(); header.MakerCode = reader.ReadUInt16(); header.Version = reader.ReadUInt16(); header.VerificationHash = reader.ReadUInt32(); header.ProgramId = reader.ReadBytes(8); header.Reserved1 = reader.ReadBytes(0x10); header.LogoRegionHash = reader.ReadBytes(0x20); header.ProductCode = reader.ReadBytes(0x10); header.ExtendedHeaderHash = reader.ReadBytes(0x20); header.ExtendedHeaderSizeInBytes = reader.ReadUInt32(); header.Reserved2 = reader.ReadBytes(4); header.Flags = NCCHHeaderFlags.Read(reader); header.PlainRegionOffsetInMediaUnits = reader.ReadUInt32(); header.PlainRegionSizeInMediaUnits = reader.ReadUInt32(); header.LogoRegionOffsetInMediaUnits = reader.ReadUInt32(); header.LogoRegionSizeInMediaUnits = reader.ReadUInt32(); header.ExeFSOffsetInMediaUnits = reader.ReadUInt32(); header.ExeFSSizeInMediaUnits = reader.ReadUInt32(); header.ExeFSHashRegionSizeInMediaUnits = reader.ReadUInt32(); header.Reserved3 = reader.ReadBytes(4); header.RomFSOffsetInMediaUnits = reader.ReadUInt32(); header.RomFSSizeInMediaUnits = reader.ReadUInt32(); header.RomFSHashRegionSizeInMediaUnits = reader.ReadUInt32(); header.Reserved4 = reader.ReadBytes(4); header.ExeFSSuperblockHash = reader.ReadBytes(0x20); header.RomFSSuperblockHash = reader.ReadBytes(0x20); return(header); } catch { return(null); } }
/// <summary> /// Read from a stream and get an NCSD header, if possible /// </summary> /// <param name="reader">BinaryReader representing the input stream</param> /// <param name="development">True if development cart, false otherwise</param> /// <returns>NCSD header object, null on error</returns> public static NCSDHeader Read(BinaryReader reader, bool development) { NCSDHeader header = new NCSDHeader(); try { header.RSA2048Signature = reader.ReadBytes(0x100); if (new string(reader.ReadChars(4)) != NCSDMagicNumber) { return(null); } header.ImageSizeInMediaUnits = reader.ReadUInt32(); header.MediaId = reader.ReadBytes(8); header.PartitionsFSType = (FilesystemType)reader.ReadUInt64(); header.PartitionsCryptType = reader.ReadBytes(8); header.PartitionsTable = new PartitionTableEntry[8]; for (int i = 0; i < 8; i++) { header.PartitionsTable[i] = PartitionTableEntry.Read(reader); } if (header.PartitionsFSType == FilesystemType.Normal || header.PartitionsFSType == FilesystemType.None) { header.ExheaderHash = reader.ReadBytes(0x20); header.AdditionalHeaderSize = reader.ReadUInt32(); header.SectorZeroOffset = reader.ReadUInt32(); header.PartitionFlags = reader.ReadBytes(8); header.PartitionIdTable = new byte[8][]; for (int i = 0; i < 8; i++) { header.PartitionIdTable[i] = reader.ReadBytes(8); } header.Reserved1 = reader.ReadBytes(0x20); header.Reserved2 = reader.ReadBytes(0xE); header.FirmUpdateByte1 = reader.ReadByte(); header.FirmUpdateByte2 = reader.ReadByte(); header.CARD2WritableAddressMediaUnits = reader.ReadBytes(4); header.CardInfoBytemask = reader.ReadBytes(4); header.Reserved3 = reader.ReadBytes(0x108); header.TitleVersion = reader.ReadUInt16(); header.CardRevision = reader.ReadUInt16(); header.Reserved4 = reader.ReadBytes(0xCEC); // Incorrectly documented as 0xCEE header.CardSeedKeyY = reader.ReadBytes(0x10); header.EncryptedCardSeed = reader.ReadBytes(0x10); header.CardSeedAESMAC = reader.ReadBytes(0x10); header.CardSeedNonce = reader.ReadBytes(0xC); header.Reserved5 = reader.ReadBytes(0xC4); header.BackupHeader = NCCHHeader.Read(reader, readSignature: false); if (development) { header.CardDeviceReserved1 = reader.ReadBytes(0x200); header.TitleKey = reader.ReadBytes(0x10); header.CardDeviceReserved2 = reader.ReadBytes(0xF0); } } else if (header.PartitionsFSType == FilesystemType.FIRM) { header.Unknown = reader.ReadBytes(0x5E); header.EncryptedMBR = reader.ReadBytes(0x42); } return(header); } catch { return(null); } }
/// <summary> /// Read from a stream and get a CIA header, if possible /// </summary> /// <param name="reader">BinaryReader representing the input stream</param> /// <returns>CIA header object, null on error</returns> public static CIAHeader Read(BinaryReader reader) { CIAHeader header = new CIAHeader(); try { header.HeaderSize = reader.ReadInt32(); header.Type = reader.ReadUInt16(); header.Version = reader.ReadUInt16(); header.CertificateChainSize = reader.ReadInt32(); header.TicketSize = reader.ReadInt32(); header.TMDFileSize = reader.ReadInt32(); header.MetaSize = reader.ReadInt32(); header.ContentSize = reader.ReadInt64(); header.ContentIndex = reader.ReadBytes(0x2000); if (reader.BaseStream.Position % 64 != 0) { reader.BaseStream.Seek(64 - (reader.BaseStream.Position % 64), SeekOrigin.Current); } header.CertificateChain = new Certificate[3]; header.CertificateChain[0] = Certificate.Read(reader); // CA header.CertificateChain[1] = Certificate.Read(reader); // Ticket header.CertificateChain[2] = Certificate.Read(reader); // TMD if (reader.BaseStream.Position % 64 != 0) { reader.BaseStream.Seek(64 - (reader.BaseStream.Position % 64), SeekOrigin.Current); } header.Ticket = Ticket.Read(reader, header.TicketSize); if (reader.BaseStream.Position % 64 != 0) { reader.BaseStream.Seek(64 - (reader.BaseStream.Position % 64), SeekOrigin.Current); } header.TMDFileData = TitleMetadata.Read(reader, header.TMDFileSize); if (reader.BaseStream.Position % 64 != 0) { reader.BaseStream.Seek(64 - (reader.BaseStream.Position % 64), SeekOrigin.Current); } long startingPosition = reader.BaseStream.Position; List <NCCHHeader> headers = new List <NCCHHeader>(); while (reader.BaseStream.Position < startingPosition + header.ContentSize) { long initPosition = reader.BaseStream.Position; NCCHHeader ncchHeader = NCCHHeader.Read(reader, readSignature: true); if (ncchHeader == null) { break; } headers.Add(ncchHeader); reader.BaseStream.Seek(initPosition + ncchHeader.ContentSizeInMediaUnits * 0x200, SeekOrigin.Begin); } header.Partitions = headers.ToArray(); if (header.MetaSize > 0) { header.MetaFileData = MetaFile.Read(reader); } return(header); } catch { return(null); } }