diff --git a/DATFromDir/DATFromDir.cs b/DATFromDir/DATFromDir.cs index 522f3dce..2e757af6 100644 --- a/DATFromDir/DATFromDir.cs +++ b/DATFromDir/DATFromDir.cs @@ -23,7 +23,7 @@ namespace SabreTools private string _tempDir; // Extraction and listing related variables - private List _roms; + private Dictionary> _dict; private List _inputs; // User specified flags @@ -214,8 +214,8 @@ namespace SabreTools /// True if the DAT could be created, false otherwise public bool Start() { - // Create an output array for all found items - _roms = new List(); + // Create an output dictionary for all found items + _dict = new Dictionary>(); /* For clarity, here is the process for SuperDAT: @@ -283,25 +283,11 @@ namespace SabreTools } // If we found nothing (error state), exit - if (_roms.Count == 0) + if (_dict.Count == 0) { return false; } - // Order the roms by name of parent, then name of rom - _roms.Sort(delegate (RomData A, RomData B) - { - if (A.Game == B.Game) - { - if (A.Name == B.Name) - { - return (int)(A.Size - B.Size); - } - return String.Compare(A.Name, B.Name); - } - return String.Compare(A.Game, B.Game); - }); - // Double check to see what it needs to be named if (_name == "") { @@ -321,8 +307,21 @@ namespace SabreTools _name = (_name == "" ? "Default" : _name); _desc = (_desc == "" ? _name + (_bare ? "" : " (" + _date + ")") : _desc); + DatData datdata = new DatData + { + Name = _name, + Description = _desc, + Version = _version, + Date = _date, + Category = _cat, + Author = _author, + ForcePacking = (_forceunpack ? ForcePacking.Unzip : ForcePacking.None), + OutputFormat = (_old ? OutputFormat.ClrMamePro : OutputFormat.Xml), + Roms = _dict, + }; + // Now write it all out as a DAT - Output.WriteToDat(_name, _desc, _version, _date, _cat, _author, _forceunpack, _old, Environment.CurrentDirectory, _roms, _logger); + Output.WriteDatfile(datdata, Environment.CurrentDirectory, _logger); return true; } @@ -331,7 +330,7 @@ namespace SabreTools /// Check a given file for hashes, based on current settings /// /// Filename of the item to be checked - private void ProcessFile (string item) + private void ProcessFile(string item) { // Create the temporary output directory DirectoryInfo di = Directory.CreateDirectory(_tempDir); @@ -409,7 +408,7 @@ namespace SabreTools continue; } - _roms.Add(new RomData + RomData rom = new RomData { Type = "rom", Game = Path.GetFileNameWithoutExtension(item), @@ -418,7 +417,19 @@ namespace SabreTools CRC = fileCRC, MD5 = fileMD5, SHA1 = fileSHA1, - }); + }; + + string key = rom.Size + "-" + rom.CRC; + if (_dict.ContainsKey(key)) + { + _dict[key].Add(rom); + } + else + { + List temp = new List(); + temp.Add(rom); + _dict.Add(key, temp); + } _logger.User("File added: " + entry + Environment.NewLine); } @@ -473,7 +484,7 @@ namespace SabreTools _logger.Log("Actual item added: " + actualitem); - _roms.Add(new RomData + RomData rom = new RomData { Type = "rom", Game = actualroot, @@ -482,7 +493,19 @@ namespace SabreTools CRC = fileCRC, MD5 = fileMD5, SHA1 = fileSHA1, - }); + }; + + string key = rom.Size + "-" + rom.CRC; + if (_dict.ContainsKey(key)) + { + _dict[key].Add(rom); + } + else + { + List temp = new List(); + temp.Add(rom); + _dict.Add(key, temp); + } _logger.User("File added: " + actualitem + Environment.NewLine); } diff --git a/DATabase/DATabase.cs b/DATabase/DATabase.cs index 70302322..58c5b72a 100644 --- a/DATabase/DATabase.cs +++ b/DATabase/DATabase.cs @@ -1314,12 +1314,12 @@ Make a selection: MergeRoms = false, }; - datdata = RomManipulation.ParseDict(filename, 0, 0, datdata, logger); + datdata = RomManipulation.Parse(filename, 0, 0, datdata, logger); logger.User("datdata.Description: " + datdata.Description); datdata.Description += ".new"; - Output.WriteToDatFromDict(datdata, Path.GetDirectoryName(filename), logger); + Output.WriteDatfile(datdata, Path.GetDirectoryName(filename), logger); } else { @@ -1354,12 +1354,12 @@ Make a selection: MergeRoms = false, }; - datdata = RomManipulation.ParseDict(filename, 0, 0, datdata, logger); + datdata = RomManipulation.Parse(filename, 0, 0, datdata, logger); logger.User("datdata.Description: " + datdata.Description); datdata.Description += ".new"; - Output.WriteToDatFromDict(datdata, Path.GetDirectoryName(filename), logger); + Output.WriteDatfile(datdata, Path.GetDirectoryName(filename), logger); } else { @@ -1394,12 +1394,12 @@ Make a selection: MergeRoms = false, }; - datdata = RomManipulation.ParseDict(filename, 0, 0, datdata, logger); + datdata = RomManipulation.Parse(filename, 0, 0, datdata, logger); logger.User("datdata.Description: " + datdata.Description); datdata.Description += ".new"; - Output.WriteToDatFromDict(datdata, Path.GetDirectoryName(filename), logger); + Output.WriteDatfile(datdata, Path.GetDirectoryName(filename), logger); } else { @@ -1430,11 +1430,42 @@ Make a selection: input = Path.GetFullPath(input); // Get the output name - string name = Path.GetFileNameWithoutExtension(input) + "-miss.txt"; + string name = Path.GetFileNameWithoutExtension(input) + "-miss"; // Read in the roms from the DAT and then write them to the file logger.User("Converting " + input); - Output.WriteToText(name, Path.GetDirectoryName(input), RomManipulation.Parse(input, 0, 0, logger), logger, usegame, prefix, postfix, addext, repext, quotes, gamename); + DatData datdata = new DatData + { + Name = "", + Description = "", + Category = "", + Version = "", + Date = "", + Author = "", + Email = "", + Homepage = "", + Url = "", + Comment = "", + Roms = new Dictionary>(), + OutputFormat = OutputFormat.MissFile, + + UseGame = usegame, + Prefix = prefix, + Postfix = postfix, + AddExt = addext, + RepExt = repext, + Quotes = quotes, + GameName = gamename, + }; + datdata = RomManipulation.Parse(input, 0, 0, datdata, logger); + datdata.Name += "-miss"; + datdata.Description += "-miss"; + + // Normalize the extensions + addext = (addext == "" || addext.StartsWith(".") ? addext : "." + addext); + repext = (repext == "" || repext.StartsWith(".") ? repext : "." + repext); + + Output.WriteDatfile(datdata, Path.GetDirectoryName(input), logger); logger.User(input + " converted to: " + name); return; } diff --git a/DATabase/ExtSplit.cs b/DATabase/ExtSplit.cs index e0360542..77f15941 100644 --- a/DATabase/ExtSplit.cs +++ b/DATabase/ExtSplit.cs @@ -73,7 +73,7 @@ namespace SabreTools }; // Load the current DAT to be processed - datdata = RomManipulation.ParseDict(_filename, 0, 0, datdata, _logger); + datdata = RomManipulation.Parse(_filename, 0, 0, datdata, _logger); // Set all of the appropriate outputs for each of the subsets OutputFormat outputFormat = RomManipulation.GetOutputFormat(_filename); @@ -172,8 +172,8 @@ namespace SabreTools } // Then write out both files - bool success = Output.WriteToDatFromDict(datdataA, _outdir, _logger); - success &= Output.WriteToDatFromDict(datdataB, _outdir, _logger); + bool success = Output.WriteDatfile(datdataA, _outdir, _logger); + success &= Output.WriteDatfile(datdataB, _outdir, _logger); return success; } diff --git a/DATabase/Generate.cs b/DATabase/Generate.cs index 9e3d382d..b967bfe5 100644 --- a/DATabase/Generate.cs +++ b/DATabase/Generate.cs @@ -155,10 +155,10 @@ namespace SabreTools } // Retrieve the list of processed roms - List roms = ProcessRoms(); + Dictionary> dict = ProcessRoms(); // If the output is null, nothing was found so return false - if (roms == null) + if (dict.Count == 0) { return false; } @@ -168,16 +168,29 @@ namespace SabreTools string intname = systemname + " (" + sourcename + ")"; string datname = systemname + " (" + sourcename + " " + version + ")"; - return Output.WriteToDat(intname, datname, version, version, "The Wizard of DATz", "The Wizard of DATz", false, _old, _outdir, roms, _logger); + DatData datdata = new DatData + { + Name = intname, + Description = datname, + Version = version, + Date = version, + Category = "The Wizard of DATz", + Author = "The Wizard of DATz", + ForcePacking = ForcePacking.None, + OutputFormat = (_old ? OutputFormat.ClrMamePro : OutputFormat.Xml), + Roms = dict, + }; + + return Output.WriteDatfile(datdata, _outdir, _logger); } /// /// Preprocess the rom data that is to be included in the outputted DAT /// /// A List of RomData objects containing all information about the files - public List ProcessRoms() + public Dictionary> ProcessRoms() { - List roms = new List(); + Dictionary> roms = new Dictionary>(); // Check if we have listed sources or systems bool sysmerged = (_systems == "" || _systems.Split(',').Length > 1); @@ -250,7 +263,17 @@ JOIN checksums (srcmerged ? " [" + temp.Source + "]" : ""); } - roms.Add(temp); + string key = temp.Size + "-" + temp.CRC; + if (roms.ContainsKey(key)) + { + roms[key].Add(temp); + } + else + { + List templist = new List(); + templist.Add(temp); + roms.Add(key, templist); + } } } } @@ -259,8 +282,10 @@ JOIN checksums // If we're in a merged mode, merge and then resort by the correct parameters if (merged) { - roms = RomManipulation.Merge(roms, true); - RomManipulation.Sort(roms, _norename); + foreach (string key in roms.Keys) + { + roms[key] = RomManipulation.Merge(roms[key]); + } } // END COMMENT @@ -338,7 +363,17 @@ JOIN source (srcmerged ? " [" + temp.Source + "]" : ""); } - roms.Add(temp); + string key = temp.Size + "-" + temp.CRC; + if (roms.ContainsKey(key)) + { + roms[key].Add(temp); + } + else + { + List templist = new List(); + templist.Add(temp); + roms.Add(key, templist); + } // Reset the variables game = ""; @@ -380,13 +415,16 @@ JOIN source // If we're in a merged mode, merge if (merged) { - roms = RomManipulation.Merge(roms); + foreach (string key in roms.Keys) + { + roms[key] = RomManipulation.Merge(roms[key]); + } } - - // Now sort the roms by the correct parameters - RomManipulation.Sort(roms, _norename); */ + /* + // THIS CODE SHOULD BE PUT IN WriteToDatFromDict + // Now check rename within games string lastname = "", lastgame = ""; for (int i = 0; i < roms.Count; i++) @@ -420,6 +458,7 @@ JOIN source // Assign back just in case roms[i] = rom; } + */ return roms; } diff --git a/DATabase/Import.cs b/DATabase/Import.cs index eb8643ba..ede610bc 100644 --- a/DATabase/Import.cs +++ b/DATabase/Import.cs @@ -399,33 +399,66 @@ namespace SabreTools } // Get all roms that are found in the DAT to see what needs to be added - List roms = RomManipulation.Parse(_filepath, sysid, srcid, _logger); - - // Sort and loop over all roms, checking for adds - RomManipulation.Sort(roms, true); - string lastgame = ""; - long gameid = -1; - using (SqliteConnection dbc = new SqliteConnection(_connectionString)) + DatData datdata = new DatData { - dbc.Open(); - foreach (RomData rom in roms) + Roms = new Dictionary>(), + }; + datdata = RomManipulation.Parse(_filepath, sysid, srcid, datdata, _logger); + + // Sort inputted roms into games + SortedDictionary> sortable = new SortedDictionary>(); + long count = 0; + foreach (List roms in datdata.Roms.Values) + { + List newroms = roms; + if (datdata.MergeRoms) { - // BEGIN COMMENT - // If we have a new game, check for a new ID - if (rom.Game != lastgame) + newroms = RomManipulation.Merge(newroms); + } + + foreach (RomData rom in newroms) + { + count++; + string key = rom.SystemID.ToString().PadLeft(10, '0') + "-" + rom.SourceID.ToString().PadLeft(10, '0') + "-" + rom.Game.ToLowerInvariant(); + if (sortable.ContainsKey(key)) { - gameid = AddGame(sysid, rom.Game, srcid, dbc); - lastgame = rom.Game; + sortable[key].Add(rom); } + else + { + List temp = new List(); + temp.Add(rom); + sortable.Add(key, temp); + } + } + } - // Try to add the rom with the game information - AddRom(rom, gameid, date, dbc); - // END COMMENT + // Loop over all roms, checking for adds + foreach (string key in sortable.Keys) + { + List roms = sortable[key]; + RomManipulation.Sort(roms, true); - /* - // Try to add the romdata - AddHash(rom, sysid, srcid, date, dbc); - */ + long gameid = -1; + using (SqliteConnection dbc = new SqliteConnection(_connectionString)) + { + dbc.Open(); + + // For each game, check for a new ID + gameid = AddGame(sysid, roms[0].Game, srcid, dbc); + + foreach (RomData rom in roms) + { + // BEGIN COMMENT + // Try to add the rom with the game information + AddRom(rom, gameid, date, dbc); + // END COMMENT + + /* + // Try to add the romdata + AddHash(rom, sysid, srcid, date, dbc); + */ + } } } diff --git a/DATabase/MergeDiff.cs b/DATabase/MergeDiff.cs index 96f35bac..f672705a 100644 --- a/DATabase/MergeDiff.cs +++ b/DATabase/MergeDiff.cs @@ -115,7 +115,7 @@ namespace SabreTools foreach (string input in _inputs) { _logger.User("Adding DAT: " + input); - userData = RomManipulation.ParseDict(input, i, 0, userData, _logger); + userData = RomManipulation.Parse(input, i, 0, userData, _logger); i++; } @@ -164,7 +164,7 @@ namespace SabreTools post = " (No Duplicates)"; // Output the difflist (a-b)+(b-a) diff - Output.WriteToDatFromDict(outerDiffData, "", _logger); + Output.WriteDatfile(outerDiffData, "", _logger); // For the AB mode-style diffs, get all required dictionaries and output with a new name // Loop through _inputs first and filter from all diffed roms to find the ones that have the same "System" @@ -205,7 +205,7 @@ namespace SabreTools } post = " (" + Path.GetFileNameWithoutExtension(_inputs[j]) + " Only)"; - Output.WriteToDatFromDict(diffData, "", _logger); + Output.WriteDatfile(diffData, "", _logger); } // Get all entries that have External dupes @@ -246,12 +246,12 @@ namespace SabreTools } } - Output.WriteToDatFromDict(dupeData, "", _logger); + Output.WriteDatfile(dupeData, "", _logger); } // Output all entries with user-defined merge else { - Output.WriteToDatFromDict(userData, "", _logger); + Output.WriteDatfile(userData, "", _logger); } return true; diff --git a/DATabase/TrimMerge.cs b/DATabase/TrimMerge.cs index 1b0a7ecf..a11b5334 100644 --- a/DATabase/TrimMerge.cs +++ b/DATabase/TrimMerge.cs @@ -98,7 +98,7 @@ namespace SabreTools ForcePacking = (_forceunpack ? ForcePacking.Unzip : ForcePacking.None), OutputFormat = RomManipulation.GetOutputFormat(filename), }; - datdata = RomManipulation.ParseDict(filename, 0, 0, datdata, _logger); + datdata = RomManipulation.Parse(filename, 0, 0, datdata, _logger); // Trim all file names according to the path that's set foreach (string key in datdata.Roms.Keys) @@ -130,7 +130,7 @@ namespace SabreTools } // Now write the file out accordingly - Output.WriteToDatFromDict(datdata, Path.GetDirectoryName(filename), _logger); + Output.WriteDatfile(datdata, Path.GetDirectoryName(filename), _logger); // Remove the original file if different and inform the user if (filename != datdata.Description + (RomManipulation.GetOutputFormat(filename) == OutputFormat.Xml ? ".xml" : ".dat")) diff --git a/DATabaseTwo/Generate.cs b/DATabaseTwo/Generate.cs index f8f2c95a..9b2589fb 100644 --- a/DATabaseTwo/Generate.cs +++ b/DATabaseTwo/Generate.cs @@ -174,7 +174,7 @@ namespace SabreTools { Int32.TryParse(sourcemap[hash], out tempSrcId); } - datdata = RomManipulation.ParseDict(file, 0, tempSrcId, datdata, _logger); + datdata = RomManipulation.Parse(file, 0, tempSrcId, datdata, _logger); } // If the dictionary is empty for any reason, tell the user and exit @@ -239,7 +239,7 @@ namespace SabreTools } // Then write out the file - Output.WriteToDatFromDict(datdata, _outroot, _logger, _norename); + Output.WriteDatfile(datdata, _outroot, _logger, _norename); return true; } diff --git a/OfflineMerge/OfflineMerge.cs b/OfflineMerge/OfflineMerge.cs index 75c16943..48fed2a0 100644 --- a/OfflineMerge/OfflineMerge.cs +++ b/OfflineMerge/OfflineMerge.cs @@ -148,8 +148,8 @@ namespace SabreTools { Roms = new Dictionary>(), }; - completeDats = RomManipulation.ParseDict(_currentAllMerged, 0, 0, completeDats, _logger); - completeDats = RomManipulation.ParseDict(_currentNewMerged, 0, 0, completeDats, _logger); + completeDats = RomManipulation.Parse(_currentAllMerged, 0, 0, completeDats, _logger); + completeDats = RomManipulation.Parse(_currentNewMerged, 0, 0, completeDats, _logger); // Now get Net New output dictionary [(currentNewMerged)-(currentAllMerged)] _logger.User("Creating and populating Net New dictionary"); @@ -205,7 +205,7 @@ namespace SabreTools { Roms = new Dictionary>(), }; - midMissing = RomManipulation.ParseDict(_currentMissingMerged, 0, 0, midMissing, _logger); + midMissing = RomManipulation.Parse(_currentMissingMerged, 0, 0, midMissing, _logger); foreach (string key in unneeded.Keys) { if (midMissing.Roms.ContainsKey(key)) @@ -441,10 +441,10 @@ namespace SabreTools Roms = have, }; - Output.WriteToDatFromDict(netNewData, "", _logger); - Output.WriteToDatFromDict(unneededData, "", _logger); - Output.WriteToDatFromDict(newMissingData, "", _logger); - Output.WriteToDatFromDict(haveData, "", _logger); + Output.WriteDatfile(netNewData, "", _logger); + Output.WriteDatfile(unneededData, "", _logger); + Output.WriteDatfile(newMissingData, "", _logger); + Output.WriteDatfile(haveData, "", _logger); return true; } @@ -458,8 +458,8 @@ namespace SabreTools { Roms = new Dictionary>(), }; - midHave = RomManipulation.ParseDict(_currentMissingMerged, 0, 0, midHave, _logger); - midHave = RomManipulation.ParseDict(_currentAllMerged, 0, 0, midHave, _logger); + midHave = RomManipulation.Parse(_currentMissingMerged, 0, 0, midHave, _logger); + midHave = RomManipulation.Parse(_currentAllMerged, 0, 0, midHave, _logger); Dictionary> have = new Dictionary>(); foreach (string key in midHave.Roms.Keys) { @@ -517,7 +517,7 @@ namespace SabreTools MergeRoms = true, Roms = have, }; - Output.WriteToDatFromDict(haveData, "", _logger); + Output.WriteDatfile(haveData, "", _logger); return true; } @@ -531,8 +531,8 @@ namespace SabreTools { Roms = new Dictionary>(), }; - midHave = RomManipulation.ParseDict(_currentMissingMerged, 0, 0, midHave, _logger); - midHave = RomManipulation.ParseDict(_currentNewMerged, 0, 0, midHave, _logger); + midHave = RomManipulation.Parse(_currentMissingMerged, 0, 0, midHave, _logger); + midHave = RomManipulation.Parse(_currentNewMerged, 0, 0, midHave, _logger); Dictionary> have = new Dictionary>(); foreach (string key in midHave.Roms.Keys) { @@ -590,7 +590,7 @@ namespace SabreTools MergeRoms = true, Roms = have, }; - Output.WriteToDatFromDict(haveData, "", _logger); + Output.WriteDatfile(haveData, "", _logger); return true; } diff --git a/SabreHelper/Output.cs b/SabreHelper/Output.cs index 0086b812..fb9f9ac5 100644 --- a/SabreHelper/Output.cs +++ b/SabreHelper/Output.cs @@ -10,134 +10,6 @@ namespace SabreTools.Helper { public class Output { - /// - /// Create and open an output file for writing - /// - /// Internal name of the DAT - /// Description and external name of the DAT - /// Version or iteration of the DAT - /// Usually the DAT creation date - /// Category of the DAT - /// DAT author - /// Force all sets to be unzipped - /// Set output mode to old-style DAT - /// Set the output directory - /// List of RomData objects representing the games to be written out - /// Logger object for console and/or file output - /// Tru if the DAT was written correctly, false otherwise - public static bool WriteToDat(string name, string description, string version, string date, string category, string author, - bool forceunpack, bool old, string outDir, List roms, Logger logger) - { - // If it's empty, use the current folder - if (outDir.Trim() == "") - { - outDir = Environment.CurrentDirectory; - } - - // Double check the outdir for the end delim - if (!outDir.EndsWith(Path.DirectorySeparatorChar.ToString())) - { - outDir += Path.DirectorySeparatorChar; - } - - // (currently uses current time, change to "last updated time") - logger.User("Opening file for writing: " + outDir + description + (old ? ".dat" : ".xml")); - - try - { - FileStream fs = File.Create(outDir + description + (old ? ".dat" : ".xml")); - StreamWriter sw = new StreamWriter(fs, Encoding.UTF8); - - string header_old = "clrmamepro (\n" + - "\tname \"" + HttpUtility.HtmlEncode(name) + "\"\n" + - "\tdescription \"" + HttpUtility.HtmlEncode(description) + "\"\n" + - "\tcategory \"" + HttpUtility.HtmlEncode(category) + "\"\n" + - "\tversion \"" + HttpUtility.HtmlEncode(version) + "\"\n" + - "\tdate \"" + HttpUtility.HtmlEncode(date) + "\"\n" + - "\tauthor \"" + HttpUtility.HtmlEncode(author) + "\"\n" + - (forceunpack ? "\tforcezipping no\n" : "") + - ")\n"; - - string header = "\n" + - "\n\n" + - "\n" + - "\t
\n" + - "\t\t" + HttpUtility.HtmlEncode(name) + "\n" + - "\t\t" + HttpUtility.HtmlEncode(description) + "\n" + - "\t\t" + HttpUtility.HtmlEncode(category) + "\n" + - "\t\t" + HttpUtility.HtmlEncode(version) + "\n" + - "\t\t" + HttpUtility.HtmlEncode(date) + "\n" + - "\t\t" + HttpUtility.HtmlEncode(author) + "\n" + - (forceunpack ? "\t\t\n" : "") + - "\t
\n"; - - // Write the header out - sw.Write((old ? header_old : header)); - - // Write out each of the machines and roms - string lastgame = null; - foreach (RomData rom in roms) - { - string state = ""; - if (lastgame != null && lastgame != rom.Game) - { - state += (old ? ")\n" : "\t\n"); - } - - if (lastgame != rom.Game) - { - state += (old ? "game (\n\tname \"" + rom.Game + "\"\n" + - "\tdescription \"" + rom.Game + "\"\n" : - "\t\n" + - "\t\t" + HttpUtility.HtmlEncode(rom.Game) + "\n"); - } - - if (old) - { - state += "\t" + rom.Type + " ( name \"" + rom.Name + "\"" + - (rom.Size != -1 && - rom.Size != 0 && - rom.CRC != RomManipulation.CRCZero && - rom.MD5 != RomManipulation.MD5Zero && - rom.SHA1 != RomManipulation.SHA1Zero ? " size " + rom.Size : "") + - (rom.CRC != "" ? " crc " + rom.CRC.ToLowerInvariant() : "") + - (rom.MD5 != "" ? " md5 " + rom.MD5.ToLowerInvariant() : "") + - (rom.SHA1 != "" ? " sha1 " + rom.SHA1.ToLowerInvariant() : "") + - " )\n"; - } - else - { - state += "\t\t<" + rom.Type + " name=\"" + HttpUtility.HtmlEncode(rom.Name) + "\"" + - (rom.Size != -1 && - rom.Size != 0 && - rom.CRC != RomManipulation.CRCZero && - rom.MD5 != RomManipulation.MD5Zero && - rom.SHA1 != RomManipulation.SHA1Zero ? " size=\"" + rom.Size + "\"" : "") + - (rom.CRC != "" ? " crc=\"" + rom.CRC.ToLowerInvariant() + "\"" : "") + - (rom.MD5 != "" ? " md5=\"" + rom.MD5.ToLowerInvariant() + "\"" : "") + - (rom.SHA1 != "" ? " sha1=\"" + rom.SHA1.ToLowerInvariant() + "\"" : "") + - "/>\n"; - } - - lastgame = rom.Game; - - sw.Write(state); - } - - sw.Write((old ? ")" : "\t\n
")); - logger.User("File written!" + Environment.NewLine); - sw.Close(); - fs.Close(); - } - catch (Exception ex) - { - logger.Error(ex.ToString()); - return false; - } - - return true; - } - /// /// Create and open an output file for writing direct from a dictionary /// @@ -150,8 +22,13 @@ namespace SabreTools.Helper /// The following features have been requested for file output: /// - Have the ability to strip special (non-ASCII) characters from rom information /// - Add a flag for ignoring roms with blank sizes + /// - For OutputFormat.MissFile: + /// + Have switch for automatically outputting to Romba format: + /// e.g. /aa/bb/cc/dd/aabbccddef770b06131a878b46d4302ac28dd126.gz + /// Anything without a SHA-1 has to be skipped /// - public static bool WriteToDatFromDict(DatData datdata, string outDir, Logger logger, bool norename = true) + /// + public static bool WriteDatfile(DatData datdata, string outDir, Logger logger, bool norename = true) { // Get all values in the dictionary and write out SortedDictionary> sortable = new SortedDictionary>(); @@ -299,6 +176,36 @@ namespace SabreTools.Helper (rom.SHA1 != "" ? " sha1 " + rom.SHA1.ToLowerInvariant() : "") + " )\n"; break; + case OutputFormat.MissFile: + string pre = datdata.Prefix + (datdata.Quotes ? "\"" : ""); + string post = (datdata.Quotes ? "\"" : "") + datdata.Postfix; + string name = (datdata.UseGame ? rom.Game : rom.Name); + if (datdata.RepExt != "") + { + string dir = Path.GetDirectoryName(name); + dir = (dir.EndsWith(Path.DirectorySeparatorChar.ToString()) ? dir : dir + Path.DirectorySeparatorChar); + dir = (dir.StartsWith(Path.DirectorySeparatorChar.ToString()) ? dir.Remove(0, 1) : dir); + name = dir + Path.GetFileNameWithoutExtension(name) + datdata.RepExt; + } + if (datdata.AddExt != "") + { + name += datdata.AddExt; + } + if (!datdata.UseGame && datdata.GameName) + { + name = (rom.Game.EndsWith(Path.DirectorySeparatorChar.ToString()) ? rom.Game : rom.Game + Path.DirectorySeparatorChar) + name; + } + + if (datdata.UseGame && rom.Game != lastgame) + { + state += pre + name + post + "\n"; + lastgame = rom.Game; + } + else if (!datdata.UseGame) + { + state += pre + name + post + "\n"; + } + break; case OutputFormat.RomCenter: state += "¬¬¬" + HttpUtility.HtmlEncode(rom.Game) + "¬" + HttpUtility.HtmlEncode(rom.Game) + @@ -346,185 +253,5 @@ namespace SabreTools.Helper return true; } - - /// - /// Output a list of roms as a text file with an arbitrary prefix and postfix - /// - /// Name of the output file - /// Output directory for the miss file - /// List of RomData objects representing the roms to be output - /// Logger object for console and/or file output - /// True if only games are written to text file (default), false for files only - /// Arbitrary string to prefix each line - /// Arbitrary string to postfix each line - /// True if quotes should be put around the item, false otherwise (default) - /// Arbitrary extension added to the end of each item - /// Arbitrary extension to replace all extensions in the item - /// True if the game name is appended (only when !usegame), false otherwise - /// True if the file was written, false otherwise - /// - /// The following features have been requested for this method: - /// - Have switch for automatically outputting to Romba format: - /// e.g. /aa/bb/cc/dd/aabbccddef770b06131a878b46d4302ac28dd126.gz - /// Anything without a SHA-1 has to be skipped - /// - public static bool WriteToText(string textfile, string outdir, List roms, Logger logger, bool useGame = true, string prefix = "", - string postfix = "", string addext = "", string repext = "", bool quotes = false, bool gamename = false) - { - // Normalize the output directory - if (outdir == "") - { - outdir = Environment.CurrentDirectory; - } - if (!outdir.EndsWith(Path.DirectorySeparatorChar.ToString())) - { - outdir += Path.DirectorySeparatorChar; - } - - // Make the output directory if it doesn't exist - if (!Directory.Exists(outdir)) - { - Directory.CreateDirectory(outdir); - } - - // Normalize the extensions - addext = (addext == "" || addext.StartsWith(".") ? addext : "." + addext); - repext = (repext == "" || repext.StartsWith(".") ? repext : "." + repext); - - logger.User("Opening file for writing: " + outdir + textfile); - - try - { - FileStream fs = File.Create(outdir + textfile); - StreamWriter sw = new StreamWriter(fs, Encoding.UTF8); - - string lastgame = ""; - foreach (RomData rom in roms) - { - string pre = prefix + (quotes ? "\"" : ""); - string post = (quotes ? "\"" : "") + postfix; - string name = (useGame ? rom.Game : rom.Name); - if (repext != "") - { - string dir = Path.GetDirectoryName(name); - dir = (dir.EndsWith(Path.DirectorySeparatorChar.ToString()) ? dir : dir + Path.DirectorySeparatorChar); - dir = (dir.StartsWith(Path.DirectorySeparatorChar.ToString()) ? dir.Remove(0, 1) : dir); - name = dir + Path.GetFileNameWithoutExtension(name) + repext; - } - if (addext != "") - { - name += addext; - } - if (!useGame && gamename) - { - name = (rom.Game.EndsWith(Path.DirectorySeparatorChar.ToString()) ? rom.Game : rom.Game + Path.DirectorySeparatorChar) + name; - } - - if (useGame && rom.Game != lastgame) - { - sw.WriteLine(pre + name + post); - lastgame = rom.Game; - } - else if (!useGame) - { - sw.WriteLine(pre + name + post); - } - } - - logger.User("File written!" + Environment.NewLine); - sw.Close(); - fs.Close(); - } - catch (Exception ex) - { - logger.Error(ex.ToString()); - return false; - } - - return true; - } - - /// - /// Convert a List of RomData objects to a List of tab-deliminated strings - /// - /// List of RomData objects representing the roms to be parsed - /// List of Strings representing the roms - public static List RomDataToString(List roms) - { - List outlist = new List(); - foreach (RomData rom in roms) - { - outlist.Add(rom.Manufacturer + "\t" + - rom.System + "\t" + - rom.SystemID + "\t" + - rom.Source + "\t" + - rom.URL + "\t" + - rom.SourceID + "\t" + - rom.Game + "\t" + - rom.Name + "\t" + - rom.Type + "\t" + - rom.Size + "\t" + - rom.CRC + "\t" + - rom.MD5 + "\t" + - rom.SHA1); - } - return outlist; - } - - /// - /// Convert a List of RomData objects' hash information to a List of tab-deliminated strings - /// - /// List of RomData objects representing the roms to be parsed - /// List of Strings representing the rom hashes - public static List HashDataToString(List roms) - { - List outlist = new List(); - foreach (RomData rom in roms) - { - outlist.Add(rom.Size + "\t" + - rom.CRC + "\t" + - rom.MD5 + "\t" + - rom.SHA1); - } - return outlist; - } - - /// - /// Convert a List of tab-deliminated strings objects to a List of RomData objects - /// - /// List of Strings representing the roms to be parsed - /// List of RomData objects representing the roms - public static List StringToRomData(List roms) - { - List outlist = new List(); - foreach (String rom in roms) - { - string[] temp = rom.Split('\t'); - try - { - outlist.Add(new RomData - { - Manufacturer = temp[0], - System = temp[1], - SystemID = Int32.Parse(temp[2]), - Source = temp[3], - URL = temp[4], - SourceID = Int32.Parse(temp[5]), - Game = temp[6], - Name = temp[7], - Type = temp[8], - Size = Int64.Parse(temp[9]), - CRC = temp[10], - MD5 = temp[11], - SHA1 = temp[12], - }); - } - catch (Exception ex) - { - Console.WriteLine(ex.ToString()); - } - } - return outlist; - } } } diff --git a/SabreHelper/RomManipulation.cs b/SabreHelper/RomManipulation.cs index ba5bff52..35b8a4e4 100644 --- a/SabreHelper/RomManipulation.cs +++ b/SabreHelper/RomManipulation.cs @@ -89,152 +89,6 @@ namespace SabreTools.Helper return xtr; } - /// - /// Parse a DAT and return all found games and roms within - /// - /// Name of the file to be parsed - /// System ID for the DAT - /// Source ID for the DAT - /// Logger object for console and/or file output - /// List of RomData objects representing the found data - public static List Parse(string filename, int sysid, int srcid, Logger logger) - { - List roms = new List(); - XmlTextReader xtr = GetXmlTextReader(filename, logger); - bool superdat = false, shouldbreak = false; - string parent = ""; - if (xtr != null) - { - xtr.MoveToContent(); - while (xtr.NodeType != XmlNodeType.None) - { - // We only want elements - if (xtr.NodeType != XmlNodeType.Element) - { - xtr.Read(); - continue; - } - - switch (xtr.Name) - { - case "datafile": - case "softwarelist": - parent = xtr.Name; - xtr.Read(); - break; - case "header": - xtr.ReadToDescendant("name"); - string content = xtr.ReadElementContentAsString(); - superdat = (content != null ? content.Contains(" - SuperDAT") : false); - while (xtr.Name != "header") - { - xtr.Read(); - } - xtr.Read(); - break; - case "machine": - case "game": - case "software": - string temptype = xtr.Name; - string tempname = ""; - - // We want to process the entire subtree of the game - XmlReader subreader = xtr.ReadSubtree(); - - if (subreader != null) - { - if (temptype == "software" && subreader.ReadToFollowing("description")) - { - tempname = subreader.ReadElementContentAsString(); - } - else - { - // There are rare cases where a malformed XML will not have the required attributes. We can only skip them. - if (xtr.AttributeCount == 0) - { - logger.Error("No attributes were found"); - xtr.ReadToNextSibling(xtr.Name); - continue; - } - tempname = xtr.GetAttribute("name"); - } - - if (superdat) - { - tempname = Regex.Match(tempname, @".*?\\(.*)").Groups[1].Value; - } - - while (subreader.Read()) - { - // We only want elements - if (subreader.NodeType != XmlNodeType.Element) - { - continue; - } - - // Get the roms from the machine - switch (subreader.Name) - { - case "rom": - case "disk": - // Take care of hex-sized files - long size = -1; - if (xtr.GetAttribute("size") != null && xtr.GetAttribute("size").Contains("0x")) - { - size = Convert.ToInt64(xtr.GetAttribute("size"), 16); - } - else if (xtr.GetAttribute("size") != null) - { - Int64.TryParse(xtr.GetAttribute("size"), out size); - } - - // Take care of hex-prefixed hashes - string crc = (xtr.GetAttribute("crc") != null ? xtr.GetAttribute("crc").ToLowerInvariant().Trim() : ""); - crc = (crc.StartsWith("0x") ? crc.Remove(0, 2) : crc); - string md5 = (xtr.GetAttribute("md5") != null ? xtr.GetAttribute("md5").ToLowerInvariant().Trim() : ""); - md5 = (md5.StartsWith("0x") ? md5.Remove(0, 2) : md5); - string sha1 = (xtr.GetAttribute("sha1") != null ? xtr.GetAttribute("sha1").ToLowerInvariant().Trim() : ""); - sha1 = (sha1.StartsWith("0x") ? sha1.Remove(0, 2) : sha1); - - roms.Add(new RomData - { - Game = tempname, - Name = xtr.GetAttribute("name"), - Type = xtr.Name, - SystemID = sysid, - SourceID = srcid, - Size = size, - CRC = crc, - MD5 = md5, - SHA1 = sha1, - }); - break; - } - } - } - - // Read to next game - if (!xtr.ReadToNextSibling(temptype)) - { - shouldbreak = true; - } - break; - default: - xtr.Read(); - break; - } - - // If we hit an endpoint, break out of the loop early - if (shouldbreak) - { - break; - } - } - } - - return roms; - } - /// /// Parse a DAT and return all found games and roms within /// @@ -244,7 +98,7 @@ namespace SabreTools.Helper /// The DatData object representing found roms to this point /// Logger object for console and/or file output /// DatData object representing the read-in data - public static DatData ParseDict(string filename, int sysid, int srcid, DatData datdata, Logger logger) + public static DatData Parse(string filename, int sysid, int srcid, DatData datdata, Logger logger) { XmlTextReader xtr = GetXmlTextReader(filename, logger); bool superdat = false, shouldbreak = false; @@ -695,50 +549,5 @@ namespace SabreTools.Helper }); return true; } - - /// - /// Get differences between two lists of RomData objects - /// - /// First RomData list - /// Second RomData list - /// Any rom that's not in both lists - /// Adapted from http://stackoverflow.com/questions/5620266/the-opposite-of-intersect - public static List Diff(List A, List B) - { - List AString = Output.RomDataToString(A); - List BString = Output.RomDataToString(B); - List CString = AString.Except(BString).Union(BString.Except(AString)).ToList(); - return Output.StringToRomData(CString); - } - - /// - /// Get all RomData objects that are in A but not in B - /// - /// First RomData list - /// Second RomData list - /// Any rom that's only in the first list - /// Adapted from http://stackoverflow.com/questions/5620266/the-opposite-of-intersect - public static List DiffOnlyInA(List A, List B) - { - List AString = Output.RomDataToString(A); - List BString = Output.RomDataToString(B); - List CString = AString.Except(BString).ToList(); - return Output.StringToRomData(CString); - } - - /// - /// Get all RomData objects that are in A and B - /// - /// First RomData list - /// Second RomData list - /// Any rom that's in both lists - /// Adapted from http://stackoverflow.com/questions/5620266/the-opposite-of-intersect - public static List DiffInAB(List A, List B) - { - List AString = Output.RomDataToString(A); - List BString = Output.RomDataToString(B); - List CString = AString.Union(BString).Except(AString.Except(BString).Union(BString.Except(AString))).ToList(); - return Output.StringToRomData(CString); - } } } diff --git a/SabreHelper/Structs.cs b/SabreHelper/Structs.cs index c5d78660..3b50bb94 100644 --- a/SabreHelper/Structs.cs +++ b/SabreHelper/Structs.cs @@ -28,6 +28,7 @@ namespace SabreTools.Helper /// public struct DatData { + // Data common to most DAT types public string Name; public string Description; public string Category; @@ -45,5 +46,15 @@ namespace SabreTools.Helper public OutputFormat OutputFormat; public bool MergeRoms; public Dictionary> Roms; + + // Data specific to the Miss DAT type + public bool UseGame; + public string Prefix; + public string Postfix; + public bool Quotes; + public string RepExt; + public string AddExt; + public bool GameName; + public bool Romba; } } diff --git a/UncompressedSize/UncompressedSize.cs b/UncompressedSize/UncompressedSize.cs index a988e908..48df0160 100644 --- a/UncompressedSize/UncompressedSize.cs +++ b/UncompressedSize/UncompressedSize.cs @@ -38,7 +38,7 @@ namespace SabreTools { Roms = new Dictionary>(), }; - datdata = RomManipulation.ParseDict(filename, 0, 0, datdata, logger); + datdata = RomManipulation.Parse(filename, 0, 0, datdata, logger); foreach (List romlist in datdata.Roms.Values) { foreach (RomData rom in romlist)