Files

392 lines
14 KiB
C#
Raw Permalink 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;
using System.IO;
using System.Linq;
using SabreTools.Numerics.Extensions;
2026-05-14 09:25:26 -04:00
using SabreTools.Security.Cryptography;
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 Xunit;
using static SabreTools.Data.Models.NintendoDisc.Constants;
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.Test
{
public class WIATests
{
/// <summary>
/// Arbitrary test-only common key — no relation to any real Wii key.
/// Used by both <see cref="BuildMinimalWiiIso"/> and <see cref="EncryptTitleKeyIndependent"/>.
/// </summary>
private static readonly byte[] TestCommonKey =
[
0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xF0, 0x0D,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
];
#region Constants
private const int HeaderAreaSize = 0x8000;
private const long IsoSize = Partition1Data + WiiGroupSize;
private const long Partition0Offset = 0x60000;
private const long Partition0Data = Partition0Offset + HeaderAreaSize;
private const long Partition1Offset = Partition0Data + WiiGroupSize;
private const long Partition1Data = Partition1Offset + HeaderAreaSize;
private const long PartitionListOffset = 0x50000;
private const long PartitionTableOffset = 0x40000;
#endregion
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
[Fact]
public void NullArray_Null()
{
byte[]? data = null;
int offset = 0;
var actual = WIA.Create(data, offset);
Assert.Null(actual);
}
[Fact]
public void EmptyArray_Null()
{
byte[]? data = [];
int offset = 0;
var actual = WIA.Create(data, offset);
Assert.Null(actual);
}
[Fact]
public void InvalidArray_Null()
{
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
int offset = 0;
var actual = WIA.Create(data, offset);
Assert.Null(actual);
}
[Fact]
public void NullStream_Null()
{
Stream? data = null;
var actual = WIA.Create(data);
Assert.Null(actual);
}
[Fact]
public void EmptyStream_Null()
{
Stream? data = new MemoryStream([]);
var actual = WIA.Create(data);
Assert.Null(actual);
}
[Fact]
public void InvalidStream_Null()
{
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
var actual = WIA.Create(data);
Assert.Null(actual);
}
/// <summary>
/// Build the smallest valid WIA we can to get a non-null wrapper,
/// but for the guard test we only need to exercise the null-path branch.
/// We can create a real wrapper via the round-trip helper and then call
/// DumpIso with a null path — that must return false.
/// </summary>
[Fact(Skip = "Common keys are validated so this cannot pass")]
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 void DumpIso_NullPath_ReturnsFalse()
{
var wia = BuildMinimalWiiWia();
Assert.NotNull(wia);
Assert.False(wia!.DumpIso(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
}
/// <summary>
/// Builds a synthetic Wii disc with 2 fake partitions (each 1 WiiGroup = 64 × 0x8000 bytes of
/// known plaintext encrypted with an arbitrary key), converts it to WIA (NONE compression),
/// reads it back through <see cref="WIA.DumpIso"/>, then decrypts every Wii data block in the
/// dumped ISO using <see cref="WiiDecrypter.DecryptBlock"/> and asserts the decrypted bytes
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
/// match the original plaintext.
///
/// This exercises both directions:
/// • WIA write path re-encrypts partition data correctly (<see cref="WIA.ConvertFromDiscToStream"/>)
/// • WIA read path (<see cref="WiaVirtualStream"/>) re-encrypts WIA decrypted groups back to
/// ISO-layout AES-CBC blocks via GetCachedEncGroup / EncryptWiiGroup
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
///
/// Anti-bias: the final decryption uses <see cref="WiiDecrypter.DecryptBlock"/> — a single-block
/// AES-CBC call that is completely independent of EncryptWiiGroup — so a symmetric bug
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
/// (broken encrypt paired with broken decrypt) would still fail the plaintext comparison.
2026-05-14 09:25:26 -04:00
/// The title key is encrypted via <see cref="AESCBC.Encrypt"/> (BouncyCastle), while the
/// verification uses <see cref="WiiDecrypter.DecryptBlock"/> — a different code path.
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>
[Fact(Skip = "Common keys are validated so this cannot pass")]
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 void Wii_WiaNoneRoundTrip_Succeeds()
{
// ---- Build synthetic Wii ISO ----
byte[] iso = BuildMinimalWiiIso(TestCommonKey);
// ---- NintendoDisc.Create must succeed ----
var nd = NintendoDisc.Create(new MemoryStream(iso));
Assert.NotNull(nd);
Assert.NotNull(nd!.PartitionTableEntries);
Assert.Equal(2, nd.PartitionTableEntries!.Length);
// ---- Compress to WIA (NONE, no lossy transforms) ----
using var wiaMs = new MemoryStream();
bool written = WIA.ConvertFromDiscToStream(nd, wiaMs,
isRvz: false,
compressionType: Data.Models.WIA.WiaRvzCompressionType.None,
compressionLevel: 5,
chunkSize: Data.Models.WIA.Constants.DefaultChunkSize,
out Exception? writeEx);
Assert.True(written, $"ConvertFromDiscToStream failed: {writeEx?.GetType().Name}: {writeEx?.Message}\n{writeEx?.StackTrace}");
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
// ---- Decompress back to ISO ----
wiaMs.Position = 0;
var wia = WIA.Create(wiaMs);
Assert.NotNull(wia);
string tempIso = Path.GetTempFileName() + ".iso";
try
{
bool dumped = wia!.DumpIso(tempIso);
Assert.True(dumped, "DumpIso should succeed");
byte[] dumpedIso = File.ReadAllBytes(tempIso);
byte[] titleKey =
[
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
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
];
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
byte[] plain0 = new byte[WiiBlocksPerGroup * WiiBlockDataSize];
for (int i = 0; i < plain0.Length; i++)
{
plain0[i] = 0xAA;
}
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
byte[] plain1 = new byte[WiiBlocksPerGroup * WiiBlockDataSize];
for (int i = 0; i < plain1.Length; i++)
{
plain1[i] = 0xBB;
}
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
// ---- Anti-bias verification: decrypt each block using DecryptBlock only ----
VerifyPartitionPlaintext(dumpedIso,
Partition0Data,
plain0,
titleKey,
WiiBlocksPerGroup,
WiiBlockSize,
WiiBlockDataSize,
partitionLabel: "Partition 0");
VerifyPartitionPlaintext(dumpedIso,
Partition1Data,
plain1,
titleKey,
WiiBlocksPerGroup,
WiiBlockSize,
WiiBlockDataSize,
partitionLabel: "Partition 1");
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
}
finally
{
if (File.Exists(tempIso))
File.Delete(tempIso);
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
}
}
#region Wii test helpers
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>
/// Builds a minimal synthetic Wii disc (one WiiGroup per partition) and returns a live
/// <see cref="WIA"/> wrapper backed by a <see cref="MemoryStream"/>.
/// Returns null if any step fails.
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>
private static WIA? BuildMinimalWiiWia()
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
{
try
{
byte[] iso = BuildMinimalWiiIso(TestCommonKey);
var nd = NintendoDisc.Create(new MemoryStream(iso));
if (nd is null)
return null;
// TODO: Force this?
nd.WiiDecrypter.RetailCommonKey = TestCommonKey;
nd.WiiDecrypter.KoreanCommonKey = TestCommonKey;
var ms = new MemoryStream();
bool ok = WIA.ConvertFromDiscToStream(nd, ms,
isRvz: false,
compressionType: Data.Models.WIA.WiaRvzCompressionType.None,
compressionLevel: 5,
chunkSize: Data.Models.WIA.Constants.DefaultChunkSize,
out var exception);
if (!ok)
return null;
ms.Position = 0;
return WIA.Create(ms);
}
catch
{
return 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
/// <summary>
/// Builds a minimal synthetic Wii ISO with 2 partitions (1 WiiGroup each), encrypted
/// with <paramref name="commonKey"/>.
/// </summary>
private static byte[] BuildMinimalWiiIso(byte[] commonKey)
{
byte[] titleKey =
[
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
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
];
byte[] titleId = [0x00, 0x01, 0x00, 0x45, 0x52, 0x53, 0x42, 0x00];
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
byte[] encTitleKey = EncryptTitleKeyIndependent(titleKey, titleId, commonKey);
byte[] plain0 = new byte[WiiGroupDataSize];
for (int i = 0; i < plain0.Length; i++)
{
plain0[i] = 0xAA;
}
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
byte[] plain1 = new byte[WiiGroupDataSize];
for (int i = 0; i < plain1.Length; i++)
{
plain1[i] = 0xBB;
}
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
byte[] enc0 = WIA.EncryptWiiGroup(plain0, titleKey, WiiBlocksPerGroup);
byte[] enc1 = WIA.EncryptWiiGroup(plain1, titleKey, WiiBlocksPerGroup);
byte[] iso = new byte[IsoSize];
iso[0] = (byte)'R'; iso[1] = (byte)'S'; iso[2] = (byte)'B'; iso[3] = (byte)'E';
iso[4] = (byte)'0'; iso[5] = (byte)'1';
iso[0x18] = 0x5D; iso[0x19] = 0x1C; iso[0x1A] = 0x9E; iso[0x1B] = 0xA3;
int off = (int)PartitionTableOffset;
iso.WriteBigEndian(ref off, 2u);
iso.WriteBigEndian(ref off, (uint)(PartitionListOffset >> 2));
off = (int)PartitionListOffset;
iso.WriteBigEndian(ref off, (uint)(Partition0Offset >> 2));
iso.WriteBigEndian(ref off, 0u);
iso.WriteBigEndian(ref off, (uint)(Partition1Offset >> 2));
iso.WriteBigEndian(ref off, 1u);
WritePartitionHeader(iso, Partition0Offset, encTitleKey, titleId, ckIdx: 0);
WritePartitionHeader(iso, Partition1Offset, encTitleKey, titleId, ckIdx: 0);
Array.Copy(enc0, 0, iso, Partition0Data, enc0.Length);
Array.Copy(enc1, 0, iso, Partition1Data, enc1.Length);
return iso;
}
/// <summary>
///
/// </summary>
/// <param name="iso"></param>
/// <param name="partOffset"></param>
/// <param name="encTitleKey"></param>
/// <param name="titleId"></param>
/// <param name="ckIdx"></param>
private static void WritePartitionHeader(byte[] iso,
long partOffset,
byte[] encTitleKey,
byte[] titleId,
byte ckIdx)
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
{
// Signature type 0x10001 at partOffset+0
int off = (int)partOffset;
iso.WriteBigEndian(ref off, 0x10001u);
// Encrypted title key at partOffset+0x1BF (16 bytes)
Array.Copy(encTitleKey, 0, iso, partOffset + 0x1BF, 16);
// Title ID at partOffset+0x1DC (8 bytes)
Array.Copy(titleId, 0, iso, partOffset + 0x1DC, 8);
// Common key index at partOffset+0x1F1
iso[partOffset + 0x1F1] = ckIdx;
// Data offset at partOffset+0x2B8 (shifted >>2): data starts at +0x8000
// 0x8000 >> 2 = 0x2000
off = (int)(partOffset + 0x2B8);
iso.WriteBigEndian(ref off, 0x2000u);
// Data size at partOffset+0x2BC (shifted >>2): exactly 1 WiiGroup = 0x200000
// 0x200000 >> 2 = 0x80000
iso.WriteBigEndian(ref off, 0x80000u);
}
/// <summary>
/// Decrypts each block of one WII partition in the dumped ISO using only
/// <see cref="WiiDecrypter.DecryptBlock"/> (a single-block AES-CBC call that is
/// completely independent of EncryptWiiGroup) and asserts the decrypted
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
/// block data matches the corresponding slice of <paramref name="expectedPlaintext"/>.
/// </summary>
private static void VerifyPartitionPlaintext(byte[] iso,
long dataStart,
byte[] expectedPlaintext,
byte[] titleKey,
int blocksPerGroup,
int blockSize,
int blockDataSize,
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
string partitionLabel)
{
for (int b = 0; b < blocksPerGroup; b++)
{
long blockOff = dataStart + ((long)b * blockSize);
// IV = bytes at offset 0x3D0 within the encrypted hash block
byte[] iv = new byte[16];
Array.Copy(iso, blockOff + 0x3D0, iv, 0, 16);
// Encrypted data block follows the 0x400-byte hash block
byte[] encData = new byte[blockDataSize];
Array.Copy(iso, blockOff + 0x400, encData, 0, blockDataSize);
byte[]? dec = WiiDecrypter.DecryptBlock(encData, titleKey, iv);
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
Assert.NotNull(dec);
// Compare against known plaintext slice
int plainOff = b * blockDataSize;
for (int i = 0; i < blockDataSize; i++)
{
if (dec![i] != expectedPlaintext[plainOff + i])
Assert.Fail($"{partitionLabel} block {b} byte {i}: expected 0x{expectedPlaintext[plainOff + i]:X2}, got 0x{dec[i]:X2}");
}
}
}
/// <summary>
/// Encrypts a Wii title key with the given <paramref name="commonKey"/> using
2026-05-14 09:25:26 -04:00
/// <see cref="AESCBC.Encrypt"/>.
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>
private static byte[] EncryptTitleKeyIndependent(byte[] titleKey, byte[] titleId, byte[] commonKey)
{
byte[] iv = new byte[16];
Array.Copy(titleId, 0, iv, 0, 8);
2026-05-14 09:25:26 -04:00
return AESCBC.Encrypt(titleKey, commonKey, iv)
?? throw new InvalidOperationException("AESCBC.Encrypt returned 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
}
#endregion
}
}