diff --git a/SabreTools.DatFiles/ItemDictionary.cs b/SabreTools.DatFiles/ItemDictionary.cs index 70b94667..6a9afda4 100644 --- a/SabreTools.DatFiles/ItemDictionary.cs +++ b/SabreTools.DatFiles/ItemDictionary.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; #endif using System.Collections.Generic; +using System.IO; #if NET40_OR_GREATER || NETCOREAPP using System.Threading.Tasks; #endif @@ -664,7 +665,7 @@ namespace SabreTools.DatFiles List sortedList = GetItemsForBucket(key); // Sort the list of items to be consistent - DatFileTool.Sort(ref sortedList, false); + Sort(ref sortedList, false); // If we're merging the roms, do so if (dedupeType == DedupeType.Full || (dedupeType == DedupeType.Game && bucketBy == ItemKey.Machine)) @@ -697,7 +698,7 @@ namespace SabreTools.DatFiles List sortedList = GetItemsForBucket(key); // Sort the list of items to be consistent - DatFileTool.Sort(ref sortedList, false); + Sort(ref sortedList, false); // Add the list back to the dictionary RemoveBucket(key); @@ -709,6 +710,59 @@ namespace SabreTools.DatFiles #endif } + /// + /// Sort a list of DatItem objects by SourceID, Game, and Name (in order) + /// + /// List of DatItem objects representing the items to be sorted + /// True if files are not renamed, false otherwise + /// True if it sorted correctly, false otherwise + private bool Sort(ref List items, bool norename) + { + items.Sort(delegate (DatItem x, DatItem y) + { + try + { + var nc = new NaturalComparer(); + + // If machine names don't match + string? xMachineName = x.GetFieldValue(DatItem.MachineKey)?.GetStringFieldValue(Models.Metadata.Machine.NameKey); + string? yMachineName = y.GetFieldValue(DatItem.MachineKey)?.GetStringFieldValue(Models.Metadata.Machine.NameKey); + if (xMachineName != yMachineName) + return nc.Compare(xMachineName, yMachineName); + + // If types don't match + string? xType = x.GetStringFieldValue(Models.Metadata.DatItem.TypeKey); + string? yType = y.GetStringFieldValue(Models.Metadata.DatItem.TypeKey); + if (xType != yType) + return xType.AsEnumValue() - yType.AsEnumValue(); + + // If directory names don't match + string? xDirectoryName = Path.GetDirectoryName(TextHelper.RemovePathUnsafeCharacters(x.GetName() ?? string.Empty)); + string? yDirectoryName = Path.GetDirectoryName(TextHelper.RemovePathUnsafeCharacters(y.GetName() ?? string.Empty)); + if (xDirectoryName != yDirectoryName) + return nc.Compare(xDirectoryName, yDirectoryName); + + // If item names don't match + string? xName = Path.GetFileName(TextHelper.RemovePathUnsafeCharacters(x.GetName() ?? string.Empty)); + string? yName = Path.GetFileName(TextHelper.RemovePathUnsafeCharacters(y.GetName() ?? string.Empty)); + if (xName != yName) + return nc.Compare(xName, yName); + + // Otherwise, compare on machine or source, depending on the flag + int? xSourceIndex = x.GetFieldValue(DatItem.SourceKey)?.Index; + int? ySourceIndex = y.GetFieldValue(DatItem.SourceKey)?.Index; + return (norename ? nc.Compare(xMachineName, yMachineName) : (xSourceIndex - ySourceIndex) ?? 0); + } + catch + { + // Absorb the error + return 0; + } + }); + + return true; + } + /// /// Sort the input DAT and get the key to be used by the item ///