using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.IO; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using System.Web; namespace SabreTools { class DATFromDir { private static string _7zPath; private static string _basePath; private static string _tempDir; private static string _baseExtract; static void Main(string[] args) { // Set local paths _7zPath = Environment.CurrentDirectory.Replace('/', '\\') + "\\7z" + (Environment.Is64BitOperatingSystem ? "\\x64" : "") + "\\"; _tempDir = Environment.CurrentDirectory.Replace('/', '\\') + "\\temp" + DateTime.Now.ToString("yyyyMMddHHmmss") + "\\"; _basePath = (args.Length == 0 ? Environment.CurrentDirectory : args[0]).Replace('/', '\\') + "\\"; // Set base arguments to be used _baseExtract = "x -o\"" + _tempDir + "\""; // Set the basic Process information for 7za ProcessStartInfo psi = new ProcessStartInfo { FileName = _7zPath + "7za.exe", RedirectStandardError = true, RedirectStandardOutput = true, UseShellExecute = false, }; // Get an output array going that has the right mappings (parent, name, size, hash) List> roms = new List>(); // This is where the main loop would go foreach (string item in Directory.GetFiles(_basePath, "*", SearchOption.AllDirectories)) { // Create the temporary output directory Directory.CreateDirectory(_tempDir); psi.Arguments = _baseExtract + " " + item; Process zip = Process.Start(psi); zip.WaitForExit(); bool encounteredErrors = zip.StandardError.ReadToEnd().Contains("ERROR"); // Get a list of files including size and hash SHA1 sha1 = SHA1.Create(); // If the file was an archive and was extracted successfully, check it if (!encounteredErrors) { foreach (string entry in Directory.GetFiles(_tempDir, "*", SearchOption.AllDirectories)) { FileStream fs = File.OpenRead(entry); string tempHash = BitConverter.ToString(sha1.ComputeHash(fs)).Replace("-", ""); fs.Close(); roms.Add(new Tuple( Path.GetFileNameWithoutExtension(item), entry.Remove(0, _tempDir.Length), (new FileInfo(entry)).Length, tempHash)); Console.WriteLine("File parsed: " + entry.Remove(0, _tempDir.Length)); } } // Otherwise, just get the info on the file itself else if (!Directory.Exists(item)) { FileStream fs; try { fs = File.OpenRead(item); } catch (IOException) { continue; } string tempHash = BitConverter.ToString(sha1.ComputeHash(fs)).Replace("-", ""); fs.Close(); string actualpath = Path.GetDirectoryName(item.Remove(0, _basePath.Length)).Replace('/', '\\').Split('\\')[0]; roms.Add(new Tuple( (actualpath == "" ? "Default" : actualpath), item.Remove(0, _basePath.Length).Remove(0, actualpath.Length + (actualpath != "" ? 1 : 0)), (new FileInfo(item)).Length, tempHash)); Console.WriteLine("File parsed: " + item.Remove(0, _basePath.Length)); } // Delete the temp directory if (Directory.Exists(_tempDir)) { Directory.Delete(_tempDir, true); } } // Order the roms by name of parent, then name of rom roms.Sort(delegate (Tuple A, Tuple B) { if (A.Item1 == B.Item1) { if (A.Item2 == B.Item2) { if (A.Item3 == B.Item3) { return String.Compare(A.Item4, B.Item4); } return (int)(A.Item3 - B.Item3); } return String.Compare(A.Item2, B.Item2); } return String.Compare(A.Item1, B.Item1); }); //TODO: So, this below section is a pretty much one for one copy of code that is written in generate // this means that in the future, "writing to DAT" will be abstracted out to the DLL so that any // properly formatted data can be passed in and it will get written as necessary. That would open // the possibiliites for different ways to generate a DAT from multiple things // Now write it all out as a DAT try { FileStream fs = File.Create("dirdat.xml"); StreamWriter sw = new StreamWriter(fs, Encoding.UTF8); string header = "\n" + "\n\n" + "\t\n" + "\t\t
\n" + "\t\t\tdirdat\n" + "\t\t\tdirdat\n" + "\t\t\tDATFromDir\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\tDATFromDir\n" + "\t\t\t\n" + "\t\t
\n"; // Write the header out sw.Write(header); // Write out each of the machines and roms string lastgame = ""; foreach (Tuple rom in roms) { string state = ""; if (lastgame != "" && lastgame != rom.Item1) { state += "\t\n"; } if (lastgame != rom.Item1) { state += "\t\n" + "\t\t" + HttpUtility.HtmlEncode(rom.Item1) + "\n"; } state += "\t\t\n"; lastgame = rom.Item1; sw.Write(state); } sw.Write("\t\n
"); Console.Write("File written!"); sw.Close(); fs.Close(); } catch (Exception ex) { Console.Write(ex.ToString()); } } } }