From af40c78b560aa7c10853400cc7c2b8a1d2b98803 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 23 Apr 2024 21:45:54 -0400 Subject: [PATCH] Handle more directly-marshalled types --- .../Deserializers/BFPK.cs | 2 +- SabreTools.Serialization/Deserializers/CFB.cs | 67 +--- SabreTools.Serialization/Deserializers/CIA.cs | 70 +--- SabreTools.Serialization/Deserializers/GCF.cs | 25 +- .../Deserializers/MoPaQ.cs | 25 +- .../Deserializers/N3DS.cs | 357 ++---------------- SabreTools.Serialization/Deserializers/NCF.cs | 20 +- .../Deserializers/Nitro.cs | 155 +------- .../Deserializers/PortableExecutable.cs | 21 +- .../Deserializers/VBSP.cs | 2 +- SabreTools.Serialization/Deserializers/VPK.cs | 15 +- SabreTools.Serialization/Deserializers/WAD.cs | 34 +- SabreTools.Serialization/Deserializers/XZP.cs | 27 +- .../Extensions.PortableExecutable.cs | 37 +- 14 files changed, 132 insertions(+), 725 deletions(-) diff --git a/SabreTools.Serialization/Deserializers/BFPK.cs b/SabreTools.Serialization/Deserializers/BFPK.cs index 797c8f59..d3607500 100644 --- a/SabreTools.Serialization/Deserializers/BFPK.cs +++ b/SabreTools.Serialization/Deserializers/BFPK.cs @@ -85,7 +85,7 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled file entry on success, null on error - private static FileEntry ParseFileEntry(Stream data) + private static FileEntry? ParseFileEntry(Stream data) { // TODO: Use marshalling here instead of building var fileEntry = new FileEntry(); diff --git a/SabreTools.Serialization/Deserializers/CFB.cs b/SabreTools.Serialization/Deserializers/CFB.cs index 0f434977..5029755c 100644 --- a/SabreTools.Serialization/Deserializers/CFB.cs +++ b/SabreTools.Serialization/Deserializers/CFB.cs @@ -42,7 +42,7 @@ namespace SabreTools.Serialization.Deserializers #region DIFAT Sector Numbers // Create a DIFAT sector table - var difatSectors = new List(); + var difatSectors = new List(); // Add the sectors from the header if (fileHeader.DIFAT != null) @@ -84,7 +84,7 @@ namespace SabreTools.Serialization.Deserializers #region FAT Sector Numbers // Create a FAT sector table - var fatSectors = new List(); + var fatSectors = new List(); // Loop through and add the FAT sectors currentSector = binary.DIFATSectorNumbers[0]; @@ -122,7 +122,7 @@ namespace SabreTools.Serialization.Deserializers #region Mini FAT Sector Numbers // Create a mini FAT sector table - var miniFatSectors = new List(); + var miniFatSectors = new List(); // Loop through and add the mini FAT sectors currentSector = (SectorNumber)fileHeader.FirstMiniFATSectorLocation; @@ -233,49 +233,23 @@ namespace SabreTools.Serialization.Deserializers /// Filled file header on success, null on error private static FileHeader? ParseFileHeader(Stream data) { - // TODO: Use marshalling here instead of building - var header = new FileHeader(); + var header = data.ReadType(); - header.Signature = data.ReadUInt64(); + if (header == null) + return null; if (header.Signature != SignatureUInt64) return null; - - header.CLSID = data.ReadGuid(); - header.MinorVersion = data.ReadUInt16(); - header.MajorVersion = data.ReadUInt16(); - header.ByteOrder = data.ReadUInt16(); if (header.ByteOrder != 0xFFFE) return null; - - header.SectorShift = data.ReadUInt16(); if (header.MajorVersion == 3 && header.SectorShift != 0x0009) return null; else if (header.MajorVersion == 4 && header.SectorShift != 0x000C) return null; - - header.MiniSectorShift = data.ReadUInt16(); - header.Reserved = data.ReadBytes(6); - header.NumberOfDirectorySectors = data.ReadUInt32(); if (header.MajorVersion == 3 && header.NumberOfDirectorySectors != 0) return null; - - header.NumberOfFATSectors = data.ReadUInt32(); - header.FirstDirectorySectorLocation = data.ReadUInt32(); - header.TransactionSignatureNumber = data.ReadUInt32(); - header.MiniStreamCutoffSize = data.ReadUInt32(); if (header.MiniStreamCutoffSize != 0x00001000) return null; - header.FirstMiniFATSectorLocation = data.ReadUInt32(); - header.NumberOfMiniFATSectors = data.ReadUInt32(); - header.FirstDIFATSectorLocation = data.ReadUInt32(); - header.NumberOfDIFATSectors = data.ReadUInt32(); - header.DIFAT = new SectorNumber?[109]; - for (int i = 0; i < header.DIFAT.Length; i++) - { - header.DIFAT[i] = (SectorNumber)data.ReadUInt32(); - } - // Skip rest of sector for version 4 if (header.MajorVersion == 4) _ = data.ReadBytes(3584); @@ -289,11 +263,11 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Sector shift from the header /// Filled sector full of sector numbers on success, null on error - private static SectorNumber?[] ParseSectorNumbers(Stream data, ushort sectorShift) + private static SectorNumber[] ParseSectorNumbers(Stream data, ushort sectorShift) { // TODO: Use marshalling here instead of building int sectorCount = (int)(Math.Pow(2, sectorShift) / sizeof(uint)); - var sectorNumbers = new SectorNumber?[sectorCount]; + var sectorNumbers = new SectorNumber[sectorCount]; for (int i = 0; i < sectorNumbers.Length; i++) { @@ -337,24 +311,15 @@ namespace SabreTools.Serialization.Deserializers /// Filled directory entry on success, null on error private static DirectoryEntry? ParseDirectoryEntry(Stream data, ushort majorVersion) { - // TODO: Use marshalling here instead of building - var directoryEntry = new DirectoryEntry(); + var directoryEntry = data.ReadType(); - byte[]? name = data.ReadBytes(64); - if (name != null) - directoryEntry.Name = Encoding.Unicode.GetString(name).TrimEnd('\0'); - directoryEntry.NameLength = data.ReadUInt16(); - directoryEntry.ObjectType = (ObjectType)data.ReadByteValue(); - directoryEntry.ColorFlag = (ColorFlag)data.ReadByteValue(); - directoryEntry.LeftSiblingID = (StreamID)data.ReadUInt32(); - directoryEntry.RightSiblingID = (StreamID)data.ReadUInt32(); - directoryEntry.ChildID = (StreamID)data.ReadUInt32(); - directoryEntry.CLSID = data.ReadGuid(); - directoryEntry.StateBits = data.ReadUInt32(); - directoryEntry.CreationTime = data.ReadUInt64(); - directoryEntry.ModifiedTime = data.ReadUInt64(); - directoryEntry.StartingSectorLocation = data.ReadUInt32(); - directoryEntry.StreamSize = data.ReadUInt64(); + if (directoryEntry == null) + return null; + + // TEMPORARY FIX FOR ASCII -> UNICODE + directoryEntry.Name = Encoding.Unicode.GetString(Encoding.ASCII.GetBytes(directoryEntry.Name)); + + // Handle version 3 entries if (majorVersion == 3) directoryEntry.StreamSize &= 0x0000FFFF; diff --git a/SabreTools.Serialization/Deserializers/CIA.cs b/SabreTools.Serialization/Deserializers/CIA.cs index 108ae7ee..a5ee3d1e 100644 --- a/SabreTools.Serialization/Deserializers/CIA.cs +++ b/SabreTools.Serialization/Deserializers/CIA.cs @@ -145,22 +145,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled CIA header on success, null on error - private static CIAHeader ParseCIAHeader(Stream data) + public static CIAHeader? ParseCIAHeader(Stream data) { - // TODO: Use marshalling here instead of building - CIAHeader ciaHeader = new CIAHeader(); - - ciaHeader.HeaderSize = data.ReadUInt32(); - ciaHeader.Type = data.ReadUInt16(); - ciaHeader.Version = data.ReadUInt16(); - ciaHeader.CertificateChainSize = data.ReadUInt32(); - ciaHeader.TicketSize = data.ReadUInt32(); - ciaHeader.TMDFileSize = data.ReadUInt32(); - ciaHeader.MetaSize = data.ReadUInt32(); - ciaHeader.ContentSize = data.ReadUInt64(); - ciaHeader.ContentIndex = data.ReadBytes(0x2000); - - return ciaHeader; + return data.ReadType(); } /// @@ -168,7 +155,7 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled certificate on success, null on error - private static Certificate? ParseCertificate(Stream data) + public static Certificate? ParseCertificate(Stream data) { // TODO: Use marshalling here instead of building Certificate certificate = new Certificate(); @@ -244,7 +231,7 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Indicates if the ticket is from CDN /// Filled ticket on success, null on error - private static Ticket? ParseTicket(Stream data, bool fromCdn = false) + public static Ticket? ParseTicket(Stream data, bool fromCdn = false) { // TODO: Use marshalling here instead of building Ticket ticket = new Ticket(); @@ -349,10 +336,10 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Indicates if the ticket is from CDN /// Filled title metadata on success, null on error - private static TitleMetadata? ParseTitleMetadata(Stream data, bool fromCdn = false) + public static TitleMetadata? ParseTitleMetadata(Stream data, bool fromCdn = false) { // TODO: Use marshalling here instead of building - TitleMetadata titleMetadata = new TitleMetadata(); + var titleMetadata = new TitleMetadata(); titleMetadata.SignatureType = (SignatureType)data.ReadUInt32(); switch (titleMetadata.SignatureType) @@ -420,11 +407,19 @@ namespace SabreTools.Serialization.Deserializers titleMetadata.ContentInfoRecords = new ContentInfoRecord[64]; for (int i = 0; i < 64; i++) { + var contentInfoRecord = ParseContentInfoRecord(data); + if (contentInfoRecord == null) + return null; + titleMetadata.ContentInfoRecords[i] = ParseContentInfoRecord(data); } titleMetadata.ContentChunkRecords = new ContentChunkRecord[titleMetadata.ContentCount]; for (int i = 0; i < titleMetadata.ContentCount; i++) { + var contentChunkRecord = ParseContentChunkRecord(data); + if (contentChunkRecord == null) + return null; + titleMetadata.ContentChunkRecords[i] = ParseContentChunkRecord(data); } @@ -450,16 +445,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled content info record on success, null on error - private static ContentInfoRecord ParseContentInfoRecord(Stream data) + public static ContentInfoRecord? ParseContentInfoRecord(Stream data) { - // TODO: Use marshalling here instead of building - ContentInfoRecord contentInfoRecord = new ContentInfoRecord(); - - contentInfoRecord.ContentIndexOffset = data.ReadUInt16(); - contentInfoRecord.ContentCommandCount = data.ReadUInt16(); - contentInfoRecord.UnhashedContentRecordsSHA256Hash = data.ReadBytes(0x20); - - return contentInfoRecord; + return data.ReadType(); } /// @@ -467,18 +455,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled content chunk record on success, null on error - private static ContentChunkRecord ParseContentChunkRecord(Stream data) + public static ContentChunkRecord? ParseContentChunkRecord(Stream data) { - // TODO: Use marshalling here instead of building - ContentChunkRecord contentChunkRecord = new ContentChunkRecord(); - - contentChunkRecord.ContentId = data.ReadUInt32(); - contentChunkRecord.ContentIndex = (ContentIndex)data.ReadUInt16(); - contentChunkRecord.ContentType = (TMDContentType)data.ReadUInt16(); - contentChunkRecord.ContentSize = data.ReadUInt64(); - contentChunkRecord.SHA256Hash = data.ReadBytes(0x20); - - return contentChunkRecord; + return data.ReadType(); } /// @@ -486,18 +465,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled meta data on success, null on error - private static MetaData ParseMetaData(Stream data) + public static MetaData? ParseMetaData(Stream data) { - // TODO: Use marshalling here instead of building - MetaData metaData = new MetaData(); - - metaData.TitleIDDependencyList = data.ReadBytes(0x180); - metaData.Reserved1 = data.ReadBytes(0x180); - metaData.CoreVersion = data.ReadUInt32(); - metaData.Reserved2 = data.ReadBytes(0xFC); - metaData.IconData = data.ReadBytes(0x36C0); - - return metaData; + return data.ReadType(); } } } \ No newline at end of file diff --git a/SabreTools.Serialization/Deserializers/GCF.cs b/SabreTools.Serialization/Deserializers/GCF.cs index ed6dccf7..c2e7cca1 100644 --- a/SabreTools.Serialization/Deserializers/GCF.cs +++ b/SabreTools.Serialization/Deserializers/GCF.cs @@ -154,6 +154,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.ItemCount; i++) { var directoryEntry = ParseDirectoryEntry(data); + if (directoryEntry == null) + return null; + file.DirectoryEntries[i] = directoryEntry; } @@ -189,13 +192,6 @@ namespace SabreTools.Serialization.Deserializers file.DirectoryNames[nameOffset] = directoryName; } - - // Loop and assign to entries - foreach (var directoryEntry in file.DirectoryEntries) - { - if (directoryEntry != null) - directoryEntry.Name = file.DirectoryNames[directoryEntry.NameOffset]; - } } #endregion @@ -478,20 +474,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache directory entry on success, null on error - private static DirectoryEntry ParseDirectoryEntry(Stream data) + private static DirectoryEntry? ParseDirectoryEntry(Stream data) { - // TODO: Use marshalling here instead of building - var directoryEntry = new DirectoryEntry(); - - directoryEntry.NameOffset = data.ReadUInt32(); - directoryEntry.ItemSize = data.ReadUInt32(); - directoryEntry.ChecksumIndex = data.ReadUInt32(); - directoryEntry.DirectoryFlags = (HL_GCF_FLAG)data.ReadUInt32(); - directoryEntry.ParentIndex = data.ReadUInt32(); - directoryEntry.NextIndex = data.ReadUInt32(); - directoryEntry.FirstIndex = data.ReadUInt32(); - - return directoryEntry; + return data.ReadType(); } /// diff --git a/SabreTools.Serialization/Deserializers/MoPaQ.cs b/SabreTools.Serialization/Deserializers/MoPaQ.cs index 517546b1..e68c5d37 100644 --- a/SabreTools.Serialization/Deserializers/MoPaQ.cs +++ b/SabreTools.Serialization/Deserializers/MoPaQ.cs @@ -404,20 +404,13 @@ namespace SabreTools.Serialization.Deserializers /// Filled user data on success, null on error private static UserData? ParseUserData(Stream data) { - var userData = new UserData(); + var userData = data.ReadType(); - byte[]? signature = data.ReadBytes(4); - if (signature == null) + if (userData == null) return null; - - userData.Signature = Encoding.ASCII.GetString(signature); if (userData.Signature != UserDataSignatureString) return null; - userData.UserDataSize = data.ReadUInt32(); - userData.HeaderOffset = data.ReadUInt32(); - userData.UserDataHeaderSize = data.ReadUInt32(); - return userData; } @@ -539,19 +532,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled patch info on success, null on error - private static PatchInfo ParsePatchInfo(Stream data) + private static PatchInfo? ParsePatchInfo(Stream data) { - // TODO: Use marshalling here instead of building - var patchInfo = new PatchInfo(); - - patchInfo.Length = data.ReadUInt32(); - patchInfo.Flags = data.ReadUInt32(); - patchInfo.DataSize = data.ReadUInt32(); - patchInfo.MD5 = data.ReadBytes(0x10); - - // TODO: Fill the sector offset table - - return patchInfo; + return data.ReadType(); } #region Helpers diff --git a/SabreTools.Serialization/Deserializers/N3DS.cs b/SabreTools.Serialization/Deserializers/N3DS.cs index 48adaa08..98935e55 100644 --- a/SabreTools.Serialization/Deserializers/N3DS.cs +++ b/SabreTools.Serialization/Deserializers/N3DS.cs @@ -186,7 +186,7 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled NCSD header on success, null on error - private static NCSDHeader? ParseNCSDHeader(Stream data) + public static NCSDHeader? ParseNCSDHeader(Stream data) { // TODO: Use marshalling here instead of building var header = new NCSDHeader(); @@ -208,7 +208,11 @@ namespace SabreTools.Serialization.Deserializers header.PartitionsTable = new PartitionTableEntry[8]; for (int i = 0; i < 8; i++) { - header.PartitionsTable[i] = ParsePartitionTableEntry(data); + var partitionTableEntry = ParsePartitionTableEntry(data); + if (partitionTableEntry == null) + return null; + + header.PartitionsTable[i] = partitionTableEntry; } if (header.PartitionsFSType == FilesystemType.Normal || header.PartitionsFSType == FilesystemType.None) @@ -243,15 +247,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled partition table entry on success, null on error - private static PartitionTableEntry ParsePartitionTableEntry(Stream data) + public static PartitionTableEntry? ParsePartitionTableEntry(Stream data) { - // TODO: Use marshalling here instead of building - var partitionTableEntry = new PartitionTableEntry(); - - partitionTableEntry.Offset = data.ReadUInt32(); - partitionTableEntry.Length = data.ReadUInt32(); - - return partitionTableEntry; + return data.ReadType(); } /// @@ -259,24 +257,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled card info header on success, null on error - private static CardInfoHeader ParseCardInfoHeader(Stream data) + public static CardInfoHeader? ParseCardInfoHeader(Stream data) { - // TODO: Use marshalling here instead of building - var 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; + return data.ReadType(); } /// @@ -284,46 +267,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled development card info header on success, null on error - private static DevelopmentCardInfoHeader? ParseDevelopmentCardInfoHeader(Stream data) + public static DevelopmentCardInfoHeader? ParseDevelopmentCardInfoHeader(Stream data) { - // TODO: Use marshalling here instead of building - var 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; - } - - /// - /// Parse a Stream into an initial data - /// - /// Stream to parse - /// Filled initial data on success, null on error - private static InitialData? ParseInitialData(Stream data) - { - // TODO: Use marshalling here instead of building - var 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; + return data.ReadType(); } /// @@ -332,7 +278,7 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Indicates if the signature should be skipped /// Filled NCCH header on success, null on error - internal static NCCHHeader ParseNCCHHeader(Stream data, bool skipSignature = false) + public static NCCHHeader ParseNCCHHeader(Stream data, bool skipSignature = false) { // TODO: Use marshalling here instead of building var header = new NCCHHeader(); @@ -356,7 +302,7 @@ namespace SabreTools.Serialization.Deserializers header.ProductCode = Encoding.ASCII.GetString(productCode).TrimEnd('\0'); header.ExtendedHeaderHash = data.ReadBytes(0x20); header.ExtendedHeaderSizeInBytes = data.ReadUInt32(); - header.Reserved2 = data.ReadBytes(4); + header.Reserved2 = data.ReadUInt32(); header.Flags = ParseNCCHHeaderFlags(data); header.PlainRegionOffsetInMediaUnits = data.ReadUInt32(); header.PlainRegionSizeInMediaUnits = data.ReadUInt32(); @@ -365,11 +311,11 @@ namespace SabreTools.Serialization.Deserializers header.ExeFSOffsetInMediaUnits = data.ReadUInt32(); header.ExeFSSizeInMediaUnits = data.ReadUInt32(); header.ExeFSHashRegionSizeInMediaUnits = data.ReadUInt32(); - header.Reserved3 = data.ReadBytes(4); + header.Reserved3 = data.ReadUInt32(); header.RomFSOffsetInMediaUnits = data.ReadUInt32(); header.RomFSSizeInMediaUnits = data.ReadUInt32(); header.RomFSHashRegionSizeInMediaUnits = data.ReadUInt32(); - header.Reserved4 = data.ReadBytes(4); + header.Reserved4 = data.ReadUInt32(); header.ExeFSSuperblockHash = data.ReadBytes(0x20); header.RomFSSuperblockHash = data.ReadBytes(0x20); @@ -381,46 +327,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled NCCH header flags on success, null on error - private static NCCHHeaderFlags ParseNCCHHeaderFlags(Stream data) + public static NCCHHeaderFlags? ParseNCCHHeaderFlags(Stream data) { - // TODO: Use marshalling here instead of building - var headerFlags = new NCCHHeaderFlags(); - - headerFlags.Reserved0 = data.ReadByteValue(); - headerFlags.Reserved1 = data.ReadByteValue(); - headerFlags.Reserved2 = data.ReadByteValue(); - headerFlags.CryptoMethod = (CryptoMethod)data.ReadByteValue(); - headerFlags.ContentPlatform = (ContentPlatform)data.ReadByteValue(); - headerFlags.MediaPlatformIndex = (ContentType)data.ReadByteValue(); - headerFlags.ContentUnitSize = data.ReadByteValue(); - headerFlags.BitMasks = (BitMasks)data.ReadByteValue(); - - return headerFlags; - } - - /// - /// Parse a Stream into an initial data - /// - /// Stream to parse - /// Filled initial data on success, null on error - private static TestData ParseTestData(Stream data) - { - // TODO: Use marshalling here instead of building - var 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; + return data.ReadType(); } /// @@ -428,203 +337,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled NCCH extended header on success, null on error - private static NCCHExtendedHeader? ParseNCCHExtendedHeader(Stream data) + public static NCCHExtendedHeader? ParseNCCHExtendedHeader(Stream data) { - // TODO: Use marshalling here instead of building - var extendedHeader = new NCCHExtendedHeader(); - - extendedHeader.SCI = ParseSystemControlInfo(data); - if (extendedHeader.SCI == null) - return null; - - extendedHeader.ACI = ParseAccessControlInfo(data); - if (extendedHeader.ACI == null) - return null; - - extendedHeader.AccessDescSignature = data.ReadBytes(0x100); - extendedHeader.NCCHHDRPublicKey = data.ReadBytes(0x100); - - extendedHeader.ACIForLimitations = ParseAccessControlInfo(data); - if (extendedHeader.ACI == null) - return null; - - return extendedHeader; - } - - /// - /// Parse a Stream into a system control info - /// - /// Stream to parse - /// Filled system control info on success, null on error - private static SystemControlInfo ParseSystemControlInfo(Stream data) - { - // TODO: Use marshalling here instead of building - var systemControlInfo = new SystemControlInfo(); - - byte[]? applicationTitle = data.ReadBytes(8); - if (applicationTitle != null) - systemControlInfo.ApplicationTitle = Encoding.ASCII.GetString(applicationTitle).TrimEnd('\0'); - systemControlInfo.Reserved1 = data.ReadBytes(5); - systemControlInfo.Flag = data.ReadByteValue(); - systemControlInfo.RemasterVersion = data.ReadUInt16(); - systemControlInfo.TextCodeSetInfo = ParseCodeSetInfo(data); - systemControlInfo.StackSize = data.ReadUInt32(); - systemControlInfo.ReadOnlyCodeSetInfo = ParseCodeSetInfo(data); - systemControlInfo.Reserved2 = data.ReadBytes(4); - systemControlInfo.DataCodeSetInfo = ParseCodeSetInfo(data); - systemControlInfo.BSSSize = data.ReadUInt32(); - systemControlInfo.DependencyModuleList = new ulong[48]; - for (int i = 0; i < 48; i++) - { - systemControlInfo.DependencyModuleList[i] = data.ReadUInt64(); - } - systemControlInfo.SystemInfo = ParseSystemInfo(data); - - return systemControlInfo; - } - - /// - /// Parse a Stream into a code set info - /// - /// Stream to parse - /// Filled code set info on success, null on error - private static CodeSetInfo ParseCodeSetInfo(Stream data) - { - // TODO: Use marshalling here instead of building - var codeSetInfo = new CodeSetInfo(); - - codeSetInfo.Address = data.ReadUInt32(); - codeSetInfo.PhysicalRegionSizeInPages = data.ReadUInt32(); - codeSetInfo.SizeInBytes = data.ReadUInt32(); - - return codeSetInfo; - } - - /// - /// Parse a Stream into a system info - /// - /// Stream to parse - /// Filled system info on success, null on error - private static SystemInfo ParseSystemInfo(Stream data) - { - // TODO: Use marshalling here instead of building - var systemInfo = new SystemInfo(); - - systemInfo.SaveDataSize = data.ReadUInt64(); - systemInfo.JumpID = data.ReadUInt64(); - systemInfo.Reserved = data.ReadBytes(0x30); - - return systemInfo; - } - - /// - /// Parse a Stream into an access control info - /// - /// Stream to parse - /// Filled access control info on success, null on error - private static AccessControlInfo ParseAccessControlInfo(Stream data) - { - // TODO: Use marshalling here instead of building - var accessControlInfo = new AccessControlInfo(); - - accessControlInfo.ARM11LocalSystemCapabilities = ParseARM11LocalSystemCapabilities(data); - accessControlInfo.ARM11KernelCapabilities = ParseARM11KernelCapabilities(data); - accessControlInfo.ARM9AccessControl = ParseARM9AccessControl(data); - - return accessControlInfo; - } - - /// - /// Parse a Stream into an ARM11 local system capabilities - /// - /// Stream to parse - /// Filled ARM11 local system capabilities on success, null on error - private static ARM11LocalSystemCapabilities ParseARM11LocalSystemCapabilities(Stream data) - { - // TODO: Use marshalling here instead of building - var arm11LocalSystemCapabilities = new ARM11LocalSystemCapabilities(); - - arm11LocalSystemCapabilities.ProgramID = data.ReadUInt64(); - arm11LocalSystemCapabilities.CoreVersion = data.ReadUInt32(); - arm11LocalSystemCapabilities.Flag1 = (ARM11LSCFlag1)data.ReadByteValue(); - arm11LocalSystemCapabilities.Flag2 = (ARM11LSCFlag2)data.ReadByteValue(); - arm11LocalSystemCapabilities.Flag0 = (ARM11LSCFlag0)data.ReadByteValue(); - arm11LocalSystemCapabilities.Priority = data.ReadByteValue(); - arm11LocalSystemCapabilities.ResourceLimitDescriptors = new ushort[16]; - for (int i = 0; i < 16; i++) - { - arm11LocalSystemCapabilities.ResourceLimitDescriptors[i] = data.ReadUInt16(); - } - arm11LocalSystemCapabilities.StorageInfo = ParseStorageInfo(data); - arm11LocalSystemCapabilities.ServiceAccessControl = new ulong[32]; - for (int i = 0; i < 32; i++) - { - arm11LocalSystemCapabilities.ServiceAccessControl[i] = data.ReadUInt64(); - } - arm11LocalSystemCapabilities.ExtendedServiceAccessControl = new ulong[2]; - for (int i = 0; i < 2; i++) - { - arm11LocalSystemCapabilities.ExtendedServiceAccessControl[i] = data.ReadUInt64(); - } - arm11LocalSystemCapabilities.Reserved = data.ReadBytes(0x0F); - arm11LocalSystemCapabilities.ResourceLimitCategory = (ResourceLimitCategory)data.ReadByteValue(); - - return arm11LocalSystemCapabilities; - } - - /// - /// Parse a Stream into a storage info - /// - /// Stream to parse - /// Filled storage info on success, null on error - private static StorageInfo ParseStorageInfo(Stream data) - { - // TODO: Use marshalling here instead of building - var storageInfo = new StorageInfo(); - - storageInfo.ExtdataID = data.ReadUInt64(); - storageInfo.SystemSavedataIDs = data.ReadBytes(8); - storageInfo.StorageAccessibleUniqueIDs = data.ReadBytes(8); - storageInfo.FileSystemAccessInfo = data.ReadBytes(7); - storageInfo.OtherAttributes = (StorageInfoOtherAttributes)data.ReadByteValue(); - - return storageInfo; - } - - /// - /// Parse a Stream into an ARM11 kernel capabilities - /// - /// Stream to parse - /// Filled ARM11 kernel capabilities on success, null on error - private static ARM11KernelCapabilities ParseARM11KernelCapabilities(Stream data) - { - // TODO: Use marshalling here instead of building - var arm11KernelCapabilities = new ARM11KernelCapabilities(); - - arm11KernelCapabilities.Descriptors = new uint[28]; - for (int i = 0; i < 28; i++) - { - arm11KernelCapabilities.Descriptors[i] = data.ReadUInt32(); - } - arm11KernelCapabilities.Reserved = data.ReadBytes(0x10); - - return arm11KernelCapabilities; - } - - /// - /// Parse a Stream into an ARM11 access control - /// - /// Stream to parse - /// Filled ARM11 access control on success, null on error - private static ARM9AccessControl ParseARM9AccessControl(Stream data) - { - // TODO: Use marshalling here instead of building - var arm9AccessControl = new ARM9AccessControl(); - - arm9AccessControl.Descriptors = data.ReadBytes(15); - arm9AccessControl.DescriptorVersion = data.ReadByteValue(); - - return arm9AccessControl; + return data.ReadType(); } /// @@ -632,7 +347,7 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled ExeFS header on success, null on error - private static ExeFSHeader? ParseExeFSHeader(Stream data) + public static ExeFSHeader? ParseExeFSHeader(Stream data) { // TODO: Use marshalling here instead of building var exeFSHeader = new ExeFSHeader(); @@ -661,7 +376,7 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled ExeFS file header on success, null on error - private static ExeFSFileHeader? ParseExeFSFileHeader(Stream data) + public static ExeFSFileHeader? ParseExeFSFileHeader(Stream data) { // TODO: Use marshalling here instead of building var exeFSFileHeader = new ExeFSFileHeader(); @@ -680,39 +395,17 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled RomFS header on success, null on error - private static RomFSHeader? ParseRomFSHeader(Stream data) + public static RomFSHeader? ParseRomFSHeader(Stream data) { - // TODO: Use marshalling here instead of building - var romFSHeader = new RomFSHeader(); + var romFSHeader = data.ReadType(); - byte[]? magicString = data.ReadBytes(4); - if (magicString == null) + if (romFSHeader == null) return null; - - romFSHeader.MagicString = Encoding.ASCII.GetString(magicString).TrimEnd('\0'); if (romFSHeader.MagicString != RomFSMagicNumber) return null; - - romFSHeader.MagicNumber = data.ReadUInt32(); if (romFSHeader.MagicNumber != RomFSSecondMagicNumber) return null; - romFSHeader.MasterHashSize = data.ReadUInt32(); - romFSHeader.Level1LogicalOffset = data.ReadUInt64(); - romFSHeader.Level1HashdataSize = data.ReadUInt64(); - romFSHeader.Level1BlockSizeLog2 = data.ReadUInt32(); - romFSHeader.Reserved1 = data.ReadBytes(4); - romFSHeader.Level2LogicalOffset = data.ReadUInt64(); - romFSHeader.Level2HashdataSize = data.ReadUInt64(); - romFSHeader.Level2BlockSizeLog2 = data.ReadUInt32(); - romFSHeader.Reserved2 = data.ReadBytes(4); - romFSHeader.Level3LogicalOffset = data.ReadUInt64(); - romFSHeader.Level3HashdataSize = data.ReadUInt64(); - romFSHeader.Level3BlockSizeLog2 = data.ReadUInt32(); - romFSHeader.Reserved3 = data.ReadBytes(4); - romFSHeader.Reserved4 = data.ReadBytes(4); - romFSHeader.OptionalInfoSize = data.ReadUInt32(); - return romFSHeader; } } diff --git a/SabreTools.Serialization/Deserializers/NCF.cs b/SabreTools.Serialization/Deserializers/NCF.cs index b2665238..081981b6 100644 --- a/SabreTools.Serialization/Deserializers/NCF.cs +++ b/SabreTools.Serialization/Deserializers/NCF.cs @@ -99,13 +99,6 @@ namespace SabreTools.Serialization.Deserializers file.DirectoryNames[nameOffset] = directoryName; } - - // Loop and assign to entries - foreach (var directoryEntry in file.DirectoryEntries) - { - if (directoryEntry != null) - directoryEntry.Name = file.DirectoryNames[directoryEntry.NameOffset]; - } } #endregion @@ -322,18 +315,7 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life No Cache directory entry on success, null on error private static DirectoryEntry? ParseDirectoryEntry(Stream data) { - // TODO: Use marshalling here instead of building - var directoryEntry = new DirectoryEntry(); - - directoryEntry.NameOffset = data.ReadUInt32(); - directoryEntry.ItemSize = data.ReadUInt32(); - directoryEntry.ChecksumIndex = data.ReadUInt32(); - directoryEntry.DirectoryFlags = (HL_NCF_FLAG)data.ReadUInt32(); - directoryEntry.ParentIndex = data.ReadUInt32(); - directoryEntry.NextIndex = data.ReadUInt32(); - directoryEntry.FirstIndex = data.ReadUInt32(); - - return directoryEntry; + return data.ReadType(); } /// diff --git a/SabreTools.Serialization/Deserializers/Nitro.cs b/SabreTools.Serialization/Deserializers/Nitro.cs index 1807a482..9d43cc81 100644 --- a/SabreTools.Serialization/Deserializers/Nitro.cs +++ b/SabreTools.Serialization/Deserializers/Nitro.cs @@ -103,6 +103,9 @@ namespace SabreTools.Serialization.Deserializers while (data.Position - fileAllocationTableOffset < header.FileAllocationTableLength) { var entry = ParseFileAllocationTableEntry(data); + if (entry == null) + return null; + fileAllocationTable.Add(entry); } @@ -122,58 +125,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled common header on success, null on error - private static CommonHeader ParseCommonHeader(Stream data) + private static CommonHeader? ParseCommonHeader(Stream data) { - // TODO: Use marshalling here instead of building - CommonHeader commonHeader = new CommonHeader(); - - byte[]? gameTitle = data.ReadBytes(12); - if (gameTitle != null) - commonHeader.GameTitle = Encoding.ASCII.GetString(gameTitle).TrimEnd('\0'); - commonHeader.GameCode = data.ReadUInt32(); - byte[]? makerCode = data.ReadBytes(2); - if (makerCode != null) - commonHeader.MakerCode = Encoding.ASCII.GetString(bytes: makerCode).TrimEnd('\0'); - commonHeader.UnitCode = (Unitcode)data.ReadByteValue(); - commonHeader.EncryptionSeedSelect = data.ReadByteValue(); - commonHeader.DeviceCapacity = data.ReadByteValue(); - commonHeader.Reserved1 = data.ReadBytes(7); - commonHeader.GameRevision = data.ReadUInt16(); - commonHeader.RomVersion = data.ReadByteValue(); - commonHeader.InternalFlags = data.ReadByteValue(); - commonHeader.ARM9RomOffset = data.ReadUInt32(); - commonHeader.ARM9EntryAddress = data.ReadUInt32(); - commonHeader.ARM9LoadAddress = data.ReadUInt32(); - commonHeader.ARM9Size = data.ReadUInt32(); - commonHeader.ARM7RomOffset = data.ReadUInt32(); - commonHeader.ARM7EntryAddress = data.ReadUInt32(); - commonHeader.ARM7LoadAddress = data.ReadUInt32(); - commonHeader.ARM7Size = data.ReadUInt32(); - commonHeader.FileNameTableOffset = data.ReadUInt32(); - commonHeader.FileNameTableLength = data.ReadUInt32(); - commonHeader.FileAllocationTableOffset = data.ReadUInt32(); - commonHeader.FileAllocationTableLength = data.ReadUInt32(); - commonHeader.ARM9OverlayOffset = data.ReadUInt32(); - commonHeader.ARM9OverlayLength = data.ReadUInt32(); - commonHeader.ARM7OverlayOffset = data.ReadUInt32(); - commonHeader.ARM7OverlayLength = data.ReadUInt32(); - commonHeader.NormalCardControlRegisterSettings = data.ReadUInt32(); - commonHeader.SecureCardControlRegisterSettings = data.ReadUInt32(); - commonHeader.IconBannerOffset = data.ReadUInt32(); - commonHeader.SecureAreaCRC = data.ReadUInt16(); - commonHeader.SecureTransferTimeout = data.ReadUInt16(); - commonHeader.ARM9Autoload = data.ReadUInt32(); - commonHeader.ARM7Autoload = data.ReadUInt32(); - commonHeader.SecureDisable = data.ReadBytes(8); - commonHeader.NTRRegionRomSize = data.ReadUInt32(); - commonHeader.HeaderSize = data.ReadUInt32(); - commonHeader.Reserved2 = data.ReadBytes(56); - commonHeader.NintendoLogo = data.ReadBytes(156); - commonHeader.NintendoLogoCRC = data.ReadUInt16(); - commonHeader.HeaderCRC = data.ReadUInt16(); - commonHeader.DebuggerReserved = data.ReadBytes(0x20); - - return commonHeader; + return data.ReadType(); } /// @@ -181,75 +135,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled extended DSi header on success, null on error - private static ExtendedDSiHeader ParseExtendedDSiHeader(Stream data) + private static ExtendedDSiHeader? ParseExtendedDSiHeader(Stream data) { - // TODO: Use marshalling here instead of building - var extendedDSiHeader = new ExtendedDSiHeader(); - - extendedDSiHeader.GlobalMBK15Settings = new uint[5]; - for (int i = 0; i < 5; i++) - { - extendedDSiHeader.GlobalMBK15Settings[i] = data.ReadUInt32(); - } - extendedDSiHeader.LocalMBK68SettingsARM9 = new uint[3]; - for (int i = 0; i < 3; i++) - { - extendedDSiHeader.LocalMBK68SettingsARM9[i] = data.ReadUInt32(); - } - extendedDSiHeader.LocalMBK68SettingsARM7 = new uint[3]; - for (int i = 0; i < 3; i++) - { - extendedDSiHeader.LocalMBK68SettingsARM7[i] = data.ReadUInt32(); - } - extendedDSiHeader.GlobalMBK9Setting = data.ReadUInt32(); - extendedDSiHeader.RegionFlags = data.ReadUInt32(); - extendedDSiHeader.AccessControl = data.ReadUInt32(); - extendedDSiHeader.ARM7SCFGEXTMask = data.ReadUInt32(); - extendedDSiHeader.ReservedFlags = data.ReadUInt32(); - extendedDSiHeader.ARM9iRomOffset = data.ReadUInt32(); - extendedDSiHeader.Reserved3 = data.ReadUInt32(); - extendedDSiHeader.ARM9iLoadAddress = data.ReadUInt32(); - extendedDSiHeader.ARM9iSize = data.ReadUInt32(); - extendedDSiHeader.ARM7iRomOffset = data.ReadUInt32(); - extendedDSiHeader.Reserved4 = data.ReadUInt32(); - extendedDSiHeader.ARM7iLoadAddress = data.ReadUInt32(); - extendedDSiHeader.ARM7iSize = data.ReadUInt32(); - extendedDSiHeader.DigestNTRRegionOffset = data.ReadUInt32(); - extendedDSiHeader.DigestNTRRegionLength = data.ReadUInt32(); - extendedDSiHeader.DigestTWLRegionOffset = data.ReadUInt32(); - extendedDSiHeader.DigestTWLRegionLength = data.ReadUInt32(); - extendedDSiHeader.DigestSectorHashtableRegionOffset = data.ReadUInt32(); - extendedDSiHeader.DigestSectorHashtableRegionLength = data.ReadUInt32(); - extendedDSiHeader.DigestBlockHashtableRegionOffset = data.ReadUInt32(); - extendedDSiHeader.DigestBlockHashtableRegionLength = data.ReadUInt32(); - extendedDSiHeader.DigestSectorSize = data.ReadUInt32(); - extendedDSiHeader.DigestBlockSectorCount = data.ReadUInt32(); - extendedDSiHeader.IconBannerSize = data.ReadUInt32(); - extendedDSiHeader.Unknown1 = data.ReadUInt32(); - extendedDSiHeader.NTRTWLRegionRomSize = data.ReadUInt32(); - extendedDSiHeader.Unknown2 = data.ReadBytes(12); - extendedDSiHeader.ModcryptArea1Offset = data.ReadUInt32(); - extendedDSiHeader.ModcryptArea1Size = data.ReadUInt32(); - extendedDSiHeader.ModcryptArea2Offset = data.ReadUInt32(); - extendedDSiHeader.ModcryptArea2Size = data.ReadUInt32(); - extendedDSiHeader.TitleID = data.ReadBytes(8); - extendedDSiHeader.DSiWarePublicSavSize = data.ReadUInt32(); - extendedDSiHeader.DSiWarePrivateSavSize = data.ReadUInt32(); - extendedDSiHeader.ReservedZero = data.ReadBytes(176); - extendedDSiHeader.Unknown2 = data.ReadBytes(0x10); - extendedDSiHeader.ARM9WithSecureAreaSHA1HMACHash = data.ReadBytes(20); - extendedDSiHeader.ARM7SHA1HMACHash = data.ReadBytes(20); - extendedDSiHeader.DigestMasterSHA1HMACHash = data.ReadBytes(20); - extendedDSiHeader.BannerSHA1HMACHash = data.ReadBytes(20); - extendedDSiHeader.ARM9iDecryptedSHA1HMACHash = data.ReadBytes(20); - extendedDSiHeader.ARM7iDecryptedSHA1HMACHash = data.ReadBytes(20); - extendedDSiHeader.Reserved5 = data.ReadBytes(40); - extendedDSiHeader.ARM9NoSecureAreaSHA1HMACHash = data.ReadBytes(20); - extendedDSiHeader.Reserved6 = data.ReadBytes(2636); - extendedDSiHeader.ReservedAndUnchecked = data.ReadBytes(0x180); - extendedDSiHeader.RSASignature = data.ReadBytes(0x80); - - return extendedDSiHeader; + return data.ReadType(); } /// @@ -257,10 +145,10 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled name table on success, null on error - private static NameTable ParseNameTable(Stream data) + private static NameTable? ParseNameTable(Stream data) { // TODO: Use marshalling here instead of building - NameTable nameTable = new NameTable(); + var nameTable = new NameTable(); // Create a variable-length table var folderAllocationTable = new List(); @@ -268,6 +156,9 @@ namespace SabreTools.Serialization.Deserializers while (entryCount > 0) { var entry = ParseFolderAllocationTableEntry(data); + if (entry == null) + return null; + folderAllocationTable.Add(entry); // If we have the root entry @@ -303,17 +194,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled folder allocation table entry on success, null on error - private static FolderAllocationTableEntry ParseFolderAllocationTableEntry(Stream data) + private static FolderAllocationTableEntry? ParseFolderAllocationTableEntry(Stream data) { - // TODO: Use marshalling here instead of building - var entry = new FolderAllocationTableEntry(); - - entry.StartOffset = data.ReadUInt32(); - entry.FirstFileIndex = data.ReadUInt16(); - entry.ParentFolderIndex = data.ReadByteValue(); - entry.Unknown = data.ReadByteValue(); - - return entry; + return data.ReadType(); } /// @@ -351,15 +234,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled name list entry on success, null on error - private static FileAllocationTableEntry ParseFileAllocationTableEntry(Stream data) + private static FileAllocationTableEntry? ParseFileAllocationTableEntry(Stream data) { - // TODO: Use marshalling here instead of building - var entry = new FileAllocationTableEntry(); - - entry.StartOffset = data.ReadUInt32(); - entry.EndOffset = data.ReadUInt32(); - - return entry; + return data.ReadType(); } } } \ No newline at end of file diff --git a/SabreTools.Serialization/Deserializers/PortableExecutable.cs b/SabreTools.Serialization/Deserializers/PortableExecutable.cs index a6981336..aeb773ca 100644 --- a/SabreTools.Serialization/Deserializers/PortableExecutable.cs +++ b/SabreTools.Serialization/Deserializers/PortableExecutable.cs @@ -883,7 +883,7 @@ namespace SabreTools.Serialization.Deserializers /// Optional header magic number indicating PE32 or PE32+ /// Section table to use for virtual address translation /// Filled import table on success, null on error - public static ImportTable ParseImportTable(Stream data, OptionalHeaderMagicNumber magic, SectionHeader?[] sections) + public static ImportTable? ParseImportTable(Stream data, OptionalHeaderMagicNumber magic, SectionHeader?[] sections) { // TODO: Use marshalling here instead of building var importTable = new ImportTable(); @@ -1085,21 +1085,30 @@ namespace SabreTools.Serialization.Deserializers int hintNameTableEntryAddress = hintNameTableEntryAddresses[i]; data.Seek(hintNameTableEntryAddress, SeekOrigin.Begin); - var hintNameTableEntry = new HintNameTableEntry(); - - hintNameTableEntry.Hint = data.ReadUInt16(); - hintNameTableEntry.Name = data.ReadNullTerminatedAnsiString(); + var hintNameTableEntry = ParseHintNameTableEntry(data); + if (hintNameTableEntry == null) + return null; importHintNameTable.Add(hintNameTableEntry); } } } - importTable.HintNameTable = importHintNameTable.ToArray(); + importTable.HintNameTable = [.. importHintNameTable]; return importTable; } + /// + /// Parse a Stream into a hint name table entry + /// + /// Stream to parse + /// Filled hint name table entry on success, null on error + public static HintNameTableEntry? ParseHintNameTableEntry(Stream data) + { + return data.ReadType(); + } + /// /// Parse a Stream into a resource directory table /// diff --git a/SabreTools.Serialization/Deserializers/VBSP.cs b/SabreTools.Serialization/Deserializers/VBSP.cs index 82efa380..ef6f3568 100644 --- a/SabreTools.Serialization/Deserializers/VBSP.cs +++ b/SabreTools.Serialization/Deserializers/VBSP.cs @@ -48,7 +48,7 @@ namespace SabreTools.Serialization.Deserializers private static Header? ParseHeader(Stream data) { // TODO: Use marshalling here instead of building - Header header = new Header(); + var header = new Header(); byte[]? signature = data.ReadBytes(4); if (signature == null) diff --git a/SabreTools.Serialization/Deserializers/VPK.cs b/SabreTools.Serialization/Deserializers/VPK.cs index d78ee798..a2c28727 100644 --- a/SabreTools.Serialization/Deserializers/VPK.cs +++ b/SabreTools.Serialization/Deserializers/VPK.cs @@ -79,6 +79,9 @@ namespace SabreTools.Serialization.Deserializers while (data.Position < initialOffset + file.ExtendedHeader.ArchiveHashLength) { var archiveHash = ParseArchiveHash(data); + if (archiveHash == null) + return null; + archiveHashes.Add(archiveHash); } @@ -124,17 +127,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Valve Package archive hash on success, null on error - private static ArchiveHash ParseArchiveHash(Stream data) + private static ArchiveHash? ParseArchiveHash(Stream data) { - // TODO: Use marshalling here instead of building - var archiveHash = new ArchiveHash(); - - archiveHash.ArchiveIndex = data.ReadUInt32(); - archiveHash.ArchiveOffset = data.ReadUInt32(); - archiveHash.Length = data.ReadUInt32(); - archiveHash.Hash = data.ReadBytes(0x10); - - return archiveHash; + return data.ReadType(); } /// diff --git a/SabreTools.Serialization/Deserializers/WAD.cs b/SabreTools.Serialization/Deserializers/WAD.cs index 71e74880..c0651e1c 100644 --- a/SabreTools.Serialization/Deserializers/WAD.cs +++ b/SabreTools.Serialization/Deserializers/WAD.cs @@ -52,6 +52,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < header.LumpCount; i++) { var lump = ParseLump(data); + if (lump == null) + return null; + file.Lumps[i] = lump; } @@ -104,20 +107,13 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life Texture Package header on success, null on error private static Header? ParseHeader(Stream data) { - // TODO: Use marshalling here instead of building - Header header = new Header(); + var header = data.ReadType
(); - byte[]? signature = data.ReadBytes(4); - if (signature == null) + if (header == null) return null; - - header.Signature = Encoding.ASCII.GetString(signature); if (header.Signature != SignatureString) return null; - header.LumpCount = data.ReadUInt32(); - header.LumpOffset = data.ReadUInt32(); - return header; } @@ -126,23 +122,9 @@ namespace SabreTools.Serialization.Deserializers ///
/// Stream to parse /// Filled Half-Life Texture Package lump on success, null on error - private static Lump ParseLump(Stream data) + private static Lump? ParseLump(Stream data) { - // TODO: Use marshalling here instead of building - Lump lump = new Lump(); - - lump.Offset = data.ReadUInt32(); - lump.DiskLength = data.ReadUInt32(); - lump.Length = data.ReadUInt32(); - lump.Type = data.ReadByteValue(); - lump.Compression = data.ReadByteValue(); - lump.Padding0 = data.ReadByteValue(); - lump.Padding1 = data.ReadByteValue(); - byte[]? name = data.ReadBytes(16); - if (name != null) - lump.Name = Encoding.ASCII.GetString(name).TrimEnd('\0'); - - return lump; + return data.ReadType(); } /// @@ -182,7 +164,7 @@ namespace SabreTools.Serialization.Deserializers lumpInfo.Width = data.ReadUInt32(); lumpInfo.Height = data.ReadUInt32(); lumpInfo.PixelOffset = data.ReadUInt32(); - _ = data.ReadBytes(12); // Unknown data + lumpInfo.UnknownData = data.ReadBytes(12); // Cache the current offset long currentOffset = data.Position; diff --git a/SabreTools.Serialization/Deserializers/XZP.cs b/SabreTools.Serialization/Deserializers/XZP.cs index f2160bc2..046a2b09 100644 --- a/SabreTools.Serialization/Deserializers/XZP.cs +++ b/SabreTools.Serialization/Deserializers/XZP.cs @@ -144,29 +144,15 @@ namespace SabreTools.Serialization.Deserializers /// Filled XBox Package File header on success, null on error private static Header? ParseHeader(Stream data) { - // TODO: Use marshalling here instead of building - Header header = new Header(); + var header = data.ReadType
(); - byte[]? signature = data.ReadBytes(4); - if (signature == null) + if (header == null) return null; - - header.Signature = Encoding.ASCII.GetString(signature); if (header.Signature != HeaderSignatureString) return null; - - header.Version = data.ReadUInt32(); if (header.Version != 6) return null; - header.PreloadDirectoryEntryCount = data.ReadUInt32(); - header.DirectoryEntryCount = data.ReadUInt32(); - header.PreloadBytes = data.ReadUInt32(); - header.HeaderLength = data.ReadUInt32(); - header.DirectoryItemCount = data.ReadUInt32(); - header.DirectoryItemOffset = data.ReadUInt32(); - header.DirectoryItemLength = data.ReadUInt32(); - return header; } @@ -226,15 +212,10 @@ namespace SabreTools.Serialization.Deserializers /// Filled XBox Package File footer on success, null on error private static Footer? ParseFooter(Stream data) { - // TODO: Use marshalling here instead of building - Footer footer = new Footer(); + var footer = data.ReadType