diff --git a/SabreTools.Library/DatFiles/Json.cs b/SabreTools.Library/DatFiles/Json.cs index 3af90a1b..1b06e0ce 100644 --- a/SabreTools.Library/DatFiles/Json.cs +++ b/SabreTools.Library/DatFiles/Json.cs @@ -250,6 +250,9 @@ namespace SabreTools.Library.DatFiles case ItemType.Feature: datItem = datItemObj.ToObject(); break; + case ItemType.Instance: + datItem = datItemObj.ToObject(); + break; case ItemType.Media: datItem = datItemObj.ToObject(); break; diff --git a/SabreTools.Library/DatItems/Analog.cs b/SabreTools.Library/DatItems/Analog.cs index 04338144..9e019f84 100644 --- a/SabreTools.Library/DatItems/Analog.cs +++ b/SabreTools.Library/DatItems/Analog.cs @@ -34,8 +34,8 @@ namespace SabreTools.Library.DatItems base.SetFields(mappings); // Handle Analog-specific fields - if (mappings.Keys.Contains(Field.DatItem_Mask)) - Mask = mappings[Field.DatItem_Mask]; + if (mappings.Keys.Contains(Field.Machine_Port_Analog_Mask)) + Mask = mappings[Field.Machine_Port_Analog_Mask]; } #endregion @@ -138,7 +138,7 @@ namespace SabreTools.Library.DatItems base.RemoveFields(fields); // Remove the fields - if (fields.Contains(Field.DatItem_Mask)) + if (fields.Contains(Field.Machine_Port_Analog_Mask)) Mask = null; } @@ -164,7 +164,7 @@ namespace SabreTools.Library.DatItems Analog newItem = item as Analog; // Replace the fields - if (fields.Contains(Field.DatItem_Mask)) + if (fields.Contains(Field.Machine_Port_Analog_Mask)) Mask = newItem.Mask; } diff --git a/SabreTools.Library/DatItems/Auxiliary.cs b/SabreTools.Library/DatItems/Auxiliary.cs index 6691fff2..6cb19455 100644 --- a/SabreTools.Library/DatItems/Auxiliary.cs +++ b/SabreTools.Library/DatItems/Auxiliary.cs @@ -290,29 +290,6 @@ namespace SabreTools.Library.DatItems #endregion } - /// - /// Represents one ListXML instance - /// - [JsonObject("instance")] - public class Instance - { - #region Fields - - /// - /// Name of the instance - /// - [JsonProperty("name")] - public string Name { get; set; } - - /// - /// Short name for the instance - /// - [JsonProperty("briefname", DefaultValueHandling = DefaultValueHandling.Ignore)] - public string BriefName { get; set; } - - #endregion - } - /// /// Represents one ListXML conflocation or diplocation /// diff --git a/SabreTools.Library/DatItems/DatItem.cs b/SabreTools.Library/DatItems/DatItem.cs index 9672634d..5b32b6c2 100644 --- a/SabreTools.Library/DatItems/DatItem.cs +++ b/SabreTools.Library/DatItems/DatItem.cs @@ -497,6 +497,9 @@ namespace SabreTools.Library.DatItems case ItemType.Feature: return new Feature(); + case ItemType.Instance: + return new Instance(); + case ItemType.Media: return new Media(); @@ -541,6 +544,7 @@ namespace SabreTools.Library.DatItems ItemType.Driver => new Driver(), ItemType.Extension => new Extension(), ItemType.Feature => new Feature(), + ItemType.Instance => new Instance(), ItemType.Media => new Media(), ItemType.RamOption => new RamOption(), ItemType.Release => new Release(), diff --git a/SabreTools.Library/DatItems/Enums.cs b/SabreTools.Library/DatItems/Enums.cs index 0adf055d..0b77fae0 100644 --- a/SabreTools.Library/DatItems/Enums.cs +++ b/SabreTools.Library/DatItems/Enums.cs @@ -497,6 +497,7 @@ namespace SabreTools.Library.DatItems Driver, Extension, Feature, + Instance, RamOption, Release, Sample, diff --git a/SabreTools.Library/DatItems/Extension.cs b/SabreTools.Library/DatItems/Extension.cs index a31fe0ec..499041d4 100644 --- a/SabreTools.Library/DatItems/Extension.cs +++ b/SabreTools.Library/DatItems/Extension.cs @@ -45,8 +45,8 @@ namespace SabreTools.Library.DatItems base.SetFields(mappings); // Handle Sample-specific fields - if (mappings.Keys.Contains(Field.DatItem_Name)) - Name = mappings[Field.DatItem_Name]; + if (mappings.Keys.Contains(Field.Machine_Device_Extension_Name)) + Name = mappings[Field.Machine_Device_Extension_Name]; } #endregion @@ -158,9 +158,9 @@ namespace SabreTools.Library.DatItems return false; // Filter on item name - if (filter.DatItem_Name.MatchesPositiveSet(Name) == false) + if (filter.Machine_Device_Extension_Name.MatchesPositiveSet(Name) == false) return false; - if (filter.DatItem_Name.MatchesNegativeSet(Name) == true) + if (filter.Machine_Device_Extension_Name.MatchesNegativeSet(Name) == true) return false; return true; @@ -176,7 +176,7 @@ namespace SabreTools.Library.DatItems base.RemoveFields(fields); // Remove the fields - if (fields.Contains(Field.DatItem_Name)) + if (fields.Contains(Field.Machine_Device_Extension_Name)) Name = null; } @@ -212,7 +212,7 @@ namespace SabreTools.Library.DatItems Extension newItem = item as Extension; // Replace the fields - if (fields.Contains(Field.DatItem_Name)) + if (fields.Contains(Field.Machine_Device_Extension_Name)) Name = newItem.Name; } diff --git a/SabreTools.Library/DatItems/Instance.cs b/SabreTools.Library/DatItems/Instance.cs new file mode 100644 index 00000000..35bc8423 --- /dev/null +++ b/SabreTools.Library/DatItems/Instance.cs @@ -0,0 +1,244 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using SabreTools.Library.Filtering; +using SabreTools.Library.Tools; +using Newtonsoft.Json; + +namespace SabreTools.Library.DatItems +{ + /// + /// Represents a single instance of another item + /// + [JsonObject("instance")] + public class Instance : DatItem + { + #region Fields + + /// + /// Name of the item + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// Short name for the instance + /// + [JsonProperty("briefname", DefaultValueHandling = DefaultValueHandling.Ignore)] + public string BriefName { get; set; } + + #endregion + + #region Accessors + + /// + /// Gets the name to use for a DatItem + /// + /// Name if available, null otherwise + public override string GetName() + { + return Name; + } + + /// + /// Set fields with given values + /// + /// Mappings dictionary + public override void SetFields(Dictionary mappings) + { + // Set base fields + base.SetFields(mappings); + + // Handle Instance-specific fields + if (mappings.Keys.Contains(Field.Machine_Device_Instance_Name)) + Name = mappings[Field.Machine_Device_Instance_Name]; + + if (mappings.Keys.Contains(Field.Machine_Device_Instance_BriefName)) + BriefName = mappings[Field.Machine_Device_Instance_BriefName]; + } + + #endregion + + #region Constructors + + /// + /// Create a default, empty Instance object + /// + public Instance() + { + Name = string.Empty; + ItemType = ItemType.Instance; + } + + #endregion + + #region Cloning Methods + + public override object Clone() + { + return new Instance() + { + Name = this.Name, + ItemType = this.ItemType, + DupeType = this.DupeType, + + AltName = this.AltName, + AltTitle = this.AltTitle, + + Original = this.Original, + OpenMSXSubType = this.OpenMSXSubType, + OpenMSXType = this.OpenMSXType, + Remark = this.Remark, + Boot = this.Boot, + + Part = this.Part, + Features = this.Features, + AreaName = this.AreaName, + AreaSize = this.AreaSize, + AreaWidth = this.AreaWidth, + AreaEndianness = this.AreaEndianness, + Value = this.Value, + LoadFlag = this.LoadFlag, + + Machine = this.Machine.Clone() as Machine, + Source = this.Source.Clone() as Source, + Remove = this.Remove, + + BriefName = this.BriefName, + }; + } + + #endregion + + #region Comparision Methods + + public override bool Equals(DatItem other) + { + // If we don't have a Instance, return false + if (ItemType != other.ItemType) + return false; + + // Otherwise, treat it as a Instance + Instance newOther = other as Instance; + + // If the Instance information matches + return (Name == newOther.Name && BriefName == newOther.BriefName); + } + + #endregion + + #region Filtering + + /// + /// Clean a DatItem according to the cleaner + /// + /// Cleaner to implement + public override void Clean(Cleaner cleaner) + { + // Clean common items first + base.Clean(cleaner); + + // If we're stripping unicode characters, strip item name + if (cleaner?.RemoveUnicode == true) + Name = Sanitizer.RemoveUnicodeCharacters(Name); + + // If we are in NTFS trim mode, trim the game name + if (cleaner?.Trim == true) + { + // Windows max name length is 260 + int usableLength = 260 - Machine.Name.Length - (cleaner.Root?.Length ?? 0); + if (Name.Length > usableLength) + { + string ext = Path.GetExtension(Name); + Name = Name.Substring(0, usableLength - ext.Length); + Name += ext; + } + } + } + + /// + /// Check to see if a DatItem passes the filter + /// + /// Filter to check against + /// True if the item passed the filter, false otherwise + public override bool PassesFilter(Filter filter) + { + // Check common fields first + if (!base.PassesFilter(filter)) + return false; + + // Filter on item name + if (filter.Machine_Device_Instance_Name.MatchesPositiveSet(Name) == false) + return false; + if (filter.Machine_Device_Instance_Name.MatchesNegativeSet(Name) == true) + return false; + + // Filter on brief name + if (filter.Machine_Device_Instance_BriefName.MatchesPositiveSet(Name) == false) + return false; + if (filter.Machine_Device_Instance_BriefName.MatchesNegativeSet(Name) == true) + return false; + + return true; + } + + /// + /// Remove fields from the DatItem + /// + /// List of Fields to remove + public override void RemoveFields(List fields) + { + // Remove common fields first + base.RemoveFields(fields); + + // Remove the fields + if (fields.Contains(Field.Machine_Device_Instance_Name)) + Name = null; + + if (fields.Contains(Field.Machine_Device_Instance_BriefName)) + BriefName = null; + } + + /// + /// Set internal names to match One Rom Per Game (ORPG) logic + /// + public override void SetOneRomPerGame() + { + string[] splitname = Name.Split('.'); + Machine.Name += $"/{string.Join(".", splitname.Take(splitname.Length > 1 ? splitname.Length - 1 : 1))}"; + Name = Path.GetFileName(Name); + } + + #endregion + + #region Sorting and Merging + + /// + /// Replace fields from another item + /// + /// DatItem to pull new information from + /// List of Fields representing what should be updated + public override void ReplaceFields(DatItem item, List fields) + { + // Replace common fields first + base.ReplaceFields(item, fields); + + // If we don't have a Instance to replace from, ignore specific fields + if (item.ItemType != ItemType.Instance) + return; + + // Cast for easier access + Instance newItem = item as Instance; + + // Replace the fields + if (fields.Contains(Field.Machine_Device_Instance_Name)) + Name = newItem.Name; + + if (fields.Contains(Field.Machine_Device_Instance_BriefName)) + BriefName = newItem.BriefName; + } + + #endregion + } +} diff --git a/SabreTools.Library/Tools/Converters.cs b/SabreTools.Library/Tools/Converters.cs index df2e3e47..e2fed492 100644 --- a/SabreTools.Library/Tools/Converters.cs +++ b/SabreTools.Library/Tools/Converters.cs @@ -1684,6 +1684,8 @@ namespace SabreTools.Library.Tools return ItemType.Extension; case "feature": return ItemType.Feature; + case "instance": + return ItemType.Instance; case "media": return ItemType.Media; case "ramoption": @@ -1720,6 +1722,7 @@ namespace SabreTools.Library.Tools "driver" => ItemType.Driver, "extension" => ItemType.Extension, "feature" => ItemType.Feature, + "instance" => ItemType.Instance, "media" => ItemType.Media, "ramoption" => ItemType.RamOption, "release" => ItemType.Release, @@ -2298,6 +2301,8 @@ namespace SabreTools.Library.Tools return "extension"; case ItemType.Feature: return "feature"; + case ItemType.Instance: + return "instance"; case ItemType.Media: return "media"; case ItemType.RamOption: @@ -2334,6 +2339,7 @@ namespace SabreTools.Library.Tools ItemType.Driver => "driver", ItemType.Extension => "extension", ItemType.Feature => "feature", + ItemType.Instance => "instance", ItemType.Media => "media", ItemType.RamOption => "ramoption", ItemType.Release => "release",