diff --git a/CHANGELIST.md b/CHANGELIST.md index f8904cd4..0128839c 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -2,6 +2,7 @@ - Fix Saturn header finding - Add Pocket PC support - Add HD-DVD-Video support +- Convert to using separate Redump library code ### 2.1 (2021-07-22) - Enum, no more diff --git a/MPF.Check/MPF.Check.csproj b/MPF.Check/MPF.Check.csproj index 33dfb2b2..fbd13d96 100644 --- a/MPF.Check/MPF.Check.csproj +++ b/MPF.Check/MPF.Check.csproj @@ -46,6 +46,7 @@ {51ab0928-13f9-44bf-a407-b6957a43a056} MPF.Library + \ No newline at end of file diff --git a/MPF.Check/Program.cs b/MPF.Check/Program.cs index 4559ca49..bc0adb8b 100644 --- a/MPF.Check/Program.cs +++ b/MPF.Check/Program.cs @@ -1,9 +1,10 @@ using System; using System.IO; using BurnOutSharp; +using MPF.Converters; using MPF.Data; -using MPF.Redump; using MPF.Utilities; +using RedumpLib.Web; namespace MPF.Check { @@ -46,7 +47,7 @@ namespace MPF.Check } // Check the MediaType - var mediaType = Converters.ToMediaType(args[0].Trim('"')); + var mediaType = EnumConverter.ToMediaType(args[0].Trim('"')); if (mediaType == MediaType.NONE) { DisplayHelp($"{args[0]} is not a recognized media type"); @@ -54,7 +55,7 @@ namespace MPF.Check } // Check the KnownSystem - var knownSystem = Converters.ToKnownSystem(args[1].Trim('"')); + var knownSystem = EnumConverter.ToKnownSystem(args[1].Trim('"')); if (knownSystem == KnownSystem.NONE) { DisplayHelp($"{args[1]} is not a recognized system"); @@ -163,7 +164,7 @@ namespace MPF.Check // Now populate an environment var options = new Options { - InternalProgram = Converters.ToInternalProgram(internalProgram), + InternalProgram = EnumConverter.ToInternalProgram(internalProgram), ScanForProtection = scan && !string.IsNullOrWhiteSpace(path), PromptForDiscInformation = false, ShowDiscEjectReminder = false, diff --git a/MPF.Library/Aaru/Parameters.cs b/MPF.Library/Aaru/Parameters.cs index 00ba37c7..7133cec2 100644 --- a/MPF.Library/Aaru/Parameters.cs +++ b/MPF.Library/Aaru/Parameters.cs @@ -10,6 +10,7 @@ using System.Xml.Serialization; using MPF.CueSheets; using MPF.Data; using MPF.Utilities; +using RedumpLib.Data; using Schemas; namespace MPF.Aaru @@ -268,7 +269,7 @@ namespace MPF.Aaru break; case KnownSystem.KonamiPython2: - if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out RedumpRegion? pythonTwoRegion, out string pythonTwoDate)) + if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out Region? pythonTwoRegion, out string pythonTwoDate)) { info.CommonDiscInfo.Comments += $"Internal Disc Serial: {pythonTwoSerial}\n"; info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion; @@ -288,7 +289,7 @@ namespace MPF.Aaru info.Extras.SecuritySectorRanges = ss ?? ""; } - if (GetXboxDMIInfo(sidecar, out string serial, out string version, out RedumpRegion? region)) + if (GetXboxDMIInfo(sidecar, out string serial, out string version, out Region? region)) { info.CommonDiscInfo.Serial = serial ?? ""; info.VersionAndEditions.Version = version ?? ""; @@ -307,7 +308,7 @@ namespace MPF.Aaru info.Extras.SecuritySectorRanges = ss360 ?? ""; } - if (GetXbox360DMIInfo(sidecar, out string serial360, out string version360, out RedumpRegion? region360)) + if (GetXbox360DMIInfo(sidecar, out string serial360, out string version360, out Region? region360)) { info.CommonDiscInfo.Serial = serial360 ?? ""; info.VersionAndEditions.Version = version360 ?? ""; @@ -316,7 +317,7 @@ namespace MPF.Aaru break; case KnownSystem.SonyPlayStation: - if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out RedumpRegion? playstationRegion, out string playstationDate)) + if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out Region? playstationRegion, out string playstationDate)) { info.CommonDiscInfo.Comments += $"Internal Disc Serial: {playstationSerial}\n"; info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion; @@ -327,7 +328,7 @@ namespace MPF.Aaru break; case KnownSystem.SonyPlayStation2: - if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out RedumpRegion? playstationTwoRegion, out string playstationTwoDate)) + if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out Region? playstationTwoRegion, out string playstationTwoDate)) { info.CommonDiscInfo.Comments += $"Internal Disc Serial: {playstationTwoSerial}\n"; info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion; @@ -2995,9 +2996,9 @@ namespace MPF.Aaru /// /// CICM Sidecar data generated by Aaru /// True on successful extraction of info, false otherwise - private static bool GetXboxDMIInfo(CICMMetadataType cicmSidecar, out string serial, out string version, out RedumpRegion? region) + private static bool GetXboxDMIInfo(CICMMetadataType cicmSidecar, out string serial, out string version, out Region? region) { - serial = null; version = null; region = RedumpRegion.World; + serial = null; version = null; region = Region.World; // If the object is null, we can't get information from it if (cicmSidecar == null) @@ -3043,9 +3044,9 @@ namespace MPF.Aaru /// /// CICM Sidecar data generated by Aaru /// True on successful extraction of info, false otherwise - private static bool GetXbox360DMIInfo(CICMMetadataType cicmSidecar, out string serial, out string version, out RedumpRegion? region) + private static bool GetXbox360DMIInfo(CICMMetadataType cicmSidecar, out string serial, out string version, out Region? region) { - serial = null; version = null; region = RedumpRegion.World; + serial = null; version = null; region = Region.World; // If the object is null, we can't get information from it if (cicmSidecar == null) diff --git a/MPF.Library/CleanRIp/Parameters.cs b/MPF.Library/CleanRIp/Parameters.cs index 5f93aec4..79768e9a 100644 --- a/MPF.Library/CleanRIp/Parameters.cs +++ b/MPF.Library/CleanRIp/Parameters.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using MPF.Data; +using RedumpLib.Data; namespace MPF.CleanRip { @@ -82,7 +83,7 @@ namespace MPF.CleanRip if (File.Exists(basePath + ".bca")) info.Extras.BCA = GetBCA(basePath + ".bca"); - if (GetGameCubeWiiInformation(basePath + "-dumpinfo.txt", out RedumpRegion? gcRegion, out string gcVersion)) + if (GetGameCubeWiiInformation(basePath + "-dumpinfo.txt", out Region? gcRegion, out string gcVersion)) { info.CommonDiscInfo.Region = gcRegion ?? info.CommonDiscInfo.Region; info.VersionAndEditions.Version = gcVersion ?? info.VersionAndEditions.Version; @@ -203,7 +204,7 @@ namespace MPF.CleanRip /// Output region, if possible /// Output internal version of the game /// - private static bool GetGameCubeWiiInformation(string dumpinfo, out RedumpRegion? region, out string version) + private static bool GetGameCubeWiiInformation(string dumpinfo, out Region? region, out string version) { region = null; version = null; @@ -238,49 +239,49 @@ namespace MPF.CleanRip switch (serial[3]) { case 'A': - region = RedumpRegion.World; + region = Region.World; break; case 'D': - region = RedumpRegion.Germany; + region = Region.Germany; break; case 'E': - region = RedumpRegion.USA; + region = Region.USA; break; case 'F': - region = RedumpRegion.France; + region = Region.France; break; case 'I': - region = RedumpRegion.Italy; + region = Region.Italy; break; case 'J': - region = RedumpRegion.Japan; + region = Region.Japan; break; case 'K': - region = RedumpRegion.Korea; + region = Region.Korea; break; case 'L': - region = RedumpRegion.Europe; // Japanese import to Europe + region = Region.Europe; // Japanese import to Europe break; case 'M': - region = RedumpRegion.Europe; // American import to Europe + region = Region.Europe; // American import to Europe break; case 'N': - region = RedumpRegion.USA; // Japanese import to USA + region = Region.USA; // Japanese import to USA break; case 'P': - region = RedumpRegion.Europe; + region = Region.Europe; break; case 'R': - region = RedumpRegion.Russia; + region = Region.Russia; break; case 'S': - region = RedumpRegion.Spain; + region = Region.Spain; break; case 'Q': - region = RedumpRegion.Korea; // Korea with Japanese language + region = Region.Korea; // Korea with Japanese language break; case 'T': - region = RedumpRegion.Korea; // Korea with English language + region = Region.Korea; // Korea with English language break; case 'X': region = null; // Not a real region code diff --git a/MPF.Library/Utilities/Converters.cs b/MPF.Library/Converters/EnumConverter.cs similarity index 54% rename from MPF.Library/Utilities/Converters.cs rename to MPF.Library/Converters/EnumConverter.cs index 91310725..d8f2fd97 100644 --- a/MPF.Library/Utilities/Converters.cs +++ b/MPF.Library/Converters/EnumConverter.cs @@ -8,10 +8,11 @@ using IMAPI2; #endif using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using RedumpLib.Data; -namespace MPF.Utilities +namespace MPF.Converters { - public static class Converters + public static class EnumConverter { #region Cross-enumeration conversions @@ -119,8 +120,6 @@ namespace MPF.Utilities return KnownSystem.MicrosoftXBOX360; case RedumpSystem.MicrosoftXboxOne: return KnownSystem.MicrosoftXBOXOne; - case RedumpSystem.MicrosoftXboxSeriesXS: - return KnownSystem.MicrosoftXboxSeriesXS; case RedumpSystem.NECPC88series: return KnownSystem.NECPC88; case RedumpSystem.NECPC98series: @@ -169,7 +168,7 @@ namespace MPF.Utilities return KnownSystem.SegaNaomi; case RedumpSystem.SegaNaomi2: return KnownSystem.SegaNaomi2; - case RedumpSystem.SegaPrologue21: + case RedumpSystem.SegaPrologue21MultimediaKaraokeSystem: return KnownSystem.SegaPrologue21; case RedumpSystem.SegaRingEdge: return KnownSystem.SegaRingEdge; @@ -191,8 +190,6 @@ namespace MPF.Utilities return KnownSystem.SonyPlayStation3; case RedumpSystem.SonyPlayStation4: return KnownSystem.SonyPlayStation4; - case RedumpSystem.SonyPlayStation5: - return KnownSystem.SonyPlayStation5; case RedumpSystem.SonyPlayStationPortable: return KnownSystem.SonyPlayStationPortable; case RedumpSystem.TABAustriaQuizard: @@ -370,8 +367,6 @@ namespace MPF.Utilities return RedumpSystem.MicrosoftXbox360; case KnownSystem.MicrosoftXBOXOne: return RedumpSystem.MicrosoftXboxOne; - case KnownSystem.MicrosoftXboxSeriesXS: - return RedumpSystem.MicrosoftXboxSeriesXS; case KnownSystem.NamcoSegaNintendoTriforce: return RedumpSystem.NamcoSegaNintendoTriforce; case KnownSystem.NamcoSystem12: @@ -421,7 +416,7 @@ namespace MPF.Utilities case KnownSystem.SegaNaomi2: return RedumpSystem.SegaNaomi2; case KnownSystem.SegaPrologue21: - return RedumpSystem.SegaPrologue21; + return RedumpSystem.SegaPrologue21MultimediaKaraokeSystem; case KnownSystem.SegaRingEdge: return RedumpSystem.SegaRingEdge; case KnownSystem.SegaRingEdge2: @@ -442,8 +437,6 @@ namespace MPF.Utilities return RedumpSystem.SonyPlayStation3; case KnownSystem.SonyPlayStation4: return RedumpSystem.SonyPlayStation4; - case KnownSystem.SonyPlayStation5: - return RedumpSystem.SonyPlayStation5; case KnownSystem.SonyPlayStationPortable: return RedumpSystem.SonyPlayStationPortable; case KnownSystem.TABAustriaQuizard: @@ -488,7 +481,7 @@ namespace MPF.Utilities if (!LongNameMethods.TryGetValue(sourceType, out MethodInfo method)) { - method = typeof(Converters).GetMethod("LongName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) }); + method = typeof(EnumConverter).GetMethod("LongName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) }); LongNameMethods.TryAdd(sourceType, method); } @@ -932,517 +925,6 @@ namespace MPF.Utilities } } - /// - /// Get the string representation of the DiscCategory enum values - /// - /// DiscCategory value to convert - /// String representing the value, if possible - public static string LongName(this RedumpDiscCategory? category) - { - switch (category) - { - case RedumpDiscCategory.Games: - return "Games"; - case RedumpDiscCategory.Demos: - return "Demos"; - case RedumpDiscCategory.Video: - return "Video"; - case RedumpDiscCategory.Audio: - return "Audio"; - case RedumpDiscCategory.Multimedia: - return "Multimedia"; - case RedumpDiscCategory.Applications: - return "Applications"; - case RedumpDiscCategory.Coverdiscs: - return "Coverdiscs"; - case RedumpDiscCategory.Educational: - return "Educational"; - case RedumpDiscCategory.BonusDiscs: - return "Bonus Discs"; - case RedumpDiscCategory.Preproduction: - return "Preproduction"; - case RedumpDiscCategory.AddOns: - return "Add-Ons"; - default: - return null; - } - } - - /// - /// Get the string representation of the Language enum values - /// - /// Language value to convert - /// String representing the value, if possible - public static string LongName(this RedumpLanguage? language) - { - switch (language) - { - case RedumpLanguage.Afrikaans: - return "Afrikaans"; - case RedumpLanguage.Albanian: - return "Albanian"; - case RedumpLanguage.Arabic: - return "Arabic"; - case RedumpLanguage.Basque: - return "Basque"; - case RedumpLanguage.Bulgarian: - return "Bulgarian"; - case RedumpLanguage.Catalan: - return "Catalan"; - case RedumpLanguage.Chinese: - return "Chinese"; - case RedumpLanguage.Croatian: - return "Croatian"; - case RedumpLanguage.Czech: - return "Czech"; - case RedumpLanguage.Danish: - return "Danish"; - case RedumpLanguage.Dutch: - return "Dutch"; - case RedumpLanguage.English: - return "English"; - case RedumpLanguage.Estonian: - return "Estonian"; - case RedumpLanguage.Finnish: - return "Finnish"; - case RedumpLanguage.French: - return "French"; - case RedumpLanguage.Gaelic: - return "Gaelic"; - case RedumpLanguage.German: - return "German"; - case RedumpLanguage.Greek: - return "Greek"; - case RedumpLanguage.Hebrew: - return "Hebrew"; - case RedumpLanguage.Hindi: - return "Hindi"; - case RedumpLanguage.Hungarian: - return "Hungarian"; - case RedumpLanguage.Indonesian: - return "Indonesian"; - case RedumpLanguage.Icelandic: - return "Icelandic"; - case RedumpLanguage.Italian: - return "Italian"; - case RedumpLanguage.Japanese: - return "Japanese"; - case RedumpLanguage.Korean: - return "Korean"; - case RedumpLanguage.Latin: - return "Latin"; - case RedumpLanguage.Latvian: - return "Latvian"; - case RedumpLanguage.Lithuanian: - return "Lithuanian"; - case RedumpLanguage.Macedonian: - return "Macedonian"; - case RedumpLanguage.Norwegian: - return "Norwegian"; - case RedumpLanguage.Polish: - return "Polish"; - case RedumpLanguage.Portuguese: - return "Portuguese"; - case RedumpLanguage.Punjabi: - return "Punjabi"; - case RedumpLanguage.Romanian: - return "Romanian"; - case RedumpLanguage.Russian: - return "Russian"; - case RedumpLanguage.Serbian: - return "Serbian"; - case RedumpLanguage.Slovak: - return "Slovak"; - case RedumpLanguage.Slovenian: - return "Slovenian"; - case RedumpLanguage.Spanish: - return "Spanish"; - case RedumpLanguage.Swedish: - return "Swedish"; - case RedumpLanguage.Tamil: - return "Tamil"; - case RedumpLanguage.Thai: - return "Thai"; - case RedumpLanguage.Turkish: - return "Turkish"; - case RedumpLanguage.Ukrainian: - return "Ukrainian"; - default: - return "Klingon (CHANGE THIS)"; - } - } - - /// - /// Get the string representation of the LanguageSelection enum values - /// - /// LanguageSelection value to convert - /// String representing the value, if possible - public static string LongName(this RedumpLanguageSelection? langSelect) - { - switch (langSelect) - { - case RedumpLanguageSelection.BiosSettings: - return "Bios settings"; - case RedumpLanguageSelection.LanguageSelector: - return "Language selector"; - case RedumpLanguageSelection.OptionsMenu: - return "Options menu"; - default: - return string.Empty; - } - } - - /// - /// Get the string representation of the Region enum values - /// - /// Region value to convert - /// String representing the value, if possible - public static string LongName(this RedumpRegion? region) - { - switch (region) - { - case RedumpRegion.Argentina: - return "Argentina"; - case RedumpRegion.Asia: - return "Asia"; - case RedumpRegion.AsiaEurope: - return "Asia, Europe"; - case RedumpRegion.AsiaUSA: - return "Asia, USA"; - case RedumpRegion.Australia: - return "Australia"; - case RedumpRegion.AustraliaGermany: - return "Australia, Germany"; - case RedumpRegion.AustraliaNewZealand: - return "Australia, New Zealand"; - case RedumpRegion.Austria: - return "Austria"; - case RedumpRegion.AustriaSwitzerland: - return "Austria, Switzerland"; - case RedumpRegion.Belgium: - return "Belgium"; - case RedumpRegion.BelgiumNetherlands: - return "Belgium, Netherlands"; - case RedumpRegion.Brazil: - return "Brazil"; - case RedumpRegion.Bulgaria: - return "Bulgaria"; - case RedumpRegion.Canada: - return "Canada"; - case RedumpRegion.China: - return "China"; - case RedumpRegion.Croatia: - return "Croatia"; - case RedumpRegion.Czech: - return "Czech"; - case RedumpRegion.Denmark: - return "Denmark"; - case RedumpRegion.Estonia: - return "Estonia"; - case RedumpRegion.Europe: - return "Europe"; - case RedumpRegion.EuropeAsia: - return "Europe, Asia"; - case RedumpRegion.EuropeAustralia: - return "Europe, Australia"; - case RedumpRegion.EuropeCanada: - return "Europe, Canada"; - case RedumpRegion.EuropeGermany: - return "Europe, Germany"; - case RedumpRegion.Export: - return "Export"; - case RedumpRegion.Finland: - return "Finland"; - case RedumpRegion.France: - return "France"; - case RedumpRegion.FranceSpain: - return "France, Spain"; - case RedumpRegion.Germany: - return "Germany"; - case RedumpRegion.GreaterChina: - return "Greater China"; - case RedumpRegion.Greece: - return "Greece"; - case RedumpRegion.Hungary: - return "Hungary"; - case RedumpRegion.Iceland: - return "Iceland"; - case RedumpRegion.India: - return "India"; - case RedumpRegion.Ireland: - return "Ireland"; - case RedumpRegion.Israel: - return "Israel"; - case RedumpRegion.Italy: - return "Italy"; - case RedumpRegion.Japan: - return "Japan"; - case RedumpRegion.JapanAsia: - return "Japan, Asia"; - case RedumpRegion.JapanEurope: - return "Japan, Europe"; - case RedumpRegion.JapanKorea: - return "Japan, Korea"; - case RedumpRegion.JapanUSA: - return "Japan, USA"; - case RedumpRegion.Korea: - return "Korea"; - case RedumpRegion.LatinAmerica: - return "Latin America"; - case RedumpRegion.Lithuania: - return "Lithuania"; - case RedumpRegion.Netherlands: - return "Netherlands"; - case RedumpRegion.NewZealand: - return "New Zealand"; - case RedumpRegion.Norway: - return "Norway"; - case RedumpRegion.Poland: - return "Poland"; - case RedumpRegion.Portugal: - return "Portugal"; - case RedumpRegion.Romania: - return "Romania"; - case RedumpRegion.Russia: - return "Russia"; - case RedumpRegion.Scandinavia: - return "Scandinavia"; - case RedumpRegion.Serbia: - return "Serbia"; - case RedumpRegion.Singapore: - return "Singapore"; - case RedumpRegion.Slovakia: - return "Slovakia"; - case RedumpRegion.SouthAfrica: - return "South Africa"; - case RedumpRegion.Spain: - return "Spain"; - case RedumpRegion.SpainPortugal: - return "Spain, Portugal"; - case RedumpRegion.Sweden: - return "Sweden"; - case RedumpRegion.Switzerland: - return "Switzerland"; - case RedumpRegion.Taiwan: - return "Taiwan"; - case RedumpRegion.Thailand: - return "Thailand"; - case RedumpRegion.Turkey: - return "Turkey"; - case RedumpRegion.UnitedArabEmirates: - return "United Arab Emirates"; - case RedumpRegion.UK: - return "UK"; - case RedumpRegion.UKAustralia: - return "UK, Australia"; - case RedumpRegion.Ukraine: - return "Ukraine"; - case RedumpRegion.USA: - return "USA"; - case RedumpRegion.USAAsia: - return "USA, Asia"; - case RedumpRegion.USAAustralia: - return "USA, Australia"; - case RedumpRegion.USABrazil: - return "USA, Brazil"; - case RedumpRegion.USACanada: - return "USA, Canada"; - case RedumpRegion.USAEurope: - return "USA, Europe"; - case RedumpRegion.USAGermany: - return "USA, Germany"; - case RedumpRegion.USAJapan: - return "USA, Japan"; - case RedumpRegion.USAKorea: - return "USA, Korea"; - case RedumpRegion.World: - return "World"; - default: - return "SPACE! (CHANGE THIS)"; - } - } - - /// - /// Get the string representation of the MediaType enum values - /// - /// RedumpSystem value to convert - /// String representing the value, if possible - public static string LongName(this RedumpSystem? system) - { - switch (system) - { - // Special BIOS sets - case RedumpSystem.MicrosoftXboxBIOS: - return "Microsoft Xbox (BIOS)"; - case RedumpSystem.NintendoGameCubeBIOS: - return "Nintendo GameCube (BIOS)"; - case RedumpSystem.SonyPlayStationBIOS: - return "Sony PlayStation (BIOS)"; - case RedumpSystem.SonyPlayStation2BIOS: - return "Sony PlayStation 2 (BIOS)"; - - // Regular systems - case RedumpSystem.AcornArchimedes: - return "Acorn Archimedes"; - case RedumpSystem.AppleMacintosh: - return "Apple Macintosh"; - case RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem: - return "Atari Jaguar CD Interactive Multimedia System"; - case RedumpSystem.AudioCD: - return "Audio CD"; - case RedumpSystem.BandaiPippin: - return "Bandai Pippin"; - case RedumpSystem.BandaiPlaydiaQuickInteractiveSystem: - return "Bandai Playdia Quick Interactive System"; - case RedumpSystem.BDVideo: - return "BD-Video"; - case RedumpSystem.CommodoreAmigaCD: - return "Commodore Amiga CD"; - case RedumpSystem.CommodoreAmigaCD32: - return "Commodore Amiga CD32"; - case RedumpSystem.CommodoreAmigaCDTV: - return "Commodore Amiga CDTV"; - case RedumpSystem.DVDVideo: - return "DVD-Video"; - case RedumpSystem.EnhancedCD: - return "Enhanced CD"; - case RedumpSystem.FujitsuFMTownsseries: - return "Fujitsu FM Towns series"; - case RedumpSystem.funworldPhotoPlay: - return "funworld Photo Play"; - case RedumpSystem.HasbroVideoNow: - return "Hasbro VideoNow"; - case RedumpSystem.HasbroVideoNowColor: - return "Hasbro VideoNow Color"; - case RedumpSystem.HasbroVideoNowJr: - return "Hasbro VideoNow Jr."; - case RedumpSystem.HasbroVideoNowXP: - return "Hasbro VideoNow XP"; - case RedumpSystem.HDDVDVideo: - return "HD DVD-Video"; - case RedumpSystem.IBMPCcompatible: - return "IBM PC compatible"; - case RedumpSystem.IncredibleTechnologiesEagle: - return "Incredible Technologies Eagle"; - case RedumpSystem.KonamieAmusement: - return "Konami e-Amusement"; - case RedumpSystem.KonamiFireBeat: - return "Konami FireBeat"; - case RedumpSystem.KonamiM2: - return "Konami M2"; - case RedumpSystem.KonamiSystem573: - return "Konami System 573"; - case RedumpSystem.KonamiSystemGV: - return "Konami System GV"; - case RedumpSystem.KonamiTwinkle: - return "Konami Twinkle"; - case RedumpSystem.MattelFisherPriceiXL: - return "Mattel Fisher-Price iXL"; - case RedumpSystem.MattelHyperScan: - return "Mattel HyperScan"; - case RedumpSystem.MemorexVisualInformationSystem: - return "Memorex Visual Information System"; - case RedumpSystem.MicrosoftXbox: - return "Microsoft Xbox"; - case RedumpSystem.MicrosoftXbox360: - return "Microsoft Xbox 360"; - case RedumpSystem.MicrosoftXboxOne: - return "Microsoft Xbox One"; - case RedumpSystem.MicrosoftXboxSeriesXS: - return "Microsoft Xbox Series X and S"; - case RedumpSystem.NamcoSegaNintendoTriforce: - return "Namco · Sega · Nintendo Triforce"; - case RedumpSystem.NamcoSystem12: - return "Namco System 12"; - case RedumpSystem.NamcoSystem246: - return "Namco System 246"; - case RedumpSystem.NavisoftNaviken21: - return "Navisoft Naviken 2.1"; - case RedumpSystem.NECPCEngineCDTurboGrafxCD: - return "NEC PC Engine CD & TurboGrafx CD"; - case RedumpSystem.NECPC88series: - return "NEC PC-88 series"; - case RedumpSystem.NECPC98series: - return "NEC PC-98 series"; - case RedumpSystem.NECPCFXPCFXGA: - return "NEC PC-FX & PC-FXGA"; - case RedumpSystem.NintendoGameCube: - return "Nintendo GameCube"; - case RedumpSystem.NintendoWii: - return "Nintendo Wii"; - case RedumpSystem.NintendoWiiU: - return "Nintendo Wii U"; - case RedumpSystem.PalmOS: - return "Palm OS"; - case RedumpSystem.Panasonic3DOInteractiveMultiplayer: - return "Panasonic 3DO Interactive Multiplayer"; - case RedumpSystem.PanasonicM2: - return "Panasonic M2"; - case RedumpSystem.PhilipsCDi: - return "Philips CD-i"; - case RedumpSystem.PhotoCD: - return "Photo CD"; - case RedumpSystem.PlayStationGameSharkUpdates: - return "PlayStation GameShark Updates"; - case RedumpSystem.PocketPC: - return "Pocket PC"; - case RedumpSystem.SegaChihiro: - return "Sega Chihiro"; - case RedumpSystem.SegaDreamcast: - return "Sega Dreamcast"; - case RedumpSystem.SegaLindbergh: - return "Sega Lindbergh"; - case RedumpSystem.SegaMegaCDSegaCD: - return "Sega Mega CD & Sega CD"; - case RedumpSystem.SegaNaomi: - return "Sega Naomi"; - case RedumpSystem.SegaNaomi2: - return "Sega Naomi 2"; - case RedumpSystem.SegaPrologue21: - return "Prologue 21"; - case RedumpSystem.SegaRingEdge: - return "Sega RingEdge"; - case RedumpSystem.SegaRingEdge2: - return "Sega RingEdge 2"; - case RedumpSystem.SegaSaturn: - return "Sega Saturn"; - case RedumpSystem.SegaTitanVideo: - return "Sega Titan Video"; - case RedumpSystem.SharpX68000: - return "Sharp X68000"; - case RedumpSystem.SNKNeoGeoCD: - return "Neo Geo CD"; - case RedumpSystem.SonyPlayStation: - return "Sony PlayStation"; - case RedumpSystem.SonyPlayStation2: - return "Sony PlayStation 2"; - case RedumpSystem.SonyPlayStation3: - return "Sony PlayStation 3"; - case RedumpSystem.SonyPlayStation4: - return "Sony PlayStation 4"; - case RedumpSystem.SonyPlayStation5: - return "Sony PlayStation 5"; - case RedumpSystem.SonyPlayStationPortable: - return "Sony PlayStation Portable"; - case RedumpSystem.TABAustriaQuizard: - return "TAB-Austria Quizard"; - case RedumpSystem.TaoiKTV: - return "Tao iKTV"; - case RedumpSystem.TomyKissSite: - return "Tomy Kiss-Site"; - case RedumpSystem.VideoCD: - return "Video CD"; - case RedumpSystem.VMLabsNUON: - return "VM Labs NUON"; - case RedumpSystem.VTechVFlashVSmilePro: - return "VTech V.Flash & V.Smile Pro"; - case RedumpSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem: - return "ZAPiT Games Game Wave Family Entertainment System"; - default: - return null; - } - } - /// /// Get the string representation of the YesNo enum values /// @@ -1485,7 +967,7 @@ namespace MPF.Utilities if (!ShortNameMethods.TryGetValue(sourceType, out MethodInfo method)) { - method = typeof(Converters).GetMethod("ShortName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) }); + method = typeof(EnumConverter).GetMethod("ShortName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) }); ShortNameMethods.TryAdd(sourceType, method); } @@ -1864,503 +1346,10 @@ namespace MPF.Utilities } } - /// - /// Get the short string representation of the Language enum values - /// - /// Language value to convert - /// Short string representing the value, if possible - public static string ShortName(this RedumpLanguage? language) - { - switch (language) - { - case RedumpLanguage.Afrikaans: - return "afr"; - case RedumpLanguage.Albanian: - return "sqi"; - case RedumpLanguage.Arabic: - return "ara"; - case RedumpLanguage.Basque: - return "baq"; - case RedumpLanguage.Bulgarian: - return "bul"; - case RedumpLanguage.Catalan: - return "cat"; - case RedumpLanguage.Chinese: - return "chi"; - case RedumpLanguage.Croatian: - return "hrv"; - case RedumpLanguage.Czech: - return "cze"; - case RedumpLanguage.Danish: - return "dan"; - case RedumpLanguage.Dutch: - return "dut"; - case RedumpLanguage.English: - return "eng"; - case RedumpLanguage.Estonian: - return "est"; - case RedumpLanguage.Finnish: - return "fin"; - case RedumpLanguage.French: - return "fre"; - case RedumpLanguage.Gaelic: - return "gla"; - case RedumpLanguage.German: - return "ger"; - case RedumpLanguage.Greek: - return "gre"; - case RedumpLanguage.Hebrew: - return "heb"; - case RedumpLanguage.Hindi: - return "hin"; - case RedumpLanguage.Hungarian: - return "hun"; - case RedumpLanguage.Indonesian: - return "ind"; - case RedumpLanguage.Icelandic: - return "isl"; - case RedumpLanguage.Italian: - return "ita"; - case RedumpLanguage.Japanese: - return "jap"; - case RedumpLanguage.Korean: - return "kor"; - case RedumpLanguage.Latin: - return "lat"; - case RedumpLanguage.Latvian: - return "lav"; - case RedumpLanguage.Lithuanian: - return "lit"; - case RedumpLanguage.Macedonian: - return "mkd"; - case RedumpLanguage.Norwegian: - return "nor"; - case RedumpLanguage.Polish: - return "pol"; - case RedumpLanguage.Portuguese: - return "por"; - case RedumpLanguage.Punjabi: - return "pan"; - case RedumpLanguage.Romanian: - return "ron"; - case RedumpLanguage.Russian: - return "rus"; - case RedumpLanguage.Serbian: - return "srp"; - case RedumpLanguage.Slovak: - return "slk"; - case RedumpLanguage.Slovenian: - return "slv"; - case RedumpLanguage.Spanish: - return "spa"; - case RedumpLanguage.Swedish: - return "swe"; - case RedumpLanguage.Tamil: - return "tam"; - case RedumpLanguage.Thai: - return "tha"; - case RedumpLanguage.Turkish: - return "tur"; - case RedumpLanguage.Ukrainian: - return "ukr"; - default: - return null; - } - } - - /// - /// Get the short string representation of the Region enum values - /// - /// Region value to convert - /// Short string representing the value, if possible - public static string ShortName(this RedumpRegion? region) - { - switch (region) - { - case RedumpRegion.Argentina: - return "Ar"; - case RedumpRegion.Asia: - return "A"; - case RedumpRegion.AsiaEurope: - return "A,E"; - case RedumpRegion.AsiaUSA: - return "A,U"; - case RedumpRegion.Australia: - return "Au"; - case RedumpRegion.AustraliaGermany: - return "Au,G"; - case RedumpRegion.AustraliaNewZealand: - return "Au,Nz"; - case RedumpRegion.Austria: - return "At"; - case RedumpRegion.AustriaSwitzerland: - return "At,Ch"; - case RedumpRegion.Belgium: - return "Be"; - case RedumpRegion.BelgiumNetherlands: - return "Be,N"; - case RedumpRegion.Brazil: - return "B"; - case RedumpRegion.Bulgaria: - return "Bg"; - case RedumpRegion.Canada: - return "Ca"; - case RedumpRegion.China: - return "C"; - case RedumpRegion.Croatia: - return "Hr"; - case RedumpRegion.Czech: - return "Cz"; - case RedumpRegion.Denmark: - return "Dk"; - case RedumpRegion.Estonia: - return "Ee"; - case RedumpRegion.Europe: - return "E"; - case RedumpRegion.EuropeAsia: - return "E,A"; - case RedumpRegion.EuropeAustralia: - return "E,Au"; - case RedumpRegion.EuropeCanada: - return "E,Ca"; - case RedumpRegion.EuropeGermany: - return "E,G"; - case RedumpRegion.Export: - return "Ex"; - case RedumpRegion.Finland: - return "Fi"; - case RedumpRegion.France: - return "F"; - case RedumpRegion.FranceSpain: - return "F,S"; - case RedumpRegion.Germany: - return "G"; - case RedumpRegion.GreaterChina: - return "GC"; - case RedumpRegion.Greece: - return "Gr"; - case RedumpRegion.Hungary: - return "H"; - case RedumpRegion.Iceland: - return "Is"; - case RedumpRegion.India: - return "In"; - case RedumpRegion.Ireland: - return "Ie"; - case RedumpRegion.Israel: - return "Il"; - case RedumpRegion.Italy: - return "I"; - case RedumpRegion.Japan: - return "J"; - case RedumpRegion.JapanAsia: - return "J,A"; - case RedumpRegion.JapanEurope: - return "J,E"; - case RedumpRegion.JapanKorea: - return "J,K"; - case RedumpRegion.JapanUSA: - return "J,U"; - case RedumpRegion.Korea: - return "K"; - case RedumpRegion.LatinAmerica: - return "LAm"; - case RedumpRegion.Lithuania: - return "Lt"; - case RedumpRegion.Netherlands: - return "N"; - case RedumpRegion.NewZealand: - return "Nz"; - case RedumpRegion.Norway: - return "No"; - case RedumpRegion.Poland: - return "P"; - case RedumpRegion.Portugal: - return "Pt"; - case RedumpRegion.Romania: - return "Ro"; - case RedumpRegion.Russia: - return "R"; - case RedumpRegion.Scandinavia: - return "Sca"; - case RedumpRegion.Serbia: - return "Rs"; - case RedumpRegion.Singapore: - return "Sg"; - case RedumpRegion.Slovakia: - return "Sk"; - case RedumpRegion.SouthAfrica: - return "Za"; - case RedumpRegion.Spain: - return "S"; - case RedumpRegion.SpainPortugal: - return "S,Pt"; - case RedumpRegion.Sweden: - return "Sw"; - case RedumpRegion.Switzerland: - return "Ch"; - case RedumpRegion.Taiwan: - return "Tw"; - case RedumpRegion.Thailand: - return "Th"; - case RedumpRegion.Turkey: - return "Tr"; - case RedumpRegion.UnitedArabEmirates: - return "Ae"; - case RedumpRegion.UK: - return "Uk"; - case RedumpRegion.UKAustralia: - return "Uk,Au"; - case RedumpRegion.Ukraine: - return "Ua"; - case RedumpRegion.USA: - return "U"; - case RedumpRegion.USAAsia: - return "U,A"; - case RedumpRegion.USAAustralia: - return "U,Au"; - case RedumpRegion.USABrazil: - return "U,B"; - case RedumpRegion.USACanada: - return "U,Ca"; - case RedumpRegion.USAEurope: - return "U,E"; - case RedumpRegion.USAGermany: - return "U,G"; - case RedumpRegion.USAJapan: - return "U,J"; - case RedumpRegion.USAKorea: - return "U,K"; - case RedumpRegion.World: - return "W"; - default: - return null; - } - } - - /// - /// Get the short string representation of the RedumpSystem enum values - /// - /// RedumpSystem value to convert - /// Short string representing the value, if possible - public static string ShortName(this RedumpSystem? system) - { - switch (system) - { - // Special BIOS sets - case RedumpSystem.MicrosoftXboxBIOS: - return "xbox-bios"; - case RedumpSystem.NintendoGameCubeBIOS: - return "gc-bios"; - case RedumpSystem.SonyPlayStationBIOS: - return "psx-bios"; - case RedumpSystem.SonyPlayStation2BIOS: - return "ps2-bios"; - - // Regular systems - case RedumpSystem.AcornArchimedes: - return "archcd"; - case RedumpSystem.AppleMacintosh: - return "mac"; - case RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem: - return "ajcd"; - case RedumpSystem.AudioCD: - return "audio-cd"; - case RedumpSystem.BandaiPippin: - return "pippin"; - case RedumpSystem.BandaiPlaydiaQuickInteractiveSystem: - return "qis"; - case RedumpSystem.BDVideo: - return "bd-video"; - case RedumpSystem.CommodoreAmigaCD: - return "acd"; - case RedumpSystem.CommodoreAmigaCD32: - return "cd32"; - case RedumpSystem.CommodoreAmigaCDTV: - return "cdtv"; - case RedumpSystem.DVDVideo: - return "dvd-video"; - case RedumpSystem.EnhancedCD: - return "enhanced-cd"; - case RedumpSystem.FujitsuFMTownsseries: - return "fmt"; - case RedumpSystem.funworldPhotoPlay: - return "fpp"; - case RedumpSystem.HasbroVideoNow: - return "hvn"; - case RedumpSystem.HasbroVideoNowColor: - return "hvnc"; - case RedumpSystem.HasbroVideoNowJr: - return "hvnjr"; - case RedumpSystem.HasbroVideoNowXP: - return "hvnxp"; - case RedumpSystem.HDDVDVideo: - return "hddvd-video"; - case RedumpSystem.IBMPCcompatible: - return "pc"; - case RedumpSystem.IncredibleTechnologiesEagle: - return "ite"; - case RedumpSystem.KonamieAmusement: - return "kea"; - case RedumpSystem.KonamiFireBeat: - return "kfb"; - case RedumpSystem.KonamiM2: - return "km2"; - case RedumpSystem.KonamiSystem573: - return "ks573"; - case RedumpSystem.KonamiSystemGV: - return "ksgv"; - case RedumpSystem.KonamiTwinkle: - return "kt"; - case RedumpSystem.MattelFisherPriceiXL: - return "ixl"; - case RedumpSystem.MattelHyperScan: - return "hs"; - case RedumpSystem.MemorexVisualInformationSystem: - return "vis"; - case RedumpSystem.MicrosoftXbox: - return "xbox"; - case RedumpSystem.MicrosoftXbox360: - return "xbox360"; - case RedumpSystem.MicrosoftXboxOne: - return "xboxone"; - case RedumpSystem.MicrosoftXboxSeriesXS: - return "xboxseries"; - case RedumpSystem.NamcoSegaNintendoTriforce: - return "triforce"; - case RedumpSystem.NamcoSystem12: - return "ns12"; - case RedumpSystem.NamcoSystem246: - return "ns246"; - case RedumpSystem.NavisoftNaviken21: - return "navi21"; - case RedumpSystem.NECPCEngineCDTurboGrafxCD: - return "pce"; - case RedumpSystem.NECPC88series: - return "pc-88"; - case RedumpSystem.NECPC98series: - return "pc-98"; - case RedumpSystem.NECPCFXPCFXGA: - return "pc-fx"; - case RedumpSystem.NintendoGameCube: - return "gc"; - case RedumpSystem.NintendoWii: - return "wii"; - case RedumpSystem.NintendoWiiU: - return "wiiu"; - case RedumpSystem.PalmOS: - return "palm"; - case RedumpSystem.Panasonic3DOInteractiveMultiplayer: - return "3do"; - case RedumpSystem.PanasonicM2: - return "m2"; - case RedumpSystem.PhilipsCDi: - return "cdi"; - case RedumpSystem.PhotoCD: - return "photo-cd"; - case RedumpSystem.PlayStationGameSharkUpdates: - return "psxgs"; - case RedumpSystem.PocketPC: - return "ppc"; - case RedumpSystem.SegaChihiro: - return "chihiro"; - case RedumpSystem.SegaDreamcast: - return "dc"; - case RedumpSystem.SegaLindbergh: - return "lindbergh"; - case RedumpSystem.SegaMegaCDSegaCD: - return "mcd"; - case RedumpSystem.SegaNaomi: - return "naomi"; - case RedumpSystem.SegaNaomi2: - return "naomi2"; - case RedumpSystem.SegaPrologue21: - return "pl21"; - case RedumpSystem.SegaRingEdge: - return "sre"; - case RedumpSystem.SegaRingEdge2: - return "sre2"; - case RedumpSystem.SegaSaturn: - return "ss"; - case RedumpSystem.SegaTitanVideo: - return "stv"; - case RedumpSystem.SharpX68000: - return "x86kcd"; - case RedumpSystem.SNKNeoGeoCD: - return "ngcd"; - case RedumpSystem.SonyPlayStation: - return "psx"; - case RedumpSystem.SonyPlayStation2: - return "ps2"; - case RedumpSystem.SonyPlayStation3: - return "ps3"; - case RedumpSystem.SonyPlayStation4: - return "ps4"; - case RedumpSystem.SonyPlayStation5: - return "ps5"; - case RedumpSystem.SonyPlayStationPortable: - return "psp"; - case RedumpSystem.TABAustriaQuizard: - return "quizard"; - case RedumpSystem.TaoiKTV: - return "iktv"; - case RedumpSystem.TomyKissSite: - return "ksite"; - case RedumpSystem.VideoCD: - return "vcd"; - case RedumpSystem.VMLabsNUON: - return "nuon"; - case RedumpSystem.VTechVFlashVSmilePro: - return "vflash"; - case RedumpSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem: - return "gamewave"; - default: - return null; - } - } - #endregion #region Convert From String - /// - /// Get the DiscCategory enum value for a given string - /// - /// String value to convert - /// DiscCategory represented by the string, if possible - public static RedumpDiscCategory? ToDiscCategory(string category) - { - switch (category.ToLowerInvariant()) - { - case "games": - return RedumpDiscCategory.Games; - case "demos": - return RedumpDiscCategory.Demos; - case "video": - return RedumpDiscCategory.Video; - case "audio": - return RedumpDiscCategory.Audio; - case "multimedia": - return RedumpDiscCategory.Multimedia; - case "applications": - return RedumpDiscCategory.Applications; - case "coverdiscs": - return RedumpDiscCategory.Coverdiscs; - case "educational": - return RedumpDiscCategory.Educational; - case "bonusdiscs": - case "bonus discs": - return RedumpDiscCategory.BonusDiscs; - case "preproduction": - return RedumpDiscCategory.Preproduction; - case "addons": - case "add-ons": - return RedumpDiscCategory.AddOns; - default: - return RedumpDiscCategory.Games; - } - } - /// /// Get the InternalProgram enum value for a given string /// @@ -3345,946 +2334,6 @@ namespace MPF.Utilities } } - /// - /// Get the Language enum value for a given string - /// - /// String value to convert - /// Language represented by the string, if possible - public static RedumpLanguage? ToRedumpLanguage(string lang) - { - switch (lang) - { - case "afr": - return RedumpLanguage.Afrikaans; - case "sqi": - return RedumpLanguage.Albanian; - case "ara": - return RedumpLanguage.Arabic; - case "baq": - return RedumpLanguage.Basque; - case "bul": - return RedumpLanguage.Bulgarian; - case "cat": - return RedumpLanguage.Catalan; - case "chi": - return RedumpLanguage.Chinese; - case "hrv": - return RedumpLanguage.Croatian; - case "cze": - return RedumpLanguage.Czech; - case "dan": - return RedumpLanguage.Danish; - case "dut": - return RedumpLanguage.Dutch; - case "eng": - return RedumpLanguage.English; - case "est": - return RedumpLanguage.Estonian; - case "fin": - return RedumpLanguage.Finnish; - case "fre": - return RedumpLanguage.French; - case "gla": - return RedumpLanguage.Gaelic; - case "ger": - return RedumpLanguage.German; - case "gre": - return RedumpLanguage.Greek; - case "heb": - return RedumpLanguage.Hebrew; - case "hin": - return RedumpLanguage.Hindi; - case "hun": - return RedumpLanguage.Hungarian; - case "ind": - return RedumpLanguage.Indonesian; - case "isl": - return RedumpLanguage.Icelandic; - case "ita": - return RedumpLanguage.Italian; - case "jap": - return RedumpLanguage.Japanese; - case "kor": - return RedumpLanguage.Korean; - case "lat": - return RedumpLanguage.Latin; - case "lav": - return RedumpLanguage.Latvian; - case "lit": - return RedumpLanguage.Lithuanian; - case "mkd": - return RedumpLanguage.Macedonian; - case "nor": - return RedumpLanguage.Norwegian; - case "pol": - return RedumpLanguage.Polish; - case "por": - return RedumpLanguage.Portuguese; - case "pan": - return RedumpLanguage.Punjabi; - case "ron": - return RedumpLanguage.Romanian; - case "rus": - return RedumpLanguage.Russian; - case "srp": - return RedumpLanguage.Serbian; - case "slk": - return RedumpLanguage.Slovak; - case "slv": - return RedumpLanguage.Slovenian; - case "spa": - return RedumpLanguage.Spanish; - case "swe": - return RedumpLanguage.Swedish; - case "tam": - return RedumpLanguage.Tamil; - case "tha": - return RedumpLanguage.Thai; - case "tur": - return RedumpLanguage.Turkish; - case "ukr": - return RedumpLanguage.Ukrainian; - default: - return null; - } - } - - /// - /// Get the Region enum value for a given string - /// - /// String value to convert - /// Region represented by the string, if possible - public static RedumpRegion? ToRedumpRegion(string region) - { - switch (region) - { - case "Ar": - return RedumpRegion.Argentina; - case "A": - return RedumpRegion.Asia; - case "A,E": - return RedumpRegion.AsiaEurope; - case "A,U": - return RedumpRegion.AsiaUSA; - case "Au": - return RedumpRegion.Australia; - case "Au,G": - return RedumpRegion.AustraliaGermany; - case "Au,Nz": - return RedumpRegion.AustraliaNewZealand; - case "At": - return RedumpRegion.Austria; - case "At,Ch": - return RedumpRegion.AustriaSwitzerland; - case "Be": - return RedumpRegion.Belgium; - case "Be,N": - return RedumpRegion.BelgiumNetherlands; - case "B": - return RedumpRegion.Brazil; - case "Bg": - return RedumpRegion.Bulgaria; - case "Ca": - return RedumpRegion.Canada; - case "C": - return RedumpRegion.China; - case "Hr": - return RedumpRegion.Croatia; - case "Cz": - return RedumpRegion.Czech; - case "Dk": - return RedumpRegion.Denmark; - case "Ee": - return RedumpRegion.Estonia; - case "E": - return RedumpRegion.Europe; - case "E,A": - return RedumpRegion.EuropeAsia; - case "E,Au": - return RedumpRegion.EuropeAustralia; - case "E,Ca": - return RedumpRegion.EuropeCanada; - case "E,G": - return RedumpRegion.EuropeGermany; - case "Ex": - return RedumpRegion.Export; - case "Fi": - return RedumpRegion.Finland; - case "F": - return RedumpRegion.France; - case "F,S": - return RedumpRegion.FranceSpain; - case "G": - return RedumpRegion.Germany; - case "GC": - return RedumpRegion.GreaterChina; - case "Gr": - return RedumpRegion.Greece; - case "H": - return RedumpRegion.Hungary; - case "Is": - return RedumpRegion.Iceland; - case "In": - return RedumpRegion.India; - case "Ie": - return RedumpRegion.Ireland; - case "Il": - return RedumpRegion.Israel; - case "I": - return RedumpRegion.Italy; - case "J": - return RedumpRegion.Japan; - case "J,A": - return RedumpRegion.JapanAsia; - case "J,E": - return RedumpRegion.JapanEurope; - case "J,K": - return RedumpRegion.JapanKorea; - case "J,U": - return RedumpRegion.JapanUSA; - case "K": - return RedumpRegion.Korea; - case "LAm": - return RedumpRegion.LatinAmerica; - case "Lt": - return RedumpRegion.Lithuania; - case "N": - return RedumpRegion.Netherlands; - case "Nz": - return RedumpRegion.NewZealand; - case "No": - return RedumpRegion.Norway; - case "P": - return RedumpRegion.Poland; - case "Pt": - return RedumpRegion.Portugal; - case "Ro": - return RedumpRegion.Romania; - case "R": - return RedumpRegion.Russia; - case "Sca": - return RedumpRegion.Scandinavia; - case "Rs": - return RedumpRegion.Serbia; - case "Sg": - return RedumpRegion.Singapore; - case "Sk": - return RedumpRegion.Slovakia; - case "Za": - return RedumpRegion.SouthAfrica; - case "S": - return RedumpRegion.Spain; - case "S,Pt": - return RedumpRegion.SpainPortugal; - case "Sw": - return RedumpRegion.Sweden; - case "Ch": - return RedumpRegion.Switzerland; - case "Tw": - return RedumpRegion.Taiwan; - case "Th": - return RedumpRegion.Thailand; - case "Tr": - return RedumpRegion.Turkey; - case "Ae": - return RedumpRegion.UnitedArabEmirates; - case "Uk": - return RedumpRegion.UK; - case "Uk,Au": - return RedumpRegion.UKAustralia; - case "Ua": - return RedumpRegion.Ukraine; - case "U": - return RedumpRegion.USA; - case "U,A": - return RedumpRegion.USAAsia; - case "U,Au": - return RedumpRegion.USAAustralia; - case "U,B": - return RedumpRegion.USABrazil; - case "U,Ca": - return RedumpRegion.USACanada; - case "U,E": - return RedumpRegion.USAEurope; - case "U,G": - return RedumpRegion.USAGermany; - case "U,J": - return RedumpRegion.USAJapan; - case "U,K": - return RedumpRegion.USAKorea; - case "W": - return RedumpRegion.World; - default: - return null; - } - } - - /// - /// Get the RedumpSystem enum value for a given string - /// - /// String value to convert - /// RedumpSystem represented by the string, if possible - public static RedumpSystem? ToRedumpSystem(string sys) - { - switch (sys) - { - // Special BIOS Sets - case "xboxbios": - case "xbox bios": - case "microsoftxboxbios": - case "microsoftxbox bios": - case "microsoft xbox bios": - return RedumpSystem.MicrosoftXboxBIOS; - case "gcbios": - case "gc bios": - case "gamecubebios": - case "ngcbios": - case "ngc bios": - case "nintendogamecubebios": - case "nintendo gamecube bios": - return RedumpSystem.NintendoGameCubeBIOS; - case "ps1bios": - case "ps1 bios": - case "psxbios": - case "psx bios": - case "playstationbios": - case "playstation bios": - case "sonyps1bios": - case "sonyps1 bios": - case "sony ps1 bios": - case "sonypsxbios": - case "sonypsx bios": - case "sony psx bios": - case "sonyplaystationbios": - case "sonyplaystation bios": - case "sony playstation bios": - return RedumpSystem.SonyPlayStationBIOS; - case "ps2bios": - case "ps2 bios": - case "playstation2bios": - case "playstation2 bios": - case "playstation 2 bios": - case "sonyps2bios": - case "sonyps2 bios": - case "sony ps2 bios": - case "sonyplaystation2bios": - case "sonyplaystation2 bios": - case "sony playstation 2 bios": - return RedumpSystem.SonyPlayStation2BIOS; - - // Regular systems - case "acorn": - case "archimedes": - case "acornarchimedes": - case "acorn archimedes": - return RedumpSystem.AcornArchimedes; - case "apple": - case "mac": - case "applemac": - case "macintosh": - case "applemacintosh": - case "apple mac": - case "apple macintosh": - return RedumpSystem.AppleMacintosh; - case "jaguar": - case "jagcd": - case "jaguarcd": - case "jaguar cd": - case "atarijaguar": - case "atarijagcd": - case "atarijaguarcd": - case "atari jaguar cd": - return RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem; - case "audio": - case "audiocd": - case "audio cd": - return RedumpSystem.AudioCD; - case "playdia": - case "playdiaqis": - case "playdiaquickinteractivesystem": - case "bandaiplaydia": - case "bandaiplaydiaquickinteractivesystem": - case "bandai playdia quick interactive system": - return RedumpSystem.BandaiPlaydiaQuickInteractiveSystem; - case "pippin": - case "bandaipippin": - case "bandai pippin": - case "applepippin": - case "apple pippin": - case "bandaiapplepippin": - case "bandai apple pippin": - case "bandai / apple pippin": - return RedumpSystem.BandaiPippin; - case "bdvideo": - case "bd-video": - case "blurayvideo": - case "bluray video": - return RedumpSystem.BDVideo; - case "amiga": - case "amigacd": - case "amiga cd": - case "commodoreamiga": - case "commodoreamigacd": - case "commodoreamiga cd": - case "commodore amiga": - case "commodore amiga cd": - return RedumpSystem.CommodoreAmigaCD; - case "cd32": - case "amigacd32": - case "amiga cd32": - case "commodoreamigacd32": - case "commodore amiga cd32": - return RedumpSystem.CommodoreAmigaCD32; - case "cdtv": - case "amigacdtv": - case "amiga cdtv": - case "commodoreamigacdtv": - case "commodore amiga cdtv": - return RedumpSystem.CommodoreAmigaCDTV; - case "dvdvideo": - case "dvd-video": - return RedumpSystem.DVDVideo; - case "enhancedcd": - case "enhanced cd": - case "enhancedcdrom": - case "enhanced cdrom": - case "enhanced cd-rom": - return RedumpSystem.EnhancedCD; - case "fmtowns": - case "fmt": - case "fm towns": - case "fujitsufmtowns": - case "fujitsu fm towns": - case "fujitsu fm towns series": - return RedumpSystem.FujitsuFMTownsseries; - case "fpp": - case "funworldphotoplay": - case "funworld photoplay": - case "funworld photo play": - return RedumpSystem.funworldPhotoPlay; - case "videonow": - case "hasbrovideonow": - case "hasbro videonow": - return RedumpSystem.HasbroVideoNow; - case "videonowcolor": - case "videonow color": - case "hasbrovideonowcolor": - case "hasbro videonow color": - return RedumpSystem.HasbroVideoNowColor; - case "videonowjr": - case "videonow jr": - case "hasbrovideonowjr": - case "hasbro videonow jr": - return RedumpSystem.HasbroVideoNowColor; - case "videonowxp": - case "videonow xp": - case "hasbrovideonowxp": - case "hasbro videonow xp": - return RedumpSystem.HasbroVideoNowColor; - case "ibm": - case "ibmpc": - case "pc": - case "ibm pc": - case "ibm pc compatible": - return RedumpSystem.IBMPCcompatible; - case "iteagle": - case "eagle": - case "incredible technologies eagle": - return RedumpSystem.IncredibleTechnologiesEagle; - case "eamusement": - case "e-amusement": - case "konamieamusement": - case "konami eamusement": - case "konamie-amusement": - case "konami e-amusement": - return RedumpSystem.KonamieAmusement; - case "firebeat": - case "konamifirebeat": - case "konami firebeat": - return RedumpSystem.KonamiFireBeat; - case "konamim2": - case "konami m2": - return RedumpSystem.KonamiM2; - case "system573": - case "system 573": - case "konamisystem573": - case "konami system 573": - return RedumpSystem.KonamiSystem573; - case "gvsystem": - case "systemgv": - case "gv system": - case "system gv": - case "konamigvsystem": - case "konamisystemgv": - case "konami gv system": - case "konami system gv": - return RedumpSystem.KonamiSystemGV; - case "twinkle": - case "konamitwinkle": - case "konami twinkle": - return RedumpSystem.KonamiTwinkle; - case "ixl": - case "mattelixl": - case "mattel ixl": - case "fisherpriceixl": - case "fisher price ixl": - case "fisher-price ixl": - case "fisherprice ixl": - case "mattelfisherpriceixl": - case "mattel fisher price ixl": - case "mattelfisherprice ixl": - case "mattel fisherprice ixl": - case "mattel fisher-price ixl": - return RedumpSystem.MattelFisherPriceiXL; - case "hyperscan": - case "mattelhyperscan": - case "mattel hyperscan": - return RedumpSystem.MattelHyperScan; - case "vis": - case "tandyvis": - case "tandy vis": - case "tandyvisualinformationsystem": - case "tandy visual information system": - case "memorexvis": - case "memorex vis": - case "memorexvisualinformationsystem": - case "memorex visual information sytem": - case "tandy / memorex visual information system": - return RedumpSystem.MemorexVisualInformationSystem; - case "xbox": - case "microsoftxbox": - case "microsoft xbox": - return RedumpSystem.MicrosoftXbox; - case "x360": - case "xbox360": - case "microsoftx360": - case "microsoftxbox360": - case "microsoft x360": - case "microsoft xbox 360": - return RedumpSystem.MicrosoftXbox360; - case "xb1": - case "xbone": - case "xboxone": - case "microsoftxbone": - case "microsoftxboxone": - case "microsoft xbone": - case "microsoft xbox one": - return RedumpSystem.MicrosoftXboxOne; - case "xbs": - case "xbseries": - case "xbseriess": - case "xbseriesx": - case "xbseriessx": - case "xboxseries": - case "xboxseriess": - case "xboxseriesx": - case "xboxseriesxs": - case "microsoftxboxseries": - case "microsoftxboxseriess": - case "microsoftxboxseriesx": - case "microsoftxboxseriesxs": - case "microsoft xbox series": - case "microsoft xbox series s": - case "microsoft xbox series x": - case "microsoft xbox series x and s": - return RedumpSystem.MicrosoftXboxSeriesXS; - case "triforce": - case "namcotriforce": - case "namco triforce": - case "segatriforce": - case "sega triforce": - case "nintendotriforce": - case "nintendo triforce": - case "namco / sega / nintendo triforce": - return RedumpSystem.NamcoSegaNintendoTriforce; - case "system12": - case "system 12": - case "namcosystem12": - case "namco system 12": - return RedumpSystem.NamcoSystem12; - case "system246": - case "system 246": - case "namcosystem246": - case "namco system 246": - case "capcomsystem246": - case "capcom system 246": - case "taitosystem246": - case "taito system 246": - case "namco / capcom / taito system 246": - return RedumpSystem.NamcoSystem246; - case "naviken": - case "naviken21": - case "naviken 2.1": - case "navisoftnaviken": - case "navisoft naviken": - case "navisoftnaviken21": - case "navisoft naviken 2.1": - return RedumpSystem.NavisoftNaviken21; - case "pcecd": - case "pce-cd": - case "tgcd": - case "tg-cd": - case "necpcecd": - case "nectgcd": - case "nec pc-engine cd": - case "nec turbografx cd": - case "nec pc-engine / turbografx cd": - return RedumpSystem.NECPCEngineCDTurboGrafxCD; - case "pc88": - case "pc-88": - case "necpc88": - case "nec pc88": - case "nec pc-88": - return RedumpSystem.NECPC88series; - case "pc98": - case "pc-98": - case "necpc98": - case "nec pc98": - case "nec pc-98": - return RedumpSystem.NECPC98series; - case "pcfx": - case "pc-fx": - case "pcfxga": - case "pc-fxga": - case "necpcfx": - case "necpcfxga": - case "nec pc-fx": - case "nec pc-fxga": - case "nec pc-fx / pc-fxga": - return RedumpSystem.NECPCFXPCFXGA; - case "gc": - case "gamecube": - case "ngc": - case "nintendogamecube": - case "nintendo gamecube": - return RedumpSystem.NintendoGameCube; - case "wii": - case "nintendowii": - case "nintendo wii": - return RedumpSystem.NintendoWii; - case "wiiu": - case "wii u": - case "nintendowiiu": - case "nintendo wii u": - return RedumpSystem.NintendoWiiU; - case "palm": - case "palmos": - return RedumpSystem.PalmOS; - case "3do": - case "3do interactive multiplayer": - case "panasonic3do": - case "panasonic 3do": - case "panasonic 3do interactive multiplayer": - return RedumpSystem.Panasonic3DOInteractiveMultiplayer; - case "panasonicm2": - case "panasonic m2": - return RedumpSystem.PanasonicM2; - case "cdi": - case "cd-i": - case "philipscdi": - case "philips cdi": - case "philips cd-i": - return RedumpSystem.PhilipsCDi; - case "photo": - case "photocd": - case "photo cd": - return RedumpSystem.PhotoCD; - case "gameshark": - case "psgameshark": - case "ps gameshark": - case "playstationgameshark": - case "playstation gameshark": - case "playstation gameshark updates": - return RedumpSystem.PlayStationGameSharkUpdates; - case "pocketpc": - case "pocket pc": - case "ppc": - return RedumpSystem.PocketPC; - case "chihiro": - case "segachihiro": - case "sega chihiro": - return RedumpSystem.SegaChihiro; - case "dc": - case "sdc": - case "dreamcast": - case "segadreamcast": - case "sega dreamcast": - return RedumpSystem.SegaDreamcast; - case "lindbergh": - case "segalindbergh": - case "sega lindbergh": - return RedumpSystem.SegaLindbergh; - case "scd": - case "mcd": - case "smcd": - case "segacd": - case "megacd": - case "segamegacd": - case "sega cd": - case "mega cd": - case "sega cd / mega cd": - return RedumpSystem.SegaMegaCDSegaCD; - case "naomi": - case "seganaomi": - case "sega naomi": - return RedumpSystem.SegaNaomi; - case "naomi2": - case "naomi 2": - case "seganaomi2": - case "sega naomi 2": - return RedumpSystem.SegaNaomi2; - case "pl21": - case "prologue21": - case "prologue 21": - case "segaprologue21": - case "sega prologue21": - case "sega prologue 21": - return RedumpSystem.SegaPrologue21; - case "ringedge": - case "segaringedge": - case "sega ringedge": - return RedumpSystem.SegaRingEdge; - case "ringedge2": - case "ringedge 2": - case "segaringedge2": - case "sega ringedge 2": - return RedumpSystem.SegaRingEdge2; - case "saturn": - case "segasaturn": - case "sega saturn": - return RedumpSystem.SegaSaturn; - case "stv": - case "titanvideo": - case "titan video": - case "segatitanvideo": - case "sega titan video": - return RedumpSystem.SegaTitanVideo; - case "x68k": - case "x68000": - case "sharpx68k": - case "sharp x68k": - case "sharpx68000": - case "sharp x68000": - return RedumpSystem.SharpX68000; - case "ngcd": - case "neogeocd": - case "neogeo cd": - case "neo geo cd": - case "snk ngcd": - case "snk neogeo cd": - case "snk neo geo cd": - return RedumpSystem.SNKNeoGeoCD; - case "ps1": - case "psx": - case "playstation": - case "sonyps1": - case "sony ps1": - case "sonypsx": - case "sony psx": - case "sonyplaystation": - case "sony playstation": - return RedumpSystem.SonyPlayStation; - case "ps2": - case "playstation2": - case "playstation 2": - case "sonyps2": - case "sony ps2": - case "sonyplaystation2": - case "sony playstation 2": - return RedumpSystem.SonyPlayStation2; - case "ps3": - case "playstation3": - case "playstation 3": - case "sonyps3": - case "sony ps3": - case "sonyplaystation3": - case "sony playstation 3": - return RedumpSystem.SonyPlayStation3; - case "ps4": - case "playstation4": - case "playstation 4": - case "sonyps4": - case "sony ps4": - case "sonyplaystation4": - case "sony playstation 4": - return RedumpSystem.SonyPlayStation4; - case "ps5": - case "playstation5": - case "playstation 5": - case "sonyps5": - case "sony ps5": - case "sonyplaystation5": - case "sony playstation 5": - return RedumpSystem.SonyPlayStation5; - case "psp": - case "playstationportable": - case "playstation portable": - case "sonypsp": - case "sony psp": - case "sonyplaystationportable": - case "sony playstation portable": - return RedumpSystem.SonyPlayStationPortable; - case "quizard": - case "tabaustriaquizard": - case "tab-austria quizard": - return RedumpSystem.TABAustriaQuizard; - case "iktv": - case "taoiktv": - case "tao iktv": - return RedumpSystem.TaoiKTV; - case "kisssite": - case "kiss-site": - case "tomykisssite": - case "tomy kisssite": - case "tomy kiss-site": - return RedumpSystem.TomyKissSite; - case "vcd": - case "videocd": - case "video cd": - return RedumpSystem.VideoCD; - case "nuon": - case "vmlabsnuon": - case "vm labs nuon": - return RedumpSystem.VMLabsNUON; - case "vflash": - case "vsmile": - case "vsmilepro": - case "vsmile pro": - case "v.flash": - case "v.smile": - case "v.smilepro": - case "v.smile pro": - case "vtechvflash": - case "vtech vflash": - case "vtech v.flash": - case "vtechvsmile": - case "vtech vsmile": - case "vtech v.smile": - case "vtechvsmilepro": - case "vtech vsmile pro": - case "vtech v.smile pro": - case "vtech v.flash - v.smile pro": - return RedumpSystem.VTechVFlashVSmilePro; - case "gamewave": - case "game wave": - case "zapit": - case "zapitgamewave": - case "zapit game wave": - case "zapit games game wave family entertainment system": - return RedumpSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem; - - default: - return null; - } - } - #endregion } - - /// - /// Serialize KnownSystem enum values - /// - public class KnownSystemConverter : JsonConverter - { - public override bool CanRead { get { return false; } } - - public override KnownSystem? ReadJson(JsonReader reader, Type objectType, KnownSystem? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, KnownSystem? value, JsonSerializer serializer) - { - JToken t = JToken.FromObject(value.ToRedumpSystem().ShortName() ?? value.ShortName() ?? string.Empty); - t.WriteTo(writer); - } - } - - /// - /// Serialize MediaType enum values - /// - public class MediaTypeConverter : JsonConverter - { - public override bool CanRead { get { return false; } } - - public override MediaType? ReadJson(JsonReader reader, Type objectType, MediaType? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, MediaType? value, JsonSerializer serializer) - { - JToken t = JToken.FromObject(value.ShortName() ?? string.Empty); - t.WriteTo(writer); - } - } - - /// - /// Serialize RedumpLanguage enum values - /// - public class RedumpLanguageConverter : JsonConverter - { - public override bool CanRead { get { return false; } } - - public override RedumpLanguage?[] ReadJson(JsonReader reader, Type objectType, RedumpLanguage?[] existingValue, bool hasExistingValue, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, RedumpLanguage?[] value, JsonSerializer serializer) - { - JArray array = new JArray(); - foreach (var val in value) - { - JToken t = JToken.FromObject(val.ShortName() ?? string.Empty); - array.Add(t); - } - - array.WriteTo(writer); - } - } - - /// - /// Serialize RedumpLanguageSelection enum values - /// - public class RedumpLanguageSelectionConverter : JsonConverter - { - public override bool CanRead { get { return false; } } - - public override RedumpLanguageSelection?[] ReadJson(JsonReader reader, Type objectType, RedumpLanguageSelection?[] existingValue, bool hasExistingValue, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, RedumpLanguageSelection?[] value, JsonSerializer serializer) - { - JArray array = new JArray(); - foreach (var val in value) - { - JToken t = JToken.FromObject(val.LongName() ?? string.Empty); - array.Add(t); - } - - array.WriteTo(writer); - } - } - - /// - /// Serialize RedumpRegion enum values - /// - public class RedumpRegionConverter : JsonConverter - { - public override bool CanRead { get { return false; } } - - public override RedumpRegion? ReadJson(JsonReader reader, Type objectType, RedumpRegion? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, RedumpRegion? value, JsonSerializer serializer) - { - JToken t = JToken.FromObject(value.ShortName() ?? string.Empty); - t.WriteTo(writer); - } - } } diff --git a/MPF.Library/Converters/KnownSystemConverter.cs b/MPF.Library/Converters/KnownSystemConverter.cs new file mode 100644 index 00000000..db349a66 --- /dev/null +++ b/MPF.Library/Converters/KnownSystemConverter.cs @@ -0,0 +1,28 @@ +using System; +using MPF.Data; +using MPF.Utilities; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using RedumpLib.Data; + +namespace MPF.Converters +{ + /// + /// Serialize KnownSystem enum values + /// + public class KnownSystemConverter : JsonConverter + { + public override bool CanRead { get { return false; } } + + public override KnownSystem? ReadJson(JsonReader reader, Type objectType, KnownSystem? existingValue, bool hasExistingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, KnownSystem? value, JsonSerializer serializer) + { + JToken t = JToken.FromObject(value.ToRedumpSystem().ShortName() ?? value.ShortName() ?? string.Empty); + t.WriteTo(writer); + } + } +} \ No newline at end of file diff --git a/MPF.Library/Converters/MediaTypeConverter.cs b/MPF.Library/Converters/MediaTypeConverter.cs new file mode 100644 index 00000000..6c7d505b --- /dev/null +++ b/MPF.Library/Converters/MediaTypeConverter.cs @@ -0,0 +1,27 @@ +using System; +using MPF.Data; +using MPF.Utilities; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MPF.Converters +{ + /// + /// Serialize MediaType enum values + /// + public class MediaTypeConverter : JsonConverter + { + public override bool CanRead { get { return false; } } + + public override MediaType? ReadJson(JsonReader reader, Type objectType, MediaType? existingValue, bool hasExistingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, MediaType? value, JsonSerializer serializer) + { + JToken t = JToken.FromObject(value.ShortName() ?? string.Empty); + t.WriteTo(writer); + } + } +} \ No newline at end of file diff --git a/MPF.Library/DD/Parameters.cs b/MPF.Library/DD/Parameters.cs index fd8d31e7..c818fd4a 100644 --- a/MPF.Library/DD/Parameters.cs +++ b/MPF.Library/DD/Parameters.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using MPF.Data; +using RedumpLib.Data; namespace MPF.DD { @@ -87,7 +88,7 @@ namespace MPF.DD switch (this.System) { case KnownSystem.KonamiPython2: - if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out RedumpRegion? pythonTwoRegion, out string pythonTwoDate)) + if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out Region? pythonTwoRegion, out string pythonTwoDate)) { info.CommonDiscInfo.Comments += $"Internal Disc Serial: {pythonTwoSerial}\n"; info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion; @@ -98,7 +99,7 @@ namespace MPF.DD break; case KnownSystem.SonyPlayStation: - if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out RedumpRegion? playstationRegion, out string playstationDate)) + if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out Region? playstationRegion, out string playstationDate)) { info.CommonDiscInfo.Comments += $"Internal Disc Serial: {playstationSerial}\n"; info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion; @@ -109,7 +110,7 @@ namespace MPF.DD break; case KnownSystem.SonyPlayStation2: - if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out RedumpRegion? playstationTwoRegion, out string playstationTwoDate)) + if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out Region? playstationTwoRegion, out string playstationTwoDate)) { info.CommonDiscInfo.Comments += $"Internal Disc Serial: {playstationTwoSerial}\n"; info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion; diff --git a/MPF.Library/Data/BaseParameters.cs b/MPF.Library/Data/BaseParameters.cs index d4979f42..fb09a753 100644 --- a/MPF.Library/Data/BaseParameters.cs +++ b/MPF.Library/Data/BaseParameters.cs @@ -10,6 +10,7 @@ using BurnOutSharp.ProtectionType; using Compress.ThreadReaders; using MPF.Hashing; using MPF.Utilities; +using RedumpLib.Data; namespace MPF.Data { @@ -1202,7 +1203,7 @@ namespace MPF.Data /// Output region, if possible /// Output EXE date in "yyyy-mm-dd" format if possible, null on error /// - protected static bool GetPlayStationExecutableInfo(char? driveLetter, out string serial, out RedumpRegion? region, out string date) + protected static bool GetPlayStationExecutableInfo(char? driveLetter, out string serial, out Region? region, out string date) { serial = null; region = null; date = null; @@ -1382,16 +1383,16 @@ namespace MPF.Data /// /// String representing the category /// Category, if possible - protected static RedumpDiscCategory? GetUMDCategory(string category) + protected static DiscCategory? GetUMDCategory(string category) { switch (category) { case "GAME": - return RedumpDiscCategory.Games; + return DiscCategory.Games; case "VIDEO": - return RedumpDiscCategory.Video; + return DiscCategory.Video; case "AUDIO": - return RedumpDiscCategory.Audio; + return DiscCategory.Audio; default: return null; } @@ -1406,7 +1407,7 @@ namespace MPF.Data /// /// PlayStation serial code /// Region mapped from name, if possible - protected static RedumpRegion? GetPlayStationRegion(string serial) + protected static Region? GetPlayStationRegion(string serial) { // Standardized "S" serials if (serial.StartsWith("S")) @@ -1416,25 +1417,25 @@ namespace MPF.Data switch (serial[2]) { case 'A': - return RedumpRegion.Asia; + return Region.Asia; case 'C': - return RedumpRegion.China; + return Region.China; case 'E': - return RedumpRegion.Europe; + return Region.Europe; case 'J': - return RedumpRegion.JapanKorea; + return Region.JapanKorea; case 'K': - return RedumpRegion.Korea; + return Region.Korea; case 'P': - return RedumpRegion.Japan; + return Region.Japan; case 'U': - return RedumpRegion.USA; + return Region.USA; } } // Japan-only special serial else if (serial.StartsWith("PAPX")) - return RedumpRegion.Japan; + return Region.Japan; // Region appears entirely random else if (serial.StartsWith("PABX")) @@ -1442,15 +1443,15 @@ namespace MPF.Data // Japan-only special serial else if (serial.StartsWith("PCBX")) - return RedumpRegion.Japan; + return Region.Japan; // Single disc known, Japan else if (serial.StartsWith("PDBX")) - return RedumpRegion.Japan; + return Region.Japan; // Single disc known, Europe else if (serial.StartsWith("PEBX")) - return RedumpRegion.Europe; + return Region.Europe; return null; } @@ -1460,24 +1461,24 @@ namespace MPF.Data /// /// Character denoting the region /// Region, if possible - protected static RedumpRegion? GetXgdRegion(char region) + protected static Region? GetXgdRegion(char region) { switch (region) { case 'W': - return RedumpRegion.World; + return Region.World; case 'A': - return RedumpRegion.USA; + return Region.USA; case 'J': - return RedumpRegion.JapanAsia; + return Region.JapanAsia; case 'E': - return RedumpRegion.Europe; + return Region.Europe; case 'K': - return RedumpRegion.USAJapan; + return Region.USAJapan; case 'L': - return RedumpRegion.USAEurope; + return Region.USAEurope; case 'H': - return RedumpRegion.JapanEurope; + return Region.JapanEurope; default: return null; } diff --git a/MPF.Library/Data/DumpEnvironment.cs b/MPF.Library/Data/DumpEnvironment.cs index 9b9ec589..adc6cc4a 100644 --- a/MPF.Library/Data/DumpEnvironment.cs +++ b/MPF.Library/Data/DumpEnvironment.cs @@ -4,13 +4,17 @@ using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; +using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using BurnOutSharp; -using MPF.Redump; +using MPF.Converters; using MPF.Utilities; using Newtonsoft.Json; +using RedumpLib.Attributes; +using RedumpLib.Data; +using RedumpLib.Web; namespace MPF.Data { @@ -633,7 +637,7 @@ namespace MPF.Data if (GetISOHashValues(hashData, out long _, out string _, out string _, out string sha1)) { // Get all matching IDs for the track - List newIds = wc.ListSearchResults(sha1); + List newIds = ListSearchResults(wc, sha1); // If we got null back, there was an error if (newIds == null) @@ -665,7 +669,7 @@ namespace MPF.Data if (info.MatchedIDs.Count == 1) { resultProgress?.Report(Result.Success($"Filling fields from existing ID {info.MatchedIDs[0]}...")); - wc.FillFromId(info, info.MatchedIDs[0]); + FillFromId(wc, info, info.MatchedIDs[0]); resultProgress?.Report(Result.Success("Information filling complete!")); } } @@ -793,7 +797,7 @@ namespace MPF.Data switch (System) { case KnownSystem.AcornArchimedes: - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.UK; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.UK; break; case KnownSystem.AppleMacintosh: @@ -814,16 +818,16 @@ namespace MPF.Data case KnownSystem.AudioCD: case KnownSystem.DVDAudio: case KnownSystem.SuperAudioCD: - info.CommonDiscInfo.Category = info.CommonDiscInfo.Category ?? RedumpDiscCategory.Audio; + info.CommonDiscInfo.Category = info.CommonDiscInfo.Category ?? DiscCategory.Audio; break; case KnownSystem.BandaiPlaydiaQuickInteractiveSystem: info.CommonDiscInfo.EXEDateBuildDate = (Options.AddPlaceholders ? Template.RequiredValue : ""); - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Japan; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Japan; break; case KnownSystem.BDVideo: - info.CommonDiscInfo.Category = info.CommonDiscInfo.Category ?? RedumpDiscCategory.BonusDiscs; + info.CommonDiscInfo.Category = info.CommonDiscInfo.Category ?? DiscCategory.BonusDiscs; info.CopyProtection.Protection = (Options.AddPlaceholders ? Template.RequiredIfExistsValue : ""); break; @@ -833,25 +837,25 @@ namespace MPF.Data case KnownSystem.CommodoreAmigaCD32: info.CommonDiscInfo.EXEDateBuildDate = (Options.AddPlaceholders ? Template.RequiredValue : ""); - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Europe; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Europe; break; case KnownSystem.CommodoreAmigaCDTV: info.CommonDiscInfo.EXEDateBuildDate = (Options.AddPlaceholders ? Template.RequiredValue : ""); - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Europe; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Europe; break; case KnownSystem.DVDVideo: - info.CommonDiscInfo.Category = info.CommonDiscInfo.Category ?? RedumpDiscCategory.BonusDiscs; + info.CommonDiscInfo.Category = info.CommonDiscInfo.Category ?? DiscCategory.BonusDiscs; break; case KnownSystem.FujitsuFMTowns: info.CommonDiscInfo.EXEDateBuildDate = (Options.AddPlaceholders ? Template.RequiredValue : ""); - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Japan; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Japan; break; case KnownSystem.FujitsuFMTownsMarty: - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Japan; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Japan; break; case KnownSystem.IncredibleTechnologiesEagle: @@ -888,20 +892,20 @@ namespace MPF.Data case KnownSystem.NavisoftNaviken21: info.CommonDiscInfo.EXEDateBuildDate = (Options.AddPlaceholders ? Template.RequiredValue : ""); - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Japan; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Japan; break; case KnownSystem.NECPC88: - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Japan; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Japan; break; case KnownSystem.NECPC98: info.CommonDiscInfo.EXEDateBuildDate = (Options.AddPlaceholders ? Template.RequiredValue : ""); - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Japan; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Japan; break; case KnownSystem.NECPCFX: - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Japan; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Japan; break; case KnownSystem.SegaChihiro: @@ -925,7 +929,7 @@ namespace MPF.Data break; case KnownSystem.SharpX68000: - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Japan; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Japan; break; case KnownSystem.SNKNeoGeoCD: @@ -933,7 +937,7 @@ namespace MPF.Data break; case KnownSystem.SonyPlayStation2: - info.CommonDiscInfo.LanguageSelection = new RedumpLanguageSelection?[] { RedumpLanguageSelection.BiosSettings, RedumpLanguageSelection.LanguageSelector, RedumpLanguageSelection.OptionsMenu }; + info.CommonDiscInfo.LanguageSelection = new LanguageSelection?[] { LanguageSelection.BiosSettings, LanguageSelection.LanguageSelector, LanguageSelection.OptionsMenu }; break; case KnownSystem.SonyPlayStation3: @@ -942,7 +946,7 @@ namespace MPF.Data break; case KnownSystem.TomyKissSite: - info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? RedumpRegion.Japan; + info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? Region.Japan; break; case KnownSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem: @@ -951,7 +955,7 @@ namespace MPF.Data } // Set the category if it's not overriden - info.CommonDiscInfo.Category = info.CommonDiscInfo.Category ?? RedumpDiscCategory.Games; + info.CommonDiscInfo.Category = info.CommonDiscInfo.Category ?? DiscCategory.Games; // Comments is one of the few fields with odd handling if (string.IsNullOrEmpty(info.CommonDiscInfo.Comments)) @@ -996,9 +1000,9 @@ namespace MPF.Data 1); AddIfExists(output, Template.CategoryField, info.CommonDiscInfo.Category.LongName(), 1); AddIfExists(output, Template.MatchingIDsField, info.MatchedIDs, 1); - AddIfExists(output, Template.RegionField, info.CommonDiscInfo.Region.LongName(), 1); - AddIfExists(output, Template.LanguagesField, (info.CommonDiscInfo.Languages ?? new RedumpLanguage?[] { null }).Select(l => l.LongName()).ToArray(), 1); - AddIfExists(output, Template.PlaystationLanguageSelectionViaField, (info.CommonDiscInfo.LanguageSelection ?? new RedumpLanguageSelection?[] { }).Select(l => l.ToString()).ToArray(), 1); + AddIfExists(output, Template.RegionField, info.CommonDiscInfo.Region.LongName() ?? "SPACE! (CHANGE THIS)", 1); + AddIfExists(output, Template.LanguagesField, (info.CommonDiscInfo.Languages ?? new Language?[] { null }).Select(l => l.LongName() ?? "Klingon (CHANGE THIS)").ToArray(), 1); + AddIfExists(output, Template.PlaystationLanguageSelectionViaField, (info.CommonDiscInfo.LanguageSelection ?? new LanguageSelection?[] { }).Select(l => l.LongName()).ToArray(), 1); AddIfExists(output, Template.DiscSerialField, info.CommonDiscInfo.Serial, 1); // All ringcode information goes in an indented area @@ -1479,5 +1483,198 @@ namespace MPF.Data } #endregion + + #region Web Calls + + /// + /// Fill out an existing SubmissionInfo object based on a disc page + /// + /// RedumpWebClient for making the connection + /// Existing SubmissionInfo object to fill + /// Redump disc ID to retrieve + private void FillFromId(RedumpWebClient wc, SubmissionInfo info, int id) + { + string discData = wc.DownloadSingleSiteID(id); + if (string.IsNullOrEmpty(discData)) + return; + + // Title, Disc Number/Letter, Disc Title + var match = Constants.TitleRegex.Match(discData); + if (match.Success) + { + string title = WebUtility.HtmlDecode(match.Groups[1].Value); + + // If we have parenthesis, title is everything before the first one + int firstParenLocation = title.IndexOf(" ("); + if (firstParenLocation >= 0) + { + info.CommonDiscInfo.Title = title.Substring(0, firstParenLocation); + var subMatches = Constants.DiscNumberLetterRegex.Match(title); + for (int i = 1; i < subMatches.Groups.Count; i++) + { + string subMatch = subMatches.Groups[i].Value; + + // Disc number or letter + if (subMatch.StartsWith("Disc")) + info.CommonDiscInfo.DiscNumberLetter = subMatch.Remove(0, "Disc ".Length); + + // Disc title + else + info.CommonDiscInfo.DiscTitle = subMatch; + } + } + // Otherwise, leave the title as-is + else + { + info.CommonDiscInfo.Title = title; + } + } + + // Foreign Title + match = Constants.ForeignTitleRegex.Match(discData); + if (match.Success) + info.CommonDiscInfo.ForeignTitleNonLatin = WebUtility.HtmlDecode(match.Groups[1].Value); + else + info.CommonDiscInfo.ForeignTitleNonLatin = null; + + // Category + match = Constants.CategoryRegex.Match(discData); + if (match.Success) + info.CommonDiscInfo.Category = Extensions.ToDiscCategory(match.Groups[1].Value); + else + info.CommonDiscInfo.Category = DiscCategory.Games; + + // Region + match = Constants.RegionRegex.Match(discData); + if (match.Success) + info.CommonDiscInfo.Region = Extensions.ToRegion(match.Groups[1].Value); + + // Languages + var matches = Constants.LanguagesRegex.Matches(discData); + if (matches.Count > 0) + { + List tempLanguages = new List(); + foreach (Match submatch in matches) + tempLanguages.Add(Extensions.ToLanguage(submatch.Groups[1].Value)); + + info.CommonDiscInfo.Languages = tempLanguages.Where(l => l != null).ToArray(); + } + + // Error count + match = Constants.ErrorCountRegex.Match(discData); + if (match.Success) + { + // If the error count is empty, fill from the page + if (string.IsNullOrEmpty(info.CommonDiscInfo.ErrorsCount)) + info.CommonDiscInfo.ErrorsCount = match.Groups[1].Value; + } + + // Version + match = Constants.VersionRegex.Match(discData); + if (match.Success) + info.VersionAndEditions.Version = WebUtility.HtmlDecode(match.Groups[1].Value); + + // Dumpers + matches = Constants.DumpersRegex.Matches(discData); + if (matches.Count > 0) + { + // Start with any currently listed dumpers + List tempDumpers = new List(); + if (info.DumpersAndStatus.Dumpers.Length > 0) + { + foreach (string dumper in info.DumpersAndStatus.Dumpers) + tempDumpers.Add(dumper); + } + + foreach (Match submatch in matches) + tempDumpers.Add(WebUtility.HtmlDecode(submatch.Groups[1].Value)); + + info.DumpersAndStatus.Dumpers = tempDumpers.ToArray(); + } + + // Comments + match = Constants.CommentsRegex.Match(discData); + if (match.Success) + { + info.CommonDiscInfo.Comments += (string.IsNullOrEmpty(info.CommonDiscInfo.Comments) ? string.Empty : "\n") + + WebUtility.HtmlDecode(match.Groups[1].Value) + .Replace("
", "\n") + .Replace("ISBN", "[T:ISBN]") + "\n"; + } + + // Contents + match = Constants.ContentsRegex.Match(discData); + if (match.Success) + { + info.CommonDiscInfo.Contents = WebUtility.HtmlDecode(match.Groups[1].Value) + .Replace("
", "\n") + .Replace("", ""); + info.CommonDiscInfo.Contents = Regex.Replace(info.CommonDiscInfo.Contents, @"
", ""); + } + + // Added + match = Constants.AddedRegex.Match(discData); + if (match.Success) + { + if (DateTime.TryParse(match.Groups[1].Value, out DateTime added)) + info.Added = added; + else + info.Added = null; + } + + // Last Modified + match = Constants.LastModifiedRegex.Match(discData); + if (match.Success) + { + if (DateTime.TryParse(match.Groups[1].Value, out DateTime lastModified)) + info.LastModified = lastModified; + else + info.LastModified = null; + } + } + + /// + /// List the disc IDs associated with a given quicksearch query + /// + /// RedumpWebClient for making the connection + /// Query string to attempt to search for + /// All disc IDs for the given query, null on error + private List ListSearchResults(RedumpWebClient wc, string query) + { + List ids = new List(); + + // Strip quotes + query = query.Trim('"', '\''); + + // Special characters become dashes + query = query.Replace(' ', '-'); + query = query.Replace('/', '-'); + query = query.Replace('\\', '/'); + + // Lowercase is defined per language + query = query.ToLowerInvariant(); + + // Keep getting quicksearch pages until there are none left + try + { + int pageNumber = 1; + while (true) + { + List pageIds = wc.CheckSingleSitePage(string.Format(Constants.QuickSearchUrl, query, pageNumber++)); + ids.AddRange(pageIds); + if (pageIds.Count <= 1) + break; + } + } + catch (Exception ex) + { + Console.WriteLine($"An exception occurred while trying to log in: {ex}"); + return null; + } + + return ids; + } + + #endregion } } diff --git a/MPF.Library/Data/Enumerations.cs b/MPF.Library/Data/Enumerations.cs index 1d6430fd..d14c4d9c 100644 --- a/MPF.Library/Data/Enumerations.cs +++ b/MPF.Library/Data/Enumerations.cs @@ -407,274 +407,6 @@ namespace MPF.Data TapeDSTLarge = 66, } - /// - /// Redump disc category - /// - public enum RedumpDiscCategory - { - Games = 1, - Demos = 2, - Video = 3, - Audio = 4, - Multimedia = 5, - Applications = 6, - Coverdiscs = 7, - Educational = 8, - BonusDiscs = 9, - Preproduction = 10, - AddOns = 11, - } - - /// - /// Redump dump status - /// - public enum RedumpDumpStatus - { - BadDumpRed = 2, - PossibleBadDumpYellow = 3, - OriginalMediaBlue = 4, - TwoOrMoreDumpsGreen = 5, - } - - /// - /// Redump supported langauge - /// - public enum RedumpLanguage - { - Afrikaans, - Albanian, - Arabic, - Basque, - Bulgarian, - Catalan, - Chinese, - Croatian, - Czech, - Danish, - Dutch, - English, - Estonian, - Finnish, - French, - Gaelic, - German, - Greek, - Hebrew, - Hindi, - Hungarian, - Indonesian, - Icelandic, - Italian, - Japanese, - Korean, - Latin, - Latvian, - Lithuanian, - Macedonian, - Norwegian, - Polish, - Portuguese, - Punjabi, - Romanian, - Russian, - Serbian, - Slovak, - Slovenian, - Spanish, - Swedish, - Tamil, - Thai, - Turkish, - Ukrainian, - } - - /// - /// Redump PS2 language selection via - /// - public enum RedumpLanguageSelection - { - BiosSettings, - LanguageSelector, - OptionsMenu, - } - - /// - /// Supported Redump region - /// - public enum RedumpRegion - { - Argentina, - Asia, - AsiaEurope, - AsiaUSA, - Australia, - AustraliaGermany, - AustraliaNewZealand, - Austria, - AustriaSwitzerland, - Belgium, - BelgiumNetherlands, - Brazil, - Bulgaria, - Canada, - China, - Croatia, - Czech, - Denmark, - Estonia, - Europe, - EuropeAsia, - EuropeAustralia, - EuropeCanada, - EuropeGermany, - Export, - Finland, - France, - FranceSpain, - Germany, - GreaterChina, - Greece, - Hungary, - Iceland, - India, - Ireland, - Israel, - Italy, - Japan, - JapanAsia, - JapanEurope, - JapanKorea, - JapanUSA, - Korea, - LatinAmerica, - Lithuania, - Netherlands, - NewZealand, - Norway, - Poland, - Portugal, - Romania, - Russia, - Scandinavia, - Serbia, - Singapore, - Slovakia, - SouthAfrica, - Spain, - SpainPortugal, - Sweden, - Switzerland, - Taiwan, - Thailand, - Turkey, - UnitedArabEmirates, - UK, - UKAustralia, - Ukraine, - USA, - USAAsia, - USAAustralia, - USABrazil, - USACanada, - USAEurope, - USAGermany, - USAJapan, - USAKorea, - World, - } - - /// - /// List of all known Redump systems - /// - public enum RedumpSystem - { - // Special BIOS sets - MicrosoftXboxBIOS, - NintendoGameCubeBIOS, - SonyPlayStationBIOS, - SonyPlayStation2BIOS, - - // Regular systems - AcornArchimedes, - AppleMacintosh, - AtariJaguarCDInteractiveMultimediaSystem, - AudioCD, - BandaiPippin, - BandaiPlaydiaQuickInteractiveSystem, - BDVideo, - CommodoreAmigaCD, - CommodoreAmigaCD32, - CommodoreAmigaCDTV, - DVDVideo, - EnhancedCD, - FujitsuFMTownsseries, - funworldPhotoPlay, - HasbroVideoNow, - HasbroVideoNowColor, - HasbroVideoNowJr, - HasbroVideoNowXP, - HDDVDVideo, - IBMPCcompatible, - IncredibleTechnologiesEagle, - KonamieAmusement, - KonamiFireBeat, - KonamiM2, - KonamiSystem573, - KonamiSystemGV, - KonamiTwinkle, - MattelFisherPriceiXL, - MattelHyperScan, - MemorexVisualInformationSystem, - MicrosoftXbox, - MicrosoftXbox360, - MicrosoftXboxOne, - MicrosoftXboxSeriesXS, - NamcoSegaNintendoTriforce, - NamcoSystem12, - NamcoSystem246, - NavisoftNaviken21, - NECPCEngineCDTurboGrafxCD, - NECPC88series, - NECPC98series, - NECPCFXPCFXGA, - NintendoGameCube, - NintendoWii, - NintendoWiiU, - PalmOS, - Panasonic3DOInteractiveMultiplayer, - PanasonicM2, - PhilipsCDi, - PhotoCD, - PlayStationGameSharkUpdates, - PocketPC, - SegaChihiro, - SegaDreamcast, - SegaLindbergh, - SegaMegaCDSegaCD, - SegaNaomi, - SegaNaomi2, - SegaPrologue21, - SegaRingEdge, - SegaRingEdge2, - SegaSaturn, - SegaTitanVideo, - SharpX68000, - SNKNeoGeoCD, - SonyPlayStation, - SonyPlayStation2, - SonyPlayStation3, - SonyPlayStation4, - SonyPlayStation5, - SonyPlayStationPortable, - TABAustriaQuizard, - TaoiKTV, - TomyKissSite, - VideoCD, - VMLabsNUON, - VTechVFlashVSmilePro, - ZAPiTGamesGameWaveFamilyEntertainmentSystem, - } - /// /// Generic yes/no values for Redump /// diff --git a/MPF.Library/Data/Options.cs b/MPF.Library/Data/Options.cs index e75953e5..63527f7a 100644 --- a/MPF.Library/Data/Options.cs +++ b/MPF.Library/Data/Options.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using MPF.Converters; using MPF.Utilities; namespace MPF.Data @@ -46,7 +47,7 @@ namespace MPF.Data get { string valueString = GetStringSetting(_settings, "InternalProgram", InternalProgram.DiscImageCreator.ToString()); - var valueEnum = Converters.ToInternalProgram(valueString); + var valueEnum = EnumConverter.ToInternalProgram(valueString); return valueEnum == InternalProgram.NONE ? InternalProgram.DiscImageCreator : valueEnum; } set @@ -85,12 +86,12 @@ namespace MPF.Data get { string valueString = GetStringSetting(_settings, "DefaultSystem", KnownSystem.NONE.ToString()); - var valueEnum = Converters.ToKnownSystem(valueString); + var valueEnum = EnumConverter.ToKnownSystem(valueString); return valueEnum ?? KnownSystem.NONE; } set { - _settings["DefaultSystem"] = Converters.GetLongName(value); + _settings["DefaultSystem"] = EnumConverter.GetLongName(value); } } diff --git a/MPF.Library/Data/SubmissionInfo.cs b/MPF.Library/Data/SubmissionInfo.cs index e7b6371a..d05796be 100644 --- a/MPF.Library/Data/SubmissionInfo.cs +++ b/MPF.Library/Data/SubmissionInfo.cs @@ -1,9 +1,12 @@ using System; using System.Collections.Generic; using System.Linq; +using MPF.Converters; using MPF.Utilities; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; +using RedumpLib.Converters; +using RedumpLib.Data; namespace MPF.Data { @@ -113,19 +116,19 @@ namespace MPF.Data public string DiscTitle { get; set; } [JsonProperty(PropertyName = "d_category", Required = Required.AllowNull)] - public RedumpDiscCategory? Category { get; set; } + public DiscCategory? Category { get; set; } [JsonProperty(PropertyName = "d_region", Required = Required.AllowNull)] - [JsonConverter(typeof(RedumpRegionConverter))] - public RedumpRegion? Region { get; set; } + [JsonConverter(typeof(RegionConverter))] + public Region? Region { get; set; } [JsonProperty(PropertyName = "d_languages", Required = Required.AllowNull)] - [JsonConverter(typeof(RedumpLanguageConverter))] - public RedumpLanguage?[] Languages { get; set; } + [JsonConverter(typeof(LanguageConverter))] + public Language?[] Languages { get; set; } [JsonProperty(PropertyName = "d_languages_selection", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)] - [JsonConverter(typeof(RedumpLanguageSelectionConverter))] - public RedumpLanguageSelection?[] LanguageSelection { get; set; } + [JsonConverter(typeof(LanguageSelectionConverter))] + public LanguageSelection?[] LanguageSelection { get; set; } [JsonProperty(PropertyName = "d_serial", NullValueHandling = NullValueHandling.Ignore)] public string Serial { get; set; } @@ -226,8 +229,8 @@ namespace MPF.Data DiscTitle = this.DiscTitle, Category = this.Category, Region = this.Region, - Languages = this.Languages?.Clone() as RedumpLanguage?[], - LanguageSelection = this.LanguageSelection?.Clone() as RedumpLanguageSelection?[], + Languages = this.Languages?.Clone() as Language?[], + LanguageSelection = this.LanguageSelection?.Clone() as LanguageSelection?[], Serial = this.Serial, Ring = this.Ring, RingId = this.RingId, @@ -406,7 +409,7 @@ namespace MPF.Data public class DumpersAndStatusSection : ICloneable { [JsonProperty(PropertyName = "d_status", NullValueHandling = NullValueHandling.Ignore)] - public RedumpDumpStatus Status { get; set; } + public DumpStatus Status { get; set; } [JsonProperty(PropertyName = "d_dumpers", NullValueHandling = NullValueHandling.Ignore)] public string[] Dumpers { get; set; } diff --git a/MPF.Library/DiscImageCreator/Parameters.cs b/MPF.Library/DiscImageCreator/Parameters.cs index 81a31d47..727229a1 100644 --- a/MPF.Library/DiscImageCreator/Parameters.cs +++ b/MPF.Library/DiscImageCreator/Parameters.cs @@ -7,6 +7,7 @@ using BurnOutSharp.External.psxt001z; using MPF.CueSheets; using MPF.Data; using MPF.Utilities; +using RedumpLib.Data; namespace MPF.DiscImageCreator { @@ -457,7 +458,7 @@ namespace MPF.DiscImageCreator break; case KnownSystem.KonamiPython2: - if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out RedumpRegion? pythonTwoRegion, out string pythonTwoDate)) + if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out Region? pythonTwoRegion, out string pythonTwoDate)) { info.CommonDiscInfo.Comments += $"Internal Disc Serial: {pythonTwoSerial}\n"; info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion; @@ -477,7 +478,7 @@ namespace MPF.DiscImageCreator info.Extras.SecuritySectorRanges = ss ?? ""; } - if (GetXboxDMIInfo(Path.Combine(outputDirectory, "DMI.bin"), out string serial, out string version, out RedumpRegion? region)) + if (GetXboxDMIInfo(Path.Combine(outputDirectory, "DMI.bin"), out string serial, out string version, out Region? region)) { info.CommonDiscInfo.Serial = serial ?? ""; info.VersionAndEditions.Version = version ?? ""; @@ -496,7 +497,7 @@ namespace MPF.DiscImageCreator info.Extras.SecuritySectorRanges = ss360 ?? ""; } - if (GetXbox360DMIInfo(Path.Combine(outputDirectory, "DMI.bin"), out string serial360, out string version360, out RedumpRegion? region360)) + if (GetXbox360DMIInfo(Path.Combine(outputDirectory, "DMI.bin"), out string serial360, out string version360, out Region? region360)) { info.CommonDiscInfo.Serial = serial360 ?? ""; info.VersionAndEditions.Version = version360 ?? ""; @@ -631,7 +632,7 @@ namespace MPF.DiscImageCreator break; case KnownSystem.SonyPlayStation: - if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out RedumpRegion? playstationRegion, out string playstationDate)) + if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out Region? playstationRegion, out string playstationDate)) { info.CommonDiscInfo.Comments += $"Internal Serial: {playstationSerial ?? ""}\n"; info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion; @@ -688,7 +689,7 @@ namespace MPF.DiscImageCreator break; case KnownSystem.SonyPlayStation2: - if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out RedumpRegion? playstationTwoRegion, out string playstationTwoDate)) + if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out Region? playstationTwoRegion, out string playstationTwoDate)) { info.CommonDiscInfo.Comments += $"Internal Disc Serial: {playstationTwoSerial}\n"; info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion; @@ -3205,9 +3206,9 @@ namespace MPF.DiscImageCreator /// /// DMI.bin file location /// True on successful extraction of info, false otherwise - private static bool GetXboxDMIInfo(string dmi, out string serial, out string version, out RedumpRegion? region) + private static bool GetXboxDMIInfo(string dmi, out string serial, out string version, out Region? region) { - serial = null; version = null; region = RedumpRegion.World; + serial = null; version = null; region = Region.World; if (!File.Exists(dmi)) return false; @@ -3236,9 +3237,9 @@ namespace MPF.DiscImageCreator /// /// DMI.bin file location /// True on successful extraction of info, false otherwise - private static bool GetXbox360DMIInfo(string dmi, out string serial, out string version, out RedumpRegion? region) + private static bool GetXbox360DMIInfo(string dmi, out string serial, out string version, out Region? region) { - serial = null; version = null; region = RedumpRegion.World; + serial = null; version = null; region = Region.World; if (!File.Exists(dmi)) return false; diff --git a/MPF.Library/MPF.Library.csproj b/MPF.Library/MPF.Library.csproj index 093251f9..b6560d69 100644 --- a/MPF.Library/MPF.Library.csproj +++ b/MPF.Library/MPF.Library.csproj @@ -73,6 +73,10 @@ + + + + runtime; compile; build; native; analyzers; buildtransitive diff --git a/MPF.Library/Redump/Extras.cs b/MPF.Library/Redump/Extras.cs deleted file mode 100644 index f17b47a0..00000000 --- a/MPF.Library/Redump/Extras.cs +++ /dev/null @@ -1,235 +0,0 @@ -using MPF.Data; - -namespace MPF.Redump -{ - /// - /// Information pertaining to Redump systems - /// - public static class Extras - { - #region Special lists - - /// - /// List of systems that are not publically accessible - /// - public static readonly RedumpSystem?[] BannedSystems = new RedumpSystem?[] - { - RedumpSystem.AudioCD, - RedumpSystem.BDVideo, - RedumpSystem.DVDVideo, - RedumpSystem.HasbroVideoNow, - RedumpSystem.HasbroVideoNowColor, - RedumpSystem.HasbroVideoNowJr, - RedumpSystem.HasbroVideoNowXP, - RedumpSystem.HDDVDVideo, - RedumpSystem.KonamiM2, - RedumpSystem.MicrosoftXbox360, - RedumpSystem.MicrosoftXboxOne, - //RedumpSystem.MicrosoftXboxSeriesXS, - RedumpSystem.NavisoftNaviken21, - RedumpSystem.NintendoWii, - RedumpSystem.NintendoWiiU, - RedumpSystem.PanasonicM2, - RedumpSystem.SegaPrologue21, - RedumpSystem.SegaRingEdge, - RedumpSystem.SegaRingEdge2, - RedumpSystem.SonyPlayStation3, - RedumpSystem.SonyPlayStation4, - //RedumpSystem.SonyPlayStation5, - RedumpSystem.VideoCD, - }; - - /// - /// List of systems that have a Cues pack - /// - public static readonly RedumpSystem?[] HasCues = new RedumpSystem?[] - { - RedumpSystem.AcornArchimedes, - RedumpSystem.AppleMacintosh, - RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem, - RedumpSystem.AudioCD, - RedumpSystem.BandaiPippin, - RedumpSystem.BandaiPlaydiaQuickInteractiveSystem, - RedumpSystem.CommodoreAmigaCD, - RedumpSystem.CommodoreAmigaCD32, - RedumpSystem.CommodoreAmigaCDTV, - RedumpSystem.FujitsuFMTownsseries, - RedumpSystem.funworldPhotoPlay, - RedumpSystem.HasbroVideoNow, - RedumpSystem.HasbroVideoNowColor, - RedumpSystem.HasbroVideoNowJr, - RedumpSystem.HasbroVideoNowXP, - RedumpSystem.IBMPCcompatible, - RedumpSystem.IncredibleTechnologiesEagle, - RedumpSystem.KonamieAmusement, - RedumpSystem.KonamiFireBeat, - RedumpSystem.KonamiM2, - RedumpSystem.KonamiSystemGV, - RedumpSystem.MattelFisherPriceiXL, - RedumpSystem.MattelHyperScan, - RedumpSystem.MemorexVisualInformationSystem, - RedumpSystem.MicrosoftXbox, - RedumpSystem.MicrosoftXbox360, - RedumpSystem.NamcoSegaNintendoTriforce, - RedumpSystem.NamcoSystem246, - RedumpSystem.NavisoftNaviken21, - RedumpSystem.NECPCEngineCDTurboGrafxCD, - RedumpSystem.NECPC88series, - RedumpSystem.NECPC98series, - RedumpSystem.NECPCFXPCFXGA, - RedumpSystem.PalmOS, - RedumpSystem.Panasonic3DOInteractiveMultiplayer, - RedumpSystem.PanasonicM2, - RedumpSystem.PhilipsCDi, - RedumpSystem.PhotoCD, - RedumpSystem.PlayStationGameSharkUpdates, - RedumpSystem.PocketPC, - RedumpSystem.SegaChihiro, - RedumpSystem.SegaDreamcast, - RedumpSystem.SegaMegaCDSegaCD, - RedumpSystem.SegaNaomi, - RedumpSystem.SegaNaomi2, - RedumpSystem.SegaPrologue21, - RedumpSystem.SegaSaturn, - RedumpSystem.SNKNeoGeoCD, - RedumpSystem.SonyPlayStation, - RedumpSystem.SonyPlayStation2, - RedumpSystem.SonyPlayStation3, - RedumpSystem.TABAustriaQuizard, - RedumpSystem.TomyKissSite, - RedumpSystem.VideoCD, - RedumpSystem.VTechVFlashVSmilePro, -}; - - /// - /// List of systems that has a Dat pack - /// - public static readonly RedumpSystem?[] HasDat = new RedumpSystem?[] - { - RedumpSystem.MicrosoftXboxBIOS, - RedumpSystem.NintendoGameCubeBIOS, - RedumpSystem.SonyPlayStationBIOS, - RedumpSystem.SonyPlayStation2BIOS, - - RedumpSystem.AcornArchimedes, - RedumpSystem.AppleMacintosh, - RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem, - RedumpSystem.AudioCD, - RedumpSystem.BandaiPippin, - RedumpSystem.BandaiPlaydiaQuickInteractiveSystem, - RedumpSystem.BDVideo, - RedumpSystem.CommodoreAmigaCD, - RedumpSystem.CommodoreAmigaCD32, - RedumpSystem.CommodoreAmigaCDTV, - RedumpSystem.DVDVideo, - RedumpSystem.FujitsuFMTownsseries, - RedumpSystem.funworldPhotoPlay, - RedumpSystem.HasbroVideoNow, - RedumpSystem.HasbroVideoNowColor, - RedumpSystem.HasbroVideoNowJr, - RedumpSystem.HasbroVideoNowXP, - RedumpSystem.HDDVDVideo, - RedumpSystem.IBMPCcompatible, - RedumpSystem.IncredibleTechnologiesEagle, - RedumpSystem.KonamieAmusement, - RedumpSystem.KonamiFireBeat, - RedumpSystem.KonamiM2, - RedumpSystem.KonamiSystemGV, - RedumpSystem.MattelFisherPriceiXL, - RedumpSystem.MattelHyperScan, - RedumpSystem.MemorexVisualInformationSystem, - RedumpSystem.MicrosoftXbox, - RedumpSystem.MicrosoftXbox360, - RedumpSystem.MicrosoftXboxOne, - //RedumpSystem.MicrosoftXboxSeriesXS, - RedumpSystem.NamcoSegaNintendoTriforce, - RedumpSystem.NamcoSystem246, - RedumpSystem.NavisoftNaviken21, - RedumpSystem.NECPCEngineCDTurboGrafxCD, - RedumpSystem.NECPC88series, - RedumpSystem.NECPC98series, - RedumpSystem.NECPCFXPCFXGA, - RedumpSystem.NintendoGameCube, - RedumpSystem.NintendoWii, - RedumpSystem.NintendoWiiU, - RedumpSystem.PalmOS, - RedumpSystem.Panasonic3DOInteractiveMultiplayer, - RedumpSystem.PanasonicM2, - RedumpSystem.PhilipsCDi, - RedumpSystem.PhotoCD, - RedumpSystem.PlayStationGameSharkUpdates, - //RedumpSystem.PocketPC, - RedumpSystem.SegaChihiro, - RedumpSystem.SegaDreamcast, - RedumpSystem.SegaLindbergh, - RedumpSystem.SegaMegaCDSegaCD, - RedumpSystem.SegaNaomi, - RedumpSystem.SegaNaomi2, - RedumpSystem.SegaRingEdge, - RedumpSystem.SegaRingEdge2, - RedumpSystem.SegaSaturn, - RedumpSystem.SNKNeoGeoCD, - RedumpSystem.SonyPlayStation, - RedumpSystem.SonyPlayStation2, - RedumpSystem.SonyPlayStation3, - RedumpSystem.SonyPlayStation4, - //RedumpSystem.SonyPlayStation5, - RedumpSystem.SonyPlayStationPortable, - RedumpSystem.TABAustriaQuizard, - RedumpSystem.TomyKissSite, - RedumpSystem.VideoCD, - RedumpSystem.VMLabsNUON, - RedumpSystem.VTechVFlashVSmilePro, - RedumpSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem, - }; - - /// - /// List of systems that has a Decrypted Keys pack - /// - public static readonly RedumpSystem?[] HasDkeys = new RedumpSystem?[] - { - RedumpSystem.SonyPlayStation3, - }; - - /// - /// List of systems that has a GDI pack - /// - public static readonly RedumpSystem?[] HasGdi = new RedumpSystem?[] - { - RedumpSystem.NamcoSegaNintendoTriforce, - RedumpSystem.SegaChihiro, - RedumpSystem.SegaDreamcast, - RedumpSystem.SegaNaomi, - RedumpSystem.SegaNaomi2, - }; - - /// - /// List of systems that has a Keys pack - /// - public static readonly RedumpSystem?[] HasKeys = new RedumpSystem?[] - { - RedumpSystem.NintendoWiiU, - RedumpSystem.SonyPlayStation3, - }; - - /// - /// List of systems that has an LSD pack - /// - public static readonly RedumpSystem?[] HasLsd = new RedumpSystem?[] - { - RedumpSystem.IBMPCcompatible, - RedumpSystem.SonyPlayStation, - }; - - /// - /// List of systems that has an SBI pack - /// - public static readonly RedumpSystem?[] HasSbi = new RedumpSystem?[] - { - RedumpSystem.IBMPCcompatible, - RedumpSystem.SonyPlayStation, - }; - - #endregion - } -} diff --git a/MPF.Library/Redump/RedumpWebClient.cs b/MPF.Library/Redump/RedumpWebClient.cs deleted file mode 100644 index 082a5978..00000000 --- a/MPF.Library/Redump/RedumpWebClient.cs +++ /dev/null @@ -1,1588 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using MPF.Data; -using MPF.Utilities; -using Newtonsoft.Json.Linq; - -namespace MPF.Redump -{ - // https://stackoverflow.com/questions/1777221/using-cookiecontainer-with-webclient-class - public class RedumpWebClient : WebClient - { - #region Regular Expressions - - /// - /// Regex matching the added field on a disc page - /// - private readonly Regex addedRegex = new Regex(@"Added(.*?)"); - - /// - /// Regex matching the barcode field on a disc page - /// - private readonly Regex barcodeRegex = new Regex(@"Barcode(.*?)"); - - /// - /// Regex matching the BCA field on a disc page - /// - private readonly Regex bcaRegex = new Regex(@"

