Пример #1
0
        /// <summary>
        /// Use cloneof tags to add roms to the children, setting the new romof tag in the process
        /// </summary>
        /// <param name="datFile">Current DatFile object to run operations on</param>
        internal static void AddRomsFromParent(DatFile datFile)
        {
            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 the parent doesnt exist, we want to continue
                if (string.IsNullOrWhiteSpace(parent))
                {
                    continue;
                }

                // If the parent doesn't have any items, we want to continue
                if (datFile.Items[parent].Count == 0)
                {
                    continue;
                }

                // If the parent exists and has items, we copy the items from the parent to the current game
                DatItem copyFrom = datFile.Items[game][0];
                ConcurrentList <DatItem> parentItems = datFile.Items[parent];
                foreach (DatItem item in parentItems)
                {
                    DatItem datItem = (DatItem)item.Clone();
                    datItem.CopyMachineInformation(copyFrom);
                    if (datFile.Items[game].Where(i => i.GetName()?.ToLowerInvariant() == datItem.GetName()?.ToLowerInvariant()).Count() == 0 &&
                        !datFile.Items[game].Contains(datItem))
                    {
                        datFile.Items.Add(game, datItem);
                    }
                }

                // Now we want to get the parent romof tag and put it in each of the items
                ConcurrentList <DatItem> items = datFile.Items[game];
                string romof = datFile.Items[parent][0].Machine.RomOf;
                foreach (DatItem item in items)
                {
                    item.Machine.RomOf = romof;
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Read Files information
        /// </summary>
        /// <param name="xtr">XmlReader to use to parse the header</param>
        /// <param name="machine">Machine to copy information from</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>
        private void ReadFiles(XmlReader xtr, Machine machine, bool statsOnly, string filename, int indexId)
        {
            // If the reader is invalid, skip
            if (xtr == null)
            {
                return;
            }

            // Otherwise, read the items
            xtr.MoveToContent();
            while (!xtr.EOF)
            {
                // We only want elements
                if (xtr.NodeType != XmlNodeType.Element)
                {
                    xtr.Read();
                    continue;
                }

                switch (xtr.Name)
                {
                case "datitem":
                    XmlSerializer xs   = new XmlSerializer(typeof(DatItem));
                    DatItem       item = xs.Deserialize(xtr.ReadSubtree()) as DatItem;
                    item.CopyMachineInformation(machine);
                    item.Source = new Source {
                        Name = filename, Index = indexId
                    };
                    ParseAddHelper(item, statsOnly);
                    xtr.Skip();
                    break;

                default:
                    xtr.Read();
                    break;
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Read set information
        /// </summary>
        /// <param name="reader">StreamReader to use to parse the header</param>
        /// <param name="resource">True if the item is a resource (bios), false otherwise</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 ReadSet(
            StreamReader reader,
            bool resource,

            // Standard Dat parsing
            string filename,
            int sysid,
            int srcid,

            // Miscellaneous
            bool keep,
            bool clean,
            bool remUnicode)
        {
            // Prepare all internal variables
            bool    containsItems = false;
            Machine machine       = new Machine()
            {
                MachineType = (resource ? MachineType.Bios : MachineType.None),
            };

            // If there's no subtree to the header, skip it
            if (reader == null || reader.EndOfStream)
            {
                return;
            }

            // Otherwise, add what is possible
            string line = reader.ReadLine();

            while (!Regex.IsMatch(line, Constants.EndPatternCMP))
            {
                // We only want elements
                if (line.Trim().StartsWith("#"))
                {
                    line = reader.ReadLine();
                    continue;
                }

                // Item-specific lines have a known pattern
                string trimmedline = line.Trim();
                if (trimmedline.StartsWith("archive (") ||
                    trimmedline.StartsWith("biosset (") ||
                    trimmedline.StartsWith("disk (") ||
                    trimmedline.StartsWith("file (") || // This is a DOSCenter file, not a SabreDAT file
                    trimmedline.StartsWith("release (") ||
                    trimmedline.StartsWith("rom (") ||
                    (trimmedline.StartsWith("sample") && !trimmedline.StartsWith("sampleof")))
                {
                    containsItems = true;
                    ItemType temptype = ItemType.Rom;
                    if (line.Trim().StartsWith("rom ("))
                    {
                        temptype = ItemType.Rom;
                    }
                    else if (line.Trim().StartsWith("disk ("))
                    {
                        temptype = ItemType.Disk;
                    }
                    else if (line.Trim().StartsWith("file ("))
                    {
                        temptype = ItemType.Rom;
                    }
                    else if (line.Trim().StartsWith("sample"))
                    {
                        temptype = ItemType.Sample;
                    }

                    // Create the proper DatItem based on the type
                    DatItem item = Utilities.GetDatItem(temptype);

                    // Then populate it with information
                    item.CopyMachineInformation(machine);

                    item.SystemID = sysid;
                    item.System   = filename;
                    item.SourceID = srcid;

                    // If we have a sample, treat it special
                    if (temptype == ItemType.Sample)
                    {
                        line      = line.Trim().Remove(0, 6).Trim().Replace("\"", ""); // Remove "sample" from the input string
                        item.Name = line;

                        // Now process and add the sample
                        ParseAddHelper(item, clean, remUnicode);
                        line = reader.ReadLine();
                        continue;
                    }

                    // Get the line split by spaces and quotes
                    string[] linegc = Utilities.SplitLineAsCMP(line);

                    // Special cases for DOSCenter DATs only because of how the lines are arranged
                    if (line.Trim().StartsWith("file ("))
                    {
                        // Loop over the specifics
                        for (int i = 0; i < linegc.Length; i++)
                        {
                            // Names are not quoted, for some stupid reason
                            if (linegc[i] == "name")
                            {
                                // Get the name in order until we find the next flag
                                while (++i < linegc.Length && linegc[i] != "size" &&
                                       linegc[i] != "date" &&
                                       linegc[i] != "crc" &&
                                       linegc[i] != "md5" &&
                                       linegc[i] != "sha1" &&
                                       linegc[i] != "sha256" &&
                                       linegc[i] != "sha384" &&
                                       linegc[i] != "sha512")
                                {
                                    item.Name += " " + linegc[i];
                                }

                                // Perform correction
                                item.Name = item.Name.TrimStart();
                                i--;
                            }

                            // Get the size from the next part
                            else if (linegc[i] == "size")
                            {
                                long tempsize = -1;
                                if (!Int64.TryParse(linegc[++i], out tempsize))
                                {
                                    tempsize = 0;
                                }
                                ((Rom)item).Size = tempsize;
                            }

                            // Get the date from the next part
                            else if (linegc[i] == "date")
                            {
                                ((Rom)item).Date = linegc[++i].Replace("\"", "") + " " + linegc[++i].Replace("\"", "");
                            }

                            // Get the CRC from the next part
                            else if (linegc[i] == "crc")
                            {
                                ((Rom)item).CRC = linegc[++i].Replace("\"", "").ToLowerInvariant();
                            }

                            // Get the MD5 from the next part
                            else if (linegc[i] == "md5")
                            {
                                ((Rom)item).MD5 = linegc[++i].Replace("\"", "").ToLowerInvariant();
                            }

                            // Get the SHA1 from the next part
                            else if (linegc[i] == "sha1")
                            {
                                ((Rom)item).SHA1 = linegc[++i].Replace("\"", "").ToLowerInvariant();
                            }

                            // Get the SHA256 from the next part
                            else if (linegc[i] == "sha256")
                            {
                                ((Rom)item).SHA256 = linegc[++i].Replace("\"", "").ToLowerInvariant();
                            }

                            // Get the SHA384 from the next part
                            else if (linegc[i] == "sha384")
                            {
                                ((Rom)item).SHA384 = linegc[++i].Replace("\"", "").ToLowerInvariant();
                            }

                            // Get the SHA512 from the next part
                            else if (linegc[i] == "sha512")
                            {
                                ((Rom)item).SHA512 = linegc[++i].Replace("\"", "").ToLowerInvariant();
                            }
                        }

                        // Now process and add the rom
                        ParseAddHelper(item, clean, remUnicode);
                        line = reader.ReadLine();
                        continue;
                    }

                    // Loop over all attributes normally and add them if possible
                    for (int i = 0; i < linegc.Length; i++)
                    {
                        // Look at the current item and use it if possible
                        string quoteless = linegc[i].Replace("\"", "");
                        switch (quoteless)
                        {
                        //If the item is empty, we automatically skip it because it's a fluke
                        case "":
                            continue;

                        // Special cases for standalone item statuses
                        case "baddump":
                        case "good":
                        case "nodump":
                        case "verified":
                            ItemStatus tempStandaloneStatus = Utilities.GetItemStatus(quoteless);
                            if (item.ItemType == ItemType.Rom)
                            {
                                ((Rom)item).ItemStatus = tempStandaloneStatus;
                            }
                            else if (item.ItemType == ItemType.Disk)
                            {
                                ((Disk)item).ItemStatus = tempStandaloneStatus;
                            }
                            break;

                        // Regular attributes
                        case "name":
                            quoteless = linegc[++i].Replace("\"", "");
                            item.Name = quoteless;
                            break;

                        case "size":
                            if (item.ItemType == ItemType.Rom)
                            {
                                quoteless = linegc[++i].Replace("\"", "");
                                if (Int64.TryParse(quoteless, out long size))
                                {
                                    ((Rom)item).Size = size;
                                }
                                else
                                {
                                    ((Rom)item).Size = -1;
                                }
                            }
                            break;

                        case "crc":
                            if (item.ItemType == ItemType.Rom)
                            {
                                quoteless       = linegc[++i].Replace("\"", "");
                                ((Rom)item).CRC = Utilities.CleanHashData(quoteless, Constants.CRCLength);
                            }
                            break;

                        case "md5":
                            if (item.ItemType == ItemType.Rom)
                            {
                                quoteless       = linegc[++i].Replace("\"", "");
                                ((Rom)item).MD5 = Utilities.CleanHashData(quoteless, Constants.MD5Length);
                            }
                            else if (item.ItemType == ItemType.Disk)
                            {
                                i++;
                                quoteless        = linegc[i].Replace("\"", "");
                                ((Disk)item).MD5 = Utilities.CleanHashData(quoteless, Constants.MD5Length);
                            }
                            break;

                        case "sha1":
                            if (item.ItemType == ItemType.Rom)
                            {
                                quoteless        = linegc[++i].Replace("\"", "");
                                ((Rom)item).SHA1 = Utilities.CleanHashData(quoteless, Constants.SHA1Length);
                            }
                            else if (item.ItemType == ItemType.Disk)
                            {
                                quoteless         = linegc[++i].Replace("\"", "");
                                ((Disk)item).SHA1 = Utilities.CleanHashData(quoteless, Constants.SHA1Length);
                            }
                            break;

                        case "sha256":
                            if (item.ItemType == ItemType.Rom)
                            {
                                quoteless          = linegc[++i].Replace("\"", "");
                                ((Rom)item).SHA256 = Utilities.CleanHashData(quoteless, Constants.SHA256Length);
                            }
                            else if (item.ItemType == ItemType.Disk)
                            {
                                quoteless           = linegc[++i].Replace("\"", "");
                                ((Disk)item).SHA256 = Utilities.CleanHashData(quoteless, Constants.SHA256Length);
                            }
                            break;

                        case "sha384":
                            if (item.ItemType == ItemType.Rom)
                            {
                                quoteless          = linegc[++i].Replace("\"", "");
                                ((Rom)item).SHA384 = Utilities.CleanHashData(quoteless, Constants.SHA384Length);
                            }
                            else if (item.ItemType == ItemType.Disk)
                            {
                                quoteless           = linegc[++i].Replace("\"", "");
                                ((Disk)item).SHA384 = Utilities.CleanHashData(quoteless, Constants.SHA384Length);
                            }
                            break;

                        case "sha512":
                            if (item.ItemType == ItemType.Rom)
                            {
                                quoteless          = linegc[++i].Replace("\"", "");
                                ((Rom)item).SHA512 = Utilities.CleanHashData(quoteless, Constants.SHA512Length);
                            }
                            else if (item.ItemType == ItemType.Disk)
                            {
                                quoteless           = linegc[++i].Replace("\"", "");
                                ((Disk)item).SHA512 = Utilities.CleanHashData(quoteless, Constants.SHA512Length);
                            }
                            break;

                        case "status":
                        case "flags":
                            quoteless = linegc[++i].Replace("\"", "");
                            ItemStatus tempFlagStatus = Utilities.GetItemStatus(quoteless);
                            if (item.ItemType == ItemType.Rom)
                            {
                                ((Rom)item).ItemStatus = tempFlagStatus;
                            }
                            else if (item.ItemType == ItemType.Disk)
                            {
                                ((Disk)item).ItemStatus = tempFlagStatus;
                            }
                            break;

                        case "date":
                            if (item.ItemType == ItemType.Rom)
                            {
                                // If we have quotes in the next item, assume only one item
                                if (linegc[i + 1].Contains("\""))
                                {
                                    quoteless = linegc[++i].Replace("\"", "");
                                }
                                // Otherwise, we assume we need to read the next two items
                                else
                                {
                                    quoteless = linegc[++i].Replace("\"", "") + " " + linegc[++i].Replace("\"", "");
                                }
                                ((Rom)item).Date = quoteless;
                            }
                            else if (item.ItemType == ItemType.Release)
                            {
                                // If we have quotes in the next item, assume only one item
                                if (linegc[i + 1].Contains("\""))
                                {
                                    quoteless = linegc[++i].Replace("\"", "");
                                }
                                // Otherwise, we assume we need to read the next two items
                                else
                                {
                                    quoteless = linegc[++i].Replace("\"", "") + " " + linegc[++i].Replace("\"", "");
                                }
                                ((Release)item).Date = quoteless;
                            }
                            break;

                        case "default":
                            if (item.ItemType == ItemType.BiosSet)
                            {
                                quoteless = linegc[++i].Replace("\"", "");
                                ((BiosSet)item).Default = Utilities.GetYesNo(quoteless.ToLowerInvariant());
                            }
                            else if (item.ItemType == ItemType.Release)
                            {
                                quoteless = linegc[++i].Replace("\"", "");
                                ((Release)item).Default = Utilities.GetYesNo(quoteless.ToLowerInvariant());
                            }
                            break;

                        case "description":
                            if (item.ItemType == ItemType.BiosSet)
                            {
                                quoteless = linegc[++i].Replace("\"", "");
                                ((BiosSet)item).Description = quoteless.ToLowerInvariant();
                            }
                            break;

                        case "region":
                            if (item.ItemType == ItemType.Release)
                            {
                                quoteless = linegc[++i].Replace("\"", "");
                                ((Release)item).Region = quoteless.ToLowerInvariant();
                            }
                            break;

                        case "language":
                            if (item.ItemType == ItemType.Release)
                            {
                                quoteless = linegc[++i].Replace("\"", "");
                                ((Release)item).Language = quoteless.ToLowerInvariant();
                            }
                            break;
                        }
                    }

                    // Now process and add the rom
                    ParseAddHelper(item, clean, remUnicode);

                    line = reader.ReadLine();
                    continue;
                }

                // Set-specific lines have a known pattern
                GroupCollection setgc   = Regex.Match(line, Constants.ItemPatternCMP).Groups;
                string          itemval = setgc[2].Value.Replace("\"", "");

                switch (setgc[1].Value)
                {
                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;

                case "description":
                    machine.Description = itemval;
                    break;

                case "year":
                    machine.Year = itemval;
                    break;

                case "manufacturer":
                    machine.Manufacturer = itemval;
                    break;

                case "cloneof":
                    machine.CloneOf = itemval;
                    break;

                case "romof":
                    machine.RomOf = itemval;
                    break;

                case "sampleof":
                    machine.SampleOf = itemval;
                    break;
                }

                line = reader.ReadLine();
            }

            // 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);
            }
        }
Пример #4
0
        /// <summary>
        /// Read item information
        /// </summary>
        /// <param name="machineObj">JObject representing a single datitem</param>
        /// <param name="filename">Name of the file to be parsed</param>
        /// <param name="indexId">Index ID for the DAT</param>
        /// <param name="machine">Machine information to add to the parsed items</param>
        private void ReadItem(
            JObject itemObj,

            // Standard Dat parsing
            string filename,
            int indexId,

            // Miscellaneous
            Machine machine)
        {
            // If we have an empty item, skip it
            if (itemObj == null)
            {
                return;
            }

            // Prepare internal variables
            DatItem datItem = null;

            // Read the datitem info, if possible
            if (itemObj.ContainsKey("datitem"))
            {
                JToken datItemObj = itemObj["datitem"];
                switch (datItemObj.Value <string>("type").AsItemType())
                {
                case ItemType.Adjuster:
                    datItem = datItemObj.ToObject <Adjuster>();
                    break;

                case ItemType.Analog:
                    datItem = datItemObj.ToObject <Analog>();
                    break;

                case ItemType.Archive:
                    datItem = datItemObj.ToObject <Archive>();
                    break;

                case ItemType.BiosSet:
                    datItem = datItemObj.ToObject <BiosSet>();
                    break;

                case ItemType.Blank:
                    datItem = datItemObj.ToObject <Blank>();
                    break;

                case ItemType.Chip:
                    datItem = datItemObj.ToObject <Chip>();
                    break;

                case ItemType.Condition:
                    datItem = datItemObj.ToObject <Condition>();
                    break;

                case ItemType.Configuration:
                    datItem = datItemObj.ToObject <Configuration>();
                    break;

                case ItemType.Control:
                    datItem = datItemObj.ToObject <Control>();
                    break;

                case ItemType.DataArea:
                    datItem = datItemObj.ToObject <DataArea>();
                    break;

                case ItemType.Device:
                    datItem = datItemObj.ToObject <Device>();
                    break;

                case ItemType.DeviceReference:
                    datItem = datItemObj.ToObject <DeviceReference>();
                    break;

                case ItemType.DipSwitch:
                    datItem = datItemObj.ToObject <DipSwitch>();
                    break;

                case ItemType.Disk:
                    datItem = datItemObj.ToObject <Disk>();
                    break;

                case ItemType.DiskArea:
                    datItem = datItemObj.ToObject <DiskArea>();
                    break;

                case ItemType.Display:
                    datItem = datItemObj.ToObject <Display>();
                    break;

                case ItemType.Driver:
                    datItem = datItemObj.ToObject <Driver>();
                    break;

                case ItemType.Extension:
                    datItem = datItemObj.ToObject <Extension>();
                    break;

                case ItemType.Feature:
                    datItem = datItemObj.ToObject <Feature>();
                    break;

                case ItemType.Info:
                    datItem = datItemObj.ToObject <Info>();
                    break;

                case ItemType.Input:
                    datItem = datItemObj.ToObject <Input>();
                    break;

                case ItemType.Instance:
                    datItem = datItemObj.ToObject <Instance>();
                    break;

                case ItemType.Location:
                    datItem = datItemObj.ToObject <Location>();
                    break;

                case ItemType.Media:
                    datItem = datItemObj.ToObject <Media>();
                    break;

                case ItemType.Part:
                    datItem = datItemObj.ToObject <Part>();
                    break;

                case ItemType.PartFeature:
                    datItem = datItemObj.ToObject <PartFeature>();
                    break;

                case ItemType.Port:
                    datItem = datItemObj.ToObject <Port>();
                    break;

                case ItemType.RamOption:
                    datItem = datItemObj.ToObject <RamOption>();
                    break;

                case ItemType.Release:
                    datItem = datItemObj.ToObject <Release>();
                    break;

                case ItemType.Rom:
                    datItem = datItemObj.ToObject <Rom>();
                    break;

                case ItemType.Sample:
                    datItem = datItemObj.ToObject <Sample>();
                    break;

                case ItemType.Setting:
                    datItem = datItemObj.ToObject <Setting>();
                    break;

                case ItemType.SharedFeature:
                    datItem = datItemObj.ToObject <SharedFeature>();
                    break;

                case ItemType.Slot:
                    datItem = datItemObj.ToObject <Slot>();
                    break;

                case ItemType.SlotOption:
                    datItem = datItemObj.ToObject <SlotOption>();
                    break;

                case ItemType.SoftwareList:
                    datItem = datItemObj.ToObject <DatItems.SoftwareList>();
                    break;

                case ItemType.Sound:
                    datItem = datItemObj.ToObject <Sound>();
                    break;
                }
            }

            // If we got a valid datitem, copy machine info and add
            if (datItem != null)
            {
                datItem.CopyMachineInformation(machine);
                datItem.Source = new Source {
                    Index = indexId, Name = filename
                };
                ParseAddHelper(datItem);
            }
        }
Пример #5
0
        /// <summary>
        /// Read set information
        /// </summary>
        /// <param name="cmpr">ClrMameProReader to use to parse the header</param>
        /// <param name="resource">True if the item is a resource (bios), false otherwise</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>
        private void ReadSet(
            ClrMameProReader cmpr,
            bool resource,
            bool statsOnly,

            // Standard Dat parsing
            string filename,
            int indexId)
        {
            // Prepare all internal variables
            bool    containsItems = false;
            Machine machine       = new Machine()
            {
                MachineType = (resource ? MachineType.Bios : 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;
                        break;

                    case "description":
                        machine.Description = itemVal;
                        break;

                    case "year":
                        machine.Year = itemVal;
                        break;

                    case "manufacturer":
                        machine.Manufacturer = itemVal;
                        break;

                    case "category":
                        machine.Category = itemVal;
                        break;

                    case "cloneof":
                        machine.CloneOf = itemVal;
                        break;

                    case "romof":
                        machine.RomOf = itemVal;
                        break;

                    case "sampleof":
                        machine.SampleOf = itemVal;
                        break;
                    }
                }

                // Handle any internal items
                else if (cmpr.RowType == CmpRowType.Internal &&
                         !string.IsNullOrWhiteSpace(cmpr.InternalName) &&
                         cmpr.Internal != null)
                {
                    containsItems = true;
                    string itemKey = cmpr.InternalName;

                    // Create the proper DatItem based on the type
                    ItemType itemType = itemKey.AsItemType() ?? ItemType.Rom;
                    DatItem  item     = DatItem.Create(itemType);

                    // Then populate it with information
                    item.CopyMachineInformation(machine);

                    item.Source.Index = indexId;
                    item.Source.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.SetName(attrVal);
                            break;

                        case "size":
                            if (item.ItemType == ItemType.Rom)
                            {
                                (item as Rom).Size = Utilities.CleanLong(attrVal);
                            }

                            break;

                        case "crc":
                            if (item.ItemType == ItemType.Rom)
                            {
                                (item as Rom).CRC = attrVal;
                            }

                            break;

                        case "md5":
                            if (item.ItemType == ItemType.Disk)
                            {
                                (item as Disk).MD5 = attrVal;
                            }
                            else if (item.ItemType == ItemType.Media)
                            {
                                (item as Media).MD5 = attrVal;
                            }
                            else if (item.ItemType == ItemType.Rom)
                            {
                                (item as Rom).MD5 = attrVal;
                            }

                            break;

                        case "sha1":
                            if (item.ItemType == ItemType.Disk)
                            {
                                (item as Disk).SHA1 = attrVal;
                            }
                            else if (item.ItemType == ItemType.Media)
                            {
                                (item as Media).SHA1 = attrVal;
                            }
                            else if (item.ItemType == ItemType.Rom)
                            {
                                (item as Rom).SHA1 = attrVal;
                            }

                            break;

                        case "sha256":
                            if (item.ItemType == ItemType.Media)
                            {
                                (item as Media).SHA256 = attrVal;
                            }
                            else if (item.ItemType == ItemType.Rom)
                            {
                                (item as Rom).SHA256 = attrVal;
                            }

                            break;

                        case "sha384":
                            if (item.ItemType == ItemType.Rom)
                            {
                                (item as Rom).SHA384 = attrVal;
                            }

                            break;

                        case "sha512":
                            if (item.ItemType == ItemType.Rom)
                            {
                                (item as Rom).SHA512 = attrVal;
                            }

                            break;

                        case "spamsum":
                            if (item.ItemType == ItemType.Media)
                            {
                                (item as Media).SpamSum = attrVal;
                            }
                            else if (item.ItemType == ItemType.Rom)
                            {
                                (item as Rom).SpamSum = attrVal;
                            }

                            break;

                        case "status":
                            ItemStatus tempFlagStatus = attrVal.AsItemStatus();
                            if (item.ItemType == ItemType.Disk)
                            {
                                (item as Disk).ItemStatus = tempFlagStatus;
                            }
                            else if (item.ItemType == ItemType.Rom)
                            {
                                (item as Rom).ItemStatus = tempFlagStatus;
                            }

                            break;

                        case "date":
                            if (item.ItemType == ItemType.Release)
                            {
                                (item as Release).Date = attrVal;
                            }
                            else if (item.ItemType == ItemType.Rom)
                            {
                                (item as Rom).Date = attrVal;
                            }

                            break;

                        case "default":
                            if (item.ItemType == ItemType.BiosSet)
                            {
                                (item as BiosSet).Default = attrVal.AsYesNo();
                            }
                            else if (item.ItemType == ItemType.Release)
                            {
                                (item as Release).Default = attrVal.AsYesNo();
                            }

                            break;

                        case "description":
                            if (item.ItemType == ItemType.BiosSet)
                            {
                                (item as BiosSet).Description = attrVal;
                            }

                            break;

                        case "region":
                            if (item.ItemType == ItemType.Release)
                            {
                                (item as Release).Region = attrVal;
                            }

                            break;

                        case "language":
                            if (item.ItemType == ItemType.Release)
                            {
                                (item as Release).Language = attrVal;
                            }

                            break;
                        }
                    }

                    // Now process and add the rom
                    ParseAddHelper(item, statsOnly);
                }
            }

            // 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);
            }
        }
