using System; using System.Collections.Generic; using Mono.Data.Sqlite; using System.IO; using System.Linq; using System.Text; using System.Web; 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.Log("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 = ""; foreach (RomData rom in roms) { string state = ""; if (lastgame != "" && 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 ? " 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 ? " 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.Log("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 /// /// 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 /// Enable output in merged mode (one game per hash) /// Set the output directory /// Dictionary containing all the roms to be written /// Logger object for console and/or file output /// True if the DAT was written correctly, false otherwise public static bool WriteToDatFromDict(string name, string description, string version, string date, string category, string author, bool forceunpack, bool old, bool merge, string outDir, Dictionary> dict, Logger logger) { // Get all values in the dictionary and write out SortedDictionary> sortable = new SortedDictionary>(); long count = 0; foreach (List roms in dict.Values) { List newroms = roms; if (merge) { newroms = RomManipulation.Merge(newroms); } foreach (RomData rom in newroms) { count++; string key = rom.SystemID + "-" + rom.SourceID + "-" + rom.Game + "-" + rom.Name; if (sortable.ContainsKey(key)) { sortable[key].Add(rom); } else { List temp = new List(); temp.Add(rom); sortable.Add(key, temp); } } } logger.Log("A total of " + count + " file hashes will be written out to file"); // Now write out to file // 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.Log("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 = ""; foreach (List roms in sortable.Values) { foreach (RomData rom in roms) { string state = ""; if (lastgame != "" && 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 != 0 ? " 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 ? " 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.Log("File written!" + Environment.NewLine); sw.Close(); fs.Close(); } catch (Exception ex) { logger.Error(ex.ToString()); return false; } 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 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.Log("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.Log("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; } } }