BCA .*?/>

" - + "RowContentsASCII" - + "(?.*?)(?.*?)(?.*?)" - + "(?.*?)(?.*?)(?.*?)" - + "(?.*?)(?.*?)(?.*?)" - + "(?.*?)(?.*?)(?.*?)", RegexOptions.Singleline); - - /// - /// Regex matching the category field on a disc page - /// - private readonly Regex categoryRegex = new Regex(@"Category(.*?)"); - - /// - /// Regex matching the comments field on a disc page - /// - private readonly Regex commentsRegex = new Regex(@"Comments(.*?)", RegexOptions.Singleline); - - /// - /// Regex matching the contents field on a disc page - /// - private readonly Regex contentsRegex = new Regex(@"Contents(.*?)", RegexOptions.Singleline); - - /// - /// Regex matching individual disc links on a results page - /// - private readonly Regex discRegex = new Regex(@""); - - /// - /// Regex matching the disc number or letter field on a disc page - /// - private readonly Regex discNumberLetterRegex = new Regex(@"\((.*?)\)"); - - /// - /// Regex matching the dumpers on a disc page - /// - private readonly Regex dumpersRegex = new Regex(@"", RegexOptions.Singleline); - - /// - /// Regex matching the edition field on a disc page - /// - private readonly Regex editionRegex = new Regex(@"Edition(.*?)"); - - /// - /// Regex matching the error count field on a disc page - /// - private readonly Regex errorCountRegex = new Regex(@"Errors count(.*?)"); - - /// - /// Regex matching the foreign title field on a disc page - /// - private readonly Regex foreignTitleRegex = new Regex(@"

