diff --git a/SabreTools.Helper/Data/Build.cs b/SabreTools.Helper/Data/Build.cs index 75723e86..05c65ecf 100644 --- a/SabreTools.Helper/Data/Build.cs +++ b/SabreTools.Helper/Data/Build.cs @@ -339,17 +339,26 @@ namespace SabreTools.Helper.Data helptext.Add(" [Can be used with other -diX flags]"); helptext.Add(" -b, --bare Don't include date in automatic name"); helptext.Add(" -gn=, --game-name= Filter by game name"); + helptext.Add(" -ngn=, --not-game= Filter by not game name"); helptext.Add(" -rn=, --rom-name= Filter by rom name"); + helptext.Add(" -nrn=, --not-rom= Filter by not rom name"); helptext.Add(" -rt=, --rom-type= Filter by rom type"); + helptext.Add(" -nrt=, --not-type= Filter by not rom type"); helptext.Add(" -sgt=, --greater= Filter by size >="); helptext.Add(" -slt=, --less= Filter by size <="); helptext.Add(" -seq=, --equal= Filter by size =="); helptext.Add(" -crc=, --crc= Filter by CRC hash"); + helptext.Add(" -ncrc=, --not-crc= Filter by not CRC hash"); helptext.Add(" -md5=, --md5= Filter by MD5 hash"); + helptext.Add(" -nmd5=, --not-md5= Filter by not MD5 hash"); helptext.Add(" -sha1=, --sha1= Filter by SHA-1 hash"); + helptext.Add(" -nsha1=, --not-sha1= Filter by not SHA-1 hash"); helptext.Add(" -is=, --status= Include only items with a given status"); helptext.Add(" Supported values are:"); - helptext.Add(" None, Good, BadDump, Nodump, Verified, NotNodump"); + helptext.Add(" None, Good, BadDump, Nodump, Verified"); + helptext.Add(" -nis=, --not-status= Exclude items with a given status"); + helptext.Add(" Supported values are:"); + helptext.Add(" None, Good, BadDump, Nodump, Verified"); helptext.Add(" -out= Output directory (overridden by --inplace)"); helptext.Add(" -mt={4} Amount of threads to use (-1 unlimted)"); diff --git a/SabreTools.Helper/Dats/Filter.cs b/SabreTools.Helper/Dats/Filter.cs index 173e7246..d1d02daa 100644 --- a/SabreTools.Helper/Dats/Filter.cs +++ b/SabreTools.Helper/Dats/Filter.cs @@ -9,15 +9,22 @@ namespace SabreTools.Helper.Dats #region Private instance variables private string _gameName; + private string _notGameName; private string _romName; + private string _notRomName; private string _romType; + private string _notRomType; private long _sizeGreaterThanOrEqual; private long _sizeLessThanOrEqual; private long _sizeEqualTo; private string _crc; + private string _notCrc; private string _md5; + private string _notMd5; private string _sha1; + private string _notSha1; private ItemStatus _itemStatus; + private ItemStatus _itemNotStatus; #endregion @@ -27,15 +34,22 @@ namespace SabreTools.Helper.Dats public Filter() { _gameName = null; + _notGameName = null; _romName = null; + _notRomName = null; _romType = null; + _notRomType = null; _sizeGreaterThanOrEqual = -1; _sizeLessThanOrEqual = -1; _sizeEqualTo = -1; _crc = null; + _notCrc = null; _md5 = null; + _notMd5 = null; _sha1 = null; + _notSha1 = null; _itemStatus = ItemStatus.NULL; + _itemNotStatus = ItemStatus.NULL; } /// @@ -51,19 +65,35 @@ namespace SabreTools.Helper.Dats /// MD5 of the rom to match (can use asterisk-partials) /// SHA-1 of the rom to match (can use asterisk-partials) /// Select roms with the given status + /// Name of the game to match (can use asterisk-partials) + /// Name of the rom to match (can use asterisk-partials) + /// Type of the rom to match + /// CRC of the rom to match (can use asterisk-partials) + /// MD5 of the rom to match (can use asterisk-partials) + /// SHA-1 of the rom to match (can use asterisk-partials) + /// Select roms with the given status public Filter(string gamename, string romname, string romtype, long sgt, - long slt, long seq, string crc, string md5, string sha1, ItemStatus itemStatus) + long slt, long seq, string crc, string md5, string sha1, ItemStatus itemStatus, + string notgamename, string notromname, string notromtype, string notcrc, string notmd5, + string notsha1, ItemStatus itemNotStatus) { _gameName = gamename; + _notGameName = notgamename; _romName = romname; + _notRomName = notromname; _romType = romtype; + _notRomType = notromtype; _sizeGreaterThanOrEqual = sgt; _sizeLessThanOrEqual = slt; _sizeEqualTo = seq; _crc = crc; + _notCrc = notcrc; _md5 = md5; + _notMd5 = notmd5; _sha1 = sha1; + _notSha1 = notsha1; _itemStatus = itemStatus; + _itemNotStatus = itemNotStatus; } /// @@ -80,16 +110,13 @@ namespace SabreTools.Helper.Dats Rom rom = (Rom)item; // Filter on status - if (_itemStatus != ItemStatus.NULL) + if (_itemStatus != ItemStatus.NULL && rom.ItemStatus != _itemStatus) { - if (_itemStatus == ItemStatus.NotNodump && rom.ItemStatus == ItemStatus.Nodump) - { - return false; - } - else if (_itemStatus != ItemStatus.NotNodump && rom.ItemStatus != _itemStatus) - { - return false; - } + return false; + } + if (_itemNotStatus != ItemStatus.NULL && rom.ItemStatus == _itemNotStatus) + { + return false; } // Filter on rom size @@ -109,7 +136,7 @@ namespace SabreTools.Helper.Dats } } - // Filter on _crc + // Filter on CRC if (!String.IsNullOrEmpty(_crc)) { if (_crc.StartsWith("*") && _crc.EndsWith("*")) @@ -141,8 +168,39 @@ namespace SabreTools.Helper.Dats } } } + if (!String.IsNullOrEmpty(_notCrc)) + { + if (_notCrc.StartsWith("*") && _notCrc.EndsWith("*")) + { + if (rom.CRC.ToLowerInvariant().Contains(_notCrc.ToLowerInvariant().Replace("*", ""))) + { + return false; + } + } + else if (_notCrc.StartsWith("*")) + { + if (rom.CRC.EndsWith(_notCrc.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else if (_notCrc.EndsWith("*")) + { + if (rom.CRC.StartsWith(_notCrc.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else + { + if (String.Equals(rom.CRC, _notCrc, StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + } - // Filter on _md5 + // Filter on MD5 if (!String.IsNullOrEmpty(_md5)) { if (_md5.StartsWith("*") && _md5.EndsWith("*")) @@ -174,8 +232,39 @@ namespace SabreTools.Helper.Dats } } } + if (!String.IsNullOrEmpty(_notMd5)) + { + if (_notMd5.StartsWith("*") && _notMd5.EndsWith("*")) + { + if (rom.MD5.ToLowerInvariant().Contains(_notMd5.ToLowerInvariant().Replace("*", ""))) + { + return false; + } + } + else if (_notMd5.StartsWith("*")) + { + if (rom.MD5.EndsWith(_notMd5.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else if (_notMd5.EndsWith("*")) + { + if (rom.MD5.StartsWith(_notMd5.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else + { + if (String.Equals(rom.MD5, _notMd5, StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + } - // Filter on _sha1 + // Filter on SHA1 if (!String.IsNullOrEmpty(_sha1)) { if (_sha1.StartsWith("*") && _sha1.EndsWith("*")) @@ -207,6 +296,37 @@ namespace SabreTools.Helper.Dats } } } + if (!String.IsNullOrEmpty(_notSha1)) + { + if (_notSha1.StartsWith("*") && _notSha1.EndsWith("*")) + { + if (rom.SHA1.ToLowerInvariant().Contains(_notSha1.ToLowerInvariant().Replace("*", ""))) + { + return false; + } + } + else if (_notSha1.StartsWith("*")) + { + if (rom.SHA1.EndsWith(_notSha1.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else if (_notSha1.EndsWith("*")) + { + if (rom.SHA1.StartsWith(_notSha1.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else + { + if (String.Equals(rom.SHA1, _notSha1, StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + } } else if (item.Type == ItemType.Disk) { @@ -215,17 +335,14 @@ namespace SabreTools.Helper.Dats // Filter on status if (_itemStatus != ItemStatus.NULL && rom.ItemStatus != _itemStatus) { - if (_itemStatus == ItemStatus.NotNodump && rom.ItemStatus == ItemStatus.Nodump) - { - return false; - } - else if (_itemStatus != ItemStatus.NotNodump && rom.ItemStatus != _itemStatus) - { - return false; - } + return false; + } + if (_itemNotStatus != ItemStatus.NULL && rom.ItemStatus == _itemNotStatus) + { + return false; } - // Filter on _md5 + // Filter on MD5 if (!String.IsNullOrEmpty(_md5)) { if (_md5.StartsWith("*") && _md5.EndsWith("*")) @@ -257,8 +374,39 @@ namespace SabreTools.Helper.Dats } } } + if (!String.IsNullOrEmpty(_notMd5)) + { + if (_notMd5.StartsWith("*") && _notMd5.EndsWith("*")) + { + if (rom.MD5.ToLowerInvariant().Contains(_notMd5.ToLowerInvariant().Replace("*", ""))) + { + return false; + } + } + else if (_notMd5.StartsWith("*")) + { + if (rom.MD5.EndsWith(_notMd5.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else if (_notMd5.EndsWith("*")) + { + if (rom.MD5.StartsWith(_notMd5.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else + { + if (String.Equals(rom.MD5, _notMd5, StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + } - // Filter on _sha1 + // Filter on SHA1 if (!String.IsNullOrEmpty(_sha1)) { if (_sha1.StartsWith("*") && _sha1.EndsWith("*")) @@ -290,6 +438,37 @@ namespace SabreTools.Helper.Dats } } } + if (!String.IsNullOrEmpty(_notSha1)) + { + if (_notSha1.StartsWith("*") && _notSha1.EndsWith("*")) + { + if (rom.SHA1.ToLowerInvariant().Contains(_notSha1.ToLowerInvariant().Replace("*", ""))) + { + return false; + } + } + else if (_notSha1.StartsWith("*")) + { + if (rom.SHA1.EndsWith(_notSha1.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else if (_notSha1.EndsWith("*")) + { + if (rom.SHA1.StartsWith(_notSha1.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else + { + if (String.Equals(rom.SHA1, _notSha1, StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + } } // Filter on game name @@ -324,6 +503,37 @@ namespace SabreTools.Helper.Dats } } } + if (!String.IsNullOrEmpty(_notGameName)) + { + if (_notGameName.StartsWith("*") && _notGameName.EndsWith("*")) + { + if (item.Machine.Name.ToLowerInvariant().Contains(_notGameName.ToLowerInvariant().Replace("*", ""))) + { + return false; + } + } + else if (_notGameName.StartsWith("*")) + { + if (item.Machine.Name.EndsWith(_notGameName.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else if (_notGameName.EndsWith("*")) + { + if (item.Machine.Name.StartsWith(_notGameName.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else + { + if (String.Equals(item.Machine.Name, _notGameName, StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + } // Filter on rom name if (!String.IsNullOrEmpty(_romName)) @@ -357,9 +567,40 @@ namespace SabreTools.Helper.Dats } } } + if (!String.IsNullOrEmpty(_notRomName)) + { + if (_notRomName.StartsWith("*") && _notRomName.EndsWith("*")) + { + if (item.Name.ToLowerInvariant().Contains(_notRomName.ToLowerInvariant().Replace("*", ""))) + { + return false; + } + } + else if (_notRomName.StartsWith("*")) + { + if (item.Name.EndsWith(_notRomName.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else if (_notRomName.EndsWith("*")) + { + if (item.Name.StartsWith(_notRomName.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + else + { + if (String.Equals(item.Name, _notRomName, StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + } + } // Filter on rom type - if (String.IsNullOrEmpty(_romType) && item.Type != ItemType.Rom && item.Type != ItemType.Disk) + if (String.IsNullOrEmpty(_romType) && String.IsNullOrEmpty(_notRomType) && item.Type != ItemType.Rom && item.Type != ItemType.Disk) { return false; } @@ -367,6 +608,10 @@ namespace SabreTools.Helper.Dats { return false; } + if (!String.IsNullOrEmpty(_notRomType) && String.Equals(item.Type.ToString(), _notRomType, StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } return true; } diff --git a/SabreTools.Helper/README.1ST b/SabreTools.Helper/README.1ST index 4876a240..5f47050b 100644 --- a/SabreTools.Helper/README.1ST +++ b/SabreTools.Helper/README.1ST @@ -791,11 +791,16 @@ Options: In times where the first DAT does not need to be written out a second time, this will skip writing it. This can often speed up the output process. - -gn=, --game-name= Filter by game name + -gn=, --not-game= Filter by game name + -ngn=, --game-name= Exclude by game name -rn=, --rom-name= Filter by rom name + -nrn=, --not-rom= Exclude by rom name -crc=, --crc= Filter by CRC hash + -ncrc=, --not-crc= Exclude by CRC hash -md5=, --md5= Filter by MD5 hash + -nmd5=, --not-md5= Exclude by MD5 hash -sha1=, --sha1= Filter by SHA-1 hash + -nsha1=, --not-sha1= Exclude by SHA-1 hash For each of the flags above, the user can specify either an exact match or can use a wildcard as defined below (case-insensitive): *00 means ends with '00' @@ -806,6 +811,9 @@ Options: -rt=, --rom-type= Filter by rom type This allows users to only include roms or disks to their liking + -nrt=, --not-type= Exclude by rom type + This allows users to only exclude roms or disks to their liking + -sgt=, --greater= Filter by size >= -slt=, --less= Filter by size <= -seq=, --equal= Filter by size == @@ -813,9 +821,13 @@ Options: various standard postfixes for size: e.g. 8kb => 8000 or 8kib => 8192 - -is=, status= Include only items with a given status + -is=, --status= Include only items with a given status Include items with one of the supported values: - None, Good, BadDump, Nodump, Verified, NotNodump + None, Good, BadDump, Nodump, Verified + + -nis=, --not-status= Exclude only items with a given status + Include items with one of the supported values: + None, Good, BadDump, Nodump, Verified -out= Set the name of the output directory This sets an output folder to be used when the files are created. If a path diff --git a/SabreTools/Partials/SabreTools_Inits.cs b/SabreTools/Partials/SabreTools_Inits.cs index c0bd347a..8c1225eb 100644 --- a/SabreTools/Partials/SabreTools_Inits.cs +++ b/SabreTools/Partials/SabreTools_Inits.cs @@ -437,6 +437,13 @@ namespace SabreTools /// MD5 of the rom to match (can use asterisk-partials) /// SHA-1 of the rom to match (can use asterisk-partials) /// Select roms with the given item status + /// Name of the game to match (can use asterisk-partials) + /// Name of the rom to match (can use asterisk-partials) + /// Type of the rom to match + /// CRC of the rom to match (can use asterisk-partials) + /// MD5 of the rom to match (can use asterisk-partials) + /// SHA-1 of the rom to match (can use asterisk-partials) + /// Select roms with the given item status /// /* Trimming info */ /// True if we are supposed to trim names to NTFS length, false otherwise /// True if all games should be replaced by '!', false otherwise @@ -499,6 +506,13 @@ namespace SabreTools string md5, string sha1, string status, + string notgamename, + string notromname, + string notromtype, + string notcrc, + string notmd5, + string notsha1, + string notstatus, /* Trimming info */ bool trim, @@ -582,8 +596,26 @@ namespace SabreTools case "verified": itemStatus = ItemStatus.Verified; break; - case "notnodump": - itemStatus = ItemStatus.NotNodump; + } + + // Set the not status flag for filtering + ItemStatus itemNotStatus = ItemStatus.NULL; + switch (status?.ToLowerInvariant()) + { + case "none": + itemNotStatus = ItemStatus.None; + break; + case "good": + itemNotStatus = ItemStatus.Good; + break; + case "baddump": + itemNotStatus = ItemStatus.BadDump; + break; + case "nodump": + itemNotStatus = ItemStatus.Nodump; + break; + case "verified": + itemNotStatus = ItemStatus.Verified; break; } @@ -657,7 +689,8 @@ namespace SabreTools }; // Create the Filter object to be used - Filter filter = new Filter(gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, itemStatus); + Filter filter = new Filter(gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, itemStatus, + notgamename, notromname, notromtype, notcrc, notmd5, notsha1, itemNotStatus); userInputDat.DetermineUpdateType(inputs, outDir, merge, diffMode, inplace, skip, bare, clean, softlist, filter, trim, single, root, maxDegreeOfParallelism, _logger); diff --git a/SabreTools/SabreTools.cs b/SabreTools/SabreTools.cs index 188abe89..c0c05f5c 100644 --- a/SabreTools/SabreTools.cs +++ b/SabreTools/SabreTools.cs @@ -131,6 +131,13 @@ namespace SabreTools homepage = null, md5 = "", name = null, + notcrc = null, + notgamename = null, + notmd5 = null, + notromname = null, + notromtype = null, + notsha1 = null, + notstatus = null, outDir = "", postfix = "", prefix = "", @@ -564,6 +571,34 @@ namespace SabreTools case "--name": name = args[++i]; break; + case "-ncrc": + case "--not-crc": + notcrc = args[++i]; + break; + case "-ngn": + case "--not-game": + notgamename = args[++i]; + break; + case "-nis": + case "--not-status": + notstatus = args[++i]; + break; + case "-nmd5": + case "--not-md5": + notmd5 = args[++i]; + break; + case "-nrn": + case "--not-rom": + notromname = args[++i]; + break; + case "-nrt": + case "--not-type": + notromtype = args[++i]; + break; + case "-nsha1": + case "--not-sha1": + notsha1 = args[++i]; + break; case "-out": case "--out": outDir = args[++i]; @@ -761,6 +796,34 @@ namespace SabreTools case "--name": name = split[1]; break; + case "-ncrc": + case "--not-crc": + notcrc = split[1]; + break; + case "-ngn": + case "--not-game": + notgamename = split[1]; + break; + case "-nis": + case "--not-status": + notstatus = split[1]; + break; + case "-nmd5": + case "--not-md5": + notmd5 = split[1]; + break; + case "-nrn": + case "--not-rom": + notromname = split[1]; + break; + case "-nrt": + case "--not-type": + notromtype = split[1]; + break; + case "-nsha1": + case "--not-sha1": + notsha1 = split[1]; + break; case "-out": case "--out": outDir = split[1]; @@ -974,8 +1037,10 @@ namespace SabreTools { InitUpdate(inputs, filename, name, description, rootdir, category, version, date, author, email, homepage, url, comment, header, superdat, forcemerge, forcend, forcepack, excludeOf, datFormat, usegame, prefix, - postfix, quotes, repext, addext, remext, datPrefix, romba, merge, diffMode, inplace, skip, removeDateFromAutomaticName, gamename, romname, - romtype, sgt, slt, seq, crc, md5, sha1, status, trim, single, root, outDir, cleanGameNames, softlist, dedup, maxParallelism); + postfix, quotes, repext, addext, remext, datPrefix, romba, merge, diffMode, inplace, skip, removeDateFromAutomaticName, + gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, status, + notgamename, notromname, notromtype, notcrc, notmd5, notsha1, notstatus, + trim, single, root, outDir, cleanGameNames, softlist, dedup, maxParallelism); } // If we're using the verifier