Files
SabreTools.Serialization/SabreTools.Metadata.DatFiles/DatFile.FromMetadata.cs

708 lines
37 KiB
C#
Raw Normal View History

2026-03-24 18:03:01 -04:00
using System;
using System.Collections.Generic;
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
using System.Threading.Tasks;
#endif
using SabreTools.Metadata.Filter;
using SabreTools.Metadata.DatItems;
using SabreTools.Metadata.DatItems.Formats;
2026-03-26 22:51:14 -04:00
using MergingFlag = SabreTools.Data.Models.Metadata.MergingFlag;
using NodumpFlag = SabreTools.Data.Models.Metadata.NodumpFlag;
using PackingFlag = SabreTools.Data.Models.Metadata.PackingFlag;
2026-03-24 18:03:01 -04:00
#pragma warning disable IDE0056 // Use index operator
#pragma warning disable IDE0060 // Remove unused parameter
namespace SabreTools.Metadata.DatFiles
{
public partial class DatFile
{
#region From Metadata
/// <summary>
/// Convert metadata information
/// </summary>
/// <param name="item">Metadata file to convert</param>
/// <param name="filename">Name of the file to be parsed</param>
/// <param name="indexId">Index ID for the DAT</param>
/// <param name="keep">True if full pathnames are to be kept, false otherwise</param>
/// <param name="statsOnly">True to only add item statistics while parsing, false otherwise</param>
/// <param name="filterRunner">Optional FilterRunner to filter items on parse</param>
internal void ConvertFromMetadata(Data.Models.Metadata.MetadataFile? item,
string filename,
int indexId,
bool keep,
bool statsOnly,
FilterRunner? filterRunner)
{
// If the metadata file is invalid, we can't do anything
if (item is null || item.Count == 0)
return;
// Create an internal source and add to the dictionary
var source = new Source(indexId, filename);
// long sourceIndex = AddSourceDB(source);
// Get the header from the metadata
var header = item.Read<Data.Models.Metadata.Header>(Data.Models.Metadata.MetadataFile.HeaderKey);
if (header is not null)
ConvertHeader(header, keep);
// Get the machines from the metadata
2026-03-26 15:16:12 -04:00
var machines = item.ReadArray<Data.Models.Metadata.Machine>(Data.Models.Metadata.MetadataFile.MachineKey);
2026-03-24 18:03:01 -04:00
if (machines is not null)
ConvertMachines(machines, source, sourceIndex: 0, statsOnly, filterRunner);
}
/// <summary>
/// Convert header information
/// </summary>
/// <param name="item">Header to convert</param>
/// <param name="keep">True if full pathnames are to be kept, false otherwise</param>
private void ConvertHeader(Data.Models.Metadata.Header? item, bool keep)
{
// If the header is invalid, we can't do anything
if (item is null || item.Count == 0)
return;
// Create an internal header
var header = new DatHeader(item);
2026-04-01 13:18:45 -04:00
Header.Name = header.Name;
2026-03-24 18:03:01 -04:00
// Convert subheader values
2026-03-26 16:52:07 -04:00
var canOpen = item.Read<Data.Models.OfflineList.CanOpen>(Data.Models.Metadata.Header.CanOpenKey);
if (canOpen?.Extension is not null)
Header.Write<string[]?>(Data.Models.Metadata.Header.CanOpenKey, canOpen.Extension);
2026-03-24 18:03:01 -04:00
2026-03-26 16:52:07 -04:00
var images = item.Read<Data.Models.OfflineList.Images>(Data.Models.Metadata.Header.ImagesKey);
if (images is not null)
2026-03-26 13:52:00 -04:00
Header.Write<Data.Models.OfflineList.Images?>(Data.Models.Metadata.Header.ImagesKey, images);
2026-03-24 18:03:01 -04:00
2026-03-26 16:52:07 -04:00
var infos = item.Read<Data.Models.OfflineList.Infos>(Data.Models.Metadata.Header.InfosKey);
if (infos is not null)
2026-03-26 13:52:00 -04:00
Header.Write<Data.Models.OfflineList.Infos?>(Data.Models.Metadata.Header.InfosKey, infos);
2026-03-24 18:03:01 -04:00
2026-03-26 16:52:07 -04:00
var newDat = item.Read<Data.Models.OfflineList.NewDat>(Data.Models.Metadata.Header.NewDatKey);
if (newDat is not null)
2026-03-26 13:52:00 -04:00
Header.Write<Data.Models.OfflineList.NewDat?>(Data.Models.Metadata.Header.NewDatKey, newDat);
2026-03-24 18:03:01 -04:00
2026-03-26 16:52:07 -04:00
var search = item.Read<Data.Models.OfflineList.Search>(Data.Models.Metadata.Header.SearchKey);
if (search is not null)
2026-03-26 13:52:00 -04:00
Header.Write<Data.Models.OfflineList.Search?>(Data.Models.Metadata.Header.SearchKey, search);
2026-03-24 18:03:01 -04:00
// Selectively set all possible fields -- TODO: Figure out how to make this less manual
2026-03-26 13:52:00 -04:00
if (Header.ReadString(Data.Models.Metadata.Header.AuthorKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.AuthorKey, header.ReadString(Data.Models.Metadata.Header.AuthorKey));
2026-04-02 02:18:08 -04:00
if (Header.BiosMode == MergingFlag.None)
Header.BiosMode = header.BiosMode;
2026-03-26 13:52:00 -04:00
if (Header.ReadString(Data.Models.Metadata.Header.BuildKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.BuildKey, header.ReadString(Data.Models.Metadata.Header.BuildKey));
if (Header.ReadString(Data.Models.Metadata.Header.CategoryKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.CategoryKey, header.ReadString(Data.Models.Metadata.Header.CategoryKey));
if (Header.ReadString(Data.Models.Metadata.Header.CommentKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.CommentKey, header.ReadString(Data.Models.Metadata.Header.CommentKey));
if (Header.ReadString(Data.Models.Metadata.Header.DateKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.DateKey, header.ReadString(Data.Models.Metadata.Header.DateKey));
if (Header.ReadString(Data.Models.Metadata.Header.DatVersionKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.DatVersionKey, header.ReadString(Data.Models.Metadata.Header.DatVersionKey));
2026-04-01 21:59:16 -04:00
if (Header.Debug is null)
Header.Debug = header.Debug;
2026-04-02 11:18:49 -04:00
if (Header.Description is null)
Header.Description = header.Description;
2026-03-26 13:52:00 -04:00
if (Header.ReadString(Data.Models.Metadata.Header.EmailKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.EmailKey, header.ReadString(Data.Models.Metadata.Header.EmailKey));
if (Header.ReadString(Data.Models.Metadata.Header.EmulatorVersionKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.EmulatorVersionKey, header.ReadString(Data.Models.Metadata.Header.EmulatorVersionKey));
2026-04-02 02:18:08 -04:00
if (Header.ForceMerging == MergingFlag.None)
Header.ForceMerging = header.ForceMerging;
if (Header.ForceNodump == NodumpFlag.None)
Header.ForceNodump = header.ForceNodump;
if (Header.ForcePacking == PackingFlag.None)
Header.ForcePacking = header.ForcePacking;
2026-04-01 21:59:16 -04:00
if (Header.ForceZipping is null)
Header.ForceZipping = header.ForceZipping;
2026-03-26 13:52:00 -04:00
if (Header.ReadString(Data.Models.Metadata.Header.HeaderKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.HeaderKey, header.ReadString(Data.Models.Metadata.Header.HeaderKey));
if (Header.ReadString(Data.Models.Metadata.Header.HomepageKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.HomepageKey, header.ReadString(Data.Models.Metadata.Header.HomepageKey));
if (Header.ReadString(Data.Models.Metadata.Header.IdKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.IdKey, header.ReadString(Data.Models.Metadata.Header.IdKey));
if (Header.ReadString(Data.Models.Metadata.Header.ImFolderKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.ImFolderKey, header.ReadString(Data.Models.Metadata.Header.ImFolderKey));
2026-04-01 21:59:16 -04:00
if (Header.LockBiosMode is null)
Header.LockBiosMode = header.LockBiosMode;
if (Header.LockRomMode is null)
Header.LockRomMode = header.LockRomMode;
if (Header.LockSampleMode is null)
Header.LockSampleMode = header.LockSampleMode;
2026-03-26 13:52:00 -04:00
if (Header.ReadString(Data.Models.Metadata.Header.MameConfigKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.MameConfigKey, header.ReadString(Data.Models.Metadata.Header.MameConfigKey));
2026-04-01 13:18:45 -04:00
if (Header.Name is null)
Header.Name = header.Name;
2026-03-26 13:52:00 -04:00
if (Header.ReadString(Data.Models.Metadata.Header.NotesKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.NotesKey, header.ReadString(Data.Models.Metadata.Header.NotesKey));
if (Header.ReadString(Data.Models.Metadata.Header.PluginKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.PluginKey, header.ReadString(Data.Models.Metadata.Header.PluginKey));
if (Header.ReadString(Data.Models.Metadata.Header.RefNameKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.RefNameKey, header.ReadString(Data.Models.Metadata.Header.RefNameKey));
2026-04-02 02:18:08 -04:00
if (Header.RomMode == MergingFlag.None)
Header.RomMode = header.RomMode;
2026-03-26 13:52:00 -04:00
if (Header.ReadString(Data.Models.Metadata.Header.RomTitleKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.RomTitleKey, header.ReadString(Data.Models.Metadata.Header.RomTitleKey));
if (Header.ReadString(Data.Models.Metadata.Header.RootDirKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.RootDirKey, header.ReadString(Data.Models.Metadata.Header.RootDirKey));
2026-04-02 02:18:08 -04:00
if (Header.SampleMode == MergingFlag.None)
Header.SampleMode = header.SampleMode;
2026-03-26 13:52:00 -04:00
if (Header.ReadString(Data.Models.Metadata.Header.SchemaLocationKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.SchemaLocationKey, header.ReadString(Data.Models.Metadata.Header.SchemaLocationKey));
if (Header.ReadString(Data.Models.Metadata.Header.ScreenshotsHeightKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.ScreenshotsHeightKey, header.ReadString(Data.Models.Metadata.Header.ScreenshotsHeightKey));
if (Header.ReadString(Data.Models.Metadata.Header.ScreenshotsWidthKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.ScreenshotsWidthKey, header.ReadString(Data.Models.Metadata.Header.ScreenshotsWidthKey));
if (Header.ReadString(Data.Models.Metadata.Header.SystemKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.SystemKey, header.ReadString(Data.Models.Metadata.Header.SystemKey));
if (Header.ReadString(Data.Models.Metadata.Header.TimestampKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.TimestampKey, header.ReadString(Data.Models.Metadata.Header.TimestampKey));
if (Header.ReadString(Data.Models.Metadata.Header.TypeKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.TypeKey, header.ReadString(Data.Models.Metadata.Header.TypeKey));
if (Header.ReadString(Data.Models.Metadata.Header.UrlKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.UrlKey, header.ReadString(Data.Models.Metadata.Header.UrlKey));
if (Header.ReadString(Data.Models.Metadata.Header.VersionKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.VersionKey, header.ReadString(Data.Models.Metadata.Header.VersionKey));
2026-03-24 18:03:01 -04:00
// Handle implied SuperDAT
2026-04-01 13:18:45 -04:00
if (Header.Name?.Contains(" - SuperDAT") == true && keep)
2026-03-24 18:03:01 -04:00
{
2026-03-26 13:52:00 -04:00
if (Header.ReadString(Data.Models.Metadata.Header.TypeKey) is null)
Header.Write<string?>(Data.Models.Metadata.Header.TypeKey, "SuperDAT");
2026-03-24 18:03:01 -04:00
}
}
/// <summary>
/// Convert machines information
/// </summary>
/// <param name="items">Machine array to convert</param>
/// <param name="source">Source to use with the converted items</param>
/// <param name="sourceIndex">Index of the Source to use with the converted items</param>
/// <param name="statsOnly">True to only add item statistics while parsing, false otherwise</param>
/// <param name="filterRunner">Optional FilterRunner to filter items on parse</param>
private void ConvertMachines(Data.Models.Metadata.Machine[]? items,
Source source,
long sourceIndex,
bool statsOnly,
FilterRunner? filterRunner)
{
// If the array is invalid, we can't do anything
if (items is null || items.Length == 0)
return;
// Loop through the machines and add
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
Parallel.ForEach(items, machine =>
#else
foreach (var machine in items)
#endif
{
ConvertMachine(machine, source, sourceIndex, statsOnly, filterRunner);
#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
});
#else
}
#endif
}
/// <summary>
/// Convert machine information
/// </summary>
/// <param name="item">Machine to convert</param>
/// <param name="source">Source to use with the converted items</param>
/// <param name="sourceIndex">Index of the Source to use with the converted items</param>
/// <param name="statsOnly">True to only add item statistics while parsing, false otherwise</param>
/// <param name="filterRunner">Optional FilterRunner to filter items on parse</param>
private void ConvertMachine(Data.Models.Metadata.Machine? item,
Source source,
long sourceIndex,
bool statsOnly,
FilterRunner? filterRunner)
{
// If the machine is invalid, we can't do anything
if (item is null || item.Count == 0)
return;
// If the machine doesn't pass the filter
if (filterRunner is not null && !filterRunner.Run(item))
return;
// Create an internal machine and add to the dictionary
var machine = new Machine(item);
// long machineIndex = AddMachineDB(machine);
// Convert items in the machine
if (item.ContainsKey(Data.Models.Metadata.Machine.AdjusterKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Adjuster>(Data.Models.Metadata.Machine.AdjusterKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Adjuster(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.ArchiveKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Archive>(Data.Models.Metadata.Machine.ArchiveKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Archive(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.BiosSetKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.BiosSet>(Data.Models.Metadata.Machine.BiosSetKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new BiosSet(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.ChipKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Chip>(Data.Models.Metadata.Machine.ChipKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Chip(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.ConfigurationKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Configuration>(Data.Models.Metadata.Machine.ConfigurationKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Configuration(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.DeviceKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Device>(Data.Models.Metadata.Machine.DeviceKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Device(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.DeviceRefKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.DeviceRef>(Data.Models.Metadata.Machine.DeviceRefKey) ?? [];
2026-03-24 18:03:01 -04:00
// Do not filter these due to later use
Array.ForEach(items, item =>
{
var datItem = new DeviceRef(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.DipSwitchKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.DipSwitch>(Data.Models.Metadata.Machine.DipSwitchKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new DipSwitch(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.DiskKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Disk>(Data.Models.Metadata.Machine.DiskKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Disk(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.DisplayKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Display>(Data.Models.Metadata.Machine.DisplayKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Display(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.DriverKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Driver>(Data.Models.Metadata.Machine.DriverKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Driver(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.DumpKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Dump>(Data.Models.Metadata.Machine.DumpKey) ?? [];
2026-03-24 18:03:01 -04:00
for (int i = 0; i < items.Length; i++)
{
var datItem = new Rom(items[i], machine, source, i);
2026-04-02 13:21:37 -04:00
if (datItem.Name is not null)
2026-03-24 18:03:01 -04:00
{
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
}
}
}
if (item.ContainsKey(Data.Models.Metadata.Machine.FeatureKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Feature>(Data.Models.Metadata.Machine.FeatureKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Feature(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.InfoKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Info>(Data.Models.Metadata.Machine.InfoKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Info(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.InputKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Input>(Data.Models.Metadata.Machine.InputKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Input(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.MediaKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Media>(Data.Models.Metadata.Machine.MediaKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Media(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.PartKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Part>(Data.Models.Metadata.Machine.PartKey) ?? [];
2026-03-24 18:03:01 -04:00
ProcessItems(items, machine, machineIndex: 0, source, sourceIndex, statsOnly, filterRunner);
}
if (item.ContainsKey(Data.Models.Metadata.Machine.PortKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Port>(Data.Models.Metadata.Machine.PortKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Port(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.RamOptionKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.RamOption>(Data.Models.Metadata.Machine.RamOptionKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new RamOption(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.ReleaseKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Release>(Data.Models.Metadata.Machine.ReleaseKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Release(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.RomKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Rom>(Data.Models.Metadata.Machine.RomKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Rom(item, machine, source);
2026-03-26 13:52:00 -04:00
datItem.Write<Source?>(DatItem.SourceKey, source);
2026-03-24 18:03:01 -04:00
datItem.CopyMachineInformation(machine);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.SampleKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Sample>(Data.Models.Metadata.Machine.SampleKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Sample(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.SharedFeatKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.SharedFeat>(Data.Models.Metadata.Machine.SharedFeatKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new SharedFeat(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.SlotKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Slot>(Data.Models.Metadata.Machine.SlotKey) ?? [];
2026-03-24 18:03:01 -04:00
// Do not filter these due to later use
Array.ForEach(items, item =>
{
var datItem = new Slot(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.SoftwareListKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.SoftwareList>(Data.Models.Metadata.Machine.SoftwareListKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new SoftwareList(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.SoundKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Sound>(Data.Models.Metadata.Machine.SoundKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Sound(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
if (item.ContainsKey(Data.Models.Metadata.Machine.VideoKey))
{
2026-03-26 15:16:12 -04:00
var items = item.ReadArray<Data.Models.Metadata.Video>(Data.Models.Metadata.Machine.VideoKey) ?? [];
2026-03-24 18:03:01 -04:00
var filtered = filterRunner is null ? items : Array.FindAll(items, i => filterRunner.Run(item));
Array.ForEach(filtered, item =>
{
var datItem = new Display(item, machine, source);
AddItem(datItem, statsOnly);
// AddItemDB(datItem, machineIndex, sourceIndex, statsOnly);
});
}
}
/// <summary>
/// Convert Part information
/// </summary>
/// <param name="items">Array of internal items to convert</param>
/// <param name="machine">Machine to use with the converted items</param>
/// <param name="machineIndex">Index of the Machine to use with the converted items</param>
/// <param name="source">Source to use with the converted items</param>
/// <param name="sourceIndex">Index of the Source to use with the converted items</param>
/// <param name="statsOnly">True to only add item statistics while parsing, false otherwise</param>
/// <param name="filterRunner">Optional FilterRunner to filter items on parse</param>
private void ProcessItems(Data.Models.Metadata.Part[] items,
Machine machine,
long machineIndex,
Source source,
long sourceIndex,
bool statsOnly,
FilterRunner? filterRunner)
{
// If the array is null or empty, return without processing
if (items.Length == 0)
return;
// Loop through the items and add
foreach (var item in items)
{
var partItem = new Part(item, machine, source);
// Handle subitems
2026-03-26 15:16:12 -04:00
var dataAreas = item.ReadArray<Data.Models.Metadata.DataArea>(Data.Models.Metadata.Part.DataAreaKey);
2026-03-24 18:03:01 -04:00
if (dataAreas is not null)
{
foreach (var dataArea in dataAreas)
{
var dataAreaItem = new DataArea(dataArea, machine, source);
2026-03-26 15:16:12 -04:00
var roms = dataArea.ReadArray<Data.Models.Metadata.Rom>(Data.Models.Metadata.DataArea.RomKey);
2026-03-24 18:03:01 -04:00
if (roms is null)
continue;
// Handle "offset" roms
List<Rom> addRoms = [];
foreach (var rom in roms)
{
// If the item doesn't pass the filter
if (filterRunner is not null && !filterRunner.Run(rom))
continue;
// Convert the item
var romItem = new Rom(rom, machine, source);
2026-03-26 13:52:00 -04:00
long? size = romItem.ReadLong(Data.Models.Metadata.Rom.SizeKey);
2026-03-24 18:03:01 -04:00
// If the rom is a continue or ignore
2026-04-02 02:18:08 -04:00
Data.Models.Metadata.LoadFlag? loadFlag = rom.LoadFlag;
2026-03-24 18:03:01 -04:00
if (loadFlag is not null
2026-04-02 02:18:08 -04:00
&& (loadFlag == Data.Models.Metadata.LoadFlag.Continue
|| loadFlag == Data.Models.Metadata.LoadFlag.Ignore))
2026-03-24 18:03:01 -04:00
{
var lastRom = addRoms[addRoms.Count - 1];
2026-03-26 13:52:00 -04:00
long? lastSize = lastRom.ReadLong(Data.Models.Metadata.Rom.SizeKey);
lastRom.Write(Data.Models.Metadata.Rom.SizeKey, lastSize + size);
2026-03-24 18:03:01 -04:00
continue;
}
2026-03-26 13:52:00 -04:00
romItem.Write<DataArea?>(Rom.DataAreaKey, dataAreaItem);
romItem.Write<Part?>(Rom.PartKey, partItem);
2026-03-24 18:03:01 -04:00
addRoms.Add(romItem);
}
// Add all of the adjusted roms
foreach (var romItem in addRoms)
{
AddItem(romItem, statsOnly);
// AddItemDB(romItem, machineIndex, sourceIndex, statsOnly);
}
}
}
2026-03-26 15:16:12 -04:00
var diskAreas = item.ReadArray<Data.Models.Metadata.DiskArea>(Data.Models.Metadata.Part.DiskAreaKey);
2026-03-24 18:03:01 -04:00
if (diskAreas is not null)
{
foreach (var diskArea in diskAreas)
{
var diskAreaitem = new DiskArea(diskArea, machine, source);
2026-03-26 15:16:12 -04:00
var disks = diskArea.ReadArray<Data.Models.Metadata.Disk>(Data.Models.Metadata.DiskArea.DiskKey);
2026-03-24 18:03:01 -04:00
if (disks is null)
continue;
foreach (var disk in disks)
{
// If the item doesn't pass the filter
if (filterRunner is not null && !filterRunner.Run(disk))
continue;
var diskItem = new Disk(disk, machine, source);
2026-03-26 13:52:00 -04:00
diskItem.Write<DiskArea?>(Disk.DiskAreaKey, diskAreaitem);
diskItem.Write<Part?>(Disk.PartKey, partItem);
2026-03-24 18:03:01 -04:00
AddItem(diskItem, statsOnly);
// AddItemDB(diskItem, machineIndex, sourceIndex, statsOnly);
}
}
}
2026-03-26 15:16:12 -04:00
var dipSwitches = item.ReadArray<Data.Models.Metadata.DipSwitch>(Data.Models.Metadata.Part.DipSwitchKey);
2026-03-24 18:03:01 -04:00
if (dipSwitches is not null)
{
foreach (var dipSwitch in dipSwitches)
{
// If the item doesn't pass the filter
if (filterRunner is not null && !filterRunner.Run(dipSwitch))
continue;
var dipSwitchItem = new DipSwitch(dipSwitch, machine, source);
2026-03-26 13:52:00 -04:00
dipSwitchItem.Write<Part?>(DipSwitch.PartKey, partItem);
2026-03-24 18:03:01 -04:00
AddItem(dipSwitchItem, statsOnly);
// AddItemDB(dipSwitchItem, machineIndex, sourceIndex, statsOnly);
}
}
2026-03-26 15:16:12 -04:00
var partFeatures = item.ReadArray<Data.Models.Metadata.Feature>(Data.Models.Metadata.Part.FeatureKey);
2026-03-24 18:03:01 -04:00
if (partFeatures is not null)
{
foreach (var partFeature in partFeatures)
{
// If the item doesn't pass the filter
if (filterRunner is not null && !filterRunner.Run(partFeature))
continue;
var partFeatureItem = new PartFeature(partFeature);
2026-03-26 13:52:00 -04:00
partFeatureItem.Write<Part?>(DipSwitch.PartKey, partItem);
partFeatureItem.Write<Source?>(DatItem.SourceKey, source);
2026-03-24 18:03:01 -04:00
partFeatureItem.CopyMachineInformation(machine);
AddItem(partFeatureItem, statsOnly);
// AddItemDB(partFeatureItem, machineIndex, sourceIndex, statsOnly);
}
}
}
}
#endregion
}
}