(.*?)

"); - - /// - /// Regex matching the "full match" ID list from a WIP disc page - /// - private readonly Regex fullMatchRegex = new Regex(@"full match ids: (.*?)"); - - /// - /// Regex matching the languages field on a disc page - /// - private readonly Regex languagesRegex = new Regex(@"\s*"); - - /// - /// Regex matching the last modified field on a disc page - /// - private readonly Regex lastModifiedRegex = new Regex(@"Last modified(.*?)"); - - /// - /// Regex matching the media field on a disc page - /// - private readonly Regex mediaRegex = new Regex(@"Media(.*?)"); - - /// - /// Regex matching individual WIP disc links on a results page - /// - private readonly Regex newDiscRegex = new Regex(@"
"); - - /// - /// Regex matching the "partial match" ID list from a WIP disc page - /// - private readonly Regex partialMatchRegex = new Regex(@"partial match ids: (.*?)"); - - /// - /// Regex matching the PVD field on a disc page - /// - private readonly Regex pvdRegex = new Regex(@"

Primary Volume Descriptor (PVD)

" - + @"Record / EntryContentsDateTimeGMT" - + @"Creation(?.*?)(?.*?)(?.*?)(?.*?)" - + @"Modification(?.*?)(?.*?)(?.*?)(?.*?)" - + @"Expiration(?.*?)(?.*?)(?.*?)(?.*?)" - + @"Effective(?.*?)(?.*?)(?.*?)(?.*?)", RegexOptions.Singleline); - - /// - /// Regex matching the region field on a disc page - /// - private readonly Regex regionRegex = new Regex(@"Region
"); - - /// - /// Regex matching a double-layer disc ringcode information - /// - private readonly Regex ringCodeDoubleRegex = new Regex(@"", RegexOptions.Singleline); // Varies based on available fields, like Addtional Mould - - /// - /// Regex matching a single-layer disc ringcode information - /// - private readonly Regex ringCodeSingleRegex = new Regex(@"", RegexOptions.Singleline); // Varies based on available fields, like Addtional Mould - - /// - /// Regex matching the serial field on a disc page - /// - private readonly Regex serialRegex = new Regex(@"Serial(.*?)"); - - /// - /// Regex matching the system field on a disc page - /// - private readonly Regex systemRegex = new Regex(@"System"); - - /// - /// Regex matching the title field on a disc page - /// - private readonly Regex titleRegex = new Regex(@"

