/// <summary> /// Read sccpluscart information /// </summary> /// <param name="reader">XmlReader representing a sccpluscart block</param> /// <param name="machine">Machine information to pass to contained items</param> /// <param name="diskno">Disk number to use when outputting to other DAT formats</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 ReadSccPlusCart( XmlReader reader, Machine machine, int diskno, // Standard Dat parsing string filename, int sysid, int srcid, // Miscellaneous bool keep, bool clean, bool remUnicode) { string hash = "", boot = "", remark = ""; bool containsItems = false; while (!reader.EOF) { // We only want elements if (reader.NodeType != XmlNodeType.Element) { reader.Read(); continue; } // Get the elements from the dump switch (reader.Name) { case "boot": boot = reader.ReadElementContentAsString(); break; case "hash": containsItems = true; hash = reader.ReadElementContentAsString(); break; case "remark": remark = reader.ReadElementContentAsString(); break; default: reader.Read(); break; } } // Create and add the new rom Rom rom = new Rom { Name = machine.Name + "_" + diskno + (!String.IsNullOrWhiteSpace(remark) ? " " + remark : ""), Size = -1, SHA1 = Utilities.CleanHashData(hash, Constants.SHA1Length), }; rom.CopyMachineInformation(machine); ParseAddHelper(rom, clean, remUnicode); return(containsItems); }
/// <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 dataarea information /// </summary> /// <param name="reader">XmlReader representing a dataarea block</param> /// <param name="machine">Machine information to pass to contained items</param> /// <param name="features">List of features from the parent part</param> /// <param name="areaname">Name of the containing area</param> /// <param name="areasize">Size of the containing area</param> /// <param name="partname">Name of the containing part</param> /// <param name="partinterface">Interface of the containing part</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 ReadDataArea( XmlReader reader, Machine machine, List <Tuple <string, string> > features, string areaname, long?areasize, string partname, string partinterface, // Standard Dat parsing string filename, int sysid, int srcid, // Miscellaneous bool keep, bool clean, bool remUnicode) { string key = ""; string temptype = reader.Name; bool containsItems = false; while (!reader.EOF) { // We only want elements if (reader.NodeType != XmlNodeType.Element) { reader.Read(); continue; } // Get the elements from the software switch (reader.Name) { case "rom": containsItems = true; // If the rom is continue or ignore, add the size to the previous rom if (reader.GetAttribute("loadflag") == "continue" || reader.GetAttribute("loadflag") == "ignore") { int index = this[key].Count - 1; DatItem lastrom = this[key][index]; if (lastrom.Type == ItemType.Rom) { ((Rom)lastrom).Size += Utilities.GetSize(reader.GetAttribute("size")); } this[key].RemoveAt(index); this[key].Add(lastrom); reader.Read(); continue; } 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), Offset = reader.GetAttribute("offset"), // Value = reader.GetAttribute("value"); ItemStatus = Utilities.GetItemStatus(reader.GetAttribute("status")), // LoadFlag = reader.GetAttribute("loadflag"), // (load16_byte|load16_word|load16_word_swap|load32_byte|load32_word|load32_word_swap|load32_dword|load64_word|load64_word_swap|reload|fill|continue|reload_plain|ignore) AreaName = areaname, AreaSize = areasize, Features = features, PartName = partname, PartInterface = partinterface, SystemID = sysid, System = filename, SourceID = srcid, }; rom.CopyMachineInformation(machine); // Now process and add the rom key = ParseAddHelper(rom, clean, remUnicode); reader.Read(); break; default: reader.Read(); break; } } return(containsItems); }
/// <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> /// Read set information /// </summary> /// <param name="cmpr">ClrMameProReader to use to parse the header</param> /// <param name="filename">Name of the file to be parsed</param> /// <param name="indexId">Index ID for the DAT</param> private void ReadGame(ClrMameProReader cmpr, string filename, int indexId) { // Prepare all internal variables bool containsItems = false; Machine machine = new Machine() { MachineType = MachineType.NULL, }; // If there's no subtree to the header, skip it if (cmpr == null || cmpr.EndOfStream) { return; } // While we don't hit an end element or end of stream while (!cmpr.EndOfStream) { cmpr.ReadNextLine(); // Ignore comments and nothingness if (cmpr.RowType == CmpRowType.None || cmpr.RowType == CmpRowType.Comment) { continue; } // If we reached the end of a section, break if (cmpr.RowType == CmpRowType.EndTopLevel) { break; } // Handle any standalone items if (cmpr.RowType == CmpRowType.Standalone && cmpr.Standalone != null) { string itemKey = cmpr.Standalone?.Key.ToLowerInvariant(); string itemVal = cmpr.Standalone?.Value; switch (itemKey) { case "name": machine.Name = (itemVal.ToLowerInvariant().EndsWith(".zip") ? itemVal.Remove(itemVal.Length - 4) : itemVal); machine.Description = (itemVal.ToLowerInvariant().EndsWith(".zip") ? itemVal.Remove(itemVal.Length - 4) : itemVal); break; } } // Handle any internal items else if (cmpr.RowType == CmpRowType.Internal && string.Equals(cmpr.InternalName, "file", StringComparison.OrdinalIgnoreCase) && cmpr.Internal != null) { containsItems = true; // Create the proper DatItem based on the type Rom item = DatItem.Create(ItemType.Rom) as Rom; // Then populate it with information item.CopyMachineInformation(machine); item.Source = new Source { Index = indexId, Name = filename, }; // Loop through all of the attributes foreach (var kvp in cmpr.Internal) { string attrKey = kvp.Key; string attrVal = kvp.Value; switch (attrKey) { //If the item is empty, we automatically skip it because it's a fluke case "": continue; // Regular attributes case "name": item.Name = attrVal; break; case "size": item.Size = Sanitizer.CleanLong(attrVal); break; case "crc": item.CRC = attrVal; break; case "date": item.Date = attrVal; break; } } // Now process and add the rom ParseAddHelper(item); } } // 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); } }
/// <summary> /// Use cloneof tags to add roms to the parents, removing the child sets in the process /// </summary> /// <param name="datFile">Current DatFile object to run operations on</param> /// <param name="subfolder">True to add DatItems to subfolder of parent (not including Disk), false otherwise</param> internal static void AddRomsFromChildren(DatFile datFile, bool subfolder = true) { List <string> games = datFile.Items.Keys.OrderBy(g => g).ToList(); foreach (string game in games) { // If the game has no items in it, we want to continue if (datFile.Items[game].Count == 0) { continue; } // Determine if the game has a parent or not string parent = null; if (!string.IsNullOrWhiteSpace(datFile.Items[game][0].Machine.CloneOf)) { parent = datFile.Items[game][0].Machine.CloneOf; } // If there is no parent, then we continue if (string.IsNullOrWhiteSpace(parent)) { continue; } // Otherwise, move the items from the current game to a subfolder of the parent game DatItem copyFrom; if (datFile.Items[parent].Count == 0) { copyFrom = new Rom(); copyFrom.Machine.Name = parent; copyFrom.Machine.Description = parent; } else { copyFrom = datFile.Items[parent][0]; } ConcurrentList <DatItem> items = datFile.Items[game]; foreach (DatItem item in items) { // Special disk handling if (item.ItemType == ItemType.Disk) { Disk disk = item as Disk; // If the merge tag exists and the parent already contains it, skip if (disk.MergeTag != null && datFile.Items[parent].Where(i => i.ItemType == ItemType.Disk).Select(i => (i as Disk).Name).Contains(disk.MergeTag)) { continue; } // If the merge tag exists but the parent doesn't contain it, add to parent else if (disk.MergeTag != null && !datFile.Items[parent].Where(i => i.ItemType == ItemType.Disk).Select(i => (i as Disk).Name).Contains(disk.MergeTag)) { disk.CopyMachineInformation(copyFrom); datFile.Items.Add(parent, disk); } // If there is no merge tag, add to parent else if (disk.MergeTag == null) { disk.CopyMachineInformation(copyFrom); datFile.Items.Add(parent, disk); } } // Special rom handling else if (item.ItemType == ItemType.Rom) { Rom rom = item as Rom; // If the merge tag exists and the parent already contains it, skip if (rom.MergeTag != null && datFile.Items[parent].Where(i => i.ItemType == ItemType.Rom).Select(i => (i as Rom).Name).Contains(rom.MergeTag)) { continue; } // If the merge tag exists but the parent doesn't contain it, add to subfolder of parent else if (rom.MergeTag != null && !datFile.Items[parent].Where(i => i.ItemType == ItemType.Rom).Select(i => (i as Rom).Name).Contains(rom.MergeTag)) { if (subfolder) { rom.Name = $"{rom.Machine.Name}\\{rom.Name}"; } rom.CopyMachineInformation(copyFrom); datFile.Items.Add(parent, rom); } // If the parent doesn't already contain this item, add to subfolder of parent else if (!datFile.Items[parent].Contains(item)) { if (subfolder) { rom.Name = $"{item.Machine.Name}\\{rom.Name}"; } rom.CopyMachineInformation(copyFrom); datFile.Items.Add(parent, rom); } } // All other that would be missing to subfolder of parent else if (!datFile.Items[parent].Contains(item)) { if (subfolder) { item.SetName($"{item.Machine.Name}\\{item.GetName()}"); } item.CopyMachineInformation(copyFrom); datFile.Items.Add(parent, item); } } // Then, remove the old game so it's not picked up by the writer datFile.Items.Remove(game); } }
/// <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); } }