diff --git a/SabreTools.DatFiles/Formats/Listxml.Reader.cs b/SabreTools.DatFiles/Formats/Listxml.Reader.cs
index 3552c656..619cc8d5 100644
--- a/SabreTools.DatFiles/Formats/Listxml.Reader.cs
+++ b/SabreTools.DatFiles/Formats/Listxml.Reader.cs
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Xml;
-using System.Xml.Schema;
using SabreTools.Core;
using SabreTools.Core.Tools;
using SabreTools.DatItems;
@@ -18,587 +16,133 @@ namespace SabreTools.DatFiles.Formats
///
public override void ParseFile(string filename, int indexId, bool keep, bool statsOnly = false, bool throwOnError = false)
{
- // Prepare all internal variables
- XmlReader xtr = XmlReader.Create(filename, new XmlReaderSettings
- {
- CheckCharacters = false,
- DtdProcessing = DtdProcessing.Ignore,
- IgnoreComments = true,
- IgnoreWhitespace = true,
- ValidationFlags = XmlSchemaValidationFlags.None,
- ValidationType = ValidationType.None,
- });
-
- // If we got a null reader, just return
- if (xtr == null)
- return;
-
- // Otherwise, read the file to the end
try
{
- xtr.MoveToContent();
- while (!xtr.EOF)
- {
- // We only want elements
- if (xtr.NodeType != XmlNodeType.Element)
- {
- xtr.Read();
- continue;
- }
+ // Deserialize the input file
+ // TODO: Support M1 DATs again
+ var mame = Serialization.Listxml.Deserialize(filename);
- switch (xtr.Name)
- {
- case "mame":
- Header.Name ??= xtr.GetAttribute("build");
- Header.Description ??= Header.Name;
- Header.Debug ??= xtr.GetAttribute("debug").AsYesNo();
- Header.MameConfig ??= xtr.GetAttribute("mameconfig");
- xtr.Read();
- break;
+ // Convert the header to the internal format
+ ConvertHeader(mame, keep);
- // Handle M1 DATs since they're 99% the same as a SL DAT
- case "m1":
- Header.Name ??= "M1";
- Header.Description ??= "M1";
- Header.Version ??= xtr.GetAttribute("version") ?? string.Empty;
- xtr.Read();
- break;
-
- // We want to process the entire subtree of the machine
- case "game": // Some older DATs still use "game"
- case "machine":
- ReadMachine(xtr.ReadSubtree(), statsOnly, filename, indexId);
-
- // Skip the machine now that we've processed it
- xtr.Skip();
- break;
-
- default:
- xtr.Read();
- break;
- }
- }
+ // Convert the game data to the internal format
+ ConvertGames(mame?.Game, filename, indexId, statsOnly);
}
catch (Exception ex) when (!throwOnError)
{
- logger.Warning(ex, $"Exception found while parsing '{filename}'");
-
- // For XML errors, just skip the affected node
- xtr?.Read();
+ string message = $"'{filename}' - An error occurred during parsing";
+ logger.Error(ex, message);
}
+ }
- xtr.Dispose();
+ #region Converters
+
+ ///
+ /// Convert header information
+ ///
+ /// Deserialized model to convert
+ /// True if full pathnames are to be kept, false otherwise (default)
+ private void ConvertHeader(Models.Listxml.Mame? mame, bool keep)
+ {
+ // If the mame is missing, we can't do anything
+ if (mame == null)
+ return;
+
+ Header.Name ??= mame.Build;
+ Header.Description ??= mame.Build;
+ Header.Build ??= mame.Build;
+ Header.Debug ??= mame.Debug.AsYesNo();
+ Header.MameConfig ??= mame.MameConfig;
+
+ // Handle implied SuperDAT
+ if (Header.Name.Contains(" - SuperDAT") && keep)
+ Header.Type ??= "SuperDAT";
}
///
- /// Read machine information
+ /// Convert games information
///
- /// XmlReader representing a machine block
- /// True to only add item statistics while parsing, false otherwise
+ /// Array of deserialized models to convert
/// Name of the file to be parsed
/// Index ID for the DAT
- private void ReadMachine(XmlReader reader, bool statsOnly, string filename, int indexId)
+ /// True to only add item statistics while parsing, false otherwise
+ private void ConvertGames(Models.Listxml.GameBase[]? games, string filename, int indexId, bool statsOnly)
{
- // If we have an empty machine, skip it
- if (reader == null)
+ // If the game array is missing, we can't do anything
+ if (games == null || !games.Any())
return;
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- // Create a new machine
- MachineType machineType = 0x0;
- if (reader.GetAttribute("isbios").AsYesNo() == true)
- machineType |= MachineType.Bios;
-
- if (reader.GetAttribute("isdevice").AsYesNo() == true)
- machineType |= MachineType.Device;
-
- if (reader.GetAttribute("ismechanical").AsYesNo() == true)
- machineType |= MachineType.Mechanical;
-
- Machine machine = new()
+ // Loop through the games and add
+ foreach (var game in games)
{
- Name = reader.GetAttribute("name"),
- Description = reader.GetAttribute("name"),
- CloneOf = reader.GetAttribute("cloneof"),
- RomOf = reader.GetAttribute("romof"),
- SampleOf = reader.GetAttribute("sampleof"),
- MachineType = (machineType == 0x0 ? MachineType.None : machineType),
+ ConvertGame(game, filename, indexId, statsOnly);
+ }
+ }
- SourceFile = reader.GetAttribute("sourcefile"),
- Runnable = reader.GetAttribute("runnable").AsRunnable(),
+ ///
+ /// Convert game 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 ConvertGame(Models.Listxml.GameBase game, string filename, int indexId, bool statsOnly)
+ {
+ // If the game is missing, we can't do anything
+ if (game == null)
+ return;
+
+ // Create the machine for copying information
+ var machine = new Machine
+ {
+ Name = game.Name,
+ SourceFile = game.SourceFile,
+ Runnable = game.Runnable.AsRunnable(),
+ CloneOf = game.CloneOf,
+ RomOf = game.RomOf,
+ SampleOf = game.SampleOf,
+ Description = game.Description,
+ Year = game.Year,
+ Manufacturer = game.Manufacturer,
+ History = game.History,
};
- // Get list for new DatItems
- List datItems = new();
+ if (game.IsBios.AsYesNo() == true)
+ machine.MachineType |= MachineType.Bios;
+ if (game.IsDevice.AsYesNo() == true)
+ machine.MachineType |= MachineType.Device;
+ if (game.IsMechanical.AsYesNo() == true)
+ machine.MachineType |= MachineType.Mechanical;
- while (!reader.EOF)
+ // Check if there are any items
+ bool containsItems = false;
+
+ // Loop through each type of item
+ ConvertBiosSets(game.BiosSet, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertRoms(game.Rom, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertDisks(game.Disk, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertDeviceRefs(game.DeviceRef, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertSamples(game.Sample, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertChips(game.Chip, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertDisplays(game.Display, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertVideos(game.Video, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertSound(game.Sound, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertInput(game.Input, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertDipSwitches(game.DipSwitch, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertConfigurations(game.Configuration, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertPorts(game.Port, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertAdjusters(game.Adjuster, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertDriver(game.Driver, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertFeatures(game.Feature, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertDevices(game.Device, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertSlots(game.Slot, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertSoftwareLists(game.SoftwareList, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertRamOptions(game.RamOption, machine, filename, indexId, statsOnly, ref containsItems);
+
+ // If we had no items, create a Blank placeholder
+ if (!containsItems)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
- {
- reader.Read();
- continue;
- }
-
- // Get the roms from the machine
- switch (reader.Name)
- {
- case "description":
- machine.Description = reader.ReadElementContentAsString();
- break;
-
- case "year":
- machine.Year = reader.ReadElementContentAsString();
- break;
-
- case "manufacturer":
- machine.Manufacturer = reader.ReadElementContentAsString();
- break;
-
- case "history":
- machine.History = reader.ReadElementContentAsString();
- break;
-
- case "adjuster":
- var adjuster = new Adjuster
- {
- Name = reader.GetAttribute("name"),
- Default = reader.GetAttribute("default").AsYesNo(),
- Conditions = new List(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- // Now read the internal tags
- ReadAdjuster(reader.ReadSubtree(), adjuster);
-
- datItems.Add(adjuster);
-
- // Skip the adjuster now that we've processed it
- reader.Skip();
- break;
-
- case "biosset":
- datItems.Add(new BiosSet
- {
- Name = reader.GetAttribute("name"),
- Description = reader.GetAttribute("description"),
- Default = reader.GetAttribute("default").AsYesNo(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- });
-
- reader.Read();
- break;
-
- case "chip":
- var chip = new Chip
- {
- Name = reader.GetAttribute("name"),
- Tag = reader.GetAttribute("tag"),
- ChipType = reader.GetAttribute("type").AsChipType(),
- Clock = Utilities.CleanLong(reader.GetAttribute("clock")),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- datItems.Add(chip);
-
- reader.Read();
- break;
-
- case "condition":
- datItems.Add(new Condition
- {
- Tag = reader.GetAttribute("tag"),
- Mask = reader.GetAttribute("mask"),
- Relation = reader.GetAttribute("relation").AsRelation(),
- Value = reader.GetAttribute("value"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- });
-
- reader.Read();
- break;
-
- case "configuration":
- var configuration = new Configuration
- {
- Name = reader.GetAttribute("name"),
- Tag = reader.GetAttribute("tag"),
- Mask = reader.GetAttribute("mask"),
- Conditions = new List(),
- Locations = new List(),
- Settings = new List(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- // Now read the internal tags
- ReadConfiguration(reader.ReadSubtree(), configuration);
-
- datItems.Add(configuration);
-
- // Skip the configuration now that we've processed it
- reader.Skip();
- break;
-
- case "device":
- var device = new Device
- {
- DeviceType = reader.GetAttribute("type").AsDeviceType(),
- Tag = reader.GetAttribute("tag"),
- FixedImage = reader.GetAttribute("fixed_image"),
- Mandatory = Utilities.CleanLong(reader.GetAttribute("mandatory")),
- Interface = reader.GetAttribute("interface"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- // Now read the internal tags
- ReadDevice(reader.ReadSubtree(), device);
-
- datItems.Add(device);
-
- // Skip the device now that we've processed it
- reader.Skip();
- break;
-
- case "device_ref":
- datItems.Add(new DeviceReference
- {
- Name = reader.GetAttribute("name"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- });
-
- reader.Read();
- break;
-
- case "dipswitch":
- var dipSwitch = new DipSwitch
- {
- Name = reader.GetAttribute("name"),
- Tag = reader.GetAttribute("tag"),
- Mask = reader.GetAttribute("mask"),
- Conditions = new List(),
- Locations = new List(),
- Values = new List(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- // Now read the internal tags
- ReadDipSwitch(reader.ReadSubtree(), dipSwitch);
-
- datItems.Add(dipSwitch);
-
- // Skip the dipswitch now that we've processed it
- reader.Skip();
- break;
-
- case "disk":
- datItems.Add(new Disk
- {
- Name = reader.GetAttribute("name"),
- SHA1 = reader.GetAttribute("sha1"),
- MergeTag = reader.GetAttribute("merge"),
- Region = reader.GetAttribute("region"),
- Index = reader.GetAttribute("index"),
- Writable = reader.GetAttribute("writable").AsYesNo(),
- ItemStatus = reader.GetAttribute("status").AsItemStatus(),
- Optional = reader.GetAttribute("optional").AsYesNo(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- });
-
- reader.Read();
- break;
-
- case "display":
- var display = new Display
- {
- Tag = reader.GetAttribute("tag"),
- DisplayType = reader.GetAttribute("type").AsDisplayType(),
- Rotate = Utilities.CleanLong(reader.GetAttribute("rotate")),
- FlipX = reader.GetAttribute("flipx").AsYesNo(),
- Width = Utilities.CleanLong(reader.GetAttribute("width")),
- Height = Utilities.CleanLong(reader.GetAttribute("height")),
- Refresh = Utilities.CleanDouble(reader.GetAttribute("refresh")),
- PixClock = Utilities.CleanLong(reader.GetAttribute("pixclock")),
- HTotal = Utilities.CleanLong(reader.GetAttribute("htotal")),
- HBEnd = Utilities.CleanLong(reader.GetAttribute("hbend")),
- HBStart = Utilities.CleanLong(reader.GetAttribute("hbstart")),
- VTotal = Utilities.CleanLong(reader.GetAttribute("vtotal")),
- VBEnd = Utilities.CleanLong(reader.GetAttribute("vbend")),
- VBStart = Utilities.CleanLong(reader.GetAttribute("vbstart")),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- datItems.Add(display);
-
- reader.Read();
- break;
-
- case "driver":
- datItems.Add(new Driver
- {
- Status = reader.GetAttribute("status").AsSupportStatus(),
- Emulation = reader.GetAttribute("emulation").AsSupportStatus(),
- Cocktail = reader.GetAttribute("cocktail").AsSupportStatus(),
- SaveState = reader.GetAttribute("savestate").AsSupported(),
- RequiresArtwork = reader.GetAttribute("requiresartwork").AsYesNo(),
- Unofficial = reader.GetAttribute("unofficial").AsYesNo(),
- NoSoundHardware = reader.GetAttribute("nosoundhardware").AsYesNo(),
- Incomplete = reader.GetAttribute("incomplete").AsYesNo(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- });
-
- reader.Read();
- break;
-
- case "feature":
- datItems.Add(new Feature
- {
- Type = reader.GetAttribute("type").AsFeatureType(),
- Status = reader.GetAttribute("status").AsFeatureStatus(),
- Overall = reader.GetAttribute("overall").AsFeatureStatus(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- });
-
- reader.Read();
- break;
-
- case "input":
- var input = new Input
- {
- Service = reader.GetAttribute("service").AsYesNo(),
- Tilt = reader.GetAttribute("tilt").AsYesNo(),
- Players = Utilities.CleanLong(reader.GetAttribute("players")),
- Coins = Utilities.CleanLong(reader.GetAttribute("coins")),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- // Now read the internal tags
- ReadInput(reader.ReadSubtree(), input);
-
- datItems.Add(input);
-
- // Skip the input now that we've processed it
- reader.Skip();
- break;
-
- case "port":
- var port = new Port
- {
- Tag = reader.GetAttribute("tag"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- // Now read the internal tags
- ReadPort(reader.ReadSubtree(), port);
-
- datItems.Add(port);
-
- // Skip the port now that we've processed it
- reader.Skip();
- break;
-
- case "ramoption":
- datItems.Add(new RamOption
- {
- Name = reader.GetAttribute("name"),
- Default = reader.GetAttribute("default").AsYesNo(),
- Content = reader.ReadElementContentAsString(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- });
-
- break;
-
- case "rom":
- datItems.Add(new Rom
- {
- Name = reader.GetAttribute("name"),
- Bios = reader.GetAttribute("bios"),
- Size = Utilities.CleanLong(reader.GetAttribute("size")),
- CRC = reader.GetAttribute("crc"),
- SHA1 = reader.GetAttribute("sha1"),
- MergeTag = reader.GetAttribute("merge"),
- Region = reader.GetAttribute("region"),
- Offset = reader.GetAttribute("offset"),
- ItemStatus = reader.GetAttribute("status").AsItemStatus(),
- Optional = reader.GetAttribute("optional").AsYesNo(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- });
-
- reader.Read();
- break;
-
- case "sample":
- datItems.Add(new Sample
- {
- Name = reader.GetAttribute("name"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- });
-
- reader.Read();
- break;
-
- case "slot":
- var slot = new Slot
- {
- Name = reader.GetAttribute("name"),
- SlotOptions = new List(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- // Now read the internal tags
- ReadSlot(reader.ReadSubtree(), slot);
-
- datItems.Add(slot);
-
- // Skip the slot now that we've processed it
- reader.Skip();
- break;
-
- case "softwarelist":
- datItems.Add(new DatItems.Formats.SoftwareList
- {
- Tag = reader.GetAttribute("tag"),
- Name = reader.GetAttribute("name"),
- Status = reader.GetAttribute("status").AsSoftwareListStatus(),
- Filter = reader.GetAttribute("filter"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- });
-
- reader.Read();
- break;
-
- case "sound":
- var sound = new Sound
- {
- Channels = Utilities.CleanLong(reader.GetAttribute("channels")),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- datItems.Add(sound);
-
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
- }
-
- // If we found items, copy the machine info and add them
- if (datItems.Any())
- {
- foreach (DatItem datItem in datItems)
- {
- datItem.CopyMachineInformation(machine);
- ParseAddHelper(datItem, statsOnly);
- }
- }
-
- // If no items were found for this machine, add a Blank placeholder
- else
- {
- Blank blank = new()
+ var blank = new Blank
{
Source = new Source
{
@@ -608,538 +152,961 @@ namespace SabreTools.DatFiles.Formats
};
blank.CopyMachineInformation(machine);
-
- // Now process and add the rom
ParseAddHelper(blank, statsOnly);
}
}
///
- /// Read slot information
+ /// Convert BiosSet information
///
- /// XmlReader representing a machine block
- /// ListXmlSlot to populate
- private void ReadSlot(XmlReader reader, Slot slot)
+ /// 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 ConvertBiosSets(Models.Listxml.BiosSet[]? biossets, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty machine, skip it
- if (reader == null)
+ // If the BiosSet array is missing, we can't do anything
+ if (biossets == null || !biossets.Any())
return;
- // Get list ready
- slot.SlotOptions = new List();
-
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ containsItems = true;
+ foreach (var biosset in biossets)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var item = new BiosSet
{
- reader.Read();
- continue;
- }
+ Name = biosset.Name,
+ Description = biosset.Description,
+ Default = biosset.Default?.AsYesNo(),
- // Get the roms from the machine
- switch (reader.Name)
- {
- case "slotoption":
- var slotOption = new SlotOption
- {
- Name = reader.GetAttribute("name"),
- DeviceName = reader.GetAttribute("devname"),
- Default = reader.GetAttribute("default").AsYesNo()
- };
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
- slot.SlotOptions.Add(slotOption);
-
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
}
///
- /// Read Input information
+ /// Convert Rom information
///
- /// XmlReader representing a diskarea block
- /// ListXmlInput to populate
- private void ReadInput(XmlReader reader, Input input)
+ /// 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 ConvertRoms(Models.Listxml.Rom[]? roms, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty input, skip it
- if (reader == null)
+ // If the Rom array is missing, we can't do anything
+ if (roms == null || !roms.Any())
return;
- // Get list ready
- input.Controls = new List();
-
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ containsItems = true;
+ foreach (var rom in roms)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var item = new Rom
{
- reader.Read();
- continue;
- }
+ Name = rom.Name,
+ Bios = rom.Bios,
+ Size = Utilities.CleanLong(rom.Size),
+ CRC = rom.CRC,
+ SHA1 = rom.SHA1,
+ MergeTag = rom.Merge,
+ Region = rom.Region,
+ Offset = rom.Offset,
+ ItemStatus = rom.Status.AsItemStatus(),
+ Optional = rom.Optional.AsYesNo(),
+ //Dispose = rom.Dispose.AsYesNo(), // TODO: Add to internal model
+ //SoundOnly = rom.SoundOnly.AsYesNo(), // TODO: Add to internal model
- // Get the information from the dipswitch
- switch (reader.Name)
- {
- case "control":
- var control = new Control
- {
- ControlType = reader.GetAttribute("type").AsControlType(),
- Player = Utilities.CleanLong(reader.GetAttribute("player")),
- Buttons = Utilities.CleanLong(reader.GetAttribute("buttons")),
- RequiredButtons = Utilities.CleanLong(reader.GetAttribute("reqbuttons")),
- Minimum = Utilities.CleanLong(reader.GetAttribute("minimum")),
- Maximum = Utilities.CleanLong(reader.GetAttribute("maximum")),
- Sensitivity = Utilities.CleanLong(reader.GetAttribute("sensitivity")),
- KeyDelta = Utilities.CleanLong(reader.GetAttribute("keydelta")),
- Reverse = reader.GetAttribute("reverse").AsYesNo(),
- Ways = reader.GetAttribute("ways"),
- Ways2 = reader.GetAttribute("ways2"),
- Ways3 = reader.GetAttribute("ways3"),
- };
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
- input.Controls.Add(control);
-
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
}
///
- /// Read DipSwitch information
+ /// Convert Disk information
///
- /// XmlReader representing a diskarea block
- /// DipSwitch to populate
- private void ReadDipSwitch(XmlReader reader, DipSwitch dipSwitch)
+ /// 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 ConvertDisks(Models.Listxml.Disk[]? disks, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty dipswitch, skip it
- if (reader == null)
+ // If the Disk array is missing, we can't do anything
+ if (disks == null || !disks.Any())
return;
- // Get lists ready
- dipSwitch.Conditions = new List();
- dipSwitch.Locations = new List();
- dipSwitch.Values = new List();
-
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ containsItems = true;
+ foreach (var disk in disks)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var item = new Disk
{
- reader.Read();
- continue;
+ Name = disk.Name,
+ MD5 = disk.MD5,
+ SHA1 = disk.SHA1,
+ MergeTag = disk.Merge,
+ Region = disk.Region,
+ Index = disk.Index,
+ Writable = disk.Writable.AsYesNo(),
+ ItemStatus = disk.Status.AsItemStatus(),
+ Optional = disk.Optional.AsYesNo(),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert DeviceRef 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 ConvertDeviceRefs(Models.Listxml.DeviceRef[]? devicerefs, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the DeviceRef array is missing, we can't do anything
+ if (devicerefs == null || !devicerefs.Any())
+ return;
+
+ containsItems = true;
+ foreach (var deviceref in devicerefs)
+ {
+ var item = new DeviceReference
+ {
+ Name = deviceref.Name,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert Sample 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 ConvertSamples(Models.Listxml.Sample[]? samples, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the Sample array is missing, we can't do anything
+ if (samples == null || !samples.Any())
+ return;
+
+ containsItems = true;
+ foreach (var sample in samples)
+ {
+ var item = new Sample
+ {
+ Name = sample.Name,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert Chip 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 ConvertChips(Models.Listxml.Chip[]? chips, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the Chip array is missing, we can't do anything
+ if (chips == null || !chips.Any())
+ return;
+
+ containsItems = true;
+ foreach (var chip in chips)
+ {
+ var item = new Chip
+ {
+ Name = chip.Name,
+ Tag = chip.Tag,
+ ChipType = chip.Type.AsChipType(),
+ //SoundOnly = chip.SoundOnly, // TODO: Add to internal model
+ Clock = Utilities.CleanLong(chip.Clock),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert Display 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 ConvertDisplays(Models.Listxml.Display[]? displays, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the Display array is missing, we can't do anything
+ if (displays == null || !displays.Any())
+ return;
+
+ containsItems = true;
+ foreach (var display in displays)
+ {
+ var item = new Display
+ {
+ Tag = display.Tag,
+ DisplayType = display.Type.AsDisplayType(),
+ Rotate = Utilities.CleanLong(display.Rotate),
+ FlipX = display.FlipX.AsYesNo(),
+ Width = Utilities.CleanLong(display.Width),
+ Height = Utilities.CleanLong(display.Height),
+ Refresh = Utilities.CleanDouble(display.Refresh),
+ PixClock = Utilities.CleanLong(display.PixClock),
+ HTotal = Utilities.CleanLong(display.HTotal),
+ HBEnd = Utilities.CleanLong(display.HBEnd),
+ HBStart = Utilities.CleanLong(display.HBStart),
+ VTotal = Utilities.CleanLong(display.VTotal),
+ VBEnd = Utilities.CleanLong(display.VBEnd),
+ VBStart = Utilities.CleanLong(display.VBStart),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert Video 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 ConvertVideos(Models.Listxml.Video[]? videos, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the Video array is missing, we can't do anything
+ if (videos == null || !videos.Any())
+ return;
+
+ containsItems = true;
+ foreach (var video in videos)
+ {
+ var item = new Display
+ {
+ DisplayType = video.Screen?.AsDisplayType() ?? DisplayType.NULL,
+ Width = Utilities.CleanLong(video.Width),
+ Height = Utilities.CleanLong(video.Height),
+ //AspectX = video.AspectX, // TODO: Add to internal model or find mapping
+ //AspectY = video.AspectY, // TODO: Add to internal model or find mapping
+ Refresh = Utilities.CleanDouble(video.Refresh),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ switch (video.Orientation)
+ {
+ case "horizontal":
+ item.Rotate = 0;
+ break;
+ case "vertical":
+ item.Rotate = 90;
+ break;
}
- // Get the information from the dipswitch
- switch (reader.Name)
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert Sound information
+ ///
+ /// Deserialized model 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 ConvertSound(Models.Listxml.Sound? sound, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the Sound is missing, we can't do anything
+ if (sound == null)
+ return;
+
+ containsItems = true;
+ var item = new Sound
+ {
+ Channels = Utilities.CleanLong(sound.Channels),
+
+ Source = new Source
{
- case "condition":
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+
+ ///
+ /// Convert Input information
+ ///
+ /// Deserialized model 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 ConvertInput(Models.Listxml.Input? input, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the Input is missing, we can't do anything
+ if (input == null)
+ return;
+
+ containsItems = true;
+ var item = new Input
+ {
+ Service = input.Service.AsYesNo(),
+ Tilt = input.Tilt.AsYesNo(),
+ Players = Utilities.CleanLong(input.Players),
+ //ControlAttr = input.ControlAttr, // TODO: Add to internal model
+ //Buttons = input.Buttons, // TODO: Add to internal model
+ Coins = Utilities.CleanLong(input.Coins),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ var controls = new List();
+ foreach (var control in input.Control ?? Array.Empty())
+ {
+ var controlItem = new Control
+ {
+ ControlType = control.Type.AsControlType(),
+ Player = Utilities.CleanLong(control.Player),
+ Buttons = Utilities.CleanLong(control.Buttons),
+ RequiredButtons = Utilities.CleanLong(control.ReqButtons),
+ Minimum = Utilities.CleanLong(control.Minimum),
+ Maximum = Utilities.CleanLong(control.Maximum),
+ Sensitivity = Utilities.CleanLong(control.Sensitivity),
+ KeyDelta = Utilities.CleanLong(control.KeyDelta),
+ Reverse = control.Reverse.AsYesNo(),
+ Ways = control.Ways,
+ Ways2 = control.Ways2,
+ Ways3 = control.Ways3,
+ };
+ controls.Add(controlItem);
+ }
+
+ if (controls.Any())
+ item.Controls = controls;
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+
+ ///
+ /// Convert DipSwitch 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 ConvertDipSwitches(Models.Listxml.DipSwitch[]? dipswitches, 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;
+
+ containsItems = true;
+ foreach (var dipswitch in dipswitches)
+ {
+ var item = new DipSwitch
+ {
+ Name = dipswitch.Name,
+ Tag = dipswitch.Tag,
+ Mask = dipswitch.Mask,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ if (dipswitch.Condition != null)
+ {
+ var condition = new Condition
+ {
+ Tag = dipswitch.Condition.Tag,
+ Mask = dipswitch.Condition.Mask,
+ Relation = dipswitch.Condition.Relation.AsRelation(),
+ Value = dipswitch.Condition.Value,
+ };
+ item.Conditions = new List { condition };
+ }
+
+ var locations = new List();
+ foreach (var diplocation in dipswitch.DipLocation ?? Array.Empty())
+ {
+ var locationItem = new Location
+ {
+ Name = diplocation.Name,
+ Number = Utilities.CleanLong(diplocation.Number),
+ Inverted = diplocation.Inverted.AsYesNo(),
+ };
+ locations.Add(locationItem);
+ }
+
+ if (locations.Any())
+ item.Locations = locations;
+
+ var settings = new List();
+ foreach (var dipvalue in dipswitch.DipValue ?? Array.Empty())
+ {
+ var settingItem = new Setting
+ {
+ Name = dipvalue.Name,
+ Value = dipvalue.Value,
+ Default = dipvalue.Default.AsYesNo(),
+ };
+
+ if (dipvalue.Condition != null)
+ {
var condition = new Condition
{
- Tag = reader.GetAttribute("tag"),
- Mask = reader.GetAttribute("mask"),
- Relation = reader.GetAttribute("relation").AsRelation(),
- Value = reader.GetAttribute("value")
+ Tag = dipvalue.Condition.Tag,
+ Mask = dipvalue.Condition.Mask,
+ Relation = dipvalue.Condition.Relation.AsRelation(),
+ Value = dipvalue.Condition.Value,
};
+ settingItem.Conditions = new List { condition };
+ }
- dipSwitch.Conditions.Add(condition);
-
- reader.Read();
- break;
-
- case "diplocation":
- var dipLocation = new Location
- {
- Name = reader.GetAttribute("name"),
- Number = Utilities.CleanLong(reader.GetAttribute("number")),
- Inverted = reader.GetAttribute("inverted").AsYesNo()
- };
-
- dipSwitch.Locations.Add(dipLocation);
-
- reader.Read();
- break;
-
- case "dipvalue":
- var dipValue = new Setting
- {
- Name = reader.GetAttribute("name"),
- Value = reader.GetAttribute("value"),
- Default = reader.GetAttribute("default").AsYesNo()
- };
-
- // Now read the internal tags
- ReadDipValue(reader, dipValue);
-
- dipSwitch.Values.Add(dipValue);
-
- // Skip the dipvalue now that we've processed it
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
+ settings.Add(settingItem);
}
+
+ if (settings.Any())
+ item.Values = settings;
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
}
///
- /// Read DipValue information
+ /// Convert Configuration information
///
- /// XmlReader representing a diskarea block
- /// Setting to populate
- private void ReadDipValue(XmlReader reader, Setting dipValue)
+ /// 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 ConvertConfigurations(Models.Listxml.Configuration[]? configurations, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty dipvalue, skip it
- if (reader == null)
+ // If the Configuration array is missing, we can't do anything
+ if (configurations == null || !configurations.Any())
return;
- // Get list ready
- dipValue.Conditions = new List();
-
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ containsItems = true;
+ foreach (var configuration in configurations)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var item = new Configuration
{
- reader.Read();
- continue;
+ Name = configuration.Name,
+ Tag = configuration.Tag,
+ Mask = configuration.Mask,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ if (configuration.Condition != null)
+ {
+ var condition = new Condition
+ {
+ Tag = configuration.Condition.Tag,
+ Mask = configuration.Condition.Mask,
+ Relation = configuration.Condition.Relation.AsRelation(),
+ Value = configuration.Condition.Value,
+ };
+ item.Conditions = new List { condition };
}
- // Get the information from the dipvalue
- switch (reader.Name)
+ var locations = new List();
+ foreach (var confLocation in configuration.ConfLocation ?? Array.Empty())
{
- case "condition":
+ var locationItem = new Location
+ {
+ Name = confLocation.Name,
+ Number = Utilities.CleanLong(confLocation.Number),
+ Inverted = confLocation.Inverted.AsYesNo(),
+ };
+ locations.Add(locationItem);
+ }
+
+ if (locations.Any())
+ item.Locations = locations;
+
+ var settings = new List();
+ foreach (var dipvalue in configuration.ConfSetting ?? Array.Empty())
+ {
+ var settingItem = new Setting
+ {
+ Name = dipvalue.Name,
+ Value = dipvalue.Value,
+ Default = dipvalue.Default.AsYesNo(),
+ };
+
+ if (dipvalue.Condition != null)
+ {
var condition = new Condition
{
- Tag = reader.GetAttribute("tag"),
- Mask = reader.GetAttribute("mask"),
- Relation = reader.GetAttribute("relation").AsRelation(),
- Value = reader.GetAttribute("value")
+ Tag = dipvalue.Condition.Tag,
+ Mask = dipvalue.Condition.Mask,
+ Relation = dipvalue.Condition.Relation.AsRelation(),
+ Value = dipvalue.Condition.Value,
};
+ settingItem.Conditions = new List { condition };
+ }
- dipValue.Conditions.Add(condition);
-
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
+ settings.Add(settingItem);
}
+
+ if (settings.Any())
+ item.Settings = settings;
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
}
///
- /// Read Configuration information
+ /// Convert Port information
///
- /// XmlReader representing a diskarea block
- /// Configuration to populate
- private void ReadConfiguration(XmlReader reader, Configuration configuration)
+ /// 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 ConvertPorts(Models.Listxml.Port[]? ports, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty configuration, skip it
- if (reader == null)
+ // If the Port array is missing, we can't do anything
+ if (ports == null || !ports.Any())
return;
- // Get lists ready
- configuration.Conditions = new List();
- configuration.Locations = new List();
- configuration.Settings = new List();
-
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ containsItems = true;
+ foreach (var port in ports)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var item = new Port
{
- reader.Read();
- continue;
+ Tag = port.Tag,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ var analogs = new List();
+ foreach (var analog in port.Analog ?? Array.Empty())
+ {
+ var analogItem = new Analog
+ {
+ Mask = analog.Mask,
+ };
+ analogs.Add(analogItem);
}
- // Get the information from the dipswitch
- switch (reader.Name)
- {
- case "condition":
- var condition = new Condition
- {
- Tag = reader.GetAttribute("tag"),
- Mask = reader.GetAttribute("mask"),
- Relation = reader.GetAttribute("relation").AsRelation(),
- Value = reader.GetAttribute("value")
- };
+ if (analogs.Any())
+ item.Analogs = analogs;
- configuration.Conditions.Add(condition);
-
- reader.Read();
- break;
-
- case "conflocation":
- var confLocation = new Location
- {
- Name = reader.GetAttribute("name"),
- Number = Utilities.CleanLong(reader.GetAttribute("number")),
- Inverted = reader.GetAttribute("inverted").AsYesNo()
- };
-
- configuration.Locations.Add(confLocation);
-
- reader.Read();
- break;
-
- case "confsetting":
- var confSetting = new Setting
- {
- Name = reader.GetAttribute("name"),
- Value = reader.GetAttribute("value"),
- Default = reader.GetAttribute("default").AsYesNo()
- };
-
- // Now read the internal tags
- ReadConfSetting(reader, confSetting);
-
- configuration.Settings.Add(confSetting);
-
- // Skip the dipvalue now that we've processed it
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
}
///
- /// Read ConfSetting information
+ /// Convert Adjuster information
///
- /// XmlReader representing a diskarea block
- /// Setting to populate
- private void ReadConfSetting(XmlReader reader, Setting confSetting)
+ /// 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 ConvertAdjusters(Models.Listxml.Adjuster[]? adjusters, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty confsetting, skip it
- if (reader == null)
+ // If the Adjuster array is missing, we can't do anything
+ if (adjusters == null || !adjusters.Any())
return;
- // Get list ready
- confSetting.Conditions = new List();
-
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ containsItems = true;
+ foreach (var adjuster in adjusters)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var item = new Adjuster
{
- reader.Read();
- continue;
+ Name = adjuster.Name,
+ Default = adjuster.Default.AsYesNo(),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ if (adjuster.Condition != null)
+ {
+ var condition = new Condition
+ {
+ Tag = adjuster.Condition.Tag,
+ Mask = adjuster.Condition.Mask,
+ Relation = adjuster.Condition.Relation.AsRelation(),
+ Value = adjuster.Condition.Value,
+ };
+ item.Conditions = new List { condition };
}
- // Get the information from the confsetting
- switch (reader.Name)
- {
- case "condition":
- var condition = new Condition
- {
- Tag = reader.GetAttribute("tag"),
- Mask = reader.GetAttribute("mask"),
- Relation = reader.GetAttribute("relation").AsRelation(),
- Value = reader.GetAttribute("value")
- };
-
- confSetting.Conditions.Add(condition);
-
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
}
///
- /// Read Port information
+ /// Convert Driver information
///
- /// XmlReader representing a diskarea block
- /// ListXmlPort to populate
- private void ReadPort(XmlReader reader, Port port)
+ /// Deserialized model 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 ConvertDriver(Models.Listxml.Driver? driver, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty port, skip it
- if (reader == null)
+ // If the Driver is missing, we can't do anything
+ if (driver == null)
return;
- // Get list ready
- port.Analogs = new List();
-
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ containsItems = true;
+ var item = new Driver
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ Status = driver.Status.AsSupportStatus(),
+ //Color = driver.Color.AsSupportStatus(), // TODO: Add to internal model
+ //Sound = driver.Sound.AsSupportStatus(), // TODO: Add to internal model
+ //PaletteSize = Utilities.CleanLong(driver.PaletteSize), // TODO: Add to internal model
+ Emulation = driver.Emulation.AsSupportStatus(),
+ Cocktail = driver.Cocktail.AsSupportStatus(),
+ SaveState = driver.SaveState.AsSupported(),
+ RequiresArtwork = driver.SaveState.AsYesNo(),
+ Unofficial = driver.Unofficial.AsYesNo(),
+ NoSoundHardware = driver.NoSoundHardware.AsYesNo(),
+ Incomplete = driver.Incomplete.AsYesNo(),
+
+ Source = new Source
{
- reader.Read();
- continue;
- }
+ Index = indexId,
+ Name = filename,
+ },
+ };
- // Get the information from the port
- switch (reader.Name)
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+
+ ///
+ /// 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
+ /// True if there were any items in the array, false otherwise
+ private void ConvertFeatures(Models.Listxml.Feature[]? features, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the Feature array is missing, we can't do anything
+ if (features == null || !features.Any())
+ return;
+
+ containsItems = true;
+ foreach (var feature in features)
+ {
+ var item = new Feature
{
- case "analog":
- var analog = new Analog
- {
- Mask = reader.GetAttribute("mask")
- };
+ Type = feature.Type.AsFeatureType(),
+ Status = feature.Status.AsFeatureStatus(),
+ Overall = feature.Overall.AsFeatureStatus(),
- port.Analogs.Add(analog);
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
}
///
- /// Read Adjuster information
+ /// Convert Device information
///
- /// XmlReader representing a diskarea block
- /// Adjuster to populate
- private void ReadAdjuster(XmlReader reader, Adjuster adjuster)
+ /// 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 ConvertDevices(Models.Listxml.Device[]? devices, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty port, skip it
- if (reader == null)
+ // If the Device array is missing, we can't do anything
+ if (devices == null || !devices.Any())
return;
- // Get list ready
- adjuster.Conditions = new List();
-
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ containsItems = true;
+ foreach (var device in devices)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var item = new Device
{
- reader.Read();
- continue;
+ DeviceType = device.Type.AsDeviceType(),
+ Tag = device.Tag,
+ FixedImage = device.FixedImage,
+ Mandatory = Utilities.CleanLong(device.Mandatory),
+ Interface = device.Interface,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ if (device.Instance != null)
+ {
+ var instance = new Instance
+ {
+ Name = device.Instance.Name,
+ BriefName = device.Instance.BriefName,
+ };
+ item.Instances = new List { instance };
}
- // Get the information from the adjuster
- switch (reader.Name)
+ var extensions = new List();
+ foreach (var extension in device.Extension ?? Array.Empty())
{
- case "condition":
- var condition = new Condition
- {
- Tag = reader.GetAttribute("tag"),
- Mask = reader.GetAttribute("mask"),
- Relation = reader.GetAttribute("relation").AsRelation(),
- Value = reader.GetAttribute("value")
- };
-
- adjuster.Conditions.Add(condition);
-
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
+ var extensionItem = new Extension
+ {
+ Name = extension.Name,
+ };
+ extensions.Add(extensionItem);
}
+
+ if (extensions.Any())
+ item.Extensions = extensions;
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
}
///
- /// Read Device information
+ /// Convert Slot information
///
- /// XmlReader representing a diskarea block
- /// ListXmlDevice to populate
- private void ReadDevice(XmlReader reader, Device device)
+ /// 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 ConvertSlots(Models.Listxml.Slot[]? slots, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty port, skip it
- if (reader == null)
+ // If the Slot array is missing, we can't do anything
+ if (slots == null || !slots.Any())
return;
- // Get lists ready
- device.Instances = new List();
- device.Extensions = new List();
-
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ containsItems = true;
+ foreach (var slot in slots)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var item = new Slot
{
- reader.Read();
- continue;
+ Name = slot.Name,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ var extensions = new List();
+ foreach (var slotoption in slot.SlotOption ?? Array.Empty())
+ {
+ var slotoptionItem = new SlotOption
+ {
+ Name = slotoption.Name,
+ DeviceName = slotoption.DevName,
+ Default = slotoption.Default.AsYesNo(),
+ };
+ extensions.Add(slotoptionItem);
}
- // Get the information from the adjuster
- switch (reader.Name)
- {
- case "instance":
- var instance = new Instance
- {
- Name = reader.GetAttribute("name"),
- BriefName = reader.GetAttribute("briefname"),
- };
+ if (extensions.Any())
+ item.SlotOptions = extensions;
- device.Instances.Add(instance);
-
- reader.Read();
- break;
-
- case "extension":
- var extension = new Extension
- {
- Name = reader.GetAttribute("name"),
- };
-
- device.Extensions.Add(extension);
-
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
}
+
+ ///
+ /// Convert SoftwareList 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 ConvertSoftwareLists(Models.Listxml.SoftwareList[]? softwarelists, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the SoftwareList array is missing, we can't do anything
+ if (softwarelists == null || !softwarelists.Any())
+ return;
+
+ containsItems = true;
+ foreach (var softwarelist in softwarelists)
+ {
+ var item = new DatItems.Formats.SoftwareList
+ {
+ Tag = softwarelist.Tag,
+ Name = softwarelist.Name,
+ Status = softwarelist.Status.AsSoftwareListStatus(),
+ Filter = softwarelist.Filter,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert RamOption 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 ConvertRamOptions(Models.Listxml.RamOption[]? ramoptions, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the RamOption array is missing, we can't do anything
+ if (ramoptions == null || !ramoptions.Any())
+ return;
+
+ containsItems = true;
+ foreach (var ramoption in ramoptions)
+ {
+ var item = new RamOption
+ {
+ Name = ramoption.Name,
+ Default = ramoption.Default.AsYesNo(),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ #endregion
}
}
diff --git a/SabreTools.DatFiles/Formats/Logiqx.Reader.cs b/SabreTools.DatFiles/Formats/Logiqx.Reader.cs
index 7293ea57..1ed0e8c0 100644
--- a/SabreTools.DatFiles/Formats/Logiqx.Reader.cs
+++ b/SabreTools.DatFiles/Formats/Logiqx.Reader.cs
@@ -271,6 +271,7 @@ namespace SabreTools.DatFiles.Formats
ConvertDisks(game.Disk, machine, filename, indexId, statsOnly, ref containsItems);
ConvertMedia(game.Media, machine, filename, indexId, statsOnly, ref containsItems);
ConvertDeviceRefs(game.DeviceRef, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertSamples(game.Sample, machine, filename, indexId, statsOnly, ref containsItems);
ConvertArchives(game.Archive, machine, filename, indexId, statsOnly, ref containsItems);
ConvertDrivers(game.Driver, machine, filename, indexId, statsOnly, ref containsItems);
ConvertSoftwareLists(game.SoftwareList, machine, filename, indexId, statsOnly, ref containsItems);
diff --git a/SabreTools.Models/Listxml/Adjuster.cs b/SabreTools.Models/Listxml/Adjuster.cs
index 706d8041..1835bd5e 100644
--- a/SabreTools.Models/Listxml/Adjuster.cs
+++ b/SabreTools.Models/Listxml/Adjuster.cs
@@ -9,6 +9,7 @@ namespace SabreTools.Models.Listxml
[XmlAttribute("name")]
public string Name { get; set; }
+ /// (yes|no) "no"
[XmlAttribute("default")]
public string Default { get; set; }
diff --git a/SabreTools.Models/Listxml/Control.cs b/SabreTools.Models/Listxml/Control.cs
index d66d07d8..cd67016a 100644
--- a/SabreTools.Models/Listxml/Control.cs
+++ b/SabreTools.Models/Listxml/Control.cs
@@ -9,31 +9,31 @@ namespace SabreTools.Models.Listxml
[XmlAttribute("type")]
public string Type { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("player")]
public string? Player { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("buttons")]
public string? Buttons { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("reqbuttons")]
public string? ReqButtons { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("minimum")]
public string? Minimum { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("maximum")]
public string? Maximum { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("sensitivity")]
public string? Sensitivity { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("keydelta")]
public string? KeyDelta { get; set; }
diff --git a/SabreTools.Models/Listxml/Device.cs b/SabreTools.Models/Listxml/Device.cs
index 1ed464a7..139d8d36 100644
--- a/SabreTools.Models/Listxml/Device.cs
+++ b/SabreTools.Models/Listxml/Device.cs
@@ -15,6 +15,7 @@ namespace SabreTools.Models.Listxml
[XmlAttribute("fixed_image")]
public string? FixedImage { get; set; }
+ /// Numeric boolean
[XmlAttribute("mandatory")]
public string? Mandatory { get; set; }
diff --git a/SabreTools.Models/Listxml/Display.cs b/SabreTools.Models/Listxml/Display.cs
index 6d274544..0a4bed41 100644
--- a/SabreTools.Models/Listxml/Display.cs
+++ b/SabreTools.Models/Listxml/Display.cs
@@ -21,43 +21,43 @@ namespace SabreTools.Models.Listxml
[XmlAttribute("flipx")]
public string? FlipX { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("width")]
public string? Width { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("height")]
public string? Height { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("refresh")]
public string Refresh { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("pixclock")]
public string? PixClock { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("htotal")]
public string? HTotal { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("hbend")]
public string? HBEnd { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("hbstart")]
public string? HBStart { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("vtotal")]
public string? VTotal { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("vbend")]
public string? VBEnd { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("vbstart")]
public string? VBStart { get; set; }
diff --git a/SabreTools.Models/Listxml/Game.cs b/SabreTools.Models/Listxml/Game.cs
index 857657e4..06bdcbaf 100644
--- a/SabreTools.Models/Listxml/Game.cs
+++ b/SabreTools.Models/Listxml/Game.cs
@@ -3,10 +3,5 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Listxml
{
[XmlRoot("game")]
- public class Game : GameBase
- {
- /// Appears after Manufacturer
- [XmlElement("history")]
- public string? History { get; set; }
- }
+ public class Game : GameBase { }
}
\ No newline at end of file
diff --git a/SabreTools.Models/Listxml/GameBase.cs b/SabreTools.Models/Listxml/GameBase.cs
index 680b7d67..26507a91 100644
--- a/SabreTools.Models/Listxml/GameBase.cs
+++ b/SabreTools.Models/Listxml/GameBase.cs
@@ -11,6 +11,22 @@ namespace SabreTools.Models.Listxml
[XmlAttribute("name")]
public string Name { get; set; }
+ /// Machine only
+ [XmlAttribute("sourcefile")]
+ public string? SourceFile { get; set; }
+
+ /// (yes|no) "no", Machine only
+ [XmlAttribute("isbios")]
+ public string? IsBios { get; set; }
+
+ /// (yes|no) "no", Machine only
+ [XmlAttribute("isdevice")]
+ public string? IsDevice { get; set; }
+
+ /// (yes|no) "no", Machine only
+ [XmlAttribute("ismechanical")]
+ public string? IsMechanical { get; set; }
+
/// (yes|no) "no"
[XmlAttribute("runnable")]
public string? Runnable { get; set; }
@@ -33,6 +49,10 @@ namespace SabreTools.Models.Listxml
[XmlElement("manufacturer")]
public string? Manufacturer { get; set; }
+ /// Game only
+ [XmlElement("history")]
+ public string? History { get; set; }
+
[XmlElement("biosset")]
public BiosSet[]? BiosSet { get; set; }
diff --git a/SabreTools.Models/Listxml/Input.cs b/SabreTools.Models/Listxml/Input.cs
index 3480dc46..281613ba 100644
--- a/SabreTools.Models/Listxml/Input.cs
+++ b/SabreTools.Models/Listxml/Input.cs
@@ -14,7 +14,7 @@ namespace SabreTools.Models.Listxml
[XmlAttribute("tilt")]
public string? Tilt { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("players")]
public string Players { get; set; }
diff --git a/SabreTools.Models/Listxml/M1.cs b/SabreTools.Models/Listxml/M1.cs
new file mode 100644
index 00000000..977faa9d
--- /dev/null
+++ b/SabreTools.Models/Listxml/M1.cs
@@ -0,0 +1,28 @@
+using System.Xml;
+using System.Xml.Serialization;
+
+namespace SabreTools.Models.Listxml
+{
+ [XmlRoot("m1")]
+ public class M1
+ {
+ [XmlAttribute("version")]
+ public string? Version { get; set; }
+
+ [XmlElement("machine", typeof(Machine))]
+ [XmlElement("game", typeof(Game))]
+ public GameBase[] Game { get; set; }
+
+ #region DO NOT USE IN PRODUCTION
+
+ /// Should be empty
+ [XmlAnyAttribute]
+ public XmlAttribute[]? ADDITIONAL_ATTRIBUTES { get; set; }
+
+ /// Should be empty
+ [XmlAnyElement]
+ public object[]? ADDITIONAL_ELEMENTS { get; set; }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/SabreTools.Models/Listxml/Machine.cs b/SabreTools.Models/Listxml/Machine.cs
index f25894dc..d4cedaa3 100644
--- a/SabreTools.Models/Listxml/Machine.cs
+++ b/SabreTools.Models/Listxml/Machine.cs
@@ -3,23 +3,5 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Listxml
{
[XmlRoot("machine")]
- public class Machine : GameBase
- {
- /// Appears after Name
-
- [XmlAttribute("sourcefile")]
- public string? SourceFile { get; set; }
-
- /// (yes|no) "no", Appears after SourceFile
- [XmlAttribute("isbios")]
- public string? IsBios { get; set; }
-
- /// (yes|no) "no", Appears after IsBios
- [XmlAttribute("isdevice")]
- public string? IsDevice { get; set; }
-
- /// (yes|no) "no", Appears after IsDevice
- [XmlAttribute("ismechanical")]
- public string? IsMechanical { get; set; }
- }
+ public class Machine : GameBase { }
}
\ No newline at end of file
diff --git a/SabreTools.Models/Listxml/Rom.cs b/SabreTools.Models/Listxml/Rom.cs
index 0b49ca6d..453b8ad0 100644
--- a/SabreTools.Models/Listxml/Rom.cs
+++ b/SabreTools.Models/Listxml/Rom.cs
@@ -12,8 +12,9 @@ namespace SabreTools.Models.Listxml
[XmlAttribute("bios")]
public string? Bios { get; set; }
+ /// Numeric
[XmlAttribute("size")]
- public long Size { get; set; }
+ public string Size { get; set; }
[XmlAttribute("crc")]
public string? CRC { get; set; }
diff --git a/SabreTools.Test/DatTools/ParserTests.cs b/SabreTools.Test/DatTools/ParserTests.cs
index 5466d519..eac293c8 100644
--- a/SabreTools.Test/DatTools/ParserTests.cs
+++ b/SabreTools.Test/DatTools/ParserTests.cs
@@ -12,7 +12,7 @@ namespace SabreTools.Test.DatTools
[InlineData("test-logiqx.xml", DatFormat.Logiqx, 6)]
//[InlineData(null, DatFormat.LogiqxDeprecated, 0)] // Not parsed separately
[InlineData("test-softwarelist.xml", DatFormat.SoftwareList, 5)]
- [InlineData("test-listxml.xml", DatFormat.Listxml, 20)]
+ [InlineData("test-listxml.xml", DatFormat.Listxml, 19)]
[InlineData("test-offlinelist.xml", DatFormat.OfflineList, 1)]
//[InlineData(null, DatFormat.SabreXML, 0)] // TODO: Create good-enough test file for this
[InlineData("test-openmsx.xml", DatFormat.OpenMSX, 3)]
diff --git a/SabreTools.Test/TestData/test-listxml.xml b/SabreTools.Test/TestData/test-listxml.xml
index 6d7cc7f7..f8be5310 100644
--- a/SabreTools.Test/TestData/test-listxml.xml
+++ b/SabreTools.Test/TestData/test-listxml.xml
@@ -12,7 +12,6 @@
-