using System; using System.Collections.Generic; using SabreTools.Metadata.DatItems; using SabreTools.Metadata.DatItems.Formats; using SabreTools.Metadata.Filter; namespace SabreTools.Metadata.DatFiles.Formats { /// /// Represents a MAME/M1 XML DAT /// public sealed class Listxml : SerializableDatFile { #region Constants /// /// DTD for original MAME XML DATs /// internal const string MAMEDTD = @" ]> "; #endregion #region Properties /// public override Data.Models.Metadata.ItemType[] SupportedTypes => [ Data.Models.Metadata.ItemType.Adjuster, Data.Models.Metadata.ItemType.BiosSet, Data.Models.Metadata.ItemType.Chip, Data.Models.Metadata.ItemType.Configuration, Data.Models.Metadata.ItemType.Device, Data.Models.Metadata.ItemType.DeviceRef, Data.Models.Metadata.ItemType.DipSwitch, Data.Models.Metadata.ItemType.Disk, Data.Models.Metadata.ItemType.Display, Data.Models.Metadata.ItemType.Driver, Data.Models.Metadata.ItemType.Feature, Data.Models.Metadata.ItemType.Input, Data.Models.Metadata.ItemType.Port, Data.Models.Metadata.ItemType.RamOption, Data.Models.Metadata.ItemType.Rom, Data.Models.Metadata.ItemType.Sample, Data.Models.Metadata.ItemType.Slot, Data.Models.Metadata.ItemType.SoftwareList, Data.Models.Metadata.ItemType.Sound, ]; #endregion /// /// Constructor designed for casting a base DatFile /// /// Parent DatFile to copy from public Listxml(DatFile? datFile) : base(datFile) { Header.DatFormat = DatFormat.Listxml; } /// public override void ParseFile(string filename, int indexId, bool keep, bool statsOnly = false, FilterRunner? filterRunner = null, bool throwOnError = false) { try { // Deserialize the input file var mame = new Serialization.Readers.Listxml().Deserialize(filename); Data.Models.Metadata.MetadataFile? metadata; if (mame is null) { var m1 = new Serialization.Readers.M1().Deserialize(filename); metadata = new Serialization.CrossModel.M1().Serialize(m1); } else { metadata = new Serialization.CrossModel.Listxml().Serialize(mame); } // Convert to the internal format ConvertFromMetadata(metadata, filename, indexId, keep, statsOnly, filterRunner); } catch (Exception ex) when (!throwOnError) { string message = $"'{filename}' - An error occurred during parsing"; _logger.Error(ex, message); } } /// protected internal override List? GetMissingRequiredFields(DatItem datItem) { List missingFields = []; switch (datItem) { case BiosSet biosset: if (string.IsNullOrEmpty(biosset.Name)) missingFields.Add(nameof(Data.Models.Metadata.BiosSet.Name)); if (string.IsNullOrEmpty(biosset.Description)) missingFields.Add(nameof(Data.Models.Metadata.BiosSet.Description)); break; case Rom rom: if (string.IsNullOrEmpty(rom.Name)) missingFields.Add(nameof(Data.Models.Metadata.Rom.Name)); if (rom.Size is null || rom.Size < 0) missingFields.Add(nameof(Data.Models.Metadata.Rom.Size)); if (string.IsNullOrEmpty(rom.CRC32) && string.IsNullOrEmpty(rom.SHA1)) { missingFields.Add(nameof(Data.Models.Metadata.Rom.SHA1)); } break; case Disk disk: if (string.IsNullOrEmpty(disk.Name)) missingFields.Add(nameof(Data.Models.Metadata.Disk.Name)); if (string.IsNullOrEmpty(disk.MD5) && string.IsNullOrEmpty(disk.SHA1)) { missingFields.Add(nameof(Data.Models.Metadata.Disk.SHA1)); } break; case DeviceRef deviceref: if (string.IsNullOrEmpty(deviceref.Name)) missingFields.Add(nameof(Data.Models.Metadata.DeviceRef.Name)); break; case Sample sample: if (string.IsNullOrEmpty(sample.Name)) missingFields.Add(nameof(Data.Models.Metadata.Sample.Name)); break; case Chip chip: if (string.IsNullOrEmpty(chip.Name)) missingFields.Add(nameof(Data.Models.Metadata.Chip.Name)); if (chip.ChipType is null) missingFields.Add(nameof(Data.Models.Metadata.Chip.ChipType)); break; case Display display: if (display.DisplayType is null) missingFields.Add(nameof(Data.Models.Metadata.Display.DisplayType)); if (display.Refresh is null) missingFields.Add(nameof(Data.Models.Metadata.Display.Refresh)); break; case Sound sound: if (sound.Channels is null) missingFields.Add(nameof(Data.Models.Metadata.Sound.Channels)); break; case Input input: if (input.Players is null) missingFields.Add(nameof(Data.Models.Metadata.Input.Players)); break; case DipSwitch dipswitch: if (string.IsNullOrEmpty(dipswitch.Name)) missingFields.Add(nameof(Data.Models.Metadata.DipSwitch.Name)); if (string.IsNullOrEmpty(dipswitch.Tag)) missingFields.Add(nameof(Data.Models.Metadata.DipSwitch.Tag)); break; case Configuration configuration: if (string.IsNullOrEmpty(configuration.Name)) missingFields.Add(nameof(Data.Models.Metadata.Configuration.Name)); if (string.IsNullOrEmpty(configuration.Tag)) missingFields.Add(nameof(Data.Models.Metadata.Configuration.Tag)); break; case Port port: if (string.IsNullOrEmpty(port.Tag)) missingFields.Add(nameof(Data.Models.Metadata.Port.Tag)); break; case Adjuster adjuster: if (string.IsNullOrEmpty(adjuster.Name)) missingFields.Add(nameof(Data.Models.Metadata.Adjuster.Name)); break; case Driver driver: if (driver.Status is null) missingFields.Add(nameof(Data.Models.Metadata.Driver.Status)); if (driver.Emulation is null) missingFields.Add(nameof(Data.Models.Metadata.Driver.Emulation)); if (driver.Cocktail is null) missingFields.Add(nameof(Data.Models.Metadata.Driver.Cocktail)); if (driver.SaveState is null) missingFields.Add(nameof(Data.Models.Metadata.Driver.SaveState)); break; case Feature feature: if (feature.FeatureType is null) missingFields.Add(nameof(Data.Models.Metadata.Feature.FeatureType)); break; case Device device: if (device.DeviceType is null) missingFields.Add(nameof(Data.Models.Metadata.Device.DeviceType)); break; case Slot slot: if (string.IsNullOrEmpty(slot.Name)) missingFields.Add(nameof(Data.Models.Metadata.Slot.Name)); break; case DatItems.Formats.SoftwareList softwarelist: if (string.IsNullOrEmpty(softwarelist.Tag)) missingFields.Add(nameof(Data.Models.Metadata.SoftwareList.Tag)); if (string.IsNullOrEmpty(softwarelist.Name)) missingFields.Add(nameof(Data.Models.Metadata.SoftwareList.Name)); if (softwarelist.Status == null) missingFields.Add(nameof(Data.Models.Metadata.SoftwareList.Status)); break; case RamOption ramoption: if (string.IsNullOrEmpty(ramoption.Name)) missingFields.Add(nameof(Data.Models.Metadata.RamOption.Name)); break; default: // Item type is not supported break; } return missingFields; } } }