diff --git a/BurnOutSharp/Enums.cs b/BurnOutSharp/Enums.cs
index 8731daf7..d799bc09 100644
--- a/BurnOutSharp/Enums.cs
+++ b/BurnOutSharp/Enums.cs
@@ -80,6 +80,11 @@
///
SevenZip,
+ ///
+ /// StarForce FileSystem file
+ ///
+ SFFS,
+
///
/// Tape archive
///
diff --git a/BurnOutSharp/FileType/SFFS.cs b/BurnOutSharp/FileType/SFFS.cs
new file mode 100644
index 00000000..180be1e0
--- /dev/null
+++ b/BurnOutSharp/FileType/SFFS.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Concurrent;
+using System.IO;
+using BurnOutSharp.Interfaces;
+using BurnOutSharp.Tools;
+
+namespace BurnOutSharp.FileType
+{
+ ///
+ /// StarForce Filesystem file
+ ///
+ public class SFFS : IScannable
+ {
+ ///
+ public ConcurrentDictionary> Scan(Scanner scanner, string file)
+ {
+ if (!File.Exists(file))
+ return null;
+
+ using (var fs = File.OpenRead(file))
+ {
+ return Scan(scanner, fs, file);
+ }
+ }
+
+ ///
+ public ConcurrentDictionary> Scan(Scanner scanner, Stream stream, string file)
+ {
+ var protections = new ConcurrentDictionary>();
+ try
+ {
+ byte[] magic = new byte[16];
+ stream.Read(magic, 0, 16);
+
+ if (Utilities.GetFileType(magic) == SupportedFileType.SFFS)
+ {
+ Utilities.AppendToDictionary(protections, file, "StarForce Filesystem Container");
+ return protections;
+ }
+ }
+ catch (Exception ex)
+ {
+ if (scanner.IncludeDebug) Console.WriteLine(ex);
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/BurnOutSharp/ProtectionType/StarForce.cs b/BurnOutSharp/ProtectionType/StarForce.cs
index 03fa8e66..1f010036 100644
--- a/BurnOutSharp/ProtectionType/StarForce.cs
+++ b/BurnOutSharp/ProtectionType/StarForce.cs
@@ -3,6 +3,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using BurnOutSharp.Interfaces;
+using BurnOutSharp.Matching;
using BurnOutSharp.Tools;
using BurnOutSharp.Wrappers;
@@ -10,6 +11,13 @@ namespace BurnOutSharp.ProtectionType
{
public class StarForce : IPathCheck, IPortableExecutableCheck
{
+ // TODO: Bring up to par with PiD.
+ // Known issues:
+ // "Game.exe" not detected, "SF Crypto" not found in protect.* files (Redump entry 96137).
+ // "HR.exe" Themida not detected, doesn't detect "[Builder]" (Is that the default StarForce?) (Redump entry 94805).
+ // "ChromeEngine3.dll" and "SGP4.dll" not detected, doesn't detect "[FL Disc]" (Redump entry 93098).
+ // "Replay.exe" not detected, doesn't detect "[FL Disc]" (Redump entry 81756).
+ // Doesn't detect "[Pro]" (Redump entry 91336).
///
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
@@ -24,12 +32,26 @@ namespace BurnOutSharp.ProtectionType
else if (name?.Contains("Protection Technology") == true) // Protection Technology (StarForce)?
return $"StarForce {Utilities.GetInternalVersion(pex)}";
+ // TODO: Decide if internal name checks are safe to use.
name = pex.InternalName;
- if (name?.Equals("CORE.EXE", StringComparison.Ordinal) == true)
- return $"StarForce {Utilities.GetInternalVersion(pex)}";
- else if (name?.Equals("protect.exe", StringComparison.Ordinal) == true)
+
+ // Found in "protect.x64" and "protect.x86" in Redump entry 94805.
+ if (name?.Equals("CORE.ADMIN", StringComparison.Ordinal) == true)
return $"StarForce {Utilities.GetInternalVersion(pex)}";
+
+ // These checks currently disabled due being possibly too generic:
+ // Found in "protect.dll" in Redump entry 94805.
+ // if (name?.Equals("CORE.DLL", StringComparison.Ordinal) == true)
+ // return $"StarForce {Utilities.GetInternalVersion(pex)}";
+ //
+ // Found in "protect.exe" in Redump entry 94805.
+ // if (name?.Equals("CORE.EXE", StringComparison.Ordinal) == true)
+ // return $"StarForce {Utilities.GetInternalVersion(pex)}";
+ //
+ // else if (name?.Equals("protect.exe", StringComparison.Ordinal) == true)
+ // return $"StarForce {Utilities.GetInternalVersion(pex)}";
+
// Check the export name table
if (pex.ExportNameTable != null)
{
@@ -40,6 +62,25 @@ namespace BurnOutSharp.ProtectionType
// TODO: Find what fvinfo field actually maps to this
name = pex.FileDescription;
+
+ // There are some File Description checks that are currently too generic to use.
+ // "Host Library" - Found in "protect.dll" in Redump entry 81756.
+ // "User Interface Application" - Found in "protect.exe" in Redump entry 81756.
+ // "Helper Application" - Found in "protect.x64" and "protect.x86" in Redump entry 81756.
+
+ // Found in "protect.exe" in Redump entry 94805.
+ if (name?.Contains("FrontLine Protection GUI Application") == true)
+ return $"StarForce {Utilities.GetInternalVersion(pex)}";
+
+ // Found in "protect.dll" in Redump entry 94805.
+ if (name?.Contains("FrontLine Protection Library") == true)
+ return $"StarForce {Utilities.GetInternalVersion(pex)}";
+
+ // Found in "protect.x64" and "protect.x86" in Redump entry 94805.
+ if (name?.Contains("FrontLine Helper") == true)
+ return $"StarForce {Utilities.GetInternalVersion(pex)}";
+
+ // TODO: Find a sample of this check.
if (name?.Contains("Protected Module") == true)
return $"StarForce 5";
@@ -62,30 +103,43 @@ namespace BurnOutSharp.ProtectionType
///
public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable files)
{
- // These have too high of a chance of over-matching by themselves
- // var matchers = new List
- // {
- // // TODO: Re-consolidate these once path matching is improved
- // new PathMatchSet(new PathMatch("/protect.dll", useEndsWith: true), "StarForce"),
- // new PathMatchSet(new PathMatch("/protect.exe", useEndsWith: true), "StarForce"),
- // };
+ var matchers = new List
+ {
+ // This file combination is found in Redump entry 21136.
+ new PathMatchSet(new List
+ {
+ new PathMatch("protect.x86", useEndsWith: true),
+ new PathMatch("protect.x64", useEndsWith: true),
+ new PathMatch("protect.dll", useEndsWith: true),
+ new PathMatch("protect.exe", useEndsWith: true),
+ new PathMatch("protect.msg", useEndsWith: true),
+ }, "StarForce"),
- // return MatchUtil.GetAllMatches(files, matchers, any: false);
- return null;
+ // This file combination is found in multiple games, such as Redump entries 81756, 91336, and 93657.
+ new PathMatchSet(new List
+ {
+ new PathMatch("protect.x86", useEndsWith: true),
+ new PathMatch("protect.x64", useEndsWith: true),
+ new PathMatch("protect.dll", useEndsWith: true),
+ new PathMatch("protect.exe", useEndsWith: true),
+ }, "StarForce"),
+
+ // This file combination is found in Redump entry 96137.
+ new PathMatchSet(new List
+ {
+ new PathMatch("protect.x86", useEndsWith: true),
+ new PathMatch("protect.dll", useEndsWith: true),
+ new PathMatch("protect.exe", useEndsWith: true),
+ }, "StarForce"),
+ };
+
+ return MatchUtil.GetAllMatches(files, matchers, any: false);
}
///
public string CheckFilePath(string path)
{
- // These have too high of a chance of over-matching by themselves
- // var matchers = new List
- // {
- // // TODO: Re-consolidate these once path matching is improved
- // new PathMatchSet(new PathMatch("/protect.dll", useEndsWith: true), "StarForce"),
- // new PathMatchSet(new PathMatch("/protect.exe", useEndsWith: true), "StarForce"),
- // };
-
- // return MatchUtil.GetFirstMatch(path, matchers, any: true);
+ // TODO: Determine if there are any file name checks that aren't too generic to use on their own.
return null;
}
}
diff --git a/BurnOutSharp/ProtectionType/Tages.cs b/BurnOutSharp/ProtectionType/Tages.cs
index 8081db1f..dbbd466e 100644
--- a/BurnOutSharp/ProtectionType/Tages.cs
+++ b/BurnOutSharp/ProtectionType/Tages.cs
@@ -151,7 +151,7 @@ namespace BurnOutSharp.ProtectionType
new PathMatchSet(new PathMatch("GAME.KWN", useEndsWith: true), "TAGES (BASIC?)"),
};
- return MatchUtil.GetAllMatches(files, matchers, any: true);
+ return MatchUtil.GetAllMatches(files, matchers, any: false);
}
///
diff --git a/BurnOutSharp/Scanner.cs b/BurnOutSharp/Scanner.cs
index b367d845..4983eb2d 100644
--- a/BurnOutSharp/Scanner.cs
+++ b/BurnOutSharp/Scanner.cs
@@ -339,6 +339,13 @@ namespace BurnOutSharp
Utilities.AppendToDictionary(protections, subProtections);
}
+ // SFFS
+ if (scannable is SFFS)
+ {
+ var subProtections = scannable.Scan(this, stream, fileName);
+ Utilities.AppendToDictionary(protections, subProtections);
+ }
+
// Text-based files
if (scannable is Textfile)
{
diff --git a/BurnOutSharp/Tools/Utilities.cs b/BurnOutSharp/Tools/Utilities.cs
index b25232c0..c9818a30 100644
--- a/BurnOutSharp/Tools/Utilities.cs
+++ b/BurnOutSharp/Tools/Utilities.cs
@@ -327,6 +327,14 @@ namespace BurnOutSharp.Tools
#endregion
+ #region SFFS
+
+ // Found in Redump entry 81756, confirmed to be "StarForce Filesystem" by PiD.
+ if (magic.StartsWith(new byte?[] { 0x53, 0x46, 0x46, 0x53, 0x01, 0x00, 0x00, 0x00 }))
+ return SupportedFileType.SFFS;
+
+ #endregion
+
#region SevenZip
if (magic.StartsWith(new byte?[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c }))