Skip to content

Commit 41ad8ad

Browse files
Small TAGES and AlphaROM improvements (#394)
* Small improvement to early TAGES detection to eliminate small handful of false positives. Also threw in a note about alpharom * Improve alpharom handling * Initial round of fixes
1 parent 201badd commit 41ad8ad

File tree

3 files changed

+56
-24
lines changed

3 files changed

+56
-24
lines changed

BinaryObjectScanner/FileType/ISO9660.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ public static bool NoteworthyApplicationUse(PrimaryVolumeDescriptor pvd)
107107
// character. If these are found to be causing issues they can be added.
108108
}
109109

110+
// Seems to come from "FERGUS_MCNEILL - ISOCD 1.00 by Pantaray, Inc. USA -"
111+
offset = 1;
112+
potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset);
113+
if (potentialAppUseString == "FS")
114+
return false;
115+
110116
offset = 141;
111117
potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset);
112118
if (potentialAppUseString == "CD-XA001")

BinaryObjectScanner/Protection/AlphaROM.cs

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Text;
23
using System.Text.RegularExpressions;
34
using BinaryObjectScanner.Interfaces;
45
using SabreTools.Data.Models.ISO9660;
@@ -56,8 +57,8 @@ public class AlphaROM : IDiskImageCheck<ISO9660>, IExecutableCheck<PortableExecu
5657
if (diskImage.VolumeDescriptorSet[0] is not PrimaryVolumeDescriptor pvd)
5758
return null;
5859

59-
// Alpharom disc check #1: disc has varying (but observed to at least always be larger than 14) length
60-
// string made up of numbers and capital letters.
60+
// Disc has varying (but observed to at least always be larger than 14) length
61+
// application identifier string made up of numbers and capital letters.
6162
// TODO: triple-check that length is never below 14
6263
int offset = 0;
6364
var applicationIdentifierString = pvd.ApplicationIdentifier.ReadNullTerminatedAnsiString(ref offset)?.Trim();
@@ -67,27 +68,49 @@ public class AlphaROM : IDiskImageCheck<ISO9660>, IExecutableCheck<PortableExecu
6768
if (!Regex.IsMatch(applicationIdentifierString, "^[A-Z0-9]*$"))
6869
return null;
6970

70-
// Alpharom disc check #2: disc has publisher identifier filled with varying amount of data (26-50 bytes
71-
// have been observed) followed by spaces. There's a decent chance this is just a Japanese text string, but
72-
// UTF, Shift-JIS, and EUC-JP all fail to display anything but garbage.
73-
74-
var publisherIdentifier = pvd.PublisherIdentifier;
75-
int firstSpace = Array.FindIndex(publisherIdentifier, b => b == 0x20);
76-
if (firstSpace <= 10 || firstSpace >= 120)
77-
return null;
78-
79-
var publisherData = new byte[firstSpace];
80-
var publisherSpaces = new byte[publisherData.Length - firstSpace];
81-
Array.Copy(publisherIdentifier, 0, publisherData, 0, firstSpace);
82-
Array.Copy(publisherIdentifier, firstSpace, publisherSpaces, 0, publisherData.Length - firstSpace);
83-
84-
if (!Array.TrueForAll(publisherSpaces, b => b == 0x20))
85-
return null;
86-
87-
if (!FileType.ISO9660.IsPureData(publisherData))
88-
return null;
71+
// While some alpharom discs have data in the publisher identifier that can be checked, not all of them do,
72+
// so that can't reliably be used. There are two formats currently observed regarding the application
73+
// identifier strings.
74+
// #1 examples: DCOBG11C1B094961XN, DCXA9083CA554846GP, RCXA1107UD2510461A
75+
// #2 examples: 2003120514103077LAHD, 20040326195254AVKC, 20051019163346WXUDCD
76+
77+
var applicationIdentifierStringBytes = Encoding.ASCII.GetBytes(applicationIdentifierString);
78+
79+
// Type #1: 18 characters long, mix of letters and numbers. Since the string has already been confirmed
80+
// to only consist of capital letters and numbers, a basic byte value check can be performed to ensure
81+
// at least 5 bytes are numbers and 5 bytes are letters. Unfortunately, there doesn't seem to be quite
82+
// enough of a pattern to have a better check than this, but it works well enough.
83+
if (applicationIdentifierString.Length == 18
84+
&& Array.FindAll(applicationIdentifierStringBytes, b => b < 60).Length >= 5
85+
&& Array.FindAll(applicationIdentifierStringBytes, b => b > 60).Length >= 5)
86+
{
87+
return "AlphaROM";
88+
}
89+
90+
// Type #2: Usually 20 characters long, but Redump ID 124334 is 18 characters long. Validate that it
91+
// starts with YYYYMMDD, followed by 6-8 more numbers, followed by letters.
92+
if (applicationIdentifierString.Length >= 18 && applicationIdentifierString.Length <= 20)
93+
{
94+
if (Int32.TryParse(applicationIdentifierString.Substring(0, 4), out int year) == false
95+
|| Int32.TryParse(applicationIdentifierString.Substring(4, 2), out int month) == false
96+
|| Int32.TryParse(applicationIdentifierString.Substring(6, 2), out int day) == false
97+
|| Int32.TryParse(applicationIdentifierString.Substring(8, 6), out int extraTime) == false)
98+
{
99+
return null;
100+
}
101+
102+
if (year >= 2009 || year < 2000 || month > 12 || day > 31)
103+
return null;
104+
105+
int index = Array.FindIndex(applicationIdentifierStringBytes, b => b > 60);
106+
107+
var startingNumbers = Encoding.ASCII.GetBytes(applicationIdentifierString.Substring(0, index));
108+
var finalCharacters = Encoding.ASCII.GetBytes(applicationIdentifierString.Substring(index));
109+
if (Array.TrueForAll(startingNumbers, b => b < 60) && Array.TrueForAll(finalCharacters, b => b > 60))
110+
return "AlphaROM";
111+
}
89112

90-
return "AlphaROM";
113+
return null;
91114
}
92115

93116
/// <inheritdoc/>

BinaryObjectScanner/Protection/Tages.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,12 @@ public class TAGES : IDiskImageCheck<ISO9660>, IExecutableCheck<PortableExecutab
4343
// Early tages has a 4-byte value at the beginning of the AU data and nothing else.
4444
// Redump ID 8776, 21321, 35932
4545
offset = 0;
46-
uint earlyTagesBytes = applicationUse.ReadUInt32LittleEndian(ref offset);
46+
var earlyTagesBytes = applicationUse.ReadUInt32LittleEndian(ref offset);
4747
var zeroBytes = applicationUse.ReadBytes(ref offset, 508);
48-
if (Array.TrueForAll(zeroBytes, b => b == 0x00) && earlyTagesBytes != 0)
48+
49+
// Check on earlyTagesBytes needed because Redump ID 56899 begins with "FUN" and is then all 0x00.
50+
// 0x70 value is probably just by chance of where early TAGES checks, but it seems to be consistent.
51+
if (Array.TrueForAll(zeroBytes, b => b == 0x00) && (earlyTagesBytes & 0x70000000) == 0x70000000)
4952
return "TAGES (Early)";
5053

5154
// The original releases of Moto Racer 3 (31578, 34669) are so early they have seemingly nothing identifiable.

0 commit comments

Comments
 (0)