diff --git a/RombaSharp/Features/Dir2Dat.cs b/RombaSharp/Features/Dir2Dat.cs index ee9e0d03..d28ecf85 100644 --- a/RombaSharp/Features/Dir2Dat.cs +++ b/RombaSharp/Features/Dir2Dat.cs @@ -54,7 +54,7 @@ namespace RombaSharp.Features datfile.Header.Name = string.IsNullOrWhiteSpace(name) ? "untitled" : name; datfile.Header.Description = description; DatTool.PopulateFromDir(datfile, source, asFiles: TreatAsFile.NonArchive); - datfile.ApplyCleaning(new Cleaner() { ExcludeFields = Hash.DeepHashes.AsFields() }); + DatTool.ApplyCleaning(datfile, new Cleaner() { ExcludeFields = Hash.DeepHashes.AsFields() }); DatTool.Write(datfile, outdat); } } diff --git a/SabreTools.DatFiles/DatFile.Filtering.cs b/SabreTools.DatFiles/DatTool.Filtering.cs similarity index 69% rename from SabreTools.DatFiles/DatFile.Filtering.cs rename to SabreTools.DatFiles/DatTool.Filtering.cs index 26832339..42652f08 100644 --- a/SabreTools.DatFiles/DatFile.Filtering.cs +++ b/SabreTools.DatFiles/DatTool.Filtering.cs @@ -14,53 +14,54 @@ using SabreTools.IO; // This file represents all methods related to the Filtering namespace namespace SabreTools.DatFiles { - public abstract partial class DatFile + public partial class DatTool { /// /// Apply cleaning methods to the DatFile /// + /// Current DatFile object to run operations on /// Cleaner to use /// True if the error that is thrown should be thrown back to the caller, false otherwise /// True if cleaning was successful, false on error - public bool ApplyCleaning(Cleaner cleaner, bool throwOnError = false) + public static bool ApplyCleaning(DatFile datFile, Cleaner cleaner, bool throwOnError = false) { try { // Perform item-level cleaning - CleanDatItems(cleaner); + CleanDatItems(datFile, cleaner); // Bucket and dedupe according to the flag if (cleaner?.DedupeRoms == DedupeType.Full) - Items.BucketBy(Field.DatItem_CRC, cleaner.DedupeRoms); + datFile.Items.BucketBy(Field.DatItem_CRC, cleaner.DedupeRoms); else if (cleaner?.DedupeRoms == DedupeType.Game) - Items.BucketBy(Field.Machine_Name, cleaner.DedupeRoms); + datFile.Items.BucketBy(Field.Machine_Name, cleaner.DedupeRoms); // Process description to machine name if (cleaner?.DescriptionAsName == true) - MachineDescriptionToName(); + MachineDescriptionToName(datFile); // If we are removing scene dates, do that now if (cleaner?.SceneDateStrip == true) - StripSceneDatesFromItems(); + StripSceneDatesFromItems(datFile); // Run the one rom per game logic, if required if (cleaner?.OneGamePerRegion == true) - OneGamePerRegion(cleaner.RegionList); + OneGamePerRegion(datFile, cleaner.RegionList); // Run the one rom per game logic, if required if (cleaner?.OneRomPerGame == true) - OneRomPerGame(); + OneRomPerGame(datFile); // If we are removing fields, do that now if (cleaner.ExcludeFields != null && cleaner.ExcludeFields.Any()) - RemoveFieldsFromItems(cleaner.ExcludeFields); + RemoveFieldsFromItems(datFile, cleaner.ExcludeFields); // Remove all marked items - Items.ClearMarked(); + datFile.Items.ClearMarked(); // We remove any blanks, if we aren't supposed to have any if (cleaner?.KeepEmptyGames == false) - Items.ClearEmpty(); + datFile.Items.ClearEmpty(); } catch (Exception ex) { @@ -75,15 +76,16 @@ namespace SabreTools.DatFiles /// /// Apply a set of Extra INIs on the DatFile /// + /// Current DatFile object to run operations on /// ExtrasIni to use /// True if the error that is thrown should be thrown back to the caller, false otherwise /// True if the extras were applied, false on error - public bool ApplyExtras(ExtraIni extras, bool throwOnError = false) + public static bool ApplyExtras(DatFile datFile, ExtraIni extras, bool throwOnError = false) { try { // Bucket by game first - Items.BucketBy(Field.Machine_Name, DedupeType.None); + datFile.Items.BucketBy(Field.Machine_Name, DedupeType.None); // Create a new set of mappings based on the items var map = new Dictionary>(); @@ -111,10 +113,10 @@ namespace SabreTools.DatFiles foreach (string key in map.Keys) { // If the key doesn't exist, continue - if (!Items.ContainsKey(key)) + if (!datFile.Items.ContainsKey(key)) continue; - List datItems = Items[key]; + List datItems = datFile.Items[key]; var mappings = map[key]; foreach (var datItem in datItems) @@ -136,11 +138,12 @@ namespace SabreTools.DatFiles /// /// Apply a Filter on the DatFile /// + /// Current DatFile object to run operations on /// Filter to use /// True if entire machines are considered, false otherwise (default) /// True if the error that is thrown should be thrown back to the caller, false otherwise /// True if the DatFile was filtered, false on error - public bool ApplyFilter(Filter filter, bool perMachine = false, bool throwOnError = false) + public static bool ApplyFilter(DatFile datFile, Filter filter, bool perMachine = false, bool throwOnError = false) { // If we have a null filter, return false if (filter == null) @@ -148,17 +151,17 @@ namespace SabreTools.DatFiles // If we're filtering per machine, bucket by machine first if (perMachine) - Items.BucketBy(Field.Machine_Name, DedupeType.None); + datFile.Items.BucketBy(Field.Machine_Name, DedupeType.None); try { // Loop over every key in the dictionary - List keys = Items.Keys.ToList(); + List keys = datFile.Items.Keys.ToList(); foreach (string key in keys) { // For every item in the current key bool machinePass = true; - List items = Items[key]; + List items = datFile.Items[key]; foreach (DatItem item in items) { // If we have a null item, we can't pass it @@ -193,7 +196,7 @@ namespace SabreTools.DatFiles } // Assign back for caution - Items[key] = items; + datFile.Items[key] = items; } } catch (Exception ex) @@ -209,17 +212,18 @@ namespace SabreTools.DatFiles /// /// Apply splitting on the DatFile /// + /// Current DatFile object to run operations on /// Split type to try /// True if DatFile tags override splitting, false otherwise /// True if the error that is thrown should be thrown back to the caller, false otherwise /// True if the DatFile was split, false on error - public bool ApplySplitting(MergingFlag splitType, bool useTags, bool throwOnError = false) + public static bool ApplySplitting(DatFile datFile, MergingFlag splitType, bool useTags, bool throwOnError = false) { try { // If we are using tags from the DAT, set the proper input for split type unless overridden if (useTags && splitType == MergingFlag.None) - splitType = Header.ForceMerging; + splitType = datFile.Header.ForceMerging; // Run internal splitting switch (splitType) @@ -228,19 +232,19 @@ namespace SabreTools.DatFiles // No-op break; case MergingFlag.Device: - CreateDeviceNonMergedSets(DedupeType.None); + CreateDeviceNonMergedSets(datFile, DedupeType.None); break; case MergingFlag.Full: - CreateFullyNonMergedSets(DedupeType.None); + CreateFullyNonMergedSets(datFile, DedupeType.None); break; case MergingFlag.NonMerged: - CreateNonMergedSets(DedupeType.None); + CreateNonMergedSets(datFile, DedupeType.None); break; case MergingFlag.Merged: - CreateMergedSets(DedupeType.None); + CreateMergedSets(datFile, DedupeType.None); break; case MergingFlag.Split: - CreateSplitSets(DedupeType.None); + CreateSplitSets(datFile, DedupeType.None); break; } } @@ -257,13 +261,14 @@ namespace SabreTools.DatFiles /// /// Apply SuperDAT naming logic to a merged DatFile /// + /// Current DatFile object to run operations on /// List of inputs to use for renaming - public void ApplySuperDAT(List inputs) + public static void ApplySuperDAT(DatFile datFile, List inputs) { - List keys = Items.Keys.ToList(); + List keys = datFile.Items.Keys.ToList(); Parallel.ForEach(keys, Globals.ParallelOptions, key => { - List items = Items[key].ToList(); + List items = datFile.Items[key].ToList(); List newItems = new List(); foreach (DatItem item in items) { @@ -282,50 +287,25 @@ namespace SabreTools.DatFiles newItems.Add(newItem); } - Items.Remove(key); - Items.AddRange(key, newItems); + datFile.Items.Remove(key); + datFile.Items.AddRange(key, newItems); }); } - /// - /// Clean individual items based on the current filter - /// - /// Cleaner to use - public void CleanDatItems(Cleaner cleaner) - { - List keys = Items.Keys.ToList(); - foreach (string key in keys) - { - // For every item in the current key - List items = Items[key]; - foreach (DatItem item in items) - { - // If we have a null item, we can't clean it it - if (item == null) - continue; - - // Run cleaning per item - item.Clean(cleaner); - } - - // Assign back for caution - Items[key] = items; - } - } - /// /// Use game descriptions as names in the DAT, updating cloneof/romof/sampleof /// + /// Current DatFile object to run operations on /// True if the error that is thrown should be thrown back to the caller, false otherwise - public void MachineDescriptionToName(bool throwOnError = false) + public static void MachineDescriptionToName(DatFile datFile, bool throwOnError = false) { try { // First we want to get a mapping for all games to description ConcurrentDictionary mapping = new ConcurrentDictionary(); - Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key => { - List items = Items[key]; + List items = datFile.Items[key]; foreach (DatItem item in items) { // If the key mapping doesn't exist, add it @@ -334,9 +314,9 @@ namespace SabreTools.DatFiles }); // Now we loop through every item and update accordingly - Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key => { - List items = Items[key]; + List items = datFile.Items[key]; List newItems = new List(); foreach (DatItem item in items) { @@ -361,8 +341,8 @@ namespace SabreTools.DatFiles } // Replace the old list of roms with the new one - Items.Remove(key); - Items.AddRange(key, newItems); + datFile.Items.Remove(key); + datFile.Items.AddRange(key, newItems); }); } catch (Exception ex) @@ -375,6 +355,7 @@ namespace SabreTools.DatFiles /// /// Filter a DAT using 1G1R logic given an ordered set of regions /// + /// Current DatFile object to run operations on /// Ordered list of regions to use /// /// In the most technical sense, the way that the region list is being used does not @@ -386,20 +367,20 @@ namespace SabreTools.DatFiles /// to clone sets based on name, nor does it have the ability to match on the /// Release DatItem type. /// - public void OneGamePerRegion(List regions) + public static void OneGamePerRegion(DatFile datFile, List regions) { // If we have null region list, make it empty if (regions == null) regions = new List(); // For sake of ease, the first thing we want to do is bucket by game - Items.BucketBy(Field.Machine_Name, DedupeType.None, norename: true); + datFile.Items.BucketBy(Field.Machine_Name, DedupeType.None, norename: true); // Then we want to get a mapping of all machines to parents Dictionary> parents = new Dictionary>(); - foreach (string key in Items.Keys) + foreach (string key in datFile.Items.Keys) { - DatItem item = Items[key][0]; + DatItem item = datFile.Items[key][0]; // Match on CloneOf first if (!string.IsNullOrEmpty(item.Machine.CloneOf)) @@ -449,25 +430,26 @@ namespace SabreTools.DatFiles parents[key].Remove(machine); // Remove the rest of the items from this key - parents[key].ForEach(k => Items.Remove(k)); + parents[key].ForEach(k => datFile.Items.Remove(k)); } // Finally, strip out the parent tags - RemoveTagsFromChild(); + RemoveTagsFromChild(datFile); } /// /// Ensure that all roms are in their own game (or at least try to ensure) /// - public void OneRomPerGame() + /// Current DatFile object to run operations on + public static void OneRomPerGame(DatFile datFile) { // Because this introduces subfolders, we need to set the SuperDAT type - Header.Type = "SuperDAT"; + datFile.Header.Type = "SuperDAT"; // For each rom, we want to update the game to be "/" - Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key => { - List items = Items[key]; + List items = datFile.Items[key]; for (int i = 0; i < items.Count; i++) { items[i].SetOneRomPerGame(); @@ -478,8 +460,9 @@ namespace SabreTools.DatFiles /// /// Remove fields as per the header /// + /// Current DatFile object to run operations on /// List of fields to use - public void RemoveFieldsFromItems(List fields) + public static void RemoveFieldsFromItems(DatFile datFile, List fields) { // If we have null field list, make it empty if (fields == null) @@ -489,23 +472,24 @@ namespace SabreTools.DatFiles logger.User("Removing filtered fields"); // Now process all of the roms - Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key => { - List items = Items[key]; + List items = datFile.Items[key]; for (int j = 0; j < items.Count; j++) { items[j].RemoveFields(fields); } - Items.Remove(key); - Items.AddRange(key, items); + datFile.Items.Remove(key); + datFile.Items.AddRange(key, items); }); } /// /// Strip the dates from the beginning of scene-style set names /// - public void StripSceneDatesFromItems() + /// Current DatFile object to run operations on + public static void StripSceneDatesFromItems(DatFile datFile) { // Output the logging statement logger.User("Stripping scene-style dates"); @@ -514,9 +498,9 @@ namespace SabreTools.DatFiles string pattern = @"([0-9]{2}\.[0-9]{2}\.[0-9]{2}-)(.*?-.*?)"; // Now process all of the roms - Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key => { - List items = Items[key]; + List items = datFile.Items[key]; for (int j = 0; j < items.Count; j++) { DatItem item = items[j]; @@ -529,11 +513,38 @@ namespace SabreTools.DatFiles items[j] = item; } - Items.Remove(key); - Items.AddRange(key, items); + datFile.Items.Remove(key); + datFile.Items.AddRange(key, items); }); } + /// + /// Clean individual items based on the current filter + /// + /// Current DatFile object to run operations on + /// Cleaner to use + private static void CleanDatItems(DatFile datFile, Cleaner cleaner) + { + List keys = datFile.Items.Keys.ToList(); + foreach (string key in keys) + { + // For every item in the current key + List items = datFile.Items[key]; + foreach (DatItem item in items) + { + // If we have a null item, we can't clean it it + if (item == null) + continue; + + // Run cleaning per item + item.Clean(cleaner); + } + + // Assign back for caution + datFile.Items[key] = items; + } + } + // TODO: Should any of these create a new DatFile in the process? // The reason this comes up is that doing any of the splits or merges // is an inherently destructive process. Making it output a new DatFile @@ -545,145 +556,151 @@ namespace SabreTools.DatFiles /// /// Use cdevice_ref tags to get full non-merged sets and remove parenting tags /// + /// Current DatFile object to run operations on /// Dedupe type to be used - private void CreateDeviceNonMergedSets(DedupeType mergeroms) + private static void CreateDeviceNonMergedSets(DatFile datFile, DedupeType mergeroms) { logger.User("Creating device non-merged sets from the DAT"); // For sake of ease, the first thing we want to do is bucket by game - Items.BucketBy(Field.Machine_Name, mergeroms, norename: true); + datFile.Items.BucketBy(Field.Machine_Name, mergeroms, norename: true); // Now we want to loop through all of the games and set the correct information - while (AddRomsFromDevices(false, false)) ; - while (AddRomsFromDevices(true, false)) ; + while (AddRomsFromDevices(datFile, false, false)) ; + while (AddRomsFromDevices(datFile, true, false)) ; // Then, remove the romof and cloneof tags so it's not picked up by the manager - RemoveTagsFromChild(); + RemoveTagsFromChild(datFile); } /// /// Use cloneof tags to create non-merged sets and remove the tags plus using the device_ref tags to get full sets /// + /// Current DatFile object to run operations on /// Dedupe type to be used - private void CreateFullyNonMergedSets(DedupeType mergeroms) + private static void CreateFullyNonMergedSets(DatFile datFile, DedupeType mergeroms) { logger.User("Creating fully non-merged sets from the DAT"); // For sake of ease, the first thing we want to do is bucket by game - Items.BucketBy(Field.Machine_Name, mergeroms, norename: true); + datFile.Items.BucketBy(Field.Machine_Name, mergeroms, norename: true); // Now we want to loop through all of the games and set the correct information - while (AddRomsFromDevices(true, true)) ; - AddRomsFromDevices(false, true); - AddRomsFromParent(); + while (AddRomsFromDevices(datFile, true, true)) ; + AddRomsFromDevices(datFile, false, true); + AddRomsFromParent(datFile); // Now that we have looped through the cloneof tags, we loop through the romof tags - AddRomsFromBios(); + AddRomsFromBios(datFile); // Then, remove the romof and cloneof tags so it's not picked up by the manager - RemoveTagsFromChild(); + RemoveTagsFromChild(datFile); } /// /// Use cloneof tags to create merged sets and remove the tags /// + /// Current DatFile object to run operations on /// Dedupe type to be used - private void CreateMergedSets(DedupeType mergeroms) + private static void CreateMergedSets(DatFile datFile, DedupeType mergeroms) { logger.User("Creating merged sets from the DAT"); // For sake of ease, the first thing we want to do is bucket by game - Items.BucketBy(Field.Machine_Name, mergeroms, norename: true); + datFile.Items.BucketBy(Field.Machine_Name, mergeroms, norename: true); // Now we want to loop through all of the games and set the correct information - AddRomsFromChildren(); + AddRomsFromChildren(datFile); // Now that we have looped through the cloneof tags, we loop through the romof tags - RemoveBiosRomsFromChild(false); - RemoveBiosRomsFromChild(true); + RemoveBiosRomsFromChild(datFile, false); + RemoveBiosRomsFromChild(datFile, true); // Finally, remove the romof and cloneof tags so it's not picked up by the manager - RemoveTagsFromChild(); + RemoveTagsFromChild(datFile); } /// /// Use cloneof tags to create non-merged sets and remove the tags /// + /// Current DatFile object to run operations on /// Dedupe type to be used - private void CreateNonMergedSets(DedupeType mergeroms) + private static void CreateNonMergedSets(DatFile datFile, DedupeType mergeroms) { logger.User("Creating non-merged sets from the DAT"); // For sake of ease, the first thing we want to do is bucket by game - Items.BucketBy(Field.Machine_Name, mergeroms, norename: true); + datFile.Items.BucketBy(Field.Machine_Name, mergeroms, norename: true); // Now we want to loop through all of the games and set the correct information - AddRomsFromParent(); + AddRomsFromParent(datFile); // Now that we have looped through the cloneof tags, we loop through the romof tags - RemoveBiosRomsFromChild(false); - RemoveBiosRomsFromChild(true); + RemoveBiosRomsFromChild(datFile, false); + RemoveBiosRomsFromChild(datFile, true); // Finally, remove the romof and cloneof tags so it's not picked up by the manager - RemoveTagsFromChild(); + RemoveTagsFromChild(datFile); } /// /// Use cloneof and romof tags to create split sets and remove the tags /// + /// Current DatFile object to run operations on /// Dedupe type to be used - private void CreateSplitSets(DedupeType mergeroms) + private static void CreateSplitSets(DatFile datFile, DedupeType mergeroms) { logger.User("Creating split sets from the DAT"); // For sake of ease, the first thing we want to do is bucket by game - Items.BucketBy(Field.Machine_Name, mergeroms, norename: true); + datFile.Items.BucketBy(Field.Machine_Name, mergeroms, norename: true); // Now we want to loop through all of the games and set the correct information - RemoveRomsFromChild(); + RemoveRomsFromChild(datFile); // Now that we have looped through the cloneof tags, we loop through the romof tags - RemoveBiosRomsFromChild(false); - RemoveBiosRomsFromChild(true); + RemoveBiosRomsFromChild(datFile, false); + RemoveBiosRomsFromChild(datFile, true); // Finally, remove the romof and cloneof tags so it's not picked up by the manager - RemoveTagsFromChild(); + RemoveTagsFromChild(datFile); } /// /// Use romof tags to add roms to the children /// - private void AddRomsFromBios() + /// Current DatFile object to run operations on + private static void AddRomsFromBios(DatFile datFile) { - List games = Items.Keys.OrderBy(g => g).ToList(); + List games = datFile.Items.Keys.OrderBy(g => g).ToList(); foreach (string game in games) { // If the game has no items in it, we want to continue - if (Items[game].Count == 0) + if (datFile.Items[game].Count == 0) continue; // Determine if the game has a parent or not string parent = null; - if (!string.IsNullOrWhiteSpace(Items[game][0].Machine.RomOf)) - parent = Items[game][0].Machine.RomOf; + if (!string.IsNullOrWhiteSpace(datFile.Items[game][0].Machine.RomOf)) + parent = datFile.Items[game][0].Machine.RomOf; // If the parent doesnt exist, we want to continue if (string.IsNullOrWhiteSpace(parent)) continue; // If the parent doesn't have any items, we want to continue - if (Items[parent].Count == 0) + if (datFile.Items[parent].Count == 0) continue; // If the parent exists and has items, we copy the items from the parent to the current game - DatItem copyFrom = Items[game][0]; - List parentItems = Items[parent]; + DatItem copyFrom = datFile.Items[game][0]; + List parentItems = datFile.Items[parent]; foreach (DatItem item in parentItems) { DatItem datItem = (DatItem)item.Clone(); datItem.CopyMachineInformation(copyFrom); - if (Items[game].Where(i => i.GetName() == datItem.GetName()).Count() == 0 && !Items[game].Contains(datItem)) - Items.Add(game, datItem); + if (datFile.Items[game].Where(i => i.GetName() == datItem.GetName()).Count() == 0 && !datFile.Items[game].Contains(datItem)) + datFile.Items.Add(game, datItem); } } } @@ -691,24 +708,25 @@ namespace SabreTools.DatFiles /// /// Use device_ref and optionally slotoption tags to add roms to the children /// + /// Current DatFile object to run operations on /// True if only child device sets are touched, false for non-device sets (default) /// True if slotoptions tags are used as well, false otherwise - private bool AddRomsFromDevices(bool dev = false, bool useSlotOptions = false) + private static bool AddRomsFromDevices(DatFile datFile, bool dev = false, bool useSlotOptions = false) { bool foundnew = false; - List machines = Items.Keys.OrderBy(g => g).ToList(); + List machines = datFile.Items.Keys.OrderBy(g => g).ToList(); foreach (string machine in machines) { // If the machine doesn't have items, we continue - if (Items[machine] == null || Items[machine].Count == 0) + if (datFile.Items[machine] == null || datFile.Items[machine].Count == 0) continue; // If the machine (is/is not) a device, we want to continue - if (dev ^ (Items[machine][0].Machine.MachineType.HasFlag(MachineType.Device))) + if (dev ^ (datFile.Items[machine][0].Machine.MachineType.HasFlag(MachineType.Device))) continue; // Get all device reference names from the current machine - List deviceReferences = Items[machine] + List deviceReferences = datFile.Items[machine] .Where(i => i.ItemType == ItemType.DeviceReference) .Select(i => i as DeviceReference) .Select(dr => dr.Name) @@ -716,7 +734,7 @@ namespace SabreTools.DatFiles .ToList(); // Get all slot option names from the current machine - List slotOptions = Items[machine] + List slotOptions = datFile.Items[machine] .Where(i => i.ItemType == ItemType.Slot) .Select(i => i as Slot) .Where(s => s.SlotOptionsSpecified) @@ -733,21 +751,21 @@ namespace SabreTools.DatFiles foreach (string deviceReference in deviceReferences) { // If the machine doesn't exist then we continue - if (Items[deviceReference] == null || Items[deviceReference].Count == 0) + if (datFile.Items[deviceReference] == null || datFile.Items[deviceReference].Count == 0) continue; // Add to the list of new device reference names - List devItems = Items[deviceReference]; + List devItems = datFile.Items[deviceReference]; newDeviceReferences.AddRange(devItems .Where(i => i.ItemType == ItemType.DeviceReference) .Select(i => (i as DeviceReference).Name)); // Set new machine information and add to the current machine - DatItem copyFrom = Items[machine][0]; + DatItem copyFrom = datFile.Items[machine][0]; foreach (DatItem item in devItems) { // If the parent machine doesn't already contain this item, add it - if (!Items[machine].Any(i => i.ItemType == item.ItemType && i.GetName() == item.GetName())) + if (!datFile.Items[machine].Any(i => i.ItemType == item.ItemType && i.GetName() == item.GetName())) { // Set that we found new items foundnew = true; @@ -755,7 +773,7 @@ namespace SabreTools.DatFiles // Clone the item and then add it DatItem datItem = (DatItem)item.Clone(); datItem.CopyMachineInformation(copyFrom); - Items.Add(machine, datItem); + datFile.Items.Add(machine, datItem); } } } @@ -764,7 +782,7 @@ namespace SabreTools.DatFiles foreach (string deviceReference in newDeviceReferences.Distinct()) { if (!deviceReferences.Contains(deviceReference)) - Items[machine].Add(new DeviceReference() { Name = deviceReference }); + datFile.Items[machine].Add(new DeviceReference() { Name = deviceReference }); } } @@ -776,11 +794,11 @@ namespace SabreTools.DatFiles foreach (string slotOption in slotOptions) { // If the machine doesn't exist then we continue - if (Items[slotOption] == null || Items[slotOption].Count == 0) + if (datFile.Items[slotOption] == null || datFile.Items[slotOption].Count == 0) continue; // Add to the list of new slot option names - List slotItems = Items[slotOption]; + List slotItems = datFile.Items[slotOption]; newSlotOptions.AddRange(slotItems .Where(i => i.ItemType == ItemType.Slot) .Where(s => (s as Slot).SlotOptionsSpecified) @@ -788,11 +806,11 @@ namespace SabreTools.DatFiles .Select(o => o.DeviceName)); // Set new machine information and add to the current machine - DatItem copyFrom = Items[machine][0]; + DatItem copyFrom = datFile.Items[machine][0]; foreach (DatItem item in slotItems) { // If the parent machine doesn't already contain this item, add it - if (!Items[machine].Any(i => i.ItemType == item.ItemType && i.GetName() == item.GetName())) + if (!datFile.Items[machine].Any(i => i.ItemType == item.ItemType && i.GetName() == item.GetName())) { // Set that we found new items foundnew = true; @@ -800,7 +818,7 @@ namespace SabreTools.DatFiles // Clone the item and then add it DatItem datItem = (DatItem)item.Clone(); datItem.CopyMachineInformation(copyFrom); - Items.Add(machine, datItem); + datFile.Items.Add(machine, datItem); } } } @@ -809,7 +827,7 @@ namespace SabreTools.DatFiles foreach (string slotOption in newSlotOptions.Distinct()) { if (!slotOptions.Contains(slotOption)) - Items[machine].Add(new Slot() { SlotOptions = new List { new SlotOption { DeviceName = slotOption } } }); + datFile.Items[machine].Add(new Slot() { SlotOptions = new List { new SlotOption { DeviceName = slotOption } } }); } } } @@ -820,45 +838,46 @@ namespace SabreTools.DatFiles /// /// Use cloneof tags to add roms to the children, setting the new romof tag in the process /// - private void AddRomsFromParent() + /// Current DatFile object to run operations on + private static void AddRomsFromParent(DatFile datFile) { - List games = Items.Keys.OrderBy(g => g).ToList(); + List games = datFile.Items.Keys.OrderBy(g => g).ToList(); foreach (string game in games) { // If the game has no items in it, we want to continue - if (Items[game].Count == 0) + if (datFile.Items[game].Count == 0) continue; // Determine if the game has a parent or not string parent = null; - if (!string.IsNullOrWhiteSpace(Items[game][0].Machine.CloneOf)) - parent = Items[game][0].Machine.CloneOf; + if (!string.IsNullOrWhiteSpace(datFile.Items[game][0].Machine.CloneOf)) + parent = datFile.Items[game][0].Machine.CloneOf; // If the parent doesnt exist, we want to continue if (string.IsNullOrWhiteSpace(parent)) continue; // If the parent doesn't have any items, we want to continue - if (Items[parent].Count == 0) + if (datFile.Items[parent].Count == 0) continue; // If the parent exists and has items, we copy the items from the parent to the current game - DatItem copyFrom = Items[game][0]; - List parentItems = Items[parent]; + DatItem copyFrom = datFile.Items[game][0]; + List parentItems = datFile.Items[parent]; foreach (DatItem item in parentItems) { DatItem datItem = (DatItem)item.Clone(); datItem.CopyMachineInformation(copyFrom); - if (Items[game].Where(i => i.GetName()?.ToLowerInvariant() == datItem.GetName()?.ToLowerInvariant()).Count() == 0 - && !Items[game].Contains(datItem)) + if (datFile.Items[game].Where(i => i.GetName()?.ToLowerInvariant() == datItem.GetName()?.ToLowerInvariant()).Count() == 0 + && !datFile.Items[game].Contains(datItem)) { - Items.Add(game, datItem); + datFile.Items.Add(game, datItem); } } // Now we want to get the parent romof tag and put it in each of the items - List items = Items[game]; - string romof = Items[parent][0].Machine.RomOf; + List items = datFile.Items[game]; + string romof = datFile.Items[parent][0].Machine.RomOf; foreach (DatItem item in items) { item.Machine.RomOf = romof; @@ -869,20 +888,21 @@ namespace SabreTools.DatFiles /// /// Use cloneof tags to add roms to the parents, removing the child sets in the process /// + /// Current DatFile object to run operations on /// True to add DatItems to subfolder of parent (not including Disk), false otherwise - private void AddRomsFromChildren(bool subfolder = true) + private static void AddRomsFromChildren(DatFile datFile, bool subfolder = true) { - List games = Items.Keys.OrderBy(g => g).ToList(); + List games = datFile.Items.Keys.OrderBy(g => g).ToList(); foreach (string game in games) { // If the game has no items in it, we want to continue - if (Items[game].Count == 0) + if (datFile.Items[game].Count == 0) continue; // Determine if the game has a parent or not string parent = null; - if (!string.IsNullOrWhiteSpace(Items[game][0].Machine.CloneOf)) - parent = Items[game][0].Machine.CloneOf; + if (!string.IsNullOrWhiteSpace(datFile.Items[game][0].Machine.CloneOf)) + parent = datFile.Items[game][0].Machine.CloneOf; // If there is no parent, then we continue if (string.IsNullOrWhiteSpace(parent)) @@ -890,7 +910,7 @@ namespace SabreTools.DatFiles // Otherwise, move the items from the current game to a subfolder of the parent game DatItem copyFrom; - if (Items[parent].Count == 0) + if (datFile.Items[parent].Count == 0) { copyFrom = new Rom(); copyFrom.Machine.Name = parent; @@ -898,10 +918,10 @@ namespace SabreTools.DatFiles } else { - copyFrom = Items[parent][0]; + copyFrom = datFile.Items[parent][0]; } - List items = Items[game]; + List items = datFile.Items[game]; foreach (DatItem item in items) { // Special disk handling @@ -910,23 +930,23 @@ namespace SabreTools.DatFiles Disk disk = item as Disk; // If the merge tag exists and the parent already contains it, skip - if (disk.MergeTag != null && Items[parent].Where(i => i.ItemType == ItemType.Disk).Select(i => (i as Disk).Name).Contains(disk.MergeTag)) + if (disk.MergeTag != null && datFile.Items[parent].Where(i => i.ItemType == ItemType.Disk).Select(i => (i as Disk).Name).Contains(disk.MergeTag)) { continue; } // If the merge tag exists but the parent doesn't contain it, add to parent - else if (disk.MergeTag != null && !Items[parent].Where(i => i.ItemType == ItemType.Disk).Select(i => (i as Disk).Name).Contains(disk.MergeTag)) + else if (disk.MergeTag != null && !datFile.Items[parent].Where(i => i.ItemType == ItemType.Disk).Select(i => (i as Disk).Name).Contains(disk.MergeTag)) { disk.CopyMachineInformation(copyFrom); - Items.Add(parent, disk); + datFile.Items.Add(parent, disk); } // If there is no merge tag, add to parent else if (disk.MergeTag == null) { disk.CopyMachineInformation(copyFrom); - Items.Add(parent, disk); + datFile.Items.Add(parent, disk); } } @@ -936,61 +956,62 @@ namespace SabreTools.DatFiles Rom rom = item as Rom; // If the merge tag exists and the parent already contains it, skip - if (rom.MergeTag != null && Items[parent].Where(i => i.ItemType == ItemType.Rom).Select(i => (i as Rom).Name).Contains(rom.MergeTag)) + if (rom.MergeTag != null && datFile.Items[parent].Where(i => i.ItemType == ItemType.Rom).Select(i => (i as Rom).Name).Contains(rom.MergeTag)) { continue; } // If the merge tag exists but the parent doesn't contain it, add to subfolder of parent - else if (rom.MergeTag != null && !Items[parent].Where(i => i.ItemType == ItemType.Rom).Select(i => (i as Rom).Name).Contains(rom.MergeTag)) + else if (rom.MergeTag != null && !datFile.Items[parent].Where(i => i.ItemType == ItemType.Rom).Select(i => (i as Rom).Name).Contains(rom.MergeTag)) { if (subfolder) rom.Name = $"{rom.Machine.Name}\\{rom.Name}"; rom.CopyMachineInformation(copyFrom); - Items.Add(parent, rom); + datFile.Items.Add(parent, rom); } // If the parent doesn't already contain this item, add to subfolder of parent - else if (!Items[parent].Contains(item)) + else if (!datFile.Items[parent].Contains(item)) { if (subfolder) rom.Name = $"{item.Machine.Name}\\{rom.Name}"; rom.CopyMachineInformation(copyFrom); - Items.Add(parent, rom); + datFile.Items.Add(parent, rom); } } // All other that would be missing to subfolder of parent - else if (!Items[parent].Contains(item)) + else if (!datFile.Items[parent].Contains(item)) { if (subfolder) item.SetFields(new Dictionary { [Field.DatItem_Name] = $"{item.Machine.Name}\\{item.GetName()}" }); item.CopyMachineInformation(copyFrom); - Items.Add(parent, item); + datFile.Items.Add(parent, item); } } // Then, remove the old game so it's not picked up by the writer - Items.Remove(game); + datFile.Items.Remove(game); } } /// /// Remove all BIOS and device sets /// - private void RemoveBiosAndDeviceSets() + /// Current DatFile object to run operations on + private static void RemoveBiosAndDeviceSets(DatFile datFile) { - List games = Items.Keys.OrderBy(g => g).ToList(); + List games = datFile.Items.Keys.OrderBy(g => g).ToList(); foreach (string game in games) { - if (Items[game].Count > 0 - && (Items[game][0].Machine.MachineType.HasFlag(MachineType.Bios) - || Items[game][0].Machine.MachineType.HasFlag(MachineType.Device))) + if (datFile.Items[game].Count > 0 + && (datFile.Items[game][0].Machine.MachineType.HasFlag(MachineType.Bios) + || datFile.Items[game][0].Machine.MachineType.HasFlag(MachineType.Device))) { - Items.Remove(game); + datFile.Items.Remove(game); } } } @@ -998,42 +1019,43 @@ namespace SabreTools.DatFiles /// /// Use romof tags to remove bios roms from children /// + /// Current DatFile object to run operations on /// True if only child Bios sets are touched, false for non-bios sets (default) - private void RemoveBiosRomsFromChild(bool bios = false) + private static void RemoveBiosRomsFromChild(DatFile datFile, bool bios = false) { // Loop through the romof tags - List games = Items.Keys.OrderBy(g => g).ToList(); + List games = datFile.Items.Keys.OrderBy(g => g).ToList(); foreach (string game in games) { // If the game has no items in it, we want to continue - if (Items[game].Count == 0) + if (datFile.Items[game].Count == 0) continue; // If the game (is/is not) a bios, we want to continue - if (bios ^ Items[game][0].Machine.MachineType.HasFlag(MachineType.Bios)) + if (bios ^ datFile.Items[game][0].Machine.MachineType.HasFlag(MachineType.Bios)) continue; // Determine if the game has a parent or not string parent = null; - if (!string.IsNullOrWhiteSpace(Items[game][0].Machine.RomOf)) - parent = Items[game][0].Machine.RomOf; + if (!string.IsNullOrWhiteSpace(datFile.Items[game][0].Machine.RomOf)) + parent = datFile.Items[game][0].Machine.RomOf; // If the parent doesnt exist, we want to continue if (string.IsNullOrWhiteSpace(parent)) continue; // If the parent doesn't have any items, we want to continue - if (Items[parent].Count == 0) + if (datFile.Items[parent].Count == 0) continue; // If the parent exists and has items, we remove the items that are in the parent from the current game - List parentItems = Items[parent]; + List parentItems = datFile.Items[parent]; foreach (DatItem item in parentItems) { DatItem datItem = (DatItem)item.Clone(); - while (Items[game].Contains(datItem)) + while (datFile.Items[game].Contains(datItem)) { - Items.Remove(game, datItem); + datFile.Items.Remove(game, datItem); } } } @@ -1042,42 +1064,43 @@ namespace SabreTools.DatFiles /// /// Use cloneof tags to remove roms from the children /// - private void RemoveRomsFromChild() + /// Current DatFile object to run operations on + private static void RemoveRomsFromChild(DatFile datFile) { - List games = Items.Keys.OrderBy(g => g).ToList(); + List games = datFile.Items.Keys.OrderBy(g => g).ToList(); foreach (string game in games) { // If the game has no items in it, we want to continue - if (Items[game].Count == 0) + if (datFile.Items[game].Count == 0) continue; // Determine if the game has a parent or not string parent = null; - if (!string.IsNullOrWhiteSpace(Items[game][0].Machine.CloneOf)) - parent = Items[game][0].Machine.CloneOf; + if (!string.IsNullOrWhiteSpace(datFile.Items[game][0].Machine.CloneOf)) + parent = datFile.Items[game][0].Machine.CloneOf; // If the parent doesnt exist, we want to continue if (string.IsNullOrWhiteSpace(parent)) continue; // If the parent doesn't have any items, we want to continue - if (Items[parent].Count == 0) + if (datFile.Items[parent].Count == 0) continue; // If the parent exists and has items, we remove the parent items from the current game - List parentItems = Items[parent]; + List parentItems = datFile.Items[parent]; foreach (DatItem item in parentItems) { DatItem datItem = (DatItem)item.Clone(); - while (Items[game].Contains(datItem)) + while (datFile.Items[game].Contains(datItem)) { - Items.Remove(game, datItem); + datFile.Items.Remove(game, datItem); } } // Now we want to get the parent romof tag and put it in each of the remaining items - List items = Items[game]; - string romof = Items[parent][0].Machine.RomOf; + List items = datFile.Items[game]; + string romof = datFile.Items[parent][0].Machine.RomOf; foreach (DatItem item in items) { item.Machine.RomOf = romof; @@ -1088,12 +1111,13 @@ namespace SabreTools.DatFiles /// /// Remove all romof and cloneof tags from all games /// - private void RemoveTagsFromChild() + /// Current DatFile object to run operations on + private static void RemoveTagsFromChild(DatFile datFile) { - List games = Items.Keys.OrderBy(g => g).ToList(); + List games = datFile.Items.Keys.OrderBy(g => g).ToList(); foreach (string game in games) { - List items = Items[game]; + List items = datFile.Items[game]; foreach (DatItem item in items) { item.Machine.CloneOf = null; diff --git a/SabreTools.DatFiles/DatTool.cs b/SabreTools.DatFiles/DatTool.cs index fd6a67f8..c3b15330 100644 --- a/SabreTools.DatFiles/DatTool.cs +++ b/SabreTools.DatFiles/DatTool.cs @@ -1,7 +1,7 @@ using SabreTools.Logging; -// TODO: What sort of internal state should this have? Would a single DatFile be appropriate? -// TODO: How much of the stuff currently in DatFile should be moved here? +// TODO: Should each of the individual pieces of partial classes be their own classes? +// TODO: Is a single, consistent internal state needed for this class at all? namespace SabreTools.DatFiles { /// diff --git a/SabreTools/Features/Batch.cs b/SabreTools/Features/Batch.cs index ae033714..5066a071 100644 --- a/SabreTools/Features/Batch.cs +++ b/SabreTools/Features/Batch.cs @@ -160,7 +160,7 @@ Reset the internal state: reset();"; // TODO: We might not want to remove dates in the future Cleaner dfdCleaner = new Cleaner() { ExcludeFields = Hash.DeepHashes.AsFields() }; dfdCleaner.ExcludeFields.Add(Field.DatItem_Date); - datFile.ApplyCleaning(dfdCleaner); + DatTool.ApplyCleaning(datFile, dfdCleaner); break; @@ -205,7 +205,7 @@ Reset the internal state: reset();"; filter.SetFilter(filterField, filterValue, filterRemove.Value); // Apply the filter blindly - datFile.ApplyFilter(filter, filterPerMachine.Value); + DatTool.ApplyFilter(datFile, filter, filterPerMachine.Value); // Cleanup after the filter // TODO: We might not want to remove immediately @@ -247,7 +247,7 @@ Reset the internal state: reset();"; extraIni.Items.Add(extraIniItem); // Apply the extra INI blindly - datFile.ApplyExtras(extraIni); + DatTool.ApplyExtras(datFile, extraIni); break; @@ -271,7 +271,7 @@ Reset the internal state: reset();"; } // Apply the merging flag - datFile.ApplySplitting(mergingFlag, false); + DatTool.ApplySplitting(datFile, mergingFlag, false); break; @@ -285,7 +285,7 @@ Reset the internal state: reset();"; } // Apply the logic - datFile.MachineDescriptionToName(); + DatTool.MachineDescriptionToName(datFile); break; @@ -299,7 +299,7 @@ Reset the internal state: reset();"; } // Run the 1G1R functionality - datFile.OneGamePerRegion(command.Arguments); + DatTool.OneGamePerRegion(datFile, command.Arguments); break; @@ -313,7 +313,7 @@ Reset the internal state: reset();"; } // Apply the logic - datFile.OneRomPerGame(); + DatTool.OneRomPerGame(datFile); break; @@ -327,7 +327,7 @@ Reset the internal state: reset();"; } // Run the removal functionality - datFile.RemoveFieldsFromItems(command.Arguments.Select(s => s.AsField()).ToList()); + DatTool.RemoveFieldsFromItems(datFile, command.Arguments.Select(s => s.AsField()).ToList()); break; @@ -341,7 +341,7 @@ Reset the internal state: reset();"; } // Apply the logic - datFile.StripSceneDatesFromItems(); + DatTool.StripSceneDatesFromItems(datFile); break; diff --git a/SabreTools/Features/DatFromDir.cs b/SabreTools/Features/DatFromDir.cs index 3fa335b1..8f9721f3 100644 --- a/SabreTools/Features/DatFromDir.cs +++ b/SabreTools/Features/DatFromDir.cs @@ -100,10 +100,10 @@ namespace SabreTools.Features if (success) { // Perform additional processing steps - datdata.ApplyExtras(Extras); - datdata.ApplySplitting(splitType, false); - datdata.ApplyFilter(Filter); - datdata.ApplyCleaning(Cleaner); + DatTool.ApplyExtras(datdata, Extras); + DatTool.ApplySplitting(datdata, splitType, false); + DatTool.ApplyFilter(datdata, Filter); + DatTool.ApplyCleaning(datdata, Cleaner); // Write out the file DatTool.Write(datdata, OutputDir); diff --git a/SabreTools/Features/Update.cs b/SabreTools/Features/Update.cs index 538bd762..844b3e87 100644 --- a/SabreTools/Features/Update.cs +++ b/SabreTools/Features/Update.cs @@ -167,10 +167,10 @@ namespace SabreTools.Features || datFile.Header.DatFormat.HasFlag(DatFormat.SSV)); // Perform additional processing steps - datFile.ApplyExtras(Extras); - datFile.ApplySplitting(GetSplitType(features), false); - datFile.ApplyFilter(Filter); - datFile.ApplyCleaning(Cleaner); + DatTool.ApplyExtras(datFile, Extras); + DatTool.ApplySplitting(datFile, GetSplitType(features), false); + DatTool.ApplyFilter(datFile, Filter); + DatTool.ApplyCleaning(datFile, Cleaner); // Get the correct output path string realOutDir = inputPath.GetOutputPath(OutputDir, GetBoolean(features, InplaceValue)); @@ -205,10 +205,10 @@ namespace SabreTools.Features datHeaders = DatTool.PopulateUserData(userInputDat, inputPaths); // Perform additional processing steps - userInputDat.ApplyExtras(Extras); - userInputDat.ApplySplitting(GetSplitType(features), false); - userInputDat.ApplyFilter(Filter); - userInputDat.ApplyCleaning(Cleaner); + DatTool.ApplyExtras(userInputDat, Extras); + DatTool.ApplySplitting(userInputDat, GetSplitType(features), false); + DatTool.ApplyFilter(userInputDat, Filter); + DatTool.ApplyCleaning(userInputDat, Cleaner); // Output only DatItems that are duplicated across inputs if (updateMode.HasFlag(UpdateMode.DiffDupesOnly)) @@ -297,10 +297,10 @@ namespace SabreTools.Features DatTool.ParseInto(repDat, inputPath, indexId: 1, keep: true); // Perform additional processing steps - repDat.ApplyExtras(Extras); - repDat.ApplySplitting(GetSplitType(features), false); - repDat.ApplyFilter(Filter); - repDat.ApplyCleaning(Cleaner); + DatTool.ApplyExtras(repDat, Extras); + DatTool.ApplySplitting(repDat, GetSplitType(features), false); + DatTool.ApplyFilter(repDat, Filter); + DatTool.ApplyCleaning(repDat, Cleaner); // Now replace the fields from the base DatFile DatTool.DiffAgainst(userInputDat, repDat, GetBoolean(Features, ByGameValue)); @@ -322,10 +322,10 @@ namespace SabreTools.Features DatTool.ParseInto(repDat, inputPath, indexId: 1, keep: true); // Perform additional processing steps - repDat.ApplyExtras(Extras); - repDat.ApplySplitting(GetSplitType(features), false); - repDat.ApplyFilter(Filter); - repDat.ApplyCleaning(Cleaner); + DatTool.ApplyExtras(repDat, Extras); + DatTool.ApplySplitting(repDat, GetSplitType(features), false); + DatTool.ApplyFilter(repDat, Filter); + DatTool.ApplyCleaning(repDat, Cleaner); // Now replace the fields from the base DatFile DatTool.BaseReplace(userInputDat, repDat, updateFields, GetBoolean(features, OnlySameValue)); @@ -342,7 +342,7 @@ namespace SabreTools.Features { // If we're in SuperDAT mode, prefix all games with their respective DATs if (string.Equals(userInputDat.Header.Type, "SuperDAT", StringComparison.OrdinalIgnoreCase)) - userInputDat.ApplySuperDAT(inputPaths); + DatTool.ApplySuperDAT(userInputDat, inputPaths); DatTool.Write(userInputDat, OutputDir); } diff --git a/SabreTools/Features/Verify.cs b/SabreTools/Features/Verify.cs index 0db683cb..dba48051 100644 --- a/SabreTools/Features/Verify.cs +++ b/SabreTools/Features/Verify.cs @@ -61,10 +61,10 @@ namespace SabreTools.Features DatTool.ParseInto(datdata, datfile, int.MaxValue, keep: true); // Perform additional processing steps - datdata.ApplyExtras(Extras); - datdata.ApplySplitting(splitType, true); - datdata.ApplyFilter(Filter); - datdata.ApplyCleaning(Cleaner); + DatTool.ApplyExtras(datdata, Extras); + DatTool.ApplySplitting(datdata, splitType, true); + DatTool.ApplyFilter(datdata, Filter); + DatTool.ApplyCleaning(datdata, Cleaner); // Set depot information datdata.Header.InputDepot = Header.InputDepot.Clone() as DepotInformation; @@ -108,10 +108,10 @@ namespace SabreTools.Features } // Perform additional processing steps - datdata.ApplyExtras(Extras); - datdata.ApplySplitting(splitType, true); - datdata.ApplyFilter(Filter); - datdata.ApplyCleaning(Cleaner); + DatTool.ApplyExtras(datdata, Extras); + DatTool.ApplySplitting(datdata, splitType, true); + DatTool.ApplyFilter(datdata, Filter); + DatTool.ApplyCleaning(datdata, Cleaner); // Set depot information datdata.Header.InputDepot = Header.InputDepot.Clone() as DepotInformation;