(.*?)

"); - - /// - /// Regex matching the current nonce token for login - /// - private readonly Regex tokenRegex = new Regex(@""); - - /// - /// Regex matching a single track on a disc page - /// - private readonly Regex trackRegex = new Regex(@"(?.*?)(?.*?)(?.*?)(?.*?)(?.*?)(?.*?)(?.*?)(?.*?)(?.*?)", RegexOptions.Singleline); - - /// - /// Regex matching the track count on a disc page - /// - private readonly Regex trackCountRegex = new Regex(@"Number of tracks(.*?)"); - - /// - /// Regex matching the version field on a disc page - /// - private readonly Regex versionRegex = new Regex(@"Version(.*?)"); - - /// - /// Regex matching the write offset field on a disc page - /// - private readonly Regex writeOffsetRegex = new Regex(@"Write offset(.*?)"); - - #endregion - - #region URLs - - /// - /// Redump disc page URL template - /// - private const string discPageUrl = @"http://redump.org/disc/{0}/"; - - /// - /// Redump last modified search URL - /// - private const string lastModifiedUrl = @"http://redump.org/discs/sort/modified/dir/desc?page={0}"; - - /// - /// Redump login page URL - /// - private const string loginUrl = "http://forum.redump.org/login/"; - - /// - /// Redump CUE pack URL template - /// - private const string packCuesUrl = @"http://redump.org/cues/{0}/"; - - /// - /// Redump DAT pack URL template - /// - private const string packDatfileUrl = @"http://redump.org/datfile/{0}/"; - - /// - /// Redump DKEYS pack URL template - /// - private const string packDkeysUrl = @"http://redump.org/dkeys/{0}/"; - - /// - /// Redump GDI pack URL template - /// - private const string packGdiUrl = @"http://redump.org/gdi/{0}/"; - - /// - /// Redump KEYS pack URL template - /// - private const string packKeysUrl = @"http://redump.org/keys/{0}/"; - - /// - /// Redump LSD pack URL template - /// - private const string packLsdUrl = @"http://redump.org/lsd/{0}/"; - - /// - /// Redump SBI pack URL template - /// - private const string packSbiUrl = @"http://redump.org/sbi/{0}/"; - - /// - /// Redump quicksearch URL template - /// - private const string quickSearchUrl = @"http://redump.org/discs/quicksearch/{0}/?page={1}"; - - /// - /// Redump user dumps URL template - /// - private const string userDumpsUrl = @"http://redump.org/discs/dumper/{0}/?page={1}"; - - /// - /// Redump WIP disc page URL template - /// - private const string wipDiscPageUrl = @"http://redump.org/newdisc/{0}/"; - - /// - /// Redump WIP dumps queue URL - /// - private const string wipDumpsUrl = @"http://redump.org/discs-wip/"; - - #endregion - - #region URL Extensions - - private const string changesExt = "changes/"; - private const string cueExt = "cue/"; - private const string editExt = "edit/"; - private const string gdiExt = "gdi/"; - private const string keyExt = "key/"; - private const string lsdExt = "lsd/"; - private const string md5Ext = "md5/"; - private const string sbiExt = "sbi/"; - private const string sfvExt = "sfv/"; - private const string sha1Ext = "sha1/"; - - #endregion - - private readonly CookieContainer m_container = new CookieContainer(); - - /// - /// Determines if user is logged into Redump - /// - public bool LoggedIn { get; set; } = false; - - /// - /// Determines if the user is a staff member - /// - public bool IsStaff { get; set; } = false; - - /// - /// Get the last downloaded filename, if possible - /// - /// - public string GetLastFilename() - { - // Try to extract the filename from the Content-Disposition header - if (!String.IsNullOrEmpty(this.ResponseHeaders["Content-Disposition"])) - return this.ResponseHeaders["Content-Disposition"].Substring(this.ResponseHeaders["Content-Disposition"].IndexOf("filename=") + 9).Replace("\"", ""); - - return null; - } - - protected override WebRequest GetWebRequest(Uri address) - { - WebRequest request = base.GetWebRequest(address); - if (request is HttpWebRequest webRequest) - { - webRequest.CookieContainer = m_container; - webRequest.Timeout = 5 * 1000; - } - - return request; - } - - #region Features - - /// - /// Login to Redump, if possible - /// - /// Redump username - /// Redump password - /// True if the user could be logged in, false otherwise, null on error - public bool? Login(string username, string password) - { - // Credentials verification - if (!string.IsNullOrWhiteSpace(username) && !string.IsNullOrWhiteSpace(password)) - { - Console.WriteLine("Credentials entered, will attempt Redump login..."); - } - else if (!string.IsNullOrWhiteSpace(username) && string.IsNullOrWhiteSpace(password)) - { - Console.WriteLine("Only a username was specified, will not attempt Redump login..."); - return false; - } - else if (string.IsNullOrWhiteSpace(username)) - { - Console.WriteLine("No credentials entered, will not attempt Redump login..."); - return false; - } - - try - { - // Get the current token from the login page - var loginPage = DownloadString(loginUrl); - string token = this.tokenRegex.Match(loginPage).Groups[1].Value; - - // Encode the values - token = WebUtility.UrlEncode(token); - username = WebUtility.UrlEncode(username); - password = WebUtility.UrlEncode(password); - - // Construct the login request - Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded"; - Encoding = Encoding.UTF8; - var response = UploadString(loginUrl, $"form_sent=1&redirect_url=&csrf_token={token}&req_username={username}&req_password={password}&save_pass=0&login=Login"); - - if (response.Contains("Incorrect username and/or password")) - { - Console.WriteLine("Invalid credentials entered, continuing without logging in..."); - return false; - } - else if (response.Contains("503 Service Unavailable")) - { - Console.WriteLine("Redump is not currently responding, continuing without logging in..."); - return null; - } - - // The user was able to be logged in - Console.WriteLine("Credentials accepted! Logged into Redump..."); - LoggedIn = true; - - // If the user is a moderator or staff, set accordingly - if (response.Contains("http://forum.redump.org/forum/9/staff/")) - IsStaff = true; - - return true; - } - catch (Exception ex) - { - Console.WriteLine($"An exception occurred while trying to log in: {ex}"); - return null; - } - } - - /// - /// Get the latest version of MPF from GitHub and the release URL - /// - public (string tag, string url) GetRemoteVersionAndUrl() - { - Headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0"; - - // TODO: Figure out a better way than having this hardcoded... - string url = "https://api.github.com/repos/SabreTools/MPF/releases/latest"; - string latestReleaseJsonString = DownloadString(url); - var latestReleaseJson = JObject.Parse(latestReleaseJsonString); - string latestTag = latestReleaseJson["tag_name"].ToString(); - string releaseUrl = latestReleaseJson["html_url"].ToString(); - - return (latestTag, releaseUrl); - } - - /// - /// Create a new SubmissionInfo object based on a disc page - /// - /// Redump disc ID to retrieve - /// Filled SubmissionInfo object on success, null on error - public SubmissionInfo CreateFromId(int id) - { - string discData = DownloadSingleSiteID(id); - if (string.IsNullOrEmpty(discData)) - return null; - - // Create the new object - SubmissionInfo info = new SubmissionInfo(); - - // Added - var match = addedRegex.Match(discData); - if (match.Success) - { - if (DateTime.TryParse(match.Groups[1].Value, out DateTime added)) - info.Added = added; - else - info.Added = null; - } - - // Barcode - match = barcodeRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Barcode = WebUtility.HtmlDecode(match.Groups[1].Value); - - // BCA - match = bcaRegex.Match(discData); - if (match.Success) - { - info.Extras.BCA = WebUtility.HtmlDecode(match.Groups[1].Value) - .Replace("
", "\n") - .Replace("
", ""); - info.Extras.BCA = Regex.Replace(info.Extras.BCA, @"
", ""); - } - - // Category - match = categoryRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Category = Converters.ToDiscCategory(match.Groups[1].Value); - else - info.CommonDiscInfo.Category = RedumpDiscCategory.Games; - - // Comments - match = commentsRegex.Match(discData); - if (match.Success) - { - info.CommonDiscInfo.Comments = WebUtility.HtmlDecode(match.Groups[1].Value) - .Replace("
", "\n") - .Replace("ISBN", "[T:ISBN]") + "\n"; - } - - // Contents - match = contentsRegex.Match(discData); - if (match.Success) - { - info.CommonDiscInfo.Contents = WebUtility.HtmlDecode(match.Groups[1].Value) - .Replace("
", "\n") - .Replace("
", ""); - info.CommonDiscInfo.Contents = Regex.Replace(info.CommonDiscInfo.Contents, @"
", ""); - } - - // Dumpers - var matches = dumpersRegex.Matches(discData); - if (matches.Count > 0) - { - List tempDumpers = new List(); - foreach (Match submatch in matches) - { - tempDumpers.Add(WebUtility.HtmlDecode(submatch.Groups[1].Value)); - } - - info.DumpersAndStatus.Dumpers = tempDumpers.ToArray(); - } - - // Edition - match = editionRegex.Match(discData); - if (match.Success) - info.VersionAndEditions.OtherEditions = WebUtility.HtmlDecode(match.Groups[1].Value); - - // Error Count - match = errorCountRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.ErrorsCount = match.Groups[1].Value; - - // Foreign Title - match = foreignTitleRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.ForeignTitleNonLatin = WebUtility.HtmlDecode(match.Groups[1].Value); - else - info.CommonDiscInfo.ForeignTitleNonLatin = null; - - // Languages - matches = languagesRegex.Matches(discData); - if (matches.Count > 0) - { - List tempLanguages = new List(); - foreach (Match submatch in matches) - { - tempLanguages.Add(Converters.ToRedumpLanguage(submatch.Groups[1].Value)); - } - - info.CommonDiscInfo.Languages = tempLanguages.Where(l => l != null).ToArray(); - } - - // Last Modified - match = lastModifiedRegex.Match(discData); - if (match.Success) - { - if (DateTime.TryParse(match.Groups[1].Value, out DateTime lastModified)) - info.LastModified = lastModified; - else - info.LastModified = null; - } - - // Media - match = mediaRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Media = Converters.ToMediaType(match.Groups[1].Value); - - // PVD - match = pvdRegex.Match(discData); - if (match.Success) - { - info.Extras.PVD = WebUtility.HtmlDecode(match.Groups[1].Value) - .Replace("
", "\n") - .Replace("
", ""); - info.Extras.PVD = Regex.Replace(info.Extras.PVD, @"
", ""); - } - - // Region - match = regionRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Region = Converters.ToRedumpRegion(match.Groups[1].Value); - - // Serial - match = serialRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Serial = WebUtility.HtmlDecode(match.Groups[1].Value); - - // System - match = systemRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.System = Converters.ToKnownSystem(match.Groups[1].Value); - - // Title, Disc Number/Letter, Disc Title - match = titleRegex.Match(discData); - if (match.Success) - { - string title = WebUtility.HtmlDecode(match.Groups[1].Value); - - // If we have parenthesis, title is everything before the first one - int firstParenLocation = title.IndexOf(" ("); - if (firstParenLocation >= 0) - { - info.CommonDiscInfo.Title = title.Substring(0, firstParenLocation); - var subMatches = discNumberLetterRegex.Match(title); - for (int i = 1; i < subMatches.Groups.Count; i++) - { - string subMatch = subMatches.Groups[i].Value; - - // Disc number or letter - if (subMatch.StartsWith("Disc")) - info.CommonDiscInfo.DiscNumberLetter = subMatch.Remove(0, "Disc ".Length); - - // Disc title - else - info.CommonDiscInfo.DiscTitle = subMatch; - } - } - // Otherwise, leave the title as-is - else - { - info.CommonDiscInfo.Title = title; - } - } - - // Tracks - matches = trackRegex.Matches(discData); - if (matches.Count > 0) - { - List tempTracks = new List(); - foreach (Match submatch in matches) - { - tempTracks.Add(submatch.Groups[1].Value); - } - - info.TracksAndWriteOffsets.ClrMameProData = string.Join("\n", tempTracks); - } - - // Track Count - match = trackCountRegex.Match(discData); - if (match.Success) - info.TracksAndWriteOffsets.Cuesheet = match.Groups[1].Value; - - // Version - match = versionRegex.Match(discData); - if (match.Success) - info.VersionAndEditions.Version = WebUtility.HtmlDecode(match.Groups[1].Value); - - // Write Offset - match = writeOffsetRegex.Match(discData); - if (match.Success) - info.TracksAndWriteOffsets.OtherWriteOffsets = WebUtility.HtmlDecode(match.Groups[1].Value); - - return info; - } - - /// - /// Download the last modified disc pages, until first failure - /// - /// Output directory to save data to - public void DownloadLastModified(string outDir) - { - // Keep getting last modified pages until there are none left - int pageNumber = 1; - while (true) - { - if (!CheckSingleSitePage(string.Format(lastModifiedUrl, pageNumber++), outDir, true)) - break; - } - } - - /// - /// Download the last submitted WIP disc pages - /// - /// Output directory to save data to - public void DownloadLastSubmitted(string outDir) - { - CheckSingleWIPPage(wipDumpsUrl, outDir, false); - } - - /// - /// Download premade packs - /// - /// Output directory to save data to - /// True to use named subfolders to store downloads, false to store directly in the output directory - public void DownloadPacks(string outDir, bool useSubfolders) - { - this.DownloadPacks(packCuesUrl, Extras.HasCues, "CUEs", outDir, useSubfolders ? "cue" : null); - this.DownloadPacks(packDatfileUrl, Extras.HasDat, "DATs", outDir, useSubfolders ? "dat" : null); - this.DownloadPacks(packDkeysUrl, Extras.HasDkeys, "Decrypted KEYS", outDir, useSubfolders ? "dkey" : null); - this.DownloadPacks(packGdiUrl, Extras.HasGdi, "GDIs", outDir, useSubfolders ? "gdi" : null); - this.DownloadPacks(packKeysUrl, Extras.HasKeys, "KEYS", outDir, useSubfolders ? "keys" : null); - this.DownloadPacks(packLsdUrl, Extras.HasKeys, "LSD", outDir, useSubfolders ? "lsd" : null); - this.DownloadPacks(packSbiUrl, Extras.HasSbi, "SBIs", outDir, useSubfolders ? "sbi" : null); - } - - /// - /// Download premade packs for an individual system - /// - /// RedumpSystem to get all possible packs for - /// Output directory to save data to - /// True to use named subfolders to store downloads, false to store directly in the output directory - public void DownloadPacksForSystem(RedumpSystem system, string outDir, bool useSubfolders) - { - RedumpSystem?[] systemAsArray = new RedumpSystem?[] { system }; - - if (Extras.HasCues.Contains(system)) - this.DownloadPacks(packCuesUrl, systemAsArray, "CUEs", outDir, useSubfolders ? "cue" : null); - - if (Extras.HasDat.Contains(system)) - this.DownloadPacks(packCuesUrl, Extras.HasDat, "DATs", outDir, useSubfolders ? "dat" : null); - - if (Extras.HasDkeys.Contains(system)) - this.DownloadPacks(packCuesUrl, Extras.HasDkeys, "Decrypted KEYS", outDir, useSubfolders ? "dkey" : null); - - if (Extras.HasGdi.Contains(system)) - this.DownloadPacks(packCuesUrl, Extras.HasGdi, "GDIs", outDir, useSubfolders ? "gdi" : null); - - if (Extras.HasKeys.Contains(system)) - this.DownloadPacks(packCuesUrl, Extras.HasKeys, "KEYS", outDir, useSubfolders ? "keys" : null); - - if (Extras.HasLsd.Contains(system)) - this.DownloadPacks(packCuesUrl, Extras.HasKeys, "LSD", outDir, useSubfolders ? "lsd" : null); - - if (Extras.HasSbi.Contains(system)) - this.DownloadPacks(packCuesUrl, Extras.HasSbi, "SBIs", outDir, useSubfolders ? "sbi" : null); - } - - /// - /// Download the disc pages associated with a given quicksearch query - /// - /// Query string to attempt to search for - public Dictionary DownloadSearchResults(string query) - { - Dictionary resultPages = new Dictionary(); - - // Strip quotes - query = query.Trim('"', '\''); - - // Special characters become dashes - query = query.Replace(' ', '-'); - query = query.Replace('/', '-'); - query = query.Replace('\\', '/'); - - // Lowercase is defined per language - query = query.ToLowerInvariant(); - - // Keep getting quicksearch pages until there are none left - int pageNumber = 1; - while (true) - { - List pageIds = CheckSingleSitePage(string.Format(quickSearchUrl, query, pageNumber++)); - foreach (int pageId in pageIds) - { - resultPages[pageId] = DownloadSingleSiteID(pageId); - } - - if (pageIds.Count <= 1) - break; - } - - return resultPages; - } - - /// - /// Download the disc pages associated with a given quicksearch query - /// - /// Query string to attempt to search for - /// Output directory to save data to - public void DownloadSearchResults(string query, string outDir) - { - // Strip quotes - query = query.Trim('"', '\''); - - // Special characters become dashes - query = query.Replace(' ', '-'); - query = query.Replace('/', '-'); - query = query.Replace('\\', '/'); - - // Lowercase is defined per language - query = query.ToLowerInvariant(); - - // Keep getting quicksearch pages until there are none left - int pageNumber = 1; - while (true) - { - if (!CheckSingleSitePage(string.Format(quickSearchUrl, query, pageNumber++), outDir, false)) - break; - } - } - - /// - /// Download the specified range of site disc pages - /// - /// Output directory to save data to - /// Starting ID for the range - /// Ending ID for the range (inclusive) - public void DownloadSiteRange(string outDir, int minId = 0, int maxId = 0) - { - if (!LoggedIn) - { - Console.WriteLine("Site download functionality is only available to Redump members"); - return; - } - - for (int id = minId; id <= maxId; id++) - { - if (DownloadSingleSiteID(id, outDir, true)) - Thread.Sleep(5 * 1000); // Intentional sleep here so we don't flood the server - } - } - - /// - /// Download the disc pages associated with the given user - /// - /// Username to check discs for - /// Output directory to save data to - public void DownloadUser(string username, string outDir) - { - if (!LoggedIn) - { - Console.WriteLine("User download functionality is only available to Redump members"); - return; - } - - // Keep getting user pages until there are none left - int pageNumber = 1; - while (true) - { - if (!CheckSingleSitePage(string.Format(userDumpsUrl, username, pageNumber++), outDir, false)) - break; - } - } - - /// - /// Download the specified range of WIP disc pages - /// - /// RedumpWebClient for all access - /// Output directory to save data to - /// Starting ID for the range - /// Ending ID for the range (inclusive) - public void DownloadWIPRange(string outDir, int minId = 0, int maxId = 0) - { - if (!LoggedIn || !IsStaff) - { - Console.WriteLine("WIP download functionality is only available to Redump moderators"); - return; - } - - for (int id = minId; id <= maxId; id++) - { - if (DownloadSingleWIPID(id, outDir, true)) - Thread.Sleep(5 * 1000); // Intentional sleep here so we don't flood the server - } - } - - /// - /// Fill out an existing SubmissionInfo object based on a disc page - /// - /// Existing SubmissionInfo object to fill - /// Redump disc ID to retrieve - public void FillFromId(SubmissionInfo info, int id) - { - string discData = DownloadSingleSiteID(id); - if (string.IsNullOrEmpty(discData)) - return; - - // Title, Disc Number/Letter, Disc Title - var match = titleRegex.Match(discData); - if (match.Success) - { - string title = WebUtility.HtmlDecode(match.Groups[1].Value); - - // If we have parenthesis, title is everything before the first one - int firstParenLocation = title.IndexOf(" ("); - if (firstParenLocation >= 0) - { - info.CommonDiscInfo.Title = title.Substring(0, firstParenLocation); - var subMatches = discNumberLetterRegex.Match(title); - for (int i = 1; i < subMatches.Groups.Count; i++) - { - string subMatch = subMatches.Groups[i].Value; - - // Disc number or letter - if (subMatch.StartsWith("Disc")) - info.CommonDiscInfo.DiscNumberLetter = subMatch.Remove(0, "Disc ".Length); - - // Disc title - else - info.CommonDiscInfo.DiscTitle = subMatch; - } - } - // Otherwise, leave the title as-is - else - { - info.CommonDiscInfo.Title = title; - } - } - - // Foreign Title - match = foreignTitleRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.ForeignTitleNonLatin = WebUtility.HtmlDecode(match.Groups[1].Value); - else - info.CommonDiscInfo.ForeignTitleNonLatin = null; - - // Category - match = categoryRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Category = Converters.ToDiscCategory(match.Groups[1].Value); - else - info.CommonDiscInfo.Category = RedumpDiscCategory.Games; - - // Region - match = regionRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Region = Converters.ToRedumpRegion(match.Groups[1].Value); - - // Languages - var matches = languagesRegex.Matches(discData); - if (matches.Count > 0) - { - List tempLanguages = new List(); - foreach (Match submatch in matches) - tempLanguages.Add(Converters.ToRedumpLanguage(submatch.Groups[1].Value)); - - info.CommonDiscInfo.Languages = tempLanguages.Where(l => l != null).ToArray(); - } - - // Error count - match = errorCountRegex.Match(discData); - if (match.Success) - { - // If the error count is empty, fill from the page - if (string.IsNullOrEmpty(info.CommonDiscInfo.ErrorsCount)) - info.CommonDiscInfo.ErrorsCount = match.Groups[1].Value; - } - - // Version - match = versionRegex.Match(discData); - if (match.Success) - info.VersionAndEditions.Version = WebUtility.HtmlDecode(match.Groups[1].Value); - - // Dumpers - matches = dumpersRegex.Matches(discData); - if (matches.Count > 0) - { - // Start with any currently listed dumpers - List tempDumpers = new List(); - if (info.DumpersAndStatus.Dumpers.Length > 0) - { - foreach (string dumper in info.DumpersAndStatus.Dumpers) - tempDumpers.Add(dumper); - } - - foreach (Match submatch in matches) - tempDumpers.Add(WebUtility.HtmlDecode(submatch.Groups[1].Value)); - - info.DumpersAndStatus.Dumpers = tempDumpers.ToArray(); - } - - // Comments - match = commentsRegex.Match(discData); - if (match.Success) - { - info.CommonDiscInfo.Comments += (string.IsNullOrEmpty(info.CommonDiscInfo.Comments) ? string.Empty : "\n") - + WebUtility.HtmlDecode(match.Groups[1].Value) - .Replace("
", "\n") - .Replace("ISBN", "[T:ISBN]") + "\n"; - } - - // Contents - match = contentsRegex.Match(discData); - if (match.Success) - { - info.CommonDiscInfo.Contents = WebUtility.HtmlDecode(match.Groups[1].Value) - .Replace("
", "\n") - .Replace("
", ""); - info.CommonDiscInfo.Contents = Regex.Replace(info.CommonDiscInfo.Contents, @"
", ""); - } - - // Added - match = addedRegex.Match(discData); - if (match.Success) - { - if (DateTime.TryParse(match.Groups[1].Value, out DateTime added)) - info.Added = added; - else - info.Added = null; - } - - // Last Modified - match = lastModifiedRegex.Match(discData); - if (match.Success) - { - if (DateTime.TryParse(match.Groups[1].Value, out DateTime lastModified)) - info.LastModified = lastModified; - else - info.LastModified = null; - } - } - - /// - /// List the disc IDs associated with a given quicksearch query - /// - /// Query string to attempt to search for - /// All disc IDs for the given query, null on error - public List ListSearchResults(string query) - { - List ids = new List(); - - // Strip quotes - query = query.Trim('"', '\''); - - // Special characters become dashes - query = query.Replace(' ', '-'); - query = query.Replace('/', '-'); - query = query.Replace('\\', '/'); - - // Lowercase is defined per language - query = query.ToLowerInvariant(); - - // Keep getting quicksearch pages until there are none left - try - { - int pageNumber = 1; - while (true) - { - List pageIds = CheckSingleSitePage(string.Format(quickSearchUrl, query, pageNumber++)); - ids.AddRange(pageIds); - if (pageIds.Count <= 1) - break; - } - } - catch (Exception ex) - { - Console.WriteLine($"An exception occurred while trying to log in: {ex}"); - return null; - } - - return ids; - } - - /// - /// List the disc IDs associated with the given user - /// - /// Username to check discs for - /// All disc IDs for the given user, null on error - public List ListUser(string username) - { - List ids = new List(); - - if (!LoggedIn) - { - Console.WriteLine("User download functionality is only available to Redump members"); - return ids; - } - - // Keep getting user pages until there are none left - try - { - int pageNumber = 1; - while (true) - { - List pageIds = CheckSingleSitePage(string.Format(userDumpsUrl, username, pageNumber++)); - ids.AddRange(pageIds); - if (pageIds.Count <= 1) - break; - } - } - catch (Exception ex) - { - Console.WriteLine($"An exception occurred while trying to log in: {ex}"); - return null; - } - - return ids; - } - - #endregion - - #region Single Page Helpers - - /// - /// Process a Redump site page as a list of possible IDs or disc page - /// - /// Base URL to download using - /// List of IDs from the page, empty on error - private List CheckSingleSitePage(string url) - { - List ids = new List(); - var dumpsPage = DownloadString(url); - - // If we have no dumps left - if (dumpsPage.Contains("No discs found.")) - return ids; - - // If we have a single disc page already - if (dumpsPage.Contains("Download:")) - { - var value = Regex.Match(dumpsPage, @"/disc/(\d+)/sfv/").Groups[1].Value; - if (int.TryParse(value, out int id)) - ids.Add(id); - - return ids; - } - - // Otherwise, traverse each dump on the page - var matches = discRegex.Matches(dumpsPage); - foreach (Match match in matches) - { - try - { - if (int.TryParse(match.Groups[1].Value, out int value)) - ids.Add(value); - } - catch (Exception ex) - { - Console.WriteLine($"An exception has occurred: {ex}"); - continue; - } - } - - return ids; - } - - /// - /// Process a Redump site page as a list of possible IDs or disc page - /// - /// Base URL to download using - /// Output directory to save data to - /// True to return on first error, false otherwise - /// True if the page could be downloaded, false otherwise - private bool CheckSingleSitePage(string url, string outDir, bool failOnSingle) - { - var dumpsPage = DownloadString(url); - - // If we have no dumps left - if (dumpsPage.Contains("No discs found.")) - return false; - - // If we have a single disc page already - if (dumpsPage.Contains("Download:")) - { - var value = Regex.Match(dumpsPage, @"/disc/(\d+)/sfv/").Groups[1].Value; - if (int.TryParse(value, out int id)) - { - bool downloaded = DownloadSingleSiteID(id, outDir, false); - if (!downloaded && failOnSingle) - return false; - } - - return false; - } - - // Otherwise, traverse each dump on the page - var matches = discRegex.Matches(dumpsPage); - foreach (Match match in matches) - { - try - { - if (int.TryParse(match.Groups[1].Value, out int value)) - { - bool downloaded = DownloadSingleSiteID(value, outDir, false); - if (!downloaded && failOnSingle) - return false; - } - } - catch (Exception ex) - { - Console.WriteLine($"An exception has occurred: {ex}"); - continue; - } - } - - return true; - } - - /// - /// Process a Redump WIP page as a list of possible IDs or disc page - /// - /// RedumpWebClient to access the packs - /// List of IDs from the page, empty on error - private List CheckSingleWIPPage(string url) - { - List ids = new List(); - var dumpsPage = DownloadString(url); - - // If we have no dumps left - if (dumpsPage.Contains("No discs found.")) - return ids; - - // Otherwise, traverse each dump on the page - var matches = newDiscRegex.Matches(dumpsPage); - foreach (Match match in matches) - { - try - { - if (int.TryParse(match.Groups[2].Value, out int value)) - ids.Add(value); - } - catch (Exception ex) - { - Console.WriteLine($"An exception has occurred: {ex}"); - continue; - } - } - - return ids; - } - - /// - /// Process a Redump WIP page as a list of possible IDs or disc page - /// - /// RedumpWebClient to access the packs - /// Output directory to save data to - /// True to return on first error, false otherwise - /// True if the page could be downloaded, false otherwise - private bool CheckSingleWIPPage(string url, string outDir, bool failOnSingle) - { - var dumpsPage = DownloadString(url); - - // If we have no dumps left - if (dumpsPage.Contains("No discs found.")) - return false; - - // Otherwise, traverse each dump on the page - var matches = newDiscRegex.Matches(dumpsPage); - foreach (Match match in matches) - { - try - { - if (int.TryParse(match.Groups[2].Value, out int value)) - { - bool downloaded = DownloadSingleWIPID(value, outDir, false); - if (!downloaded && failOnSingle) - return false; - } - } - catch (Exception ex) - { - Console.WriteLine($"An exception has occurred: {ex}"); - continue; - } - } - - return true; - } - - #endregion - - #region Download Helpers - - /// - /// Download a single pack - /// - /// Base URL to download using - /// System to download packs for - /// Byte array containing the downloaded pack, null on error - private byte[] DownloadSinglePack(string url, RedumpSystem? system) - { - try - { - return DownloadData(string.Format(url, system.ShortName())); - } - catch (Exception ex) - { - Console.WriteLine($"An exception has occurred: {ex}"); - return null; - } - } - - /// - /// Download a single pack - /// - /// Base URL to download using - /// System to download packs for - /// Output directory to save data to - /// Named subfolder for the pack, used optionally - private void DownloadSinglePack(string url, RedumpSystem? system, string outDir, string subfolder) - { - try - { - string tempfile = Path.Combine(outDir, "tmp" + Guid.NewGuid().ToString()); - DownloadFile(string.Format(url, system.ShortName()), tempfile); - MoveOrDelete(tempfile, GetLastFilename(), outDir, subfolder); - } - catch (Exception ex) - { - Console.WriteLine($"An exception has occurred: {ex}"); - } - } - - /// - /// Download an individual site ID data, if possible - /// - /// Redump disc ID to retrieve - /// String containing the page contents if successful, null on error - private string DownloadSingleSiteID(int id) - { - string paddedId = id.ToString().PadLeft(5, '0'); - Console.WriteLine($"Processing ID: {paddedId}"); - try - { - string discPage = DownloadString(string.Format(discPageUrl, +id)); - if (discPage.Contains($"Disc with ID \"{id}\" doesn't exist")) - { - Console.WriteLine($"ID {paddedId} could not be found!"); - return null; - } - - Console.WriteLine($"ID {paddedId} has been successfully downloaded"); - return discPage; - } - catch (Exception ex) - { - Console.WriteLine($"An exception has occurred: {ex}"); - return null; - } - } - - /// - /// Download an individual site ID data, if possible - /// - /// Redump disc ID to retrieve - /// Output directory to save data to - /// True to rename deleted entries, false otherwise - /// True if all data was downloaded, false otherwise - private bool DownloadSingleSiteID(int id, string outDir, bool rename) - { - string paddedId = id.ToString().PadLeft(5, '0'); - string paddedIdDir = Path.Combine(outDir, paddedId); - Console.WriteLine($"Processing ID: {paddedId}"); - try - { - string discPage = DownloadString(string.Format(discPageUrl, +id)); - if (discPage.Contains($"Disc with ID \"{id}\" doesn't exist")) - { - try - { - if (rename) - { - if (Directory.Exists(paddedIdDir) && rename) - Directory.Move(paddedIdDir, paddedIdDir + "-deleted"); - else - Directory.CreateDirectory(paddedIdDir + "-deleted"); - } - } - catch { } - - Console.WriteLine($"ID {paddedId} could not be found!"); - return false; - } - - // Check if the page has been updated since the last time it was downloaded, if possible - if (File.Exists(Path.Combine(paddedIdDir, "disc.html"))) - { - // Read in the cached file - var oldDiscPage = File.ReadAllText(Path.Combine(paddedIdDir, "disc.html")); - - // Check for the last modified date in both pages - var oldResult = lastModifiedRegex.Match(oldDiscPage); - var newResult = lastModifiedRegex.Match(discPage); - - // If both pages contain the same modified date, skip it - if (oldResult.Success && newResult.Success && oldResult.Groups[1].Value == newResult.Groups[1].Value) - { - Console.WriteLine($"ID {paddedId} has not been changed since last download"); - return false; - } - - // If neither page contains a modified date, skip it - else if (!oldResult.Success && !newResult.Success) - { - Console.WriteLine($"ID {paddedId} has not been changed since last download"); - return false; - } - } - - // Create ID subdirectory - Directory.CreateDirectory(paddedIdDir); - - // View Edit History - if (discPage.Contains($" - /// Download an individual WIP ID data, if possible - /// - /// Redump WIP disc ID to retrieve - /// String containing the page contents if successful, null on error - private string DownloadSingleWIPID(int id) - { - string paddedId = id.ToString().PadLeft(5, '0'); - Console.WriteLine($"Processing ID: {paddedId}"); - try - { - string discPage = DownloadString(string.Format(wipDiscPageUrl, +id)); - if (discPage.Contains($"System \"{id}\" doesn't exist")) - { - Console.WriteLine($"ID {paddedId} could not be found!"); - return null; - } - - Console.WriteLine($"ID {paddedId} has been successfully downloaded"); - return discPage; - } - catch (Exception ex) - { - Console.WriteLine($"An exception has occurred: {ex}"); - return null; - } - } - - /// - /// Download an individual WIP ID data, if possible - /// - /// Redump WIP disc ID to retrieve - /// Output directory to save data to - /// True to rename deleted entries, false otherwise - /// True if all data was downloaded, false otherwise - private bool DownloadSingleWIPID(int id, string outDir, bool rename) - { - string paddedId = id.ToString().PadLeft(5, '0'); - string paddedIdDir = Path.Combine(outDir, paddedId); - Console.WriteLine($"Processing ID: {paddedId}"); - try - { - string discPage = DownloadString(string.Format(wipDiscPageUrl, +id)); - if (discPage.Contains($"System \"{id}\" doesn't exist")) - { - try - { - if (rename) - { - if (Directory.Exists(paddedIdDir) && rename) - Directory.Move(paddedIdDir, paddedIdDir + "-deleted"); - else - Directory.CreateDirectory(paddedIdDir + "-deleted"); - } - } - catch { } - - Console.WriteLine($"ID {paddedId} could not be found!"); - return false; - } - - // Check if the page has been updated since the last time it was downloaded, if possible - if (File.Exists(Path.Combine(paddedIdDir, "disc.html"))) - { - // Read in the cached file - var oldDiscPage = File.ReadAllText(Path.Combine(paddedIdDir, "disc.html")); - - // Check for the full match ID in both pages - var oldResult = fullMatchRegex.Match(oldDiscPage); - var newResult = fullMatchRegex.Match(discPage); - - // If both pages contain the same ID, skip it - if (oldResult.Success && newResult.Success && oldResult.Groups[1].Value == newResult.Groups[1].Value) - { - Console.WriteLine($"ID {paddedId} has not been changed since last download"); - return false; - } - - // If neither page contains an ID, skip it - else if (!oldResult.Success && !newResult.Success) - { - Console.WriteLine($"ID {paddedId} has not been changed since last download"); - return false; - } - } - - // Create ID subdirectory - Directory.CreateDirectory(paddedIdDir); - - // HTML - using (var discStreamWriter = File.CreateText(Path.Combine(paddedIdDir, "disc.html"))) - { - discStreamWriter.Write(discPage); - } - - Console.WriteLine($"ID {paddedId} has been successfully downloaded"); - return true; - } - catch (Exception ex) - { - Console.WriteLine($"An exception has occurred: {ex}"); - return false; - } - } - - #endregion - - #region Internal Helpers - - /// - /// Download a set of packs - /// - /// Base URL to download using - /// Systems to download packs for - /// Name of the pack that is downloading - private Dictionary DownloadPacks(string url, RedumpSystem?[] systems, string title) - { - var packsDictionary = new Dictionary(); - - // If we didn't have credentials - if (!LoggedIn) - systems = systems.Where(s => !Extras.BannedSystems.Contains(s)).ToArray(); - - Console.WriteLine($"Downloading {title}"); - foreach (var system in systems) - { - Console.Write($"\r{system.LongName()}{new string(' ', Console.BufferWidth - system.LongName().Length - 1)}"); - byte[] pack = DownloadSinglePack(url, system); - if (pack != null) - packsDictionary.Add(system, pack); - } - - Console.Write($"\rComplete!{new string(' ', Console.BufferWidth - 10)}"); - Console.WriteLine(); - - return packsDictionary; - } - - /// - /// Download a set of packs - /// - /// Base URL to download using - /// Systems to download packs for - /// Name of the pack that is downloading - /// Output directory to save data to - /// Named subfolder for the pack, used optionally - private void DownloadPacks(string url, RedumpSystem?[] systems, string title, string outDir, string subfolder) - { - // If we didn't have credentials - if (!LoggedIn) - systems = systems.Where(s => !Extras.BannedSystems.Contains(s)).ToArray(); - - Console.WriteLine($"Downloading {title}"); - foreach (var system in systems) - { - Console.Write($"\r{system.LongName()}{new string(' ', Console.BufferWidth - system.LongName().Length - 1)}"); - DownloadSinglePack(url, system, outDir, subfolder); - } - - Console.Write($"\rComplete!{new string(' ', Console.BufferWidth - 10)}"); - Console.WriteLine(); - } - - /// - /// Move a tempfile to a new name unless it aleady exists, in which case, delete the tempfile - /// - /// Path to existing temporary file - /// Path to new output file - /// Output directory to save data to - /// Optional subfolder to append to the path - private void MoveOrDelete(string tempfile, string newfile, string outDir, string subfolder) - { - if (!string.IsNullOrWhiteSpace(newfile)) - { - if (!string.IsNullOrWhiteSpace(subfolder)) - { - if (!Directory.Exists(Path.Combine(outDir, subfolder))) - Directory.CreateDirectory(Path.Combine(outDir, subfolder)); - - newfile = Path.Combine(subfolder, newfile); - } - - if (File.Exists(Path.Combine(outDir, newfile))) - File.Delete(tempfile); - else - File.Move(tempfile, Path.Combine(outDir, newfile)); - } - else - File.Delete(tempfile); - } - - #endregion - } -} diff --git a/MPF.Library/UmdImageCreator/Parameters.cs b/MPF.Library/UmdImageCreator/Parameters.cs index 0a5c306b..fb0c79ef 100644 --- a/MPF.Library/UmdImageCreator/Parameters.cs +++ b/MPF.Library/UmdImageCreator/Parameters.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using MPF.Data; +using RedumpLib.Data; namespace MPF.UmdImageCreator { @@ -74,10 +75,10 @@ namespace MPF.UmdImageCreator info.SizeAndChecksums.SHA1 = sha1; } - if (GetUMDAuxInfo(basePath + "_disc.txt", out string title, out RedumpDiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize)) + if (GetUMDAuxInfo(basePath + "_disc.txt", out string title, out DiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize)) { info.CommonDiscInfo.Title = title ?? ""; - info.CommonDiscInfo.Category = umdcat ?? RedumpDiscCategory.Games; + info.CommonDiscInfo.Category = umdcat ?? DiscCategory.Games; info.VersionAndEditions.Version = umdversion ?? ""; info.SizeAndChecksums.Size = umdsize; @@ -169,7 +170,7 @@ namespace MPF.UmdImageCreator /// /// _disc.txt file location /// True on successful extraction of info, false otherwise - private static bool GetUMDAuxInfo(string disc, out string title, out RedumpDiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize) + private static bool GetUMDAuxInfo(string disc, out string title, out DiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize) { title = null; umdcat = null; umdversion = null; umdlayer = null; umdsize = -1; diff --git a/MPF.Library/Utilities/Tools.cs b/MPF.Library/Utilities/Tools.cs index 763dc8fd..79b89c5f 100644 --- a/MPF.Library/Utilities/Tools.cs +++ b/MPF.Library/Utilities/Tools.cs @@ -1,6 +1,8 @@ using System; +using System.Net; using System.Reflection; -using MPF.Redump; +using Newtonsoft.Json.Linq; +using RedumpLib.Web; namespace MPF.Utilities { @@ -87,19 +89,16 @@ namespace MPF.Utilities string version = $"{assemblyVersion.Major}.{assemblyVersion.Minor}" + (assemblyVersion.Build != 0 ? $".{assemblyVersion.Build}" : string.Empty); // Get the latest tag from GitHub - using (var client = new RedumpWebClient()) - { - (string tag, string url) = client.GetRemoteVersionAndUrl(); - bool different = version != tag; + (string tag, string url) = GetRemoteVersionAndUrl(); + bool different = version != tag; - string message = $"Local version: {version}" - + $"{Environment.NewLine}Remote version: {tag}" - + (different - ? $"{Environment.NewLine}The update URL has been added copied to your clipboard" - : $"{Environment.NewLine}You have the newest version!"); + string message = $"Local version: {version}" + + $"{Environment.NewLine}Remote version: {tag}" + + (different + ? $"{Environment.NewLine}The update URL has been added copied to your clipboard" + : $"{Environment.NewLine}You have the newest version!"); - return (different, message, url); - } + return (different, message, url); } /// @@ -111,6 +110,26 @@ namespace MPF.Utilities return assemblyVersion.InformationalVersion; } + /// + /// Get the latest version of MPF from GitHub and the release URL + /// + private static (string tag, string url) GetRemoteVersionAndUrl() + { + using (WebClient wc = new WebClient()) + { + wc.Headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0"; + + // TODO: Figure out a better way than having this hardcoded... + string url = "https://api.github.com/repos/SabreTools/MPF/releases/latest"; + string latestReleaseJsonString = wc.DownloadString(url); + var latestReleaseJson = JObject.Parse(latestReleaseJsonString); + string latestTag = latestReleaseJson["tag_name"].ToString(); + string releaseUrl = latestReleaseJson["html_url"].ToString(); + + return (latestTag, releaseUrl); + } + } + #endregion } } diff --git a/MPF.Library/Utilities/Validators.cs b/MPF.Library/Utilities/Validators.cs index 552fcf96..024c4319 100644 --- a/MPF.Library/Utilities/Validators.cs +++ b/MPF.Library/Utilities/Validators.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Management; using System.Threading.Tasks; using BurnOutSharp; +using MPF.Converters; using MPF.Data; #if NET_FRAMEWORK using IMAPI2; @@ -736,7 +737,7 @@ namespace MPF.Utilities // Get all supported drive types var drives = DriveInfo.GetDrives() .Where(d => desiredDriveTypes.Contains(d.DriveType)) - .Select(d => new Drive(Converters.ToInternalDriveType(d.DriveType), d)) + .Select(d => new Drive(EnumConverter.ToInternalDriveType(d.DriveType), d)) .ToList(); // Get the floppy drives and set the flag from removable diff --git a/MPF.Test/Utilities/ConvertersTest.cs b/MPF.Test/Converters/EnumConverterTest.cs similarity index 86% rename from MPF.Test/Utilities/ConvertersTest.cs rename to MPF.Test/Converters/EnumConverterTest.cs index b098fef7..50d49d6d 100644 --- a/MPF.Test/Utilities/ConvertersTest.cs +++ b/MPF.Test/Converters/EnumConverterTest.cs @@ -76,28 +76,6 @@ namespace MPF.Test.Utilities Assert.Equal(expected, actual); } - [Theory] - [InlineData(MediaType.CDROM, "CD-ROM")] - [InlineData(MediaType.LaserDisc, "LD-ROM / LV-ROM")] - [InlineData(MediaType.NONE, "Unknown")] - public void MediaTypeToStringTest(MediaType? mediaType, string expected) - { - string actual = Converters.LongName(mediaType); - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData(KnownSystem.MicrosoftXBOX, "Microsoft XBOX")] - [InlineData(KnownSystem.NECPC88, "NEC PC-88")] - [InlineData(KnownSystem.KonamiPython, "Konami Python")] - [InlineData(KnownSystem.HDDVDVideo, "HD-DVD-Video")] - [InlineData(KnownSystem.NONE, "Unknown")] - public void KnownSystemToStringTest(KnownSystem? knownSystem, string expected) - { - string actual = Converters.LongName(knownSystem); - Assert.Equal(expected, actual); - } - [Theory] [MemberData(nameof(KnownSystems))] public void KnownSystemHasValidCategory(KnownSystemComboBoxItem system) diff --git a/MPF.Test/Utilities/KnownSystemExtensionsTest.cs b/MPF.Test/Converters/KnownSystemExtensionsTest.cs similarity index 66% rename from MPF.Test/Utilities/KnownSystemExtensionsTest.cs rename to MPF.Test/Converters/KnownSystemExtensionsTest.cs index a2049e5c..4393118e 100644 --- a/MPF.Test/Utilities/KnownSystemExtensionsTest.cs +++ b/MPF.Test/Converters/KnownSystemExtensionsTest.cs @@ -1,12 +1,25 @@ using System; +using MPF.Converters; using MPF.Data; using MPF.Utilities; using Xunit; -namespace MPF.Test.Utilities +namespace MPF.Test.Converters { public class KnownSystemExtensionsTest { + [Theory] + [InlineData(KnownSystem.MicrosoftXBOX, "Microsoft XBOX")] + [InlineData(KnownSystem.NECPC88, "NEC PC-88")] + [InlineData(KnownSystem.KonamiPython, "Konami Python")] + [InlineData(KnownSystem.HDDVDVideo, "HD-DVD-Video")] + [InlineData(KnownSystem.NONE, "Unknown")] + public void KnownSystemToStringTest(KnownSystem? knownSystem, string expected) + { + string actual = EnumConverter.LongName(knownSystem); + Assert.Equal(expected, actual); + } + [Fact] public void IsMarkerTest() { diff --git a/MPF.Test/Utilities/MediaTypeExtensionsTest.cs b/MPF.Test/Converters/MediaTypeExtensionsTest.cs similarity index 75% rename from MPF.Test/Utilities/MediaTypeExtensionsTest.cs rename to MPF.Test/Converters/MediaTypeExtensionsTest.cs index aee60e63..43b72e86 100644 --- a/MPF.Test/Utilities/MediaTypeExtensionsTest.cs +++ b/MPF.Test/Converters/MediaTypeExtensionsTest.cs @@ -1,11 +1,22 @@ -using MPF.Data; +using MPF.Converters; +using MPF.Data; using MPF.Utilities; using Xunit; -namespace MPF.Test.Utilities +namespace MPF.Test.Converters { public class MediaTypeExtensionsTest { + [Theory] + [InlineData(MediaType.CDROM, "CD-ROM")] + [InlineData(MediaType.LaserDisc, "LD-ROM / LV-ROM")] + [InlineData(MediaType.NONE, "Unknown")] + public void MediaTypeToStringTest(MediaType? mediaType, string expected) + { + string actual = EnumConverter.LongName(mediaType); + Assert.Equal(expected, actual); + } + [Theory] [InlineData(MediaType.CDROM, "CD-ROM")] [InlineData(MediaType.LaserDisc, "LD-ROM / LV-ROM")] diff --git a/MPF.sln b/MPF.sln index e42796ae..22b0e7f0 100644 --- a/MPF.sln +++ b/MPF.sln @@ -18,6 +18,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedumpLib", "RedumpLib\RedumpLib.csproj", "{13574913-A426-4644-9955-F49AD0876E5F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -40,6 +42,10 @@ Global {8CFDE289-E171-4D49-A40D-5293265C1253}.Debug|Any CPU.Build.0 = Debug|Any CPU {8CFDE289-E171-4D49-A40D-5293265C1253}.Release|Any CPU.ActiveCfg = Release|Any CPU {8CFDE289-E171-4D49-A40D-5293265C1253}.Release|Any CPU.Build.0 = Release|Any CPU + {13574913-A426-4644-9955-F49AD0876E5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {13574913-A426-4644-9955-F49AD0876E5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {13574913-A426-4644-9955-F49AD0876E5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {13574913-A426-4644-9955-F49AD0876E5F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MPF/ComboBoxItems/Element.cs b/MPF/ComboBoxItems/Element.cs index fb8c3e60..e4a8bbd0 100644 --- a/MPF/ComboBoxItems/Element.cs +++ b/MPF/ComboBoxItems/Element.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using MPF.Converters; using MPF.Utilities; namespace MPF @@ -22,7 +23,7 @@ namespace MPF public static implicit operator T? (Element item) => item?.Data; /// - public string Name => Converters.GetLongName(Data); + public string Name => EnumConverter.GetLongName(Data); public override string ToString() => Name; diff --git a/MPF/ComboBoxItems/KnownSystemComboBoxItem.cs b/MPF/ComboBoxItems/KnownSystemComboBoxItem.cs index 7e74d632..5bf1bb97 100644 --- a/MPF/ComboBoxItems/KnownSystemComboBoxItem.cs +++ b/MPF/ComboBoxItems/KnownSystemComboBoxItem.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using MPF.Converters; using MPF.Data; using MPF.Utilities; @@ -24,9 +25,9 @@ namespace MPF get { if (IsHeader) - return "---------- " + Converters.GetLongName(Data as KnownSystemCategory?) + " ----------"; + return "---------- " + EnumConverter.GetLongName(Data as KnownSystemCategory?) + " ----------"; else - return Converters.GetLongName(Data as KnownSystem?); + return EnumConverter.GetLongName(Data as KnownSystem?); } } diff --git a/MPF/MPF.csproj b/MPF/MPF.csproj index 5806bba8..b2c6729c 100644 --- a/MPF/MPF.csproj +++ b/MPF/MPF.csproj @@ -51,6 +51,7 @@ {51ab0928-13f9-44bf-a407-b6957a43a056} MPF.Library + diff --git a/MPF/ViewModels/DiscInformationViewModel.cs b/MPF/ViewModels/DiscInformationViewModel.cs index ce1c7056..58a3f2aa 100644 --- a/MPF/ViewModels/DiscInformationViewModel.cs +++ b/MPF/ViewModels/DiscInformationViewModel.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Windows; using MPF.Data; using MPF.Windows; +using RedumpLib.Data; namespace MPF.GUI.ViewModels { @@ -27,22 +28,22 @@ namespace MPF.GUI.ViewModels /// /// List of available disc categories /// - public List> Categories { get; private set; } = Element.GenerateElements().ToList(); + public List> Categories { get; private set; } = Element.GenerateElements().ToList(); /// /// List of available regions /// - public List> Regions { get; private set; } = Element.GenerateElements().ToList(); + public List> Regions { get; private set; } = Element.GenerateElements().ToList(); /// /// List of available languages /// - public List> Languages { get; private set; } = Element.GenerateElements().ToList(); + public List> Languages { get; private set; } = Element.GenerateElements().ToList(); /// /// List of available languages /// - public List> LanguageSelections { get; private set; } = Element.GenerateElements().ToList(); + public List> LanguageSelections { get; private set; } = Element.GenerateElements().ToList(); #endregion @@ -234,11 +235,11 @@ namespace MPF.GUI.ViewModels /// public void Save() { - SubmissionInfo.CommonDiscInfo.Category = (Parent.CategoryComboBox.SelectedItem as Element)?.Value ?? RedumpDiscCategory.Games; - SubmissionInfo.CommonDiscInfo.Region = (Parent.RegionComboBox.SelectedItem as Element)?.Value ?? RedumpRegion.World; + SubmissionInfo.CommonDiscInfo.Category = (Parent.CategoryComboBox.SelectedItem as Element)?.Value ?? DiscCategory.Games; + SubmissionInfo.CommonDiscInfo.Region = (Parent.RegionComboBox.SelectedItem as Element)?.Value ?? Region.World; SubmissionInfo.CommonDiscInfo.Languages = Languages.Where(l => l.IsChecked).Select(l => l?.Value).ToArray(); if (!SubmissionInfo.CommonDiscInfo.Languages.Any()) - SubmissionInfo.CommonDiscInfo.Languages = new RedumpLanguage?[] { null }; + SubmissionInfo.CommonDiscInfo.Languages = new Language?[] { null }; SubmissionInfo.CommonDiscInfo.LanguageSelection = LanguageSelections.Where(ls => ls.IsChecked).Select(ls => ls?.Value).ToArray(); } diff --git a/MPF/ViewModels/MainViewModel.cs b/MPF/ViewModels/MainViewModel.cs index 441d801b..9899561c 100644 --- a/MPF/ViewModels/MainViewModel.cs +++ b/MPF/ViewModels/MainViewModel.cs @@ -7,6 +7,7 @@ using System.Windows.Controls; using System.Windows.Media; using WinForms = System.Windows.Forms; using BurnOutSharp; +using MPF.Converters; using MPF.Data; using MPF.Utilities; using MPF.Windows; @@ -735,7 +736,7 @@ namespace MPF.GUI.ViewModels { App.Logger.VerboseLog($"Trying to detect system for drive {Drives[App.Instance.DriveLetterComboBox.SelectedIndex].Letter}.. "); var currentSystem = Validators.GetKnownSystem(Drives[App.Instance.DriveLetterComboBox.SelectedIndex], App.Options.DefaultSystem); - App.Logger.VerboseLogLn(currentSystem == KnownSystem.NONE ? "unable to detect." : ("detected " + Converters.GetLongName(currentSystem) + ".")); + App.Logger.VerboseLogLn(currentSystem == KnownSystem.NONE ? "unable to detect." : ("detected " + EnumConverter.GetLongName(currentSystem) + ".")); if (currentSystem != KnownSystem.NONE) { @@ -946,7 +947,7 @@ namespace MPF.GUI.ViewModels if (index != -1) App.Instance.MediaTypeComboBox.SelectedIndex = index; else - App.Instance.StatusLabel.Content = $"Disc of type '{Converters.LongName(CurrentMediaType)}' found, but the current system does not support it!"; + App.Instance.StatusLabel.Content = $"Disc of type '{EnumConverter.LongName(CurrentMediaType)}' found, but the current system does not support it!"; // Ensure the UI gets updated App.Instance.UpdateLayout(); diff --git a/MPF/ViewModels/OptionsViewModel.cs b/MPF/ViewModels/OptionsViewModel.cs index 1b3b8330..4cfc0585 100644 --- a/MPF/ViewModels/OptionsViewModel.cs +++ b/MPF/ViewModels/OptionsViewModel.cs @@ -5,8 +5,8 @@ using System.Linq; using System.Windows; using System.Windows.Forms; using MPF.Data; -using MPF.Redump; using MPF.Windows; +using RedumpLib.Web; using WPFCustomMessageBox; namespace MPF.GUI.ViewModels diff --git a/RedumpLib/Attributes/AttributeHelper.cs b/RedumpLib/Attributes/AttributeHelper.cs new file mode 100644 index 00000000..e4f87eca --- /dev/null +++ b/RedumpLib/Attributes/AttributeHelper.cs @@ -0,0 +1,48 @@ +using System; +using System.Linq; + +namespace RedumpLib.Attributes +{ + public static class AttributeHelper + { + /// + /// Get the HumanReadableAttribute from a supported value + /// + /// Value to use + /// HumanReadableAttribute attached to the value + public static HumanReadableAttribute GetAttribute(T value) + { + // Null value in, null value out + if (value == null) + return null; + + // Current enumeration type + var enumType = typeof(T); + if (Nullable.GetUnderlyingType(enumType) != null) + enumType = Nullable.GetUnderlyingType(enumType); + + // If the value returns a null on ToString, just return null + string valueStr = value.ToString(); + if (string.IsNullOrWhiteSpace(valueStr)) + return null; + + // Get the member info array + var memberInfos = enumType?.GetMember(valueStr); + if (memberInfos == null) + return null; + + // Get the enum value info from the array, if possible + var enumValueMemberInfo = memberInfos.FirstOrDefault(m => m.DeclaringType == enumType); + if (enumValueMemberInfo == null) + return null; + + // Try to get the relevant attribute + var attributes = enumValueMemberInfo.GetCustomAttributes(typeof(HumanReadableAttribute), true); + if (attributes == null) + return null; + + // Return the first attribute, if possible + return (HumanReadableAttribute)attributes.FirstOrDefault(); + } + } +} \ No newline at end of file diff --git a/RedumpLib/Attributes/HumanReadableAttribute.cs b/RedumpLib/Attributes/HumanReadableAttribute.cs new file mode 100644 index 00000000..74e50861 --- /dev/null +++ b/RedumpLib/Attributes/HumanReadableAttribute.cs @@ -0,0 +1,14 @@ +using System; + +namespace RedumpLib.Attributes +{ + /// + /// Generic attribute for human readable values + /// + public class HumanReadableAttribute : Attribute + { + public string LongName { get; set; } + + public string ShortName { get; set; } + } +} \ No newline at end of file diff --git a/RedumpLib/Attributes/SystemAttribute.cs b/RedumpLib/Attributes/SystemAttribute.cs new file mode 100644 index 00000000..94292af4 --- /dev/null +++ b/RedumpLib/Attributes/SystemAttribute.cs @@ -0,0 +1,48 @@ +namespace RedumpLib.Attributes +{ + /// + /// Attribute specifc to Redump System values + /// + public class SystemAttribute : HumanReadableAttribute + { + /// + /// System is restricted to dumpers + /// + public bool IsBanned { get; set; } = false; + + /// + /// System has a CUE pack + /// + public bool HasCues { get; set; } = false; + + /// + /// System has a DAT + /// + public bool HasDat { get; set; } = false; + + /// + /// System has a decrypted keys pack + /// + public bool HasDkeys { get; set; } = false; + + /// + /// System has a GDI pack + /// + public bool HasGdi { get; set; } = false; + + /// + /// System has a keys pack + /// + public bool HasKeys { get; set; } = false; + + /// + /// System has an LSD pack + /// + public bool HasLsd { get; set; } = false; + + /// + /// System has an SBI pack + /// + public bool HasSbi { get; set; } = false; + } +} \ No newline at end of file diff --git a/RedumpLib/Converters/DiscCategoryConverter.cs b/RedumpLib/Converters/DiscCategoryConverter.cs new file mode 100644 index 00000000..fe738241 --- /dev/null +++ b/RedumpLib/Converters/DiscCategoryConverter.cs @@ -0,0 +1,32 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using RedumpLib.Data; + +namespace RedumpLib.Converters +{ + /// + /// Serialize DiscCategory enum values + /// + public class DiscCategoryConverter : JsonConverter + { + public override bool CanRead { get { return false; } } + + public override DiscCategory?[] ReadJson(JsonReader reader, Type objectType, DiscCategory?[] existingValue, bool hasExistingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, DiscCategory?[] value, JsonSerializer serializer) + { + JArray array = new JArray(); + foreach (var val in value) + { + JToken t = JToken.FromObject(val.LongName() ?? string.Empty); + array.Add(t); + } + + array.WriteTo(writer); + } + } +} \ No newline at end of file diff --git a/RedumpLib/Converters/LanguageConverter.cs b/RedumpLib/Converters/LanguageConverter.cs new file mode 100644 index 00000000..c9819ac0 --- /dev/null +++ b/RedumpLib/Converters/LanguageConverter.cs @@ -0,0 +1,32 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using RedumpLib.Data; + +namespace RedumpLib.Converters +{ + /// + /// Serialize Language enum values + /// + public class LanguageConverter : JsonConverter + { + public override bool CanRead { get { return false; } } + + public override Language?[] ReadJson(JsonReader reader, Type objectType, Language?[] existingValue, bool hasExistingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, Language?[] value, JsonSerializer serializer) + { + JArray array = new JArray(); + foreach (var val in value) + { + JToken t = JToken.FromObject(val.ShortName() ?? string.Empty); + array.Add(t); + } + + array.WriteTo(writer); + } + } +} \ No newline at end of file diff --git a/RedumpLib/Converters/LanguageSelectionConverter.cs b/RedumpLib/Converters/LanguageSelectionConverter.cs new file mode 100644 index 00000000..24b0dee5 --- /dev/null +++ b/RedumpLib/Converters/LanguageSelectionConverter.cs @@ -0,0 +1,32 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using RedumpLib.Data; + +namespace RedumpLib.Converters +{ + /// + /// Serialize LanguageSelection enum values + /// + public class LanguageSelectionConverter : JsonConverter + { + public override bool CanRead { get { return false; } } + + public override LanguageSelection?[] ReadJson(JsonReader reader, Type objectType, LanguageSelection?[] existingValue, bool hasExistingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, LanguageSelection?[] value, JsonSerializer serializer) + { + JArray array = new JArray(); + foreach (var val in value) + { + JToken t = JToken.FromObject(val.LongName() ?? string.Empty); + array.Add(t); + } + + array.WriteTo(writer); + } + } +} \ No newline at end of file diff --git a/RedumpLib/Converters/RegionConverter.cs b/RedumpLib/Converters/RegionConverter.cs new file mode 100644 index 00000000..44f9a88a --- /dev/null +++ b/RedumpLib/Converters/RegionConverter.cs @@ -0,0 +1,26 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using RedumpLib.Data; + +namespace RedumpLib.Converters +{ + /// + /// Serialize Region enum values + /// + public class RegionConverter : JsonConverter + { + public override bool CanRead { get { return false; } } + + public override Region? ReadJson(JsonReader reader, Type objectType, Region? existingValue, bool hasExistingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, Region? value, JsonSerializer serializer) + { + JToken t = JToken.FromObject(value.ShortName() ?? string.Empty); + t.WriteTo(writer); + } + } +} \ No newline at end of file diff --git a/RedumpLib/Converters/SystemConverter.cs b/RedumpLib/Converters/SystemConverter.cs new file mode 100644 index 00000000..1c935de1 --- /dev/null +++ b/RedumpLib/Converters/SystemConverter.cs @@ -0,0 +1,26 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using RedumpLib.Data; + +namespace RedumpLib.Converters +{ + /// + /// Serialize RedumpSystem enum values + /// + public class SystemConverter : JsonConverter + { + public override bool CanRead { get { return false; } } + + public override RedumpSystem? ReadJson(JsonReader reader, Type objectType, RedumpSystem? existingValue, bool hasExistingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, RedumpSystem? value, JsonSerializer serializer) + { + JToken t = JToken.FromObject(value.ShortName() ?? string.Empty); + t.WriteTo(writer); + } + } +} \ No newline at end of file diff --git a/RedumpLib/Data/Constants.cs b/RedumpLib/Data/Constants.cs new file mode 100644 index 00000000..75afae0b --- /dev/null +++ b/RedumpLib/Data/Constants.cs @@ -0,0 +1,301 @@ +using System.Text.RegularExpressions; + +namespace RedumpLib.Data +{ + public static class Constants + { + // TODO: Add RegexOptions.Compiled + #region Regular Expressions + + /// + /// Regex matching the added field on a disc page + /// + public static Regex AddedRegex = new Regex(@"Added(.*?)"); + + /// + /// Regex matching the barcode field on a disc page + /// + public static Regex BarcodeRegex = new Regex(@"Barcode(.*?)"); + + /// + /// Regex matching the BCA field on a disc page + /// + public static Regex BcaRegex = new Regex(@"

