Skip to content

Commit 4af8d71

Browse files
Finish StarForce, initial PR review ready
1 parent cf3f874 commit 4af8d71

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

BinaryObjectScanner/Protection/AlphaROM.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public class AlphaROM : IExecutableCheck<PortableExecutable>, IISOCheck<ISO9660>
9393
{
9494
// Checks can be made even easier once UDF support exists, as most (although not all, some early discs like
9595
// redump ID 124111 have no UDF partition) discs have "Settec" slathered over every field UDF lets them.
96-
96+
9797
var pvd = (PrimaryVolumeDescriptor)iso.VolumeDescriptorSet[0];
9898

9999
// Alpharom disc check #1: disc has varying (but observed to at least always be larger than 14) length
@@ -115,9 +115,9 @@ public class AlphaROM : IExecutableCheck<PortableExecutable>, IISOCheck<ISO9660>
115115

116116
var publisherIdentifier = pvd.PublisherIdentifier;
117117
var firstSpace = Array.FindIndex(publisherIdentifier, b => b == 0x20);
118-
119118
if (firstSpace <= 10 || firstSpace >= 120)
120119
return null;
120+
121121
var publisherData = new byte[firstSpace];
122122
var publisherSpaces = new byte[publisherData.Length - firstSpace];
123123
Array.Copy(publisherIdentifier, 0, publisherData, 0, firstSpace);

BinaryObjectScanner/Protection/StarForce.cs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Text.RegularExpressions;
34
using BinaryObjectScanner.Interfaces;
5+
using SabreTools.Data.Models.ISO9660;
46
using SabreTools.IO;
57
using SabreTools.IO.Extensions;
68
using SabreTools.IO.Matching;
79
using SabreTools.Serialization.Wrappers;
810

911
namespace BinaryObjectScanner.Protection
1012
{
11-
public class StarForce : IExecutableCheck<PortableExecutable>, IPathCheck
13+
public class StarForce : IExecutableCheck<PortableExecutable>, IPathCheck, IISOCheck<ISO9660>
1214
{
1315
// TODO: Bring up to par with PiD.
1416
// Known issues:
@@ -160,5 +162,48 @@ public List<string> CheckDirectoryPath(string path, List<string>? files)
160162
// TODO: Determine if there are any file name checks that aren't too generic to use on their own.
161163
return null;
162164
}
165+
166+
public string? CheckISO(string file, ISO9660 iso, bool includeDebug)
167+
{
168+
var pvd = (PrimaryVolumeDescriptor)iso.VolumeDescriptorSet[0];
169+
170+
int offset = 0;
171+
172+
// StarForce Keyless check #1: the key is stored in the Data Preparer identifier. Length varies, minimum
173+
// length unknown, but it shouldn't be less than 8 at the very least. It's usually 15-24. It's only
174+
// made up of numbers, capital letters, and dashes.
175+
var dataPreparerIdentiferString = pvd.DataPreparerIdentifier.ReadNullTerminatedAnsiString(ref offset)?.Trim();
176+
if (dataPreparerIdentiferString == null || dataPreparerIdentiferString.Length < 8)
177+
return null;
178+
179+
if (!Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9-]*$"))
180+
return null;
181+
182+
// Starforce Keyless check #2: the reserved 653 bytes start with a 32-bit LE number that's slightly less
183+
// than the length of the volume size space. The difference varies, it's usually around 10. Check 500 to be
184+
// safe. The rest of the data is all 0x00.
185+
if (FileType.ISO9660.NoteworthyApplicationUse(pvd))
186+
return null;
187+
188+
if (!FileType.ISO9660.NoteworthyReserved653Bytes(pvd))
189+
return null;
190+
191+
offset = 0;
192+
193+
var reserved653Bytes = pvd.Reserved653Bytes;
194+
var initialValue = reserved653Bytes.ReadUInt32LittleEndian(ref offset);
195+
var zeroBytes = reserved653Bytes.ReadBytes(ref offset, 508);
196+
197+
if (initialValue + 500 < pvd.VolumeSpaceSize || !Array.TrueForAll(zeroBytes, b => b == 0x00))
198+
return null;
199+
200+
// It's unfortunately not known to be possible to detect non-keyless StarForce discs.
201+
202+
// It may be worth returning the key, as it tells you what set of DPM your disc corresponds to, and it would
203+
// also help show why a disc might be an alt of another disc (there are at least a decent amount of StarForce
204+
// Keyless alts that would amtch otherwise). Unclear if this is desired by the users of BOS or those affected
205+
// by it.
206+
return $"StarForce Keyless - {dataPreparerIdentiferString}";
207+
}
163208
}
164209
}

0 commit comments

Comments
 (0)