From f9c207cf09906e08637befe050cd76a636412556 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 12 Mar 2024 11:53:58 -0400 Subject: [PATCH] Take care of some TODO items --- SabreTools.DatFiles/DatFile.FromMetadata.cs | 19 ++- SabreTools.DatFiles/DatFile.ToMetadata.cs | 37 ++++- SabreTools.DatFiles/DatFile.cs | 1 - SabreTools.DatFiles/DatHeader.cs | 30 ++-- SabreTools.DatFiles/Formats/Listxml.Reader.cs | 12 +- SabreTools.DatItems/Formats/Auxiliary.cs | 8 - SabreTools.DatItems/Machine.cs | 133 +++------------- SabreTools.DatItems/Trurip.cs | 146 ++++++++++++++++++ SabreTools.Filter/FilterRunner.cs | 2 +- SabreTools.Test/Core/ConvertersTests.cs | 2 - SabreTools/Features/BaseFeature.cs | 15 +- 11 files changed, 255 insertions(+), 150 deletions(-) create mode 100644 SabreTools.DatItems/Trurip.cs diff --git a/SabreTools.DatFiles/DatFile.FromMetadata.cs b/SabreTools.DatFiles/DatFile.FromMetadata.cs index b8a5161c..190ab95e 100644 --- a/SabreTools.DatFiles/DatFile.FromMetadata.cs +++ b/SabreTools.DatFiles/DatFile.FromMetadata.cs @@ -57,7 +57,9 @@ namespace SabreTools.DatFiles } if (item.ContainsKey(Models.Metadata.Header.ImagesKey)) { - // TODO: Add to internal model + var images = item.Read(Models.Metadata.Header.ImagesKey); + if (images != null) + Header.SetFieldValue(Models.Metadata.Header.ImagesKey, images); } if (item.ContainsKey(Models.Metadata.Header.InfosKey)) { @@ -358,6 +360,17 @@ namespace SabreTools.DatFiles if (machine.GetStringFieldValue(Models.Metadata.Machine.SupportedKey) != null) machine.SetFieldValue(Models.Metadata.Machine.SupportedKey, machine.GetStringFieldValue(Models.Metadata.Machine.SupportedKey).AsEnumValue().AsStringValue()); + // Handle Trurip object, if it exists + if (item.ContainsKey(Models.Metadata.Machine.TruripKey)) + { + var truripItem = item.Read(Models.Metadata.Machine.TruripKey); + if (truripItem != null) + { + var trurip = new DatItems.Trurip(truripItem); + machine.SetFieldValue(Models.Metadata.Machine.TruripKey, trurip); + } + } + // Convert items in the machine if (item.ContainsKey(Models.Metadata.Machine.AdjusterKey)) { @@ -489,10 +502,6 @@ namespace SabreTools.DatFiles var items = ReadItemArray(item, Models.Metadata.Machine.SoundKey); ProcessItems(items, machine, filename, indexId, statsOnly); } - if (item.ContainsKey(Models.Metadata.Machine.TruripKey)) - { - // TODO: Figure out what this maps to - } if (item.ContainsKey(Models.Metadata.Machine.VideoKey)) { var items = ReadItemArray(item, Models.Metadata.Machine.VideoKey); diff --git a/SabreTools.DatFiles/DatFile.ToMetadata.cs b/SabreTools.DatFiles/DatFile.ToMetadata.cs index f7c72c88..c7becdc1 100644 --- a/SabreTools.DatFiles/DatFile.ToMetadata.cs +++ b/SabreTools.DatFiles/DatFile.ToMetadata.cs @@ -57,8 +57,8 @@ namespace SabreTools.DatFiles // Convert subheader values if (Header.CanOpenSpecified) header[Models.Metadata.Header.CanOpenKey] = new Models.OfflineList.CanOpen { Extension = Header.GetStringArrayFieldValue(Models.Metadata.Header.CanOpenKey) }; - // if (Header.ImagesSpecified) - // // TODO: Add to internal model + if (Header.ImagesSpecified) + header[Models.Metadata.Header.ImagesKey] = Header.GetFieldValue(Models.Metadata.Header.ImagesKey); if (Header.InfosSpecified) { var infoItem = new Models.OfflineList.Infos(); @@ -210,6 +210,22 @@ namespace SabreTools.DatFiles // Create a machine to hold everything var machine = items[0].GetFieldValue(DatItems.DatItem.MachineKey)!.GetInternalClone(); + // Handle Trurip object, if it exists + if (machine.ContainsKey(Models.Metadata.Machine.TruripKey)) + { + var trurip = machine.Read(Models.Metadata.Machine.TruripKey); + if (trurip != null) + { + var truripItem = trurip.ConvertToLogiqx(); + truripItem.Publisher = machine.ReadString(Models.Metadata.Machine.PublisherKey); + truripItem.Year = machine.ReadString(Models.Metadata.Machine.YearKey); + truripItem.Players = machine.ReadString(Models.Metadata.Machine.PlayersKey); + truripItem.Source = machine.ReadString(Models.Metadata.Machine.SourceFileKey); + truripItem.CloneOf = machine.ReadString(Models.Metadata.Machine.CloneOfKey); + machine[Models.Metadata.Machine.TruripKey] = truripItem; + } + } + // Loop through and convert the items to respective lists for (int index = 0; index < items.Count; index++) { @@ -271,8 +287,7 @@ namespace SabreTools.DatFiles AppendToMachineKey(machine, Models.Metadata.Machine.DiskKey, diskItem); break; case DatItems.Formats.Display display: - // TODO: Handle cases where it's actually a Video - var displayItem = display.GetInternalClone(); + var displayItem = ProcessItem(display); EnsureMachineKey(machine, Models.Metadata.Machine.DisplayKey); AppendToMachineKey(machine, Models.Metadata.Machine.DisplayKey, displayItem); break; @@ -501,6 +516,20 @@ namespace SabreTools.DatFiles return diskItem; } + /// + /// Convert Display information + /// + /// Item to convert + /// Machine to use for Part and DiskArea + private static Models.Metadata.Display ProcessItem(DatItems.Formats.Display item) + { + var displayItem = item.GetInternalClone(); + + // TODO: Handle cases where it's actually a Video + + return displayItem; + } + /// /// Convert Input information /// diff --git a/SabreTools.DatFiles/DatFile.cs b/SabreTools.DatFiles/DatFile.cs index 64fb1576..4fad40c1 100644 --- a/SabreTools.DatFiles/DatFile.cs +++ b/SabreTools.DatFiles/DatFile.cs @@ -259,7 +259,6 @@ namespace SabreTools.DatFiles else if ((size == 0 || size == null) && (string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.CRCKey)) || rom.HasZeroHash())) { - // TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually rom.SetFieldValue(Models.Metadata.Rom.SizeKey, Constants.SizeZero.ToString()); rom.SetFieldValue(Models.Metadata.Rom.CRCKey, Constants.CRCZero); rom.SetFieldValue(Models.Metadata.Rom.MD5Key, Constants.MD5Zero); diff --git a/SabreTools.DatFiles/DatHeader.cs b/SabreTools.DatFiles/DatHeader.cs index 67cee0e7..69d69388 100644 --- a/SabreTools.DatFiles/DatHeader.cs +++ b/SabreTools.DatFiles/DatHeader.cs @@ -82,16 +82,6 @@ namespace SabreTools.DatFiles #region Fields - [JsonIgnore] - public bool InfosSpecified - { - get - { - var infos = GetFieldValue(Models.Metadata.Header.InfosKey); - return infos != null && infos.Length > 0; - } - } - [JsonIgnore] public bool CanOpenSpecified { @@ -102,6 +92,25 @@ namespace SabreTools.DatFiles } } + [JsonIgnore] + public bool ImagesSpecified + { + get + { + return GetFieldValue(Models.Metadata.Header.ImagesKey) != null; + } + } + + [JsonIgnore] + public bool InfosSpecified + { + get + { + var infos = GetFieldValue(Models.Metadata.Header.InfosKey); + return infos != null && infos.Length > 0; + } + } + [JsonIgnore] public bool NewDatSpecified { @@ -302,6 +311,7 @@ namespace SabreTools.DatFiles header.SetFieldValue(Models.Metadata.Header.HomepageKey, GetStringFieldValue(Models.Metadata.Header.HomepageKey)); header.SetFieldValue(Models.Metadata.Header.IdKey, GetStringFieldValue(Models.Metadata.Header.IdKey)); header.SetFieldValue(Models.Metadata.Header.InfosKey, GetFieldValue(Models.Metadata.Header.InfosKey)); // TODO: Perform a deep clone + header.SetFieldValue(Models.Metadata.Header.ImagesKey, GetFieldValue(Models.Metadata.Header.ImagesKey)); // TODO: Perform a deep clone header.SetFieldValue(DatHeader.InputDepotKey, GetFieldValue(DatHeader.InputDepotKey)?.Clone() as DepotInformation); header.SetFieldValue(DatHeader.OutputDepotKey, GetFieldValue(DatHeader.OutputDepotKey)?.Clone() as DepotInformation); header.SetFieldValue(Models.Metadata.Header.LockBiosModeKey, GetBoolFieldValue(Models.Metadata.Header.LockBiosModeKey)); diff --git a/SabreTools.DatFiles/Formats/Listxml.Reader.cs b/SabreTools.DatFiles/Formats/Listxml.Reader.cs index ec76b3ce..43eb3a6d 100644 --- a/SabreTools.DatFiles/Formats/Listxml.Reader.cs +++ b/SabreTools.DatFiles/Formats/Listxml.Reader.cs @@ -13,9 +13,17 @@ namespace SabreTools.DatFiles.Formats try { // Deserialize the input file - // TODO: Support M1 DATs again var mame = new Serialization.Files.Listxml().Deserialize(filename); - var metadata = new Serialization.CrossModel.Listxml().Serialize(mame); + Models.Metadata.MetadataFile? metadata; + if (mame == null) + { + var m1 = new Serialization.Files.M1().Deserialize(filename); + metadata = new Serialization.CrossModel.M1().Serialize(m1); + } + else + { + metadata = new Serialization.CrossModel.Listxml().Serialize(mame); + } // Convert to the internal format ConvertMetadata(metadata, filename, indexId, keep, statsOnly); diff --git a/SabreTools.DatItems/Formats/Auxiliary.cs b/SabreTools.DatItems/Formats/Auxiliary.cs index 7a47b2e8..ec6649eb 100644 --- a/SabreTools.DatItems/Formats/Auxiliary.cs +++ b/SabreTools.DatItems/Formats/Auxiliary.cs @@ -6,10 +6,6 @@ using Newtonsoft.Json; /// namespace SabreTools.DatItems.Formats { - #region DatItem - - #region OpenMSX - /// /// Represents the OpenMSX original value /// @@ -36,8 +32,4 @@ namespace SabreTools.DatItems.Formats [JsonIgnore] private readonly Models.Metadata.Original _internal = []; } - - #endregion - - #endregion //DatItem } diff --git a/SabreTools.DatItems/Machine.cs b/SabreTools.DatItems/Machine.cs index cc1ac1c4..5f63daf5 100644 --- a/SabreTools.DatItems/Machine.cs +++ b/SabreTools.DatItems/Machine.cs @@ -33,77 +33,6 @@ namespace SabreTools.DatItems #region Fields - // TODO: Should this be a separate object for TruRip? - #region Logiqx EmuArc - - /// - /// Title ID - /// - [JsonProperty("titleid", DefaultValueHandling = DefaultValueHandling.Ignore)] - [XmlElement("titleid")] - public string? TitleID { get; set; } = null; - - /// - /// Machine developer - /// - [JsonProperty("developer", DefaultValueHandling = DefaultValueHandling.Ignore)] - [XmlElement("developer")] - public string? Developer { get; set; } = null; - - /// - /// Game genre - /// - [JsonProperty("genre", DefaultValueHandling = DefaultValueHandling.Ignore)] - [XmlElement("genre")] - public string? Genre { get; set; } = null; - - /// - /// Game subgenre - /// - [JsonProperty("subgenre", DefaultValueHandling = DefaultValueHandling.Ignore)] - [XmlElement("subgenre")] - public string? Subgenre { get; set; } = null; - - /// - /// Game ratings - /// - [JsonProperty("ratings", DefaultValueHandling = DefaultValueHandling.Ignore)] - [XmlElement("ratings")] - public string? Ratings { get; set; } = null; - - /// - /// Game score - /// - [JsonProperty("score", DefaultValueHandling = DefaultValueHandling.Ignore)] - [XmlElement("score")] - public string? Score { get; set; } = null; - - /// - /// Is the machine enabled - /// - [JsonProperty("enabled", DefaultValueHandling = DefaultValueHandling.Ignore)] - [XmlElement("enabled")] - public string? Enabled { get; set; } = null; // bool? - - /// - /// Does the game have a CRC check - /// - [JsonProperty("hascrc", DefaultValueHandling = DefaultValueHandling.Ignore)] - [XmlElement("hascrc")] - public bool? Crc { get; set; } = null; - - [JsonIgnore] - public bool CrcSpecified { get { return Crc != null; } } - - /// - /// Machine relations - /// - [JsonProperty("relatedto", DefaultValueHandling = DefaultValueHandling.Ignore)] - [XmlElement("relatedto")] - public string? RelatedTo { get; set; } = null; - - #endregion - /// /// Internal Machine model /// @@ -112,6 +41,28 @@ namespace SabreTools.DatItems #endregion + #region Constructors + + public Machine() { } + + public Machine(Models.Metadata.Machine machine) + { + // Get all fields to automatically copy without processing + var nonItemFields = TypeHelper.GetConstants(typeof(Models.Metadata.Machine)); + if (nonItemFields == null) + return; + + // Populate the internal machine from non-filter fields + _machine = []; + foreach (string fieldName in nonItemFields) + { + if (machine.ContainsKey(fieldName)) + _machine[fieldName] = machine[fieldName]; + } + } + + #endregion + #region Accessors /// @@ -230,28 +181,6 @@ namespace SabreTools.DatItems #endregion - #region Constructors - - public Machine() { } - - public Machine(Models.Metadata.Machine machine) - { - // Get all fields to automatically copy without processing - var nonItemFields = TypeHelper.GetConstants(typeof(Models.Metadata.Machine)); - if (nonItemFields == null) - return; - - // Populate the internal machine from non-filter fields - _machine = []; - foreach (string fieldName in nonItemFields) - { - if (machine.ContainsKey(fieldName)) - _machine[fieldName] = machine[fieldName]; - } - } - - #endregion - #region Cloning methods /// @@ -262,25 +191,7 @@ namespace SabreTools.DatItems { return new Machine() { - #region Common - _machine = this._machine.Clone() as Models.Metadata.Machine ?? [], - - #endregion - - #region Logiqx EmuArc - - TitleID = this.TitleID, - Developer = this.Developer, - Genre = this.Genre, - Subgenre = this.Subgenre, - Ratings = this.Ratings, - Score = this.Score, - Enabled = this.Enabled, - Crc = this.Crc, - RelatedTo = this.RelatedTo, - - #endregion }; } diff --git a/SabreTools.DatItems/Trurip.cs b/SabreTools.DatItems/Trurip.cs new file mode 100644 index 00000000..28a495cd --- /dev/null +++ b/SabreTools.DatItems/Trurip.cs @@ -0,0 +1,146 @@ +using System; +using System.Xml.Serialization; +using Newtonsoft.Json; +using SabreTools.Core.Tools; + +namespace SabreTools.DatItems +{ + /// + /// Represents TruRip/EmuArc-specific values on a machine + /// + [JsonObject("trurip"), XmlRoot("trurip")] + public sealed class Trurip : ICloneable + { + #region Fields + + /// + /// Title ID + /// + [JsonProperty("titleid", DefaultValueHandling = DefaultValueHandling.Ignore)] + [XmlElement("titleid")] + public string? TitleID { get; set; } = null; + + /// + /// Machine developer + /// + [JsonProperty("developer", DefaultValueHandling = DefaultValueHandling.Ignore)] + [XmlElement("developer")] + public string? Developer { get; set; } = null; + + /// + /// Game genre + /// + [JsonProperty("genre", DefaultValueHandling = DefaultValueHandling.Ignore)] + [XmlElement("genre")] + public string? Genre { get; set; } = null; + + /// + /// Game subgenre + /// + [JsonProperty("subgenre", DefaultValueHandling = DefaultValueHandling.Ignore)] + [XmlElement("subgenre")] + public string? Subgenre { get; set; } = null; + + /// + /// Game ratings + /// + [JsonProperty("ratings", DefaultValueHandling = DefaultValueHandling.Ignore)] + [XmlElement("ratings")] + public string? Ratings { get; set; } = null; + + /// + /// Game score + /// + [JsonProperty("score", DefaultValueHandling = DefaultValueHandling.Ignore)] + [XmlElement("score")] + public string? Score { get; set; } = null; + + /// + /// Is the machine enabled + /// + [JsonProperty("enabled", DefaultValueHandling = DefaultValueHandling.Ignore)] + [XmlElement("enabled")] + public string? Enabled { get; set; } = null; // bool? + + /// + /// Does the game have a CRC check + /// + [JsonProperty("hascrc", DefaultValueHandling = DefaultValueHandling.Ignore)] + [XmlElement("hascrc")] + public bool? Crc { get; set; } = null; + + [JsonIgnore] + public bool CrcSpecified { get { return Crc != null; } } + + /// + /// Machine relations + /// + [JsonProperty("relatedto", DefaultValueHandling = DefaultValueHandling.Ignore)] + [XmlElement("relatedto")] + public string? RelatedTo { get; set; } = null; + + #endregion + + #region Constructors + + public Trurip() { } + + public Trurip(Models.Logiqx.Trurip trurip) + { + TitleID = trurip.TitleID; + Developer = trurip.Developer; + Genre = trurip.Genre; + Subgenre = trurip.Subgenre; + Ratings = trurip.Ratings; + Score = trurip.Score; + Enabled = trurip.Enabled; + Crc = trurip.CRC.AsYesNo(); + RelatedTo = trurip.RelatedTo; + } + + #endregion + + #region Cloning methods + + /// + /// Create a clone of the current object + /// + /// New object with the same values as the current one + public object Clone() + { + return new Trurip() + { + TitleID = this.TitleID, + Developer = this.Developer, + Genre = this.Genre, + Subgenre = this.Subgenre, + Ratings = this.Ratings, + Score = this.Score, + Enabled = this.Enabled, + Crc = this.Crc, + RelatedTo = this.RelatedTo, + }; + } + + /// + /// Convert to the internal Logiqx model + /// + public Models.Logiqx.Trurip ConvertToLogiqx() + { + return new Models.Logiqx.Trurip() + { + TitleID = this.TitleID, + Developer = this.Developer, + Genre = this.Genre, + Subgenre = this.Subgenre, + Ratings = this.Ratings, + Score = this.Score, + Enabled = this.Enabled, + CRC = this.Crc.FromYesNo(), + RelatedTo = this.RelatedTo, + }; + } + + #endregion + } +} diff --git a/SabreTools.Filter/FilterRunner.cs b/SabreTools.Filter/FilterRunner.cs index e2c11a6c..2c9a127c 100644 --- a/SabreTools.Filter/FilterRunner.cs +++ b/SabreTools.Filter/FilterRunner.cs @@ -38,7 +38,7 @@ namespace SabreTools.Filter filters.Add(new FilterObject(filterString)); } - this.Filters = filters.ToArray(); + this.Filters = [.. filters]; } /// diff --git a/SabreTools.Test/Core/ConvertersTests.cs b/SabreTools.Test/Core/ConvertersTests.cs index d7f0e14c..99a10ae9 100644 --- a/SabreTools.Test/Core/ConvertersTests.cs +++ b/SabreTools.Test/Core/ConvertersTests.cs @@ -404,8 +404,6 @@ namespace SabreTools.Test.Core Assert.Equal(expected, actual); } - // TODO: Write new test for all supported DatHeaderField values - [Theory] [InlineData(DeviceType.NULL, null)] [InlineData(DeviceType.Unknown, "unknown")] diff --git a/SabreTools/Features/BaseFeature.cs b/SabreTools/Features/BaseFeature.cs index ea558efa..5b956221 100644 --- a/SabreTools/Features/BaseFeature.cs +++ b/SabreTools/Features/BaseFeature.cs @@ -1,19 +1,18 @@ using System; using System.Collections.Generic; using System.IO; - +using Microsoft.Data.Sqlite; using SabreTools.Core; using SabreTools.Core.Tools; using SabreTools.DatFiles; using SabreTools.DatTools; using SabreTools.FileTypes; using SabreTools.Filtering; +using SabreTools.Hashing; using SabreTools.Help; using SabreTools.IO; using SabreTools.Logging; using SabreTools.Reports; -using Microsoft.Data.Sqlite; -using SabreTools.Hashing; namespace SabreTools.Features { @@ -2238,11 +2237,15 @@ Some special strings that can be used: { // Populate filters List filterPairs = GetList(features, FilterListValue); - var filterRunner = new Filter.FilterRunner(filterPairs.ToArray()); - // TODO: Support this use case somehow // Include 'of" in game filters - //filter.MachineFilter.IncludeOfInGame = GetBoolean(features, MatchOfTagsValue); + bool matchOfTags = GetBoolean(features, MatchOfTagsValue); + if (matchOfTags) + { + // TODO: Support this use case somehow + } + + var filterRunner = new Filter.FilterRunner(filterPairs.ToArray()); return filterRunner; }