BCA .*?/>

" + + "RowContentsASCII" + + "(?.*?)(?.*?)(?.*?)" + + "(?.*?)(?.*?)(?.*?)" + + "(?.*?)(?.*?)(?.*?)" + + "(?.*?)(?.*?)(?.*?)"); + + /// + /// Regex matching the category field on a disc page + /// + public static Regex CategoryRegex = new Regex(@"Category(.*?)"); + + /// + /// Regex matching the comments field on a disc page + /// + public static Regex CommentsRegex = new Regex(@"Comments(.*?)"); + + /// + /// Regex matching the contents field on a disc page + /// + public static Regex ContentsRegex = new Regex(@"Contents(.*?)"); + + /// + /// Regex matching individual disc links on a results page + /// + public static Regex DiscRegex = new Regex(@"
"); + + /// + /// Regex matching the disc number or letter field on a disc page + /// + public static Regex DiscNumberLetterRegex = new Regex(@"\((.*?)\)"); + + /// + /// Regex matching the dumpers on a disc page + /// + public static Regex DumpersRegex = new Regex(@""); + + /// + /// Regex matching the edition field on a disc page + /// + public static Regex EditionRegex = new Regex(@"Edition(.*?)"); + + /// + /// Regex matching the error count field on a disc page + /// + public static Regex ErrorCountRegex = new Regex(@"Errors count(.*?)"); + + /// + /// Regex matching the foreign title field on a disc page + /// + public static Regex ForeignTitleRegex = new Regex(@"

