From d9bf16deefbcd82552fdc341ed2c743c43156480 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Fri, 18 Sep 2026 10:15:54 -0400 Subject: [PATCH] OpenMSX has changed a bit --- SabreTools.Data.Models/Metadata/Rom.cs | 4 ++ SabreTools.Data.Models/OpenMSX/RomBase.cs | 22 ++++++++--- SabreTools.Data.Models/OpenMSX/Software.cs | 39 +++++++++++++++++-- .../DatFileTests.FromMetadata.cs | 2 + .../DatFileTests.ToMetadata.cs | 1 + .../Formats/OpenMSX.cs | 21 ++++++---- SabreTools.Metadata.DatItems/Formats/Rom.cs | 6 +++ .../FilterObjectTests.cs | 2 + SabreTools.Metadata.Filter/Constants.cs | 1 + SabreTools.Metadata.Filter/FilterObject.cs | 3 ++ .../OpenMSXTests.cs | 33 ++++++++++++++-- .../OpenMSX.Deserializer.cs | 21 ++++++---- .../OpenMSX.Serializer.cs | 8 +++- .../OpenMSXTests.cs | 33 ++++++++++++++-- SabreTools.Serialization.Readers/OpenMSX.cs | 36 ++++++++++++++--- SabreTools.Serialization.Writers/OpenMSX.cs | 25 ++++++++---- 16 files changed, 210 insertions(+), 47 deletions(-) diff --git a/SabreTools.Data.Models/Metadata/Rom.cs b/SabreTools.Data.Models/Metadata/Rom.cs index d1993916..53295fc2 100644 --- a/SabreTools.Data.Models/Metadata/Rom.cs +++ b/SabreTools.Data.Models/Metadata/Rom.cs @@ -192,6 +192,9 @@ namespace SabreTools.Data.Models.Metadata /// (baddump|nodump|good|verified) "good" public ItemStatus? Status { get; set; } + /// Possibly enum; OpenMSX.RomBase + public string? StatusMisc { get; set; } + /// ArchiveDotOrg.File public string? Summation { get; set; } @@ -353,6 +356,7 @@ namespace SabreTools.Data.Models.Metadata obj.SpamSum = SpamSum; obj.Start = Start; obj.Status = Status; + obj.StatusMisc = StatusMisc; obj.Summation = Summation; obj.TesseractOCR = TesseractOCR; obj.TesseractOCRConverted = TesseractOCRConverted; diff --git a/SabreTools.Data.Models/OpenMSX/RomBase.cs b/SabreTools.Data.Models/OpenMSX/RomBase.cs index feff7c76..51254b78 100644 --- a/SabreTools.Data.Models/OpenMSX/RomBase.cs +++ b/SabreTools.Data.Models/OpenMSX/RomBase.cs @@ -8,17 +8,29 @@ namespace SabreTools.Data.Models.OpenMSX /// public abstract class RomBase { - [XmlElement("start")] - public string? Start { get; set; } + /// + /// "hash" in older versions, "sha1" in newer versions + /// + [XmlElement("hash")] + [XmlElement("sha1")] + public string? SHA1 { get; set; } [XmlElement("type")] public string? Type { get; set; } - /// SHA-1 hash - [XmlElement("hash")] - public string? Hash { get; set; } + /// + /// Only present in newer versions + /// + [XmlElement("status")] + public string? Status { get; set; } [XmlElement("remark")] public string? Remark { get; set; } + + /// + /// Only present in older versions + /// + [XmlElement("start")] + public string? Start { get; set; } } } diff --git a/SabreTools.Data.Models/OpenMSX/Software.cs b/SabreTools.Data.Models/OpenMSX/Software.cs index b760f8e6..30f9a977 100644 --- a/SabreTools.Data.Models/OpenMSX/Software.cs +++ b/SabreTools.Data.Models/OpenMSX/Software.cs @@ -6,30 +6,63 @@ namespace SabreTools.Data.Models.OpenMSX [XmlRoot("software")] public class Software { + /// + /// Element in older versions and DTD, attribute in newer versions + /// [Required] + [XmlAttribute("title")] [XmlElement("title")] public string? Title { get; set; } - [XmlElement("genmsxid")] - public string? GenMSXID { get; set; } - + /// + /// Element in older versions and DTD, attribute in newer versions + /// [Required] + [XmlAttribute("system")] [XmlElement("system")] public string? System { get; set; } + /// + /// Element in older versions and DTD, attribute in newer versions + /// [Required] + [XmlAttribute("company")] [XmlElement("company")] public string? Company { get; set; } + /// + /// Element in older versions and DTD, attribute in newer versions + /// [Required] + [XmlAttribute("year")] [XmlElement("year")] public string? Year { get; set; } + /// + /// Element in older versions and DTD, attribute in newer versions + /// [Required] + [XmlAttribute("country")] [XmlElement("country")] public string? Country { get; set; } + /// + /// Element in older versions and DTD, attribute in newer versions + /// + [XmlAttribute("genmsxid")] + [XmlElement("genmsxid")] + public string? GenMSXID { get; set; } + + /// + /// Present in older versions + /// [XmlElement("dump")] public Dump[]? Dump { get; set; } + + /// + /// Present in newer versions + /// + [XmlElement("rom")] + public RomBase[]? Rom { get; set; } } } diff --git a/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs b/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs index f31ab053..8f80ac8e 100644 --- a/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs +++ b/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs @@ -839,6 +839,7 @@ namespace SabreTools.Metadata.DatFiles.Test SpamSum = HashType.SpamSum.ZeroString, Start = "start", Status = Data.Models.Metadata.ItemStatus.Good, + StatusMisc = "status", Summation = "summation", TesseractOCR = "ocr", TesseractOCRConverted = "ocr_converted", @@ -1516,6 +1517,7 @@ namespace SabreTools.Metadata.DatFiles.Test Assert.Equal(HashType.SpamSum.ZeroString, rom.SpamSum); Assert.Equal("start", rom.Start); Assert.Equal(Data.Models.Metadata.ItemStatus.Good, rom.Status); + Assert.Equal("status", rom.StatusMisc); Assert.Equal("summation", rom.Summation); Assert.Equal("ocr", rom.TesseractOCR); Assert.Equal("ocr_converted", rom.TesseractOCRConverted); diff --git a/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs b/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs index 8a99997e..512bb79c 100644 --- a/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs +++ b/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs @@ -1066,6 +1066,7 @@ namespace SabreTools.Metadata.DatFiles.Test Assert.Equal(HashType.SpamSum.ZeroString, rom.SpamSum); Assert.Equal("start", rom.Start); Assert.Equal(Data.Models.Metadata.ItemStatus.Good, rom.Status); + Assert.Equal("status", rom.StatusMisc); Assert.Equal("summation", rom.Summation); Assert.Equal("ocr", rom.TesseractOCR); Assert.Equal("ocr_converted", rom.TesseractOCRConverted); diff --git a/SabreTools.Metadata.DatFiles/Formats/OpenMSX.cs b/SabreTools.Metadata.DatFiles/Formats/OpenMSX.cs index 04b72f91..a9f91924 100644 --- a/SabreTools.Metadata.DatFiles/Formats/OpenMSX.cs +++ b/SabreTools.Metadata.DatFiles/Formats/OpenMSX.cs @@ -29,17 +29,22 @@ namespace SabreTools.Metadata.DatFiles.Formats "; #endregion diff --git a/SabreTools.Metadata.DatItems/Formats/Rom.cs b/SabreTools.Metadata.DatItems/Formats/Rom.cs index be603944..dda41996 100644 --- a/SabreTools.Metadata.DatItems/Formats/Rom.cs +++ b/SabreTools.Metadata.DatItems/Formats/Rom.cs @@ -442,6 +442,12 @@ namespace SabreTools.Metadata.DatItems.Formats set => _internal.Status = value; } + public string? StatusMisc + { + get => _internal.StatusMisc; + set => _internal.StatusMisc = value; + } + public string? Summation { get => _internal.Summation; diff --git a/SabreTools.Metadata.Filter.Test/FilterObjectTests.cs b/SabreTools.Metadata.Filter.Test/FilterObjectTests.cs index f98b108d..be755509 100644 --- a/SabreTools.Metadata.Filter.Test/FilterObjectTests.cs +++ b/SabreTools.Metadata.Filter.Test/FilterObjectTests.cs @@ -1661,6 +1661,7 @@ namespace SabreTools.Metadata.Filter.Test [InlineData("rom.spamsum", "3::")] [InlineData("rom.start", "start")] [InlineData("rom.status", "good")] + [InlineData("rom.status_misc", "status")] [InlineData("rom.summation", "summation")] [InlineData("rom.ocr", "ocr")] [InlineData("rom.tesseractocr", "ocr")] @@ -1785,6 +1786,7 @@ namespace SabreTools.Metadata.Filter.Test SpamSum = HashType.SpamSum.ZeroString, Start = "start", Status = ItemStatus.Good, + StatusMisc = "status", Summation = "summation", TesseractOCR = "ocr", TesseractOCRConverted = "ocr_converted", diff --git a/SabreTools.Metadata.Filter/Constants.cs b/SabreTools.Metadata.Filter/Constants.cs index 7a864d15..b3e9910b 100644 --- a/SabreTools.Metadata.Filter/Constants.cs +++ b/SabreTools.Metadata.Filter/Constants.cs @@ -625,6 +625,7 @@ namespace SabreTools.Metadata.Filter "spamsum", "start", "status", + "status_misc", "summation", "tesseractocr", "tesseractocrconverted", diff --git a/SabreTools.Metadata.Filter/FilterObject.cs b/SabreTools.Metadata.Filter/FilterObject.cs index 5571030f..86d1d59d 100644 --- a/SabreTools.Metadata.Filter/FilterObject.cs +++ b/SabreTools.Metadata.Filter/FilterObject.cs @@ -2099,6 +2099,9 @@ namespace SabreTools.Metadata.Filter case "status": checkValue = obj.Status?.AsStringValue(); return true; + case "status_misc": + checkValue = obj.StatusMisc; + return true; case "summation": checkValue = obj.Summation; return true; diff --git a/SabreTools.Serialization.CrossModel.Test/OpenMSXTests.cs b/SabreTools.Serialization.CrossModel.Test/OpenMSXTests.cs index 99abe6e8..d6cd3d0d 100644 --- a/SabreTools.Serialization.CrossModel.Test/OpenMSXTests.cs +++ b/SabreTools.Serialization.CrossModel.Test/OpenMSXTests.cs @@ -40,11 +40,19 @@ namespace SabreTools.Serialization.CrossModel.Test Content = "content", }; + var standalone_rom = new Data.Models.OpenMSX.Rom + { + SHA1 = "sha1", + Type = "type", + Status = "status", + Remark = "remark", + }; + var rom = new Data.Models.OpenMSX.Rom { Start = "start", Type = "type", - Hash = "hash", + SHA1 = "hash", Remark = "remark", }; @@ -59,7 +67,7 @@ namespace SabreTools.Serialization.CrossModel.Test { Start = "start", Type = "type", - Hash = "hash", + SHA1 = "hash", Remark = "remark", }; @@ -74,7 +82,7 @@ namespace SabreTools.Serialization.CrossModel.Test { Start = "start", Type = "type", - Hash = "hash", + SHA1 = "hash", Remark = "remark", }; @@ -94,6 +102,7 @@ namespace SabreTools.Serialization.CrossModel.Test Year = "year", Country = "country", Dump = [dump_rom, dump_megarom, dump_sccpluscart], + Rom = [standalone_rom], }; return new Data.Models.OpenMSX.SoftwareDb @@ -122,6 +131,10 @@ namespace SabreTools.Serialization.CrossModel.Test { Validate(dump); } + + Assert.NotNull(software.Rom); + var rom = Assert.Single(software.Rom); + ValidateStandalone(rom); } /// @@ -154,7 +167,19 @@ namespace SabreTools.Serialization.CrossModel.Test Assert.NotNull(rombase); Assert.Equal("start", rombase.Start); Assert.Equal("type", rombase.Type); - Assert.Equal("hash", rombase.Hash); + Assert.Equal("hash", rombase.SHA1); + Assert.Equal("remark", rombase.Remark); + } + + /// + /// Validate a RomBase + /// + private static void ValidateStandalone(Data.Models.OpenMSX.RomBase? rombase) + { + Assert.NotNull(rombase); + Assert.Equal("sha1", rombase.SHA1); + Assert.Equal("type", rombase.Type); + Assert.Equal("status", rombase.Status); Assert.Equal("remark", rombase.Remark); } } diff --git a/SabreTools.Serialization.CrossModel/OpenMSX.Deserializer.cs b/SabreTools.Serialization.CrossModel/OpenMSX.Deserializer.cs index 26ccc553..3317fe89 100644 --- a/SabreTools.Serialization.CrossModel/OpenMSX.Deserializer.cs +++ b/SabreTools.Serialization.CrossModel/OpenMSX.Deserializer.cs @@ -41,17 +41,21 @@ namespace SabreTools.Serialization.CrossModel var game = new Software { Title = item.Name, - GenMSXID = item.GenMSXID, System = item.System, Company = item.Company, Year = item.Year, Country = item.Country, + GenMSXID = item.GenMSXID, }; var dumps = item.Dump; if (dumps is not null && dumps.Length > 0) game.Dump = Array.ConvertAll(dumps, ConvertFromInternalModel); + var roms = item.Rom; + if (roms is not null && roms.Length > 0) + game.Rom = Array.ConvertAll(roms, ConvertRomFromInternalModel); + return game; } @@ -90,10 +94,11 @@ namespace SabreTools.Serialization.CrossModel { var megaRom = new MegaRom { - Start = item.Start, + SHA1 = item.SHA1, Type = item.OpenMSXType, - Hash = item.SHA1, + Status = item.StatusMisc, Remark = item.Remark, + Start = item.Start, }; return megaRom; } @@ -118,10 +123,11 @@ namespace SabreTools.Serialization.CrossModel { var rom = new Rom { - Start = item.Start, + SHA1 = item.SHA1, Type = item.OpenMSXType, - Hash = item.SHA1, + Status = item.StatusMisc, Remark = item.Remark, + Start = item.Start, }; return rom; } @@ -133,10 +139,11 @@ namespace SabreTools.Serialization.CrossModel { var sccPlusCart = new SCCPlusCart { - Start = item.Start, + SHA1 = item.SHA1, Type = item.OpenMSXType, - Hash = item.SHA1, + Status = item.StatusMisc, Remark = item.Remark, + Start = item.Start, }; return sccPlusCart; } diff --git a/SabreTools.Serialization.CrossModel/OpenMSX.Serializer.cs b/SabreTools.Serialization.CrossModel/OpenMSX.Serializer.cs index 1575fcf4..751238b9 100644 --- a/SabreTools.Serialization.CrossModel/OpenMSX.Serializer.cs +++ b/SabreTools.Serialization.CrossModel/OpenMSX.Serializer.cs @@ -52,6 +52,9 @@ namespace SabreTools.Serialization.CrossModel if (item.Dump is not null && item.Dump.Length > 0) machine.Dump = Array.ConvertAll(item.Dump, ConvertToInternalModel); + if (item.Rom is not null && item.Rom.Length > 0) + machine.Rom = Array.ConvertAll(item.Rom, ConvertToInternalModel); + return machine; } @@ -112,10 +115,11 @@ namespace SabreTools.Serialization.CrossModel { var rom = new Data.Models.Metadata.Rom { - Start = item.Start, + SHA1 = item.SHA1, OpenMSXType = item.Type, - SHA1 = item.Hash, + StatusMisc = item.Status, Remark = item.Remark, + Start = item.Start, }; return rom; } diff --git a/SabreTools.Serialization.Readers.Test/OpenMSXTests.cs b/SabreTools.Serialization.Readers.Test/OpenMSXTests.cs index 704e6a75..2924b0e5 100644 --- a/SabreTools.Serialization.Readers.Test/OpenMSXTests.cs +++ b/SabreTools.Serialization.Readers.Test/OpenMSXTests.cs @@ -106,11 +106,19 @@ namespace SabreTools.Serialization.Readers.Test Content = "content", }; + var standalone_rom = new Data.Models.OpenMSX.Rom + { + SHA1 = "sha1", + Type = "type", + Status = "status", + Remark = "remark", + }; + var rom = new Data.Models.OpenMSX.Rom { Start = "start", Type = "type", - Hash = "hash", + SHA1 = "hash", Remark = "remark", }; @@ -125,7 +133,7 @@ namespace SabreTools.Serialization.Readers.Test { Start = "start", Type = "type", - Hash = "hash", + SHA1 = "hash", Remark = "remark", }; @@ -140,7 +148,7 @@ namespace SabreTools.Serialization.Readers.Test { Start = "start", Type = "type", - Hash = "hash", + SHA1 = "hash", Remark = "remark", }; @@ -160,6 +168,7 @@ namespace SabreTools.Serialization.Readers.Test Year = "year", Country = "country", Dump = [dump_rom, dump_megarom, dump_sccpluscart], + Rom = [standalone_rom], }; return new Data.Models.OpenMSX.SoftwareDb @@ -188,6 +197,10 @@ namespace SabreTools.Serialization.Readers.Test { Validate(dump); } + + Assert.NotNull(software.Rom); + var rom = Assert.Single(software.Rom); + ValidateStandalone(rom); } /// @@ -220,7 +233,19 @@ namespace SabreTools.Serialization.Readers.Test Assert.NotNull(rombase); Assert.Equal("start", rombase.Start); Assert.Equal("type", rombase.Type); - Assert.Equal("hash", rombase.Hash); + Assert.Equal("hash", rombase.SHA1); + Assert.Equal("remark", rombase.Remark); + } + + /// + /// Validate a RomBase + /// + private static void ValidateStandalone(Data.Models.OpenMSX.RomBase? rombase) + { + Assert.NotNull(rombase); + Assert.Equal("sha1", rombase.SHA1); + Assert.Equal("type", rombase.Type); + Assert.Equal("status", rombase.Status); Assert.Equal("remark", rombase.Remark); } } diff --git a/SabreTools.Serialization.Readers/OpenMSX.cs b/SabreTools.Serialization.Readers/OpenMSX.cs index a7800244..51fbb345 100644 --- a/SabreTools.Serialization.Readers/OpenMSX.cs +++ b/SabreTools.Serialization.Readers/OpenMSX.cs @@ -253,11 +253,12 @@ namespace SabreTools.Serialization.Readers switch (reader.Name) { - case "start": - if (obj.Start is not null && Debug) + case "hash": + case "sha1": + if (obj.SHA1 is not null && Debug) Console.WriteLine($"'{reader.Name}' element already found, overwriting"); - obj.Start = reader.ReadElementContentAsString(); + obj.SHA1 = reader.ReadElementContentAsString(); break; case "type": if (obj.Type is not null && Debug) @@ -265,11 +266,11 @@ namespace SabreTools.Serialization.Readers obj.Type = reader.ReadElementContentAsString(); break; - case "hash": - if (obj.Hash is not null && Debug) + case "status": + if (obj.Status is not null && Debug) Console.WriteLine($"'{reader.Name}' element already found, overwriting"); - obj.Hash = reader.ReadElementContentAsString(); + obj.Status = reader.ReadElementContentAsString(); break; case "remark": if (obj.Remark is not null && Debug) @@ -277,6 +278,12 @@ namespace SabreTools.Serialization.Readers obj.Remark = reader.ReadElementContentAsString(); break; + case "start": + if (obj.Start is not null && Debug) + Console.WriteLine($"'{reader.Name}' element already found, overwriting"); + + obj.Start = reader.ReadElementContentAsString(); + break; default: if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); @@ -297,11 +304,19 @@ namespace SabreTools.Serialization.Readers { var obj = new Software(); + obj.Title = reader.GetAttribute("title"); + obj.System = reader.GetAttribute("system"); + obj.Company = reader.GetAttribute("company"); + obj.Year = reader.GetAttribute("year"); + obj.Country = reader.GetAttribute("country"); + obj.GenMSXID = reader.GetAttribute("genmsxid"); + // Handle empty elements if (reader.IsEmptyElement) return obj; List dumps = []; + List roms = []; reader.Read(); while (!reader.EOF) @@ -369,6 +384,13 @@ namespace SabreTools.Serialization.Readers reader.Skip(); break; + case "rom": + var rom = ParseRomBase(reader); + if (rom is not null) + roms.Add(rom); + + reader.Skip(); + break; default: if (Debug) Console.Error.WriteLine($"Element '{reader.Name}' is not recognized"); @@ -379,6 +401,8 @@ namespace SabreTools.Serialization.Readers if (dumps.Count > 0) obj.Dump = [.. dumps]; + if (roms.Count > 0) + obj.Rom = [.. roms]; return obj; } diff --git a/SabreTools.Serialization.Writers/OpenMSX.cs b/SabreTools.Serialization.Writers/OpenMSX.cs index be72ecb9..cacde7d0 100644 --- a/SabreTools.Serialization.Writers/OpenMSX.cs +++ b/SabreTools.Serialization.Writers/OpenMSX.cs @@ -141,10 +141,11 @@ namespace SabreTools.Serialization.Writers else return; - writer.WriteOptionalElementString("start", obj.Start); + writer.WriteOptionalElementString("sha1", obj.SHA1); writer.WriteOptionalElementString("type", obj.Type); - writer.WriteOptionalElementString("hash", obj.Hash); + writer.WriteOptionalElementString("status", obj.Status); writer.WriteOptionalElementString("remark", obj.Remark); + writer.WriteOptionalElementString("start", obj.Start); writer.WriteEndElement(); } @@ -158,12 +159,12 @@ namespace SabreTools.Serialization.Writers { 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); + writer.WriteRequiredAttributeString("title", obj.Title); + writer.WriteRequiredAttributeString("system", obj.System); + writer.WriteRequiredAttributeString("company", obj.Company); + writer.WriteRequiredAttributeString("country", obj.Country); + writer.WriteRequiredAttributeString("year", obj.Year); + writer.WriteOptionalAttributeString("genmsxid", obj.GenMSXID); if (obj.Dump is not null && obj.Dump.Length > 0) { @@ -173,6 +174,14 @@ namespace SabreTools.Serialization.Writers } } + if (obj.Rom is not null && obj.Rom.Length > 0) + { + foreach (var rom in obj.Rom) + { + WriteRomBase(rom, writer); + } + } + writer.WriteEndElement(); } }