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';
- }
}
}