(.*?)

"); + + /// + /// Regex matching the "full match" ID list from a WIP disc page + /// + public static Regex FullMatchRegex = new Regex(@"full match ids: (.*?)"); + + /// + /// Regex matching the languages field on a disc page + /// + public static Regex LanguagesRegex = new Regex(@"\s*"); + + /// + /// Regex matching the last modified field on a disc page + /// + public static Regex LastModifiedRegex = new Regex(@"Last modified(.*?)"); + + /// + /// Regex matching the media field on a disc page + /// + public static Regex MediaRegex = new Regex(@"Media(.*?)"); + + /// + /// Regex matching individual WIP disc links on a results page + /// + public static Regex NewDiscRegex = new Regex(@"
"); + + /// + /// Regex matching the "partial match" ID list from a WIP disc page + /// + public static Regex PartialMatchRegex = new Regex(@"partial match ids: (.*?)"); + + /// + /// Regex matching the PVD field on a disc page + /// + public static Regex PvdRegex = new Regex(@"

Primary Volume Descriptor (PVD)

" + + @"Record / EntryContentsDateTimeGMT" + + @"Creation(?.*?)(?.*?)(?.*?)(?.*?)" + + @"Modification(?.*?)(?.*?)(?.*?)(?.*?)" + + @"Expiration(?.*?)(?.*?)(?.*?)(?.*?)" + + @"Effective(?.*?)(?.*?)(?.*?)(?.*?)"); + + /// + /// Regex matching the region field on a disc page + /// + public static Regex RegionRegex = new Regex(@"Region
"); + + /// + /// Regex matching a double-layer disc ringcode information + /// + public static Regex RingCodeDoubleRegex = new Regex(@""); // Varies based on available fields, like Addtional Mould + + /// + /// Regex matching a single-layer disc ringcode information + /// + public static Regex RingCodeSingleRegex = new Regex(@""); // Varies based on available fields, like Addtional Mould + + /// + /// Regex matching the serial field on a disc page + /// + public static Regex SerialRegex = new Regex(@"Serial(.*?)"); + + /// + /// Regex matching the system field on a disc page + /// + public static Regex SystemRegex = new Regex(@"System"); + + /// + /// Regex matching the title field on a disc page + /// + public static Regex TitleRegex = new Regex(@"

(.*?)

