Files
SabreTools.Serialization/SabreTools.Wrappers/Helpers/FileSystemTableReader.cs

173 lines
5.4 KiB
C#
Raw Normal View History

Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
using System.Collections.Generic;
// TODO: Remove when IO is updated
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
namespace SabreTools.Wrappers
{
/// <summary>
/// Lightweight GameCube / Wii File-System Table (FST) reader used by
/// <see cref="RvzPackEncoder"/> to distinguish real-file regions from junk.
///
/// Mirrors Dolphin's FileSystemGCWii offset-to-file-info cache
/// (m_offset_file_info_cache).
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
/// </summary>
public sealed class FileSystemTableReader
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
{
/// <summary>
/// File entry with start and end byte offsets on disc
/// </summary>
public struct FileEntry
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
{
public long FileStart;
public long FileEnd;
}
/// <remarks>
/// Sorted ascending by FileEnd for O(log n) upper_bound queries.
/// </remarks>
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
private readonly List<FileEntry> _files;
private FileSystemTableReader(List<FileEntry> files)
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
{
_files = files;
}
/// <summary>
/// Parses a raw FST binary blob and returns a <see cref="FileSystemTableReader"/>,
/// or null if the data is too short or structurally invalid.
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
/// </summary>
/// <param name="fstData">
/// Raw FST bytes exactly as stored on disc (GameCube) or in decrypted
/// Wii partition data.
/// </param>
/// <param name="offsetShift">
/// Bit-shift to convert raw file-offset fields to byte addresses.
/// 0 for GameCube (direct bytes); 2 for Wii (offset × 4).
/// </param>
public static FileSystemTableReader? TryParse(byte[] fstData, int offsetShift)
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
{
// Read the file system table
var table = Serialization.Readers.NintendoDisc.ParseFileSystemTable(fstData);
if (table is null)
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
return null;
// Filter out the entries to non-empty files only
var filtered = new List<FileEntry>();
foreach (var entry in table.Entries)
{
// Directory entry
if ((entry.NameOffset & 0xFF000000) != 0)
continue;
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
// Empty file
if (entry.FileSize == 0)
continue;
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
long fileStart = entry.FileOffset << offsetShift;
long fileEnd = fileStart + entry.FileSize;
var fileEntry = new FileEntry
{
FileStart = fileStart,
FileEnd = fileEnd,
};
filtered.Add(fileEntry);
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
}
// Sort ascending by FileEnd so binary-search upper_bound works correctly.
filtered.Sort(delegate (FileEntry a, FileEntry b)
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
{
return a.FileEnd.CompareTo(b.FileEnd);
});
return new FileSystemTableReader(filtered);
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
}
/// <summary>
/// Returns the file entry whose byte range contains <paramref name="discOffset"/>,
/// or null if no file does.
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
/// </summary>
/// TODO: Determine how to use List<T>.BinarySearch here
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
public FileEntry? FindFileInfo(long discOffset)
{
if (_files.Count == 0)
return null;
// Binary search: first index where _files[i].FileEnd > discOffset
int lo = 0, hi = _files.Count;
while (lo < hi)
{
int mid = (lo + hi) >> 1;
if (_files[mid].FileEnd <= discOffset)
lo = mid + 1;
else
hi = mid;
}
if (lo >= _files.Count)
return null;
var e = _files[lo];
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
if (e.FileStart <= discOffset)
return e;
return null;
}
/// <summary>
/// Returns the smallest FileEnd value strictly greater than
/// <paramref name="discOffset"/>, or null if there is none.
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
/// </summary>
public long? FindNextFileEnd(long discOffset)
{
if (_files.Count == 0)
return null;
int lo = 0, hi = _files.Count;
while (lo < hi)
{
int mid = (lo + hi) >> 1;
if (_files[mid].FileEnd <= discOffset)
lo = mid + 1;
else
hi = mid;
}
return lo < _files.Count ? _files[lo].FileEnd : null;
}
/// <summary>
/// Returns the smallest FileStart value strictly greater than
/// <paramref name="discOffset"/>, or null if there is none.
Dolphin lib (#85) * Add GCZ, WIA/RVZ, and NintendoDisc (GameCube/Wii) format support Port of DolphinIsoLib into SabreTools.Serialization architecture: - Data.Models: GCZ/, WIA/, NintendoDisc/ model subdirectories (15 files) - Serialization.Readers: GCZ, WIA, NintendoDisc readers - Serialization.Writers: GCZ, WIA writers (structural metadata; full round-trip TODO) - Wrappers: NintendoDisc, GCZ, WIA wrappers with Encryption partial class - Wrappers: WiaRvzCompressionHelper (BZip2/LZMA/LZMA2/Zstd, net462+ guarded) - WrapperType + WrapperFactory: GCZ, WIA, NintendoDisc entries added GetInnerWrapper() decompression and NintendoDisc.Extraction FST extraction are stubbed with TODO comments pending full implementation. * Implement GetInnerWrapper for GCZ and WIA, full NintendoDisc extraction * Add GCZ/WIA/RVZ write pipeline and Nintendo disc compression helpers * Add WIA/RVZ table decompression, NintendoDisc/GCZ printing, NintendoDisc detection for .iso files * Fix NintendoDisc header layout, GC magic, and add embedded disc header to WIA/GCZ printing - Fix GCMagicWord: 0xC23D3C1F -> 0xC2339F3D (confirmed from Dolphin DiscUtils.h) - Fix disc header field layout to match Dolphin's confirmed offsets: MakerCode is bytes 4-5 of the 6-char GameId (no separate field at 0x006), DiscNumber at 0x006, DiscVersion at 0x007, unused region is 14 bytes (0x00A-0x017) - Update NintendoDisc reader: derive MakerCode from GameId[4..5], fix skip count - Add ParseDiscHeaderOnly() to reader for partial (short) stream parsing - Guard DisableHash/DisableEnc reads at the 0x080 boundary for 128-byte embedded headers - Guard DOL/FST skip for streams shorter than full 0x440 boot block - Fix WrapperFactory: NintendoDisc magic detection now precedes .iso -> ISO9660 fallback - Add GameId-prefix heuristic in WrapperFactory for GC discs lacking magic word - Add GameId-prefix platform fallback in reader for GC discs without GCMagicWord - Add DiscHeader property to WIA wrapper (parsed from Header2.DiscHeader bytes) - Add DiscHeader property to GCZ wrapper (decompresses first block only) - Add ReadDiscHeader() helper to GCZ for lightweight first-block decompression - Print embedded disc header (Game ID, Maker, Disc/Rev, Title) in WIA.Printing.cs and GCZ.Printing.cs * Fix Wii partition extraction: correct IV, FST size shift, partition naming - Block decryption: IV is at raw block offset 0x3D0 (still-encrypted), matching Dolphin/DolphinIsoLib WiiPartitionDecryptor.DecryptBlock exactly. - FST size field at boot.bin 0x428 is also stored >>2 on Wii; apply <<2 to get true byte size. - Partition folder naming now matches DolphinIsoLib WiiDiscExtractor exactly: type 0->GM+n, 1->UP+n, 2->CH+n, printable ASCII unknown->raw 4-char string, non-printable->P{index}. SSBB VC channels extract as HA8E, HA9E, etc. - ExtractionTool peek buffer increased from 16 to 32 bytes. Verified: SSBB GM0 extracts 5524 files, boot.bin/fst.bin byte-identical to Dolphin reference extraction. * Fix FST extraction: create zero-byte files instead of skipping them Files with fileSize=0 in the FST were silently skipped. Now they are created as empty files, matching Dolphin/DolphinIsoLib behavior. Verified: SSBB now extracts 5958 files with 0 missing, 0 extra, 0 size mismatches, and 0 hash mismatches vs DolphinIsoLib reference. * Add GCZ/WIA/RVZ virtual stream extraction via NintendoDisc wrapper * Address PR #85 review comments (Copilot + mnadareski) * Address PR #85 review comments * Replace custom endian helpers and SHA1 with SabreTools.IO equivalents * Update GCZ.Printing.cs * Update NintendoDisc.Printing.cs * Update WIA.Printing.cs * Add WIA/RVZ Wii partition crypto round-trip support - Add AesCbc internal helper (BouncyCastle AES-CBC encrypt/decrypt) - Add NintendoDisc.CommonKeyProvider hook for injectable test keys - Fix sha1.Terminate() missing in all three ComputeSha1 helpers in WIA.cs - Fix Wii partition dataOff alignment to 0x8000 boundary - Add WIA.EncryptWiiGroup (internal) for re-encrypting plaintext groups - Add WIA.DumpIso to WIA.Writing.cs (WIA/RVZ -> flat ISO conversion) - Add WiaVirtualStream on-demand group decompression - Add _preDecryptedReader bypass on NintendoDisc for WIA extraction path - Add WIATests.cs with Wii crypto round-trip test using synthetic data - Move DumpIso from WIA.Extraction.cs to WIA.Writing.cs - Bump DumpIso read buffer from 1 MiB to 2 MiB (aligns to WIA chunk size) - Add InternalsVisibleTo SabreTools.Wrappers.Test in csproj * Remove hardcoded Wii common keys from NintendoDisc.Encryption - Delete the embedded WiiCommonKeyRetail and WiiCommonKeyKorean byte arrays from NintendoDisc.Encryption.cs. - Make CommonKeyProvider public so any caller (not just tests) can inject keys; DecryptTitleKey now returns null when no key is available for the requested index rather than falling back to hardcoded values. - Add NintendoDiscEncryptionTests.cs: - Argument guard and no-provider tests for DecryptTitleKey. - Fake-key round-trip test (encrypt then decrypt with injected key). - Integration test that reads TestData/NintendoDisc/keys.json, verifies each key against hardcoded SHA256 constants, and skips silently if the file is absent or the keys do not match. - LoadKeyProvider helper (named JSON format, index-keyed). - Add [Collection(NintendoDisc)] to both NintendoDiscEncryptionTests and WIATests to prevent parallel access to the static CommonKeyProvider from racing between test classes. - Add TestData/NintendoDisc/keys.json.example documenting the expected key file format. - Add Newtonsoft.Json reference to SabreTools.Wrappers.Test.csproj. * Didn't actually commit the changes. My bad. Fixed. * Edited a comment * Added in XUnit outputs that show up in Test Viewer in VS --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2026-05-12 09:41:32 -05:00
/// </summary>
public long? FindNextFileStart(long discOffset)
{
if (_files.Count == 0)
return null;
// Sort is by FileEnd; scan all entries whose FileEnd > discOffset
int lo = 0, hi = _files.Count;
while (lo < hi)
{
int mid = (lo + hi) >> 1;
if (_files[mid].FileEnd <= discOffset)
lo = mid + 1;
else
hi = mid;
}
long? best = null;
for (int i = lo; i < _files.Count; i++)
{
long start = _files[i].FileStart;
if (start <= discOffset)
continue;
if (best == null || start < best.Value)
best = start;
}
return best;
}
}
}