using System; using System.Collections.Generic; using SabreTools.Data.Extensions; 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 Fields /// public override ItemType[] SupportedTypes => [ ItemType.Adjuster, ItemType.BiosSet, ItemType.Chip, ItemType.Condition, ItemType.Configuration, ItemType.Device, ItemType.DeviceRef, ItemType.DipSwitch, ItemType.Disk, ItemType.Display, ItemType.Driver, ItemType.Feature, ItemType.Input, ItemType.Port, ItemType.RamOption, ItemType.Rom, ItemType.Sample, ItemType.Slot, ItemType.SoftwareList, ItemType.Sound, ]; #endregion /// /// Constructor designed for casting a base DatFile /// /// Parent DatFile to copy from public Listxml(DatFile? datFile) : base(datFile) { Header.Write(DatHeader.DatFormatKey, 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.GetName())) missingFields.Add(Data.Models.Metadata.BiosSet.NameKey); if (string.IsNullOrEmpty(biosset.ReadString(Data.Models.Metadata.BiosSet.DescriptionKey))) missingFields.Add(Data.Models.Metadata.BiosSet.DescriptionKey); break; case Rom rom: if (string.IsNullOrEmpty(rom.GetName())) missingFields.Add(Data.Models.Metadata.Rom.NameKey); if (rom.ReadLong(Data.Models.Metadata.Rom.SizeKey) is null || rom.ReadLong(Data.Models.Metadata.Rom.SizeKey) < 0) missingFields.Add(Data.Models.Metadata.Rom.SizeKey); if (string.IsNullOrEmpty(rom.ReadString(Data.Models.Metadata.Rom.CRCKey)) && string.IsNullOrEmpty(rom.ReadString(Data.Models.Metadata.Rom.SHA1Key))) { missingFields.Add(Data.Models.Metadata.Rom.SHA1Key); } break; case Disk disk: if (string.IsNullOrEmpty(disk.GetName())) missingFields.Add(Data.Models.Metadata.Disk.NameKey); if (string.IsNullOrEmpty(disk.ReadString(Data.Models.Metadata.Disk.MD5Key)) && string.IsNullOrEmpty(disk.ReadString(Data.Models.Metadata.Disk.SHA1Key))) { missingFields.Add(Data.Models.Metadata.Disk.SHA1Key); } break; case DeviceRef deviceref: if (string.IsNullOrEmpty(deviceref.GetName())) missingFields.Add(Data.Models.Metadata.DeviceRef.NameKey); break; case Sample sample: if (string.IsNullOrEmpty(sample.GetName())) missingFields.Add(Data.Models.Metadata.Sample.NameKey); break; case Chip chip: if (string.IsNullOrEmpty(chip.GetName())) missingFields.Add(Data.Models.Metadata.Chip.NameKey); if (chip.ReadString(Data.Models.Metadata.Chip.ChipTypeKey).AsChipType() is null) missingFields.Add(Data.Models.Metadata.Chip.ChipTypeKey); break; case Display display: if (display.ReadString(Data.Models.Metadata.Display.DisplayTypeKey).AsDisplayType() is null) missingFields.Add(Data.Models.Metadata.Display.DisplayTypeKey); if (display.ReadDouble(Data.Models.Metadata.Display.RefreshKey) is null) missingFields.Add(Data.Models.Metadata.Display.RefreshKey); break; case Sound sound: if (sound.ReadLong(Data.Models.Metadata.Sound.ChannelsKey) is null) missingFields.Add(Data.Models.Metadata.Sound.ChannelsKey); break; case Input input: if (input.ReadLong(Data.Models.Metadata.Input.PlayersKey) is null) missingFields.Add(Data.Models.Metadata.Input.PlayersKey); break; case DipSwitch dipswitch: if (string.IsNullOrEmpty(dipswitch.GetName())) missingFields.Add(Data.Models.Metadata.DipSwitch.NameKey); if (string.IsNullOrEmpty(dipswitch.ReadString(Data.Models.Metadata.DipSwitch.TagKey))) missingFields.Add(Data.Models.Metadata.DipSwitch.TagKey); break; case Configuration configuration: if (string.IsNullOrEmpty(configuration.GetName())) missingFields.Add(Data.Models.Metadata.Configuration.NameKey); if (string.IsNullOrEmpty(configuration.ReadString(Data.Models.Metadata.Configuration.TagKey))) missingFields.Add(Data.Models.Metadata.Configuration.TagKey); break; case Port port: if (string.IsNullOrEmpty(port.ReadString(Data.Models.Metadata.Port.TagKey))) missingFields.Add(Data.Models.Metadata.Port.TagKey); break; case Adjuster adjuster: if (string.IsNullOrEmpty(adjuster.GetName())) missingFields.Add(Data.Models.Metadata.Adjuster.NameKey); break; case Driver driver: if (driver.ReadString(Data.Models.Metadata.Driver.StatusKey).AsSupportStatus() is null) missingFields.Add(Data.Models.Metadata.Driver.StatusKey); if (driver.ReadString(Data.Models.Metadata.Driver.EmulationKey).AsSupportStatus() is null) missingFields.Add(Data.Models.Metadata.Driver.EmulationKey); if (driver.ReadString(Data.Models.Metadata.Driver.CocktailKey).AsSupportStatus() is null) missingFields.Add(Data.Models.Metadata.Driver.CocktailKey); if (driver.ReadString(Data.Models.Metadata.Driver.SaveStateKey).AsSupportStatus() is null) missingFields.Add(Data.Models.Metadata.Driver.SaveStateKey); break; case Feature feature: if (feature.ReadString(Data.Models.Metadata.Feature.FeatureTypeKey).AsFeatureType() is null) missingFields.Add(Data.Models.Metadata.Feature.FeatureTypeKey); break; case Device device: if (device.ReadString(Data.Models.Metadata.Device.DeviceTypeKey).AsDeviceType() is null) missingFields.Add(Data.Models.Metadata.Device.DeviceTypeKey); break; case Slot slot: if (string.IsNullOrEmpty(slot.GetName())) missingFields.Add(Data.Models.Metadata.Slot.NameKey); break; case DatItems.Formats.SoftwareList softwarelist: if (string.IsNullOrEmpty(softwarelist.ReadString(Data.Models.Metadata.SoftwareList.TagKey))) missingFields.Add(Data.Models.Metadata.SoftwareList.TagKey); if (string.IsNullOrEmpty(softwarelist.GetName())) missingFields.Add(Data.Models.Metadata.SoftwareList.NameKey); if (softwarelist.ReadString(Data.Models.Metadata.SoftwareList.StatusKey).AsSoftwareListStatus() == null) missingFields.Add(Data.Models.Metadata.SoftwareList.StatusKey); break; case RamOption ramoption: if (string.IsNullOrEmpty(ramoption.GetName())) missingFields.Add(Data.Models.Metadata.RamOption.NameKey); break; default: // Item type is not supported break; } return missingFields; } } }