"); + + /// + /// Regex matching the current nonce token for login + /// + public static Regex TokenRegex = new Regex(@""); + + /// + /// Regex matching a single track on a disc page + /// + public static Regex TrackRegex = new Regex(@"(?.*?)(?.*?)(?.*?)(?.*?)(?.*?)(?.*?)(?.*?)(?.*?)(?.*?)"); + + /// + /// Regex matching the track count on a disc page + /// + public static Regex TrackCountRegex = new Regex(@"Number of tracks(.*?)"); + + /// + /// Regex matching the version field on a disc page + /// + public static Regex VersionRegex = new Regex(@"Version(.*?)"); + + /// + /// Regex matching the write offset field on a disc page + /// + public static Regex WriteOffsetRegex = new Regex(@"Write offset(.*?)"); + + #endregion + + #region URLs + + /// + /// Redump disc page URL template + /// + public const string DiscPageUrl = @"http://redump.org/disc/{0}/"; + + /// + /// Redump last modified search URL + /// + public const string LastModifiedUrl = @"http://redump.org/discs/sort/modified/dir/desc?page={0}"; + + /// + /// Redump login page URL + /// + public const string LoginUrl = "http://forum.redump.org/login/"; + + /// + /// Redump CUE pack URL template + /// + public const string PackCuesUrl = @"http://redump.org/cues/{0}/"; + + /// + /// Redump DAT pack URL template + /// + public const string PackDatfileUrl = @"http://redump.org/datfile/{0}/"; + + /// + /// Redump DKEYS pack URL template + /// + public const string PackDkeysUrl = @"http://redump.org/dkeys/{0}/"; + + /// + /// Redump GDI pack URL template + /// + public const string PackGdiUrl = @"http://redump.org/gdi/{0}/"; + + /// + /// Redump KEYS pack URL template + /// + public const string PackKeysUrl = @"http://redump.org/keys/{0}/"; + + /// + /// Redump LSD pack URL template + /// + public const string PackLsdUrl = @"http://redump.org/lsd/{0}/"; + + /// + /// Redump SBI pack URL template + /// + public const string PackSbiUrl = @"http://redump.org/sbi/{0}/"; + + /// + /// Redump quicksearch URL template + /// + public const string QuickSearchUrl = @"http://redump.org/discs/quicksearch/{0}/?page={1}"; + + /// + /// Redump user dumps URL template + /// + public const string UserDumpsUrl = @"http://redump.org/discs/dumper/{0}/?page={1}"; + + /// + /// Redump WIP disc page URL template + /// + public const string WipDiscPageUrl = @"http://redump.org/newdisc/{0}/"; + + /// + /// Redump WIP dumps queue URL + /// + public const string WipDumpsUrl = @"http://redump.org/discs-wip/"; + + #endregion + + #region URL Extensions + + /// + /// Changes page subpath + /// + public const string ChangesExt = "changes/"; + + /// + /// Cuesheet download subpath + /// + public const string CueExt = "cue/"; + + /// + /// Edit page subpath + /// + public const string EditExt = "edit/"; + + /// + /// GDI download subpath + /// + public const string GdiExt = "gdi/"; + + /// + /// Key download subpath + /// + public const string KeyExt = "key/"; + + /// + /// LSD download subpath + /// + public const string LsdExt = "lsd/"; + + /// + /// MD5 download subpath + /// + public const string Md5Ext = "md5/"; + + /// + /// SBI download subpath + /// + public const string SbiExt = "sbi/"; + + /// + /// SFV download subpath + /// + public const string SfvExt = "sfv/"; + + /// + /// SHA1 download subpath + /// + public const string Sha1Ext = "sha1/"; + + #endregion + + } +} \ No newline at end of file diff --git a/RedumpLib/Data/Enumerations.cs b/RedumpLib/Data/Enumerations.cs new file mode 100644 index 00000000..e2d998bf --- /dev/null +++ b/RedumpLib/Data/Enumerations.cs @@ -0,0 +1,720 @@ +using RedumpLib.Attributes; + +namespace RedumpLib.Data +{ + /// + /// List of all disc categories + /// + public enum DiscCategory + { + [HumanReadable(LongName = "Games")] + Games = 1, + + [HumanReadable(LongName = "Demos")] + Demos = 2, + + [HumanReadable(LongName = "Video")] + Video = 3, + + [HumanReadable(LongName = "Audio")] + Audio = 4, + + [HumanReadable(LongName = "Multimedia")] + Multimedia = 5, + + [HumanReadable(LongName = "Applications")] + Applications = 6, + + [HumanReadable(LongName = "Coverdiscs")] + Coverdiscs = 7, + + [HumanReadable(LongName = "Educational")] + Educational = 8, + + [HumanReadable(LongName = "Bonus Discs")] + BonusDiscs = 9, + + [HumanReadable(LongName = "Preproduction")] + Preproduction = 10, + + [HumanReadable(LongName = "Add-Ons")] + AddOns = 11, + } + + /// + /// Dump status + /// + public enum DumpStatus + { + BadDumpRed = 2, + PossibleBadDumpYellow = 3, + OriginalMediaBlue = 4, + TwoOrMoHumanReadablesGreen = 5, + } + + /// + /// Determines what download type to initate + /// + public enum Feature + { + NONE, + Site, + WIP, + Packs, + User, + Quicksearch, + } + + /// + /// List of all disc langauges + /// + public enum Language + { + [HumanReadable(LongName = "Afrikaans", ShortName = "afr")] + Afrikaans, + + [HumanReadable(LongName = "Albanian", ShortName = "sqi")] + Albanian, + + [HumanReadable(LongName = "Arabic", ShortName = "ara")] + Arabic, + + [HumanReadable(LongName = "Basque", ShortName = "baq")] + Basque, + + [HumanReadable(LongName = "Bulgarian", ShortName = "bul")] + Bulgarian, + + [HumanReadable(LongName = "Catalan", ShortName = "cat")] + Catalan, + + [HumanReadable(LongName = "Chinese", ShortName = "chi")] + Chinese, + + [HumanReadable(LongName = "Croatian", ShortName = "hrv")] + Croatian, + + [HumanReadable(LongName = "Czech", ShortName = "cze")] + Czech, + + [HumanReadable(LongName = "Danish", ShortName = "dan")] + Danish, + + [HumanReadable(LongName = "Dutch", ShortName = "dut")] + Dutch, + + [HumanReadable(LongName = "English", ShortName = "eng")] + English, + + [HumanReadable(LongName = "Estonian", ShortName = "est")] + Estonian, + + [HumanReadable(LongName = "Finnish", ShortName = "fin")] + Finnish, + + [HumanReadable(LongName = "French", ShortName = "fre")] + French, + + [HumanReadable(LongName = "Gaelic", ShortName = "gla")] + Gaelic, + + [HumanReadable(LongName = "German", ShortName = "ger")] + German, + + [HumanReadable(LongName = "Greek", ShortName = "gre")] + Greek, + + [HumanReadable(LongName = "Hebrew", ShortName = "heb")] + Hebrew, + + [HumanReadable(LongName = "Hindi", ShortName = "hin")] + Hindi, + + [HumanReadable(LongName = "Hungarian", ShortName = "hun")] + Hungarian, + + [HumanReadable(LongName = "Indonesian", ShortName = "ind")] + Indonesian, + + [HumanReadable(LongName = "Icelandic", ShortName = "isl")] + Icelandic, + + [HumanReadable(LongName = "Italian", ShortName = "ita")] + Italian, + + [HumanReadable(LongName = "Japanese", ShortName = "jap")] + Japanese, + + [HumanReadable(LongName = "Korean", ShortName = "kor")] + Korean, + + [HumanReadable(LongName = "Latin", ShortName = "lat")] + Latin, + + [HumanReadable(LongName = "Latvian", ShortName = "lav")] + Latvian, + + [HumanReadable(LongName = "Lithuanian", ShortName = "lit")] + Lithuanian, + + [HumanReadable(LongName = "Macedonian", ShortName = "mkd")] + Macedonian, + + [HumanReadable(LongName = "Norwegian", ShortName = "nor")] + Norwegian, + + [HumanReadable(LongName = "Polish", ShortName = "pol")] + Polish, + + [HumanReadable(LongName = "Portuguese", ShortName = "por")] + Portuguese, + + [HumanReadable(LongName = "Punjabi", ShortName = "pan")] + Punjabi, + + [HumanReadable(LongName = "Romanian", ShortName = "ron")] + Romanian, + + [HumanReadable(LongName = "Russian", ShortName = "rus")] + Russian, + + [HumanReadable(LongName = "Serbian", ShortName = "srp")] + Serbian, + + [HumanReadable(LongName = "Slovak", ShortName = "slk")] + Slovak, + + [HumanReadable(LongName = "Slovenian", ShortName = "slv")] + Slovenian, + + [HumanReadable(LongName = "Spanish", ShortName = "spa")] + Spanish, + + [HumanReadable(LongName = "Swedish", ShortName = "swe")] + Swedish, + + [HumanReadable(LongName = "Tamil", ShortName = "tam")] + Tamil, + + [HumanReadable(LongName = "Thai", ShortName = "tha")] + Thai, + + [HumanReadable(LongName = "Turkish", ShortName = "tur")] + Turkish, + + [HumanReadable(LongName = "Ukrainian", ShortName = "ukr")] + Ukrainian, + } + + /// + /// All possible language selections + /// + public enum LanguageSelection + { + [HumanReadable(LongName = "Bios settings")] + BiosSettings, + + [HumanReadable(LongName = "Language selector")] + LanguageSelector, + + [HumanReadable(LongName = "Options menu")] + OptionsMenu, + } + + /// + /// List of all known systems + /// + public enum RedumpSystem + { + // Special BIOS sets + [System(LongName = "Microsoft Xbox (BIOS)", ShortName = "xbox-bios", HasDat = true)] + MicrosoftXboxBIOS, + + [System(LongName = "Nintendo GameCube (BIOS)", ShortName = "gc-bios", HasDat = true)] + NintendoGameCubeBIOS, + + [System(LongName = "Sony PlayStation (BIOS)", ShortName = "psx-bios", HasDat = true)] + SonyPlayStationBIOS, + + [System(LongName = "Sony PlayStation 2 (BIOS)", ShortName = "ps2-bios", HasDat = true)] + SonyPlayStation2BIOS, + + // Regular systems + [System(LongName = "Acorn Archimedes", ShortName = "archcd", HasCues = true, HasDat = true)] + AcornArchimedes, + + [System(LongName = "Apple Macintosh", ShortName = "mac", HasCues = true, HasDat = true)] + AppleMacintosh, + + [System(LongName = "Atari Jaguar CD Interactive Multimedia System", ShortName = "ajcd", HasCues = true, HasDat = true)] + AtariJaguarCDInteractiveMultimediaSystem, + + [System(LongName = "Audio CD", ShortName = "audio-cd", IsBanned = true, HasCues = true, HasDat = true)] + AudioCD, + + [System(LongName = "Bandai Pippin", ShortName = "pippin", HasCues = true, HasDat = true)] + BandaiPippin, + + [System(LongName = "Bandai Playdia Quick Interactive System", ShortName = "qis", HasCues = true, HasDat = true)] + BandaiPlaydiaQuickInteractiveSystem, + + [System(LongName = "BD-Video", ShortName = "bd-video", IsBanned = true, HasDat = true)] + BDVideo, + + [System(LongName = "Commodore Amiga CD", ShortName = "acd", HasCues = true, HasDat = true)] + CommodoreAmigaCD, + + [System(LongName = "Commodore Amiga CD32", ShortName = "cd32", HasCues = true, HasDat = true)] + CommodoreAmigaCD32, + + [System(LongName = "Commodore Amiga CDTV", ShortName = "cdtv", HasCues = true, HasDat = true)] + CommodoreAmigaCDTV, + + [System(LongName = "DVD-Video", ShortName = "dvd-video", IsBanned = true, HasDat = true)] + DVDVideo, + + [System(LongName = "Enhanced CD", ShortName = "enhanced-cd", IsBanned = true)] + EnhancedCD, + + [System(LongName = "Fujitsu FM Towns series", ShortName = "fmt", HasCues = true, HasDat = true)] + FujitsuFMTownsseries, + + [System(LongName = "funworld Photo Play", ShortName = "fpp", HasCues = true, HasDat = true)] + funworldPhotoPlay, + + [System(LongName = "Hasbro VideoNow", ShortName = "hvn", IsBanned = true, HasCues = true, HasDat = true)] + HasbroVideoNow, + + [System(LongName = "Hasbro VideoNow Color", ShortName = "hvnc", IsBanned = true, HasCues = true, HasDat = true)] + HasbroVideoNowColor, + + [System(LongName = "Hasbro VideoNow Jr.", ShortName = "hvnjr", IsBanned = true, HasCues = true, HasDat = true)] + HasbroVideoNowJr, + + [System(LongName = "Hasbro VideoNow XP", ShortName = "hvnxp", IsBanned = true, HasCues = true, HasDat = true)] + HasbroVideoNowXP, + + [System(LongName = "HD DVD-Video", ShortName = "hddvd-video", IsBanned = true, HasDat = true)] + HDDVDVideo, + + [System(LongName = "IBM PC compatible", ShortName = "pc", HasCues = true, HasDat = true, HasLsd = true, HasSbi = true)] + IBMPCcompatible, + + [System(LongName = "Incredible Technologies Eagle", ShortName = "ite", HasCues = true, HasDat = true)] + IncredibleTechnologiesEagle, + + [System(LongName = "Konami e-Amusement", ShortName = "kea", HasCues = true, HasDat = true)] + KonamieAmusement, + + [System(LongName = "Konami FireBeat", ShortName = "kfb", HasCues = true, HasDat = true)] + KonamiFireBeat, + + [System(LongName = "Konami M2", ShortName = "km2", IsBanned = true, HasCues = true, HasDat = true)] + KonamiM2, + + [System(LongName = "Konami System 573", ShortName = "ks573")] + KonamiSystem573, + + [System(LongName = "Konami System GV", ShortName = "ksgv", HasCues = true, HasDat = true)] + KonamiSystemGV, + + [System(LongName = "Konami Twinkle", ShortName = "kt")] + KonamiTwinkle, + + [System(LongName = "Mattel Fisher-Price iXL", ShortName = "ixl", HasCues = true, HasDat = true)] + MattelFisherPriceiXL, + + [System(LongName = "Mattel HyperScan", ShortName = "hs", HasCues = true, HasDat = true)] + MattelHyperScan, + + [System(LongName = "Memorex Visual Information System", ShortName = "vis", HasCues = true, HasDat = true)] + MemorexVisualInformationSystem, + + [System(LongName = "Microsoft Xbox", ShortName = "xbox", HasCues = true, HasDat = true)] + MicrosoftXbox, + + [System(LongName = "Microsoft Xbox 360", ShortName = "xbox360", IsBanned = true, HasCues = true, HasDat = true)] + MicrosoftXbox360, + + [System(LongName = "Microsoft Xbox One", ShortName = "xboxone", IsBanned = true, HasDat = true)] + MicrosoftXboxOne, + + //[System(LongName = "Microsoft Xbox Series X/S", ShortName = "xboxxs", IsBanned = true)] + //MicrosoftXboxSeriesXandS, // TODO: Not available yet + + [System(LongName = "Namco · Sega · Nintendo Triforce", ShortName = "triforce", HasCues = true, HasDat = true, HasGdi = true)] + NamcoSegaNintendoTriforce, + + [System(LongName = "Namco System 12", ShortName = "ns12")] + NamcoSystem12, + + [System(LongName = "Namco System 246", ShortName = "ns246", HasCues = true, HasDat = true)] + NamcoSystem246, + + [System(LongName = "Navisoft Naviken 2.1", ShortName = "navi21", IsBanned = true, HasCues = true, HasDat = true)] + NavisoftNaviken21, + + [System(LongName = "NEC PC Engine CD & TurboGrafx CD", ShortName = "pce", HasCues = true, HasDat = true)] + NECPCEngineCDTurboGrafxCD, + + [System(LongName = "NEC PC-88 series", ShortName = "pc-88", HasCues = true, HasDat = true)] + NECPC88series, + + [System(LongName = "NEC PC-98 series", ShortName = "pc-98", HasCues = true, HasDat = true)] + NECPC98series, + + [System(LongName = "NEC PC-FX & PC-FXGA", ShortName = "pc-fx", HasCues = true, HasDat = true)] + NECPCFXPCFXGA, + + [System(LongName = "Nintendo GameCube", ShortName = "gc", HasDat = true)] + NintendoGameCube, + + [System(LongName = "Nintendo Wii", ShortName = "wii", IsBanned = true, HasDat = true)] + NintendoWii, + + [System(LongName = "Nintendo Wii U", ShortName = "wiiu", IsBanned = true, HasDat = true, HasKeys = true)] + NintendoWiiU, + + [System(LongName = "Palm OS", ShortName = "palm", HasCues = true, HasDat = true)] + PalmOS, + + [System(LongName = "Panasonic 3DO Interactive Multiplayer", ShortName = "3do", HasCues = true, HasDat = true)] + Panasonic3DOInteractiveMultiplayer, + + [System(LongName = "Panasonic M2", ShortName = "m2", IsBanned = true, HasCues = true, HasDat = true)] + PanasonicM2, + + [System(LongName = "Philips CD-i", ShortName = "cdi", HasCues = true, HasDat = true)] + PhilipsCDi, + + [System(LongName = "Philips CD-i Digital Video", ShortName = "cdi-video", IsBanned = true)] + PhilipsCDiDigitalVideo, + + [System(LongName = "Photo CD", ShortName = "photo-cd", HasCues = true, HasDat = true)] + PhotoCD, + + [System(LongName = "PlayStation GameShark Updates", ShortName = "psxgs", HasCues = true, HasDat = true)] + PlayStationGameSharkUpdates, + + [System(LongName = "Pocket PC", ShortName = "ppc", HasCues = true, HasDat = true)] + PocketPC, + + [System(LongName = "Sega Chihiro", ShortName = "chihiro", HasCues = true, HasDat = true, HasGdi = true)] + SegaChihiro, + + [System(LongName = "Sega Dreamcast", ShortName = "dc", HasCues = true, HasDat = true, HasGdi = true)] + SegaDreamcast, + + [System(LongName = "Sega Lindbergh", ShortName = "lindbergh", HasDat = true)] + SegaLindbergh, + + [System(LongName = "Sega Mega CD & Sega CD", ShortName = "mcd", HasCues = true, HasDat = true)] + SegaMegaCDSegaCD, + + [System(LongName = "Sega Naomi", ShortName = "naomi", HasCues = true, HasDat = true, HasGdi = true)] + SegaNaomi, + + [System(LongName = "Sega Naomi 2", ShortName = "naomi2", HasCues = true, HasDat = true, HasGdi = true)] + SegaNaomi2, + + [System(LongName = "Sega Prologue 21 Multimedia Karaoke System", ShortName = "sp21", HasCues = true, HasDat = true)] + SegaPrologue21MultimediaKaraokeSystem, + + [System(LongName = "Sega RingEdge", ShortName = "sre", IsBanned = true, HasDat = true)] + SegaRingEdge, + + [System(LongName = "Sega RingEdge 2", ShortName = "sre2", IsBanned = true, HasDat = true)] + SegaRingEdge2, + + [System(LongName = "Sega Saturn", ShortName = "ss", HasCues = true, HasDat = true)] + SegaSaturn, + + [System(LongName = "Sega Titan Video", ShortName = "stv")] + SegaTitanVideo, + + [System(LongName = "Sharp X68000", ShortName = "x86kcd", HasCues = true, HasDat = true)] + SharpX68000, + + [System(LongName = "Neo Geo CD", ShortName = "ngcd", HasCues = true, HasDat = true)] + SNKNeoGeoCD, + + [System(LongName = "Sony PlayStation", ShortName = "psx", HasCues = true, HasDat = true, HasLsd = true, HasSbi = true)] + SonyPlayStation, + + [System(LongName = "Sony PlayStation 2", ShortName = "ps2", HasCues = true, HasDat = true)] + SonyPlayStation2, + + [System(LongName = "Sony PlayStation 3", ShortName = "ps3", IsBanned = true, HasCues = true, HasDat = true, HasDkeys = true, HasKeys = true)] + SonyPlayStation3, + + [System(LongName = "Sony PlayStation 4", ShortName = "ps4", IsBanned = true, HasDat = true)] + SonyPlayStation4, + + //[System(LongName = "Sony PlayStation 5", ShortName = "ps5", IsBanned = true)] + //SonyPlayStation5, // TODO: Not available yet + + [System(LongName = "Sony PlayStation Portable", ShortName = "psp", HasDat = true)] + SonyPlayStationPortable, + + [System(LongName = "TAB-Austria Quizard", ShortName = "quizard", HasCues = true, HasDat = true)] + TABAustriaQuizard, + + [System(LongName = "Tao iKTV", ShortName = "iktv")] + TaoiKTV, + + [System(LongName = "Tomy Kiss-Site", ShortName = "ksite", HasCues = true, HasDat = true)] + TomyKissSite, + + [System(LongName = "Video CD", ShortName = "vcd", IsBanned = true, HasCues = true, HasDat = true)] + VideoCD, + + [System(LongName = "VM Labs NUON", ShortName = "nuon", HasDat = true)] + VMLabsNUON, + + [System(LongName = "VTech V.Flash & V.Smile Pro", ShortName = "vflash", HasCues = true, HasDat = true)] + VTechVFlashVSmilePro, + + [System(LongName = "ZAPiT Games Game Wave Family Entertainment System", ShortName = "gamewave", HasDat = true)] + ZAPiTGamesGameWaveFamilyEntertainmentSystem, + } + + /// + /// List of all known regions + /// + public enum Region + { + [HumanReadable(LongName = "Argentina", ShortName = "Ar")] + Argentina, + + [HumanReadable(LongName = "Asia", ShortName = "A")] + Asia, + + [HumanReadable(LongName = "Asia, Europe", ShortName = "A,E")] + AsiaEurope, + + [HumanReadable(LongName = "Asia, USA", ShortName = "A,U")] + AsiaUSA, + + [HumanReadable(LongName = "Australia", ShortName = "Au")] + Australia, + + [HumanReadable(LongName = "Australia, Germany", ShortName = "Au,G")] + AustraliaGermany, + + [HumanReadable(LongName = "Australia, New Zealand", ShortName = "Au,Nz")] + AustraliaNewZealand, + + [HumanReadable(LongName = "Austria", ShortName = "At")] + Austria, + + [HumanReadable(LongName = "Austria, Switzerland", ShortName = "At,Ch")] + AustriaSwitzerland, + + [HumanReadable(LongName = "Belgium", ShortName = "Be")] + Belgium, + + [HumanReadable(LongName = "Belgium, Netherlands", ShortName = "Be,N")] + BelgiumNetherlands, + + [HumanReadable(LongName = "Brazil", ShortName = "B")] + Brazil, + + [HumanReadable(LongName = "Bulgaria", ShortName = "Bg")] + Bulgaria, + + [HumanReadable(LongName = "Canada", ShortName = "Ca")] + Canada, + + [HumanReadable(LongName = "China", ShortName = "C")] + China, + + [HumanReadable(LongName = "Croatia", ShortName = "Hr")] + Croatia, + + [HumanReadable(LongName = "Czech", ShortName = "Cz")] + Czech, + + [HumanReadable(LongName = "Denmark", ShortName = "Dk")] + Denmark, + + [HumanReadable(LongName = "Estonia", ShortName = "Ee")] + Estonia, + + [HumanReadable(LongName = "Europe", ShortName = "E")] + Europe, + + [HumanReadable(LongName = "Europe, Asia", ShortName = "E,A")] + EuropeAsia, + + [HumanReadable(LongName = "Europe, Australia", ShortName = "E,Au")] + EuropeAustralia, + + [HumanReadable(LongName = "Europe, Canada", ShortName = "E,Ca")] + EuropeCanada, + + [HumanReadable(LongName = "Europe, Germany", ShortName = "E,G")] + EuropeGermany, + + [HumanReadable(LongName = "Export", ShortName = "Ex")] + Export, + + [HumanReadable(LongName = "Finland", ShortName = "Fi")] + Finland, + + [HumanReadable(LongName = "France", ShortName = "F")] + France, + + [HumanReadable(LongName = "France, Spain", ShortName = "F,S")] + FranceSpain, + + [HumanReadable(LongName = "Germany", ShortName = "G")] + Germany, + + [HumanReadable(LongName = "Greater China", ShortName = "GC")] + GreaterChina, + + [HumanReadable(LongName = "Greece", ShortName = "Gr")] + Greece, + + [HumanReadable(LongName = "Hungary", ShortName = "H")] + Hungary, + + [HumanReadable(LongName = "Iceland", ShortName = "Is")] + Iceland, + + [HumanReadable(LongName = "India", ShortName = "In")] + India, + + [HumanReadable(LongName = "Ireland", ShortName = "Ie")] + Ireland, + + [HumanReadable(LongName = "Israel", ShortName = "Il")] + Israel, + + [HumanReadable(LongName = "Italy", ShortName = "I")] + Italy, + + [HumanReadable(LongName = "Japan", ShortName = "J")] + Japan, + + [HumanReadable(LongName = "Japan, Asia", ShortName = "J,A")] + JapanAsia, + + [HumanReadable(LongName = "Japan, Europe", ShortName = "J,E")] + JapanEurope, + + [HumanReadable(LongName = "Japan, Korea", ShortName = "J,K")] + JapanKorea, + + [HumanReadable(LongName = "Japan, USA", ShortName = "J,U")] + JapanUSA, + + [HumanReadable(LongName = "Korea", ShortName = "K")] + Korea, + + [HumanReadable(LongName = "Latin America", ShortName = "LAm")] + LatinAmerica, + + [HumanReadable(LongName = "Lithuania", ShortName = "Lt")] + Lithuania, + + [HumanReadable(LongName = "Netherlands", ShortName = "N")] + Netherlands, + + [HumanReadable(LongName = "New Zealand", ShortName = "Nz")] + NewZealand, + + [HumanReadable(LongName = "Norway", ShortName = "No")] + Norway, + + [HumanReadable(LongName = "Poland", ShortName = "P")] + Poland, + + [HumanReadable(LongName = "Portugal", ShortName = "Pt")] + Portugal, + + [HumanReadable(LongName = "Romania", ShortName = "Ro")] + Romania, + + [HumanReadable(LongName = "Russia", ShortName = "R")] + Russia, + + [HumanReadable(LongName = "Scandinavia", ShortName = "Sca")] + Scandinavia, + + [HumanReadable(LongName = "Serbia", ShortName = "Rs")] + Serbia, + + [HumanReadable(LongName = "Singapore", ShortName = "Sg")] + Singapore, + + [HumanReadable(LongName = "Slovakia", ShortName = "Sk")] + Slovakia, + + [HumanReadable(LongName = "South Africa", ShortName = "Za")] + SouthAfrica, + + [HumanReadable(LongName = "Spain", ShortName = "S")] + Spain, + + [HumanReadable(LongName = "Spain, Portugal", ShortName = "S,Pt")] + SpainPortugal, + + [HumanReadable(LongName = "Sweden", ShortName = "Sw")] + Sweden, + + [HumanReadable(LongName = "Switzerland", ShortName = "Ch")] + Switzerland, + + [HumanReadable(LongName = "Taiwan", ShortName = "Tw")] + Taiwan, + + [HumanReadable(LongName = "Thailand", ShortName = "Th")] + Thailand, + + [HumanReadable(LongName = "Turkey", ShortName = "Tr")] + Turkey, + + [HumanReadable(LongName = "United Arab Emirates", ShortName = "Ae")] + UnitedArabEmirates, + + [HumanReadable(LongName = "UK", ShortName = "Uk")] + UK, + + [HumanReadable(LongName = "UK, Australia", ShortName = "Uk,Au")] + UKAustralia, + + [HumanReadable(LongName = "Ukraine", ShortName = "Ue")] + Ukraine, + + [HumanReadable(LongName = "USA", ShortName = "U")] + USA, + + [HumanReadable(LongName = "USA, Asia", ShortName = "U,A")] + USAAsia, + + [HumanReadable(LongName = "USA, Australia", ShortName = "U,Au")] + USAAustralia, + + [HumanReadable(LongName = "USA, Brazil", ShortName = "U,B")] + USABrazil, + + [HumanReadable(LongName = "USA, Canada", ShortName = "U,Ca")] + USACanada, + + [HumanReadable(LongName = "USA, Europe", ShortName = "U,E")] + USAEurope, + + [HumanReadable(LongName = "USA, Germany", ShortName = "U,G")] + USAGermany, + + [HumanReadable(LongName = "USA, Japan", ShortName = "U,J")] + USAJapan, + + [HumanReadable(LongName = "USA, Korea", ShortName = "U,K")] + USAKorea, + + [HumanReadable(LongName = "World", ShortName = "W")] + World, + } +} diff --git a/RedumpLib/Data/Extensions.cs b/RedumpLib/Data/Extensions.cs new file mode 100644 index 00000000..b16b3762 --- /dev/null +++ b/RedumpLib/Data/Extensions.cs @@ -0,0 +1,998 @@ +using RedumpLib.Attributes; + +namespace RedumpLib.Data +{ + /// + /// Information pertaining to Redump systems + /// + public static class Extensions + { + #region Category + + /// + /// Get the Redump longnames for each known category + /// + /// + /// + public static string LongName(this DiscCategory? category) => AttributeHelper.GetAttribute(category)?.LongName; + + /// + /// Get the Category enum value for a given string + /// + /// String value to convert + /// Category represented by the string, if possible + public static DiscCategory? ToDiscCategory(string category) + { + switch (category.ToLowerInvariant()) + { + case "games": + return DiscCategory.Games; + case "demos": + return DiscCategory.Demos; + case "video": + return DiscCategory.Video; + case "audio": + return DiscCategory.Audio; + case "multimedia": + return DiscCategory.Multimedia; + case "applications": + return DiscCategory.Applications; + case "coverdiscs": + return DiscCategory.Coverdiscs; + case "educational": + return DiscCategory.Educational; + case "bonusdiscs": + case "bonus discs": + return DiscCategory.BonusDiscs; + case "preproduction": + return DiscCategory.Preproduction; + case "addons": + case "add-ons": + return DiscCategory.AddOns; + default: + return DiscCategory.Games; + } + } + + #endregion + + #region Language + + /// + /// Get the Redump longnames for each known language + /// + /// + /// + public static string LongName(this Language? language) => AttributeHelper.GetAttribute(language)?.LongName; + + /// + /// Get the Redump shortnames for each known language + /// + /// + /// + public static string ShortName(this Language? language) => AttributeHelper.GetAttribute(language)?.ShortName; + + /// + /// Get the Language enum value for a given string + /// + /// String value to convert + /// Language represented by the string, if possible + public static Language? ToLanguage(string lang) + { + switch (lang) + { + case "afr": + return Language.Afrikaans; + case "sqi": + return Language.Albanian; + case "ara": + return Language.Arabic; + case "baq": + return Language.Basque; + case "bul": + return Language.Bulgarian; + case "cat": + return Language.Catalan; + case "chi": + return Language.Chinese; + case "hrv": + return Language.Croatian; + case "cze": + return Language.Czech; + case "dan": + return Language.Danish; + case "dut": + return Language.Dutch; + case "eng": + return Language.English; + case "est": + return Language.Estonian; + case "fin": + return Language.Finnish; + case "fre": + return Language.French; + case "gla": + return Language.Gaelic; + case "ger": + return Language.German; + case "gre": + return Language.Greek; + case "heb": + return Language.Hebrew; + case "hin": + return Language.Hindi; + case "hun": + return Language.Hungarian; + case "ind": + return Language.Indonesian; + case "isl": + return Language.Icelandic; + case "ita": + return Language.Italian; + case "jap": + return Language.Japanese; + case "kor": + return Language.Korean; + case "lat": + return Language.Latin; + case "lav": + return Language.Latvian; + case "lit": + return Language.Lithuanian; + case "mkd": + return Language.Macedonian; + case "nor": + return Language.Norwegian; + case "pol": + return Language.Polish; + case "por": + return Language.Portuguese; + case "pan": + return Language.Punjabi; + case "ron": + return Language.Romanian; + case "rus": + return Language.Russian; + case "srp": + return Language.Serbian; + case "slk": + return Language.Slovak; + case "slv": + return Language.Slovenian; + case "spa": + return Language.Spanish; + case "swe": + return Language.Swedish; + case "tam": + return Language.Tamil; + case "tha": + return Language.Thai; + case "tur": + return Language.Turkish; + case "ukr": + return Language.Ukrainian; + default: + return null; + } + } + + #endregion + + #region Language Selection + + /// + /// Get the string representation of the LanguageSelection enum values + /// + /// LanguageSelection value to convert + /// String representing the value, if possible + public static string LongName(this LanguageSelection? langSelect) => AttributeHelper.GetAttribute(langSelect)?.LongName; + + #endregion + + #region Region + + /// + /// Get the Redump longnames for each known region + /// + /// + /// + public static string LongName(this Region? region) => AttributeHelper.GetAttribute(region)?.LongName; + + /// + /// Get the Redump shortnames for each known region + /// + /// + /// + public static string ShortName(this Region? region) => AttributeHelper.GetAttribute(region)?.ShortName; + + /// + /// Get the Region enum value for a given string + /// + /// String value to convert + /// Region represented by the string, if possible + public static Region? ToRegion(string region) + { + switch (region) + { + case "Ar": + return Region.Argentina; + case "A": + return Region.Asia; + case "A,E": + return Region.AsiaEurope; + case "A,U": + return Region.AsiaUSA; + case "Au": + return Region.Australia; + case "Au,G": + return Region.AustraliaGermany; + case "Au,Nz": + return Region.AustraliaNewZealand; + case "At": + return Region.Austria; + case "At,Ch": + return Region.AustriaSwitzerland; + case "Be": + return Region.Belgium; + case "Be,N": + return Region.BelgiumNetherlands; + case "B": + return Region.Brazil; + case "Bg": + return Region.Bulgaria; + case "Ca": + return Region.Canada; + case "C": + return Region.China; + case "Hr": + return Region.Croatia; + case "Cz": + return Region.Czech; + case "Dk": + return Region.Denmark; + case "Ee": + return Region.Estonia; + case "E": + return Region.Europe; + case "E,A": + return Region.EuropeAsia; + case "E,Au": + return Region.EuropeAustralia; + case "E,Ca": + return Region.EuropeCanada; + case "E,G": + return Region.EuropeGermany; + case "Ex": + return Region.Export; + case "Fi": + return Region.Finland; + case "F": + return Region.France; + case "F,S": + return Region.FranceSpain; + case "G": + return Region.Germany; + case "GC": + return Region.GreaterChina; + case "Gr": + return Region.Greece; + case "H": + return Region.Hungary; + case "Is": + return Region.Iceland; + case "In": + return Region.India; + case "Ie": + return Region.Ireland; + case "Il": + return Region.Israel; + case "I": + return Region.Italy; + case "J": + return Region.Japan; + case "J,A": + return Region.JapanAsia; + case "J,E": + return Region.JapanEurope; + case "J,K": + return Region.JapanKorea; + case "J,U": + return Region.JapanUSA; + case "K": + return Region.Korea; + case "LAm": + return Region.LatinAmerica; + case "Lt": + return Region.Lithuania; + case "N": + return Region.Netherlands; + case "Nz": + return Region.NewZealand; + case "No": + return Region.Norway; + case "P": + return Region.Poland; + case "Pt": + return Region.Portugal; + case "Ro": + return Region.Romania; + case "R": + return Region.Russia; + case "Sca": + return Region.Scandinavia; + case "Rs": + return Region.Serbia; + case "Sg": + return Region.Singapore; + case "Sk": + return Region.Slovakia; + case "Za": + return Region.SouthAfrica; + case "S": + return Region.Spain; + case "S,Pt": + return Region.SpainPortugal; + case "Sw": + return Region.Sweden; + case "Ch": + return Region.Switzerland; + case "Tw": + return Region.Taiwan; + case "Th": + return Region.Thailand; + case "Tr": + return Region.Turkey; + case "Ae": + return Region.UnitedArabEmirates; + case "Uk": + return Region.UK; + case "Uk,Au": + return Region.UKAustralia; + case "Ue": + return Region.Ukraine; + case "U": + return Region.USA; + case "U,A": + return Region.USAAsia; + case "U,Au": + return Region.USAAustralia; + case "U,B": + return Region.USABrazil; + case "U,Ca": + return Region.USACanada; + case "U,E": + return Region.USAEurope; + case "U,G": + return Region.USAGermany; + case "U,J": + return Region.USAJapan; + case "U,K": + return Region.USAKorea; + case "W": + return Region.World; + default: + return null; + } + } + + #endregion + + #region System + + /// + /// Get the Redump longnames for each known system + /// + /// + /// + public static string LongName(this RedumpSystem? system) => AttributeHelper.GetAttribute(system)?.LongName; + + /// + /// Get the Redump shortnames for each known system + /// + /// + /// + public static string ShortName(this RedumpSystem? system) => AttributeHelper.GetAttribute(system)?.ShortName; + + /// + /// Determine if a system is restricted to dumpers + /// + public static bool IsBanned(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper.GetAttribute(system))?.IsBanned ?? false; + + /// + /// Determine if a system has a CUE pack + /// + public static bool HasCues(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper.GetAttribute(system))?.HasCues ?? false; + + /// + /// Determine if a system has a DAT + /// + public static bool HasDat(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper.GetAttribute(system))?.HasDat ?? false; + + /// + /// Determine if a system has a decrypted keys pack + /// + public static bool HasDkeys(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper.GetAttribute(system))?.HasDkeys ?? false; + + /// + /// Determine if a system has a GDI pack + /// + public static bool HasGdi(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper.GetAttribute(system))?.HasGdi ?? false; + + /// + /// Determine if a system has a keys pack + /// + public static bool HasKeys(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper.GetAttribute(system))?.HasKeys ?? false; + + /// + /// Determine if a system has an LSD pack + /// + public static bool HasLsd(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper.GetAttribute(system))?.HasLsd ?? false; + + /// + /// Determine if a system has an SBI pack + /// + public static bool HasSbi(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper.GetAttribute(system))?.HasSbi ?? false; + + /// + /// Get the RedumpSystem enum value for a given string + /// + /// String value to convert + /// RedumpSystem represented by the string, if possible + public static RedumpSystem? ToRedumpSystem(string sys) + { + switch (sys) + { + // Special BIOS Sets + case "xboxbios": + case "xbox bios": + case "microsoftxboxbios": + case "microsoftxbox bios": + case "microsoft xbox bios": + return RedumpSystem.MicrosoftXboxBIOS; + case "gcbios": + case "gc bios": + case "gamecubebios": + case "ngcbios": + case "ngc bios": + case "nintendogamecubebios": + case "nintendo gamecube bios": + return RedumpSystem.NintendoGameCubeBIOS; + case "ps1bios": + case "ps1 bios": + case "psxbios": + case "psx bios": + case "playstationbios": + case "playstation bios": + case "sonyps1bios": + case "sonyps1 bios": + case "sony ps1 bios": + case "sonypsxbios": + case "sonypsx bios": + case "sony psx bios": + case "sonyplaystationbios": + case "sonyplaystation bios": + case "sony playstation bios": + return RedumpSystem.SonyPlayStationBIOS; + case "ps2bios": + case "ps2 bios": + case "playstation2bios": + case "playstation2 bios": + case "playstation 2 bios": + case "sonyps2bios": + case "sonyps2 bios": + case "sony ps2 bios": + case "sonyplaystation2bios": + case "sonyplaystation2 bios": + case "sony playstation 2 bios": + return RedumpSystem.SonyPlayStation2BIOS; + + // Regular systems + case "acorn": + case "archimedes": + case "acornarchimedes": + case "acorn archimedes": + return RedumpSystem.AcornArchimedes; + case "apple": + case "mac": + case "applemac": + case "macintosh": + case "applemacintosh": + case "apple mac": + case "apple macintosh": + return RedumpSystem.AppleMacintosh; + case "jaguar": + case "jagcd": + case "jaguarcd": + case "jaguar cd": + case "atarijaguar": + case "atarijagcd": + case "atarijaguarcd": + case "atari jaguar cd": + return RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem; + case "audio": + case "audiocd": + case "audio cd": + return RedumpSystem.AudioCD; + case "playdia": + case "playdiaqis": + case "playdiaquickinteractivesystem": + case "bandaiplaydia": + case "bandaiplaydiaquickinteractivesystem": + case "bandai playdia quick interactive system": + return RedumpSystem.BandaiPlaydiaQuickInteractiveSystem; + case "pippin": + case "bandaipippin": + case "bandai pippin": + case "applepippin": + case "apple pippin": + case "bandaiapplepippin": + case "bandai apple pippin": + case "bandai / apple pippin": + return RedumpSystem.BandaiPippin; + case "bdvideo": + case "bd-video": + case "blurayvideo": + case "bluray video": + return RedumpSystem.BDVideo; + case "amiga": + case "amigacd": + case "amiga cd": + case "commodoreamiga": + case "commodoreamigacd": + case "commodoreamiga cd": + case "commodore amiga": + case "commodore amiga cd": + return RedumpSystem.CommodoreAmigaCD; + case "cd32": + case "amigacd32": + case "amiga cd32": + case "commodoreamigacd32": + case "commodore amiga cd32": + return RedumpSystem.CommodoreAmigaCD32; + case "cdtv": + case "amigacdtv": + case "amiga cdtv": + case "commodoreamigacdtv": + case "commodore amiga cdtv": + return RedumpSystem.CommodoreAmigaCDTV; + case "dvdvideo": + case "dvd-video": + return RedumpSystem.DVDVideo; + case "enhancedcd": + case "enhanced cd": + case "enhancedcdrom": + case "enhanced cdrom": + case "enhanced cd-rom": + return RedumpSystem.EnhancedCD; + case "fmtowns": + case "fmt": + case "fm towns": + case "fujitsufmtowns": + case "fujitsu fm towns": + case "fujitsu fm towns series": + return RedumpSystem.FujitsuFMTownsseries; + case "fpp": + case "funworldphotoplay": + case "funworld photoplay": + case "funworld photo play": + return RedumpSystem.funworldPhotoPlay; + case "videonow": + case "hasbrovideonow": + case "hasbro videonow": + return RedumpSystem.HasbroVideoNow; + case "videonowcolor": + case "videonow color": + case "hasbrovideonowcolor": + case "hasbro videonow color": + return RedumpSystem.HasbroVideoNowColor; + case "videonowjr": + case "videonow jr": + case "hasbrovideonowjr": + case "hasbro videonow jr": + return RedumpSystem.HasbroVideoNowColor; + case "videonowxp": + case "videonow xp": + case "hasbrovideonowxp": + case "hasbro videonow xp": + return RedumpSystem.HasbroVideoNowColor; + case "hddvd-video": + case "hd dvd video": + case "hd-dvd video": + case "hd dvd-video": + case "hd-dvd-video": + return RedumpSystem.HDDVDVideo; + case "ibm": + case "ibmpc": + case "pc": + case "ibm pc": + case "ibm pc compatible": + return RedumpSystem.IBMPCcompatible; + case "iteagle": + case "eagle": + case "incredible technologies eagle": + return RedumpSystem.IncredibleTechnologiesEagle; + case "eamusement": + case "e-amusement": + case "konamieamusement": + case "konami eamusement": + case "konamie-amusement": + case "konami e-amusement": + return RedumpSystem.KonamieAmusement; + case "firebeat": + case "konamifirebeat": + case "konami firebeat": + return RedumpSystem.KonamiFireBeat; + case "konamim2": + case "konami m2": + return RedumpSystem.KonamiM2; + case "system573": + case "system 573": + case "konamisystem573": + case "konami system 573": + return RedumpSystem.KonamiSystem573; + case "gvsystem": + case "systemgv": + case "gv system": + case "system gv": + case "konamigvsystem": + case "konamisystemgv": + case "konami gv system": + case "konami system gv": + return RedumpSystem.KonamiSystemGV; + case "twinkle": + case "konamitwinkle": + case "konami twinkle": + return RedumpSystem.KonamiTwinkle; + case "ixl": + case "mattelixl": + case "mattel ixl": + case "fisherpriceixl": + case "fisher price ixl": + case "fisher-price ixl": + case "fisherprice ixl": + case "mattelfisherpriceixl": + case "mattel fisher price ixl": + case "mattelfisherprice ixl": + case "mattel fisherprice ixl": + case "mattel fisher-price ixl": + return RedumpSystem.MattelFisherPriceiXL; + case "hyperscan": + case "mattelhyperscan": + case "mattel hyperscan": + return RedumpSystem.MattelHyperScan; + case "vis": + case "tandyvis": + case "tandy vis": + case "tandyvisualinformationsystem": + case "tandy visual information system": + case "memorexvis": + case "memorex vis": + case "memorexvisualinformationsystem": + case "memorex visual information sytem": + case "tandy / memorex visual information system": + return RedumpSystem.MemorexVisualInformationSystem; + case "xbox": + case "microsoftxbox": + case "microsoft xbox": + return RedumpSystem.MicrosoftXbox; + case "x360": + case "xbox360": + case "microsoftx360": + case "microsoftxbox360": + case "microsoft x360": + case "microsoft xbox 360": + return RedumpSystem.MicrosoftXbox360; + case "xb1": + case "xbone": + case "xboxone": + case "microsoftxbone": + case "microsoftxboxone": + case "microsoft xbone": + case "microsoft xbox one": + return RedumpSystem.MicrosoftXboxOne; + case "triforce": + case "namcotriforce": + case "namco triforce": + case "segatriforce": + case "sega triforce": + case "nintendotriforce": + case "nintendo triforce": + case "namco / sega / nintendo triforce": + return RedumpSystem.NamcoSegaNintendoTriforce; + case "system12": + case "system 12": + case "namcosystem12": + case "namco system 12": + return RedumpSystem.NamcoSystem12; + case "system246": + case "system 246": + case "namcosystem246": + case "namco system 246": + case "capcomsystem246": + case "capcom system 246": + case "taitosystem246": + case "taito system 246": + case "namco / capcom / taito system 246": + return RedumpSystem.NamcoSystem246; + case "naviken": + case "naviken21": + case "naviken 2.1": + case "navisoftnaviken": + case "navisoft naviken": + case "navisoftnaviken21": + case "navisoft naviken 2.1": + return RedumpSystem.NavisoftNaviken21; + case "pcecd": + case "pce-cd": + case "tgcd": + case "tg-cd": + case "necpcecd": + case "nectgcd": + case "nec pc-engine cd": + case "nec turbografx cd": + case "nec pc-engine / turbografx cd": + return RedumpSystem.NECPCEngineCDTurboGrafxCD; + case "pc88": + case "pc-88": + case "necpc88": + case "nec pc88": + case "nec pc-88": + return RedumpSystem.NECPC88series; + case "pc98": + case "pc-98": + case "necpc98": + case "nec pc98": + case "nec pc-98": + return RedumpSystem.NECPC98series; + case "pcfx": + case "pc-fx": + case "pcfxga": + case "pc-fxga": + case "necpcfx": + case "necpcfxga": + case "nec pc-fx": + case "nec pc-fxga": + case "nec pc-fx / pc-fxga": + return RedumpSystem.NECPCFXPCFXGA; + case "gc": + case "gamecube": + case "ngc": + case "nintendogamecube": + case "nintendo gamecube": + return RedumpSystem.NintendoGameCube; + case "wii": + case "nintendowii": + case "nintendo wii": + return RedumpSystem.NintendoWii; + case "wiiu": + case "wii u": + case "nintendowiiu": + case "nintendo wii u": + return RedumpSystem.NintendoWiiU; + case "palm": + case "palmos": + return RedumpSystem.PalmOS; + case "3do": + case "3do interactive multiplayer": + case "panasonic3do": + case "panasonic 3do": + case "panasonic 3do interactive multiplayer": + return RedumpSystem.Panasonic3DOInteractiveMultiplayer; + case "panasonicm2": + case "panasonic m2": + return RedumpSystem.PanasonicM2; + case "cdi": + case "cd-i": + case "philipscdi": + case "philips cdi": + case "philips cd-i": + return RedumpSystem.PhilipsCDi; + case "cdi-video": + case "cdi video": + case "cd-i-video": + case "cd-i video": + case "cdidigitalvideo": + case "cdi digital video": + case "cd-i digital video": + case "philipscdivideo": + case "philips cdi-video": + case "philips cdi video": + case "philips cd-ivideo": + case "philips cd-i-video": + case "philips cd-i video": + case "philipscdidigitalvideo": + case "philips cdi digital video": + case "philips cd-idigitalvideo": + case "philips cd-i digital video": + return RedumpSystem.PhilipsCDiDigitalVideo; + case "photo": + case "photocd": + case "photo cd": + return RedumpSystem.PhotoCD; + case "gameshark": + case "psgameshark": + case "ps gameshark": + case "playstationgameshark": + case "playstation gameshark": + case "playstation gameshark updates": + return RedumpSystem.PlayStationGameSharkUpdates; + case "ppc": + case "pocketpc": + case "pocket pc": + return RedumpSystem.PocketPC; + case "chihiro": + case "segachihiro": + case "sega chihiro": + return RedumpSystem.SegaChihiro; + case "dc": + case "sdc": + case "dreamcast": + case "segadreamcast": + case "sega dreamcast": + return RedumpSystem.SegaDreamcast; + case "lindbergh": + case "segalindbergh": + case "sega lindbergh": + return RedumpSystem.SegaLindbergh; + case "scd": + case "mcd": + case "smcd": + case "segacd": + case "megacd": + case "segamegacd": + case "sega cd": + case "mega cd": + case "sega cd / mega cd": + return RedumpSystem.SegaMegaCDSegaCD; + case "naomi": + case "seganaomi": + case "sega naomi": + return RedumpSystem.SegaNaomi; + case "naomi2": + case "naomi 2": + case "seganaomi2": + case "sega naomi 2": + return RedumpSystem.SegaNaomi2; + case "sp21": + case "prologue21": + case "prologue 21": + case "segaprologue21": + case "sega prologue21": + case "sega prologue 21": + case "segaprologue21multimediakaraokesystem": + case "sega prologue21 multimedia karaoke system": + case "sega prologue 21 multimedia karaoke system": + return RedumpSystem.SegaPrologue21MultimediaKaraokeSystem; + case "ringedge": + case "segaringedge": + case "sega ringedge": + return RedumpSystem.SegaRingEdge; + case "ringedge2": + case "ringedge 2": + case "segaringedge2": + case "sega ringedge 2": + return RedumpSystem.SegaRingEdge2; + case "saturn": + case "segasaturn": + case "sega saturn": + return RedumpSystem.SegaSaturn; + case "stv": + case "titanvideo": + case "titan video": + case "segatitanvideo": + case "sega titan video": + return RedumpSystem.SegaTitanVideo; + case "x68k": + case "x68000": + case "sharpx68k": + case "sharp x68k": + case "sharpx68000": + case "sharp x68000": + return RedumpSystem.SharpX68000; + case "ngcd": + case "neogeocd": + case "neogeo cd": + case "neo geo cd": + case "snk ngcd": + case "snk neogeo cd": + case "snk neo geo cd": + return RedumpSystem.SNKNeoGeoCD; + case "ps1": + case "psx": + case "playstation": + case "sonyps1": + case "sony ps1": + case "sonypsx": + case "sony psx": + case "sonyplaystation": + case "sony playstation": + return RedumpSystem.SonyPlayStation; + case "ps2": + case "playstation2": + case "playstation 2": + case "sonyps2": + case "sony ps2": + case "sonyplaystation2": + case "sony playstation 2": + return RedumpSystem.SonyPlayStation2; + case "ps3": + case "playstation3": + case "playstation 3": + case "sonyps3": + case "sony ps3": + case "sonyplaystation3": + case "sony playstation 3": + return RedumpSystem.SonyPlayStation3; + case "ps4": + case "playstation4": + case "playstation 4": + case "sonyps4": + case "sony ps4": + case "sonyplaystation4": + case "sony playstation 4": + return RedumpSystem.SonyPlayStation4; + case "psp": + case "playstationportable": + case "playstation portable": + case "sonypsp": + case "sony psp": + case "sonyplaystationportable": + case "sony playstation portable": + return RedumpSystem.SonyPlayStationPortable; + case "quizard": + case "tabaustriaquizard": + case "tab-austria quizard": + return RedumpSystem.TABAustriaQuizard; + case "iktv": + case "taoiktv": + case "tao iktv": + return RedumpSystem.TaoiKTV; + case "kisssite": + case "kiss-site": + case "tomykisssite": + case "tomy kisssite": + case "tomy kiss-site": + return RedumpSystem.TomyKissSite; + case "vcd": + case "videocd": + case "video cd": + return RedumpSystem.VideoCD; + case "nuon": + case "vmlabsnuon": + case "vm labs nuon": + return RedumpSystem.VMLabsNUON; + case "vflash": + case "vsmile": + case "vsmilepro": + case "vsmile pro": + case "v.flash": + case "v.smile": + case "v.smilepro": + case "v.smile pro": + case "vtechvflash": + case "vtech vflash": + case "vtech v.flash": + case "vtechvsmile": + case "vtech vsmile": + case "vtech v.smile": + case "vtechvsmilepro": + case "vtech vsmile pro": + case "vtech v.smile pro": + case "vtech v.flash - v.smile pro": + return RedumpSystem.VTechVFlashVSmilePro; + case "gamewave": + case "game wave": + case "zapit": + case "zapitgamewave": + case "zapit game wave": + case "zapit games game wave family entertainment system": + return RedumpSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem; + + default: + return null; + } + } + + #endregion + } +} diff --git a/RedumpLib/RedumpLib.csproj b/RedumpLib/RedumpLib.csproj new file mode 100644 index 00000000..f4cddcc9 --- /dev/null +++ b/RedumpLib/RedumpLib.csproj @@ -0,0 +1,13 @@ + + + + net48;netcoreapp3.1;net5.0 + x86 + false + + + + + + + diff --git a/RedumpLib/Web/RedumpWebClient.cs b/RedumpLib/Web/RedumpWebClient.cs new file mode 100644 index 00000000..241568f3 --- /dev/null +++ b/RedumpLib/Web/RedumpWebClient.cs @@ -0,0 +1,699 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using RedumpLib.Data; + +namespace RedumpLib.Web +{ + // https://stackoverflow.com/questions/1777221/using-cookiecontainer-with-webclient-class + public class RedumpWebClient : WebClient + { + private readonly CookieContainer m_container = new CookieContainer(); + + /// + /// Determines if user is logged into Redump + /// + public bool LoggedIn { get; private set; } = false; + + /// + /// Determines if the user is a staff member + /// + public bool IsStaff { get; private set; } = false; + + /// + /// Get the last downloaded filename, if possible + /// + /// + public string GetLastFilename() + { + // If the response headers are null or empty + if (ResponseHeaders == null || ResponseHeaders.Count != 0) + return null; + + // If we don't have the response header we care about + string headerValue = ResponseHeaders.Get("Content-Disposition"); + if (string.IsNullOrWhiteSpace(headerValue)) + return null; + + // Extract the filename from the value + return headerValue.Substring(headerValue.IndexOf("filename=") + 9).Replace("\"", ""); + } + + /// + protected override WebRequest GetWebRequest(Uri address) + { + WebRequest request = base.GetWebRequest(address); + HttpWebRequest webRequest = request as HttpWebRequest; + if (webRequest != null) + { + webRequest.CookieContainer = m_container; + } + + return request; + } + + /// + /// Login to Redump, if possible + /// + /// Redump username + /// Redump password + /// True if the user could be logged in, false otherwise, null on error + public bool? Login(string username, string password) + { + // Credentials verification + if (!string.IsNullOrWhiteSpace(username) && !string.IsNullOrWhiteSpace(password)) + { + Console.WriteLine("Credentials entered, will attempt Redump login..."); + } + else if (!string.IsNullOrWhiteSpace(username) && string.IsNullOrWhiteSpace(password)) + { + Console.WriteLine("Only a username was specified, will not attempt Redump login..."); + return false; + } + else if (string.IsNullOrWhiteSpace(username)) + { + Console.WriteLine("No credentials entered, will not attempt Redump login..."); + return false; + } + + try + { + // Get the current token from the login page + var loginPage = DownloadString(Constants.LoginUrl); + string token = Constants.TokenRegex.Match(loginPage).Groups[1].Value; + + // Construct the login request + Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded"; + Encoding = Encoding.UTF8; + var response = UploadString(Constants.LoginUrl, $"form_sent=1&redirect_url=&csrf_token={token}&req_username={username}&req_password={password}&save_pass=0"); + + if (response.Contains("Incorrect username and/or password.")) + { + Console.WriteLine("Invalid credentials entered, continuing without logging in..."); + return false; + } + + // The user was able to be logged in + Console.WriteLine("Credentials accepted! Logged into Redump..."); + LoggedIn = true; + + // If the user is a moderator or staff, set accordingly + if (response.Contains("http://forum.redump.org/forum/9/staff/")) + IsStaff = true; + + return true; + } + catch (Exception ex) + { + Console.WriteLine($"An exception occurred while trying to log in: {ex}"); + return null; + } + } + + #region Single Page Helpers + + /// + /// Process a Redump site page as a list of possible IDs or disc page + /// + /// Base URL to download using + /// List of IDs from the page, empty on error + public List CheckSingleSitePage(string url) + { + List ids = new List(); + var dumpsPage = DownloadString(url); + + // If we have no dumps left + if (dumpsPage.Contains("No discs found.")) + return ids; + + // If we have a single disc page already + if (dumpsPage.Contains("Download:")) + { + var value = Regex.Match(dumpsPage, @"/disc/(\d+)/sfv/").Groups[1].Value; + if (int.TryParse(value, out int id)) + ids.Add(id); + + return ids; + } + + // Otherwise, traverse each dump on the page + var matches = Constants.DiscRegex.Matches(dumpsPage); + foreach (Match match in matches) + { + try + { + if (int.TryParse(match.Groups[1].Value, out int value)) + ids.Add(value); + } + catch (Exception ex) + { + Console.WriteLine($"An exception has occurred: {ex}"); + continue; + } + } + + return ids; + } + + /// + /// Process a Redump site page as a list of possible IDs or disc page + /// + /// Base URL to download using + /// Output directory to save data to + /// True to return on first error, false otherwise + /// True if the page could be downloaded, false otherwise + public bool CheckSingleSitePage(string url, string outDir, bool failOnSingle) + { + var dumpsPage = DownloadString(url); + + // If we have no dumps left + if (dumpsPage.Contains("No discs found.")) + return false; + + // If we have a single disc page already + if (dumpsPage.Contains("Download:")) + { + var value = Regex.Match(dumpsPage, @"/disc/(\d+)/sfv/").Groups[1].Value; + if (int.TryParse(value, out int id)) + { + bool downloaded = DownloadSingleSiteID(id, outDir, false); + if (!downloaded && failOnSingle) + return false; + } + + return false; + } + + // Otherwise, traverse each dump on the page + var matches = Constants.DiscRegex.Matches(dumpsPage); + foreach (Match match in matches) + { + try + { + if (int.TryParse(match.Groups[1].Value, out int value)) + { + bool downloaded = DownloadSingleSiteID(value, outDir, false); + if (!downloaded && failOnSingle) + return false; + } + } + catch (Exception ex) + { + Console.WriteLine($"An exception has occurred: {ex}"); + continue; + } + } + + return true; + } + + /// + /// Process a Redump WIP page as a list of possible IDs or disc page + /// + /// RedumpWebClient to access the packs + /// List of IDs from the page, empty on error + public List CheckSingleWIPPage(string url) + { + List ids = new List(); + var dumpsPage = DownloadString(url); + + // If we have no dumps left + if (dumpsPage.Contains("No discs found.")) + return ids; + + // Otherwise, traverse each dump on the page + var matches = Constants.NewDiscRegex.Matches(dumpsPage); + foreach (Match match in matches) + { + try + { + if (int.TryParse(match.Groups[2].Value, out int value)) + ids.Add(value); + } + catch (Exception ex) + { + Console.WriteLine($"An exception has occurred: {ex}"); + continue; + } + } + + return ids; + } + + /// + /// Process a Redump WIP page as a list of possible IDs or disc page + /// + /// RedumpWebClient to access the packs + /// Output directory to save data to + /// True to return on first error, false otherwise + /// True if the page could be downloaded, false otherwise + public bool CheckSingleWIPPage(string url, string outDir, bool failOnSingle) + { + var dumpsPage = DownloadString(url); + + // If we have no dumps left + if (dumpsPage.Contains("No discs found.")) + return false; + + // Otherwise, traverse each dump on the page + var matches = Constants.NewDiscRegex.Matches(dumpsPage); + foreach (Match match in matches) + { + try + { + if (int.TryParse(match.Groups[2].Value, out int value)) + { + bool downloaded = DownloadSingleWIPID(value, outDir, false); + if (!downloaded && failOnSingle) + return false; + } + } + catch (Exception ex) + { + Console.WriteLine($"An exception has occurred: {ex}"); + continue; + } + } + + return true; + } + + #endregion + + #region Download Helpers + + /// + /// Download a single pack + /// + /// Base URL to download using + /// System to download packs for + /// Byte array containing the downloaded pack, null on error + public byte[] DownloadSinglePack(string url, RedumpSystem? system) + { + try + { + return DownloadData(string.Format(url, system.ShortName())); + } + catch (Exception ex) + { + Console.WriteLine($"An exception has occurred: {ex}"); + return null; + } + } + + /// + /// Download a single pack + /// + /// Base URL to download using + /// System to download packs for + /// Output directory to save data to + /// Named subfolder for the pack, used optionally + public void DownloadSinglePack(string url, RedumpSystem? system, string outDir, string subfolder) + { + try + { + // If no output directory is defined, use the current directory instead + if (string.IsNullOrWhiteSpace(outDir)) + outDir = Environment.CurrentDirectory; + + string tempfile = Path.Combine(outDir, "tmp" + Guid.NewGuid().ToString()); + DownloadFile(string.Format(url, system.ShortName()), tempfile); + MoveOrDelete(tempfile, GetLastFilename(), outDir, subfolder); + } + catch (Exception ex) + { + Console.WriteLine($"An exception has occurred: {ex}"); + } + } + + /// + /// Download an individual site ID data, if possible + /// + /// Redump disc ID to retrieve + /// String containing the page contents if successful, null on error + public string DownloadSingleSiteID(int id) + { + string paddedId = id.ToString().PadLeft(5, '0'); + Console.WriteLine($"Processing ID: {paddedId}"); + try + { + string discPage = DownloadString(string.Format(Constants.DiscPageUrl, +id)); + if (discPage.Contains($"Disc with ID \"{id}\" doesn't exist")) + { + Console.WriteLine($"ID {paddedId} could not be found!"); + return null; + } + + Console.WriteLine($"ID {paddedId} has been successfully downloaded"); + return discPage; + } + catch (Exception ex) + { + Console.WriteLine($"An exception has occurred: {ex}"); + return null; + } + } + + /// + /// Download an individual site ID data, if possible + /// + /// Redump disc ID to retrieve + /// Output directory to save data to + /// True to rename deleted entries, false otherwise + /// True if all data was downloaded, false otherwise + public bool DownloadSingleSiteID(int id, string outDir, bool rename) + { + // If no output directory is defined, use the current directory instead + if (string.IsNullOrWhiteSpace(outDir)) + outDir = Environment.CurrentDirectory; + + string paddedId = id.ToString().PadLeft(5, '0'); + string paddedIdDir = Path.Combine(outDir, paddedId); + Console.WriteLine($"Processing ID: {paddedId}"); + try + { + string discPage = DownloadString(string.Format(Constants.DiscPageUrl, +id)); + if (discPage.Contains($"Disc with ID \"{id}\" doesn't exist")) + { + try + { + if (rename) + { + if (Directory.Exists(paddedIdDir) && rename) + Directory.Move(paddedIdDir, paddedIdDir + "-deleted"); + else + Directory.CreateDirectory(paddedIdDir + "-deleted"); + } + } + catch { } + + Console.WriteLine($"ID {paddedId} could not be found!"); + return false; + } + + // Check if the page has been updated since the last time it was downloaded, if possible + if (File.Exists(Path.Combine(paddedIdDir, "disc.html"))) + { + // Read in the cached file + var oldDiscPage = File.ReadAllText(Path.Combine(paddedIdDir, "disc.html")); + + // Check for the last modified date in both pages + var oldResult = Constants.LastModifiedRegex.Match(oldDiscPage); + var newResult = Constants.LastModifiedRegex.Match(discPage); + + // If both pages contain the same modified date, skip it + if (oldResult.Success && newResult.Success && oldResult.Groups[1].Value == newResult.Groups[1].Value) + { + Console.WriteLine($"ID {paddedId} has not been changed since last download"); + return false; + } + + // If neither page contains a modified date, skip it + else if (!oldResult.Success && !newResult.Success) + { + Console.WriteLine($"ID {paddedId} has not been changed since last download"); + return false; + } + } + + // Create ID subdirectory + Directory.CreateDirectory(paddedIdDir); + + // View Edit History + if (discPage.Contains($"
+ /// Download an individual WIP ID data, if possible + /// + /// Redump WIP disc ID to retrieve + /// String containing the page contents if successful, null on error + public string DownloadSingleWIPID(int id) + { + string paddedId = id.ToString().PadLeft(5, '0'); + Console.WriteLine($"Processing ID: {paddedId}"); + try + { + string discPage = DownloadString(string.Format(Constants.WipDiscPageUrl, +id)); + if (discPage.Contains($"System \"{id}\" doesn't exist")) + { + Console.WriteLine($"ID {paddedId} could not be found!"); + return null; + } + + Console.WriteLine($"ID {paddedId} has been successfully downloaded"); + return discPage; + } + catch (Exception ex) + { + Console.WriteLine($"An exception has occurred: {ex}"); + return null; + } + } + + /// + /// Download an individual WIP ID data, if possible + /// + /// Redump WIP disc ID to retrieve + /// Output directory to save data to + /// True to rename deleted entries, false otherwise + /// True if all data was downloaded, false otherwise + public bool DownloadSingleWIPID(int id, string outDir, bool rename) + { + // If no output directory is defined, use the current directory instead + if (string.IsNullOrWhiteSpace(outDir)) + outDir = Environment.CurrentDirectory; + + string paddedId = id.ToString().PadLeft(5, '0'); + string paddedIdDir = Path.Combine(outDir, paddedId); + Console.WriteLine($"Processing ID: {paddedId}"); + try + { + string discPage = DownloadString(string.Format(Constants.WipDiscPageUrl, +id)); + if (discPage.Contains($"System \"{id}\" doesn't exist")) + { + try + { + if (rename) + { + if (Directory.Exists(paddedIdDir) && rename) + Directory.Move(paddedIdDir, paddedIdDir + "-deleted"); + else + Directory.CreateDirectory(paddedIdDir + "-deleted"); + } + } + catch { } + + Console.WriteLine($"ID {paddedId} could not be found!"); + return false; + } + + // Check if the page has been updated since the last time it was downloaded, if possible + if (File.Exists(Path.Combine(paddedIdDir, "disc.html"))) + { + // Read in the cached file + var oldDiscPage = File.ReadAllText(Path.Combine(paddedIdDir, "disc.html")); + + // Check for the full match ID in both pages + var oldResult = Constants.FullMatchRegex.Match(oldDiscPage); + var newResult = Constants.FullMatchRegex.Match(discPage); + + // If both pages contain the same ID, skip it + if (oldResult.Success && newResult.Success && oldResult.Groups[1].Value == newResult.Groups[1].Value) + { + Console.WriteLine($"ID {paddedId} has not been changed since last download"); + return false; + } + + // If neither page contains an ID, skip it + else if (!oldResult.Success && !newResult.Success) + { + Console.WriteLine($"ID {paddedId} has not been changed since last download"); + return false; + } + } + + // Create ID subdirectory + Directory.CreateDirectory(paddedIdDir); + + // HTML + using (var discStreamWriter = File.CreateText(Path.Combine(paddedIdDir, "disc.html"))) + { + discStreamWriter.Write(discPage); + } + + Console.WriteLine($"ID {paddedId} has been successfully downloaded"); + return true; + } + catch (Exception ex) + { + Console.WriteLine($"An exception has occurred: {ex}"); + return false; + } + } + + #endregion + + #region Helpers + + /// + /// Download a set of packs + /// + /// Base URL to download using + /// Systems to download packs for + /// Name of the pack that is downloading + public Dictionary DownloadPacks(string url, RedumpSystem?[] systems, string title) + { + var packsDictionary = new Dictionary(); + + Console.WriteLine($"Downloading {title}"); + foreach (var system in systems) + { + // If the system is null, we can't do anything + if (system == null) + continue; + + // If we didn't have credentials + if (!LoggedIn && system.IsBanned()) + continue; + + // If the system is unknown, we can't do anything + string longName = system.LongName(); + if (string.IsNullOrWhiteSpace(longName)) + continue; + + Console.Write($"\r{longName}{new string(' ', Console.BufferWidth - longName.Length - 1)}"); + byte[] pack = DownloadSinglePack(url, system); + if (pack != null) + packsDictionary.Add(system.Value, pack); + } + + Console.Write($"\rComplete!{new string(' ', Console.BufferWidth - 10)}"); + Console.WriteLine(); + + return packsDictionary; + } + + /// + /// Download a set of packs + /// + /// Base URL to download using + /// Systems to download packs for + /// Name of the pack that is downloading + /// Output directory to save data to + /// Named subfolder for the pack, used optionally + public void DownloadPacks(string url, RedumpSystem?[] systems, string title, string outDir, string subfolder) + { + Console.WriteLine($"Downloading {title}"); + foreach (var system in systems) + { + // If we didn't have credentials + if (!LoggedIn && system.IsBanned()) + continue; + + // If the system is unknown, we can't do anything + string longName = system.LongName(); + if (string.IsNullOrWhiteSpace(longName)) + continue; + + Console.Write($"\r{longName}{new string(' ', Console.BufferWidth - longName.Length - 1)}"); + DownloadSinglePack(url, system, outDir, subfolder); + } + + Console.Write($"\rComplete!{new string(' ', Console.BufferWidth - 10)}"); + Console.WriteLine(); + } + + /// + /// Move a tempfile to a new name unless it aleady exists, in which case, delete the tempfile + /// + /// Path to existing temporary file + /// Path to new output file + /// Output directory to save data to + /// Optional subfolder to append to the path + private void MoveOrDelete(string tempfile, string newfile, string outDir, string subfolder) + { + if (!string.IsNullOrWhiteSpace(newfile)) + { + if (!string.IsNullOrWhiteSpace(subfolder)) + { + if (!Directory.Exists(Path.Combine(outDir, subfolder))) + Directory.CreateDirectory(Path.Combine(outDir, subfolder)); + + newfile = Path.Combine(subfolder, newfile); + } + + if (File.Exists(Path.Combine(outDir, newfile))) + File.Delete(tempfile); + else + File.Move(tempfile, Path.Combine(outDir, newfile)); + } + else + File.Delete(tempfile); + } + + #endregion + } +}