Convert to using separate Redump library code

This commit is contained in:
Matt Nadareski
2021-08-18 15:32:45 -07:00
parent 0fb3bc1106
commit c8610ee16a
44 changed files with 3455 additions and 4206 deletions

View File

@@ -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

View File

@@ -46,6 +46,7 @@
<Project>{51ab0928-13f9-44bf-a407-b6957a43a056}</Project>
<Name>MPF.Library</Name>
</ProjectReference>
<ProjectReference Include="..\RedumpLib\RedumpLib.csproj" />
</ItemGroup>
</Project>

View File

@@ -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,

View File

@@ -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
/// </summary>
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
/// <returns>True on successful extraction of info, false otherwise</returns>
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
/// </summary>
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
/// <returns>True on successful extraction of info, false otherwise</returns>
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)

View File

@@ -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
/// <param name="region">Output region, if possible</param>
/// <param name="version">Output internal version of the game</param>
/// <returns></returns>
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

View File

@@ -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
{
/// <summary>
/// Serialize KnownSystem enum values
/// </summary>
public class KnownSystemConverter : JsonConverter<KnownSystem?>
{
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);
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using MPF.Data;
using MPF.Utilities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace MPF.Converters
{
/// <summary>
/// Serialize MediaType enum values
/// </summary>
public class MediaTypeConverter : JsonConverter<MediaType?>
{
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);
}
}
}

View File

@@ -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;

View File

@@ -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
/// <param name="region">Output region, if possible</param>
/// <param name="date">Output EXE date in "yyyy-mm-dd" format if possible, null on error</param>
/// <returns></returns>
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
/// </summary>
/// <param name="region">String representing the category</param>
/// <returns>Category, if possible</returns>
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
/// </summary>
/// <param name="serial">PlayStation serial code</param>
/// <returns>Region mapped from name, if possible</returns>
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
/// </summary>
/// <param name="region">Character denoting the region</param>
/// <returns>Region, if possible</returns>
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;
}

View File

@@ -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<int> newIds = wc.ListSearchResults(sha1);
List<int> 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
/// <summary>
/// Fill out an existing SubmissionInfo object based on a disc page
/// </summary>
/// <param name="wc">RedumpWebClient for making the connection</param>
/// <param name="info">Existing SubmissionInfo object to fill</param>
/// <param name="id">Redump disc ID to retrieve</param>
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<Language?> tempLanguages = new List<Language?>();
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<string> tempDumpers = new List<string>();
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("<br />", "\n")
.Replace("<b>ISBN</b>", "[T:ISBN]") + "\n";
}
// Contents
match = Constants.ContentsRegex.Match(discData);
if (match.Success)
{
info.CommonDiscInfo.Contents = WebUtility.HtmlDecode(match.Groups[1].Value)
.Replace("<br />", "\n")
.Replace("</div>", "");
info.CommonDiscInfo.Contents = Regex.Replace(info.CommonDiscInfo.Contents, @"<div .*?>", "");
}
// 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;
}
}
/// <summary>
/// List the disc IDs associated with a given quicksearch query
/// </summary>
/// <param name="wc">RedumpWebClient for making the connection</param>
/// <param name="query">Query string to attempt to search for</param>
/// <returns>All disc IDs for the given query, null on error</returns>
private List<int> ListSearchResults(RedumpWebClient wc, string query)
{
List<int> ids = new List<int>();
// 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<int> 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
}
}

View File

@@ -407,274 +407,6 @@ namespace MPF.Data
TapeDSTLarge = 66,
}
/// <summary>
/// Redump disc category
/// </summary>
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,
}
/// <summary>
/// Redump dump status
/// </summary>
public enum RedumpDumpStatus
{
BadDumpRed = 2,
PossibleBadDumpYellow = 3,
OriginalMediaBlue = 4,
TwoOrMoreDumpsGreen = 5,
}
/// <summary>
/// Redump supported langauge
/// </summary>
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,
}
/// <summary>
/// Redump PS2 language selection via
/// </summary>
public enum RedumpLanguageSelection
{
BiosSettings,
LanguageSelector,
OptionsMenu,
}
/// <summary>
/// Supported Redump region
/// </summary>
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,
}
/// <summary>
/// List of all known Redump systems
/// </summary>
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,
}
/// <summary>
/// Generic yes/no values for Redump
/// </summary>

View File

@@ -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);
}
}

View File

@@ -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; }

View File

@@ -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
/// </summary>
/// <param name="dmi">DMI.bin file location</param>
/// <returns>True on successful extraction of info, false otherwise</returns>
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
/// </summary>
/// <param name="dmi">DMI.bin file location</param>
/// <returns>True on successful extraction of info, false otherwise</returns>
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;

