diff --git a/SabreTools.DatFiles/DatFile.MetadataConverter.cs b/SabreTools.DatFiles/DatFile.MetadataConverter.cs index 196d3832..729a774c 100644 --- a/SabreTools.DatFiles/DatFile.MetadataConverter.cs +++ b/SabreTools.DatFiles/DatFile.MetadataConverter.cs @@ -5,7 +5,6 @@ using SabreTools.Core.Tools; namespace SabreTools.DatFiles { - // TODO: Convert nested items (e.g. Configuration, DipLocation) public partial class DatFile { #region Converters @@ -646,32 +645,6 @@ namespace SabreTools.DatFiles } } - /// - /// Convert DataArea information - /// - /// Array of internal items to convert - /// Machine to use with the converted items - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - private void ProcessItems(Models.Metadata.DataArea[]? items, DatItems.Machine machine, string filename, int indexId, bool statsOnly) - { - // If the array is null or empty, return without processing - if (items == null || items.Length == 0) - return; - - // TODO: Extract Roms - - // Loop through the items and add - foreach (var item in items) - { - var datItem = new DatItems.Formats.DataArea(item); - datItem.SetFieldValue(DatItems.DatItem.SourceKey, new DatItems.Source { Index = indexId, Name = filename }); - datItem.CopyMachineInformation(machine); - ParseAddHelper(datItem, statsOnly); - } - } - /// /// Convert Device information /// @@ -742,30 +715,6 @@ namespace SabreTools.DatFiles } } - /// - /// Convert DipLocation information - /// - /// Array of internal items to convert - /// Machine to use with the converted items - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - private void ProcessItems(Models.Metadata.DipLocation[]? items, DatItems.Machine machine, string filename, int indexId, bool statsOnly) - { - // If the array is null or empty, return without processing - if (items == null || items.Length == 0) - return; - - // Loop through the items and add - foreach (var item in items) - { - var datItem = new DatItems.Formats.DipLocation(item); - datItem.SetFieldValue(DatItems.DatItem.SourceKey, new DatItems.Source { Index = indexId, Name = filename }); - datItem.CopyMachineInformation(machine); - ParseAddHelper(datItem, statsOnly); - } - } - /// /// Convert DipSwitch information /// @@ -833,30 +782,6 @@ namespace SabreTools.DatFiles } } - /// - /// Convert DipValue information - /// - /// Array of internal items to convert - /// Machine to use with the converted items - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - private void ProcessItems(Models.Metadata.DipValue[]? items, DatItems.Machine machine, string filename, int indexId, bool statsOnly) - { - // If the array is null or empty, return without processing - if (items == null || items.Length == 0) - return; - - // Loop through the items and add - foreach (var item in items) - { - var datItem = new DatItems.Formats.DipValue(item); - datItem.SetFieldValue(DatItems.DatItem.SourceKey, new DatItems.Source { Index = indexId, Name = filename }); - datItem.CopyMachineInformation(machine); - ParseAddHelper(datItem, statsOnly); - } - } - /// /// Convert Disk information /// @@ -881,32 +806,6 @@ namespace SabreTools.DatFiles } } - /// - /// Convert DiskArea information - /// - /// Array of internal items to convert - /// Machine to use with the converted items - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - private void ProcessItems(Models.Metadata.DiskArea[]? items, DatItems.Machine machine, string filename, int indexId, bool statsOnly) - { - // If the array is null or empty, return without processing - if (items == null || items.Length == 0) - return; - - // TODO: Extract Disks - - // Loop through the items and add - foreach (var item in items) - { - var datItem = new DatItems.Formats.DiskArea(item); - datItem.SetFieldValue(DatItems.DatItem.SourceKey, new DatItems.Source { Index = indexId, Name = filename }); - datItem.CopyMachineInformation(machine); - ParseAddHelper(datItem, statsOnly); - } - } - /// /// Convert Display information /// @@ -1147,17 +1046,81 @@ namespace SabreTools.DatFiles if (items == null || items.Length == 0) return; - // TODO: Extract DataAreas - // TODO: Extract DiskAreas - // TODO: Extract DipSwitches - // Loop through the items and add foreach (var item in items) { - var datItem = new DatItems.Formats.Part(item); - datItem.SetFieldValue(DatItems.DatItem.SourceKey, new DatItems.Source { Index = indexId, Name = filename }); - datItem.CopyMachineInformation(machine); - ParseAddHelper(datItem, statsOnly); + var partItem = new DatItems.Formats.Part(item); + + // Handle subitems + var dataAreas = ReadItemArray(item, Models.Metadata.Part.DataAreaKey); + if (dataAreas != null) + { + foreach (var dataArea in dataAreas) + { + var dataAreaItem = new DatItems.Formats.DataArea(dataArea); + var roms = ReadItemArray(dataArea, Models.Metadata.DataArea.RomKey); + if (roms == null) + continue; + + foreach (var rom in roms) + { + var romItem = new DatItems.Formats.Rom(rom); + romItem.SetFieldValue(DatItems.Formats.Rom.DataAreaKey, dataAreaItem); + romItem.SetFieldValue(DatItems.Formats.Rom.PartKey, partItem); + romItem.SetFieldValue(DatItems.DatItem.SourceKey, new DatItems.Source { Index = indexId, Name = filename }); + romItem.CopyMachineInformation(machine); + ParseAddHelper(romItem, statsOnly); + } + } + } + + var diskAreas = ReadItemArray(item, Models.Metadata.Part.DiskAreaKey); + if (diskAreas != null) + { + foreach (var diskArea in diskAreas) + { + var diskAreaitem = new DatItems.Formats.DiskArea(diskArea); + var disks = ReadItemArray(diskArea, Models.Metadata.DiskArea.DiskKey); + if (disks == null) + continue; + + foreach (var disk in disks) + { + var diskItem = new DatItems.Formats.Disk(disk); + diskItem.SetFieldValue(DatItems.Formats.Disk.DiskAreaKey, diskAreaitem); + diskItem.SetFieldValue(DatItems.Formats.Disk.PartKey, partItem); + diskItem.SetFieldValue(DatItems.DatItem.SourceKey, new DatItems.Source { Index = indexId, Name = filename }); + diskItem.CopyMachineInformation(machine); + ParseAddHelper(diskItem, statsOnly); + } + } + + var dipSwitches = ReadItemArray(item, Models.Metadata.Part.DipSwitchKey); + if (dipSwitches != null) + { + foreach (var dipSwitch in dipSwitches) + { + var dipSwitchItem = new DatItems.Formats.DipSwitch(dipSwitch); + dipSwitchItem.SetFieldValue(DatItems.DatItem.SourceKey, new DatItems.Source { Index = indexId, Name = filename }); + dipSwitchItem.CopyMachineInformation(machine); + + var dipValues = ReadItemArray(dipSwitch, Models.Metadata.DipSwitch.DipValueKey); + if (dipValues != null) + { + var subValues = new List(); + foreach (var value in dipValues) + { + var subItem = new DatItems.Formats.DipValue(value); + subValues.Add(subItem); + } + + dipSwitchItem.SetFieldValue(Models.Metadata.DipSwitch.DipValueKey, [.. subValues]); + } + + ParseAddHelper(dipSwitchItem, statsOnly); + } + } + } } } diff --git a/SabreTools.DatFiles/Formats/SoftwareList.Reader.cs b/SabreTools.DatFiles/Formats/SoftwareList.Reader.cs index ad39518a..fa8fa8b5 100644 --- a/SabreTools.DatFiles/Formats/SoftwareList.Reader.cs +++ b/SabreTools.DatFiles/Formats/SoftwareList.Reader.cs @@ -1,10 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using SabreTools.Core; -using SabreTools.Core.Tools; -using SabreTools.DatItems; -using SabreTools.DatItems.Formats; namespace SabreTools.DatFiles.Formats { @@ -20,12 +14,10 @@ namespace SabreTools.DatFiles.Formats { // Deserialize the input file var softwarelist = new Serialization.Files.SoftwareList().Deserialize(filename); + var metadata = new Serialization.CrossModel.SoftwareList().Serialize(softwarelist); - // Convert the header to the internal format - ConvertHeader(softwarelist, keep); - - // Convert the software data to the internal format - ConvertSoftware(softwarelist?.Software, filename, indexId, statsOnly); + // Convert to the internal format + ConvertMetadata(metadata, filename, indexId, keep, statsOnly); } catch (Exception ex) when (!throwOnError) { @@ -33,369 +25,5 @@ namespace SabreTools.DatFiles.Formats logger.Error(ex, message); } } - - #region Converters - - /// - /// Convert header information - /// - /// Deserialized model to convert - /// True if full pathnames are to be kept, false otherwise (default) - private void ConvertHeader(Models.SoftwareList.SoftwareList? softwarelist, bool keep) - { - // If the datafile is missing, we can't do anything - if (softwarelist == null) - return; - - if (Header.GetFieldValue(Models.Metadata.Header.NameKey) == null) - Header.SetFieldValue(Models.Metadata.Header.NameKey, softwarelist.Name); - if (Header.GetFieldValue(Models.Metadata.Header.DescriptionKey) == null) - Header.SetFieldValue(Models.Metadata.Header.DescriptionKey, softwarelist.Description); - if (Header.GetFieldValue(Models.Metadata.Header.CommentKey) == null) - Header.SetFieldValue(Models.Metadata.Header.CommentKey, softwarelist.Notes); - - // Handle implied SuperDAT - if (Header.GetFieldValue(Models.Metadata.Header.NameKey)?.Contains(" - SuperDAT") == true && keep) - { - if (Header.GetFieldValue(Models.Metadata.Header.TypeKey) == null) - Header.SetFieldValue(Models.Metadata.Header.TypeKey, "SuperDAT"); - } - } - - /// - /// Convert software information - /// - /// Array of deserialized models to convert - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - private void ConvertSoftware(Models.SoftwareList.Software[]? software, string filename, int indexId, bool statsOnly) - { - // If the game array is missing, we can't do anything - if (software == null || !software.Any()) - return; - - // Loop through the software and add - foreach (var sw in software) - { - ConvertSoftware(sw, filename, indexId, statsOnly); - } - } - - /// - /// Convert software information - /// - /// Deserialized model to convert - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - private void ConvertSoftware(Models.SoftwareList.Software software, string filename, int indexId, bool statsOnly) - { - // If the game is missing, we can't do anything - if (software == null) - return; - - // Create the machine for copying information - var machine = new Machine(); - machine.SetFieldValue(Models.Metadata.Machine.CloneOfKey, software.CloneOf); - machine.SetFieldValue(Models.Metadata.Machine.CommentKey, software.Notes); - machine.SetFieldValue(Models.Metadata.Machine.DescriptionKey, software.Description); - machine.SetFieldValue(Models.Metadata.Machine.NameKey, software.Name); - machine.SetFieldValue(Models.Metadata.Machine.PublisherKey, software.Publisher); - machine.SetFieldValue(Models.Metadata.Machine.SupportedKey, software.Supported.AsEnumValue()); - machine.SetFieldValue(Models.Metadata.Machine.YearKey, software.Year); - - // Add all Info objects - foreach (var info in software.Info ?? []) - { - var infoItem = new Info(); - infoItem.SetName(info.Name); - infoItem.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - infoItem.SetFieldValue(Models.Metadata.Info.ValueKey, info.Value); - - infoItem.CopyMachineInformation(machine); - ParseAddHelper(infoItem, statsOnly); - } - - // Add all SharedFeat objects - foreach (var sharedfeat in software.SharedFeat ?? []) - { - var sharedfeatItem = new SharedFeat(); - sharedfeatItem.SetName(sharedfeat.Name); - sharedfeatItem.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - sharedfeatItem.SetFieldValue(Models.Metadata.SharedFeat.ValueKey, sharedfeat.Value); - - sharedfeatItem.CopyMachineInformation(machine); - ParseAddHelper(sharedfeatItem, statsOnly); - } - - // Check if there are any items - bool containsItems = false; - - // Loop through each type of item - ConvertPart(software.Part, machine, filename, indexId, statsOnly, ref containsItems); - - // If we had no items, create a Blank placeholder - if (!containsItems) - { - var blank = new Blank(); - blank.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - - blank.CopyMachineInformation(machine); - ParseAddHelper(blank, statsOnly); - } - } - - /// - /// Convert Part information - /// - /// Array of deserialized models to convert - /// Prefilled machine to use - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - /// True if there were any items in the array, false otherwise - private void ConvertPart(Models.SoftwareList.Part[]? parts, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems) - { - // If the parts array is missing, we can't do anything - if (parts == null || !parts.Any()) - return; - - foreach (var part in parts) - { - var item = new Part(); - item.SetName(part.Name); - item.SetFieldValue(Models.Metadata.Part.InterfaceKey, part.Interface); - item.SetFieldValue(Models.Metadata.Part.FeatureKey, CreateFeatures(part.Feature, machine, filename, indexId, statsOnly)); - item.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - - item.CopyMachineInformation(machine); - - ConvertDataArea(part.DataArea, item, machine, filename, indexId, statsOnly, ref containsItems); - ConvertDiskArea(part.DiskArea, item, machine, filename, indexId, statsOnly, ref containsItems); - ConvertDipSwitch(part.DipSwitch, item, machine, filename, indexId, statsOnly, ref containsItems); - } - } - - /// - /// Convert Feature information - /// - /// Array of deserialized models to convert - /// Prefilled machine to use - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - private static PartFeature[]? CreateFeatures(Models.SoftwareList.Feature[]? features, Machine machine, string filename, int indexId, bool statsOnly) - { - // If the feature array is missing, we can't do anything - if (features == null || !features.Any()) - return null; - - var partFeatures = new List(); - foreach (var feature in features) - { - var item = new PartFeature(); - item.SetName(feature.Name); - item.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - item.SetFieldValue(Models.Metadata.Feature.ValueKey, feature.Value); - - item.CopyMachineInformation(machine); - partFeatures.Add(item); - } - - return [.. partFeatures]; - } - - /// - /// Convert DataArea information - /// - /// Array of deserialized models to convert - /// Parent Part to use - /// Prefilled machine to use - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - /// True if there were any items in the array, false otherwise - private void ConvertDataArea(Models.SoftwareList.DataArea[]? dataareas, Part part, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems) - { - // If the dataarea array is missing, we can't do anything - if (dataareas == null || !dataareas.Any()) - return; - - foreach (var dataarea in dataareas) - { - var item = new DataArea(); - item.SetName(dataarea.Name); - item.SetFieldValue(Models.Metadata.DataArea.EndiannessKey, dataarea.Endianness.AsEnumValue()); - item.SetFieldValue(Models.Metadata.DataArea.SizeKey, NumberHelper.ConvertToInt64(dataarea.Size)); - item.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - item.SetFieldValue(Models.Metadata.DataArea.WidthKey, NumberHelper.ConvertToInt64(dataarea.Width)); - - item.CopyMachineInformation(machine); - ConvertRoms(dataarea.Rom, part, item, machine, filename, indexId, statsOnly, ref containsItems); - } - } - - /// - /// Convert Rom information - /// - /// Array of deserialized models to convert - /// Parent Part to use - /// Parent DataArea to use - /// Prefilled machine to use - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - /// True if there were any items in the array, false otherwise - private void ConvertRoms(Models.SoftwareList.Rom[]? roms, Part part, DataArea dataarea, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems) - { - // If the rom array is missing, we can't do anything - if (roms == null || !roms.Any()) - return; - - containsItems = true; - foreach (var rom in roms) - { - var item = new Rom(); - item.SetName(rom.Name); - item.SetFieldValue(Models.Metadata.Rom.CRCKey, rom.CRC); - item.SetFieldValue(Rom.DataAreaKey, dataarea); - item.SetFieldValue(Models.Metadata.Rom.LoadFlagKey, rom.LoadFlag.AsEnumValue()); - item.SetFieldValue(Models.Metadata.Rom.OffsetKey, rom.Offset); - item.SetFieldValue(Rom.PartKey, part); - item.SetFieldValue(Models.Metadata.Rom.SHA1Key, rom.SHA1); - item.SetFieldValue(Models.Metadata.Rom.SizeKey, NumberHelper.ConvertToInt64(rom.Size ?? rom.Length)); - item.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - item.SetFieldValue(Models.Metadata.Rom.StatusKey, rom.Status.AsEnumValue()); - item.SetFieldValue(Models.Metadata.Rom.ValueKey, rom.Value); - - item.CopyMachineInformation(machine); - ParseAddHelper(item, statsOnly); - } - } - - /// - /// Convert DiskArea information - /// - /// Array of deserialized models to convert - /// Parent Part to use - /// Prefilled machine to use - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - /// True if there were any items in the array, false otherwise - private void ConvertDiskArea(Models.SoftwareList.DiskArea[]? diskareas, Part part, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems) - { - // If the diskarea array is missing, we can't do anything - if (diskareas == null || !diskareas.Any()) - return; - - foreach (var diskarea in diskareas) - { - var item = new DiskArea(); - item.SetName(diskarea.Name); - item.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - - item.CopyMachineInformation(machine); - ConvertDisks(diskarea.Disk, part, item, machine, filename, indexId, statsOnly, ref containsItems); - } - } - - /// - /// Convert Disk information - /// - /// Array of deserialized models to convert - /// Parent Part to use - /// Parent DiskArea to use - /// Prefilled machine to use - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - /// True if there were any items in the array, false otherwise - private void ConvertDisks(Models.SoftwareList.Disk[]? disks, Part part, DiskArea diskarea, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems) - { - // If the rom array is missing, we can't do anything - if (disks == null || !disks.Any()) - return; - - containsItems = true; - foreach (var disk in disks) - { - var item = new Disk(); - item.SetName(disk.Name); - item.SetFieldValue(Disk.DiskAreaKey, diskarea); - item.SetFieldValue(Models.Metadata.Disk.StatusKey, disk.Status?.AsEnumValue() ?? ItemStatus.NULL); - item.SetFieldValue(Models.Metadata.Disk.MD5Key, disk.MD5); - item.SetFieldValue(Disk.PartKey, part); - item.SetFieldValue(Models.Metadata.Disk.SHA1Key, disk.SHA1); - item.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - item.SetFieldValue(Models.Metadata.Disk.WritableKey, disk.Writeable.AsYesNo()); - - item.CopyMachineInformation(machine); - ParseAddHelper(item, statsOnly); - } - } - - /// - /// Convert DipSwitch information - /// - /// Array of deserialized models to convert - /// Parent Part to use - /// Prefilled machine to use - /// Name of the file to be parsed - /// Index ID for the DAT - /// True to only add item statistics while parsing, false otherwise - /// True if there were any items in the array, false otherwise - private void ConvertDipSwitch(Models.SoftwareList.DipSwitch[]? dipswitches, Part part, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems) - { - // If the dipswitch array is missing, we can't do anything - if (dipswitches == null || !dipswitches.Any()) - return; - - foreach (var dipswitch in dipswitches) - { - var item = new DipSwitch(); - item.SetName(dipswitch.Name); - item.SetFieldValue(Models.Metadata.DipSwitch.DipValueKey, CreateDipValues(dipswitch.DipValue, machine, filename, indexId)?.ToArray()); - item.SetFieldValue(DipSwitch.PartKey, part); - item.SetFieldValue(Models.Metadata.DipSwitch.MaskKey, dipswitch.Mask); - item.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - item.SetFieldValue(Models.Metadata.DipSwitch.TagKey, dipswitch.Tag); - - item.CopyMachineInformation(machine); - ParseAddHelper(item, statsOnly); - } - } - - /// - /// Convert DipValue information - /// - /// Array of deserialized models to convert - /// Prefilled machine to use - /// Name of the file to be parsed - /// Index ID for the DAT - private static List? CreateDipValues(Models.SoftwareList.DipValue[]? dipvalues, Machine machine, string filename, int indexId) - { - // If the feature array is missing, we can't do anything - if (dipvalues == null || !dipvalues.Any()) - return null; - - var settings = new List(); - foreach (var dipvalue in dipvalues) - { - var item = new DipValue(); - item.SetName(dipvalue.Name); - item.SetFieldValue(Models.Metadata.DipValue.DefaultKey, dipvalue.Default.AsYesNo()); - item.SetFieldValue(DatItem.SourceKey, new Source { Index = indexId, Name = filename }); - item.SetFieldValue(Models.Metadata.DipValue.ValueKey, dipvalue.Value); - - item.CopyMachineInformation(machine); - settings.Add(item); - } - - return settings; - } - - #endregion } }