From d3c98499083cfc06b8f9f93f18c2cb00f7d70404 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Thu, 14 May 2026 20:08:32 -0400 Subject: [PATCH] Attempt to fix detection issues --- .../NintendoDiscExtensions.cs | 8 ++ .../NintendoDisc.cs | 2 + SabreTools.Wrappers/WrapperFactory.cs | 75 ++++++++----------- 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/SabreTools.Data.Extensions/NintendoDiscExtensions.cs b/SabreTools.Data.Extensions/NintendoDiscExtensions.cs index d7e1223d..ee74d6ee 100644 --- a/SabreTools.Data.Extensions/NintendoDiscExtensions.cs +++ b/SabreTools.Data.Extensions/NintendoDiscExtensions.cs @@ -65,5 +65,13 @@ namespace SabreTools.Data.Extensions /// public static bool IsGameCubeTitleType(this char c) => c == 'G' || c == 'D' || c == 'R'; + + /// + /// Returns true if the byte is a known Nintendo disc title type code + /// (first byte of the 6-char GameId, e.g. 'G'=GameCube, 'R'=GameCube, + /// 'D'=GameCube demo, 'S'=Wii, 'F'=Wii channel) + /// + public static bool IsNintendoDiscTitleType(this byte b) + => b == 'G' || b == 'D' || b == 'R' || b == 'S' || b == 'F'; } } diff --git a/SabreTools.Serialization.Readers/NintendoDisc.cs b/SabreTools.Serialization.Readers/NintendoDisc.cs index 229dcf0c..d79afe86 100644 --- a/SabreTools.Serialization.Readers/NintendoDisc.cs +++ b/SabreTools.Serialization.Readers/NintendoDisc.cs @@ -34,6 +34,8 @@ namespace SabreTools.Serialization.Readers // Determine platform from magic words; fall back to GameId prefix for // GC discs that omit the magic word (e.g. some redump/scene ISOs) Platform platform = disc.Header.GetPlatform(); + if (platform == Platform.Unknown) + return null; // Parse Wii-specific structures if (platform == Platform.Wii) diff --git a/SabreTools.Wrappers/WrapperFactory.cs b/SabreTools.Wrappers/WrapperFactory.cs index e5cf75ac..6dbe7da7 100644 --- a/SabreTools.Wrappers/WrapperFactory.cs +++ b/SabreTools.Wrappers/WrapperFactory.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using SabreTools.Data.Extensions; using SabreTools.IO.Extensions; using SabreTools.Matching; using SabreTools.Numerics.Extensions; @@ -541,36 +542,6 @@ namespace SabreTools.Wrappers #endregion - #region NintendoDisc - - // Wii disc magic at offset 0x018 (0x5D1C9EA3 stored big-endian on disc) - if (magic.Length > 0x1B && magic[0x18] == 0x5D && magic[0x19] == 0x1C && magic[0x1A] == 0x9E && magic[0x1B] == 0xA3) - return WrapperType.NintendoDisc; - - // GameCube disc magic at offset 0x01C (0xC2339F3D stored big-endian on disc) - if (magic.Length > 0x1F && magic[0x1C] == 0xC2 && magic[0x1D] == 0x33 && magic[0x1E] == 0x9F && magic[0x1F] == 0x3D) - return WrapperType.NintendoDisc; - - // GameCube/Wii disc by GameId prefix: first byte is a known title type code, - // bytes 1-2 are ASCII letters (region + developer), bytes 3-4 are ASCII digits or letters (title code), - // byte 5 is an ASCII digit (disc number). Covers redump ISOs that lack magic words. - if (magic.Length > 5 - && IsNintendoDiscTitleType(magic[0]) - && magic[1] >= 0x41 && magic[1] <= 0x5A // A-Z - && ((magic[2] >= 0x30 && magic[2] <= 0x39) || (magic[2] >= 0x41 && magic[2] <= 0x5A)) // 0-9 or A-Z - && ((magic[3] >= 0x30 && magic[3] <= 0x39) || (magic[3] >= 0x41 && magic[3] <= 0x5A)) // 0-9 or A-Z - && ((magic[4] >= 0x30 && magic[4] <= 0x39) || (magic[4] >= 0x41 && magic[4] <= 0x5A)) // 0-9 or A-Z - && magic[5] >= 0x30 && magic[5] <= 0x39 // 0-9 - && (extension.Equals("iso", StringComparison.OrdinalIgnoreCase) - || extension.Equals("gcm", StringComparison.OrdinalIgnoreCase))) - return WrapperType.NintendoDisc; - - // .gcm files are always GameCube disc images - if (extension.Equals("gcm", StringComparison.OrdinalIgnoreCase)) - return WrapperType.NintendoDisc; - - #endregion - #region ISO9660 if (extension.Equals("iso", StringComparison.OrdinalIgnoreCase)) @@ -658,6 +629,38 @@ namespace SabreTools.Wrappers #endregion + #region NintendoDisc + + // Wii disc magic at offset 0x018 (0x5D1C9EA3 stored big-endian on disc) + if (magic.Length > 0x1B && magic[0x18] == 0x5D && magic[0x19] == 0x1C && magic[0x1A] == 0x9E && magic[0x1B] == 0xA3) + return WrapperType.NintendoDisc; + + // GameCube disc magic at offset 0x01C (0xC2339F3D stored big-endian on disc) + if (magic.Length > 0x1F && magic[0x1C] == 0xC2 && magic[0x1D] == 0x33 && magic[0x1E] == 0x9F && magic[0x1F] == 0x3D) + return WrapperType.NintendoDisc; + + // GameCube/Wii disc by GameId prefix: first byte is a known title type code, + // bytes 1-2 are ASCII letters (region + developer), bytes 3-4 are ASCII digits or letters (title code), + // byte 5 is an ASCII digit (disc number). Covers redump ISOs that lack magic words. + if (magic.Length > 5 + && magic[0].IsNintendoDiscTitleType() + && magic[1] >= 'A' && magic[1] <= 'Z' + && ((magic[2] >= '0' && magic[2] <= '9') || (magic[2] >= 'A' && magic[2] <= 'Z')) + && ((magic[3] >= '0' && magic[3] <= '9') || (magic[3] >= 'A' && magic[3] <= 'Z')) + && ((magic[4] >= '0' && magic[4] <= '9') || (magic[4] >= 'A' && magic[4] <= 'Z')) + && magic[5] >= '0' && magic[5] <= '9' + && (extension.Equals("iso", StringComparison.OrdinalIgnoreCase) + || extension.Equals("gcm", StringComparison.OrdinalIgnoreCase))) + { + return WrapperType.NintendoDisc; + } + + // .gcm files are always GameCube disc images + if (extension.Equals("gcm", StringComparison.OrdinalIgnoreCase)) + return WrapperType.NintendoDisc; + + #endregion + #region Nitro // DS cart image @@ -1186,17 +1189,5 @@ namespace SabreTools.Wrappers // We couldn't find a supported match return WrapperType.UNKNOWN; } - - /// - /// Returns true if the byte is a known Nintendo disc title type code - /// (first byte of the 6-char GameId, e.g. 'G'=GameCube, 'R'=GameCube, - /// 'D'=GameCube demo, 'S'=Wii, 'F'=Wii channel) - /// - private static bool IsNintendoDiscTitleType(byte b) - { - // Standard GameCube and Wii title type prefixes used by Nintendo and licensees - return b == (byte)'G' || b == (byte)'D' || b == (byte)'R' - || b == (byte)'S' || b == (byte)'F'; - } } }