From b671c87ed0e9844d37a3ff81803e9fcf4c0243c4 Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Sun, 16 Nov 2025 12:32:53 -0500 Subject: [PATCH 1/3] Small improvement to early TAGES detection to eliminate small handful of false positives. Also threw in a note about alpharom --- BinaryObjectScanner/FileType/ISO9660.cs | 5 +++++ BinaryObjectScanner/Protection/AlphaROM.cs | 1 + BinaryObjectScanner/Protection/Tages.cs | 7 +++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/BinaryObjectScanner/FileType/ISO9660.cs b/BinaryObjectScanner/FileType/ISO9660.cs index 9e16bbf9..61a37834 100644 --- a/BinaryObjectScanner/FileType/ISO9660.cs +++ b/BinaryObjectScanner/FileType/ISO9660.cs @@ -107,6 +107,11 @@ public static bool NoteworthyApplicationUse(PrimaryVolumeDescriptor pvd) // character. If these are found to be causing issues they can be added. } + offset = 1; + potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset); + if (potentialAppUseString == "FS") + return false; + offset = 141; potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset); if (potentialAppUseString == "CD-XA001") diff --git a/BinaryObjectScanner/Protection/AlphaROM.cs b/BinaryObjectScanner/Protection/AlphaROM.cs index 43c44047..d77fd308 100644 --- a/BinaryObjectScanner/Protection/AlphaROM.cs +++ b/BinaryObjectScanner/Protection/AlphaROM.cs @@ -70,6 +70,7 @@ public class AlphaROM : IDiskImageCheck, IExecutableCheck b == 0x20); diff --git a/BinaryObjectScanner/Protection/Tages.cs b/BinaryObjectScanner/Protection/Tages.cs index b6d1081e..044f97d0 100644 --- a/BinaryObjectScanner/Protection/Tages.cs +++ b/BinaryObjectScanner/Protection/Tages.cs @@ -43,9 +43,12 @@ public class TAGES : IDiskImageCheck, IExecutableCheck b == 0x00) && earlyTagesBytes != 0) + + // Check on earlyTagesBytes needed because Redump ID 56899 begins with "FUN" and is then all 0x00. + // 0x70 value is probably just by chance of where early TAGES checks, but it seems to be consistent. + if (Array.TrueForAll(zeroBytes, b => b == 0x00) && !Array.TrueForAll(earlyTagesBytes, b => b == 0x00) && earlyTagesBytes[3] == 0x70) return "TAGES (Early)"; // The original releases of Moto Racer 3 (31578, 34669) are so early they have seemingly nothing identifiable. From 57ba906e226b9999fa848cf95378b03625750bb6 Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Sun, 16 Nov 2025 14:01:10 -0500 Subject: [PATCH 2/3] Improve alpharom handling --- BinaryObjectScanner/Protection/AlphaROM.cs | 63 ++++++++++++++-------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/BinaryObjectScanner/Protection/AlphaROM.cs b/BinaryObjectScanner/Protection/AlphaROM.cs index d77fd308..40e01e1d 100644 --- a/BinaryObjectScanner/Protection/AlphaROM.cs +++ b/BinaryObjectScanner/Protection/AlphaROM.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using System.Text.RegularExpressions; using BinaryObjectScanner.Interfaces; using SabreTools.Data.Models.ISO9660; @@ -56,8 +57,8 @@ public class AlphaROM : IDiskImageCheck, IExecutableCheck, IExecutableCheck b == 0x20); - if (firstSpace <= 10 || firstSpace >= 120) - return null; - - var publisherData = new byte[firstSpace]; - var publisherSpaces = new byte[publisherData.Length - firstSpace]; - Array.Copy(publisherIdentifier, 0, publisherData, 0, firstSpace); - Array.Copy(publisherIdentifier, firstSpace, publisherSpaces, 0, publisherData.Length - firstSpace); - - if (!Array.TrueForAll(publisherSpaces, b => b == 0x20)) - return null; - - if (!FileType.ISO9660.IsPureData(publisherData)) - return null; + // While some alpharom discs have data in the publisher identifier that can be checked, not all of them do, + // so that can't reliably be used. There are two formats currently observed regarding the application + // identifier strings. + // #1 examples: DCOBG11C1B094961XN, DCXA9083CA554846GP, RCXA1107UD2510461A + // #2 examples: 2003120514103077LAHD, 20040326195254AVKC, 20051019163346WXUDCD + + var applicationIdentifierStringBytes = Encoding.ASCII.GetBytes(applicationIdentifierString); + + // Type #1: 18 characters long, mix of letters and numbers. Since the string has already been confirmed + // to only consist of capital letters and numbers, a basic byte value check can be performed to ensure + // at least 5 bytes are numbers and 5 bytes are letters. Unfortunately, there doesn't seem to be quite + // enough of a pattern to have a better check than this, but it works well enough. + if (applicationIdentifierString.Length == 18 + && Array.FindAll(applicationIdentifierStringBytes, b => b < 60).Length >= 5 + && Array.FindAll(applicationIdentifierStringBytes, b => b > 60).Length >= 5) + return "AlphaROM"; + + // Type #2: Usually 20 characters long, but Redump ID 124334 is 18 characters long. Validate that it + // starts with YYYYMMDD, followed by 6-8 more numbers, followed by letters. + if (applicationIdentifierString.Length >= 18 && applicationIdentifierString.Length <= 20) + { + if (Int32.TryParse(applicationIdentifierString.Substring(0, 4), out int year) == false + || Int32.TryParse(applicationIdentifierString.Substring(4, 2), out int month) == false + || Int32.TryParse(applicationIdentifierString.Substring(6, 2), out int day) == false + || Int32.TryParse(applicationIdentifierString.Substring(8, 6), out int extraTime) == false) + return null; + if (year >= 2009 || year < 2000 || month > 12 || day > 31) + return null; + + int index = Array.FindIndex(applicationIdentifierStringBytes, b => b > 60); + + var startingNumbers = Encoding.ASCII.GetBytes(applicationIdentifierString.Substring(0, index)); + var finalCharacters = Encoding.ASCII.GetBytes(applicationIdentifierString.Substring(index)); + if (Array.TrueForAll(startingNumbers, b => b < 60) && Array.TrueForAll(finalCharacters, b => b > 60)) + return "AlphaROM"; + } - return "AlphaROM"; + return null; } /// From 7c401ed2d552addd7368ebb6e6cdbddc76faebad Mon Sep 17 00:00:00 2001 From: HeroponRikiBestest Date: Sun, 16 Nov 2025 15:41:40 -0500 Subject: [PATCH 3/3] Initial round of fixes --- BinaryObjectScanner/FileType/ISO9660.cs | 1 + BinaryObjectScanner/Protection/AlphaROM.cs | 13 +++++++++---- BinaryObjectScanner/Protection/Tages.cs | 6 +++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/BinaryObjectScanner/FileType/ISO9660.cs b/BinaryObjectScanner/FileType/ISO9660.cs index 61a37834..244ac1c5 100644 --- a/BinaryObjectScanner/FileType/ISO9660.cs +++ b/BinaryObjectScanner/FileType/ISO9660.cs @@ -107,6 +107,7 @@ public static bool NoteworthyApplicationUse(PrimaryVolumeDescriptor pvd) // character. If these are found to be causing issues they can be added. } + // Seems to come from "FERGUS_MCNEILL - ISOCD 1.00 by Pantaray, Inc. USA -" offset = 1; potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset); if (potentialAppUseString == "FS") diff --git a/BinaryObjectScanner/Protection/AlphaROM.cs b/BinaryObjectScanner/Protection/AlphaROM.cs index 40e01e1d..fd7161af 100644 --- a/BinaryObjectScanner/Protection/AlphaROM.cs +++ b/BinaryObjectScanner/Protection/AlphaROM.cs @@ -80,20 +80,25 @@ public class AlphaROM : IDiskImageCheck, IExecutableCheck b < 60).Length >= 5 && Array.FindAll(applicationIdentifierStringBytes, b => b > 60).Length >= 5) + { return "AlphaROM"; + } // Type #2: Usually 20 characters long, but Redump ID 124334 is 18 characters long. Validate that it // starts with YYYYMMDD, followed by 6-8 more numbers, followed by letters. if (applicationIdentifierString.Length >= 18 && applicationIdentifierString.Length <= 20) { if (Int32.TryParse(applicationIdentifierString.Substring(0, 4), out int year) == false - || Int32.TryParse(applicationIdentifierString.Substring(4, 2), out int month) == false - || Int32.TryParse(applicationIdentifierString.Substring(6, 2), out int day) == false - || Int32.TryParse(applicationIdentifierString.Substring(8, 6), out int extraTime) == false) + || Int32.TryParse(applicationIdentifierString.Substring(4, 2), out int month) == false + || Int32.TryParse(applicationIdentifierString.Substring(6, 2), out int day) == false + || Int32.TryParse(applicationIdentifierString.Substring(8, 6), out int extraTime) == false) + { return null; + } + if (year >= 2009 || year < 2000 || month > 12 || day > 31) return null; diff --git a/BinaryObjectScanner/Protection/Tages.cs b/BinaryObjectScanner/Protection/Tages.cs index 044f97d0..dbb86998 100644 --- a/BinaryObjectScanner/Protection/Tages.cs +++ b/BinaryObjectScanner/Protection/Tages.cs @@ -43,12 +43,12 @@ public class TAGES : IDiskImageCheck, IExecutableCheck b == 0x00) && !Array.TrueForAll(earlyTagesBytes, b => b == 0x00) && earlyTagesBytes[3] == 0x70) + if (Array.TrueForAll(zeroBytes, b => b == 0x00) && (earlyTagesBytes & 0x70000000) == 0x70000000) return "TAGES (Early)"; // The original releases of Moto Racer 3 (31578, 34669) are so early they have seemingly nothing identifiable.