diff --git a/SabreTools.Library/DatFiles/ClrMamePro.cs b/SabreTools.Library/DatFiles/ClrMamePro.cs
index 5ad32231..4114150d 100644
--- a/SabreTools.Library/DatFiles/ClrMamePro.cs
+++ b/SabreTools.Library/DatFiles/ClrMamePro.cs
@@ -241,6 +241,9 @@ namespace SabreTools.Library.DatFiles
case "manufacturer":
machine.Manufacturer = itemVal;
break;
+ case "category":
+ machine.Category = itemVal;
+ break;
case "cloneof":
machine.CloneOf = itemVal;
break;
@@ -634,6 +637,8 @@ namespace SabreTools.Library.DatFiles
cmpw.WriteStandalone("year", datItem.Year);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Manufacturer, DatHeader.ExcludeFields)))
cmpw.WriteStandalone("manufacturer", datItem.Manufacturer);
+ if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Category, DatHeader.ExcludeFields)))
+ cmpw.WriteStandalone("category", datItem.Category);
cmpw.Flush();
}
diff --git a/SabreTools.Library/DatFiles/DatFile.cs b/SabreTools.Library/DatFiles/DatFile.cs
index bbd33c5d..3abcc10c 100644
--- a/SabreTools.Library/DatFiles/DatFile.cs
+++ b/SabreTools.Library/DatFiles/DatFile.cs
@@ -1147,6 +1147,9 @@ namespace SabreTools.Library.DatFiles
if (updateFields.Contains(Field.Publisher))
newDatItem.Publisher = firstDupe.Publisher;
+ if (updateFields.Contains(Field.Category))
+ newDatItem.Category = firstDupe.Category;
+
if (updateFields.Contains(Field.RomOf))
newDatItem.RomOf = firstDupe.RomOf;
@@ -3659,6 +3662,7 @@ namespace SabreTools.Library.DatFiles
name = item.Name,
manufacturer = item.Manufacturer,
publisher = item.Publisher,
+ category = item.Category,
crc = string.Empty,
md5 = string.Empty,
ripemd160 = string.Empty,
@@ -3709,6 +3713,7 @@ namespace SabreTools.Library.DatFiles
.Replace("%name%", name)
.Replace("%manufacturer%", manufacturer)
.Replace("%publisher%", publisher)
+ .Replace("%category%", category)
.Replace("%crc%", crc)
.Replace("%md5%", md5)
.Replace("%ripemd160%", ripemd160)
diff --git a/SabreTools.Library/DatFiles/Filter.cs b/SabreTools.Library/DatFiles/Filter.cs
index c2cc7555..de9ef15c 100644
--- a/SabreTools.Library/DatFiles/Filter.cs
+++ b/SabreTools.Library/DatFiles/Filter.cs
@@ -15,138 +15,284 @@ namespace SabreTools.Library.DatFiles
///
/// Represents the filtering operations that need to be performed on a set of items, usually a DAT
///
- /// TODO: Can this use `Field` instead of explicit filters?
+ /// TODO: Can clever use of Filtering allow for easier external splitting methods?
public class Filter
{
- #region Pubically facing variables
+ #region Private instance variables
#region Machine Filters
///
/// Include or exclude machine names
///
- public FilterItem MachineName { get; set; } = new FilterItem();
+ private FilterItem MachineName = new FilterItem();
///
- /// Include romof and cloneof when filtering machine names
+ /// Include or exclude machine comments
///
- public FilterItem IncludeOfInGame { get; set; } = new FilterItem() { Neutral = false };
+ private FilterItem Comment = new FilterItem();
///
/// Include or exclude machine descriptions
///
- public FilterItem MachineDescription { get; set; } = new FilterItem();
+ private FilterItem MachineDescription = new FilterItem();
///
- /// Include or exclude machine types
+ /// Include or exclude machine years
///
- public FilterItem MachineTypes { get; set; } = new FilterItem() { Positive = MachineType.NULL, Negative = MachineType.NULL };
+ private FilterItem Year = new FilterItem();
+
+ ///
+ /// Include or exclude machine manufacturers
+ ///
+ private FilterItem Manufacturer = new FilterItem();
+
+ ///
+ /// Include or exclude machine publishers
+ ///
+ private FilterItem Publisher = new FilterItem();
+
+ ///
+ /// Include or exclude machine categories
+ ///
+ private FilterItem Category = new FilterItem();
+
+ ///
+ /// Include or exclude machine romof
+ ///
+ private FilterItem RomOf = new FilterItem();
+
+ ///
+ /// Include or exclude machine cloneof
+ ///
+ private FilterItem CloneOf = new FilterItem();
+
+ ///
+ /// Include or exclude machine sampleof
+ ///
+ private FilterItem SampleOf = new FilterItem();
+
+ ///
+ /// Include or exclude items with the "Supported" tag
+ ///
+ private FilterItem Supported = new FilterItem() { Neutral = null };
+
+ ///
+ /// Include or exclude machine source file
+ ///
+ private FilterItem SourceFile = new FilterItem();
///
/// Include or exclude items with the "Runnable" tag
///
- public FilterItem Runnable { get; set; } = new FilterItem() { Neutral = null };
+ private FilterItem Runnable = new FilterItem() { Neutral = null };
+
+ ///
+ /// Include or exclude machine board
+ ///
+ private FilterItem Board = new FilterItem();
+
+ ///
+ /// Include or exclude machine rebuildto
+ ///
+ private FilterItem RebuildTo = new FilterItem();
+
+ // TODO: Machine.Devices - List
+ // TODO: Machine.SlotOptions - List
+ // TODO: Machine.Infos - List>
+
+ ///
+ /// Include or exclude machine types
+ ///
+ private FilterItem MachineTypes = new FilterItem() { Positive = MachineType.NULL, Negative = MachineType.NULL };
#endregion
#region DatItem Filters
- ///
- /// Include or exclude item names
- ///
- public FilterItem ItemName { get; set; } = new FilterItem();
-
///
/// Include or exclude item types
///
- public FilterItem ItemTypes { get; set; } = new FilterItem();
+ private FilterItem ItemTypes = new FilterItem();
+
+ ///
+ /// Include or exclude item names
+ ///
+ private FilterItem ItemName = new FilterItem();
+
+ // TODO: DatItem.Features - List>
+
+ ///
+ /// Include or exclude part names
+ ///
+ private FilterItem PartName = new FilterItem();
+
+ ///
+ /// Include or exclude part interfaces
+ ///
+ private FilterItem PartInterface = new FilterItem();
+
+ ///
+ /// Include or exclude area names
+ ///
+ private FilterItem AreaName = new FilterItem();
+
+ ///
+ /// Include or exclude area sizes
+ ///
+ /// Positive means "Greater than or equal", Negative means "Less than or equal", Neutral means "Equal"
+ private FilterItem AreaSize = new FilterItem() { Positive = null, Negative = null, Neutral = null };
+
+ ///
+ /// Include or exclude items with the "Default" tag
+ ///
+ private FilterItem Default = new FilterItem() { Neutral = null };
+
+ ///
+ /// Include or exclude descriptions
+ ///
+ private FilterItem Description = new FilterItem();
///
/// Include or exclude item sizes
///
/// Positive means "Greater than or equal", Negative means "Less than or equal", Neutral means "Equal"
- public FilterItem Size { get; set; } = new FilterItem() { Positive = -1, Negative = -1, Neutral = -1 };
+ private FilterItem Size = new FilterItem() { Positive = -1, Negative = -1, Neutral = -1 };
///
/// Include or exclude CRC32 hashes
///
- public FilterItem CRC { get; set; } = new FilterItem();
+ private FilterItem CRC = new FilterItem();
///
/// Include or exclude MD5 hashes
///
- public FilterItem MD5 { get; set; } = new FilterItem();
+ private FilterItem MD5 = new FilterItem();
#if NET_FRAMEWORK
///
/// Include or exclude RIPEMD160 hashes
///
- public FilterItem RIPEMD160 { get; set; } = new FilterItem();
+ private FilterItem RIPEMD160 = new FilterItem();
#endif
///
/// Include or exclude SHA-1 hashes
///
- public FilterItem SHA1 { get; set; } = new FilterItem();
+ private FilterItem SHA1 = new FilterItem();
///
/// Include or exclude SHA-256 hashes
///
- public FilterItem SHA256 { get; set; } = new FilterItem();
+ private FilterItem SHA256 = new FilterItem();
///
/// Include or exclude SHA-384 hashes
///
- public FilterItem SHA384 { get; set; } = new FilterItem();
+ private FilterItem SHA384 = new FilterItem();
///
/// Include or exclude SHA-512 hashes
///
- public FilterItem SHA512 { get; set; } = new FilterItem();
+ private FilterItem SHA512 = new FilterItem();
+
+ ///
+ /// Include or exclude merge tags
+ ///
+ private FilterItem MergeTag = new FilterItem();
+
+ ///
+ /// Include or exclude regions
+ ///
+ private FilterItem Region = new FilterItem();
+
+ ///
+ /// Include or exclude indexes
+ ///
+ private FilterItem Index = new FilterItem();
+
+ ///
+ /// Include or exclude items with the "Writable" tag
+ ///
+ private FilterItem Writable = new FilterItem() { Neutral = null };
+
+ ///
+ /// Include or exclude items with the "Writable" tag
+ ///
+ private FilterItem Optional = new FilterItem() { Neutral = null };
///
/// Include or exclude item statuses
///
- public FilterItem ItemStatuses { get; set; } = new FilterItem() { Positive = ItemStatus.NULL, Negative = ItemStatus.NULL };
+ private FilterItem Status = new FilterItem() { Positive = ItemStatus.NULL, Negative = ItemStatus.NULL };
+
+ ///
+ /// Include or exclude languages
+ ///
+ private FilterItem Language = new FilterItem();
+
+ ///
+ /// Include or exclude dates
+ ///
+ private FilterItem Date = new FilterItem();
+
+ ///
+ /// Include or exclude bioses
+ ///
+ private FilterItem Bios = new FilterItem();
+
+ ///
+ /// Include or exclude offsets
+ ///
+ private FilterItem Offset = new FilterItem();
#endregion
- #region Manipulation Filters
+ #endregion // Private instance variables
+
+ #region Pubically facing variables
+
+ #region Manipulation Flags
///
/// Clean all names to WoD standards
///
- public FilterItem Clean { get; set; } = new FilterItem() { Neutral = false };
+ public bool Clean { get; set; }
///
/// Set Machine Description from Machine Name
///
- public FilterItem DescriptionAsName { get; set; } = new FilterItem() { Neutral = false };
+ public bool DescriptionAsName { get; set; }
+
+ ///
+ /// Include romof and cloneof when filtering machine names
+ ///
+ public bool IncludeOfInGame { get; set; }
///
/// Internally split a DatFile
///
- public FilterItem InternalSplit { get; set; } = new FilterItem() { Neutral = SplitType.None };
+ public SplitType InternalSplit { get; set; }
///
/// Remove all unicode characters
///
- public FilterItem RemoveUnicode { get; set; } = new FilterItem() { Neutral = false };
-
- ///
- /// Change all machine names to "!"
- ///
- public FilterItem Single { get; set; } = new FilterItem() { Neutral = false };
-
- ///
- /// Trim total machine and item name to not exceed NTFS limits
- ///
- public FilterItem Trim { get; set; } = new FilterItem() { Neutral = false };
+ public bool RemoveUnicode { get; set; }
///
/// Include root directory when determing trim sizes
///
- public FilterItem Root { get; set; } = new FilterItem() { Neutral = null };
+ public string Root { get; set; }
+
+ ///
+ /// Change all machine names to "!"
+ ///
+ public bool Single { get; set; }
+
+ ///
+ /// Trim total machine and item name to not exceed NTFS limits
+ ///
+ public bool Trim { get; set; }
#endregion
@@ -154,6 +300,456 @@ namespace SabreTools.Library.DatFiles
#region Instance methods
+ #region Filter Population
+
+ ///
+ /// Populate the filters object using a set of key:value filters
+ ///
+ /// List of key:value where ~key/!key is negated
+ public void PopulateFromList(List filters)
+ {
+ foreach (string filterPair in filters)
+ {
+ string filterPairTrimmed = filterPair.Trim('"', ' ', '\t');
+ bool negate = filterPairTrimmed.StartsWith("!")
+ || filterPairTrimmed.StartsWith("~")
+ || filterPairTrimmed.StartsWith("not-");
+ filterPairTrimmed = filterPairTrimmed.TrimStart('!', '~');
+ filterPairTrimmed = filterPairTrimmed.StartsWith("not-") ? filterPairTrimmed.Substring(4) : filterPairTrimmed;
+
+ string filterFieldString = filterPairTrimmed.Split(':')[0].ToLowerInvariant().Trim('"', ' ', '\t');
+ string filterValue = filterPairTrimmed.Substring(filterFieldString.Length + 1).Trim('"', ' ', '\t');
+
+ Field filterField = filterFieldString.AsField();
+ SetFilter(filterField, filterValue, negate);
+ }
+ }
+
+ ///
+ /// Set multiple filters from key
+ ///
+ /// Key for the filter to be set
+ /// List of values for the filter
+ /// True if negative filter, false otherwise
+ public void SetFilter(Field key, List values, bool negate)
+ {
+ foreach (string value in values)
+ {
+ SetFilter(key, value, negate);
+ }
+ }
+
+ ///
+ /// Set a single filter from key
+ ///
+ /// Key for the filter to be set
+ /// Value of the filter
+ /// True if negative filter, false otherwise
+ public void SetFilter(Field key, string value, bool negate)
+ {
+ switch (key)
+ {
+ #region Machine Filters
+
+ case Field.MachineName:
+ if (negate)
+ MachineName.NegativeSet.Add(value);
+ else
+ MachineName.PositiveSet.Add(value);
+ break;
+
+ case Field.Comment:
+ if (negate)
+ Comment.NegativeSet.Add(value);
+ else
+ Comment.PositiveSet.Add(value);
+ break;
+
+ case Field.Description:
+ if (negate)
+ MachineDescription.NegativeSet.Add(value);
+ else
+ MachineDescription.PositiveSet.Add(value);
+ break;
+
+ case Field.Year:
+ if (negate)
+ Year.NegativeSet.Add(value);
+ else
+ Year.PositiveSet.Add(value);
+ break;
+
+ case Field.Manufacturer:
+ if (negate)
+ Manufacturer.NegativeSet.Add(value);
+ else
+ Manufacturer.PositiveSet.Add(value);
+ break;
+
+ case Field.Publisher:
+ if (negate)
+ Publisher.NegativeSet.Add(value);
+ else
+ Publisher.PositiveSet.Add(value);
+ break;
+
+ case Field.Category:
+ if (negate)
+ Category.NegativeSet.Add(value);
+ else
+ Category.PositiveSet.Add(value);
+ break;
+
+ case Field.RomOf:
+ if (negate)
+ RomOf.NegativeSet.Add(value);
+ else
+ RomOf.PositiveSet.Add(value);
+ break;
+
+ case Field.CloneOf:
+ if (negate)
+ CloneOf.NegativeSet.Add(value);
+ else
+ CloneOf.PositiveSet.Add(value);
+ break;
+
+ case Field.SampleOf:
+ if (negate)
+ SampleOf.NegativeSet.Add(value);
+ else
+ SampleOf.PositiveSet.Add(value);
+ break;
+
+ case Field.Supported:
+ if (negate || value.Equals("false", StringComparison.OrdinalIgnoreCase))
+ Supported.Neutral = false;
+ else
+ Supported.Neutral = true;
+ break;
+
+ case Field.SourceFile:
+ if (negate)
+ SourceFile.NegativeSet.Add(value);
+ else
+ SourceFile.PositiveSet.Add(value);
+ break;
+
+ case Field.Runnable:
+ if (negate || value.Equals("false", StringComparison.OrdinalIgnoreCase))
+ Runnable.Neutral = false;
+ else
+ Runnable.Neutral = true;
+ break;
+
+ case Field.Board:
+ if (negate)
+ Board.NegativeSet.Add(value);
+ else
+ Board.PositiveSet.Add(value);
+ break;
+
+ case Field.RebuildTo:
+ if (negate)
+ RebuildTo.NegativeSet.Add(value);
+ else
+ RebuildTo.PositiveSet.Add(value);
+ break;
+
+ case Field.MachineType:
+ if (negate)
+ MachineTypes.Negative |= value.AsMachineType();
+ else
+ MachineTypes.Positive |= value.AsMachineType();
+ break;
+
+ #endregion
+
+ #region DatItem Filters
+
+ case Field.ItemType:
+ if (value.AsItemType() == null)
+ return;
+
+ if (negate)
+ ItemTypes.NegativeSet.Add(value);
+ else
+ ItemTypes.PositiveSet.Add(value);
+ break;
+
+ case Field.Name:
+ if (negate)
+ ItemName.NegativeSet.Add(value);
+ else
+ ItemName.PositiveSet.Add(value);
+ break;
+
+ case Field.PartName:
+ if (negate)
+ PartName.NegativeSet.Add(value);
+ else
+ PartName.PositiveSet.Add(value);
+ break;
+
+ case Field.PartInterface:
+ if (negate)
+ PartInterface.NegativeSet.Add(value);
+ else
+ PartInterface.PositiveSet.Add(value);
+ break;
+
+ case Field.AreaName:
+ if (negate)
+ AreaName.NegativeSet.Add(value);
+ else
+ AreaName.PositiveSet.Add(value);
+ break;
+
+ case Field.AreaSize:
+ bool? asOperation = null;
+ if (value.StartsWith(">"))
+ asOperation = true;
+ else if (value.StartsWith("<"))
+ asOperation = false;
+ else if (value.StartsWith("="))
+ asOperation = null;
+
+ string areasizeString = value.TrimStart('>', '<', '=');
+ if (!Int64.TryParse(areasizeString, out long areasize))
+ return;
+
+ // Equal
+ if (asOperation == null && !negate)
+ {
+ AreaSize.Neutral = areasize;
+ }
+
+ // Not Equal
+ else if (asOperation == null && negate)
+ {
+ AreaSize.Negative = areasize - 1;
+ AreaSize.Positive = areasize + 1;
+ }
+
+ // Greater Than or Equal
+ else if (asOperation == true && !negate)
+ {
+ AreaSize.Positive = areasize;
+ }
+
+ // Strictly Less Than
+ else if (asOperation == true && negate)
+ {
+ AreaSize.Negative = areasize - 1;
+ }
+
+ // Less Than or Equal
+ else if (asOperation == false && !negate)
+ {
+ AreaSize.Negative = areasize;
+ }
+
+ // Strictly Greater Than
+ else if (asOperation == false && negate)
+ {
+ AreaSize.Positive = areasize + 1;
+ }
+
+ break;
+
+ case Field.Default:
+ if (negate || value.Equals("false", StringComparison.OrdinalIgnoreCase))
+ Default.Neutral = false;
+ else
+ Default.Neutral = true;
+ break;
+
+ case Field.BiosDescription:
+ if (negate)
+ Description.NegativeSet.Add(value);
+ else
+ Description.PositiveSet.Add(value);
+ break;
+
+ case Field.Size:
+ bool? sOperation = null;
+ if (value.StartsWith(">"))
+ sOperation = true;
+ else if (value.StartsWith("<"))
+ sOperation = false;
+ else if (value.StartsWith("="))
+ sOperation = null;
+
+ string sizeString = value.TrimStart('>', '<', '=');
+ if (!Int64.TryParse(sizeString, out long size))
+ return;
+
+ // Equal
+ if (sOperation == null && !negate)
+ {
+ Size.Neutral = size;
+ }
+
+ // Not Equal
+ else if (sOperation == null && negate)
+ {
+ Size.Negative = size - 1;
+ Size.Positive = size + 1;
+ }
+
+ // Greater Than or Equal
+ else if (sOperation == true && !negate)
+ {
+ Size.Positive = size;
+ }
+
+ // Strictly Less Than
+ else if (sOperation == true && negate)
+ {
+ Size.Negative = size - 1;
+ }
+
+ // Less Than or Equal
+ else if (sOperation == false && !negate)
+ {
+ Size.Negative = size;
+ }
+
+ // Strictly Greater Than
+ else if (sOperation == false && negate)
+ {
+ Size.Positive = size + 1;
+ }
+
+ break;
+
+ case Field.CRC:
+ if (negate)
+ CRC.NegativeSet.Add(value);
+ else
+ CRC.PositiveSet.Add(value);
+ break;
+
+ case Field.MD5:
+ if (negate)
+ MD5.NegativeSet.Add(value);
+ else
+ MD5.PositiveSet.Add(value);
+ break;
+
+#if NET_FRAMEWORK
+ case Field.RIPEMD160:
+ if (negate)
+ RIPEMD160.NegativeSet.Add(value);
+ else
+ RIPEMD160.PositiveSet.Add(value);
+ break;
+#endif
+
+ case Field.SHA1:
+ if (negate)
+ SHA1.NegativeSet.Add(value);
+ else
+ SHA1.PositiveSet.Add(value);
+ break;
+
+ case Field.SHA256:
+ if (negate)
+ SHA256.NegativeSet.Add(value);
+ else
+ SHA256.PositiveSet.Add(value);
+ break;
+
+ case Field.SHA384:
+ if (negate)
+ SHA384.NegativeSet.Add(value);
+ else
+ SHA384.PositiveSet.Add(value);
+ break;
+
+ case Field.SHA512:
+ if (negate)
+ SHA512.NegativeSet.Add(value);
+ else
+ SHA512.PositiveSet.Add(value);
+ break;
+
+ case Field.Merge:
+ if (negate)
+ MergeTag.NegativeSet.Add(value);
+ else
+ MergeTag.PositiveSet.Add(value);
+ break;
+
+ case Field.Region:
+ if (negate)
+ Region.NegativeSet.Add(value);
+ else
+ Region.PositiveSet.Add(value);
+ break;
+
+ case Field.Index:
+ if (negate)
+ Index.NegativeSet.Add(value);
+ else
+ Index.PositiveSet.Add(value);
+ break;
+
+ case Field.Writable:
+ if (negate || value.Equals("false", StringComparison.OrdinalIgnoreCase))
+ Writable.Neutral = false;
+ else
+ Writable.Neutral = true;
+ break;
+
+ case Field.Optional:
+ if (negate || value.Equals("false", StringComparison.OrdinalIgnoreCase))
+ Optional.Neutral = false;
+ else
+ Optional.Neutral = true;
+ break;
+
+ case Field.Status:
+ if (negate)
+ Status.Negative |= value.AsItemStatus();
+ else
+ Status.Positive |= value.AsItemStatus();
+ break;
+
+ case Field.Language:
+ if (negate)
+ Language.NegativeSet.Add(value);
+ else
+ Language.PositiveSet.Add(value);
+ break;
+
+ case Field.Date:
+ if (negate)
+ Date.NegativeSet.Add(value);
+ else
+ Date.PositiveSet.Add(value);
+ break;
+
+ case Field.Bios:
+ if (negate)
+ Bios.NegativeSet.Add(value);
+ else
+ Bios.PositiveSet.Add(value);
+ break;
+
+ case Field.Offset:
+ if (negate)
+ Offset.NegativeSet.Add(value);
+ else
+ Offset.PositiveSet.Add(value);
+ break;
+
+ #endregion
+ }
+ }
+
+ #endregion
+
///
/// Filter a DatFile using the inputs
///
@@ -177,7 +773,7 @@ namespace SabreTools.Library.DatFiles
if (ItemPasses(item))
{
// If we're stripping unicode characters, do so from all relevant things
- if (this.RemoveUnicode.Neutral)
+ if (this.RemoveUnicode)
{
item.Name = Sanitizer.RemoveUnicodeCharacters(item.Name);
item.MachineName = Sanitizer.RemoveUnicodeCharacters(item.MachineName);
@@ -185,21 +781,21 @@ namespace SabreTools.Library.DatFiles
}
// If we're in cleaning mode, do so from all relevant things
- if (this.Clean.Neutral)
+ if (this.Clean)
{
item.MachineName = Sanitizer.CleanGameName(item.MachineName);
item.MachineDescription = Sanitizer.CleanGameName(item.MachineDescription);
}
// If we are in single game mode, rename all games
- if (this.Single.Neutral)
+ if (this.Single)
item.MachineName = "!";
// If we are in NTFS trim mode, trim the game name
- if (this.Trim.Neutral)
+ if (this.Trim)
{
// Windows max name length is 260
- int usableLength = 260 - item.MachineName.Length - this.Root.Neutral.Length;
+ int usableLength = 260 - item.MachineName.Length - this.Root.Length;
if (item.Name.Length > usableLength)
{
string ext = Path.GetExtension(item.Name);
@@ -221,15 +817,15 @@ namespace SabreTools.Library.DatFiles
}
// Process description to machine name
- if (this.DescriptionAsName.Neutral)
+ if (this.DescriptionAsName)
MachineDescriptionToName(datFile);
// If we are using tags from the DAT, set the proper input for split type unless overridden
- if (useTags && this.InternalSplit.Neutral == SplitType.None)
- this.InternalSplit.Neutral = datFile.DatHeader.ForceMerging.AsSplitType();
+ if (useTags && this.InternalSplit == SplitType.None)
+ this.InternalSplit = datFile.DatHeader.ForceMerging.AsSplitType();
// Run internal splitting
- ProcessSplitType(datFile, this.InternalSplit.Neutral);
+ ProcessSplitType(datFile, this.InternalSplit);
// We remove any blanks, if we aren't supposed to have any
if (!datFile.DatHeader.KeepEmptyGames)
@@ -261,6 +857,114 @@ namespace SabreTools.Library.DatFiles
return true;
}
+ ///
+ /// Filter a DatFile outputting to a new DatFile
+ ///
+ /// DatFile to filter
+ /// True if DatFile tags override splitting, false otherwise
+ /// True if the DatFile was filtered, false on error
+ public DatFile FilterTo(DatFile datFile, bool useTags)
+ {
+ DatFile outDat = DatFile.Create(datFile.DatHeader);
+
+ try
+ {
+ // Loop over every key in the dictionary
+ List keys = datFile.Keys;
+ foreach (string key in keys)
+ {
+ // For every item in the current key
+ List items = datFile[key];
+ List newitems = new List();
+ foreach (DatItem item in items)
+ {
+ // If the rom passes the filter, include it
+ if (ItemPasses(item))
+ {
+ // If we're stripping unicode characters, do so from all relevant things
+ if (this.RemoveUnicode)
+ {
+ item.Name = Sanitizer.RemoveUnicodeCharacters(item.Name);
+ item.MachineName = Sanitizer.RemoveUnicodeCharacters(item.MachineName);
+ item.MachineDescription = Sanitizer.RemoveUnicodeCharacters(item.MachineDescription);
+ }
+
+ // If we're in cleaning mode, do so from all relevant things
+ if (this.Clean)
+ {
+ item.MachineName = Sanitizer.CleanGameName(item.MachineName);
+ item.MachineDescription = Sanitizer.CleanGameName(item.MachineDescription);
+ }
+
+ // If we are in single game mode, rename all games
+ if (this.Single)
+ item.MachineName = "!";
+
+ // If we are in NTFS trim mode, trim the game name
+ if (this.Trim)
+ {
+ // Windows max name length is 260
+ int usableLength = 260 - item.MachineName.Length - this.Root.Length;
+ if (item.Name.Length > usableLength)
+ {
+ string ext = Path.GetExtension(item.Name);
+ item.Name = item.Name.Substring(0, usableLength - ext.Length);
+ item.Name += ext;
+ }
+ }
+
+ // Lock the list and add the item back
+ lock (newitems)
+ {
+ newitems.Add(item);
+ }
+ }
+ }
+
+ outDat.AddRange(key, newitems);
+ }
+
+ // Process description to machine name
+ if (this.DescriptionAsName)
+ MachineDescriptionToName(outDat);
+
+ // If we are using tags from the DAT, set the proper input for split type unless overridden
+ if (useTags && this.InternalSplit == SplitType.None)
+ this.InternalSplit = outDat.DatHeader.ForceMerging.AsSplitType();
+
+ // Run internal splitting
+ ProcessSplitType(outDat, this.InternalSplit);
+
+ // We remove any blanks, if we aren't supposed to have any
+ if (!outDat.DatHeader.KeepEmptyGames)
+ {
+ foreach (string key in outDat.Keys)
+ {
+ List items = outDat[key];
+ List newitems = items.Where(i => i.ItemType != ItemType.Blank).ToList();
+
+ outDat.Remove(key);
+ outDat.AddRange(key, newitems);
+ }
+ }
+
+ // If we are removing scene dates, do that now
+ if (outDat.DatHeader.SceneDateStrip)
+ StripSceneDatesFromItems(outDat);
+
+ // Run the one rom per game logic, if required
+ if (outDat.DatHeader.OneRom)
+ OneRomPerGame(outDat);
+ }
+ catch (Exception ex)
+ {
+ Globals.Logger.Error(ex.ToString());
+ return null;
+ }
+
+ return outDat;
+ }
+
///
/// Check to see if a DatItem passes the filter
///
@@ -272,131 +976,11 @@ namespace SabreTools.Library.DatFiles
if (item == null)
return false;
- // Filter on machine type
- if (this.MachineTypes.MatchesPositive(MachineType.NULL, item.MachineType) == false)
- return false;
- if (this.MachineTypes.MatchesNegative(MachineType.NULL, item.MachineType) == true)
- return false;
-
- // Filter on machine runability
- if (this.Runnable.MatchesNeutral(null, item.Runnable) == false)
- return false;
-
- // Take care of Rom and Disk specific differences
- if (item.ItemType == ItemType.Rom)
- {
- Rom rom = (Rom)item;
-
- // Filter on status
- if (this.ItemStatuses.MatchesPositive(ItemStatus.NULL, rom.ItemStatus) == false)
- return false;
- if (this.ItemStatuses.MatchesNegative(ItemStatus.NULL, rom.ItemStatus) == true)
- return false;
-
- // Filter on rom size
- if (this.Size.MatchesNeutral(-1, rom.Size) == false)
- return false;
- else if (this.Size.MatchesPositive(-1, rom.Size) == false)
- return false;
- else if (this.Size.MatchesNegative(-1, rom.Size) == false)
- return false;
-
- // Filter on CRC
- if (this.CRC.MatchesPositiveSet(rom.CRC) == false)
- return false;
- if (this.CRC.MatchesNegativeSet(rom.CRC) == true)
- return false;
-
- // Filter on MD5
- if (this.MD5.MatchesPositiveSet(rom.MD5) == false)
- return false;
- if (this.MD5.MatchesNegativeSet(rom.MD5) == true)
- return false;
-
-#if NET_FRAMEWORK
- // Filter on RIPEMD160
- if (this.RIPEMD160.MatchesPositiveSet(rom.RIPEMD160) == false)
- return false;
- if (this.RIPEMD160.MatchesNegativeSet(rom.RIPEMD160) == true)
- return false;
-#endif
-
- // Filter on SHA-1
- if (this.SHA1.MatchesPositiveSet(rom.SHA1) == false)
- return false;
- if (this.SHA1.MatchesNegativeSet(rom.SHA1) == true)
- return false;
-
- // Filter on SHA-256
- if (this.SHA256.MatchesPositiveSet(rom.SHA256) == false)
- return false;
- if (this.SHA256.MatchesNegativeSet(rom.SHA256) == true)
- return false;
-
- // Filter on SHA-384
- if (this.SHA384.MatchesPositiveSet(rom.SHA384) == false)
- return false;
- if (this.SHA384.MatchesNegativeSet(rom.SHA384) == true)
- return false;
-
- // Filter on SHA-512
- if (this.SHA512.MatchesPositiveSet(rom.SHA512) == false)
- return false;
- if (this.SHA512.MatchesNegativeSet(rom.SHA512) == true)
- return false;
- }
- else if (item.ItemType == ItemType.Disk)
- {
- Disk rom = (Disk)item;
-
- // Filter on status
- if (this.ItemStatuses.MatchesPositive(ItemStatus.NULL, rom.ItemStatus) == false)
- return false;
- if (this.ItemStatuses.MatchesNegative(ItemStatus.NULL, rom.ItemStatus) == true)
- return false;
-
- // Filter on MD5
- if (this.MD5.MatchesPositiveSet(rom.MD5) == false)
- return false;
- if (this.MD5.MatchesNegativeSet(rom.MD5) == true)
- return false;
-
-#if NET_FRAMEWORK
- // Filter on RIPEMD160
- if (this.RIPEMD160.MatchesPositiveSet(rom.RIPEMD160) == false)
- return false;
- if (this.RIPEMD160.MatchesNegativeSet(rom.RIPEMD160) == true)
- return false;
-#endif
-
- // Filter on SHA-1
- if (this.SHA1.MatchesPositiveSet(rom.SHA1) == false)
- return false;
- if (this.SHA1.MatchesNegativeSet(rom.SHA1) == true)
- return false;
-
- // Filter on SHA-256
- if (this.SHA256.MatchesPositiveSet(rom.SHA256) == false)
- return false;
- if (this.SHA256.MatchesNegativeSet(rom.SHA256) == true)
- return false;
-
- // Filter on SHA-384
- if (this.SHA384.MatchesPositiveSet(rom.SHA384) == false)
- return false;
- if (this.SHA384.MatchesNegativeSet(rom.SHA384) == true)
- return false;
-
- // Filter on SHA-512
- if (this.SHA512.MatchesPositiveSet(rom.SHA512) == false)
- return false;
- if (this.SHA512.MatchesNegativeSet(rom.SHA512) == true)
- return false;
- }
+ #region Machine Filters
// Filter on machine name
bool? machineNameFound = this.MachineName.MatchesPositiveSet(item.MachineName);
- if (this.IncludeOfInGame.Neutral)
+ if (this.IncludeOfInGame)
{
machineNameFound |= (this.MachineName.MatchesPositiveSet(item.CloneOf) == true);
machineNameFound |= (this.MachineName.MatchesPositiveSet(item.RomOf) == true);
@@ -405,7 +989,7 @@ namespace SabreTools.Library.DatFiles
return false;
machineNameFound = this.MachineName.MatchesNegativeSet(item.MachineName);
- if (this.IncludeOfInGame.Neutral)
+ if (this.IncludeOfInGame)
{
machineNameFound |= (this.MachineName.MatchesNegativeSet(item.CloneOf) == true);
machineNameFound |= (this.MachineName.MatchesNegativeSet(item.RomOf) == true);
@@ -413,19 +997,98 @@ namespace SabreTools.Library.DatFiles
if (machineNameFound == false)
return false;
+ // Filter on comment
+ if (this.Comment.MatchesPositiveSet(item.Comment) == false)
+ return false;
+ if (this.Comment.MatchesNegativeSet(item.Comment) == true)
+ return false;
+
// Filter on machine description
if (this.MachineDescription.MatchesPositiveSet(item.MachineDescription) == false)
return false;
if (this.MachineDescription.MatchesNegativeSet(item.MachineDescription) == true)
return false;
- // Filter on item name
- if (this.ItemName.MatchesPositiveSet(item.Name) == false)
+ // Filter on year
+ if (this.Year.MatchesPositiveSet(item.Year) == false)
return false;
- if (this.ItemName.MatchesNegativeSet(item.Name) == true)
+ if (this.Year.MatchesNegativeSet(item.Year) == true)
return false;
+ // Filter on manufacturer
+ if (this.Manufacturer.MatchesPositiveSet(item.Manufacturer) == false)
+ return false;
+ if (this.Manufacturer.MatchesNegativeSet(item.Manufacturer) == true)
+ return false;
+
+ // Filter on publisher
+ if (this.Publisher.MatchesPositiveSet(item.Publisher) == false)
+ return false;
+ if (this.Publisher.MatchesNegativeSet(item.Publisher) == true)
+ return false;
+
+ // Filter on category
+ if (this.Category.MatchesPositiveSet(item.Category) == false)
+ return false;
+ if (this.Category.MatchesNegativeSet(item.Category) == true)
+ return false;
+
+ // Filter on romof
+ if (this.RomOf.MatchesPositiveSet(item.RomOf) == false)
+ return false;
+ if (this.RomOf.MatchesNegativeSet(item.RomOf) == true)
+ return false;
+
+ // Filter on cloneof
+ if (this.CloneOf.MatchesPositiveSet(item.CloneOf) == false)
+ return false;
+ if (this.CloneOf.MatchesNegativeSet(item.CloneOf) == true)
+ return false;
+
+ // Filter on sampleof
+ if (this.SampleOf.MatchesPositiveSet(item.SampleOf) == false)
+ return false;
+ if (this.SampleOf.MatchesNegativeSet(item.SampleOf) == true)
+ return false;
+
+ // Filter on supported
+ if (this.Supported.MatchesNeutral(null, item.Supported) == false)
+ return false;
+
+ // Filter on source file
+ if (this.SourceFile.MatchesPositiveSet(item.SourceFile) == false)
+ return false;
+ if (this.SourceFile.MatchesNegativeSet(item.SourceFile) == true)
+ return false;
+
+ // Filter on runnable
+ if (this.Runnable.MatchesNeutral(null, item.Runnable) == false)
+ return false;
+
+ // Filter on board
+ if (this.Board.MatchesPositiveSet(item.Board) == false)
+ return false;
+ if (this.Board.MatchesNegativeSet(item.Board) == true)
+ return false;
+
+ // Filter on rebuildto
+ if (this.RebuildTo.MatchesPositiveSet(item.RebuildTo) == false)
+ return false;
+ if (this.RebuildTo.MatchesNegativeSet(item.RebuildTo) == true)
+ return false;
+
+ // Filter on machine type
+ if (this.MachineTypes.MatchesPositive(MachineType.NULL, item.MachineType) == false)
+ return false;
+ if (this.MachineTypes.MatchesNegative(MachineType.NULL, item.MachineType) == true)
+ return false;
+
+ #endregion
+
+ #region DatItem Filters
+
// Filter on item type
+ // TODO: Remove default filtering at some point
if (this.ItemTypes.PositiveSet.Count == 0 && this.ItemTypes.NegativeSet.Count == 0
&& item.ItemType != ItemType.Rom && item.ItemType != ItemType.Disk && item.ItemType != ItemType.Blank)
return false;
@@ -434,6 +1097,268 @@ namespace SabreTools.Library.DatFiles
if (this.ItemTypes.MatchesNegativeSet(item.ItemType.ToString()) == true)
return false;
+ // Filter on item name
+ if (this.ItemName.MatchesPositiveSet(item.Name) == false)
+ return false;
+ if (this.ItemName.MatchesNegativeSet(item.Name) == true)
+ return false;
+
+ // Filter on part name
+ if (this.PartName.MatchesPositiveSet(item.PartName) == false)
+ return false;
+ if (this.PartName.MatchesNegativeSet(item.PartName) == true)
+ return false;
+
+ // Filter on part interface
+ if (this.PartInterface.MatchesPositiveSet(item.PartInterface) == false)
+ return false;
+ if (this.PartInterface.MatchesNegativeSet(item.PartInterface) == true)
+ return false;
+
+ // Filter on area name
+ if (this.AreaName.MatchesPositiveSet(item.AreaName) == false)
+ return false;
+ if (this.AreaName.MatchesNegativeSet(item.AreaName) == true)
+ return false;
+
+ // Filter on area size
+ if (this.AreaSize.MatchesNeutral(null, item.AreaSize) == false)
+ return false;
+ else if (this.AreaSize.MatchesPositive(null, item.AreaSize) == false)
+ return false;
+ else if (this.AreaSize.MatchesNegative(null, item.AreaSize) == false)
+ return false;
+
+ // Take care of item-specific differences
+ switch (item.ItemType)
+ {
+ case ItemType.Archive:
+ // Archive has no special fields
+ break;
+
+ case ItemType.BiosSet:
+ BiosSet biosSet = (BiosSet)item;
+
+ // Filter on description
+ if (this.Description.MatchesNeutral(null, biosSet.Description) == false)
+ return false;
+
+ // Filter on default
+ if (this.Default.MatchesNeutral(null, biosSet.Default) == false)
+ return false;
+
+ break;
+
+ case ItemType.Blank:
+ // Blank has no special fields
+ break;
+
+ case ItemType.Disk:
+ Disk disk = (Disk)item;
+
+ // Filter on MD5
+ if (this.MD5.MatchesPositiveSet(disk.MD5) == false)
+ return false;
+ if (this.MD5.MatchesNegativeSet(disk.MD5) == true)
+ return false;
+
+#if NET_FRAMEWORK
+ // Filter on RIPEMD160
+ if (this.RIPEMD160.MatchesPositiveSet(disk.RIPEMD160) == false)
+ return false;
+ if (this.RIPEMD160.MatchesNegativeSet(disk.RIPEMD160) == true)
+ return false;
+#endif
+
+ // Filter on SHA-1
+ if (this.SHA1.MatchesPositiveSet(disk.SHA1) == false)
+ return false;
+ if (this.SHA1.MatchesNegativeSet(disk.SHA1) == true)
+ return false;
+
+ // Filter on SHA-256
+ if (this.SHA256.MatchesPositiveSet(disk.SHA256) == false)
+ return false;
+ if (this.SHA256.MatchesNegativeSet(disk.SHA256) == true)
+ return false;
+
+ // Filter on SHA-384
+ if (this.SHA384.MatchesPositiveSet(disk.SHA384) == false)
+ return false;
+ if (this.SHA384.MatchesNegativeSet(disk.SHA384) == true)
+ return false;
+
+ // Filter on SHA-512
+ if (this.SHA512.MatchesPositiveSet(disk.SHA512) == false)
+ return false;
+ if (this.SHA512.MatchesNegativeSet(disk.SHA512) == true)
+ return false;
+
+ // Filter on merge tag
+ if (this.MergeTag.MatchesPositiveSet(disk.MergeTag) == false)
+ return false;
+ if (this.MergeTag.MatchesNegativeSet(disk.MergeTag) == true)
+ return false;
+
+ // Filter on region
+ if (this.Region.MatchesPositiveSet(disk.Region) == false)
+ return false;
+ if (this.Region.MatchesNegativeSet(disk.Region) == true)
+ return false;
+
+ // Filter on index
+ if (this.Index.MatchesPositiveSet(disk.Index) == false)
+ return false;
+ if (this.Index.MatchesNegativeSet(disk.Index) == true)
+ return false;
+
+ // Filter on writable
+ if (this.Writable.MatchesNeutral(null, disk.Writable) == false)
+ return false;
+
+ // Filter on status
+ if (this.Status.MatchesPositive(ItemStatus.NULL, disk.ItemStatus) == false)
+ return false;
+ if (this.Status.MatchesNegative(ItemStatus.NULL, disk.ItemStatus) == true)
+ return false;
+
+ // Filter on optional
+ if (this.Optional.MatchesNeutral(null, disk.Optional) == false)
+ return false;
+
+ break;
+
+ case ItemType.Release:
+ Release release = (Release)item;
+
+ // Filter on region
+ if (this.Region.MatchesPositiveSet(release.Region) == false)
+ return false;
+ if (this.Region.MatchesNegativeSet(release.Region) == true)
+ return false;
+
+ // Filter on language
+ if (this.Language.MatchesPositiveSet(release.Language) == false)
+ return false;
+ if (this.Language.MatchesNegativeSet(release.Language) == true)
+ return false;
+
+ // Filter on date
+ if (this.Date.MatchesPositiveSet(release.Date) == false)
+ return false;
+ if (this.Date.MatchesNegativeSet(release.Date) == true)
+ return false;
+
+ // Filter on default
+ if (this.Default.MatchesNeutral(null, release.Default) == false)
+ return false;
+
+ break;
+
+ case ItemType.Rom:
+ Rom rom = (Rom)item;
+
+ // Filter on bios
+ if (this.Bios.MatchesPositiveSet(rom.Bios) == false)
+ return false;
+ if (this.Bios.MatchesNegativeSet(rom.Bios) == true)
+ return false;
+
+ // Filter on rom size
+ if (this.Size.MatchesNeutral(-1, rom.Size) == false)
+ return false;
+ else if (this.Size.MatchesPositive(-1, rom.Size) == false)
+ return false;
+ else if (this.Size.MatchesNegative(-1, rom.Size) == false)
+ return false;
+
+ // Filter on CRC
+ if (this.CRC.MatchesPositiveSet(rom.CRC) == false)
+ return false;
+ if (this.CRC.MatchesNegativeSet(rom.CRC) == true)
+ return false;
+
+ // Filter on MD5
+ if (this.MD5.MatchesPositiveSet(rom.MD5) == false)
+ return false;
+ if (this.MD5.MatchesNegativeSet(rom.MD5) == true)
+ return false;
+
+#if NET_FRAMEWORK
+ // Filter on RIPEMD160
+ if (this.RIPEMD160.MatchesPositiveSet(rom.RIPEMD160) == false)
+ return false;
+ if (this.RIPEMD160.MatchesNegativeSet(rom.RIPEMD160) == true)
+ return false;
+#endif
+
+ // Filter on SHA-1
+ if (this.SHA1.MatchesPositiveSet(rom.SHA1) == false)
+ return false;
+ if (this.SHA1.MatchesNegativeSet(rom.SHA1) == true)
+ return false;
+
+ // Filter on SHA-256
+ if (this.SHA256.MatchesPositiveSet(rom.SHA256) == false)
+ return false;
+ if (this.SHA256.MatchesNegativeSet(rom.SHA256) == true)
+ return false;
+
+ // Filter on SHA-384
+ if (this.SHA384.MatchesPositiveSet(rom.SHA384) == false)
+ return false;
+ if (this.SHA384.MatchesNegativeSet(rom.SHA384) == true)
+ return false;
+
+ // Filter on SHA-512
+ if (this.SHA512.MatchesPositiveSet(rom.SHA512) == false)
+ return false;
+ if (this.SHA512.MatchesNegativeSet(rom.SHA512) == true)
+ return false;
+
+ // Filter on merge tag
+ if (this.MergeTag.MatchesPositiveSet(rom.MergeTag) == false)
+ return false;
+ if (this.MergeTag.MatchesNegativeSet(rom.MergeTag) == true)
+ return false;
+
+ // Filter on region
+ if (this.Region.MatchesPositiveSet(rom.Region) == false)
+ return false;
+ if (this.Region.MatchesNegativeSet(rom.Region) == true)
+ return false;
+
+ // Filter on offset
+ if (this.Offset.MatchesPositiveSet(rom.Offset) == false)
+ return false;
+ if (this.Offset.MatchesNegativeSet(rom.Offset) == true)
+ return false;
+
+ // Filter on date
+ if (this.Date.MatchesPositiveSet(rom.Date) == false)
+ return false;
+ if (this.Date.MatchesNegativeSet(rom.Date) == true)
+ return false;
+
+ // Filter on status
+ if (this.Status.MatchesPositive(ItemStatus.NULL, rom.ItemStatus) == false)
+ return false;
+ if (this.Status.MatchesNegative(ItemStatus.NULL, rom.ItemStatus) == true)
+ return false;
+
+ // Filter on optional
+ if (this.Optional.MatchesNeutral(null, rom.Optional) == false)
+ return false;
+
+ break;
+
+ case ItemType.Sample:
+ // Sample has no special fields
+ break;
+ }
+
+ #endregion
+
return true;
}
@@ -639,7 +1564,7 @@ namespace SabreTools.Library.DatFiles
continue;
// If the game (is/is not) a bios, we want to continue
- if (dev ^ (datFile[game][0].MachineType.HasFlag(MachineType.Device)))
+ if (dev ^ (datFile[game][0].MachineType.HasFlag(Data.MachineType.Device)))
continue;
// If the game has no devices, we continue
@@ -801,14 +1726,14 @@ namespace SabreTools.Library.DatFiles
foreach (DatItem item in items)
{
// If the disk doesn't have a valid merge tag OR the merged file doesn't exist in the parent, then add it
- if (item.ItemType == ItemType.Disk && (((Disk)item).MergeTag == null || !datFile[parent].Select(i => i.Name).Contains(((Disk)item).MergeTag)))
+ if (item.ItemType == Data.ItemType.Disk && (((Disk)item).MergeTag == null || !datFile[parent].Select(i => i.Name).Contains(((Disk)item).MergeTag)))
{
item.CopyMachineInformation(copyFrom);
datFile.Add(parent, item);
}
// Otherwise, if the parent doesn't already contain the non-disk (or a merge-equivalent), add it
- else if (item.ItemType != ItemType.Disk && !datFile[parent].Contains(item))
+ else if (item.ItemType != Data.ItemType.Disk && !datFile[parent].Contains(item))
{
// Rename the child so it's in a subfolder
item.Name = $"{item.MachineName}\\{item.Name}";
@@ -836,8 +1761,8 @@ namespace SabreTools.Library.DatFiles
foreach (string game in games)
{
if (datFile[game].Count > 0
- && (datFile[game][0].MachineType.HasFlag(MachineType.Bios)
- || datFile[game][0].MachineType.HasFlag(MachineType.Device)))
+ && (datFile[game][0].MachineType.HasFlag(Data.MachineType.Bios)
+ || datFile[game][0].MachineType.HasFlag(Data.MachineType.Device)))
{
datFile.Remove(game);
}
@@ -860,7 +1785,7 @@ namespace SabreTools.Library.DatFiles
continue;
// If the game (is/is not) a bios, we want to continue
- if (bios ^ datFile[game][0].MachineType.HasFlag(MachineType.Bios))
+ if (bios ^ datFile[game][0].MachineType.HasFlag(Data.MachineType.Bios))
continue;
// Determine if the game has a parent or not
diff --git a/SabreTools.Library/DatFiles/Json.cs b/SabreTools.Library/DatFiles/Json.cs
index 2af6f384..43846891 100644
--- a/SabreTools.Library/DatFiles/Json.cs
+++ b/SabreTools.Library/DatFiles/Json.cs
@@ -317,6 +317,10 @@ namespace SabreTools.Library.DatFiles
machine.Publisher = jtr.ReadAsString();
break;
+ case "category":
+ machine.Category = jtr.ReadAsString();
+ break;
+
case "romof":
machine.RomOf = jtr.ReadAsString();
break;
@@ -1023,6 +1027,11 @@ namespace SabreTools.Library.DatFiles
jtw.WritePropertyName("publisher");
jtw.WriteValue(datItem.Publisher);
}
+ if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Category, DatHeader.ExcludeFields)))
+ {
+ jtw.WritePropertyName("category");
+ jtw.WriteValue(datItem.Category);
+ }
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RomOf, DatHeader.ExcludeFields)) && !string.Equals(datItem.MachineName, datItem.RomOf, StringComparison.OrdinalIgnoreCase))
{
jtw.WritePropertyName("romof");
diff --git a/SabreTools.Library/DatFiles/Listxml.cs b/SabreTools.Library/DatFiles/Listxml.cs
index 72aafb96..f3330ac6 100644
--- a/SabreTools.Library/DatFiles/Listxml.cs
+++ b/SabreTools.Library/DatFiles/Listxml.cs
@@ -716,6 +716,8 @@ namespace SabreTools.Library.DatFiles
xtw.WriteElementString("year", datItem.Year);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Publisher, DatHeader.ExcludeFields)))
xtw.WriteElementString("publisher", datItem.Publisher);
+ if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Category, DatHeader.ExcludeFields)))
+ xtw.WriteElementString("category", datItem.Category);
if (!DatHeader.ExcludeFields[(int)Field.Infos] && datItem.Infos != null && datItem.Infos.Count > 0)
{
diff --git a/SabreTools.Library/DatFiles/Logiqx.cs b/SabreTools.Library/DatFiles/Logiqx.cs
index 9974af4e..9cda841d 100644
--- a/SabreTools.Library/DatFiles/Logiqx.cs
+++ b/SabreTools.Library/DatFiles/Logiqx.cs
@@ -377,6 +377,10 @@ namespace SabreTools.Library.DatFiles
machine.Publisher = reader.ReadElementContentAsString();
break;
+ case "category": // Not technically supported but used by some legacy DATs
+ machine.Category = reader.ReadElementContentAsString();
+ break;
+
case "trurip": // This is special metadata unique to TruRip
ReadTruRip(reader.ReadSubtree(), machine);
@@ -588,7 +592,7 @@ namespace SabreTools.Library.DatFiles
break;
case "genre":
- reader.ReadElementContentAsString();
+ machine.Category = reader.ReadElementContentAsString();
break;
case "subgenre":
@@ -894,6 +898,8 @@ namespace SabreTools.Library.DatFiles
xtw.WriteElementString("publisher", datItem.Publisher);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Manufacturer, DatHeader.ExcludeFields)))
xtw.WriteElementString("manufacturer", datItem.Manufacturer);
+ if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Category, DatHeader.ExcludeFields)))
+ xtw.WriteElementString("category", datItem.Category);
xtw.Flush();
}
diff --git a/SabreTools.Library/DatFiles/SeparatedValue.cs b/SabreTools.Library/DatFiles/SeparatedValue.cs
index 0d69e64f..7525dbb7 100644
--- a/SabreTools.Library/DatFiles/SeparatedValue.cs
+++ b/SabreTools.Library/DatFiles/SeparatedValue.cs
@@ -213,6 +213,10 @@ namespace SabreTools.Library.DatFiles
machine.Publisher = value;
break;
+ case "Machine.Category":
+ machine.Category = value;
+ break;
+
case "Machine.RomOf":
machine.RomOf = value;
break;
diff --git a/SabreTools.Library/DatFiles/SoftwareList.cs b/SabreTools.Library/DatFiles/SoftwareList.cs
index 0a272730..9c8b73d0 100644
--- a/SabreTools.Library/DatFiles/SoftwareList.cs
+++ b/SabreTools.Library/DatFiles/SoftwareList.cs
@@ -174,6 +174,10 @@ namespace SabreTools.Library.DatFiles
machine.Publisher = reader.ReadElementContentAsString();
break;
+ case "category":
+ machine.Category = reader.ReadElementContentAsString();
+ break;
+
case "info":
machine.Infos.Add(new KeyValuePair(reader.GetAttribute("name"), reader.GetAttribute("value")));
reader.Read();
@@ -717,6 +721,8 @@ namespace SabreTools.Library.DatFiles
xtw.WriteElementString("year", datItem.Year);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Publisher, DatHeader.ExcludeFields)))
xtw.WriteElementString("publisher", datItem.Publisher);
+ if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Category, DatHeader.ExcludeFields)))
+ xtw.WriteElementString("category", datItem.Category);
if (!DatHeader.ExcludeFields[(int)Field.Infos] && datItem.Infos != null && datItem.Infos.Count > 0)
{
diff --git a/SabreTools.Library/DatItems/Archive.cs b/SabreTools.Library/DatItems/Archive.cs
index aafb1ee4..aee0343e 100644
--- a/SabreTools.Library/DatItems/Archive.cs
+++ b/SabreTools.Library/DatItems/Archive.cs
@@ -32,6 +32,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported,
Publisher = this.Publisher,
+ Category = this.Category,
Infos = this.Infos,
PartName = this.PartName,
PartInterface = this.PartInterface,
diff --git a/SabreTools.Library/DatItems/BiosSet.cs b/SabreTools.Library/DatItems/BiosSet.cs
index 775aa76d..1f745bab 100644
--- a/SabreTools.Library/DatItems/BiosSet.cs
+++ b/SabreTools.Library/DatItems/BiosSet.cs
@@ -49,6 +49,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported,
Publisher = this.Publisher,
+ Category = this.Category,
Infos = this.Infos,
PartName = this.PartName,
PartInterface = this.PartInterface,
diff --git a/SabreTools.Library/DatItems/Blank.cs b/SabreTools.Library/DatItems/Blank.cs
index b52295c2..993df723 100644
--- a/SabreTools.Library/DatItems/Blank.cs
+++ b/SabreTools.Library/DatItems/Blank.cs
@@ -32,6 +32,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported,
Publisher = this.Publisher,
+ Category = this.Category,
Infos = this.Infos,
PartName = this.PartName,
PartInterface = this.PartInterface,
diff --git a/SabreTools.Library/DatItems/DatItem.cs b/SabreTools.Library/DatItems/DatItem.cs
index 2bb7d6d2..633ac29c 100644
--- a/SabreTools.Library/DatItems/DatItem.cs
+++ b/SabreTools.Library/DatItems/DatItem.cs
@@ -206,6 +206,32 @@ namespace SabreTools.Library.DatItems
}
}
+ ///
+ /// Machine category, if available
+ ///
+ [JsonIgnore]
+ public string Category
+ {
+ get
+ {
+ if (_machine == null)
+ {
+ _machine = new Machine();
+ }
+
+ return _machine.Category;
+ }
+ set
+ {
+ if (_machine == null)
+ {
+ _machine = new Machine();
+ }
+
+ _machine.Category = value;
+ }
+ }
+
///
/// Machine romof parent
///
@@ -633,6 +659,9 @@ namespace SabreTools.Library.DatItems
case Field.Publisher:
fieldValue = this.Publisher;
break;
+ case Field.Category:
+ fieldValue = this.Category;
+ break;
case Field.RomOf:
fieldValue = this.RomOf;
break;
diff --git a/SabreTools.Library/DatItems/Disk.cs b/SabreTools.Library/DatItems/Disk.cs
index 615e2a29..04b46b3d 100644
--- a/SabreTools.Library/DatItems/Disk.cs
+++ b/SabreTools.Library/DatItems/Disk.cs
@@ -173,6 +173,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported,
Publisher = this.Publisher,
+ Category = this.Category,
Infos = this.Infos,
PartName = this.PartName,
PartInterface = this.PartInterface,
@@ -241,6 +242,7 @@ namespace SabreTools.Library.DatItems
Year = this.Year,
Manufacturer = this.Manufacturer,
Publisher = this.Publisher,
+ Category = this.Category,
RomOf = this.RomOf,
CloneOf = this.CloneOf,
SampleOf = this.SampleOf,
diff --git a/SabreTools.Library/DatItems/Machine.cs b/SabreTools.Library/DatItems/Machine.cs
index 89ab533b..3b10f24a 100644
--- a/SabreTools.Library/DatItems/Machine.cs
+++ b/SabreTools.Library/DatItems/Machine.cs
@@ -49,6 +49,12 @@ namespace SabreTools.Library.DatItems
[JsonProperty("publisher")]
public string Publisher { get; set; }
+ ///
+ /// Category, if available
+ ///
+ [JsonProperty("category")]
+ public string Category { get; set; }
+
///
/// fomof parent
///
@@ -138,6 +144,7 @@ namespace SabreTools.Library.DatItems
Year = null;
Manufacturer = null;
Publisher = null;
+ Category = null;
RomOf = null;
CloneOf = null;
SampleOf = null;
@@ -165,6 +172,7 @@ namespace SabreTools.Library.DatItems
Year = null;
Manufacturer = null;
Publisher = null;
+ Category = null;
RomOf = null;
CloneOf = null;
SampleOf = null;
@@ -197,6 +205,7 @@ namespace SabreTools.Library.DatItems
Year = this.Year,
Manufacturer = this.Manufacturer,
Publisher = this.Publisher,
+ Category = this.Category,
RomOf = this.RomOf,
CloneOf = this.CloneOf,
SampleOf = this.SampleOf,
diff --git a/SabreTools.Library/DatItems/Release.cs b/SabreTools.Library/DatItems/Release.cs
index b21246b8..fb848720 100644
--- a/SabreTools.Library/DatItems/Release.cs
+++ b/SabreTools.Library/DatItems/Release.cs
@@ -65,6 +65,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported,
Publisher = this.Publisher,
+ Category = this.Category,
Infos = this.Infos,
PartName = this.PartName,
PartInterface = this.PartInterface,
diff --git a/SabreTools.Library/DatItems/Rom.cs b/SabreTools.Library/DatItems/Rom.cs
index bef91677..2ebd12cf 100644
--- a/SabreTools.Library/DatItems/Rom.cs
+++ b/SabreTools.Library/DatItems/Rom.cs
@@ -220,6 +220,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported,
Publisher = this.Publisher,
+ Category = this.Category,
Infos = this.Infos,
PartName = this.PartName,
PartInterface = this.PartInterface,
diff --git a/SabreTools.Library/DatItems/Sample.cs b/SabreTools.Library/DatItems/Sample.cs
index 09e1275f..ad036ad7 100644
--- a/SabreTools.Library/DatItems/Sample.cs
+++ b/SabreTools.Library/DatItems/Sample.cs
@@ -32,6 +32,7 @@ namespace SabreTools.Library.DatItems
Supported = this.Supported,
Publisher = this.Publisher,
+ Category = this.Category,
Infos = this.Infos,
PartName = this.PartName,
PartInterface = this.PartInterface,
diff --git a/SabreTools.Library/Data/Enums.cs b/SabreTools.Library/Data/Enums.cs
index 8f89d17e..42a4e3e9 100644
--- a/SabreTools.Library/Data/Enums.cs
+++ b/SabreTools.Library/Data/Enums.cs
@@ -261,7 +261,6 @@
Game,
}
-
///
/// Determines the DAT deduplication type
///
@@ -351,6 +350,7 @@
NULL = 0,
// Generic DatItem
+ ItemType,
Name,
PartName,
PartInterface,
@@ -365,6 +365,7 @@
Year,
Manufacturer,
Publisher,
+ Category,
RomOf,
CloneOf,
SampleOf,
diff --git a/SabreTools.Library/README.1ST b/SabreTools.Library/README.1ST
index 7f9e890f..634b4bbe 100644
--- a/SabreTools.Library/README.1ST
+++ b/SabreTools.Library/README.1ST
@@ -334,6 +334,26 @@ Options:
compare against the input DATs. This flag forces all CHDs to be
treated like regular files.
+ -fi=, --filter= Filter a game/rom field with the given value(s)
+ Filter any valid item or machine field from inputs. Filters are input
+ in the form 'key:value' or '!key:value', where the '!' signifies 'not'
+ matching. Numeric values may also prefix the 'value' with '>', '<', or
+ '=' accordingly. Key examples include: romof, category, and game.
+ Additionally, the user can specify an exact match or full C#-style
+ regex for pattern matching. Multiple instances of this flag are
+ allowed.
+
+ -cat=, --category-filter= Filter by category
+ Include only items with this category in the output. Additionally,
+ the user can specify an exact match or full C#-style regex for
+ pattern matching. Multiple instances of this flag are allowed.
+
+ -ncat=, --not-category= Filter by not category
+ Include only items without this category in the output.
+ Additionally, the user can specify an exact match or full C#-style
+ regex for pattern matching. Multiple instances of this flag are
+ allowed.
+
-gn=, --game-name= Filter by game name
Include only items with this game name in the output. Additionally,
the user can specify an exact match or full C#-style regex for
@@ -950,6 +970,7 @@ Options:
- %name% - Replaced with the Rom name
- %manufacturer% - Replaced with game Manufacturer
- %publisher% - Replaced with game Publisher
+ - %category% - Replaced with game Category
- %crc% - Replaced with the CRC
- %md5% - Replaced with the MD5
- %ripemd160% - Replaced with the RIPEMD160 (.NET Framework 4.8 only)
@@ -1276,6 +1297,26 @@ Options:
second time, this will skip writing it. This can often speed up
the output process. [Both diff-cascade and diff-reverse-cascade]
+ -fi=, --filter= Filter a game/rom field with the given value(s)
+ Filter any valid item or machine field from inputs. Filters are input
+ in the form 'key:value' or '!key:value', where the '!' signifies 'not'
+ matching. Numeric values may also prefix the 'value' with '>', '<', or
+ '=' accordingly. Key examples include: romof, category, and game.
+ Additionally, the user can specify an exact match or full C#-style
+ regex for pattern matching. Multiple instances of this flag are
+ allowed.
+
+ -cat=, --category-filter= Filter by category
+ Include only items with this category in the output. Additionally,
+ the user can specify an exact match or full C#-style regex for
+ pattern matching. Multiple instances of this flag are allowed.
+
+ -ncat=, --not-category= Filter by not category
+ Include only items without this category in the output.
+ Additionally, the user can specify an exact match or full C#-style
+ regex for pattern matching. Multiple instances of this flag are
+ allowed.
+
-gn=, --game-name= Filter by game name
Include only items with this game name in the output. Additionally,
the user can specify an exact match or full C#-style regex for
@@ -1533,6 +1574,26 @@ Options:
parent sets based on the cloneof and romof tags as well as device
references. This is incompatible with the other --dat-X flags.
+ -fi=, --filter= Filter a game/rom field with the given value(s)
+ Filter any valid item or machine field from inputs. Filters are input
+ in the form 'key:value' or '!key:value', where the '!' signifies 'not'
+ matching. Numeric values may also prefix the 'value' with '>', '<', or
+ '=' accordingly. Key examples include: romof, category, and game.
+ Additionally, the user can specify an exact match or full C#-style
+ regex for pattern matching. Multiple instances of this flag are
+ allowed.
+
+ -cat=, --category-filter= Filter by category
+ Include only items with this category in the output. Additionally,
+ the user can specify an exact match or full C#-style regex for
+ pattern matching. Multiple instances of this flag are allowed.
+
+ -ncat=, --not-category= Filter by not category
+ Include only items without this category in the output.
+ Additionally, the user can specify an exact match or full C#-style
+ regex for pattern matching. Multiple instances of this flag are
+ allowed.
+
-gn=, --game-name= Filter by game name
Include only items with this game name in the output. Additionally,
the user can specify an exact match or full C#-style regex for
diff --git a/SabreTools.Library/Tools/Converters.cs b/SabreTools.Library/Tools/Converters.cs
index 899f0d30..14fcde20 100644
--- a/SabreTools.Library/Tools/Converters.cs
+++ b/SabreTools.Library/Tools/Converters.cs
@@ -122,45 +122,78 @@ namespace SabreTools.Library.Tools
switch (input?.ToLowerInvariant())
{
case "areaname":
+ case "area-name":
return Field.AreaName;
case "areasize":
+ case "area-size":
return Field.AreaSize;
case "bios":
return Field.Bios;
case "biosdescription":
- case "bios description":
+ case "bios-description":
case "biossetdescription":
- case "biosset description":
- case "bios set description":
+ case "biosset-description":
+ case "bios-set-description":
return Field.BiosDescription;
case "board":
return Field.Board;
+ case "category":
+ case "machinecategory":
+ case "machine-category":
+ return Field.Category;
case "cloneof":
return Field.CloneOf;
case "comment":
return Field.Comment;
case "crc":
+ case "crc32":
return Field.CRC;
case "default":
return Field.Default;
case "date":
return Field.Date;
+ case "desc":
case "description":
+ case "gamedesc":
+ case "gamedescription":
+ case "game-description":
+ case "machinedesc":
+ case "machinedescription":
+ case "machine-description":
return Field.Description;
case "devices":
return Field.Devices;
+ case "equal":
+ case "greater":
+ case "less":
+ case "size":
+ return Field.Size;
case "features":
return Field.Features;
case "gamename":
case "machinename":
return Field.MachineName;
case "gametype":
+ case "game-type":
case "machinetype":
+ case "machine-type":
return Field.MachineType;
case "index":
return Field.Index;
case "infos":
return Field.Infos;
+ case "itemname":
+ case "item-name":
+ case "name":
+ return Field.Name;
+ case "itemtatus":
+ case "item-status":
+ case "status":
+ return Field.Status;
+ case "itemtype":
+ case "item-type":
+ case "type":
+ return Field.ItemType;
case "language":
return Field.Language;
case "manufacturer":
@@ -168,16 +201,18 @@ namespace SabreTools.Library.Tools
case "md5":
return Field.MD5;
case "merge":
+ case "mergetag":
+ case "merge-tag":
return Field.Merge;
- case "name":
- return Field.Name;
case "offset":
return Field.Offset;
case "optional":
return Field.Optional;
case "partinterface":
+ case "part-interface":
return Field.PartInterface;
case "partname":
+ case "part-name":
return Field.PartName;
case "publisher":
return Field.Publisher;
@@ -196,21 +231,23 @@ namespace SabreTools.Library.Tools
case "sampleof":
return Field.SampleOf;
case "sha1":
+ case "sha-1":
return Field.SHA1;
case "sha256":
+ case "sha-256":
return Field.SHA256;
case "sha384":
+ case "sha-384":
return Field.SHA384;
case "sha512":
+ case "sha-512":
return Field.SHA512;
- case "size":
- return Field.Size;
case "slotoptions":
+ case "slot-options":
return Field.SlotOptions;
case "sourcefile":
+ case "source-file":
return Field.SourceFile;
- case "status":
- return Field.Status;
case "supported":
return Field.Supported;
case "writable":
diff --git a/SabreTools/SabreTools.Help.cs b/SabreTools/SabreTools.Help.cs
index cd2e15db..9582d7ae 100644
--- a/SabreTools/SabreTools.Help.cs
+++ b/SabreTools/SabreTools.Help.cs
@@ -1269,6 +1269,20 @@ namespace SabreTools
}
}
+ public const string CategoryListValue = "category-filter";
+ private static Feature CategoryListInput
+ {
+ get
+ {
+ return new Feature(
+ CategoryListValue,
+ new List() { "-cat", "--category-filter" },
+ "Filter by Category",
+ FeatureType.List,
+ longDescription: "Include only items with this Category in the output. Additionally, the user can specify an exact match or full C#-style regex for pattern matching. Multiple instances of this flag are allowed.");
+ }
+ }
+
public const string CrcListValue = "crc";
private static Feature CrcListInput
{
@@ -1339,6 +1353,20 @@ namespace SabreTools
}
}
+ public const string FilterListValue = "filter";
+ private static Feature FilterListInput
+ {
+ get
+ {
+ return new Feature(
+ FilterListValue,
+ new List() { "-fi", "--filter" },
+ "Filter a game/rom field with the given value(s)",
+ FeatureType.List,
+ longDescription: "Filter any valid item or machine field from inputs. Filters are input in the form 'key:value' or '!key:value', where the '!' signifies 'not' matching. Numeric values may also prefix the 'value' with '>', '<', or '=' accordingly. Key examples include: romof, category, and game. Additionally, the user can specify an exact match or full C#-style regex for pattern matching. Multiple instances of this flag are allowed.");
+ }
+ }
+
public const string GameDescriptionListValue = "game-description";
private static Feature GameDescriptionListInput
{
@@ -1424,6 +1452,20 @@ Possible values are: None, Bios, Device, Mechanical");
}
}
+ public const string NotCategoryListValue = "not-category";
+ private static Feature NotCategoryListInput
+ {
+ get
+ {
+ return new Feature(
+ NotCategoryListValue,
+ new List() { "-ncat", "--not-category" },
+ "Filter by not Category",
+ FeatureType.List,
+ longDescription: "Include only items without this Category in the output. Additionally, the user can specify an exact match or full C#-style regex for pattern matching. Multiple instances of this flag are allowed.");
+ }
+ }
+
public const string NotCrcListValue = "not-crc";
private static Feature NotCrcListInput
{
@@ -2055,6 +2097,7 @@ Some special strings that can be used:
- %name% - Replaced with the Rom name
- %manufacturer% - Replaced with game Manufacturer
- %publisher% - Replaced with game Publisher
+- %category% - Replaced with game Category
- %crc% - Replaced with the CRC
- %md5% - Replaced with the MD5"
#if NET_FRAMEWORK
@@ -2087,6 +2130,7 @@ Some special strings that can be used:
- %name% - Replaced with the Rom name
- %manufacturer% - Replaced with game Manufacturer
- %publisher% - Replaced with game Publisher
+- %category% - Replaced with game Category
- %crc% - Replaced with the CRC
- %md5% - Replaced with the MD5
- %sha1% - Replaced with the SHA-1
@@ -2297,106 +2341,243 @@ Some special strings that can be used:
{
Filter filter = new Filter();
- // Clean names
- filter.Clean.Neutral = GetBoolean(features, CleanValue);
+ // Use the Filter flag first
+ List filterPairs = GetList(features, FilterListValue);
+ filter.PopulateFromList(filterPairs);
+
+ #region Obsoleted Inputs
+
+ // Category
+ if (features.ContainsKey(NotCategoryListValue))
+ {
+ Globals.Logger.User($"This flag '{NotCategoryListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.Category, GetList(features, NotCategoryListValue), true);
+ }
+ if (features.ContainsKey(CategoryListValue))
+ {
+ Globals.Logger.User($"This flag '{CategoryListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.Category, GetList(features, CategoryListValue), false);
+ }
// CRC
- filter.CRC.NegativeSet.AddRange(GetList(features, NotCrcListValue));
- filter.CRC.PositiveSet.AddRange(GetList(features, CrcListValue));
-
- // Machine description as machine name
- filter.DescriptionAsName.Neutral = GetBoolean(features, DescriptionAsNameValue);
-
- // Include 'of" in game filters
- filter.IncludeOfInGame.Neutral = GetBoolean(features, MatchOfTagsValue);
-
- // Internal splitting
- filter.InternalSplit.Neutral = GetSplitType(features);
+ if (features.ContainsKey(NotCrcListValue))
+ {
+ Globals.Logger.User($"This flag '{NotCrcListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.CRC, GetList(features, NotCrcListValue), true);
+ }
+ if (features.ContainsKey(CrcListValue))
+ {
+ Globals.Logger.User($"This flag '{CrcListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.CRC, GetList(features, NotCrcListValue), false);
+ }
// Item name
- filter.ItemName.NegativeSet.AddRange(GetList(features, NotItemNameListValue));
- filter.ItemName.PositiveSet.AddRange(GetList(features, ItemNameListValue));
+ if (features.ContainsKey(NotItemNameListValue))
+ {
+ Globals.Logger.User($"This flag '{NotItemNameListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.Name, GetList(features, NotItemNameListValue), true);
+ }
+ if (features.ContainsKey(ItemNameListValue))
+ {
+ Globals.Logger.User($"This flag '{ItemNameListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.Name, GetList(features, ItemNameListValue), false);
+ }
// Item status
- foreach (string stat in GetList(features, NotStatusListValue))
+ if (features.ContainsKey(NotStatusListValue))
{
- filter.ItemStatuses.Negative |= stat.AsItemStatus();
+ Globals.Logger.User($"This flag '{NotStatusListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.Status, GetList(features, NotStatusListValue), true);
}
- foreach (string stat in GetList(features, StatusListValue))
+ if (features.ContainsKey(StatusListValue))
{
- filter.ItemStatuses.Positive |= stat.AsItemStatus();
+ Globals.Logger.User($"This flag '{StatusListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.Status, GetList(features, StatusListValue), false);
}
// Item type
- filter.ItemTypes.NegativeSet.AddRange(GetList(features, NotItemTypeListValue));
- filter.ItemTypes.PositiveSet.AddRange(GetList(features, ItemTypeListValue));
+ if (features.ContainsKey(NotItemTypeListValue))
+ {
+ Globals.Logger.User($"This flag '{NotItemTypeListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.ItemType, GetList(features, NotItemTypeListValue), true);
+ }
+ if (features.ContainsKey(ItemTypeListValue))
+ {
+ Globals.Logger.User($"This flag '{ItemTypeListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.ItemType, GetList(features, ItemTypeListValue), false);
+ }
// Machine description
- filter.MachineDescription.NegativeSet.AddRange(GetList(features, NotGameDescriptionListValue));
- filter.MachineDescription.PositiveSet.AddRange(GetList(features, GameDescriptionListValue));
+ if (features.ContainsKey(NotGameDescriptionListValue))
+ {
+ Globals.Logger.User($"This flag '{NotGameDescriptionListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.Description, GetList(features, NotGameDescriptionListValue), true);
+ }
+ if (features.ContainsKey(GameDescriptionListValue))
+ {
+ Globals.Logger.User($"This flag '{GameDescriptionListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.Description, GetList(features, GameDescriptionListValue), false);
+ }
// Machine name
- filter.MachineName.NegativeSet.AddRange(GetList(features, NotGameNameListValue));
- filter.MachineName.PositiveSet.AddRange(GetList(features, GameNameListValue));
+ if (features.ContainsKey(NotGameNameListValue))
+ {
+ Globals.Logger.User($"This flag '{NotGameNameListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.MachineName, GetList(features, NotGameNameListValue), true);
+ }
+ if (features.ContainsKey(GameNameListValue))
+ {
+ Globals.Logger.User($"This flag '{GameNameListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.MachineName, GetList(features, GameNameListValue), false);
+ }
// Machine type
- foreach (string mach in GetList(features, NotGameTypeListValue))
+ if (features.ContainsKey(NotGameTypeListValue))
{
- filter.MachineTypes.Negative |= mach.AsMachineType();
+ Globals.Logger.User($"This flag '{NotGameTypeListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.MachineType, GetList(features, NotGameTypeListValue), true);
}
- foreach (string mach in GetList(features, GameTypeListValue))
+ if (features.ContainsKey(GameTypeListValue))
{
- filter.MachineTypes.Positive |= mach.AsMachineType();
+ Globals.Logger.User($"This flag '{GameTypeListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.MachineType, GetList(features, GameTypeListValue), false);
}
// MD5
- filter.MD5.NegativeSet.AddRange(GetList(features, NotMd5ListValue));
- filter.MD5.PositiveSet.AddRange(GetList(features, Md5ListValue));
-
- // Remove unicode characters
- filter.RemoveUnicode.Neutral = GetBoolean(features, RemoveUnicodeValue);
+ if (features.ContainsKey(NotMd5ListValue))
+ {
+ Globals.Logger.User($"This flag '{NotMd5ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.MD5, GetList(features, NotMd5ListValue), true);
+ }
+ if (features.ContainsKey(Md5ListValue))
+ {
+ Globals.Logger.User($"This flag '{Md5ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.MD5, GetList(features, Md5ListValue), false);
+ }
#if NET_FRAMEWORK
// RIPEMD160
- filter.RIPEMD160.NegativeSet.AddRange(GetList(features, NotRipeMd160ListValue));
- filter.RIPEMD160.PositiveSet.AddRange(GetList(features, RipeMd160ListValue));
+ if (features.ContainsKey(NotRipeMd160ListValue))
+ {
+ Globals.Logger.User($"This flag '{NotRipeMd160ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.RIPEMD160, GetList(features, NotRipeMd160ListValue), true);
+ }
+ if (features.ContainsKey(RipeMd160ListValue))
+ {
+ Globals.Logger.User($"This flag '{RipeMd160ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.RIPEMD160, GetList(features, RipeMd160ListValue), false);
+ }
#endif
- // Root directory
- filter.Root.Neutral = GetString(features, RootDirStringValue);
-
// Runnable
- if (GetBoolean(features, NotRunnableValue))
- filter.Runnable.Neutral = false;
- if (GetBoolean(features, RunnableValue))
- filter.Runnable.Neutral = true;
+ if (features.ContainsKey(NotRunnableValue))
+ {
+ Globals.Logger.User($"This flag '{NotRunnableValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.Runnable, string.Empty, true);
+ }
+ if (features.ContainsKey(RunnableValue))
+ {
+ Globals.Logger.User($"This flag '{RunnableValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.Runnable, string.Empty, false);
+ }
- // SHA-1
- filter.SHA1.NegativeSet.AddRange(GetList(features, NotSha1ListValue));
- filter.SHA1.PositiveSet.AddRange(GetList(features, Sha1ListValue));
+ // SHA1
+ if (features.ContainsKey(NotSha1ListValue))
+ {
+ Globals.Logger.User($"This flag '{NotSha1ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.SHA1, GetList(features, NotSha1ListValue), true);
+ }
+ if (features.ContainsKey(Sha1ListValue))
+ {
+ Globals.Logger.User($"This flag '{Sha1ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.SHA1, GetList(features, Sha1ListValue), false);
+ }
- // SHA-256
- filter.SHA256.NegativeSet.AddRange(GetList(features, NotSha256ListValue));
- filter.SHA256.PositiveSet.AddRange(GetList(features, Sha256ListValue));
+ // SHA256
+ if (features.ContainsKey(NotSha256ListValue))
+ {
+ Globals.Logger.User($"This flag '{NotSha256ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.SHA256, GetList(features, NotSha256ListValue), true);
+ }
+ if (features.ContainsKey(Sha256ListValue))
+ {
+ Globals.Logger.User($"This flag '{Sha256ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.SHA256, GetList(features, Sha256ListValue), false);
+ }
- // SHA-384
- filter.SHA384.NegativeSet.AddRange(GetList(features, NotSha384ListValue));
- filter.SHA384.PositiveSet.AddRange(GetList(features, Sha384ListValue));
+ // SHA384
+ if (features.ContainsKey(NotSha384ListValue))
+ {
+ Globals.Logger.User($"This flag '{NotSha384ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.SHA384, GetList(features, NotSha384ListValue), true);
+ }
+ if (features.ContainsKey(Sha384ListValue))
+ {
+ Globals.Logger.User($"This flag '{Sha384ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.SHA384, GetList(features, Sha384ListValue), false);
+ }
- // SHA-512
- filter.SHA512.NegativeSet.AddRange(GetList(features, NotSha512ListValue));
- filter.SHA512.PositiveSet.AddRange(GetList(features, Sha512ListValue));
-
- // Single game in output
- filter.Single.Neutral = GetBoolean(features, SingleSetValue);
+ // SHA512
+ if (features.ContainsKey(NotSha512ListValue))
+ {
+ Globals.Logger.User($"This flag '{NotSha512ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.SHA512, GetList(features, NotSha512ListValue), true);
+ }
+ if (features.ContainsKey(Sha512ListValue))
+ {
+ Globals.Logger.User($"This flag '{Sha512ListValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ filter.SetFilter(Field.SHA512, GetList(features, Sha512ListValue), false);
+ }
// Size
- filter.Size.Negative = Sanitizer.ToSize(GetString(features, LessStringValue));
- filter.Size.Neutral = Sanitizer.ToSize(GetString(features, EqualStringValue));
- filter.Size.Positive = Sanitizer.ToSize(GetString(features, GreaterStringValue));
+ if (features.ContainsKey(LessStringValue))
+ {
+ Globals.Logger.User($"This flag '{LessStringValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ var value = Sanitizer.ToSize(GetString(features, LessStringValue));
+ filter.SetFilter(Field.Size, $"<{value}", false);
+ }
+ if (features.ContainsKey(EqualStringValue))
+ {
+ Globals.Logger.User($"This flag '{EqualStringValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ var value = Sanitizer.ToSize(GetString(features, EqualStringValue));
+ filter.SetFilter(Field.Size, $"={value}", false);
+ }
+ if (features.ContainsKey(GreaterStringValue))
+ {
+ Globals.Logger.User($"This flag '{GreaterStringValue}' is deprecated, please use {string.Join(", ", FilterListInput.Flags)} instead");
+ var value = Sanitizer.ToSize(GetString(features, GreaterStringValue));
+ filter.SetFilter(Field.Size, $">{value}", false);
+ }
+
+ #endregion
+
+ #region Filter manipulation flags
+
+ // Clean names
+ filter.Clean = GetBoolean(features, CleanValue);
+
+ // Machine description as machine name
+ filter.DescriptionAsName = GetBoolean(features, DescriptionAsNameValue);
+
+ // Include 'of" in game filters
+ filter.IncludeOfInGame = GetBoolean(features, MatchOfTagsValue);
+
+ // Internal splitting
+ filter.InternalSplit = GetSplitType(features);
+
+ // Remove unicode characters
+ filter.RemoveUnicode = GetBoolean(features, RemoveUnicodeValue);
+
+ // Root directory
+ filter.Root = GetString(features, RootDirStringValue);
+
+ // Single game in output
+ filter.Single = GetBoolean(features, SingleSetValue);
// Trim to NTFS length
- filter.Trim.Neutral = GetBoolean(features, TrimValue);
+ filter.Trim = GetBoolean(features, TrimValue);
+
+ #endregion
return filter;
}
@@ -2714,6 +2895,9 @@ Some special strings that can be used:
AddFeature(CopyFilesFlag);
AddFeature(HeaderStringInput);
AddFeature(ChdsAsFilesFlag);
+ AddFeature(FilterListInput);
+ AddFeature(CategoryListInput);
+ AddFeature(NotCategoryListInput);
AddFeature(GameNameListInput);
AddFeature(NotGameNameListInput);
AddFeature(GameDescriptionListInput);
@@ -3238,6 +3422,9 @@ The stats that are outputted are as follows:
this[DiffCascadeFlag].AddFeature(SkipFirstOutputFlag);
AddFeature(DiffReverseCascadeFlag);
this[DiffReverseCascadeFlag].AddFeature(SkipFirstOutputFlag);
+ AddFeature(FilterListInput);
+ AddFeature(CategoryListInput);
+ AddFeature(NotCategoryListInput);
AddFeature(GameNameListInput);
AddFeature(NotGameNameListInput);
AddFeature(GameDescriptionListInput);
@@ -3369,6 +3556,9 @@ The stats that are outputted are as follows:
AddFeature(DatDeviceNonMergedFlag);
AddFeature(DatNonMergedFlag);
AddFeature(DatFullNonMergedFlag);
+ AddFeature(FilterListInput);
+ AddFeature(CategoryListInput);
+ AddFeature(NotCategoryListInput);
AddFeature(GameNameListInput);
AddFeature(NotGameNameListInput);
AddFeature(GameDescriptionListInput);