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
}
}