diff --git a/SabreTools.Helper/Data/Constants.cs b/SabreTools.Helper/Data/Constants.cs
index 977f7b44..a12f2847 100644
--- a/SabreTools.Helper/Data/Constants.cs
+++ b/SabreTools.Helper/Data/Constants.cs
@@ -74,6 +74,7 @@ namespace SabreTools.Helper
#region Regex conversion patterns
+ public const string XmlPattern = @"<(.*?)>(.*?)(.*?)>";
public const string HeaderPatternCMP = @"(^.*?) \($";
public const string ItemPatternCMP = @"^\s*(\S*?) (.*)";
public const string EndPatternCMP = @"^\s*\)\s*$";
diff --git a/SabreTools.Helper/Objects/Dat/DatFile.cs b/SabreTools.Helper/Objects/Dat/DatFile.cs
index 3b1881b6..031f9c3e 100644
--- a/SabreTools.Helper/Objects/Dat/DatFile.cs
+++ b/SabreTools.Helper/Objects/Dat/DatFile.cs
@@ -2825,7 +2825,7 @@ namespace SabreTools.Helper
(subreader.GetAttribute("name") != null && subreader.GetAttribute("name") != "" ? "\"" + xtr.GetAttribute("name") + "\"" : "ROM NAME NOT FOUND"));
its = ItemStatus.BadDump;
}
- if (subreader.GetAttribute("flags") == "itemStatus" || subreader.GetAttribute("status") == "itemStatus")
+ if (subreader.GetAttribute("flags") == "nodump" || subreader.GetAttribute("status") == "nodump")
{
logger.Verbose("Nodump detected: " +
(subreader.GetAttribute("name") != null && subreader.GetAttribute("name") != "" ? "\"" + xtr.GetAttribute("name") + "\"" : "ROM NAME NOT FOUND"));
@@ -2985,7 +2985,7 @@ namespace SabreTools.Helper
"\"" + xtr.GetAttribute("name") + "\"" : "ROM NAME NOT FOUND"));
its = ItemStatus.BadDump;
break;
- case "itemStatus":
+ case "nodump":
logger.Verbose("Nodump detected: " + (xtr.GetAttribute("name") != null && xtr.GetAttribute("name") != "" ?
"\"" + xtr.GetAttribute("name") + "\"" : "ROM NAME NOT FOUND"));
its = ItemStatus.Nodump;
@@ -3930,6 +3930,875 @@ namespace SabreTools.Helper
}
}
+ ///
+ /// Parse an XML DAT (Logiqx, OfflineList, SabreDAT, and Software List) 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
+ /// 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 the given status
+ /// True if we are supposed to trim names to NTFS length, false otherwise
+ /// 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
+ /// 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)
+ /// This version does not fully support OL or SabreDAT
+ private void ParseXMLString(
+ // Standard Dat parsing
+ string filename,
+ int sysid,
+ int srcid,
+
+ // Rom filtering
+ string gamename,
+ string romname,
+ string romtype,
+ long sgt,
+ long slt,
+ long seq,
+ string crc,
+ string md5,
+ string sha1,
+ ItemStatus itemStatus,
+
+ // Rom renaming
+ bool trim,
+ bool single,
+ string root,
+
+ // Miscellaneous
+ Logger logger,
+ bool keep,
+ bool clean,
+ bool softlist)
+
+ {
+ // Open a file reader
+ Encoding enc = Style.GetEncoding(filename);
+ StreamReader sr = new StreamReader(File.OpenRead(filename), enc);
+
+ bool superdat = false;
+ while (!sr.EndOfStream)
+ {
+ string line = sr.ReadLine().Trim();
+
+ GroupCollection matched = Regex.Match(line, Constants.XmlPattern).Groups;
+
+ // Comments in XML DATs start with a "))
+ {
+ sr.ReadLine();
+ }
+ continue;
+ }
+
+ // Handle MAME listxml since they're halfway between a SL and a Logiqx XML
+ else if (line.StartsWith(" attribs = GetAttributes(line.Substring(1, line.Length - 3));
+
+ if (attribs.ContainsKey("build"))
+ {
+ Name = (String.IsNullOrEmpty(Name) ? attribs["build"] : Name);
+ Description = (String.IsNullOrEmpty(Description) ? Name : Name);
+ }
+ }
+
+ // New software lists have this behavior
+ else if (line.StartsWith(" attribs = GetAttributes(line.Substring(1, line.Length - 3));
+
+ if (attribs.ContainsKey("name"))
+ {
+ Name = (String.IsNullOrEmpty(Name) ? attribs["name"] : Name);
+ }
+ if (attribs.ContainsKey("description"))
+ {
+ Description = (String.IsNullOrEmpty(Description) ? attribs["description"] : Description);
+ }
+ if (attribs.ContainsKey("forcemerging"))
+ {
+ switch (attribs["forcemerging"])
+ {
+ case "split":
+ ForceMerging = ForceMerging.Split;
+ break;
+ case "none":
+ ForceMerging = ForceMerging.None;
+ break;
+ case "full":
+ ForceMerging = ForceMerging.Full;
+ break;
+ }
+ }
+ if (attribs.ContainsKey("forceitemstatus"))
+ {
+ switch (attribs["forceitemstatus"])
+ {
+ case "obsolete":
+ ForceNodump = ForceNodump.Obsolete;
+ break;
+ case "required":
+ ForceNodump = ForceNodump.Required;
+ break;
+ case "ignore":
+ ForceNodump = ForceNodump.Ignore;
+ break;
+ }
+ }
+ if (attribs.ContainsKey("forcepacking"))
+ {
+ switch (attribs["forcepacking"])
+ {
+ case "zip":
+ ForcePacking = ForcePacking.Zip;
+ break;
+ case "unzip":
+ ForcePacking = ForcePacking.Unzip;
+ break;
+ }
+ }
+ }
+
+ // Handle M1 DATs since they're 99% the same as a SL DAT
+ else if (line.StartsWith(" attribs = GetAttributes(line.Substring(1, line.Length - 3));
+
+ if (attribs.ContainsKey("version"))
+ {
+ Version = (String.IsNullOrEmpty(Version) ? attribs["version"] : Version);
+ }
+ }
+
+ // OfflineList has a different header format
+ else if (line.StartsWith(""))
+ {
+ line = sr.ReadLine().Trim();
+
+ // Get the list of items from the line
+ matched = Regex.Match(line, Constants.XmlPattern).Groups;
+
+ // Get all header items (ONLY OVERWRITE IF THERE'S NO DATA)
+ if (matched[0].Value.ToLowerInvariant().StartsWith("datname"))
+ {
+ Name = (String.IsNullOrEmpty(Name) ? matched[1].Value : Name);
+ superdat = superdat || Name.Contains(" - SuperDAT");
+ if (keep && superdat)
+ {
+ Type = (String.IsNullOrEmpty(Type) ? "SuperDAT" : Type);
+ }
+ }
+ else if (matched[0].Value.ToLowerInvariant().StartsWith("datversionurl"))
+ {
+ Url = (String.IsNullOrEmpty(Name) ? matched[1].Value : Url);
+ break;
+ }
+ }
+ }
+
+ // If the line is the header
+ else if (line.Contains(""))
+ {
+ while (!line.Contains(""))
+ {
+ line = sr.ReadLine().Trim();
+
+ // Get the list of items from the line
+ matched = Regex.Match(line, Constants.XmlPattern).Groups;
+
+ // Now check for all of the header items
+ if (matched[0].Value.StartsWith("name"))
+ {
+ Name = (String.IsNullOrEmpty(Name) ? matched[1].Value : Name);
+ superdat = superdat || Name.Contains(" - SuperDAT");
+ if (keep && superdat)
+ {
+ Type = (String.IsNullOrEmpty(Type) ? "SuperDAT" : Type);
+ }
+ }
+ else if (matched[0].Value.StartsWith("description"))
+ {
+ Description = (String.IsNullOrEmpty(Description) ? matched[1].Value : Description);
+ }
+ else if (matched[0].Value.StartsWith("rootdir"))
+ {
+ RootDir = (String.IsNullOrEmpty(RootDir) ? matched[1].Value : RootDir);
+ }
+ else if (matched[0].Value.StartsWith("category"))
+ {
+ Category = (String.IsNullOrEmpty(Category) ? matched[1].Value : Category);
+ }
+ else if (matched[0].Value.StartsWith("version"))
+ {
+ Version = (String.IsNullOrEmpty(Version) ? matched[1].Value : Version);
+ }
+ else if (matched[0].Value.StartsWith("date"))
+ {
+ Date = (String.IsNullOrEmpty(Date) ? matched[1].Value : Date);
+ }
+ else if (matched[0].Value.StartsWith("author"))
+ {
+ Author = (String.IsNullOrEmpty(Author) ? matched[1].Value : Author);
+
+ // Special cases for SabreDAT
+ Dictionary attribs = GetAttributes(matched[0].Value);
+ if (attribs.ContainsKey("email"))
+ {
+ Email = (String.IsNullOrEmpty(Email) ? attribs["email"] : Email);
+ }
+ if (attribs.ContainsKey("homepage"))
+ {
+ Homepage = (String.IsNullOrEmpty(Homepage) ? attribs["homepage"] : Homepage);
+ }
+ if (attribs.ContainsKey("url"))
+ {
+ Url = (String.IsNullOrEmpty(Url) ? attribs["url"] : Url);
+ }
+ }
+ else if (matched[0].Value.StartsWith("email"))
+ {
+ Email = (String.IsNullOrEmpty(Date) ? matched[1].Value : Email);
+ }
+ else if (matched[0].Value.StartsWith("homepage"))
+ {
+ Homepage = (String.IsNullOrEmpty(Homepage) ? matched[1].Value : Homepage);
+ }
+ else if (matched[0].Value.StartsWith("url"))
+ {
+ Url = (String.IsNullOrEmpty(Url) ? matched[1].Value : Url);
+ }
+ else if (matched[0].Value.StartsWith("comment"))
+ {
+ Comment = (String.IsNullOrEmpty(Comment) ? matched[1].Value : Comment);
+ }
+ else if (matched[0].Value.StartsWith("type"))
+ {
+ Type = (String.IsNullOrEmpty(Type) ? matched[1].Value : Type);
+ superdat = superdat || matched[1].Value.Contains("SuperDAT");
+ break;
+ }
+ else if (matched[0].Value.StartsWith("clrmamepro") || matched[0].Value.StartsWith("romcenter"))
+ {
+ Dictionary attribs = GetAttributes(matched[0].Value);
+ if (attribs.ContainsKey("header"))
+ {
+ Header = (String.IsNullOrEmpty(Header) ? attribs["header"].ToString() : Header);
+ }
+ if (attribs.ContainsKey("plugin"))
+ {
+ Header = (String.IsNullOrEmpty(Header) ? attribs["plugin"].ToString() : Header);
+ }
+ if (attribs.ContainsKey("forcemerging"))
+ {
+ switch (attribs["forcemerging"])
+ {
+ case "split":
+ ForceMerging = ForceMerging.Split;
+ break;
+ case "none":
+ ForceMerging = ForceMerging.None;
+ break;
+ case "full":
+ ForceMerging = ForceMerging.Full;
+ break;
+ }
+ }
+ if (attribs.ContainsKey("forceitemstatus"))
+ {
+ switch (attribs["forceitemstatus"])
+ {
+ case "obsolete":
+ ForceNodump = ForceNodump.Obsolete;
+ break;
+ case "required":
+ ForceNodump = ForceNodump.Required;
+ break;
+ case "ignore":
+ ForceNodump = ForceNodump.Ignore;
+ break;
+ }
+ }
+ if (attribs.ContainsKey("forcepacking"))
+ {
+ switch (attribs["forcepacking"])
+ {
+ case "zip":
+ ForcePacking = ForcePacking.Zip;
+ break;
+ case "unzip":
+ ForcePacking = ForcePacking.Unzip;
+ break;
+ }
+ }
+ }
+ else if (line.Contains(""))
+ {
+ while (!line.Contains(""))
+ {
+ line = sr.ReadLine().Trim();
+
+ if (line.StartsWith("flag"))
+ {
+ Dictionary attribs = GetAttributes(line.Substring(1, line.Length - 3));
+
+ if (attribs.ContainsKey("name") && attribs.ContainsKey("value"))
+ {
+ switch (attribs["name"])
+ {
+ case "type":
+ Type = (String.IsNullOrEmpty(Type) ? attribs["value"] : Type);
+ superdat = superdat || matched[1].Value.Contains("SuperDAT");
+ break;
+ case "forcemerging":
+ switch (attribs["value"])
+ {
+ case "split":
+ ForceMerging = ForceMerging.Split;
+ break;
+ case "none":
+ ForceMerging = ForceMerging.None;
+ break;
+ case "full":
+ ForceMerging = ForceMerging.Full;
+ break;
+ }
+ break;
+ case "forceitemStatus":
+ switch (attribs["value"])
+ {
+ case "obsolete":
+ ForceNodump = ForceNodump.Obsolete;
+ break;
+ case "required":
+ ForceNodump = ForceNodump.Required;
+ break;
+ case "ignore":
+ ForceNodump = ForceNodump.Ignore;
+ break;
+ }
+ break;
+ case "forcepacking":
+ switch (attribs["value"])
+ {
+ case "zip":
+ ForcePacking = ForcePacking.Zip;
+ break;
+ case "unzip":
+ ForcePacking = ForcePacking.Unzip;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // If the line is a game/machine
+ if (matched[0].Value.StartsWith("game") || matched[0].Value.StartsWith("machine") || matched[0].Value.StartsWith("software"))
+ {
+ string gamedesc = "", comment = "", year = "", manufacturer = "", key = "";
+ bool isbios = false;
+
+ // Get the game information
+ Dictionary gameattribs = GetAttributes(matched[0].Value);
+
+ string tempname = (gameattribs.ContainsKey("name") ? gameattribs["name"] : "");
+ string sourcefile = (gameattribs.ContainsKey("sourcefile") ? gameattribs["sourcefile"] : "");
+ if (gameattribs.ContainsKey("isbios"))
+ {
+ switch (gameattribs["isbios"])
+ {
+ case "no":
+ isbios = false;
+ break;
+ case "yes":
+ isbios = true;
+ break;
+ }
+ }
+ string cloneof = (gameattribs.ContainsKey("cloneof") ? gameattribs["cloneof"] : "");
+ string romof = (gameattribs.ContainsKey("romof") ? gameattribs["romof"] : "");
+ string sampleof = (gameattribs.ContainsKey("sampleof") ? gameattribs["sampleof"] : "");
+ string board = (gameattribs.ContainsKey("board") ? gameattribs["board"] : "");
+ string rebuildto = (gameattribs.ContainsKey("rebuildto") ? gameattribs["rebuildto"] : "");
+
+ while (!line.Contains("") && !line.Contains("") && !line.Contains(""))
+ {
+ line = sr.ReadLine().Trim();
+
+ // Get the list of items from the line
+ matched = Regex.Match(line, Constants.XmlPattern).Groups;
+
+ // Standalone game values
+ if (matched[0].Value.StartsWith("comment"))
+ {
+ comment = matched[1].Value;
+ }
+ else if (matched[0].Value.StartsWith("description"))
+ {
+ gamedesc = matched[1].Value;
+ }
+ else if (matched[0].Value.StartsWith("year"))
+ {
+ year = matched[1].Value;
+ }
+ else if (matched[0].Value.StartsWith("manufacturer"))
+ {
+ manufacturer = matched[1].Value;
+ }
+
+ // Now for the different file types
+ else if (line.StartsWith(" attribs = GetAttributes(line.Substring(1, line.Length - 3));
+
+ Archive item = new Archive((attribs.ContainsKey("name") ? attribs["name"] : ""),
+ tempname,
+ comment,
+ gamedesc,
+ year,
+ manufacturer,
+ romof,
+ cloneof,
+ sampleof,
+ sourcefile,
+ isbios,
+ board,
+ rebuildto,
+ sysid,
+ "",
+ srcid,
+ "");
+
+ // Now process and add the item
+ key = "";
+ ParseAddHelper(item, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, itemStatus, trim, single, root, clean, logger, out key);
+ }
+ else if (line.StartsWith(" attribs = GetAttributes(line.Substring(1, line.Length - 3));
+
+ bool @default = false;
+ if (attribs.ContainsKey("default"))
+ {
+ switch (attribs["default"])
+ {
+ case "no":
+ @default = false;
+ break;
+ case "yes":
+ @default = true;
+ break;
+ }
+ }
+
+ BiosSet item = new BiosSet((attribs.ContainsKey("name") ? attribs["name"] : ""),
+ (attribs.ContainsKey("description") ? attribs["description"] : ""),
+ @default,
+ tempname,
+ comment,
+ gamedesc,
+ year,
+ manufacturer,
+ romof,
+ cloneof,
+ sampleof,
+ sourcefile,
+ isbios,
+ board,
+ rebuildto,
+ sysid,
+ "",
+ srcid,
+ "");
+
+ // Now process and add the item
+ key = "";
+ ParseAddHelper(item, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, itemStatus, trim, single, root, clean, logger, out key);
+ }
+ else if (line.StartsWith(" attribs = GetAttributes(line.Substring(1, line.Length - 3));
+
+ ItemStatus its = ItemStatus.None;
+ if (attribs.ContainsKey("flags"))
+ {
+ if (attribs["flags"] == "good")
+ {
+ its = ItemStatus.Good;
+ }
+ if (attribs["flags"] == "baddump")
+ {
+ logger.Verbose("Bad dump detected: " +
+ (attribs.ContainsKey("name") ? "\"" + attribs["name"] + "\"" : "ROM NAME NOT FOUND"));
+ its = ItemStatus.BadDump;
+ }
+ if (attribs["flags"] == "nodump")
+ {
+ logger.Verbose("Nodump detected: " +
+ (attribs.ContainsKey("name") ? "\"" + attribs["name"] + "\"" : "ROM NAME NOT FOUND"));
+ its = ItemStatus.Nodump;
+ }
+ if (attribs["flags"] == "verified")
+ {
+ its = ItemStatus.Verified;
+ }
+ }
+ if (attribs.ContainsKey("status"))
+ {
+ if (attribs["status"] == "good")
+ {
+ its = ItemStatus.Good;
+ }
+ if (attribs["status"] == "baddump")
+ {
+ logger.Verbose("Bad dump detected: " +
+ (attribs.ContainsKey("name") ? "\"" + attribs["name"] + "\"" : "ROM NAME NOT FOUND"));
+ its = ItemStatus.BadDump;
+ }
+ if (attribs["status"] == "nodump")
+ {
+ logger.Verbose("Nodump detected: " +
+ (attribs.ContainsKey("name") ? "\"" + attribs["name"] + "\"" : "ROM NAME NOT FOUND"));
+ its = ItemStatus.Nodump;
+ }
+ if (attribs["status"] == "verified")
+ {
+ its = ItemStatus.Verified;
+ }
+ }
+
+ // If the rom has a Date attached, read it in and then sanitize it
+ string date = "";
+ if (attribs.ContainsKey("date"))
+ {
+ DateTime dateTime = DateTime.Now;
+ if (DateTime.TryParse(attribs["date"], out dateTime))
+ {
+ date = dateTime.ToString();
+ }
+ else
+ {
+ date = attribs["date"];
+ }
+ }
+
+ // If we're in clean mode, sanitize the game name
+ if (clean)
+ {
+ tempname = Style.CleanGameName(tempname.Split(Path.DirectorySeparatorChar));
+ }
+
+ Disk item = new Disk((attribs.ContainsKey("name") ? attribs["name"] : ""),
+ (attribs.ContainsKey("md5") ? attribs["md5"] : ""),
+ (attribs.ContainsKey("sha1") ? attribs["sha1"] : ""),
+ its,
+ tempname,
+ comment,
+ gamedesc,
+ year,
+ manufacturer,
+ romof,
+ cloneof,
+ sampleof,
+ sourcefile,
+ isbios,
+ board,
+ rebuildto,
+ sysid,
+ "",
+ srcid,
+ "");
+
+ // Now process and add the item
+ key = "";
+ ParseAddHelper(item, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, itemStatus, trim, single, root, clean, logger, out key);
+ }
+ else if (line.StartsWith(" attribs = GetAttributes(line.Substring(1, line.Length - 3));
+
+ bool @default = false;
+ if (attribs.ContainsKey("default"))
+ {
+ switch (attribs["default"])
+ {
+ case "no":
+ @default = false;
+ break;
+ case "yes":
+ @default = true;
+ break;
+ }
+ }
+
+ Release item = new Release((attribs.ContainsKey("name") ? attribs["name"] : ""),
+ (attribs.ContainsKey("region") ? attribs["region"] : ""),
+ (attribs.ContainsKey("language") ? attribs["language"] : ""),
+ (attribs.ContainsKey("date") ? attribs["date"] : ""),
+ @default,
+ tempname,
+ comment,
+ gamedesc,
+ year,
+ manufacturer,
+ romof,
+ cloneof,
+ sampleof,
+ sourcefile,
+ isbios,
+ board,
+ rebuildto,
+ sysid,
+ "",
+ srcid,
+ "");
+
+ // Now process and add the item
+ key = "";
+ ParseAddHelper(item, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, itemStatus, trim, single, root, clean, logger, out key);
+ }
+ else if (line.StartsWith(" attribs = GetAttributes(line.Substring(1, line.Length - 3));
+
+ ItemStatus its = ItemStatus.None;
+ if (attribs.ContainsKey("flags"))
+ {
+ if (attribs["flags"] == "good")
+ {
+ its = ItemStatus.Good;
+ }
+ if (attribs["flags"] == "baddump")
+ {
+ logger.Verbose("Bad dump detected: " +
+ (attribs.ContainsKey("name") ? "\"" + attribs["name"] + "\"" : "ROM NAME NOT FOUND"));
+ its = ItemStatus.BadDump;
+ }
+ if (attribs["flags"] == "nodump")
+ {
+ logger.Verbose("Nodump detected: " +
+ (attribs.ContainsKey("name") ? "\"" + attribs["name"] + "\"" : "ROM NAME NOT FOUND"));
+ its = ItemStatus.Nodump;
+ }
+ if (attribs["flags"] == "verified")
+ {
+ its = ItemStatus.Verified;
+ }
+ }
+ if (attribs.ContainsKey("status"))
+ {
+ if (attribs["status"] == "good")
+ {
+ its = ItemStatus.Good;
+ }
+ if (attribs["status"] == "baddump")
+ {
+ logger.Verbose("Bad dump detected: " +
+ (attribs.ContainsKey("name") ? "\"" + attribs["name"] + "\"" : "ROM NAME NOT FOUND"));
+ its = ItemStatus.BadDump;
+ }
+ if (attribs["status"] == "nodump")
+ {
+ logger.Verbose("Nodump detected: " +
+ (attribs.ContainsKey("name") ? "\"" + attribs["name"] + "\"" : "ROM NAME NOT FOUND"));
+ its = ItemStatus.Nodump;
+ }
+ if (attribs["status"] == "verified")
+ {
+ its = ItemStatus.Verified;
+ }
+ }
+
+ // If the rom has a Date attached, read it in and then sanitize it
+ string date = "";
+ if (attribs.ContainsKey("date"))
+ {
+ DateTime dateTime = DateTime.Now;
+ if (DateTime.TryParse(attribs["date"], out dateTime))
+ {
+ date = dateTime.ToString();
+ }
+ else
+ {
+ date = attribs["date"];
+ }
+ }
+
+ // Take care of hex-sized files
+ long size = -1;
+ if (attribs.ContainsKey("size") && attribs["size"].Contains("0x"))
+ {
+ size = Convert.ToInt64(attribs["size"], 16);
+ }
+ else if (attribs.ContainsKey("size"))
+ {
+ Int64.TryParse(attribs["size"], out size);
+ }
+
+ // If the rom is continue or ignore, add the size to the previous rom
+ if (attribs.ContainsKey("loadflag") && (attribs["loadflag"] == "continue" || attribs["loadflag"] == "ignore"))
+ {
+ int index = Files[key].Count() - 1;
+ DatItem lastrom = Files[key][index];
+ if (lastrom.Type == ItemType.Rom)
+ {
+ ((Rom)lastrom).Size += size;
+ }
+ Files[key].RemoveAt(index);
+ Files[key].Add(lastrom);
+ continue;
+ }
+
+ Rom item = new Rom((attribs.ContainsKey("name") ? attribs["name"] : ""),
+ size,
+ (attribs.ContainsKey("crc") ? attribs["crc"] : ""),
+ (attribs.ContainsKey("md5") ? attribs["md5"] : ""),
+ (attribs.ContainsKey("sha1") ? attribs["sha1"] : ""),
+ its,
+ (attribs.ContainsKey("date") ? attribs["date"] : ""),
+ tempname,
+ comment,
+ gamedesc,
+ year,
+ manufacturer,
+ romof,
+ cloneof,
+ sampleof,
+ sourcefile,
+ isbios,
+ board,
+ rebuildto,
+ sysid,
+ "",
+ srcid,
+ "");
+
+ // Now process and add the item
+ key = "";
+ ParseAddHelper(item, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, itemStatus, trim, single, root, clean, logger, out key);
+ }
+ else if (line.StartsWith(" attribs = GetAttributes(line.Substring(1, line.Length - 3));
+
+ Sample item = new Sample((attribs.ContainsKey("name") ? attribs["name"] : ""),
+ tempname,
+ comment,
+ gamedesc,
+ year,
+ manufacturer,
+ romof,
+ cloneof,
+ sampleof,
+ sourcefile,
+ isbios,
+ board,
+ rebuildto,
+ sysid,
+ "",
+ srcid,
+ "");
+
+ // Now process and add the item
+ key = "";
+ ParseAddHelper(item, gamename, romname, romtype, sgt, slt, seq, crc, md5, sha1, itemStatus, trim, single, root, clean, logger, out key);
+ }
+ }
+ }
+ }
+
+ sr.Dispose();
+ }
+
+ ///
+ /// Get attributes from an XML element
+ ///
+ /// Opening tag to be parsed
+ /// Mapping of attribute to values
+ private Dictionary GetAttributes(string line)
+ {
+ Dictionary attribs = new Dictionary();
+
+ string[] gc = line.Trim().Split(' ');
+
+ // Loop over all attributes and add them if possible
+ string attrib = "", val = "";
+ for (int i = 1; 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;
+ }
+
+ // Contains an equal sign, even number of quotes, not in attribute
+ else if (gc[i].Contains("=") && Regex.Matches(gc[i], "\"").Count % 2 == 0 && attrib == "")
+ {
+ attribs.Add(gc[i].Split('=')[0], gc[i].Split('=')[1].Replace("\"", ""));
+ }
+
+ // Contains an equal sign, even number of quotes, in attribute
+ else if (gc[i].Contains("=") && Regex.Matches(gc[i], "\"").Count % 2 == 0 && attrib != "")
+ {
+ val += " " + gc[i];
+ }
+
+ // Contains an equal sign, odd number of quotes, not in attribute
+ else if (gc[i].Contains("=") && Regex.Matches(gc[i], "\"").Count % 2 == 1 && attrib == "")
+ {
+ attrib = gc[i].Split('=')[0];
+ val = gc[i].Split('=')[1].Replace("\"", "");
+ }
+
+ // Contains no equal sign, even number of quotes, not in attribute
+ else if (!gc[i].Contains("=") && Regex.Matches(gc[i], "\"").Count % 2 == 0 && attrib == "")
+ {
+ attribs.Add(gc[i], null);
+ }
+
+ // Contains no equal sign, (even number of quotes XOR not in attribute)
+ else if (!gc[i].Contains("=") && (Regex.Matches(gc[i], "\"").Count % 2 == 0 ^ attrib == ""))
+ {
+ // Impossible in XML, singular attributes can't be quoted
+ }
+
+ // Contains odd number of quotes, in attribute
+ else if (Regex.Matches(gc[i], "\"").Count % 2 == 1 && attrib != "")
+ {
+ val += " " + gc[i].Replace("\"", "");
+ attribs.Add(attrib, val);
+ attrib = "";
+ val = "";
+ }
+ }
+
+ return attribs;
+ }
+
///
/// Add a rom to the Dat after checking
///