void CacheDatomaticReleases(Platform platform) { //TODO: customize dialog window to explain what is going on here--i.e., that you have to find a datomatic file // Configure open file dialog box Microsoft.Win32.OpenFileDialog Dialog = new Microsoft.Win32.OpenFileDialog(); Dialog.FileName = "Document"; // Default file name Dialog.DefaultExt = ".dat"; // Default file extension Dialog.Filter = "DAT files (.xml; .txt; .dat)|*.xml;*.txt;*.dat|ZIP files (.zip)|*.zip|All files (*.*)|*.*"; // Filter files by extension // Show open file dialog box bool?result = Dialog.ShowDialog() ?? false; // Process XML file if (result == true && File.Exists(Dialog.FileName)) { Stopwatch Watch1 = Stopwatch.StartNew(); #if DEBUG Stopwatch Watch2 = Stopwatch.StartNew(); #endif XDocument DatomaticFile; // Unpack Datomatic from zip file if it is zipped if (Path.GetExtension(Dialog.FileName) == ".zip") { using (ZipArchive archive = ZipFile.Open(Dialog.FileName, ZipArchiveMode.Read)) { string zipentryname = Path.GetFileNameWithoutExtension(Dialog.FileName) + ".dat"; using (var dattext = archive.GetEntry(zipentryname).Open()) { DatomaticFile = XDocument.Load(dattext); } } } else { DatomaticFile = XDocument.Load(Dialog.FileName); } List <Region> datomaticRegions = R.Data.Regions.Where(x => x.Datomatic != null).ToList(); // Add release where required to make sure xelements have standardized info foreach (XElement gameElement in DatomaticFile.Root.Elements("game")) { if (!gameElement.Descendants("release").Any()) { string elementName = gameElement.SafeGetA(attribute: "name") ?? "Unk"; string regionName = "UNK"; // Get the region using regex from parenthesis foreach (Region region in datomaticRegions) { if (Regex.IsMatch(elementName, @"\([^)]*" + region.Datomatic + @"[^)]*\)")) { regionName = region.Datomatic; break; } } if (regionName == "UNK") { foreach (Region region in datomaticRegions) { if (Regex.IsMatch(elementName, @"\([^)]*" + region.Title + @"[^)]*\)")) { regionName = region.Datomatic; break; } } } XElement ReleaseNode = new XElement("release"); ReleaseNode.Add(new XAttribute("name", elementName)); ReleaseNode.Add(new XAttribute("region", regionName)); gameElement.Add(ReleaseNode); } } try { List <XElement> parentElements = DatomaticFile.Root.Descendants("game").Where(x => x.SafeGetA(attribute: "cloneof") == null).ToList(); List <XElement> childElements = DatomaticFile.Root.Descendants("game").Where(x => x.SafeGetA(attribute: "cloneof") != null).ToList(); #if DEBUG Watch2.Restart(); Debug.WriteLine("00: " + Watch2.ElapsedMilliseconds); Watch2.Restart(); #endif int j = 0; int parentCount = parentElements.Count; int releaseCount = DatomaticFile.Root.Descendants("release").Count(); int romCount = DatomaticFile.Root.Descendants("rom").Count(); Reporter.Report("Found " + parentCount + " games, " + romCount + " ROMs and " + releaseCount + " releases."); //Extract releases from the datomatic file foreach (XElement parentElement in parentElements) { // For reporting only if (j++ % (parentCount / 10) == 0) { Reporter.Report("Getting " + j + @" / " + parentCount + " " + Watch1.Elapsed.ToString(@"m\:ss") + " elapsed."); Watch1.Restart(); } Game game = null; string parentTitle = parentElement.SafeGetA(attribute: "name"); #if DEBUG Watch2.Restart(); #endif // Collect all child roms List <XElement> romElements = childElements.Where(x => x.SafeGetA(attribute: "cloneof") == parentTitle).ToList(); romElements.Insert(0, parentElement); #if DEBUG Debug.WriteLine("A: " + Watch2.ElapsedMilliseconds); Watch2.Restart(); #endif // Check if game exists foreach (XElement romElement in romElements) { string romElementSha1 = romElement.SafeGetA(element1: "rom", attribute: "sha1"); #if DEBUG Watch2.Restart(); #endif Release release = platform.Releases.FirstOrDefault(x => x.Rom.SHA1 == romElementSha1); if (release != null) { game = release.Game; break; // Game exists--no need to keep looking } #if DEBUG Debug.WriteLine("AA: " + Watch2.ElapsedMilliseconds); Watch2.Restart(); #endif } #if DEBUG Debug.WriteLine("B: " + Watch2.ElapsedMilliseconds); Watch2.Restart(); #endif // If the game wasn't found, create a new one and add it if (game == null) { game = new Game(); R.Data.Games.Add(game); } // Check if each rom exists foreach (XElement romElement in romElements) { string romElementSha1 = romElement.SafeGetA(element1: "rom", attribute: "sha1"); if (romElementSha1 == null) { continue; // Malformed element } var rom = R.Data.Roms.FirstOrDefault(x => x.SHA1 == romElementSha1); // Not found, create a new one if (rom == null) { rom = new Rom(); // { Platform_ID = platform.ID }; R.Data.Roms.Add(rom); } #if DEBUG Watch2.Restart(); #endif // Whether existing or new, overwrite properties with new data ParseElementToRom(romElement, rom); #if DEBUG Debug.WriteLine("C: " + Watch2.ElapsedMilliseconds); Watch2.Restart(); #endif // Get the releases from the rom element foreach (XElement releaseElement in romElement.Descendants("release")) { //string releaseTitle = releaseElement.SafeGetA(attribute: "name"); string releaseRegionTitle = releaseElement.SafeGetA(attribute: "region"); if (releaseRegionTitle == null) { Reporter.Report("Skipped release (SHA1: " + romElementSha1 + ") because the datomatic file lists it with no region"); continue; } long?regionID = R.Data.Regions.FirstOrDefault(x => (x.Datomatic == releaseRegionTitle) || (x.Title == releaseRegionTitle)).ID; if (regionID == null) { Reporter.Report("Skipped Datomatic release (SHA1: " + romElementSha1 + ", Region: " + releaseRegionTitle + ") because the region wasn't recognized. Consider adding this region to the database"); continue; } #if DEBUG Watch2.Restart(); #endif Release release = platform.Releases.FirstOrDefault(x => x.Rom_ID == rom.ID && x.Region_ID == regionID); if (release == null) { release = new Release(); release.Game = game; release.Rom = rom; release.Region_ID = (long)regionID; platform.Releases.Add(release); } #if DEBUG Debug.WriteLine("D: " + Watch2.ElapsedMilliseconds); Watch2.Restart(); #endif ParseElementToRelease(releaseElement, release); #if DEBUG Debug.WriteLine("E: " + Watch2.ElapsedMilliseconds); Watch2.Restart(); #endif } } } // Update platform cache date string dateString = DatomaticFile.SafeGetB("header", "date"); DateTime cacheDate; if (dateString != null) { CultureInfo enUS = new CultureInfo("en-US"); if (DateTime.TryParseExact(dateString, "yyyyMMdd-hhmmss", enUS, DateTimeStyles.None, out cacheDate)) { platform.CacheDate = cacheDate; } else { platform.CacheDate = DateTime.Now; } } Reporter.Report("Finished."); } catch (NullReferenceException) { // Ignore } } else { Reporter.Report("File not found."); } }
public Result(Rom rom) { Rom = rom; FilePath = rom.FilePath; }
public static async Task GetAtariGamesAsync() { using (OpenVGDBEntities OVGdata = new OpenVGDBEntities()) { await Task.Run(() => { OVGdata.Configuration.LazyLoadingEnabled = false; OVGdata.VGDBROMS.Load(); OVGdata.VGDBRELEASES.Load(); OVGdata.VGDBRELEASES.Include(XamlGeneratedNamespace => XamlGeneratedNamespace.VGDBROM).Load(); List <VGDBROM> atariVgdbRoms = OVGdata.VGDBROMS.Where(x => x.systemID == 3 && !x.romFileName.Contains(@"(Hack)") && !x.romFileName.Contains(@"(208 in 1)") && !x.romFileName.Contains(@"(CCE)") && !x.romFileName.Contains(@"(2600 Screen Search Console)")).OrderBy(x => x.romFileName).ToList(); List <Release> newAtariReleases = new List <Release>(); List <VGDBROM> finishedVgdbRoms = new List <VGDBROM>(); int z = 0; Platform atariPlatform = R.Data.Platforms.FirstOrDefault(x => x.Title.Contains("2600")); foreach (VGDBROM atariVgdbRom in atariVgdbRoms) { if (!finishedVgdbRoms.Contains(atariVgdbRom)) { Reporter.Report(z++.ToString()); Game game = new Game(); R.Data.Games.Add(game); List <VGDBROM> currentGameVgdbRoms = atariVgdbRoms .Where(x => x.AtariParentTitle == atariVgdbRom.AtariParentTitle || (!string.IsNullOrEmpty(x.AKA) && x.AKA == atariVgdbRom.AtariParentTitle) || (!string.IsNullOrEmpty(atariVgdbRom.AKA) && atariVgdbRom.AKA == x.AtariParentTitle) && !finishedVgdbRoms.Contains(x) ).ToList(); VGDBROM parentRom = currentGameVgdbRoms.FirstOrDefault(x => x.romFileName.Contains(@"~")); if (parentRom != null) { currentGameVgdbRoms.Remove(parentRom); currentGameVgdbRoms.Insert(0, parentRom); } foreach (VGDBROM gameVgdbRom in currentGameVgdbRoms) { Rom rom = gameVgdbRom; if (!atariPlatform.Roms.Any(x => x.SHA1 == rom.SHA1)) { atariPlatform.Roms.Add(rom); foreach (VGDBRELEAS atariVgdbRelease in gameVgdbRom.VGDBRELEASES) { Release release = atariVgdbRelease; release.Rom = rom; release.Game = game; newAtariReleases.Add(release); } } } finishedVgdbRoms.AddRange(currentGameVgdbRoms); } } newAtariReleases = newAtariReleases.OrderBy(x => x.Title).ToList(); atariPlatform.Releases.AddRange(newAtariReleases); R.Data.Save(); //TODO Report total removed }); } }
/// <summary> /// Legacy function to cache releases from direct MAME output. Caches only working releases. To be deprecated. /// </summary> public void CacheReleases() { Stopwatch Watch = Stopwatch.StartNew(); Stopwatch Watch1 = Stopwatch.StartNew(); List <XElement> machineElements = new(); Reporter.Report("Getting xml file from MAME..."); // Scan through xml file from MAME and pick out working games XmlReaderSettings settings = new() { DtdProcessing = DtdProcessing.Parse }; using (Process process = MAMEexe(@"-lx")) using (XmlReader reader = XmlReader.Create(process.StandardOutput, settings)) { int machineCount = 0; while (reader.Read()) { if (reader.Name == "machine") { XElement machineElement = XNode.ReadFrom(reader) as XElement; string emulationStatus = machineElement.SafeGetA(element1: "driver", attribute: "emulation"); string publisher = machineElement.SafeGetA("manufacturer"); if ((emulationStatus == "good") && !Regex.IsMatch(publisher, @"hack|bootleg")) { machineElements.Add(machineElement); if (++machineCount % 100 == 0) { Reporter.Report(machineCount + " machines"); } } } } } List <XElement> parentElements = machineElements.Where(x => x.SafeGetA(attribute: "cloneof") == null).ToList(); List <XElement> childElements = machineElements.Where(x => x.SafeGetA(attribute: "cloneof") != null).ToList(); int parentCount = parentElements.Count; int childCount = childElements.Count; int j = 0; Reporter.Report("Found " + parentCount + " parent machines and " + childCount + " child machines."); foreach (XElement parentElement in parentElements) { if (++j % (parentCount / 10) == 0) { Reporter.Report("Working " + j + " / " + parentCount + " parent machines."); } Game game = null; string parentName = parentElement.SafeGetA(attribute: "name"); List <XElement> romElements = childElements.Where(x => x.SafeGetA(attribute: "cloneof") == parentName).ToList(); romElements.Insert(0, parentElement); // Check if game exists foreach (XElement romElement in romElements) { string romElementName = romElement.SafeGetA(attribute: "name") + ".zip"; Release tRelease = arcadePlatform.Releases.FirstOrDefault(x => x.Rom.FileName == romElementName); if (tRelease != null) { game = tRelease.Game; break; // Game exists--no need to keep looking } } if (game == null) { game = new Game(); R.Data.Games.Add(game); } // Check if each rom exists and each release exists foreach (XElement romElement in romElements) { string romElementName = romElement.SafeGetA(attribute: "name") + ".zip"; var rom = arcadePlatform.Roms.FirstOrDefault(x => x.FileName == romElementName); // Not found, create a new one if (rom == null) { rom = new Robin.Rom(); arcadePlatform.Roms.Add(rom); } rom.Title = romElement.SafeGetA("description"); rom.FileName = romElementName; rom.Source = "MAME"; var release = arcadePlatform.Releases.FirstOrDefault(x => x.Rom.FileName == romElementName); if (release == null) { release = new Release { Rom = rom }; arcadePlatform.Releases.Add(release); } release.Title = rom.Title; release.Game = game; ParseReleaseFromElement(romElement, release); } } List <Release> orphanReleases = arcadePlatform.Releases.Where(x => x.Game == null).ToList(); int orphanCount = orphanReleases.Count; if (orphanCount > 0) { // Get list of clones from MAME to help clean up orphans Reporter.Report("Getting list of clones..."); Watch1.Restart(); List <string[]> cloneList = CloneList(); j = 0; Reporter.ReportInline(Watch1.Elapsed.ToString(@"m\:ss")); Reporter.Report("Cleaning up " + orphanCount + " orphans..."); Watch1.Restart(); foreach (Release orphanRelease in orphanReleases) { if (++j % (parentCount / 10) == 0) { Reporter.Report("Working " + j + " / " + orphanCount + " orphans."); } string[] clonePair = cloneList.FirstOrDefault(x => x[0] + @".zip" == orphanRelease.Rom.FileName); // First look through arcadePlatform to see if the parent is there if (arcadePlatform.Releases.Any(x => x.Rom.FileName == clonePair[1] + @".zip")) { Release parentRelease = arcadePlatform.Releases.FirstOrDefault(x => x.Rom.FileName == clonePair[1] + @".zip"); orphanRelease.Game = parentRelease.Game; } // If the parent is not in arcadePlatform, go back to mame to get the parent else { using Process process1 = MAMEexe(@"-lx " + clonePair[1]); using StreamReader MameOutput = process1.StandardOutput; string text = MameOutput.ReadToEnd(); XElement machineElement = XElement.Parse(text).Element("machine"); Release parentRelease = new(); Game parentGame = new(); ParseReleaseFromElement(machineElement, parentRelease); parentRelease.Game = parentGame; orphanRelease.Game = parentGame; R.Data.Games.Add(parentGame); arcadePlatform.Releases.Add(parentRelease); Debug.WriteLine(machineElement.SafeGetA(element1: "driver", attribute: "status")); } } } else { Reporter.Report("No orphans found."); } Reporter.Report("Finished: " + Watch.Elapsed.ToString(@"m\:ss")); }