From 66da74e00a3e67cb978dfff68e399c2e72d761dc Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sun, 12 May 2024 11:46:05 -0400 Subject: [PATCH] Fix resource table issues with NE --- .../Deserializers/NewExecutable.cs | 29 ++++++++++++++----- .../Extensions.NewExecutable.cs | 18 ++---------- .../Printers/NewExecutable.cs | 2 +- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/SabreTools.Serialization/Deserializers/NewExecutable.cs b/SabreTools.Serialization/Deserializers/NewExecutable.cs index 0e68c685..276eae77 100644 --- a/SabreTools.Serialization/Deserializers/NewExecutable.cs +++ b/SabreTools.Serialization/Deserializers/NewExecutable.cs @@ -76,7 +76,7 @@ namespace SabreTools.Serialization.Deserializers // If the offset for the segment table doesn't exist tableAddress = initialOffset + (int)stub.Header.NewExeHeaderAddr - + executableHeader.SegmentTableOffset; + + executableHeader.ResourceTableOffset; if (tableAddress >= data.Length) return executable; @@ -262,7 +262,7 @@ namespace SabreTools.Serialization.Deserializers /// 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, ushort count) { long initialOffset = data.Position; @@ -270,13 +270,23 @@ namespace SabreTools.Serialization.Deserializers var resourceTable = new ResourceTable(); resourceTable.AlignmentShiftCount = data.ReadUInt16(); - resourceTable.ResourceTypes = new ResourceTypeInformationEntry[count]; - for (int i = 0; i < resourceTable.ResourceTypes.Length; i++) + var resourceTypes = new List(); + + for (int i = 0; i < count; i++) { var entry = new ResourceTypeInformationEntry(); + entry.TypeID = data.ReadUInt16(); entry.ResourceCount = data.ReadUInt16(); entry.Reserved = data.ReadUInt32(); + + // A zero type ID marks the end of the resource type information blocks. + if (entry.TypeID == 0) + { + resourceTypes.Add(entry); + break; + } + entry.Resources = new ResourceTypeResourceEntry[entry.ResourceCount]; for (int j = 0; j < entry.ResourceCount; j++) { @@ -287,20 +297,23 @@ namespace SabreTools.Serialization.Deserializers entry.Resources[j] = resource; } - resourceTable.ResourceTypes[i] = entry; + resourceTypes.Add(entry); } + resourceTable.ResourceTypes = [.. resourceTypes]; + // Get the full list of unique string offsets var stringOffsets = resourceTable.ResourceTypes .Where(rt => rt != null) - .Where(rt => rt!.IsIntegerType() == false) + .Where(rt => !rt!.IsIntegerType() && rt!.TypeID != 0) .Select(rt => rt!.TypeID) .Union(resourceTable.ResourceTypes - .Where(rt => rt != null) + .Where(rt => rt != null && rt!.TypeID != 0) .SelectMany(rt => rt!.Resources ?? []) - .Where(r => r!.IsIntegerType() == false) + .Where(r => !r!.IsIntegerType()) .Select(r => r!.ResourceID)) .Distinct() + .Where(o => o != 0) .OrderBy(o => o) .ToList(); diff --git a/SabreTools.Serialization/Extensions.NewExecutable.cs b/SabreTools.Serialization/Extensions.NewExecutable.cs index b8572954..a5511100 100644 --- a/SabreTools.Serialization/Extensions.NewExecutable.cs +++ b/SabreTools.Serialization/Extensions.NewExecutable.cs @@ -9,13 +9,8 @@ namespace SabreTools.Serialization /// /// Resource type information entry to check /// True if the entry is an integer type, false if an offset, null on error - public static bool? IsIntegerType(this ResourceTypeInformationEntry entry) + public static bool IsIntegerType(this ResourceTypeInformationEntry entry) { - // We can't do anything with an invalid entry - if (entry == null) - return null; - - // If the highest order bit is set, it's an integer type return (entry.TypeID & 0x8000) != 0; } @@ -24,13 +19,8 @@ namespace SabreTools.Serialization /// /// Resource type resource entry to check /// True if the entry is an integer type, false if an offset, null on error - public static bool? IsIntegerType(this ResourceTypeResourceEntry entry) + public static bool IsIntegerType(this ResourceTypeResourceEntry entry) { - // We can't do anything with an invalid entry - if (entry == null) - return null; - - // If the highest order bit is set, it's an integer type return (entry.ResourceID & 0x8000) != 0; } @@ -41,10 +31,6 @@ namespace SabreTools.Serialization /// SegmentEntryType corresponding to the type public static SegmentEntryType GetEntryType(this EntryTableBundle entry) { - // We can't do anything with an invalid entry - if (entry == null) - return SegmentEntryType.Unused; - // Determine the entry type based on segment indicator if (entry.SegmentIndicator == 0x00) return SegmentEntryType.Unused; diff --git a/SabreTools.Serialization/Printers/NewExecutable.cs b/SabreTools.Serialization/Printers/NewExecutable.cs index b6fb7251..10b041b6 100644 --- a/SabreTools.Serialization/Printers/NewExecutable.cs +++ b/SabreTools.Serialization/Printers/NewExecutable.cs @@ -188,7 +188,7 @@ namespace SabreTools.Serialization.Printers { // TODO: If not integer type, print out name var resource = entry.Resources[j]; - builder.AppendLine($" Resource Entry {i}"); + builder.AppendLine($" Resource Entry {j}"); if (resource == null) { builder.AppendLine(" [NULL]");