diff --git a/RombaSharp/Partials/RombaSharp_Inits.cs b/RombaSharp/Partials/RombaSharp_Inits.cs index 39a6f93c..5e929669 100644 --- a/RombaSharp/Partials/RombaSharp_Inits.cs +++ b/RombaSharp/Partials/RombaSharp_Inits.cs @@ -63,7 +63,7 @@ namespace SabreTools Name = Path.GetFileName(inputs[0]) + " Dir2Dat", Description = Path.GetFileName(inputs[0]) + " Dir2Dat", OutputFormat = OutputFormat.Xml, - Files = new Dictionary>(), + Files = new Dictionary>(), }; Logger logger = new Logger(false, ""); diff --git a/SabreTools.Helper/Data/Structs.cs b/SabreTools.Helper/Data/Structs.cs index 2f37f94c..931132cb 100644 --- a/SabreTools.Helper/Data/Structs.cs +++ b/SabreTools.Helper/Data/Structs.cs @@ -191,116 +191,6 @@ namespace SabreTools.Helper } } - /// - /// Intermediate struct for holding and processing rom data - /// - public struct Rom : IComparable, IEquatable - { - public Machine Machine; - public string Name; - public ItemType Type; - public Hash HashData; - public DupeType Dupe; - public bool Nodump; - public string Date; - public SourceMetadata Metadata; - - // Non rom or disk - public string Region; - public string Language; - public bool? Default; - public string Description; - - public int CompareTo(object obj) - { - int ret = 0; - - try - { - Rom comp = (Rom)obj; - - if (this.Machine.Name == comp.Machine.Name) - { - if (this.Name == comp.Name) - { - ret = (this.Equals(comp) ? 0 : 1); - } - ret = String.Compare(this.Name, comp.Name); - } - ret = String.Compare(this.Machine.Name, comp.Machine.Name); - } - catch - { - ret = 1; - } - - return ret; - } - - public bool Equals(Rom other) - { - bool dupefound = false; - - // If either is a nodump, it's never a match - if (this.Nodump || other.Nodump) - { - return dupefound; - } - - if (this.Type == ItemType.Rom && other.Type == ItemType.Rom) - { - dupefound = this.HashData.Equals(other.HashData, false); - } - else if (this.Type == ItemType.Disk && other.Type == ItemType.Disk) - { - dupefound = this.HashData.Equals(other.HashData, true); - } - - return dupefound; - } - } - - /// - /// Intermediate metadata kept with a RomData object representing source information - /// - public struct SourceMetadata - { - public int SystemID; - public string System; - public int SourceID; - public string Source; - } - - /// - /// Intermediate struct for holding and processing Rom/Machine data - /// - public struct Machine : IEquatable - { - public string Name; - public string Comment; - public string Description; - public string Year; - public string Manufacturer; - public string RomOf; - public string CloneOf; - public string SampleOf; - public string SourceFile; - public bool IsBios; - public string Board; - public string RebuildTo; - public bool TorrentZipped; - - public bool Equals(Machine other) - { - if (this.Name == other.Name) - { - return true; - } - - return false; - } - } - /// /// Intermediate struct for holding DAT information /// @@ -326,7 +216,7 @@ namespace SabreTools.Helper public ForcePacking ForcePacking; public OutputFormat OutputFormat; public bool MergeRoms; - public Dictionary> Files; + public Dictionary> Files; // Data specific to the Miss DAT type public bool UseGame; @@ -416,7 +306,7 @@ namespace SabreTools.Helper ForcePacking = this.ForcePacking, OutputFormat = this.OutputFormat, MergeRoms = this.MergeRoms, - Files = new Dictionary>(), + Files = new Dictionary>(), UseGame = this.UseGame, Prefix = this.Prefix, Postfix = this.Postfix, diff --git a/SabreTools.Helper/Objects/DATFromDir.cs b/SabreTools.Helper/Objects/DATFromDir.cs index a4781e3f..fb338823 100644 --- a/SabreTools.Helper/Objects/DATFromDir.cs +++ b/SabreTools.Helper/Objects/DATFromDir.cs @@ -57,8 +57,8 @@ namespace SabreTools { _basePath = Path.GetFullPath(basePath); _datdata = datdata; - _datdata.Files = new Dictionary>(); - _datdata.Files.Add("null", new List()); + _datdata.Files = new Dictionary>(); + _datdata.Files.Add("null", new List()); _noMD5 = noMD5; _noSHA1 = noSHA1; _bare = bare; @@ -158,25 +158,7 @@ namespace SabreTools } _logger.Log("Adding blank empty folder: " + gamename); - - Rom blankrom = new Rom - { - Name = romname, - Machine = new Machine - { - Name = gamename, - Description = gamename, - }, - HashData = new Hash - { - Size = -1, - CRC = "null", - MD5 = "null", - SHA1 = "null", - }, - }; - - _datdata.Files["null"].Add(blankrom); + _datdata.Files["null"].Add(new Rom(romname, gamename)); } }); } @@ -221,7 +203,7 @@ namespace SabreTools { if (!_datdata.Files.ContainsKey(key)) { - _datdata.Files.Add(key, new List()); + _datdata.Files.Add(key, new List()); } _datdata.Files[key].Add(rom); @@ -321,18 +303,33 @@ namespace SabreTools /// Process a single file as a file (with found Rom data) /// /// File to be added - /// Rom data to be used to write to file + /// Rom data to be used to write to file /// Path the represents the parent directory /// Parent game to be used - private void ProcessFileHelper(string item, Rom rom, string basepath, string parent) + private void ProcessFileHelper(string item, DatItem datItem, string basepath, string parent) { + // If the datItem isn't a Rom or Disk, return + if (datItem.Type != ItemType.Rom && datItem.Type != ItemType.Disk) + { + return; + } + + string key = ""; + if (datItem.Type == ItemType.Rom) + { + key = ((Rom)datItem).HashData.Size + "-" + ((Rom)datItem).HashData.CRC; + } + else + { + key = ((Disk)datItem).HashData.Size + "-" + ((Disk)datItem).HashData.MD5; + } + // Add the list if it doesn't exist already - string key = rom.HashData.Size + "-" + rom.HashData.CRC; lock (_datdata.Files) { if (!_datdata.Files.ContainsKey(key)) { - _datdata.Files.Add(key, new List()); + _datdata.Files.Add(key, new List()); } } @@ -406,17 +403,14 @@ namespace SabreTools } // Update rom information - rom.Machine = new Machine - { - Name = gamename, - Description = gamename, - }; - rom.Name = romname; + datItem.Name = romname; + datItem.MachineName = gamename; + datItem.MachineDescription = gamename; // Add the file information to the DAT lock (_datdata.Files) { - _datdata.Files[key].Add(rom); + _datdata.Files[key].Add(datItem); } _logger.User("File added: " + romname + Environment.NewLine); diff --git a/SabreTools.Helper/Objects/DatObjects/Archive.cs b/SabreTools.Helper/Objects/DatObjects/Archive.cs new file mode 100644 index 00000000..1f0eaea2 --- /dev/null +++ b/SabreTools.Helper/Objects/DatObjects/Archive.cs @@ -0,0 +1,91 @@ +namespace SabreTools.Helper +{ + public class Archive : DatItem + { + #region Constructors + + /// + /// Create a default, empty Archive object + /// + public Archive() + { + _name = ""; + _itemType = ItemType.Archive; + } + + /// + /// Create a new Archive object with the included information + /// + /// Name of the item, including extension + public Archive(string name) + { + _name = name; + _itemType = ItemType.Archive; + } + + /// + /// Create a new Archive object with the included information + /// + /// Name of the item, including extension + /// Name for the machine/game + /// Comment for the machine/game + /// Description for the machine/game + /// Year for the machine/game + /// Manufacturer name for the machine/game + /// Set that this machine/game is a rom of + /// Set that this machine/game is a clone of + /// Set that this machine/game is a sample of + /// Source file for the machine/game + /// True if this game is a BIOS, false otherwise + /// Name of the board for this machine/game + /// Name of the game to rebuild to + /// System ID to be associated with + /// System Name to be associated with + /// Source ID to be associated with + /// Source Name to be associated with + public Archive(string name, string machineName, string comment, string machineDescription, string year, + string manufacturer, string romOf, string cloneOf, string sampleOf, string sourceFile, bool isBios, string board, string rebuildTo, + int systemId, string systemName, int sourceId, string sourceName) + { + _name = name; + _itemType = ItemType.Archive; + _machineName = machineName; + _comment = comment; + _machineDescription = machineDescription; + _year = year; + _manufacturer = manufacturer; + _romOf = romOf; + _cloneOf = cloneOf; + _sampleOf = sampleOf; + _sourceFile = sourceFile; + _isBios = isBios; + _board = board; + _rebuildTo = rebuildTo; + _systemId = systemId; + _systemName = systemName; + _sourceId = sourceId; + _sourceName = sourceName; + } + + #endregion + + #region Comparision Methods + + public override bool Equals(DatItem other) + { + // If we don't have a rom, return false + if (_itemType == other.Type) + { + return false; + } + + // Otherwise, treat it as a rom + Archive newOther = (Archive)other; + + // If the archive information matches + return (_name == newOther.Name); + } + + #endregion + } +} diff --git a/SabreTools.Helper/Objects/DatObjects/BiosSet.cs b/SabreTools.Helper/Objects/DatObjects/BiosSet.cs new file mode 100644 index 00000000..ec412bcf --- /dev/null +++ b/SabreTools.Helper/Objects/DatObjects/BiosSet.cs @@ -0,0 +1,121 @@ +namespace SabreTools.Helper +{ + public class BiosSet : DatItem + { + #region Private instance variables + + private string _description; + private bool? _default; + + #endregion + + #region Publicly facing variables + + public string Description + { + get { return _description; } + set { _description = value; } + } + public bool? Default + { + get { return _default; } + set { _default = value; } + } + + #endregion + + #region Constructors + + /// + /// Create a default, empty Sample object + /// + public BiosSet() + { + _name = ""; + _itemType = ItemType.BiosSet; + } + + /// + /// Create a new Sample object with the included information + /// + /// Name of the item, including extension + /// Description of the Bios set item + /// True if this is the default BIOS, false if it is not, null for undefined + public BiosSet(string name, string description, bool? @default) + { + _name = name; + _itemType = ItemType.BiosSet; + _description = description; + _default = @default; + } + + /// + /// Create a new Sample object with the included information + /// + /// Name of the item, including extension + /// Description of the Bios set item + /// True if this is the default BIOS, false if it is not, null for undefined + /// Name for the machine/game + /// Comment for the machine/game + /// Description for the machine/game + /// Year for the machine/game + /// Manufacturer name for the machine/game + /// Set that this machine/game is a rom of + /// Set that this machine/game is a clone of + /// Set that this machine/game is a sample of + /// Source file for the machine/game + /// True if this game is a BIOS, false otherwise + /// Name of the board for this machine/game + /// Name of the game to rebuild to + /// System ID to be associated with + /// System Name to be associated with + /// Source ID to be associated with + /// Source Name to be associated with + public BiosSet(string name, string description, bool? @default, string machineName, string comment, string machineDescription, string year, + string manufacturer, string romOf, string cloneOf, string sampleOf, string sourceFile, bool isBios, string board, string rebuildTo, + int systemId, string systemName, int sourceId, string sourceName) + { + _name = name; + _itemType = ItemType.BiosSet; + _description = description; + _default = @default; + _machineName = machineName; + _comment = comment; + _machineDescription = machineDescription; + _year = year; + _manufacturer = manufacturer; + _romOf = romOf; + _cloneOf = cloneOf; + _sampleOf = sampleOf; + _sourceFile = sourceFile; + _isBios = isBios; + _board = board; + _rebuildTo = rebuildTo; + _systemId = systemId; + _systemName = systemName; + _sourceId = sourceId; + _sourceName = sourceName; + } + + #endregion + + #region Comparision Methods + + public override bool Equals(DatItem other) + { + // If we don't have a rom, return false + if (_itemType == other.Type) + { + return false; + } + + // Otherwise, treat it as a rom + BiosSet newOther = (BiosSet)other; + + // If the archive information matches + return (_name == newOther.Name && _description == newOther.Description && _default == newOther.Default); + } + + #endregion + } +} diff --git a/SabreTools.Helper/Objects/DatObjects/Disk.cs b/SabreTools.Helper/Objects/DatObjects/Disk.cs new file mode 100644 index 00000000..8ad768ac --- /dev/null +++ b/SabreTools.Helper/Objects/DatObjects/Disk.cs @@ -0,0 +1,146 @@ +namespace SabreTools.Helper +{ + public class Disk : DatItem + { + #region Private instance variables + + // Disk information + private Hash _hashData; + // private string _merge; + // private DiskStatus _romStatus; + private bool _nodump; + + #endregion + + #region Publicly facing variables + + // Disk information + public Hash HashData + { + get { return _hashData; } + set { _hashData = value; } + } + public bool Nodump + { + get { return _nodump; } + set { _nodump = value; } + } + + #endregion + + #region Constructors + + /// + /// Create a default, empty Disk object + /// + public Disk() + { + _name = ""; + _itemType = ItemType.Disk; + _dupeType = DupeType.None; + _nodump = false; + } + + /// + /// Create a new Disk object with the included information + /// + /// Name of the item, including extension + /// String representation of the MD5 + /// String representation of the SHA-1 + /// True if the file is a nodump, false otherwise + public Disk(string name, string md5, string sha1, bool nodump) + { + _name = name; + _itemType = ItemType.Disk; + _hashData = new Hash + { + MD5 = md5.ToLowerInvariant(), + SHA1 = sha1.ToLowerInvariant(), + }; + _nodump = nodump; + } + + /// + /// Create a new Disk object with the included information + /// + /// Name of the item, including extension + /// String representation of the MD5 + /// String representation of the SHA-1 + /// True if the file is a nodump, false otherwise + /// Name for the machine/game + /// Comment for the machine/game + /// Description for the machine/game + /// Year for the machine/game + /// Manufacturer name for the machine/game + /// Set that this machine/game is a rom of + /// Set that this machine/game is a clone of + /// Set that this machine/game is a sample of + /// Source file for the machine/game + /// True if this game is a BIOS, false otherwise + /// Name of the board for this machine/game + /// Name of the game to rebuild to + /// System ID to be associated with + /// System Name to be associated with + /// Source ID to be associated with + /// Source Name to be associated with + public Disk(string name, string md5, string sha1, bool nodump, string machineName, string comment, + string machineDescription, string year, string manufacturer, string romOf, string cloneOf, string sampleOf, string sourceFile, + bool isBios, string board, string rebuildTo, int systemId, string systemName, int sourceId, string sourceName) + { + _name = name; + _itemType = ItemType.Disk; + _hashData = new Hash + { + MD5 = md5.ToLowerInvariant(), + SHA1 = sha1.ToLowerInvariant(), + }; + _nodump = nodump; + _machineName = machineName; + _comment = comment; + _machineDescription = machineDescription; + _year = year; + _manufacturer = manufacturer; + _romOf = romOf; + _cloneOf = cloneOf; + _sampleOf = sampleOf; + _sourceFile = sourceFile; + _isBios = isBios; + _board = board; + _rebuildTo = rebuildTo; + _systemId = systemId; + _systemName = systemName; + _sourceId = sourceId; + _sourceName = sourceName; + } + + #endregion + + #region Comparision Methods + + public override bool Equals(DatItem other) + { + bool dupefound = false; + + // If we don't have a rom, return false + if (_itemType == other.Type) + { + return dupefound; + } + + // Otherwise, treat it as a rom + Disk newOther = (Disk)other; + + // If either is a nodump, it's never a match + if (_nodump || newOther.Nodump) + { + return dupefound; + } + + dupefound = _hashData.Equals(newOther.HashData, false); + + return dupefound; + } + + #endregion + } +} diff --git a/SabreTools.Helper/Objects/DatObjects/Release.cs b/SabreTools.Helper/Objects/DatObjects/Release.cs new file mode 100644 index 00000000..a82b6433 --- /dev/null +++ b/SabreTools.Helper/Objects/DatObjects/Release.cs @@ -0,0 +1,149 @@ +namespace SabreTools.Helper +{ + public class Release : DatItem + { + #region Private instance variables + + private string _region; + private string _language; + private string _date; + private bool? _default; + + #endregion + + #region Publicly facing variables + + public string Region + { + get { return _region; } + set { _region = value; } + } + public string Language + { + get { return _language; } + set { _language = value; } + } + public string Date + { + get { return _date; } + set { _date = value; } + } + public bool? Default + { + get { return _default; } + set { _default = value; } + } + + #endregion + + #region Constructors + + /// + /// Create a default, empty Release object + /// + public Release() + { + _name = ""; + _itemType = ItemType.Release; + _region = ""; + _language = ""; + _date = ""; + _default = null; + } + + /// + /// Create a new Release object with the included information + /// + /// Name of the item, including extension + /// Region of the item + /// Language of the item + /// String representation of the Date + /// True if this is the default BIOS, false if it is not, null for undefined + public Release(string name, string region, string language, string date, bool? @default) + { + _name = name; + _itemType = ItemType.Release; + _region = region; + _language = language; + _date = date; + _default = @default; + } + + /// + /// Create a new Release object with the included information + /// + /// Name of the item, including extension + /// Region of the item + /// Language of the item + /// String representation of the Date + /// True if this is the default BIOS, false if it is not, null for undefined + /// Name for the machine/game + /// Comment for the machine/game + /// Description for the machine/game + /// Year for the machine/game + /// Manufacturer name for the machine/game + /// Set that this machine/game is a rom of + /// Set that this machine/game is a clone of + /// Set that this machine/game is a sample of + /// Source file for the machine/game + /// True if this game is a BIOS, false otherwise + /// Name of the board for this machine/game + /// Name of the game to rebuild to + /// System ID to be associated with + /// System Name to be associated with + /// Source ID to be associated with + /// Source Name to be associated with + public Release(string name, string region, string language, string date, bool? @default, string machineName, string comment, + string machineDescription, string year, string manufacturer, string romOf, string cloneOf, string sampleOf, string sourceFile, + bool isBios, string board, string rebuildTo, int systemId, string systemName, int sourceId, string sourceName) + { + _name = name; + _itemType = ItemType.Release; + _region = region; + _language = language; + _date = date; + _default = @default; + _machineName = machineName; + _comment = comment; + _machineDescription = machineDescription; + _year = year; + _manufacturer = manufacturer; + _romOf = romOf; + _cloneOf = cloneOf; + _sampleOf = sampleOf; + _sourceFile = sourceFile; + _isBios = isBios; + _board = board; + _rebuildTo = rebuildTo; + _systemId = systemId; + _systemName = systemName; + _sourceId = sourceId; + _sourceName = sourceName; + } + + #endregion + + #region Comparision Methods + + public override bool Equals(DatItem other) + { + // If we don't have a rom, return false + if (_itemType == other.Type) + { + return false; + } + + // Otherwise, treat it as a rom + Release newOther = (Release)other; + + // If the archive information matches + return (_name == newOther.Name + && _region == newOther.Region + && _language == newOther.Language + && _date == newOther.Date + && _default == newOther.Default); + } + + #endregion + } +} diff --git a/SabreTools.Helper/Objects/DatObjects/Rom.cs b/SabreTools.Helper/Objects/DatObjects/Rom.cs new file mode 100644 index 00000000..51d195ad --- /dev/null +++ b/SabreTools.Helper/Objects/DatObjects/Rom.cs @@ -0,0 +1,175 @@ +namespace SabreTools.Helper +{ + public class Rom : DatItem + { + #region Private instance variables + + // Rom information + private Hash _hashData; + // private string _merge; + // private RomStatus _romStatus; + private bool _nodump; + private string _date; + + #endregion + + #region Publicly facing variables + + // Rom information + public Hash HashData + { + get { return _hashData; } + set { _hashData = value; } + } + public bool Nodump + { + get { return _nodump; } + set { _nodump = value; } + } + public string Date + { + get { return _date; } + set { _date = value; } + } + + #endregion + + #region Constructors + + /// + /// Create a default, empty Rom object + /// + public Rom() + { + _name = ""; + _itemType = ItemType.Rom; + _dupeType = DupeType.None; + _nodump = false; + _date = ""; + } + + /// + /// Create a "blank" Rom object + /// + /// + /// + public Rom(string name, string machineName) : + this(name, -1, "null", "null", "null", false, null, machineName, null, machineName, null, null, null, null, null, null, false, null, null, -1, null, -1, null) + { + } + + /// + /// Create a new Rom object with the included information + /// + /// Name of the item, including extension + /// Long size of the item + /// String representation of the CRC + /// String representation of the MD5 + /// String representation of the SHA-1 + /// True if the file is a nodump, false otherwise + /// String representation of the Date + public Rom(string name, long size, string crc, string md5, string sha1, bool nodump, string date) + { + _name = name; + _itemType = ItemType.Rom; + _hashData = new Hash + { + Size = size, + CRC = crc.ToLowerInvariant(), + MD5 = md5.ToLowerInvariant(), + SHA1 = sha1.ToLowerInvariant(), + }; + _nodump = nodump; + _date = date; + } + + /// + /// Create a new Rom object with the included information + /// + /// Name of the item, including extension + /// Long size of the item + /// String representation of the CRC + /// String representation of the MD5 + /// String representation of the SHA-1 + /// True if the file is a nodump, false otherwise + /// String representation of the Date + /// Name for the machine/game + /// Comment for the machine/game + /// Description for the machine/game + /// Year for the machine/game + /// Manufacturer name for the machine/game + /// Set that this machine/game is a rom of + /// Set that this machine/game is a clone of + /// Set that this machine/game is a sample of + /// Source file for the machine/game + /// True if this game is a BIOS, false otherwise + /// Name of the board for this machine/game + /// Name of the game to rebuild to + /// System ID to be associated with + /// System Name to be associated with + /// Source ID to be associated with + /// Source Name to be associated with + public Rom(string name, long size, string crc, string md5, string sha1, bool nodump, string date, string machineName, + string comment, string machineDescription, string year, string manufacturer, string romOf, string cloneOf, string sampleOf, + string sourceFile, bool isBios, string board, string rebuildTo, int systemId, string systemName, int sourceId, string sourceName) + { + _name = name; + _itemType = ItemType.Rom; + _hashData = new Hash + { + Size = size, + CRC = crc.ToLowerInvariant(), + MD5 = md5.ToLowerInvariant(), + SHA1 = sha1.ToLowerInvariant(), + }; + _nodump = nodump; + _date = date; + _machineName = machineName; + _comment = comment; + _machineDescription = machineDescription; + _year = year; + _manufacturer = manufacturer; + _romOf = romOf; + _cloneOf = cloneOf; + _sampleOf = sampleOf; + _sourceFile = sourceFile; + _isBios = isBios; + _board = board; + _rebuildTo = rebuildTo; + _systemId = systemId; + _systemName = systemName; + _sourceId = sourceId; + _sourceName = sourceName; + } + + #endregion + + #region Comparision Methods + + public override bool Equals(DatItem other) + { + bool dupefound = false; + + // If we don't have a rom, return false + if (_itemType == other.Type) + { + return dupefound; + } + + // Otherwise, treat it as a rom + Rom newOther = (Rom)other; + + // If either is a nodump, it's never a match + if (_nodump || newOther.Nodump) + { + return dupefound; + } + + dupefound = _hashData.Equals(newOther.HashData, false); + + return dupefound; + } + + #endregion + } +} diff --git a/SabreTools.Helper/Objects/DatObjects/Sample.cs b/SabreTools.Helper/Objects/DatObjects/Sample.cs new file mode 100644 index 00000000..01331f1c --- /dev/null +++ b/SabreTools.Helper/Objects/DatObjects/Sample.cs @@ -0,0 +1,91 @@ +namespace SabreTools.Helper +{ + public class Sample : DatItem + { + #region Constructors + + /// + /// Create a default, empty Sample object + /// + public Sample() + { + _name = ""; + _itemType = ItemType.Sample; + } + + /// + /// Create a new Sample object with the included information + /// + /// Name of the item, including extension + public Sample(string name) + { + _name = name; + _itemType = ItemType.Sample; + } + + /// + /// Create a new Sample object with the included information + /// + /// Name of the item, including extension + /// Name for the machine/game + /// Comment for the machine/game + /// Description for the machine/game + /// Year for the machine/game + /// Manufacturer name for the machine/game + /// Set that this machine/game is a rom of + /// Set that this machine/game is a clone of + /// Set that this machine/game is a sample of + /// Source file for the machine/game + /// True if this game is a BIOS, false otherwise + /// Name of the board for this machine/game + /// Name of the game to rebuild to + /// System ID to be associated with + /// System Name to be associated with + /// Source ID to be associated with + /// Source Name to be associated with + public Sample(string name, string machineName, string comment, string machineDescription, string year, + string manufacturer, string romOf, string cloneOf, string sampleOf, string sourceFile, bool isBios, string board, string rebuildTo, + int systemId, string systemName, int sourceId, string sourceName) + { + _name = name; + _itemType = ItemType.Sample; + _machineName = machineName; + _comment = comment; + _machineDescription = machineDescription; + _year = year; + _manufacturer = manufacturer; + _romOf = romOf; + _cloneOf = cloneOf; + _sampleOf = sampleOf; + _sourceFile = sourceFile; + _isBios = isBios; + _board = board; + _rebuildTo = rebuildTo; + _systemId = systemId; + _systemName = systemName; + _sourceId = sourceId; + _sourceName = sourceName; + } + + #endregion + + #region Comparision Methods + + public override bool Equals(DatItem other) + { + // If we don't have a rom, return false + if (_itemType == other.Type) + { + return false; + } + + // Otherwise, treat it as a rom + Sample newOther = (Sample)other; + + // If the archive information matches + return (_name == newOther.Name); + } + + #endregion + } +} diff --git a/SabreTools.Helper/Objects/Generate.cs b/SabreTools.Helper/Objects/Generate.cs index bd43c90f..046695c1 100644 --- a/SabreTools.Helper/Objects/Generate.cs +++ b/SabreTools.Helper/Objects/Generate.cs @@ -9,7 +9,7 @@ namespace SabreTools /// /// Generate a DAT from the data in the database /// - class Generate : IGenerate + public class Generate : IGenerate { // Private instance variables private string _systems; @@ -153,7 +153,7 @@ namespace SabreTools } // Retrieve the list of processed roms - Dictionary> dict = ProcessRoms(); + Dictionary> dict = ProcessRoms(); // If the output is null, nothing was found so return false if (dict.Count == 0) @@ -186,9 +186,9 @@ namespace SabreTools /// Preprocess the rom data that is to be included in the outputted DAT /// /// A List of Rom objects containing all information about the files - public Dictionary> ProcessRoms() + public Dictionary> ProcessRoms() { - Dictionary> roms = new Dictionary>(); + Dictionary> roms = new Dictionary>(); // Check if we have listed sources or systems bool sysmerged = (_systems == "" || _systems.Split(',').Length > 1); @@ -236,47 +236,42 @@ JOIN checksums // Retrieve and process the roms for merging while (sldr.Read()) { - Rom temp = new Rom + DatItem temp; + string key = ""; + switch (sldr.GetString(8).ToLowerInvariant()) { - Name = sldr.GetString(7), - Type = (sldr.GetString(8) == "disk" ? ItemType.Disk : ItemType.Rom), - Machine = new Machine - { - Name = sldr.GetString(6), - Manufacturer = sldr.GetString(0), - }, - Metadata = new SourceMetadata - { - System = sldr.GetString(1), - SystemID = sldr.GetInt32(2), - Source = sldr.GetString(3), - SourceID = sldr.GetInt32(5), - }, - HashData = new Hash - { - Size = sldr.GetInt64(9), - CRC = sldr.GetString(10), - MD5 = sldr.GetString(11), - SHA1 = sldr.GetString(12), - }, - }; + case "disk": + temp = new Disk(sldr.GetString(7), sldr.GetString(11), sldr.GetString(12), false, sldr.GetString(13), sldr.GetString(6), + sldr.GetString(6), null, sldr.GetString(0), null, null, null, null, false, null, null, sldr.GetInt32(2), + sldr.GetString(1), sldr.GetInt32(5), sldr.GetString(3)); + + key = ((Disk)temp).HashData.Size + "-" + ((Disk)temp).HashData.CRC; + break; + case "rom": + default: + temp = new Rom(sldr.GetString(7), sldr.GetInt64(9), sldr.GetString(10), sldr.GetString(11), sldr.GetString(12), false, + sldr.GetString(13), sldr.GetString(6), null, sldr.GetString(6), null, sldr.GetString(0), null, null, null, null, false, + null, null, sldr.GetInt32(2), sldr.GetString(1), sldr.GetInt32(5), sldr.GetString(3)); + + key = ((Disk)temp).HashData.Size + "-" + ((Disk)temp).HashData.CRC; + break; + } // Rename the game associated if it's still valid and we allow renames if (merged && !_norename) { - temp.Machine.Name = temp.Machine.Name + - (sysmerged ? " [" + temp.Machine.Manufacturer + " - " + temp.Metadata.System + "]" : "") + - (srcmerged ? " [" + temp.Metadata.Source + "]" : ""); + temp.MachineName = temp.MachineName + + (sysmerged ? " [" + temp.Manufacturer + " - " + temp.System + "]" : "") + + (srcmerged ? " [" + temp.Source + "]" : ""); } - string key = temp.HashData.Size + "-" + temp.HashData.CRC; if (roms.ContainsKey(key)) { roms[key].Add(temp); } else { - List templist = new List(); + List templist = new List(); templist.Add(temp); roms.Add(key, templist); } @@ -290,7 +285,7 @@ JOIN checksums { foreach (string key in roms.Keys) { - roms[key] = RomTools.Merge(roms[key], _logger); + roms[key] = DatItem.Merge(roms[key], _logger); } } // END COMMENT diff --git a/SabreTools.Helper/Objects/GenerateTwo.cs b/SabreTools.Helper/Objects/GenerateTwo.cs index 41d6c82d..381357ab 100644 --- a/SabreTools.Helper/Objects/GenerateTwo.cs +++ b/SabreTools.Helper/Objects/GenerateTwo.cs @@ -188,14 +188,14 @@ namespace SabreTools List keys = datdata.Files.Keys.ToList(); foreach (string key in keys) { - List temp = new List(); - List newroms = datdata.Files[key]; + List temp = new List(); + List newroms = datdata.Files[key]; for (int i = 0; i < newroms.Count; i++) { - Rom rom = newroms[i]; + Rom rom = (Rom)newroms[i]; // In the case that the RomData is incomplete, skip it - if (rom.Name == null || rom.Machine.Name == null) + if (rom.Name == null || rom.MachineName == null) { continue; } @@ -209,27 +209,27 @@ namespace SabreTools rom.Name = Regex.Replace(rom.Name, @"(.*) \.(.*)", "$1.$2"); // Run the name through the filters to make sure that it's correct - rom.Machine.Name = Style.NormalizeChars(rom.Machine.Name); - rom.Machine.Name = Style.RussianToLatin(rom.Machine.Name); - rom.Machine.Name = Style.SearchPattern(rom.Machine.Name); + rom.MachineName = Style.NormalizeChars(rom.MachineName); + rom.MachineName = Style.RussianToLatin(rom.MachineName); + rom.MachineName = Style.SearchPattern(rom.MachineName); // WoD gets rid of anything past the first "(" or "[" as the name, we will do the same string stripPattern = @"(([[(].*[\)\]] )?([^([]+))"; Regex stripRegex = new Regex(stripPattern); - Match stripMatch = stripRegex.Match(rom.Machine.Name); - rom.Machine.Name = stripMatch.Groups[1].Value; + Match stripMatch = stripRegex.Match(rom.MachineName); + rom.MachineName = stripMatch.Groups[1].Value; - rom.Machine.Name = rom.Machine.Name.TrimEnd().TrimStart(); + rom.MachineName = rom.MachineName.TrimEnd().TrimStart(); if (!_norename) { - rom.Machine.Name += " [" + sources[rom.Metadata.SourceID] + "]"; + rom.MachineName += " [" + sources[rom.SourceID] + "]"; } // If a game has source "0" it's Default. Make this Int32.MaxValue for sorting purposes - if (rom.Metadata.SourceID == 0) + if (rom.SourceID == 0) { - rom.Metadata.SourceID = Int32.MaxValue; + rom.SourceID = Int32.MaxValue; } temp.Add(rom); diff --git a/SabreTools.Helper/Objects/Import.cs b/SabreTools.Helper/Objects/Import.cs index 2834b292..16f802c7 100644 --- a/SabreTools.Helper/Objects/Import.cs +++ b/SabreTools.Helper/Objects/Import.cs @@ -370,27 +370,27 @@ namespace SabreTools DatTools.Parse(_filepath, sysid, srcid, ref datdata, _logger); // Sort inputted roms into games - SortedDictionary> sortable = new SortedDictionary>(); + SortedDictionary> sortable = new SortedDictionary>(); long count = 0; - foreach (List roms in datdata.Files.Values) + foreach (List roms in datdata.Files.Values) { - List newroms = roms; + List newroms = roms; if (datdata.MergeRoms) { - newroms = RomTools.Merge(newroms, _logger); + newroms = DatItem.Merge(newroms, _logger); } foreach (Rom rom in newroms) { count++; - string key = rom.Metadata.SystemID.ToString().PadLeft(10, '0') + "-" + rom.Metadata.SourceID.ToString().PadLeft(10, '0') + "-" + rom.Machine.Name.ToLowerInvariant(); + string key = rom.SystemID.ToString().PadLeft(10, '0') + "-" + rom.SourceID.ToString().PadLeft(10, '0') + "-" + rom.MachineName.ToLowerInvariant(); if (sortable.ContainsKey(key)) { sortable[key].Add(rom); } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); sortable.Add(key, temp); } @@ -400,8 +400,8 @@ namespace SabreTools // Loop over all roms, checking for adds foreach (string key in sortable.Keys) { - List roms = sortable[key]; - RomTools.Sort(ref roms, true); + List roms = sortable[key]; + DatItem.Sort(ref roms, true); long gameid = -1; using (SqliteConnection dbc = new SqliteConnection(_connectionString)) @@ -409,7 +409,7 @@ namespace SabreTools dbc.Open(); // For each game, check for a new ID - gameid = AddGame(sysid, roms[0].Machine.Name, srcid, dbc); + gameid = AddGame(sysid, roms[0].MachineName, srcid, dbc); foreach (Rom rom in roms) { @@ -573,14 +573,14 @@ COMMIT;"; // WoD gets rid of anything past the first "(" or "[" as the name, we will do the same string stripPattern = @"(([[(].*[\)\]] )?([^([]+))"; Regex stripRegex = new Regex(stripPattern); - Match stripMatch = stripRegex.Match(rom.Machine.Name); - rom.Machine.Name = stripMatch.Groups[1].Value; + Match stripMatch = stripRegex.Match(rom.MachineName); + rom.MachineName = stripMatch.Groups[1].Value; // Run the name through the filters to make sure that it's correct - rom.Machine.Name = Style.NormalizeChars(rom.Machine.Name); - rom.Machine.Name = Style.RussianToLatin(rom.Machine.Name); - rom.Machine.Name = Style.SearchPattern(rom.Machine.Name); - rom.Machine.Name = rom.Machine.Name.Trim(); + rom.MachineName = Style.NormalizeChars(rom.MachineName); + rom.MachineName = Style.RussianToLatin(rom.MachineName); + rom.MachineName = Style.SearchPattern(rom.MachineName); + rom.MachineName = rom.MachineName.Trim(); // Process the rom name @@ -629,11 +629,11 @@ COMMIT;"; query = @"BEGIN; INSERT OR IGNORE INTO hashdata (hashid, key, value) VALUES " + "(" + hashid + ", 'name', '" + rom.Name.Replace("'", "''") + "'), " + - "(" + hashid + ", 'game', '" + rom.Machine.Name.Replace("'", "''") + "'), " + + "(" + hashid + ", 'game', '" + rom.MachineName.Replace("'", "''") + "'), " + "(" + hashid + ", 'type', '" + rom.Type + "'), " + "(" + hashid + ", 'lastupdated', '" + date + @"'); -INSERT OR IGNORE INTO gamesystem (game, systemid) VALUES ('" + rom.Machine.Name.Replace("'", "''") + "', " + sysid + @"); -INSERT OR IGNORE INTO gamesource (game, sourceid) VALUES ('" + rom.Machine.Name.Replace("'", "''") + "', " + srcid + @"); +INSERT OR IGNORE INTO gamesystem (game, systemid) VALUES ('" + rom.MachineName.Replace("'", "''") + "', " + sysid + @"); +INSERT OR IGNORE INTO gamesource (game, sourceid) VALUES ('" + rom.MachineName.Replace("'", "''") + "', " + srcid + @"); COMMIT;"; using (SqliteCommand slc = new SqliteCommand(query, dbc)) diff --git a/SabreTools.Helper/Objects/SimpleSort.cs b/SabreTools.Helper/Objects/SimpleSort.cs index 5ae87992..5a978d1b 100644 --- a/SabreTools.Helper/Objects/SimpleSort.cs +++ b/SabreTools.Helper/Objects/SimpleSort.cs @@ -76,7 +76,7 @@ namespace SabreTools.Helper _cursorLeft = Console.CursorLeft; _matched = new Dat { - Files = new Dictionary>(), + Files = new Dictionary>(), }; } @@ -145,7 +145,7 @@ namespace SabreTools.Helper // Setup the fixdat _matched = (Dat)_datdata.CloneHeader(); - _matched.Files = new Dictionary>(); + _matched.Files = new Dictionary>(); _matched.FileName = "fixDat_" + _matched.FileName; _matched.Name = "fixDat_" + _matched.Name; _matched.Description = "fixDat_" + _matched.Description; @@ -153,12 +153,12 @@ namespace SabreTools.Helper // Now that all files are parsed, get only files found in directory bool found = false; - foreach (List roms in _datdata.Files.Values) + foreach (List roms in _datdata.Files.Values) { - List newroms = RomTools.Merge(roms, _logger); + List newroms = DatItem.Merge(roms, _logger); foreach (Rom rom in newroms) { - if (rom.Metadata.SourceID == 99) + if (rom.SourceID == 99) { found = true; string key = rom.HashData.Size + "-" + rom.HashData.CRC; @@ -168,7 +168,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); _matched.Files.Add(key, temp); } @@ -343,7 +343,7 @@ namespace SabreTools.Helper _logger.User("Getting source file information..."); Dat matchdat = new Dat { - Files = new Dictionary>(), + Files = new Dictionary>(), }; foreach (string file in files) { @@ -409,15 +409,15 @@ namespace SabreTools.Helper #region Find all files to rebuild and bucket by game // Create a dictionary of from/to Rom mappings - Dictionary toFromMap = new Dictionary(); + Dictionary toFromMap = new Dictionary(); // Now populate it foreach (string key in matchdat.Files.Keys) { - foreach (Rom rom in matchdat.Files[key]) + foreach (DatItem rom in matchdat.Files[key]) { - List matched = RomTools.GetDuplicates(rom, _datdata, _logger, true); - foreach (Rom match in matched) + List matched = DatItem.GetDuplicates(rom, _datdata, _logger, true); + foreach (DatItem match in matched) { try { @@ -429,7 +429,7 @@ namespace SabreTools.Helper } // Then bucket the keys by game for better output - SortedDictionary> keysByGame = DatTools.BucketByGame(toFromMap.Keys.ToList(), false, true, _logger); + SortedDictionary> keysByGame = DatTools.BucketByGame(toFromMap.Keys.ToList(), false, true, _logger); #endregion @@ -467,7 +467,7 @@ namespace SabreTools.Helper } // Otherwise, set the machine name as the full path to the file - rom.Machine.Name = Path.GetDirectoryName(Path.GetFullPath(file)); + rom.MachineName = Path.GetDirectoryName(Path.GetFullPath(file)); // Add the rom information to the Dat string key = rom.HashData.Size + "-" + rom.HashData.CRC; @@ -477,7 +477,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); matchdat.Files.Add(key, temp); } @@ -494,7 +494,7 @@ namespace SabreTools.Helper Skippers.TransformStream(input, output, rule, _logger, false, true); Rom romNH = FileTools.GetSingleStreamInfo(output); romNH.Name = "HEAD::" + rom.Name; - romNH.Machine.Name = rom.Machine.Name; + romNH.MachineName = rom.MachineName; // Add the rom information to the Dat key = romNH.HashData.Size + "-" + romNH.HashData.CRC; @@ -504,7 +504,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(romNH); matchdat.Files.Add(key, temp); } @@ -548,7 +548,7 @@ namespace SabreTools.Helper } // Try to find the matches to the file that was found - List foundroms = RomTools.GetDuplicates(rom, _datdata, _logger); + List foundroms = DatItem.GetDuplicates(rom, _datdata, _logger); _logger.Log("File '" + input + "' had " + foundroms.Count + " matches in the DAT!"); foreach (Rom found in foundroms) { @@ -562,7 +562,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(found); _matched.Files.Add(key, temp); } @@ -570,7 +570,7 @@ namespace SabreTools.Helper if (_toFolder) { // Copy file to output directory - string gamedir = Path.Combine(_outDir, found.Machine.Name); + string gamedir = Path.Combine(_outDir, found.MachineName); if (!Directory.Exists(gamedir)) { Directory.CreateDirectory(gamedir); @@ -618,7 +618,7 @@ namespace SabreTools.Helper } // Try to find the matches to the file that was found - List founddroms = RomTools.GetDuplicates(drom, _datdata, _logger); + List founddroms = DatItem.GetDuplicates(drom, _datdata, _logger); _logger.Log("File '" + newinput + "' had " + founddroms.Count + " matches in the DAT!"); foreach (Rom found in founddroms) { @@ -630,7 +630,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(found); _matched.Files.Add(key, temp); } @@ -641,7 +641,7 @@ namespace SabreTools.Helper if (_toFolder) { // Copy file to output directory - string gamedir = Path.Combine(_outDir, found.Machine.Name); + string gamedir = Path.Combine(_outDir, found.MachineName); if (!Directory.Exists(gamedir)) { Directory.CreateDirectory(gamedir); @@ -683,7 +683,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(newfound); _matched.Files.Add(key, temp); } @@ -691,7 +691,7 @@ namespace SabreTools.Helper if (_toFolder) { // Copy file to output directory - string gamedir = Path.Combine(_outDir, found.Machine.Name); + string gamedir = Path.Combine(_outDir, found.MachineName); if (!Directory.Exists(gamedir)) { Directory.CreateDirectory(gamedir); @@ -750,7 +750,7 @@ namespace SabreTools.Helper foreach (Rom rom in internalRomData) { // Try to find the matches to the file that was found - List foundroms = RomTools.GetDuplicates(rom, _datdata, _logger); + List foundroms = DatItem.GetDuplicates(rom, _datdata, _logger); _logger.Log("File '" + rom.Name + "' had " + foundroms.Count + " matches in the DAT!"); foreach (Rom found in foundroms) { @@ -762,7 +762,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(found); _matched.Files.Add(key, temp); } @@ -774,7 +774,7 @@ namespace SabreTools.Helper string outfile = FileTools.ExtractSingleItemFromArchive(input, rom.Name, _tempDir, _logger); if (File.Exists(outfile)) { - string gamedir = Path.Combine(_outDir, found.Machine.Name); + string gamedir = Path.Combine(_outDir, found.MachineName); if (!Directory.Exists(gamedir)) { Directory.CreateDirectory(gamedir); @@ -888,7 +888,7 @@ namespace SabreTools.Helper } // Now process the inputs (assumed that it's archived sets as of right now - Dictionary> scanned = new Dictionary>(); + Dictionary> scanned = new Dictionary>(); foreach (string archive in Directory.EnumerateFiles(_outDir, "*", SearchOption.AllDirectories)) { // If we are in quickscan, get the list of roms that way @@ -921,7 +921,7 @@ namespace SabreTools.Helper } else { - List templist = new List(); + List templist = new List(); templist.Add(rom); scanned.Add(key, templist); } @@ -935,7 +935,7 @@ namespace SabreTools.Helper } // Now that we have all of the from DAT and from folder roms, we try to match them, removing the perfect matches - Dictionary> remove = new Dictionary>(); + Dictionary> remove = new Dictionary>(); foreach (string key in scanned.Keys) { // If the key doesn't even exist in the DAT, then mark the entire key for removal @@ -953,8 +953,8 @@ namespace SabreTools.Helper // Otherwise check each of the values individually else { - List romsList = _datdata.Files[key]; - List scannedList = scanned[key]; + List romsList = _datdata.Files[key]; + List scannedList = scanned[key]; foreach (Rom rom in scannedList) { if (!romsList.Contains(rom)) @@ -965,7 +965,7 @@ namespace SabreTools.Helper } else { - List templist = new List(); + List templist = new List(); templist.Add(rom); remove.Add(key, templist); } diff --git a/SabreTools.Helper/Objects/Stats.cs b/SabreTools.Helper/Objects/Stats.cs index f50236d2..ce1887d2 100644 --- a/SabreTools.Helper/Objects/Stats.cs +++ b/SabreTools.Helper/Objects/Stats.cs @@ -49,7 +49,7 @@ namespace SabreTools.Helper List games = new List(); Dat datdata = new Dat(); DatTools.Parse(filename, 0, 0, ref datdata, _logger); - SortedDictionary> newroms = DatTools.BucketByGame(datdata.Files, false, true, _logger, false); + SortedDictionary> newroms = DatTools.BucketByGame(datdata.Files, false, true, _logger, false); // Output single DAT stats (if asked) if (_single) @@ -116,7 +116,7 @@ Please check the log folder if the stats scrolled offscreen"); datdata.NodumpCount = 0; // Loop through and add - foreach (List roms in datdata.Files.Values) + foreach (List roms in datdata.Files.Values) { foreach (Rom rom in roms) { @@ -131,7 +131,7 @@ Please check the log folder if the stats scrolled offscreen"); } } - SortedDictionary> newroms = DatTools.BucketByGame(datdata.Files, false, true, logger, false); + SortedDictionary> newroms = DatTools.BucketByGame(datdata.Files, false, true, logger, false); if (datdata.TotalSize < 0) { datdata.TotalSize = Int64.MaxValue + datdata.TotalSize; diff --git a/SabreTools.Helper/SabreTools.Helper.csproj b/SabreTools.Helper/SabreTools.Helper.csproj index 4d75e236..b4b0891c 100644 --- a/SabreTools.Helper/SabreTools.Helper.csproj +++ b/SabreTools.Helper/SabreTools.Helper.csproj @@ -101,11 +101,18 @@ + + + + + + + @@ -130,7 +137,6 @@ Resources.fr-FR.resx - @@ -142,8 +148,6 @@ - - diff --git a/SabreTools.Helper/Skippers/Skippers.cs b/SabreTools.Helper/Skippers/Skippers.cs index 7c482b78..e6e2250d 100644 --- a/SabreTools.Helper/Skippers/Skippers.cs +++ b/SabreTools.Helper/Skippers/Skippers.cs @@ -10,7 +10,7 @@ namespace SabreTools.Helper public class Skippers { // Local paths - public const string Path = "Skippers"; + public const string LocalPath = "Skippers"; // Header skippers represented by a list of skipper objects private static List _list; @@ -56,9 +56,9 @@ namespace SabreTools.Helper _list = new List(); } - foreach (string skipperFile in Directory.EnumerateFiles(Path, "*", SearchOption.AllDirectories)) + foreach (string skipperFile in Directory.EnumerateFiles(LocalPath, "*", SearchOption.AllDirectories)) { - _list.Add(PopulateSkippersHelper(System.IO.Path.GetFullPath(skipperFile))); + _list.Add(PopulateSkippersHelper(Path.GetFullPath(skipperFile))); } } @@ -527,9 +527,9 @@ namespace SabreTools.Helper } // Create the output directory if it doesn't already - if (!Directory.Exists(System.IO.Path.GetDirectoryName(output))) + if (!Directory.Exists(Path.GetDirectoryName(output))) { - Directory.CreateDirectory(System.IO.Path.GetDirectoryName(output)); + Directory.CreateDirectory(Path.GetDirectoryName(output)); } logger.User("Attempting to apply rule to '" + input + "'"); @@ -725,7 +725,7 @@ namespace SabreTools.Helper XmlDocument doc = new XmlDocument(); try { - doc.LoadXml(File.ReadAllText(System.IO.Path.Combine(Path, skipper + ".xml"))); + doc.LoadXml(File.ReadAllText(Path.Combine(LocalPath, skipper + ".xml"))); } catch (XmlException ex) { diff --git a/SabreTools.Helper/Tools/DatTools.cs b/SabreTools.Helper/Tools/DatTools.cs index 8c33d203..13d071c0 100644 --- a/SabreTools.Helper/Tools/DatTools.cs +++ b/SabreTools.Helper/Tools/DatTools.cs @@ -180,7 +180,7 @@ namespace SabreTools.Helper // Make sure there's a dictionary to read to if (datdata.Files == null) { - datdata.Files = new Dictionary>(); + datdata.Files = new Dictionary>(); } // Now parse the correct type of DAT @@ -307,27 +307,48 @@ namespace SabreTools.Helper temptype = ItemType.Sample; } - Rom rom = new Rom + // Create the proper DatItem based on the type + DatItem item; + switch (temptype) { - Machine = new Machine - { - Name = tempgamename, - Description = gamedesc, - CloneOf = cloneof, - RomOf = romof, - SampleOf = sampleof, - Manufacturer = manufacturer, - Year = year, - }, - Type = temptype, - Metadata = new SourceMetadata { SystemID = sysid, SourceID = srcid }, - }; + case ItemType.Archive: + item = new Archive(); + break; + case ItemType.BiosSet: + item = new BiosSet(); + break; + case ItemType.Disk: + item = new Disk(); + break; + case ItemType.Release: + item = new Release(); + break; + case ItemType.Sample: + item = new Sample(); + break; + case ItemType.Rom: + default: + item = new Rom(); + break; + } + + // Then populate it with information + item.MachineName = tempgamename; + item.MachineDescription = gamedesc; + item.CloneOf = cloneof; + item.RomOf = romof; + item.SampleOf = sampleof; + item.Manufacturer = manufacturer; + item.Year = year; + item.SystemID = sysid; + item.SourceID = srcid; + Hash tempHash = new Hash(); // If we have a sample, treat it special if (temptype == ItemType.Sample) { line = line.Trim().Remove(0, 6).Trim().Replace("\"", ""); // Remove "sample" from the input string - rom.Name = line; + item.Name = line; } // Otherwise, process the rest of the line @@ -348,7 +369,14 @@ namespace SabreTools.Helper // Special case for nodump... else if (gc[i] == "nodump" && attrib != "status" && attrib != "flags") { - rom.Nodump = true; + if (item.Type == ItemType.Rom) + { + ((Rom)item).Nodump = true; + } + else if (item.Type == ItemType.Disk) + { + ((Disk)item).Nodump = true; + } } // Even number of quotes, not in a quote, not in attribute else if (Regex.Matches(gc[i], "\"").Count % 2 == 0 && !quote && attrib == "") @@ -361,28 +389,38 @@ namespace SabreTools.Helper switch (attrib.ToLowerInvariant()) { case "name": - rom.Name = gc[i].Replace("\"", ""); + item.Name = gc[i].Replace("\"", ""); break; case "size": - Int64.TryParse(gc[i].Replace("\"", ""), out rom.HashData.Size); + Int64.TryParse(gc[i].Replace("\"", ""), out tempHash.Size); break; case "crc": - rom.HashData.CRC = gc[i].Replace("\"", "").ToLowerInvariant(); + tempHash.CRC = gc[i].Replace("\"", "").ToLowerInvariant(); break; case "md5": - rom.HashData.MD5 = gc[i].Replace("\"", "").ToLowerInvariant(); + tempHash.MD5 = gc[i].Replace("\"", "").ToLowerInvariant(); break; case "sha1": - rom.HashData.SHA1 = gc[i].Replace("\"", "").ToLowerInvariant(); + tempHash.SHA1 = gc[i].Replace("\"", "").ToLowerInvariant(); break; case "flags": if (gc[i].Replace("\"", "").ToLowerInvariant() == "nodump") { - rom.Nodump = true; + if (item.Type == ItemType.Rom) + { + ((Rom)item).Nodump = true; + } + else if (item.Type == ItemType.Disk) + { + ((Disk)item).Nodump = true; + } } break; case "date": - rom.Date = gc[i].Replace("\"", "") + " " + gc[i + 1].Replace("\"", ""); + if (item.Type == ItemType.Rom) + { + ((Rom)item).Date = gc[i].Replace("\"", "") + " " + gc[i + 1].Replace("\"", ""); + } i++; break; } @@ -422,28 +460,38 @@ namespace SabreTools.Helper switch (attrib.ToLowerInvariant()) { case "name": - rom.Name = val; + item.Name = val; break; case "size": - Int64.TryParse(val, out rom.HashData.Size); + Int64.TryParse(val, out tempHash.Size); break; case "crc": - rom.HashData.CRC = val.ToLowerInvariant(); + tempHash.CRC = val.ToLowerInvariant(); break; case "md5": - rom.HashData.MD5 = val.ToLowerInvariant(); + tempHash.MD5 = val.ToLowerInvariant(); break; case "sha1": - rom.HashData.SHA1 = val.ToLowerInvariant(); + tempHash.SHA1 = val.ToLowerInvariant(); break; case "flags": if (val.ToLowerInvariant() == "nodump") { - rom.Nodump = true; + if (item.Type == ItemType.Rom) + { + ((Rom)item).Nodump = true; + } + else if (item.Type == ItemType.Disk) + { + ((Disk)item).Nodump = true; + } } break; case "date": - rom.Date = gc[i].Replace("\"", "") + " " + gc[i + 1].Replace("\"", ""); + if (item.Type == ItemType.Rom) + { + ((Rom)item).Date = gc[i].Replace("\"", "") + " " + gc[i + 1].Replace("\"", ""); + } i++; break; } @@ -457,7 +505,15 @@ namespace SabreTools.Helper // Now process and add the rom string key = ""; - ParseAddHelper(rom, ref datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, clean, logger, out key); + if (item.Type == ItemType.Rom) + { + ((Rom)item).HashData = tempHash; + } + else if (item.Type == ItemType.Disk) + { + ((Disk)item).HashData = tempHash; + } + ParseAddHelper(item, ref datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, clean, logger, out key); } // If the line is anything but a rom or disk and we're in a block else if (Regex.IsMatch(line, Constants.ItemPatternCMP) && block) @@ -741,23 +797,8 @@ namespace SabreTools.Helper */ string[] rominfo = line.Split('¬'); - Rom rom = new Rom - { - Machine = new Machine - { - Name = rominfo[3], - Description = rominfo[4], - CloneOf = rominfo[1], - RomOf = rominfo[8], - }, - Name = rominfo[5], - HashData = new Hash - { - CRC = rominfo[6].ToLowerInvariant(), - Size = Int64.Parse(rominfo[7]), - }, - Metadata = new SourceMetadata { SystemID = sysid, SourceID = srcid }, - }; + Rom rom = new Rom(rominfo[5], Int64.Parse(rominfo[7]), rominfo[6], null, null, false, null, rominfo[3], null, + rominfo[4], null, null, rominfo[8], rominfo[1], null, null, false, null, null, sysid, null, srcid, null); // Now process and add the rom string key = ""; @@ -844,24 +885,7 @@ namespace SabreTools.Helper if (empty) { string tempgame = String.Join("\\", parent); - - Rom rom = new Rom - { - Type = ItemType.Rom, - Name = "null", - Machine = new Machine - { - Name = tempgame, - Description = tempgame, - }, - HashData = new Hash - { - Size = -1, - CRC = "null", - MD5 = "null", - SHA1 = "null", - }, - }; + Rom rom = new Rom("null", tempgame); // Now process and add the rom ParseAddHelper(rom, ref datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, clean, logger, out key); @@ -1238,23 +1262,7 @@ namespace SabreTools.Helper } } - Rom relrom = new Rom - { - Machine = new Machine - { - Name = tempname, - Description = gamedesc, - RomOf = romof, - CloneOf = cloneof, - SampleOf = sampleof, - }, - Name = subreader.GetAttribute("name"), - Type = ItemType.Release, - Region = subreader.GetAttribute("region"), - Language = subreader.GetAttribute("language"), - Default = defaultrel, - Metadata = new SourceMetadata { SystemID = sysid, System = filename, SourceID = srcid }, - }; + DatItem relrom = new Release(subreader.GetAttribute("name"), subreader.GetAttribute("region"), subreader.GetAttribute("language"), date, defaultrel); // Now process and add the rom ParseAddHelper(relrom, ref datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, clean, logger, out key); @@ -1275,22 +1283,8 @@ namespace SabreTools.Helper } } - Rom biosrom = new Rom - { - Machine = new Machine - { - Name = tempname, - Description = gamedesc, - RomOf = romof, - CloneOf = cloneof, - SampleOf = sampleof, - }, - Name = subreader.GetAttribute("name"), - Type = ItemType.BiosSet, - Description = subreader.GetAttribute("description"), - Default = defaultbios, - Metadata = new SourceMetadata { SystemID = sysid, System = filename, SourceID = srcid }, - }; + DatItem biosrom = new BiosSet(subreader.GetAttribute("name"), subreader.GetAttribute("description"), defaultbios, + tempname, null, gamedesc, null, null, romof, cloneof, sampleof, null, false, null, null, sysid, filename, srcid, null); // Now process and add the rom ParseAddHelper(biosrom, ref datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, clean, logger, out key); @@ -1298,21 +1292,17 @@ namespace SabreTools.Helper subreader.Read(); break; case "archive": + DatItem archiverom = new Archive(subreader.GetAttribute("name"), tempname, null, gamedesc, null, null, + romof, cloneof, sampleof, null, false, null, null, sysid, filename, srcid, null); + + // Now process and add the rom + ParseAddHelper(archiverom, ref datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, clean, logger, out key); + + subreader.Read(); + break; case "sample": - Rom samplerom = new Rom - { - Machine = new Machine - { - Name = tempname, - Description = gamedesc, - RomOf = romof, - CloneOf = cloneof, - SampleOf = sampleof, - }, - Name = subreader.GetAttribute("name"), - Type = (subreader.Name == "sample" ? ItemType.Sample : ItemType.Archive), - Metadata = new SourceMetadata { SystemID = sysid, System = filename, SourceID = srcid }, - }; + DatItem samplerom = new Sample(subreader.GetAttribute("name"), tempname, null, gamedesc, null, null, + romof, cloneof, sampleof, null, false, null, null, sysid, filename, srcid, null); // Now process and add the rom ParseAddHelper(samplerom, ref datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, clean, logger, out key); @@ -1362,8 +1352,13 @@ namespace SabreTools.Helper if (subreader.GetAttribute("loadflag") == "continue" || subreader.GetAttribute("loadflag") == "ignore") { int index = datdata.Files[key].Count() - 1; - Rom lastrom = datdata.Files[key][index]; - lastrom.HashData.Size += size; + DatItem lastrom = datdata.Files[key][index]; + if (lastrom.Type == ItemType.Rom) + { + Hash temphash = ((Rom)lastrom).HashData; + temphash.Size += size; + ((Rom)lastrom).HashData = temphash; + } datdata.Files[key].RemoveAt(index); datdata.Files[key].Add(lastrom); subreader.Read(); @@ -1376,29 +1371,22 @@ namespace SabreTools.Helper tempname = Style.CleanGameName(tempname.Split(Path.DirectorySeparatorChar)); } - Rom inrom = new Rom + DatItem inrom; + switch (subreader.Name.ToLowerInvariant()) { - Machine = new Machine - { - Name = tempname, - Description = gamedesc, - RomOf = romof, - CloneOf = cloneof, - SampleOf = sampleof, - }, - Name = subreader.GetAttribute("name"), - Type = (subreader.Name.ToLowerInvariant() == "disk" ? ItemType.Disk : ItemType.Rom), - HashData = new Hash - { - Size = size, - CRC = subreader.GetAttribute("crc")?.ToLowerInvariant(), - MD5 = subreader.GetAttribute("md5")?.ToLowerInvariant(), - SHA1 = subreader.GetAttribute("sha1")?.ToLowerInvariant(), - }, - Nodump = isnodump, - Date = date, - Metadata = new SourceMetadata { SystemID = sysid, System = filename, SourceID = srcid }, - }; + case "disk": + inrom = new Disk(subreader.GetAttribute("name"), subreader.GetAttribute("md5")?.ToLowerInvariant(), + subreader.GetAttribute("sha1")?.ToLowerInvariant(), isnodump, tempname, null, gamedesc, null, null, + romof, cloneof, sampleof, null, false, null, null, sysid, filename, srcid, null); + break; + case "rom": + default: + inrom = new Rom(subreader.GetAttribute("name"), size, subreader.GetAttribute("crc")?.ToLowerInvariant(), + subreader.GetAttribute("md5")?.ToLowerInvariant(), subreader.GetAttribute("sha1")?.ToLowerInvariant(), isnodump, + date, tempname, null, gamedesc, null, null, romof, cloneof, sampleof, null, false, null, null, sysid, filename, + srcid, null); + break; + } // Now process and add the rom ParseAddHelper(inrom, ref datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, clean, logger, out key); @@ -1417,23 +1405,7 @@ namespace SabreTools.Helper { tempname = (parent.Count > 0 ? String.Join("\\", parent) + Path.DirectorySeparatorChar : "") + tempname; - Rom inrom = new Rom - { - Type = ItemType.Rom, - Name = "null", - Machine = new Machine - { - Name = tempname, - Description = tempname, - }, - HashData = new Hash - { - Size = -1, - CRC = "null", - MD5 = "null", - SHA1 = "null", - } - }; + Rom inrom = new Rom("null", tempname); // Now process and add the rom ParseAddHelper(inrom, ref datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, clean, logger, out key); @@ -1525,8 +1497,13 @@ namespace SabreTools.Helper if (xtr.GetAttribute("loadflag") == "continue" || xtr.GetAttribute("loadflag") == "ignore") { int index = datdata.Files[key].Count() - 1; - Rom lastrom = datdata.Files[key][index]; - lastrom.HashData.Size += size; + DatItem lastrom = datdata.Files[key][index]; + if (lastrom.Type == ItemType.Rom) + { + Hash temphash = ((Rom)lastrom).HashData; + temphash.Size += size; + ((Rom)lastrom).HashData = temphash; + } datdata.Files[key].RemoveAt(index); datdata.Files[key].Add(lastrom); continue; @@ -1545,25 +1522,22 @@ namespace SabreTools.Helper } } - Rom rom = new Rom + DatItem rom; + switch (xtr.GetAttribute("type").ToLowerInvariant()) { - Machine = new Machine - { - Name = tempname, - }, - Name = xtr.GetAttribute("name"), - Type = (xtr.GetAttribute("type").ToLowerInvariant() == "disk" ? ItemType.Disk : ItemType.Rom), - HashData = new Hash - { - Size = size, - CRC = xtr.GetAttribute("crc")?.ToLowerInvariant(), - MD5 = xtr.GetAttribute("md5")?.ToLowerInvariant(), - SHA1 = xtr.GetAttribute("sha1")?.ToLowerInvariant(), - }, - Nodump = isnodump, - Date = date, - Metadata = new SourceMetadata { SystemID = sysid, System = filename, SourceID = srcid }, - }; + case "disk": + rom = new Disk(xtr.GetAttribute("name"), xtr.GetAttribute("md5")?.ToLowerInvariant(), + xtr.GetAttribute("sha1")?.ToLowerInvariant(), isnodump, tempname, null, tempname, null, null, + null, null, null, null, false, null, null, sysid, filename, srcid, null); + break; + case "rom": + default: + rom = new Rom(xtr.GetAttribute("name"), size, xtr.GetAttribute("crc")?.ToLowerInvariant(), + xtr.GetAttribute("md5")?.ToLowerInvariant(), xtr.GetAttribute("sha1")?.ToLowerInvariant(), isnodump, + date, tempname, null, tempname, null, null, null, null, null, null, false, null, null, sysid, filename, + srcid, null); + break; + } // Now process and add the rom ParseAddHelper(rom, ref datdata, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, clean, logger, out key); @@ -1584,7 +1558,7 @@ namespace SabreTools.Helper /// /// Add a rom to the Dat after checking /// - /// Rom data to check against + /// Item data to check against /// Dat to add information to, if possible /// Name of the game to match (can use asterisk-partials) /// Name of the rom to match (can use asterisk-partials) @@ -1600,96 +1574,145 @@ namespace SabreTools.Helper /// True if all games should be replaced by '!', false otherwise /// String representing root directory to compare against for length calculation /// Logger object for console and/or file output - private static void ParseAddHelper(Rom rom, ref Dat datdata, string gamename, string romname, string romtype, long sgt, long slt, + private static void ParseAddHelper(DatItem item, ref Dat datdata, string gamename, string romname, string romtype, long sgt, long slt, long seq, string crc, string md5, string sha1, bool? nodump, bool trim, bool single, string root, bool clean, Logger logger, out string key) { key = ""; // If there's no name in the rom, we log and skip it - if (String.IsNullOrEmpty(rom.Name)) + if (String.IsNullOrEmpty(item.Name)) { logger.Warning("Rom with no name found! Skipping..."); return; } // If we're in cleaning mode, sanitize the game name - rom.Machine.Name = (clean ? Style.CleanGameName(rom.Machine.Name) : rom.Machine.Name); + item.MachineName = (clean ? Style.CleanGameName(item.MachineName) : item.MachineName); - // Sanitize the hashes from null, hex sizes, and "true blank" strings - rom.HashData.CRC = Style.CleanHashData(rom.HashData.CRC, Constants.CRCLength); - rom.HashData.MD5 = Style.CleanHashData(rom.HashData.MD5, Constants.MD5Length); - rom.HashData.SHA1 = Style.CleanHashData(rom.HashData.SHA1, Constants.SHA1Length); - - // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info - if (rom.Type == ItemType.Rom - && (rom.HashData.Size == 0 || rom.HashData.Size == -1) - && ((rom.HashData.CRC == Constants.CRCZero || rom.HashData.CRC == "") - || rom.HashData.MD5 == Constants.MD5Zero - || rom.HashData.SHA1 == Constants.SHA1Zero)) + // If we have a Rom or a Disk, clean the hash data + if (item.Type == ItemType.Rom) { - rom.HashData.Size = Constants.SizeZero; - rom.HashData.CRC = Constants.CRCZero; - rom.HashData.MD5 = Constants.MD5Zero; - rom.HashData.SHA1 = Constants.SHA1Zero; + Rom itemRom = (Rom)item; + + // Sanitize the hashes from null, hex sizes, and "true blank" strings + Hash tempItemHash = itemRom.HashData; + tempItemHash.CRC = Style.CleanHashData(itemRom.HashData.CRC, Constants.CRCLength); + tempItemHash.MD5 = Style.CleanHashData(itemRom.HashData.MD5, Constants.MD5Length); + tempItemHash.SHA1 = Style.CleanHashData(itemRom.HashData.SHA1, Constants.SHA1Length); + + // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info + if ((tempItemHash.Size == 0 || tempItemHash.Size == -1) + && ((tempItemHash.CRC == Constants.CRCZero || tempItemHash.CRC == "") + || tempItemHash.MD5 == Constants.MD5Zero + || tempItemHash.SHA1 == Constants.SHA1Zero)) + { + tempItemHash.Size = Constants.SizeZero; + tempItemHash.CRC = Constants.CRCZero; + tempItemHash.MD5 = Constants.MD5Zero; + tempItemHash.SHA1 = Constants.SHA1Zero; + } + // If the file has no size and it's not the above case, skip and log + else if (itemRom.Type == ItemType.Rom && (tempItemHash.Size == 0 || tempItemHash.Size == -1)) + { + logger.Warning("Incomplete entry for \"" + itemRom.Name + "\" will be output as nodump"); + itemRom.Nodump = true; + } + + itemRom.HashData = tempItemHash; + item = itemRom; } - // If the file has no size and it's not the above case, skip and log - else if (rom.Type == ItemType.Rom && (rom.HashData.Size == 0 || rom.HashData.Size == -1)) + else if (item.Type == ItemType.Disk) { - logger.Warning("Incomplete entry for \"" + rom.Name + "\" will be output as nodump"); - rom.Nodump = true; + Disk itemDisk = (Disk)item; + + // Sanitize the hashes from null, hex sizes, and "true blank" strings + Hash tempItemHash = itemDisk.HashData; + tempItemHash.MD5 = Style.CleanHashData(itemDisk.HashData.MD5, Constants.MD5Length); + tempItemHash.SHA1 = Style.CleanHashData(itemDisk.HashData.SHA1, Constants.SHA1Length); + + itemDisk.HashData = tempItemHash; + item = itemDisk; } // If the rom passes the filter, include it - if (RomTools.Filter(rom, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, logger)) + if (DatItem.Filter(item, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, nodump, logger)) { // If we are in single game mode, rename all games if (single) { - rom.Machine.Name = "!"; + item.MachineName = "!"; } // If we are in NTFS trim mode, trim the game name if (trim) { // Windows max name length is 260 - int usableLength = 260 - rom.Machine.Name.Length - root.Length; - if (rom.Name.Length > usableLength) + int usableLength = 260 - item.MachineName.Length - root.Length; + if (item.Name.Length > usableLength) { - string ext = Path.GetExtension(rom.Name); - rom.Name = rom.Name.Substring(0, usableLength - ext.Length); - rom.Name += ext; + string ext = Path.GetExtension(item.Name); + item.Name = item.Name.Substring(0, usableLength - ext.Length); + item.Name += ext; } } // If we have a disk, make sure that the value for size is -1 - if (rom.Type == ItemType.Disk) + if (item.Type == ItemType.Disk) { - logger.Log("Disk found: \"" + rom.Name + "\""); - rom.HashData.Size = -1; + logger.Log("Disk found: \"" + item.Name + "\""); + Hash tempDiskHash = ((Disk)item).HashData; + tempDiskHash.Size = -1; + ((Disk)item).HashData = tempDiskHash; } lock (datdata.Files) { - key = rom.HashData.Size + "-" + rom.HashData.CRC; + // Get the key and add statistical data + switch (item.Type) + { + case ItemType.Archive: + case ItemType.BiosSet: + case ItemType.Release: + case ItemType.Sample: + key = item.Type.ToString(); + break; + case ItemType.Disk: + key = ((Disk)item).HashData.Size + "-" + ((Disk)item).HashData.CRC; + + // Add statistical data + datdata.DiskCount += 1; + datdata.TotalSize += (((Disk)item).Nodump ? 0 : ((Disk)item).HashData.Size); + datdata.MD5Count += (String.IsNullOrEmpty(((Disk)item).HashData.MD5) ? 0 : 1); + datdata.SHA1Count += (String.IsNullOrEmpty(((Disk)item).HashData.SHA1) ? 0 : 1); + datdata.NodumpCount += (((Disk)item).Nodump ? 1 : 0); + break; + case ItemType.Rom: + key = ((Rom)item).HashData.Size + "-" + ((Rom)item).HashData.CRC; + + // Add statistical data + datdata.RomCount += 1; + datdata.TotalSize += (((Rom)item).Nodump ? 0 : ((Rom)item).HashData.Size); + datdata.CRCCount += (String.IsNullOrEmpty(((Rom)item).HashData.CRC) ? 0 : 1); + datdata.MD5Count += (String.IsNullOrEmpty(((Rom)item).HashData.MD5) ? 0 : 1); + datdata.SHA1Count += (String.IsNullOrEmpty(((Rom)item).HashData.SHA1) ? 0 : 1); + datdata.NodumpCount += (((Rom)item).Nodump ? 1 : 0); + break; + default: + key = "default"; + break; + } + + // Add the item to the DAT if (datdata.Files.ContainsKey(key)) { - datdata.Files[key].Add(rom); + datdata.Files[key].Add(item); } else { - List newvalue = new List(); - newvalue.Add(rom); + List newvalue = new List(); + newvalue.Add(item); datdata.Files.Add(key, newvalue); } - - // Add statistical data - datdata.RomCount += (rom.Type == ItemType.Rom ? 1 : 0); - datdata.DiskCount += (rom.Type == ItemType.Disk ? 1 : 0); - datdata.TotalSize += (rom.Nodump ? 0 : rom.HashData.Size); - datdata.CRCCount += (String.IsNullOrEmpty(rom.HashData.CRC) ? 0 : 1); - datdata.MD5Count += (String.IsNullOrEmpty(rom.HashData.MD5) ? 0 : 1); - datdata.SHA1Count += (String.IsNullOrEmpty(rom.HashData.SHA1) ? 0 : 1); - datdata.NodumpCount += (rom.Nodump ? 1 : 0); } } } @@ -1707,9 +1730,9 @@ namespace SabreTools.Helper /// Logger object for file and console output /// True if the number of hashes counted is to be output (default), false otherwise /// SortedDictionary bucketed by game name - public static SortedDictionary> BucketByGame(List list, bool mergeroms, bool norename, Logger logger, bool output = true) + public static SortedDictionary> BucketByGame(List list, bool mergeroms, bool norename, Logger logger, bool output = true) { - Dictionary> dict = new Dictionary>(); + Dictionary> dict = new Dictionary>(); dict.Add("key", list); return BucketByGame(dict, mergeroms, norename, logger, output); } @@ -1723,11 +1746,11 @@ namespace SabreTools.Helper /// Logger object for file and console output /// True if the number of hashes counted is to be output (default), false otherwise /// SortedDictionary bucketed by game name - public static SortedDictionary> BucketByGame(IDictionary> dict, bool mergeroms, bool norename, Logger logger, bool output = true) + public static SortedDictionary> BucketByGame(IDictionary> dict, bool mergeroms, bool norename, Logger logger, bool output = true) { logger.User("Organizing " + (mergeroms ? "and merging " : "") + "roms for output"); - SortedDictionary> sortable = new SortedDictionary>(); + SortedDictionary> sortable = new SortedDictionary>(); long count = 0; // If we have a null dict or an empty one, output a new dictionary @@ -1739,29 +1762,29 @@ namespace SabreTools.Helper // Process each all of the roms foreach (string key in dict.Keys) { - List roms = dict[key]; + List roms = dict[key]; if (mergeroms) { - roms = RomTools.Merge(roms, logger); + roms = DatItem.Merge(roms, logger); } foreach (Rom rom in roms) { count++; string newkey = (norename ? "" - : rom.Metadata.SystemID.ToString().PadLeft(10, '0') + : rom.SystemID.ToString().PadLeft(10, '0') + "-" - + rom.Metadata.SourceID.ToString().PadLeft(10, '0') + "-") - + (String.IsNullOrEmpty(rom.Machine.Name) + + rom.SourceID.ToString().PadLeft(10, '0') + "-") + + (String.IsNullOrEmpty(rom.MachineName) ? "Default" - : rom.Machine.Name.ToLowerInvariant()); + : rom.MachineName.ToLowerInvariant()); if (sortable.ContainsKey(newkey)) { sortable[newkey].Add(rom); } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); sortable.Add(newkey, temp); } @@ -1772,8 +1795,8 @@ namespace SabreTools.Helper List keys = sortable.Keys.ToList(); foreach (string key in keys) { - List sortedlist = sortable[key]; - RomTools.Sort(ref sortedlist, norename); + List sortedlist = sortable[key]; + DatItem.Sort(ref sortedlist, norename); sortable[key] = sortedlist; } @@ -1786,86 +1809,6 @@ namespace SabreTools.Helper return sortable; } - /// - /// Take an arbitrarily ordered List and return a Dictionary sorted by size and hash - /// - /// Input unsorted list - /// True if roms should be deduped, false otherwise - /// True if games should only be compared on game and file name, false if system and source are counted - /// Logger object for file and console output - /// True if the number of hashes counted is to be output (default), false otherwise - /// SortedDictionary bucketed by size and hash - public static SortedDictionary> BucketByHashSize(List list, bool mergeroms, bool norename, Logger logger, bool output = true) - { - Dictionary> dict = new Dictionary>(); - dict.Add("key", list); - return BucketByHashSize(dict, mergeroms, norename, logger, output); - } - - /// - /// Take an arbitrarily bucketed Dictionary and return one sorted by size and hash - /// - /// Input unsorted dictionary - /// True if roms should be deduped, false otherwise - /// True if games should only be compared on game and file name, false if system and source are counted - /// Logger object for file and console output - /// True if the number of hashes counted is to be output (default), false otherwise - /// SortedDictionary bucketed by size and hash - public static SortedDictionary> BucketByHashSize(IDictionary> dict, bool mergeroms, bool norename, Logger logger, bool output = true) - { - SortedDictionary> sortable = new SortedDictionary>(); - long count = 0; - - // If we have a null dict or an empty one, output a new dictionary - if (dict == null || dict.Count == 0) - { - return sortable; - } - - // Process each all of the roms - foreach (List roms in dict.Values) - { - List newroms = roms; - if (mergeroms) - { - newroms = RomTools.Merge(newroms, logger); - } - - foreach (Rom rom in newroms) - { - count++; - string key = rom.HashData.Size + "-" + rom.HashData.CRC; - if (sortable.ContainsKey(key)) - { - sortable[key].Add(rom); - } - else - { - List temp = new List(); - temp.Add(rom); - sortable.Add(key, temp); - } - } - } - - // Now go through and sort all of the lists - List keys = sortable.Keys.ToList(); - foreach (string key in keys) - { - List sortedlist = sortable[key]; - RomTools.Sort(ref sortedlist, norename); - sortable[key] = sortedlist; - } - - // Output the count if told to - if (output) - { - logger.User("A total of " + count + " file hashes will be written out to file"); - } - - return sortable; - } - #endregion #region Converting and Updating @@ -2070,7 +2013,7 @@ namespace SabreTools.Helper datHeaders[i] = new Dat { OutputFormat = (inputDat.OutputFormat != 0 ? inputDat.OutputFormat: 0), - Files = new Dictionary>(), + Files = new Dictionary>(), MergeRoms = inputDat.MergeRoms, }; @@ -2082,7 +2025,7 @@ namespace SabreTools.Helper logger.User("Populating internal DAT"); userData = (Dat)inputDat.CloneHeader(); - userData.Files = new Dictionary>(); + userData.Files = new Dictionary>(); for (int i = 0; i < inputs.Count; i++) { List keys = datHeaders[i].Files.Keys.ToList(); @@ -2132,7 +2075,7 @@ namespace SabreTools.Helper outerDiffData.FileName += post; outerDiffData.Name += post; outerDiffData.Description += post; - outerDiffData.Files = new Dictionary>(); + outerDiffData.Files = new Dictionary>(); } // Have External dupes @@ -2143,7 +2086,7 @@ namespace SabreTools.Helper dupeData.FileName += post; dupeData.Name += post; dupeData.Description += post; - dupeData.Files = new Dictionary>(); + dupeData.Files = new Dictionary>(); } // Create a list of DatData objects representing individual output files @@ -2161,7 +2104,7 @@ namespace SabreTools.Helper diffData.FileName += innerpost; diffData.Name += innerpost; diffData.Description += innerpost; - diffData.Files = new Dictionary>(); + diffData.Files = new Dictionary>(); outDatsArray[j] = diffData; }); @@ -2175,7 +2118,7 @@ namespace SabreTools.Helper List keys = userData.Files.Keys.ToList(); foreach (string key in keys) { - List roms = RomTools.Merge(userData.Files[key], logger); + List roms = DatItem.Merge(userData.Files[key], logger); if (roms != null && roms.Count > 0) { @@ -2189,15 +2132,15 @@ namespace SabreTools.Helper // Individual DATs that are output if ((diff & DiffMode.Individuals) != 0) { - if (outDats[rom.Metadata.SystemID].Files.ContainsKey(key)) + if (outDats[rom.SystemID].Files.ContainsKey(key)) { - outDats[rom.Metadata.SystemID].Files[key].Add(rom); + outDats[rom.SystemID].Files[key].Add(rom); } else { - List tl = new List(); + List tl = new List(); tl.Add(rom); - outDats[rom.Metadata.SystemID].Files.Add(key, tl); + outDats[rom.SystemID].Files.Add(key, tl); } } @@ -2205,7 +2148,7 @@ namespace SabreTools.Helper if ((diff & DiffMode.NoDupes) != 0) { Rom newrom = rom; - newrom.Machine.Name += " (" + Path.GetFileNameWithoutExtension(inputs[newrom.Metadata.SystemID].Split('¬')[0]) + ")"; + newrom.MachineName += " (" + Path.GetFileNameWithoutExtension(inputs[newrom.SystemID].Split('¬')[0]) + ")"; if (outerDiffData.Files.ContainsKey(key)) { @@ -2213,7 +2156,7 @@ namespace SabreTools.Helper } else { - List tl = new List(); + List tl = new List(); tl.Add(rom); outerDiffData.Files.Add(key, tl); } @@ -2227,7 +2170,7 @@ namespace SabreTools.Helper if (rom.Dupe >= DupeType.ExternalHash) { Rom newrom = rom; - newrom.Machine.Name += " (" + Path.GetFileNameWithoutExtension(inputs[newrom.Metadata.SystemID].Split('¬')[0]) + ")"; + newrom.MachineName += " (" + Path.GetFileNameWithoutExtension(inputs[newrom.SystemID].Split('¬')[0]) + ")"; if (dupeData.Files.ContainsKey(key)) { @@ -2235,7 +2178,7 @@ namespace SabreTools.Helper } else { - List tl = new List(); + List tl = new List(); tl.Add(rom); dupeData.Files.Add(key, tl); } @@ -2320,7 +2263,7 @@ namespace SabreTools.Helper diffData.Name += post; diffData.Description += post; } - diffData.Files = new Dictionary>(); + diffData.Files = new Dictionary>(); outDatsArray[j] = diffData; }); @@ -2335,21 +2278,21 @@ namespace SabreTools.Helper foreach (string key in keys) { - List roms = RomTools.Merge(userData.Files[key], logger); + List< DatItem> roms = DatItem.Merge(userData.Files[key], logger); if (roms != null && roms.Count > 0) { foreach (Rom rom in roms) { - if (outDats[rom.Metadata.SystemID].Files.ContainsKey(key)) + if (outDats[rom.SystemID].Files.ContainsKey(key)) { - outDats[rom.Metadata.SystemID].Files[key].Add(rom); + outDats[rom.SystemID].Files[key].Add(rom); } else { - List tl = new List(); + List tl = new List(); tl.Add(rom); - outDats[rom.Metadata.SystemID].Files.Add(key, tl); + outDats[rom.SystemID].Files.Add(key, tl); } } } @@ -2397,18 +2340,18 @@ namespace SabreTools.Helper List keys = userData.Files.Keys.ToList(); foreach (string key in keys) { - List newroms = new List(); - foreach (Rom rom in userData.Files[key]) + List newroms = new List(); + foreach (DatItem rom in userData.Files[key]) { - Rom newrom = rom; - string filename = inputs[newrom.Metadata.SystemID].Split('¬')[0]; - string rootpath = inputs[newrom.Metadata.SystemID].Split('¬')[1]; + DatItem newrom = rom; + string filename = inputs[newrom.SystemID].Split('¬')[0]; + string rootpath = inputs[newrom.SystemID].Split('¬')[1]; rootpath += (rootpath == "" ? "" : Path.DirectorySeparatorChar.ToString()); filename = filename.Remove(0, rootpath.Length); - newrom.Machine.Name = Path.GetDirectoryName(filename) + Path.DirectorySeparatorChar + newrom.MachineName = Path.GetDirectoryName(filename) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(filename) + Path.DirectorySeparatorChar - + newrom.Machine.Name; + + newrom.MachineName; newroms.Add(newrom); } userData.Files[key] = newroms; @@ -2508,7 +2451,7 @@ namespace SabreTools.Helper } // Bucket roms by game name and optionally dedupe - SortedDictionary> sortable = BucketByGame(datdata.Files, datdata.MergeRoms, norename, logger); + SortedDictionary> sortable = BucketByGame(datdata.Files, datdata.MergeRoms, norename, logger); // Get the outfile name Dictionary outfiles = Style.CreateOutfileNames(outDir, datdata, overwrite); @@ -2537,53 +2480,59 @@ namespace SabreTools.Helper foreach (string key in keys) { - List roms = sortable[key]; + List roms = sortable[key]; for (int index = 0; index < roms.Count; index++) { - Rom rom = roms[index]; + DatItem rom = roms[index]; // There are apparently times when a null rom can skip by, skip them - if (rom.Name == null || rom.Machine.Name == null) + if (rom.Name == null || rom.MachineName == null) { logger.Warning("Null rom found!"); continue; } - List newsplit = rom.Machine.Name.Split('\\').ToList(); + List newsplit = rom.MachineName.Split('\\').ToList(); // If we have a different game and we're not at the start of the list, output the end of last item - if (lastgame != null && lastgame.ToLowerInvariant() != rom.Machine.Name.ToLowerInvariant()) + if (lastgame != null && lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant()) { depth = WriteEndGame(sw, outputFormat, rom, splitpath, newsplit, lastgame, depth, out last, logger); } // If we have a new game, output the beginning of the new item - if (lastgame == null || lastgame.ToLowerInvariant() != rom.Machine.Name.ToLowerInvariant()) + if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant()) { depth = WriteStartGame(sw, outputFormat, rom, newsplit, lastgame, depth, last, logger); } // If we have a "null" game (created by DATFromDir or something similar), log it to file - if (rom.HashData.Size == -1 && rom.HashData.CRC == "null" && rom.HashData.MD5 == "null" && rom.HashData.SHA1 == "null") + if (rom.Type == ItemType.Rom + && ((Rom)rom).HashData.Size == -1 + && ((Rom)rom).HashData.CRC == "null" + && ((Rom)rom).HashData.MD5 == "null" + && ((Rom)rom).HashData.SHA1 == "null") { - logger.Log("Empty folder found: " + rom.Machine.Name); + logger.Log("Empty folder found: " + rom.MachineName); // If we're in a mode that doesn't allow for actual empty folders, add the blank info if (outputFormat != OutputFormat.SabreDat && outputFormat != OutputFormat.MissFile) { rom.Name = (rom.Name == "null" ? "-" : rom.Name); - rom.HashData.Size = Constants.SizeZero; - rom.HashData.CRC = Constants.CRCZero; - rom.HashData.MD5 = Constants.MD5Zero; - rom.HashData.SHA1 = Constants.SHA1Zero; + Hash tempHash = ((Rom)rom).HashData; + tempHash.Size = Constants.SizeZero; + tempHash.CRC = Constants.CRCZero; + tempHash.MD5 = Constants.MD5Zero; + tempHash.SHA1 = Constants.SHA1Zero; + ((Rom)rom).HashData = tempHash; } // Otherwise, set the new path and such, write out, and continue else { splitpath = newsplit; - lastgame = rom.Machine.Name; + lastgame = rom.MachineName; continue; } } @@ -2593,7 +2542,7 @@ namespace SabreTools.Helper // Set the new data to compare against splitpath = newsplit; - lastgame = rom.Machine.Name; + lastgame = rom.MachineName; } } @@ -2758,26 +2707,26 @@ namespace SabreTools.Helper /// Last known depth to cycle back from (SabreDAT only) /// Logger object for file and console output /// The new depth of the tag - public static int WriteStartGame(StreamWriter sw, OutputFormat outputFormat, Rom rom, List newsplit, string lastgame, int depth, int last, Logger logger) + public static int WriteStartGame(StreamWriter sw, OutputFormat outputFormat, DatItem rom, List newsplit, string lastgame, int depth, int last, Logger logger) { try { // No game should start with a path separator - if (rom.Machine.Name.StartsWith(Path.DirectorySeparatorChar.ToString())) + if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString())) { - rom.Machine.Name = rom.Machine.Name.Substring(1); + rom.MachineName = rom.MachineName.Substring(1); } string state = ""; switch (outputFormat) { case OutputFormat.ClrMamePro: - state += "game (\n\tname \"" + rom.Machine.Name + "\"\n" + - (String.IsNullOrEmpty(rom.Machine.RomOf) ? "" : "\tromof \"" + rom.Machine.RomOf + "\"\n") + - (String.IsNullOrEmpty(rom.Machine.CloneOf) ? "" : "\tcloneof \"" + rom.Machine.CloneOf + "\"\n") + - "\tdescription \"" + (String.IsNullOrEmpty(rom.Machine.Description) ? rom.Machine.Name : rom.Machine.Description) + "\"\n" + - (String.IsNullOrEmpty(rom.Machine.Year) ? "" : "\tyear " + rom.Machine.Year + "\n") + - (String.IsNullOrEmpty(rom.Machine.Manufacturer) ? "" : "\tmanufacturer \"" + rom.Machine.Manufacturer + "\"\n"); + state += "game (\n\tname \"" + rom.MachineName + "\"\n" + + (String.IsNullOrEmpty(rom.RomOf) ? "" : "\tromof \"" + rom.RomOf + "\"\n") + + (String.IsNullOrEmpty(rom.CloneOf) ? "" : "\tcloneof \"" + rom.CloneOf + "\"\n") + + "\tdescription \"" + (String.IsNullOrEmpty(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription) + "\"\n" + + (String.IsNullOrEmpty(rom.Year) ? "" : "\tyear " + rom.Year + "\n") + + (String.IsNullOrEmpty(rom.Manufacturer) ? "" : "\tmanufacturer \"" + rom.Manufacturer + "\"\n"); break; case OutputFormat.SabreDat: @@ -2793,16 +2742,16 @@ namespace SabreTools.Helper depth = depth - (last == -1 ? 0 : last) + newsplit.Count; break; case OutputFormat.Xml: - state += "\t\n" + - (String.IsNullOrEmpty(rom.Machine.Comment) ? "" : "\t\t" + HttpUtility.HtmlEncode(rom.Machine.Comment) + "\n") + - "\t\t" + HttpUtility.HtmlEncode((String.IsNullOrEmpty(rom.Machine.Description) ? rom.Machine.Name : rom.Machine.Description)) + "\n" + - (String.IsNullOrEmpty(rom.Machine.Year) ? "" : "\t\t" + HttpUtility.HtmlEncode(rom.Machine.Year) + "\n") + - (String.IsNullOrEmpty(rom.Machine.Manufacturer) ? "" : "\t\t" + HttpUtility.HtmlEncode(rom.Machine.Manufacturer) + "\n"); + (String.IsNullOrEmpty(rom.Comment) ? "" : "\t\t" + HttpUtility.HtmlEncode(rom.Comment) + "\n") + + "\t\t" + HttpUtility.HtmlEncode((String.IsNullOrEmpty(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription)) + "\n" + + (String.IsNullOrEmpty(rom.Year) ? "" : "\t\t" + HttpUtility.HtmlEncode(rom.Year) + "\n") + + (String.IsNullOrEmpty(rom.Manufacturer) ? "" : "\t\t" + HttpUtility.HtmlEncode(rom.Manufacturer) + "\n"); break; } @@ -2831,7 +2780,7 @@ namespace SabreTools.Helper /// Last known depth to cycle back from (SabreDAT only) /// Logger object for file and console output /// The new depth of the tag - public static int WriteEndGame(StreamWriter sw, OutputFormat outputFormat, Rom rom, List splitpath, List newsplit, string lastgame, int depth, out int last, Logger logger) + public static int WriteEndGame(StreamWriter sw, OutputFormat outputFormat, DatItem rom, List splitpath, List newsplit, string lastgame, int depth, out int last, Logger logger) { last = 0; @@ -2842,7 +2791,7 @@ namespace SabreTools.Helper switch (outputFormat) { case OutputFormat.ClrMamePro: - state += (String.IsNullOrEmpty(rom.Machine.SampleOf) ? "" : "\tsampleof \"" + rom.Machine.SampleOf + "\"\n") + ")\n"; + state += (String.IsNullOrEmpty(rom.SampleOf) ? "" : "\tsampleof \"" + rom.SampleOf + "\"\n") + ")\n"; break; case OutputFormat.SabreDat: if (splitpath != null) @@ -2903,10 +2852,12 @@ namespace SabreTools.Helper /// Logger object for file and console output /// True if blank roms should be skipped on output, false otherwise (default) /// True if the data was written, false on error - public static bool WriteRomData(StreamWriter sw, OutputFormat outputFormat, Rom rom, string lastgame, Dat datdata, int depth, Logger logger, bool ignoreblanks = false) + public static bool WriteRomData(StreamWriter sw, OutputFormat outputFormat, DatItem rom, string lastgame, Dat datdata, int depth, Logger logger, bool ignoreblanks = false) { // If we are in ignore blanks mode AND we have a blank (0-size) rom, skip - if (ignoreblanks && (rom.HashData.Size == 0 || rom.HashData.Size == -1)) + if (ignoreblanks + && (rom.Type == ItemType.Rom + && (((Rom)rom).HashData.Size == 0 || ((Rom)rom).HashData.Size == -1))) { return true; } @@ -2917,66 +2868,171 @@ namespace SabreTools.Helper switch (outputFormat) { case OutputFormat.ClrMamePro: - state += "\t" + rom.Type.ToString().ToLowerInvariant() + " ( name \"" + rom.Name + "\"" + - (rom.HashData.Size != -1 ? " size " + rom.HashData.Size : "") + - (!String.IsNullOrEmpty(rom.HashData.CRC) ? " crc " + rom.HashData.CRC.ToLowerInvariant() : "") + - (!String.IsNullOrEmpty(rom.HashData.MD5) ? " md5 " + rom.HashData.MD5.ToLowerInvariant() : "") + - (!String.IsNullOrEmpty(rom.HashData.SHA1) ? " sha1 " + rom.HashData.SHA1.ToLowerInvariant() : "") + - (!String.IsNullOrEmpty(rom.Date) ? " date \"" + rom.Date + "\"" : "") + - (rom.Nodump ? " flags nodump" : "") + - " )\n"; + switch (rom.Type) + { + case ItemType.Archive: + state += "\tarchive ( name\"" + rom.Name + "\"" + + " )\n"; + break; + case ItemType.BiosSet: + state += "\tbiosset ( name\"" + rom.Name + "\"" + + (!String.IsNullOrEmpty(((BiosSet)rom).Description) ? " description \"" + ((BiosSet)rom).Description + "\"" : "") + + (((BiosSet)rom).Default != null + ? "default " + ((BiosSet)rom).Default.ToString().ToLowerInvariant() + : "") + + " )\n"; + break; + case ItemType.Disk: + state += "\tdisk ( name \"" + rom.Name + "\"" + + (!String.IsNullOrEmpty(((Disk)rom).HashData.MD5) ? " md5 " + ((Disk)rom).HashData.MD5.ToLowerInvariant() : "") + + (!String.IsNullOrEmpty(((Disk)rom).HashData.SHA1) ? " sha1 " + ((Disk)rom).HashData.SHA1.ToLowerInvariant() : "") + + (((Disk)rom).Nodump ? " flags nodump" : "") + + " )\n"; + break; + case ItemType.Release: + state += "\trelease ( name\"" + rom.Name + "\"" + + (!String.IsNullOrEmpty(((Release)rom).Region) ? " region \"" + ((Release)rom).Region + "\"" : "") + + (!String.IsNullOrEmpty(((Release)rom).Language) ? " language \"" + ((Release)rom).Language + "\"" : "") + + (!String.IsNullOrEmpty(((Release)rom).Date) ? " date \"" + ((Release)rom).Date + "\"" : "") + + (((Release)rom).Default != null + ? "default " + ((Release)rom).Default.ToString().ToLowerInvariant() + : "") + + " )\n"; + break; + case ItemType.Rom: + state += "\trom ( name \"" + rom.Name + "\"" + + (((Rom)rom).HashData.Size != -1 ? " size " + ((Rom)rom).HashData.Size : "") + + (!String.IsNullOrEmpty(((Rom)rom).HashData.CRC) ? " crc " + ((Rom)rom).HashData.CRC.ToLowerInvariant() : "") + + (!String.IsNullOrEmpty(((Rom)rom).HashData.MD5) ? " md5 " + ((Rom)rom).HashData.MD5.ToLowerInvariant() : "") + + (!String.IsNullOrEmpty(((Rom)rom).HashData.SHA1) ? " sha1 " + ((Rom)rom).HashData.SHA1.ToLowerInvariant() : "") + + (!String.IsNullOrEmpty(((Rom)rom).Date) ? " date \"" + ((Rom)rom).Date + "\"" : "") + + (((Rom)rom).Nodump ? " flags nodump" : "") + + " )\n"; + break; + case ItemType.Sample: + state += "\tsample ( name\"" + rom.Name + "\"" + + " )\n"; + break; + } + break; case OutputFormat.MissFile: + // Missfile should only output Rom and Disk + if (rom.Type != ItemType.Disk && rom.Type != ItemType.Disk) + { + return true; + } + string pre = datdata.Prefix + (datdata.Quotes ? "\"" : ""); string post = (datdata.Quotes ? "\"" : "") + datdata.Postfix; - // Check for special strings in prefix and postfix - pre = pre - .Replace("%game%", rom.Machine.Name) - .Replace("%name%", rom.Name) - .Replace("%crc%", rom.HashData.CRC) - .Replace("%md5%", rom.HashData.MD5) - .Replace("%sha1%", rom.HashData.SHA1) - .Replace("%size%", rom.HashData.Size.ToString()); - post = post - .Replace("%game%", rom.Machine.Name) - .Replace("%name%", rom.Name) - .Replace("%crc%", rom.HashData.CRC) - .Replace("%md5%", rom.HashData.MD5) - .Replace("%sha1%", rom.HashData.SHA1) - .Replace("%size%", rom.HashData.Size.ToString()); + if (rom.Type == ItemType.Rom) + { + // Check for special strings in prefix and postfix + pre = pre + .Replace("%game%", rom.MachineName) + .Replace("%name%", rom.Name) + .Replace("%crc%", ((Rom)rom).HashData.CRC) + .Replace("%md5%", ((Rom)rom).HashData.MD5) + .Replace("%sha1%", ((Rom)rom).HashData.SHA1) + .Replace("%size%", ((Rom)rom).HashData.Size.ToString()); + post = post + .Replace("%game%", rom.MachineName) + .Replace("%name%", rom.Name) + .Replace("%crc%", ((Rom)rom).HashData.CRC) + .Replace("%md5%", ((Rom)rom).HashData.MD5) + .Replace("%sha1%", ((Rom)rom).HashData.SHA1) + .Replace("%size%", ((Rom)rom).HashData.Size.ToString()); + } + else if (rom.Type == ItemType.Disk) + { + // Check for special strings in prefix and postfix + pre = pre + .Replace("%game%", rom.MachineName) + .Replace("%name%", rom.Name) + .Replace("%md5%", ((Disk)rom).HashData.MD5) + .Replace("%sha1%", ((Disk)rom).HashData.SHA1); + post = post + .Replace("%game%", rom.MachineName) + .Replace("%name%", rom.Name) + .Replace("%md5%", ((Disk)rom).HashData.MD5) + .Replace("%sha1%", ((Disk)rom).HashData.SHA1); + } // If we're in Romba mode, the state is consistent if (datdata.Romba) { - // We can only write out if there's a SHA-1 - if (rom.HashData.SHA1 != "") + if (rom.Type == ItemType.Rom) { - string name = rom.HashData.SHA1.Substring(0, 2) + "/" + rom.HashData.SHA1.Substring(2, 2) + "/" + rom.HashData.SHA1.Substring(4, 2) + "/" + - rom.HashData.SHA1.Substring(6, 2) + "/" + rom.HashData.SHA1 + ".gz"; - state += pre + name + post + "\n"; + // We can only write out if there's a SHA-1 + if (((Rom)rom).HashData.SHA1 != "") + { + string name = ((Rom)rom).HashData.SHA1.Substring(0, 2) + + "/" + ((Rom)rom).HashData.SHA1.Substring(2, 2) + + "/" + ((Rom)rom).HashData.SHA1.Substring(4, 2) + + "/" + ((Rom)rom).HashData.SHA1.Substring(6, 2) + + "/" + ((Rom)rom).HashData.SHA1 + ".gz"; + state += pre + name + post + "\n"; + } + } + else if (rom.Type == ItemType.Disk) + { + // We can only write out if there's a SHA-1 + if (((Disk)rom).HashData.SHA1 != "") + { + string name = ((Disk)rom).HashData.SHA1.Substring(0, 2) + + "/" + ((Disk)rom).HashData.SHA1.Substring(2, 2) + + "/" + ((Disk)rom).HashData.SHA1.Substring(4, 2) + + "/" + ((Disk)rom).HashData.SHA1.Substring(6, 2) + + "/" + ((Disk)rom).HashData.SHA1 + ".gz"; + state += pre + name + post + "\n"; + } } } - // If we're in TSV mode, similarly the state is consistent - else if (datdata.XSV == true) + // If we're in TSV/CSV mode, similarly the state is consistent + else if (datdata.XSV != null) { - string inline = "\"" + datdata.FileName + "\"\t\"" + datdata.Name + "\"\t\"" + datdata.Description + "\"\t\"" + rom.Machine + "\"\t\"" + rom.Machine + "\"\t\"" + - rom.Type.ToString().ToLowerInvariant() + "\"\t\"" + (rom.Type == ItemType.Rom ? rom.Name : "") + "\"\t\"" + (rom.Type == ItemType.Disk ? rom.Name : "") + "\"\t\"" + rom.HashData.Size + "\"\t\"" + - rom.HashData.CRC + "\"\t\"" + rom.HashData.MD5 + "\"\t\"" + rom.HashData.SHA1 + "\"\t" + (rom.Nodump ? "\"Nodump\"" : "\"\""); - state += pre + inline + post + "\n"; - } - // If we're in CSV mode, similarly the state is consistent - else if (datdata.XSV == false) - { - string inline = "\"" + datdata.FileName + "\",\"" + datdata.Name + "\",\"" + datdata.Description + "\",\"" + rom.Machine + "\",\"" + rom.Machine + "\",\"" + - rom.Type.ToString().ToLowerInvariant() + "\",\"" + (rom.Type == ItemType.Rom ? rom.Name : "") + "\",\"" + (rom.Type == ItemType.Disk ? rom.Name : "") + "\",\"" + rom.HashData.Size + "\",\"" + - rom.HashData.CRC + "\",\"" + rom.HashData.MD5 + "\",\"" + rom.HashData.SHA1 + "\"," + (rom.Nodump ? "\"Nodump\"" : "\"\""); - state += pre + inline + post + "\n"; + string separator = (datdata.XSV == true ? "\t" : ","); + + if (rom.Type == ItemType.Rom) + { + string inline = "\"" + datdata.FileName + "\"" + + separator + "\"" + datdata.Name + "\"" + + separator + "\"" + datdata.Description+ "\"" + + separator + "\"" + rom.MachineName + "\"" + + separator + "\"" + rom.MachineDescription + "\"" + + separator + "\"rom\"" + + separator + "\"" + rom.Name + "\"" + + separator + "\"\"" + + separator + "\"" + ((Rom)rom).HashData.Size + "\"" + + separator + "\"" + ((Rom)rom).HashData.CRC + "\"" + + separator + "\"" + ((Rom)rom).HashData.MD5 + "\"" + + separator + "\"" + ((Rom)rom).HashData.SHA1 + "\"" + + separator + (((Rom)rom).Nodump ? "\"Nodump\"" : "\"\""); + state += pre + inline + post + "\n"; + } + else if (rom.Type == ItemType.Disk) + { + string inline = "\"" + datdata.FileName + "\"" + + separator + "\"" + datdata.Name + "\"" + + separator + "\"" + datdata.Description + "\"" + + separator + "\"" + rom.MachineName + "\"" + + separator + "\"" + rom.MachineDescription + "\"" + + separator + "\"disk\"" + + separator + "\"\"" + + separator + "\"" + rom.Name + "\"" + + separator + "\"\"" + + separator + "\"\"" + + separator + "\"" + ((Disk)rom).HashData.MD5 + "\"" + + separator + "\"" + ((Disk)rom).HashData.SHA1 + "\"" + + separator + (((Disk)rom).Nodump ? "\"Nodump\"" : "\"\""); + state += pre + inline + post + "\n"; + } } // Otherwise, use any flags else { - string name = (datdata.UseGame ? rom.Machine.Name : rom.Name); + string name = (datdata.UseGame ? rom.MachineName : rom.Name); if (datdata.RepExt != "" || datdata.RemExt) { if (datdata.RemExt) @@ -2994,13 +3050,13 @@ namespace SabreTools.Helper } if (!datdata.UseGame && datdata.GameName) { - name = Path.Combine(rom.Machine.Name, name); + name = Path.Combine(rom.MachineName, name); } - if (datdata.UseGame && rom.Machine.Name != lastgame) + if (datdata.UseGame && rom.MachineName != lastgame) { state += pre + name + post + "\n"; - lastgame = rom.Machine.Name; + lastgame = rom.MachineName; } else if (!datdata.UseGame) { @@ -3009,22 +3065,52 @@ namespace SabreTools.Helper } break; case OutputFormat.RedumpMD5: - state += rom.HashData.MD5 + " *" + rom.Name + "\n"; + if (rom.Type == ItemType.Rom) + { + state += ((Rom)rom).HashData.MD5 + " *" + rom.Name + "\n"; + } + else if (rom.Type == ItemType.Disk) + { + state += ((Disk)rom).HashData.MD5 + " *" + rom.Name + "\n"; + } break; case OutputFormat.RedumpSFV: - state += rom.Name + " " + rom.HashData.CRC + "\n"; + if (rom.Type == ItemType.Rom) + { + state += rom.Name + " " + ((Rom)rom).HashData.CRC + "\n"; + } break; case OutputFormat.RedumpSHA1: - state += rom.HashData.SHA1 + " *" + rom.Name + "\n"; + if (rom.Type == ItemType.Rom) + { + state += ((Rom)rom).HashData.SHA1 + " *" + rom.Name + "\n"; + } + else if (rom.Type == ItemType.Disk) + { + state += ((Disk)rom).HashData.SHA1 + " *" + rom.Name + "\n"; + } break; case OutputFormat.RomCenter: - state += "¬" + (String.IsNullOrEmpty(rom.Machine.CloneOf) ? "" : HttpUtility.HtmlEncode(rom.Machine.CloneOf)) + - "¬" + (String.IsNullOrEmpty(rom.Machine.CloneOf) ? "" : HttpUtility.HtmlEncode(rom.Machine.CloneOf)) + - "¬" + HttpUtility.HtmlEncode(rom.Machine.Name) + - "¬" + HttpUtility.HtmlEncode((String.IsNullOrEmpty(rom.Machine.Description) ? rom.Machine.Name : rom.Machine.Description)) + + if (rom.Type == ItemType.Rom) + { + state += "¬" + (String.IsNullOrEmpty(rom.CloneOf) ? "" : HttpUtility.HtmlEncode(rom.CloneOf)) + + "¬" + (String.IsNullOrEmpty(rom.CloneOf) ? "" : HttpUtility.HtmlEncode(rom.CloneOf)) + + "¬" + HttpUtility.HtmlEncode(rom.MachineName) + + "¬" + HttpUtility.HtmlEncode((String.IsNullOrEmpty(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription)) + "¬" + HttpUtility.HtmlEncode(rom.Name) + - "¬" + rom.HashData.CRC.ToLowerInvariant() + - "¬" + (rom.HashData.Size != -1 ? rom.HashData.Size.ToString() : "") + "¬¬¬\n"; + "¬" + ((Rom)rom).HashData.CRC.ToLowerInvariant() + + "¬" + (((Rom)rom).HashData.Size != -1 ? ((Rom)rom).HashData.Size.ToString() : "") + "¬¬¬\n"; + } + else if (rom.Type == ItemType.Disk) + { + state += "¬" + (String.IsNullOrEmpty(rom.CloneOf) ? "" : HttpUtility.HtmlEncode(rom.CloneOf)) + + "¬" + (String.IsNullOrEmpty(rom.CloneOf) ? "" : HttpUtility.HtmlEncode(rom.CloneOf)) + + "¬" + HttpUtility.HtmlEncode(rom.MachineName) + + "¬" + HttpUtility.HtmlEncode((String.IsNullOrEmpty(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription)) + + "¬" + HttpUtility.HtmlEncode(rom.Name) + + "¬¬¬¬¬\n"; + } + break; case OutputFormat.SabreDat: string prefix = ""; @@ -3032,29 +3118,106 @@ namespace SabreTools.Helper { prefix += "\t"; } - state += prefix; - state += "\n" + prefix + "\t\n" + - prefix + "\t\t\n" + - prefix + "\t\n" + - prefix + "\n" : - "/>\n"); + + switch (rom.Type) + { + case ItemType.Archive: + state += "\n"; + break; + case ItemType.BiosSet: + state += "\n"; + break; + case ItemType.Disk: + state += "\n" + prefix + "\t\n" + + prefix + "\t\t\n" + + prefix + "\t\n" + + prefix + "\n" : "/>\n"); + break; + case ItemType.Release: + state += "\n"; + break; + case ItemType.Rom: + state += "\n" + prefix + "\t\n" + + prefix + "\t\t\n" + + prefix + "\t\n" + + prefix + "\n" : "/>\n"); + break; + case ItemType.Sample: + state += "\n"; + break; + } break; case OutputFormat.Xml: - state += "\t\t<" + rom.Type.ToString().ToLowerInvariant() + " name=\"" + HttpUtility.HtmlEncode(rom.Name) + "\"" + - (rom.Type == ItemType.Rom && rom.HashData.Size != -1 ? " size=\"" + rom.HashData.Size + "\"" : "") + - (!String.IsNullOrEmpty(rom.HashData.CRC) ? " crc=\"" + rom.HashData.CRC.ToLowerInvariant() + "\"" : "") + - (!String.IsNullOrEmpty(rom.HashData.MD5) ? " md5=\"" + rom.HashData.MD5.ToLowerInvariant() + "\"" : "") + - (!String.IsNullOrEmpty(rom.HashData.SHA1) ? " sha1=\"" + rom.HashData.SHA1.ToLowerInvariant() + "\"" : "") + - (!String.IsNullOrEmpty(rom.Date) ? " date=\"" + rom.Date + "\"" : "") + - (rom.Nodump ? " status=\"nodump\"" : "") + - "/>\n"; + switch (rom.Type) + { + case ItemType.Archive: + state += "\t\t\n"; + break; + case ItemType.BiosSet: + state += "\t\t\n"; + break; + case ItemType.Disk: + state += "\t\t\n"; + break; + case ItemType.Release: + state += "\t\t\n"; + break; + case ItemType.Rom: + state += "\t\t\n"; + break; + case ItemType.Sample: + state += "\t\t\n"; + break; + } break; } @@ -3191,7 +3354,7 @@ namespace SabreTools.Helper Homepage = datdata.Homepage, Url = datdata.Url, Comment = datdata.Comment, - Files = new Dictionary>(), + Files = new Dictionary>(), OutputFormat = outputFormat, }; Dat datdataB = new Dat @@ -3207,7 +3370,7 @@ namespace SabreTools.Helper Homepage = datdata.Homepage, Url = datdata.Url, Comment = datdata.Comment, - Files = new Dictionary>(), + Files = new Dictionary>(), OutputFormat = outputFormat, }; @@ -3220,7 +3383,7 @@ namespace SabreTools.Helper // Now separate the roms accordingly foreach (string key in datdata.Files.Keys) { - foreach (Rom rom in datdata.Files[key]) + foreach (DatItem rom in datdata.Files[key]) { if (newExtA.Contains(Path.GetExtension(rom.Name.ToUpperInvariant()))) { @@ -3230,7 +3393,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); datdataA.Files.Add(key, temp); } @@ -3243,7 +3406,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); datdataB.Files.Add(key, temp); } @@ -3256,7 +3419,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); datdataA.Files.Add(key, temp); } @@ -3266,7 +3429,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); datdataB.Files.Add(key, temp); } @@ -3337,7 +3500,7 @@ namespace SabreTools.Helper ForcePacking = datdata.ForcePacking, OutputFormat = outputFormat, MergeRoms = datdata.MergeRoms, - Files = new Dictionary>(), + Files = new Dictionary>(), }; Dat sha1 = new Dat { @@ -3359,7 +3522,7 @@ namespace SabreTools.Helper ForcePacking = datdata.ForcePacking, OutputFormat = outputFormat, MergeRoms = datdata.MergeRoms, - Files = new Dictionary>(), + Files = new Dictionary>(), }; Dat md5 = new Dat { @@ -3381,7 +3544,7 @@ namespace SabreTools.Helper ForcePacking = datdata.ForcePacking, OutputFormat = outputFormat, MergeRoms = datdata.MergeRoms, - Files = new Dictionary>(), + Files = new Dictionary>(), }; Dat crc = new Dat { @@ -3403,18 +3566,48 @@ namespace SabreTools.Helper ForcePacking = datdata.ForcePacking, OutputFormat = outputFormat, MergeRoms = datdata.MergeRoms, - Files = new Dictionary>(), + Files = new Dictionary>(), + }; + + Dat other = new Dat + { + FileName = datdata.FileName + " (Other)", + Name = datdata.Name + " (Other)", + Description = datdata.Description + " (Other)", + Category = datdata.Category, + Version = datdata.Version, + Date = datdata.Date, + Author = datdata.Author, + Email = datdata.Email, + Homepage = datdata.Homepage, + Url = datdata.Url, + Comment = datdata.Comment, + Header = datdata.Header, + Type = datdata.Type, + ForceMerging = datdata.ForceMerging, + ForceNodump = datdata.ForceNodump, + ForcePacking = datdata.ForcePacking, + OutputFormat = outputFormat, + MergeRoms = datdata.MergeRoms, + Files = new Dictionary>(), }; // Now populate each of the DAT objects in turn List keys = datdata.Files.Keys.ToList(); foreach (string key in keys) { - List roms = datdata.Files[key]; - foreach (Rom rom in roms) + List roms = datdata.Files[key]; + foreach (DatItem rom in roms) { + // If the file is not a Rom or Disk, continue + if (rom.Type != ItemType.Disk && rom.Type != ItemType.Rom) + { + continue; + } + // If the file is a nodump - if (rom.Nodump) + if ((rom.Type == ItemType.Rom && ((Rom)rom).Nodump) + || (rom.Type == ItemType.Disk && ((Disk)rom).Nodump)) { if (nodump.Files.ContainsKey(key)) { @@ -3422,13 +3615,14 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); nodump.Files.Add(key, temp); } } // If the file has a SHA-1 - else if (rom.HashData.SHA1 != null && rom.HashData.SHA1 != "") + else if ((rom.Type == ItemType.Rom && !String.IsNullOrEmpty(((Rom)rom).HashData.SHA1)) + || (rom.Type == ItemType.Disk && !String.IsNullOrEmpty(((Disk)rom).HashData.SHA1))) { if (sha1.Files.ContainsKey(key)) { @@ -3436,13 +3630,14 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); sha1.Files.Add(key, temp); } } // If the file has no SHA-1 but has an MD5 - else if (rom.HashData.MD5 != null && rom.HashData.MD5 != "") + else if ((rom.Type == ItemType.Rom && !String.IsNullOrEmpty(((Rom)rom).HashData.MD5)) + || (rom.Type == ItemType.Disk && !String.IsNullOrEmpty(((Disk)rom).HashData.MD5))) { if (md5.Files.ContainsKey(key)) { @@ -3450,13 +3645,14 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); md5.Files.Add(key, temp); } } - // All other cases - else + // If the file has no MD5 but a CRC + else if ((rom.Type == ItemType.Rom && !String.IsNullOrEmpty(((Rom)rom).HashData.SHA1)) + || (rom.Type == ItemType.Disk && !String.IsNullOrEmpty(((Disk)rom).HashData.SHA1))) { if (crc.Files.ContainsKey(key)) { @@ -3464,11 +3660,24 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); crc.Files.Add(key, temp); } } + else + { + if (other.Files.ContainsKey(key)) + { + other.Files[key].Add(rom); + } + else + { + List temp = new List(); + temp.Add(rom); + other.Files.Add(key, temp); + } + } } } @@ -3551,7 +3760,7 @@ namespace SabreTools.Helper ForcePacking = datdata.ForcePacking, OutputFormat = outputFormat, MergeRoms = datdata.MergeRoms, - Files = new Dictionary>(), + Files = new Dictionary>(), }; Dat diskdat = new Dat { @@ -3573,7 +3782,7 @@ namespace SabreTools.Helper ForcePacking = datdata.ForcePacking, OutputFormat = outputFormat, MergeRoms = datdata.MergeRoms, - Files = new Dictionary>(), + Files = new Dictionary>(), }; Dat sampledat = new Dat { @@ -3595,15 +3804,15 @@ namespace SabreTools.Helper ForcePacking = datdata.ForcePacking, OutputFormat = outputFormat, MergeRoms = datdata.MergeRoms, - Files = new Dictionary>(), + Files = new Dictionary>(), }; // Now populate each of the DAT objects in turn List keys = datdata.Files.Keys.ToList(); foreach (string key in keys) { - List roms = datdata.Files[key]; - foreach (Rom rom in roms) + List roms = datdata.Files[key]; + foreach (DatItem rom in roms) { // If the file is a Rom if (rom.Type == ItemType.Rom) @@ -3614,7 +3823,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); romdat.Files.Add(key, temp); } @@ -3628,7 +3837,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); diskdat.Files.Add(key, temp); } @@ -3643,7 +3852,7 @@ namespace SabreTools.Helper } else { - List temp = new List(); + List temp = new List(); temp.Add(rom); sampledat.Files.Add(key, temp); } diff --git a/SabreTools.Helper/Tools/DatToolsHash.cs b/SabreTools.Helper/Tools/DatToolsHash.cs deleted file mode 100644 index dee319bc..00000000 --- a/SabreTools.Helper/Tools/DatToolsHash.cs +++ /dev/null @@ -1,1534 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using System.Xml; - -namespace SabreTools.Helper -{ - /// - /// DAT manipulation tools that rely on HashData and related structs - /// - /// THIS IS NOT IN SYNC WITH THE MAIN DATTOOLS CLASS, WILL NEED AN UPDATE BEFORE THAT IS POSSIBLE - public class DatToolsHash - { - #region DAT Parsing - - /// - /// Parse a DAT and return all found games and roms within - /// - /// Name of the file to be parsed - /// System ID for the DAT - /// Source ID for the DAT - /// The DatData object representing found roms to this point - /// Logger object for console and/or file output - /// True if full pathnames are to be kept, false otherwise (default) - /// True if game names are sanitized, false otherwise (default) - /// DatData object representing the read-in data - public static DatData Parse(string filename, int sysid, int srcid, DatData datdata, Logger logger, bool keep = false, bool clean = false, bool softlist = false, bool keepext = false) - { - // Check the file extension first as a safeguard - string ext = Path.GetExtension(filename).ToLowerInvariant(); - if (ext != ".txt" && ext != ".dat" && ext != ".xml") - { - return datdata; - } - - // If the output filename isn't set already, get the internal filename - datdata.FileName = (String.IsNullOrEmpty(datdata.FileName) ? (keepext ? Path.GetFileName(filename) : Path.GetFileNameWithoutExtension(filename)) : datdata.FileName); - - // If the output type isn't set already, get the internal output type - datdata.OutputFormat = (datdata.OutputFormat == 0 ? DatTools.GetOutputFormat(filename, logger) : datdata.OutputFormat); - - // Make sure there's a dictionary to read to - if (datdata.Hashes == null) - { - datdata.Hashes = new List(); - } - - // Now parse the correct type of DAT - switch (DatTools.GetOutputFormat(filename, logger)) - { - case OutputFormat.ClrMamePro: - return ParseCMP(filename, sysid, srcid, datdata, logger, keep, clean); - case OutputFormat.RomCenter: - return ParseRC(filename, sysid, srcid, datdata, logger, clean); - case OutputFormat.SabreDat: - case OutputFormat.Xml: - return ParseXML(filename, sysid, srcid, datdata, logger, keep, clean, softlist); - default: - return datdata; - } - } - - /// - /// Parse a ClrMamePro DAT and return all found games and roms within - /// - /// Name of the file to be parsed - /// System ID for the DAT - /// Source ID for the DAT - /// The DatData object representing found roms to this point - /// Logger object for console and/or file output - /// True if full pathnames are to be kept, false otherwise (default) - /// True if game names are sanitized, false otherwise (default) - /// DatData object representing the read-in data - public static DatData ParseCMP(string filename, int sysid, int srcid, DatData datdata, Logger logger, bool keep, bool clean) - { - // Open a file reader - StreamReader sr = new StreamReader(File.OpenRead(filename)); - - bool block = false, superdat = false; - string blockname = "", gamename = "", gamedesc = ""; - while (!sr.EndOfStream) - { - string line = sr.ReadLine(); - - // Comments in CMP DATs start with a # - if (line.Trim().StartsWith("#")) - { - continue; - } - - // If the line is the header or a game - if (Regex.IsMatch(line, Constants.HeaderPatternCMP)) - { - GroupCollection gc = Regex.Match(line, Constants.HeaderPatternCMP).Groups; - - if (gc[1].Value == "clrmamepro" || gc[1].Value == "romvault") - { - blockname = "header"; - } - - block = true; - } - - // If the line is a rom or disk and we're in a block - else if ((line.Trim().StartsWith("rom (") || line.Trim().StartsWith("disk (")) && block) - { - // If we're in cleaning mode, sanitize the game name - gamename = (clean ? Style.CleanGameName(gamename) : gamename); - - RomData romData = new RomData - { - Type = (line.Trim().StartsWith("disk (") ? ItemType.Disk : ItemType.Rom), - Machine = new MachineData - { - Name = gamename, - Description = gamedesc, - SystemID = sysid, - SourceID = srcid, - }, - }; - HashData hashData = new HashData - { - Roms = new List(), - }; - - string[] gc = line.Trim().Split(' '); - - // Loop over all attributes and add them if possible - bool quote = false; - string attrib = "", val = ""; - for (int i = 2; i < gc.Length; i++) - { - //If the item is empty, we automatically skip it because it's a fluke - if (gc[i].Trim() == String.Empty) - { - continue; - } - // Special case for nodump... - else if (gc[i] == "nodump" && attrib != "status" && attrib != "flags") - { - romData.Nodump = true; - } - // Even number of quotes, not in a quote, not in attribute - else if (Regex.Matches(gc[i], "\"").Count % 2 == 0 && !quote && attrib == "") - { - attrib = gc[i].Replace("\"", ""); - } - // Even number of quotes, not in a quote, in attribute - else if (Regex.Matches(gc[i], "\"").Count % 2 == 0 && !quote && attrib != "") - { - switch (attrib.ToLowerInvariant()) - { - case "name": - romData.Name = gc[i].Replace("\"", ""); - break; - case "size": - Int64.TryParse(gc[i].Replace("\"", ""), out hashData.Size); - break; - case "crc": - hashData.CRC = Style.StringToByteArray(gc[i].Replace("\"", "")); - break; - case "md5": - hashData.MD5 = Style.StringToByteArray(gc[i].Replace("\"", "")); - break; - case "sha1": - hashData.SHA1 = Style.StringToByteArray(gc[i].Replace("\"", "")); - break; - case "flags": - if (gc[i].Replace("\"", "").ToLowerInvariant() == "nodump") - { - romData.Nodump = true; - } - break; - } - - attrib = ""; - } - // Even number of quotes, in a quote, not in attribute - else if (Regex.Matches(gc[i], "\"").Count % 2 == 0 && quote && attrib == "") - { - // Attributes can't have quoted names - } - // Even number of quotes, in a quote, in attribute - else if (Regex.Matches(gc[i], "\"").Count % 2 == 0 && quote && attrib != "") - { - val += " " + gc[i]; - } - // Odd number of quotes, not in a quote, not in attribute - else if (Regex.Matches(gc[i], "\"").Count % 2 == 1 && !quote && attrib == "") - { - // Attributes can't have quoted names - } - // Odd number of quotes, not in a quote, in attribute - else if (Regex.Matches(gc[i], "\"").Count % 2 == 1 && !quote && attrib != "") - { - val = gc[i].Replace("\"", ""); - quote = true; - } - // Odd number of quotes, in a quote, not in attribute - else if (Regex.Matches(gc[i], "\"").Count % 2 == 1 && quote && attrib == "") - { - quote = false; - } - // Odd number of quotes, in a quote, in attribute - else if (Regex.Matches(gc[i], "\"").Count % 2 == 1 && quote && attrib != "") - { - val += " " + gc[i].Replace("\"", ""); - switch (attrib.ToLowerInvariant()) - { - case "name": - romData.Name = val; - break; - case "size": - Int64.TryParse(val, out hashData.Size); - break; - case "crc": - hashData.CRC = Style.StringToByteArray(val); - break; - case "md5": - hashData.MD5 = Style.StringToByteArray(val); - break; - case "sha1": - hashData.SHA1 = Style.StringToByteArray(val); - break; - case "flags": - if (val.ToLowerInvariant() == "nodump") - { - romData.Nodump = true; - } - break; - } - - quote = false; - attrib = ""; - val = ""; - } - } - - // Sanitize the hashes from null, hex sizes, and "true blank" strings - hashData.CRC = Style.CleanHashData(hashData.CRC, Constants.CRCBytesLength); - hashData.MD5 = Style.CleanHashData(hashData.MD5, Constants.MD5BytesLength); - hashData.SHA1 = Style.CleanHashData(hashData.SHA1, Constants.SHA1BytesLength); - - // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info - if (romData.Type == ItemType.Rom - && (hashData.Size == 0 || hashData.Size == -1) - && ((hashData.CRC == Constants.CRCZeroBytes || hashData.CRC == null) - || hashData.MD5 == Constants.MD5ZeroBytes - || hashData.SHA1 == Constants.SHA1ZeroBytes)) - { - hashData.Size = Constants.SizeZero; - hashData.CRC = Constants.CRCZeroBytes; - hashData.MD5 = Constants.MD5ZeroBytes; - hashData.SHA1 = Constants.SHA1ZeroBytes; - } - // If the file has no size and it's not the above case, skip and log - else if (romData.Type == ItemType.Rom && (hashData.Size == 0 || hashData.Size == -1)) - { - logger.Warning("Incomplete entry for \"" + romData.Name + "\" will be output as nodump"); - romData.Nodump = true; - } - - // If we have a disk, make sure that the value for size is -1 - if (romData.Type == ItemType.Disk) - { - hashData.Size = -1; - } - - // Now add the hash to the Dat - if (datdata.Hashes.Contains(hashData)) - { - datdata.Hashes[datdata.Hashes.IndexOf(hashData)].Roms.Add(romData); - } - else - { - hashData.Roms.Add(romData); - datdata.Hashes.Add(hashData); - } - - // Add statistical data - datdata.RomCount += (romData.Type == ItemType.Rom ? 1 : 0); - datdata.DiskCount += (romData.Type == ItemType.Disk ? 1 : 0); - datdata.TotalSize += (romData.Nodump ? 0 : hashData.Size); - datdata.CRCCount += (hashData.CRC == null ? 0 : 1); - datdata.MD5Count += (hashData.MD5 == null ? 0 : 1); - datdata.SHA1Count += (hashData.SHA1 == null ? 0 : 1); - datdata.NodumpCount += (romData.Nodump ? 1 : 0); - } - // If the line is anything but a rom or disk and we're in a block - else if (Regex.IsMatch(line, Constants.ItemPatternCMP) && block) - { - GroupCollection gc = Regex.Match(line, Constants.ItemPatternCMP).Groups; - - if (gc[1].Value == "name" && blockname != "header") - { - gamename = gc[2].Value.Replace("\"", ""); - } - else if (gc[1].Value == "description" && blockname != "header") - { - gamedesc = gc[2].Value.Replace("\"", ""); - } - else - { - string itemval = gc[2].Value.Replace("\"", ""); - switch (gc[1].Value) - { - case "name": - datdata.Name = (String.IsNullOrEmpty(datdata.Name) ? itemval : datdata.Name); - superdat = superdat || itemval.Contains(" - SuperDAT"); - if (keep && superdat) - { - datdata.Type = (String.IsNullOrEmpty(datdata.Type) ? "SuperDAT" : datdata.Type); - } - break; - case "description": - datdata.Description = (String.IsNullOrEmpty(datdata.Description) ? itemval : datdata.Description); - break; - case "rootdir": - datdata.RootDir = (String.IsNullOrEmpty(datdata.RootDir) ? itemval : datdata.RootDir); - break; - case "category": - datdata.Category = (String.IsNullOrEmpty(datdata.Category) ? itemval : datdata.Category); - break; - case "version": - datdata.Version = (String.IsNullOrEmpty(datdata.Version) ? itemval : datdata.Version); - break; - case "date": - datdata.Date = (String.IsNullOrEmpty(datdata.Date) ? itemval : datdata.Date); - break; - case "author": - datdata.Author = (String.IsNullOrEmpty(datdata.Author) ? itemval : datdata.Author); - break; - case "email": - datdata.Email = (String.IsNullOrEmpty(datdata.Email) ? itemval : datdata.Email); - break; - case "homepage": - datdata.Homepage = (String.IsNullOrEmpty(datdata.Homepage) ? itemval : datdata.Homepage); - break; - case "url": - datdata.Url = (String.IsNullOrEmpty(datdata.Url) ? itemval : datdata.Url); - break; - case "comment": - datdata.Comment = (String.IsNullOrEmpty(datdata.Comment) ? itemval : datdata.Comment); - break; - case "header": - datdata.Header = (String.IsNullOrEmpty(datdata.Header) ? itemval : datdata.Header); - break; - case "type": - datdata.Type = (String.IsNullOrEmpty(datdata.Type) ? itemval : datdata.Type); - superdat = superdat || itemval.Contains("SuperDAT"); - break; - case "forcemerging": - switch (itemval) - { - case "none": - datdata.ForceMerging = ForceMerging.None; - break; - case "split": - datdata.ForceMerging = ForceMerging.Split; - break; - case "full": - datdata.ForceMerging = ForceMerging.Full; - break; - } - break; - case "forcezipping": - datdata.ForcePacking = (itemval == "yes" ? ForcePacking.Zip : ForcePacking.Unzip); - break; - } - } - } - - // If we find an end bracket that's not associated with anything else, the block is done - else if (Regex.IsMatch(line, Constants.EndPatternCMP) && block) - { - block = false; - blockname = ""; - gamename = ""; - } - } - - sr.Close(); - sr.Dispose(); - - return datdata; - } - - /// - /// Parse a RomCenter DAT and return all found games and roms within - /// - /// Name of the file to be parsed - /// System ID for the DAT - /// Source ID for the DAT - /// The DatData object representing found roms to this point - /// Logger object for console and/or file output - /// True if game names are sanitized, false otherwise (default) - /// DatData object representing the read-in data - public static DatData ParseRC(string filename, int sysid, int srcid, DatData datdata, Logger logger, bool clean) - { - // Read the input file, if possible - logger.Log("Attempting to read file: \"" + filename + "\""); - - // Check if file exists - if (!File.Exists(filename)) - { - logger.Warning("File '" + filename + "' could not read from!"); - return datdata; - } - - // If it does, open a file reader - StreamReader sr = new StreamReader(File.OpenRead(filename)); - - string blocktype = ""; - while (!sr.EndOfStream) - { - string line = sr.ReadLine(); - - // If the line is the start of the credits section - if (line.ToLowerInvariant().Contains("[credits]")) - { - blocktype = "credits"; - } - // If the line is the start of the dat section - else if (line.ToLowerInvariant().Contains("[dat]")) - { - blocktype = "dat"; - } - // If the line is the start of the emulator section - else if (line.ToLowerInvariant().Contains("[emulator]")) - { - blocktype = "emulator"; - } - // If the line is the start of the game section - else if (line.ToLowerInvariant().Contains("[games]")) - { - blocktype = "games"; - } - // Otherwise, it's not a section and it's data, so get out all data - else - { - // If we have an author - if (line.StartsWith("author=")) - { - datdata.Author = (String.IsNullOrEmpty(datdata.Author) ? line.Split('=')[1] : datdata.Author); - } - // If we have one of the three version tags - else if (line.StartsWith("version=")) - { - switch (blocktype) - { - case "credits": - datdata.Version = (String.IsNullOrEmpty(datdata.Version) ? line.Split('=')[1] : datdata.Version); - break; - case "emulator": - datdata.Description = (String.IsNullOrEmpty(datdata.Description) ? line.Split('=')[1] : datdata.Description); - break; - } - } - // If we have a comment - else if (line.StartsWith("comment=")) - { - datdata.Comment = (String.IsNullOrEmpty(datdata.Comment) ? line.Split('=')[1] : datdata.Comment); - } - // If we have the split flag - else if (line.StartsWith("split=")) - { - int split = 0; - if (Int32.TryParse(line.Split('=')[1], out split)) - { - if (split == 1) - { - datdata.ForceMerging = ForceMerging.Split; - } - } - } - // If we have the merge tag - else if (line.StartsWith("merge=")) - { - int merge = 0; - if (Int32.TryParse(line.Split('=')[1], out merge)) - { - if (merge == 1) - { - datdata.ForceMerging = ForceMerging.Full; - } - } - } - // If we have the refname tag - else if (line.StartsWith("refname=")) - { - datdata.Name = (String.IsNullOrEmpty(datdata.Name) ? line.Split('=')[1] : datdata.Name); - } - // If we have a rom - else if (line.StartsWith("¬")) - { - /* - The rominfo order is as follows: - 1 - parent name - 2 - parent description - 3 - game name - 4 - game description - 5 - rom name - 6 - rom crc - 7 - rom size - 8 - romof name - 9 - merge name - */ - string[] rominfo = line.Split('¬'); - - // If we're in cleaning mode, sanitize the game name - rominfo[3] = (clean ? Style.CleanGameName(rominfo[3]) : rominfo[3]); - - RomData romData = new RomData - { - Name = rominfo[5], - Machine = new MachineData - { - Name = rominfo[3], - Description = rominfo[4], - CloneOf = rominfo[1], - RomOf = rominfo[1], - SystemID = sysid, - SourceID = srcid, - }, - }; - HashData hashData = new HashData - { - Size = Int64.Parse(rominfo[7]), - CRC = Style.StringToByteArray(rominfo[6]), - }; - - // Sanitize the hashes from null, hex sizes, and "true blank" strings - hashData.CRC = Style.CleanHashData(hashData.CRC, Constants.CRCBytesLength); - hashData.MD5 = Style.CleanHashData(hashData.MD5, Constants.MD5BytesLength); - hashData.SHA1 = Style.CleanHashData(hashData.SHA1, Constants.SHA1BytesLength); - - // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info - if (romData.Type == ItemType.Rom - && (hashData.Size == 0 || hashData.Size == -1) - && ((hashData.CRC == Constants.CRCZeroBytes || hashData.CRC == null) - || hashData.MD5 == Constants.MD5ZeroBytes - || hashData.SHA1 == Constants.SHA1ZeroBytes)) - { - hashData.Size = Constants.SizeZero; - hashData.CRC = Constants.CRCZeroBytes; - hashData.MD5 = Constants.MD5ZeroBytes; - hashData.SHA1 = Constants.SHA1ZeroBytes; - } - // If the file has no size and it's not the above case, skip and log - else if (romData.Type == ItemType.Rom && (hashData.Size == 0 || hashData.Size == -1)) - { - logger.Warning("Incomplete entry for \"" + romData.Name + "\" will be output as nodump"); - romData.Nodump = true; - } - - // If we have a disk, make sure that the value for size is -1 - if (romData.Type == ItemType.Disk) - { - hashData.Size = -1; - } - - // Now add the hash to the Dat - if (datdata.Hashes.Contains(hashData)) - { - datdata.Hashes[datdata.Hashes.IndexOf(hashData)].Roms.Add(romData); - } - else - { - hashData.Roms.Add(romData); - datdata.Hashes.Add(hashData); - } - - // Add statistical data - datdata.RomCount += (romData.Type == ItemType.Rom ? 1 : 0); - datdata.DiskCount += (romData.Type == ItemType.Disk ? 1 : 0); - datdata.TotalSize += (romData.Nodump ? 0 : hashData.Size); - datdata.CRCCount += (hashData.CRC == null ? 0 : 1); - datdata.MD5Count += (hashData.MD5 == null ? 0 : 1); - datdata.SHA1Count += (hashData.SHA1 == null ? 0 : 1); - datdata.NodumpCount += (romData.Nodump ? 1 : 0); - } - } - } - - sr.Close(); - sr.Dispose(); - - return datdata; - } - - /// - /// Parse an XML DAT (Logiqx, SabreDAT, or SL) and return all found games and roms within - /// - /// Name of the file to be parsed - /// System ID for the DAT - /// Source ID for the DAT - /// The DatData object representing found roms to this point - /// Logger object for console and/or file output - /// True if full pathnames are to be kept, false otherwise (default) - /// True if game names are sanitized, false otherwise (default) - /// True if SL XML names should be kept, false otherwise (default) - /// DatData object representing the read-in data - public static DatData ParseXML(string filename, int sysid, int srcid, DatData datdata, Logger logger, bool keep, bool clean, bool softlist) - { - // Prepare all internal variables - XmlReader subreader, headreader, flagreader; - bool superdat = false, nodump = false, empty = true; - string crc = "", md5 = "", sha1 = "", date = ""; - long size = -1; - List parent = new List(); - - XmlTextReader xtr = DatTools.GetXmlTextReader(filename, logger); - if (xtr != null) - { - xtr.MoveToContent(); - while (!xtr.EOF) - { - // If we're ending a folder or game, take care of possibly empty games and removing from the parent - if (xtr.NodeType == XmlNodeType.EndElement && (xtr.Name == "directory" || xtr.Name == "dir")) - { - // If we didn't find any items in the folder, make sure to add the blank rom - if (empty) - { - string tempgame = String.Join("\\", parent); - - // If we're in cleaning mode, sanitize the game name - tempgame = (clean ? Style.CleanGameName(tempgame) : tempgame); - - RomData romData = new RomData - { - Type = ItemType.Rom, - Name = "null", - Machine = new MachineData - { - Name = tempgame, - Description = tempgame, - }, - }; - HashData hashData = new HashData - { - Size = -1, - CRC = null, - MD5 = null, - SHA1 = null, - Roms = new List(), - }; - - // Now add the hash to the Dat - if (datdata.Hashes.Contains(hashData)) - { - datdata.Hashes[datdata.Hashes.IndexOf(hashData)].Roms.Add(romData); - } - else - { - hashData.Roms.Add(romData); - datdata.Hashes.Add(hashData); - } - - // Add statistical data - datdata.RomCount += (romData.Type == ItemType.Rom ? 1 : 0); - datdata.DiskCount += (romData.Type == ItemType.Disk ? 1 : 0); - datdata.TotalSize += (romData.Nodump ? 0 : hashData.Size); - datdata.CRCCount += (hashData.CRC == null ? 0 : 1); - datdata.MD5Count += (hashData.MD5 == null ? 0 : 1); - datdata.SHA1Count += (hashData.SHA1 == null ? 0 : 1); - datdata.NodumpCount += (romData.Nodump ? 1 : 0); - } - - // Regardless, end the current folder - int parentcount = parent.Count; - if (parentcount == 0) - { - logger.Log("Empty parent: " + String.Join("\\", parent)); - empty = true; - } - - // If we have an end folder element, remove one item from the parent, if possible - if (parentcount > 0) - { - parent.RemoveAt(parent.Count - 1); - if (keep && parentcount > 1) - { - datdata.Type = (String.IsNullOrEmpty(datdata.Type) ? "SuperDAT" : datdata.Type); - superdat = true; - } - } - } - - // We only want elements - if (xtr.NodeType != XmlNodeType.Element) - { - xtr.Read(); - continue; - } - - switch (xtr.Name) - { - // New software lists have this behavior - case "softwarelist": - if (xtr.GetAttribute("name") != null) - { - datdata.Name = (String.IsNullOrEmpty(datdata.Name) ? xtr.GetAttribute("name") : datdata.Name); - } - if (xtr.GetAttribute("description") != null) - { - datdata.Description = (String.IsNullOrEmpty(datdata.Description) ? xtr.GetAttribute("description") : datdata.Description); - } - xtr.Read(); - break; - // Handle M1 DATs since they're 99% the same as a SL DAT - case "m1": - datdata.Name = (String.IsNullOrEmpty(datdata.Name) ? "M1" : datdata.Name); - datdata.Description = (String.IsNullOrEmpty(datdata.Description) ? "M1" : datdata.Description); - if (xtr.GetAttribute("version") != null) - { - datdata.Version = (String.IsNullOrEmpty(datdata.Version) ? xtr.GetAttribute("version") : datdata.Version); - } - break; - case "header": - // We want to process the entire subtree of the header - headreader = xtr.ReadSubtree(); - - if (headreader != null) - { - while (!headreader.EOF) - { - // We only want elements - if (headreader.NodeType != XmlNodeType.Element || headreader.Name == "header") - { - headreader.Read(); - continue; - } - - // Get all header items (ONLY OVERWRITE IF THERE'S NO DATA) - string content = ""; - switch (headreader.Name) - { - case "name": - content = headreader.ReadElementContentAsString(); ; - datdata.Name = (String.IsNullOrEmpty(datdata.Name) ? content : datdata.Name); - superdat = superdat || content.Contains(" - SuperDAT"); - if (keep && superdat) - { - datdata.Type = (String.IsNullOrEmpty(datdata.Type) ? "SuperDAT" : datdata.Type); - } - break; - case "description": - content = headreader.ReadElementContentAsString(); - datdata.Description = (String.IsNullOrEmpty(datdata.Description) ? content : datdata.Description); - break; - case "rootdir": - content = headreader.ReadElementContentAsString(); - datdata.RootDir = (String.IsNullOrEmpty(datdata.RootDir) ? content : datdata.RootDir); - break; - case "category": - content = headreader.ReadElementContentAsString(); - datdata.Category = (String.IsNullOrEmpty(datdata.Category) ? content : datdata.Category); - break; - case "version": - content = headreader.ReadElementContentAsString(); - datdata.Version = (String.IsNullOrEmpty(datdata.Version) ? content : datdata.Version); - break; - case "date": - content = headreader.ReadElementContentAsString(); - datdata.Date = (String.IsNullOrEmpty(datdata.Date) ? content : datdata.Date); - break; - case "author": - content = headreader.ReadElementContentAsString(); - datdata.Author = (String.IsNullOrEmpty(datdata.Author) ? content : datdata.Author); - - // Special cases for SabreDAT - datdata.Email = (String.IsNullOrEmpty(datdata.Email) && !String.IsNullOrEmpty(headreader.GetAttribute("email")) ? - headreader.GetAttribute("email") : datdata.Email); - datdata.Homepage = (String.IsNullOrEmpty(datdata.Homepage) && !String.IsNullOrEmpty(headreader.GetAttribute("homepage")) ? - headreader.GetAttribute("homepage") : datdata.Email); - datdata.Url = (String.IsNullOrEmpty(datdata.Url) && !String.IsNullOrEmpty(headreader.GetAttribute("url")) ? - headreader.GetAttribute("url") : datdata.Email); - break; - case "email": - content = headreader.ReadElementContentAsString(); - datdata.Email = (String.IsNullOrEmpty(datdata.Email) ? content : datdata.Email); - break; - case "homepage": - content = headreader.ReadElementContentAsString(); - datdata.Homepage = (String.IsNullOrEmpty(datdata.Homepage) ? content : datdata.Homepage); - break; - case "url": - content = headreader.ReadElementContentAsString(); - datdata.Url = (String.IsNullOrEmpty(datdata.Url) ? content : datdata.Url); - break; - case "comment": - content = headreader.ReadElementContentAsString(); - datdata.Comment = (String.IsNullOrEmpty(datdata.Comment) ? content : datdata.Comment); - break; - case "type": - content = headreader.ReadElementContentAsString(); - datdata.Type = (String.IsNullOrEmpty(datdata.Type) ? content : datdata.Type); - superdat = superdat || content.Contains("SuperDAT"); - break; - case "clrmamepro": - if (headreader.GetAttribute("header") != null) - { - datdata.Header = (String.IsNullOrEmpty(datdata.Header) ? headreader.GetAttribute("header") : datdata.Header); - } - if (headreader.GetAttribute("forcemerging") != null) - { - switch (headreader.GetAttribute("forcemerging")) - { - case "split": - datdata.ForceMerging = ForceMerging.Split; - break; - case "none": - datdata.ForceMerging = ForceMerging.None; - break; - case "full": - datdata.ForceMerging = ForceMerging.Full; - break; - } - } - if (headreader.GetAttribute("forcenodump") != null) - { - switch (headreader.GetAttribute("forcenodump")) - { - case "obsolete": - datdata.ForceNodump = ForceNodump.Obsolete; - break; - case "required": - datdata.ForceNodump = ForceNodump.Required; - break; - case "ignore": - datdata.ForceNodump = ForceNodump.Ignore; - break; - } - } - if (headreader.GetAttribute("forcepacking") != null) - { - switch (headreader.GetAttribute("forcepacking")) - { - case "zip": - datdata.ForcePacking = ForcePacking.Zip; - break; - case "unzip": - datdata.ForcePacking = ForcePacking.Unzip; - break; - } - } - headreader.Read(); - break; - case "flags": - flagreader = xtr.ReadSubtree(); - if (flagreader != null) - { - while (!flagreader.EOF) - { - // We only want elements - if (flagreader.NodeType != XmlNodeType.Element || flagreader.Name == "flags") - { - flagreader.Read(); - continue; - } - - switch (flagreader.Name) - { - case "flag": - if (flagreader.GetAttribute("name") != null && flagreader.GetAttribute("value") != null) - { - content = flagreader.GetAttribute("value"); - switch (flagreader.GetAttribute("name")) - { - case "type": - datdata.Type = (String.IsNullOrEmpty(datdata.Type) ? content : datdata.Type); - superdat = superdat || content.Contains("SuperDAT"); - break; - case "forcemerging": - switch (content) - { - case "split": - datdata.ForceMerging = ForceMerging.Split; - break; - case "none": - datdata.ForceMerging = ForceMerging.None; - break; - case "full": - datdata.ForceMerging = ForceMerging.Full; - break; - } - break; - case "forcenodump": - switch (content) - { - case "obsolete": - datdata.ForceNodump = ForceNodump.Obsolete; - break; - case "required": - datdata.ForceNodump = ForceNodump.Required; - break; - case "ignore": - datdata.ForceNodump = ForceNodump.Ignore; - break; - } - break; - case "forcepacking": - switch (content) - { - case "zip": - datdata.ForcePacking = ForcePacking.Zip; - break; - case "unzip": - datdata.ForcePacking = ForcePacking.Unzip; - break; - } - break; - } - } - flagreader.Read(); - break; - default: - flagreader.Read(); - break; - } - } - } - headreader.Skip(); - break; - default: - headreader.Read(); - break; - } - } - } - - // Skip the header node now that we've processed it - xtr.Skip(); - break; - case "machine": - case "game": - case "software": - string temptype = xtr.Name; - string tempname = "", gamedesc = ""; - - // We want to process the entire subtree of the game - subreader = xtr.ReadSubtree(); - - // Safeguard for interesting case of "software" without anything except roms - bool software = false; - - // If we have a subtree, add what is possible - if (subreader != null) - { - if (!softlist && temptype == "software" && subreader.ReadToFollowing("description")) - { - tempname = subreader.ReadElementContentAsString(); - tempname = tempname.Replace('/', '_').Replace("\"", "''"); - software = true; - } - else - { - // There are rare cases where a malformed XML will not have the required attributes. We can only skip them. - if (xtr.AttributeCount == 0) - { - logger.Error("No attributes were found"); - xtr.Skip(); - continue; - } - tempname = xtr.GetAttribute("name"); - } - - if (superdat && !keep) - { - string tempout = Regex.Match(tempname, @".*?\\(.*)").Groups[1].Value; - if (tempout != "") - { - tempname = tempout; - } - } - // Get the name of the game from the parent - else if (superdat && keep && parent.Count > 0) - { - tempname = String.Join("\\", parent) + "\\" + tempname; - } - - while (software || subreader.Read()) - { - software = false; - - // We only want elements - if (subreader.NodeType != XmlNodeType.Element) - { - continue; - } - - // Get the roms from the machine - switch (subreader.Name) - { - case "description": - gamedesc = subreader.ReadElementContentAsString(); - break; - case "rom": - case "disk": - empty = false; - - // If the rom is nodump, flag it - nodump = false; - if (subreader.GetAttribute("flags") == "nodump" || subreader.GetAttribute("status") == "nodump") - { - logger.Log("Nodump detected: " + - (subreader.GetAttribute("name") != null && subreader.GetAttribute("name") != "" ? "\"" + xtr.GetAttribute("name") + "\"" : "ROM NAME NOT FOUND")); - nodump = true; - } - - // If the rom has a Date attached, read it in and then sanitize it - date = ""; - if (subreader.GetAttribute("date") != null) - { - date = DateTime.Parse(subreader.GetAttribute("date")).ToString(); - } - - // Take care of hex-sized files - size = -1; - if (subreader.GetAttribute("size") != null && subreader.GetAttribute("size").Contains("0x")) - { - size = Convert.ToInt64(subreader.GetAttribute("size"), 16); - } - else if (subreader.GetAttribute("size") != null) - { - Int64.TryParse(subreader.GetAttribute("size"), out size); - } - - // If the rom is continue or ignore, add the size to the previous rom - if (subreader.GetAttribute("loadflag") == "continue" || subreader.GetAttribute("loadflag") == "ignore") - { - int index = datdata.Hashes.Count() - 1; - HashData lasthash = datdata.Hashes[index]; - lasthash.Size += size; - datdata.Hashes.RemoveAt(index); - datdata.Hashes.Add(lasthash); - continue; - } - - // Sanitize the hashes from null, hex sizes, and "true blank" strings - crc = Style.CleanHashData(subreader.GetAttribute("crc"), Constants.CRCLength); - md5 = Style.CleanHashData(subreader.GetAttribute("md5"), Constants.MD5Length); - sha1 = Style.CleanHashData(subreader.GetAttribute("sha1"), Constants.SHA1Length); - - // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info - if (subreader.Name == "rom" && (size == 0 || size == -1) && - ((crc == Constants.CRCZero || crc == "") || md5 == Constants.MD5Zero || sha1 == Constants.SHA1Zero)) - { - size = Constants.SizeZero; - crc = Constants.CRCZero; - md5 = Constants.MD5Zero; - sha1 = Constants.SHA1Zero; - } - // If the file has no size and it's not the above case, skip and log - else if (subreader.Name == "rom" && (size == 0 || size == -1)) - { - logger.Warning("Incomplete entry for \"" + subreader.GetAttribute("name") + "\" will be output as nodump"); - nodump = true; - } - - // If we're in clean mode, sanitize the game name - if (clean) - { - tempname = Style.CleanGameName(tempname.Split(Path.DirectorySeparatorChar)); - } - - // Only add the rom if there's useful information in it - if (!(crc == "" && md5 == "" && sha1 == "") || nodump) - { - // If we got to this point and it's a disk, log it because some tools don't like disks - if (subreader.Name == "disk") - { - logger.Log("Disk found: \"" + subreader.GetAttribute("name") + "\""); - } - - // Now add the hash to the Dat - RomData romData = new RomData - { - Name = subreader.GetAttribute("name"), - Type = (subreader.Name.ToLowerInvariant() == "disk" ? ItemType.Disk : ItemType.Rom), - Nodump = nodump, - Date = date, - Machine = new MachineData - { - Name = tempname, - Description = gamedesc, - SystemID = sysid, - System = filename, - SourceID = srcid, - }, - }; - HashData hashData = new HashData - { - Size = size, - CRC = Style.CleanHashData(Style.StringToByteArray(crc), Constants.CRCBytesLength), - MD5 = Style.CleanHashData(Style.StringToByteArray(md5), Constants.MD5BytesLength), - SHA1 = Style.CleanHashData(Style.StringToByteArray(sha1), Constants.SHA1BytesLength), - Roms = new List(), - }; - - if (datdata.Hashes.Contains(hashData)) - { - datdata.Hashes[datdata.Hashes.IndexOf(hashData)].Roms.Add(romData); - } - else - { - hashData.Roms.Add(romData); - datdata.Hashes.Add(hashData); - } - - // Add statistical data - datdata.RomCount += (romData.Type == ItemType.Rom ? 1 : 0); - datdata.DiskCount += (romData.Type == ItemType.Disk ? 1 : 0); - datdata.TotalSize += (romData.Nodump ? 0 : hashData.Size); - datdata.CRCCount += (hashData.CRC == null ? 0 : 1); - datdata.MD5Count += (hashData.MD5 == null ? 0 : 1); - datdata.SHA1Count += (hashData.SHA1 == null ? 0 : 1); - datdata.NodumpCount += (romData.Nodump ? 1 : 0); - } - // Otherwise, log that it wasn't added - else - { - logger.Log("Rom was not added: '" + xtr.GetAttribute("name") + "'"); - } - break; - } - } - } - - // If we didn't find any items in the folder, make sure to add the blank rom - if (empty) - { - tempname = (parent.Count > 0 ? String.Join("\\", parent) + Path.DirectorySeparatorChar : "") + tempname; - - // If we're in cleaning mode, sanitize the game name - tempname = (clean ? Style.CleanGameName(tempname.Split(Path.DirectorySeparatorChar)) : tempname); - - // Now add the hash to the Dat - RomData romData = new RomData - { - Type = ItemType.Rom, - Name = "null", - Machine = new MachineData - { - Name = tempname, - Description = tempname, - }, - }; - HashData hashData = new HashData - { - Size = -1, - CRC = null, - MD5 = null, - SHA1 = null, - Roms = new List(), - }; - - if (datdata.Hashes.Contains(hashData)) - { - datdata.Hashes[datdata.Hashes.IndexOf(hashData)].Roms.Add(romData); - } - else - { - hashData.Roms.Add(romData); - datdata.Hashes.Add(hashData); - } - - // Add statistical data - datdata.RomCount += (romData.Type == ItemType.Rom ? 1 : 0); - datdata.DiskCount += (romData.Type == ItemType.Disk ? 1 : 0); - datdata.TotalSize += (romData.Nodump ? 0 : hashData.Size); - datdata.CRCCount += (hashData.CRC == null ? 0 : 1); - datdata.MD5Count += (hashData.MD5 == null ? 0 : 1); - datdata.SHA1Count += (hashData.SHA1 == null ? 0 : 1); - datdata.NodumpCount += (romData.Nodump ? 1 : 0); - } - - // Regardless, end the current folder - if (parent.Count == 0) - { - empty = true; - } - xtr.Skip(); - break; - case "dir": - case "directory": - // Set SuperDAT flag for all SabreDAT inputs, regardless of depth - superdat = true; - if (keep) - { - datdata.Type = (datdata.Type == "" ? "SuperDAT" : datdata.Type); - } - - string foldername = (xtr.GetAttribute("name") == null ? "" : xtr.GetAttribute("name")); - if (foldername != "") - { - parent.Add(foldername); - } - - xtr.Read(); - break; - case "file": - empty = false; - - // If the rom is nodump, flag it - nodump = false; - flagreader = xtr.ReadSubtree(); - if (flagreader != null) - { - while (!flagreader.EOF) - { - // We only want elements - if (flagreader.NodeType != XmlNodeType.Element || flagreader.Name == "flags") - { - flagreader.Read(); - continue; - } - - switch (flagreader.Name) - { - case "flag": - case "status": - if (flagreader.GetAttribute("name") != null && flagreader.GetAttribute("value") != null) - { - string content = flagreader.GetAttribute("value"); - switch (flagreader.GetAttribute("name")) - { - case "nodump": - logger.Log("Nodump detected: " + (xtr.GetAttribute("name") != null && xtr.GetAttribute("name") != "" ? - "\"" + xtr.GetAttribute("name") + "\"" : "ROM NAME NOT FOUND")); - nodump = true; - break; - } - } - break; - } - - flagreader.Read(); - } - } - - // If the rom has a Date attached, read it in and then sanitize it - date = ""; - if (xtr.GetAttribute("date") != null) - { - date = DateTime.Parse(xtr.GetAttribute("date")).ToString(); - } - - // Take care of hex-sized files - size = -1; - if (xtr.GetAttribute("size") != null && xtr.GetAttribute("size").Contains("0x")) - { - size = Convert.ToInt64(xtr.GetAttribute("size"), 16); - } - else if (xtr.GetAttribute("size") != null) - { - Int64.TryParse(xtr.GetAttribute("size"), out size); - } - - // If the rom is continue or ignore, add the size to the previous rom - if (xtr.GetAttribute("loadflag") == "continue" || xtr.GetAttribute("loadflag") == "ignore") - { - int index = datdata.Hashes.Count() - 1; - HashData lasthash = datdata.Hashes[index]; - lasthash.Size += size; - datdata.Hashes.RemoveAt(index); - datdata.Hashes.Add(lasthash); - continue; - } - - // Sanitize the hashes from null, hex sizes, and "true blank" strings - crc = Style.CleanHashData(xtr.GetAttribute("crc"), Constants.CRCLength); - md5 = Style.CleanHashData(xtr.GetAttribute("md5"), Constants.MD5Length); - sha1 = Style.CleanHashData(xtr.GetAttribute("sha1"), Constants.SHA1Length); - - // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info - if (xtr.GetAttribute("type") == "rom" && (size == 0 || size == -1) && ((crc == Constants.CRCZero || crc == "") || md5 == Constants.MD5Zero || sha1 == Constants.SHA1Zero)) - { - size = Constants.SizeZero; - crc = Constants.CRCZero; - md5 = Constants.MD5Zero; - sha1 = Constants.SHA1Zero; - } - // If the file has no size and it's not the above case, skip and log - else if (xtr.GetAttribute("type") == "rom" && (size == 0 || size == -1)) - { - logger.Warning("Incomplete entry for \"" + xtr.GetAttribute("name") + "\" will be output as nodump"); - nodump = true; - } - - // Get the name of the game from the parent - tempname = String.Join("\\", parent); - - // If we aren't keeping names, trim out the path - if (!keep || !superdat) - { - string tempout = Regex.Match(tempname, @".*?\\(.*)").Groups[1].Value; - if (tempout != "") - { - tempname = tempout; - } - } - - // If we're in cleaning mode, sanitize the game name - tempname = (clean ? Style.CleanGameName(tempname) : tempname); - - // Only add the rom if there's useful information in it - if (!(crc == "" && md5 == "" && sha1 == "") || nodump) - { - // If we got to this point and it's a disk, log it because some tools don't like disks - if (xtr.GetAttribute("type") == "disk") - { - logger.Log("Disk found: \"" + xtr.GetAttribute("name") + "\""); - } - - // Now add the hash to the Dat - RomData romData = new RomData - { - Name = xtr.GetAttribute("name"), - Type = (xtr.GetAttribute("type").ToLowerInvariant() == "disk" ? ItemType.Disk : ItemType.Rom), - Nodump = nodump, - Date = date, - Machine = new MachineData - { - Name = tempname, - SystemID = sysid, - System = filename, - SourceID = srcid, - }, - }; - HashData hashData = new HashData - { - Size = size, - CRC = Style.CleanHashData(Style.StringToByteArray(crc), Constants.CRCBytesLength), - MD5 = Style.CleanHashData(Style.StringToByteArray(md5), Constants.MD5BytesLength), - SHA1 = Style.CleanHashData(Style.StringToByteArray(sha1), Constants.SHA1BytesLength), - Roms = new List(), - }; - - if (datdata.Hashes.Contains(hashData)) - { - datdata.Hashes[datdata.Hashes.IndexOf(hashData)].Roms.Add(romData); - } - else - { - hashData.Roms.Add(romData); - datdata.Hashes.Add(hashData); - } - - // Add statistical data - datdata.RomCount += (romData.Type == ItemType.Rom ? 1 : 0); - datdata.DiskCount += (romData.Type == ItemType.Disk ? 1 : 0); - datdata.TotalSize += (romData.Nodump ? 0 : hashData.Size); - datdata.CRCCount += (hashData.CRC == null ? 0 : 1); - datdata.MD5Count += (hashData.MD5 == null ? 0 : 1); - datdata.SHA1Count += (hashData.SHA1 == null ? 0 : 1); - datdata.NodumpCount += (romData.Nodump ? 1 : 0); - } - xtr.Read(); - break; - default: - xtr.Read(); - break; - } - } - - xtr.Close(); - xtr.Dispose(); - } - - return datdata; - } - - #endregion - - #region Bucketing methods - - /// - /// Take an arbitrarily ordered List and return a Dictionary sorted by Game - /// - /// Input unsorted list - /// True if roms should be deduped, false otherwise - /// True if games should only be compared on game and file name, false if system and source are counted - /// Logger object for file and console output - /// True if the number of hashes counted is to be output (default), false otherwise - /// SortedDictionary bucketed by game name - public static SortedDictionary> BucketByGame(List list, bool mergeroms, bool norename, Logger logger, bool output = true) - { - Dictionary> dict = new Dictionary>(); - dict.Add("key", list); - return BucketByGame(dict, mergeroms, norename, logger, output); - } - - /// - /// Take an arbitrarily bucketed Dictionary and return one sorted by Game - /// - /// Input unsorted dictionary - /// True if roms should be deduped, false otherwise - /// True if games should only be compared on game and file name, false if system and source are counted - /// Logger object for file and console output - /// True if the number of hashes counted is to be output (default), false otherwise - /// SortedDictionary bucketed by game name> BucketByGame(IDictionary> dict, bool mergeroms, bool norename, Logger logger, bool output = true) - { - SortedDictionary> sortable = new SortedDictionary>(); - long count = 0; - - // If we have a null dict or an empty one, output a new dictionary - if (dict == null || dict.Count == 0) - { - return sortable; - } - - // Process each all of the roms - foreach (string key in dict.Keys) - { - List hashes = dict[key]; - if (mergeroms) - { - hashes = RomToolsHash.Merge(hashes, logger); - } - - foreach (HashData hash in hashes) - { - count++; - string newkey = (norename ? "" - : hash.Roms[0].Machine.SystemID.ToString().PadLeft(10, '0') - + "-" - + hash.Roms[0].Machine.SourceID.ToString().PadLeft(10, '0') + "-") - + (String.IsNullOrEmpty(hash.Roms[0].Machine.Name) - ? "" - : hash.Roms[0].Machine.Name.ToLowerInvariant()); - if (sortable.ContainsKey(newkey)) - { - sortable[newkey].Add(hash); - } - else - { - List temp = new List(); - temp.Add(hash); - sortable.Add(newkey, temp); - } - } - } - - // Output the count if told to - if (output) - { - logger.User("A total of " + count + " file hashes will be written out to file"); - } - - return sortable; - } - - /// - /// Take an arbitrarily ordered List and return a Dictionary sorted by size and hash - /// - /// Input unsorted list - /// True if roms should be deduped, false otherwise - /// True if games should only be compared on game and file name, false if system and source are counted - /// Logger object for file and console output - /// True if the number of hashes counted is to be output (default), false otherwise - /// SortedDictionary bucketed by size and hash - public static SortedDictionary> BucketByHashSize(List list, bool mergeroms, bool norename, Logger logger, bool output = true) - { - Dictionary> dict = new Dictionary>(); - dict.Add("key", list); - return BucketByHashSize(dict, mergeroms, norename, logger, output); - } - - /// - /// Take an arbitrarily bucketed Dictionary and return one sorted by size and hash - /// - /// Input unsorted dictionary - /// True if roms should be deduped, false otherwise - /// True if games should only be compared on game and file name, false if system and source are counted - /// Logger object for file and console output - /// True if the number of hashes counted is to be output (default), false otherwise - /// SortedDictionary bucketed by size and hash - public static SortedDictionary> BucketByHashSize(IDictionary> dict, bool mergeroms, bool norename, Logger logger, bool output = true) - { - SortedDictionary> sortable = new SortedDictionary>(); - long count = 0; - - // If we have a null dict or an empty one, output a new dictionary - if (dict == null || dict.Count == 0) - { - return sortable; - } - - // Process each all of the roms - foreach (List hashes in dict.Values) - { - List newhashes = hashes; - if (mergeroms) - { - newhashes = RomToolsHash.Merge(newhashes, logger); - } - - foreach (HashData hash in newhashes) - { - count++; - string key = hash.Size + "-" + BitConverter.ToString(hash.CRC).Replace("-", string.Empty); - if (sortable.ContainsKey(key)) - { - sortable[key].Add(hash); - } - else - { - List temp = new List(); - temp.Add(hash); - sortable.Add(key, temp); - } - } - } - - // Output the count if told to - if (output) - { - logger.User("A total of " + count + " file hashes will be written out to file"); - } - - return sortable; - } - - #endregion - - #region Converting and updating - - #endregion - } -} diff --git a/SabreTools.Helper/Tools/FileTools.cs b/SabreTools.Helper/Tools/FileTools.cs index c669aca5..ff4118d6 100644 --- a/SabreTools.Helper/Tools/FileTools.cs +++ b/SabreTools.Helper/Tools/FileTools.cs @@ -63,7 +63,7 @@ namespace SabreTools.Helper } // Get the output archive name from the first rebuild rom - string archiveFileName = Path.Combine(outDir, roms[0].Machine.Name + ".zip"); + string archiveFileName = Path.Combine(outDir, roms[0].MachineName + ".zip"); // First, open the archive ZipArchive outarchive = null; @@ -172,7 +172,7 @@ namespace SabreTools.Helper } // Get the output archive name from the first rebuild rom - string archiveFileName = Path.Combine(outDir, roms[0].Machine.Name + ".zip"); + string archiveFileName = Path.Combine(outDir, roms[0].MachineName + ".zip"); // Set internal variables Stream writeStream = null; @@ -760,18 +760,21 @@ namespace SabreTools.Helper } crc.Update(buffer, 0, 0); - rom.HashData.CRC = crc.Value.ToString("X8").ToLowerInvariant(); + Hash tempHash = new Hash(); + tempHash.CRC = crc.Value.ToString("X8").ToLowerInvariant(); if (!noMD5) { md5.TransformFinalBlock(buffer, 0, 0); - rom.HashData.MD5 = BitConverter.ToString(md5.Hash).Replace("-", "").ToLowerInvariant(); + tempHash.MD5 = BitConverter.ToString(md5.Hash).Replace("-", "").ToLowerInvariant(); } if (!noSHA1) { sha1.TransformFinalBlock(buffer, 0, 0); - rom.HashData.SHA1 = BitConverter.ToString(sha1.Hash).Replace("-", "").ToLowerInvariant(); + tempHash.SHA1 = BitConverter.ToString(sha1.Hash).Replace("-", "").ToLowerInvariant(); } + + rom.HashData = tempHash; } } catch (IOException) @@ -860,10 +863,7 @@ namespace SabreTools.Helper { Type = ItemType.Rom, Name = reader.Entry.Key, - Machine = new Machine - { - Name = gamename, - }, + MachineName = gamename, HashData = new Hash { Size = (size == 0 ? reader.Entry.Size : size), @@ -948,10 +948,7 @@ namespace SabreTools.Helper Rom rom = new Rom { Type = ItemType.Rom, - Machine = new Machine - { - Name = Path.GetFileNameWithoutExtension(input).ToLowerInvariant(), - }, + MachineName = Path.GetFileNameWithoutExtension(input).ToLowerInvariant(), Name = Path.GetFileNameWithoutExtension(input).ToLowerInvariant(), HashData = new Hash { diff --git a/SabreTools.Helper/Tools/RomTools.cs b/SabreTools.Helper/Tools/RomTools.cs deleted file mode 100644 index 35592988..00000000 --- a/SabreTools.Helper/Tools/RomTools.cs +++ /dev/null @@ -1,505 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace SabreTools.Helper -{ - public class RomTools - { - #region Rom-based sorting and merging - - /// - /// Determine if a rom should be included based on filters - /// - /// User supplied Rom to check - /// Name of the game to match (can use asterisk-partials) - /// Name of the rom to match (can use asterisk-partials) - /// Type of the rom to match - /// Find roms greater than or equal to this size - /// Find roms less than or equal to this size - /// Find roms equal to this size - /// CRC of the rom to match (can use asterisk-partials) - /// MD5 of the rom to match (can use asterisk-partials) - /// SHA-1 of the rom to match (can use asterisk-partials) - /// Select roms with nodump status as follows: null (match all), true (match Nodump only), false (exclude Nodump) - /// Logging object for console and file output - /// Returns true if it should be included, false otherwise - public static bool Filter(Rom romdata, string gamename, string romname, string romtype, long sgt, - long slt, long seq, string crc, string md5, string sha1, bool? nodump, Logger logger) - { - // Filter on nodump status - if (nodump == true && !romdata.Nodump) - { - return false; - } - if (nodump == false && romdata.Nodump) - { - return false; - } - - // Filter on game name - if (!String.IsNullOrEmpty(gamename)) - { - if (gamename.StartsWith("*") && gamename.EndsWith("*")) - { - if (!romdata.Machine.Name.ToLowerInvariant().Contains(gamename.ToLowerInvariant().Replace("*", ""))) - { - return false; - } - } - else if (gamename.StartsWith("*")) - { - if (!romdata.Machine.Name.EndsWith(gamename.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - else if (gamename.EndsWith("*")) - { - if (!romdata.Machine.Name.StartsWith(gamename.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - else - { - if (!String.Equals(romdata.Machine.Name, gamename, StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - } - - // Filter on rom name - if (!String.IsNullOrEmpty(romname)) - { - if (romname.StartsWith("*") && romname.EndsWith("*")) - { - if (!romdata.Name.ToLowerInvariant().Contains(romname.ToLowerInvariant().Replace("*", ""))) - { - return false; - } - } - else if (romname.StartsWith("*")) - { - if (!romdata.Name.EndsWith(romname.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - else if (romname.EndsWith("*")) - { - if (!romdata.Name.StartsWith(romname.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - else - { - if (!String.Equals(romdata.Name, romname, StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - } - - // Filter on rom type - if (String.IsNullOrEmpty(romtype) && romdata.Type != ItemType.Rom && romdata.Type != ItemType.Disk) - { - return false; - } - if (!String.IsNullOrEmpty(romtype) && !String.Equals(romdata.Type.ToString(), romtype, StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - - // Filter on rom size - if (seq != -1 && romdata.HashData.Size != seq) - { - return false; - } - else - { - if (sgt != -1 && romdata.HashData.Size < sgt) - { - return false; - } - if (slt != -1 && romdata.HashData.Size > slt) - { - return false; - } - } - - // Filter on crc - if (!String.IsNullOrEmpty(crc)) - { - if (crc.StartsWith("*") && crc.EndsWith("*")) - { - if (!romdata.HashData.CRC.ToLowerInvariant().Contains(crc.ToLowerInvariant().Replace("*", ""))) - { - return false; - } - } - else if (crc.StartsWith("*")) - { - if (!romdata.HashData.CRC.EndsWith(crc.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - else if (crc.EndsWith("*")) - { - if (!romdata.HashData.CRC.StartsWith(crc.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - else - { - if (!String.Equals(romdata.HashData.CRC, crc, StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - } - - // Filter on md5 - if (!String.IsNullOrEmpty(md5)) - { - if (md5.StartsWith("*") && md5.EndsWith("*")) - { - if (!romdata.HashData.MD5.ToLowerInvariant().Contains(md5.ToLowerInvariant().Replace("*", ""))) - { - return false; - } - } - else if (md5.StartsWith("*")) - { - if (!romdata.HashData.MD5.EndsWith(md5.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - else if (md5.EndsWith("*")) - { - if (!romdata.HashData.MD5.StartsWith(md5.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - else - { - if (!String.Equals(romdata.HashData.MD5, md5, StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - } - - // Filter on sha1 - if (!String.IsNullOrEmpty(sha1)) - { - if (sha1.StartsWith("*") && sha1.EndsWith("*")) - { - if (!romdata.HashData.SHA1.ToLowerInvariant().Contains(sha1.ToLowerInvariant().Replace("*", ""))) - { - return false; - } - } - else if (sha1.StartsWith("*")) - { - if (!romdata.HashData.SHA1.EndsWith(sha1.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - else if (sha1.EndsWith("*")) - { - if (!romdata.HashData.SHA1.StartsWith(sha1.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - else - { - if (!String.Equals(romdata.HashData.SHA1, sha1, StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - } - } - - return true; - } - - /// - /// Merge an arbitrary set of ROMs based on the supplied information - /// - /// List of RomData objects representing the roms to be merged - /// Logger object for console and/or file output - /// A List of RomData objects representing the merged roms - public static List Merge(List inroms, Logger logger) - { - // Check for null or blank roms first - if (inroms == null || inroms.Count == 0) - { - return new List(); - } - - // Create output list - List outroms = new List(); - - // Then deduplicate them by checking to see if data matches previous saved roms - foreach (Rom rom in inroms) - { - // If it's a nodump, add and skip - if (rom.Nodump) - { - outroms.Add(rom); - continue; - } - - // If it's the first rom in the list, don't touch it - if (outroms.Count != 0) - { - // Check if the rom is a duplicate - DupeType dupetype = DupeType.None; - Rom savedrom = new Rom(); - int pos = -1; - for (int i = 0; i < outroms.Count; i++) - { - Rom lastrom = outroms[i]; - - // Get the duplicate status - dupetype = GetDuplicateStatus(rom, lastrom, logger); - - // If it's a duplicate, skip adding it to the output but add any missing information - if (dupetype != DupeType.None) - { - savedrom = lastrom; - pos = i; - - savedrom.HashData.CRC = (String.IsNullOrEmpty(savedrom.HashData.CRC) && !String.IsNullOrEmpty(rom.HashData.CRC) ? rom.HashData.CRC : savedrom.HashData.CRC); - savedrom.HashData.MD5 = (String.IsNullOrEmpty(savedrom.HashData.MD5) && !String.IsNullOrEmpty(rom.HashData.MD5) ? rom.HashData.MD5 : savedrom.HashData.MD5); - savedrom.HashData.SHA1 = (String.IsNullOrEmpty(savedrom.HashData.SHA1) && !String.IsNullOrEmpty(rom.HashData.SHA1) ? rom.HashData.SHA1 : savedrom.HashData.SHA1); - savedrom.Dupe = dupetype; - - // If the current system has a lower ID than the previous, set the system accordingly - if (rom.Metadata.SystemID < savedrom.Metadata.SystemID) - { - savedrom.Metadata.SystemID = rom.Metadata.SystemID; - savedrom.Metadata.System = rom.Metadata.System; - savedrom.Machine.Name = rom.Machine.Name; - savedrom.Name = rom.Name; - } - - // If the current source has a lower ID than the previous, set the source accordingly - if (rom.Metadata.SourceID < savedrom.Metadata.SourceID) - { - savedrom.Metadata.SourceID = rom.Metadata.SourceID; - savedrom.Metadata.Source = rom.Metadata.Source; - savedrom.Machine.Name = rom.Machine.Name; - savedrom.Name = rom.Name; - } - - break; - } - } - - // If no duplicate is found, add it to the list - if (dupetype == DupeType.None) - { - outroms.Add(rom); - } - // Otherwise, if a new rom information is found, add that - else - { - outroms.RemoveAt(pos); - outroms.Insert(pos, savedrom); - } - } - else - { - outroms.Add(rom); - } - } - - // Then return the result - return outroms; - } - - /// - /// List all duplicates found in a DAT based on a rom - /// - /// Rom to use as a base - /// DAT to match against - /// Logger object for console and/or file output - /// True to remove matched roms from the input, false otherwise (default) - /// List of matched RomData objects - public static List GetDuplicates(Rom lastrom, Dat datdata, Logger logger, bool remove = false) - { - List output = new List(); - - // Check for an empty rom list first - if (datdata.Files == null || datdata.Files.Count == 0) - { - return output; - } - - // Try to find duplicates - List keys = datdata.Files.Keys.ToList(); - foreach (string key in keys) - { - List roms = datdata.Files[key]; - List left = new List(); - - foreach (Rom rom in roms) - { - if (IsDuplicate(rom, lastrom, logger)) - { - output.Add(rom); - } - else - { - left.Add(rom); - } - } - - // If we're in removal mode, replace the list with the new one - if (remove) - { - datdata.Files[key] = left; - } - } - - return output; - } - - /// - /// Determine if a file is a duplicate using partial matching logic - /// - /// Rom to check for duplicate status - /// Rom to use as a baseline - /// Logger object for console and/or file output - /// True if the roms are duplicates, false otherwise - public static bool IsDuplicate(Rom rom, Rom lastrom, Logger logger) - { - bool dupefound = rom.Equals(lastrom); - - // More wonderful SHA-1 logging that has to be done - if (rom.HashData.SHA1 == lastrom.HashData.SHA1 && rom.HashData.Size != lastrom.HashData.Size) - { - logger.User("SHA-1 mismatch - Hash: " + rom.HashData.SHA1); - } - - return dupefound; - } - - /// - /// Return the duplicate status of two roms - /// - /// Current rom to check - /// Last rom to check against - /// Logger object for console and/or file output - /// The DupeType corresponding to the relationship between the two - public static DupeType GetDuplicateStatus(Rom rom, Rom lastrom, Logger logger) - { - DupeType output = DupeType.None; - - // If we don't have a duplicate at all, return none - if (!IsDuplicate(rom, lastrom, logger)) - { - return output; - } - - // If the duplicate is external already or should be, set it - if (lastrom.Dupe >= DupeType.ExternalHash || lastrom.Metadata.SystemID != rom.Metadata.SystemID || lastrom.Metadata.SourceID != rom.Metadata.SourceID) - { - if (lastrom.Machine.Name == rom.Machine.Name && lastrom.Name == rom.Name) - { - output = DupeType.ExternalAll; - } - else - { - output = DupeType.ExternalHash; - } - } - - // Otherwise, it's considered an internal dupe - else - { - if (lastrom.Machine.Name == rom.Machine.Name && lastrom.Name == rom.Name) - { - output = DupeType.InternalAll; - } - else - { - output = DupeType.InternalHash; - } - } - - return output; - } - - /// - /// Sort a list of RomData objects by SystemID, SourceID, Game, and Name (in order) - /// - /// List of RomData objects representing the roms to be sorted - /// True if files are not renamed, false otherwise - /// True if it sorted correctly, false otherwise - public static bool Sort(ref List roms, bool norename) - { - try - { - roms.Sort(delegate (Rom x, Rom y) - { - if (x.Metadata.SystemID == y.Metadata.SystemID) - { - if (x.Metadata.SourceID == y.Metadata.SourceID) - { - if (x.Machine.Name == y.Machine.Name) - { - if ((x.Type == ItemType.Rom || x.Type == ItemType.Disk) && (y.Type == ItemType.Rom || y.Type == ItemType.Disk)) - { - if (Path.GetDirectoryName(x.Name) == Path.GetDirectoryName(y.Name)) - { - return Style.CompareNumeric(Path.GetFileName(x.Name), Path.GetFileName(y.Name)); - } - return Style.CompareNumeric(Path.GetDirectoryName(x.Name), Path.GetDirectoryName(y.Name)); - } - else if ((x.Type == ItemType.Rom || x.Type == ItemType.Disk) && (y.Type != ItemType.Rom && y.Type != ItemType.Disk)) - { - return -1; - } - else if ((x.Type != ItemType.Rom && x.Type != ItemType.Disk) && (y.Type == ItemType.Rom || y.Type == ItemType.Disk)) - { - return 1; - } - else - { - if (Path.GetDirectoryName(x.Name) == Path.GetDirectoryName(y.Name)) - { - return Style.CompareNumeric(Path.GetFileName(x.Name), Path.GetFileName(y.Name)); - } - return Style.CompareNumeric(Path.GetDirectoryName(x.Name), Path.GetDirectoryName(y.Name)); - } - } - return Style.CompareNumeric(x.Machine.Name, y.Machine.Name); - } - return (norename ? Style.CompareNumeric(x.Machine.Name, y.Machine.Name) : x.Metadata.SourceID - y.Metadata.SourceID); - } - return (norename ? Style.CompareNumeric(x.Machine.Name, y.Machine.Name) : x.Metadata.SystemID - y.Metadata.SystemID); - }); - return true; - } - catch (Exception) - { - // Absorb the error - return false; - } - } - - #endregion - } -} diff --git a/SabreTools.Helper/Tools/RomToolsHash.cs b/SabreTools.Helper/Tools/RomToolsHash.cs deleted file mode 100644 index 632295c2..00000000 --- a/SabreTools.Helper/Tools/RomToolsHash.cs +++ /dev/null @@ -1,225 +0,0 @@ -using System.Collections.Generic; - -namespace SabreTools.Helper -{ - public class RomToolsHash - { - #region HashData-based sorting and merging - - /// - /// Merge an arbitrary set of ROMs based on the supplied information - /// - /// List of HashData objects representing the roms to be merged - /// Logger object for console and/or file output - /// A List of HashData objects representing the merged roms - public static List Merge(List inhashes, Logger logger) - { - // Create output list - List outroms = new List(); - - // Check for null or blank roms first - if (inhashes == null || inhashes.Count == 0) - { - return outroms; - } - - // Then deduplicate them by checking to see if data matches previous saved roms - foreach (HashData hash in inhashes) - { - // If it's a nodump, add and skip - if (hash.Roms[0].Nodump) - { - outroms.Add(hash); - continue; - } - - // If it's the first rom in the list, don't touch it - if (outroms.Count != 0) - { - // Check if the rom is a duplicate - DupeType dupetype = DupeType.None; - HashData savedHash = new HashData(); - int pos = -1; - for (int i = 0; i < outroms.Count; i++) - { - HashData lastrom = outroms[i]; - RomData savedRom = savedHash.Roms[0]; - MachineData savedMachine = savedRom.Machine; - - // Get the duplicate status - dupetype = GetDuplicateStatus(hash, lastrom, logger); - - // If it's a duplicate, skip adding it to the output but add any missing information - if (dupetype != DupeType.None) - { - savedHash = lastrom; - pos = i; - - savedHash.CRC = (savedHash.CRC == null && hash.CRC != null ? hash.CRC : savedHash.CRC); - savedHash.MD5 = (savedHash.MD5 == null && hash.MD5 != null ? hash.MD5 : savedHash.MD5); - savedHash.SHA1 = (savedHash.SHA1 == null && hash.SHA1 != null ? hash.SHA1 : savedHash.SHA1); - savedRom.DupeType = dupetype; - - // If the current system has a lower ID than the previous, set the system accordingly - if (hash.Roms[0].Machine.SystemID < savedMachine.SystemID) - { - savedMachine.SystemID = hash.Roms[0].Machine.SystemID; - savedMachine.System = hash.Roms[0].Machine.System; - savedMachine.Name = hash.Roms[0].Machine.Name; - savedRom.Name = hash.Roms[0].Name; - } - - // If the current source has a lower ID than the previous, set the source accordingly - if (hash.Roms[0].Machine.SourceID < savedMachine.SourceID) - { - savedMachine.SourceID = hash.Roms[0].Machine.SourceID; - savedMachine.Source = hash.Roms[0].Machine.Source; - savedMachine.Name = hash.Roms[0].Machine.Name; - savedRom.Name = hash.Roms[0].Name; - } - - break; - } - } - - // If no duplicate is found, add it to the list - if (dupetype == DupeType.None) - { - outroms.Add(hash); - } - // Otherwise, if a new rom information is found, add that - else - { - outroms.RemoveAt(pos); - outroms.Insert(pos, savedHash); - } - } - else - { - outroms.Add(hash); - } - } - - // Then return the result - return outroms; - } - - /* - /// - /// List all duplicates found in a DAT based on a rom - /// - /// Hash to use as a base - /// DAT to match against - /// Logger object for console and/or file output - /// True to remove matched roms from the input, false otherwise (default) - /// List of matched HashData objects - public static List GetDuplicates(HashData lastrom, DatData datdata, Logger logger, bool remove = false) - { - List output = new List(); - - // Check for an empty rom list first - if (datdata.Hashes == null || datdata.Hashes.Count == 0) - { - return output; - } - - // Try to find duplicates - for (int i = 0; i < datdata.Hashes.Count; i++) - { - - List roms = datdata.Files[key]; - List left = new List(); - foreach (Rom rom in roms) - { - if (IsDuplicate(rom, lastrom, logger)) - { - output.Add(rom); - } - else - { - left.Add(rom); - } - } - - // If we're in removal mode, replace the list with the new one - if (remove) - { - datdata.Files[key] = left; - } - } - - return output; - } - */ - - /// - /// Determine if a file is a duplicate using partial matching logic - /// - /// Hash to check for duplicate status - /// Hash to use as a baseline - /// Logger object for console and/or file output - /// True if the hashes are duplicates, false otherwise - public static bool IsDuplicate(HashData hash, int hashIndex, HashData lastHash, int lastHashIndex, Logger logger) - { - bool dupefound = hash.Equals(lastHash); - - // More wonderful SHA-1 logging that has to be done - if (hash.SHA1 == lastHash.SHA1 && hash.Size != lastHash.Size) - { - logger.User("SHA-1 mismatch - Hash: " + hash.SHA1); - } - - return dupefound; - } - - /// - /// Return the duplicate status of two hashes - /// - /// Current hash to check - /// Last hash to check against - /// Logger object for console and/or file output - /// The DupeType corresponding to the relationship between the two - public static DupeType GetDuplicateStatus(HashData hash, HashData lasthash, Logger logger) - { - DupeType output = DupeType.None; - - /* - // If we don't have a duplicate at all, return none - if (!IsDuplicate(hash, lasthash, logger)) - { - return output; - } - */ - - // If the duplicate is external already or should be, set it - if (lasthash.Roms[0].DupeType >= DupeType.ExternalHash || lasthash.Roms[0].Machine.SystemID != hash.Roms[0].Machine.SystemID || lasthash.Roms[0].Machine.SourceID != hash.Roms[0].Machine.SourceID) - { - if (lasthash.Roms[0].Machine.Name == hash.Roms[0].Machine.Name && lasthash.Roms[0].Name == hash.Roms[0].Name) - { - output = DupeType.ExternalAll; - } - else - { - output = DupeType.ExternalHash; - } - } - - // Otherwise, it's considered an internal dupe - else - { - if (lasthash.Roms[0].Machine.Name == hash.Roms[0].Machine.Name && lasthash.Roms[0].Name == hash.Roms[0].Name) - { - output = DupeType.InternalAll; - } - else - { - output = DupeType.InternalHash; - } - } - - return output; - } - - #endregion - } -} diff --git a/SabreTools/Partials/SabreTools_Inits.cs b/SabreTools/Partials/SabreTools_Inits.cs index 62ca2fcb..231afd17 100644 --- a/SabreTools/Partials/SabreTools_Inits.cs +++ b/SabreTools/Partials/SabreTools_Inits.cs @@ -140,7 +140,7 @@ namespace SabreTools OutputFormat = (outputFormat == 0 ? OutputFormat.Xml : outputFormat), Romba = romba, Type = (superdat ? "SuperDAT" : ""), - Files = new Dictionary>(), + Files = new Dictionary>(), }; // For each input directory, create a DAT @@ -150,7 +150,7 @@ namespace SabreTools { // Clone the base Dat for information Dat datdata = (Dat)basedat.Clone(); - datdata.Files = new Dictionary>(); + datdata.Files = new Dictionary>(); string basePath = Path.GetFullPath(path); DATFromDir dfd = new DATFromDir(basePath, datdata, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, addBlanks, addDate, tempDir, maxDegreeOfParallelism, _logger);