using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Xml.Linq; using System.Security.Cryptography; namespace AutomatedROMTools { /// /// The AutomatedROMTools Class which interacts with the Main Program Class. /// class AutomatedROMTools { #region Private Members // Private members. private string _strAppName = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).ProductName; // Product Name private string _strAppVersion = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).ProductVersion; // Product Version private string _strAppCopyright = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).LegalCopyright; // Product Copyright private string _strCommandSwitch = "-help"; // Command switch (-version/-help/-license) private string _strPathPatchesDir = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Patches"); // Path to the patches directory private string _strPathROMsDir = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "ROMs"); // Path to the ROMs directory private string _strPathROMsDeheadedDir = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "ROMsDeheaded"); // Path to the deheadered ROMs directory private string _strPathROMsTrimmedDir = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "ROMsTrimmed"); // Path to the trimmed ROMs directory private string _strPathDatsDir = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Dats"); // Path to the Dats directory private string _strPathDatsSortedDir = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DatsSorted"); // Path to the sorted Dats directory private string _strPathDatsSplitDir = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DatsSplit"); // Path to the split Dats directory private string _strFilterText = ""; // Text to filter private string _strComment = ""; // Comment to use in ROMs datafiles private string _strPathLogFile = ""; // Path to the log file private List _arrLog = new List(); // The log string list array private int _intBufferSize = 1024 * 1024; // Buffer size private int _intTrimmedROMSize = 0; // Trimmed ROM size private int _intSizeToTrim = 0; // Size to trim from the ROM #endregion #region Getters/Setters Public Accessors // Public member accessors. public string AppName { get { return _strAppName; } set { } } public string AppVersion { get { return _strAppVersion; } set { } } public string AppCopyright { get { return _strAppCopyright; } set { } } public string CommandSwitch { get { return _strCommandSwitch; } set { _strCommandSwitch = value; } } public string PathPatchesDir { get { return _strPathPatchesDir; } set { _strPathPatchesDir = value; } } public string PathROMsDir { get { return _strPathROMsDir; } set { _strPathROMsDir = value; } } public string PathROMsDeheadedDir { get { return _strPathROMsDeheadedDir; } set { _strPathROMsDeheadedDir = value; } } public string PathROMsTrimmedDir { get { return _strPathROMsTrimmedDir; } set { _strPathROMsTrimmedDir = value; } } public string PathDatsDir { get { return _strPathDatsDir; } set { _strPathDatsDir = value; } } public string PathDatsSortedDir { get { return _strPathDatsSortedDir; } set { _strPathDatsSortedDir = value; } } public string PathDatsSplitDir { get { return _strPathDatsSplitDir; } set { _strPathDatsSplitDir = value; } } public string FilterText { get { return _strFilterText; } set { _strFilterText = value; } } public string Comment { get { return _strComment; } set { _strComment = value; } } public string PathLogFile { get { return _strPathLogFile; } set { _strPathLogFile = value; } } public List Log { get { return _arrLog; } set { _arrLog = value; } } public int BufferSize { get { return _intBufferSize; } set { _intBufferSize = value; } } public int TrimmedROMSize { get { return _intTrimmedROMSize; } set { _intTrimmedROMSize = value; } } public int SizeToTrim { get { return _intSizeToTrim; } set { _intSizeToTrim = value; } } #endregion #region CLI /// /// Sets the variables passed from the CLI. /// /// public void SetVariablesFromCLI(string[] strArgs) { try { foreach (string strArg in strArgs) { if (Regex.IsMatch(strArg, "^-", RegexOptions.IgnoreCase) == true) { // Set the command switch. CommandSwitch = strArg; } if (Regex.IsMatch(strArg, "^DD:", RegexOptions.IgnoreCase) == true) { // Set the path to the Dats directory. PathDatsDir = strArg.Substring(3); } if (Regex.IsMatch(strArg, "^DO:", RegexOptions.IgnoreCase) == true) { // Set the path to the sorted Dats directory. PathDatsSortedDir = strArg.Substring(3); } if (Regex.IsMatch(strArg, "^DP:", RegexOptions.IgnoreCase) == true) { // Set the path to the split Dats directory. PathDatsSplitDir = strArg.Substring(3); } if (Regex.IsMatch(strArg, "^FT:", RegexOptions.IgnoreCase) == true) { // Set the filter text. FilterText = strArg.Substring(3); } if (Regex.IsMatch(strArg, "^RD:", RegexOptions.IgnoreCase) == true) { // Set the path to the ROMs directory. PathROMsDir = strArg.Substring(3); } if (Regex.IsMatch(strArg, "^RE:", RegexOptions.IgnoreCase) == true) { // Set the path to the deheadered ROMs directory. PathROMsDeheadedDir = strArg.Substring(3); } if (Regex.IsMatch(strArg, "^RT:", RegexOptions.IgnoreCase) == true) { // Set the path to the trimmed ROMs directory. PathROMsTrimmedDir = strArg.Substring(3); } if (Regex.IsMatch(strArg, "^CO:", RegexOptions.IgnoreCase) == true) { // Set the comment to use in datafiles. Comment = strArg.Substring(3); } if (Regex.IsMatch(strArg, "^LF:", RegexOptions.IgnoreCase) == true) { // Set the path to the log file. PathLogFile = strArg.Substring(3); } if (Regex.IsMatch(strArg, "^BS:", RegexOptions.IgnoreCase) == true) { // Set the buffer size. BufferSize = Convert.ToInt32(strArg.Substring(3)); } if (Regex.IsMatch(strArg, "^RS:", RegexOptions.IgnoreCase) == true) { // Set the trimmed ROM size. TrimmedROMSize = Convert.ToInt32(strArg.Substring(3)); } if (Regex.IsMatch(strArg, "^TS:", RegexOptions.IgnoreCase) == true) { // Set the size to trim from the ROM. SizeToTrim = Convert.ToInt32(strArg.Substring(3)); } } } catch (Exception ex) { // Print to screen OutputLine("Error: Setting options from CLI failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } /// /// Processes the command switch. /// public void ProcessCommandSwitch() { switch (CommandSwitch) { case "-buildpatchesdat": BuildPatchesDatafile(); // Build a datafile from the Patches directory. break; case "-buildromsdat": BuildROMsDatafile(); // Build a datafile from the ROMs directory. break; case "-deheadall": DeheadAllROMs(); // Deheader all FDS/NES/7800/Lynx ROMs. break; case "-deheadfds": DeheadFDSROMs(); // Deheader all FDS ROMs. break; case "-deheadnes": DeheadNESROMs(); // Deheader all NES ROMs. break; case "-deheada78": DeheadA78ROMs(); // Deheader all 7800 ROMs. break; case "-deheadlnx": DeheadLnxROMs(); // Deheader all Lynx ROMs. break; case "-sorta2z": SortA2Z(); // Sort all game names from A-Z in all datafiles. break; case "-sortz2a": SortZ2A(); // Sort all game names from Z-A in all datafiles. break; case "-split": SplitDats(); // Split all datafiles using a text filter. break; case "-trimzerosfrombegin": LTrimROMs(); // Trim all zeros from the beginning of all possible ROMs. break; case "-trimzerosfromend": RTrimROMs(); // Trim all zeros from the end of all possible ROMs. break; case "-trimtosizefromend": STrimROMs(); // Trim all possible ROMs to a specific size. break; case "-trimsizefrombegin": SFLTrimROMs(); // Trim a specific size from the beginning of all possible ROMs. break; case "-trimsizefromend": SFRTrimROMs(); // Trim a specific size from the end of all possible ROMs. break; case "-license": PrintLicense(); // Print the license text. break; case "-version": // Do nothing. // Do nothing. break; default: PrintHelp(); // Print the help text. break; } } #endregion #region Save Log /// /// Saves the log to a text file. /// public void SaveLog() { try { // Determine if the user selected a log filename. if (PathLogFile.Length > 0) { // Get the log file directory name. FileInfo fi = new FileInfo(PathLogFile); // Create log file directory if it doesn't exist. if (Directory.Exists(fi.DirectoryName) == false) Directory.CreateDirectory(fi.DirectoryName); // Save the contents of the log to a text file. File.WriteAllLines(PathLogFile, Log); // Print to screen OutputLine("Info: Log file saved (" + PathLogFile + ")"); OutputLine(""); } } catch (Exception ex) { // Print to screen OutputLine("Error: Saving log file failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } #endregion #region Printers /// /// Prints the help text. /// public void PrintHelp() { // Print to screen OutputLine("Usage:"); OutputLine("\tAutomatedROMTools-CLI.exe [-command] [option:]"); OutputLine("\tOptions that contain spaces must be enclosed in quotations"); OutputLine("\tOptions may be specified in any order"); OutputLine("\tOnly one command may be be used"); OutputLine(""); OutputLine("-------------------------------------------------------------------------------"); OutputLine(""); OutputLine("Build Patches Datafile Example:"); OutputLine("\tAutomatedROMTools-CLI.exe -buildpatchesdat"); OutputLine(""); OutputLine("Build ROMs Datafile Example:"); OutputLine("\tAutomatedROMTools-CLI.exe -buildromsdat"); OutputLine(""); OutputLine("Dehead ROMs Example:"); OutputLine("\tAutomatedROMTools-CLI.exe -deheadall"); OutputLine(""); OutputLine("Split All Datafiles Example:"); OutputLine("\tAutomatedROMTools-CLI.exe -split \"(USA)\""); OutputLine(""); OutputLine("Sort Game Names In All Datafiles Example:"); OutputLine("\tAutomatedROMTools-CLI.exe -sorta2z"); OutputLine(""); OutputLine("Trim ROMs Example:"); OutputLine("\tAutomatedROMTools-CLI.exe -trimzerosfromend"); OutputLine(""); OutputLine("-------------------------------------------------------------------------------"); OutputLine(""); OutputLine("Standard Commands:"); OutputLine("\t-buildpatchesdat\tBuild a datafile from the Patches directory"); OutputLine("\t-buildromsdat\t\tBuild a datafile from the ROMs directory"); OutputLine("\t-deheadall\t\tDeheader all FDS/NES/7800/Lynx ROMs"); OutputLine("\t-deheadfds\t\tDeheader all FDS ROMs"); OutputLine("\t-deheadnes\t\tDeheader all NES ROMs"); OutputLine("\t-deheada78\t\tDeheader all 7800 ROMs"); OutputLine("\t-deheadlnx\t\tDeheader all Lynx ROMs"); OutputLine("\t-sorta2z\t\tSort all game names from A-Z in all datafiles"); OutputLine("\t-sortz2a\t\tSort all game names from Z-A in all datafiles"); OutputLine("\t-splitall\t\tSplit all datafiles using a text filter"); // OutputLine("\t-trimzerosfrombegin\tTrim all zeros from the beginning of all ROMs"); OutputLine("\t-trimzerosfromend\tTrim all zeros from the end of all ROMs"); // OutputLine("\t-trimtosizefromend\tTrim all possible ROMs to a specific size"); // OutputLine("\t-trimsizefrombegin\tTrim a specific size from the beginning of ROMs"); // OutputLine("\t-trimsizefromend\tTrim a specific size from the end of ROMs"); OutputLine("\t-help\t\t\tPrint the help"); OutputLine("\t-license\t\tPrint the license"); OutputLine("\t-version\t\tPrint the version"); OutputLine(""); OutputLine("-------------------------------------------------------------------------------"); OutputLine(""); OutputLine("Standard Options:"); OutputLine("\tDD:\t\tPath to the Dats directory"); OutputLine("\tDO:\t\tPath to the sorted Dats directory"); OutputLine("\tDP:\t\tPath to the split Dats directory"); OutputLine("\tRD:\t\tPath to the ROMs directory"); OutputLine("\tRE:\t\tPath to the deheadered ROMs directory"); OutputLine("\tRT:\t\tPath to the trimmed ROMs directory"); OutputLine("\tCO:\t\tComment to use for building a datafile"); OutputLine("\tFT:\t\tText to filter"); OutputLine("\tLF:\t\tPath to the log file"); OutputLine("\tBS:\t\tBuffer size (Default: 1048576)"); OutputLine("\tRS:\t\tTrimmed ROM size"); OutputLine("\tTS:\t\tSize to trim from ROMs"); OutputLine(""); } /// /// Prints the license text. /// public void PrintLicense() { // Print to screen OutputLine("-------------------------------------------------------------------------------"); OutputLine("AutomatedROMTools - License version 20250729"); OutputLine("Copyright (c) 2016-2025 AutomatedROMTools - All Rights Reserved"); OutputLine("-------------------------------------------------------------------------------"); OutputLine(""); OutputLine("Redistribution and use in binary forms, without modification,"); OutputLine("is permitted provided that the following conditions are met:"); OutputLine(""); OutputLine("1.This software may not be reverse engineered, decompiled,"); OutputLine(" or disassembled."); OutputLine(""); OutputLine("2.Redistributions of source code are not permitted whatsoever,"); OutputLine(" under any conditions."); OutputLine(""); OutputLine("3.Redistributions in binary form must reproduce the above copyright"); OutputLine(" notice, this list of conditions and the following disclaimer in"); OutputLine(" the documentation and/or other materials provided with the"); OutputLine(" distribution."); OutputLine(""); OutputLine("4.Redistributions in binary form must retain the following acknowledgment:"); OutputLine(" \"This product includes AutomatedROMTools software, which is freely available.\""); OutputLine(""); OutputLine("5.AutomatedROMTools may publish revised and/or new versions of the"); OutputLine(" license from time to time. Each version will be given a"); OutputLine(" distinguishing version number. No one other than AutomatedROMTools has"); OutputLine(" the right to modify the terms applicable to covered code created"); OutputLine(" under this License."); OutputLine(""); OutputLine("6.This software may not be used for any illegal purposes or activities."); OutputLine(" It is your responsibility to use this software in accordance with all"); OutputLine(" applicable laws."); OutputLine(""); OutputLine("7.This software is for use only on files that you own"); OutputLine(" or have the right to use it on."); OutputLine(""); OutputLine("-------------------------------------------------------------------------------"); OutputLine(""); OutputLine("THIS SOFTWARE IS PROVIDED BY THE BUILDEMALL DEVELOPMENT TEAM 'AS IS'"); OutputLine("AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,"); OutputLine("THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A"); OutputLine("PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE BUILDEMALL"); OutputLine("DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,"); OutputLine("INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES"); OutputLine("(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR"); OutputLine("SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)"); OutputLine("HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,"); OutputLine("STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)"); OutputLine("ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED"); OutputLine("OF THE POSSIBILITY OF SUCH DAMAGE."); OutputLine(""); } /// /// Prints the version and copyright notice texts. /// public void PrintVersion() { // Print to screen OutputLine("------------------------------------------------------------------------------"); OutputLine(AppName + " v" + AppVersion); OutputLine(AppCopyright); OutputLine("------------------------------------------------------------------------------"); OutputLine(""); } /// /// Outputs a line of text. /// /// private void OutputLine(string strMsg) { // Print the line of text to the console window. Console.WriteLine(strMsg); // Print the line of text to the log. if (PathLogFile.Length > 0) { // Add the line of text to the log. Log.Add(strMsg); } } #endregion #region Checkers /// /// Checks the Patches directory path. /// /// private bool PathPatchesDirCheck() { // Set the exit flag value. bool boolReturnValue = false; // Check if the directory exists. if (Directory.Exists(PathPatchesDir) == true) { // Set the exit flag value. boolReturnValue = false; } else { // Print to screen and set the exit flag value. OutputLine("Error: The Patches directory path does not exist (" + PathPatchesDir + ")"); boolReturnValue = true; } // Return the exit flag value. return boolReturnValue; } /// /// Checks the Dats directory path. /// /// private bool PathDatsDirCheck() { // Set the exit flag value. bool boolReturnValue = false; // Check if the directory exists. if (Directory.Exists(PathDatsDir) == true) { // Set the exit flag value. boolReturnValue = false; } else { // Print to screen and set the exit flag value. OutputLine("Error: The Dats directory path does not exist (" + PathDatsDir + ")"); boolReturnValue = true; } // Return the exit flag value. return boolReturnValue; } /// /// Checks the sorted Dats directory path. /// /// private bool PathDatsSortedDirCheck() { // Set the exit flag value. bool boolReturnValue = false; // Check if the directory exists. if (Directory.Exists(PathDatsSortedDir) == true) { // Set the exit flag value. boolReturnValue = false; } else { // Print to screen and set the exit flag value. OutputLine("Error: The sorted Dats directory path does not exist (" + PathDatsSortedDir + ")"); boolReturnValue = true; } // Return the exit flag value. return boolReturnValue; } /// /// Checks the split Dats directory path. /// /// private bool PathDatsSplitDirCheck() { // Set the exit flag value. bool boolReturnValue = false; // Check if the directory exists. if (Directory.Exists(PathDatsSplitDir) == true) { // Set the exit flag value. boolReturnValue = false; } else { // Print to screen and set the exit flag value. OutputLine("Error: The split Dats directory path does not exist (" + PathDatsSplitDir + ")"); boolReturnValue = true; } // Return the exit flag value. return boolReturnValue; } /// /// Checks the ROMs directory path. /// /// private bool PathROMsDirCheck() { // Set the exit flag value. bool boolReturnValue = false; // Check if the directory exists. if (Directory.Exists(PathROMsDir) == true) { // Set the exit flag value. boolReturnValue = false; } else { // Print to screen and set the exit flag value. OutputLine("Error: The ROMs directory path does not exist (" + PathROMsDir + ")"); boolReturnValue = true; } // Return the exit flag value. return boolReturnValue; } /// /// Checks the deheadered ROMs directory path. /// /// private bool PathROMsDeheadedDirCheck() { // Set the exit flag value. bool boolReturnValue = false; // Check if the directory exists. if (Directory.Exists(PathROMsDeheadedDir) == true) { // Set the exit flag value. boolReturnValue = false; } else { // Print to screen and set the exit flag value. OutputLine("Error: The deheadered ROMs directory path does not exist (" + PathROMsDeheadedDir + ")"); boolReturnValue = true; } // Return the exit flag value. return boolReturnValue; } /// /// Checks the trimmed ROMs directory path. /// /// private bool PathROMsTrimmedDirCheck() { // Set the exit flag value. bool boolReturnValue = false; // Check if the directory exists. if (Directory.Exists(PathROMsTrimmedDir) == true) { // Set the exit flag value. boolReturnValue = false; } else { // Print to screen and set the exit flag value. OutputLine("Error: The trimmed ROMs directory path does not exist (" + PathROMsTrimmedDir + ")"); boolReturnValue = true; } // Return the exit flag value. return boolReturnValue; } #endregion #region Dehead ROMs /// /// Deheaders all possible FDS ROMs. /// private void DeheadFDSROMs() { try { // Print to screen OutputLine("Info: Deheadering all possible FDS ROMs ..."); // Declarations int intCounterTotalDeheaded = 0; // Total deheadered counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathROMsDeheadedDir = PathROMsDeheadedDir; // Path to the deheadered ROMs directory // Checkers bool boolPathROMsDirCheck = PathROMsDirCheck(); bool boolPathROMsDeheadedDirCheck = PathROMsDeheadedDirCheck(); // Check the paths and directories. if (boolPathROMsDirCheck == false && boolPathROMsDeheadedDirCheck == false) { // Print to screen OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); OutputLine("Options: ROMsDeheaded Directory (" + strPathROMsDeheadedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.fds", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Deheader all of the ROMs. foreach (string strPathFile in arrDirFiles) { FileInfo fiInputFile = new FileInfo(strPathFile); if (fiInputFile.Length > 16) { OutputLine("Deheading: " + fiInputFile.FullName); int intOutputFileLength = (int)(fiInputFile.Length - 16); byte[] arrOutputFileBytes = new byte[intOutputFileLength]; using (BinaryReader reader = new BinaryReader(new FileStream(fiInputFile.FullName, FileMode.Open))) { reader.BaseStream.Seek(16, SeekOrigin.Begin); reader.Read(arrOutputFileBytes, 0, intOutputFileLength); } File.WriteAllBytes(Path.Combine(strPathROMsDeheadedDir, fiInputFile.Name), arrOutputFileBytes); intCounterTotalDeheaded = intCounterTotalDeheaded + 1; } } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Deheadered " + intCounterTotalDeheaded + " ROMs in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Deheadering all possible FDS ROMs completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Deheadering all possible FDS ROMs failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } /// /// Deheaders all possible NES ROMs. /// private void DeheadNESROMs() { try { // Print to screen OutputLine("Info: Deheadering all possible NES ROMs ..."); // Declarations int intCounterTotalDeheaded = 0; // Total deheadered counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathROMsDeheadedDir = PathROMsDeheadedDir; // Path to the deheadered ROMs directory // Checkers bool boolPathROMsDirCheck = PathROMsDirCheck(); bool boolPathROMsDeheadedDirCheck = PathROMsDeheadedDirCheck(); // Check the paths and directories. if (boolPathROMsDirCheck == false && boolPathROMsDeheadedDirCheck == false) { // Print to screen OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); OutputLine("Options: ROMsDeheaded Directory (" + strPathROMsDeheadedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.nes", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Deheader all of the ROMs. foreach (string strPathFile in arrDirFiles) { FileInfo fiInputFile = new FileInfo(strPathFile); if (fiInputFile.Length > 16) { OutputLine("Deheading: " + fiInputFile.FullName); int intOutputFileLength = (int)(fiInputFile.Length - 16); byte[] arrOutputFileBytes = new byte[intOutputFileLength]; using (BinaryReader reader = new BinaryReader(new FileStream(fiInputFile.FullName, FileMode.Open))) { reader.BaseStream.Seek(16, SeekOrigin.Begin); reader.Read(arrOutputFileBytes, 0, intOutputFileLength); } File.WriteAllBytes(Path.Combine(strPathROMsDeheadedDir, fiInputFile.Name), arrOutputFileBytes); intCounterTotalDeheaded = intCounterTotalDeheaded + 1; } } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Deheadered " + intCounterTotalDeheaded + " ROMs in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Deheadering all possible NES ROMs completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Deheadering all possible NES ROMs failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } /// /// Deheaders all possible 7800 ROMs. /// private void DeheadA78ROMs() { try { // Print to screen OutputLine("Info: Deheadering all possible 7800 ROMs ..."); // Declarations int intCounterTotalDeheaded = 0; // Total deheadered counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathROMsDeheadedDir = PathROMsDeheadedDir; // Path to the deheadered ROMs directory // Checkers bool boolPathROMsDirCheck = PathROMsDirCheck(); bool boolPathROMsDeheadedDirCheck = PathROMsDeheadedDirCheck(); // Check the paths and directories. if (boolPathROMsDirCheck == false && boolPathROMsDeheadedDirCheck == false) { // Print to screen OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); OutputLine("Options: ROMsDeheaded Directory (" + strPathROMsDeheadedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.a78", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Deheader all of the ROMs. foreach (string strPathFile in arrDirFiles) { FileInfo fiInputFile = new FileInfo(strPathFile); if (fiInputFile.Length > 128) { OutputLine("Deheading: " + fiInputFile.FullName); int intOutputFileLength = (int)(fiInputFile.Length - 128); byte[] arrOutputFileBytes = new byte[intOutputFileLength]; using (BinaryReader reader = new BinaryReader(new FileStream(fiInputFile.FullName, FileMode.Open))) { reader.BaseStream.Seek(128, SeekOrigin.Begin); reader.Read(arrOutputFileBytes, 0, intOutputFileLength); } File.WriteAllBytes(Path.Combine(strPathROMsDeheadedDir, fiInputFile.Name), arrOutputFileBytes); intCounterTotalDeheaded = intCounterTotalDeheaded + 1; } } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Deheadered " + intCounterTotalDeheaded + " ROMs in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Deheadering all possible 7800 ROMs completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Deheadering all possible 7800 ROMs failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } /// /// Deheaders all possible Lynx ROMs. /// private void DeheadLnxROMs() { try { // Print to screen OutputLine("Info: Deheadering all possible Lynx ROMs ..."); // Declarations int intCounterTotalDeheaded = 0; // Total deheadered counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathROMsDeheadedDir = PathROMsDeheadedDir; // Path to the deheadered ROMs directory // Checkers bool boolPathROMsDirCheck = PathROMsDirCheck(); bool boolPathROMsDeheadedDirCheck = PathROMsDeheadedDirCheck(); // Check the paths and directories. if (boolPathROMsDirCheck == false && boolPathROMsDeheadedDirCheck == false) { // Print to screen OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); OutputLine("Options: ROMsDeheaded Directory (" + strPathROMsDeheadedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.lnx", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Deheader all of the ROMs. foreach (string strPathFile in arrDirFiles) { FileInfo fiInputFile = new FileInfo(strPathFile); if (fiInputFile.Length > 64) { OutputLine("Deheading: " + fiInputFile.FullName); int intOutputFileLength = (int)(fiInputFile.Length - 64); byte[] arrOutputFileBytes = new byte[intOutputFileLength]; using (BinaryReader reader = new BinaryReader(new FileStream(fiInputFile.FullName, FileMode.Open))) { reader.BaseStream.Seek(64, SeekOrigin.Begin); reader.Read(arrOutputFileBytes, 0, intOutputFileLength); } File.WriteAllBytes(Path.Combine(strPathROMsDeheadedDir, fiInputFile.Name), arrOutputFileBytes); intCounterTotalDeheaded = intCounterTotalDeheaded + 1; } } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Deheadered " + intCounterTotalDeheaded + " ROMs in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Deheadering all possible Lynx ROMs completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Deheadering all possible Lynx ROMs failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } /// /// Deheaders all possible ROMs. /// private void DeheadAllROMs() { try { // Print to screen OutputLine("Info: Deheadering all possible ROMs ..."); // Declarations int intCounterTotalDeheaded = 0; // Total deheadered counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathROMsDeheadedDir = PathROMsDeheadedDir; // Path to the deheadered ROMs directory // Checkers bool boolPathROMsDirCheck = PathROMsDirCheck(); bool boolPathROMsDeheadedDirCheck = PathROMsDeheadedDirCheck(); // Check the paths and directories. if (boolPathROMsDirCheck == false && boolPathROMsDeheadedDirCheck == false) { // Print to screen OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); OutputLine("Options: ROMsDeheaded Directory (" + strPathROMsDeheadedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.*", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Deheader all of the ROMs. foreach (string strPathFile in arrDirFiles) { FileInfo fiInputFile = new FileInfo(strPathFile); if ((fiInputFile.Extension == ".fds" || fiInputFile.Extension == ".nes") && fiInputFile.Length > 16) { OutputLine("Deheading: " + fiInputFile.FullName); int intOutputFileLength = (int)(fiInputFile.Length - 16); byte[] arrOutputFileBytes = new byte[intOutputFileLength]; using (BinaryReader reader = new BinaryReader(new FileStream(fiInputFile.FullName, FileMode.Open))) { reader.BaseStream.Seek(16, SeekOrigin.Begin); reader.Read(arrOutputFileBytes, 0, intOutputFileLength); } File.WriteAllBytes(Path.Combine(strPathROMsDeheadedDir, fiInputFile.Name), arrOutputFileBytes); intCounterTotalDeheaded = intCounterTotalDeheaded + 1; } else if (fiInputFile.Extension == ".lnx" && fiInputFile.Length > 64) { OutputLine("Deheading: " + fiInputFile.FullName); int intOutputFileLength = (int)(fiInputFile.Length - 64); byte[] arrOutputFileBytes = new byte[intOutputFileLength]; using (BinaryReader reader = new BinaryReader(new FileStream(fiInputFile.FullName, FileMode.Open))) { reader.BaseStream.Seek(64, SeekOrigin.Begin); reader.Read(arrOutputFileBytes, 0, intOutputFileLength); } File.WriteAllBytes(Path.Combine(strPathROMsDeheadedDir, fiInputFile.Name), arrOutputFileBytes); intCounterTotalDeheaded = intCounterTotalDeheaded + 1; } else if (fiInputFile.Extension == ".a78" && fiInputFile.Length > 128) { OutputLine("Deheading: " + fiInputFile.FullName); int intOutputFileLength = (int)(fiInputFile.Length - 128); byte[] arrOutputFileBytes = new byte[intOutputFileLength]; using (BinaryReader reader = new BinaryReader(new FileStream(fiInputFile.FullName, FileMode.Open))) { reader.BaseStream.Seek(128, SeekOrigin.Begin); reader.Read(arrOutputFileBytes, 0, intOutputFileLength); } File.WriteAllBytes(Path.Combine(strPathROMsDeheadedDir, fiInputFile.Name), arrOutputFileBytes); intCounterTotalDeheaded = intCounterTotalDeheaded + 1; } } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Deheadered " + intCounterTotalDeheaded + " ROMs in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Deheadering all possible ROMs completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Deheadering all possible ROMs failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } #endregion #region Sort Game Names /// /// Sorts all game names in all datafiles from A-Z. /// private void SortA2Z() { try { // Print to screen OutputLine("Info: Sorting all game names in all datafiles ..."); // Declarations int intCounterTotalSorted = 0; // Total sorted counter int intCountArrDirFiles = 0; // Total loop count string strPathDatsDir = PathDatsDir; // Path to the Dats directory string strPathDatsSortedDir = PathDatsSortedDir; // Path to the sorted Dats directory // Checkers bool boolPathDatsDirCheck = PathDatsDirCheck(); bool boolPathDatsSortedDirCheck = PathDatsSortedDirCheck(); // Check the paths and directories. if (boolPathDatsDirCheck == false && boolPathDatsSortedDirCheck == false) { // Print to screen OutputLine("Options: Dats Directory (" + strPathDatsDir + ")"); OutputLine("Options: DatsSorted Directory (" + strPathDatsSortedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathDatsDir, "*.*", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Sort all of the game names in all datafiles. foreach (string strPathFile in arrDirFiles) { FileInfo fiInputFile = new FileInfo(strPathFile); if (fiInputFile.Extension == ".dat" || fiInputFile.Extension == ".ppd" || fiInputFile.Extension == ".xml") { try { XDocument xdocDatafile = XDocument.Load(strPathFile); XDocument xdocDatafileNew = new XDocument(); OutputLine("Sorting: " + fiInputFile.Name); xdocDatafileNew.Declaration = xdocDatafile.Declaration; xdocDatafileNew.Add(xdocDatafile.Root); xdocDatafileNew.Root.RemoveNodes(); xdocDatafileNew.Root.Add(xdocDatafile.Root.Elements("header")); xdocDatafileNew.Root.Add(xdocDatafile.Root.Elements("game").OrderBy(e => e.Attribute("name").Value)); xdocDatafileNew.Save(Path.Combine(strPathDatsSortedDir, fiInputFile.Name)); intCounterTotalSorted = intCounterTotalSorted + 1; } catch { // Print to screen OutputLine("Error: Incompatible datafile (" + fiInputFile.Name + ")"); } } } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Sorted " + intCounterTotalSorted + " Dats in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Sorting all game names in all datafiles completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Sorting all game names in all datafiles failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } /// /// Sorts all game names in all datafiles from Z-A. /// private void SortZ2A() { try { // Print to screen OutputLine("Info: Sorting all game names in all datafiles ..."); // Declarations int intCounterTotalSorted = 0; // Total sorted counter int intCountArrDirFiles = 0; // Total loop count string strPathDatsDir = PathDatsDir; // Path to the Dats directory string strPathDatsSortedDir = PathDatsSortedDir; // Path to the sorted Dats directory // Checkers bool boolPathDatsDirCheck = PathDatsDirCheck(); bool boolPathDatsSortedDirCheck = PathDatsSortedDirCheck(); // Check the paths and directories. if (boolPathDatsDirCheck == false && boolPathDatsSortedDirCheck == false) { // Print to screen OutputLine("Options: Dats Directory (" + strPathDatsDir + ")"); OutputLine("Options: DatsSorted Directory (" + strPathDatsSortedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathDatsDir, "*.*", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Sort all of the game names in all datafiles. foreach (string strPathFile in arrDirFiles) { FileInfo fiInputFile = new FileInfo(strPathFile); if (fiInputFile.Extension == ".dat" || fiInputFile.Extension == ".ppd" || fiInputFile.Extension == ".xml") { try { XDocument xdocDatafile = XDocument.Load(strPathFile); XDocument xdocDatafileNew = new XDocument(); OutputLine("Sorting: " + fiInputFile.Name); xdocDatafileNew.Declaration = xdocDatafile.Declaration; xdocDatafileNew.Add(xdocDatafile.Root); xdocDatafileNew.Root.RemoveNodes(); xdocDatafileNew.Root.Add(xdocDatafile.Root.Elements("header")); xdocDatafileNew.Root.Add(xdocDatafile.Root.Elements("game").OrderByDescending(e => e.Attribute("name").Value)); xdocDatafileNew.Save(Path.Combine(strPathDatsSortedDir, fiInputFile.Name)); intCounterTotalSorted = intCounterTotalSorted + 1; } catch { // Print to screen OutputLine("Error: Incompatible datafile (" + fiInputFile.Name + ")"); } } } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Sorted " + intCounterTotalSorted + " Dats in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Sorting all game names in all datafiles completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Sorting all game names in all datafiles failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } #endregion #region Split Datafiles /// /// Splits all datafiles. /// private void SplitDats() { try { // Print to screen OutputLine("Info: Splitting all datafiles ..."); // Declarations int intCounterTotalSplit = 0; // Total split counter int intCountArrDirFiles = 0; // Total loop count string strPathDatsDir = PathDatsDir; // Path to the Dats directory string strPathDatsSplitDir = PathDatsSplitDir; // Path to the split Dats directory string strFilterText = FilterText; // Text to filter // Checkers bool boolPathDatsDirCheck = PathDatsDirCheck(); bool boolPathDatsSplitDirCheck = PathDatsSplitDirCheck(); // Check the paths and directories. if (boolPathDatsDirCheck == false && boolPathDatsSplitDirCheck == false) { // Print to screen OutputLine("Options: Dats Directory (" + strPathDatsDir + ")"); OutputLine("Options: DatsSplit Directory (" + strPathDatsSplitDir + ")"); OutputLine("Options: Filter Text (" + strFilterText + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathDatsDir, "*.*", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Split all datafiles. foreach (string strPathFile in arrDirFiles) { int intCounterTotalGames = 0; FileInfo fiInputFile = new FileInfo(strPathFile); if (fiInputFile.Extension == ".dat" || fiInputFile.Extension == ".ppd" || fiInputFile.Extension == ".xml") { try { XDocument xdocDatafile = XDocument.Load(strPathFile); XDocument xdocDatafileNew = new XDocument(); OutputLine("Splitting: " + fiInputFile.Name); xdocDatafileNew.Declaration = xdocDatafile.Declaration; xdocDatafileNew.Add(xdocDatafile.Root); xdocDatafileNew.Root.RemoveNodes(); xdocDatafileNew.Root.Add(xdocDatafile.Root.Elements("header")); foreach (XElement xelGame in xdocDatafile.Descendants("game")) { if (xelGame.Attribute("name").Value.Contains(strFilterText)) { xdocDatafileNew.Root.Add(xelGame); intCounterTotalGames = intCounterTotalGames + 1; } } string strName = xdocDatafile.Element("datafile").Element("header").Element("name").Value + " [" + strFilterText + "]"; string strVersion = DateTime.Now.ToString("yyyyMMdd HHmmss"); string strDate = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"); string strDescription = strName + " (" + intCounterTotalGames + ") (" + strVersion + ")"; string strAuthor = xdocDatafile.Element("datafile").Element("header").Element("author").Value + ", " + AppName + " v" + AppVersion; string strOutputFileName = Path.Combine(strPathDatsSplitDir, strDescription + fiInputFile.Extension); strOutputFileName = Regex.Replace(strOutputFileName, "\\/", "-"); xdocDatafileNew.Element("datafile").Element("header").Element("name").Value = strName; if (xdocDatafileNew.Element("datafile").Element("header").Descendants("description").Count() > 0) { xdocDatafileNew.Element("datafile").Element("header").Element("description").Value = strDescription; } if (xdocDatafileNew.Element("datafile").Element("header").Descendants("version").Count() > 0) { xdocDatafileNew.Element("datafile").Element("header").Element("version").Value = strVersion; } if (xdocDatafileNew.Element("datafile").Element("header").Descendants("date").Count() > 0) { xdocDatafileNew.Element("datafile").Element("header").Element("date").Value = strDate; } if (xdocDatafileNew.Element("datafile").Element("header").Descendants("author").Count() > 0) { xdocDatafileNew.Element("datafile").Element("header").Element("author").Value = strAuthor; } xdocDatafileNew.Save(strOutputFileName); intCounterTotalSplit = intCounterTotalSplit + 1; } catch { // Print to screen OutputLine("Error: Incompatible datafile (" + fiInputFile.Name + ")"); } } } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Split " + intCounterTotalSplit + " Dats in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Splitting all datafiles completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Splitting all datafiles failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } #endregion #region Build Patches Datafile /// /// Builds a datafile from the Patches directory. /// public void BuildPatchesDatafile() { try { // Print to screen OutputLine("Info: Building new patches datafile ..."); // Declarations int intCounterTotalBuilt = 0; // Total built counter int intCountArrDirFiles = 0; // Total loop count string strPathPatchesDir = PathPatchesDir; // Path to the Patches directory string strPathDatsDir = PathDatsDir; // Path to the Dats directory string strName = Path.GetFileName(PathPatchesDir); // Datafile name string strVersion = DateTime.Now.ToString("yyyyMMdd HHmmss"); // Datafile version string strDate = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"); // Datafile date string strDescription = strName + " (0) (" + strVersion + ")"; // Datafile description string strCategory = "Games"; // Datafile category string strAuthor = AppName + " v" + AppVersion; // Datafile author string strComment = Comment; // Datafile comment string strPathSaveFilename = ""; // Path to the new datafile // Checkers bool boolPathDatsDirCheck = PathDatsDirCheck(); bool boolPathPatchesDirCheck = PathPatchesDirCheck(); // Check the paths and directories. if (boolPathDatsDirCheck == false && boolPathPatchesDirCheck == false) { // Print to screen OutputLine("Options: Patches Directory (" + strPathPatchesDir + ")"); OutputLine("Options: Dats Directory (" + strPathDatsDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathPatchesDir, "*.xd3"); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Build a datafile from the patches directory files. if (intCountArrDirFiles > 0) { // Create a new datafile XDocument. XDocument xdocDatafile = new XDocument( new XDeclaration("1.0", "utf-8", "yes"), new XElement("datafile", new XElement("header", new XElement("name", strName), new XElement("description", strDescription), new XElement("category", strCategory), new XElement("version", strVersion), new XElement("date", strDate), new XElement("author", strAuthor), new XElement("comment", strComment) ) ) ); // Loop through the directory files array. foreach (string strPathFile in arrDirFiles) { // Get the patch filesize and filename. string strRomFilename = Path.GetFileName(strPathFile); string strRomFileSize = new FileInfo(strPathFile).Length.ToString(); // Print to screen OutputLine("Adding: " + strRomFilename); // Get the game name, category and description. string strGameName = Path.GetFileNameWithoutExtension(strPathFile); string strGameCategory = "Patches"; string strGameDescription = Path.GetFileNameWithoutExtension(strPathFile); // Get the patch hashes. byte[] arrRomFileHashSHA1 = new SHA1CryptoServiceProvider().ComputeHash(File.OpenRead(strPathFile)); byte[] arrRomFileHashMD5 = new MD5CryptoServiceProvider().ComputeHash(File.OpenRead(strPathFile)); byte[] arrRomFileHashCRC = new CRC32CryptoServiceProvider().ComputeHash(File.OpenRead(strPathFile)); string strRomFileHashSHA1 = BitConverter.ToString(arrRomFileHashSHA1).Replace("-", "").ToLower(); string strRomFileHashMD5 = BitConverter.ToString(arrRomFileHashMD5).Replace("-", "").ToLower(); string strRomFileHashCRC = BitConverter.ToString(arrRomFileHashCRC).Replace("-", "").ToLower(); // Add the patch file to the datafile XDocument. xdocDatafile.Element("datafile").Add( new XElement("game", new XAttribute("name", strGameName), new XElement("category", strGameCategory), new XElement("description", strGameDescription), new XElement("rom", new XAttribute("name", strRomFilename), new XAttribute("size", strRomFileSize), new XAttribute("crc", strRomFileHashCRC), new XAttribute("md5", strRomFileHashMD5), new XAttribute("sha1", strRomFileHashSHA1) ) ) ); // Increment the counter. intCounterTotalBuilt = intCounterTotalBuilt + 1; } // Modify the datafile header elements and filename. xdocDatafile.Element("datafile").Element("header").Element("description").Value = strName + " (" + intCounterTotalBuilt + ") (" + strVersion + ")"; strPathSaveFilename = Path.Combine(strPathDatsDir, strName + " (" + intCounterTotalBuilt + ") (" + strVersion + ").dat"); // Save the contents of the datafile XDocument to the file. xdocDatafile.Save(strPathSaveFilename); } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: " + intCounterTotalBuilt + " patches added to datafile successfully in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Building patches datafile completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Building patches datafile failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } #endregion #region Build ROMs Datafile /// /// Builds a datafile from the ROMs directory. /// public void BuildROMsDatafile() { try { // Print to screen OutputLine("Info: Building new ROMs datafile ..."); // Declarations int intCounterTotalBuilt = 0; // Total built counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathDatsDir = PathDatsDir; // Path to the Dats directory string strName = Path.GetFileName(PathROMsDir); // Datafile name string strVersion = DateTime.Now.ToString("yyyyMMdd HHmmss"); // Datafile version string strDate = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"); // Datafile date string strDescription = strName + " (0) (" + strVersion + ")"; // Datafile description string strCategory = "Games"; // Datafile category string strAuthor = AppName + " v" + AppVersion; // Datafile author string strComment = Comment; // Datafile comment string strPathSaveFilename = ""; // Path to the new datafile // Checkers bool boolPathDatsDirCheck = PathDatsDirCheck(); bool boolPathROMsDirCheck = PathROMsDirCheck(); // Check the paths and directories. if (boolPathDatsDirCheck == false && boolPathROMsDirCheck == false) { // Print to screen OutputLine("Options: Dats Directory (" + strPathDatsDir + ")"); OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.*"); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Build a datafile from the ROMs directory files. if (intCountArrDirFiles > 0) { // Create a new datafile XDocument. XDocument xdocDatafile = new XDocument( new XDeclaration("1.0", "utf-8", "yes"), new XElement("datafile", new XElement("header", new XElement("name", strName), new XElement("description", strDescription), new XElement("category", strCategory), new XElement("version", strVersion), new XElement("date", strDate), new XElement("author", strAuthor), new XElement("comment", strComment) ) ) ); // Loop through the directory files array. foreach (string strPathFile in arrDirFiles) { // Get the ROM filesize and filename. string strRomFilename = Path.GetFileName(strPathFile); string strRomFileSize = new FileInfo(strPathFile).Length.ToString(); // Print to screen OutputLine("Adding: " + strRomFilename); // Get the game name, category and description. string strGameName = Path.GetFileNameWithoutExtension(strPathFile); string strGameCategory = "Games"; string strGameDescription = Path.GetFileNameWithoutExtension(strPathFile); // Get the ROM hashes. byte[] arrRomFileHashSHA1 = new SHA1CryptoServiceProvider().ComputeHash(File.OpenRead(strPathFile)); byte[] arrRomFileHashMD5 = new MD5CryptoServiceProvider().ComputeHash(File.OpenRead(strPathFile)); byte[] arrRomFileHashCRC = new CRC32CryptoServiceProvider().ComputeHash(File.OpenRead(strPathFile)); string strRomFileHashSHA1 = BitConverter.ToString(arrRomFileHashSHA1).Replace("-", "").ToLower(); string strRomFileHashMD5 = BitConverter.ToString(arrRomFileHashMD5).Replace("-", "").ToLower(); string strRomFileHashCRC = BitConverter.ToString(arrRomFileHashCRC).Replace("-", "").ToLower(); // Add the patch file to the datafile XDocument. xdocDatafile.Element("datafile").Add( new XElement("game", new XAttribute("name", strGameName), new XElement("category", strGameCategory), new XElement("description", strGameDescription), new XElement("rom", new XAttribute("name", strRomFilename), new XAttribute("size", strRomFileSize), new XAttribute("crc", strRomFileHashCRC), new XAttribute("md5", strRomFileHashMD5), new XAttribute("sha1", strRomFileHashSHA1) ) ) ); // Increment the counter. intCounterTotalBuilt = intCounterTotalBuilt + 1; } // Modify the datafile header elements and filename. xdocDatafile.Element("datafile").Element("header").Element("description").Value = strName + " (" + intCounterTotalBuilt + ") (" + strVersion + ")"; strPathSaveFilename = Path.Combine(strPathDatsDir, strName + " (" + intCounterTotalBuilt + ") (" + strVersion + ").dat"); // Save the contents of the datafile XDocument to the file. xdocDatafile.Save(strPathSaveFilename); } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: " + intCounterTotalBuilt + " ROMs added to datafile successfully in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Building ROMs datafile completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Building ROMs datafile failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } #endregion #region Trim ROMs /// /// Trims the zeros from the beginning of all possible ROMs. /// public void LTrimROMs() { try { // Print to screen OutputLine("Info: Trimming the zeros from the beginning of all possible ROMs ..."); // Declarations int intCounterTotalTrimmed = 0; // Total trimmed counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathROMsTrimmedDir = PathROMsTrimmedDir; // Path to the trimmed ROMs directory int intBufferSize = BufferSize; // Buffer size // Checkers bool boolPathROMsDirCheck = PathROMsDirCheck(); bool boolPathROMsTrimmedDirCheck = PathROMsTrimmedDirCheck(); // Check the paths and directories. if (boolPathROMsDirCheck == false && boolPathROMsTrimmedDirCheck == false) { // Print to screen OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); OutputLine("Options: ROMsTrimmed Directory (" + strPathROMsTrimmedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.*", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Trim all of the ROMs. foreach (string strPathFile in arrDirFiles) { OutputLine("Info: Trimming the zeros from the beginning of all possible ROMs is not yet implemented"); } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Trimmed " + intCounterTotalTrimmed + " ROMs in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Trimming the zeros from the beginning of ROMs completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Trimming ROMs failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } /// /// Trims the zeros from the end of all possible ROMs. /// public void RTrimROMs() { try { // Print to screen OutputLine("Info: Trimming the zeros from the end of all possible ROMs ..."); // Declarations int intCounterTotalTrimmed = 0; // Total trimmed counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathROMsTrimmedDir = PathROMsTrimmedDir; // Path to the trimmed ROMs directory int intBufferSize = BufferSize; // Buffer size // Checkers bool boolPathROMsDirCheck = PathROMsDirCheck(); bool boolPathROMsTrimmedDirCheck = PathROMsTrimmedDirCheck(); // Check the paths and directories. if (boolPathROMsDirCheck == false && boolPathROMsTrimmedDirCheck == false) { // Print to screen OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); OutputLine("Options: ROMsTrimmed Directory (" + strPathROMsTrimmedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.*", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Trim all of the ROMs. foreach (string strPathFile in arrDirFiles) { int intNumBytes; using (FileStream fsInputFile = new FileStream(strPathFile, FileMode.Open)) { OutputLine("Info: Checking (" + strPathFile + ")"); bool boolExitFlag = false; fsInputFile.Seek(0, SeekOrigin.End); for (intNumBytes = -1; boolExitFlag == false; intNumBytes++) { fsInputFile.Seek(-1, SeekOrigin.Current); byte byteByte = (byte)fsInputFile.ReadByte(); if (byteByte == 0) { boolExitFlag = false; } else { boolExitFlag = true; } fsInputFile.Seek(-1, SeekOrigin.Current); } } if (intNumBytes > 0) { OutputLine("Info: Trimming " + intNumBytes + " bytes from the end of (" + strPathFile + ")"); using (FileStream fsInputFile = new FileStream(strPathFile, FileMode.Open)) { using (FileStream fsOutputFile = new FileStream(Path.Combine(strPathROMsTrimmedDir, Path.GetFileName(strPathFile)), FileMode.Create)) { long longOutputFileLength = fsInputFile.Length - intNumBytes; fsOutputFile.SetLength(longOutputFileLength); int bytesRead = -1; byte[] bytes = new byte[intBufferSize]; while ((bytesRead = fsInputFile.Read(bytes, 0, intBufferSize)) > 0) { if (fsInputFile.Position < longOutputFileLength) { fsOutputFile.Write(bytes, 0, bytesRead); } else { bytesRead = (int)(longOutputFileLength - fsOutputFile.Position); fsOutputFile.Write(bytes, 0, bytesRead); } } } } intCounterTotalTrimmed = intCounterTotalTrimmed + 1; } } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Trimmed " + intCounterTotalTrimmed + " ROMs in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Trimming the zeros from the end of ROMs completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Trimming ROMs failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } /// /// Trims all possible ROMs to a specific size. /// public void STrimROMs() { try { // Print to screen OutputLine("Info: Trimming all possible ROMs to a specific size ..."); // Declarations int intCounterTotalTrimmed = 0; // Total trimmed counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathROMsTrimmedDir = PathROMsTrimmedDir; // Path to the trimmed ROMs directory int intBufferSize = BufferSize; // Buffer size // Checkers bool boolPathROMsDirCheck = PathROMsDirCheck(); bool boolPathROMsTrimmedDirCheck = PathROMsTrimmedDirCheck(); // Check the paths and directories. if (boolPathROMsDirCheck == false && boolPathROMsTrimmedDirCheck == false) { // Print to screen OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); OutputLine("Options: ROMsTrimmed Directory (" + strPathROMsTrimmedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.*", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Trim all of the ROMs. foreach (string strPathFile in arrDirFiles) { OutputLine("Info: Trimming all possible ROMs to a specific size is not yet implemented"); } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Trimmed " + intCounterTotalTrimmed + " ROMs in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Trimming ROMs to a specific size completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Trimming ROMs failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } /// /// Trims a specific size from the beginning of all possible ROMs. /// public void SFLTrimROMs() { try { // Print to screen OutputLine("Info: Trimming bytes from the beginning of all possible ROMs ..."); // Declarations int intCounterTotalTrimmed = 0; // Total trimmed counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathROMsTrimmedDir = PathROMsTrimmedDir; // Path to the trimmed ROMs directory int intBufferSize = BufferSize; // Buffer size // Checkers bool boolPathROMsDirCheck = PathROMsDirCheck(); bool boolPathROMsTrimmedDirCheck = PathROMsTrimmedDirCheck(); // Check the paths and directories. if (boolPathROMsDirCheck == false && boolPathROMsTrimmedDirCheck == false) { // Print to screen OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); OutputLine("Options: ROMsTrimmed Directory (" + strPathROMsTrimmedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.*", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Trim all of the ROMs. foreach (string strPathFile in arrDirFiles) { OutputLine("Info: Trimming bytes from the beginning of all possible ROMs is not yet implemented"); } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Trimmed " + intCounterTotalTrimmed + " ROMs in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Trimming bytes from the beginning of ROMs completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Trimming ROMs failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } /// /// Trims a specific size from the end of all possible ROMs. /// public void SFRTrimROMs() { try { // Print to screen OutputLine("Info: Trimming bytes from the end of all possible ROMs ..."); // Declarations int intCounterTotalTrimmed = 0; // Total trimmed counter int intCountArrDirFiles = 0; // Total loop count string strPathROMsDir = PathROMsDir; // Path to the ROMs directory string strPathROMsTrimmedDir = PathROMsTrimmedDir; // Path to the trimmed ROMs directory int intBufferSize = BufferSize; // Buffer size // Checkers bool boolPathROMsDirCheck = PathROMsDirCheck(); bool boolPathROMsTrimmedDirCheck = PathROMsTrimmedDirCheck(); // Check the paths and directories. if (boolPathROMsDirCheck == false && boolPathROMsTrimmedDirCheck == false) { // Print to screen OutputLine("Options: ROMs Directory (" + strPathROMsDir + ")"); OutputLine("Options: ROMsTrimmed Directory (" + strPathROMsTrimmedDir + ")"); // Get the directory files array and count. string[] arrDirFiles = Directory.GetFiles(strPathROMsDir, "*.*", SearchOption.AllDirectories); intCountArrDirFiles = arrDirFiles.Count(); // Create and start a stopwatch. var stopWatch = new Stopwatch(); stopWatch.Start(); // Main loop - Trim all of the ROMs. foreach (string strPathFile in arrDirFiles) { OutputLine("Info: Trimming bytes from the end of all possible ROMs is not yet implemented"); } // Stop the stopwatch. stopWatch.Stop(); // Print to screen OutputLine("Info: Trimmed " + intCounterTotalTrimmed + " ROMs in " + stopWatch.Elapsed); } // Print to screen OutputLine("Info: Trimming bytes from the end of ROMs completed"); OutputLine(""); } catch (Exception ex) { // Print to screen OutputLine("Error: Trimming ROMs failed"); OutputLine("Error: " + ex.Message); OutputLine(""); } } #endregion } }