diff --git a/SabreTools.DatFiles/ItemDictionaryDB.cs b/SabreTools.DatFiles/ItemDictionaryDB.cs index 429d2d49..1b8ffb09 100644 --- a/SabreTools.DatFiles/ItemDictionaryDB.cs +++ b/SabreTools.DatFiles/ItemDictionaryDB.cs @@ -736,7 +736,7 @@ namespace SabreTools.DatFiles /// Merge an arbitrary set of item pairs based on the supplied information /// /// List of pairs representing the items to be merged - private List> Deduplicate(List> itemMappings) + private List> Merge(List> itemMappings) { // Check for null or blank roms first if (itemMappings == null || itemMappings.Count == 0) @@ -769,83 +769,66 @@ namespace SabreTools.DatFiles nodumpCount++; continue; } + // If it's the first non-nodump rom in the list, don't touch it - else if (output.Count == 0 || output.Count == nodumpCount) + if (output.Count == nodumpCount) { output.Add(new KeyValuePair(itemIndex, datItem)); continue; } - // Check if the rom is a duplicate - DupeType dupetype = 0x00; - long savedIndex = -1; - DatItem saveditem = new Blank(); - int pos = -1; - for (int i = 0; i < output.Count; i++) - { - long lastIndex = output[i].Key; - DatItem lastrom = output[i].Value; - - // Get the sources associated with the items - var savedSource = _sources[_itemToSourceMapping[savedIndex]]; - var itemSource = _sources[_itemToSourceMapping[itemIndex]]; - - // Get the duplicate status - dupetype = datItem.GetDuplicateStatus(itemSource, lastrom, savedSource); - - // If it's a duplicate, skip adding it to the output but add any missing information - if (dupetype != 0x00) - { - savedIndex = lastIndex; - saveditem = lastrom; - pos = i; - - // Disks, Media, and Roms have more information to fill - if (datItem is Disk disk && saveditem is Disk savedDisk) - savedDisk.FillMissingInformation(disk); - else if (datItem is DatItems.Formats.File fileItem && saveditem is DatItems.Formats.File savedFile) - savedFile.FillMissingInformation(fileItem); - else if (datItem is Media media && saveditem is Media savedMedia) - savedMedia.FillMissingInformation(media); - else if (datItem is Rom romItem && saveditem is Rom savedRom) - savedRom.FillMissingInformation(romItem); - - saveditem.SetFieldValue(DatItem.DupeTypeKey, dupetype); - - // Get the machines associated with the items - var savedMachine = _machines[_itemToMachineMapping[savedIndex]]; - var itemMachine = _machines[_itemToMachineMapping[itemIndex]]; - - // If the current system has a lower ID than the previous, set the system accordingly - if (itemSource?.Index < savedSource?.Index) - { - _itemToSourceMapping[itemIndex] = _itemToSourceMapping[savedIndex]; - _machines[_itemToMachineMapping[savedIndex]] = (itemMachine.Clone() as Machine)!; - saveditem.SetName(datItem.GetName()); - } - - // If the current machine is a child of the new machine, use the new machine instead - if (savedMachine.GetStringFieldValue(Models.Metadata.Machine.CloneOfKey) == itemMachine.GetStringFieldValue(Models.Metadata.Machine.NameKey) - || savedMachine.GetStringFieldValue(Models.Metadata.Machine.RomOfKey) == itemMachine.GetStringFieldValue(Models.Metadata.Machine.NameKey)) - { - _machines[_itemToMachineMapping[savedIndex]] = (itemMachine.Clone() as Machine)!; - saveditem.SetName(datItem.GetName()); - } - - break; - } - } - - // If no duplicate is found, add it to the list - if (dupetype == 0x00) + // Find the index of the first duplicate, if one exists + int pos = output.FindIndex(lastItem => datItem.GetDuplicateStatus(lastItem.Value) != 0x00); + if (pos < 0) { output.Add(new KeyValuePair(itemIndex, datItem)); + continue; } - // Otherwise, if a new rom information is found, add that + + // Get the duplicate item + long savedIndex = output[pos].Key; + DatItem savedItem = output[pos].Value; + DupeType dupetype = datItem.GetDuplicateStatus(savedItem); + + // Disks, Media, and Roms have more information to fill + if (datItem is Disk diskItem && savedItem is Disk savedDisk) + savedDisk.FillMissingInformation(diskItem); + else if (datItem is DatItems.Formats.File fileItem && savedItem is DatItems.Formats.File savedFile) + savedFile.FillMissingInformation(fileItem); + else if (datItem is Media mediaItem && savedItem is Media savedMedia) + savedMedia.FillMissingInformation(mediaItem); + else if (datItem is Rom romItem && savedItem is Rom savedRom) + savedRom.FillMissingInformation(romItem); + + savedItem.SetFieldValue(DatItem.DupeTypeKey, dupetype); + + // Get the sources associated with the items + var savedSource = _sources[_itemToSourceMapping[savedIndex]]; + var itemSource = _sources[_itemToSourceMapping[itemIndex]]; + + // Get the machines associated with the items + var savedMachine = _machines[_itemToMachineMapping[savedIndex]]; + var itemMachine = _machines[_itemToMachineMapping[itemIndex]]; + + // If the current system has a lower ID than the previous, set the system accordingly + if (itemSource?.Index < savedSource?.Index) { - output.RemoveAt(pos); - output.Insert(pos, new KeyValuePair(savedIndex, saveditem)); + _itemToSourceMapping[itemIndex] = _itemToSourceMapping[savedIndex]; + _machines[_itemToMachineMapping[savedIndex]] = (itemMachine.Clone() as Machine)!; + savedItem.SetName(datItem.GetName()); } + + // If the current machine is a child of the new machine, use the new machine instead + if (savedMachine.GetStringFieldValue(Models.Metadata.Machine.CloneOfKey) == itemMachine.GetStringFieldValue(Models.Metadata.Machine.NameKey) + || savedMachine.GetStringFieldValue(Models.Metadata.Machine.RomOfKey) == itemMachine.GetStringFieldValue(Models.Metadata.Machine.NameKey)) + { + _machines[_itemToMachineMapping[savedIndex]] = (itemMachine.Clone() as Machine)!; + savedItem.SetName(datItem.GetName()); + } + + // Replace the original item in the list + output.RemoveAt(pos); + output.Insert(pos, new KeyValuePair(savedIndex, savedItem)); } return output; @@ -1072,7 +1055,7 @@ namespace SabreTools.DatFiles // If we're merging the roms, do so if (dedupeType == DedupeType.Full || (dedupeType == DedupeType.Game && bucketBy == ItemKey.Machine)) - datItems = Deduplicate(datItems); + datItems = Merge(datItems); _buckets[bucketKeys[i]] = [.. datItems.Select(kvp => kvp.Key)]; #if NET40_OR_GREATER || NETCOREAPP diff --git a/SabreTools.DatItems/DatItem.cs b/SabreTools.DatItems/DatItem.cs index 6ac2045e..d1dee63d 100644 --- a/SabreTools.DatItems/DatItem.cs +++ b/SabreTools.DatItems/DatItem.cs @@ -123,75 +123,6 @@ namespace SabreTools.DatItems /// Clone of the DatItem public abstract object Clone(); - /// - /// Conditionally copy all machine information from another item - /// - /// Existing item to copy information from - /// - /// The cases when Machine data is updated: - /// - Current machine is a clone of the other machine - /// - Current machine is a rom of the other machine - /// - public void ConditionalUpdateMachine(DatItem item) - { - // Get the machines for the two items - Machine? selfMachine = GetFieldValue(DatItem.MachineKey); - Machine? itemMachine = item.GetFieldValue(DatItem.MachineKey); - - // If either machine is missing - if (selfMachine == null || itemMachine == null) - return; - - // Get the required strings - string? selfCloneOf = selfMachine.GetStringFieldValue(Models.Metadata.Machine.CloneOfKey); - string? selfRomOf = selfMachine.GetStringFieldValue(Models.Metadata.Machine.RomOfKey); - string? otherMachineName = itemMachine.GetStringFieldValue(Models.Metadata.Machine.NameKey); - - // If the other machine has no name - if (otherMachineName == null) - return; - - // If the current machine is a child of the new machine, use the new machine instead - if (selfCloneOf == otherMachineName) - { - CopyMachineInformation(item); - SetName(item.GetName()); - } - else if (selfRomOf == otherMachineName) - { - CopyMachineInformation(item); - SetName(item.GetName()); - } - } - - /// - /// Conditionally copy all source information from another item - /// - /// Existing item to copy information from - /// - /// The cases when Source data is updated: - /// - Current source data has an index higher than the other item - /// - public void ConditionalUpdateSource(DatItem item) - { - // Get the sources for comparison - Source? selfSource = GetFieldValue(DatItem.SourceKey); - Source? itemSource = item.GetFieldValue(DatItem.SourceKey); - - // If either source is missing - if (selfSource == null || itemSource == null) - return; - - // Use the new source if less than - if (selfSource.Index > itemSource.Index) - { - SetFieldValue(DatItem.SourceKey, itemSource.Clone() as Source); - CopyMachineInformation(item); - SetName(item.GetName()); - return; - } - } - /// /// Copy all machine information over in one shot /// diff --git a/SabreTools.DatItems/DatItemTool.cs b/SabreTools.DatItems/DatItemTool.cs index 314b5cd2..300ee2b1 100644 --- a/SabreTools.DatItems/DatItemTool.cs +++ b/SabreTools.DatItems/DatItemTool.cs @@ -281,85 +281,93 @@ namespace SabreTools.DatItems return []; // Create output list - List outfiles = []; + List output = []; // Then deduplicate them by checking to see if data matches previous saved roms int nodumpCount = 0; - foreach (DatItem item in items) + foreach (DatItem datItem in items) { // If we don't have a Disk, File, Media, or Rom, we skip checking for duplicates - if (item is not Disk && item is not Formats.File && item is not Media && item is not Rom) + if (datItem is not Disk && datItem is not Formats.File && datItem is not Media && datItem is not Rom) continue; // If it's a nodump, add and skip - if (item is Rom rom && rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue() == ItemStatus.Nodump) + if (datItem is Rom rom && rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue() == ItemStatus.Nodump) { - outfiles.Add(item); + output.Add(datItem); nodumpCount++; continue; } - else if (item is Disk disk && disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue() == ItemStatus.Nodump) + else if (datItem is Disk disk && disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue() == ItemStatus.Nodump) { - outfiles.Add(item); + output.Add(datItem); nodumpCount++; continue; } // If it's the first non-nodump item in the list, don't touch it - if (outfiles.Count == nodumpCount) + if (output.Count == nodumpCount) { - outfiles.Add(item); + output.Add(datItem); continue; } - // Check if the item is a duplicate - DupeType dupetype = 0x00; - DatItem savedItem = new Blank(); - int pos = -1; - for (int i = 0; i < outfiles.Count; i++) + // Find the index of the first duplicate, if one exists + int pos = output.FindIndex(lastItem => datItem.GetDuplicateStatus(lastItem) != 0x00); + if (pos < 0) { - // Get the next item - DatItem lastItem = outfiles[i]; - - // Get the duplicate status - dupetype = item.GetDuplicateStatus(lastItem); - if (dupetype == 0x00) - continue; - - // If it's a duplicate, skip adding it to the output but add any missing information - savedItem = lastItem; - pos = i; - - // Disks, File, Media, and Roms have more information to fill - if (item is Disk disk && savedItem is Disk savedDisk) - savedDisk.FillMissingInformation(disk); - else if (item is Formats.File fileItem && savedItem is Formats.File savedFile) - savedFile.FillMissingInformation(fileItem); - else if (item is Media media && savedItem is Media savedMedia) - savedMedia.FillMissingInformation(media); - else if (item is Rom romItem && savedItem is Rom savedRom) - savedRom.FillMissingInformation(romItem); - - // Set the duplicate type on the saved item - savedItem.SetFieldValue(DatItem.DupeTypeKey, dupetype); - break; + output.Add(datItem); + continue; } - // If no duplicate is found, add it to the list - if (dupetype == 0x00 || pos < 0) + // Get the duplicate item + DatItem savedItem = output[pos]; + DupeType dupetype = datItem.GetDuplicateStatus(savedItem); + + // Disks, File, Media, and Roms have more information to fill + if (datItem is Disk diskItem && savedItem is Disk savedDisk) + savedDisk.FillMissingInformation(diskItem); + else if (datItem is Formats.File fileItem && savedItem is Formats.File savedFile) + savedFile.FillMissingInformation(fileItem); + else if (datItem is Media mediaItem && savedItem is Media savedMedia) + savedMedia.FillMissingInformation(mediaItem); + else if (datItem is Rom romItem && savedItem is Rom savedRom) + savedRom.FillMissingInformation(romItem); + + // Set the duplicate type on the saved item + savedItem.SetFieldValue(DatItem.DupeTypeKey, dupetype); + + // Get the sources associated with the items + var savedSource = savedItem.GetFieldValue(DatItem.SourceKey); + var itemSource = datItem.GetFieldValue(DatItem.SourceKey); + + // Get the machines associated with the items + var savedMachine = savedItem.GetFieldValue(DatItem.MachineKey); + var itemMachine = datItem.GetFieldValue(DatItem.MachineKey); + + // If the current system has a lower ID than the previous, set the system accordingly + if (itemSource?.Index < savedSource?.Index) { - outfiles.Add(item); + datItem.SetFieldValue(DatItem.SourceKey, savedSource.Clone() as Source); + savedItem.CopyMachineInformation(datItem); + savedItem.SetName(datItem.GetName()); } - // Otherwise, if a new rom information is found, add that - else + + // If the current machine is a child of the new machine, use the new machine instead + if (savedMachine?.GetStringFieldValue(Models.Metadata.Machine.CloneOfKey) == itemMachine?.GetStringFieldValue(Models.Metadata.Machine.NameKey) + || savedMachine?.GetStringFieldValue(Models.Metadata.Machine.RomOfKey) == itemMachine?.GetStringFieldValue(Models.Metadata.Machine.NameKey)) { - outfiles.RemoveAt(pos); - outfiles.Insert(pos, savedItem); + savedItem.CopyMachineInformation(datItem); + savedItem.SetName(datItem.GetName()); } + + // Replace the original item in the list + output.RemoveAt(pos); + output.Insert(pos, savedItem); } // Then return the result - return outfiles; + return output; } /// diff --git a/SabreTools.DatItems/Formats/Disk.cs b/SabreTools.DatItems/Formats/Disk.cs index 826cdba5..c1eb5804 100644 --- a/SabreTools.DatItems/Formats/Disk.cs +++ b/SabreTools.DatItems/Formats/Disk.cs @@ -99,11 +99,7 @@ namespace SabreTools.DatItems.Formats /// /// Disk to fill information from public void FillMissingInformation(Disk other) - { - _internal.FillMissingHashes(other._internal); - ConditionalUpdateSource(other); - ConditionalUpdateMachine(other); - } + => _internal.FillMissingHashes(other._internal); /// /// Get unique duplicate suffix on name collision diff --git a/SabreTools.DatItems/Formats/File.cs b/SabreTools.DatItems/Formats/File.cs index 01a5fcc6..b288a56f 100644 --- a/SabreTools.DatItems/Formats/File.cs +++ b/SabreTools.DatItems/Formats/File.cs @@ -207,9 +207,6 @@ namespace SabreTools.DatItems.Formats if (_sha256.IsNullOrEmpty() && !other._sha256.IsNullOrEmpty()) _sha256 = other._sha256; - - ConditionalUpdateSource(other); - ConditionalUpdateMachine(other); } /// diff --git a/SabreTools.DatItems/Formats/Media.cs b/SabreTools.DatItems/Formats/Media.cs index 35a8def1..809d4270 100644 --- a/SabreTools.DatItems/Formats/Media.cs +++ b/SabreTools.DatItems/Formats/Media.cs @@ -60,11 +60,7 @@ namespace SabreTools.DatItems.Formats /// /// Media to fill information from public void FillMissingInformation(Media other) - { - _internal.FillMissingHashes(other._internal); - ConditionalUpdateSource(other); - ConditionalUpdateMachine(other); - } + => _internal.FillMissingHashes(other._internal); /// /// Get unique duplicate suffix on name collision diff --git a/SabreTools.DatItems/Formats/Rom.cs b/SabreTools.DatItems/Formats/Rom.cs index 50b07c0e..35b9b0a9 100644 --- a/SabreTools.DatItems/Formats/Rom.cs +++ b/SabreTools.DatItems/Formats/Rom.cs @@ -103,11 +103,7 @@ namespace SabreTools.DatItems.Formats /// /// Rom to fill information from public void FillMissingInformation(Rom other) - { - _internal.FillMissingHashes(other._internal); - ConditionalUpdateSource(other); - ConditionalUpdateMachine(other); - } + => _internal.FillMissingHashes(other._internal); /// /// Get unique duplicate suffix on name collision