View File

@@ -73,6 +73,10 @@
<None Remove="Aaru\CICMMetadata\README.md" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\RedumpLib\RedumpLib.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="1.7.0" GeneratePathProperty="true">
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>

View File

@@ -1,235 +0,0 @@
using MPF.Data;
namespace MPF.Redump
{
/// <summary>
/// Information pertaining to Redump systems
/// </summary>
public static class Extras
{
#region Special lists
/// <summary>
/// List of systems that are not publically accessible
/// </summary>
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,
};
/// <summary>
/// List of systems that have a Cues pack
/// </summary>
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,
};
/// <summary>
/// List of systems that has a Dat pack
/// </summary>
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,
};
/// <summary>
/// List of systems that has a Decrypted Keys pack
/// </summary>
public static readonly RedumpSystem?[] HasDkeys = new RedumpSystem?[]
{
RedumpSystem.SonyPlayStation3,
};
/// <summary>
/// List of systems that has a GDI pack
/// </summary>
public static readonly RedumpSystem?[] HasGdi = new RedumpSystem?[]
{
RedumpSystem.NamcoSegaNintendoTriforce,
RedumpSystem.SegaChihiro,
RedumpSystem.SegaDreamcast,
RedumpSystem.SegaNaomi,
RedumpSystem.SegaNaomi2,
};
/// <summary>
/// List of systems that has a Keys pack
/// </summary>
public static readonly RedumpSystem?[] HasKeys = new RedumpSystem?[]
{
RedumpSystem.NintendoWiiU,
RedumpSystem.SonyPlayStation3,
};
/// <summary>
/// List of systems that has an LSD pack
/// </summary>
public static readonly RedumpSystem?[] HasLsd = new RedumpSystem?[]
{
RedumpSystem.IBMPCcompatible,
RedumpSystem.SonyPlayStation,
};
/// <summary>
/// List of systems that has an SBI pack
/// </summary>
public static readonly RedumpSystem?[] HasSbi = new RedumpSystem?[]
{
RedumpSystem.IBMPCcompatible,
RedumpSystem.SonyPlayStation,
};
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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
/// </summary>
/// <param name="disc">_disc.txt file location</param>
/// <returns>True on successful extraction of info, false otherwise</returns>
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;

View File

@@ -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);
}
/// <summary>
@@ -111,6 +110,26 @@ namespace MPF.Utilities
return assemblyVersion.InformationalVersion;
}
/// <summary>
/// Get the latest version of MPF from GitHub and the release URL
/// </summary>
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
}
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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()
{

View File

@@ -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")]

View File

@@ -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

View File

@@ -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<T> item) => item?.Data;
/// <inheritdoc/>
public string Name => Converters.GetLongName(Data);
public string Name => EnumConverter.GetLongName(Data);
public override string ToString() => Name;

View File

@@ -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?);
}
}

View File

@@ -51,6 +51,7 @@
<Project>{51ab0928-13f9-44bf-a407-b6957a43a056}</Project>
<Name>MPF.Library</Name>
</ProjectReference>
<ProjectReference Include="..\RedumpLib\RedumpLib.csproj" />
</ItemGroup>
<ItemGroup>

View File

@@ -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
/// <summary>
/// List of available disc categories
/// </summary>
public List<Element<RedumpDiscCategory>> Categories { get; private set; } = Element<RedumpDiscCategory>.GenerateElements().ToList();
public List<Element<DiscCategory>> Categories { get; private set; } = Element<DiscCategory>.GenerateElements().ToList();
/// <summary>
/// List of available regions
/// </summary>
public List<Element<RedumpRegion>> Regions { get; private set; } = Element<RedumpRegion>.GenerateElements().ToList();
public List<Element<Region>> Regions { get; private set; } = Element<Region>.GenerateElements().ToList();
/// <summary>
/// List of available languages
/// </summary>
public List<Element<RedumpLanguage>> Languages { get; private set; } = Element<RedumpLanguage>.GenerateElements().ToList();
public List<Element<Language>> Languages { get; private set; } = Element<Language>.GenerateElements().ToList();
/// <summary>
/// List of available languages
/// </summary>
public List<Element<RedumpLanguageSelection>> LanguageSelections { get; private set; } = Element<RedumpLanguageSelection>.GenerateElements().ToList();
public List<Element<LanguageSelection>> LanguageSelections { get; private set; } = Element<LanguageSelection>.GenerateElements().ToList();
#endregion
@@ -234,11 +235,11 @@ namespace MPF.GUI.ViewModels
/// </summary>
public void Save()
{
SubmissionInfo.CommonDiscInfo.Category = (Parent.CategoryComboBox.SelectedItem as Element<RedumpDiscCategory>)?.Value ?? RedumpDiscCategory.Games;
SubmissionInfo.CommonDiscInfo.Region = (Parent.RegionComboBox.SelectedItem as Element<RedumpRegion>)?.Value ?? RedumpRegion.World;
SubmissionInfo.CommonDiscInfo.Category = (Parent.CategoryComboBox.SelectedItem as Element<DiscCategory>)?.Value ?? DiscCategory.Games;
SubmissionInfo.CommonDiscInfo.Region = (Parent.RegionComboBox.SelectedItem as Element<Region>)?.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();
}

