From bb622248581cdd94294657a0f651e70c0d45f55e Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 17 Jan 2018 13:01:33 -0800 Subject: [PATCH] [ClrMamePro] Fix and use new parser --- SabreTools.Library/DatFiles/ClrMamePro.cs | 571 +--------------------- 1 file changed, 8 insertions(+), 563 deletions(-) diff --git a/SabreTools.Library/DatFiles/ClrMamePro.cs b/SabreTools.Library/DatFiles/ClrMamePro.cs index e0fd9a35..c6265923 100644 --- a/SabreTools.Library/DatFiles/ClrMamePro.cs +++ b/SabreTools.Library/DatFiles/ClrMamePro.cs @@ -59,561 +59,6 @@ namespace SabreTools.Library.DatFiles Encoding enc = Utilities.GetEncoding(filename); StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc); - bool block = false, superdat = false, containsItems = false; - string blockname = "", tempgamename = "", gamedesc = "", cloneof = "", - romof = "", sampleof = "", year = "", manufacturer = ""; - 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" || gc[1].Value.ToLowerInvariant() == "doscenter") - { - blockname = "header"; - } - - block = true; - containsItems = false; - } - - // If the line is a rom-like item and we're in a block - else if ((line.Trim().StartsWith("rom (") - || line.Trim().StartsWith("disk (") - || line.Trim().StartsWith("file (") - || (line.Trim().StartsWith("sample") && !line.Trim().StartsWith("sampleof")) - ) && block) - { - containsItems = true; - ItemType temptype = ItemType.Rom; - if (line.Trim().StartsWith("rom (")) - { - temptype = ItemType.Rom; - } - else if (line.Trim().StartsWith("disk (")) - { - temptype = ItemType.Disk; - } - else if (line.Trim().StartsWith("file (")) - { - temptype = ItemType.Rom; - } - else if (line.Trim().StartsWith("sample")) - { - temptype = ItemType.Sample; - } - - // Create the proper DatItem based on the type - DatItem item = Utilities.GetDatItem(temptype); - - // 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; - - // 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 - item.Name = line; - - // Now process and add the sample - ParseAddHelper(item, clean, remUnicode); - - continue; - } - - // Get the line split by spaces and quotes - string[] gc = Utilities.SplitLineAsCMP(line); - - // Special cases for DOSCenter DATs only because of how the lines are arranged - if (line.Trim().StartsWith("file (")) - { - // Loop over the specifics - for (int i = 0; i < gc.Length; i++) - { - // Names are not quoted, for some stupid reason - if (gc[i] == "name") - { - // Get the name in order until we find the next flag - while (++i < gc.Length && gc[i] != "size" && gc[i] != "date" && gc[i] != "crc" && gc[i] != "md5" - && gc[i] != "sha1" && gc[i] != "sha256" && gc[i] != "sha384" && gc[i] != "sha512") - { - item.Name += " " + gc[i]; - } - - // Perform correction - item.Name = item.Name.TrimStart(); - i--; - } - - // Get the size from the next part - else if (gc[i] == "size") - { - long tempsize = -1; - if (!Int64.TryParse(gc[++i], out tempsize)) - { - tempsize = 0; - } - ((Rom)item).Size = tempsize; - } - - // Get the date from the next part - else if (gc[i] == "date") - { - ((Rom)item).Date = gc[++i].Replace("\"", "") + " " + gc[++i].Replace("\"", ""); - } - - // Get the CRC from the next part - else if (gc[i] == "crc") - { - ((Rom)item).CRC = gc[++i].Replace("\"", "").ToLowerInvariant(); - } - - // Get the MD5 from the next part - else if (gc[i] == "md5") - { - ((Rom)item).MD5 = gc[++i].Replace("\"", "").ToLowerInvariant(); - } - - // Get the SHA1 from the next part - else if (gc[i] == "sha1") - { - ((Rom)item).SHA1 = gc[++i].Replace("\"", "").ToLowerInvariant(); - } - - // Get the SHA256 from the next part - else if (gc[i] == "sha256") - { - ((Rom)item).SHA256 = gc[++i].Replace("\"", "").ToLowerInvariant(); - } - - // Get the SHA384 from the next part - else if (gc[i] == "sha384") - { - ((Rom)item).SHA384 = gc[++i].Replace("\"", "").ToLowerInvariant(); - } - - // Get the SHA512 from the next part - else if (gc[i] == "sha512") - { - ((Rom)item).SHA512 = gc[++i].Replace("\"", "").ToLowerInvariant(); - } - } - - // Now process and add the rom - ParseAddHelper(item, clean, remUnicode); - continue; - } - - // Loop over all attributes normally and add them if possible - for (int i = 0; i < gc.Length; i++) - { - // Look at the current item and use it if possible - string quoteless = gc[i].Replace("\"", ""); - switch (quoteless) - { - //If the item is empty, we automatically skip it because it's a fluke - case "": - continue; - - // Special cases for standalone item statuses - case "baddump": - if (item.Type == ItemType.Rom) - { - ((Rom)item).ItemStatus = ItemStatus.BadDump; - } - else if (item.Type == ItemType.Disk) - { - ((Disk)item).ItemStatus = ItemStatus.BadDump; - } - break; - case "good": - if (item.Type == ItemType.Rom) - { - ((Rom)item).ItemStatus = ItemStatus.Good; - } - else if (item.Type == ItemType.Disk) - { - ((Disk)item).ItemStatus = ItemStatus.Good; - } - break; - case "nodump": - if (item.Type == ItemType.Rom) - { - ((Rom)item).ItemStatus = ItemStatus.Nodump; - } - else if (item.Type == ItemType.Disk) - { - ((Disk)item).ItemStatus = ItemStatus.Nodump; - } - break; - case "verified": - if (item.Type == ItemType.Rom) - { - ((Rom)item).ItemStatus = ItemStatus.Verified; - } - else if (item.Type == ItemType.Disk) - { - ((Disk)item).ItemStatus = ItemStatus.Verified; - } - break; - - // Regular attributes - case "name": - quoteless = gc[++i].Replace("\"", ""); - item.Name = quoteless; - break; - case "size": - if (item.Type == ItemType.Rom) - { - quoteless = gc[++i].Replace("\"", ""); - if (Int64.TryParse(quoteless, out long size)) - { - ((Rom)item).Size = size; - } - else - { - ((Rom)item).Size = -1; - } - } - break; - case "crc": - if (item.Type == ItemType.Rom) - { - quoteless = gc[++i].Replace("\"", ""); - ((Rom)item).CRC = quoteless.ToLowerInvariant(); - } - break; - case "md5": - if (item.Type == ItemType.Rom) - { - quoteless = gc[++i].Replace("\"", ""); - ((Rom)item).MD5 = quoteless.ToLowerInvariant(); - } - else if (item.Type == ItemType.Disk) - { - i++; - quoteless = gc[i].Replace("\"", ""); - ((Disk)item).MD5 = quoteless.ToLowerInvariant(); - } - break; - case "sha1": - if (item.Type == ItemType.Rom) - { - quoteless = gc[++i].Replace("\"", ""); - ((Rom)item).SHA1 = quoteless.ToLowerInvariant(); - } - else if (item.Type == ItemType.Disk) - { - quoteless = gc[++i].Replace("\"", ""); - ((Disk)item).SHA1 = quoteless.ToLowerInvariant(); - } - break; - case "sha256": - if (item.Type == ItemType.Rom) - { - quoteless = gc[++i].Replace("\"", ""); - ((Rom)item).SHA256 = quoteless.ToLowerInvariant(); - } - else if (item.Type == ItemType.Disk) - { - quoteless = gc[++i].Replace("\"", ""); - ((Disk)item).SHA256 = quoteless.ToLowerInvariant(); - } - break; - case "sha384": - if (item.Type == ItemType.Rom) - { - quoteless = gc[++i].Replace("\"", ""); - ((Rom)item).SHA384 = quoteless.ToLowerInvariant(); - } - else if (item.Type == ItemType.Disk) - { - quoteless = gc[++i].Replace("\"", ""); - ((Disk)item).SHA384 = quoteless.ToLowerInvariant(); - } - break; - case "sha512": - if (item.Type == ItemType.Rom) - { - quoteless = gc[++i].Replace("\"", ""); - ((Rom)item).SHA512 = quoteless.ToLowerInvariant(); - } - else if (item.Type == ItemType.Disk) - { - quoteless = gc[++i].Replace("\"", ""); - ((Disk)item).SHA512 = quoteless.ToLowerInvariant(); - } - break; - case "status": - case "flags": - quoteless = gc[++i].Replace("\"", ""); - if (quoteless.ToLowerInvariant() == "good") - { - if (item.Type == ItemType.Rom) - { - ((Rom)item).ItemStatus = ItemStatus.Good; - } - else if (item.Type == ItemType.Disk) - { - ((Disk)item).ItemStatus = ItemStatus.Good; - } - } - else if (quoteless.ToLowerInvariant() == "baddump") - { - if (item.Type == ItemType.Rom) - { - ((Rom)item).ItemStatus = ItemStatus.BadDump; - } - else if (item.Type == ItemType.Disk) - { - ((Disk)item).ItemStatus = ItemStatus.BadDump; - } - } - else if (quoteless.ToLowerInvariant() == "nodump") - { - if (item.Type == ItemType.Rom) - { - ((Rom)item).ItemStatus = ItemStatus.Nodump; - } - else if (item.Type == ItemType.Disk) - { - ((Disk)item).ItemStatus = ItemStatus.Nodump; - } - } - else if (quoteless.ToLowerInvariant() == "verified") - { - if (item.Type == ItemType.Rom) - { - ((Rom)item).ItemStatus = ItemStatus.Verified; - } - else if (item.Type == ItemType.Disk) - { - ((Disk)item).ItemStatus = ItemStatus.Verified; - } - } - break; - case "date": - if (item.Type == ItemType.Rom) - { - // If we have quotes in the next item, assume only one item - if (gc[i + 1].Contains("\"")) - { - quoteless = gc[++i].Replace("\"", ""); - } - // Otherwise, we assume we need to read the next two items - else - { - quoteless = gc[++i].Replace("\"", "") + " " + gc[++i].Replace("\"", ""); - } - ((Rom)item).Date = quoteless; - } - break; - } - } - - // Now process and add the rom - ParseAddHelper(item, clean, remUnicode); - } - - // 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 (blockname != "header") - { - string itemval = gc[2].Value.Replace("\"", ""); - switch (gc[1].Value) - { - case "name": - tempgamename = (itemval.ToLowerInvariant().EndsWith(".zip") ? itemval.Remove(itemval.Length - 4) : itemval); - break; - case "description": - gamedesc = itemval; - break; - case "romof": - romof = itemval; - break; - case "cloneof": - cloneof = itemval; - break; - case "year": - year = itemval; - break; - case "manufacturer": - manufacturer = itemval; - break; - case "sampleof": - sampleof = itemval; - break; - } - } - else - { - string itemval = gc[2].Value.Replace("\"", ""); - - if (line.Trim().StartsWith("Name:")) - { - Name = (String.IsNullOrWhiteSpace(Name) ? line.Substring(6) : Name); - superdat = superdat || itemval.Contains(" - SuperDAT"); - if (keep && superdat) - { - Type = (String.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type); - } - continue; - } - - switch (gc[1].Value) - { - case "name": - case "Name:": - Name = (String.IsNullOrWhiteSpace(Name) ? itemval : Name); - superdat = superdat || itemval.Contains(" - SuperDAT"); - if (keep && superdat) - { - Type = (String.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type); - } - break; - case "description": - case "Description:": - Description = (String.IsNullOrWhiteSpace(Description) ? itemval : Description); - break; - case "rootdir": - RootDir = (String.IsNullOrWhiteSpace(RootDir) ? itemval : RootDir); - break; - case "category": - Category = (String.IsNullOrWhiteSpace(Category) ? itemval : Category); - break; - case "version": - case "Version:": - Version = (String.IsNullOrWhiteSpace(Version) ? itemval : Version); - break; - case "date": - case "Date:": - Date = (String.IsNullOrWhiteSpace(Date) ? itemval : Date); - break; - case "author": - case "Author:": - Author = (String.IsNullOrWhiteSpace(Author) ? itemval : Author); - break; - case "email": - Email = (String.IsNullOrWhiteSpace(Email) ? itemval : Email); - break; - case "homepage": - case "Homepage:": - Homepage = (String.IsNullOrWhiteSpace(Homepage) ? itemval : Homepage); - break; - case "url": - Url = (String.IsNullOrWhiteSpace(Url) ? itemval : Url); - break; - case "comment": - case "Comment:": - Comment = (String.IsNullOrWhiteSpace(Comment) ? itemval : Comment); - break; - case "header": - Header = (String.IsNullOrWhiteSpace(Header) ? itemval : Header); - break; - case "type": - Type = (String.IsNullOrWhiteSpace(Type) ? itemval : Type); - superdat = superdat || itemval.Contains("SuperDAT"); - break; - case "forcemerging": - if (ForceMerging == ForceMerging.None) - { - ForceMerging = Utilities.GetForceMerging(itemval); - } - break; - case "forcezipping": - if (ForcePacking == ForcePacking.None) - { - ForcePacking = Utilities.GetForcePacking(itemval); - } - break; - case "forcepacking": - if (ForcePacking == ForcePacking.None) - { - ForcePacking = Utilities.GetForcePacking(itemval); - } - 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) - { - // If no items were found for this machine, add a Blank placeholder - if (!containsItems) - { - Blank blank = new Blank() - { - MachineName = tempgamename, - MachineDescription = gamedesc, - CloneOf = cloneof, - RomOf = romof, - SampleOf = sampleof, - Manufacturer = manufacturer, - Year = year, - - SystemID = sysid, - SourceID = srcid, - }; - - // Now process and add the rom - ParseAddHelper(blank, clean, remUnicode); - } - - block = false; containsItems = false; - blockname = ""; tempgamename = ""; gamedesc = ""; cloneof = ""; - romof = ""; sampleof = ""; year = ""; manufacturer = ""; - } - } - - sr.Dispose(); - } - - /// - /// 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 - /// True if full pathnames are to be kept, false otherwise (default) - /// True if game names are sanitized, false otherwise (default) - /// True if we should remove non-ASCII characters from output, false otherwise (default) - public void ParseFileStripped( - // Standard Dat parsing - string filename, - int sysid, - int srcid, - - // Miscellaneous - bool keep, - bool clean, - bool remUnicode) - { - // Open a file reader - Encoding enc = Utilities.GetEncoding(filename); - StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc); - while (!sr.EndOfStream) { string line = sr.ReadLine(); @@ -628,18 +73,20 @@ namespace SabreTools.Library.DatFiles if (Regex.IsMatch(line, Constants.HeaderPatternCMP)) { GroupCollection gc = Regex.Match(line, Constants.HeaderPatternCMP).Groups; + string normalizedValue = gc[1].Value.ToLowerInvariant(); // If we have a known header - if (gc[1].Value == "clrmamepro" - || gc[1].Value == "romvault" - || gc[1].Value.ToLowerInvariant() == "doscenter") + if (normalizedValue == "clrmamepro" + || normalizedValue == "romvault" + || normalizedValue == "doscenter") { ReadHeader(sr, keep); } // If we have a known set type - else if (gc[1].Value == "set" - || gc[1].Value == "game" - || gc[1].Value == "machine") + else if (normalizedValue == "set" // Used by the most ancient DATs + || normalizedValue == "game" // Used by most CMP DATs + || normalizedValue == "machine" // Possibly used by MAME CMP DATs + || normalizedValue == "resource") // Used by some other DATs to denote a BIOS set { ReadSet(sr, filename, sysid, srcid, keep, clean, remUnicode); } @@ -654,7 +101,6 @@ namespace SabreTools.Library.DatFiles /// /// StreamReader to use to parse the header /// True if full pathnames are to be kept, false otherwise (default) - /// TODO: Make sure this only is called if the block is "clrmamepro", "doscenter", "romcenter" private void ReadHeader(StreamReader reader, bool keep) { bool superdat = false; @@ -787,7 +233,6 @@ namespace SabreTools.Library.DatFiles /// True if full pathnames are to be kept, false otherwise (default) /// True if game names are sanitized, false otherwise (default) /// True if we should remove non-ASCII characters from output, false otherwise (default) - /// TODO: Make sure this is only called if the block is "set", "game", "machine" private void ReadSet( StreamReader reader,