Dark Messiah of Might and Magic GCF extraction fails due to the next index being one past the final entry index #19

Closed
opened 2026-01-29 21:16:37 +00:00 by claunia · 3 comments
Owner

Originally created by @HeroponRikiBestest on GitHub (Nov 30, 2025).

Seems to impact most if not all of the GCF files, in all releases of Dark Messiah of Might and Magic on redump. For this output, I'm using mm_engine_pub.gcf since it's one of the smallest ones and should be present on every release.

When running get_files for the GCFs, the wrapper enters this loop

4b39ee8d00/SabreTools.Serialization/Wrappers/GCF.cs (L95)

with a valid starting index. However, after it's been added to the block entries, it tries to get the index of the next block. The index it gets is 22781. The size of Model.BlockEntries for this GCF is 22781, so this will fail with an out of bounds exception. I assume it's not coincidence that it just happens to be the exact size of the array, but I don't know enough about GCFs to say why.

Console output:

Checking possible path: /home/bestest/testBosIssue/mm_engine_pub.gcf
Attempting to extract all files from /home/bestest/testBosIssue/mm_engine_pub.gcf
Attempting to extract from 'Half-Life Game Cache File (GCF)'

Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at SabreTools.Serialization.Wrappers.GCF.get_Files() in /home/runner/work/SabreTools.Serialization/SabreTools.Serialization/SabreTools.Serialization/Wrappers/GCF.cs:line 97
   at SabreTools.Serialization.Wrappers.GCF.Extract(String outputDirectory, Boolean includeDebug) in /home/runner/work/SabreTools.Serialization/SabreTools.Serialization/SabreTools.Serialization/Wrappers/GCF.Extraction.cs:line 13
   at ExtractionTool.Features.MainFeature.ExtractFile(String file) in /home/runner/work/SabreTools.Serialization/SabreTools.Serialization/ExtractionTool/Features/MainFeature.cs:line 180
   at ExtractionTool.Features.MainFeature.ExtractPath(String path) in /home/runner/work/SabreTools.Serialization/SabreTools.Serialization/ExtractionTool/Features/MainFeature.cs:line 95
   at ExtractionTool.Features.MainFeature.Execute() in /home/runner/work/SabreTools.Serialization/SabreTools.Serialization/ExtractionTool/Features/MainFeature.cs:line 73
Originally created by @HeroponRikiBestest on GitHub (Nov 30, 2025). Seems to impact most if not all of the GCF files, in all releases of Dark Messiah of Might and Magic on redump. For this output, I'm using `mm_engine_pub.gcf` since it's one of the smallest ones and should be present on every release. When running get_files for the GCFs, the wrapper enters this loop https://github.com/SabreTools/SabreTools.Serialization/blob/4b39ee8d0058ce20101c0ae41ef755e6fe6e3f50/SabreTools.Serialization/Wrappers/GCF.cs#L95 with a valid starting index. However, after it's been added to the block entries, it tries to get the index of the next block. The index it gets is 22781. The size of Model.BlockEntries for this GCF is 22781, so this will fail with an out of bounds exception. I assume it's not coincidence that it just happens to be the exact size of the array, but I don't know enough about GCFs to say why. Console output: ``` Checking possible path: /home/bestest/testBosIssue/mm_engine_pub.gcf Attempting to extract all files from /home/bestest/testBosIssue/mm_engine_pub.gcf Attempting to extract from 'Half-Life Game Cache File (GCF)' Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array. at SabreTools.Serialization.Wrappers.GCF.get_Files() in /home/runner/work/SabreTools.Serialization/SabreTools.Serialization/SabreTools.Serialization/Wrappers/GCF.cs:line 97 at SabreTools.Serialization.Wrappers.GCF.Extract(String outputDirectory, Boolean includeDebug) in /home/runner/work/SabreTools.Serialization/SabreTools.Serialization/SabreTools.Serialization/Wrappers/GCF.Extraction.cs:line 13 at ExtractionTool.Features.MainFeature.ExtractFile(String file) in /home/runner/work/SabreTools.Serialization/SabreTools.Serialization/ExtractionTool/Features/MainFeature.cs:line 180 at ExtractionTool.Features.MainFeature.ExtractPath(String path) in /home/runner/work/SabreTools.Serialization/SabreTools.Serialization/ExtractionTool/Features/MainFeature.cs:line 95 at ExtractionTool.Features.MainFeature.Execute() in /home/runner/work/SabreTools.Serialization/SabreTools.Serialization/ExtractionTool/Features/MainFeature.cs:line 73 ```
Author
Owner

@mnadareski commented on GitHub (Dec 2, 2025):

This should be caught by the condition of the while loop. If the next entry index is the block count, it's meant to break, as is documented in the model as well. The issue you're seeing is implying that the index is either not getting set or the value is not the block count, both of which are not good.

@mnadareski commented on GitHub (Dec 2, 2025): This should be caught by the condition of the `while` loop. If the next entry index is the block count, it's meant to break, as is documented in the model as well. The issue you're seeing is implying that the index is either not getting set or the value is not the block count, both of which are not good.
Author
Owner

@HeroponRikiBestest commented on GitHub (Dec 2, 2025):

The condition is the while loop isn't to check Model.BlockCount's size, it's to check Model.DataBlockHeader.BlockCount, which for this gcf is 812384356. Since it's not 22781, it's not caught by the condition of the while loop.

  {SabreTools.Data.Models.GCF.DataBlockHeader}
    BlockCount: 812384356
    BlockSize: 1819303732
    BlocksUsed: 1818321503
    Checksum: 1635021673
    FirstBlockOffset: 1919252833
    LastVersionPlayed: 1668689458
@HeroponRikiBestest commented on GitHub (Dec 2, 2025): The condition is the while loop isn't to check Model.BlockCount's size, it's to check Model.DataBlockHeader.BlockCount, which for this gcf is 812384356. Since it's not 22781, it's not caught by the condition of the while loop. ```cs {SabreTools.Data.Models.GCF.DataBlockHeader} BlockCount: 812384356 BlockSize: 1819303732 BlocksUsed: 1818321503 Checksum: 1635021673 FirstBlockOffset: 1919252833 LastVersionPlayed: 1668689458 ```
Author
Owner

@HeroponRikiBestest commented on GitHub (Dec 4, 2025):

Fixed as of latest commits

@HeroponRikiBestest commented on GitHub (Dec 4, 2025): Fixed as of latest commits
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: SabreTools/SabreTools.Serialization#19