From d705a4b316d6bd558ec264d489a39642bf7802bf Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Thu, 10 Sep 2020 11:27:25 -0700 Subject: [PATCH] UmdImageCreator stands alone --- DICUI.Library/Data/Enumerations.cs | 3 +- DICUI.Library/DiscImageCreator/Converters.cs | 1 - DICUI.Library/DiscImageCreator/Parameters.cs | 73 ----- DICUI.Library/UmdImageCreator/Parameters.cs | 325 +++++++++++++++++++ DICUI.Library/Utilities/Converters.cs | 5 +- DICUI.Library/Utilities/DumpEnvironment.cs | 8 + 6 files changed, 339 insertions(+), 76 deletions(-) create mode 100644 DICUI.Library/UmdImageCreator/Parameters.cs diff --git a/DICUI.Library/Data/Enumerations.cs b/DICUI.Library/Data/Enumerations.cs index ff37ddd4..7403604c 100644 --- a/DICUI.Library/Data/Enumerations.cs +++ b/DICUI.Library/Data/Enumerations.cs @@ -23,11 +23,12 @@ namespace DICUI.Data // Dumping support Aaru, DD, - DiscImageCreator, // Includes UmdImageCreator + DiscImageCreator, // Verification support only CleanRip, DCDumper, + UmdImageCreator, } /// diff --git a/DICUI.Library/DiscImageCreator/Converters.cs b/DICUI.Library/DiscImageCreator/Converters.cs index a5496170..0a01042b 100644 --- a/DICUI.Library/DiscImageCreator/Converters.cs +++ b/DICUI.Library/DiscImageCreator/Converters.cs @@ -103,7 +103,6 @@ namespace DICUI.DiscImageCreator case MediaType.HDDVD: case MediaType.BluRay: case MediaType.NintendoWiiOpticalDisc: - case MediaType.UMD: return ".iso"; case MediaType.LaserDisc: case MediaType.NintendoGameCubeGameDisc: diff --git a/DICUI.Library/DiscImageCreator/Parameters.cs b/DICUI.Library/DiscImageCreator/Parameters.cs index 81cb5367..90c39ec8 100644 --- a/DICUI.Library/DiscImageCreator/Parameters.cs +++ b/DICUI.Library/DiscImageCreator/Parameters.cs @@ -1622,14 +1622,6 @@ namespace DICUI.DiscImageCreator break; - case MediaType.UMD: - return File.Exists(basePath + "_disc.txt") - || File.Exists(basePath + "_mainError.txt") - || File.Exists(basePath + "_mainInfo.txt") - || File.Exists(basePath + "_volDesc.txt"); - - break; - default: // Non-dumping commands will usually produce no output, so this is irrelevant return true; @@ -1738,22 +1730,6 @@ namespace DICUI.DiscImageCreator info.Extras.PIC = GetPIC(Path.Combine(outputDirectory, "PIC.bin")) ?? ""; break; - - case MediaType.UMD: - info.Extras.PVD = GetPVD(basePath + "_mainInfo.txt") ?? ""; - - if (GetUMDAuxInfo(basePath + "_disc.txt", out string title, out DiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize)) - { - info.CommonDiscInfo.Title = title ?? ""; - info.CommonDiscInfo.Category = umdcat ?? DiscCategory.Games; - info.VersionAndEditions.Version = umdversion ?? ""; - info.SizeAndChecksums.Size = umdsize; - - if (!string.IsNullOrWhiteSpace(umdlayer)) - info.SizeAndChecksums.Layerbreak = Int64.Parse(umdlayer ?? "-1"); - } - - break; } // Extract info based specifically on KnownSystem @@ -2734,55 +2710,6 @@ namespace DICUI.DiscImageCreator } } - /// - /// Get the UMD auxiliary info from the outputted files, if possible - /// - /// _disc.txt file location - /// True on successful extraction of info, false otherwise - private static bool GetUMDAuxInfo(string disc, out string title, out DiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize) - { - title = null; umdcat = null; umdversion = null; umdlayer = null; umdsize = -1; - - // If the file doesn't exist, we can't get info from it - if (!File.Exists(disc)) - return false; - - using (StreamReader sr = File.OpenText(disc)) - { - try - { - // Loop through everything to get the first instance of each required field - string line = string.Empty; - while (!sr.EndOfStream) - { - line = sr.ReadLine().Trim(); - - if (line.StartsWith("TITLE") && title == null) - title = line.Substring("TITLE: ".Length); - else if (line.StartsWith("DISC_VERSION") && umdversion == null) - umdversion = line.Split(' ')[1]; - else if (line.StartsWith("pspUmdTypes")) - umdcat = GetUMDCategory(line.Split(' ')[1]); - else if (line.StartsWith("L0 length")) - umdlayer = line.Split(' ')[2]; - else if (line.StartsWith("FileSize:")) - umdsize = Int64.Parse(line.Split(' ')[1]); - } - - // If the L0 length is the size of the full disc, there's no layerbreak - if (Int64.Parse(umdlayer) * 2048 == umdsize) - umdlayer = null; - - return true; - } - catch - { - // We don't care what the exception is right now - return false; - } - } - } - /// /// Get the write offset from the input file, if possible /// diff --git a/DICUI.Library/UmdImageCreator/Parameters.cs b/DICUI.Library/UmdImageCreator/Parameters.cs new file mode 100644 index 00000000..e0f0c2f3 --- /dev/null +++ b/DICUI.Library/UmdImageCreator/Parameters.cs @@ -0,0 +1,325 @@ +using System; +using System.IO; +using DICUI.Data; +using DICUI.Utilities; +using DICUI.Web; + +namespace DICUI.UmdImageCreator +{ + /// + /// Represents a generic set of UmdImageCreator parameters + /// + public class Parameters : BaseParameters + { + /// + /// Populate a Parameters object from a param string + /// + /// String possibly representing a set of parameters + public Parameters(string parameters) + : base(parameters) + { + this.InternalProgram = InternalProgram.UmdImageCreator; + } + + /// + /// Generate parameters based on a set of known inputs + /// + /// KnownSystem value to use + /// MediaType value to use + /// Drive letter to use + /// Filename to use + /// Drive speed to use + /// Enable paranoid mode (safer dumping) + /// Enable quiet mode (no beeps) + /// User-defined reread count + public Parameters(KnownSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, bool paranoid, bool quietMode, int retryCount) + : base(system, type, driveLetter, filename, driveSpeed, paranoid, quietMode, retryCount) + { + } + + /// + /// Blindly generate a parameter string based on the inputs + /// + /// Correctly formatted parameter string, null on error + public override string GenerateParameters() => null; + + /// + /// Get the input path from the implementation + /// + /// String representing the path, null on error + public override string InputPath() => null; + + /// + /// Get the output path from the implementation + /// + /// String representing the path, null on error + public override string OutputPath() => null; + + /// + /// Get the processing speed from the implementation + /// + /// int? representing the speed, null on error + public override int? GetSpeed() => null; + + /// + /// Set the processing speed int the implementation + /// + /// int? representing the speed + public override void SetSpeed(int? speed) { } + + /// + /// Get the MediaType from the current set of parameters + /// + /// MediaType value if successful, null on error + public override MediaType? GetMediaType() => null; + + /// + /// Gets if the current command is considered a dumping command or not + /// + /// True if it's a dumping command, false otherwise + public override bool IsDumpingCommand() => true; + + /// + /// Reset all special variables to have default values + /// + protected override void ResetValues() { } + + /// + /// Set default parameters for a given system and media type + /// + /// KnownSystem value to use + /// MediaType value to use + /// Drive letter to use + /// Filename to use + /// Drive speed to use + /// Enable paranoid mode (safer dumping) + /// User-defined reread count + protected override void SetDefaultParameters( + KnownSystem? system, + MediaType? type, + char driveLetter, + string filename, + int? driveSpeed, + bool paranoid, + int retryCount) + { + } + + /// + /// Scan a possible parameter string and populate whatever possible + /// + /// String possibly representing parameters + /// + protected override bool ValidateAndSetParameters(string parameters) => true; + + /// + /// Validate if all required output files exist + /// + /// Base filename and path to use for checking + /// KnownSystem type representing the media + /// MediaType type representing the media + /// Optional result progress callback + /// + public override bool CheckAllOutputFilesExist(string basePath, KnownSystem? system, MediaType? type, IProgress progress = null) + { + string missingFiles = string.Empty; + switch (type) + { + case MediaType.UMD: + if (!File.Exists($"{basePath}_disc.txt")) + missingFiles += $";{basePath}_disc.txt"; + if (!File.Exists($"{basePath}_mainError.txt")) + missingFiles += $";{basePath}_mainError.txt"; + if (!File.Exists($"{basePath}_mainInfo.txt")) + missingFiles += $";{basePath}_mainInfo.txt"; + if (!File.Exists($"{basePath}_volDesc.txt")) + missingFiles += $";{basePath}_volDesc.txt"; + + break; + + default: + // Non-dumping commands will usually produce no output, so this is irrelevant + return true; + } + + // Use the missing files list as an indicator + if (string.IsNullOrEmpty(missingFiles)) + { + return true; + } + else + { + progress?.Report(Result.Failure($"The following files were missing: {missingFiles.TrimStart(';')}")); + return false; + } + } + + /// + /// Generate a SubmissionInfo for the output files + /// + /// Base submission info to fill in specifics for + /// Base filename and path to use for checking + /// KnownSystem type representing the media + /// MediaType type representing the media + /// Drive representing the disc to get information from + /// + public override void GenerateSubmissionInfo(SubmissionInfo info, string basePath, KnownSystem? system, MediaType? type, Drive drive) + { + // Fill in the hash data + info.TracksAndWriteOffsets.ClrMameProData = GetDatfile(basePath + ".dat"); + + // Extract info based generically on MediaType + switch (type) + { + case MediaType.UMD: + info.Extras.PVD = GetPVD(basePath + "_mainInfo.txt") ?? ""; + + if (GetUMDAuxInfo(basePath + "_disc.txt", out string title, out DiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize)) + { + info.CommonDiscInfo.Title = title ?? ""; + info.CommonDiscInfo.Category = umdcat ?? DiscCategory.Games; + info.VersionAndEditions.Version = umdversion ?? ""; + info.SizeAndChecksums.Size = umdsize; + + if (!string.IsNullOrWhiteSpace(umdlayer)) + info.SizeAndChecksums.Layerbreak = Int64.Parse(umdlayer ?? "-1"); + } + + break; + } + } + + #region Information Extraction Methods + + /// + /// Get the proper datfile from the input file, if possible + /// + /// .dat file location + /// Relevant pieces of the datfile, null on error + private static string GetDatfile(string dat) + { + // If the file doesn't exist, we can't get info from it + if (!File.Exists(dat)) + return null; + + using (StreamReader sr = File.OpenText(dat)) + { + try + { + // Make sure this file is a .dat + if (sr.ReadLine() != "") + return null; + if (sr.ReadLine() != "") + return null; + + // Fast forward to the rom lines + while (!sr.ReadLine().TrimStart().StartsWith("Games + sr.ReadLine(); // Plextor + + // Now that we're at the relevant entries, read each line in and concatenate + string pvd = "", line = sr.ReadLine().Trim(); + while (line.StartsWith(" + /// Get the PVD from the input file, if possible + /// + /// _mainInfo.txt file location + /// Newline-deliminated PVD if possible, null on error + private static string GetPVD(string mainInfo) + { + // If the file doesn't exist, we can't get info from it + if (!File.Exists(mainInfo)) + return null; + + using (StreamReader sr = File.OpenText(mainInfo)) + { + try + { + // Make sure we're in the right sector + while (!sr.ReadLine().StartsWith("========== LBA[000016, 0x00010]: Main Channel ==========")) ; + + // Fast forward to the PVD + while (!sr.ReadLine().StartsWith("0310")) ; + + // Now that we're at the PVD, read each line in and concatenate + string pvd = ""; + for (int i = 0; i < 6; i++) + pvd += sr.ReadLine() + "\n"; // 320-370 + + return pvd; + } + catch + { + // We don't care what the exception is right now + return null; + } + } + } + + /// + /// Get the UMD auxiliary info from the outputted files, if possible + /// + /// _disc.txt file location + /// True on successful extraction of info, false otherwise + private static bool GetUMDAuxInfo(string disc, out string title, out DiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize) + { + title = null; umdcat = null; umdversion = null; umdlayer = null; umdsize = -1; + + // If the file doesn't exist, we can't get info from it + if (!File.Exists(disc)) + return false; + + using (StreamReader sr = File.OpenText(disc)) + { + try + { + // Loop through everything to get the first instance of each required field + string line = string.Empty; + while (!sr.EndOfStream) + { + line = sr.ReadLine().Trim(); + + if (line.StartsWith("TITLE") && title == null) + title = line.Substring("TITLE: ".Length); + else if (line.StartsWith("DISC_VERSION") && umdversion == null) + umdversion = line.Split(' ')[1]; + else if (line.StartsWith("pspUmdTypes")) + umdcat = GetUMDCategory(line.Split(' ')[1]); + else if (line.StartsWith("L0 length")) + umdlayer = line.Split(' ')[2]; + else if (line.StartsWith("FileSize:")) + umdsize = Int64.Parse(line.Split(' ')[1]); + } + + // If the L0 length is the size of the full disc, there's no layerbreak + if (Int64.Parse(umdlayer) * 2048 == umdsize) + umdlayer = null; + + return true; + } + catch + { + // We don't care what the exception is right now + return false; + } + } + } + + #endregion + } +} diff --git a/DICUI.Library/Utilities/Converters.cs b/DICUI.Library/Utilities/Converters.cs index e5869e81..8c58dc49 100644 --- a/DICUI.Library/Utilities/Converters.cs +++ b/DICUI.Library/Utilities/Converters.cs @@ -484,6 +484,9 @@ namespace DICUI.Utilities case InternalProgram.DCDumper: return "DCDumper"; + case InternalProgram.UmdImageCreator: + return "UmdImageCreator"; + #endregion case InternalProgram.NONE: @@ -1298,7 +1301,7 @@ namespace DICUI.Utilities case "umd": case "umdcreator": case "umdimagecreator": - return InternalProgram.DiscImageCreator; // TODO: Make separate internally + return InternalProgram.UmdImageCreator; default: return InternalProgram.NONE; diff --git a/DICUI.Library/Utilities/DumpEnvironment.cs b/DICUI.Library/Utilities/DumpEnvironment.cs index 23d72986..0e64ebd7 100644 --- a/DICUI.Library/Utilities/DumpEnvironment.cs +++ b/DICUI.Library/Utilities/DumpEnvironment.cs @@ -208,6 +208,10 @@ namespace DICUI.Utilities this.Parameters = null; // TODO: Create correct parameter type when supported break; + case InternalProgram.UmdImageCreator: + this.Parameters = new UmdImageCreator.Parameters(parameters); + break; + // This should never happen, but it needs a fallback default: this.Parameters = new DiscImageCreator.Parameters(parameters); @@ -245,6 +249,10 @@ namespace DICUI.Utilities this.Parameters.ExecutablePath = null; break; + case InternalProgram.UmdImageCreator: + this.Parameters.ExecutablePath = null; + break; + // This should never happen, but it needs a fallback default: this.InternalProgram = InternalProgram.DiscImageCreator;