From 52f0846d5d646172b62fa58e0a7b131773a48f96 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 23 Apr 2024 21:00:10 -0400 Subject: [PATCH] Add and fix some deserializers --- .../Deserializers/BFPK.cs | 13 +- SabreTools.Serialization/Deserializers/BSP.cs | 25 +- SabreTools.Serialization/Deserializers/CFB.cs | 8 +- SabreTools.Serialization/Deserializers/GCF.cs | 243 ++++++------------ SabreTools.Serialization/Deserializers/IRD.cs | 2 +- .../Deserializers/InstallShieldArchiveV3.cs | 5 +- .../Deserializers/InstallShieldCabinet.cs | 60 +---- .../Deserializers/LinearExecutable.cs | 136 ++-------- .../Deserializers/MSDOS.cs | 19 +- .../Deserializers/MoPaQ.cs | 32 +-- .../Deserializers/N3DS.cs | 16 +- SabreTools.Serialization/Deserializers/NCF.cs | 158 ++++-------- .../Deserializers/NewExecutable.cs | 205 ++++++++++----- .../Deserializers/Nitro.cs | 10 +- SabreTools.Serialization/Deserializers/PAK.cs | 28 +- SabreTools.Serialization/Deserializers/PFF.cs | 64 ++--- SabreTools.Serialization/Deserializers/PIC.cs | 29 +-- .../Deserializers/PortableExecutable.cs | 164 ++++-------- .../Deserializers/Quantum.cs | 16 +- SabreTools.Serialization/Deserializers/SFB.cs | 35 +++ SabreTools.Serialization/Deserializers/SFO.cs | 91 +++++++ .../Deserializers/VBSP.cs | 24 +- SabreTools.Serialization/Deserializers/VPK.cs | 55 ++-- SabreTools.Serialization/Deserializers/XZP.cs | 29 +-- .../Extensions.PortableExecutable.cs | 101 +++----- 25 files changed, 618 insertions(+), 950 deletions(-) create mode 100644 SabreTools.Serialization/Deserializers/SFB.cs create mode 100644 SabreTools.Serialization/Deserializers/SFO.cs diff --git a/SabreTools.Serialization/Deserializers/BFPK.cs b/SabreTools.Serialization/Deserializers/BFPK.cs index 818edf1b..797c8f59 100644 --- a/SabreTools.Serialization/Deserializers/BFPK.cs +++ b/SabreTools.Serialization/Deserializers/BFPK.cs @@ -70,20 +70,13 @@ namespace SabreTools.Serialization.Deserializers /// Filled 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[]? magic = data.ReadBytes(4); - if (magic == null) + if (header == null) return null; - - header.Magic = Encoding.ASCII.GetString(magic); if (header.Magic != SignatureString) return null; - header.Version = data.ReadInt32(); - header.Files = data.ReadInt32(); - return header; } @@ -95,7 +88,7 @@ namespace SabreTools.Serialization.Deserializers private static FileEntry ParseFileEntry(Stream data) { // TODO: Use marshalling here instead of building - FileEntry fileEntry = new FileEntry(); + var fileEntry = new FileEntry(); fileEntry.NameSize = data.ReadInt32(); if (fileEntry.NameSize > 0) diff --git a/SabreTools.Serialization/Deserializers/BSP.cs b/SabreTools.Serialization/Deserializers/BSP.cs index 70152115..6f93ffb9 100644 --- a/SabreTools.Serialization/Deserializers/BSP.cs +++ b/SabreTools.Serialization/Deserializers/BSP.cs @@ -47,6 +47,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < HL_BSP_LUMP_COUNT; i++) { var lump = ParseLump(data); + if (lump == null) + return null; + file.Lumps[i] = lump; } @@ -102,13 +105,13 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Level header on success, null on error + /// Only recognized versions are 29 and 30 private static Header? ParseHeader(Stream data) { - // TODO: Use marshalling here instead of building - Header header = new Header(); + var header = data.ReadType
(); - // Only recognized versions are 29 and 30 - header.Version = data.ReadUInt32(); + if (header == null) + return null; if (header.Version != 29 && header.Version != 30) return null; @@ -120,15 +123,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled 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.Length = data.ReadUInt32(); - - return lump; + return data.ReadType(); } /// @@ -139,7 +136,7 @@ namespace SabreTools.Serialization.Deserializers private static TextureHeader ParseTextureHeader(Stream data) { // TODO: Use marshalling here instead of building - TextureHeader textureHeader = new TextureHeader(); + var textureHeader = new TextureHeader(); textureHeader.TextureCount = data.ReadUInt32(); @@ -166,7 +163,7 @@ namespace SabreTools.Serialization.Deserializers private static Texture ParseTexture(Stream data, uint mipmap = 0) { // TODO: Use marshalling here instead of building - Texture texture = new Texture(); + var texture = new Texture(); byte[]? name = data.ReadBytes(16)?.TakeWhile(c => c != '\0')?.ToArray(); if (name != null) diff --git a/SabreTools.Serialization/Deserializers/CFB.cs b/SabreTools.Serialization/Deserializers/CFB.cs index 983e816c..0f434977 100644 --- a/SabreTools.Serialization/Deserializers/CFB.cs +++ b/SabreTools.Serialization/Deserializers/CFB.cs @@ -234,7 +234,7 @@ namespace SabreTools.Serialization.Deserializers private static FileHeader? ParseFileHeader(Stream data) { // TODO: Use marshalling here instead of building - FileHeader header = new FileHeader(); + var header = new FileHeader(); header.Signature = data.ReadUInt64(); if (header.Signature != SignatureUInt64) @@ -315,7 +315,7 @@ namespace SabreTools.Serialization.Deserializers // TODO: Use marshalling here instead of building const int directoryEntrySize = 64 + 2 + 1 + 1 + 4 + 4 + 4 + 16 + 4 + 8 + 8 + 4 + 8; int sectorCount = (int)(Math.Pow(2, sectorShift) / directoryEntrySize); - DirectoryEntry[] directoryEntries = new DirectoryEntry[sectorCount]; + var directoryEntries = new DirectoryEntry[sectorCount]; for (int i = 0; i < directoryEntries.Length; i++) { @@ -335,10 +335,10 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Major version from the header /// Filled directory entry on success, null on error - private static DirectoryEntry ParseDirectoryEntry(Stream data, ushort majorVersion) + private static DirectoryEntry? ParseDirectoryEntry(Stream data, ushort majorVersion) { // TODO: Use marshalling here instead of building - DirectoryEntry directoryEntry = new DirectoryEntry(); + var directoryEntry = new DirectoryEntry(); byte[]? name = data.ReadBytes(64); if (name != null) diff --git a/SabreTools.Serialization/Deserializers/GCF.cs b/SabreTools.Serialization/Deserializers/GCF.cs index 389381b1..ed6dccf7 100644 --- a/SabreTools.Serialization/Deserializers/GCF.cs +++ b/SabreTools.Serialization/Deserializers/GCF.cs @@ -58,6 +58,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < blockEntryHeader.BlockCount; i++) { var blockEntry = ParseBlockEntry(data); + if (blockEntry == null) + return null; + file.BlockEntries[i] = blockEntry; } @@ -84,6 +87,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < fragmentationMapHeader.BlockCount; i++) { var fragmentationMap = ParseFragmentationMap(data); + if (fragmentationMap == null) + return null; + file.FragmentationMaps[i] = fragmentationMap; } @@ -115,6 +121,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < file.BlockEntryMapHeader.BlockCount; i++) { var blockEntryMap = ParseBlockEntryMap(data); + if (blockEntryMap == null) + return null; + file.BlockEntryMaps[i] = blockEntryMap; } } @@ -200,6 +209,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.Info1Count; i++) { var directoryInfo1Entry = ParseDirectoryInfo1Entry(data); + if (directoryInfo1Entry == null) + return null; + file.DirectoryInfo1Entries[i] = directoryInfo1Entry; } @@ -214,6 +226,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.ItemCount; i++) { var directoryInfo2Entry = ParseDirectoryInfo2Entry(data); + if (directoryInfo2Entry == null) + return null; + file.DirectoryInfo2Entries[i] = directoryInfo2Entry; } @@ -228,6 +243,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.CopyCount; i++) { var directoryCopyEntry = ParseDirectoryCopyEntry(data); + if (directoryCopyEntry == null) + return null; + file.DirectoryCopyEntries[i] = directoryCopyEntry; } @@ -242,6 +260,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.LocalCount; i++) { var directoryLocalEntry = ParseDirectoryLocalEntry(data); + if (directoryLocalEntry == null) + return null; + file.DirectoryLocalEntries[i] = directoryLocalEntry; } @@ -274,6 +295,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.ItemCount; i++) { var directoryMapEntry = ParseDirectoryMapEntry(data); + if (directoryMapEntry == null) + return null; + file.DirectoryMapEntries[i] = directoryMapEntry; } @@ -315,6 +339,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < checksumMapHeader.ItemCount; i++) { var checksumMapEntry = ParseChecksumMapEntry(data); + if (checksumMapEntry == null) + return null; + file.ChecksumMapEntries[i] = checksumMapEntry; } @@ -329,6 +356,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < checksumMapHeader.ChecksumCount; i++) { var checksumEntry = ParseChecksumEntry(data); + if (checksumEntry == null) + return null; + file.ChecksumEntries[i] = checksumEntry; } @@ -359,30 +389,17 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life Game Cache 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
(); - header.Dummy0 = data.ReadUInt32(); + if (header == null) + return null; if (header.Dummy0 != 0x00000001) return null; - - header.MajorVersion = data.ReadUInt32(); if (header.MajorVersion != 0x00000001) return null; - - header.MinorVersion = data.ReadUInt32(); if (header.MinorVersion != 3 && header.MinorVersion != 5 && header.MinorVersion != 6) return null; - header.CacheID = data.ReadUInt32(); - header.LastVersionPlayed = data.ReadUInt32(); - header.Dummy1 = data.ReadUInt32(); - header.Dummy2 = data.ReadUInt32(); - header.FileSize = data.ReadUInt32(); - header.BlockSize = data.ReadUInt32(); - header.BlockCount = data.ReadUInt32(); - header.Dummy3 = data.ReadUInt32(); - return header; } @@ -391,21 +408,9 @@ namespace SabreTools.Serialization.Deserializers ///
/// Stream to parse /// Filled Half-Life Game Cache block entry header on success, null on error - private static BlockEntryHeader ParseBlockEntryHeader(Stream data) + private static BlockEntryHeader? ParseBlockEntryHeader(Stream data) { - // TODO: Use marshalling here instead of building - BlockEntryHeader blockEntryHeader = new BlockEntryHeader(); - - blockEntryHeader.BlockCount = data.ReadUInt32(); - blockEntryHeader.BlocksUsed = data.ReadUInt32(); - blockEntryHeader.Dummy0 = data.ReadUInt32(); - blockEntryHeader.Dummy1 = data.ReadUInt32(); - blockEntryHeader.Dummy2 = data.ReadUInt32(); - blockEntryHeader.Dummy3 = data.ReadUInt32(); - blockEntryHeader.Dummy4 = data.ReadUInt32(); - blockEntryHeader.Checksum = data.ReadUInt32(); - - return blockEntryHeader; + return data.ReadType(); } /// @@ -413,20 +418,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache block entry on success, null on error - private static BlockEntry ParseBlockEntry(Stream data) + private static BlockEntry? ParseBlockEntry(Stream data) { - // TODO: Use marshalling here instead of building - BlockEntry blockEntry = new BlockEntry(); - - blockEntry.EntryFlags = data.ReadUInt32(); - blockEntry.FileDataOffset = data.ReadUInt32(); - blockEntry.FileDataSize = data.ReadUInt32(); - blockEntry.FirstDataBlockIndex = data.ReadUInt32(); - blockEntry.NextBlockEntryIndex = data.ReadUInt32(); - blockEntry.PreviousBlockEntryIndex = data.ReadUInt32(); - blockEntry.DirectoryIndex = data.ReadUInt32(); - - return blockEntry; + return data.ReadType(); } /// @@ -434,17 +428,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache fragmentation map header on success, null on error - private static FragmentationMapHeader ParseFragmentationMapHeader(Stream data) + private static FragmentationMapHeader? ParseFragmentationMapHeader(Stream data) { - // TODO: Use marshalling here instead of building - FragmentationMapHeader fragmentationMapHeader = new FragmentationMapHeader(); - - fragmentationMapHeader.BlockCount = data.ReadUInt32(); - fragmentationMapHeader.FirstUnusedEntry = data.ReadUInt32(); - fragmentationMapHeader.Terminator = data.ReadUInt32(); - fragmentationMapHeader.Checksum = data.ReadUInt32(); - - return fragmentationMapHeader; + return data.ReadType(); } /// @@ -452,14 +438,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache fragmentation map on success, null on error - private static FragmentationMap ParseFragmentationMap(Stream data) + private static FragmentationMap? ParseFragmentationMap(Stream data) { - // TODO: Use marshalling here instead of building - FragmentationMap fragmentationMap = new FragmentationMap(); - - fragmentationMap.NextDataBlockIndex = data.ReadUInt32(); - - return fragmentationMap; + return data.ReadType(); } /// @@ -467,18 +448,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache block entry map header on success, null on error - private static BlockEntryMapHeader ParseBlockEntryMapHeader(Stream data) + private static BlockEntryMapHeader? ParseBlockEntryMapHeader(Stream data) { - // TODO: Use marshalling here instead of building - BlockEntryMapHeader blockEntryMapHeader = new BlockEntryMapHeader(); - - blockEntryMapHeader.BlockCount = data.ReadUInt32(); - blockEntryMapHeader.FirstBlockEntryIndex = data.ReadUInt32(); - blockEntryMapHeader.LastBlockEntryIndex = data.ReadUInt32(); - blockEntryMapHeader.Dummy0 = data.ReadUInt32(); - blockEntryMapHeader.Checksum = data.ReadUInt32(); - - return blockEntryMapHeader; + return data.ReadType(); } /// @@ -486,15 +458,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache block entry map on success, null on error - private static BlockEntryMap ParseBlockEntryMap(Stream data) + private static BlockEntryMap? ParseBlockEntryMap(Stream data) { - // TODO: Use marshalling here instead of building - BlockEntryMap blockEntryMap = new BlockEntryMap(); - - blockEntryMap.PreviousBlockEntryIndex = data.ReadUInt32(); - blockEntryMap.NextBlockEntryIndex = data.ReadUInt32(); - - return blockEntryMap; + return data.ReadType(); } /// @@ -502,27 +468,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache directory header on success, null on error - private static DirectoryHeader ParseDirectoryHeader(Stream data) + private static DirectoryHeader? ParseDirectoryHeader(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryHeader directoryHeader = new DirectoryHeader(); - - directoryHeader.Dummy0 = data.ReadUInt32(); - directoryHeader.CacheID = data.ReadUInt32(); - directoryHeader.LastVersionPlayed = data.ReadUInt32(); - directoryHeader.ItemCount = data.ReadUInt32(); - directoryHeader.FileCount = data.ReadUInt32(); - directoryHeader.Dummy1 = data.ReadUInt32(); - directoryHeader.DirectorySize = data.ReadUInt32(); - directoryHeader.NameSize = data.ReadUInt32(); - directoryHeader.Info1Count = data.ReadUInt32(); - directoryHeader.CopyCount = data.ReadUInt32(); - directoryHeader.LocalCount = data.ReadUInt32(); - directoryHeader.Dummy2 = data.ReadUInt32(); - directoryHeader.Dummy3 = data.ReadUInt32(); - directoryHeader.Checksum = data.ReadUInt32(); - - return directoryHeader; + return data.ReadType(); } /// @@ -533,7 +481,7 @@ namespace SabreTools.Serialization.Deserializers private static DirectoryEntry ParseDirectoryEntry(Stream data) { // TODO: Use marshalling here instead of building - DirectoryEntry directoryEntry = new DirectoryEntry(); + var directoryEntry = new DirectoryEntry(); directoryEntry.NameOffset = data.ReadUInt32(); directoryEntry.ItemSize = data.ReadUInt32(); @@ -551,14 +499,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache directory info 1 entry on success, null on error - private static DirectoryInfo1Entry ParseDirectoryInfo1Entry(Stream data) + private static DirectoryInfo1Entry? ParseDirectoryInfo1Entry(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryInfo1Entry directoryInfo1Entry = new DirectoryInfo1Entry(); - - directoryInfo1Entry.Dummy0 = data.ReadUInt32(); - - return directoryInfo1Entry; + return data.ReadType(); } /// @@ -566,14 +509,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache directory info 2 entry on success, null on error - private static DirectoryInfo2Entry ParseDirectoryInfo2Entry(Stream data) + private static DirectoryInfo2Entry? ParseDirectoryInfo2Entry(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryInfo2Entry directoryInfo2Entry = new DirectoryInfo2Entry(); - - directoryInfo2Entry.Dummy0 = data.ReadUInt32(); - - return directoryInfo2Entry; + return data.ReadType(); } /// @@ -581,14 +519,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache directory copy entry on success, null on error - private static DirectoryCopyEntry ParseDirectoryCopyEntry(Stream data) + private static DirectoryCopyEntry? ParseDirectoryCopyEntry(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryCopyEntry directoryCopyEntry = new DirectoryCopyEntry(); - - directoryCopyEntry.DirectoryIndex = data.ReadUInt32(); - - return directoryCopyEntry; + return data.ReadType(); } /// @@ -596,14 +529,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache directory local entry on success, null on error - private static DirectoryLocalEntry ParseDirectoryLocalEntry(Stream data) + private static DirectoryLocalEntry? ParseDirectoryLocalEntry(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryLocalEntry directoryLocalEntry = new DirectoryLocalEntry(); - - directoryLocalEntry.DirectoryIndex = data.ReadUInt32(); - - return directoryLocalEntry; + return data.ReadType(); } /// @@ -613,14 +541,12 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life Game Cache directory map header on success, null on error private static DirectoryMapHeader? ParseDirectoryMapHeader(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryMapHeader directoryMapHeader = new DirectoryMapHeader(); + var directoryMapHeader = data.ReadType(); - directoryMapHeader.Dummy0 = data.ReadUInt32(); + if (directoryMapHeader == null) + return null; if (directoryMapHeader.Dummy0 != 0x00000001) return null; - - directoryMapHeader.Dummy1 = data.ReadUInt32(); if (directoryMapHeader.Dummy1 != 0x00000000) return null; @@ -632,14 +558,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache directory map entry on success, null on error - private static DirectoryMapEntry ParseDirectoryMapEntry(Stream data) + private static DirectoryMapEntry? ParseDirectoryMapEntry(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryMapEntry directoryMapEntry = new DirectoryMapEntry(); - - directoryMapEntry.FirstBlockIndex = data.ReadUInt32(); - - return directoryMapEntry; + return data.ReadType(); } /// @@ -649,15 +570,13 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life Game Cache checksum header on success, null on error private static ChecksumHeader? ParseChecksumHeader(Stream data) { - // TODO: Use marshalling here instead of building - ChecksumHeader checksumHeader = new ChecksumHeader(); + var checksumHeader = data.ReadType(); - checksumHeader.Dummy0 = data.ReadUInt32(); + if (checksumHeader == null) + return null; if (checksumHeader.Dummy0 != 0x00000001) return null; - checksumHeader.ChecksumSize = data.ReadUInt32(); - return checksumHeader; } @@ -668,20 +587,15 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life Game Cache checksum map header on success, null on error private static ChecksumMapHeader? ParseChecksumMapHeader(Stream data) { - // TODO: Use marshalling here instead of building - ChecksumMapHeader checksumMapHeader = new ChecksumMapHeader(); + var checksumMapHeader = data.ReadType(); - checksumMapHeader.Dummy0 = data.ReadUInt32(); + if (checksumMapHeader == null) + return null; if (checksumMapHeader.Dummy0 != 0x14893721) return null; - - checksumMapHeader.Dummy1 = data.ReadUInt32(); if (checksumMapHeader.Dummy1 != 0x00000001) return null; - checksumMapHeader.ItemCount = data.ReadUInt32(); - checksumMapHeader.ChecksumCount = data.ReadUInt32(); - return checksumMapHeader; } @@ -690,15 +604,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache checksum map entry on success, null on error - private static ChecksumMapEntry ParseChecksumMapEntry(Stream data) + private static ChecksumMapEntry? ParseChecksumMapEntry(Stream data) { - // TODO: Use marshalling here instead of building - ChecksumMapEntry checksumMapEntry = new ChecksumMapEntry(); - - checksumMapEntry.ChecksumCount = data.ReadUInt32(); - checksumMapEntry.FirstChecksumIndex = data.ReadUInt32(); - - return checksumMapEntry; + return data.ReadType(); } /// @@ -706,14 +614,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Game Cache checksum entry on success, null on error - private static ChecksumEntry ParseChecksumEntry(Stream data) + private static ChecksumEntry? ParseChecksumEntry(Stream data) { - // TODO: Use marshalling here instead of building - ChecksumEntry checksumEntry = new ChecksumEntry(); - - checksumEntry.Checksum = data.ReadUInt32(); - - return checksumEntry; + return data.ReadType(); } /// @@ -722,10 +625,10 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Minor version field from the header /// Filled Half-Life Game Cache data block header on success, null on error - private static DataBlockHeader ParseDataBlockHeader(Stream data, uint minorVersion) + private static DataBlockHeader? ParseDataBlockHeader(Stream data, uint minorVersion) { // TODO: Use marshalling here instead of building - DataBlockHeader dataBlockHeader = new DataBlockHeader(); + var dataBlockHeader = new DataBlockHeader(); // In version 3 the DataBlockHeader is missing the LastVersionPlayed field. if (minorVersion >= 5) diff --git a/SabreTools.Serialization/Deserializers/IRD.cs b/SabreTools.Serialization/Deserializers/IRD.cs index 5c391978..37686caa 100644 --- a/SabreTools.Serialization/Deserializers/IRD.cs +++ b/SabreTools.Serialization/Deserializers/IRD.cs @@ -20,7 +20,7 @@ namespace SabreTools.Serialization.Deserializers // Cache the current offset int initialOffset = (int)data.Position; - // Create a new media key block to fill + // Create a new IRD to fill var ird = new Models.IRD.File(); ird.Magic = data.ReadBytes(4); diff --git a/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs b/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs index 1e7edfa0..2cddbb85 100644 --- a/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs +++ b/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs @@ -96,14 +96,11 @@ namespace SabreTools.Serialization.Deserializers public static Header? ParseHeader(Stream data) { var header = data.ReadType
(); + if (header == null) return null; - - // Invalid signature if (header.Signature1 != 0x8C655D13) // TODO: Move constant to Models return null; - - // Invalid TOC address if (header.TocAddress >= data.Length) return null; diff --git a/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs b/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs index 21626be7..8637b162 100644 --- a/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs +++ b/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.IO; -using System.Text; using SabreTools.IO.Extensions; using SabreTools.Models.InstallShieldCabinet; using static SabreTools.Models.InstallShieldCabinet.Constants; @@ -335,21 +334,13 @@ namespace SabreTools.Serialization.Deserializers /// Filled common header on success, null on error public static CommonHeader? ParseCommonHeader(Stream data) { - CommonHeader commonHeader = new CommonHeader(); + var commonHeader = data.ReadType(); - byte[]? signature = data.ReadBytes(4); - if (signature == null) + if (commonHeader == null) return null; - - commonHeader.Signature = Encoding.ASCII.GetString(signature); if (commonHeader.Signature != SignatureString) return null; - commonHeader.Version = data.ReadUInt32(); - commonHeader.VolumeInfo = data.ReadUInt32(); - commonHeader.DescriptorOffset = data.ReadUInt32(); - commonHeader.DescriptorSize = data.ReadUInt32(); - return commonHeader; } @@ -406,46 +397,9 @@ namespace SabreTools.Serialization.Deserializers ///
/// Stream to parse /// Filled descriptor on success, null on error - public static Descriptor ParseDescriptor(Stream data) + public static Descriptor? ParseDescriptor(Stream data) { - Descriptor descriptor = new Descriptor(); - - descriptor.StringsOffset = data.ReadUInt32(); - descriptor.Reserved0 = data.ReadUInt32(); - descriptor.ComponentListOffset = data.ReadUInt32(); - descriptor.FileTableOffset = data.ReadUInt32(); - descriptor.Reserved1 = data.ReadUInt32(); - descriptor.FileTableSize = data.ReadUInt32(); - descriptor.FileTableSize2 = data.ReadUInt32(); - descriptor.DirectoryCount = data.ReadUInt16(); - descriptor.Reserved2 = data.ReadUInt32(); - descriptor.Reserved3 = data.ReadUInt16(); - descriptor.Reserved4 = data.ReadUInt32(); - descriptor.FileCount = data.ReadUInt32(); - descriptor.FileTableOffset2 = data.ReadUInt32(); - descriptor.ComponentTableInfoCount = data.ReadUInt16(); - descriptor.ComponentTableOffset = data.ReadUInt32(); - descriptor.Reserved5 = data.ReadUInt32(); - descriptor.Reserved6 = data.ReadUInt32(); - - descriptor.FileGroupOffsets = new uint[MAX_FILE_GROUP_COUNT]; - for (int i = 0; i < descriptor.FileGroupOffsets.Length; i++) - { - descriptor.FileGroupOffsets[i] = data.ReadUInt32(); - } - - descriptor.ComponentOffsets = new uint[MAX_COMPONENT_COUNT]; - for (int i = 0; i < descriptor.ComponentOffsets.Length; i++) - { - descriptor.ComponentOffsets[i] = data.ReadUInt32(); - } - - descriptor.SetupTypesOffset = data.ReadUInt32(); - descriptor.SetupTableOffset = data.ReadUInt32(); - descriptor.Reserved7 = data.ReadUInt32(); - descriptor.Reserved8 = data.ReadUInt32(); - - return descriptor; + return data.ReadType(); } /// @@ -457,7 +411,7 @@ namespace SabreTools.Serialization.Deserializers /// Filled offset list on success, null on error public static OffsetList ParseOffsetList(Stream data, int majorVersion, uint descriptorOffset) { - OffsetList offsetList = new OffsetList(); + var offsetList = new OffsetList(); offsetList.NameOffset = data.ReadUInt32(); offsetList.DescriptorOffset = data.ReadUInt32(); @@ -490,7 +444,7 @@ namespace SabreTools.Serialization.Deserializers /// Filled file group on success, null on error public static FileGroup ParseFileGroup(Stream data, int majorVersion, uint descriptorOffset) { - FileGroup fileGroup = new FileGroup(); + var fileGroup = new FileGroup(); fileGroup.NameOffset = data.ReadUInt32(); @@ -553,7 +507,7 @@ namespace SabreTools.Serialization.Deserializers /// Filled component on success, null on error public static Component ParseComponent(Stream data, int majorVersion, uint descriptorOffset) { - Component component = new Component(); + var component = new Component(); component.IdentifierOffset = data.ReadUInt32(); component.DescriptorOffset = data.ReadUInt32(); diff --git a/SabreTools.Serialization/Deserializers/LinearExecutable.cs b/SabreTools.Serialization/Deserializers/LinearExecutable.cs index 66af552d..2bb998a3 100644 --- a/SabreTools.Serialization/Deserializers/LinearExecutable.cs +++ b/SabreTools.Serialization/Deserializers/LinearExecutable.cs @@ -425,63 +425,13 @@ namespace SabreTools.Serialization.Deserializers /// Filled information block on success, null on error public static InformationBlock? ParseInformationBlock(Stream data) { - // TODO: Use marshalling here instead of building - var informationBlock = new InformationBlock(); + var informationBlock = data.ReadType(); - byte[]? magic = data.ReadBytes(2); - if (magic == null) + if (informationBlock == null) return null; - - informationBlock.Signature = Encoding.ASCII.GetString(magic); if (informationBlock.Signature != LESignatureString && informationBlock.Signature != LXSignatureString) return null; - informationBlock.ByteOrder = (ByteOrder)data.ReadByteValue(); - informationBlock.WordOrder = (WordOrder)data.ReadByteValue(); - informationBlock.ExecutableFormatLevel = data.ReadUInt32(); - informationBlock.CPUType = (CPUType)data.ReadUInt16(); - informationBlock.ModuleOS = (OperatingSystem)data.ReadUInt16(); - informationBlock.ModuleVersion = data.ReadUInt32(); - informationBlock.ModuleTypeFlags = (ModuleFlags)data.ReadUInt32(); - informationBlock.ModuleNumberPages = data.ReadUInt32(); - informationBlock.InitialObjectCS = data.ReadUInt32(); - informationBlock.InitialEIP = data.ReadUInt32(); - informationBlock.InitialObjectSS = data.ReadUInt32(); - informationBlock.InitialESP = data.ReadUInt32(); - informationBlock.MemoryPageSize = data.ReadUInt32(); - informationBlock.BytesOnLastPage = data.ReadUInt32(); - informationBlock.FixupSectionSize = data.ReadUInt32(); - informationBlock.FixupSectionChecksum = data.ReadUInt32(); - informationBlock.LoaderSectionSize = data.ReadUInt32(); - informationBlock.LoaderSectionChecksum = data.ReadUInt32(); - informationBlock.ObjectTableOffset = data.ReadUInt32(); - informationBlock.ObjectTableCount = data.ReadUInt32(); - informationBlock.ObjectPageMapOffset = data.ReadUInt32(); - informationBlock.ObjectIterateDataMapOffset = data.ReadUInt32(); - informationBlock.ResourceTableOffset = data.ReadUInt32(); - informationBlock.ResourceTableCount = data.ReadUInt32(); - informationBlock.ResidentNamesTableOffset = data.ReadUInt32(); - informationBlock.EntryTableOffset = data.ReadUInt32(); - informationBlock.ModuleDirectivesTableOffset = data.ReadUInt32(); - informationBlock.ModuleDirectivesCount = data.ReadUInt32(); - informationBlock.FixupPageTableOffset = data.ReadUInt32(); - informationBlock.FixupRecordTableOffset = data.ReadUInt32(); - informationBlock.ImportedModulesNameTableOffset = data.ReadUInt32(); - informationBlock.ImportedModulesCount = data.ReadUInt32(); - informationBlock.ImportProcedureNameTableOffset = data.ReadUInt32(); - informationBlock.PerPageChecksumTableOffset = data.ReadUInt32(); - informationBlock.DataPagesOffset = data.ReadUInt32(); - informationBlock.PreloadPageCount = data.ReadUInt32(); - informationBlock.NonResidentNamesTableOffset = data.ReadUInt32(); - informationBlock.NonResidentNamesTableLength = data.ReadUInt32(); - informationBlock.NonResidentNamesTableChecksum = data.ReadUInt32(); - informationBlock.AutomaticDataObject = data.ReadUInt32(); - informationBlock.DebugInformationOffset = data.ReadUInt32(); - informationBlock.DebugInformationLength = data.ReadUInt32(); - informationBlock.PreloadInstancePagesNumber = data.ReadUInt32(); - informationBlock.DemandInstancePagesNumber = data.ReadUInt32(); - informationBlock.ExtraHeapAllocation = data.ReadUInt32(); - return informationBlock; } @@ -490,19 +440,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled object table entry on success, null on error - public static ObjectTableEntry ParseObjectTableEntry(Stream data) + public static ObjectTableEntry? ParseObjectTableEntry(Stream data) { - // TODO: Use marshalling here instead of building - var entry = new ObjectTableEntry(); - - entry.VirtualSegmentSize = data.ReadUInt32(); - entry.RelocationBaseAddress = data.ReadUInt32(); - entry.ObjectFlags = (ObjectFlags)data.ReadUInt16(); - entry.PageTableIndex = data.ReadUInt32(); - entry.PageTableEntries = data.ReadUInt32(); - entry.Reserved = data.ReadUInt32(); - - return entry; + return data.ReadType(); } /// @@ -510,16 +450,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled object page map entry on success, null on error - public static ObjectPageMapEntry ParseObjectPageMapEntry(Stream data) + public static ObjectPageMapEntry? ParseObjectPageMapEntry(Stream data) { - // TODO: Use marshalling here instead of building - var entry = new ObjectPageMapEntry(); - - entry.PageDataOffset = data.ReadUInt32(); - entry.DataSize = data.ReadUInt16(); - entry.Flags = (ObjectPageFlags)data.ReadUInt16(); - - return entry; + return data.ReadType(); } /// @@ -527,18 +460,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled resource table entry on success, null on error - public static ResourceTableEntry ParseResourceTableEntry(Stream data) + public static ResourceTableEntry? ParseResourceTableEntry(Stream data) { - // TODO: Use marshalling here instead of building - var entry = new ResourceTableEntry(); - - entry.TypeID = (ResourceTableEntryType)data.ReadUInt32(); - entry.NameID = data.ReadUInt16(); - entry.ResourceSize = data.ReadUInt32(); - entry.ObjectNumber = data.ReadUInt16(); - entry.Offset = data.ReadUInt32(); - - return entry; + return data.ReadType(); } /// @@ -631,16 +555,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled module format directives table entry on success, null on error - public static ModuleFormatDirectivesTableEntry ParseModuleFormatDirectivesTableEntry(Stream data) + public static ModuleFormatDirectivesTableEntry? ParseModuleFormatDirectivesTableEntry(Stream data) { - // TODO: Use marshalling here instead of building - var entry = new ModuleFormatDirectivesTableEntry(); - - entry.DirectiveNumber = (DirectiveNumber)data.ReadUInt16(); - entry.DirectiveDataLength = data.ReadUInt16(); - entry.DirectiveDataOffset = data.ReadUInt32(); - - return entry; + return data.ReadType(); } /// @@ -648,20 +565,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled verify record directive table entry on success, null on error - public static VerifyRecordDirectiveTableEntry ParseVerifyRecordDirectiveTableEntry(Stream data) + public static VerifyRecordDirectiveTableEntry? ParseVerifyRecordDirectiveTableEntry(Stream data) { - // TODO: Use marshalling here instead of building - var entry = new VerifyRecordDirectiveTableEntry(); - - entry.EntryCount = data.ReadUInt16(); - entry.OrdinalIndex = data.ReadUInt16(); - entry.Version = data.ReadUInt16(); - entry.ObjectEntriesCount = data.ReadUInt16(); - entry.ObjectNumberInModule = data.ReadUInt16(); - entry.ObjectLoadBaseAddress = data.ReadUInt16(); - entry.ObjectVirtualAddressSize = data.ReadUInt16(); - - return entry; + return data.ReadType(); } /// @@ -669,14 +575,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled fix-up page table entry on success, null on error - public static FixupPageTableEntry ParseFixupPageTableEntry(Stream data) + public static FixupPageTableEntry? ParseFixupPageTableEntry(Stream data) { - // TODO: Use marshalling here instead of building - var entry = new FixupPageTableEntry(); - - entry.Offset = data.ReadUInt32(); - - return entry; + return data.ReadType(); } /// @@ -945,14 +846,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled per-page checksum table entry on success, null on error - public static PerPageChecksumTableEntry ParsePerPageChecksumTableEntry(Stream data) + public static PerPageChecksumTableEntry? ParsePerPageChecksumTableEntry(Stream data) { - // TODO: Use marshalling here instead of building - var entry = new PerPageChecksumTableEntry(); - - entry.Checksum = data.ReadUInt32(); - - return entry; + return data.ReadType(); } /// diff --git a/SabreTools.Serialization/Deserializers/MSDOS.cs b/SabreTools.Serialization/Deserializers/MSDOS.cs index e68c3154..9661427b 100644 --- a/SabreTools.Serialization/Deserializers/MSDOS.cs +++ b/SabreTools.Serialization/Deserializers/MSDOS.cs @@ -126,20 +126,31 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Number of relocation table entries to read /// Filled relocation table on success, null on error - private static RelocationEntry[] ParseRelocationTable(Stream data, int count) + private static RelocationEntry[]? ParseRelocationTable(Stream data, int count) { // TODO: Use marshalling here instead of building var relocationTable = new RelocationEntry[count]; for (int i = 0; i < count; i++) { - var entry = new RelocationEntry(); - entry.Offset = data.ReadUInt16(); - entry.Segment = data.ReadUInt16(); + var entry = ParseRelocationEntry(data); + if (entry == null) + return null; + relocationTable[i] = entry; } return relocationTable; } + + /// + /// Parse a Stream into a relocation table entry + /// + /// Stream to parse + /// Filled relocation table entry on success, null on error + public static RelocationEntry? ParseRelocationEntry(Stream data) + { + return data.ReadType(); + } } } \ No newline at end of file diff --git a/SabreTools.Serialization/Deserializers/MoPaQ.cs b/SabreTools.Serialization/Deserializers/MoPaQ.cs index 156ed286..517546b1 100644 --- a/SabreTools.Serialization/Deserializers/MoPaQ.cs +++ b/SabreTools.Serialization/Deserializers/MoPaQ.cs @@ -404,7 +404,7 @@ namespace SabreTools.Serialization.Deserializers /// Filled user data on success, null on error private static UserData? ParseUserData(Stream data) { - UserData userData = new UserData(); + var userData = new UserData(); byte[]? signature = data.ReadBytes(4); if (signature == null) @@ -428,7 +428,7 @@ namespace SabreTools.Serialization.Deserializers /// Filled HET table on success, null on error private static HetTable? ParseHetTable(Stream data) { - HetTable hetTable = new HetTable(); + var hetTable = new HetTable(); // Common Headers byte[]? signature = data.ReadBytes(4); @@ -465,7 +465,7 @@ namespace SabreTools.Serialization.Deserializers /// Filled BET table on success, null on error private static BetTable? ParseBetTable(Stream data) { - BetTable betTable = new BetTable(); + var betTable = new BetTable(); // Common Headers byte[]? signature = data.ReadBytes(4); @@ -519,18 +519,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled hash entry on success, null on error - private static HashEntry ParseHashEntry(Stream data) + private static HashEntry? ParseHashEntry(Stream data) { - // TODO: Use marshalling here instead of building - HashEntry hashEntry = new HashEntry(); - - hashEntry.NameHashPartA = data.ReadUInt32(); - hashEntry.NameHashPartB = data.ReadUInt32(); - hashEntry.Locale = (Locale)data.ReadUInt16(); - hashEntry.Platform = data.ReadUInt16(); - hashEntry.BlockIndex = data.ReadUInt32(); - - return hashEntry; + return data.ReadType(); } /// @@ -538,16 +529,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled block entry on success, null on error - private static BlockEntry ParseBlockEntry(Stream data) + private static BlockEntry? ParseBlockEntry(Stream data) { - BlockEntry blockEntry = new BlockEntry(); - - blockEntry.FilePosition = data.ReadUInt32(); - blockEntry.CompressedSize = data.ReadUInt32(); - blockEntry.UncompressedSize = data.ReadUInt32(); - blockEntry.Flags = (FileFlags)data.ReadUInt32(); - - return blockEntry; + return data.ReadType(); } /// @@ -558,7 +542,7 @@ namespace SabreTools.Serialization.Deserializers private static PatchInfo ParsePatchInfo(Stream data) { // TODO: Use marshalling here instead of building - PatchInfo patchInfo = new PatchInfo(); + var patchInfo = new PatchInfo(); patchInfo.Length = data.ReadUInt32(); patchInfo.Flags = data.ReadUInt32(); diff --git a/SabreTools.Serialization/Deserializers/N3DS.cs b/SabreTools.Serialization/Deserializers/N3DS.cs index 28f55f5b..48adaa08 100644 --- a/SabreTools.Serialization/Deserializers/N3DS.cs +++ b/SabreTools.Serialization/Deserializers/N3DS.cs @@ -137,7 +137,11 @@ namespace SabreTools.Serialization.Deserializers data.Seek(offset, SeekOrigin.Begin); // Parse the ExeFS header - cart.ExeFSHeaders[i] = ParseExeFSHeader(data); + var exeFsHeader = ParseExeFSHeader(data); + if (exeFsHeader == null) + return null; + + cart.ExeFSHeaders[i] = exeFsHeader; } #endregion @@ -628,7 +632,7 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled ExeFS header on success, null on error - private static ExeFSHeader ParseExeFSHeader(Stream data) + private static ExeFSHeader? ParseExeFSHeader(Stream data) { // TODO: Use marshalling here instead of building var exeFSHeader = new ExeFSHeader(); @@ -636,7 +640,11 @@ namespace SabreTools.Serialization.Deserializers exeFSHeader.FileHeaders = new ExeFSFileHeader[10]; for (int i = 0; i < 10; i++) { - exeFSHeader.FileHeaders[i] = ParseExeFSFileHeader(data); + var exeFsFileHeader = ParseExeFSFileHeader(data); + if (exeFsFileHeader == null) + return null; + + exeFSHeader.FileHeaders[i] = exeFsFileHeader; } exeFSHeader.Reserved = data.ReadBytes(0x20); exeFSHeader.FileHashes = new byte[10][]; @@ -653,7 +661,7 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled ExeFS file header on success, null on error - private static ExeFSFileHeader ParseExeFSFileHeader(Stream data) + private static ExeFSFileHeader? ParseExeFSFileHeader(Stream data) { // TODO: Use marshalling here instead of building var exeFSFileHeader = new ExeFSFileHeader(); diff --git a/SabreTools.Serialization/Deserializers/NCF.cs b/SabreTools.Serialization/Deserializers/NCF.cs index 318a2769..b2665238 100644 --- a/SabreTools.Serialization/Deserializers/NCF.cs +++ b/SabreTools.Serialization/Deserializers/NCF.cs @@ -61,6 +61,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; } @@ -116,6 +119,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.Info1Count; i++) { var directoryInfo1Entry = ParseDirectoryInfo1Entry(data); + if (directoryInfo1Entry == null) + return null; + file.DirectoryInfo1Entries[i] = directoryInfo1Entry; } @@ -130,6 +136,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.ItemCount; i++) { var directoryInfo2Entry = ParseDirectoryInfo2Entry(data); + if (directoryInfo2Entry == null) + return null; + file.DirectoryInfo2Entries[i] = directoryInfo2Entry; } @@ -144,6 +153,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.CopyCount; i++) { var directoryCopyEntry = ParseDirectoryCopyEntry(data); + if (directoryCopyEntry == null) + return null; + file.DirectoryCopyEntries[i] = directoryCopyEntry; } @@ -158,6 +170,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.LocalCount; i++) { var directoryLocalEntry = ParseDirectoryLocalEntry(data); + if (directoryLocalEntry == null) + return null; + file.DirectoryLocalEntries[i] = directoryLocalEntry; } @@ -187,6 +202,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < directoryHeader.ItemCount; i++) { var unknownEntry = ParseUnknownEntry(data); + if (unknownEntry == null) + return null; + file.UnknownEntries[i] = unknownEntry; } @@ -228,6 +246,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < checksumMapHeader.ItemCount; i++) { var checksumMapEntry = ParseChecksumMapEntry(data); + if (checksumMapEntry == null) + return null; + file.ChecksumMapEntries[i] = checksumMapEntry; } @@ -242,6 +263,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < checksumMapHeader.ChecksumCount; i++) { var checksumEntry = ParseChecksumEntry(data); + if (checksumEntry == null) + return null; + file.ChecksumEntries[i] = checksumEntry; } @@ -260,30 +284,17 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life No Cache 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
(); - header.Dummy0 = data.ReadUInt32(); + if (header == null) + return null; if (header.Dummy0 != 0x00000001) return null; - - header.MajorVersion = data.ReadUInt32(); if (header.MajorVersion != 0x00000002) return null; - - header.MinorVersion = data.ReadUInt32(); if (header.MinorVersion != 1) return null; - header.CacheID = data.ReadUInt32(); - header.LastVersionPlayed = data.ReadUInt32(); - header.Dummy1 = data.ReadUInt32(); - header.Dummy2 = data.ReadUInt32(); - header.FileSize = data.ReadUInt32(); - header.BlockSize = data.ReadUInt32(); - header.BlockCount = data.ReadUInt32(); - header.Dummy3 = data.ReadUInt32(); - return header; } @@ -294,27 +305,13 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life No Cache directory header on success, null on error private static DirectoryHeader? ParseDirectoryHeader(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryHeader directoryHeader = new DirectoryHeader(); + var directoryHeader = data.ReadType(); - directoryHeader.Dummy0 = data.ReadUInt32(); + if (directoryHeader == null) + return null; if (directoryHeader.Dummy0 != 0x00000004) return null; - directoryHeader.CacheID = data.ReadUInt32(); - directoryHeader.LastVersionPlayed = data.ReadUInt32(); - directoryHeader.ItemCount = data.ReadUInt32(); - directoryHeader.FileCount = data.ReadUInt32(); - directoryHeader.ChecksumDataLength = data.ReadUInt32(); - directoryHeader.DirectorySize = data.ReadUInt32(); - directoryHeader.NameSize = data.ReadUInt32(); - directoryHeader.Info1Count = data.ReadUInt32(); - directoryHeader.CopyCount = data.ReadUInt32(); - directoryHeader.LocalCount = data.ReadUInt32(); - directoryHeader.Dummy1 = data.ReadUInt32(); - directoryHeader.Dummy2 = data.ReadUInt32(); - directoryHeader.Checksum = data.ReadUInt32(); - return directoryHeader; } @@ -323,10 +320,10 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life No 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 - DirectoryEntry directoryEntry = new DirectoryEntry(); + var directoryEntry = new DirectoryEntry(); directoryEntry.NameOffset = data.ReadUInt32(); directoryEntry.ItemSize = data.ReadUInt32(); @@ -344,14 +341,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life No Cache directory info 1 entry on success, null on error - private static DirectoryInfo1Entry ParseDirectoryInfo1Entry(Stream data) + private static DirectoryInfo1Entry? ParseDirectoryInfo1Entry(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryInfo1Entry directoryInfo1Entry = new DirectoryInfo1Entry(); - - directoryInfo1Entry.Dummy0 = data.ReadUInt32(); - - return directoryInfo1Entry; + return data.ReadType(); } /// @@ -359,14 +351,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life No Cache directory info 2 entry on success, null on error - private static DirectoryInfo2Entry ParseDirectoryInfo2Entry(Stream data) + private static DirectoryInfo2Entry? ParseDirectoryInfo2Entry(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryInfo2Entry directoryInfo2Entry = new DirectoryInfo2Entry(); - - directoryInfo2Entry.Dummy0 = data.ReadUInt32(); - - return directoryInfo2Entry; + return data.ReadType(); } /// @@ -374,14 +361,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life No Cache directory copy entry on success, null on error - private static DirectoryCopyEntry ParseDirectoryCopyEntry(Stream data) + private static DirectoryCopyEntry? ParseDirectoryCopyEntry(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryCopyEntry directoryCopyEntry = new DirectoryCopyEntry(); - - directoryCopyEntry.DirectoryIndex = data.ReadUInt32(); - - return directoryCopyEntry; + return data.ReadType(); } /// @@ -389,14 +371,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life No Cache directory local entry on success, null on error - private static DirectoryLocalEntry ParseDirectoryLocalEntry(Stream data) + private static DirectoryLocalEntry? ParseDirectoryLocalEntry(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryLocalEntry directoryLocalEntry = new DirectoryLocalEntry(); - - directoryLocalEntry.DirectoryIndex = data.ReadUInt32(); - - return directoryLocalEntry; + return data.ReadType(); } /// @@ -406,14 +383,12 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life No Cache unknown header on success, null on error private static UnknownHeader? ParseUnknownHeader(Stream data) { - // TODO: Use marshalling here instead of building - UnknownHeader unknownHeader = new UnknownHeader(); + var unknownHeader = data.ReadType(); - unknownHeader.Dummy0 = data.ReadUInt32(); + if (unknownHeader == null) + return null; if (unknownHeader.Dummy0 != 0x00000001) return null; - - unknownHeader.Dummy1 = data.ReadUInt32(); if (unknownHeader.Dummy1 != 0x00000000) return null; @@ -425,14 +400,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life No Cacheunknown entry on success, null on error - private static UnknownEntry ParseUnknownEntry(Stream data) + private static UnknownEntry? ParseUnknownEntry(Stream data) { - // TODO: Use marshalling here instead of building - UnknownEntry unknownEntry = new UnknownEntry(); - - unknownEntry.Dummy0 = data.ReadUInt32(); - - return unknownEntry; + return data.ReadType(); } /// @@ -442,15 +412,13 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life No Cache checksum header on success, null on error private static ChecksumHeader? ParseChecksumHeader(Stream data) { - // TODO: Use marshalling here instead of building - ChecksumHeader checksumHeader = new ChecksumHeader(); + var checksumHeader = data.ReadType(); - checksumHeader.Dummy0 = data.ReadUInt32(); + if (checksumHeader == null) + return null; if (checksumHeader.Dummy0 != 0x00000001) return null; - checksumHeader.ChecksumSize = data.ReadUInt32(); - return checksumHeader; } @@ -461,20 +429,15 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life No Cache checksum map header on success, null on error private static ChecksumMapHeader? ParseChecksumMapHeader(Stream data) { - // TODO: Use marshalling here instead of building - ChecksumMapHeader checksumMapHeader = new ChecksumMapHeader(); + var checksumMapHeader = data.ReadType(); - checksumMapHeader.Dummy0 = data.ReadUInt32(); + if (checksumMapHeader == null) + return null; if (checksumMapHeader.Dummy0 != 0x14893721) return null; - - checksumMapHeader.Dummy1 = data.ReadUInt32(); if (checksumMapHeader.Dummy1 != 0x00000001) return null; - checksumMapHeader.ItemCount = data.ReadUInt32(); - checksumMapHeader.ChecksumCount = data.ReadUInt32(); - return checksumMapHeader; } @@ -483,15 +446,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life No Cache checksum map entry on success, null on error - private static ChecksumMapEntry ParseChecksumMapEntry(Stream data) + private static ChecksumMapEntry? ParseChecksumMapEntry(Stream data) { - // TODO: Use marshalling here instead of building - ChecksumMapEntry checksumMapEntry = new ChecksumMapEntry(); - - checksumMapEntry.ChecksumCount = data.ReadUInt32(); - checksumMapEntry.FirstChecksumIndex = data.ReadUInt32(); - - return checksumMapEntry; + return data.ReadType(); } /// @@ -499,14 +456,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life No Cache checksum entry on success, null on error - private static ChecksumEntry ParseChecksumEntry(Stream data) + private static ChecksumEntry? ParseChecksumEntry(Stream data) { - // TODO: Use marshalling here instead of building - ChecksumEntry checksumEntry = new ChecksumEntry(); - - checksumEntry.Checksum = data.ReadUInt32(); - - return checksumEntry; + return data.ReadType(); } } } \ No newline at end of file diff --git a/SabreTools.Serialization/Deserializers/NewExecutable.cs b/SabreTools.Serialization/Deserializers/NewExecutable.cs index a7aad63a..bec0fb13 100644 --- a/SabreTools.Serialization/Deserializers/NewExecutable.cs +++ b/SabreTools.Serialization/Deserializers/NewExecutable.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using SabreTools.IO.Extensions; using SabreTools.Models.NewExecutable; using static SabreTools.Models.NewExecutable.Constants; @@ -214,48 +213,13 @@ namespace SabreTools.Serialization.Deserializers /// Filled executable header on success, null on error public static ExecutableHeader? ParseExecutableHeader(Stream data) { - // TODO: Use marshalling here instead of building - var header = new ExecutableHeader(); + var header = data.ReadType(); - byte[]? magic = data.ReadBytes(2); - if (magic == null) + if (header == null) return null; - - header.Magic = Encoding.ASCII.GetString(magic); if (header.Magic != SignatureString) return null; - header.LinkerVersion = data.ReadByteValue(); - header.LinkerRevision = data.ReadByteValue(); - header.EntryTableOffset = data.ReadUInt16(); - header.EntryTableSize = data.ReadUInt16(); - header.CrcChecksum = data.ReadUInt32(); - header.FlagWord = (HeaderFlag)data.ReadUInt16(); - header.AutomaticDataSegmentNumber = data.ReadUInt16(); - header.InitialHeapAlloc = data.ReadUInt16(); - header.InitialStackAlloc = data.ReadUInt16(); - header.InitialCSIPSetting = data.ReadUInt32(); - header.InitialSSSPSetting = data.ReadUInt32(); - header.FileSegmentCount = data.ReadUInt16(); - header.ModuleReferenceTableSize = data.ReadUInt16(); - header.NonResidentNameTableSize = data.ReadUInt16(); - header.SegmentTableOffset = data.ReadUInt16(); - header.ResourceTableOffset = data.ReadUInt16(); - header.ResidentNameTableOffset = data.ReadUInt16(); - header.ModuleReferenceTableOffset = data.ReadUInt16(); - header.ImportedNamesTableOffset = data.ReadUInt16(); - header.NonResidentNamesTableOffset = data.ReadUInt32(); - header.MovableEntriesCount = data.ReadUInt16(); - header.SegmentAlignmentShiftCount = data.ReadUInt16(); - header.ResourceEntriesCount = data.ReadUInt16(); - header.TargetOperatingSystem = (OperatingSystem)data.ReadByteValue(); - header.AdditionalFlags = (OS2Flag)data.ReadByteValue(); - header.ReturnThunkOffset = data.ReadUInt16(); - header.SegmentReferenceThunkOffset = data.ReadUInt16(); - header.MinCodeSwapAreaSize = data.ReadUInt16(); - header.WindowsSDKRevision = data.ReadByteValue(); - header.WindowsSDKVersion = data.ReadByteValue(); - return header; } @@ -265,31 +229,40 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Number of segment table entries to read /// Filled segment table on success, null on error - public static SegmentTableEntry[] ParseSegmentTable(Stream data, int count) + public static SegmentTableEntry[]? ParseSegmentTable(Stream data, int count) { // TODO: Use marshalling here instead of building var segmentTable = new SegmentTableEntry[count]; for (int i = 0; i < count; i++) { - var entry = new SegmentTableEntry(); - entry.Offset = data.ReadUInt16(); - entry.Length = data.ReadUInt16(); - entry.FlagWord = (SegmentTableEntryFlag)data.ReadUInt16(); - entry.MinimumAllocationSize = data.ReadUInt16(); + var entry = ParseSegmentTableEntry(data); + if (entry == null) + return null; + segmentTable[i] = entry; } return segmentTable; } + /// + /// Parse a Stream into a segment table entry + /// + /// Stream to parse + /// Filled segment table entry on success, null on error + public static SegmentTableEntry? ParseSegmentTableEntry(Stream data) + { + return data.ReadType(); + } + /// /// Parse a Stream into a resource table /// /// Stream to parse /// Number of resource table entries to read /// Filled resource table on success, null on error - public static ResourceTable ParseResourceTable(Stream data, int count) + public static ResourceTable? ParseResourceTable(Stream data, int count) { long initialOffset = data.Position; @@ -308,12 +281,10 @@ namespace SabreTools.Serialization.Deserializers for (int j = 0; j < entry.ResourceCount; j++) { // TODO: Should we read and store the resource data? - var resource = new ResourceTypeResourceEntry(); - resource.Offset = data.ReadUInt16(); - resource.Length = data.ReadUInt16(); - resource.FlagWord = (ResourceTypeResourceFlag)data.ReadUInt16(); - resource.ResourceID = data.ReadUInt16(); - resource.Reserved = data.ReadUInt32(); + var resource = ParseResourceTypeResourceEntry(data); + if (resource == null) + return null; + entry.Resources[j] = resource; } resourceTable.ResourceTypes[i] = entry; @@ -339,66 +310,124 @@ namespace SabreTools.Serialization.Deserializers { int stringOffset = (int)(stringOffsets[i] + initialOffset); data.Seek(stringOffset, SeekOrigin.Begin); - var str = new ResourceTypeAndNameString(); - str.Length = data.ReadByteValue(); - str.Text = data.ReadBytes(str.Length); + + var str = ParseResourceTypeAndNameString(data); + if (str == null) + return null; + resourceTable.TypeAndNameStrings[stringOffsets[i]] = str; } return resourceTable; } + /// + /// Parse a Stream into a resource entry + /// + /// Stream to parse + /// Filled resource entry on success, null on error + public static ResourceTypeResourceEntry? ParseResourceTypeResourceEntry(Stream data) + { + // TODO: Should we read and store the resource data? + return data.ReadType(); + } + + /// + /// Parse a Stream into a resource type and name string + /// + /// Stream to parse + /// Filled resource type and name string on success, null on error + public static ResourceTypeAndNameString? ParseResourceTypeAndNameString(Stream data) + { + // TODO: Use marshalling here instead of building + var str = new ResourceTypeAndNameString(); + + str.Length = data.ReadByteValue(); + str.Text = data.ReadBytes(str.Length); + + return str; + } + /// /// Parse a Stream into a resident-name table /// /// Stream to parse /// First address not part of the resident-name table /// Filled resident-name table on success, null on error - public static ResidentNameTableEntry[] ParseResidentNameTable(Stream data, int endOffset) + public static ResidentNameTableEntry[]? ParseResidentNameTable(Stream data, int endOffset) { // TODO: Use marshalling here instead of building var residentNameTable = new List(); while (data.Position < endOffset) { - var entry = new ResidentNameTableEntry(); - entry.Length = data.ReadByteValue(); - entry.NameString = data.ReadBytes(entry.Length); - entry.OrdinalNumber = data.ReadUInt16(); + var entry = ParseResidentNameTableEntry(data); + if (entry == null) + return null; + residentNameTable.Add(entry); } return [.. residentNameTable]; } + /// + /// Parse a Stream into a resident-name table entry + /// + /// Stream to parse + /// Filled resident-name table entry on success, null on error + public static ResidentNameTableEntry? ParseResidentNameTableEntry(Stream data) + { + // TODO: Use marshalling here instead of building + var entry = new ResidentNameTableEntry(); + + entry.Length = data.ReadByteValue(); + entry.NameString = data.ReadBytes(entry.Length); + entry.OrdinalNumber = data.ReadUInt16(); + + return entry; + } + /// /// Parse a Stream into a module-reference table /// /// Stream to parse /// Number of module-reference table entries to read /// Filled module-reference table on success, null on error - public static ModuleReferenceTableEntry[] ParseModuleReferenceTable(Stream data, int count) + public static ModuleReferenceTableEntry[]? ParseModuleReferenceTable(Stream data, int count) { // TODO: Use marshalling here instead of building var moduleReferenceTable = new ModuleReferenceTableEntry[count]; for (int i = 0; i < count; i++) { - var entry = new ModuleReferenceTableEntry(); - entry.Offset = data.ReadUInt16(); + var entry = ParseModuleReferenceTableEntry(data); + if (entry == null) + return null; + moduleReferenceTable[i] = entry; } return moduleReferenceTable; } + /// + /// Parse a Stream into a module-reference table entry + /// + /// Stream to parse + /// Filled module-reference table entry on success, null on error + public static ModuleReferenceTableEntry? ParseModuleReferenceTableEntry(Stream data) + { + return data.ReadType(); + } + /// /// Parse a Stream into an imported-name table /// /// Stream to parse /// First address not part of the imported-name table /// Filled imported-name table on success, null on error - public static Dictionary ParseImportedNameTable(Stream data, int endOffset) + public static Dictionary? ParseImportedNameTable(Stream data, int endOffset) { // TODO: Use marshalling here instead of building var importedNameTable = new Dictionary(); @@ -406,15 +435,32 @@ namespace SabreTools.Serialization.Deserializers while (data.Position < endOffset) { ushort currentOffset = (ushort)data.Position; - var entry = new ImportedNameTableEntry(); - entry.Length = data.ReadByteValue(); - entry.NameString = data.ReadBytes(entry.Length); + var entry = ParseImportedNameTableEntry(data); + if (entry == null) + return null; + importedNameTable[currentOffset] = entry; } return importedNameTable; } + /// + /// Parse a Stream into an imported-name table entry + /// + /// Stream to parse + /// Filled imported-name table entry on success, null on error + public static ImportedNameTableEntry? ParseImportedNameTableEntry(Stream data) + { + // TODO: Use marshalling here instead of building + var entry = new ImportedNameTableEntry(); + + entry.Length = data.ReadByteValue(); + entry.NameString = data.ReadBytes(entry.Length); + + return entry; + } + /// /// Parse a Stream into an entry table /// @@ -460,21 +506,38 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// First address not part of the nonresident-name table /// Filled nonresident-name table on success, null on error - public static NonResidentNameTableEntry[] ParseNonResidentNameTable(Stream data, int endOffset) + public static NonResidentNameTableEntry[]? ParseNonResidentNameTable(Stream data, int endOffset) { // TODO: Use marshalling here instead of building var residentNameTable = new List(); while (data.Position < endOffset) { - var entry = new NonResidentNameTableEntry(); - entry.Length = data.ReadByteValue(); - entry.NameString = data.ReadBytes(entry.Length); - entry.OrdinalNumber = data.ReadUInt16(); + var entry = ParseNonResidentNameTableEntry(data); + if (entry == null) + return null; + residentNameTable.Add(entry); } return [.. residentNameTable]; } + + /// + /// Parse a Stream into a nonresident-name table entry + /// + /// Stream to parse + /// Filled nonresident-name table entry on success, null on error + public static NonResidentNameTableEntry? ParseNonResidentNameTableEntry(Stream data) + { + // TODO: Use marshalling here instead of building + var entry = new NonResidentNameTableEntry(); + + entry.Length = data.ReadByteValue(); + entry.NameString = data.ReadBytes(entry.Length); + entry.OrdinalNumber = data.ReadUInt16(); + + return entry; + } } } \ No newline at end of file diff --git a/SabreTools.Serialization/Deserializers/Nitro.cs b/SabreTools.Serialization/Deserializers/Nitro.cs index 56bb37b0..1807a482 100644 --- a/SabreTools.Serialization/Deserializers/Nitro.cs +++ b/SabreTools.Serialization/Deserializers/Nitro.cs @@ -184,7 +184,7 @@ namespace SabreTools.Serialization.Deserializers private static ExtendedDSiHeader ParseExtendedDSiHeader(Stream data) { // TODO: Use marshalling here instead of building - ExtendedDSiHeader extendedDSiHeader = new ExtendedDSiHeader(); + var extendedDSiHeader = new ExtendedDSiHeader(); extendedDSiHeader.GlobalMBK15Settings = new uint[5]; for (int i = 0; i < 5; i++) @@ -226,6 +226,8 @@ namespace SabreTools.Serialization.Deserializers 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(); @@ -304,7 +306,7 @@ namespace SabreTools.Serialization.Deserializers private static FolderAllocationTableEntry ParseFolderAllocationTableEntry(Stream data) { // TODO: Use marshalling here instead of building - FolderAllocationTableEntry entry = new FolderAllocationTableEntry(); + var entry = new FolderAllocationTableEntry(); entry.StartOffset = data.ReadUInt32(); entry.FirstFileIndex = data.ReadUInt16(); @@ -322,7 +324,7 @@ namespace SabreTools.Serialization.Deserializers private static NameListEntry? ParseNameListEntry(Stream data) { // TODO: Use marshalling here instead of building - NameListEntry entry = new NameListEntry(); + var entry = new NameListEntry(); byte flagAndSize = data.ReadByteValue(); if (flagAndSize == 0xFF) @@ -352,7 +354,7 @@ namespace SabreTools.Serialization.Deserializers private static FileAllocationTableEntry ParseFileAllocationTableEntry(Stream data) { // TODO: Use marshalling here instead of building - FileAllocationTableEntry entry = new FileAllocationTableEntry(); + var entry = new FileAllocationTableEntry(); entry.StartOffset = data.ReadUInt32(); entry.EndOffset = data.ReadUInt32(); diff --git a/SabreTools.Serialization/Deserializers/PAK.cs b/SabreTools.Serialization/Deserializers/PAK.cs index e9b26607..e8473a9a 100644 --- a/SabreTools.Serialization/Deserializers/PAK.cs +++ b/SabreTools.Serialization/Deserializers/PAK.cs @@ -1,5 +1,4 @@ using System.IO; -using System.Text; using SabreTools.IO.Extensions; using SabreTools.Models.PAK; using static SabreTools.Models.PAK.Constants; @@ -54,6 +53,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < file.DirectoryItems.Length; i++) { var directoryItem = ParseDirectoryItem(data); + if (directoryItem == null) + return null; + file.DirectoryItems[i] = directoryItem; } @@ -69,20 +71,13 @@ namespace SabreTools.Serialization.Deserializers /// Filled Half-Life 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.DirectoryOffset = data.ReadUInt32(); - header.DirectoryLength = data.ReadUInt32(); - return header; } @@ -91,18 +86,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Half-Life Package directory item on success, null on error - private static DirectoryItem ParseDirectoryItem(Stream data) + private static DirectoryItem? ParseDirectoryItem(Stream data) { - // TODO: Use marshalling here instead of building - DirectoryItem directoryItem = new DirectoryItem(); - - byte[]? itemName = data.ReadBytes(56); - if (itemName != null) - directoryItem.ItemName = Encoding.ASCII.GetString(itemName).TrimEnd('\0'); - directoryItem.ItemOffset = data.ReadUInt32(); - directoryItem.ItemLength = data.ReadUInt32(); - - return directoryItem; + return data.ReadType(); } } } \ No newline at end of file diff --git a/SabreTools.Serialization/Deserializers/PFF.cs b/SabreTools.Serialization/Deserializers/PFF.cs index 7d38a273..8743ea6e 100644 --- a/SabreTools.Serialization/Deserializers/PFF.cs +++ b/SabreTools.Serialization/Deserializers/PFF.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Runtime.InteropServices; using System.Text; using SabreTools.IO.Extensions; using SabreTools.Models.PFF; @@ -92,47 +93,27 @@ namespace SabreTools.Serialization.Deserializers /// Filled header on success, null on error private static Header? ParseHeader(Stream data) { - // TODO: Use marshalling here instead of building - Header header = new Header(); - - header.HeaderSize = data.ReadUInt32(); - byte[]? signature = data.ReadBytes(4); - if (signature == null) + var header = data.ReadType
(); + if (header == null) return null; - header.Signature = Encoding.ASCII.GetString(signature); - header.NumberOfFiles = data.ReadUInt32(); - header.FileSegmentSize = data.ReadUInt32(); - switch (header.Signature) + return header.Signature switch { - case Version0SignatureString: - if (header.FileSegmentSize != Version0HSegmentSize) - return null; - break; + Version0SignatureString when header.FileSegmentSize != Version0HSegmentSize => null, + Version0SignatureString => header, - case Version2SignatureString: - if (header.FileSegmentSize != Version2SegmentSize) - return null; - break; + Version2SignatureString when header.FileSegmentSize != Version2SegmentSize => null, + Version2SignatureString => header, - // Version 3 can sometimes have Version 2 segment sizes - case Version3SignatureString: - if (header.FileSegmentSize != Version2SegmentSize && header.FileSegmentSize != Version3SegmentSize) - return null; - break; + Version3SignatureString when header.FileSegmentSize != Version2SegmentSize + && header.FileSegmentSize != Version3SegmentSize => null, + Version3SignatureString => header, - case Version4SignatureString: - if (header.FileSegmentSize != Version4SegmentSize) - return null; - break; + Version4SignatureString when header.FileSegmentSize != Version4SegmentSize => null, + Version4SignatureString => header, - default: - return null; - } - - header.FileListOffset = data.ReadUInt32(); - - return header; + _ => null, + }; } /// @@ -140,18 +121,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled footer on success, null on error - private static Footer ParseFooter(Stream data) + private static Footer? ParseFooter(Stream data) { - // TODO: Use marshalling here instead of building - Footer footer = new Footer(); - - footer.SystemIP = data.ReadUInt32(); - footer.Reserved = data.ReadUInt32(); - byte[]? kingTag = data.ReadBytes(4); - if (kingTag != null) - footer.KingTag = Encoding.ASCII.GetString(kingTag); - - return footer; + return data.ReadType