using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using SabreTools.Helper; namespace SabreTools { public class OfflineMerge { // Instance variables private string _currentAllMerged; private string _currentMissingMerged; private string _currentNewMerged; private bool _fake; private Logger _logger; // Static required variables private static long sizezero = 0; private static string crczero = "00000000"; private static string md5zero = "d41d8cd98f00b204e9800998ecf8427e"; private static string sha1zero = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; /// /// Instantiate an OfflineMerge object /// /// Old-current DAT with merged and deduped values /// Old-current missing DAT with merged and deduped values /// New-current DAT with merged and deduped values /// True if all values should be replaced with default 0-byte values, false otherwise /// Logger object for console and file output public OfflineMerge (string currentAllMerged, string currentMissingMerged, string currentNewMerged, bool fake, Logger logger) { _currentAllMerged = currentAllMerged.Replace("\"", ""); _currentMissingMerged = currentMissingMerged.Replace("\"", ""); _currentNewMerged = currentNewMerged; _fake = fake; _logger = logger; } public static void Main(string[] args) { // Perform initial setup and verification Logger logger = new Logger(false, "database.log"); logger.Start(); Console.Clear(); // Credits take precidence over all if ((new List(args)).Contains("--credits")) { Build.Credits(); logger.Close(); return; } // If there's no arguments, show the help if (args.Length == 0) { Build.Help(); logger.Close(); return; } // Set all default values bool help = false, fake = false; string currentAllMerged = "", currentMissingMerged = "", currentNewMerged = ""; // Determine which switches are enabled (with values if necessary) foreach (string arg in args) { switch (arg) { case "-?": case "-h": case "--help": help = true; break; case "-f": case "--fake": fake = true; break; default: if (File.Exists(arg.Replace("\"", ""))) { logger.Log("File found: " + arg); if (currentAllMerged == "") { currentAllMerged = arg.Replace("\"", ""); } else if (currentMissingMerged == "") { currentMissingMerged = arg.Replace("\"", ""); } else if (currentNewMerged == "") { currentNewMerged = arg.Replace("\"", ""); } else { logger.Warning("Only 3 input files are required; ignoring " + arg); } } else if (Directory.Exists(arg.Replace("\"", ""))) { logger.Log("Directory found: " + arg); foreach (string file in Directory.GetFiles(arg.Replace("\"", ""), "*", SearchOption.AllDirectories)) { if (currentAllMerged == "") { currentAllMerged = file.Replace("\"", ""); } else if (currentMissingMerged == "") { currentMissingMerged = file.Replace("\"", ""); } else if (currentNewMerged == "") { currentNewMerged = file.Replace("\"", ""); } else { logger.Warning("Only 3 input files are required; ignoring " + arg); } } } else { logger.Warning("Invalid input detected: " + arg); Console.WriteLine(); Build.Help(); logger.Close(); return; } break; } } // If help is set or any of the inputs are empty, show help if (help || currentAllMerged == "" || currentMissingMerged == "" || currentNewMerged == "") { Build.Help(); logger.Close(); return; } // Otherwise, run the program OfflineMerge om = new OfflineMerge(currentAllMerged, currentMissingMerged, currentNewMerged, fake, logger); om.Process(); } /// /// Process the supplied inputs and create the three required outputs: /// (a) Net New - (currentNewMerged)-(currentAllMerged) /// (b) Unneeded - (currentAllMerged)-(currentNewMerged) /// (c) New Missing - (a)+(currentMissingMerged-(b)) /// /// True if the files were created properly, false otherwise public bool Process() { // First get the combination Dictionary of currentAllMerged and currentNewMerged _logger.Log("Adding Current and New Merged DATs to the dictionary"); Dictionary> completeDats = new Dictionary>(); completeDats = RomManipulation.ParseDict(_currentAllMerged, 0, 0, completeDats, _logger); completeDats = RomManipulation.ParseDict(_currentNewMerged, 0, 0, completeDats, _logger); // Now get Net New output dictionary _logger.Log("Creating and populating Net New dictionary"); Dictionary> netNew = new Dictionary>(); foreach (string key in completeDats.Keys) { if (completeDats[key].Count == 1) { if (completeDats[key][0].System == _currentNewMerged) { if (netNew.ContainsKey(key)) { netNew[key].Add(completeDats[key][0]); } else { List temp = new List(); temp.Add(completeDats[key][0]); netNew.Add(key, temp); } } } } // Now create the Unneeded dictionary _logger.Log("Creating and populating Uneeded dictionary"); Dictionary> unneeded = new Dictionary>(); foreach (string key in completeDats.Keys) { if (completeDats[key].Count == 1) { if (completeDats[key][0].System == _currentAllMerged) { if (netNew.ContainsKey(key)) { netNew[key].Add(completeDats[key][0]); } else { List temp = new List(); temp.Add(completeDats[key][0]); netNew.Add(key, temp); } } } } // Now create the New Missing dictionary _logger.Log("Creating and populating New Missing dictionary"); Dictionary> midMissing = new Dictionary>(); midMissing = RomManipulation.ParseDict(_currentMissingMerged, 0, 0, midMissing, _logger); foreach (string key in unneeded.Keys) { if (midMissing.ContainsKey(key)) { midMissing[key].AddRange(unneeded[key]); } else { midMissing.Add(key, unneeded[key]); } } Dictionary> newMissing = new Dictionary>(); foreach (string key in midMissing.Keys) { if (midMissing[key].Count == 1) { if (midMissing[key][0].System == _currentMissingMerged) { if (newMissing.ContainsKey(key)) { newMissing[key].Add(midMissing[key][0]); } else { List temp = new List(); temp.Add(midMissing[key][0]); newMissing.Add(key, temp); } } } } foreach (string key in netNew.Keys) { if (newMissing.ContainsKey(key)) { newMissing[key].AddRange(netNew[key]); } else { newMissing.Add(key, netNew[key]); } } // If we are supposed to replace everything in the output with default values, do so if (_fake) { _logger.Log("Replacing all hashes in Net New with 0-byte values"); List keys = netNew.Keys.ToList(); foreach (string key in keys) { List temp = new List(); List roms = netNew[key]; for (int i = 0; i < roms.Count; i++) { RomData rom = roms[i]; rom.Size = sizezero; rom.CRC = crczero; rom.MD5 = md5zero; rom.SHA1 = sha1zero; temp.Add(rom); } netNew[key] = temp; } _logger.Log("Replacing all hashes in Unneeded with 0-byte values"); keys = unneeded.Keys.ToList(); foreach (string key in keys) { List temp = new List(); List roms = unneeded[key]; for (int i = 0; i < roms.Count; i++) { RomData rom = roms[i]; rom.Size = sizezero; rom.CRC = crczero; rom.MD5 = md5zero; rom.SHA1 = sha1zero; temp.Add(rom); } unneeded[key] = temp; } _logger.Log("Replacing all hashes in New Missing with 0-byte values"); keys = newMissing.Keys.ToList(); foreach (string key in keys) { List temp = new List(); List roms = newMissing[key]; for (int i = 0; i < roms.Count; i++) { RomData rom = roms[i]; rom.Size = sizezero; rom.CRC = crczero; rom.MD5 = md5zero; rom.SHA1 = sha1zero; temp.Add(rom); } newMissing[key] = temp; } } // Finally, output all of the files Output.WriteToDatFromDict("Net New", "Net New", "", DateTime.Now.ToString("yyyy-MM-dd"), "", "SabreTools", false, false, true, "", netNew, _logger); Output.WriteToDatFromDict("Unneeded", "Unneeded", "", DateTime.Now.ToString("yyyy-MM-dd"), "", "SabreTools", false, false, true, "", unneeded, _logger); Output.WriteToDatFromDict("New Missing", "New Missing", "", DateTime.Now.ToString("yyyy-MM-dd"), "", "SabreTools", false, false, true, "", newMissing, _logger); return true; } } }