/// <summary> /// Remove fields with given values /// </summary> /// <param name="biosSet">BiosSet to remove fields from</param> private void RemoveFields(BiosSet biosSet) { if (DatItemFields.Contains(DatItemField.Description)) { biosSet.Description = null; } if (DatItemFields.Contains(DatItemField.Default)) { biosSet.Default = null; } }
/// <summary> /// Read game/machine information /// </summary> /// <param name="reader">XmlReader to use to parse the machine</param> /// <param name="dirs">List of dirs to prepend to the game name</param> /// <param name="filename">Name of the file to be parsed</param> /// <param name="sysid">System ID for the DAT</param> /// <param name="srcid">Source ID for the DAT</param> /// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param> /// <param name="clean">True if game names are sanitized, false otherwise (default)</param> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param> private void ReadMachine( XmlReader reader, List <string> dirs, // Standard Dat parsing string filename, int sysid, int srcid, // Miscellaneous bool keep, bool clean, bool remUnicode) { // If we have an empty machine, skip it if (reader == null) { return; } // Otherwise, add what is possible reader.MoveToContent(); string key = ""; string temptype = reader.Name; bool containsItems = false; // Create a new machine MachineType machineType = MachineType.NULL; if (Utilities.GetYesNo(reader.GetAttribute("isbios")) == true) { machineType |= MachineType.Bios; } if (Utilities.GetYesNo(reader.GetAttribute("isdevice")) == true) // Listxml-specific, used by older DATs { machineType |= MachineType.Device; } if (Utilities.GetYesNo(reader.GetAttribute("ismechanical")) == true) // Listxml-specific, used by older DATs { machineType |= MachineType.Mechanical; } string dirsString = (dirs != null && dirs.Count() > 0 ? string.Join("/", dirs) + "/" : ""); Machine machine = new Machine { Name = dirsString + reader.GetAttribute("name"), Description = dirsString + reader.GetAttribute("name"), SourceFile = reader.GetAttribute("sourcefile"), Board = reader.GetAttribute("board"), RebuildTo = reader.GetAttribute("rebuildto"), Runnable = Utilities.GetYesNo(reader.GetAttribute("runnable")), // Listxml-specific, used by older DATs Comment = "", CloneOf = reader.GetAttribute("cloneof") ?? "", RomOf = reader.GetAttribute("romof") ?? "", SampleOf = reader.GetAttribute("sampleof") ?? "", MachineType = (machineType == MachineType.NULL ? MachineType.None : machineType), }; if (Type == "SuperDAT" && !keep) { string tempout = Regex.Match(machine.Name, @".*?\\(.*)").Groups[1].Value; if (!String.IsNullOrWhiteSpace(tempout)) { machine.Name = tempout; } } while (!reader.EOF) { // We only want elements if (reader.NodeType != XmlNodeType.Element) { reader.Read(); continue; } // Get the roms from the machine switch (reader.Name) { case "comment": // There can be multiple comments by spec machine.Comment += reader.ReadElementContentAsString(); break; case "description": machine.Description = reader.ReadElementContentAsString(); break; case "year": machine.Year = reader.ReadElementContentAsString(); break; case "manufacturer": machine.Manufacturer = reader.ReadElementContentAsString(); break; case "publisher": // Not technically supported but used by some legacy DATs machine.Publisher = reader.ReadElementContentAsString(); break; case "trurip": // This is special metadata unique to TruRip ReadTruRip(reader.ReadSubtree(), machine); // Skip the trurip node now that we've processed it reader.Skip(); break; case "release": containsItems = true; DatItem release = new Release { Name = reader.GetAttribute("name"), Region = reader.GetAttribute("region"), Language = reader.GetAttribute("language"), Date = reader.GetAttribute("date"), Default = Utilities.GetYesNo(reader.GetAttribute("default")), }; release.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(release, clean, remUnicode); reader.Read(); break; case "biosset": containsItems = true; DatItem biosset = new BiosSet { Name = reader.GetAttribute("name"), Description = reader.GetAttribute("description"), Default = Utilities.GetYesNo(reader.GetAttribute("default")), SystemID = sysid, System = filename, SourceID = srcid, }; biosset.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(biosset, clean, remUnicode); reader.Read(); break; case "rom": containsItems = true; DatItem rom = new Rom { Name = reader.GetAttribute("name"), Size = Utilities.GetSize(reader.GetAttribute("size")), CRC = Utilities.CleanHashData(reader.GetAttribute("crc"), Constants.CRCLength), MD5 = Utilities.CleanHashData(reader.GetAttribute("md5"), Constants.MD5Length), SHA1 = Utilities.CleanHashData(reader.GetAttribute("sha1"), Constants.SHA1Length), SHA256 = Utilities.CleanHashData(reader.GetAttribute("sha256"), Constants.SHA256Length), SHA384 = Utilities.CleanHashData(reader.GetAttribute("sha384"), Constants.SHA384Length), SHA512 = Utilities.CleanHashData(reader.GetAttribute("sha512"), Constants.SHA512Length), MergeTag = reader.GetAttribute("merge"), ItemStatus = Utilities.GetItemStatus(reader.GetAttribute("status")), Date = Utilities.GetDate(reader.GetAttribute("date")), SystemID = sysid, System = filename, SourceID = srcid, }; rom.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(rom, clean, remUnicode); reader.Read(); break; case "disk": containsItems = true; DatItem disk = new Disk { Name = reader.GetAttribute("name"), MD5 = Utilities.CleanHashData(reader.GetAttribute("md5"), Constants.MD5Length), SHA1 = Utilities.CleanHashData(reader.GetAttribute("sha1"), Constants.SHA1Length), SHA256 = Utilities.CleanHashData(reader.GetAttribute("sha256"), Constants.SHA256Length), SHA384 = Utilities.CleanHashData(reader.GetAttribute("sha384"), Constants.SHA384Length), SHA512 = Utilities.CleanHashData(reader.GetAttribute("sha512"), Constants.SHA512Length), MergeTag = reader.GetAttribute("merge"), ItemStatus = Utilities.GetItemStatus(reader.GetAttribute("status")), SystemID = sysid, System = filename, SourceID = srcid, }; disk.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(disk, clean, remUnicode); reader.Read(); break; case "sample": containsItems = true; DatItem samplerom = new Sample { Name = reader.GetAttribute("name"), SystemID = sysid, System = filename, SourceID = srcid, }; samplerom.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(samplerom, clean, remUnicode); reader.Read(); break; case "archive": containsItems = true; DatItem archiverom = new Archive { Name = reader.GetAttribute("name"), SystemID = sysid, System = filename, SourceID = srcid, }; archiverom.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(archiverom, clean, remUnicode); reader.Read(); break; default: reader.Read(); break; } } // If no items were found for this machine, add a Blank placeholder if (!containsItems) { Blank blank = new Blank() { SystemID = sysid, System = filename, SourceID = srcid, }; blank.CopyMachineInformation(machine); // Now process and add the rom ParseAddHelper(blank, clean, remUnicode); } }
/// <summary> /// Read directory information /// </summary> /// <param name="reader">XmlReader to use to parse the header</param> /// <param name="filename">Name of the file to be parsed</param> /// <param name="sysid">System ID for the DAT</param> /// <param name="srcid">Source ID for the DAT</param> /// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param> /// <param name="clean">True if game names are sanitized, false otherwise (default)</param> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param> private bool ReadDirectory(XmlReader reader, List <string> parent, // Standard Dat parsing string filename, int sysid, int srcid, // Miscellaneous bool keep, bool clean, bool remUnicode) { // Prepare all internal variables XmlReader flagreader; bool empty = true; string key = "", date = ""; long size = -1; ItemStatus its = ItemStatus.None; // If there's no subtree to the header, skip it if (reader == null) { return(empty); } string foldername = (reader.GetAttribute("name") ?? ""); if (!String.IsNullOrWhiteSpace(foldername)) { parent.Add(foldername); } // Otherwise, read what we can from the directory while (!reader.EOF) { // If we're ending a folder or game, take care of possibly empty games and removing from the parent if (reader.NodeType == XmlNodeType.EndElement && (reader.Name == "directory" || reader.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); Rom rom = new Rom("null", tempgame, omitFromScan: Hash.DeepHashes); // TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually // Now process and add the rom key = ParseAddHelper(rom, clean, remUnicode); } // Regardless, end the current folder int parentcount = parent.Count; if (parentcount == 0) { Globals.Logger.Verbose("Empty parent '{0}' found in '{1}'", String.Join("\\", parent), filename); 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) { Type = (String.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type); } } } // We only want elements if (reader.NodeType != XmlNodeType.Element) { reader.Read(); continue; } // Get all directory items string content = ""; switch (reader.Name) { // Directories can contain directories case "dir": case "directory": ReadDirectory(reader.ReadSubtree(), parent, filename, sysid, srcid, keep, clean, remUnicode); // Skip the directory node now that we've processed it reader.Read(); break; case "file": empty = false; // If the rom is itemStatus, flag it its = ItemStatus.None; flagreader = reader.ReadSubtree(); // If the subtree is empty, skip it if (flagreader == null) { reader.Skip(); continue; } 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"); its = Utilities.GetItemStatus(flagreader.GetAttribute("name")); } break; } flagreader.Read(); } // If the rom has a Date attached, read it in and then sanitize it date = Utilities.GetDate(reader.GetAttribute("date")); // Take care of hex-sized files size = Utilities.GetSize(reader.GetAttribute("size")); Machine dir = new Machine(); // Get the name of the game from the parent dir.Name = String.Join("\\", parent); dir.Description = dir.Name; DatItem datItem; switch (reader.GetAttribute("type").ToLowerInvariant()) { case "archive": datItem = new Archive { Name = reader.GetAttribute("name"), SystemID = sysid, System = filename, SourceID = srcid, }; break; case "biosset": datItem = new BiosSet { Name = reader.GetAttribute("name"), Description = reader.GetAttribute("description"), Default = Utilities.GetYesNo(reader.GetAttribute("default")), SystemID = sysid, System = filename, SourceID = srcid, }; break; case "disk": datItem = new Disk { Name = reader.GetAttribute("name"), MD5 = Utilities.CleanHashData(reader.GetAttribute("md5"), Constants.MD5Length), SHA1 = Utilities.CleanHashData(reader.GetAttribute("sha1"), Constants.SHA1Length), SHA256 = Utilities.CleanHashData(reader.GetAttribute("sha256"), Constants.SHA256Length), SHA384 = Utilities.CleanHashData(reader.GetAttribute("sha384"), Constants.SHA384Length), SHA512 = Utilities.CleanHashData(reader.GetAttribute("sha512"), Constants.SHA512Length), ItemStatus = its, SystemID = sysid, System = filename, SourceID = srcid, }; break; case "release": datItem = new Release { Name = reader.GetAttribute("name"), Region = reader.GetAttribute("region"), Language = reader.GetAttribute("language"), Date = reader.GetAttribute("date"), Default = Utilities.GetYesNo(reader.GetAttribute("default")), SystemID = sysid, System = filename, SourceID = srcid, }; break; case "rom": datItem = new Rom { Name = reader.GetAttribute("name"), Size = size, CRC = Utilities.CleanHashData(reader.GetAttribute("crc"), Constants.CRCLength), MD5 = Utilities.CleanHashData(reader.GetAttribute("md5"), Constants.MD5Length), SHA1 = Utilities.CleanHashData(reader.GetAttribute("sha1"), Constants.SHA1Length), SHA256 = Utilities.CleanHashData(reader.GetAttribute("sha256"), Constants.SHA256Length), SHA384 = Utilities.CleanHashData(reader.GetAttribute("sha384"), Constants.SHA384Length), SHA512 = Utilities.CleanHashData(reader.GetAttribute("sha512"), Constants.SHA512Length), ItemStatus = its, Date = date, SystemID = sysid, System = filename, SourceID = srcid, }; break; case "sample": datItem = new Sample { Name = reader.GetAttribute("name"), SystemID = sysid, System = filename, SourceID = srcid, }; break; default: // By default, create a new Blank, just in case datItem = new Blank(); break; } datItem?.CopyMachineInformation(dir); // Now process and add the rom key = ParseAddHelper(datItem, clean, remUnicode); reader.Read(); break; } } return(empty); }
/// <summary> /// Read machine information /// </summary> /// <param name="reader">XmlReader representing a machine block</param> /// <param name="filename">Name of the file to be parsed</param> /// <param name="sysid">System ID for the DAT</param> /// <param name="srcid">Source ID for the DAT</param> /// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param> /// <param name="clean">True if game names are sanitized, false otherwise (default)</param> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param> private void ReadMachine( XmlReader reader, // Standard Dat parsing string filename, int sysid, int srcid, // Miscellaneous bool keep, bool clean, bool remUnicode) { // If we have an empty machine, skip it if (reader == null) { return; } // Otherwise, add what is possible reader.MoveToContent(); string key = ""; string temptype = reader.Name; bool containsItems = false; // Create a new machine MachineType machineType = MachineType.NULL; if (Utilities.GetYesNo(reader.GetAttribute("isbios")) == true) { machineType |= MachineType.Bios; } if (Utilities.GetYesNo(reader.GetAttribute("isdevice")) == true) { machineType |= MachineType.Device; } if (Utilities.GetYesNo(reader.GetAttribute("ismechanical")) == true) { machineType |= MachineType.Mechanical; } Machine machine = new Machine { Name = reader.GetAttribute("name"), Description = reader.GetAttribute("name"), SourceFile = reader.GetAttribute("sourcefile"), Runnable = Utilities.GetYesNo(reader.GetAttribute("runnable")), Comment = "", CloneOf = reader.GetAttribute("cloneof") ?? "", RomOf = reader.GetAttribute("romof") ?? "", SampleOf = reader.GetAttribute("sampleof") ?? "", Devices = new List <string>(), SlotOptions = new List <string>(), MachineType = (machineType == MachineType.NULL ? MachineType.None : machineType), }; while (!reader.EOF) { // We only want elements if (reader.NodeType != XmlNodeType.Element) { reader.Read(); continue; } // Get the roms from the machine switch (reader.Name) { case "description": machine.Description = reader.ReadElementContentAsString(); break; case "year": machine.Year = reader.ReadElementContentAsString(); break; case "manufacturer": machine.Manufacturer = reader.ReadElementContentAsString(); break; case "biosset": containsItems = true; DatItem biosset = new BiosSet { Name = reader.GetAttribute("name"), Description = reader.GetAttribute("description"), Default = Utilities.GetYesNo(reader.GetAttribute("default")), SystemID = sysid, System = filename, SourceID = srcid, }; biosset.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(biosset, clean, remUnicode); reader.Read(); break; case "rom": containsItems = true; DatItem rom = new Rom { Name = reader.GetAttribute("name"), Bios = reader.GetAttribute("bios"), Size = Utilities.GetSize(reader.GetAttribute("size")), CRC = Utilities.CleanHashData(reader.GetAttribute("crc"), Constants.CRCLength), MD5 = Utilities.CleanHashData(reader.GetAttribute("md5"), Constants.MD5Length), SHA1 = Utilities.CleanHashData(reader.GetAttribute("sha1"), Constants.SHA1Length), SHA256 = Utilities.CleanHashData(reader.GetAttribute("sha256"), Constants.SHA256Length), SHA384 = Utilities.CleanHashData(reader.GetAttribute("sha384"), Constants.SHA384Length), SHA512 = Utilities.CleanHashData(reader.GetAttribute("sha512"), Constants.SHA512Length), MergeTag = reader.GetAttribute("merge"), Region = reader.GetAttribute("region"), Offset = reader.GetAttribute("offset"), ItemStatus = Utilities.GetItemStatus(reader.GetAttribute("status")), Optional = Utilities.GetYesNo(reader.GetAttribute("optional")), SystemID = sysid, System = filename, SourceID = srcid, }; rom.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(rom, clean, remUnicode); reader.Read(); break; case "disk": containsItems = true; DatItem disk = new Disk { Name = reader.GetAttribute("name"), MD5 = Utilities.CleanHashData(reader.GetAttribute("md5"), Constants.MD5Length), SHA1 = Utilities.CleanHashData(reader.GetAttribute("sha1"), Constants.SHA1Length), SHA256 = Utilities.CleanHashData(reader.GetAttribute("sha256"), Constants.SHA256Length), SHA384 = Utilities.CleanHashData(reader.GetAttribute("sha384"), Constants.SHA384Length), SHA512 = Utilities.CleanHashData(reader.GetAttribute("sha512"), Constants.SHA512Length), MergeTag = reader.GetAttribute("merge"), Region = reader.GetAttribute("region"), Index = reader.GetAttribute("index"), Writable = Utilities.GetYesNo(reader.GetAttribute("writable")), ItemStatus = Utilities.GetItemStatus(reader.GetAttribute("status")), Optional = Utilities.GetYesNo(reader.GetAttribute("optional")), SystemID = sysid, System = filename, SourceID = srcid, }; disk.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(disk, clean, remUnicode); reader.Read(); break; case "device_ref": string device_ref_name = reader.GetAttribute("name"); if (!machine.Devices.Contains(device_ref_name)) { machine.Devices.Add(device_ref_name); } reader.Read(); break; case "sample": containsItems = true; DatItem samplerom = new Sample { Name = reader.GetAttribute("name"), SystemID = sysid, System = filename, SourceID = srcid, }; samplerom.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(samplerom, clean, remUnicode); reader.Read(); break; case "chip": // string chip_name = reader.GetAttribute("name"); // string chip_tag = reader.GetAttribute("tag"); // string chip_type = reader.GetAttribute("type"); // (cpu|audio) // string chip_clock = reader.GetAttribute("clock"); reader.Read(); break; case "display": // string display_tag = reader.GetAttribute("tag"); // string display_type = reader.GetAttribute("type"); // (raster|vector|lcd|svg|unknown) // string display_rotate = reader.GetAttribute("rotate"); // (0|90|180|270) // bool? display_flipx = Utilities.GetYesNo(reader.GetAttribute("flipx")); // string display_width = reader.GetAttribute("width"); // string display_height = reader.GetAttribute("height"); // string display_refresh = reader.GetAttribute("refresh"); // string display_pixclock = reader.GetAttribute("pixclock"); // string display_htotal = reader.GetAttribute("htotal"); // string display_hbend = reader.GetAttribute("hbend"); // string display_hbstart = reader.GetAttribute("hbstart"); // string display_vtotal = reader.GetAttribute("vtotal"); // string display_vbend = reader.GetAttribute("vbend"); // string display_vbstart = reader.GetAttribute("vbstart"); reader.Read(); break; case "sound": // string sound_channels = reader.GetAttribute("channels"); reader.Read(); break; case "condition": // string condition_tag = reader.GetAttribute("tag"); // string condition_mask = reader.GetAttribute("mask"); // string condition_relation = reader.GetAttribute("relation"); // (eq|ne|gt|le|lt|ge) // string condition_value = reader.GetAttribute("value"); reader.Read(); break; case "input": // bool? input_service = Utilities.GetYesNo(reader.GetAttribute("service")); // bool? input_tilt = Utilities.GetYesNo(reader.GetAttribute("tilt")); // string input_players = reader.GetAttribute("players"); // string input_coins = reader.GetAttribute("coins"); // // While the subtree contains <control> elements... // string control_type = reader.GetAttribute("type"); // string control_player = reader.GetAttribute("player"); // string control_buttons = reader.GetAttribute("buttons"); // string control_regbuttons = reader.GetAttribute("regbuttons"); // string control_minimum = reader.GetAttribute("minimum"); // string control_maximum = reader.GetAttribute("maximum"); // string control_sensitivity = reader.GetAttribute("sensitivity"); // string control_keydelta = reader.GetAttribute("keydelta"); // bool? control_reverse = Utilities.GetYesNo(reader.GetAttribute("reverse")); // string control_ways = reader.GetAttribute("ways"); // string control_ways2 = reader.GetAttribute("ways2"); // string control_ways3 = reader.GetAttribute("ways3"); reader.Skip(); break; case "dipswitch": // string dipswitch_name = reader.GetAttribute("name"); // string dipswitch_tag = reader.GetAttribute("tag"); // string dipswitch_mask = reader.GetAttribute("mask"); // // While the subtree contains <diplocation> elements... // string diplocation_name = reader.GetAttribute("name"); // string diplocation_number = reader.GetAttribute("number"); // bool? diplocation_inverted = Utilities.GetYesNo(reader.GetAttribute("inverted")); // // While the subtree contains <dipvalue> elements... // string dipvalue_name = reader.GetAttribute("name"); // string dipvalue_value = reader.GetAttribute("value"); // bool? dipvalue_default = Utilities.GetYesNo(reader.GetAttribute("default")); reader.Skip(); break; case "configuration": // string configuration_name = reader.GetAttribute("name"); // string configuration_tag = reader.GetAttribute("tag"); // string configuration_mask = reader.GetAttribute("mask"); // // While the subtree contains <conflocation> elements... // string conflocation_name = reader.GetAttribute("name"); // string conflocation_number = reader.GetAttribute("number"); // bool? conflocation_inverted = Utilities.GetYesNo(reader.GetAttribute("inverted")); // // While the subtree contains <confsetting> elements... // string confsetting_name = reader.GetAttribute("name"); // string confsetting_value = reader.GetAttribute("value"); // bool? confsetting_default = Utilities.GetYesNo(reader.GetAttribute("default")); reader.Skip(); break; case "port": // string port_tag = reader.GetAttribute("tag"); // // While the subtree contains <analog> elements... // string analog_mask = reader.GetAttribute("mask"); reader.Skip(); break; case "adjuster": // string adjuster_name = reader.GetAttribute("name"); // bool? adjuster_default = Utilities.GetYesNo(reader.GetAttribute("default")); // // For the one possible <condition> element... // string condition_tag = reader.GetAttribute("tag"); // string condition_mask = reader.GetAttribute("mask"); // string condition_relation = reader.GetAttribute("relation"); // (eq|ne|gt|le|lt|ge) // string condition_value = reader.GetAttribute("value"); reader.Skip(); break; case "driver": // string driver_status = reader.GetAttribute("status"); // (good|imperfect|preliminary) // string driver_emulation = reader.GetAttribute("emulation"); // (good|imperfect|preliminary) // string driver_cocktail = reader.GetAttribute("cocktail"); // (good|imperfect|preliminary) // string driver_savestate = reader.GetAttribute("savestate"); // (supported|unsupported) reader.Read(); break; case "feature": // string feature_type = reader.GetAttribute("type"); // (protection|palette|graphics|sound|controls|keyboard|mouse|microphone|camera|disk|printer|lan|wan|timing) // string feature_status = reader.GetAttribute("status"); // (unemulated|imperfect) // string feature_overall = reader.GetAttribute("overall"); // (unemulated|imperfect) reader.Read(); break; case "device": // string device_type = reader.GetAttribute("type"); // string device_tag = reader.GetAttribute("tag"); // string device_fixed_image = reader.GetAttribute("fixed_image"); // string device_mandatory = reader.GetAttribute("mandatory"); // string device_interface = reader.GetAttribute("interface"); // // For the one possible <instance> element... // string instance_name = reader.GetAttribute("name"); // string instance_briefname = reader.GetAttribute("briefname"); // // While the subtree contains <extension> elements... // string extension_name = reader.GetAttribute("name"); reader.Skip(); break; case "slot": // string slot_name = reader.GetAttribute("name"); ReadSlot(reader.ReadSubtree(), machine); // Skip the slot now that we've processed it reader.Skip(); break; case "softwarelist": // string softwarelist_name = reader.GetAttribute("name"); // string softwarelist_status = reader.GetAttribute("status"); // (original|compatible) // string softwarelist_filter = reader.GetAttribute("filter"); reader.Read(); break; case "ramoption": // string ramoption_default = reader.GetAttribute("default"); reader.Read(); break; default: reader.Read(); break; } } // If no items were found for this machine, add a Blank placeholder if (!containsItems) { Blank blank = new Blank() { SystemID = sysid, System = filename, SourceID = srcid, }; blank.CopyMachineInformation(machine); // Now process and add the rom ParseAddHelper(blank, clean, remUnicode); } }
/// <summary> /// Parse a character-separated value DAT and return all found games and roms within /// </summary> /// <param name="filename">Name of the file to be parsed</param> /// <param name="sysid">System ID for the DAT</param> /// <param name="srcid">Source ID for the DAT</param> /// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param> /// <param name="clean">True if game names are sanitized, false otherwise (default)</param> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param> public override void ParseFile( // 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); // Create an empty list of columns to parse though List <string> columns = new List <string>(); long linenum = -1; while (!sr.EndOfStream) { string line = sr.ReadLine(); linenum++; // Parse the first line, getting types from the column names if (linenum == 0) { string[] parsedColumns = line.Split(_delim); foreach (string parsed in parsedColumns) { switch (parsed.ToLowerInvariant().Trim('"')) { case "file": case "filename": case "file name": columns.Add("DatFile.FileName"); break; case "internal name": columns.Add("DatFile.Name"); break; case "description": case "dat description": columns.Add("DatFile.Description"); break; case "game name": case "game": case "machine": columns.Add("Machine.Name"); break; case "game description": columns.Add("Description"); break; case "type": columns.Add("DatItem.Type"); break; case "rom": case "romname": case "rom name": case "name": columns.Add("Rom.Name"); break; case "disk": case "diskname": case "disk name": columns.Add("Disk.Name"); break; case "size": columns.Add("DatItem.Size"); break; case "crc": case "crc hash": columns.Add("DatItem.CRC"); break; case "md5": case "md5 hash": columns.Add("DatItem.MD5"); break; case "sha1": case "sha-1": case "sha1 hash": case "sha-1 hash": columns.Add("DatItem.SHA1"); break; case "sha256": case "sha-256": case "sha256 hash": case "sha-256 hash": columns.Add("DatItem.SHA256"); break; case "sha384": case "sha-384": case "sha384 hash": case "sha-384 hash": columns.Add("DatItem.SHA384"); break; case "sha512": case "sha-512": case "sha512 hash": case "sha-512 hash": columns.Add("DatItem.SHA512"); break; case "nodump": case "no dump": case "status": case "item status": columns.Add("DatItem.Nodump"); break; case "date": columns.Add("DatItem.Date"); break; default: columns.Add("INVALID"); break; } } continue; } // Otherwise, we want to split the line and parse string[] parsedLine = line.Split(_delim); // If the line doesn't have the correct number of columns, we log and skip if (parsedLine.Length != columns.Count) { Globals.Logger.Warning("Malformed line found in '{0}' at line {1}", filename, linenum); continue; } // Set the output item information string machineName = null, machineDesc = null, name = null, crc = null, md5 = null, sha1 = null, sha256 = null, sha384 = null, sha512 = null, date = null; long size = -1; ItemType itemType = ItemType.Rom; ItemStatus status = ItemStatus.None; // Now we loop through and get values for everything for (int i = 0; i < columns.Count; i++) { string value = parsedLine[i].Trim('"'); switch (columns[i]) { case "DatFile.FileName": FileName = (String.IsNullOrWhiteSpace(FileName) ? value : FileName); break; case "DatFile.Name": Name = (String.IsNullOrWhiteSpace(Name) ? value : Name); break; case "DatFile.Description": Description = (String.IsNullOrWhiteSpace(Description) ? value : Description); break; case "Machine.Name": machineName = value; break; case "Description": machineDesc = value; break; case "DatItem.Type": itemType = Utilities.GetItemType(value) ?? ItemType.Rom; break; case "Rom.Name": case "Disk.Name": name = String.IsNullOrWhiteSpace(value) ? name : value; break; case "DatItem.Size": if (!Int64.TryParse(value, out size)) { size = -1; } break; case "DatItem.CRC": crc = Utilities.CleanHashData(value, Constants.CRCLength); break; case "DatItem.MD5": md5 = Utilities.CleanHashData(value, Constants.MD5Length); break; case "DatItem.SHA1": sha1 = Utilities.CleanHashData(value, Constants.SHA1Length); break; case "DatItem.SHA256": sha256 = Utilities.CleanHashData(value, Constants.SHA256Length); break; case "DatItem.SHA384": sha384 = Utilities.CleanHashData(value, Constants.SHA384Length); break; case "DatItem.SHA512": sha512 = Utilities.CleanHashData(value, Constants.SHA512Length); break; case "DatItem.Nodump": status = Utilities.GetItemStatus(value); break; case "DatItem.Date": date = value; break; } } // And now we populate and add the new item switch (itemType) { case ItemType.Archive: Archive archive = new Archive() { Name = name, MachineName = machineName, MachineDescription = machineDesc, }; ParseAddHelper(archive, clean, remUnicode); break; case ItemType.BiosSet: BiosSet biosset = new BiosSet() { Name = name, MachineName = machineName, Description = machineDesc, }; ParseAddHelper(biosset, clean, remUnicode); break; case ItemType.Disk: Disk disk = new Disk() { Name = name, MD5 = md5, SHA1 = sha1, SHA256 = sha256, SHA384 = sha384, SHA512 = sha512, MachineName = machineName, MachineDescription = machineDesc, ItemStatus = status, }; ParseAddHelper(disk, clean, remUnicode); break; case ItemType.Release: Release release = new Release() { Name = name, MachineName = machineName, MachineDescription = machineDesc, }; ParseAddHelper(release, clean, remUnicode); break; case ItemType.Rom: Rom rom = new Rom() { Name = name, Size = size, CRC = crc, MD5 = md5, SHA1 = sha1, SHA256 = sha256, SHA384 = sha384, SHA512 = sha512, Date = date, MachineName = machineName, MachineDescription = machineDesc, ItemStatus = status, }; ParseAddHelper(rom, clean, remUnicode); break; case ItemType.Sample: Sample sample = new Sample() { Name = name, MachineName = machineName, MachineDescription = machineDesc, }; ParseAddHelper(sample, clean, remUnicode); break; } } }
/// <summary> /// Read game/machine information /// </summary> /// <param name="reader">XmlReader to use to parse the machine</param> /// <param name="dirs">List of dirs to prepend to the game name</param> /// <param name="statsOnly">True to only add item statistics while parsing, false otherwise</param> /// <param name="filename">Name of the file to be parsed</param> /// <param name="indexId">Index ID for the DAT</param> /// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param> private void ReadMachine( XmlReader reader, List <string> dirs, bool statsOnly, // Standard Dat parsing string filename, int indexId, // Miscellaneous bool keep) { // If we have an empty machine, skip it if (reader == null) { return; } // Otherwise, add what is possible reader.MoveToContent(); bool containsItems = false; // Create a new machine MachineType machineType = 0x0; if (reader.GetAttribute("isbios").AsYesNo() == true) { machineType |= MachineType.Bios; } if (reader.GetAttribute("isdevice").AsYesNo() == true) // Listxml-specific, used by older DATs { machineType |= MachineType.Device; } if (reader.GetAttribute("ismechanical").AsYesNo() == true) // Listxml-specific, used by older DATs { machineType |= MachineType.Mechanical; } string dirsString = (dirs != null && dirs.Count() > 0 ? string.Join("/", dirs) + "/" : string.Empty); Machine machine = new Machine { Name = dirsString + reader.GetAttribute("name"), Description = dirsString + reader.GetAttribute("name"), SourceFile = reader.GetAttribute("sourcefile"), Board = reader.GetAttribute("board"), RebuildTo = reader.GetAttribute("rebuildto"), Runnable = reader.GetAttribute("runnable").AsRunnable(), // Used by older DATs CloneOf = reader.GetAttribute("cloneof"), RomOf = reader.GetAttribute("romof"), SampleOf = reader.GetAttribute("sampleof"), MachineType = (machineType == 0x0 ? MachineType.NULL : machineType), }; if (Header.Type == "SuperDAT" && !keep) { string tempout = Regex.Match(machine.Name, @".*?\\(.*)").Groups[1].Value; if (!string.IsNullOrWhiteSpace(tempout)) { machine.Name = tempout; } } while (!reader.EOF) { // We only want elements if (reader.NodeType != XmlNodeType.Element) { reader.Read(); continue; } // Get the roms from the machine switch (reader.Name) { case "comment": // There can be multiple comments by spec machine.Comment += reader.ReadElementContentAsString(); break; case "description": machine.Description = reader.ReadElementContentAsString(); break; case "year": machine.Year = reader.ReadElementContentAsString(); break; case "manufacturer": machine.Manufacturer = reader.ReadElementContentAsString(); break; case "publisher": // Not technically supported but used by some legacy DATs machine.Publisher = reader.ReadElementContentAsString(); break; case "category": // Not technically supported but used by some legacy DATs machine.Category = reader.ReadElementContentAsString(); break; case "trurip": // This is special metadata unique to EmuArc ReadTruRip(reader.ReadSubtree(), machine); // Skip the trurip node now that we've processed it reader.Skip(); break; case "archive": containsItems = true; DatItem archive = new Archive { Name = reader.GetAttribute("name"), Source = new Source { Index = indexId, Name = filename, }, }; archive.CopyMachineInformation(machine); // Now process and add the archive ParseAddHelper(archive, statsOnly); reader.Read(); break; case "biosset": containsItems = true; DatItem biosSet = new BiosSet { Name = reader.GetAttribute("name"), Description = reader.GetAttribute("description"), Default = reader.GetAttribute("default").AsYesNo(), Source = new Source { Index = indexId, Name = filename, }, }; biosSet.CopyMachineInformation(machine); // Now process and add the biosSet ParseAddHelper(biosSet, statsOnly); reader.Read(); break; case "disk": containsItems = true; DatItem disk = new Disk { Name = reader.GetAttribute("name"), MD5 = reader.GetAttribute("md5"), SHA1 = reader.GetAttribute("sha1"), MergeTag = reader.GetAttribute("merge"), ItemStatus = reader.GetAttribute("status").AsItemStatus(), Source = new Source { Index = indexId, Name = filename, }, }; disk.CopyMachineInformation(machine); // Now process and add the disk ParseAddHelper(disk, statsOnly); reader.Read(); break; case "media": containsItems = true; DatItem media = new Media { Name = reader.GetAttribute("name"), MD5 = reader.GetAttribute("md5"), SHA1 = reader.GetAttribute("sha1"), SHA256 = reader.GetAttribute("sha256"), SpamSum = reader.GetAttribute("spamsum"), Source = new Source { Index = indexId, Name = filename, }, }; media.CopyMachineInformation(machine); // Now process and add the media ParseAddHelper(media, statsOnly); reader.Read(); break; case "release": containsItems = true; DatItem release = new Release { Name = reader.GetAttribute("name"), Region = reader.GetAttribute("region"), Language = reader.GetAttribute("language"), Date = reader.GetAttribute("date"), Default = reader.GetAttribute("default").AsYesNo(), }; release.CopyMachineInformation(machine); // Now process and add the release ParseAddHelper(release, statsOnly); reader.Read(); break; case "rom": containsItems = true; DatItem rom = new Rom { Name = reader.GetAttribute("name"), Size = Utilities.CleanLong(reader.GetAttribute("size")), CRC = reader.GetAttribute("crc"), MD5 = reader.GetAttribute("md5"), SHA1 = reader.GetAttribute("sha1"), SHA256 = reader.GetAttribute("sha256"), SHA384 = reader.GetAttribute("sha384"), SHA512 = reader.GetAttribute("sha512"), SpamSum = reader.GetAttribute("spamsum"), MergeTag = reader.GetAttribute("merge"), ItemStatus = reader.GetAttribute("status").AsItemStatus(), Date = CleanDate(reader.GetAttribute("date")), Inverted = reader.GetAttribute("inverted").AsYesNo(), Source = new Source { Index = indexId, Name = filename, }, }; rom.CopyMachineInformation(machine); // Now process and add the rom ParseAddHelper(rom, statsOnly); reader.Read(); break; case "sample": containsItems = true; DatItem sample = new Sample { Name = reader.GetAttribute("name"), Source = new Source { Index = indexId, Name = filename, }, }; sample.CopyMachineInformation(machine); // Now process and add the sample ParseAddHelper(sample, statsOnly); reader.Read(); break; default: reader.Read(); break; } } // If no items were found for this machine, add a Blank placeholder if (!containsItems) { Blank blank = new Blank() { Source = new Source { Index = indexId, Name = filename, }, }; blank.CopyMachineInformation(machine); // Now process and add the rom ParseAddHelper(blank, statsOnly); } }