Skip to content

Commit 57ba906

Browse files
Improve alpharom handling
1 parent b671c87 commit 57ba906

File tree

1 file changed

+40
-23
lines changed

1 file changed

+40
-23
lines changed

BinaryObjectScanner/Protection/AlphaROM.cs

Lines changed: 40 additions & 23 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,28 +68,44 @@ 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-
// TODO: This fails on some discs like Redump ID 127450, where publisher identifier is all 0x00.
74-
75-
var publisherIdentifier = pvd.PublisherIdentifier;
76-
int firstSpace = Array.FindIndex(publisherIdentifier, b => b == 0x20);
77-
if (firstSpace <= 10 || firstSpace >= 120)
78-
return null;
79-
80-
var publisherData = new byte[firstSpace];
81-
var publisherSpaces = new byte[publisherData.Length - firstSpace];
82-
Array.Copy(publisherIdentifier, 0, publisherData, 0, firstSpace);
83-
Array.Copy(publisherIdentifier, firstSpace, publisherSpaces, 0, publisherData.Length - firstSpace);
84-
85-
if (!Array.TrueForAll(publisherSpaces, b => b == 0x20))
86-
return null;
87-
88-
if (!FileType.ISO9660.IsPureData(publisherData))
89-
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+
return "AlphaROM";
87+
88+
// Type #2: Usually 20 characters long, but Redump ID 124334 is 18 characters long. Validate that it
89+
// starts with YYYYMMDD, followed by 6-8 more numbers, followed by letters.
90+
if (applicationIdentifierString.Length >= 18 && applicationIdentifierString.Length <= 20)
91+
{
92+
if (Int32.TryParse(applicationIdentifierString.Substring(0, 4), out int year) == false
93+
|| Int32.TryParse(applicationIdentifierString.Substring(4, 2), out int month) == false
94+
|| Int32.TryParse(applicationIdentifierString.Substring(6, 2), out int day) == false
95+
|| Int32.TryParse(applicationIdentifierString.Substring(8, 6), out int extraTime) == false)
96+
return null;
97+
if (year >= 2009 || year < 2000 || month > 12 || day > 31)
98+
return null;
99+
100+
int index = Array.FindIndex(applicationIdentifierStringBytes, b => b > 60);
101+
102+
var startingNumbers = Encoding.ASCII.GetBytes(applicationIdentifierString.Substring(0, index));
103+
var finalCharacters = Encoding.ASCII.GetBytes(applicationIdentifierString.Substring(index));
104+
if (Array.TrueForAll(startingNumbers, b => b < 60) && Array.TrueForAll(finalCharacters, b => b > 60))
105+
return "AlphaROM";
106+
}
90107

91-
return "AlphaROM";
108+
return null;
92109
}
93110

94111
/// <inheritdoc/>

0 commit comments

Comments
 (0)