From 4d362bb79145a7fdb3967b6fcd8deda3e0ffe66d Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 31 Mar 2026 18:08:40 -0400 Subject: [PATCH] Use XmlTextWriter for XML DAT writing --- .../Formats/Logiqx.cs | 8 +- .../ArchiveDotOrgTests.cs | 2 +- .../ListxmlTests.cs | 8 +- .../LogiqxTests.cs | 4 +- .../M1Tests.cs | 4 +- .../MessTests.cs | 4 +- .../OfflineListTests.cs | 2 +- .../OpenMSXTests.cs | 2 +- .../SoftwareListTests.cs | 9 +- .../ArchiveDotOrgTests.cs | 2 +- .../ListxmlTests.cs | 2 +- .../LogiqxTests.cs | 2 +- .../M1Tests.cs | 2 +- .../MessTests.cs | 2 +- .../OfflineListTests.cs | 2 +- .../OpenMSXTests.cs | 2 +- .../SoftwareListTests.cs | 2 +- .../ArchiveDotOrg.cs | 128 ++- SabreTools.Serialization.Writers/Listxml.cs | 837 +++++++++++++++++- SabreTools.Serialization.Writers/Logiqx.cs | 538 ++++++++++- SabreTools.Serialization.Writers/M1.cs | 837 +++++++++++++++++- SabreTools.Serialization.Writers/Mess.cs | 837 +++++++++++++++++- .../OfflineList.cs | 444 +++++++++- SabreTools.Serialization.Writers/OpenMSX.cs | 156 +++- .../SoftwareList.cs | 332 ++++++- SabreTools.Serialization.Writers/XmlFile.cs | 130 --- 26 files changed, 4076 insertions(+), 222 deletions(-) delete mode 100644 SabreTools.Serialization.Writers/XmlFile.cs diff --git a/SabreTools.Metadata.DatFiles/Formats/Logiqx.cs b/SabreTools.Metadata.DatFiles/Formats/Logiqx.cs index e69367d6..f5b86759 100644 --- a/SabreTools.Metadata.DatFiles/Formats/Logiqx.cs +++ b/SabreTools.Metadata.DatFiles/Formats/Logiqx.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using SabreTools.Data.Extensions; using SabreTools.Metadata.DatItems; @@ -382,13 +382,13 @@ namespace SabreTools.Metadata.DatFiles.Formats var metadata = ConvertToMetadata(ignoreblanks); var datafile = new Serialization.CrossModel.Logiqx().Deserialize(metadata, _useGame); - // TODO: Reenable doctype writing + // TODO: Enable No-Intro doctype writing instead of Logiqx // Only write the doctype if we don't have No-Intro data bool success; if (string.IsNullOrEmpty(Header.ReadString(Data.Models.Metadata.Header.IdKey))) - success = new Serialization.Writers.Logiqx().Serialize(datafile, outfile, null, null, null, null); + success = new Serialization.Writers.Logiqx().SerializeFile(datafile, outfile); else - success = new Serialization.Writers.Logiqx().Serialize(datafile, outfile, null, null, null, null); + success = new Serialization.Writers.Logiqx().SerializeFile(datafile, outfile); if (!success) { diff --git a/SabreTools.Serialization.Readers.Test/ArchiveDotOrgTests.cs b/SabreTools.Serialization.Readers.Test/ArchiveDotOrgTests.cs index d297bbaf..793b864b 100644 --- a/SabreTools.Serialization.Readers.Test/ArchiveDotOrgTests.cs +++ b/SabreTools.Serialization.Readers.Test/ArchiveDotOrgTests.cs @@ -80,7 +80,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.ArchiveDotOrg.Files files = Build(); // Serialize to stream - Stream? actual = serializer.Serialize(files); + Stream? actual = serializer.SerializeStream(files); Assert.NotNull(actual); // Serialize back to original model diff --git a/SabreTools.Serialization.Readers.Test/ListxmlTests.cs b/SabreTools.Serialization.Readers.Test/ListxmlTests.cs index 61c80329..6405b523 100644 --- a/SabreTools.Serialization.Readers.Test/ListxmlTests.cs +++ b/SabreTools.Serialization.Readers.Test/ListxmlTests.cs @@ -80,7 +80,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.Listxml.Mame mame = Build(game: true); // Serialize to stream - Stream? actual = serializer.Serialize(mame); + Stream? actual = serializer.SerializeStream(mame); Assert.NotNull(actual); // Serialize back to original model @@ -108,7 +108,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.Listxml.Mame mame = Build(game: false); // Serialize to stream - Stream? actual = serializer.Serialize(mame); + Stream? actual = serializer.SerializeStream(mame); Assert.NotNull(actual); // Serialize back to original model @@ -240,7 +240,7 @@ namespace SabreTools.Serialization.Readers.Test Service = "XXXXXX", Tilt = "XXXXXX", Players = "XXXXXX", - //ControlAttr = "XXXXXX", // Mututally exclusive with input.Control + ControlAttr = "XXXXXX", Buttons = "XXXXXX", Coins = "XXXXXX", Control = [control], @@ -668,7 +668,7 @@ namespace SabreTools.Serialization.Readers.Test Assert.Equal("XXXXXX", input.Service); Assert.Equal("XXXXXX", input.Tilt); Assert.Equal("XXXXXX", input.Players); - //Assert.Equal("XXXXXX", input.ControlAttr); // Mututally exclusive with input.Control + Assert.Equal("XXXXXX", input.ControlAttr); // Mututally exclusive with input.Control Assert.Equal("XXXXXX", input.Buttons); Assert.Equal("XXXXXX", input.Coins); diff --git a/SabreTools.Serialization.Readers.Test/LogiqxTests.cs b/SabreTools.Serialization.Readers.Test/LogiqxTests.cs index 39750fb0..c7f44a7d 100644 --- a/SabreTools.Serialization.Readers.Test/LogiqxTests.cs +++ b/SabreTools.Serialization.Readers.Test/LogiqxTests.cs @@ -80,7 +80,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.Logiqx.Datafile df = Build(game: true); // Serialize to stream - Stream? metadata = serializer.Serialize(df); + Stream? metadata = serializer.SerializeStream(df); Assert.NotNull(metadata); // Serialize back to original model @@ -112,7 +112,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.Logiqx.Datafile df = Build(game: false); // Serialize to stream - Stream? metadata = serializer.Serialize(df); + Stream? metadata = serializer.SerializeStream(df); Assert.NotNull(metadata); // Serialize back to original model diff --git a/SabreTools.Serialization.Readers.Test/M1Tests.cs b/SabreTools.Serialization.Readers.Test/M1Tests.cs index e560fdfb..a9493600 100644 --- a/SabreTools.Serialization.Readers.Test/M1Tests.cs +++ b/SabreTools.Serialization.Readers.Test/M1Tests.cs @@ -80,7 +80,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.Listxml.M1 m1 = Build(game: true); // Serialize to generic model - Stream? metadata = serializer.Serialize(m1); + Stream? metadata = serializer.SerializeStream(m1); Assert.NotNull(metadata); // Serialize to stream @@ -106,7 +106,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.Listxml.M1 m1 = Build(game: false); // Serialize to generic model - Stream? metadata = serializer.Serialize(m1); + Stream? metadata = serializer.SerializeStream(m1); Assert.NotNull(metadata); // Serialize to stream diff --git a/SabreTools.Serialization.Readers.Test/MessTests.cs b/SabreTools.Serialization.Readers.Test/MessTests.cs index 459e1ffa..4abddd17 100644 --- a/SabreTools.Serialization.Readers.Test/MessTests.cs +++ b/SabreTools.Serialization.Readers.Test/MessTests.cs @@ -80,7 +80,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.Listxml.Mess m1 = Build(game: true); // Serialize to generic model - Stream? metadata = serializer.Serialize(m1); + Stream? metadata = serializer.SerializeStream(m1); Assert.NotNull(metadata); // Serialize to stream @@ -106,7 +106,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.Listxml.Mess m1 = Build(game: false); // Serialize to generic model - Stream? metadata = serializer.Serialize(m1); + Stream? metadata = serializer.SerializeStream(m1); Assert.NotNull(metadata); // Serialize to stream diff --git a/SabreTools.Serialization.Readers.Test/OfflineListTests.cs b/SabreTools.Serialization.Readers.Test/OfflineListTests.cs index 3ed1d29f..f0c821b5 100644 --- a/SabreTools.Serialization.Readers.Test/OfflineListTests.cs +++ b/SabreTools.Serialization.Readers.Test/OfflineListTests.cs @@ -80,7 +80,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.OfflineList.Dat dat = Build(); // Serialize to stream - Stream? metadata = serializer.Serialize(dat); + Stream? metadata = serializer.SerializeStream(dat); Assert.NotNull(metadata); // Serialize back to original model diff --git a/SabreTools.Serialization.Readers.Test/OpenMSXTests.cs b/SabreTools.Serialization.Readers.Test/OpenMSXTests.cs index 7ea7e92d..e2ef4d31 100644 --- a/SabreTools.Serialization.Readers.Test/OpenMSXTests.cs +++ b/SabreTools.Serialization.Readers.Test/OpenMSXTests.cs @@ -80,7 +80,7 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.OpenMSX.SoftwareDb sdb = Build(); // Serialize to stream - Stream? metadata = serializer.Serialize(sdb); + Stream? metadata = serializer.SerializeStream(sdb); Assert.NotNull(metadata); // Serialize back to original model diff --git a/SabreTools.Serialization.Readers.Test/SoftwareListTests.cs b/SabreTools.Serialization.Readers.Test/SoftwareListTests.cs index 2f77bbf0..bbe3a738 100644 --- a/SabreTools.Serialization.Readers.Test/SoftwareListTests.cs +++ b/SabreTools.Serialization.Readers.Test/SoftwareListTests.cs @@ -80,9 +80,16 @@ namespace SabreTools.Serialization.Readers.Test Data.Models.SoftwareList.SoftwareList sl = Build(); // Serialize to stream - Stream? actual = serializer.Serialize(sl); + Stream? actual = serializer.SerializeStream(sl); Assert.NotNull(actual); + if (actual is MemoryStream ms) + { + byte[] bytes = ms.ToArray(); + string str = System.Text.Encoding.UTF8.GetString(bytes); + System.Console.WriteLine(str); + } + // Serialize back to original model Data.Models.SoftwareList.SoftwareList? newSl = deserializer.Deserialize(actual); diff --git a/SabreTools.Serialization.Writers.Test/ArchiveDotOrgTests.cs b/SabreTools.Serialization.Writers.Test/ArchiveDotOrgTests.cs index 07db7652..0c2e2d4b 100644 --- a/SabreTools.Serialization.Writers.Test/ArchiveDotOrgTests.cs +++ b/SabreTools.Serialization.Writers.Test/ArchiveDotOrgTests.cs @@ -17,7 +17,7 @@ namespace SabreTools.Serialization.Writers.Test public void SerializeStream_Null_Null() { var serializer = new ArchiveDotOrg(); - Stream? actual = serializer.Serialize(null); + Stream? actual = serializer.SerializeStream(null); Assert.Null(actual); } } diff --git a/SabreTools.Serialization.Writers.Test/ListxmlTests.cs b/SabreTools.Serialization.Writers.Test/ListxmlTests.cs index 7f32a393..e7fea049 100644 --- a/SabreTools.Serialization.Writers.Test/ListxmlTests.cs +++ b/SabreTools.Serialization.Writers.Test/ListxmlTests.cs @@ -17,7 +17,7 @@ namespace SabreTools.Serialization.Writers.Test public void SerializeStream_Null_Null() { var serializer = new Listxml(); - Stream? actual = serializer.Serialize(null); + Stream? actual = serializer.SerializeStream(null); Assert.Null(actual); } } diff --git a/SabreTools.Serialization.Writers.Test/LogiqxTests.cs b/SabreTools.Serialization.Writers.Test/LogiqxTests.cs index 3d2914ce..e40a0691 100644 --- a/SabreTools.Serialization.Writers.Test/LogiqxTests.cs +++ b/SabreTools.Serialization.Writers.Test/LogiqxTests.cs @@ -17,7 +17,7 @@ namespace SabreTools.Serialization.Writers.Test public void SerializeStream_Null_Null() { var serializer = new Logiqx(); - Stream? actual = serializer.Serialize(null); + Stream? actual = serializer.SerializeStream(null); Assert.Null(actual); } } diff --git a/SabreTools.Serialization.Writers.Test/M1Tests.cs b/SabreTools.Serialization.Writers.Test/M1Tests.cs index fca80bc8..7cc79717 100644 --- a/SabreTools.Serialization.Writers.Test/M1Tests.cs +++ b/SabreTools.Serialization.Writers.Test/M1Tests.cs @@ -17,7 +17,7 @@ namespace SabreTools.Serialization.Writers.Test public void SerializeStream_Null_Null() { var serializer = new M1(); - Stream? actual = serializer.Serialize(null); + Stream? actual = serializer.SerializeStream(null); Assert.Null(actual); } } diff --git a/SabreTools.Serialization.Writers.Test/MessTests.cs b/SabreTools.Serialization.Writers.Test/MessTests.cs index acbdd4cd..0344fb30 100644 --- a/SabreTools.Serialization.Writers.Test/MessTests.cs +++ b/SabreTools.Serialization.Writers.Test/MessTests.cs @@ -17,7 +17,7 @@ namespace SabreTools.Serialization.Writers.Test public void SerializeStream_Null_Null() { var serializer = new Mess(); - Stream? actual = serializer.Serialize(null); + Stream? actual = serializer.SerializeStream(null); Assert.Null(actual); } } diff --git a/SabreTools.Serialization.Writers.Test/OfflineListTests.cs b/SabreTools.Serialization.Writers.Test/OfflineListTests.cs index 3c058087..f6c419e9 100644 --- a/SabreTools.Serialization.Writers.Test/OfflineListTests.cs +++ b/SabreTools.Serialization.Writers.Test/OfflineListTests.cs @@ -17,7 +17,7 @@ namespace SabreTools.Serialization.Writers.Test public void SerializeStream_Null_Null() { var serializer = new OfflineList(); - Stream? actual = serializer.Serialize(null); + Stream? actual = serializer.SerializeStream(null); Assert.Null(actual); } } diff --git a/SabreTools.Serialization.Writers.Test/OpenMSXTests.cs b/SabreTools.Serialization.Writers.Test/OpenMSXTests.cs index c61de641..4074064d 100644 --- a/SabreTools.Serialization.Writers.Test/OpenMSXTests.cs +++ b/SabreTools.Serialization.Writers.Test/OpenMSXTests.cs @@ -17,7 +17,7 @@ namespace SabreTools.Serialization.Writers.Test public void SerializeStream_Null_Null() { var serializer = new OpenMSX(); - Stream? actual = serializer.Serialize(null); + Stream? actual = serializer.SerializeStream(null); Assert.Null(actual); } } diff --git a/SabreTools.Serialization.Writers.Test/SoftwareListTests.cs b/SabreTools.Serialization.Writers.Test/SoftwareListTests.cs index ea888adf..cba1fa29 100644 --- a/SabreTools.Serialization.Writers.Test/SoftwareListTests.cs +++ b/SabreTools.Serialization.Writers.Test/SoftwareListTests.cs @@ -17,7 +17,7 @@ namespace SabreTools.Serialization.Writers.Test public void SerializeStream_Null_Null() { var serializer = new SoftwareList(); - Stream? actual = serializer.Serialize(null); + Stream? actual = serializer.SerializeStream(null); Assert.Null(actual); } } diff --git a/SabreTools.Serialization.Writers/ArchiveDotOrg.cs b/SabreTools.Serialization.Writers/ArchiveDotOrg.cs index 1bf8a96d..c431dcee 100644 --- a/SabreTools.Serialization.Writers/ArchiveDotOrg.cs +++ b/SabreTools.Serialization.Writers/ArchiveDotOrg.cs @@ -1,9 +1,133 @@ +using System.IO; +using System.Text; +using System.Xml; using SabreTools.Data.Models.ArchiveDotOrg; +using SabreTools.IO.Extensions; +using SabreTools.Text.Extensions; namespace SabreTools.Serialization.Writers { - public class ArchiveDotOrg : XmlFile + public class ArchiveDotOrg : BaseBinaryWriter { - // All logic taken care of in the base class + /// + public override Stream? SerializeStream(Files? obj) + { + // If the metadata file is null + if (obj is null) + return null; + + // Setup the writer and output + var stream = new MemoryStream(); + var writer = new XmlTextWriter(stream, Encoding.UTF8); + writer.Formatting = Formatting.Indented; + + // Write the files, if they exist + WriteFiles(obj, writer); + writer.Flush(); + + // Return the stream + stream.SeekIfPossible(0, SeekOrigin.Begin); + return stream; + } + + /// + /// Write a File to an XmlTextWriter + /// + /// File to write + /// XmlTextReader to write to + private static void WriteFile(Data.Models.ArchiveDotOrg.File obj, XmlTextWriter writer) + { + writer.WriteStartElement("file"); + + writer.WriteOptionalAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("source", obj.Source); + + writer.WriteOptionalElementString("btih", obj.BitTorrentMagnetHash); + writer.WriteOptionalElementString("mtime", obj.LastModifiedTime); + writer.WriteOptionalElementString("size", obj.Size); + writer.WriteOptionalElementString("md5", obj.MD5); + writer.WriteOptionalElementString("crc32", obj.CRC32); + writer.WriteOptionalElementString("sha1", obj.SHA1); + writer.WriteOptionalElementString("filecount", obj.FileCount); + writer.WriteOptionalElementString("format", obj.Format); + writer.WriteOptionalElementString("original", obj.Original); + writer.WriteOptionalElementString("summation", obj.Summation); + writer.WriteOptionalElementString("matrix_number", obj.MatrixNumber); + writer.WriteOptionalElementString("collection-catalog-number", obj.CollectionCatalogNumber); + writer.WriteOptionalElementString("publisher", obj.Publisher); + writer.WriteOptionalElementString("comment", obj.Comment); + + // ASR-Related + writer.WriteOptionalElementString("asr_detected_lang", obj.ASRDetectedLang); + writer.WriteOptionalElementString("asr_detected_lang_conf", obj.ASRDetectedLangConf); + writer.WriteOptionalElementString("asr_transcribed_lang", obj.ASRTranscribedLang); + writer.WriteOptionalElementString("whisper_asr_module_version", obj.WhisperASRModuleVersion); + writer.WriteOptionalElementString("whisper_model_hash", obj.WhisperModelHash); + writer.WriteOptionalElementString("whisper_model_name", obj.WhisperModelName); + writer.WriteOptionalElementString("whisper_version", obj.WhisperVersion); + + // OCR-Related + writer.WriteOptionalElementString("cloth_cover_detection_module_version", obj.ClothCoverDetectionModuleVersion); + writer.WriteOptionalElementString("hocr_char_to_word_hocr_version", obj.hOCRCharToWordhOCRVersion); + writer.WriteOptionalElementString("hocr_char_to_word_module_version", obj.hOCRCharToWordModuleVersion); + writer.WriteOptionalElementString("hocr_fts_text_hocr_version", obj.hOCRFtsTexthOCRVersion); + writer.WriteOptionalElementString("hocr_fts_text_module_version", obj.hOCRFtsTextModuleVersion); + writer.WriteOptionalElementString("hocr_pageindex_hocr_version", obj.hOCRPageIndexhOCRVersion); + writer.WriteOptionalElementString("hocr_pageindex_module_version", obj.hOCRPageIndexModuleVersion); + writer.WriteOptionalElementString("ocr", obj.TesseractOCR); + writer.WriteOptionalElementString("ocr_converted", obj.TesseractOCRConverted); + writer.WriteOptionalElementString("ocr_detected_lang", obj.TesseractOCRDetectedLang); + writer.WriteOptionalElementString("ocr_detected_lang_conf", obj.TesseractOCRDetectedLangConf); + writer.WriteOptionalElementString("ocr_detected_script", obj.TesseractOCRDetectedScript); + writer.WriteOptionalElementString("ocr_detected_script_conf", obj.TesseractOCRDetectedScriptConf); + writer.WriteOptionalElementString("ocr_module_version", obj.TesseractOCRModuleVersion); + writer.WriteOptionalElementString("ocr_parameters", obj.TesseractOCRParameters); + writer.WriteOptionalElementString("pdf_module_version", obj.PDFModuleVersion); + writer.WriteOptionalElementString("word_conf_0_10", obj.WordConfidenceInterval0To10); + writer.WriteOptionalElementString("word_conf_11_20", obj.WordConfidenceInterval11To20); + writer.WriteOptionalElementString("word_conf_21_30", obj.WordConfidenceInterval21To30); + writer.WriteOptionalElementString("word_conf_31_40", obj.WordConfidenceInterval31To40); + writer.WriteOptionalElementString("word_conf_41_50", obj.WordConfidenceInterval41To50); + writer.WriteOptionalElementString("word_conf_51_60", obj.WordConfidenceInterval51To60); + writer.WriteOptionalElementString("word_conf_61_70", obj.WordConfidenceInterval61To70); + writer.WriteOptionalElementString("word_conf_71_80", obj.WordConfidenceInterval71To80); + writer.WriteOptionalElementString("word_conf_81_90", obj.WordConfidenceInterval81To90); + writer.WriteOptionalElementString("word_conf_91_100", obj.WordConfidenceInterval91To100); + + // Media-Related + writer.WriteOptionalElementString("album", obj.Album); + writer.WriteOptionalElementString("artist", obj.Artist); + writer.WriteOptionalElementString("bitrate", obj.Bitrate); + writer.WriteOptionalElementString("creator", obj.Creator); + writer.WriteOptionalElementString("height", obj.Height); + writer.WriteOptionalElementString("length", obj.Length); + writer.WriteOptionalElementString("preview-image", obj.PreviewImage); + writer.WriteOptionalElementString("rotation", obj.Rotation); + writer.WriteOptionalElementString("title", obj.Title); + writer.WriteOptionalElementString("track", obj.Track); + writer.WriteOptionalElementString("width", obj.Width); + + writer.WriteEndElement(); + } + + /// + /// Write a Files to an XmlTextWriter + /// + /// Files to write + /// XmlTextReader to write to + private static void WriteFiles(Files obj, XmlTextWriter writer) + { + writer.WriteStartElement("files"); + + if (obj.File is not null && obj.File.Length > 0) + { + foreach (var file in obj.File) + { + WriteFile(file, writer); + } + } + + writer.WriteEndElement(); + } } } diff --git a/SabreTools.Serialization.Writers/Listxml.cs b/SabreTools.Serialization.Writers/Listxml.cs index 722dde32..2323df31 100644 --- a/SabreTools.Serialization.Writers/Listxml.cs +++ b/SabreTools.Serialization.Writers/Listxml.cs @@ -1,9 +1,842 @@ +using System.IO; +using System.Text; +using System.Xml; using SabreTools.Data.Models.Listxml; +using SabreTools.IO.Extensions; +using SabreTools.Text.Extensions; namespace SabreTools.Serialization.Writers { - public class Listxml : XmlFile + public class Listxml : BaseBinaryWriter { - // All logic taken care of in the base class + /// + public override Stream? SerializeStream(Mame? obj) + { + // If the metadata file is null + if (obj is null) + return null; + + // Setup the writer and output + var stream = new MemoryStream(); + var writer = new XmlTextWriter(stream, Encoding.UTF8); + writer.Formatting = Formatting.Indented; + + // Write the Mame, if it exists + WriteMame(obj, writer); + writer.Flush(); + + // Return the stream + stream.SeekIfPossible(0, SeekOrigin.Begin); + return stream; + } + + /// + /// Write a Mame to an XmlTextWriter + /// + /// Mame to write + /// XmlTextReader to write to + private static void WriteMame(Mame obj, XmlTextWriter writer) + { + writer.WriteStartElement("mame"); + + writer.WriteOptionalAttributeString("build", obj.Build); + writer.WriteOptionalAttributeString("debug", obj.Debug); + writer.WriteRequiredAttributeString("mameconfig", obj.MameConfig); + + if (obj.Game is not null && obj.Game.Length > 0) + { + foreach (var gameBase in obj.Game) + { + WriteGameBase(gameBase, writer); + } + } + + writer.WriteEndElement(); + } + + #region Items + + /// + /// Write a Adjuster to an XmlTextWriter + /// + /// Adjuster to write + /// XmlTextReader to write to + private static void WriteAdjuster(Adjuster obj, XmlTextWriter writer) + { + writer.WriteStartElement("adjuster"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Analog to an XmlTextWriter + /// + /// Analog to write + /// XmlTextReader to write to + private static void WriteAnalog(Analog obj, XmlTextWriter writer) + { + writer.WriteStartElement("analog"); + + writer.WriteRequiredAttributeString("mask", obj.Mask); + + writer.WriteEndElement(); + } + + /// + /// Write a BiosSet to an XmlTextWriter + /// + /// BiosSet to write + /// XmlTextReader to write to + private static void WriteBiosSet(BiosSet obj, XmlTextWriter writer) + { + writer.WriteStartElement("biosset"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("description", obj.Description); + writer.WriteOptionalAttributeString("default", obj.Default); + + writer.WriteEndElement(); + } + + /// + /// Write a Chip to an XmlTextWriter + /// + /// Chip to write + /// XmlTextReader to write to + private static void WriteChip(Chip obj, XmlTextWriter writer) + { + writer.WriteStartElement("chip"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("soundonly", obj.SoundOnly); + writer.WriteOptionalAttributeString("clock", obj.Clock); + + writer.WriteEndElement(); + } + + /// + /// Write a Condition to an XmlTextWriter + /// + /// Condition to write + /// XmlTextReader to write to + private static void WriteCondition(Condition obj, XmlTextWriter writer) + { + writer.WriteStartElement("condition"); + + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("mask", obj.Mask); + writer.WriteRequiredAttributeString("relation", obj.Relation); + writer.WriteRequiredAttributeString("value", obj.Value); + + writer.WriteEndElement(); + } + + /// + /// Write a Configuration to an XmlTextWriter + /// + /// Configuration to write + /// XmlTextReader to write to + private static void WriteConfiguration(Configuration obj, XmlTextWriter writer) + { + writer.WriteStartElement("configuration"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteOptionalAttributeString("mask", obj.Mask); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + if (obj.ConfLocation is not null && obj.ConfLocation.Length > 0) + { + foreach (var confLocation in obj.ConfLocation) + { + WriteConfLocation(confLocation, writer); + } + } + + if (obj.ConfSetting is not null && obj.ConfSetting.Length > 0) + { + foreach (var confSetting in obj.ConfSetting) + { + WriteConfSetting(confSetting, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a ConfLocation to an XmlTextWriter + /// + /// ConfLocation to write + /// XmlTextReader to write to + private static void WriteConfLocation(ConfLocation obj, XmlTextWriter writer) + { + writer.WriteStartElement("conflocation"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("number", obj.Number); + writer.WriteOptionalAttributeString("inverted", obj.Inverted); + + writer.WriteEndElement(); + } + + /// + /// Write a ConfSetting to an XmlTextWriter + /// + /// ConfSetting to write + /// XmlTextReader to write to + private static void WriteConfSetting(ConfSetting obj, XmlTextWriter writer) + { + writer.WriteStartElement("confsetting"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("value", obj.Value); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Control to an XmlTextWriter + /// + /// Control to write + /// XmlTextReader to write to + private static void WriteControl(Control obj, XmlTextWriter writer) + { + writer.WriteStartElement("control"); + + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("player", obj.Player); + writer.WriteOptionalAttributeString("buttons", obj.Buttons); + writer.WriteOptionalAttributeString("reqbuttons", obj.ReqButtons); + writer.WriteOptionalAttributeString("minimum", obj.Minimum); + writer.WriteOptionalAttributeString("maximum", obj.Maximum); + writer.WriteOptionalAttributeString("sensitivity", obj.Sensitivity); + writer.WriteOptionalAttributeString("keydelta", obj.KeyDelta); + writer.WriteOptionalAttributeString("reverse", obj.Reverse); + writer.WriteOptionalAttributeString("ways", obj.Ways); + writer.WriteOptionalAttributeString("ways2", obj.Ways2); + writer.WriteOptionalAttributeString("ways3", obj.Ways3); + + writer.WriteEndElement(); + } + + /// + /// Write a Device to an XmlTextWriter + /// + /// Device to write + /// XmlTextReader to write to + private static void WriteDevice(Device obj, XmlTextWriter writer) + { + writer.WriteStartElement("device"); + + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("tag", obj.Tag); + writer.WriteOptionalAttributeString("fixed_image", obj.FixedImage); + writer.WriteOptionalAttributeString("mandatory", obj.Mandatory); + writer.WriteOptionalAttributeString("interface", obj.Interface); + + if (obj.Instance is not null) + WriteInstance(obj.Instance, writer); + + if (obj.Extension is not null && obj.Extension.Length > 0) + { + foreach (var extension in obj.Extension) + { + WriteExtension(extension, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a DeviceRef to an XmlTextWriter + /// + /// DeviceRef to write + /// XmlTextReader to write to + private static void WriteDeviceRef(DeviceRef obj, XmlTextWriter writer) + { + writer.WriteStartElement("device_ref"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a DipLocation to an XmlTextWriter + /// + /// DipLocation to write + /// XmlTextReader to write to + private static void WriteDipLocation(DipLocation obj, XmlTextWriter writer) + { + writer.WriteStartElement("diplocation"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("number", obj.Number); + writer.WriteOptionalAttributeString("inverted", obj.Inverted); + + writer.WriteEndElement(); + } + + /// + /// Write a DipSwitch to an XmlTextWriter + /// + /// DipSwitch to write + /// XmlTextReader to write to + private static void WriteDipSwitch(DipSwitch obj, XmlTextWriter writer) + { + writer.WriteStartElement("dipswitch"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteOptionalAttributeString("mask", obj.Mask); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + if (obj.DipLocation is not null && obj.DipLocation.Length > 0) + { + foreach (var dipLocation in obj.DipLocation) + { + WriteDipLocation(dipLocation, writer); + } + } + + if (obj.DipValue is not null && obj.DipValue.Length > 0) + { + foreach (var dipValue in obj.DipValue) + { + WriteDipValue(dipValue, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a DipValue to an XmlTextWriter + /// + /// DipValue to write + /// XmlTextReader to write to + private static void WriteDipValue(DipValue obj, XmlTextWriter writer) + { + writer.WriteStartElement("dipvalue"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("value", obj.Value); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Disk to an XmlTextWriter + /// + /// Disk to write + /// XmlTextReader to write to + private static void WriteDisk(Disk obj, XmlTextWriter writer) + { + writer.WriteStartElement("disk"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("md5", obj.MD5); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("merge", obj.Merge); + writer.WriteOptionalAttributeString("region", obj.Region); + writer.WriteOptionalAttributeString("index", obj.Index); + writer.WriteOptionalAttributeString("writable", obj.Writable); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("optional", obj.Optional); + + writer.WriteEndElement(); + } + + /// + /// Write a Display to an XmlTextWriter + /// + /// Display to write + /// XmlTextReader to write to + private static void WriteDisplay(Display obj, XmlTextWriter writer) + { + writer.WriteStartElement("display"); + + writer.WriteOptionalAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("rotate", obj.Rotate); + writer.WriteOptionalAttributeString("flipx", obj.FlipX); + writer.WriteOptionalAttributeString("width", obj.Width); + writer.WriteOptionalAttributeString("height", obj.Height); + writer.WriteRequiredAttributeString("refresh", obj.Refresh); + writer.WriteOptionalAttributeString("pixclock", obj.PixClock); + writer.WriteOptionalAttributeString("htotal", obj.HTotal); + writer.WriteOptionalAttributeString("hbend", obj.HBEnd); + writer.WriteOptionalAttributeString("hbstart", obj.HBStart); + writer.WriteOptionalAttributeString("vtotal", obj.VTotal); + writer.WriteOptionalAttributeString("vbend", obj.VBEnd); + writer.WriteOptionalAttributeString("vbstart", obj.VBStart); + + writer.WriteEndElement(); + } + + /// + /// Write a Driver to an XmlTextWriter + /// + /// Driver to write + /// XmlTextReader to write to + private static void WriteDriver(Driver obj, XmlTextWriter writer) + { + writer.WriteStartElement("driver"); + + writer.WriteRequiredAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("color", obj.Color); + writer.WriteOptionalAttributeString("sound", obj.Sound); + writer.WriteOptionalAttributeString("palettesize", obj.PaletteSize); + writer.WriteRequiredAttributeString("emulation", obj.Emulation); + writer.WriteRequiredAttributeString("cocktail", obj.Cocktail); + writer.WriteRequiredAttributeString("savestate", obj.SaveState); + writer.WriteOptionalAttributeString("requiresartwork", obj.RequiresArtwork); + writer.WriteOptionalAttributeString("unofficial", obj.Unofficial); + writer.WriteOptionalAttributeString("nosoundhardware", obj.NoSoundHardware); + writer.WriteOptionalAttributeString("incomplete", obj.Incomplete); + + writer.WriteEndElement(); + } + + /// + /// Write a Extension to an XmlTextWriter + /// + /// Extension to write + /// XmlTextReader to write to + private static void WriteExtension(Extension obj, XmlTextWriter writer) + { + writer.WriteStartElement("extension"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a Feature to an XmlTextWriter + /// + /// Feature to write + /// XmlTextReader to write to + private static void WriteFeature(Feature obj, XmlTextWriter writer) + { + writer.WriteStartElement("feature"); + + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("overall", obj.Overall); + + writer.WriteEndElement(); + } + + /// + /// Write a GameBase to an XmlTextWriter + /// + /// GameBase to write + /// XmlTextReader to write to + private static void WriteGameBase(GameBase obj, XmlTextWriter writer) + { + if (obj is Game) + writer.WriteStartElement("game"); + else if (obj is Machine) + writer.WriteStartElement("machine"); + else + return; + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("sourcefile", obj.SourceFile); + writer.WriteOptionalAttributeString("isbios", obj.IsBios); + writer.WriteOptionalAttributeString("isdevice", obj.IsDevice); + writer.WriteOptionalAttributeString("ismechanical", obj.IsMechanical); + writer.WriteOptionalAttributeString("runnable", obj.Runnable); + writer.WriteOptionalAttributeString("cloneof", obj.CloneOf); + writer.WriteOptionalAttributeString("romof", obj.RomOf); + writer.WriteOptionalAttributeString("sampleof", obj.SampleOf); + + writer.WriteRequiredElementString("description", obj.Description); + writer.WriteOptionalElementString("year", obj.Year); + writer.WriteOptionalElementString("manufacturer", obj.Manufacturer); + writer.WriteOptionalElementString("history", obj.History); + + if (obj.BiosSet is not null && obj.BiosSet.Length > 0) + { + foreach (var biosSet in obj.BiosSet) + { + WriteBiosSet(biosSet, writer); + } + } + + if (obj.Rom is not null && obj.Rom.Length > 0) + { + foreach (var rom in obj.Rom) + { + WriteRom(rom, writer); + } + } + + if (obj.Disk is not null && obj.Disk.Length > 0) + { + foreach (var disk in obj.Disk) + { + WriteDisk(disk, writer); + } + } + + if (obj.DeviceRef is not null && obj.DeviceRef.Length > 0) + { + foreach (var deviceRef in obj.DeviceRef) + { + WriteDeviceRef(deviceRef, writer); + } + } + + if (obj.Sample is not null && obj.Sample.Length > 0) + { + foreach (var sample in obj.Sample) + { + WriteSample(sample, writer); + } + } + + if (obj.Chip is not null && obj.Chip.Length > 0) + { + foreach (var chip in obj.Chip) + { + WriteChip(chip, writer); + } + } + + if (obj.Display is not null && obj.Display.Length > 0) + { + foreach (var display in obj.Display) + { + WriteDisplay(display, writer); + } + } + + if (obj.Video is not null && obj.Video.Length > 0) + { + foreach (var video in obj.Video) + { + WriteVideo(video, writer); + } + } + + if (obj.Sound is not null) + WriteSound(obj.Sound, writer); + + if (obj.Input is not null) + WriteInput(obj.Input, writer); + + if (obj.DipSwitch is not null && obj.DipSwitch.Length > 0) + { + foreach (var dipSwitch in obj.DipSwitch) + { + WriteDipSwitch(dipSwitch, writer); + } + } + + if (obj.Configuration is not null && obj.Configuration.Length > 0) + { + foreach (var configuration in obj.Configuration) + { + WriteConfiguration(configuration, writer); + } + } + + if (obj.Port is not null && obj.Port.Length > 0) + { + foreach (var port in obj.Port) + { + WritePort(port, writer); + } + } + + if (obj.Adjuster is not null && obj.Adjuster.Length > 0) + { + foreach (var adjuster in obj.Adjuster) + { + WriteAdjuster(adjuster, writer); + } + } + + if (obj.Driver is not null) + WriteDriver(obj.Driver, writer); + + if (obj.Feature is not null && obj.Feature.Length > 0) + { + foreach (var feature in obj.Feature) + { + WriteFeature(feature, writer); + } + } + + if (obj.Device is not null && obj.Device.Length > 0) + { + foreach (var device in obj.Device) + { + WriteDevice(device, writer); + } + } + + if (obj.Slot is not null && obj.Slot.Length > 0) + { + foreach (var slot in obj.Slot) + { + WriteSlot(slot, writer); + } + } + + if (obj.SoftwareList is not null && obj.SoftwareList.Length > 0) + { + foreach (var softwareList in obj.SoftwareList) + { + WriteSoftwareList(softwareList, writer); + } + } + + if (obj.RamOption is not null && obj.RamOption.Length > 0) + { + foreach (var ramOption in obj.RamOption) + { + WriteRamOption(ramOption, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Input to an XmlTextWriter + /// + /// Input to write + /// XmlTextReader to write to + private static void WriteInput(Input obj, XmlTextWriter writer) + { + writer.WriteStartElement("input"); + + writer.WriteOptionalAttributeString("service", obj.Service); + writer.WriteOptionalAttributeString("tilt", obj.Tilt); + writer.WriteRequiredAttributeString("players", obj.Players); + writer.WriteOptionalAttributeString("control", obj.ControlAttr); + writer.WriteOptionalAttributeString("buttons", obj.Buttons); + writer.WriteOptionalAttributeString("coins", obj.Coins); + + if (obj.Control is not null && obj.Control.Length > 0) + { + foreach (var control in obj.Control) + { + WriteControl(control, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Instance to an XmlTextWriter + /// + /// Instance to write + /// XmlTextReader to write to + private static void WriteInstance(Instance obj, XmlTextWriter writer) + { + writer.WriteStartElement("instance"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("briefname", obj.BriefName); + + writer.WriteEndElement(); + } + + /// + /// Write a Port to an XmlTextWriter + /// + /// Port to write + /// XmlTextReader to write to + private static void WritePort(Port obj, XmlTextWriter writer) + { + writer.WriteStartElement("port"); + + writer.WriteRequiredAttributeString("tag", obj.Tag); + + if (obj.Analog is not null && obj.Analog.Length > 0) + { + foreach (var analog in obj.Analog) + { + WriteAnalog(analog, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a RamOption to an XmlTextWriter + /// + /// RamOption to write + /// XmlTextReader to write to + private static void WriteRamOption(RamOption obj, XmlTextWriter writer) + { + writer.WriteStartElement("ramoption"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Content is not null) + writer.WriteValue(obj.Content); + + writer.WriteEndElement(); + } + + /// + /// Write a Rom to an XmlTextWriter + /// + /// Rom to write + /// XmlTextReader to write to + private static void WriteRom(Rom obj, XmlTextWriter writer) + { + writer.WriteStartElement("rom"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("bios", obj.Bios); + writer.WriteRequiredAttributeString("size", obj.Size); + writer.WriteOptionalAttributeString("crc", obj.CRC); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("merge", obj.Merge); + writer.WriteOptionalAttributeString("region", obj.Region); + writer.WriteOptionalAttributeString("offset", obj.Offset); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("optional", obj.Optional); + writer.WriteOptionalAttributeString("dispose", obj.Dispose); + writer.WriteOptionalAttributeString("soundonly", obj.SoundOnly); + + writer.WriteEndElement(); + } + + /// + /// Write a Sample to an XmlTextWriter + /// + /// Sample to write + /// XmlTextReader to write to + private static void WriteSample(Sample obj, XmlTextWriter writer) + { + writer.WriteStartElement("sample"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a Slot to an XmlTextWriter + /// + /// Slot to write + /// XmlTextReader to write to + private static void WriteSlot(Slot obj, XmlTextWriter writer) + { + writer.WriteStartElement("slot"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + if (obj.SlotOption is not null && obj.SlotOption.Length > 0) + { + foreach (var slotOption in obj.SlotOption) + { + WriteSlotOption(slotOption, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a SlotOption to an XmlTextWriter + /// + /// SlotOption to write + /// XmlTextReader to write to + private static void WriteSlotOption(SlotOption obj, XmlTextWriter writer) + { + writer.WriteStartElement("slotoption"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("devname", obj.DevName); + writer.WriteOptionalAttributeString("default", obj.Default); + + writer.WriteEndElement(); + } + + /// + /// Write a SoftwareList to an XmlTextWriter + /// + /// SoftwareList to write + /// XmlTextReader to write to + private static void WriteSoftwareList(Data.Models.Listxml.SoftwareList obj, XmlTextWriter writer) + { + writer.WriteStartElement("softwarelist"); + + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("filter", obj.Filter); + + writer.WriteEndElement(); + } + + /// + /// Write a Sound to an XmlTextWriter + /// + /// Sound to write + /// XmlTextReader to write to + private static void WriteSound(Sound obj, XmlTextWriter writer) + { + writer.WriteStartElement("sound"); + + writer.WriteRequiredAttributeString("channels", obj.Channels); + + writer.WriteEndElement(); + } + + /// + /// Write a Video to an XmlTextWriter + /// + /// Video to write + /// XmlTextReader to write to + private static void WriteVideo(Video obj, XmlTextWriter writer) + { + writer.WriteStartElement("video"); + + writer.WriteRequiredAttributeString("screen", obj.Screen); + writer.WriteRequiredAttributeString("orientation", obj.Orientation); + writer.WriteOptionalAttributeString("width", obj.Width); + writer.WriteOptionalAttributeString("height", obj.Height); + writer.WriteOptionalAttributeString("aspectx", obj.AspectX); + writer.WriteOptionalAttributeString("aspecty", obj.AspectY); + writer.WriteRequiredAttributeString("refresh", obj.Refresh); + + writer.WriteEndElement(); + } + + #endregion } } diff --git a/SabreTools.Serialization.Writers/Logiqx.cs b/SabreTools.Serialization.Writers/Logiqx.cs index 0fc7a258..410b813c 100644 --- a/SabreTools.Serialization.Writers/Logiqx.cs +++ b/SabreTools.Serialization.Writers/Logiqx.cs @@ -1,9 +1,13 @@ using System.IO; +using System.Text; +using System.Xml; using SabreTools.Data.Models.Logiqx; +using SabreTools.IO.Extensions; +using SabreTools.Text.Extensions; namespace SabreTools.Serialization.Writers { - public class Logiqx : XmlFile + public class Logiqx : BaseBinaryWriter { #region Constants @@ -29,27 +33,519 @@ namespace SabreTools.Serialization.Writers #endregion - #region IByteWriter - - /// - public override byte[]? SerializeArray(Datafile? obj) - => SerializeArray(obj, DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSysId); - - #endregion - - #region IFileWriter - - /// - public override bool SerializeFile(Datafile? obj, string? path) - => Serialize(obj, path, DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSysId); - - #endregion - - #region IStreamWriter - - /// + /// public override Stream? SerializeStream(Datafile? obj) - => Serialize(obj, DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSysId); + { + // If the metadata file is null + if (obj is null) + return null; + + // Setup the writer and output + var stream = new MemoryStream(); + var writer = new XmlTextWriter(stream, Encoding.UTF8); + writer.Formatting = Formatting.Indented; + + // Write document type + writer.WriteDocType(DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSubset); + + // Write the SoftwareDb, if it exists + WriteDatafile(obj, writer); + writer.Flush(); + + // Return the stream + stream.SeekIfPossible(0, SeekOrigin.Begin); + return stream; + } + + /// + /// Write a Datafile to an XmlTextWriter + /// + /// Datafile to write + /// XmlTextReader to write to + private static void WriteDatafile(Datafile obj, XmlTextWriter writer) + { + writer.WriteStartElement("datafile"); + + writer.WriteOptionalAttributeString("build", obj.Build); + writer.WriteOptionalAttributeString("debug", obj.Debug); + + // TODO: Fix schema location writing + // writer.WriteOptionalAttributeString("schemaLocation", obj.SchemaLocation); + + if (obj.Header is not null) + WriteHeader(obj.Header, writer); + + if (obj.Game is not null && obj.Game.Length > 0) + { + foreach (var gameBase in obj.Game) + { + WriteGameBase(gameBase, writer); + } + } + + if (obj.Dir is not null && obj.Dir.Length > 0) + { + foreach (var dir in obj.Dir) + { + WriteDir(dir, writer); + } + } + + writer.WriteEndElement(); + } + + #region Header + + /// + /// Write a ClrMamePro to an XmlTextWriter + /// + /// ClrMamePro to write + /// XmlTextReader to write to + private static void WriteClrMamePro(Data.Models.Logiqx.ClrMamePro obj, XmlTextWriter writer) + { + writer.WriteStartElement("clrmamepro"); + + writer.WriteOptionalAttributeString("header", obj.Header); + writer.WriteOptionalAttributeString("forcemerging", obj.ForceMerging); + writer.WriteOptionalAttributeString("forcenodump", obj.ForceNodump); + writer.WriteOptionalAttributeString("forcepacking", obj.ForcePacking); + + writer.WriteEndElement(); + } + + /// + /// Write a Header to an XmlTextWriter + /// + /// Header to write + /// XmlTextReader to write to + private static void WriteHeader(Header obj, XmlTextWriter writer) + { + writer.WriteStartElement("header"); + + writer.WriteOptionalElementString("id", obj.Id); + writer.WriteRequiredElementString("name", obj.Name); + writer.WriteRequiredElementString("description", obj.Description); + writer.WriteOptionalElementString("rootdir", obj.RootDir); + writer.WriteOptionalElementString("category", obj.Category); + writer.WriteRequiredElementString("version", obj.Version); + writer.WriteOptionalElementString("date", obj.Date); + writer.WriteRequiredElementString("author", obj.Author); + writer.WriteOptionalElementString("email", obj.Email); + writer.WriteOptionalElementString("homepage", obj.Homepage); + writer.WriteOptionalElementString("url", obj.Url); + writer.WriteOptionalElementString("comment", obj.Comment); + writer.WriteOptionalElementString("type", obj.Type); + + if (obj.ClrMamePro is not null) + WriteClrMamePro(obj.ClrMamePro, writer); + + if (obj.RomCenter is not null) + WriteRomCenter(obj.RomCenter, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a RomCenter to an XmlTextWriter + /// + /// RomCenter to write + /// XmlTextReader to write to + private static void WriteRomCenter(Data.Models.Logiqx.RomCenter obj, XmlTextWriter writer) + { + writer.WriteStartElement("romcenter"); + + writer.WriteOptionalAttributeString("plugin", obj.Plugin); + writer.WriteOptionalAttributeString("rommode", obj.RomMode); + writer.WriteOptionalAttributeString("biosmode", obj.BiosMode); + writer.WriteOptionalAttributeString("samplemode", obj.SampleMode); + writer.WriteOptionalAttributeString("lockrommode", obj.LockRomMode); + writer.WriteOptionalAttributeString("lockbiosmode", obj.LockBiosMode); + writer.WriteOptionalAttributeString("locksamplemode", obj.LockSampleMode); + + writer.WriteEndElement(); + } + + #endregion + + #region Items + + /// + /// Write a Archive to an XmlTextWriter + /// + /// Archive to write + /// XmlTextReader to write to + private static void WriteArchive(Archive obj, XmlTextWriter writer) + { + writer.WriteStartElement("archive"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a BiosSet to an XmlTextWriter + /// + /// BiosSet to write + /// XmlTextReader to write to + private static void WriteBiosSet(BiosSet obj, XmlTextWriter writer) + { + writer.WriteStartElement("biosset"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("description", obj.Description); + writer.WriteOptionalAttributeString("default", obj.Default); + + writer.WriteEndElement(); + } + + /// + /// Write a DeviceRef to an XmlTextWriter + /// + /// DeviceRef to write + /// XmlTextReader to write to + private static void WriteDeviceRef(DeviceRef obj, XmlTextWriter writer) + { + writer.WriteStartElement("device_ref"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a Dir to an XmlTextWriter + /// + /// Dir to write + /// XmlTextReader to write to + private static void WriteDir(Dir obj, XmlTextWriter writer) + { + writer.WriteStartElement("dir"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + if (obj.Subdir is not null && obj.Subdir.Length > 0) + { + foreach (var subdir in obj.Subdir) + { + WriteDir(subdir, writer); + } + } + + if (obj.Game is not null && obj.Game.Length > 0) + { + foreach (var game in obj.Game) + { + WriteGameBase(game, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Disk to an XmlTextWriter + /// + /// Disk to write + /// XmlTextReader to write to + private static void WriteDisk(Disk obj, XmlTextWriter writer) + { + writer.WriteStartElement("disk"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("md5", obj.MD5); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("merge", obj.Merge); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("region", obj.Region); + + writer.WriteEndElement(); + } + + /// + /// Write a Driver to an XmlTextWriter + /// + /// Driver to write + /// XmlTextReader to write to + private static void WriteDriver(Driver obj, XmlTextWriter writer) + { + writer.WriteStartElement("driver"); + + writer.WriteRequiredAttributeString("status", obj.Status); + writer.WriteRequiredAttributeString("emulation", obj.Emulation); + writer.WriteRequiredAttributeString("cocktail", obj.Cocktail); + writer.WriteRequiredAttributeString("savestate", obj.SaveState); + writer.WriteOptionalAttributeString("requiresartwork", obj.RequiresArtwork); + writer.WriteOptionalAttributeString("unofficial", obj.Unofficial); + writer.WriteOptionalAttributeString("nosoundhardware", obj.NoSoundHardware); + writer.WriteOptionalAttributeString("incomplete", obj.Incomplete); + + writer.WriteEndElement(); + } + + /// + /// Write a GameBase to an XmlTextWriter + /// + /// GameBase to write + /// XmlTextReader to write to + private static void WriteGameBase(GameBase obj, XmlTextWriter writer) + { + if (obj is Game) + writer.WriteStartElement("game"); + else if (obj is Machine) + writer.WriteStartElement("machine"); + else + return; + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("sourcefile", obj.SourceFile); + writer.WriteOptionalAttributeString("isbios", obj.IsBios); + writer.WriteOptionalAttributeString("isdevice", obj.IsDevice); + writer.WriteOptionalAttributeString("ismechanical", obj.IsMechanical); + writer.WriteOptionalAttributeString("cloneof", obj.CloneOf); + writer.WriteOptionalAttributeString("romof", obj.RomOf); + writer.WriteOptionalAttributeString("sampleof", obj.SampleOf); + writer.WriteOptionalAttributeString("board", obj.Board); + writer.WriteOptionalAttributeString("rebuildto", obj.RebuildTo); + writer.WriteOptionalAttributeString("id", obj.Id); + writer.WriteOptionalAttributeString("cloneofid", obj.CloneOfId); + writer.WriteOptionalAttributeString("runnable", obj.Runnable); + + if (obj.Comment is not null && obj.Comment.Length > 0) + { + foreach (var comment in obj.Comment) + { + writer.WriteRequiredElementString("comment", comment); + } + } + + writer.WriteRequiredElementString("description", obj.Description); + writer.WriteOptionalElementString("year", obj.Year); + writer.WriteOptionalElementString("manufacturer", obj.Manufacturer); + writer.WriteOptionalElementString("publisher", obj.Publisher); + + if (obj.Category is not null && obj.Category.Length > 0) + { + foreach (var category in obj.Category) + { + writer.WriteRequiredElementString("category", category); + } + } + + if (obj.Trurip is not null) + WriteTrurip(obj.Trurip, writer); + + if (obj.Release is not null && obj.Release.Length > 0) + { + foreach (var release in obj.Release) + { + WriteRelease(release, writer); + } + } + + if (obj.BiosSet is not null && obj.BiosSet.Length > 0) + { + foreach (var biosSet in obj.BiosSet) + { + WriteBiosSet(biosSet, writer); + } + } + + if (obj.Rom is not null && obj.Rom.Length > 0) + { + foreach (var rom in obj.Rom) + { + WriteRom(rom, writer); + } + } + + if (obj.Disk is not null && obj.Disk.Length > 0) + { + foreach (var disk in obj.Disk) + { + WriteDisk(disk, writer); + } + } + + if (obj.Media is not null && obj.Media.Length > 0) + { + foreach (var media in obj.Media) + { + WriteMedia(media, writer); + } + } + + if (obj.DeviceRef is not null && obj.DeviceRef.Length > 0) + { + foreach (var deviceRef in obj.DeviceRef) + { + WriteDeviceRef(deviceRef, writer); + } + } + + if (obj.Sample is not null && obj.Sample.Length > 0) + { + foreach (var sample in obj.Sample) + { + WriteSample(sample, writer); + } + } + + if (obj.Archive is not null && obj.Archive.Length > 0) + { + foreach (var archive in obj.Archive) + { + WriteArchive(archive, writer); + } + } + + if (obj.Driver is not null) + WriteDriver(obj.Driver, writer); + + if (obj.SoftwareList is not null && obj.SoftwareList.Length > 0) + { + foreach (var softwareList in obj.SoftwareList) + { + WriteSoftwareList(softwareList, writer); + } + } + + writer.WriteOptionalElementString("url", obj.Url); + writer.WriteOptionalElementString("hash", obj.Hash); + + writer.WriteEndElement(); + } + + /// + /// Write a Media to an XmlTextWriter + /// + /// Media to write + /// XmlTextReader to write to + private static void WriteMedia(Media obj, XmlTextWriter writer) + { + writer.WriteStartElement("media"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("md5", obj.MD5); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("sha256", obj.SHA256); + writer.WriteOptionalAttributeString("spamsum", obj.SpamSum); + + writer.WriteEndElement(); + } + + /// + /// Write a Release to an XmlTextWriter + /// + /// Release to write + /// XmlTextReader to write to + private static void WriteRelease(Release obj, XmlTextWriter writer) + { + writer.WriteStartElement("release"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("region", obj.Region); + writer.WriteOptionalAttributeString("language", obj.Language); + writer.WriteOptionalAttributeString("date", obj.Date); + writer.WriteOptionalAttributeString("default", obj.Default); + + writer.WriteEndElement(); + } + + /// + /// Write a Rom to an XmlTextWriter + /// + /// Rom to write + /// XmlTextReader to write to + private static void WriteRom(Rom obj, XmlTextWriter writer) + { + writer.WriteStartElement("rom"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("size", obj.Size); + writer.WriteOptionalAttributeString("crc16", obj.CRC16); + writer.WriteOptionalAttributeString("crc", obj.CRC); + writer.WriteOptionalAttributeString("crc64", obj.CRC64); + writer.WriteOptionalAttributeString("md2", obj.MD2); + writer.WriteOptionalAttributeString("md4", obj.MD4); + writer.WriteOptionalAttributeString("md5", obj.MD5); + writer.WriteOptionalAttributeString("ripemd128", obj.RIPEMD128); + writer.WriteOptionalAttributeString("ripemd160", obj.RIPEMD160); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("sha256", obj.SHA256); + writer.WriteOptionalAttributeString("sha384", obj.SHA384); + writer.WriteOptionalAttributeString("sha512", obj.SHA512); + writer.WriteOptionalAttributeString("spamsum", obj.SpamSum); + writer.WriteOptionalAttributeString("xxh3_64", obj.xxHash364); + writer.WriteOptionalAttributeString("xxh3_128", obj.xxHash3128); + writer.WriteOptionalAttributeString("merge", obj.Merge); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("serial", obj.Serial); + writer.WriteOptionalAttributeString("header", obj.Header); + writer.WriteOptionalAttributeString("date", obj.Date); + writer.WriteOptionalAttributeString("inverted", obj.Inverted); + writer.WriteOptionalAttributeString("mia", obj.MIA); + + writer.WriteEndElement(); + } + + /// + /// Write a Sample to an XmlTextWriter + /// + /// Sample to write + /// XmlTextReader to write to + private static void WriteSample(Sample obj, XmlTextWriter writer) + { + writer.WriteStartElement("sample"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a SoftwareList to an XmlTextWriter + /// + /// SoftwareList to write + /// XmlTextReader to write to + private static void WriteSoftwareList(Data.Models.Logiqx.SoftwareList obj, XmlTextWriter writer) + { + writer.WriteStartElement("softwarelist"); + + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("filter", obj.Filter); + + writer.WriteEndElement(); + } + + /// + /// Write a Trurip to an XmlTextWriter + /// + /// Trurip to write + /// XmlTextReader to write to + private static void WriteTrurip(Trurip obj, XmlTextWriter writer) + { + writer.WriteStartElement("trurip"); + + writer.WriteOptionalElementString("titleid", obj.TitleID); + writer.WriteOptionalElementString("publisher", obj.Publisher); + writer.WriteOptionalElementString("developer", obj.Developer); + writer.WriteOptionalElementString("year", obj.Year); + writer.WriteOptionalElementString("genre", obj.Genre); + writer.WriteOptionalElementString("subgenre", obj.Subgenre); + writer.WriteOptionalElementString("ratings", obj.Ratings); + writer.WriteOptionalElementString("score", obj.Score); + writer.WriteOptionalElementString("players", obj.Players); + writer.WriteOptionalElementString("enabled", obj.Enabled); + writer.WriteOptionalElementString("crc", obj.CRC); + writer.WriteOptionalElementString("source", obj.Source); + writer.WriteOptionalElementString("cloneof", obj.CloneOf); + writer.WriteOptionalElementString("relatedto", obj.RelatedTo); + + writer.WriteEndElement(); + } #endregion } diff --git a/SabreTools.Serialization.Writers/M1.cs b/SabreTools.Serialization.Writers/M1.cs index 2a92dc5c..c718d080 100644 --- a/SabreTools.Serialization.Writers/M1.cs +++ b/SabreTools.Serialization.Writers/M1.cs @@ -1,7 +1,840 @@ +using System.IO; +using System.Text; +using System.Xml; +using SabreTools.Data.Models.Listxml; +using SabreTools.IO.Extensions; +using SabreTools.Text.Extensions; + namespace SabreTools.Serialization.Writers { - public class M1 : XmlFile + public class M1 : BaseBinaryWriter { - // All logic taken care of in the base class + /// + public override Stream? SerializeStream(Data.Models.Listxml.M1? obj) + { + // If the metadata file is null + if (obj is null) + return null; + + // Setup the writer and output + var stream = new MemoryStream(); + var writer = new XmlTextWriter(stream, Encoding.UTF8); + writer.Formatting = Formatting.Indented; + + // Write the M1, if it exists + WriteM1(obj, writer); + writer.Flush(); + + // Return the stream + stream.SeekIfPossible(0, SeekOrigin.Begin); + return stream; + } + + /// + /// Write a M1 to an XmlTextWriter + /// + /// M1 to write + /// XmlTextReader to write to + private static void WriteM1(Data.Models.Listxml.M1 obj, XmlTextWriter writer) + { + writer.WriteStartElement("m1"); + + writer.WriteOptionalAttributeString("version", obj.Version); + + if (obj.Game is not null && obj.Game.Length > 0) + { + foreach (var gameBase in obj.Game) + { + WriteGameBase(gameBase, writer); + } + } + + writer.WriteEndElement(); + } + + #region Items + + /// + /// Write a Adjuster to an XmlTextWriter + /// + /// Adjuster to write + /// XmlTextReader to write to + private static void WriteAdjuster(Adjuster obj, XmlTextWriter writer) + { + writer.WriteStartElement("adjuster"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Analog to an XmlTextWriter + /// + /// Analog to write + /// XmlTextReader to write to + private static void WriteAnalog(Analog obj, XmlTextWriter writer) + { + writer.WriteStartElement("analog"); + + writer.WriteRequiredAttributeString("mask", obj.Mask); + + writer.WriteEndElement(); + } + + /// + /// Write a BiosSet to an XmlTextWriter + /// + /// BiosSet to write + /// XmlTextReader to write to + private static void WriteBiosSet(BiosSet obj, XmlTextWriter writer) + { + writer.WriteStartElement("biosset"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("description", obj.Description); + writer.WriteOptionalAttributeString("default", obj.Default); + + writer.WriteEndElement(); + } + + /// + /// Write a Chip to an XmlTextWriter + /// + /// Chip to write + /// XmlTextReader to write to + private static void WriteChip(Chip obj, XmlTextWriter writer) + { + writer.WriteStartElement("chip"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("soundonly", obj.SoundOnly); + writer.WriteOptionalAttributeString("clock", obj.Clock); + + writer.WriteEndElement(); + } + + /// + /// Write a Condition to an XmlTextWriter + /// + /// Condition to write + /// XmlTextReader to write to + private static void WriteCondition(Condition obj, XmlTextWriter writer) + { + writer.WriteStartElement("condition"); + + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("mask", obj.Mask); + writer.WriteRequiredAttributeString("relation", obj.Relation); + writer.WriteRequiredAttributeString("value", obj.Value); + + writer.WriteEndElement(); + } + + /// + /// Write a Configuration to an XmlTextWriter + /// + /// Configuration to write + /// XmlTextReader to write to + private static void WriteConfiguration(Configuration obj, XmlTextWriter writer) + { + writer.WriteStartElement("configuration"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteOptionalAttributeString("mask", obj.Mask); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + if (obj.ConfLocation is not null && obj.ConfLocation.Length > 0) + { + foreach (var confLocation in obj.ConfLocation) + { + WriteConfLocation(confLocation, writer); + } + } + + if (obj.ConfSetting is not null && obj.ConfSetting.Length > 0) + { + foreach (var confSetting in obj.ConfSetting) + { + WriteConfSetting(confSetting, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a ConfLocation to an XmlTextWriter + /// + /// ConfLocation to write + /// XmlTextReader to write to + private static void WriteConfLocation(ConfLocation obj, XmlTextWriter writer) + { + writer.WriteStartElement("conflocation"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("number", obj.Number); + writer.WriteOptionalAttributeString("inverted", obj.Inverted); + + writer.WriteEndElement(); + } + + /// + /// Write a ConfSetting to an XmlTextWriter + /// + /// ConfSetting to write + /// XmlTextReader to write to + private static void WriteConfSetting(ConfSetting obj, XmlTextWriter writer) + { + writer.WriteStartElement("confsetting"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("value", obj.Value); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Control to an XmlTextWriter + /// + /// Control to write + /// XmlTextReader to write to + private static void WriteControl(Control obj, XmlTextWriter writer) + { + writer.WriteStartElement("control"); + + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("player", obj.Player); + writer.WriteOptionalAttributeString("buttons", obj.Buttons); + writer.WriteOptionalAttributeString("reqbuttons", obj.ReqButtons); + writer.WriteOptionalAttributeString("minimum", obj.Minimum); + writer.WriteOptionalAttributeString("maximum", obj.Maximum); + writer.WriteOptionalAttributeString("sensitivity", obj.Sensitivity); + writer.WriteOptionalAttributeString("keydelta", obj.KeyDelta); + writer.WriteOptionalAttributeString("reverse", obj.Reverse); + writer.WriteOptionalAttributeString("ways", obj.Ways); + writer.WriteOptionalAttributeString("ways2", obj.Ways2); + writer.WriteOptionalAttributeString("ways3", obj.Ways3); + + writer.WriteEndElement(); + } + + /// + /// Write a Device to an XmlTextWriter + /// + /// Device to write + /// XmlTextReader to write to + private static void WriteDevice(Device obj, XmlTextWriter writer) + { + writer.WriteStartElement("device"); + + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("tag", obj.Tag); + writer.WriteOptionalAttributeString("fixed_image", obj.FixedImage); + writer.WriteOptionalAttributeString("mandatory", obj.Mandatory); + writer.WriteOptionalAttributeString("interface", obj.Interface); + + if (obj.Instance is not null) + WriteInstance(obj.Instance, writer); + + if (obj.Extension is not null && obj.Extension.Length > 0) + { + foreach (var extension in obj.Extension) + { + WriteExtension(extension, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a DeviceRef to an XmlTextWriter + /// + /// DeviceRef to write + /// XmlTextReader to write to + private static void WriteDeviceRef(DeviceRef obj, XmlTextWriter writer) + { + writer.WriteStartElement("device_ref"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a DipLocation to an XmlTextWriter + /// + /// DipLocation to write + /// XmlTextReader to write to + private static void WriteDipLocation(DipLocation obj, XmlTextWriter writer) + { + writer.WriteStartElement("diplocation"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("number", obj.Number); + writer.WriteOptionalAttributeString("inverted", obj.Inverted); + + writer.WriteEndElement(); + } + + /// + /// Write a DipSwitch to an XmlTextWriter + /// + /// DipSwitch to write + /// XmlTextReader to write to + private static void WriteDipSwitch(DipSwitch obj, XmlTextWriter writer) + { + writer.WriteStartElement("dipswitch"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteOptionalAttributeString("mask", obj.Mask); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + if (obj.DipLocation is not null && obj.DipLocation.Length > 0) + { + foreach (var dipLocation in obj.DipLocation) + { + WriteDipLocation(dipLocation, writer); + } + } + + if (obj.DipValue is not null && obj.DipValue.Length > 0) + { + foreach (var dipValue in obj.DipValue) + { + WriteDipValue(dipValue, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a DipValue to an XmlTextWriter + /// + /// DipValue to write + /// XmlTextReader to write to + private static void WriteDipValue(DipValue obj, XmlTextWriter writer) + { + writer.WriteStartElement("dipvalue"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("value", obj.Value); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Disk to an XmlTextWriter + /// + /// Disk to write + /// XmlTextReader to write to + private static void WriteDisk(Disk obj, XmlTextWriter writer) + { + writer.WriteStartElement("disk"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("md5", obj.MD5); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("merge", obj.Merge); + writer.WriteOptionalAttributeString("region", obj.Region); + writer.WriteOptionalAttributeString("index", obj.Index); + writer.WriteOptionalAttributeString("writable", obj.Writable); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("optional", obj.Optional); + + writer.WriteEndElement(); + } + + /// + /// Write a Display to an XmlTextWriter + /// + /// Display to write + /// XmlTextReader to write to + private static void WriteDisplay(Display obj, XmlTextWriter writer) + { + writer.WriteStartElement("display"); + + writer.WriteOptionalAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("rotate", obj.Rotate); + writer.WriteOptionalAttributeString("flipx", obj.FlipX); + writer.WriteOptionalAttributeString("width", obj.Width); + writer.WriteOptionalAttributeString("height", obj.Height); + writer.WriteRequiredAttributeString("refresh", obj.Refresh); + writer.WriteOptionalAttributeString("pixclock", obj.PixClock); + writer.WriteOptionalAttributeString("htotal", obj.HTotal); + writer.WriteOptionalAttributeString("hbend", obj.HBEnd); + writer.WriteOptionalAttributeString("hbstart", obj.HBStart); + writer.WriteOptionalAttributeString("vtotal", obj.VTotal); + writer.WriteOptionalAttributeString("vbend", obj.VBEnd); + writer.WriteOptionalAttributeString("vbstart", obj.VBStart); + + writer.WriteEndElement(); + } + + /// + /// Write a Driver to an XmlTextWriter + /// + /// Driver to write + /// XmlTextReader to write to + private static void WriteDriver(Driver obj, XmlTextWriter writer) + { + writer.WriteStartElement("driver"); + + writer.WriteRequiredAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("color", obj.Color); + writer.WriteOptionalAttributeString("sound", obj.Sound); + writer.WriteOptionalAttributeString("palettesize", obj.PaletteSize); + writer.WriteRequiredAttributeString("emulation", obj.Emulation); + writer.WriteRequiredAttributeString("cocktail", obj.Cocktail); + writer.WriteRequiredAttributeString("savestate", obj.SaveState); + writer.WriteOptionalAttributeString("requiresartwork", obj.RequiresArtwork); + writer.WriteOptionalAttributeString("unofficial", obj.Unofficial); + writer.WriteOptionalAttributeString("nosoundhardware", obj.NoSoundHardware); + writer.WriteOptionalAttributeString("incomplete", obj.Incomplete); + + writer.WriteEndElement(); + } + + /// + /// Write a Extension to an XmlTextWriter + /// + /// Extension to write + /// XmlTextReader to write to + private static void WriteExtension(Extension obj, XmlTextWriter writer) + { + writer.WriteStartElement("extension"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a Feature to an XmlTextWriter + /// + /// Feature to write + /// XmlTextReader to write to + private static void WriteFeature(Feature obj, XmlTextWriter writer) + { + writer.WriteStartElement("feature"); + + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("overall", obj.Overall); + + writer.WriteEndElement(); + } + + /// + /// Write a GameBase to an XmlTextWriter + /// + /// GameBase to write + /// XmlTextReader to write to + private static void WriteGameBase(GameBase obj, XmlTextWriter writer) + { + if (obj is Game) + writer.WriteStartElement("game"); + else if (obj is Machine) + writer.WriteStartElement("machine"); + else + return; + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("sourcefile", obj.SourceFile); + writer.WriteOptionalAttributeString("isbios", obj.IsBios); + writer.WriteOptionalAttributeString("isdevice", obj.IsDevice); + writer.WriteOptionalAttributeString("ismechanical", obj.IsMechanical); + writer.WriteOptionalAttributeString("runnable", obj.Runnable); + writer.WriteOptionalAttributeString("cloneof", obj.CloneOf); + writer.WriteOptionalAttributeString("romof", obj.RomOf); + writer.WriteOptionalAttributeString("sampleof", obj.SampleOf); + + writer.WriteRequiredElementString("description", obj.Description); + writer.WriteOptionalElementString("year", obj.Year); + writer.WriteOptionalElementString("manufacturer", obj.Manufacturer); + writer.WriteOptionalElementString("history", obj.History); + + if (obj.BiosSet is not null && obj.BiosSet.Length > 0) + { + foreach (var biosSet in obj.BiosSet) + { + WriteBiosSet(biosSet, writer); + } + } + + if (obj.Rom is not null && obj.Rom.Length > 0) + { + foreach (var rom in obj.Rom) + { + WriteRom(rom, writer); + } + } + + if (obj.Disk is not null && obj.Disk.Length > 0) + { + foreach (var disk in obj.Disk) + { + WriteDisk(disk, writer); + } + } + + if (obj.DeviceRef is not null && obj.DeviceRef.Length > 0) + { + foreach (var deviceRef in obj.DeviceRef) + { + WriteDeviceRef(deviceRef, writer); + } + } + + if (obj.Sample is not null && obj.Sample.Length > 0) + { + foreach (var sample in obj.Sample) + { + WriteSample(sample, writer); + } + } + + if (obj.Chip is not null && obj.Chip.Length > 0) + { + foreach (var chip in obj.Chip) + { + WriteChip(chip, writer); + } + } + + if (obj.Display is not null && obj.Display.Length > 0) + { + foreach (var display in obj.Display) + { + WriteDisplay(display, writer); + } + } + + if (obj.Video is not null && obj.Video.Length > 0) + { + foreach (var video in obj.Video) + { + WriteVideo(video, writer); + } + } + + if (obj.Sound is not null) + WriteSound(obj.Sound, writer); + + if (obj.Input is not null) + WriteInput(obj.Input, writer); + + if (obj.DipSwitch is not null && obj.DipSwitch.Length > 0) + { + foreach (var dipSwitch in obj.DipSwitch) + { + WriteDipSwitch(dipSwitch, writer); + } + } + + if (obj.Configuration is not null && obj.Configuration.Length > 0) + { + foreach (var configuration in obj.Configuration) + { + WriteConfiguration(configuration, writer); + } + } + + if (obj.Port is not null && obj.Port.Length > 0) + { + foreach (var port in obj.Port) + { + WritePort(port, writer); + } + } + + if (obj.Adjuster is not null && obj.Adjuster.Length > 0) + { + foreach (var adjuster in obj.Adjuster) + { + WriteAdjuster(adjuster, writer); + } + } + + if (obj.Driver is not null) + WriteDriver(obj.Driver, writer); + + if (obj.Feature is not null && obj.Feature.Length > 0) + { + foreach (var feature in obj.Feature) + { + WriteFeature(feature, writer); + } + } + + if (obj.Device is not null && obj.Device.Length > 0) + { + foreach (var device in obj.Device) + { + WriteDevice(device, writer); + } + } + + if (obj.Slot is not null && obj.Slot.Length > 0) + { + foreach (var slot in obj.Slot) + { + WriteSlot(slot, writer); + } + } + + if (obj.SoftwareList is not null && obj.SoftwareList.Length > 0) + { + foreach (var softwareList in obj.SoftwareList) + { + WriteSoftwareList(softwareList, writer); + } + } + + if (obj.RamOption is not null && obj.RamOption.Length > 0) + { + foreach (var ramOption in obj.RamOption) + { + WriteRamOption(ramOption, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Input to an XmlTextWriter + /// + /// Input to write + /// XmlTextReader to write to + private static void WriteInput(Input obj, XmlTextWriter writer) + { + writer.WriteStartElement("input"); + + writer.WriteOptionalAttributeString("service", obj.Service); + writer.WriteOptionalAttributeString("tilt", obj.Tilt); + writer.WriteRequiredAttributeString("players", obj.Players); + writer.WriteOptionalAttributeString("control", obj.ControlAttr); + writer.WriteOptionalAttributeString("buttons", obj.Buttons); + writer.WriteOptionalAttributeString("coins", obj.Coins); + + if (obj.Control is not null && obj.Control.Length > 0) + { + foreach (var control in obj.Control) + { + WriteControl(control, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Instance to an XmlTextWriter + /// + /// Instance to write + /// XmlTextReader to write to + private static void WriteInstance(Instance obj, XmlTextWriter writer) + { + writer.WriteStartElement("instance"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("briefname", obj.BriefName); + + writer.WriteEndElement(); + } + + /// + /// Write a Port to an XmlTextWriter + /// + /// Port to write + /// XmlTextReader to write to + private static void WritePort(Port obj, XmlTextWriter writer) + { + writer.WriteStartElement("port"); + + writer.WriteRequiredAttributeString("tag", obj.Tag); + + if (obj.Analog is not null && obj.Analog.Length > 0) + { + foreach (var analog in obj.Analog) + { + WriteAnalog(analog, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a RamOption to an XmlTextWriter + /// + /// RamOption to write + /// XmlTextReader to write to + private static void WriteRamOption(RamOption obj, XmlTextWriter writer) + { + writer.WriteStartElement("ramoption"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Content is not null) + writer.WriteValue(obj.Content); + + writer.WriteEndElement(); + } + + /// + /// Write a Rom to an XmlTextWriter + /// + /// Rom to write + /// XmlTextReader to write to + private static void WriteRom(Rom obj, XmlTextWriter writer) + { + writer.WriteStartElement("rom"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("bios", obj.Bios); + writer.WriteRequiredAttributeString("size", obj.Size); + writer.WriteOptionalAttributeString("crc", obj.CRC); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("merge", obj.Merge); + writer.WriteOptionalAttributeString("region", obj.Region); + writer.WriteOptionalAttributeString("offset", obj.Offset); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("optional", obj.Optional); + writer.WriteOptionalAttributeString("dispose", obj.Dispose); + writer.WriteOptionalAttributeString("soundonly", obj.SoundOnly); + + writer.WriteEndElement(); + } + + /// + /// Write a Sample to an XmlTextWriter + /// + /// Sample to write + /// XmlTextReader to write to + private static void WriteSample(Sample obj, XmlTextWriter writer) + { + writer.WriteStartElement("sample"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a Slot to an XmlTextWriter + /// + /// Slot to write + /// XmlTextReader to write to + private static void WriteSlot(Slot obj, XmlTextWriter writer) + { + writer.WriteStartElement("slot"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + if (obj.SlotOption is not null && obj.SlotOption.Length > 0) + { + foreach (var slotOption in obj.SlotOption) + { + WriteSlotOption(slotOption, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a SlotOption to an XmlTextWriter + /// + /// SlotOption to write + /// XmlTextReader to write to + private static void WriteSlotOption(SlotOption obj, XmlTextWriter writer) + { + writer.WriteStartElement("slotoption"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("devname", obj.DevName); + writer.WriteOptionalAttributeString("default", obj.Default); + + writer.WriteEndElement(); + } + + /// + /// Write a SoftwareList to an XmlTextWriter + /// + /// SoftwareList to write + /// XmlTextReader to write to + private static void WriteSoftwareList(Data.Models.Listxml.SoftwareList obj, XmlTextWriter writer) + { + writer.WriteStartElement("softwarelist"); + + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("filter", obj.Filter); + + writer.WriteEndElement(); + } + + /// + /// Write a Sound to an XmlTextWriter + /// + /// Sound to write + /// XmlTextReader to write to + private static void WriteSound(Sound obj, XmlTextWriter writer) + { + writer.WriteStartElement("sound"); + + writer.WriteRequiredAttributeString("channels", obj.Channels); + + writer.WriteEndElement(); + } + + /// + /// Write a Video to an XmlTextWriter + /// + /// Video to write + /// XmlTextReader to write to + private static void WriteVideo(Video obj, XmlTextWriter writer) + { + writer.WriteStartElement("video"); + + writer.WriteRequiredAttributeString("screen", obj.Screen); + writer.WriteRequiredAttributeString("orientation", obj.Orientation); + writer.WriteOptionalAttributeString("width", obj.Width); + writer.WriteOptionalAttributeString("height", obj.Height); + writer.WriteOptionalAttributeString("aspectx", obj.AspectX); + writer.WriteOptionalAttributeString("aspecty", obj.AspectY); + writer.WriteRequiredAttributeString("refresh", obj.Refresh); + + writer.WriteEndElement(); + } + + #endregion } } diff --git a/SabreTools.Serialization.Writers/Mess.cs b/SabreTools.Serialization.Writers/Mess.cs index cc382e1c..f7399d07 100644 --- a/SabreTools.Serialization.Writers/Mess.cs +++ b/SabreTools.Serialization.Writers/Mess.cs @@ -1,7 +1,840 @@ +using System.IO; +using System.Text; +using System.Xml; +using SabreTools.Data.Models.Listxml; +using SabreTools.IO.Extensions; +using SabreTools.Text.Extensions; + namespace SabreTools.Serialization.Writers { - public class Mess : XmlFile + public class Mess : BaseBinaryWriter { - // All logic taken care of in the base class + /// + public override Stream? SerializeStream(Data.Models.Listxml.Mess? obj) + { + // If the metadata file is null + if (obj is null) + return null; + + // Setup the writer and output + var stream = new MemoryStream(); + var writer = new XmlTextWriter(stream, Encoding.UTF8); + writer.Formatting = Formatting.Indented; + + // Write the Mess, if it exists + WriteMess(obj, writer); + writer.Flush(); + + // Return the stream + stream.SeekIfPossible(0, SeekOrigin.Begin); + return stream; + } + + /// + /// Write a Mess to an XmlTextWriter + /// + /// Mess to write + /// XmlTextReader to write to + private static void WriteMess(Data.Models.Listxml.Mess obj, XmlTextWriter writer) + { + writer.WriteStartElement("mess"); + + writer.WriteOptionalAttributeString("version", obj.Version); + + if (obj.Game is not null && obj.Game.Length > 0) + { + foreach (var gameBase in obj.Game) + { + WriteGameBase(gameBase, writer); + } + } + + writer.WriteEndElement(); + } + + #region Items + + /// + /// Write a Adjuster to an XmlTextWriter + /// + /// Adjuster to write + /// XmlTextReader to write to + private static void WriteAdjuster(Adjuster obj, XmlTextWriter writer) + { + writer.WriteStartElement("adjuster"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Analog to an XmlTextWriter + /// + /// Analog to write + /// XmlTextReader to write to + private static void WriteAnalog(Analog obj, XmlTextWriter writer) + { + writer.WriteStartElement("analog"); + + writer.WriteRequiredAttributeString("mask", obj.Mask); + + writer.WriteEndElement(); + } + + /// + /// Write a BiosSet to an XmlTextWriter + /// + /// BiosSet to write + /// XmlTextReader to write to + private static void WriteBiosSet(BiosSet obj, XmlTextWriter writer) + { + writer.WriteStartElement("biosset"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("description", obj.Description); + writer.WriteOptionalAttributeString("default", obj.Default); + + writer.WriteEndElement(); + } + + /// + /// Write a Chip to an XmlTextWriter + /// + /// Chip to write + /// XmlTextReader to write to + private static void WriteChip(Chip obj, XmlTextWriter writer) + { + writer.WriteStartElement("chip"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("soundonly", obj.SoundOnly); + writer.WriteOptionalAttributeString("clock", obj.Clock); + + writer.WriteEndElement(); + } + + /// + /// Write a Condition to an XmlTextWriter + /// + /// Condition to write + /// XmlTextReader to write to + private static void WriteCondition(Condition obj, XmlTextWriter writer) + { + writer.WriteStartElement("condition"); + + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("mask", obj.Mask); + writer.WriteRequiredAttributeString("relation", obj.Relation); + writer.WriteRequiredAttributeString("value", obj.Value); + + writer.WriteEndElement(); + } + + /// + /// Write a Configuration to an XmlTextWriter + /// + /// Configuration to write + /// XmlTextReader to write to + private static void WriteConfiguration(Configuration obj, XmlTextWriter writer) + { + writer.WriteStartElement("configuration"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteOptionalAttributeString("mask", obj.Mask); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + if (obj.ConfLocation is not null && obj.ConfLocation.Length > 0) + { + foreach (var confLocation in obj.ConfLocation) + { + WriteConfLocation(confLocation, writer); + } + } + + if (obj.ConfSetting is not null && obj.ConfSetting.Length > 0) + { + foreach (var confSetting in obj.ConfSetting) + { + WriteConfSetting(confSetting, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a ConfLocation to an XmlTextWriter + /// + /// ConfLocation to write + /// XmlTextReader to write to + private static void WriteConfLocation(ConfLocation obj, XmlTextWriter writer) + { + writer.WriteStartElement("conflocation"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("number", obj.Number); + writer.WriteOptionalAttributeString("inverted", obj.Inverted); + + writer.WriteEndElement(); + } + + /// + /// Write a ConfSetting to an XmlTextWriter + /// + /// ConfSetting to write + /// XmlTextReader to write to + private static void WriteConfSetting(ConfSetting obj, XmlTextWriter writer) + { + writer.WriteStartElement("confsetting"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("value", obj.Value); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Control to an XmlTextWriter + /// + /// Control to write + /// XmlTextReader to write to + private static void WriteControl(Control obj, XmlTextWriter writer) + { + writer.WriteStartElement("control"); + + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("player", obj.Player); + writer.WriteOptionalAttributeString("buttons", obj.Buttons); + writer.WriteOptionalAttributeString("reqbuttons", obj.ReqButtons); + writer.WriteOptionalAttributeString("minimum", obj.Minimum); + writer.WriteOptionalAttributeString("maximum", obj.Maximum); + writer.WriteOptionalAttributeString("sensitivity", obj.Sensitivity); + writer.WriteOptionalAttributeString("keydelta", obj.KeyDelta); + writer.WriteOptionalAttributeString("reverse", obj.Reverse); + writer.WriteOptionalAttributeString("ways", obj.Ways); + writer.WriteOptionalAttributeString("ways2", obj.Ways2); + writer.WriteOptionalAttributeString("ways3", obj.Ways3); + + writer.WriteEndElement(); + } + + /// + /// Write a Device to an XmlTextWriter + /// + /// Device to write + /// XmlTextReader to write to + private static void WriteDevice(Device obj, XmlTextWriter writer) + { + writer.WriteStartElement("device"); + + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("tag", obj.Tag); + writer.WriteOptionalAttributeString("fixed_image", obj.FixedImage); + writer.WriteOptionalAttributeString("mandatory", obj.Mandatory); + writer.WriteOptionalAttributeString("interface", obj.Interface); + + if (obj.Instance is not null) + WriteInstance(obj.Instance, writer); + + if (obj.Extension is not null && obj.Extension.Length > 0) + { + foreach (var extension in obj.Extension) + { + WriteExtension(extension, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a DeviceRef to an XmlTextWriter + /// + /// DeviceRef to write + /// XmlTextReader to write to + private static void WriteDeviceRef(DeviceRef obj, XmlTextWriter writer) + { + writer.WriteStartElement("device_ref"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a DipLocation to an XmlTextWriter + /// + /// DipLocation to write + /// XmlTextReader to write to + private static void WriteDipLocation(DipLocation obj, XmlTextWriter writer) + { + writer.WriteStartElement("diplocation"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("number", obj.Number); + writer.WriteOptionalAttributeString("inverted", obj.Inverted); + + writer.WriteEndElement(); + } + + /// + /// Write a DipSwitch to an XmlTextWriter + /// + /// DipSwitch to write + /// XmlTextReader to write to + private static void WriteDipSwitch(DipSwitch obj, XmlTextWriter writer) + { + writer.WriteStartElement("dipswitch"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteOptionalAttributeString("mask", obj.Mask); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + if (obj.DipLocation is not null && obj.DipLocation.Length > 0) + { + foreach (var dipLocation in obj.DipLocation) + { + WriteDipLocation(dipLocation, writer); + } + } + + if (obj.DipValue is not null && obj.DipValue.Length > 0) + { + foreach (var dipValue in obj.DipValue) + { + WriteDipValue(dipValue, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a DipValue to an XmlTextWriter + /// + /// DipValue to write + /// XmlTextReader to write to + private static void WriteDipValue(DipValue obj, XmlTextWriter writer) + { + writer.WriteStartElement("dipvalue"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("value", obj.Value); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Condition is not null) + WriteCondition(obj.Condition, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Disk to an XmlTextWriter + /// + /// Disk to write + /// XmlTextReader to write to + private static void WriteDisk(Disk obj, XmlTextWriter writer) + { + writer.WriteStartElement("disk"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("md5", obj.MD5); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("merge", obj.Merge); + writer.WriteOptionalAttributeString("region", obj.Region); + writer.WriteOptionalAttributeString("index", obj.Index); + writer.WriteOptionalAttributeString("writable", obj.Writable); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("optional", obj.Optional); + + writer.WriteEndElement(); + } + + /// + /// Write a Display to an XmlTextWriter + /// + /// Display to write + /// XmlTextReader to write to + private static void WriteDisplay(Display obj, XmlTextWriter writer) + { + writer.WriteStartElement("display"); + + writer.WriteOptionalAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("rotate", obj.Rotate); + writer.WriteOptionalAttributeString("flipx", obj.FlipX); + writer.WriteOptionalAttributeString("width", obj.Width); + writer.WriteOptionalAttributeString("height", obj.Height); + writer.WriteRequiredAttributeString("refresh", obj.Refresh); + writer.WriteOptionalAttributeString("pixclock", obj.PixClock); + writer.WriteOptionalAttributeString("htotal", obj.HTotal); + writer.WriteOptionalAttributeString("hbend", obj.HBEnd); + writer.WriteOptionalAttributeString("hbstart", obj.HBStart); + writer.WriteOptionalAttributeString("vtotal", obj.VTotal); + writer.WriteOptionalAttributeString("vbend", obj.VBEnd); + writer.WriteOptionalAttributeString("vbstart", obj.VBStart); + + writer.WriteEndElement(); + } + + /// + /// Write a Driver to an XmlTextWriter + /// + /// Driver to write + /// XmlTextReader to write to + private static void WriteDriver(Driver obj, XmlTextWriter writer) + { + writer.WriteStartElement("driver"); + + writer.WriteRequiredAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("color", obj.Color); + writer.WriteOptionalAttributeString("sound", obj.Sound); + writer.WriteOptionalAttributeString("palettesize", obj.PaletteSize); + writer.WriteRequiredAttributeString("emulation", obj.Emulation); + writer.WriteRequiredAttributeString("cocktail", obj.Cocktail); + writer.WriteRequiredAttributeString("savestate", obj.SaveState); + writer.WriteOptionalAttributeString("requiresartwork", obj.RequiresArtwork); + writer.WriteOptionalAttributeString("unofficial", obj.Unofficial); + writer.WriteOptionalAttributeString("nosoundhardware", obj.NoSoundHardware); + writer.WriteOptionalAttributeString("incomplete", obj.Incomplete); + + writer.WriteEndElement(); + } + + /// + /// Write a Extension to an XmlTextWriter + /// + /// Extension to write + /// XmlTextReader to write to + private static void WriteExtension(Extension obj, XmlTextWriter writer) + { + writer.WriteStartElement("extension"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a Feature to an XmlTextWriter + /// + /// Feature to write + /// XmlTextReader to write to + private static void WriteFeature(Feature obj, XmlTextWriter writer) + { + writer.WriteStartElement("feature"); + + writer.WriteRequiredAttributeString("type", obj.Type); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("overall", obj.Overall); + + writer.WriteEndElement(); + } + + /// + /// Write a GameBase to an XmlTextWriter + /// + /// GameBase to write + /// XmlTextReader to write to + private static void WriteGameBase(GameBase obj, XmlTextWriter writer) + { + if (obj is Game) + writer.WriteStartElement("game"); + else if (obj is Machine) + writer.WriteStartElement("machine"); + else + return; + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("sourcefile", obj.SourceFile); + writer.WriteOptionalAttributeString("isbios", obj.IsBios); + writer.WriteOptionalAttributeString("isdevice", obj.IsDevice); + writer.WriteOptionalAttributeString("ismechanical", obj.IsMechanical); + writer.WriteOptionalAttributeString("runnable", obj.Runnable); + writer.WriteOptionalAttributeString("cloneof", obj.CloneOf); + writer.WriteOptionalAttributeString("romof", obj.RomOf); + writer.WriteOptionalAttributeString("sampleof", obj.SampleOf); + + writer.WriteRequiredElementString("description", obj.Description); + writer.WriteOptionalElementString("year", obj.Year); + writer.WriteOptionalElementString("manufacturer", obj.Manufacturer); + writer.WriteOptionalElementString("history", obj.History); + + if (obj.BiosSet is not null && obj.BiosSet.Length > 0) + { + foreach (var biosSet in obj.BiosSet) + { + WriteBiosSet(biosSet, writer); + } + } + + if (obj.Rom is not null && obj.Rom.Length > 0) + { + foreach (var rom in obj.Rom) + { + WriteRom(rom, writer); + } + } + + if (obj.Disk is not null && obj.Disk.Length > 0) + { + foreach (var disk in obj.Disk) + { + WriteDisk(disk, writer); + } + } + + if (obj.DeviceRef is not null && obj.DeviceRef.Length > 0) + { + foreach (var deviceRef in obj.DeviceRef) + { + WriteDeviceRef(deviceRef, writer); + } + } + + if (obj.Sample is not null && obj.Sample.Length > 0) + { + foreach (var sample in obj.Sample) + { + WriteSample(sample, writer); + } + } + + if (obj.Chip is not null && obj.Chip.Length > 0) + { + foreach (var chip in obj.Chip) + { + WriteChip(chip, writer); + } + } + + if (obj.Display is not null && obj.Display.Length > 0) + { + foreach (var display in obj.Display) + { + WriteDisplay(display, writer); + } + } + + if (obj.Video is not null && obj.Video.Length > 0) + { + foreach (var video in obj.Video) + { + WriteVideo(video, writer); + } + } + + if (obj.Sound is not null) + WriteSound(obj.Sound, writer); + + if (obj.Input is not null) + WriteInput(obj.Input, writer); + + if (obj.DipSwitch is not null && obj.DipSwitch.Length > 0) + { + foreach (var dipSwitch in obj.DipSwitch) + { + WriteDipSwitch(dipSwitch, writer); + } + } + + if (obj.Configuration is not null && obj.Configuration.Length > 0) + { + foreach (var configuration in obj.Configuration) + { + WriteConfiguration(configuration, writer); + } + } + + if (obj.Port is not null && obj.Port.Length > 0) + { + foreach (var port in obj.Port) + { + WritePort(port, writer); + } + } + + if (obj.Adjuster is not null && obj.Adjuster.Length > 0) + { + foreach (var adjuster in obj.Adjuster) + { + WriteAdjuster(adjuster, writer); + } + } + + if (obj.Driver is not null) + WriteDriver(obj.Driver, writer); + + if (obj.Feature is not null && obj.Feature.Length > 0) + { + foreach (var feature in obj.Feature) + { + WriteFeature(feature, writer); + } + } + + if (obj.Device is not null && obj.Device.Length > 0) + { + foreach (var device in obj.Device) + { + WriteDevice(device, writer); + } + } + + if (obj.Slot is not null && obj.Slot.Length > 0) + { + foreach (var slot in obj.Slot) + { + WriteSlot(slot, writer); + } + } + + if (obj.SoftwareList is not null && obj.SoftwareList.Length > 0) + { + foreach (var softwareList in obj.SoftwareList) + { + WriteSoftwareList(softwareList, writer); + } + } + + if (obj.RamOption is not null && obj.RamOption.Length > 0) + { + foreach (var ramOption in obj.RamOption) + { + WriteRamOption(ramOption, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Input to an XmlTextWriter + /// + /// Input to write + /// XmlTextReader to write to + private static void WriteInput(Input obj, XmlTextWriter writer) + { + writer.WriteStartElement("input"); + + writer.WriteOptionalAttributeString("service", obj.Service); + writer.WriteOptionalAttributeString("tilt", obj.Tilt); + writer.WriteRequiredAttributeString("players", obj.Players); + writer.WriteOptionalAttributeString("control", obj.ControlAttr); + writer.WriteOptionalAttributeString("buttons", obj.Buttons); + writer.WriteOptionalAttributeString("coins", obj.Coins); + + if (obj.Control is not null && obj.Control.Length > 0) + { + foreach (var control in obj.Control) + { + WriteControl(control, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Instance to an XmlTextWriter + /// + /// Instance to write + /// XmlTextReader to write to + private static void WriteInstance(Instance obj, XmlTextWriter writer) + { + writer.WriteStartElement("instance"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("briefname", obj.BriefName); + + writer.WriteEndElement(); + } + + /// + /// Write a Port to an XmlTextWriter + /// + /// Port to write + /// XmlTextReader to write to + private static void WritePort(Port obj, XmlTextWriter writer) + { + writer.WriteStartElement("port"); + + writer.WriteRequiredAttributeString("tag", obj.Tag); + + if (obj.Analog is not null && obj.Analog.Length > 0) + { + foreach (var analog in obj.Analog) + { + WriteAnalog(analog, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a RamOption to an XmlTextWriter + /// + /// RamOption to write + /// XmlTextReader to write to + private static void WriteRamOption(RamOption obj, XmlTextWriter writer) + { + writer.WriteStartElement("ramoption"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("default", obj.Default); + + if (obj.Content is not null) + writer.WriteValue(obj.Content); + + writer.WriteEndElement(); + } + + /// + /// Write a Rom to an XmlTextWriter + /// + /// Rom to write + /// XmlTextReader to write to + private static void WriteRom(Rom obj, XmlTextWriter writer) + { + writer.WriteStartElement("rom"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("bios", obj.Bios); + writer.WriteRequiredAttributeString("size", obj.Size); + writer.WriteOptionalAttributeString("crc", obj.CRC); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("merge", obj.Merge); + writer.WriteOptionalAttributeString("region", obj.Region); + writer.WriteOptionalAttributeString("offset", obj.Offset); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("optional", obj.Optional); + writer.WriteOptionalAttributeString("dispose", obj.Dispose); + writer.WriteOptionalAttributeString("soundonly", obj.SoundOnly); + + writer.WriteEndElement(); + } + + /// + /// Write a Sample to an XmlTextWriter + /// + /// Sample to write + /// XmlTextReader to write to + private static void WriteSample(Sample obj, XmlTextWriter writer) + { + writer.WriteStartElement("sample"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + writer.WriteEndElement(); + } + + /// + /// Write a Slot to an XmlTextWriter + /// + /// Slot to write + /// XmlTextReader to write to + private static void WriteSlot(Slot obj, XmlTextWriter writer) + { + writer.WriteStartElement("slot"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + if (obj.SlotOption is not null && obj.SlotOption.Length > 0) + { + foreach (var slotOption in obj.SlotOption) + { + WriteSlotOption(slotOption, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a SlotOption to an XmlTextWriter + /// + /// SlotOption to write + /// XmlTextReader to write to + private static void WriteSlotOption(SlotOption obj, XmlTextWriter writer) + { + writer.WriteStartElement("slotoption"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("devname", obj.DevName); + writer.WriteOptionalAttributeString("default", obj.Default); + + writer.WriteEndElement(); + } + + /// + /// Write a SoftwareList to an XmlTextWriter + /// + /// SoftwareList to write + /// XmlTextReader to write to + private static void WriteSoftwareList(Data.Models.Listxml.SoftwareList obj, XmlTextWriter writer) + { + writer.WriteStartElement("softwarelist"); + + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("filter", obj.Filter); + + writer.WriteEndElement(); + } + + /// + /// Write a Sound to an XmlTextWriter + /// + /// Sound to write + /// XmlTextReader to write to + private static void WriteSound(Sound obj, XmlTextWriter writer) + { + writer.WriteStartElement("sound"); + + writer.WriteRequiredAttributeString("channels", obj.Channels); + + writer.WriteEndElement(); + } + + /// + /// Write a Video to an XmlTextWriter + /// + /// Video to write + /// XmlTextReader to write to + private static void WriteVideo(Video obj, XmlTextWriter writer) + { + writer.WriteStartElement("video"); + + writer.WriteRequiredAttributeString("screen", obj.Screen); + writer.WriteRequiredAttributeString("orientation", obj.Orientation); + writer.WriteOptionalAttributeString("width", obj.Width); + writer.WriteOptionalAttributeString("height", obj.Height); + writer.WriteOptionalAttributeString("aspectx", obj.AspectX); + writer.WriteOptionalAttributeString("aspecty", obj.AspectY); + writer.WriteRequiredAttributeString("refresh", obj.Refresh); + + writer.WriteEndElement(); + } + + #endregion } } diff --git a/SabreTools.Serialization.Writers/OfflineList.cs b/SabreTools.Serialization.Writers/OfflineList.cs index 03c8e528..8595fa85 100644 --- a/SabreTools.Serialization.Writers/OfflineList.cs +++ b/SabreTools.Serialization.Writers/OfflineList.cs @@ -1,9 +1,449 @@ +using System.IO; +using System.Text; +using System.Xml; using SabreTools.Data.Models.OfflineList; +using SabreTools.IO.Extensions; +using SabreTools.Text.Extensions; namespace SabreTools.Serialization.Writers { - public class OfflineList : XmlFile + public class OfflineList : BaseBinaryWriter { - // All logic taken care of in the base class + /// + public override Stream? SerializeStream(Dat? obj) + { + // If the metadata file is null + if (obj is null) + return null; + + // Setup the writer and output + var stream = new MemoryStream(); + var writer = new XmlTextWriter(stream, Encoding.UTF8); + writer.Formatting = Formatting.Indented; + + // Write the Dat, if it exists + WriteDat(obj, writer); + writer.Flush(); + + // Return the stream + stream.SeekIfPossible(0, SeekOrigin.Begin); + return stream; + } + + /// + /// Write a Dat to an XmlTextWriter + /// + /// Dat to write + /// XmlTextReader to write to + private static void WriteDat(Dat obj, XmlTextWriter writer) + { + writer.WriteStartElement("dat"); + + // TODO: Fix this schema reading/writing + // writer.WriteOptionalAttributeString("noNamespaceSchemaLocation", obj.NoNamespaceSchemaLocation); + + if (obj.Configuration is not null) + WriteConfiguration(obj.Configuration, writer); + + if (obj.Games is not null) + WriteGames(obj.Games, writer); + + if (obj.GUI is not null) + WriteGUI(obj.GUI, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a CanOpen to an XmlTextWriter + /// + /// CanOpen to write + /// XmlTextReader to write to + private static void WriteCanOpen(CanOpen obj, XmlTextWriter writer) + { + writer.WriteStartElement("canOpen"); + + if (obj.Extension is not null && obj.Extension.Length > 0) + { + foreach (var extension in obj.Extension) + { + writer.WriteOptionalElementString("extension", extension); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Configuration to an XmlTextWriter + /// + /// Configuration to write + /// XmlTextReader to write to + private static void WriteConfiguration(Configuration obj, XmlTextWriter writer) + { + writer.WriteStartElement("configuration"); + + writer.WriteOptionalElementString("datName", obj.DatName); + writer.WriteOptionalElementString("imFolder", obj.ImFolder); + writer.WriteOptionalElementString("datVersion", obj.DatVersion); + writer.WriteOptionalElementString("system", obj.System); + writer.WriteOptionalElementString("screenshotsWidth", obj.ScreenshotsWidth); + writer.WriteOptionalElementString("screenshotsHeight", obj.ScreenshotsHeight); + + if (obj.Infos is not null) + WriteInfos(obj.Infos, writer); + + if (obj.CanOpen is not null) + WriteCanOpen(obj.CanOpen, writer); + + if (obj.NewDat is not null) + WriteNewDat(obj.NewDat, writer); + + if (obj.Search is not null) + WriteSearch(obj.Search, writer); + + writer.WriteOptionalElementString("romTitle", obj.RomTitle); + + writer.WriteEndElement(); + } + + /// + /// Write a DatUrl to an XmlTextWriter + /// + /// DatUrl to write + /// XmlTextReader to write to + private static void WriteDatUrl(DatUrl obj, XmlTextWriter writer) + { + writer.WriteStartElement("datURL"); + + writer.WriteOptionalAttributeString("fileName", obj.FileName); + + if (obj.Content is not null) + writer.WriteRaw(obj.Content); + + writer.WriteEndElement(); + } + + /// + /// Write a FileRomCRC to an XmlTextWriter + /// + /// FileRomCRC to write + /// XmlTextReader to write to + private static void WriteFileRomCRC(FileRomCRC obj, XmlTextWriter writer) + { + writer.WriteStartElement("romCRC"); + + writer.WriteOptionalAttributeString("extension", obj.Extension); + + if (obj.Content is not null) + writer.WriteRaw(obj.Content); + + writer.WriteEndElement(); + } + + /// + /// Write a Files to an XmlTextWriter + /// + /// Files to write + /// XmlTextReader to write to + private static void WriteFiles(Files obj, XmlTextWriter writer) + { + writer.WriteStartElement("files"); + + if (obj.RomCRC is not null && obj.RomCRC.Length > 0) + { + foreach (var extension in obj.RomCRC) + { + WriteFileRomCRC(extension, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Find to an XmlTextWriter + /// + /// Find to write + /// XmlTextReader to write to + private static void WriteFind(Find obj, XmlTextWriter writer) + { + writer.WriteStartElement("find"); + + writer.WriteOptionalAttributeString("operation", obj.Operation); + writer.WriteOptionalAttributeString("value", obj.Value); + + if (obj.Content is not null) + writer.WriteRaw(obj.Content); + + writer.WriteEndElement(); + } + + /// + /// Write a Game to an XmlTextWriter + /// + /// Game to write + /// XmlTextReader to write to + private static void WriteGame(Game obj, XmlTextWriter writer) + { + writer.WriteStartElement("game"); + + writer.WriteOptionalElementString("imageNumber", obj.ImageNumber); + writer.WriteOptionalElementString("releaseNumber", obj.ReleaseNumber); + writer.WriteOptionalElementString("title", obj.Title); + writer.WriteOptionalElementString("saveType", obj.SaveType); + writer.WriteOptionalElementString("romSize", obj.RomSize); + writer.WriteOptionalElementString("publisher", obj.Publisher); + writer.WriteOptionalElementString("location", obj.Location); + writer.WriteOptionalElementString("sourceRom", obj.SourceRom); + writer.WriteOptionalElementString("language", obj.Language); + + if (obj.Files is not null) + WriteFiles(obj.Files, writer); + + writer.WriteOptionalElementString("im1CRC", obj.Im1CRC); + writer.WriteOptionalElementString("im2CRC", obj.Im2CRC); + writer.WriteOptionalElementString("comment", obj.Comment); + writer.WriteOptionalElementString("duplicateID", obj.DuplicateID); + + writer.WriteEndElement(); + } + + /// + /// Write a Games to an XmlTextWriter + /// + /// Games to write + /// XmlTextReader to write to + private static void WriteGames(Games obj, XmlTextWriter writer) + { + writer.WriteStartElement("games"); + + if (obj.Game is not null && obj.Game.Length > 0) + { + foreach (var game in obj.Game) + { + WriteGame(game, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a GUI to an XmlTextWriter + /// + /// GUI to write + /// XmlTextReader to write to + private static void WriteGUI(GUI obj, XmlTextWriter writer) + { + writer.WriteStartElement("gui"); + + if (obj.Images is not null) + WriteImages(obj.Images, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Image to an XmlTextWriter + /// + /// Image to write + /// XmlTextReader to write to + private static void WriteImage(Image obj, XmlTextWriter writer) + { + writer.WriteStartElement("image"); + + writer.WriteOptionalAttributeString("x", obj.X); + writer.WriteOptionalAttributeString("y", obj.Y); + writer.WriteOptionalAttributeString("width", obj.Width); + writer.WriteOptionalAttributeString("height", obj.Height); + + writer.WriteEndElement(); + } + + /// + /// Write a Images to an XmlTextWriter + /// + /// Images to write + /// XmlTextReader to write to + private static void WriteImages(Images obj, XmlTextWriter writer) + { + writer.WriteStartElement("images"); + + writer.WriteOptionalAttributeString("width", obj.Width); + writer.WriteOptionalAttributeString("height", obj.Height); + + if (obj.Image is not null && obj.Image.Length > 0) + { + foreach (var image in obj.Image) + { + WriteImage(image, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a InfoBase to an XmlTextWriter + /// + /// InfoBase to write + /// XmlTextReader to write to + private static void WriteInfoBase(InfoBase obj, XmlTextWriter writer) + { + if (obj is Title) + writer.WriteStartElement("title"); + else if (obj is Location) + writer.WriteStartElement("location"); + else if (obj is Publisher) + writer.WriteStartElement("publisher"); + else if (obj is SourceRom) + writer.WriteStartElement("sourceRom"); + else if (obj is SaveType) + writer.WriteStartElement("saveType"); + else if (obj is RomSize) + writer.WriteStartElement("romSize"); + else if (obj is ReleaseNumber) + writer.WriteStartElement("releaseNumber"); + else if (obj is ImageNumber) + writer.WriteStartElement("imageNumber"); + else if (obj is LanguageNumber) + writer.WriteStartElement("languageNumber"); + else if (obj is Comment) + writer.WriteStartElement("comment"); + else if (obj is RomCRC) + writer.WriteStartElement("romCRC"); + else if (obj is Im1CRC) + writer.WriteStartElement("im1CRC"); + else if (obj is Im2CRC) + writer.WriteStartElement("im2CRC"); + else if (obj is Languages) + writer.WriteStartElement("languages"); + else + return; + + writer.WriteOptionalAttributeString("visible", obj.Visible); + writer.WriteOptionalAttributeString("inNamingOption", obj.InNamingOption); + writer.WriteOptionalAttributeString("default", obj.Default); + + writer.WriteEndElement(); + } + + /// + /// Write a Infos to an XmlTextWriter + /// + /// Infos to write + /// XmlTextReader to write to + private static void WriteInfos(Infos obj, XmlTextWriter writer) + { + writer.WriteStartElement("infos"); + + if (obj.Title is not null) + WriteInfoBase(obj.Title, writer); + + if (obj.Location is not null) + WriteInfoBase(obj.Location, writer); + + if (obj.Publisher is not null) + WriteInfoBase(obj.Publisher, writer); + + if (obj.SourceRom is not null) + WriteInfoBase(obj.SourceRom, writer); + + if (obj.SaveType is not null) + WriteInfoBase(obj.SaveType, writer); + + if (obj.RomSize is not null) + WriteInfoBase(obj.RomSize, writer); + + if (obj.ReleaseNumber is not null) + WriteInfoBase(obj.ReleaseNumber, writer); + + if (obj.ImageNumber is not null) + WriteInfoBase(obj.ImageNumber, writer); + + if (obj.LanguageNumber is not null) + WriteInfoBase(obj.LanguageNumber, writer); + + if (obj.Comment is not null) + WriteInfoBase(obj.Comment, writer); + + if (obj.RomCRC is not null) + WriteInfoBase(obj.RomCRC, writer); + + if (obj.Im1CRC is not null) + WriteInfoBase(obj.Im1CRC, writer); + + if (obj.Im2CRC is not null) + WriteInfoBase(obj.Im2CRC, writer); + + if (obj.Languages is not null) + WriteInfoBase(obj.Languages, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a NewDat to an XmlTextWriter + /// + /// NewDat to write + /// XmlTextReader to write to + private static void WriteNewDat(NewDat obj, XmlTextWriter writer) + { + writer.WriteStartElement("newDat"); + + writer.WriteOptionalElementString("datVersionURL", obj.DatVersionUrl); + + if (obj.DatUrl is not null) + WriteDatUrl(obj.DatUrl, writer); + + writer.WriteOptionalElementString("imURL", obj.ImUrl); + + writer.WriteEndElement(); + } + + /// + /// Write a Search to an XmlTextWriter + /// + /// Search to write + /// XmlTextReader to write to + private static void WriteSearch(Search obj, XmlTextWriter writer) + { + writer.WriteStartElement("search"); + + if (obj.To is not null && obj.To.Length > 0) + { + foreach (var to in obj.To) + { + WriteTo(to, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a To to an XmlTextWriter + /// + /// To to write + /// XmlTextReader to write to + private static void WriteTo(To obj, XmlTextWriter writer) + { + writer.WriteStartElement("to"); + + writer.WriteOptionalAttributeString("value", obj.Value); + writer.WriteOptionalAttributeString("default", obj.Default); + writer.WriteOptionalAttributeString("auto", obj.Auto); + + if (obj.Find is not null && obj.Find.Length > 0) + { + foreach (var find in obj.Find) + { + WriteFind(find, writer); + } + } + + writer.WriteEndElement(); + } } } diff --git a/SabreTools.Serialization.Writers/OpenMSX.cs b/SabreTools.Serialization.Writers/OpenMSX.cs index fadd2aea..81f12d7a 100644 --- a/SabreTools.Serialization.Writers/OpenMSX.cs +++ b/SabreTools.Serialization.Writers/OpenMSX.cs @@ -1,9 +1,13 @@ using System.IO; +using System.Text; +using System.Xml; using SabreTools.Data.Models.OpenMSX; +using SabreTools.IO.Extensions; +using SabreTools.Text.Extensions; namespace SabreTools.Serialization.Writers { - public class OpenMSX : XmlFile + public class OpenMSX : BaseBinaryWriter { #region Constants @@ -29,28 +33,136 @@ namespace SabreTools.Serialization.Writers #endregion - #region IByteWriter - - /// - public override byte[]? SerializeArray(SoftwareDb? obj) - => SerializeArray(obj, DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSysId); - - #endregion - - #region IFileWriter - - /// - public override bool SerializeFile(SoftwareDb? obj, string? path) - => Serialize(obj, path, DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSysId); - - #endregion - - #region IStreamWriter - - /// + /// public override Stream? SerializeStream(SoftwareDb? obj) - => Serialize(obj, DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSysId); + { + // If the metadata file is null + if (obj is null) + return null; - #endregion + // Setup the writer and output + var stream = new MemoryStream(); + var writer = new XmlTextWriter(stream, Encoding.UTF8); + writer.Formatting = Formatting.Indented; + + // Write document type + writer.WriteDocType(DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSubset); + + // Write the SoftwareDb, if it exists + WriteSoftwareDb(obj, writer); + writer.Flush(); + + // Return the stream + stream.SeekIfPossible(0, SeekOrigin.Begin); + return stream; + } + + /// + /// Write a SoftwareDb to an XmlTextWriter + /// + /// SoftwareDb to write + /// XmlTextReader to write to + private static void WriteSoftwareDb(SoftwareDb obj, XmlTextWriter writer) + { + writer.WriteStartElement("softwaredb"); + + writer.WriteOptionalAttributeString("timestamp", obj.Timestamp); + + if (obj.Software is not null && obj.Software.Length > 0) + { + foreach (var software in obj.Software) + { + WriteSoftware(software, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Dump to an XmlTextWriter + /// + /// Dump to write + /// XmlTextReader to write to + private static void WriteDump(Dump obj, XmlTextWriter writer) + { + writer.WriteStartElement("dump"); + + if (obj.Original is not null) + WriteOriginal(obj.Original, writer); + + if (obj.Rom is not null) + WriteRomBase(obj.Rom, writer); + + writer.WriteEndElement(); + } + + /// + /// Write a Original to an XmlTextWriter + /// + /// Original to write + /// XmlTextReader to write to + private static void WriteOriginal(Original obj, XmlTextWriter writer) + { + writer.WriteStartElement("original"); + + writer.WriteOptionalAttributeString("value", obj.Value); + + if (obj.Content is not null) + writer.WriteRaw(obj.Content); + + writer.WriteEndElement(); + } + + /// + /// Write a RomBase to an XmlTextWriter + /// + /// RomBase to write + /// XmlTextReader to write to + private static void WriteRomBase(RomBase obj, XmlTextWriter writer) + { + if (obj is MegaRom) + writer.WriteStartElement("megarom"); + else if (obj is Rom) + writer.WriteStartElement("rom"); + else if (obj is SCCPlusCart) + writer.WriteStartElement("sccpluscart"); + else + return; + + writer.WriteOptionalElementString("start", obj.Start); + writer.WriteOptionalElementString("type", obj.Type); + writer.WriteOptionalElementString("hash", obj.Hash); + writer.WriteOptionalElementString("remark", obj.Remark); + + writer.WriteEndElement(); + } + + /// + /// Write a Software to an XmlTextWriter + /// + /// Software to write + /// XmlTextReader to write to + private static void WriteSoftware(Software obj, XmlTextWriter writer) + { + writer.WriteStartElement("software"); + + writer.WriteRequiredElementString("title", obj.Title); + writer.WriteOptionalElementString("genmsxid", obj.GenMSXID); + writer.WriteRequiredElementString("system", obj.System); + writer.WriteRequiredElementString("company", obj.Company); + writer.WriteRequiredElementString("year", obj.Year); + writer.WriteRequiredElementString("country", obj.Country); + + if (obj.Dump is not null && obj.Dump.Length > 0) + { + foreach (var dump in obj.Dump) + { + WriteDump(dump, writer); + } + } + + writer.WriteEndElement(); + } } } diff --git a/SabreTools.Serialization.Writers/SoftwareList.cs b/SabreTools.Serialization.Writers/SoftwareList.cs index 8006bf2c..dbf2ef9f 100644 --- a/SabreTools.Serialization.Writers/SoftwareList.cs +++ b/SabreTools.Serialization.Writers/SoftwareList.cs @@ -1,8 +1,13 @@ using System.IO; +using System.Text; +using System.Xml; +using SabreTools.Data.Models.SoftwareList; +using SabreTools.IO.Extensions; +using SabreTools.Text.Extensions; namespace SabreTools.Serialization.Writers { - public class SoftwareList : XmlFile + public class SoftwareList : BaseBinaryWriter { #region Constants @@ -28,19 +33,320 @@ namespace SabreTools.Serialization.Writers #endregion - #region IFileWriter - - /// - public override bool SerializeFile(Data.Models.SoftwareList.SoftwareList? obj, string? path) - => Serialize(obj, path, DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSysId); - - #endregion - - #region IStreamWriter - - /// + /// public override Stream? SerializeStream(Data.Models.SoftwareList.SoftwareList? obj) - => Serialize(obj, DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSysId); + { + // If the metadata file is null + if (obj is null) + return null; + + // Setup the writer and output + var stream = new MemoryStream(); + var writer = new XmlTextWriter(stream, Encoding.UTF8); + writer.Formatting = Formatting.Indented; + + // Write document type + writer.WriteDocType(DocTypeName, DocTypePubId, DocTypeSysId, DocTypeSubset); + + // Write the SoftwareDb, if it exists + WriteSoftwareList(obj, writer); + writer.Flush(); + + // Return the stream + stream.SeekIfPossible(0, SeekOrigin.Begin); + return stream; + } + + /// + /// Write a SoftwareList to an XmlTextWriter + /// + /// SoftwareList to write + /// XmlTextReader to write to + private static void WriteSoftwareList(Data.Models.SoftwareList.SoftwareList obj, XmlTextWriter writer) + { + writer.WriteStartElement("softwarelist"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("description", obj.Description); + + writer.WriteOptionalElementString("notes", obj.Notes); + + if (obj.Software is not null && obj.Software.Length > 0) + { + foreach (var software in obj.Software) + { + WriteSoftware(software, writer); + } + } + + writer.WriteEndElement(); + } + + #region Items + + /// + /// Write a DataArea to an XmlTextWriter + /// + /// DataArea to write + /// XmlTextReader to write to + private static void WriteDataArea(DataArea obj, XmlTextWriter writer) + { + writer.WriteStartElement("dataarea"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("size", obj.Size); + writer.WriteOptionalAttributeString("width", obj.Width); + writer.WriteOptionalAttributeString("endianness", obj.Endianness); + + if (obj.Rom is not null && obj.Rom.Length > 0) + { + foreach (var rom in obj.Rom) + { + WriteRom(rom, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a DipSwitch to an XmlTextWriter + /// + /// DipSwitch to write + /// XmlTextReader to write to + private static void WriteDipSwitch(DipSwitch obj, XmlTextWriter writer) + { + writer.WriteStartElement("dipswitch"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("tag", obj.Tag); + writer.WriteOptionalAttributeString("mask", obj.Mask); + + if (obj.DipValue is not null && obj.DipValue.Length > 0) + { + foreach (var dipValue in obj.DipValue) + { + WriteDipValue(dipValue, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a DipValue to an XmlTextWriter + /// + /// DipValue to write + /// XmlTextReader to write to + private static void WriteDipValue(DipValue obj, XmlTextWriter writer) + { + writer.WriteStartElement("dipvalue"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("value", obj.Value); + writer.WriteOptionalAttributeString("default", obj.Default); + + writer.WriteEndElement(); + } + + /// + /// Write a Disk to an XmlTextWriter + /// + /// Disk to write + /// XmlTextReader to write to + private static void WriteDisk(Disk obj, XmlTextWriter writer) + { + writer.WriteStartElement("disk"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("md5", obj.MD5); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("writable", obj.Writeable); + + writer.WriteEndElement(); + } + + /// + /// Write a DiskArea to an XmlTextWriter + /// + /// DiskArea to write + /// XmlTextReader to write to + private static void WriteDiskArea(DiskArea obj, XmlTextWriter writer) + { + writer.WriteStartElement("diskarea"); + + writer.WriteRequiredAttributeString("name", obj.Name); + + if (obj.Disk is not null && obj.Disk.Length > 0) + { + foreach (var disk in obj.Disk) + { + WriteDisk(disk, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Feature to an XmlTextWriter + /// + /// Feature to write + /// XmlTextReader to write to + private static void WriteFeature(Feature obj, XmlTextWriter writer) + { + writer.WriteStartElement("feature"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("value", obj.Value); + + writer.WriteEndElement(); + } + + /// + /// Write a Info to an XmlTextWriter + /// + /// Info to write + /// XmlTextReader to write to + private static void WriteInfo(Info obj, XmlTextWriter writer) + { + writer.WriteStartElement("info"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("value", obj.Value); + + writer.WriteEndElement(); + } + + /// + /// Write a Part to an XmlTextWriter + /// + /// Part to write + /// XmlTextReader to write to + private static void WritePart(Part obj, XmlTextWriter writer) + { + writer.WriteStartElement("part"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteRequiredAttributeString("interface", obj.Interface); + + if (obj.Feature is not null && obj.Feature.Length > 0) + { + foreach (var feature in obj.Feature) + { + WriteFeature(feature, writer); + } + } + + if (obj.DataArea is not null && obj.DataArea.Length > 0) + { + foreach (var dataArea in obj.DataArea) + { + WriteDataArea(dataArea, writer); + } + } + + if (obj.DiskArea is not null && obj.DiskArea.Length > 0) + { + foreach (var diskArea in obj.DiskArea) + { + WriteDiskArea(diskArea, writer); + } + } + + if (obj.DipSwitch is not null && obj.DipSwitch.Length > 0) + { + foreach (var dipSwitch in obj.DipSwitch) + { + WriteDipSwitch(dipSwitch, writer); + } + } + + writer.WriteEndElement(); + } + + /// + /// Write a Rom to an XmlTextWriter + /// + /// Rom to write + /// XmlTextReader to write to + private static void WriteRom(Rom obj, XmlTextWriter writer) + { + writer.WriteStartElement("rom"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("size", obj.Size); + writer.WriteOptionalAttributeString("length", obj.Length); + writer.WriteOptionalAttributeString("crc", obj.CRC); + writer.WriteOptionalAttributeString("sha1", obj.SHA1); + writer.WriteOptionalAttributeString("offset", obj.Offset); + writer.WriteOptionalAttributeString("value", obj.Value); + writer.WriteOptionalAttributeString("status", obj.Status); + writer.WriteOptionalAttributeString("loadflag", obj.LoadFlag); + + writer.WriteEndElement(); + } + + /// + /// Write a SharedFeat to an XmlTextWriter + /// + /// SharedFeat to write + /// XmlTextReader to write to + private static void WriteSharedFeat(SharedFeat obj, XmlTextWriter writer) + { + writer.WriteStartElement("sharedfeat"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("value", obj.Value); + + writer.WriteEndElement(); + } + + /// + /// Write a Software to an XmlTextWriter + /// + /// Software to write + /// XmlTextReader to write to + private static void WriteSoftware(Software obj, XmlTextWriter writer) + { + writer.WriteStartElement("software"); + + writer.WriteRequiredAttributeString("name", obj.Name); + writer.WriteOptionalAttributeString("cloneof", obj.CloneOf); + writer.WriteOptionalAttributeString("supported", obj.Supported); + + writer.WriteRequiredElementString("description", obj.Description); + writer.WriteRequiredElementString("year", obj.Year); + writer.WriteRequiredElementString("publisher", obj.Publisher); + writer.WriteOptionalElementString("notes", obj.Notes); + + if (obj.Info is not null && obj.Info.Length > 0) + { + foreach (var info in obj.Info) + { + WriteInfo(info, writer); + } + } + + if (obj.SharedFeat is not null && obj.SharedFeat.Length > 0) + { + foreach (var sharedFeat in obj.SharedFeat) + { + WriteSharedFeat(sharedFeat, writer); + } + } + + if (obj.Part is not null && obj.Part.Length > 0) + { + foreach (var part in obj.Part) + { + WritePart(part, writer); + } + } + + writer.WriteEndElement(); + } #endregion } diff --git a/SabreTools.Serialization.Writers/XmlFile.cs b/SabreTools.Serialization.Writers/XmlFile.cs deleted file mode 100644 index fa7fa37e..00000000 --- a/SabreTools.Serialization.Writers/XmlFile.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System.IO; -using System.Text; -using System.Xml; -using System.Xml.Serialization; -using SabreTools.IO.Extensions; - -namespace SabreTools.Serialization.Writers -{ - /// - /// Base class for other XML serializers - /// - /// - public class XmlFile : BaseBinaryWriter - { - #region IByteWriter - - /// - public override byte[]? SerializeArray(T? obj) - => SerializeArray(obj, null, null, null, null); - - /// - /// Serializes the defined type to a byte array - /// - /// Data to serialize - /// Optional DOCTYPE name - /// Optional DOCTYPE pubid - /// Optional DOCTYPE sysid - /// Optional DOCTYPE name - /// Byte array containing serialized data on success, null otherwise - public byte[]? SerializeArray(T? obj, string? name = null, string? pubid = null, string? sysid = null, string? subset = null) - { - using var stream = Serialize(obj, name, pubid, sysid, subset); - if (stream is null) - return null; - - byte[] bytes = new byte[stream.Length]; - int read = stream.Read(bytes, 0, bytes.Length); - return bytes; - } - - #endregion - - #region IFileWriter - - /// - public override bool SerializeFile(T? obj, string? path) - => Serialize(obj, path, null, null, null, null); - - /// - /// Serializes the defined type to an XML file - /// - /// Data to serialize - /// Path to the file to serialize to - /// Optional DOCTYPE name - /// Optional DOCTYPE pubid - /// Optional DOCTYPE sysid - /// Optional DOCTYPE name - /// True on successful serialization, false otherwise - public bool Serialize(T? obj, string? path, string? name = null, string? pubid = null, string? sysid = null, string? subset = null) - { - if (string.IsNullOrEmpty(path)) - return false; - - using var stream = Serialize(obj, name, pubid, sysid, subset); - if (stream is null) - return false; - - using var fs = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.None); - stream.BlockCopy(fs); - fs.Flush(); - - return true; - } - - #endregion - - #region IStreamWriter - - /// - public override Stream? SerializeStream(T? obj) - => Serialize(obj, null, null, null, null); - - /// - /// Serializes the defined type to a stream - /// - /// Data to serialize - /// Optional DOCTYPE name - /// Optional DOCTYPE pubid - /// Optional DOCTYPE sysid - /// Optional DOCTYPE name - /// Stream containing serialized data on success, null otherwise - public Stream? Serialize(T? obj, string? name = null, string? pubid = null, string? sysid = null, string? subset = null) - { - // If the object is null - if (obj is null) - return null; - - // Setup the serializer and the writer - var serializer = new XmlSerializer(typeof(T)); - var namespaces = new XmlSerializerNamespaces(); - namespaces.Add("", ""); - - var settings = new XmlWriterSettings - { - CheckCharacters = false, - Encoding = Encoding.UTF8, - Indent = true, - IndentChars = "\t", -#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER - NamespaceHandling = NamespaceHandling.OmitDuplicates, -#endif - NewLineChars = "\n", - }; - var stream = new MemoryStream(); - var streamWriter = new StreamWriter(stream); - var xmlWriter = XmlWriter.Create(streamWriter, settings); - - // Write the doctype if provided - if (!string.IsNullOrEmpty(name)) - xmlWriter.WriteDocType(name, pubid, sysid, subset); - - // Perform the deserialization and return - serializer.Serialize(xmlWriter, obj, namespaces); - stream.SeekIfPossible(0, SeekOrigin.Begin); - return stream; - } - - #endregion - } -}