using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using SabreTools.Helper; namespace SabreTools { public class Filter { // Private instance variables private string _filename; private string _outdir; private string _gamename; private string _romname; private string _romtype; private long _sgt; private long _slt; private long _seq; private string _crc; private string _md5; private string _sha1; private bool? _nodump; private Logger _logger; /// /// Create a Filter object /// /// Name of the file to be parsed /// Output directory to write the file to /// 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 /// Find roms greater than or equal to this size /// Find roms less than or equal to this size /// Find roms equal to this size /// 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 nodump status as follows: null (match all), true (match Nodump only), false (exclude Nodump) /// Logging object for file and console output public Filter(string filename, string outdir, string gamename, string romname, string romtype, long sgt, long slt, long seq, string crc, string md5, string sha1, bool? nodump, Logger logger) { _filename = filename; _outdir = (outdir == "" ? Path.GetDirectoryName(_filename) : outdir); _gamename = gamename; _romname = romname; _romtype = romtype; _sgt = sgt; _slt = slt; _seq = seq; _crc = crc; _md5 = md5; _sha1 = sha1; _nodump = nodump; _logger = logger; } /// /// Start help or use supplied parameters /// /// String array representing command line parameters public static void Main(string[] args) { Console.Clear(); // Credits take precidence over all if ((new List(args)).Contains("--credits")) { Build.Credits(); return; } Logger logger = new Logger(true, "filter.log"); logger.Start(); // First things first, take care of all of the arguments that this could have bool? nodump = null; string outdir = "", gamename = "", romname = "", romtype = "", crc = "", md5 = "", sha1= ""; long sgt = -1, slt = -1, seq = -1; List inputs = new List(); foreach (string arg in args) { switch (arg) { case "-h": case "-?": case "--help": Build.Help(); logger.Close(); return; case "-nd": case "--nodump": nodump = true; break; case "-nnd": case "--not-nodump": nodump = false; break; default: // Numerical inputs if (arg.StartsWith("-seq=") || arg.StartsWith("--equal=")) { if (!Int64.TryParse(arg.Split('=')[1], out seq)) { seq = -1; } } else if (arg.StartsWith("-sgt=") || arg.StartsWith("--greater=")) { if (!Int64.TryParse(arg.Split('=')[1], out sgt)) { sgt = -1; } } else if (arg.StartsWith("-slt=") || arg.StartsWith("--less=")) { if (!Int64.TryParse(arg.Split('=')[1], out slt)) { slt = -1; } } // String inputs else if (arg.StartsWith("-out=") || arg.StartsWith("--out=")) { outdir = arg.Split('=')[1]; } else if (arg.StartsWith("-crc=") || arg.StartsWith("--crc=")) { crc = arg.Split('=')[1]; } else if (arg.StartsWith("-gn=") || arg.StartsWith("--game-name=")) { gamename = arg.Split('=')[1]; } else if (arg.StartsWith("-md5=") || arg.StartsWith("--md5=")) { md5 = arg.Split('=')[1]; } else if (arg.StartsWith("-rn=") || arg.StartsWith("--rom-name=")) { romname = arg.Split('=')[1]; } else if (arg.StartsWith("-rt=") || arg.StartsWith("--rom-type=")) { romtype = arg.Split('=')[1]; } else if (arg.StartsWith("-sha1=") || arg.StartsWith("--sha1=")) { sha1 = arg.Split('=')[1]; } else { inputs.Add(arg); } break; } } // If there's no inputs, show the help if (inputs.Count == 0) { Build.Help(); logger.Close(); return; } // Output the title Build.Start("Filter"); // If any of the inputs are not valid, show the help foreach (string input in inputs) { if (!File.Exists(input) && !Directory.Exists(input)) { logger.Error(input + " is not a valid input!"); Console.WriteLine(); Build.Help(); return; } } // Create new Filter objects for each input Filter filter; bool success = true; foreach (string input in inputs) { string newinput = Path.GetFullPath(input.Replace("\"", "")); if (File.Exists(newinput)) { filter = new Filter(newinput, outdir, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, logger); success &= filter.Process(); } if (Directory.Exists(newinput)) { foreach (string file in Directory.EnumerateFiles(newinput, "*", SearchOption.AllDirectories)) { string nestedoutdir = ""; if (outdir != "") { nestedoutdir = outdir + Path.GetDirectoryName(file).Remove(0, newinput.Length); } filter = new Filter(file, nestedoutdir, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, logger); success &= filter.Process(); } } } // If we failed, show the help if (!success) { Console.WriteLine(); Build.Help(); } logger.Close(); } /// /// Process an individual DAT with the given information /// /// True if the DAT was output, false otherwise public bool Process() { _logger.User("Processing file: '" + _filename + "'"); // Populated the DAT information DatData datdata = new DatData(); datdata = RomManipulation.Parse(_filename, 0, 0, datdata, _logger); // Now loop through and create a new Rom dictionary using filtered values Dictionary> dict = new Dictionary>(); List keys = datdata.Roms.Keys.ToList(); foreach (string key in keys) { List roms = datdata.Roms[key]; foreach (RomData rom in roms) { // Filter on nodump status if (_nodump == true && !rom.Nodump) { continue; } if (_nodump == false && rom.Nodump) { continue; } // Filter on game name if (_gamename != "") { if (!(_gamename.StartsWith("*") && _gamename.EndsWith("*") && rom.Game.Contains(_gamename.Replace("*", "")))) { continue; } else if (!(_gamename.StartsWith("*") && rom.Game.EndsWith(_gamename.Replace("*", "")))) { continue; } else if (!(_gamename.EndsWith("*") && rom.Game.StartsWith(_gamename.Replace("*", "")))) { continue; } } // Filter on rom name if (_romname != "") { if (!(_romname.StartsWith("*") && _romname.EndsWith("*") && rom.Name.Contains(_romname.Replace("*", "")))) { continue; } else if (!(_romname.StartsWith("*") && rom.Name.EndsWith(_romname.Replace("*", "")))) { continue; } else if (!(_romname.EndsWith("*") && rom.Name.StartsWith(_romname.Replace("*", "")))) { continue; } } // Filter on rom type if (_romtype != "" && rom.Type != _romtype) { continue; } // Filter on rom size if (_seq != -1 && rom.Size != _seq) { continue; } else { if (_sgt != -1 && rom.Size < _sgt) { continue; } if (_slt != -1 && rom.Size > _slt) { continue; } } // Filter on crc if (_crc != "") { if (!(_crc.StartsWith("*") && _crc.EndsWith("*") && rom.CRC.Contains(_crc.Replace("*", "")))) { continue; } else if (!(_crc.StartsWith("*") && rom.CRC.EndsWith(_crc.Replace("*", "")))) { continue; } else if (!(_crc.EndsWith("*") && rom.CRC.StartsWith(_crc.Replace("*", "")))) { continue; } } // Filter on md5 if (_md5 != "") { if (!(_md5.StartsWith("*") && _md5.EndsWith("*") && rom.MD5.Contains(_md5.Replace("*", "")))) { continue; } else if (!(_md5.StartsWith("*") && rom.MD5.EndsWith(_md5.Replace("*", "")))) { continue; } else if (!(_md5.EndsWith("*") && rom.MD5.StartsWith(_md5.Replace("*", "")))) { continue; } } // Filter on sha1 if (_sha1 != "") { if (!(_sha1.StartsWith("*") && _sha1.EndsWith("*") && rom.SHA1.Contains(_sha1.Replace("*", "")))) { continue; } else if (!(_sha1.StartsWith("*") && rom.SHA1.EndsWith(_sha1.Replace("*", "")))) { continue; } else if (!(_sha1.EndsWith("*") && rom.SHA1.StartsWith(_sha1.Replace("*", "")))) { continue; } } // If it made it this far, add the rom to the output dictionary if (dict.ContainsKey(key)) { dict[key].Add(rom); } else { List temp = new List(); temp.Add(rom); dict.Add(key, temp); } } // Now clean up by removing the old list datdata.Roms[key] = null; } // Get the correct output values datdata.Name += " (Filtered)"; datdata.Description += " (Filtered)"; datdata.Roms = dict; // Now write the file out and return return Output.WriteDatfile(datdata, _outdir, _logger); } } }