diff --git a/SabreTools.Library/DatFiles/ItemDictionary.cs b/SabreTools.Library/DatFiles/ItemDictionary.cs
index 31d211db..e4dd2b0f 100644
--- a/SabreTools.Library/DatFiles/ItemDictionary.cs
+++ b/SabreTools.Library/DatFiles/ItemDictionary.cs
@@ -119,6 +119,12 @@ namespace SabreTools.Library.DatFiles
[JsonIgnore]
public long ConfigurationCount { get; private set; } = 0;
+ ///
+ /// Number of DataArea items
+ ///
+ [JsonIgnore]
+ public long DataAreaCount { get; private set; } = 0;
+
///
/// Number of Device items
///
@@ -143,6 +149,12 @@ namespace SabreTools.Library.DatFiles
[JsonIgnore]
public long DiskCount { get; private set; } = 0;
+ ///
+ /// Number of DiskArea items
+ ///
+ [JsonIgnore]
+ public long DiskAreaCount { get; private set; } = 0;
+
///
/// Number of Display items
///
@@ -179,6 +191,12 @@ namespace SabreTools.Library.DatFiles
[JsonIgnore]
public long MediaCount { get; private set; } = 0;
+ ///
+ /// Number of Part items
+ ///
+ [JsonIgnore]
+ public long PartCount { get; private set; } = 0;
+
///
/// Number of PartFeature items
///
@@ -586,6 +604,9 @@ namespace SabreTools.Library.DatFiles
case ItemType.Configuration:
ConfigurationCount++;
break;
+ case ItemType.DataArea:
+ DataAreaCount++;
+ break;
case ItemType.Device:
DeviceCount++;
break;
@@ -608,6 +629,9 @@ namespace SabreTools.Library.DatFiles
NodumpCount += ((item as Disk).ItemStatus == ItemStatus.Nodump ? 1 : 0);
VerifiedCount += ((item as Disk).ItemStatus == ItemStatus.Verified ? 1 : 0);
break;
+ case ItemType.DiskArea:
+ DiskAreaCount++;
+ break;
case ItemType.Display:
DisplayCount++;
break;
@@ -629,6 +653,9 @@ namespace SabreTools.Library.DatFiles
SHA1Count += (string.IsNullOrWhiteSpace((item as Media).SHA1) ? 0 : 1);
SHA256Count += (string.IsNullOrWhiteSpace((item as Media).SHA256) ? 0 : 1);
break;
+ case ItemType.Part:
+ PartCount++;
+ break;
case ItemType.PartFeature:
PartFeatureCount++;
break;
@@ -772,6 +799,9 @@ namespace SabreTools.Library.DatFiles
case ItemType.Configuration:
ConfigurationCount--;
break;
+ case ItemType.DataArea:
+ DataAreaCount--;
+ break;
case ItemType.Device:
DeviceCount--;
break;
@@ -794,6 +824,9 @@ namespace SabreTools.Library.DatFiles
NodumpCount -= ((item as Disk).ItemStatus == ItemStatus.Nodump ? 1 : 0);
VerifiedCount -= ((item as Disk).ItemStatus == ItemStatus.Verified ? 1 : 0);
break;
+ case ItemType.DiskArea:
+ DiskAreaCount--;
+ break;
case ItemType.Display:
DisplayCount--;
break;
@@ -815,6 +848,9 @@ namespace SabreTools.Library.DatFiles
SHA1Count -= (string.IsNullOrWhiteSpace((item as Media).SHA1) ? 0 : 1);
SHA256Count -= (string.IsNullOrWhiteSpace((item as Media).SHA256) ? 0 : 1);
break;
+ case ItemType.Part:
+ PartCount--;
+ break;
case ItemType.PartFeature:
PartFeatureCount--;
break;
diff --git a/SabreTools.Library/DatFiles/Json.cs b/SabreTools.Library/DatFiles/Json.cs
index 2244e670..8ec1c536 100644
--- a/SabreTools.Library/DatFiles/Json.cs
+++ b/SabreTools.Library/DatFiles/Json.cs
@@ -235,6 +235,9 @@ namespace SabreTools.Library.DatFiles
case ItemType.Control:
datItem = datItemObj.ToObject();
break;
+ case ItemType.DataArea:
+ datItem = datItemObj.ToObject();
+ break;
case ItemType.Device:
datItem = datItemObj.ToObject();
break;
@@ -247,6 +250,9 @@ namespace SabreTools.Library.DatFiles
case ItemType.Disk:
datItem = datItemObj.ToObject();
break;
+ case ItemType.DiskArea:
+ datItem = datItemObj.ToObject();
+ break;
case ItemType.Display:
datItem = datItemObj.ToObject();
break;
@@ -274,6 +280,9 @@ namespace SabreTools.Library.DatFiles
case ItemType.Media:
datItem = datItemObj.ToObject();
break;
+ case ItemType.Part:
+ datItem = datItemObj.ToObject();
+ break;
case ItemType.PartFeature:
datItem = datItemObj.ToObject();
break;
diff --git a/SabreTools.Library/DatItems/Auxiliary.cs b/SabreTools.Library/DatItems/Auxiliary.cs
index 07a1e749..ec61a292 100644
--- a/SabreTools.Library/DatItems/Auxiliary.cs
+++ b/SabreTools.Library/DatItems/Auxiliary.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -32,78 +33,5 @@ namespace SabreTools.Library.DatItems
#endregion
- #region SoftwareList
-
- ///
- /// Represents one SoftwareList dataarea object
- ///
- ///
- /// One DataArea can contain multiple Rom items
- ///
- [JsonObject("dataarea")]
- public class DataArea
- {
- ///
- /// Name of the item
- ///
- [JsonProperty("name", DefaultValueHandling = DefaultValueHandling.Ignore)]
- public string Name { get; set; }
-
- ///
- /// Total size of the area
- ///
- [JsonProperty("size", DefaultValueHandling = DefaultValueHandling.Ignore)]
- public long? Size { get; set; }
-
- ///
- /// Word width for the area
- ///
- [JsonProperty("width", DefaultValueHandling = DefaultValueHandling.Ignore)]
- public long? Width { get; set; }
-
- ///
- /// Byte endianness of the area
- ///
- [JsonProperty("endianness", DefaultValueHandling = DefaultValueHandling.Ignore)]
- public Endianness Endianness { get; set; }
- }
-
- ///
- /// Represents one SoftwareList diskarea object
- ///
- ///
- /// One DiskArea can contain multiple Disk items
- ///
- [JsonObject("diskarea")]
- public class DiskArea
- {
- ///
- /// Name of the item
- ///
- [JsonProperty("name", DefaultValueHandling = DefaultValueHandling.Ignore)]
- public string Name { get; set; }
- }
-
- ///
- /// Represents one SoftwareList part object
- ///
- ///
- /// One Part can contain multiple PartFeature, DataArea, DiskArea, and DipSwitch items
- ///
- [JsonObject("part")]
- public class Part
- {
- [JsonProperty("name")]
- public string Name { get; set; }
-
- [JsonProperty("interface")]
- public string Interface { get; set; }
-
- [JsonProperty("features", DefaultValueHandling = DefaultValueHandling.Ignore)]
- public List Features { get; set; }
- }
-
- #endregion
-
#endregion //DatItem
}
diff --git a/SabreTools.Library/DatItems/DatItem.cs b/SabreTools.Library/DatItems/DatItem.cs
index 0cf87719..6cb1f0e5 100644
--- a/SabreTools.Library/DatItems/DatItem.cs
+++ b/SabreTools.Library/DatItems/DatItem.cs
@@ -114,15 +114,7 @@ namespace SabreTools.Library.DatItems
Field.DatItem_Boot,
// Rom (SoftwareList)
- Field.DatItem_AreaName,
- Field.DatItem_AreaSize,
- Field.DatItem_AreaWidth,
- Field.DatItem_AreaEndianness,
Field.DatItem_LoadFlag,
- Field.DatItem_Part_Name,
- Field.DatItem_Part_Interface,
- Field.DatItem_Part_Feature_Name,
- Field.DatItem_Part_Feature_Value,
Field.DatItem_Value,
// Disk
@@ -169,6 +161,12 @@ namespace SabreTools.Library.DatItems
Field.DatItem_Control_Ways2,
Field.DatItem_Control_Ways3,
+ // DataArea
+ Field.DatItem_AreaName,
+ Field.DatItem_AreaSize,
+ Field.DatItem_AreaWidth,
+ Field.DatItem_AreaEndianness,
+
// Device
Field.DatItem_DeviceType,
Field.DatItem_FixedImage,
@@ -219,6 +217,14 @@ namespace SabreTools.Library.DatItems
Field.DatItem_Location_Number,
Field.DatItem_Location_Inverted,
+ // Part
+ Field.DatItem_Part_Name,
+ Field.DatItem_Part_Interface,
+
+ // PartFeature
+ Field.DatItem_Part_Feature_Name,
+ Field.DatItem_Part_Feature_Value,
+
// RamOption
Field.DatItem_Content,
@@ -394,6 +400,9 @@ namespace SabreTools.Library.DatItems
case ItemType.Control:
return new Control();
+ case ItemType.DataArea:
+ return new DataArea();
+
case ItemType.Device:
return new Device();
@@ -406,6 +415,9 @@ namespace SabreTools.Library.DatItems
case ItemType.Disk:
return new Disk();
+ case ItemType.DiskArea:
+ return new DiskArea();
+
case ItemType.Display:
return new Display();
@@ -433,6 +445,9 @@ namespace SabreTools.Library.DatItems
case ItemType.Media:
return new Media();
+ case ItemType.Part:
+ return new Part();
+
case ItemType.PartFeature:
return new PartFeature();
diff --git a/SabreTools.Library/DatItems/DataArea.cs b/SabreTools.Library/DatItems/DataArea.cs
new file mode 100644
index 00000000..0c8370fb
--- /dev/null
+++ b/SabreTools.Library/DatItems/DataArea.cs
@@ -0,0 +1,283 @@
+using System;
+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
+{
+ ///
+ /// SoftwareList dataarea information
+ ///
+ /// One DataArea can contain multiple Rom items
+ [JsonObject("dataarea")]
+ public class DataArea : DatItem
+ {
+ #region Fields
+
+ ///
+ /// Name of the item
+ ///
+ [JsonProperty("name", DefaultValueHandling = DefaultValueHandling.Ignore)]
+ public string Name { get; set; }
+
+ ///
+ /// Total size of the area
+ ///
+ [JsonProperty("size", DefaultValueHandling = DefaultValueHandling.Ignore)]
+ public long? Size { get; set; }
+
+ ///
+ /// Word width for the area
+ ///
+ [JsonProperty("width", DefaultValueHandling = DefaultValueHandling.Ignore)]
+ public long? Width { get; set; }
+
+ ///
+ /// Byte endianness of the area
+ ///
+ [JsonProperty("endianness", DefaultValueHandling = DefaultValueHandling.Ignore)]
+ public Endianness Endianness { 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 DataArea-specific fields
+ if (mappings.Keys.Contains(Field.DatItem_AreaName))
+ Name = mappings[Field.DatItem_AreaName];
+
+ if (mappings.Keys.Contains(Field.DatItem_AreaSize))
+ {
+ if (Int64.TryParse(mappings[Field.DatItem_AreaSize], out long areaSize))
+ Size = areaSize;
+ }
+
+ if (mappings.Keys.Contains(Field.DatItem_AreaWidth))
+ {
+ if (Int64.TryParse(mappings[Field.DatItem_AreaWidth], out long areaWidth))
+ Width = areaWidth;
+ }
+
+ if (mappings.Keys.Contains(Field.DatItem_AreaEndianness))
+ Endianness = mappings[Field.DatItem_AreaEndianness].AsEndianness();
+ }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Create a default, empty DataArea object
+ ///
+ public DataArea()
+ {
+ Name = string.Empty;
+ ItemType = ItemType.DataArea;
+ }
+
+ #endregion
+
+ #region Cloning Methods
+
+ public override object Clone()
+ {
+ return new DataArea()
+ {
+ ItemType = this.ItemType,
+ DupeType = this.DupeType,
+
+ Machine = this.Machine.Clone() as Machine,
+ Source = this.Source.Clone() as Source,
+ Remove = this.Remove,
+
+ Name = this.Name,
+ Size = this.Size,
+ Width = this.Width,
+ Endianness = this.Endianness,
+ };
+ }
+
+ #endregion
+
+ #region Comparision Methods
+
+ public override bool Equals(DatItem other)
+ {
+ // If we don't have a DataArea, return false
+ if (ItemType != other.ItemType)
+ return false;
+
+ // Otherwise, treat it as a DataArea
+ DataArea newOther = other as DataArea;
+
+ // If the DataArea information matches
+ return (Name == newOther.Name
+ && Size == newOther.Size
+ && Width == newOther.Width
+ && Endianness == newOther.Endianness);
+ }
+
+ #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 area name
+ if (filter.DatItem_AreaName.MatchesPositiveSet(Name) == false)
+ return false;
+ if (filter.DatItem_AreaName.MatchesNegativeSet(Name) == true)
+ return false;
+
+ // Filter on area size
+ if (filter.DatItem_AreaSize.MatchesNeutral(null, Size) == false)
+ return false;
+ else if (filter.DatItem_AreaSize.MatchesPositive(null, Size) == false)
+ return false;
+ else if (filter.DatItem_AreaSize.MatchesNegative(null, Size) == false)
+ return false;
+
+ // Filter on area byte width
+ if (filter.DatItem_AreaWidth.MatchesPositive(null, Width) == false)
+ return false;
+ if (filter.DatItem_AreaWidth.MatchesNegative(null, Width) == true)
+ return false;
+
+ // Filter on area endianness
+ if (filter.DatItem_AreaEndianness.MatchesPositive(Endianness.NULL, Endianness) == false)
+ return false;
+ if (filter.DatItem_AreaEndianness.MatchesNegative(Endianness.NULL, Endianness) == 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.DatItem_AreaName))
+ Name = null;
+
+ if (fields.Contains(Field.DatItem_AreaSize))
+ Size = null;
+
+ if (fields.Contains(Field.DatItem_AreaWidth))
+ Width = null;
+
+ if (fields.Contains(Field.DatItem_AreaEndianness))
+ Endianness = Endianness.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 DataArea to replace from, ignore specific fields
+ if (item.ItemType != ItemType.DataArea)
+ return;
+
+ // Cast for easier access
+ DataArea newItem = item as DataArea;
+
+ // Replace the fields
+ if (fields.Contains(Field.DatItem_AreaName))
+ Name = newItem.Name;
+
+ if (fields.Contains(Field.DatItem_AreaSize))
+ Size = newItem.Size;
+
+ if (fields.Contains(Field.DatItem_AreaWidth))
+ Width = newItem.Width;
+
+ if (fields.Contains(Field.DatItem_AreaEndianness))
+ Endianness = newItem.Endianness;
+ }
+
+ #endregion
+ }
+}
diff --git a/SabreTools.Library/DatItems/DipSwitch.cs b/SabreTools.Library/DatItems/DipSwitch.cs
index 7fd27c03..3b43d1b3 100644
--- a/SabreTools.Library/DatItems/DipSwitch.cs
+++ b/SabreTools.Library/DatItems/DipSwitch.cs
@@ -129,23 +129,11 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- if (mappings.Keys.Contains(Field.DatItem_Part_Name))
- {
- if (Part == null)
- Part = new Part();
+ // Handle Part-specific fields
+ if (Part == null)
+ Part = new Part();
- Part.Name = mappings[Field.DatItem_Part_Name];
- }
-
- if (mappings.Keys.Contains(Field.DatItem_Part_Interface))
- {
- if (Part == null)
- Part = new Part();
-
- Part.Interface = mappings[Field.DatItem_Part_Interface];
- }
-
- // TODO: Handle DatItem_Part_Feature*
+ Part.SetFields(mappings);
#endregion
}
@@ -209,7 +197,9 @@ namespace SabreTools.Library.DatItems
if (!match)
return match;
- // TODO: Handle Part*
+ // If the part matches
+ if (Part != null)
+ match &= (Part == newOther.Part);
// If the conditions match
if (Conditions != null)
@@ -337,19 +327,12 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- // Filter on part name
- if (filter.DatItem_Part_Name.MatchesPositiveSet(Part?.Name) == false)
- return false;
- if (filter.DatItem_Part_Name.MatchesNegativeSet(Part?.Name) == true)
- return false;
-
- // Filter on part interface
- if (filter.DatItem_Part_Interface.MatchesPositiveSet(Part?.Interface) == false)
- return false;
- if (filter.DatItem_Part_Interface.MatchesNegativeSet(Part?.Interface) == true)
- return false;
-
- // TODO: Handle DatItem_Part_Feature*
+ // Filter on Part
+ if (Part != null)
+ {
+ if (!Part.PassesFilter(filter))
+ return false;
+ }
#endregion
@@ -406,13 +389,8 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- if (fields.Contains(Field.DatItem_Part_Name) && Part != null)
- Part.Name = null;
-
- if (fields.Contains(Field.DatItem_Part_Interface) && Part != null)
- Part.Interface = null;
-
- // TODO: Handle DatItem_Part_Feature*
+ if (Part != null)
+ Part.RemoveFields(fields);
#endregion
}
@@ -477,23 +455,8 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- if (fields.Contains(Field.DatItem_Part_Name))
- {
- if (Part == null)
- Part = new Part();
-
- Part.Name = newItem.Part?.Name;
- }
-
- if (fields.Contains(Field.DatItem_Part_Interface))
- {
- if (Part == null)
- Part = new Part();
-
- Part.Interface = newItem.Part?.Interface;
- }
-
- // TODO: Handle DatItem_Part_Feature*
+ if (Part != null && newItem.Part != null)
+ Part.ReplaceFields(newItem.Part, fields);
#endregion
}
diff --git a/SabreTools.Library/DatItems/Disk.cs b/SabreTools.Library/DatItems/Disk.cs
index 9bf68118..d34bb75a 100644
--- a/SabreTools.Library/DatItems/Disk.cs
+++ b/SabreTools.Library/DatItems/Disk.cs
@@ -158,31 +158,17 @@ namespace SabreTools.Library.DatItems
if (mappings.Keys.Contains(Field.DatItem_Optional))
Optional = mappings[Field.DatItem_Optional].AsYesNo();
- if (mappings.Keys.Contains(Field.DatItem_AreaName))
- {
- if (DiskArea == null)
- DiskArea = new DiskArea();
+ // Handle DiskArea-specific fields
+ if (DiskArea == null)
+ DiskArea = new DiskArea();
- DiskArea.Name = mappings[Field.DatItem_AreaName];
- }
+ DiskArea.SetFields(mappings);
- if (mappings.Keys.Contains(Field.DatItem_Part_Name))
- {
- if (Part == null)
- Part = new Part();
+ // Handle Part-specific fields
+ if (Part == null)
+ Part = new Part();
- Part.Name = mappings[Field.DatItem_Part_Name];
- }
-
- if (mappings.Keys.Contains(Field.DatItem_Part_Interface))
- {
- if (Part == null)
- Part = new Part();
-
- Part.Interface = mappings[Field.DatItem_Part_Interface];
- }
-
- // TODO: Handle DatItem_Part_Feature*
+ Part.SetFields(mappings);
}
#endregion
@@ -474,25 +460,19 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- // Filter on area name
- if (filter.DatItem_AreaName.MatchesPositiveSet(DiskArea?.Name) == false)
- return false;
- if (filter.DatItem_AreaName.MatchesNegativeSet(DiskArea?.Name) == true)
- return false;
+ // Filter on DiskArea
+ if (DiskArea != null)
+ {
+ if (!DiskArea.PassesFilter(filter))
+ return false;
+ }
- // Filter on part name
- if (filter.DatItem_Part_Name.MatchesPositiveSet(Part?.Name) == false)
- return false;
- if (filter.DatItem_Part_Name.MatchesNegativeSet(Part?.Name) == true)
- return false;
-
- // Filter on part interface
- if (filter.DatItem_Part_Interface.MatchesPositiveSet(Part?.Interface) == false)
- return false;
- if (filter.DatItem_Part_Interface.MatchesNegativeSet(Part?.Interface) == true)
- return false;
-
- // TODO: Handle DatItem_Part_Feature*
+ // Filter on Part
+ if (Part != null)
+ {
+ if (!Part.PassesFilter(filter))
+ return false;
+ }
#endregion
@@ -543,19 +523,11 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- if (fields.Contains(Field.DatItem_AreaName))
- {
- if (DiskArea != null)
- DiskArea.Name = null;
- }
+ if (DiskArea != null)
+ DiskArea.RemoveFields(fields);
- if (fields.Contains(Field.DatItem_Part_Name) && Part != null)
- Part.Name = null;
-
- if (fields.Contains(Field.DatItem_Part_Interface) && Part != null)
- Part.Interface = null;
-
- // TODO: Handle DatItem_Part_Feature*
+ if (Part != null)
+ Part.RemoveFields(fields);
#endregion
}
@@ -667,31 +639,11 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- if (fields.Contains(Field.DatItem_AreaName))
- {
- if (DiskArea == null)
- DiskArea = new DiskArea();
+ if (DiskArea != null && newItem.DiskArea != null)
+ DiskArea.ReplaceFields(newItem.DiskArea, fields);
- DiskArea.Name = newItem.DiskArea?.Name;
- }
-
- if (fields.Contains(Field.DatItem_Part_Name))
- {
- if (Part == null)
- Part = new Part();
-
- Part.Name = newItem.Part?.Name;
- }
-
- if (fields.Contains(Field.DatItem_Part_Interface))
- {
- if (Part == null)
- Part = new Part();
-
- Part.Interface = newItem.Part?.Interface;
- }
-
- // TODO: Handle DatItem_Part_Feature*
+ if (Part != null && newItem.Part != null)
+ Part.ReplaceFields(newItem.Part, fields);
#endregion
}
diff --git a/SabreTools.Library/DatItems/DiskArea.cs b/SabreTools.Library/DatItems/DiskArea.cs
new file mode 100644
index 00000000..57eb9c50
--- /dev/null
+++ b/SabreTools.Library/DatItems/DiskArea.cs
@@ -0,0 +1,206 @@
+using System;
+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
+{
+ ///
+ /// SoftwareList diskarea information
+ ///
+ /// One DiskArea can contain multiple Disk items
+ [JsonObject("diskarea")]
+ public class DiskArea : DatItem
+ {
+ #region Fields
+
+ ///
+ /// Name of the item
+ ///
+ [JsonProperty("name", DefaultValueHandling = DefaultValueHandling.Ignore)]
+ public string Name { 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 DiskArea-specific fields
+ if (mappings.Keys.Contains(Field.DatItem_AreaName))
+ Name = mappings[Field.DatItem_AreaName];
+ }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Create a default, empty DiskArea object
+ ///
+ public DiskArea()
+ {
+ Name = string.Empty;
+ ItemType = ItemType.DiskArea;
+ }
+
+ #endregion
+
+ #region Cloning Methods
+
+ public override object Clone()
+ {
+ return new DiskArea()
+ {
+ ItemType = this.ItemType,
+ DupeType = this.DupeType,
+
+ Machine = this.Machine.Clone() as Machine,
+ Source = this.Source.Clone() as Source,
+ Remove = this.Remove,
+
+ Name = this.Name,
+ };
+ }
+
+ #endregion
+
+ #region Comparision Methods
+
+ public override bool Equals(DatItem other)
+ {
+ // If we don't have a DiskArea, return false
+ if (ItemType != other.ItemType)
+ return false;
+
+ // Otherwise, treat it as a DiskArea
+ DiskArea newOther = other as DiskArea;
+
+ // If the DiskArea information matches
+ return (Name == newOther.Name);
+ }
+
+ #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 area name
+ if (filter.DatItem_AreaName.MatchesPositiveSet(Name) == false)
+ return false;
+ if (filter.DatItem_AreaName.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.DatItem_AreaName))
+ Name = 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 DiskArea to replace from, ignore specific fields
+ if (item.ItemType != ItemType.DiskArea)
+ return;
+
+ // Cast for easier access
+ DiskArea newItem = item as DiskArea;
+
+ // Replace the fields
+ if (fields.Contains(Field.DatItem_AreaName))
+ Name = newItem.Name;
+ }
+
+ #endregion
+ }
+}
diff --git a/SabreTools.Library/DatItems/Enums.cs b/SabreTools.Library/DatItems/Enums.cs
index 9500ae94..b24ab3fa 100644
--- a/SabreTools.Library/DatItems/Enums.cs
+++ b/SabreTools.Library/DatItems/Enums.cs
@@ -302,15 +302,7 @@ namespace SabreTools.Library.DatItems
DatItem_Boot,
// Rom (SoftwareList)
- DatItem_AreaName, // TODO: DataArea/DiskArea?
- DatItem_AreaSize, // TODO: DataArea?
- DatItem_AreaWidth, // TODO: DataArea?
- DatItem_AreaEndianness, // TODO: DataArea?
DatItem_LoadFlag,
- DatItem_Part_Name, // TODO: Part?
- DatItem_Part_Interface, // TODO: Part?
- DatItem_Part_Feature_Name, // TODO: PartFeature?
- DatItem_Part_Feature_Value, // TODO: PartFeature?
DatItem_Value,
// Disk
@@ -357,6 +349,12 @@ namespace SabreTools.Library.DatItems
DatItem_Control_Ways2,
DatItem_Control_Ways3,
+ // DataArea
+ DatItem_AreaName,
+ DatItem_AreaSize,
+ DatItem_AreaWidth,
+ DatItem_AreaEndianness,
+
// Device
DatItem_DeviceType,
DatItem_FixedImage,
@@ -407,6 +405,14 @@ namespace SabreTools.Library.DatItems
DatItem_Location_Number,
DatItem_Location_Inverted,
+ // Part
+ DatItem_Part_Name,
+ DatItem_Part_Interface,
+
+ // PartFeature
+ DatItem_Part_Feature_Name,
+ DatItem_Part_Feature_Value,
+
// RamOption
DatItem_Content,
@@ -474,9 +480,11 @@ namespace SabreTools.Library.DatItems
Condition,
Configuration,
Control,
+ DataArea,
Device,
DeviceReference,
DipSwitch,
+ DiskArea,
Display,
Driver,
Extension,
@@ -485,6 +493,7 @@ namespace SabreTools.Library.DatItems
Input,
Instance,
Location,
+ Part,
PartFeature,
Port,
RamOption,
diff --git a/SabreTools.Library/DatItems/Part.cs b/SabreTools.Library/DatItems/Part.cs
new file mode 100644
index 00000000..2950c58f
--- /dev/null
+++ b/SabreTools.Library/DatItems/Part.cs
@@ -0,0 +1,271 @@
+using System;
+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
+{
+ ///
+ /// SoftwareList part information
+ ///
+ /// One Part can contain multiple PartFeature, DataArea, DiskArea, and DipSwitch items
+ [JsonObject("part")]
+ public class Part : DatItem
+ {
+ #region Fields
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("interface")]
+ public string Interface { get; set; }
+
+ [JsonProperty("features", DefaultValueHandling = DefaultValueHandling.Ignore)]
+ public List Features { 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 Part-specific fields
+ if (mappings.Keys.Contains(Field.DatItem_Part_Name))
+ Name = mappings[Field.DatItem_Part_Name];
+
+ if (mappings.Keys.Contains(Field.DatItem_Part_Interface))
+ Interface = mappings[Field.DatItem_Part_Interface];
+
+ // Handle Feature-specific fields
+ if (Features != null)
+ {
+ foreach (PartFeature partFeature in Features)
+ {
+ partFeature.SetFields(mappings);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Create a default, empty Part object
+ ///
+ public Part()
+ {
+ Name = string.Empty;
+ ItemType = ItemType.Part;
+ }
+
+ #endregion
+
+ #region Cloning Methods
+
+ public override object Clone()
+ {
+ return new Part()
+ {
+ ItemType = this.ItemType,
+ DupeType = this.DupeType,
+
+ Machine = this.Machine.Clone() as Machine,
+ Source = this.Source.Clone() as Source,
+ Remove = this.Remove,
+
+ Name = this.Name,
+ Interface = this.Interface,
+ Features = this.Features,
+ };
+ }
+
+ #endregion
+
+ #region Comparision Methods
+
+ public override bool Equals(DatItem other)
+ {
+ // If we don't have a Part, return false
+ if (ItemType != other.ItemType)
+ return false;
+
+ // Otherwise, treat it as a Part
+ Part newOther = other as Part;
+
+ // If the Part information matches
+ bool match = (Name == newOther.Name
+ && Interface == newOther.Interface);
+ if (!match)
+ return match;
+
+ // If the features match
+ if (Features != null)
+ {
+ foreach (PartFeature partFeature in Features)
+ {
+ match &= newOther.Features.Contains(partFeature);
+ }
+ }
+
+ return match;
+ }
+
+ #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 part name
+ if (filter.DatItem_Part_Name.MatchesPositiveSet(Name) == false)
+ return false;
+ if (filter.DatItem_Part_Name.MatchesNegativeSet(Name) == true)
+ return false;
+
+ // Filter on part interface
+ if (filter.DatItem_Part_Interface.MatchesPositiveSet(Interface) == false)
+ return false;
+ if (filter.DatItem_Part_Interface.MatchesNegativeSet(Interface) == true)
+ return false;
+
+ // Filter on features
+ if (Features != null)
+ {
+ foreach (PartFeature partFeature in Features)
+ {
+ if (!partFeature.PassesFilter(filter))
+ 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.DatItem_Part_Name))
+ Name = null;
+
+ if (fields.Contains(Field.DatItem_Part_Interface))
+ Interface = null;
+
+ if (Features != null)
+ {
+ foreach (PartFeature partFeature in Features)
+ {
+ partFeature.RemoveFields(fields);
+ }
+ }
+ }
+
+ ///
+ /// 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 Part to replace from, ignore specific fields
+ if (item.ItemType != ItemType.Part)
+ return;
+
+ // Cast for easier access
+ Part newItem = item as Part;
+
+ // Replace the fields
+ if (fields.Contains(Field.DatItem_Part_Name))
+ Name = newItem.Name;
+
+ if (fields.Contains(Field.DatItem_Part_Interface))
+ Interface = newItem.Interface;
+
+ // DatItem_Part_Feature_* doesn't make sense here
+ // since not every part feature under the other item
+ // can replace every part feature under this item
+ }
+
+ #endregion
+ }
+}
diff --git a/SabreTools.Library/DatItems/PartFeature.cs b/SabreTools.Library/DatItems/PartFeature.cs
index 4c327273..83601180 100644
--- a/SabreTools.Library/DatItems/PartFeature.cs
+++ b/SabreTools.Library/DatItems/PartFeature.cs
@@ -51,11 +51,11 @@ namespace SabreTools.Library.DatItems
base.SetFields(mappings);
// Handle PartFeature-specific fields
- if (mappings.Keys.Contains(Field.DatItem_Name))
- Name = mappings[Field.DatItem_Name];
+ if (mappings.Keys.Contains(Field.DatItem_Part_Feature_Name))
+ Name = mappings[Field.DatItem_Part_Feature_Name];
- if (mappings.Keys.Contains(Field.DatItem_Value))
- Value = mappings[Field.DatItem_Value];
+ if (mappings.Keys.Contains(Field.DatItem_Part_Feature_Value))
+ Value = mappings[Field.DatItem_Part_Feature_Value];
}
#endregion
@@ -151,15 +151,15 @@ namespace SabreTools.Library.DatItems
return false;
// Filter on item name
- if (filter.DatItem_Name.MatchesPositiveSet(Name) == false)
+ if (filter.DatItem_Part_Feature_Name.MatchesPositiveSet(Name) == false)
return false;
- if (filter.DatItem_Name.MatchesNegativeSet(Name) == true)
+ if (filter.DatItem_Part_Feature_Name.MatchesNegativeSet(Name) == true)
return false;
// Filter on info value
- if (filter.DatItem_Value.MatchesPositiveSet(Value) == false)
+ if (filter.DatItem_Part_Feature_Value.MatchesPositiveSet(Value) == false)
return false;
- if (filter.DatItem_Value.MatchesNegativeSet(Value) == true)
+ if (filter.DatItem_Part_Feature_Value.MatchesNegativeSet(Value) == true)
return false;
return true;
@@ -175,10 +175,10 @@ namespace SabreTools.Library.DatItems
base.RemoveFields(fields);
// Remove the fields
- if (fields.Contains(Field.DatItem_Name))
+ if (fields.Contains(Field.DatItem_Part_Feature_Name))
Name = null;
- if (fields.Contains(Field.DatItem_Value))
+ if (fields.Contains(Field.DatItem_Part_Feature_Value))
Value = null;
}
@@ -214,10 +214,10 @@ namespace SabreTools.Library.DatItems
PartFeature newItem = item as PartFeature;
// Replace the fields
- if (fields.Contains(Field.DatItem_Name))
+ if (fields.Contains(Field.DatItem_Part_Feature_Name))
Name = newItem.Name;
- if (fields.Contains(Field.DatItem_Value))
+ if (fields.Contains(Field.DatItem_Part_Feature_Value))
Value = newItem.Value;
}
diff --git a/SabreTools.Library/DatItems/Rom.cs b/SabreTools.Library/DatItems/Rom.cs
index c51c91af..0bcaa771 100644
--- a/SabreTools.Library/DatItems/Rom.cs
+++ b/SabreTools.Library/DatItems/Rom.cs
@@ -368,64 +368,24 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- if (mappings.Keys.Contains(Field.DatItem_AreaName))
- {
- if (DataArea == null)
- DataArea = new DataArea();
-
- DataArea.Name = mappings[Field.DatItem_AreaName];
- }
-
- if (mappings.Keys.Contains(Field.DatItem_AreaSize))
- {
- if (DataArea == null)
- DataArea = new DataArea();
-
- if (Int64.TryParse(mappings[Field.DatItem_AreaSize], out long areaSize))
- DataArea.Size = areaSize;
- }
-
- if (mappings.Keys.Contains(Field.DatItem_AreaWidth))
- {
- if (DataArea == null)
- DataArea = new DataArea();
-
- if (Int64.TryParse(mappings[Field.DatItem_AreaWidth], out long areaWidth))
- DataArea.Width = areaWidth;
- }
-
- if (mappings.Keys.Contains(Field.DatItem_AreaEndianness))
- {
- if (DataArea == null)
- DataArea = new DataArea();
-
- DataArea.Endianness = mappings[Field.DatItem_AreaEndianness].AsEndianness();
- }
-
if (mappings.Keys.Contains(Field.DatItem_LoadFlag))
LoadFlag = mappings[Field.DatItem_LoadFlag].AsLoadFlag();
- if (mappings.Keys.Contains(Field.DatItem_Part_Name))
- {
- if (Part == null)
- Part = new Part();
-
- Part.Name = mappings[Field.DatItem_Part_Name];
- }
-
- if (mappings.Keys.Contains(Field.DatItem_Part_Interface))
- {
- if (Part == null)
- Part = new Part();
-
- Part.Interface = mappings[Field.DatItem_Part_Interface];
- }
-
- // TODO: Handle DatItem_Part_Feature*
-
if (mappings.Keys.Contains(Field.DatItem_Value))
Value = mappings[Field.DatItem_Value];
+ // Handle DataArea-specific fields
+ if (DataArea == null)
+ DataArea = new DataArea();
+
+ DataArea.SetFields(mappings);
+
+ // Handle Part-specific fields
+ if (Part == null)
+ Part = new Part();
+
+ Part.SetFields(mappings);
+
#endregion
}
@@ -894,57 +854,31 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- // Filter on area name
- if (filter.DatItem_AreaName.MatchesPositiveSet(DataArea?.Name) == false)
- return false;
- if (filter.DatItem_AreaName.MatchesNegativeSet(DataArea?.Name) == true)
- return false;
-
- // Filter on area size
- if (filter.DatItem_AreaSize.MatchesNeutral(null, DataArea?.Size) == false)
- return false;
- else if (filter.DatItem_AreaSize.MatchesPositive(null, DataArea?.Size) == false)
- return false;
- else if (filter.DatItem_AreaSize.MatchesNegative(null, DataArea?.Size) == false)
- return false;
-
- // Filter on area byte width
- if (filter.DatItem_AreaWidth.MatchesPositive(null, DataArea?.Width) == false)
- return false;
- if (filter.DatItem_AreaWidth.MatchesNegative(null, DataArea?.Width) == true)
- return false;
-
- // Filter on area endianness
- if (filter.DatItem_AreaEndianness.MatchesPositive(Endianness.NULL, DataArea?.Endianness ?? Endianness.NULL) == false)
- return false;
- if (filter.DatItem_AreaEndianness.MatchesNegative(Endianness.NULL, DataArea?.Endianness ?? Endianness.NULL) == true)
- return false;
-
// Filter on load flag
if (filter.DatItem_LoadFlag.MatchesPositive(LoadFlag.NULL, LoadFlag) == false)
return false;
if (filter.DatItem_LoadFlag.MatchesNegative(LoadFlag.NULL, LoadFlag) == true)
return false;
- // Filter on part name
- if (filter.DatItem_Part_Name.MatchesPositiveSet(Part?.Name) == false)
- return false;
- if (filter.DatItem_Part_Name.MatchesNegativeSet(Part?.Name) == true)
- return false;
-
- // Filter on part interface
- if (filter.DatItem_Part_Interface.MatchesPositiveSet(Part?.Interface) == false)
- return false;
- if (filter.DatItem_Part_Interface.MatchesNegativeSet(Part?.Interface) == true)
- return false;
-
// Filter on value
if (filter.DatItem_Value.MatchesPositiveSet(Value) == false)
return false;
if (filter.DatItem_Value.MatchesNegativeSet(Value) == true)
return false;
- // TODO: Handle DatItem_Part_Feature*
+ // Filter on DataArea
+ if (DataArea != null)
+ {
+ if (!DataArea.PassesFilter(filter))
+ return false;
+ }
+
+ // Filter on Part
+ if (Part != null)
+ {
+ if (!Part.PassesFilter(filter))
+ return false;
+ }
#endregion
@@ -1050,44 +984,18 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- if (fields.Contains(Field.DatItem_AreaName))
- {
- if (DataArea != null)
- DataArea.Name = null;
- }
-
- if (fields.Contains(Field.DatItem_AreaSize))
- {
- if (DataArea != null)
- DataArea.Size = null;
- }
-
- if (fields.Contains(Field.DatItem_AreaWidth))
- {
- if (DataArea != null)
- DataArea.Width = null;
- }
-
- if (fields.Contains(Field.DatItem_AreaEndianness))
- {
- if (DataArea != null)
- DataArea.Endianness = Endianness.NULL;
- }
-
if (fields.Contains(Field.DatItem_LoadFlag))
LoadFlag = LoadFlag.NULL;
- if (fields.Contains(Field.DatItem_Part_Name) && Part != null)
- Part.Name = null;
-
- if (fields.Contains(Field.DatItem_Part_Interface) && Part != null)
- Part.Interface = null;
-
- // TODO: Handle DatItem_Part_Feature*
-
if (fields.Contains(Field.DatItem_Value))
Value = null;
+ if (DataArea != null)
+ DataArea.RemoveFields(fields);
+
+ if (Part != null)
+ Part.RemoveFields(fields);
+
#endregion
}
@@ -1290,58 +1198,17 @@ namespace SabreTools.Library.DatItems
#region SoftwareList
- if (fields.Contains(Field.DatItem_AreaName))
- {
- if (DataArea == null)
- DataArea = new DataArea();
-
- DataArea.Name = newItem.DataArea?.Name;
- }
-
- if (fields.Contains(Field.DatItem_AreaSize))
- {
- if (DataArea == null)
- DataArea = new DataArea();
-
- DataArea.Size = newItem.DataArea?.Size;
- }
-
- if (fields.Contains(Field.DatItem_AreaWidth))
- {
- if (DataArea == null)
- DataArea = new DataArea();
-
- DataArea.Width = newItem.DataArea?.Width;
- }
-
- if (fields.Contains(Field.DatItem_AreaEndianness))
- {
- if (DataArea == null)
- DataArea = new DataArea();
-
- DataArea.Endianness = newItem.DataArea?.Endianness ?? Endianness.NULL;
- }
-
if (fields.Contains(Field.DatItem_LoadFlag))
LoadFlag = newItem.LoadFlag;
- if (fields.Contains(Field.DatItem_Part_Name))
- {
- if (Part == null)
- Part = new Part();
+ if (fields.Contains(Field.DatItem_Value))
+ Value = newItem.Value;
- Part.Name = newItem.Part?.Name;
- }
+ if (DataArea != null && newItem.DataArea != null)
+ DataArea.ReplaceFields(newItem.DataArea, fields);
- if (fields.Contains(Field.DatItem_Part_Interface))
- {
- if (Part == null)
- Part = new Part();
-
- Part.Interface = newItem.Part?.Interface;
- }
-
- // TODO: Handle DatItem_Part_Feature*
+ if (Part != null && newItem.Part != null)
+ Part.ReplaceFields(newItem.Part, fields);
#endregion
}
diff --git a/SabreTools.Library/Filtering/Filter.cs b/SabreTools.Library/Filtering/Filter.cs
index 85b43b4c..089ace63 100644
--- a/SabreTools.Library/Filtering/Filter.cs
+++ b/SabreTools.Library/Filtering/Filter.cs
@@ -134,15 +134,7 @@ namespace SabreTools.Library.Filtering
public FilterItem DatItem_Boot { get; private set; } = new FilterItem();
// Rom (SoftwareList)
- public FilterItem DatItem_AreaName { get; private set; } = new FilterItem();
- public FilterItem DatItem_AreaSize { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null };
- public FilterItem DatItem_AreaWidth { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null };
- public FilterItem DatItem_AreaEndianness { get; private set; } = new FilterItem() { Positive = Endianness.NULL, Negative = Endianness.NULL };
public FilterItem DatItem_LoadFlag { get; private set; } = new FilterItem() { Positive = LoadFlag.NULL, Negative = LoadFlag.NULL };
- public FilterItem DatItem_Part_Name { get; private set; } = new FilterItem();
- public FilterItem DatItem_Part_Interface { get; private set; } = new FilterItem();
- public FilterItem DatItem_Part_Feature_Name { get; private set; } = new FilterItem();
- public FilterItem DatItem_Part_Feature_Value { get; private set; } = new FilterItem();
public FilterItem DatItem_Value { get; private set; } = new FilterItem();
// Disk
@@ -189,6 +181,12 @@ namespace SabreTools.Library.Filtering
public FilterItem DatItem_Control_Ways2 { get; private set; } = new FilterItem();
public FilterItem DatItem_Control_Ways3 { get; private set; } = new FilterItem();
+ // DataArea
+ public FilterItem DatItem_AreaName { get; private set; } = new FilterItem();
+ public FilterItem DatItem_AreaSize { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null };
+ public FilterItem DatItem_AreaWidth { get; private set; } = new FilterItem() { Positive = null, Negative = null, Neutral = null };
+ public FilterItem DatItem_AreaEndianness { get; private set; } = new FilterItem() { Positive = Endianness.NULL, Negative = Endianness.NULL };
+
// Device
public FilterItem DatItem_DeviceType { get; private set; } = new FilterItem();
public FilterItem DatItem_FixedImage { get; private set; } = new FilterItem();
@@ -238,6 +236,14 @@ namespace SabreTools.Library.Filtering
public FilterItem DatItem_Location_Name { get; private set; } = new FilterItem();
public FilterItem DatItem_Location_Number { get; private set; } = new FilterItem();
public FilterItem DatItem_Location_Inverted { get; private set; } = new FilterItem() { Neutral = null };
+
+ // Part
+ public FilterItem DatItem_Part_Name { get; private set; } = new FilterItem();
+ public FilterItem DatItem_Part_Interface { get; private set; } = new FilterItem();
+
+ // PartFeature
+ public FilterItem DatItem_Part_Feature_Name { get; private set; } = new FilterItem();
+ public FilterItem DatItem_Part_Feature_Value { get; private set; } = new FilterItem();
// RamOption
public FilterItem DatItem_Content { get; private set; } = new FilterItem();
@@ -643,25 +649,6 @@ namespace SabreTools.Library.Filtering
break;
// Rom (SoftwareList)
- case Field.DatItem_AreaName:
- SetStringFilter(DatItem_AreaName, value, negate);
- break;
-
- case Field.DatItem_AreaSize:
- SetOptionalLongFilter(DatItem_AreaSize, value, negate);
- break;
-
- case Field.DatItem_AreaWidth:
- SetOptionalLongFilter(DatItem_AreaWidth, value, negate);
- break;
-
- case Field.DatItem_AreaEndianness:
- if (negate)
- DatItem_AreaEndianness.Negative |= value.AsEndianness();
- else
- DatItem_AreaEndianness.Positive |= value.AsEndianness();
- break;
-
case Field.DatItem_LoadFlag:
if (negate)
DatItem_LoadFlag.Negative |= value.AsLoadFlag();
@@ -669,22 +656,6 @@ namespace SabreTools.Library.Filtering
DatItem_LoadFlag.Positive |= value.AsLoadFlag();
break;
- case Field.DatItem_Part_Name:
- SetStringFilter(DatItem_Part_Name, value, negate);
- break;
-
- case Field.DatItem_Part_Interface:
- SetStringFilter(DatItem_Part_Interface, value, negate);
- break;
-
- case Field.DatItem_Part_Feature_Name:
- SetStringFilter(DatItem_Part_Feature_Name, value, negate);
- break;
-
- case Field.DatItem_Part_Feature_Value:
- SetStringFilter(DatItem_Part_Feature_Value, value, negate);
- break;
-
case Field.DatItem_Value:
SetStringFilter(DatItem_Value, value, negate);
break;
@@ -813,6 +784,26 @@ namespace SabreTools.Library.Filtering
SetStringFilter(DatItem_Control_Ways3, value, negate);
break;
+ // DataArea
+ case Field.DatItem_AreaName:
+ SetStringFilter(DatItem_AreaName, value, negate);
+ break;
+
+ case Field.DatItem_AreaSize:
+ SetOptionalLongFilter(DatItem_AreaSize, value, negate);
+ break;
+
+ case Field.DatItem_AreaWidth:
+ SetOptionalLongFilter(DatItem_AreaWidth, value, negate);
+ break;
+
+ case Field.DatItem_AreaEndianness:
+ if (negate)
+ DatItem_AreaEndianness.Negative |= value.AsEndianness();
+ else
+ DatItem_AreaEndianness.Positive |= value.AsEndianness();
+ break;
+
// Device
case Field.DatItem_DeviceType:
SetStringFilter(DatItem_DeviceType, value, negate);
@@ -981,6 +972,24 @@ namespace SabreTools.Library.Filtering
SetBooleanFilter(DatItem_Location_Inverted, value, negate);
break;
+ // Part
+ case Field.DatItem_Part_Name:
+ SetStringFilter(DatItem_Part_Name, value, negate);
+ break;
+
+ case Field.DatItem_Part_Interface:
+ SetStringFilter(DatItem_Part_Interface, value, negate);
+ break;
+
+ // PartFeature
+ case Field.DatItem_Part_Feature_Name:
+ SetStringFilter(DatItem_Part_Feature_Name, value, negate);
+ break;
+
+ case Field.DatItem_Part_Feature_Value:
+ SetStringFilter(DatItem_Part_Feature_Value, value, negate);
+ break;
+
// RamOption
case Field.DatItem_Content:
SetStringFilter(DatItem_Content, value, negate);
diff --git a/SabreTools.Library/Tools/Converters.cs b/SabreTools.Library/Tools/Converters.cs
index b61881d4..71ac0b0e 100644
--- a/SabreTools.Library/Tools/Converters.cs
+++ b/SabreTools.Library/Tools/Converters.cs
@@ -1635,6 +1635,8 @@ namespace SabreTools.Library.Tools
return ItemType.Configuration;
case "control":
return ItemType.Control;
+ case "dataarea":
+ return ItemType.DataArea;
case "device":
return ItemType.Device;
case "device_ref":
@@ -1643,6 +1645,8 @@ namespace SabreTools.Library.Tools
return ItemType.DipSwitch;
case "disk":
return ItemType.Disk;
+ case "diskarea":
+ return ItemType.DiskArea;
case "display":
return ItemType.Display;
case "driver":
@@ -1661,6 +1665,8 @@ namespace SabreTools.Library.Tools
return ItemType.Location;
case "media":
return ItemType.Media;
+ case "part":
+ return ItemType.Part;
case "partfeature":
case "part_feature":
return ItemType.PartFeature;
@@ -1701,10 +1707,12 @@ namespace SabreTools.Library.Tools
"condition" => ItemType.Condition,
"configuration" => ItemType.Configuration,
"control" => ItemType.Control,
+ "dataarea" => ItemType.DataArea,
"device" => ItemType.Device,
"device_ref" => ItemType.DeviceReference,
"dipswitch" => ItemType.DipSwitch,
"disk" => ItemType.Disk,
+ "diskarea" => ItemType.DiskArea,
"display" => ItemType.Display,
"driver" => ItemType.Driver,
"extension" => ItemType.Extension,
@@ -1714,6 +1722,7 @@ namespace SabreTools.Library.Tools
"instance" => ItemType.Instance,
"location" => ItemType.Location,
"media" => ItemType.Media,
+ "part" => ItemType.Part,
"partfeature" => ItemType.PartFeature,
"part_feature" => ItemType.PartFeature,
"port" => ItemType.Port,
@@ -2515,6 +2524,8 @@ namespace SabreTools.Library.Tools
return "configuration";
case ItemType.Control:
return "control";
+ case ItemType.DataArea:
+ return "dataarea";
case ItemType.Device:
return "device";
case ItemType.DeviceReference:
@@ -2523,6 +2534,8 @@ namespace SabreTools.Library.Tools
return "dipswitch";
case ItemType.Disk:
return "disk";
+ case ItemType.DiskArea:
+ return "diskarea";
case ItemType.Display:
return "display";
case ItemType.Driver:
@@ -2541,6 +2554,8 @@ namespace SabreTools.Library.Tools
return "location";
case ItemType.Media:
return "media";
+ case ItemType.Part:
+ return "part";
case ItemType.PartFeature:
return "part_feature";
case ItemType.Port:
@@ -2580,10 +2595,12 @@ namespace SabreTools.Library.Tools
ItemType.Condition => "condition",
ItemType.Configuration => "configuration",
ItemType.Control => "control",
+ ItemType.DataArea => "dataarea",
ItemType.Device => "device",
ItemType.DeviceReference => "device_ref",
ItemType.DipSwitch => "dipswitch",
ItemType.Disk => "disk",
+ ItemType.DiskArea => "diskarea",
ItemType.Display => "display",
ItemType.Driver => "driver",
ItemType.Extension => "extension",
@@ -2593,6 +2610,7 @@ namespace SabreTools.Library.Tools
ItemType.Instance => "instance",
ItemType.Location => "location",
ItemType.Media => "media",
+ ItemType.Part => "part",
ItemType.PartFeature => "part_feature",
ItemType.Port => "port",
ItemType.RamOption => "ramoption",