Add Nintendo Disc extensions tests

This commit is contained in:
Matt Nadareski
2026-05-12 22:47:19 -04:00
parent b805c91cb3
commit cf586f7af2
3 changed files with 172 additions and 38 deletions

View File

@@ -0,0 +1,129 @@
using SabreTools.Data.Models.NintendoDisc;
using Xunit;
namespace SabreTools.Data.Extensions.Test
{
public class NintendoDiscExtensionsTests
{
#region GetPlatform
[Fact]
public void GetPlatform_Object_WiiMagic_Wii()
{
var header = new DiscHeader { WiiMagic = Constants.WiiMagicWord };
Platform actual = header.GetPlatform();
Assert.Equal(Platform.Wii, actual);
}
[Fact]
public void GetPlatform_Object_GCMagic_GC()
{
var header = new DiscHeader { GCMagic = Constants.GCMagicWord };
Platform actual = header.GetPlatform();
Assert.Equal(Platform.GameCube, actual);
}
[Fact]
public void GetPlatform_Object_ValidGameID_GC()
{
var header = new DiscHeader { GameId = "GABC01" };
Platform actual = header.GetPlatform();
Assert.Equal(Platform.GameCube, actual);
}
[Fact]
public void GetPlatform_Object_InvalidGameID_Unknown()
{
var header = new DiscHeader { GameId = "XABC01" };
Platform actual = header.GetPlatform();
Assert.Equal(Platform.Unknown, actual);
}
[Fact]
public void GetPlatform_Object_DefaultHeader_Unknown()
{
var header = new DiscHeader();
Platform actual = header.GetPlatform();
Assert.Equal(Platform.Unknown, actual);
}
[Fact]
public void GetPlatform_Bytes_WiiMagic_Wii()
{
byte[] header =
[
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00-0x07
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08-0x0F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10-0x17
0x5D, 0x1C, 0x9E, 0xA3, 0x00, 0x00, 0x00, 0x00, // 0x18-0x1F
];
Platform actual = header.GetPlatform();
Assert.Equal(Platform.Wii, actual);
}
[Fact]
public void GetPlatform_Bytes_GCMagic_GC()
{
byte[] header =
[
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00-0x07
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08-0x0F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10-0x17
0x00, 0x00, 0x00, 0x00, 0xC2, 0x33, 0x9F, 0x3D, // 0x18-0x1F
];
Platform actual = header.GetPlatform();
Assert.Equal(Platform.GameCube, actual);
}
[Fact]
public void GetPlatform_Bytes_ValidGameID_GC()
{
byte[] header = [(byte)'G', (byte)'A', (byte)'B', (byte)'C'];
Platform actual = header.GetPlatform();
Assert.Equal(Platform.GameCube, actual);
}
[Fact]
public void GetPlatform_Bytes_InvalidGameID_Unknown()
{
byte[] header = [(byte)'G', (byte)'A', (byte)'B', 0x00];
Platform actual = header.GetPlatform();
Assert.Equal(Platform.Unknown, actual);
}
[Fact]
public void GetPlatform_Bytes_DefaultHeader_Unknown()
{
byte[] header = [];
Platform actual = header.GetPlatform();
Assert.Equal(Platform.Unknown, actual);
}
#endregion
#region IsGameCubeTitleType
[Theory]
[InlineData('\0', false)]
[InlineData('a', false)]
[InlineData('A', false)]
[InlineData('d', false)]
[InlineData('D', true)]
[InlineData('g', false)]
[InlineData('G', true)]
[InlineData('r', false)]
[InlineData('R', true)]
public void IsGameCubeTitleTypeTest(char c, bool expected)
{
bool actual = c.IsGameCubeTitleType();
Assert.Equal(expected, actual);
}
#endregion
}
}

View File

@@ -1,8 +1,8 @@
using SabreTools.Data.Models.NintendoDisc;
using SabreTools.Numerics.Extensions;
namespace SabreTools.Data.Extensions
{
// TODO: Write tests for these
public static class NintendoDiscExtensions
{
/// <summary>
@@ -14,12 +14,51 @@ namespace SabreTools.Data.Extensions
return Platform.Wii;
else if (header.GCMagic == Constants.GCMagicWord)
return Platform.GameCube;
else if (header.GameId is not null && header.GameId.Length >= 1 && IsGameCubeTitleType(header.GameId[0]))
else if (header.GameId.Length >= 1 && IsGameCubeTitleType(header.GameId[0]))
return Platform.GameCube;
else
return Platform.Unknown;
}
/// <summary>
/// Get the platform associated with a disc header
/// </summary>
public static Platform GetPlatform(this byte[] header)
{
// Check for Wii magic bytes
if (header.Length >= 0x1C)
{
int offset = 0x18;
uint magic = header.ReadUInt32BigEndian(ref offset);
if (magic == Constants.WiiMagicWord)
return Platform.Wii;
}
// Check for GameCube magic bytes
if (header.Length >= 0x20)
{
int offset = 0x1C;
uint magic = header.ReadUInt32BigEndian(ref offset);
if (magic == Constants.GCMagicWord)
return Platform.GameCube;
}
// Check for a valid game ID
if (header.Length >= 4)
{
for (int i = 0; i < 4; i++)
{
byte c = header[i];
if (!((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')))
return Platform.Unknown;
}
return Platform.GameCube;
}
return Platform.Unknown;
}
/// <summary>
/// Returns true if the GameId first character is a known GameCube title type prefix.
/// Used as a fallback when the GC magic word is absent from the disc image.

View File

@@ -4,6 +4,7 @@ using System.IO;
#if NET462_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
using System.Threading.Tasks;
#endif
using SabreTools.Data.Extensions;
using SabreTools.Data.Models.NintendoDisc;
using SabreTools.Data.Models.WIA;
using SabreTools.Hashing;
@@ -136,7 +137,7 @@ namespace SabreTools.Wrappers
if (discHdr is null)
return false;
Platform platform = DetectWiaPlatform(discHdr);
Platform platform = discHdr.GetPlatform();
return platform switch
{
Platform.GameCube => WriteGameCube(source, dest, isRvz, compressionType, compressionLevel, chunkSize, isoSize, discHdr),
@@ -1562,41 +1563,6 @@ namespace SabreTools.Wrappers
#region Helpers
/// <summary>
///
/// </summary>
/// <param name="header"></param>
/// <returns></returns>
/// TODO: Can this be replaced by <see cref="NintendoDiscExtensions.GetPlatform"/>
private static Platform DetectWiaPlatform(byte[] header)
{
if (header.Length >= 0x1C)
{
uint wiiMagic = (uint)((header[0x18] << 24) | (header[0x19] << 16) | (header[0x1A] << 8) | header[0x1B]);
if (wiiMagic == WiiMagicWord)
return Platform.Wii;
}
if (header.Length >= 4)
{
bool valid = true;
for (int i = 0; i < 4; i++)
{
char c = (char)header[i];
if (!((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')))
{
valid = false;
break;
}
}
if (valid)
return Platform.GameCube;
}
return Platform.Unknown;
}
/// <summary>
///
/// </summary>