diff --git a/CHANGELIST.md b/CHANGELIST.md index c0fc15ce..bd2dafe5 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -66,6 +66,7 @@ - Use dated default output filenames - Update packages - Scan disc image if not multi-track +- Scan multi-track images for protection ### 3.5.0 (2025-10-10) diff --git a/MPF.Frontend/Tools/SubmissionGenerator.cs b/MPF.Frontend/Tools/SubmissionGenerator.cs index ed7c57e9..86eabd4f 100644 --- a/MPF.Frontend/Tools/SubmissionGenerator.cs +++ b/MPF.Frontend/Tools/SubmissionGenerator.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; #endif using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; using BinaryObjectScanner; using MPF.Processors; @@ -127,40 +128,11 @@ namespace MPF.Frontend.Tools { resultProgress?.Report(ResultEventArgs.Success("Running copy protection scan... this might take a while!")); - Dictionary>? protections = null; try { + Dictionary>? protections = null; if (options.ScanForProtection) - { - // Scan the mounted drive path - if (drive?.Name != null) - protections = await ProtectionTool.RunProtectionScanOnPath(drive.Name, options, protectionProgress); - - // Scan the disc image, if possible - Dictionary> imageProtections = []; - if (File.Exists($"{basePath}.iso")) - { - imageProtections = await ProtectionTool.RunProtectionScanOnImage($"{basePath}.iso", options, protectionProgress); - } - else if (File.Exists($"{basePath}.bin")) - { - imageProtections = await ProtectionTool.RunProtectionScanOnImage($"{basePath}.bin", options, protectionProgress); - } - // TODO: Add scanning for multi-track images based on cue parsing - - // Add image protections, if any exist - if (imageProtections.Count > 0) - { - protections = []; - foreach (var kvp in imageProtections) - { - if (!protections.ContainsKey(kvp.Key)) - protections[kvp.Key] = []; - - protections[kvp.Key].AddRange(kvp.Value); - } - } - } + protections = await GetProtections(basePath, drive, options, protectionProgress); var protectionString = ProtectionTool.FormatProtections(protections); @@ -1100,6 +1072,86 @@ namespace MPF.Frontend.Tools info.VersionAndEditions.Version = valueFunc(drive) ?? string.Empty; } + /// + /// Get the protections for a disc based on the mounted path and disc image + /// + private async static Task>> GetProtections(string basePath, + Drive? drive, + Options options, + IProgress? protectionProgress = null) + { + // Setup the output protections dictionary + Dictionary> protections = []; + + // Scan the mounted drive path + if (drive?.Name != null) + protections = await ProtectionTool.RunProtectionScanOnPath(drive.Name, options, protectionProgress); + + // Scan the disc image, if possible + Dictionary> imageProtections = []; + if (File.Exists($"{basePath}.iso")) + { + imageProtections = await ProtectionTool.RunProtectionScanOnImage($"{basePath}.iso", options, protectionProgress); + } + else if (File.Exists($"{basePath}.bin")) + { + imageProtections = await ProtectionTool.RunProtectionScanOnImage($"{basePath}.bin", options, protectionProgress); + } + else if (File.Exists($"{basePath}.cue")) + { + string[] cueLines = File.ReadAllLines($"{basePath}.cue"); + foreach (string cueLine in cueLines) + { + // Skip all non-FILE lines + if (!cueLine.StartsWith("FILE")) + continue; + + // Extract the information + var match = Regex.Match(cueLine, @"FILE ""(.*?)"" BINARY"); + if (!match.Success || match.Groups.Count == 0) + continue; + + // Get the track name from the matches + string trackName = match.Groups[1].Value; + trackName = Path.GetFileNameWithoutExtension(trackName); + string baseDir = Path.GetDirectoryName(basePath) ?? string.Empty; + string trackPath = Path.Combine(baseDir, trackName); + + // Scan the track for protections, if it exists + if (File.Exists($"{trackPath}.bin")) + { + var trackProtections = await ProtectionTool.RunProtectionScanOnImage($"{trackPath}.bin", options, protectionProgress); + + // Add track protections, if any exist + if (trackProtections.Count > 0) + { + foreach (var kvp in trackProtections) + { + if (!imageProtections.ContainsKey(kvp.Key)) + imageProtections[kvp.Key] = []; + + imageProtections[kvp.Key].AddRange(kvp.Value); + } + } + } + } + } + + // Add image protections, if any exist + if (imageProtections.Count > 0) + { + foreach (var kvp in imageProtections) + { + if (!protections.ContainsKey(kvp.Key)) + protections[kvp.Key] = []; + + protections[kvp.Key].AddRange(kvp.Value); + } + } + + return protections; + } + /// /// Reformat a protection dictionary for submission info ///