Пример #6
0
        /// <summary>
        /// Use device_ref and optionally slotoption tags to add roms to the children
        /// </summary>
        /// <param name="datFile">Current DatFile object to run operations on</param>
        /// <param name="dev">True if only child device sets are touched, false for non-device sets (default)</param>
        /// <param name="useSlotOptions">True if slotoptions tags are used as well, false otherwise</param>
        internal static bool AddRomsFromDevices(DatFile datFile, bool dev = false, bool useSlotOptions = false)
        {
            bool          foundnew = false;
            List <string> machines = datFile.Items.Keys.OrderBy(g => g).ToList();

            foreach (string machine in machines)
            {
                // If the machine doesn't have items, we continue
                if (datFile.Items[machine] == null || datFile.Items[machine].Count == 0)
                {
                    continue;
                }

                // If the machine (is/is not) a device, we want to continue
                if (dev ^ (datFile.Items[machine][0].Machine.MachineType.HasFlag(MachineType.Device)))
                {
                    continue;
                }

                // Get all device reference names from the current machine
                List <string> deviceReferences = datFile.Items[machine]
                                                 .Where(i => i.ItemType == ItemType.DeviceReference)
                                                 .Select(i => i as DeviceReference)
                                                 .Select(dr => dr.Name)
                                                 .Distinct()
                                                 .ToList();

                // Get all slot option names from the current machine
                List <string> slotOptions = datFile.Items[machine]
                                            .Where(i => i.ItemType == ItemType.Slot)
                                            .Select(i => i as Slot)
                                            .Where(s => s.SlotOptionsSpecified)
                                            .SelectMany(s => s.SlotOptions)
                                            .Select(so => so.DeviceName)
                                            .Distinct()
                                            .ToList();

                // If we're checking device references
                if (deviceReferences.Any())
                {
                    // Loop through all names and check the corresponding machines
                    List <string> newDeviceReferences = new List <string>();
                    foreach (string deviceReference in deviceReferences)
                    {
                        // If the machine doesn't exist then we continue
                        if (datFile.Items[deviceReference] == null || datFile.Items[deviceReference].Count == 0)
                        {
                            continue;
                        }

                        // Add to the list of new device reference names
                        ConcurrentList <DatItem> devItems = datFile.Items[deviceReference];
                        newDeviceReferences.AddRange(devItems
                                                     .Where(i => i.ItemType == ItemType.DeviceReference)
                                                     .Select(i => (i as DeviceReference).Name));

                        // Set new machine information and add to the current machine
                        DatItem copyFrom = datFile.Items[machine][0];
                        foreach (DatItem item in devItems)
                        {
                            // If the parent machine doesn't already contain this item, add it
                            if (!datFile.Items[machine].Any(i => i.ItemType == item.ItemType && i.GetName() == item.GetName()))
                            {
                                // Set that we found new items
                                foundnew = true;

                                // Clone the item and then add it
                                DatItem datItem = (DatItem)item.Clone();
                                datItem.CopyMachineInformation(copyFrom);
                                datFile.Items.Add(machine, datItem);
                            }
                        }
                    }

                    // Now that every device reference is accounted for, add the new list of device references, if they don't already exist
                    foreach (string deviceReference in newDeviceReferences.Distinct())
                    {
                        if (!deviceReferences.Contains(deviceReference))
                        {
                            datFile.Items[machine].Add(new DeviceReference()
                            {
                                Name = deviceReference
                            });
                        }
                    }
                }

                // If we're checking slotoptions
                if (useSlotOptions && slotOptions.Any())
                {
                    // Loop through all names and check the corresponding machines
                    List <string> newSlotOptions = new List <string>();
                    foreach (string slotOption in slotOptions)
                    {
                        // If the machine doesn't exist then we continue
                        if (datFile.Items[slotOption] == null || datFile.Items[slotOption].Count == 0)
                        {
                            continue;
                        }

                        // Add to the list of new slot option names
                        ConcurrentList <DatItem> slotItems = datFile.Items[slotOption];
                        newSlotOptions.AddRange(slotItems
                                                .Where(i => i.ItemType == ItemType.Slot)
                                                .Where(s => (s as Slot).SlotOptionsSpecified)
                                                .SelectMany(s => (s as Slot).SlotOptions)
                                                .Select(o => o.DeviceName));

                        // Set new machine information and add to the current machine
                        DatItem copyFrom = datFile.Items[machine][0];
                        foreach (DatItem item in slotItems)
                        {
                            // If the parent machine doesn't already contain this item, add it
                            if (!datFile.Items[machine].Any(i => i.ItemType == item.ItemType && i.GetName() == item.GetName()))
                            {
                                // Set that we found new items
                                foundnew = true;

                                // Clone the item and then add it
                                DatItem datItem = (DatItem)item.Clone();
                                datItem.CopyMachineInformation(copyFrom);
                                datFile.Items.Add(machine, datItem);
                            }
                        }
                    }

                    // Now that every device is accounted for, add the new list of slot options, if they don't already exist
                    foreach (string slotOption in newSlotOptions.Distinct())
                    {
                        if (!slotOptions.Contains(slotOption))
                        {
                            datFile.Items[machine].Add(new Slot()
                            {
                                SlotOptions = new List <SlotOption> {
                                    new SlotOption {
                                        DeviceName = slotOption
                                    }
                                }
                            });
                        }
                    }
                }
            }

            return(foundnew);
        }
