diff --git a/BinaryObjectScanner/Factory.cs b/BinaryObjectScanner/Factory.cs index 6efcb73d..46ce7135 100644 --- a/BinaryObjectScanner/Factory.cs +++ b/BinaryObjectScanner/Factory.cs @@ -20,6 +20,8 @@ namespace BinaryObjectScanner //case SupportedFileType.N3DS: return new FileType.N3DS(); //case SupportedFileType.Nitro: return new FileType.Nitro(); case SupportedFileType.PLJ: return new FileType.PLJ(); + case SupportedFileType.RealArcadeInstaller: return new FileType.RealArcadeInstaller(); + case SupportedFileType.RealArcadeMezzanine: return new FileType.RealArcadeMezzanine(); case SupportedFileType.SFFS: return new FileType.SFFS(); case SupportedFileType.Textfile: return new FileType.Textfile(); default: return null; diff --git a/BinaryObjectScanner/FileType/RealArcadeInstaller.cs b/BinaryObjectScanner/FileType/RealArcadeInstaller.cs new file mode 100644 index 00000000..5033ac6d --- /dev/null +++ b/BinaryObjectScanner/FileType/RealArcadeInstaller.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using BinaryObjectScanner.Interfaces; +using SabreTools.Matching; + +namespace BinaryObjectScanner.FileType +{ + /// + /// RealArcade Installer. Known to use the ".rgs" file extension. + /// + /// TODO: Add further parsing, game ID and name should be possible to parse. + /// + public class RealArcadeInstaller : IDetectable + { + /// + public string? Detect(string file, bool includeDebug) + { + if (!File.Exists(file)) + return null; + + using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + return Detect(fs, file, includeDebug); + } + } + + /// + public string? Detect(Stream stream, string file, bool includeDebug) + { + try + { + byte[] magic = new byte[16]; + stream.Read(magic, 0, 16); + + // RASGI2.0 + // Found in the ".rgs" files in IA item "Nova_RealArcadeCD_USA". + if (magic.StartsWith(new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 })) + return "RealArcade Installer"; + } + catch (Exception ex) + { + if (includeDebug) Console.WriteLine(ex); + } + + return null; + } + } +} diff --git a/BinaryObjectScanner/FileType/RealArcadeMezzanine.cs b/BinaryObjectScanner/FileType/RealArcadeMezzanine.cs new file mode 100644 index 00000000..9b5a7ff3 --- /dev/null +++ b/BinaryObjectScanner/FileType/RealArcadeMezzanine.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using BinaryObjectScanner.Interfaces; +using SabreTools.Matching; + +namespace BinaryObjectScanner.FileType +{ + /// + /// RealArcade Mezzanine files, which contain metadata. Known to use the ".mez" file extension. + /// + /// TODO: Add further parsing, game ID should be possible to parse. + /// + public class RealArcadeMezzanine : IDetectable + { + /// + public string? Detect(string file, bool includeDebug) + { + if (!File.Exists(file)) + return null; + + using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + return Detect(fs, file, includeDebug); + } + } + + /// + public string? Detect(Stream stream, string file, bool includeDebug) + { + try + { + byte[] magic = new byte[16]; + stream.Read(magic, 0, 16); + + // XZip2.0 + // Found in the ".mez" files in IA item "Nova_RealArcadeCD_USA". + if (magic.StartsWith(new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 })) + return "RealArcade Mezzanine"; + } + catch (Exception ex) + { + if (includeDebug) Console.WriteLine(ex); + } + + return null; + } + } +} diff --git a/BinaryObjectScanner/Protection/RealArcade.cs b/BinaryObjectScanner/Protection/RealArcade.cs new file mode 100644 index 00000000..3a355670 --- /dev/null +++ b/BinaryObjectScanner/Protection/RealArcade.cs @@ -0,0 +1,75 @@ +using System; +#if NET40_OR_GREATER || NETCOREAPP +using System.Collections.Concurrent; +#endif +using System.Collections.Generic; +using System.Linq; +using BinaryObjectScanner.Interfaces; +using SabreTools.Matching; +using SabreTools.Serialization.Wrappers; + +namespace BinaryObjectScanner.Protection +{ + /// + /// RealArcade was a game platform that allowed users to play timed demos of games, and then prompted them to purchase the game in order to play the game without a limit. + /// Although the servers are long dead, there is a community project actively being developed to allow users to properly download and play these games. + /// Links: + /// https://github.com/lightbulbatelier/RealArcade-DGA + /// https://archive.org/details/realrcade-games-preservation-project + /// + public class RealArcade : IPathCheck, IPortableExecutableCheck + { + /// + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) + { + // Get the sections from the executable, if possible + var sections = pex.Model.SectionTable; + if (sections == null) + return null; + + // Get the .data section strings, if they exist + var strs = pex.GetFirstSectionStrings(".data"); + if (strs != null) + { + // Found in "rebound.exe" in the installation directory for "Rebound" in IA item "Nova_RealArcadeCD_USA". + if (strs.Any(s => s.Contains("RngInterstitialDLL"))) + return "RealArcade"; + } + + // Found in "RngInterstitial.dll" in the RealArcade installation directory in IA item "Nova_RealArcadeCD_USA". + var name = pex.FileDescription; + if (name?.Contains("RngInterstitial") == true) + return "RealArcade"; + + return null; + } + + /// +#if NET20 || NET35 + public Queue CheckDirectoryPath(string path, IEnumerable? files) +#else + public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable? files) +#endif + { + var matchers = new List + { + // ".rgs" and ".mez" files are also associated with RealArcade. + new(new FilePathMatch("RngInterstitial.dll"), "RealArcade"), + }; + + return MatchUtil.GetAllMatches(files, matchers, any: true); + } + + /// + public string? CheckFilePath(string path) + { + var matchers = new List + { + // ".rgs" and ".mez" files are also associated with RealArcade. + new(new FilePathMatch("RngInterstitial.dll"), "RealArcade"), + }; + + return MatchUtil.GetFirstMatch(path, matchers, any: true); + } + } +} diff --git a/BinaryObjectScanner/Utilities/Enums.cs b/BinaryObjectScanner/Utilities/Enums.cs index 7ae80b5d..ffe29922 100644 --- a/BinaryObjectScanner/Utilities/Enums.cs +++ b/BinaryObjectScanner/Utilities/Enums.cs @@ -140,6 +140,16 @@ /// RAR, + /// + /// RealArcade Installer + /// + RealArcadeInstaller, + + /// + /// RealArcade Mezzanine + /// + RealArcadeMezzanine, + /// /// 7-zip archive /// diff --git a/BinaryObjectScanner/Utilities/FileTypes.cs b/BinaryObjectScanner/Utilities/FileTypes.cs index 98455851..e49cad4a 100644 --- a/BinaryObjectScanner/Utilities/FileTypes.cs +++ b/BinaryObjectScanner/Utilities/FileTypes.cs @@ -259,6 +259,20 @@ namespace BinaryObjectScanner.Utilities #endregion + #region RealArcade + + // RASGI2.0 + // Found in the ".rgs files in IA item "Nova_RealArcadeCD_USA". + if (magic.StartsWith(new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 })) + return SupportedFileType.RealArcadeInstaller; + + // XZip2.0 + // Found in the ".mez" files in IA item "Nova_RealArcadeCD_USA". + if (magic.StartsWith(new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 })) + return SupportedFileType.RealArcadeMezzanine; + + #endregion + #region SevenZip if (magic.StartsWith(new byte?[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c })) diff --git a/README.md b/README.md index 455b53e7..9df435da 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ Below is a list of protections detected by BinaryObjectScanner. The two columns | Protect DVD-Video | False | True | Unconfirmed¹ | | PlayStation Anti-modchip | True | False | En/Jp, not "Red Hand"; PSX executables only | | Rainbow Sentinel | True | True | | +| RealArcade | True | True | | | Ring PROTECH / ProRing | True | True | Partially unconfirmed² | | RipGuard | True | True | Partially unconfirmed² | | Roxxe | True | False | |