diff --git a/SabreTools.DatFiles/ItemDictionaryDB.cs b/SabreTools.DatFiles/ItemDictionaryDB.cs
index e58505b1..e996ba7c 100644
--- a/SabreTools.DatFiles/ItemDictionaryDB.cs
+++ b/SabreTools.DatFiles/ItemDictionaryDB.cs
@@ -1206,6 +1206,171 @@ namespace SabreTools.DatFiles
#region Splitting
+ ///
+ /// Use device_ref and optionally slotoption tags to add roms to the children
+ ///
+ /// True if only child device sets are touched, false for non-device sets
+ /// True if slotoptions tags are used as well, false otherwise
+ public bool AddRomsFromDevices(bool dev, bool useSlotOptions)
+ {
+ bool foundnew = false;
+ List games = [.. SortedKeys];
+ foreach (string game in games)
+ {
+ // Get the items for this game
+ var items = GetDatItemsForBucket(game);
+
+ // If the machine doesn't have items, we continue
+ if (items == null || items.Length == 0)
+ continue;
+
+ // Get the machine for the first item
+ var machine = GetMachineForItem(items[0].Item1);
+ if (machine.Item2 == null)
+ continue;
+
+ // If the machine (is/is not) a device, we want to continue
+ if (dev ^ (machine.Item2.GetBoolFieldValue(Models.Metadata.Machine.IsDeviceKey) == true))
+ continue;
+
+ // Get all device reference names from the current machine
+ List deviceReferences = items
+ .Where(i => i.Item2 is DeviceRef)
+ .Select(i => i.Item2 as DeviceRef)
+ .Select(dr => dr!.GetName())
+ .Distinct()
+ .ToList();
+
+ // Get all slot option names from the current machine
+ List slotOptions = items
+ .Where(i => i.Item2 is Slot)
+ .Select(i => i.Item2 as Slot)
+ .Where(s => s!.SlotOptionsSpecified)
+ .SelectMany(s => s!.GetFieldValue(Models.Metadata.Slot.SlotOptionKey)!)
+ .Select(so => so.GetStringFieldValue(Models.Metadata.SlotOption.DevNameKey))
+ .Distinct()
+ .ToList();
+
+ // If we're checking device references
+ if (deviceReferences.Any())
+ {
+ // Loop through all names and check the corresponding machines
+ List newDeviceReferences = [];
+ foreach (string? deviceReference in deviceReferences)
+ {
+ // If the device reference is invalid
+ if (deviceReference == null)
+ continue;
+
+ // If the machine doesn't exist then we continue
+ var devItems = GetDatItemsForBucket(deviceReference);
+ if (devItems == null || devItems.Length == 0)
+ continue;
+
+ // Add to the list of new device reference names
+ newDeviceReferences.AddRange(devItems
+ .Where(i => i.Item2 is DeviceRef)
+ .Select(i => (i.Item2 as DeviceRef)!.GetName()!));
+
+ // Set new machine information and add to the current machine
+ var copyFrom = GetMachineForItem(GetDatItemsForBucket(game)![0].Item1);
+ if (copyFrom.Item2 == null)
+ continue;
+
+ foreach ((long, DatItem) item in devItems)
+ {
+ // If the parent machine doesn't already contain this item, add it
+ if (!GetDatItemsForBucket(game)!
+ .Any(i => i.Item2.GetStringFieldValue(Models.Metadata.DatItem.TypeKey) == item.Item2.GetStringFieldValue(Models.Metadata.DatItem.TypeKey)
+ && i.Item2.GetName() == item.Item2.GetName()))
+ {
+ // Set that we found new items
+ foundnew = true;
+
+ // Clone the item and then add it
+ DatItem datItem = (item.Item2.Clone() as DatItem)!;
+ AddItem(datItem, machine.Item1);
+ }
+ }
+ }
+
+ // Now that every device reference is accounted for, add the new list of device references, if they don't already exist
+ foreach (string deviceReference in newDeviceReferences.Distinct())
+ {
+ if (!deviceReferences.Contains(deviceReference))
+ {
+ var deviceRef = new DeviceRef();
+ deviceRef.SetName(deviceReference);
+ AddItem(deviceRef, machine.Item1);
+ }
+ }
+ }
+
+ // If we're checking slotoptions
+ if (useSlotOptions && slotOptions.Any())
+ {
+ // Loop through all names and check the corresponding machines
+ List newSlotOptions = [];
+ foreach (string? slotOption in slotOptions)
+ {
+ // If the slot option is invalid
+ if (slotOption == null)
+ continue;
+
+ // If the machine doesn't exist then we continue
+ var slotItems = GetDatItemsForBucket(slotOption);
+ if (slotItems == null || slotItems.Length == 0)
+ continue;
+
+ // Add to the list of new slot option names
+ newSlotOptions.AddRange(slotItems
+ .Where(i => i.Item2 is Slot)
+ .Where(s => (s.Item2 as Slot)!.SlotOptionsSpecified)
+ .SelectMany(s => (s.Item2 as Slot)!.GetFieldValue(Models.Metadata.Slot.SlotOptionKey)!)
+ .Select(o => o.GetStringFieldValue(Models.Metadata.SlotOption.DevNameKey)!));
+
+ // Set new machine information and add to the current machine
+ var copyFrom = GetMachineForItem(GetDatItemsForBucket(game)![0].Item1);
+ if (copyFrom.Item2 == null)
+ continue;
+
+ foreach ((long, DatItem) item in slotItems)
+ {
+ // If the parent machine doesn't already contain this item, add it
+ if (!GetDatItemsForBucket(game)!
+ .Any(i => i.Item2.GetStringFieldValue(Models.Metadata.DatItem.TypeKey) == item.Item2.GetStringFieldValue(Models.Metadata.DatItem.TypeKey)
+ && i.Item2.GetName() == item.Item2.GetName()))
+ {
+ // Set that we found new items
+ foundnew = true;
+
+ // Clone the item and then add it
+ DatItem datItem = (item.Item2.Clone() as DatItem)!;
+ AddItem(datItem, machine.Item1);
+ }
+ }
+ }
+
+ // Now that every device is accounted for, add the new list of slot options, if they don't already exist
+ foreach (string slotOption in newSlotOptions.Distinct())
+ {
+ if (!slotOptions.Contains(slotOption))
+ {
+ var slotOptionItem = new SlotOption();
+ slotOptionItem.SetFieldValue(Models.Metadata.SlotOption.DevNameKey, slotOption);
+
+ var slotItem = new Slot();
+ slotItem.SetFieldValue(Models.Metadata.Slot.SlotOptionKey, [slotOptionItem]);
+
+ AddItem(slotItem, machine.Item1);
+ }
+ }
+ }
+ }
+
+ return foundnew;
+ }
+
///
/// Use cloneof tags to add roms to the children, setting the new romof tag in the process
///
diff --git a/SabreTools.Filtering/Splitter.cs b/SabreTools.Filtering/Splitter.cs
index f0d35b3a..fac4efed 100644
--- a/SabreTools.Filtering/Splitter.cs
+++ b/SabreTools.Filtering/Splitter.cs
@@ -109,7 +109,9 @@ namespace SabreTools.Filtering
// Now we want to loop through all of the games and set the correct information
while (AddRomsFromDevices(datFile, false, false)) ;
+ while (datFile.ItemsDB.AddRomsFromDevices(false, false)) ;
while (AddRomsFromDevices(datFile, true, false)) ;
+ while (datFile.ItemsDB.AddRomsFromDevices(true, false)) ;
// Then, remove the romof and cloneof tags so it's not picked up by the manager
RemoveTagsFromChild(datFile);
@@ -154,7 +156,9 @@ namespace SabreTools.Filtering
// Now we want to loop through all of the games and set the correct information
while (AddRomsFromDevices(datFile, true, true)) ;
+ while (datFile.ItemsDB.AddRomsFromDevices(true, true)) ;
AddRomsFromDevices(datFile, false, true);
+ datFile.ItemsDB.AddRomsFromDevices(false, true);
AddRomsFromParent(datFile);
datFile.ItemsDB.AddRomsFromParent();
@@ -439,8 +443,6 @@ namespace SabreTools.Filtering
return foundnew;
}
- // TODO: Add AddRomsFromDevicesDB
-
///
/// Use cloneof tags to add roms to the children, setting the new romof tag in the process
///