Пример #7
0
        /// <summary>
        /// Find duplicates and rebuild individual files to output
        /// </summary>
        /// <param name="datFile">Current DatFile object to rebuild from</param>
        /// <param name="datItem">Information for the current file to rebuild from</param>
        /// <param name="file">Name of the file to process</param>
        /// <param name="outDir">Output directory to use to build to</param>
        /// <param name="date">True if the date from the DAT should be used if available, false otherwise</param>
        /// <param name="inverse">True if the DAT should be used as a filter instead of a template, false otherwise</param>
        /// <param name="outputFormat">Output format that files should be written to</param>
        /// <param name="isZip">True if the input file is an archive, false if the file is TGZ/TXZ, null otherwise</param>
        /// <returns>True if the file was able to be rebuilt, false otherwise</returns>
        private static bool RebuildIndividualFile(
            DatFile datFile,
            DatItem datItem,
            string file,
            string outDir,
            bool date,
            bool inverse,
            OutputFormat outputFormat,
            bool?isZip = null)
        {
            // Set the initial output value
            bool rebuilt = false;

            // If the DatItem is a Disk or Media, force rebuilding to a folder except if TGZ or TXZ
            if ((datItem.ItemType == ItemType.Disk || datItem.ItemType == ItemType.Media) &&
                !(outputFormat == OutputFormat.TorrentGzip || outputFormat == OutputFormat.TorrentGzipRomba) &&
                !(outputFormat == OutputFormat.TorrentXZ || outputFormat == OutputFormat.TorrentXZRomba))
            {
                outputFormat = OutputFormat.Folder;
            }

            // If we have a Disk or Media, change it into a Rom for later use
            if (datItem.ItemType == ItemType.Disk)
            {
                datItem = (datItem as Disk).ConvertToRom();
            }
            else if (datItem.ItemType == ItemType.Media)
            {
                datItem = (datItem as Media).ConvertToRom();
            }

            // Prepopluate a key string
            string crc = (datItem as Rom).CRC ?? string.Empty;

            // Try to get the stream for the file
            if (!GetFileStream(datItem, file, isZip, out Stream fileStream))
            {
                return(false);
            }

            // If either we have duplicates or we're filtering
            if (ShouldRebuild(datFile, datItem, fileStream, inverse, out ConcurrentList <DatItem> dupes))
            {
                // If we have a very specific TGZ->TGZ case, just copy it accordingly
                if (RebuildTorrentGzip(datFile, datItem, file, outDir, outputFormat, isZip))
                {
                    return(true);
                }

                // If we have a very specific TXZ->TXZ case, just copy it accordingly
                if (RebuildTorrentXz(datFile, datItem, file, outDir, outputFormat, isZip))
                {
                    return(true);
                }

                logger.User($"{(inverse ? "No matches" : "Matches")} found for '{Path.GetFileName(datItem.GetName() ?? datItem.ItemType.ToString())}', rebuilding accordingly...");
                rebuilt = true;

                // Special case for partial packing mode
                bool shouldCheck = false;
                if (outputFormat == OutputFormat.Folder && datFile.Header.ForcePacking == PackingFlag.Partial)
                {
                    shouldCheck = true;
                    datFile.Items.BucketBy(ItemKey.Machine, DedupeType.None, lower: false);
                }

                // Now loop through the list and rebuild accordingly
                foreach (DatItem item in dupes)
                {
                    // If we should check for the items in the machine
                    if (shouldCheck && datFile.Items[item.Machine.Name].Count > 1)
                    {
                        outputFormat = OutputFormat.Folder;
                    }
                    else if (shouldCheck && datFile.Items[item.Machine.Name].Count == 1)
                    {
                        outputFormat = OutputFormat.ParentFolder;
                    }

                    // Get the output archive, if possible
                    Folder outputArchive = GetPreconfiguredFolder(datFile, date, outputFormat);

                    // Now rebuild to the output file
                    outputArchive.Write(fileStream, outDir, (item as Rom).ConvertToBaseFile());
                }

                // Close the input stream
                fileStream?.Dispose();
            }

            // Now we want to take care of headers, if applicable
            if (datFile.Header.HeaderSkipper != null)
            {
                // Check to see if we have a matching header first
                SkipperMatch.Init();
                SkipperRule rule = SkipperMatch.GetMatchingRule(fileStream, Path.GetFileNameWithoutExtension(datFile.Header.HeaderSkipper));

                // If there's a match, create the new file to write
                if (rule.Tests != null && rule.Tests.Count != 0)
                {
                    // If the file could be transformed correctly
                    MemoryStream transformStream = new MemoryStream();
                    if (rule.TransformStream(fileStream, transformStream, keepReadOpen: true, keepWriteOpen: true))
                    {
                        // Get the file informations that we will be using
                        Rom headerless = new Rom(BaseFile.GetInfo(transformStream, keepReadOpen: true));

                        // If we have duplicates and we're not filtering
                        if (ShouldRebuild(datFile, headerless, transformStream, false, out dupes))
                        {
                            logger.User($"Headerless matches found for '{Path.GetFileName(datItem.GetName() ?? datItem.ItemType.ToString())}', rebuilding accordingly...");
                            rebuilt = true;

                            // Now loop through the list and rebuild accordingly
                            foreach (DatItem item in dupes)
                            {
                                // Create a headered item to use as well
                                datItem.CopyMachineInformation(item);
                                datItem.SetName($"{datItem.GetName()}_{crc}");

                                // Get the output archive, if possible
                                Folder outputArchive = GetPreconfiguredFolder(datFile, date, outputFormat);

                                // Now rebuild to the output file
                                bool eitherSuccess = false;
                                eitherSuccess |= outputArchive.Write(transformStream, outDir, (item as Rom).ConvertToBaseFile());
                                eitherSuccess |= outputArchive.Write(fileStream, outDir, (datItem as Rom).ConvertToBaseFile());

                                // Now add the success of either rebuild
                                rebuilt &= eitherSuccess;
                            }
                        }
                    }

                    // Dispose of the stream
                    transformStream?.Dispose();
                }

                // Dispose of the stream
                fileStream?.Dispose();
            }

            return(rebuilt);
        }