diff --git a/SabreTools.Data.Models/Logiqx/GameBase.cs b/SabreTools.Data.Models/Logiqx/GameBase.cs index 8dda6ebc..28e6d4ab 100644 --- a/SabreTools.Data.Models/Logiqx/GameBase.cs +++ b/SabreTools.Data.Models/Logiqx/GameBase.cs @@ -78,7 +78,7 @@ namespace SabreTools.Data.Models.Logiqx [XmlElement("trurip")] public Trurip? Trurip { get; set; } - [XmlElement(elementName: "release")] + [XmlElement("release")] public Release[]? Release { get; set; } [XmlElement("biosset")] diff --git a/SabreTools.Serialization.Readers.Test/LogiqxTests.cs b/SabreTools.Serialization.Readers.Test/LogiqxTests.cs index d31d7eaa..39750fb0 100644 --- a/SabreTools.Serialization.Readers.Test/LogiqxTests.cs +++ b/SabreTools.Serialization.Readers.Test/LogiqxTests.cs @@ -90,7 +90,7 @@ namespace SabreTools.Serialization.Readers.Test Assert.NotNull(newDf); Assert.Equal("XXXXXX", newDf.Build); Assert.Equal("XXXXXX", newDf.Debug); - Assert.Equal("XXXXXX", newDf.SchemaLocation); + // Assert.Equal("XXXXXX", newDf.SchemaLocation); // TODO: Fix this based on No-Intro DATs Validate(newDf.Header); Assert.NotNull(newDf.Game); @@ -122,7 +122,7 @@ namespace SabreTools.Serialization.Readers.Test Assert.NotNull(newDf); Assert.Equal("XXXXXX", newDf.Build); Assert.Equal("XXXXXX", newDf.Debug); - Assert.Equal("XXXXXX", newDf.SchemaLocation); + // Assert.Equal("XXXXXX", newDf.SchemaLocation); // TODO: Fix this based on No-Intro DATs Validate(newDf.Header); Assert.NotNull(newDf.Game); diff --git a/SabreTools.Serialization.Readers.Test/OfflineListTests.cs b/SabreTools.Serialization.Readers.Test/OfflineListTests.cs index 76df621e..3ed1d29f 100644 --- a/SabreTools.Serialization.Readers.Test/OfflineListTests.cs +++ b/SabreTools.Serialization.Readers.Test/OfflineListTests.cs @@ -88,7 +88,7 @@ namespace SabreTools.Serialization.Readers.Test // Validate the data Assert.NotNull(newDat); - Assert.Equal("XXXXXX", newDat.NoNamespaceSchemaLocation); + // Assert.Equal("XXXXXX", newDat.NoNamespaceSchemaLocation); // TODO: Fix this based on schema Validate(newDat.Configuration); Validate(newDat.Games); Validate(newDat.GUI); diff --git a/SabreTools.Serialization.Readers/ArchiveDotOrg.cs b/SabreTools.Serialization.Readers/ArchiveDotOrg.cs index 04730f3d..9add6d13 100644 --- a/SabreTools.Serialization.Readers/ArchiveDotOrg.cs +++ b/SabreTools.Serialization.Readers/ArchiveDotOrg.cs @@ -1,9 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Xml; using SabreTools.Data.Models.ArchiveDotOrg; namespace SabreTools.Serialization.Readers { - public class ArchiveDotOrg : XmlFile + public class ArchiveDotOrg : BaseBinaryReader { - // All logic taken care of in the base class + /// + public override Files? Deserialize(System.IO.Stream? data) + { + // If the data is invalid + if (data is null || !data.CanRead) + return null; + + try + { + // Cache the current offset + long initialOffset = data.Position; + + // Create the XmlTextReader + var reader = new XmlTextReader(data); + reader.WhitespaceHandling = WhitespaceHandling.None; + + // Parse the XML, if possible + Files? files = null; + while (reader.Read()) + { + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "files": + if (files is not null && Debug) + Console.WriteLine($"'{reader.Name}' element already found, overwriting"); + + files = ParseFiles(reader); + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + break; + } + } + + return files; + } + catch + { + // Ignore the actual error + return null; + } + } + + /// + /// Parse from an XmlTextReader into a Files + /// + /// XmlTextReader to read from + /// Filled Files on success, null on error + public Files ParseFiles(XmlTextReader reader) + { + var obj = new Files(); + + List files = []; + while (reader.Read()) + { + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "file": + var file = ParseFile(reader); + if (file is not null) + files.Add(file); + + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + reader.Skip(); + break; + } + } + + obj.File = [.. files]; + + return obj; + } + + /// + /// Parse from an XmlTextReader into a File + /// + /// XmlTextReader to read from + /// Filled File on success, null on error + public File ParseFile(XmlTextReader reader) + { + var obj = new File(); + + obj.Name = reader.GetAttribute("name"); + obj.Source = reader.GetAttribute("source"); + + reader.Read(); + while (!reader.EOF) + { + // An ending element means exit + if (reader.NodeType == XmlNodeType.EndElement) + break; + + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "btih": + obj.BitTorrentMagnetHash = reader.ReadElementContentAsString(); + break; + case "mtime": + obj.LastModifiedTime = reader.ReadElementContentAsString(); + break; + case "size": + obj.Size = reader.ReadElementContentAsString(); + break; + case "md5": + obj.MD5 = reader.ReadElementContentAsString(); + break; + case "crc32": + obj.CRC32 = reader.ReadElementContentAsString(); + break; + case "sha1": + obj.SHA1 = reader.ReadElementContentAsString(); + break; + case "filecount": + obj.FileCount = reader.ReadElementContentAsString(); + break; + case "format": + obj.Format = reader.ReadElementContentAsString(); + break; + case "original": + obj.Original = reader.ReadElementContentAsString(); + break; + case "summation": + obj.Summation = reader.ReadElementContentAsString(); + break; + case "matrix_number": + obj.MatrixNumber = reader.ReadElementContentAsString(); + break; + case "collection-catalog-number": + obj.CollectionCatalogNumber = reader.ReadElementContentAsString(); + break; + case "publisher": + obj.Publisher = reader.ReadElementContentAsString(); + break; + case "comment": + obj.Comment = reader.ReadElementContentAsString(); + break; + + // ASR-Related + case "asr_detected_lang": + obj.ASRDetectedLang = reader.ReadElementContentAsString(); + break; + case "asr_detected_lang_conf": + obj.ASRDetectedLangConf = reader.ReadElementContentAsString(); + break; + case "asr_transcribed_lang": + obj.ASRTranscribedLang = reader.ReadElementContentAsString(); + break; + case "whisper_asr_module_version": + obj.WhisperASRModuleVersion = reader.ReadElementContentAsString(); + break; + case "whisper_model_hash": + obj.WhisperModelHash = reader.ReadElementContentAsString(); + break; + case "whisper_model_name": + obj.WhisperModelName = reader.ReadElementContentAsString(); + break; + case "whisper_version": + obj.WhisperVersion = reader.ReadElementContentAsString(); + break; + + // OCR-Related + case "cloth_cover_detection_module_version": + obj.ClothCoverDetectionModuleVersion = reader.ReadElementContentAsString(); + break; + case "hocr_char_to_word_hocr_version": + obj.hOCRCharToWordhOCRVersion = reader.ReadElementContentAsString(); + break; + case "hocr_char_to_word_module_version": + obj.hOCRCharToWordModuleVersion = reader.ReadElementContentAsString(); + break; + case "hocr_fts_text_hocr_version": + obj.hOCRFtsTexthOCRVersion = reader.ReadElementContentAsString(); + break; + case "hocr_fts_text_module_version": + obj.hOCRFtsTextModuleVersion = reader.ReadElementContentAsString(); + break; + case "hocr_pageindex_hocr_version": + obj.hOCRPageIndexhOCRVersion = reader.ReadElementContentAsString(); + break; + case "hocr_pageindex_module_version": + obj.hOCRPageIndexModuleVersion = reader.ReadElementContentAsString(); + break; + case "ocr": + obj.TesseractOCR = reader.ReadElementContentAsString(); + break; + case "ocr_converted": + obj.TesseractOCRConverted = reader.ReadElementContentAsString(); + break; + case "ocr_detected_lang": + obj.TesseractOCRDetectedLang = reader.ReadElementContentAsString(); + break; + case "ocr_detected_lang_conf": + obj.TesseractOCRDetectedLangConf = reader.ReadElementContentAsString(); + break; + case "ocr_detected_script": + obj.TesseractOCRDetectedScript = reader.ReadElementContentAsString(); + break; + case "ocr_detected_script_conf": + obj.TesseractOCRDetectedScriptConf = reader.ReadElementContentAsString(); + break; + case "ocr_module_version": + obj.TesseractOCRModuleVersion = reader.ReadElementContentAsString(); + break; + case "ocr_parameters": + obj.TesseractOCRParameters = reader.ReadElementContentAsString(); + break; + case "pdf_module_version": + obj.PDFModuleVersion = reader.ReadElementContentAsString(); + break; + case "word_conf_0_10": + obj.WordConfidenceInterval0To10 = reader.ReadElementContentAsString(); + break; + case "word_conf_11_20": + obj.WordConfidenceInterval11To20 = reader.ReadElementContentAsString(); + break; + case "word_conf_21_30": + obj.WordConfidenceInterval21To30 = reader.ReadElementContentAsString(); + break; + case "word_conf_31_40": + obj.WordConfidenceInterval31To40 = reader.ReadElementContentAsString(); + break; + case "word_conf_41_50": + obj.WordConfidenceInterval41To50 = reader.ReadElementContentAsString(); + break; + case "word_conf_51_60": + obj.WordConfidenceInterval51To60 = reader.ReadElementContentAsString(); + break; + case "word_conf_61_70": + obj.WordConfidenceInterval61To70 = reader.ReadElementContentAsString(); + break; + case "word_conf_71_80": + obj.WordConfidenceInterval71To80 = reader.ReadElementContentAsString(); + break; + case "word_conf_81_90": + obj.WordConfidenceInterval81To90 = reader.ReadElementContentAsString(); + break; + case "word_conf_91_100": + obj.WordConfidenceInterval91To100 = reader.ReadElementContentAsString(); + break; + + // Media-Related + case "album": + obj.Album = reader.ReadElementContentAsString(); + break; + case "artist": + obj.Artist = reader.ReadElementContentAsString(); + break; + case "bitrate": + obj.Bitrate = reader.ReadElementContentAsString(); + break; + case "creator": + obj.Creator = reader.ReadElementContentAsString(); + break; + case "height": + obj.Height = reader.ReadElementContentAsString(); + break; + case "length": + obj.Length = reader.ReadElementContentAsString(); + break; + case "preview-image": + obj.PreviewImage = reader.ReadElementContentAsString(); + break; + case "rotation": + obj.Rotation = reader.ReadElementContentAsString(); + break; + case "title": + obj.Title = reader.ReadElementContentAsString(); + break; + case "track": + obj.Track = reader.ReadElementContentAsString(); + break; + case "width": + obj.Width = reader.ReadElementContentAsString(); + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + reader.Skip(); + break; + } + } + + return obj; + } } } diff --git a/SabreTools.Serialization.Readers/Listxml.cs b/SabreTools.Serialization.Readers/Listxml.cs index 3fc7287c..f51cbad5 100644 --- a/SabreTools.Serialization.Readers/Listxml.cs +++ b/SabreTools.Serialization.Readers/Listxml.cs @@ -1,9 +1,1189 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; using SabreTools.Data.Models.Listxml; namespace SabreTools.Serialization.Readers { - public class Listxml : XmlFile + public class Listxml : BaseBinaryReader { - // All logic taken care of in the base class + /// + public override Mame? Deserialize(Stream? data) + { + // If the data is invalid + if (data is null || !data.CanRead) + return null; + + try + { + // Cache the current offset + long initialOffset = data.Position; + + // Create the XmlTextReader + var reader = new XmlTextReader(data); + reader.WhitespaceHandling = WhitespaceHandling.None; + + // Parse the XML, if possible + Mame? mame = null; + while (reader.Read()) + { + // An ending element means exit + if (reader.NodeType == XmlNodeType.EndElement) + break; + + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "mame": + if (mame is not null && Debug) + Console.WriteLine($"'{reader.Name}' element already found, overwriting"); + + mame = ParseMame(reader); + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + break; + } + } + + return mame; + } + catch + { + // Ignore the actual error + return null; + } + } + + /// + /// Parse from an XmlTextReader into a Mame + /// + /// XmlTextReader to read from + /// Filled Mame on success, null on error + public Mame ParseMame(XmlTextReader reader) + { + var obj = new Mame(); + + obj.Build = reader.GetAttribute("build"); + obj.Debug = reader.GetAttribute("debug"); + obj.MameConfig = reader.GetAttribute("mameconfig"); + + List games = []; + while (reader.Read()) + { + // An ending element means exit + if (reader.NodeType == XmlNodeType.EndElement) + break; + + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "machine": + case "game": + var game = ParseGameBase(reader); + if (game is not null) + games.Add(game); + + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + break; + } + } + + obj.Game = [.. games]; + + return obj; + } + + #region Items + + /// + /// Parse from an XmlTextReader into a Adjuster + /// + /// XmlTextReader to read from + /// Filled Adjuster on success, null on error + public Adjuster ParseAdjuster(XmlTextReader reader) + { + var obj = new Adjuster(); + + obj.Name = reader.GetAttribute("name"); + obj.Default = reader.GetAttribute("default"); + + while (reader.Read()) + { + // An ending element means exit + if (reader.NodeType == XmlNodeType.EndElement) + break; + + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "condition": + if (obj.Condition is not null && Debug) + Console.WriteLine($"'{reader.Name}' element already found, overwriting"); + + obj.Condition = ParseCondition(reader); + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + break; + } + } + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Analog + /// + /// XmlTextReader to read from + /// Filled Analog on success, null on error + public Analog ParseAnalog(XmlTextReader reader) + { + var obj = new Analog(); + + obj.Mask = reader.GetAttribute("mask"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a BiosSet + /// + /// XmlTextReader to read from + /// Filled BiosSet on success, null on error + public BiosSet ParseBiosSet(XmlTextReader reader) + { + var obj = new BiosSet(); + + obj.Name = reader.GetAttribute("name"); + obj.Description = reader.GetAttribute("description"); + obj.Default = reader.GetAttribute("default"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Chip + /// + /// XmlTextReader to read from + /// Filled Chip on success, null on error + public Chip ParseChip(XmlTextReader reader) + { + var obj = new Chip(); + + obj.Name = reader.GetAttribute("name"); + obj.Tag = reader.GetAttribute("tag"); + obj.Type = reader.GetAttribute("type"); + obj.SoundOnly = reader.GetAttribute("soundonly"); + obj.Clock = reader.GetAttribute("clock"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Condition + /// + /// XmlTextReader to read from + /// Filled Condition on success, null on error + public Condition ParseCondition(XmlTextReader reader) + { + var obj = new Condition(); + + obj.Tag = reader.GetAttribute("tag"); + obj.Mask = reader.GetAttribute("mask"); + obj.Relation = reader.GetAttribute("relation"); + obj.Value = reader.GetAttribute("value"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Configuration + /// + /// XmlTextReader to read from + /// Filled Configuration on success, null on error + public Configuration ParseConfiguration(XmlTextReader reader) + { + var obj = new Configuration(); + + obj.Name = reader.GetAttribute("name"); + obj.Tag = reader.GetAttribute("tag"); + obj.Mask = reader.GetAttribute("mask"); + + List confLocations = []; + List confSettings = []; + + while (reader.Read()) + { + // An ending element means exit + if (reader.NodeType == XmlNodeType.EndElement) + break; + + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "condition": + if (obj.Condition is not null && Debug) + Console.WriteLine($"'{reader.Name}' element already found, overwriting"); + + obj.Condition = ParseCondition(reader); + break; + case "conflocation": + var confLocation = ParseConfLocation(reader); + if (confLocation is not null) + confLocations.Add(confLocation); + + break; + case "confsetting": + var confSetting = ParseConfSetting(reader); + if (confSetting is not null) + confSettings.Add(confSetting); + + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + break; + } + } + + if (confLocations.Count > 0) + obj.ConfLocation = [.. confLocations]; + if (confSettings.Count > 0) + obj.ConfSetting = [.. confSettings]; + + return obj; + } + + /// + /// Parse from an XmlTextReader into a ConfLocation + /// + /// XmlTextReader to read from + /// Filled ConfLocation on success, null on error + public ConfLocation ParseConfLocation(XmlTextReader reader) + { + var obj = new ConfLocation(); + + obj.Name = reader.GetAttribute("name"); + obj.Number = reader.GetAttribute("number"); + obj.Inverted = reader.GetAttribute("inverted"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a ConfSetting + /// + /// XmlTextReader to read from + /// Filled ConfSetting on success, null on error + public ConfSetting ParseConfSetting(XmlTextReader reader) + { + var obj = new ConfSetting(); + + obj.Name = reader.GetAttribute("name"); + obj.Value = reader.GetAttribute("value"); + obj.Default = reader.GetAttribute("default"); + + while (reader.Read()) + { + // An ending element means exit + if (reader.NodeType == XmlNodeType.EndElement) + break; + + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "condition": + if (obj.Condition is not null && Debug) + Console.WriteLine($"'{reader.Name}' element already found, overwriting"); + + obj.Condition = ParseCondition(reader); + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + break; + } + } + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Control + /// + /// XmlTextReader to read from + /// Filled Control on success, null on error + public Control ParseControl(XmlTextReader reader) + { + var obj = new Control(); + + obj.Type = reader.GetAttribute("type"); + obj.Player = reader.GetAttribute("player"); + obj.Buttons = reader.GetAttribute("buttons"); + obj.ReqButtons = reader.GetAttribute("reqbuttons"); + obj.Minimum = reader.GetAttribute("minimum"); + obj.Maximum = reader.GetAttribute("maximum"); + obj.Sensitivity = reader.GetAttribute("sensitivity"); + obj.KeyDelta = reader.GetAttribute("keydelta"); + obj.Reverse = reader.GetAttribute("reverse"); + obj.Ways = reader.GetAttribute("ways"); + obj.Ways2 = reader.GetAttribute("ways2"); + obj.Ways3 = reader.GetAttribute("ways3"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Device + /// + /// XmlTextReader to read from + /// Filled Device on success, null on error + public Device ParseDevice(XmlTextReader reader) + { + var obj = new Device(); + + obj.Type = reader.GetAttribute("type"); + obj.Tag = reader.GetAttribute("tag"); + obj.FixedImage = reader.GetAttribute("fixed_image"); + obj.Mandatory = reader.GetAttribute("mandatory"); + obj.Interface = reader.GetAttribute("interface"); + + List extensions = []; + + while (reader.Read()) + { + // An ending element means exit + if (reader.NodeType == XmlNodeType.EndElement) + break; + + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "instance": + if (obj.Instance is not null && Debug) + Console.WriteLine($"'{reader.Name}' element already found, overwriting"); + + obj.Instance = ParseInstance(reader); + break; + case "extension": + var extension = ParseExtension(reader); + if (extension is not null) + extensions.Add(extension); + + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + break; + } + } + + if (extensions.Count > 0) + obj.Extension = [.. extensions]; + + return obj; + } + + /// + /// Parse from an XmlTextReader into a DeviceRef + /// + /// XmlTextReader to read from + /// Filled DeviceRef on success, null on error + public DeviceRef ParseDeviceRef(XmlTextReader reader) + { + var obj = new DeviceRef(); + + obj.Name = reader.GetAttribute("name"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a DipLocation + /// + /// XmlTextReader to read from + /// Filled DipLocation on success, null on error + public DipLocation ParseDipLocation(XmlTextReader reader) + { + var obj = new DipLocation(); + + obj.Name = reader.GetAttribute("name"); + obj.Number = reader.GetAttribute("number"); + obj.Inverted = reader.GetAttribute("inverted"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a DipSwitch + /// + /// XmlTextReader to read from + /// Filled DipSwitch on success, null on error + public DipSwitch ParseDipSwitch(XmlTextReader reader) + { + var obj = new DipSwitch(); + + obj.Name = reader.GetAttribute("name"); + obj.Tag = reader.GetAttribute("tag"); + obj.Mask = reader.GetAttribute("mask"); + + List dipLocations = []; + List dipValues = []; + + while (reader.Read()) + { + // An ending element means exit + if (reader.NodeType == XmlNodeType.EndElement) + break; + + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "condition": + if (obj.Condition is not null && Debug) + Console.WriteLine($"'{reader.Name}' element already found, overwriting"); + + obj.Condition = ParseCondition(reader); + break; + case "diplocation": + var dipLocation = ParseDipLocation(reader); + if (dipLocation is not null) + dipLocations.Add(dipLocation); + + break; + case "dipvalue": + var dipValue = ParseDipValue(reader); + if (dipValue is not null) + dipValues.Add(dipValue); + + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + break; + } + } + + if (dipLocations.Count > 0) + obj.DipLocation = [.. dipLocations]; + if (dipValues.Count > 0) + obj.DipValue = [.. dipValues]; + + return obj; + } + + /// + /// Parse from an XmlTextReader into a DipValue + /// + /// XmlTextReader to read from + /// Filled DipValue on success, null on error + public DipValue ParseDipValue(XmlTextReader reader) + { + var obj = new DipValue(); + + obj.Name = reader.GetAttribute("name"); + obj.Value = reader.GetAttribute("value"); + obj.Default = reader.GetAttribute("default"); + + while (reader.Read()) + { + // An ending element means exit + if (reader.NodeType == XmlNodeType.EndElement) + break; + + // Only process starting elements + if (!reader.IsStartElement()) + continue; + + switch (reader.Name) + { + case "condition": + if (obj.Condition is not null && Debug) + Console.WriteLine($"'{reader.Name}' element already found, overwriting"); + + obj.Condition = ParseCondition(reader); + break; + + default: + if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); + break; + } + } + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Disk + /// + /// XmlTextReader to read from + /// Filled Disk on success, null on error + public Disk ParseDisk(XmlTextReader reader) + { + var obj = new Disk(); + + obj.Name = reader.GetAttribute("name"); + obj.MD5 = reader.GetAttribute("md5"); + obj.SHA1 = reader.GetAttribute("sha1"); + obj.Merge = reader.GetAttribute("merge"); + obj.Region = reader.GetAttribute("region"); + obj.Index = reader.GetAttribute("index"); + obj.Writable = reader.GetAttribute("writable"); + obj.Status = reader.GetAttribute("status"); + obj.Optional = reader.GetAttribute("optional"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Display + /// + /// XmlTextReader to read from + /// Filled Display on success, null on error + public Display ParseDisplay(XmlTextReader reader) + { + var obj = new Display(); + + obj.Tag = reader.GetAttribute("tag"); + obj.Type = reader.GetAttribute("type"); + obj.Rotate = reader.GetAttribute("rotate"); + obj.FlipX = reader.GetAttribute("flipx"); + obj.Width = reader.GetAttribute("width"); + obj.Height = reader.GetAttribute("height"); + obj.Refresh = reader.GetAttribute("refresh"); + obj.PixClock = reader.GetAttribute("pixclock"); + obj.HTotal = reader.GetAttribute("htotal"); + obj.HBEnd = reader.GetAttribute("hbend"); + obj.HBStart = reader.GetAttribute("hbstart"); + obj.VTotal = reader.GetAttribute("vtotal"); + obj.VBEnd = reader.GetAttribute("vbend"); + obj.VBStart = reader.GetAttribute("vbstart"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Driver + /// + /// XmlTextReader to read from + /// Filled Driver on success, null on error + public Driver ParseDriver(XmlTextReader reader) + { + var obj = new Driver(); + + obj.Status = reader.GetAttribute("status"); + obj.Color = reader.GetAttribute("color"); + obj.Sound = reader.GetAttribute("sound"); + obj.PaletteSize = reader.GetAttribute("palettesize"); + obj.Emulation = reader.GetAttribute("emulation"); + obj.Cocktail = reader.GetAttribute("cocktail"); + obj.SaveState = reader.GetAttribute("savestate"); + obj.RequiresArtwork = reader.GetAttribute("requiresartwork"); + obj.Unofficial = reader.GetAttribute("unofficial"); + obj.NoSoundHardware = reader.GetAttribute("nosoundhardware"); + obj.Incomplete = reader.GetAttribute("incomplete"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Extension + /// + /// XmlTextReader to read from + /// Filled Extension on success, null on error + public Extension ParseExtension(XmlTextReader reader) + { + var obj = new Extension(); + + obj.Name = reader.GetAttribute("name"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a Feature + /// + /// XmlTextReader to read from + /// Filled Feature on success, null on error + public Feature ParseFeature(XmlTextReader reader) + { + var obj = new Feature(); + + obj.Type = reader.GetAttribute("type"); + obj.Status = reader.GetAttribute("status"); + obj.Overall = reader.GetAttribute("overall"); + + return obj; + } + + /// + /// Parse from an XmlTextReader into a GameBase + /// + /// XmlTextReader to read from + /// Filled GameBase on success, null on error + public GameBase? ParseGameBase(XmlTextReader reader) + { + GameBase obj; + if (reader.Name == "game") + obj = new Game(); + else if (reader.Name == "machine") + obj = new Machine(); + else + return null; + + obj.Name = reader.GetAttribute("name"); + obj.SourceFile = reader.GetAttribute("sourcefile"); + obj.IsBios = reader.GetAttribute("isbios"); + obj.IsDevice = reader.GetAttribute("isdevice"); + obj.IsMechanical = reader.GetAttribute("ismechanical"); + obj.Runnable = reader.GetAttribute("runnable"); + obj.CloneOf = reader.GetAttribute("cloneof"); + obj.RomOf = reader.GetAttribute("romof"); + obj.SampleOf = reader.GetAttribute("sampleof"); + + List biosSets = []; + List roms = []; + List disks = []; + List deviceRefs = []; + List samples = []; + List chips = []; + List displays = []; + List