View File

@@ -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();

View File

@@ -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

View File

@@ -0,0 +1,48 @@
using System;
using System.Linq;
namespace RedumpLib.Attributes
{
public static class AttributeHelper<T>
{
/// <summary>
/// Get the HumanReadableAttribute from a supported value
/// </summary>
/// <param name="value">Value to use</param>
/// <returns>HumanReadableAttribute attached to the value</returns>
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();
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
namespace RedumpLib.Attributes
{
/// <summary>
/// Generic attribute for human readable values
/// </summary>
public class HumanReadableAttribute : Attribute
{
public string LongName { get; set; }
public string ShortName { get; set; }
}
}

View File

@@ -0,0 +1,48 @@
namespace RedumpLib.Attributes
{
/// <summary>
/// Attribute specifc to Redump System values
/// </summary>
public class SystemAttribute : HumanReadableAttribute
{
/// <summary>
/// System is restricted to dumpers
/// </summary>
public bool IsBanned { get; set; } = false;
/// <summary>
/// System has a CUE pack
/// </summary>
public bool HasCues { get; set; } = false;
/// <summary>
/// System has a DAT
/// </summary>
public bool HasDat { get; set; } = false;
/// <summary>
/// System has a decrypted keys pack
/// </summary>
public bool HasDkeys { get; set; } = false;
/// <summary>
/// System has a GDI pack
/// </summary>
public bool HasGdi { get; set; } = false;
/// <summary>
/// System has a keys pack
/// </summary>
public bool HasKeys { get; set; } = false;
/// <summary>
/// System has an LSD pack
/// </summary>
public bool HasLsd { get; set; } = false;
/// <summary>
/// System has an SBI pack
/// </summary>
public bool HasSbi { get; set; } = false;
}
}

View File

@@ -0,0 +1,32 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RedumpLib.Data;
namespace RedumpLib.Converters
{
/// <summary>
/// Serialize DiscCategory enum values
/// </summary>
public class DiscCategoryConverter : JsonConverter<DiscCategory?[]>
{
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);
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RedumpLib.Data;
namespace RedumpLib.Converters
{
/// <summary>
/// Serialize Language enum values
/// </summary>
public class LanguageConverter : JsonConverter<Language?[]>
{
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);
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RedumpLib.Data;
namespace RedumpLib.Converters
{
/// <summary>
/// Serialize LanguageSelection enum values
/// </summary>
public class LanguageSelectionConverter : JsonConverter<LanguageSelection?[]>
{
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);
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RedumpLib.Data;
namespace RedumpLib.Converters
{
/// <summary>
/// Serialize Region enum values
/// </summary>
public class RegionConverter : JsonConverter<Region?>
{
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);
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RedumpLib.Data;
namespace RedumpLib.Converters
{
/// <summary>
/// Serialize RedumpSystem enum values
/// </summary>
public class SystemConverter : JsonConverter<RedumpSystem?>
{
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);
}
}
}

301
RedumpLib/Data/Constants.cs Normal file
View File

@@ -0,0 +1,301 @@
using System.Text.RegularExpressions;
namespace RedumpLib.Data
{
public static class Constants
{
// TODO: Add RegexOptions.Compiled
#region Regular Expressions
/// <summary>
/// Regex matching the added field on a disc page
/// </summary>
public static Regex AddedRegex = new Regex(@"<tr><th>Added</th><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching the barcode field on a disc page
/// </summary>
public static Regex BarcodeRegex = new Regex(@"<tr><th>Barcode</th></tr><tr><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching the BCA field on a disc page
/// </summary>
public static Regex BcaRegex = new Regex(@"<h3>BCA .*?/></h3></td><td .*?></td></tr>"
+ "<tr><th>Row</th><th>Contents</th><th>ASCII</th></tr>"
+ "<tr><td>(?<row1number>.*?)</td><td>(?<row1contents>.*?)</td><td>(?<row1ascii>.*?)</td></tr>"
+ "<tr><td>(?<row2number>.*?)</td><td>(?<row2contents>.*?)</td><td>(?<row2ascii>.*?)</td></tr>"
+ "<tr><td>(?<row3number>.*?)</td><td>(?<row3contents>.*?)</td><td>(?<row3ascii>.*?)</td></tr>"
+ "<tr><td>(?<row4number>.*?)</td><td>(?<row4contents>.*?)</td><td>(?<row4ascii>.*?)</td></tr>");
/// <summary>
/// Regex matching the category field on a disc page
/// </summary>
public static Regex CategoryRegex = new Regex(@"<tr><th>Category</th><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching the comments field on a disc page
/// </summary>
public static Regex CommentsRegex = new Regex(@"<tr><th>Comments</th></tr><tr><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching the contents field on a disc page
/// </summary>
public static Regex ContentsRegex = new Regex(@"<tr><th>Contents</th></tr><tr .*?><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching individual disc links on a results page
/// </summary>
public static Regex DiscRegex = new Regex(@"<a href=""/disc/(\d+)/"">");
/// <summary>
/// Regex matching the disc number or letter field on a disc page
/// </summary>
public static Regex DiscNumberLetterRegex = new Regex(@"\((.*?)\)");
/// <summary>
/// Regex matching the dumpers on a disc page
/// </summary>
public static Regex DumpersRegex = new Regex(@"<a href=""/discs/dumper/(.*?)/"">");
/// <summary>
/// Regex matching the edition field on a disc page
/// </summary>
public static Regex EditionRegex = new Regex(@"<tr><th>Edition</th><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching the error count field on a disc page
/// </summary>
public static Regex ErrorCountRegex = new Regex(@"<tr><th>Errors count</th><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching the foreign title field on a disc page
/// </summary>
public static Regex ForeignTitleRegex = new Regex(@"<h2>(.*?)</h2>");
/// <summary>
/// Regex matching the "full match" ID list from a WIP disc page
/// </summary>
public static Regex FullMatchRegex = new Regex(@"<td class=""static"">full match ids: (.*?)</td>");
/// <summary>
/// Regex matching the languages field on a disc page
/// </summary>
public static Regex LanguagesRegex = new Regex(@"<img src=""/images/languages/(.*?)\.png"" alt="".*?"" title="".*?"" />\s*");
/// <summary>
/// Regex matching the last modified field on a disc page
/// </summary>
public static Regex LastModifiedRegex = new Regex(@"<tr><th>Last modified</th><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching the media field on a disc page
/// </summary>
public static Regex MediaRegex = new Regex(@"<tr><th>Media</th><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching individual WIP disc links on a results page
/// </summary>
public static Regex NewDiscRegex = new Regex(@"<a (style=.*)?href=""/newdisc/(\d+)/"">");
/// <summary>
/// Regex matching the "partial match" ID list from a WIP disc page
/// </summary>
public static Regex PartialMatchRegex = new Regex(@"<td class=""static"">partial match ids: (.*?)</td>");
/// <summary>
/// Regex matching the PVD field on a disc page
/// </summary>
public static Regex PvdRegex = new Regex(@"<h3>Primary Volume Descriptor (PVD) <img .*?/></h3></td><td .*?></td></tr>"
+ @"<tr><th>Record / Entry</th><th>Contents</th><th>Date</th><th>Time</th><th>GMT</th></tr>"
+ @"<tr><td>Creation</td><td>(?<creationbytes>.*?)</td><td>(?<creationdate>.*?)</td><td>(?<creationtime>.*?)</td><td>(?<creationtimezone>.*?)</td></tr>"
+ @"<tr><td>Modification</td><td>(?<modificationbytes>.*?)</td><td>(?<modificationdate>.*?)</td><td>(?<modificationtime>.*?)</td><td>(?<modificationtimezone>.*?)</td></tr>"
+ @"<tr><td>Expiration</td><td>(?<expirationbytes>.*?)</td><td>(?<expirationdate>.*?)</td><td>(?<expirationtime>.*?)</td><td>(?<expirationtimezone>.*?)</td></tr>"
+ @"<tr><td>Effective</td><td>(?<effectivebytes>.*?)</td><td>(?<effectivedate>.*?)</td><td>(?<effectivetime>.*?)</td><td>(?<effectivetimezone>.*?)</td></tr>");
/// <summary>
/// Regex matching the region field on a disc page
/// </summary>
public static Regex RegionRegex = new Regex(@"<tr><th>Region</th><td><a href=""/discs/region/(.*?)/"">");
/// <summary>
/// Regex matching a double-layer disc ringcode information
/// </summary>
public static Regex RingCodeDoubleRegex = new Regex(@""); // Varies based on available fields, like Addtional Mould
/// <summary>
/// Regex matching a single-layer disc ringcode information
/// </summary>
public static Regex RingCodeSingleRegex = new Regex(@""); // Varies based on available fields, like Addtional Mould
/// <summary>
/// Regex matching the serial field on a disc page
/// </summary>
public static Regex SerialRegex = new Regex(@"<tr><th>Serial</th><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching the system field on a disc page
/// </summary>
public static Regex SystemRegex = new Regex(@"<tr><th>System</th><td><a href=""/discs/system/(.*?)/"">");
/// <summary>
/// Regex matching the title field on a disc page
/// </summary>
public static Regex TitleRegex = new Regex(@"<h1>(.*?)</h1>");
/// <summary>
/// Regex matching the current nonce token for login
/// </summary>
public static Regex TokenRegex = new Regex(@"<input type=""hidden"" name=""csrf_token"" value=""(.*?)"" />");
/// <summary>
/// Regex matching a single track on a disc page
/// </summary>
public static Regex TrackRegex = new Regex(@"<tr><td>(?<number>.*?)</td><td>(?<type>.*?)</td><td>(?<pregap>.*?)</td><td>(?<length>.*?)</td><td>(?<sectors>.*?)</td><td>(?<size>.*?)</td><td>(?<crc32>.*?)</td><td>(?<md5>.*?)</td><td>(?<sha1>.*?)</td></tr>");
/// <summary>
/// Regex matching the track count on a disc page
/// </summary>
public static Regex TrackCountRegex = new Regex(@"<tr><th>Number of tracks</th><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching the version field on a disc page
/// </summary>
public static Regex VersionRegex = new Regex(@"<tr><th>Version</th><td>(.*?)</td></tr>");
/// <summary>
/// Regex matching the write offset field on a disc page
/// </summary>
public static Regex WriteOffsetRegex = new Regex(@"<tr><th>Write offset</th><td>(.*?)</td></tr>");
#endregion
#region URLs
/// <summary>
/// Redump disc page URL template
/// </summary>
public const string DiscPageUrl = @"http://redump.org/disc/{0}/";
/// <summary>
/// Redump last modified search URL
/// </summary>
public const string LastModifiedUrl = @"http://redump.org/discs/sort/modified/dir/desc?page={0}";
/// <summary>
/// Redump login page URL
/// </summary>
public const string LoginUrl = "http://forum.redump.org/login/";
/// <summary>
/// Redump CUE pack URL template
/// </summary>
public const string PackCuesUrl = @"http://redump.org/cues/{0}/";
/// <summary>
/// Redump DAT pack URL template
/// </summary>
public const string PackDatfileUrl = @"http://redump.org/datfile/{0}/";
/// <summary>
/// Redump DKEYS pack URL template
/// </summary>
public const string PackDkeysUrl = @"http://redump.org/dkeys/{0}/";
/// <summary>
/// Redump GDI pack URL template
/// </summary>
public const string PackGdiUrl = @"http://redump.org/gdi/{0}/";
/// <summary>
/// Redump KEYS pack URL template
/// </summary>
public const string PackKeysUrl = @"http://redump.org/keys/{0}/";
/// <summary>
/// Redump LSD pack URL template
/// </summary>
public const string PackLsdUrl = @"http://redump.org/lsd/{0}/";
/// <summary>
/// Redump SBI pack URL template
/// </summary>
public const string PackSbiUrl = @"http://redump.org/sbi/{0}/";
/// <summary>
/// Redump quicksearch URL template
/// </summary>
public const string QuickSearchUrl = @"http://redump.org/discs/quicksearch/{0}/?page={1}";
/// <summary>
/// Redump user dumps URL template
/// </summary>
public const string UserDumpsUrl = @"http://redump.org/discs/dumper/{0}/?page={1}";
/// <summary>
/// Redump WIP disc page URL template
/// </summary>
public const string WipDiscPageUrl = @"http://redump.org/newdisc/{0}/";
/// <summary>
/// Redump WIP dumps queue URL
/// </summary>
public const string WipDumpsUrl = @"http://redump.org/discs-wip/";
#endregion
#region URL Extensions
/// <summary>
/// Changes page subpath
/// </summary>
public const string ChangesExt = "changes/";
/// <summary>
/// Cuesheet download subpath
/// </summary>
public const string CueExt = "cue/";
/// <summary>
/// Edit page subpath
/// </summary>
public const string EditExt = "edit/";
/// <summary>
/// GDI download subpath
/// </summary>
public const string GdiExt = "gdi/";
/// <summary>
/// Key download subpath
/// </summary>
public const string KeyExt = "key/";
/// <summary>
/// LSD download subpath
/// </summary>
public const string LsdExt = "lsd/";
/// <summary>
/// MD5 download subpath
/// </summary>
public const string Md5Ext = "md5/";
/// <summary>
/// SBI download subpath
/// </summary>
public const string SbiExt = "sbi/";
/// <summary>
/// SFV download subpath
/// </summary>
public const string SfvExt = "sfv/";
/// <summary>
/// SHA1 download subpath
/// </summary>
public const string Sha1Ext = "sha1/";
#endregion
}
}

View File

@@ -0,0 +1,720 @@
using RedumpLib.Attributes;
namespace RedumpLib.Data
{
/// <summary>
/// List of all disc categories
/// </summary>
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,
}
/// <summary>
/// Dump status
/// </summary>
public enum DumpStatus
{
BadDumpRed = 2,
PossibleBadDumpYellow = 3,
OriginalMediaBlue = 4,
TwoOrMoHumanReadablesGreen = 5,
}
/// <summary>
/// Determines what download type to initate
/// </summary>
public enum Feature
{
NONE,
Site,
WIP,
Packs,
User,
Quicksearch,
}
/// <summary>
/// List of all disc langauges
/// </summary>
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,
}
/// <summary>
/// All possible language selections
/// </summary>
public enum LanguageSelection
{
[HumanReadable(LongName = "Bios settings")]
BiosSettings,
[HumanReadable(LongName = "Language selector")]
LanguageSelector,
[HumanReadable(LongName = "Options menu")]
OptionsMenu,
}
/// <summary>
/// List of all known systems
/// </summary>
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,
}
/// <summary>
/// List of all known regions
/// </summary>
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,
}
}

View File

@@ -0,0 +1,998 @@
using RedumpLib.Attributes;
namespace RedumpLib.Data
{
/// <summary>
/// Information pertaining to Redump systems
/// </summary>
public static class Extensions
{
#region Category
/// <summary>
/// Get the Redump longnames for each known category
/// </summary>
/// <param name="category"></param>
/// <returns></returns>
public static string LongName(this DiscCategory? category) => AttributeHelper<DiscCategory?>.GetAttribute(category)?.LongName;
/// <summary>
/// Get the Category enum value for a given string
/// </summary>
/// <param name="category">String value to convert</param>
/// <returns>Category represented by the string, if possible</returns>
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
/// <summary>
/// Get the Redump longnames for each known language
/// </summary>
/// <param name="language"></param>
/// <returns></returns>
public static string LongName(this Language? language) => AttributeHelper<Language?>.GetAttribute(language)?.LongName;
/// <summary>
/// Get the Redump shortnames for each known language
/// </summary>
/// <param name="language"></param>
/// <returns></returns>
public static string ShortName(this Language? language) => AttributeHelper<Language?>.GetAttribute(language)?.ShortName;
/// <summary>
/// Get the Language enum value for a given string
/// </summary>
/// <param name="lang">String value to convert</param>
/// <returns>Language represented by the string, if possible</returns>
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
/// <summary>
/// Get the string representation of the LanguageSelection enum values
/// </summary>
/// <param name="langSelect">LanguageSelection value to convert</param>
/// <returns>String representing the value, if possible</returns>
public static string LongName(this LanguageSelection? langSelect) => AttributeHelper<LanguageSelection?>.GetAttribute(langSelect)?.LongName;
#endregion
#region Region
/// <summary>
/// Get the Redump longnames for each known region
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
public static string LongName(this Region? region) => AttributeHelper<Region?>.GetAttribute(region)?.LongName;
/// <summary>
/// Get the Redump shortnames for each known region
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
public static string ShortName(this Region? region) => AttributeHelper<Region?>.GetAttribute(region)?.ShortName;
/// <summary>
/// Get the Region enum value for a given string
/// </summary>
/// <param name="region">String value to convert</param>
/// <returns>Region represented by the string, if possible</returns>
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
/// <summary>
/// Get the Redump longnames for each known system
/// </summary>
/// <param name="system"></param>
/// <returns></returns>
public static string LongName(this RedumpSystem? system) => AttributeHelper<RedumpSystem?>.GetAttribute(system)?.LongName;
/// <summary>
/// Get the Redump shortnames for each known system
/// </summary>
/// <param name="system"></param>
/// <returns></returns>
public static string ShortName(this RedumpSystem? system) => AttributeHelper<RedumpSystem?>.GetAttribute(system)?.ShortName;
/// <summary>
/// Determine if a system is restricted to dumpers
/// </summary>
public static bool IsBanned(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper<RedumpSystem?>.GetAttribute(system))?.IsBanned ?? false;
/// <summary>
/// Determine if a system has a CUE pack
/// </summary>
public static bool HasCues(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper<RedumpSystem?>.GetAttribute(system))?.HasCues ?? false;
/// <summary>
/// Determine if a system has a DAT
/// </summary>
public static bool HasDat(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper<RedumpSystem?>.GetAttribute(system))?.HasDat ?? false;
/// <summary>
/// Determine if a system has a decrypted keys pack
/// </summary>
public static bool HasDkeys(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper<RedumpSystem?>.GetAttribute(system))?.HasDkeys ?? false;
/// <summary>
/// Determine if a system has a GDI pack
/// </summary>
public static bool HasGdi(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper<RedumpSystem?>.GetAttribute(system))?.HasGdi ?? false;
/// <summary>
/// Determine if a system has a keys pack
/// </summary>
public static bool HasKeys(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper<RedumpSystem?>.GetAttribute(system))?.HasKeys ?? false;
/// <summary>
/// Determine if a system has an LSD pack
/// </summary>
public static bool HasLsd(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper<RedumpSystem?>.GetAttribute(system))?.HasLsd ?? false;
/// <summary>
/// Determine if a system has an SBI pack
/// </summary>
public static bool HasSbi(this RedumpSystem? system) => ((SystemAttribute)AttributeHelper<RedumpSystem?>.GetAttribute(system))?.HasSbi ?? false;
/// <summary>
/// Get the RedumpSystem enum value for a given string
/// </summary>
/// <param name="sys">String value to convert</param>
/// <returns>RedumpSystem represented by the string, if possible</returns>
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
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net48;netcoreapp3.1;net5.0</TargetFrameworks>
<PlatformTarget>x86</PlatformTarget>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>

View File

@@ -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();
/// <summary>
/// Determines if user is logged into Redump
/// </summary>
public bool LoggedIn { get; private set; } = false;
/// <summary>
/// Determines if the user is a staff member
/// </summary>
public bool IsStaff { get; private set; } = false;
/// <summary>
/// Get the last downloaded filename, if possible
/// </summary>
/// <returns></returns>
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("\"", "");
}
/// <inheritdoc/>
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;
}
/// <summary>
/// Login to Redump, if possible
/// </summary>
/// <param name="username">Redump username</param>
/// <param name="password">Redump password</param>
/// <returns>True if the user could be logged in, false otherwise, null on error</returns>
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
/// <summary>
/// Process a Redump site page as a list of possible IDs or disc page
/// </summary>
/// <param name="url">Base URL to download using</param>
/// <returns>List of IDs from the page, empty on error</returns>
public List<int> CheckSingleSitePage(string url)
{
List<int> ids = new List<int>();
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("<b>Download:</b>"))
{
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;
}
/// <summary>
/// Process a Redump site page as a list of possible IDs or disc page
/// </summary>
/// <param name="url">Base URL to download using</param>
/// <param name="outDir">Output directory to save data to</param>
/// <param name="failOnSingle">True to return on first error, false otherwise</param>
/// <returns>True if the page could be downloaded, false otherwise</returns>
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("<b>Download:</b>"))
{
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;
}
/// <summary>
/// Process a Redump WIP page as a list of possible IDs or disc page
/// </summary>
/// <param name="wc">RedumpWebClient to access the packs</param>
/// <returns>List of IDs from the page, empty on error</returns>
public List<int> CheckSingleWIPPage(string url)
{
List<int> ids = new List<int>();
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;
}
/// <summary>
/// Process a Redump WIP page as a list of possible IDs or disc page
/// </summary>
/// <param name="wc">RedumpWebClient to access the packs</param>
/// <param name="outDir">Output directory to save data to</param>
/// <param name="failOnSingle">True to return on first error, false otherwise</param>
/// <returns>True if the page could be downloaded, false otherwise</returns>
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
/// <summary>
/// Download a single pack
/// </summary>
/// <param name="url">Base URL to download using</param>
/// <param name="system">System to download packs for</param>
/// <returns>Byte array containing the downloaded pack, null on error</returns>
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;
}
}
/// <summary>
/// Download a single pack
/// </summary>
/// <param name="url">Base URL to download using</param>
/// <param name="system">System to download packs for</param>
/// <param name="outDir">Output directory to save data to</param>
/// <param name="subfolder">Named subfolder for the pack, used optionally</param>
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}");
}
}
/// <summary>
/// Download an individual site ID data, if possible
/// </summary>
/// <param name="id">Redump disc ID to retrieve</param>
/// <returns>String containing the page contents if successful, null on error</returns>
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;
}
}
/// <summary>
/// Download an individual site ID data, if possible
/// </summary>
/// <param name="id">Redump disc ID to retrieve</param>
/// <param name="outDir">Output directory to save data to</param>
/// <param name="rename">True to rename deleted entries, false otherwise</param>
/// <returns>True if all data was downloaded, false otherwise</returns>
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($"<a href=\"/disc/{id}/changes/\""))
DownloadFile(string.Format(Constants.DiscPageUrl, +id) + Constants.ChangesExt, Path.Combine(paddedIdDir, "changes.html"));
// CUE
if (discPage.Contains($"<a href=\"/disc/{id}/cue/\""))
DownloadFile(string.Format(Constants.DiscPageUrl, +id) + Constants.CueExt, Path.Combine(paddedIdDir, paddedId + ".cue"));
// Edit disc
if (discPage.Contains($"<a href=\"/disc/{id}/edit/\""))
DownloadFile(string.Format(Constants.DiscPageUrl, +id) + Constants.EditExt, Path.Combine(paddedIdDir, "edit.html"));
// GDI
if (discPage.Contains($"<a href=\"/disc/{id}/gdi/\""))
DownloadFile(string.Format(Constants.DiscPageUrl, +id) + Constants.GdiExt, Path.Combine(paddedIdDir, paddedId + ".gdi"));
// KEYS
if (discPage.Contains($"<a href=\"/disc/{id}/key/\""))
DownloadFile(string.Format(Constants.DiscPageUrl, +id) + Constants.KeyExt, Path.Combine(paddedIdDir, paddedId + ".key"));
// LSD
if (discPage.Contains($"<a href=\"/disc/{id}/lsd/\""))
DownloadFile(string.Format(Constants.DiscPageUrl, +id) + Constants.LsdExt, Path.Combine(paddedIdDir, paddedId + ".lsd"));
// MD5
if (discPage.Contains($"<a href=\"/disc/{id}/md5/\""))
DownloadFile(string.Format(Constants.DiscPageUrl, +id) + Constants.Md5Ext, Path.Combine(paddedIdDir, paddedId + ".md5"));
// Review WIP entry
if (Constants.NewDiscRegex.IsMatch(discPage))
{
var match = Constants.NewDiscRegex.Match(discPage);
DownloadFile(string.Format(Constants.WipDiscPageUrl, match.Groups[2].Value), Path.Combine(paddedIdDir, "newdisc.html"));
}
// SBI
if (discPage.Contains($"<a href=\"/disc/{id}/sbi/\""))
DownloadFile(string.Format(Constants.DiscPageUrl, +id) + Constants.SbiExt, Path.Combine(paddedIdDir, paddedId + ".sbi"));
// SFV
if (discPage.Contains($"<a href=\"/disc/{id}/sfv/\""))
DownloadFile(string.Format(Constants.DiscPageUrl, +id) + Constants.SfvExt, Path.Combine(paddedIdDir, paddedId + ".sfv"));
// SHA1
if (discPage.Contains($"<a href=\"/disc/{id}/sha1/\""))
DownloadFile(string.Format(Constants.DiscPageUrl, +id) + Constants.Sha1Ext, Path.Combine(paddedIdDir, paddedId + ".sha1"));
// HTML (Last in case of errors)
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;
}
}
/// <summary>
/// Download an individual WIP ID data, if possible
/// </summary>
/// <param name="id">Redump WIP disc ID to retrieve</param>
/// <returns>String containing the page contents if successful, null on error</returns>
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;
}
}
/// <summary>
/// Download an individual WIP ID data, if possible
/// </summary>
/// <param name="id">Redump WIP disc ID to retrieve</param>
/// <param name="outDir">Output directory to save data to</param>
/// <param name="rename">True to rename deleted entries, false otherwise</param>
/// <returns>True if all data was downloaded, false otherwise</returns>
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
/// <summary>
/// Download a set of packs
/// </summary>
/// <param name="url">Base URL to download using</param>
/// <param name="system">Systems to download packs for</param>
/// <param name="title">Name of the pack that is downloading</param>
public Dictionary<RedumpSystem, byte[]> DownloadPacks(string url, RedumpSystem?[] systems, string title)
{
var packsDictionary = new Dictionary<RedumpSystem, byte[]>();
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;
}
/// <summary>
/// Download a set of packs
/// </summary>
/// <param name="url">Base URL to download using</param>
/// <param name="system">Systems to download packs for</param>
/// <param name="title">Name of the pack that is downloading</param>
/// <param name="outDir">Output directory to save data to</param>
/// <param name="subfolder">Named subfolder for the pack, used optionally</param>
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();
}
/// <summary>
/// Move a tempfile to a new name unless it aleady exists, in which case, delete the tempfile
/// </summary>
/// <param name="tempfile">Path to existing temporary file</param>
/// <param name="newfile">Path to new output file</param>
/// <param name="outDir">Output directory to save data to</param>
/// <param name="subfolder">Optional subfolder to append to the path</param>
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
}
}