diff --git a/SabreTools.Helper/Tools/DatTools.cs b/SabreTools.Helper/Tools/DatTools.cs index 8417e268..88dc9b9d 100644 --- a/SabreTools.Helper/Tools/DatTools.cs +++ b/SabreTools.Helper/Tools/DatTools.cs @@ -1574,9 +1574,14 @@ namespace SabreTools.Helper /// /// Convert, update, and filter a DAT file /// - /// Name of the input file or folder + /// Names of the input files and/or folders /// User specified inputs contained in a DatData object /// Optional param for output directory + /// True if input files should be merged into a single file, false otherwise + /// True if the input files should be diffed with each other, false otherwise + /// True if the diffed files should be cascade diffed, false otherwise + /// True if the cascade-diffed files should overwrite their inputs, false otherwise + /// True if the date should not be appended to the default name, false otherwise [OBSOLETE] /// True to clean the game names to WoD standard, false otherwise (default) /// Name of the game to match (can use asterisk-partials) /// Name of the rom to match (can use asterisk-partials) @@ -1589,59 +1594,139 @@ namespace SabreTools.Helper /// SHA-1 of the rom to match (can use asterisk-partials) /// Select roms with nodump status as follows: null (match all), true (match Nodump only), false (exclude Nodump) /// Logging object for console and file output - public static void Update(string inputFileName, Dat datdata, string outputDirectory, bool clean, string gamename, string romname, - string romtype, long sgt, long slt, long seq, string crc, string md5, string sha1, bool? nodump, Logger logger) + public static void Update(List inputFileNames, Dat datdata, string outputDirectory, bool merge, bool diff, bool cascade, bool inplace, + bool bare, bool clean, string gamename, string romname, string romtype, long sgt, long slt, long seq, string crc, string md5, + string sha1, bool? nodump, Logger logger) { - // Clean the input string - if (inputFileName != "") + // If we're in merging or diffing mode, use the full list of inputs + if (merge || diff) { - inputFileName = Path.GetFullPath(inputFileName); - } + // Create a dictionary of all ROMs from the input DATs + datdata.FileName = datdata.Description; + Dat userData; + List datHeaders = PopulateUserData(inputFileNames, inplace, clean, outputDirectory, datdata, out userData, logger); - if (File.Exists(inputFileName)) - { - logger.User("Processing \"" + Path.GetFileName(inputFileName) + "\""); - datdata = Parse(inputFileName, 0, 0, datdata, logger, true, clean); - datdata = Filter(datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, logger); - - // If the extension matches, append ".new" to the filename - string extension = (datdata.OutputFormat == OutputFormat.Xml || datdata.OutputFormat == OutputFormat.SabreDat ? ".xml" : ".dat"); - if (outputDirectory == "" && Path.GetExtension(inputFileName) == extension) + // Modify the Dictionary if necessary and output the results + if (diff && !cascade) { - datdata.FileName += ".new"; + DiffNoCascade(outputDirectory, userData, inputFileNames, logger); } - - Output.WriteDatfile(datdata, (outputDirectory == "" ? Path.GetDirectoryName(inputFileName) : outputDirectory), logger); - } - else if (Directory.Exists(inputFileName)) - { - inputFileName = Path.GetFullPath(inputFileName) + Path.DirectorySeparatorChar; - - foreach (string file in Directory.EnumerateFiles(inputFileName, "*", SearchOption.AllDirectories)) + // If we're in cascade and diff, output only cascaded diffs + else if (diff && cascade) { - logger.User("Processing \"" + Path.GetFullPath(file).Remove(0, inputFileName.Length) + "\""); - Dat innerDatdata = (Dat)datdata.Clone(); - innerDatdata.Roms = null; - innerDatdata = Parse(file, 0, 0, innerDatdata, logger, true, clean); - innerDatdata = Filter(innerDatdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, logger); - - // If the extension matches, append ".new" to the filename - string extension = (innerDatdata.OutputFormat == OutputFormat.Xml || innerDatdata.OutputFormat == OutputFormat.SabreDat ? ".xml" : ".dat"); - if (outputDirectory == "" && Path.GetExtension(file) == extension) - { - innerDatdata.FileName += ".new"; - } - - Output.WriteDatfile(innerDatdata, (outputDirectory == "" ? Path.GetDirectoryName(file) : outputDirectory + Path.GetDirectoryName(file).Remove(0, inputFileName.Length - 1)), logger); + DiffCascade(outputDirectory, inplace, userData, inputFileNames, datHeaders, logger); + } + // Output all entries with user-defined merge + else + { + MergeNoDiff(outputDirectory, userData, inputFileNames, datHeaders, logger); } } + // Otherwise, loop through all of the inputs individually else { - logger.Error("I'm sorry but " + inputFileName + " doesn't exist!"); + for (int i = 0; i < inputFileNames.Count; i++) + { + string inputFileName = inputFileNames[i]; + + // Clean the input string + if (inputFileName != "") + { + inputFileName = Path.GetFullPath(inputFileName); + } + + if (File.Exists(inputFileName)) + { + logger.User("Processing \"" + Path.GetFileName(inputFileName) + "\""); + datdata = Parse(inputFileName, 0, 0, datdata, logger, true, clean); + datdata = Filter(datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, logger); + + // If the extension matches, append ".new" to the filename + string extension = (datdata.OutputFormat == OutputFormat.Xml || datdata.OutputFormat == OutputFormat.SabreDat ? ".xml" : ".dat"); + if (outputDirectory == "" && Path.GetExtension(inputFileName) == extension) + { + datdata.FileName += ".new"; + } + + Output.WriteDatfile(datdata, (outputDirectory == "" ? Path.GetDirectoryName(inputFileName) : outputDirectory), logger); + } + else if (Directory.Exists(inputFileName)) + { + inputFileName = Path.GetFullPath(inputFileName) + Path.DirectorySeparatorChar; + + foreach (string file in Directory.EnumerateFiles(inputFileName, "*", SearchOption.AllDirectories)) + { + logger.User("Processing \"" + Path.GetFullPath(file).Remove(0, inputFileName.Length) + "\""); + Dat innerDatdata = (Dat)datdata.Clone(); + innerDatdata.Roms = null; + innerDatdata = Parse(file, 0, 0, innerDatdata, logger, true, clean); + innerDatdata = Filter(innerDatdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, logger); + + // If the extension matches, append ".new" to the filename + string extension = (innerDatdata.OutputFormat == OutputFormat.Xml || innerDatdata.OutputFormat == OutputFormat.SabreDat ? ".xml" : ".dat"); + if (outputDirectory == "" && Path.GetExtension(file) == extension) + { + innerDatdata.FileName += ".new"; + } + + Output.WriteDatfile(innerDatdata, (outputDirectory == "" ? Path.GetDirectoryName(file) : outputDirectory + Path.GetDirectoryName(file).Remove(0, inputFileName.Length - 1)), logger); + } + } + else + { + logger.Error("I'm sorry but " + inputFileName + " doesn't exist!"); + } + } } return; } + /// + /// Populate the user DatData object from the input files + /// + /// Output user DatData object to output + /// List of DatData objects representing headers + private static List PopulateUserData(List inputs, bool inplace, bool clean, string outdir, Dat inputDat, out Dat userData, Logger logger) + { + List datHeaders = new List(); + + int i = 0; + userData = new Dat + { + Roms = new Dictionary>(), + MergeRoms = inputDat.MergeRoms, + }; + foreach (string input in inputs) + { + logger.User("Adding DAT: " + input.Split('¬')[0]); + userData = DatTools.Parse(input.Split('¬')[0], i, 0, userData, logger, true, clean); + i++; + + // If we are in inplace mode or redirecting output, save the DAT data + if (inplace || !String.IsNullOrEmpty(outdir)) + { + datHeaders.Add((Dat)userData.CloneHeader()); + + // Reset the header values so the next can be captured + userData.FileName = ""; + userData.Name = ""; + userData.Description = ""; + userData.Version = ""; + userData.Date = ""; + userData.Category = ""; + userData.Author = ""; + userData.ForcePacking = ForcePacking.None; + userData.OutputFormat = OutputFormat.None; + userData.Type = ""; + } + } + + // Set the output values + userData = (Dat)inputDat.CloneHeader(); + + return datHeaders; + } + /// /// Filter an input DAT file /// @@ -1809,5 +1894,253 @@ namespace SabreTools.Helper return datdata; } + + /// + /// Output non-cascading diffs + /// + /// Main DatData to draw information from + public static void DiffNoCascade(string outdir, Dat userData, List inputs, Logger logger) + { + DateTime start = DateTime.Now; + logger.User("Initializing all output DATs"); + + // Don't have External dupes + string post = " (No Duplicates)"; + Dat outerDiffData = (Dat)userData.CloneHeader(); + outerDiffData.FileName += post; + outerDiffData.Name += post; + outerDiffData.Description += post; + + // Have External dupes + post = " (Duplicates)"; + Dat dupeData = (Dat)userData.CloneHeader(); + dupeData.FileName += post; + dupeData.Name += post; + dupeData.Description += post; + + // Create a list of DatData objects representing individual output files + List outDats = new List(); + + // Loop through each of the inputs and get or create a new DatData object + for (int j = 0; j < inputs.Count; j++) + { + post = " (" + Path.GetFileNameWithoutExtension(inputs[j].Split('¬')[0]) + " Only)"; + Dat diffData = (Dat)userData.CloneHeader(); + diffData.FileName += post; + diffData.Name += post; + diffData.Description += post; + outDats.Add(diffData); + } + logger.User("Initializing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); + + // Now, loop through the dictionary and populate the correct DATs + start = DateTime.Now; + logger.User("Populating all output DATs"); + List keys = userData.Roms.Keys.ToList(); + foreach (string key in keys) + { + List roms = RomTools.Merge(userData.Roms[key], logger); + + if (roms != null && roms.Count > 0) + { + foreach (Rom rom in roms) + { + // No duplicates + if (rom.Dupe < DupeType.ExternalHash) + { + // Individual DATs that are output + if (outDats[rom.Metadata.SystemID].Roms.ContainsKey(key)) + { + outDats[rom.Metadata.SystemID].Roms[key].Add(rom); + } + else + { + List tl = new List(); + tl.Add(rom); + outDats[rom.Metadata.SystemID].Roms.Add(key, tl); + } + + // Merged no-duplicates DAT + Rom newrom = rom; + newrom.Game += " (" + Path.GetFileNameWithoutExtension(inputs[newrom.Metadata.SystemID].Split('¬')[0]) + ")"; + + if (outerDiffData.Roms.ContainsKey(key)) + { + outerDiffData.Roms[key].Add(newrom); + } + else + { + List tl = new List(); + tl.Add(rom); + outerDiffData.Roms.Add(key, tl); + } + } + + // Duplicates only + if (rom.Dupe >= DupeType.ExternalHash) + { + Rom newrom = rom; + newrom.Game += " (" + Path.GetFileNameWithoutExtension(inputs[newrom.Metadata.SystemID].Split('¬')[0]) + ")"; + + if (dupeData.Roms.ContainsKey(key)) + { + dupeData.Roms[key].Add(newrom); + } + else + { + List tl = new List(); + tl.Add(rom); + dupeData.Roms.Add(key, tl); + } + } + } + } + } + logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); + + // Finally, loop through and output each of the DATs + start = DateTime.Now; + logger.User("Outputting all created DATs"); + + // Output the difflist (a-b)+(b-a) diff + Output.WriteDatfile(outerDiffData, outdir, logger); + + // Output the (ab) diff + Output.WriteDatfile(dupeData, outdir, logger); + + // Output the individual (a-b) DATs + for (int j = 0; j < inputs.Count; j++) + { + // If we have an output directory set, replace the path + string path = outdir + (Path.GetDirectoryName(inputs[j].Split('¬')[0]).Remove(0, inputs[j].Split('¬')[1].Length)); + + // If we have more than 0 roms, output + if (outDats[j].Roms.Count > 0) + { + Output.WriteDatfile(outDats[j], path, logger); + } + } + logger.User("Outputting complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); + } + + /// + /// Output cascading diffs + /// + /// Main DatData to draw information from + /// Dat headers used optionally + public static void DiffCascade(string outdir, bool inplace, Dat userData, List inputs, List datHeaders, Logger logger) + { + string post = ""; + + // Create a list of DatData objects representing output files + List outDats = new List(); + + // Loop through each of the inputs and get or create a new DatData object + DateTime start = DateTime.Now; + logger.User("Initializing all output DATs"); + for (int j = 0; j < inputs.Count; j++) + { + post = " (" + Path.GetFileNameWithoutExtension(inputs[j].Split('¬')[0]) + " Only)"; + Dat diffData; + + // If we're in inplace mode, take the appropriate DatData object already stored + if (inplace || !String.IsNullOrEmpty(outdir)) + { + diffData = datHeaders[j]; + } + else + { + diffData = (Dat)userData.CloneHeader(); + diffData.FileName += post; + diffData.Name += post; + diffData.Description += post; + } + outDats.Add(diffData); + } + logger.User("Initializing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); + + // Now, loop through the dictionary and populate the correct DATs + start = DateTime.Now; + logger.User("Populating all output DATs"); + List keys = userData.Roms.Keys.ToList(); + foreach (string key in keys) + { + List roms = RomTools.Merge(userData.Roms[key], logger); + + if (roms != null && roms.Count > 0) + { + foreach (Rom rom in roms) + { + if (outDats[rom.Metadata.SystemID].Roms.ContainsKey(key)) + { + outDats[rom.Metadata.SystemID].Roms[key].Add(rom); + } + else + { + List tl = new List(); + tl.Add(rom); + outDats[rom.Metadata.SystemID].Roms.Add(key, tl); + } + } + } + } + logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); + + // Finally, loop through and output each of the DATs + start = DateTime.Now; + logger.User("Outputting all created DATs"); + for (int j = 0; j < inputs.Count; j++) + { + // If we have an output directory set, replace the path + string path = ""; + if (inplace) + { + path = Path.GetDirectoryName(inputs[j].Split('¬')[0]); + } + else if (!String.IsNullOrEmpty(outdir)) + { + path = outdir + (Path.GetDirectoryName(inputs[j].Split('¬')[0]).Remove(0, inputs[j].Split('¬')[1].Length)); + } + + // If we have more than 0 roms, output + if (outDats[j].Roms.Count > 0) + { + Output.WriteDatfile(outDats[j], path, logger); + } + } + logger.User("Outputting complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); + } + + /// + /// Output user defined merge + /// + /// Main DatData to draw information from + /// Dat headers used optionally + public static void MergeNoDiff(string outdir, Dat userData, List inputs, List datHeaders, Logger logger) + { + // If we're in SuperDAT mode, prefix all games with their respective DATs + if (userData.Type == "SuperDAT") + { + List keys = userData.Roms.Keys.ToList(); + foreach (string key in keys) + { + List newroms = new List(); + foreach (Rom rom in userData.Roms[key]) + { + Rom newrom = rom; + string filename = inputs[newrom.Metadata.SystemID].Split('¬')[0]; + string rootpath = inputs[newrom.Metadata.SystemID].Split('¬')[1]; + + rootpath += (rootpath == "" ? "" : Path.DirectorySeparatorChar.ToString()); + filename = filename.Remove(0, rootpath.Length); + newrom.Game = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename), newrom.Game); + newroms.Add(newrom); + } + userData.Roms[key] = newroms; + } + } + + Output.WriteDatfile(userData, outdir, logger); + } } } diff --git a/SabreTools/MergeDiff.cs b/SabreTools/MergeDiff.cs deleted file mode 100644 index 8c3b93be..00000000 --- a/SabreTools/MergeDiff.cs +++ /dev/null @@ -1,442 +0,0 @@ -using SabreTools.Helper; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace SabreTools -{ - public class MergeDiff - { - // Listing related variables - private List _inputs; - - // User specified flags - private bool _diff; - private bool _dedup; - private bool _bare; - private bool _forceunpack; - private bool _old; - private bool _superdat; - private bool _cascade; - private bool _inplace; - private bool _clean; - - // User specified strings - private string _name; - private string _desc; - private string _cat; - private string _version; - private string _author; - private string _outdir; - - // Other required variables - private string _date = DateTime.Now.ToString("yyyy-MM-dd"); - private Logger _logger; - - /// - /// Create a new MergeDAT object - /// - /// A List of Strings representing the DATs or DAT folders to be merged - /// Internal name of the DAT - /// Description and external name of the DAT - /// Category for the DAT - /// Version of the DAT - /// Author of the DAT - /// True if all diff variants should be outputted, false otherwise - /// True if a DiffDat of all inputs is wanted, false otherwise - /// True if the outputted file should remove duplicates, false otherwise - /// True if the date should be omitted from the DAT, false otherwise - /// True if the forcepacking="unzip" tag is to be added, false otherwise - /// True if a old-style DAT should be output, false otherwise - /// True if DATs should be parsed into SuperDAT format, false otherwise - /// True if the outputted diffs should be cascaded, false otherwise - /// True if cascaded diffs overwrite the source files, false otherwise - /// New output directory for outputted DATs (blank means default) - /// True to clean the game names to WoD standard, false otherwise (default) - /// Logger object for console and file output - public MergeDiff(List inputs, string name, string desc, string cat, string version, string author, - bool diff, bool dedup, bool bare, bool forceunpack, bool old, bool superdat, bool cascade, bool inplace, - string outdir, bool clean, Logger logger) - { - _inputs = inputs; - _name = name; - _desc = desc; - _cat = cat; - _version = version; - _author = author; - _diff = diff; - _dedup = dedup; - _bare = bare; - _forceunpack = forceunpack; - _old = old; - _superdat = superdat; - _cascade = cascade; - _inplace = inplace; - _outdir = outdir; - _clean = clean; - _logger = logger; - } - - /// - /// Combine DATs, optionally diffing and deduping them - /// - /// True if the DATs merged correctly, false otherwise - public bool Process() - { - // Check if there are enough inputs - if (_inputs.Count < 1) - { - _logger.Warning("At least 1 input is required!"); - return false; - } - - // Get the values that will be used - if (_name == "") - { - _name = (_diff ? "DiffDAT" : "MergeDAT") + (_superdat ? "-SuperDAT" : "") + (_dedup ? "-deduped" : ""); - } - if (_desc == "") - { - _desc = (_diff ? "DiffDAT" : "MergeDAT") + (_superdat ? "-SuperDAT" : "") + (_dedup ? " - deduped" : ""); - if (!_bare) - { - _desc += " (" + _date + ")"; - } - } - if (_cat == "" && _diff) - { - _cat = "DiffDAT"; - } - if (_author == "") - { - _author = "SabreTools"; - } - - // Create a dictionary of all ROMs from the input DATs - Dat userData; - List datHeaders = PopulateUserData(out userData); - - // Modify the Dictionary if necessary and output the results - if (_diff && !_cascade) - { - DiffNoCascade(_outdir, userData, _inputs, _logger); - } - // If we're in cascade and diff, output only cascaded diffs - else if (_diff && _cascade) - { - DiffCascade(_outdir, _inplace, userData, _inputs, datHeaders, _logger); - } - // Output all entries with user-defined merge - else - { - MergeNoDiff(_outdir, userData, _inputs, datHeaders, _logger); - } - - return true; - } - - /// - /// Populate the user DatData object from the input files - /// - /// Output user DatData object to output - /// List of DatData objects representing headers - private List PopulateUserData(out Dat userData) - { - List datHeaders = new List(); - - int i = 0; - userData = new Dat - { - Roms = new Dictionary>(), - MergeRoms = _dedup, - }; - foreach (string input in _inputs) - { - _logger.User("Adding DAT: " + input.Split('¬')[0]); - userData = DatTools.Parse(input.Split('¬')[0], i, 0, userData, _logger, true, _clean); - i++; - - // If we are in inplace mode or redirecting output, save the DAT data - if (_inplace || !String.IsNullOrEmpty(_outdir)) - { - datHeaders.Add((Dat)userData.CloneHeader()); - - // Reset the header values so the next can be captured - userData.FileName = ""; - userData.Name = ""; - userData.Description = ""; - userData.Version = ""; - userData.Date = ""; - userData.Category = ""; - userData.Author = ""; - userData.ForcePacking = ForcePacking.None; - userData.OutputFormat = OutputFormat.None; - userData.Type = ""; - } - } - - // Set the output values - userData.FileName = _desc; - userData.Name = _name; - userData.Description = _desc; - userData.Version = _version; - userData.Date = _date; - userData.Category = _cat; - userData.Author = _author; - userData.ForcePacking = (_forceunpack ? ForcePacking.Unzip : ForcePacking.None); - userData.OutputFormat = (_old ? OutputFormat.ClrMamePro : OutputFormat.Xml); - userData.Type = (_superdat ? "SuperDAT" : ""); - - return datHeaders; - } - - /// - /// Output non-cascading diffs - /// - /// Main DatData to draw information from - public void DiffNoCascade(string outdir, Dat userData, List inputs, Logger logger) - { - DateTime start = DateTime.Now; - logger.User("Initializing all output DATs"); - - // Don't have External dupes - string post = " (No Duplicates)"; - Dat outerDiffData = (Dat)userData.CloneHeader(); - outerDiffData.FileName += post; - outerDiffData.Name += post; - outerDiffData.Description += post; - - // Have External dupes - post = " (Duplicates)"; - Dat dupeData = (Dat)userData.CloneHeader(); - dupeData.FileName += post; - dupeData.Name += post; - dupeData.Description += post; - - // Create a list of DatData objects representing individual output files - List outDats = new List(); - - // Loop through each of the inputs and get or create a new DatData object - for (int j = 0; j < inputs.Count; j++) - { - post = " (" + Path.GetFileNameWithoutExtension(inputs[j].Split('¬')[0]) + " Only)"; - Dat diffData = (Dat)userData.CloneHeader(); - diffData.FileName += post; - diffData.Name += post; - diffData.Description += post; - outDats.Add(diffData); - } - logger.User("Initializing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); - - // Now, loop through the dictionary and populate the correct DATs - start = DateTime.Now; - logger.User("Populating all output DATs"); - List keys = userData.Roms.Keys.ToList(); - foreach (string key in keys) - { - List roms = RomTools.Merge(userData.Roms[key], logger); - - if (roms != null && roms.Count > 0) - { - foreach (Rom rom in roms) - { - // No duplicates - if (rom.Dupe < DupeType.ExternalHash) - { - // Individual DATs that are output - if (outDats[rom.Metadata.SystemID].Roms.ContainsKey(key)) - { - outDats[rom.Metadata.SystemID].Roms[key].Add(rom); - } - else - { - List tl = new List(); - tl.Add(rom); - outDats[rom.Metadata.SystemID].Roms.Add(key, tl); - } - - // Merged no-duplicates DAT - Rom newrom = rom; - newrom.Game += " (" + Path.GetFileNameWithoutExtension(inputs[newrom.Metadata.SystemID].Split('¬')[0]) + ")"; - - if (outerDiffData.Roms.ContainsKey(key)) - { - outerDiffData.Roms[key].Add(newrom); - } - else - { - List tl = new List(); - tl.Add(rom); - outerDiffData.Roms.Add(key, tl); - } - } - - // Duplicates only - if (rom.Dupe >= DupeType.ExternalHash) - { - Rom newrom = rom; - newrom.Game += " (" + Path.GetFileNameWithoutExtension(inputs[newrom.Metadata.SystemID].Split('¬')[0]) + ")"; - - if (dupeData.Roms.ContainsKey(key)) - { - dupeData.Roms[key].Add(newrom); - } - else - { - List tl = new List(); - tl.Add(rom); - dupeData.Roms.Add(key, tl); - } - } - } - } - } - logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); - - // Finally, loop through and output each of the DATs - start = DateTime.Now; - logger.User("Outputting all created DATs"); - - // Output the difflist (a-b)+(b-a) diff - Output.WriteDatfile(outerDiffData, outdir, logger); - - // Output the (ab) diff - Output.WriteDatfile(dupeData, outdir, logger); - - // Output the individual (a-b) DATs - for (int j = 0; j < inputs.Count; j++) - { - // If we have an output directory set, replace the path - string path = outdir + (Path.GetDirectoryName(inputs[j].Split('¬')[0]).Remove(0, inputs[j].Split('¬')[1].Length)); - - // If we have more than 0 roms, output - if (outDats[j].Roms.Count > 0) - { - Output.WriteDatfile(outDats[j], path, logger); - } - } - logger.User("Outputting complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); - } - - /// - /// Output cascading diffs - /// - /// Main DatData to draw information from - /// Dat headers used optionally - private void DiffCascade(string outdir, bool inplace, Dat userData, List inputs, List datHeaders, Logger logger) - { - string post = ""; - - // Create a list of DatData objects representing output files - List outDats = new List(); - - // Loop through each of the inputs and get or create a new DatData object - DateTime start = DateTime.Now; - logger.User("Initializing all output DATs"); - for (int j = 0; j < inputs.Count; j++) - { - post = " (" + Path.GetFileNameWithoutExtension(inputs[j].Split('¬')[0]) + " Only)"; - Dat diffData; - - // If we're in inplace mode, take the appropriate DatData object already stored - if (inplace || !String.IsNullOrEmpty(outdir)) - { - diffData = datHeaders[j]; - } - else - { - diffData = (Dat)userData.CloneHeader(); - diffData.FileName += post; - diffData.Name += post; - diffData.Description += post; - } - outDats.Add(diffData); - } - logger.User("Initializing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); - - // Now, loop through the dictionary and populate the correct DATs - start = DateTime.Now; - logger.User("Populating all output DATs"); - List keys = userData.Roms.Keys.ToList(); - foreach (string key in keys) - { - List roms = RomTools.Merge(userData.Roms[key], logger); - - if (roms != null && roms.Count > 0) - { - foreach (Rom rom in roms) - { - if (outDats[rom.Metadata.SystemID].Roms.ContainsKey(key)) - { - outDats[rom.Metadata.SystemID].Roms[key].Add(rom); - } - else - { - List tl = new List(); - tl.Add(rom); - outDats[rom.Metadata.SystemID].Roms.Add(key, tl); - } - } - } - } - logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); - - // Finally, loop through and output each of the DATs - start = DateTime.Now; - logger.User("Outputting all created DATs"); - for (int j = 0; j < inputs.Count; j++) - { - // If we have an output directory set, replace the path - string path = ""; - if (inplace) - { - path = Path.GetDirectoryName(inputs[j].Split('¬')[0]); - } - else if (!String.IsNullOrEmpty(outdir)) - { - path = outdir + (Path.GetDirectoryName(inputs[j].Split('¬')[0]).Remove(0, inputs[j].Split('¬')[1].Length)); - } - - // If we have more than 0 roms, output - if (outDats[j].Roms.Count > 0) - { - Output.WriteDatfile(outDats[j], path, logger); - } - } - logger.User("Outputting complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); - } - - /// - /// Output user defined merge - /// - /// Main DatData to draw information from - /// Dat headers used optionally - private void MergeNoDiff(string outdir, Dat userData, List inputs, List datHeaders, Logger logger) - { - // If we're in SuperDAT mode, prefix all games with their respective DATs - if (userData.Type == "SuperDAT") - { - List keys = userData.Roms.Keys.ToList(); - foreach (string key in keys) - { - List newroms = new List(); - foreach (Rom rom in userData.Roms[key]) - { - Rom newrom = rom; - string filename = inputs[newrom.Metadata.SystemID].Split('¬')[0]; - string rootpath = inputs[newrom.Metadata.SystemID].Split('¬')[1]; - - rootpath += (rootpath == "" ? "" : Path.DirectorySeparatorChar.ToString()); - filename = filename.Remove(0, rootpath.Length); - newrom.Game = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename), newrom.Game); - newroms.Add(newrom); - } - userData.Roms[key] = newroms; - } - } - - Output.WriteDatfile(userData, outdir, logger); - } - } -} diff --git a/SabreTools/Partials/SabreTools_Inits.cs b/SabreTools/Partials/SabreTools_Inits.cs index 3805a232..53da1685 100644 --- a/SabreTools/Partials/SabreTools_Inits.cs +++ b/SabreTools/Partials/SabreTools_Inits.cs @@ -74,7 +74,7 @@ namespace SabreTools /// /// Wrap converting and updating DAT file from any format to any format /// - /// Input filename + /// List of input filenames /// /* Normal DAT header info */ /// New filename /// New name @@ -107,6 +107,12 @@ namespace SabreTools /// Add the dat name as a directory prefix /// Output files in romba format /// Output files in TSV format + /// /* Merging and Diffing info */ + /// True if input files should be merged into a single file, false otherwise + /// True if the input files should be diffed with each other, false otherwise + /// True if the diffed files should be cascade diffed, false otherwise + /// True if the cascade-diffed files should overwrite their inputs, false otherwise + /// True if the date should not be appended to the default name, false otherwise [OBSOLETE] /// /* Filtering info */ /// Name of the game to match (can use asterisk-partials) /// Name of the rom to match (can use asterisk-partials) @@ -122,7 +128,7 @@ namespace SabreTools /// Optional param for output directory /// True to clean the game names to WoD standard, false otherwise (default) /// True to dedupe the roms in the DAT, false otherwise (default) - private static void InitUpdate(string input, + private static void InitUpdate(List inputs, /* Normal DAT header info */ string filename, string name, @@ -157,6 +163,13 @@ namespace SabreTools bool romba, bool tsv, + /* Merging and Diffing info */ + bool merge, + bool diff, + bool cascade, + bool inplace, + bool bare, + /* Filtering info */ string gamename, string romname, @@ -227,6 +240,32 @@ namespace SabreTools addext = (addext == "" || addext.StartsWith(".") ? addext : "." + addext); repext = (repext == "" || repext.StartsWith(".") ? repext : "." + repext); + // If we're in merge or diff mode and the names aren't set, set defaults + if (merge || diff) + { + // Get the values that will be used + if (name == "") + { + name = (diff ? "DiffDAT" : "MergeDAT") + (superdat ? "-SuperDAT" : "") + (dedup ? "-deduped" : ""); + } + if (description == "") + { + description = (diff ? "DiffDAT" : "MergeDAT") + (superdat ? "-SuperDAT" : "") + (dedup ? " - deduped" : ""); + if (!bare) + { + description += " (" + date + ")"; + } + } + if (category == "" && diff) + { + category = "DiffDAT"; + } + if (author == "") + { + author = "SabreTools"; + } + } + // Populate the DatData object Dat userInputDat = new Dat { @@ -262,31 +301,37 @@ namespace SabreTools if (outputCMP) { userInputDat.OutputFormat = OutputFormat.ClrMamePro; - DatTools.Update(input, userInputDat, outdir, clean, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); + DatTools.Update(inputs, userInputDat, outdir, merge, diff, cascade, inplace, bare, clean, + gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); } - if (outputMiss || romba) + if (outputMiss) { userInputDat.OutputFormat = OutputFormat.MissFile; - DatTools.Update(input, userInputDat, outdir, clean, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); + DatTools.Update(inputs, userInputDat, outdir, merge, diff, cascade, inplace, bare, clean, + gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); } if (outputRC) { userInputDat.OutputFormat = OutputFormat.RomCenter; - DatTools.Update(input, userInputDat, outdir, clean, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); + DatTools.Update(inputs, userInputDat, outdir, merge, diff, cascade, inplace, bare, clean, + gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); } if (outputSD) { userInputDat.OutputFormat = OutputFormat.SabreDat; - DatTools.Update(input, userInputDat, outdir, clean, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); + DatTools.Update(inputs, userInputDat, outdir, merge, diff, cascade, inplace, bare, clean, + gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); } if (outputXML) { userInputDat.OutputFormat = OutputFormat.Xml; - DatTools.Update(input, userInputDat, outdir, clean, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); + DatTools.Update(inputs, userInputDat, outdir, merge, diff, cascade, inplace, bare, clean, + gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); } - if (!outputCMP && !(outputMiss || romba) && !outputRC && !outputSD && !outputXML) + if (!outputCMP && !outputMiss && !outputRC && !outputSD && !outputXML) { - DatTools.Update(input, userInputDat, outdir, clean, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); + DatTools.Update(inputs, userInputDat, outdir, merge, diff, cascade, inplace, bare, clean, + gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, _logger); } } @@ -372,71 +417,6 @@ namespace SabreTools } } - /// - /// Wrap merging, diffing, and deduping 2 or mor DATs - /// - /// A List of Strings representing the DATs or DAT folders to be merged - /// Internal name of the DAT - /// Description and external name of the DAT - /// Category for the DAT - /// Version of the DAT - /// Author of the DAT - /// True if a DiffDat of all inputs is wanted, false otherwise - /// True if the outputted file should remove duplicates, false otherwise - /// True if the date should be omitted from the DAT, false otherwise - /// True if the forcepacking="unzip" tag is to be added, false otherwise - /// True if a old-style DAT should be output, false otherwise - /// True if DATs should be merged in SuperDAT style, false otherwise - /// True if the outputted diffs should be cascaded, false otherwise - /// True if cascaded diffs overwrite the source files, false otherwise - /// Output directory for the files (blank is default) - /// True to clean the game names to WoD standard, false otherwise (default) - private static void InitMergeDiff(List inputs, string name, string desc, string cat, string version, string author, - bool diff, bool dedup, bool bare, bool forceunpack, bool old, bool superdat, bool cascade, bool inplace, string outdir = "", bool clean = false) - { - // Make sure there are no folders in inputs - List newInputs = new List(); - foreach (string input in inputs) - { - if (Directory.Exists(input)) - { - foreach (string file in Directory.EnumerateFiles(input, "*", SearchOption.AllDirectories)) - { - try - { - newInputs.Add(Path.GetFullPath(file) + "¬" + Path.GetFullPath(input)); - } - catch (PathTooLongException) - { - _logger.Warning("The path for " + file + " was too long"); - } - catch (Exception ex) - { - _logger.Error(ex.ToString()); - } - } - } - else if (File.Exists(input)) - { - try - { - newInputs.Add(Path.GetFullPath(input) + "¬" + Path.GetDirectoryName(Path.GetFullPath(input))); - } - catch (PathTooLongException) - { - _logger.Warning("The path for " + input + " was too long"); - } - catch (Exception ex) - { - _logger.Error(ex.ToString()); - } - } - } - - MergeDiff md = new MergeDiff(newInputs, name, desc, cat, version, author, diff, dedup, bare, forceunpack, old, superdat, cascade, inplace, outdir, clean, _logger); - md.Process(); - } - /// /// Wrap splitting a DAT by 2 extensions /// diff --git a/SabreTools/SabreTools.cs b/SabreTools/SabreTools.cs index 6f9b90ee..079a5e60 100644 --- a/SabreTools/SabreTools.cs +++ b/SabreTools/SabreTools.cs @@ -638,16 +638,13 @@ namespace SabreTools ListSystems(); } - // Convert, update, and filter a DAT or folder of DATs - else if (update || outputCMP || outputMiss || outputRC || outputSD || outputXML) + // Convert, update, merge, diff, and filter a DAT or folder of DATs + else if (update || outputCMP || outputMiss || outputRC || outputSD || outputXML || merge || diff) { - foreach (string input in inputs) - { - InitUpdate(input, filename, name, description, category, version, date, author, email, homepage, url, comment, header, - superdat, forcemerge, forcend, forcepack, outputCMP, outputMiss, outputRC, outputSD, outputXML, usegame, prefix, - postfix, quotes, repext, addext, datprefix, romba, tsv, gamename, romname, romtype, sgt, slt, seq, crc, md5, - sha1, nodump, outdir, clean, dedup); - } + InitUpdate(inputs, filename, name, description, category, version, date, author, email, homepage, url, comment, header, + superdat, forcemerge, forcend, forcepack, outputCMP, outputMiss, outputRC, outputSD, outputXML, usegame, prefix, + postfix, quotes, repext, addext, datprefix, romba, tsv, merge, diff, cascade, inplace, bare, gamename, romname, + romtype, sgt, slt, seq, crc, md5, sha1, nodump, outdir, clean, dedup); } // Add a source or system @@ -699,12 +696,6 @@ namespace SabreTools InitExtSplit(inputs, exta, extb, outdir); } - // Merge, diff, and dedupe at least 2 DATs - else if (merge || diff) - { - InitMergeDiff(inputs, name, description, category, version, author, diff, dedup, bare, forceunpack, old, superdat, cascade, inplace, outdir, clean); - } - // Split a DAT by available hashes else if (hashsplit) { diff --git a/SabreTools/SabreTools.csproj b/SabreTools/SabreTools.csproj index 2909e81d..f9208af4 100644 --- a/SabreTools/SabreTools.csproj +++ b/SabreTools/SabreTools.csproj @@ -106,7 +106,6 @@ -