diff --git a/SabreTools.DatFiles/Formats/Logiqx.Reader.cs b/SabreTools.DatFiles/Formats/Logiqx.Reader.cs
index aa7d96e7..41a56a96 100644
--- a/SabreTools.DatFiles/Formats/Logiqx.Reader.cs
+++ b/SabreTools.DatFiles/Formats/Logiqx.Reader.cs
@@ -1,8 +1,5 @@
using System;
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
-using System.Xml;
-using System.Xml.Schema;
+using System.Linq;
using SabreTools.Core;
using SabreTools.Core.Tools;
using SabreTools.DatItems;
@@ -18,526 +15,267 @@ 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,
- });
-
- List dirs = new();
-
- // 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)
- {
- // If we're ending a dir, remove the last item from the dirs list, if possible
- if (xtr.Name == "dir" && dirs.Count > 0)
- dirs.RemoveAt(dirs.Count - 1);
+ // Deserialize the input file
+ var metadataFile = Serialization.Logiqx.Deserialize(filename);
- xtr.Read();
- continue;
- }
+ // Convert the header to the internal format
+ ConvertHeader(metadataFile, keep);
- switch (xtr.Name)
- {
- // The datafile tag can have some attributes
- case "datafile":
- Header.Build ??= xtr.GetAttribute("build");
- Header.Debug ??= xtr.GetAttribute("debug").AsYesNo();
- xtr.Read();
- break;
+ // Convert the game data to the internal format
+ ConvertGames(metadataFile?.Game, filename, indexId, statsOnly);
- // We want to process the entire subtree of the header
- case "header":
- ReadHeader(xtr.ReadSubtree(), keep);
-
- // Skip the header node now that we've processed it
- xtr.Skip();
- break;
-
- // Unique to RomVault-created DATs
- case "dir":
- Header.Type = "SuperDAT";
- dirs.Add(xtr.GetAttribute("name") ?? string.Empty);
- xtr.Read();
- break;
-
- // We want to process the entire subtree of the game
- case "machine": // New-style Logiqx
- case "game": // Old-style Logiqx
- ReadMachine(xtr.ReadSubtree(), dirs, statsOnly, filename, indexId, keep);
-
- // Skip the machine now that we've processed it
- xtr.Skip();
- break;
-
- default:
- xtr.Read();
- break;
- }
- }
+ // Convert the dir data to the internal format
+ ConvertDirs(metadataFile?.Dir, 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();
}
- ///
- /// Read header information
- ///
- /// XmlReader to use to parse the header
- /// True if full pathnames are to be kept, false otherwise (default)
- private void ReadHeader(XmlReader reader, bool keep)
- {
- bool superdat = false;
+ #region Converters
- // If there's no subtree to the header, skip it
- if (reader == null)
+ ///
+ /// Convert header information
+ ///
+ /// Deserialized model to convert
+ /// True if full pathnames are to be kept, false otherwise (default)
+ private void ConvertHeader(Models.Logiqx.Datafile? datafile, bool keep)
+ {
+ // If the datafile is missing, we can't do anything
+ if (datafile == null)
return;
- // Otherwise, add what is possible
- reader.MoveToContent();
+ Header.Build ??= datafile.Build;
+ Header.Debug ??= datafile.Debug.AsYesNo();
+ // SchemaLocation is specifically skipped
- while (!reader.EOF)
- {
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element || reader.Name == "header")
- {
- reader.Read();
- continue;
- }
-
- // Get all header items (ONLY OVERWRITE IF THERE'S NO DATA)
- string content;
- switch (reader.Name)
- {
- case "id":
- content = reader.ReadElementContentAsString();
- Header.NoIntroID ??= content;
- break;
-
- case "name":
- content = reader.ReadElementContentAsString();
- Header.Name ??= content;
- superdat |= content.Contains(" - SuperDAT");
- if (keep && superdat)
- {
- Header.Type ??= "SuperDAT";
- }
- break;
-
- case "description":
- content = reader.ReadElementContentAsString();
- Header.Description ??= content;
- break;
-
- case "rootdir": // This is exclusive to TruRip XML
- content = reader.ReadElementContentAsString();
- Header.RootDir ??= content;
- break;
-
- case "category":
- content = reader.ReadElementContentAsString();
- Header.Category = (Header.Category == null ? content : $"{Header.Category};{content}");
- break;
-
- case "version":
- content = reader.ReadElementContentAsString();
- Header.Version ??= content;
- break;
-
- case "date":
- content = reader.ReadElementContentAsString();
- Header.Date ??= content.Replace(".", "/");
- break;
-
- case "author":
- content = reader.ReadElementContentAsString();
- Header.Author ??= content;
- break;
-
- case "email":
- content = reader.ReadElementContentAsString();
- Header.Email ??= content;
- break;
-
- case "homepage":
- content = reader.ReadElementContentAsString();
- Header.Homepage ??= content;
- break;
-
- case "url":
- content = reader.ReadElementContentAsString();
- Header.Url ??= content;
- break;
-
- case "comment":
- content = reader.ReadElementContentAsString();
- Header.Comment = (Header.Comment ?? content);
- break;
-
- case "type": // This is exclusive to TruRip XML
- content = reader.ReadElementContentAsString();
- Header.Type ??= content;
- superdat |= content.Contains("SuperDAT");
- break;
-
- case "clrmamepro":
- if (Header.HeaderSkipper == null)
- Header.HeaderSkipper = reader.GetAttribute("header");
-
- if (Header.ForceMerging == MergingFlag.None)
- Header.ForceMerging = reader.GetAttribute("forcemerging").AsMergingFlag();
-
- if (Header.ForceNodump == NodumpFlag.None)
- Header.ForceNodump = reader.GetAttribute("forcenodump").AsNodumpFlag();
-
- if (Header.ForcePacking == PackingFlag.None)
- Header.ForcePacking = reader.GetAttribute("forcepacking").AsPackingFlag();
-
- reader.Read();
- break;
-
- case "romcenter":
- if (Header.System == null)
- Header.System = reader.GetAttribute("plugin");
-
- if (Header.RomMode == MergingFlag.None)
- Header.RomMode = reader.GetAttribute("rommode").AsMergingFlag();
-
- if (Header.BiosMode == MergingFlag.None)
- Header.BiosMode = reader.GetAttribute("biosmode").AsMergingFlag();
-
- if (Header.SampleMode == MergingFlag.None)
- Header.SampleMode = reader.GetAttribute("samplemode").AsMergingFlag();
-
- if (Header.LockRomMode == null)
- Header.LockRomMode = reader.GetAttribute("lockrommode").AsYesNo();
-
- if (Header.LockBiosMode == null)
- Header.LockBiosMode = reader.GetAttribute("lockbiosmode").AsYesNo();
-
- if (Header.LockSampleMode == null)
- Header.LockSampleMode = reader.GetAttribute("locksamplemode").AsYesNo();
-
- reader.Read();
- break;
- default:
- reader.Read();
- break;
- }
- }
+ ConvertHeader(datafile.Header, keep);
}
///
- /// Read game/machine information
+ /// Convert header information
///
- /// XmlReader to use to parse the machine
- /// List of dirs to prepend to the game name
- /// True to only add item statistics while parsing, false otherwise
+ /// Deserialized model to convert
+ /// True if full pathnames are to be kept, false otherwise (default)
+ private void ConvertHeader(Models.Logiqx.Header? header, bool keep)
+ {
+ // If the header is missing, we can't do anything
+ if (header == null)
+ return;
+
+ Header.NoIntroID ??= header.Id;
+ Header.Name ??= header.Name;
+ Header.Description ??= header.Description;
+ Header.RootDir ??= header.RootDir;
+ Header.Category ??= header.Category;
+ Header.Version ??= header.Version;
+ Header.Date ??= header.Date;
+ Header.Author ??= header.Author;
+ Header.Email ??= header.Email;
+ Header.Homepage ??= header.Homepage;
+ Header.Url ??= header.Url;
+ Header.Comment ??= header.Comment;
+ Header.Type ??= header.Type;
+
+ ConvertSubheader(header.ClrMamePro);
+ ConvertSubheader(header.RomCenter);
+
+ // Handle implied SuperDAT
+ if (header.Name.Contains(" - SuperDAT") && keep)
+ Header.Type ??= "SuperDAT";
+ }
+
+ ///
+ /// Convert subheader information
+ ///
+ /// Deserialized model to convert
+ private void ConvertSubheader(Models.Logiqx.ClrMamePro? clrMamePro)
+ {
+ // If the subheader is missing, we can't do anything
+ if (clrMamePro == null)
+ return;
+
+ Header.HeaderSkipper ??= clrMamePro.Header;
+
+ if (Header.ForceMerging == MergingFlag.None)
+ Header.ForceMerging = clrMamePro.ForceMerging.AsMergingFlag();
+ if (Header.ForceNodump == NodumpFlag.None)
+ Header.ForceNodump = clrMamePro.ForceNodump.AsNodumpFlag();
+ if (Header.ForcePacking == PackingFlag.None)
+ Header.ForcePacking = clrMamePro.ForcePacking.AsPackingFlag();
+ }
+
+ ///
+ /// Convert subheader information
+ ///
+ /// Deserialized model to convert
+ private void ConvertSubheader(Models.Logiqx.RomCenter? romCenter)
+ {
+ // If the subheader is missing, we can't do anything
+ if (romCenter == null)
+ return;
+
+ Header.System ??= romCenter.Plugin;
+
+ if (Header.RomMode == MergingFlag.None)
+ Header.RomMode = romCenter.RomMode.AsMergingFlag();
+ if (Header.BiosMode == MergingFlag.None)
+ Header.BiosMode = romCenter.BiosMode.AsMergingFlag();
+ if (Header.SampleMode == MergingFlag.None)
+ Header.SampleMode = romCenter.SampleMode.AsMergingFlag();
+
+ Header.LockRomMode ??= romCenter.LockRomMode.AsYesNo();
+ Header.LockBiosMode ??= romCenter.LockBiosMode.AsYesNo();
+ Header.LockSampleMode ??= romCenter.LockSampleMode.AsYesNo();
+ }
+
+ ///
+ /// Convert dirs information
+ ///
+ /// Array of deserialized models to convert
/// Name of the file to be parsed
/// Index ID for the DAT
- /// True if full pathnames are to be kept, false otherwise (default)
- private void ReadMachine(
- XmlReader reader,
- List dirs,
- bool statsOnly,
-
- // Standard Dat parsing
- string filename,
- int indexId,
-
- // Miscellaneous
- bool keep)
+ /// True to only add item statistics while parsing, false otherwise
+ private void ConvertDirs(Models.Logiqx.Dir[]? dirs, string filename, int indexId, bool statsOnly)
{
- // If we have an empty machine, skip it
- if (reader == null)
+ // If the dir array is missing, we can't do anything
+ if (dirs == null || !dirs.Any())
return;
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- bool containsItems = false;
-
- // Create a new machine
- MachineType machineType = 0x0;
- if (reader.GetAttribute("isbios").AsYesNo() == true)
- machineType |= MachineType.Bios;
-
- string dirsString = (dirs != null && dirs.Count > 0 ? string.Join("/", dirs) + "/" : string.Empty);
- Machine machine = new()
+ // Loop through the dirs and add
+ foreach (var dir in dirs)
{
- Name = dirsString + reader.GetAttribute("name"),
- Description = dirsString + reader.GetAttribute("name"),
- SourceFile = reader.GetAttribute("sourcefile"),
- Board = reader.GetAttribute("board"),
- RebuildTo = reader.GetAttribute("rebuildto"),
- NoIntroId = reader.GetAttribute("id"),
- NoIntroCloneOfId = reader.GetAttribute("cloneofid"),
- Runnable = reader.GetAttribute("runnable").AsRunnable(), // Used by older DATs
+ ConvertDir(dir, filename, indexId, statsOnly);
+ }
+ }
- CloneOf = reader.GetAttribute("cloneof"),
- RomOf = reader.GetAttribute("romof"),
- SampleOf = reader.GetAttribute("sampleof"),
+ ///
+ /// Convert dir 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 ConvertDir(Models.Logiqx.Dir dir, string filename, int indexId, bool statsOnly)
+ {
+ // If the game array is missing, we can't do anything
+ if (dir.Game == null || !dir.Game.Any())
+ return;
- MachineType = (machineType == 0x0 ? MachineType.None : machineType),
+ // Loop through the games and add
+ foreach (var game in dir.Game)
+ {
+ ConvertGame(game, filename, indexId, statsOnly, dir.Name);
+ }
+ }
+
+ ///
+ /// Convert games 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 ConvertGames(Models.Logiqx.GameBase[]? games, string filename, int indexId, bool statsOnly)
+ {
+ // If the game array is missing, we can't do anything
+ if (games == null || !games.Any())
+ return;
+
+ // Loop through the games and add
+ foreach (var game in games)
+ {
+ ConvertGame(game, filename, indexId, statsOnly);
+ }
+ }
+
+ ///
+ /// 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.Logiqx.GameBase game, string filename, int indexId, bool statsOnly, string dirname = null)
+ {
+ // 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,
+ CloneOf = game.CloneOf,
+ RomOf = game.RomOf,
+ SampleOf = game.SampleOf,
+ Board = game.Board,
+ RebuildTo = game.RebuildTo,
+ NoIntroId = game.Id,
+ NoIntroCloneOfId = game.CloneOfId,
+ Runnable = game.Runnable.AsRunnable(),
+
+ Comment = string.Join(';', game.Comment),
+ Description = game.Description,
+ Year = game.Year,
+ Manufacturer = game.Manufacturer,
+ Publisher = game.Publisher,
+ Category = string.Join(';', game.Category),
};
- if (Header.Type == "SuperDAT" && !keep)
+ if (!string.IsNullOrWhiteSpace(dirname))
+ machine.Name = $"{dirname}/{machine.Name}";
+
+ 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;
+
+ if (game.Trurip != null)
{
- string tempout = Regex.Match(machine.Name, @".*?\\(.*)").Groups[1].Value;
- if (!string.IsNullOrWhiteSpace(tempout))
- machine.Name = tempout;
+ var trurip = game.Trurip;
+
+ machine.TitleID = trurip.TitleID;
+ machine.Publisher = trurip.Publisher;
+ machine.Developer = trurip.Developer;
+ machine.Year = trurip.Year;
+ machine.Genre = trurip.Genre;
+ machine.Subgenre = trurip.Subgenre;
+ machine.Ratings = trurip.Ratings;
+ machine.Score = trurip.Score;
+ machine.Players = trurip.Players;
+ machine.Enabled = trurip.Enabled;
+ machine.Crc = trurip.CRC.AsYesNo();
+ machine.SourceFile = trurip.Source;
+ machine.CloneOf = trurip.CloneOf;
+ machine.RelatedTo = trurip.RelatedTo;
}
- while (!reader.EOF)
- {
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
- {
- reader.Read();
- continue;
- }
+ // Check if there are any items
+ bool containsItems = false;
- // Get the roms from the machine
- switch (reader.Name)
- {
- case "comment": // There can be multiple comments by spec
- machine.Comment += reader.ReadElementContentAsString();
- break;
+ // Loop through each type of item
+ ConvertReleases(game.Release, machine, filename, indexId, statsOnly, ref containsItems);
+ 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);
+ ConvertMedia(game.Media, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertDeviceRefs(game.DeviceRef, 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);
- case "description":
- machine.Description = reader.ReadElementContentAsString();
- break;
-
- case "year":
- machine.Year = reader.ReadElementContentAsString();
- break;
-
- case "manufacturer":
- machine.Manufacturer = reader.ReadElementContentAsString();
- break;
-
- case "publisher": // Not technically supported but used by some legacy DATs
- machine.Publisher = reader.ReadElementContentAsString();
- break;
-
- case "category": // Not technically supported but used by some legacy DATs
- machine.Category = reader.ReadElementContentAsString();
- break;
-
- case "trurip": // This is special metadata unique to EmuArc
- ReadTruRip(reader.ReadSubtree(), machine);
-
- // Skip the trurip node now that we've processed it
- reader.Skip();
- break;
-
- case "archive":
- containsItems = true;
-
- DatItem archive = new Archive
- {
- Name = reader.GetAttribute("name"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- archive.CopyMachineInformation(machine);
-
- // Now process and add the archive
- ParseAddHelper(archive, statsOnly);
-
- reader.Read();
- break;
-
- case "biosset":
- containsItems = true;
-
- DatItem biosSet = new BiosSet
- {
- Name = reader.GetAttribute("name"),
- Description = reader.GetAttribute("description"),
- Default = reader.GetAttribute("default").AsYesNo(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- biosSet.CopyMachineInformation(machine);
-
- // Now process and add the biosSet
- ParseAddHelper(biosSet, statsOnly);
-
- reader.Read();
- break;
-
- case "disk":
- containsItems = true;
-
- DatItem disk = new Disk
- {
- Name = reader.GetAttribute("name"),
- MD5 = reader.GetAttribute("md5"),
- SHA1 = reader.GetAttribute("sha1"),
- MergeTag = reader.GetAttribute("merge"),
- ItemStatus = reader.GetAttribute("status").AsItemStatus(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- disk.CopyMachineInformation(machine);
-
- // Now process and add the disk
- ParseAddHelper(disk, statsOnly);
-
- reader.Read();
- break;
-
- case "media":
- containsItems = true;
-
- DatItem media = new Media
- {
- Name = reader.GetAttribute("name"),
- MD5 = reader.GetAttribute("md5"),
- SHA1 = reader.GetAttribute("sha1"),
- SHA256 = reader.GetAttribute("sha256"),
- SpamSum = reader.GetAttribute("spamsum"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- media.CopyMachineInformation(machine);
-
- // Now process and add the media
- ParseAddHelper(media, statsOnly);
-
- reader.Read();
- break;
-
- case "release":
- containsItems = true;
-
- DatItem release = new Release
- {
- Name = reader.GetAttribute("name"),
- Region = reader.GetAttribute("region"),
- Language = reader.GetAttribute("language"),
- Date = reader.GetAttribute("date"),
- Default = reader.GetAttribute("default").AsYesNo(),
- };
-
- release.CopyMachineInformation(machine);
-
- // Now process and add the release
- ParseAddHelper(release, statsOnly);
-
- reader.Read();
- break;
-
- case "rom":
- containsItems = true;
-
- DatItem rom = new Rom
- {
- Name = reader.GetAttribute("name"),
- Size = Utilities.CleanLong(reader.GetAttribute("size")),
- CRC = reader.GetAttribute("crc"),
- MD5 = reader.GetAttribute("md5"),
- SHA1 = reader.GetAttribute("sha1"),
- SHA256 = reader.GetAttribute("sha256"),
- SHA384 = reader.GetAttribute("sha384"),
- SHA512 = reader.GetAttribute("sha512"),
- SpamSum = reader.GetAttribute("spamsum"),
- MergeTag = reader.GetAttribute("merge"),
- ItemStatus = reader.GetAttribute("status").AsItemStatus(),
- Date = CleanDate(reader.GetAttribute("date")),
- Inverted = reader.GetAttribute("inverted").AsYesNo(),
- MIA = reader.GetAttribute("mia").AsYesNo(),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- rom.CopyMachineInformation(machine);
-
- // Now process and add the rom
- ParseAddHelper(rom, statsOnly);
-
- reader.Read();
- break;
-
- case "sample":
- containsItems = true;
-
- DatItem sample = new Sample
- {
- Name = reader.GetAttribute("name"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- };
-
- sample.CopyMachineInformation(machine);
-
- // Now process and add the sample
- ParseAddHelper(sample, statsOnly);
-
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
- }
-
- // If no items were found for this machine, add a Blank placeholder
+ // If we had no items, create a Blank placeholder
if (!containsItems)
{
- Blank blank = new()
+ var blank = new Blank
{
Source = new Source
{
@@ -547,99 +285,391 @@ namespace SabreTools.DatFiles.Formats
};
blank.CopyMachineInformation(machine);
-
- // Now process and add the rom
ParseAddHelper(blank, statsOnly);
}
}
///
- /// Read EmuArc information
+ /// Convert Release information
///
- /// True if full pathnames are to be kept, false otherwise (default)
- /// Machine information to pass to contained items
- private void ReadTruRip(XmlReader reader, Machine machine)
+ /// 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 ConvertReleases(Models.Logiqx.Release[]? releases, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty trurip, skip it
- if (reader == null)
+ // If the release array is missing, we can't do anything
+ if (releases == null || !releases.Any())
return;
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ containsItems = true;
+ foreach (var release in releases)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var item = new Release
{
- reader.Read();
- continue;
- }
+ Name = release.Name,
+ Region = release.Region,
+ Language = release.Language,
+ Date = release.Date,
+ Default = release.Default?.AsYesNo(),
- // Get the information from the trurip
- switch (reader.Name)
- {
- case "titleid":
- machine.TitleID = reader.ReadElementContentAsString();
- break;
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
- case "publisher":
- machine.Publisher = reader.ReadElementContentAsString();
- break;
-
- case "developer":
- machine.Developer = reader.ReadElementContentAsString();
- break;
-
- case "year":
- machine.Year = reader.ReadElementContentAsString();
- break;
-
- case "genre":
- machine.Genre = reader.ReadElementContentAsString();
- break;
-
- case "subgenre":
- machine.Subgenre = reader.ReadElementContentAsString();
- break;
-
- case "ratings":
- machine.Ratings = reader.ReadElementContentAsString();
- break;
-
- case "score":
- machine.Score = reader.ReadElementContentAsString();
- break;
-
- case "players":
- machine.Players = reader.ReadElementContentAsString();
- break;
-
- case "enabled":
- machine.Enabled = reader.ReadElementContentAsString();
- break;
-
- case "crc":
- machine.Crc = reader.ReadElementContentAsString().AsYesNo();
- break;
-
- case "source":
- machine.SourceFile = reader.ReadElementContentAsString();
- break;
-
- case "cloneof":
- machine.CloneOf = reader.ReadElementContentAsString();
- break;
-
- case "relatedto":
- machine.RelatedTo = reader.ReadElementContentAsString();
- break;
-
- default:
- reader.Read();
- break;
- }
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
}
}
+
+ ///
+ /// Convert BiosSet 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 ConvertBiosSets(Models.Logiqx.BiosSet[]? biossets, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the biosset array is missing, we can't do anything
+ if (biossets == null || !biossets.Any())
+ return;
+
+ containsItems = true;
+ foreach (var biosset in biossets)
+ {
+ var item = new BiosSet
+ {
+ Name = biosset.Name,
+ Description = biosset.Description,
+ Default = biosset.Default?.AsYesNo(),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert Rom 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 ConvertRoms(Models.Logiqx.Rom[]? roms, 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
+ {
+ Name = rom.Name,
+ Size = Utilities.CleanLong(rom.Size),
+ CRC = rom.CRC,
+ MD5 = rom.MD5,
+ SHA1 = rom.SHA1,
+ SHA256 = rom.SHA256,
+ SHA384 = rom.SHA384,
+ SHA512 = rom.SHA512,
+ SpamSum = rom.SpamSum,
+ //xxHash364 = rom.xxHash364, // TODO: Add to internal model
+ //xxHash3128 = rom.xxHash3128, // TODO: Add to internal model
+ MergeTag = rom.Merge,
+ ItemStatus = rom.Status?.AsItemStatus() ?? ItemStatus.NULL,
+ //Serial = rom.Serial, // TODO: Add to internal model
+ //Header = rom.Header, // TODO: Add to internal model
+ Date = rom.Date,
+ Inverted = rom.Inverted?.AsYesNo(),
+ MIA = rom.MIA?.AsYesNo(),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert Disk 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 ConvertDisks(Models.Logiqx.Disk[]? disks, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the disk 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
+ {
+ Name = disk.Name,
+ MD5 = disk.MD5,
+ SHA1 = disk.SHA1,
+ MergeTag = disk.Merge,
+ ItemStatus = disk.Status?.AsItemStatus() ?? ItemStatus.NULL,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert Media 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 ConvertMedia(Models.Logiqx.Media[]? media, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the media array is missing, we can't do anything
+ if (media == null || !media.Any())
+ return;
+
+ containsItems = true;
+ foreach (var medium in media)
+ {
+ var item = new Media
+ {
+ Name = medium.Name,
+ MD5 = medium.MD5,
+ SHA1 = medium.SHA1,
+ SHA256 = medium.SHA256,
+ SpamSum = medium.SpamSum,
+
+ 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.Logiqx.DeviceRef[]? devicerefs, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the devicerefs 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 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 ConvertSamples(Models.Logiqx.Sample[]? samples, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the samples 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 Archive 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 ConvertArchives(Models.Logiqx.Archive[]? archives, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the archive array is missing, we can't do anything
+ if (archives == null || !archives.Any())
+ return;
+
+ containsItems = true;
+ foreach (var archive in archives)
+ {
+ var item = new Archive
+ {
+ Name = archive.Name,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert Driver 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 ConvertDrivers(Models.Logiqx.Driver[]? drivers, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the drivers array is missing, we can't do anything
+ if (drivers == null || !drivers.Any())
+ return;
+
+ containsItems = true;
+ foreach (var driver in drivers)
+ {
+ var item = new Driver
+ {
+ Status = driver.Status?.AsSupportStatus() ?? SupportStatus.NULL,
+ Emulation = driver.Emulation?.AsSupportStatus() ?? SupportStatus.NULL,
+ Cocktail = driver.Cocktail?.AsSupportStatus() ?? SupportStatus.NULL,
+ SaveState = driver.SaveState?.AsSupported() ?? Supported.NULL,
+ RequiresArtwork = driver.RequiresArtwork?.AsYesNo(),
+ Unofficial = driver.Unofficial?.AsYesNo(),
+ NoSoundHardware = driver.NoSoundHardware?.AsYesNo(),
+ Incomplete = driver.Incomplete?.AsYesNo(),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ 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.Logiqx.SoftwareList[]? softwarelists, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the softwarelists 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() ?? SoftwareListStatus.None,
+ Filter = softwarelist.Filter,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ #endregion
}
}
diff --git a/SabreTools.Models/Logiqx/Archive.cs b/SabreTools.Models/Logiqx/Archive.cs
index 68d41b8f..116e92b2 100644
--- a/SabreTools.Models/Logiqx/Archive.cs
+++ b/SabreTools.Models/Logiqx/Archive.cs
@@ -4,9 +4,21 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Logiqx
{
[XmlRoot("archive")]
- public class Archive : ItemBase
+ public class Archive
{
[XmlAttribute("name")]
public string Name { 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/Logiqx/BiosSet.cs b/SabreTools.Models/Logiqx/BiosSet.cs
index bf928661..6ee7315c 100644
--- a/SabreTools.Models/Logiqx/BiosSet.cs
+++ b/SabreTools.Models/Logiqx/BiosSet.cs
@@ -4,7 +4,7 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Logiqx
{
[XmlRoot("biosset")]
- public class BiosSet : ItemBase
+ public class BiosSet
{
[XmlAttribute("name")]
public string Name { get; set; }
@@ -15,5 +15,17 @@ namespace SabreTools.Models.Logiqx
/// (yes|no) "no"
[XmlAttribute("default")]
public string? Default { 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/Logiqx/DeviceRef.cs b/SabreTools.Models/Logiqx/DeviceRef.cs
index e2a0937c..bad6f97e 100644
--- a/SabreTools.Models/Logiqx/DeviceRef.cs
+++ b/SabreTools.Models/Logiqx/DeviceRef.cs
@@ -4,9 +4,21 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Logiqx
{
[XmlRoot("device_ref")]
- public class DeviceRef : ItemBase
+ public class DeviceRef
{
[XmlAttribute("name")]
public string Name { 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/Logiqx/Disk.cs b/SabreTools.Models/Logiqx/Disk.cs
index 9d9e81f7..b1c37ebf 100644
--- a/SabreTools.Models/Logiqx/Disk.cs
+++ b/SabreTools.Models/Logiqx/Disk.cs
@@ -4,7 +4,7 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Logiqx
{
[XmlRoot("disk")]
- public class Disk : ItemBase
+ public class Disk
{
[XmlAttribute("name")]
public string Name { get; set; }
@@ -29,5 +29,17 @@ namespace SabreTools.Models.Logiqx
public string? Region { get; set; }
#endregion
+
+ #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/Logiqx/Driver.cs b/SabreTools.Models/Logiqx/Driver.cs
index d970b328..2485c552 100644
--- a/SabreTools.Models/Logiqx/Driver.cs
+++ b/SabreTools.Models/Logiqx/Driver.cs
@@ -4,7 +4,7 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Logiqx
{
[XmlRoot("driver")]
- public class Driver : ItemBase
+ public class Driver
{
/// (good|imperfect|preliminary)
[XmlAttribute("status")]
@@ -37,5 +37,17 @@ namespace SabreTools.Models.Logiqx
/// (yes|no) "no"
[XmlAttribute("incomplete")]
public string? Incomplete { 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/Logiqx/GameBase.cs b/SabreTools.Models/Logiqx/GameBase.cs
index 12b00bb8..f4e98fed 100644
--- a/SabreTools.Models/Logiqx/GameBase.cs
+++ b/SabreTools.Models/Logiqx/GameBase.cs
@@ -56,17 +56,35 @@ namespace SabreTools.Models.Logiqx
[XmlElement("category")]
public string[]? Category { get; set; }
- [XmlElement("release", typeof(Release))]
- [XmlElement("biosset", typeof(BiosSet))]
- [XmlElement("rom", typeof(Rom))]
- [XmlElement("disk", typeof(Disk))]
- [XmlElement("media", typeof(Media))] // Aaru extension
- [XmlElement("device_ref", typeof(DeviceRef))] // MAME extension
- [XmlElement("sample", typeof(Sample))]
- [XmlElement("archive", typeof(Archive))]
- [XmlElement("driver", typeof(Driver))] // MAME extension
- [XmlElement("softwarelist", typeof(SoftwareList))] // MAME extension
- public ItemBase[]? Item { get; set; }
+ [XmlElement(elementName: "release")]
+ public Release[]? Release { get; set; }
+
+ [XmlElement("biosset")]
+ public BiosSet[]? BiosSet { get; set; }
+
+ [XmlElement("rom")]
+ public Rom[]? Rom { get; set; }
+
+ [XmlElement("disk")]
+ public Disk[]? Disk { get; set; }
+
+ [XmlElement("media")] // Aaru extension
+ public Media[]? Media { get; set; }
+
+ [XmlElement("device_ref")] // MAME extension
+ public DeviceRef[]? DeviceRef { get; set; }
+
+ [XmlElement("sample")]
+ public Sample[]? Sample { get; set; }
+
+ [XmlElement("archive")]
+ public Archive[]? Archive { get; set; }
+
+ [XmlElement("driver")] // MAME extension
+ public Driver[]? Driver { get; set; }
+
+ [XmlElement("softwarelist")] // MAME extension
+ public SoftwareList[]? SoftwareList { get; set; }
#region MAME Extensions
diff --git a/SabreTools.Models/Logiqx/ItemBase.cs b/SabreTools.Models/Logiqx/ItemBase.cs
deleted file mode 100644
index 61b16a51..00000000
--- a/SabreTools.Models/Logiqx/ItemBase.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System.Xml;
-using System.Xml.Serialization;
-
-namespace SabreTools.Models.Logiqx
-{
- ///
- /// Base class to unify the various item types
- ///
- public abstract class ItemBase
- {
- #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/Logiqx/Media.cs b/SabreTools.Models/Logiqx/Media.cs
index c26d295a..deb1f008 100644
--- a/SabreTools.Models/Logiqx/Media.cs
+++ b/SabreTools.Models/Logiqx/Media.cs
@@ -4,7 +4,7 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Logiqx
{
[XmlRoot("media")]
- public class Media : ItemBase
+ public class Media
{
[XmlAttribute("name")]
public string Name { get; set; }
@@ -20,5 +20,17 @@ namespace SabreTools.Models.Logiqx
[XmlAttribute("spamsum")]
public string? SpamSum { 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/Logiqx/Release.cs b/SabreTools.Models/Logiqx/Release.cs
index 68a9d581..0210a322 100644
--- a/SabreTools.Models/Logiqx/Release.cs
+++ b/SabreTools.Models/Logiqx/Release.cs
@@ -4,7 +4,7 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Logiqx
{
[XmlRoot("release")]
- public class Release : ItemBase
+ public class Release
{
[XmlAttribute("name")]
public string Name { get; set; }
@@ -21,5 +21,17 @@ namespace SabreTools.Models.Logiqx
/// (yes|no) "no"
[XmlAttribute("default")]
public string? Default { 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/Logiqx/Rom.cs b/SabreTools.Models/Logiqx/Rom.cs
index 74a1820c..5d60d03a 100644
--- a/SabreTools.Models/Logiqx/Rom.cs
+++ b/SabreTools.Models/Logiqx/Rom.cs
@@ -4,13 +4,13 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Logiqx
{
[XmlRoot("rom")]
- public class Rom : ItemBase
+ public class Rom
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("size")]
- public long Size { get; set; }
+ public string Size { get; set; }
[XmlAttribute("crc")]
public string? CRC { get; set; }
@@ -86,5 +86,17 @@ namespace SabreTools.Models.Logiqx
public string? MIA { get; set; }
#endregion
+
+ #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/Logiqx/Sample.cs b/SabreTools.Models/Logiqx/Sample.cs
index 3dccd9df..e9c05638 100644
--- a/SabreTools.Models/Logiqx/Sample.cs
+++ b/SabreTools.Models/Logiqx/Sample.cs
@@ -4,9 +4,21 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Logiqx
{
[XmlRoot("sample")]
- public class Sample : ItemBase
+ public class Sample
{
[XmlAttribute("name")]
public string Name { 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/Logiqx/SoftwareList.cs b/SabreTools.Models/Logiqx/SoftwareList.cs
index fa3b39d4..b2e3d91c 100644
--- a/SabreTools.Models/Logiqx/SoftwareList.cs
+++ b/SabreTools.Models/Logiqx/SoftwareList.cs
@@ -4,7 +4,7 @@ using System.Xml.Serialization;
namespace SabreTools.Models.Logiqx
{
[XmlRoot("softwarelist")]
- public class SoftwareList : ItemBase
+ public class SoftwareList
{
[XmlAttribute("tag")]
public string Tag { get; set; }
@@ -18,5 +18,17 @@ namespace SabreTools.Models.Logiqx
[XmlAttribute("filter")]
public string? Filter { 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.Test/Serialization/DeserializationTests.cs b/SabreTools.Test/Serialization/DeserializationTests.cs
index d6aa7d06..f79b32ba 100644
--- a/SabreTools.Test/Serialization/DeserializationTests.cs
+++ b/SabreTools.Test/Serialization/DeserializationTests.cs
@@ -541,7 +541,61 @@ namespace SabreTools.Test.Parser
Assert.Null(game.ADDITIONAL_ATTRIBUTES);
Assert.Null(game.ADDITIONAL_ELEMENTS);
- foreach (var item in game.Item ?? Array.Empty())
+ foreach (var item in game.Release ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.BiosSet ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Rom ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Disk ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Media ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.DeviceRef ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Sample ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Archive ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Driver ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.SoftwareList ?? Array.Empty())
{
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
Assert.Null(item.ADDITIONAL_ELEMENTS);
@@ -562,11 +616,65 @@ namespace SabreTools.Test.Parser
Assert.Null(game.ADDITIONAL_ATTRIBUTES);
Assert.Null(game.ADDITIONAL_ELEMENTS);
- foreach (var item in game.Item ?? Array.Empty())
- {
- Assert.Null(item.ADDITIONAL_ATTRIBUTES);
- Assert.Null(item.ADDITIONAL_ELEMENTS);
- }
+ foreach (var item in game.Release ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.BiosSet ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Rom ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Disk ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Media ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.DeviceRef ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Sample ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Archive ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.Driver ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
+
+ foreach (var item in game.SoftwareList ?? Array.Empty())
+ {
+ Assert.Null(item.ADDITIONAL_ATTRIBUTES);
+ Assert.Null(item.ADDITIONAL_ELEMENTS);
+ }
if (game.Trurip != null)
{