mirror of
https://github.com/SabreTools/SabreTools.RedumpLib.git
synced 2026-02-08 13:54:31 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
652270c8c7 | ||
|
|
905d8a94fb | ||
|
|
3ee8416695 | ||
|
|
49fa06da55 | ||
|
|
70e29afd89 | ||
|
|
2a402a53db |
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
|
||||
@@ -24,20 +24,20 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.10.0-release-24177-07" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0-release-24177-07" />
|
||||
<PackageReference Include="xunit" Version="2.8.0" />
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.11.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.13.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.8.0" />
|
||||
<PackageReference Include="xunit.core" Version="2.8.0" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.8.0" />
|
||||
<PackageReference Include="xunit.extensibility.execution" Version="2.8.0" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.8.0">
|
||||
<PackageReference Include="xunit.analyzers" Version="1.16.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.core" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.extensibility.execution" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.9.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.0">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
|
||||
namespace SabreTools.RedumpLib.Attributes
|
||||
{
|
||||
@@ -25,24 +27,36 @@ namespace SabreTools.RedumpLib.Attributes
|
||||
string? valueStr = value?.ToString();
|
||||
if (string.IsNullOrEmpty(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
|
||||
#if NET20 || NET35
|
||||
System.Reflection.MemberInfo? enumValueMemberInfo = null;
|
||||
foreach (var m in memberInfos)
|
||||
{
|
||||
if (m.DeclaringType != enumType)
|
||||
continue;
|
||||
|
||||
enumValueMemberInfo = m;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
var enumValueMemberInfo = memberInfos.FirstOrDefault(m => m.DeclaringType == enumType);
|
||||
#endif
|
||||
if (enumValueMemberInfo == null)
|
||||
return null;
|
||||
|
||||
|
||||
// Try to get the relevant attribute
|
||||
var attributes = enumValueMemberInfo.GetCustomAttributes(typeof(HumanReadableAttribute), true);
|
||||
if (attributes == null)
|
||||
if (attributes == null || attributes.Length == 0)
|
||||
return null;
|
||||
|
||||
|
||||
// Return the first attribute, if possible
|
||||
return attributes.FirstOrDefault() as HumanReadableAttribute;
|
||||
return attributes[0] as HumanReadableAttribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -269,22 +271,30 @@ namespace SabreTools.RedumpLib
|
||||
if (title != null && firstParenLocation >= 0)
|
||||
{
|
||||
info.CommonDiscInfo!.Title = title.Substring(0, firstParenLocation);
|
||||
var subMatches = Constants.DiscNumberLetterRegex.Matches(title);
|
||||
foreach (Match subMatch in subMatches.Cast<Match>())
|
||||
var submatches = Constants.DiscNumberLetterRegex.Matches(title);
|
||||
#if NET20 || NET35
|
||||
foreach (Match submatch in submatches)
|
||||
#else
|
||||
foreach (Match submatch in submatches.Cast<Match>())
|
||||
#endif
|
||||
{
|
||||
var subMatchValue = subMatch.Groups[1].Value;
|
||||
var submatchValue = submatch.Groups[1].Value;
|
||||
|
||||
// Disc number or letter
|
||||
if (subMatchValue.StartsWith("Disc"))
|
||||
info.CommonDiscInfo.DiscNumberLetter = subMatchValue.Remove(0, "Disc ".Length);
|
||||
if (submatchValue.StartsWith("Disc"))
|
||||
info.CommonDiscInfo.DiscNumberLetter = submatchValue.Remove(0, "Disc ".Length);
|
||||
|
||||
// Issue number
|
||||
else if (subMatchValue.All(c => char.IsNumber(c)))
|
||||
info.CommonDiscInfo.Title += $" ({subMatchValue})";
|
||||
#if NET20 || NET35
|
||||
else if (long.TryParse(submatchValue, out _))
|
||||
#else
|
||||
else if (submatchValue.All(c => char.IsNumber(c)))
|
||||
#endif
|
||||
info.CommonDiscInfo.Title += $" ({submatchValue})";
|
||||
|
||||
// Disc title
|
||||
else
|
||||
info.CommonDiscInfo.DiscTitle = subMatchValue;
|
||||
info.CommonDiscInfo.DiscTitle = submatchValue;
|
||||
}
|
||||
}
|
||||
// Otherwise, leave the title as-is
|
||||
@@ -321,12 +331,18 @@ namespace SabreTools.RedumpLib
|
||||
if (matches.Count > 0)
|
||||
{
|
||||
var tempLanguages = new List<Language?>();
|
||||
#if NET20 || NET35
|
||||
foreach (Match submatch in matches)
|
||||
#else
|
||||
foreach (Match submatch in matches.Cast<Match>())
|
||||
#endif
|
||||
{
|
||||
tempLanguages.Add(Extensions.ToLanguage(submatch.Groups[1].Value));
|
||||
var language = Extensions.ToLanguage(submatch.Groups[1].Value);
|
||||
if (language != null)
|
||||
tempLanguages.Add(language);
|
||||
}
|
||||
|
||||
info.CommonDiscInfo.Languages = tempLanguages.Where(l => l != null).ToArray();
|
||||
info.CommonDiscInfo.Languages = [.. tempLanguages];
|
||||
}
|
||||
|
||||
// Serial
|
||||
@@ -366,7 +382,11 @@ namespace SabreTools.RedumpLib
|
||||
tempDumpers.Add(dumper);
|
||||
}
|
||||
|
||||
#if NET20 || NET35
|
||||
foreach (Match submatch in matches)
|
||||
#else
|
||||
foreach (Match submatch in matches.Cast<Match>())
|
||||
#endif
|
||||
{
|
||||
string? dumper = WebUtility.HtmlDecode(submatch.Groups[1].Value);
|
||||
if (dumper != null)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
using SabreTools.RedumpLib.Attributes;
|
||||
|
||||
namespace SabreTools.RedumpLib.Data
|
||||
@@ -923,28 +925,71 @@ namespace SabreTools.RedumpLib.Data
|
||||
/// <returns>Language represented by the string, if possible</returns>
|
||||
public static Language? ToLanguage(string lang)
|
||||
{
|
||||
var languages = Enum.GetValues(typeof(Language)).Cast<Language?>().ToList();
|
||||
#if NET20 || NET35
|
||||
var languages = new List<Language?>();
|
||||
foreach (Language l in Enum.GetValues(typeof(Language)))
|
||||
{
|
||||
languages.Add(new Nullable<Language>(l));
|
||||
}
|
||||
#else
|
||||
var languages = Enum.GetValues(typeof(Language))
|
||||
.Cast<Language?>()
|
||||
.ToList();
|
||||
#endif
|
||||
|
||||
// Check ISO 639-1 codes
|
||||
#if NET20 || NET35
|
||||
var languageMapping = new Dictionary<string, Language?>();
|
||||
foreach (var l in languages)
|
||||
{
|
||||
if (l.TwoLetterCode() == null)
|
||||
continue;
|
||||
|
||||
languageMapping[l.TwoLetterCode() ?? string.Empty] = l;
|
||||
}
|
||||
#else
|
||||
Dictionary<string, Language?> languageMapping = languages
|
||||
.Where(l => l.TwoLetterCode() != null)
|
||||
.ToDictionary(l => l.TwoLetterCode() ?? string.Empty, l => l);
|
||||
#endif
|
||||
|
||||
if (languageMapping.ContainsKey(lang))
|
||||
return languageMapping[lang];
|
||||
|
||||
// Check standard ISO 639-2 codes
|
||||
#if NET20 || NET35
|
||||
languageMapping = new Dictionary<string, Language?>();
|
||||
foreach (var l in languages)
|
||||
{
|
||||
if (l.ThreeLetterCode() == null)
|
||||
continue;
|
||||
|
||||
languageMapping[l.ThreeLetterCode() ?? string.Empty] = l;
|
||||
}
|
||||
#else
|
||||
languageMapping = languages
|
||||
.Where(l => l.ThreeLetterCode() != null)
|
||||
.ToDictionary(l => l.ThreeLetterCode() ?? string.Empty, l => l);
|
||||
#endif
|
||||
|
||||
if (languageMapping.ContainsKey(lang))
|
||||
return languageMapping[lang];
|
||||
|
||||
// Check alternate ISO 639-2 codes
|
||||
#if NET20 || NET35
|
||||
languageMapping = new Dictionary<string, Language?>();
|
||||
foreach (var l in languages)
|
||||
{
|
||||
if (l.ThreeLetterCodeAlt() == null)
|
||||
continue;
|
||||
|
||||
languageMapping[l.ThreeLetterCodeAlt() ?? string.Empty] = l;
|
||||
}
|
||||
#else
|
||||
languageMapping = languages
|
||||
.Where(l => l.ThreeLetterCodeAlt() != null)
|
||||
.ToDictionary(l => l.ThreeLetterCodeAlt() ?? string.Empty, l => l);
|
||||
#endif
|
||||
|
||||
if (languageMapping.ContainsKey(lang))
|
||||
return languageMapping[lang];
|
||||
@@ -1069,12 +1114,33 @@ namespace SabreTools.RedumpLib.Data
|
||||
public static Region? ToRegion(string region)
|
||||
{
|
||||
region = region.ToLowerInvariant();
|
||||
var regions = Enum.GetValues(typeof(Region)).Cast<Region?>().ToList();
|
||||
#if NET20 || NET35
|
||||
var regions = new List<Region?>();
|
||||
foreach (Region r in Enum.GetValues(typeof(Region)))
|
||||
{
|
||||
regions.Add(new Nullable<Region>(r));
|
||||
}
|
||||
#else
|
||||
var regions = Enum.GetValues(typeof(Region))
|
||||
.Cast<Region?>()
|
||||
.ToList();
|
||||
#endif
|
||||
|
||||
// Check ISO 3166-1 alpha-2 codes
|
||||
#if NET20 || NET35
|
||||
var regionMapping = new Dictionary<string, Region?>();
|
||||
foreach (var r in regions)
|
||||
{
|
||||
if (r.ShortName() == null)
|
||||
continue;
|
||||
|
||||
regionMapping[r.ShortName()?.ToLowerInvariant() ?? string.Empty] = r;
|
||||
}
|
||||
#else
|
||||
Dictionary<string, Region?> regionMapping = regions
|
||||
.Where(r => r.ShortName() != null)
|
||||
.ToDictionary(r => r.ShortName()?.ToLowerInvariant() ?? string.Empty, r => r);
|
||||
#endif
|
||||
|
||||
if (regionMapping.ContainsKey(region))
|
||||
return regionMapping[region];
|
||||
@@ -1097,7 +1163,7 @@ namespace SabreTools.RedumpLib.Data
|
||||
{
|
||||
string? shortName = ((SiteCode?)val).ShortName()?.TrimEnd(':');
|
||||
string? longName = ((SiteCode?)val).LongName()?.TrimEnd(':');
|
||||
|
||||
|
||||
bool isCommentCode = ((SiteCode?)val).IsCommentCode();
|
||||
bool isContentCode = ((SiteCode?)val).IsContentCode();
|
||||
bool isMultiline = ((SiteCode?)val).IsMultiLine();
|
||||
@@ -1385,10 +1451,22 @@ namespace SabreTools.RedumpLib.Data
|
||||
{
|
||||
var systems = new List<string>();
|
||||
|
||||
#if NET20 || NET35
|
||||
var knownSystems = new List<RedumpSystem?>();
|
||||
foreach (RedumpSystem s in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
var ns = new Nullable<RedumpSystem>(s);
|
||||
if (ns != null && !ns.IsMarker() && ns.GetCategory() != SystemCategory.NONE)
|
||||
knownSystems.Add(ns);
|
||||
}
|
||||
|
||||
knownSystems.Sort((x, y) => (x.LongName() ?? string.Empty).CompareTo(y.LongName() ?? string.Empty));
|
||||
#else
|
||||
var knownSystems = Enum.GetValues(typeof(RedumpSystem))
|
||||
.OfType<RedumpSystem?>()
|
||||
.Where(s => s != null && !s.IsMarker() && s.GetCategory() != SystemCategory.NONE)
|
||||
.OrderBy(s => s.LongName() ?? string.Empty);
|
||||
#endif
|
||||
|
||||
foreach (var val in knownSystems)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
using Newtonsoft.Json;
|
||||
using SabreTools.RedumpLib.Converters;
|
||||
|
||||
@@ -73,6 +75,20 @@ namespace SabreTools.RedumpLib.Data
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
#if NET20 || NET35
|
||||
Dictionary<string, string>? artifacts = null;
|
||||
if (this.Artifacts != null)
|
||||
{
|
||||
artifacts = new Dictionary<string, string>();
|
||||
foreach (var kvp in this.Artifacts)
|
||||
{
|
||||
artifacts[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
#else
|
||||
var artifacts = this.Artifacts?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
#endif
|
||||
|
||||
return new SubmissionInfo
|
||||
{
|
||||
SchemaVersion = this.SchemaVersion,
|
||||
@@ -90,7 +106,7 @@ namespace SabreTools.RedumpLib.Data
|
||||
TracksAndWriteOffsets = this.TracksAndWriteOffsets?.Clone() as TracksAndWriteOffsetsSection,
|
||||
SizeAndChecksums = this.SizeAndChecksums?.Clone() as SizeAndChecksumsSection,
|
||||
DumpingInfo = this.DumpingInfo?.Clone() as DumpingInfoSection,
|
||||
Artifacts = this.Artifacts?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
|
||||
Artifacts = artifacts,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -233,6 +249,31 @@ namespace SabreTools.RedumpLib.Data
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
#if NET20 || NET35
|
||||
Dictionary<SiteCode, string>? commentsSpecialFields = null;
|
||||
if (this.CommentsSpecialFields != null)
|
||||
{
|
||||
commentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
foreach (var kvp in this.CommentsSpecialFields)
|
||||
{
|
||||
commentsSpecialFields[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<SiteCode, string>? contentsSpecialFields = null;
|
||||
if (this.ContentsSpecialFields != null)
|
||||
{
|
||||
contentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
foreach (var kvp in this.ContentsSpecialFields)
|
||||
{
|
||||
contentsSpecialFields[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
#else
|
||||
var commentsSpecialFields = this.CommentsSpecialFields?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
var contentsSpecialFields = this.ContentsSpecialFields?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
#endif
|
||||
|
||||
return new CommonDiscInfoSection
|
||||
{
|
||||
System = this.System,
|
||||
@@ -271,9 +312,9 @@ namespace SabreTools.RedumpLib.Data
|
||||
EXEDateBuildDate = this.EXEDateBuildDate,
|
||||
ErrorsCount = this.ErrorsCount,
|
||||
Comments = this.Comments,
|
||||
CommentsSpecialFields = this.CommentsSpecialFields?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
|
||||
CommentsSpecialFields = commentsSpecialFields,
|
||||
Contents = this.Contents,
|
||||
ContentsSpecialFields = this.ContentsSpecialFields?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
|
||||
ContentsSpecialFields = contentsSpecialFields,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -414,13 +455,27 @@ namespace SabreTools.RedumpLib.Data
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
#if NET20 || NET35
|
||||
Dictionary<string, List<string>?>? fullProtections = null;
|
||||
if (this.FullProtections != null)
|
||||
{
|
||||
fullProtections = new Dictionary<string, List<string>?>();
|
||||
foreach (var kvp in this.FullProtections)
|
||||
{
|
||||
fullProtections[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
#else
|
||||
var fullProtections = this.FullProtections?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
#endif
|
||||
|
||||
return new CopyProtectionSection
|
||||
{
|
||||
AntiModchip = this.AntiModchip,
|
||||
LibCrypt = this.LibCrypt,
|
||||
LibCryptData = this.LibCryptData,
|
||||
Protection = this.Protection,
|
||||
FullProtections = this.FullProtections?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
|
||||
FullProtections = fullProtections,
|
||||
SecuROMData = this.SecuROMData,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Text.RegularExpressions;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
@@ -14,11 +16,14 @@ namespace SabreTools.RedumpLib
|
||||
/// <param name="info">Information object that should contain normalized values</param>
|
||||
/// <param name="enableRedumpCompatibility">True to enable Redump compatiblity, false otherwise</param>
|
||||
/// <returns>List of strings representing each line of an output file, null on error</returns>
|
||||
public static (List<string>?, string?) FormatOutputData(SubmissionInfo? info, bool enableRedumpCompatibility)
|
||||
public static List<string>? FormatOutputData(SubmissionInfo? info, bool enableRedumpCompatibility, out string? status)
|
||||
{
|
||||
// Check to see if the inputs are valid
|
||||
if (info == null)
|
||||
return (null, "Submission information was missing");
|
||||
{
|
||||
status = "Submission information was missing";
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -55,8 +60,28 @@ namespace SabreTools.RedumpLib
|
||||
AddIfExists(output, Template.FullyMatchingIDField, info.FullyMatchedID?.ToString(), 1);
|
||||
AddIfExists(output, Template.PartiallyMatchingIDsField, info.PartiallyMatchedIDs, 1);
|
||||
AddIfExists(output, Template.RegionField, info.CommonDiscInfo?.Region.LongName() ?? "SPACE! (CHANGE THIS)", 1);
|
||||
#if NET20 || NET35
|
||||
var languages = info.CommonDiscInfo?.Languages ?? [null];
|
||||
var languageStrings = new List<string>();
|
||||
foreach (var l in languages)
|
||||
{
|
||||
languageStrings.Add(l.LongName() ?? "SILENCE! (CHANGE THIS)");
|
||||
}
|
||||
|
||||
AddIfExists(output, Template.LanguagesField, languageStrings.ToArray(), 1);
|
||||
|
||||
var langaugeSelections = info.CommonDiscInfo?.LanguageSelection ?? [];
|
||||
var languageSelectionStrings = new List<string?>();
|
||||
foreach (var l in langaugeSelections)
|
||||
{
|
||||
languageSelectionStrings.Add(l.LongName());
|
||||
}
|
||||
|
||||
AddIfExists(output, Template.PlaystationLanguageSelectionViaField, languageSelectionStrings.ToArray(), 1);
|
||||
#else
|
||||
AddIfExists(output, Template.LanguagesField, (info.CommonDiscInfo?.Languages ?? [null]).Select(l => l.LongName() ?? "SILENCE! (CHANGE THIS)").ToArray(), 1);
|
||||
AddIfExists(output, Template.PlaystationLanguageSelectionViaField, (info.CommonDiscInfo?.LanguageSelection ?? []).Select(l => l.LongName()).ToArray(), 1);
|
||||
#endif
|
||||
AddIfExists(output, Template.DiscSerialField, info.CommonDiscInfo?.Serial, 1);
|
||||
|
||||
// All ringcode information goes in an indented area
|
||||
@@ -254,11 +279,13 @@ namespace SabreTools.RedumpLib
|
||||
}
|
||||
}
|
||||
|
||||
return (output, "Formatting complete!");
|
||||
status = "Formatting complete!";
|
||||
return output;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (null, $"Error formatting submission info: {ex}");
|
||||
status = $"Error formatting submission info: {ex}";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,13 +300,31 @@ namespace SabreTools.RedumpLib
|
||||
return;
|
||||
|
||||
// Process the comments field
|
||||
if (info.CommonDiscInfo?.CommentsSpecialFields != null && info.CommonDiscInfo.CommentsSpecialFields?.Any() == true)
|
||||
if (info.CommonDiscInfo?.CommentsSpecialFields != null && info.CommonDiscInfo.CommentsSpecialFields.Count > 0)
|
||||
{
|
||||
// If the field is missing, add an empty one to fill in
|
||||
if (info.CommonDiscInfo.Comments == null)
|
||||
info.CommonDiscInfo.Comments = string.Empty;
|
||||
|
||||
// Add all special fields before any comments
|
||||
#if NET20 || NET35
|
||||
var orderedCommentTags = OrderCommentTags(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
var commentTagStrings = new List<string>();
|
||||
foreach (var kvp in orderedCommentTags)
|
||||
{
|
||||
if (string.IsNullOrEmpty(kvp.Value))
|
||||
continue;
|
||||
|
||||
string? formatted = FormatSiteTag(kvp);
|
||||
if (formatted == null)
|
||||
continue;
|
||||
|
||||
commentTagStrings.Add(formatted);
|
||||
}
|
||||
|
||||
info.CommonDiscInfo.Comments = string.Join("\n", commentTagStrings.ToArray())
|
||||
+ "\n" + info.CommonDiscInfo.Comments;
|
||||
#else
|
||||
info.CommonDiscInfo.Comments = string.Join(
|
||||
"\n", OrderCommentTags(info.CommonDiscInfo.CommentsSpecialFields)
|
||||
.Where(kvp => !string.IsNullOrEmpty(kvp.Value))
|
||||
@@ -287,6 +332,7 @@ namespace SabreTools.RedumpLib
|
||||
.Where(s => !string.IsNullOrEmpty(s))
|
||||
.ToArray()
|
||||
) + "\n" + info.CommonDiscInfo.Comments;
|
||||
#endif
|
||||
|
||||
// Normalize newlines
|
||||
info.CommonDiscInfo.Comments = info.CommonDiscInfo.Comments.Replace("\r\n", "\n");
|
||||
@@ -299,13 +345,31 @@ namespace SabreTools.RedumpLib
|
||||
}
|
||||
|
||||
// Process the contents field
|
||||
if (info.CommonDiscInfo?.ContentsSpecialFields != null && info.CommonDiscInfo.ContentsSpecialFields?.Any() == true)
|
||||
if (info.CommonDiscInfo?.ContentsSpecialFields != null && info.CommonDiscInfo.ContentsSpecialFields.Count > 0)
|
||||
{
|
||||
// If the field is missing, add an empty one to fill in
|
||||
if (info.CommonDiscInfo.Contents == null)
|
||||
info.CommonDiscInfo.Contents = string.Empty;
|
||||
|
||||
// Add all special fields before any contents
|
||||
#if NET20 || NET35
|
||||
var orderedContentTags = OrderContentTags(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
var contentTagStrings = new List<string>();
|
||||
foreach (var kvp in orderedContentTags)
|
||||
{
|
||||
if (string.IsNullOrEmpty(kvp.Value))
|
||||
continue;
|
||||
|
||||
string? formatted = FormatSiteTag(kvp);
|
||||
if (formatted == null)
|
||||
continue;
|
||||
|
||||
contentTagStrings.Add(formatted);
|
||||
}
|
||||
|
||||
info.CommonDiscInfo.Contents = string.Join("\n", contentTagStrings.ToArray())
|
||||
+ "\n" + info.CommonDiscInfo.Contents;
|
||||
#else
|
||||
info.CommonDiscInfo.Contents = string.Join(
|
||||
"\n", OrderContentTags(info.CommonDiscInfo.ContentsSpecialFields)
|
||||
.Where(kvp => !string.IsNullOrEmpty(kvp.Value))
|
||||
@@ -313,6 +377,7 @@ namespace SabreTools.RedumpLib
|
||||
.Where(s => !string.IsNullOrEmpty(s))
|
||||
.ToArray()
|
||||
) + "\n" + info.CommonDiscInfo.Contents;
|
||||
#endif
|
||||
|
||||
// Normalize newlines
|
||||
info.CommonDiscInfo.Contents = info.CommonDiscInfo.Contents.Replace("\r\n", "\n");
|
||||
@@ -360,7 +425,11 @@ namespace SabreTools.RedumpLib
|
||||
|
||||
// If the value contains a newline
|
||||
value = value.Replace("\r\n", "\n");
|
||||
#if NET20 || NET35
|
||||
if (value.Contains("\n"))
|
||||
#else
|
||||
if (value.Contains('\n'))
|
||||
#endif
|
||||
{
|
||||
output.Add(prefix + key + ":"); output.Add("");
|
||||
string[] values = value.Split('\n');
|
||||
@@ -426,7 +495,17 @@ namespace SabreTools.RedumpLib
|
||||
if (value == null || value.Count == 0)
|
||||
return;
|
||||
|
||||
#if NET20 || NET35
|
||||
var valueStrings = new List<string>();
|
||||
foreach (int o in value)
|
||||
{
|
||||
valueStrings.Add(o.ToString());
|
||||
}
|
||||
|
||||
AddIfExists(output, key, string.Join(", ", valueStrings.ToArray()), indent);
|
||||
#else
|
||||
AddIfExists(output, key, string.Join(", ", value.Select(o => o.ToString()).ToArray()), indent);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.RedumpLib
|
||||
@@ -40,8 +39,13 @@ namespace SabreTools.RedumpLib
|
||||
new StringBuilder(256) :
|
||||
new StringBuilder(value.Length);
|
||||
|
||||
sb.Append(valueSpan.Take(index).ToArray());
|
||||
HtmlDecode(valueSpan.Skip(index).ToArray(), ref sb);
|
||||
char[] take = new char[index];
|
||||
Array.Copy(valueSpan, take, index);
|
||||
sb.Append(take);
|
||||
|
||||
char[] skip = new char[valueSpan.Length - index];
|
||||
Array.Copy(valueSpan, index, skip, 0, skip.Length);
|
||||
HtmlDecode(skip, ref sb);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
@@ -57,7 +61,8 @@ namespace SabreTools.RedumpLib
|
||||
// We found a '&'. Now look for the next ';' or '&'. The idea is that
|
||||
// if we find another '&' before finding a ';', then this is not an entity,
|
||||
// and the next '&' might start a real entity (VSWhidbey 275184)
|
||||
char[] inputSlice = input.Skip(i + 1).ToArray();
|
||||
char[] inputSlice = new char[input.Length - (i + 1)];
|
||||
Array.Copy(input, i + 1, inputSlice, 0, inputSlice.Length);
|
||||
|
||||
int semicolonPos = Array.IndexOf(inputSlice, ';');
|
||||
int ampersandPos = Array.IndexOf(inputSlice, '&');
|
||||
@@ -81,9 +86,13 @@ namespace SabreTools.RedumpLib
|
||||
// å --> same char in hex
|
||||
// See http://www.w3.org/TR/REC-html40/charset.html#entities
|
||||
|
||||
int offset = inputSlice[1] == 'x' || inputSlice[1] == 'X' ? 2 : 1;
|
||||
char[] inputSliceNoPrefix = new char[entityLength - offset];
|
||||
Array.Copy(inputSlice, offset, inputSliceNoPrefix, 0, inputSliceNoPrefix.Length);
|
||||
|
||||
bool parsedSuccessfully = inputSlice[1] == 'x' || inputSlice[1] == 'X'
|
||||
? uint.TryParse(new string(inputSlice.Skip(2).Take(entityLength - 2).ToArray()), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out uint parsedValue)
|
||||
: uint.TryParse(new string(inputSlice.Skip(1).Take(entityLength - 1).ToArray()), NumberStyles.Integer, CultureInfo.InvariantCulture, out parsedValue);
|
||||
? uint.TryParse(new string(inputSliceNoPrefix), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out uint parsedValue)
|
||||
: uint.TryParse(new string(inputSliceNoPrefix), NumberStyles.Integer, CultureInfo.InvariantCulture, out parsedValue);
|
||||
|
||||
if (parsedSuccessfully)
|
||||
{
|
||||
@@ -112,7 +121,8 @@ namespace SabreTools.RedumpLib
|
||||
}
|
||||
else
|
||||
{
|
||||
char[] entity = inputSlice.Take(entityLength).ToArray();
|
||||
char[] entity = new char[entityLength];
|
||||
Array.Copy(inputSlice, entity, entityLength);
|
||||
i = entityEndPosition; // already looked at everything until semicolon
|
||||
char entityChar = HtmlEntities.Lookup(entity);
|
||||
|
||||
@@ -414,7 +424,10 @@ namespace SabreTools.RedumpLib
|
||||
ulong key = BitConverter.ToUInt64(tableData, 0);
|
||||
char value = (char)BitConverter.ToUInt16(tableData, sizeof(ulong));
|
||||
dictionary[key] = value;
|
||||
tableData = tableData.Skip((sizeof(ulong) + sizeof(char))).ToArray();
|
||||
|
||||
byte[] tempTableData = new byte[tableData.Length - (sizeof(ulong) + sizeof(char))];
|
||||
Array.Copy(tableData, (sizeof(ulong) + sizeof(char)), tempTableData, 0, tempTableData.Length);
|
||||
tableData = tempTableData;
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>1.4.1</Version>
|
||||
<Version>1.4.2</Version>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
@@ -26,21 +26,16 @@
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Support for old .NET versions -->
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`))">
|
||||
<PackageReference Include="MinValueTupleBridge" Version="0.2.1" />
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`))">
|
||||
<PackageReference Include="Net30.LinqBridge" Version="1.3.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))">
|
||||
<PackageReference Include="MinAsyncBridge" Version="0.12.4" />
|
||||
<PackageReference Include="MinThreadingBridge" Version="0.11.4" />
|
||||
<PackageReference Include="Net30.LinqBridge" Version="1.3.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net4`))">
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.8" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.10" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Threading.Tasks;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Web;
|
||||
@@ -130,27 +132,27 @@ namespace SabreTools.RedumpLib
|
||||
/// <param name="rc">RedumpClient for making the connection</param>
|
||||
/// <param name="info">Existing SubmissionInfo object to fill</param>
|
||||
/// <param name="sha1">SHA-1 hash to check against</param>
|
||||
/// <returns>True if the track was found, false otherwise; List of found values, if possible</returns>
|
||||
public async static Task<(bool, List<int>?, string?)> ValidateSingleTrack(RedumpClient rc, SubmissionInfo info, string? sha1)
|
||||
/// <returns>List of found values, if possible</returns>
|
||||
public async static Task<List<int>?> ValidateSingleTrack(RedumpClient rc, SubmissionInfo info, string? sha1)
|
||||
{
|
||||
// Get all matching IDs for the track
|
||||
var newIds = await ListSearchResults(rc, sha1);
|
||||
|
||||
// If we got null back, there was an error
|
||||
if (newIds == null)
|
||||
return (false, null, "There was an unknown error retrieving information from Redump");
|
||||
return null;
|
||||
|
||||
// If no IDs match, just return
|
||||
if (!newIds.Any())
|
||||
return (false, null, $"There were no matching IDs for track with SHA-1 of '{sha1}'");
|
||||
if (newIds.Count == 0)
|
||||
return null;
|
||||
|
||||
// Join the list of found IDs to the existing list, if possible
|
||||
if (info.PartiallyMatchedIDs != null && info.PartiallyMatchedIDs.Any())
|
||||
if (info.PartiallyMatchedIDs != null && info.PartiallyMatchedIDs.Count > 0)
|
||||
info.PartiallyMatchedIDs.AddRange(newIds);
|
||||
else
|
||||
info.PartiallyMatchedIDs = newIds;
|
||||
|
||||
return (true, newIds, $"There were matching ID(s) found for track with SHA-1 of '{sha1}'");
|
||||
return newIds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -159,17 +161,17 @@ namespace SabreTools.RedumpLib
|
||||
/// <param name="rc">RedumpClient for making the connection</param>
|
||||
/// <param name="info">Existing SubmissionInfo object to fill</param>
|
||||
/// <param name="resultProgress">Optional result progress callback</param>
|
||||
/// <returns>True if the track was found, false otherwise; List of found values, if possible</returns>
|
||||
public async static Task<(bool, List<int>?, string?)> ValidateUniversalHash(RedumpClient rc, SubmissionInfo info)
|
||||
/// <returns>List of found values, if possible</returns>
|
||||
public async static Task<List<int>?> ValidateUniversalHash(RedumpClient rc, SubmissionInfo info)
|
||||
{
|
||||
// If we don't have special fields
|
||||
if (info.CommonDiscInfo?.CommentsSpecialFields == null)
|
||||
return (false, null, "Universal hash was missing");
|
||||
return null;
|
||||
|
||||
// If we don't have a universal hash
|
||||
string? universalHash = info.CommonDiscInfo.CommentsSpecialFields[SiteCode.UniversalHash];
|
||||
if (string.IsNullOrEmpty(universalHash))
|
||||
return (false, null, "Universal hash was missing");
|
||||
return null;
|
||||
|
||||
// Format the universal hash for finding within the comments
|
||||
string universalHashQuery = $"{universalHash.Substring(0, universalHash.Length - 1)}/comments/only";
|
||||
@@ -179,19 +181,19 @@ namespace SabreTools.RedumpLib
|
||||
|
||||
// If we got null back, there was an error
|
||||
if (newIds == null)
|
||||
return (false, null, "There was an unknown error retrieving information from Redump");
|
||||
return null;
|
||||
|
||||
// If no IDs match, just return
|
||||
if (!newIds.Any())
|
||||
return (false, null, $"There were no matching IDs for universal hash of '{universalHash}'");
|
||||
if (newIds.Count == 0)
|
||||
return null;
|
||||
|
||||
// Join the list of found IDs to the existing list, if possible
|
||||
if (info.PartiallyMatchedIDs != null && info.PartiallyMatchedIDs.Any())
|
||||
if (info.PartiallyMatchedIDs != null && info.PartiallyMatchedIDs.Count > 0)
|
||||
info.PartiallyMatchedIDs.AddRange(newIds);
|
||||
else
|
||||
info.PartiallyMatchedIDs = newIds;
|
||||
|
||||
return (true, newIds, $"There were matching ID(s) found for universal hash of '{universalHash}'");
|
||||
return newIds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
using System;
|
||||
#if NET20 || NET35
|
||||
using System.Collections.Generic;
|
||||
#endif
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Threading.Tasks;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
@@ -18,12 +23,84 @@ namespace SabreTools.RedumpLib.Web
|
||||
/// <param name="useSubfolders">True to use named subfolders to store downloads, false to store directly in the output directory</param>
|
||||
public static async Task<bool> DownloadPacks(RedumpClient rc, string? outDir, bool useSubfolders)
|
||||
{
|
||||
#if NETFRAMEWORK || NETCOREAPP3_1
|
||||
var systems = Enum.GetValues(typeof(RedumpSystem)).OfType<RedumpSystem>().Select(s => new Nullable<RedumpSystem>(s));
|
||||
#if NET20 || NET35
|
||||
var systems = new List<RedumpSystem?>();
|
||||
foreach (RedumpSystem s in Enum.GetValues(typeof(RedumpSystem)))
|
||||
{
|
||||
systems.Add(new Nullable<RedumpSystem>(s));
|
||||
}
|
||||
#elif NET40_OR_GREATER || NETCOREAPP3_1
|
||||
var systems = Enum.GetValues(typeof(RedumpSystem))
|
||||
.OfType<RedumpSystem>()
|
||||
.Select(s => new Nullable<RedumpSystem>(s));
|
||||
#else
|
||||
var systems = Enum.GetValues<RedumpSystem>().Select(s => new RedumpSystem?(s));
|
||||
#endif
|
||||
|
||||
#if NET20 || NET35
|
||||
var filtered = new List<RedumpSystem?>();
|
||||
foreach (var s in systems)
|
||||
{
|
||||
if (s.HasCues())
|
||||
filtered.Add(s);
|
||||
}
|
||||
await rc.DownloadPacks(Constants.PackCuesUrl, filtered.ToArray(), "CUEs", outDir, useSubfolders ? "cue" : null);
|
||||
|
||||
filtered = new List<RedumpSystem?>();
|
||||
foreach (var s in systems)
|
||||
{
|
||||
if (s.HasDat())
|
||||
filtered.Add(s);
|
||||
}
|
||||
await rc.DownloadPacks(Constants.PackDatfileUrl, filtered.ToArray(), "DATs", outDir, useSubfolders ? "dat" : null);
|
||||
|
||||
filtered = new List<RedumpSystem?>();
|
||||
foreach (var s in systems)
|
||||
{
|
||||
if (s.HasCues())
|
||||
filtered.Add(s);
|
||||
}
|
||||
|
||||
filtered = new List<RedumpSystem?>();
|
||||
foreach (var s in systems)
|
||||
{
|
||||
if (s.HasDkeys())
|
||||
filtered.Add(s);
|
||||
}
|
||||
await rc.DownloadPacks(Constants.PackDkeysUrl, filtered.ToArray(), "Decrypted KEYS", outDir, useSubfolders ? "dkey" : null);
|
||||
|
||||
filtered = new List<RedumpSystem?>();
|
||||
foreach (var s in systems)
|
||||
{
|
||||
if (s.HasGdi())
|
||||
filtered.Add(s);
|
||||
}
|
||||
await rc.DownloadPacks(Constants.PackGdiUrl, filtered.ToArray(), "GDIs", outDir, useSubfolders ? "gdi" : null);
|
||||
|
||||
filtered = new List<RedumpSystem?>();
|
||||
foreach (var s in systems)
|
||||
{
|
||||
if (s.HasKeys())
|
||||
filtered.Add(s);
|
||||
}
|
||||
await rc.DownloadPacks(Constants.PackKeysUrl, filtered.ToArray(), "KEYS", outDir, useSubfolders ? "keys" : null);
|
||||
|
||||
filtered = new List<RedumpSystem?>();
|
||||
foreach (var s in systems)
|
||||
{
|
||||
if (s.HasLsd())
|
||||
filtered.Add(s);
|
||||
}
|
||||
await rc.DownloadPacks(Constants.PackLsdUrl, filtered.ToArray(), "LSD", outDir, useSubfolders ? "lsd" : null);
|
||||
|
||||
filtered = new List<RedumpSystem?>();
|
||||
foreach (var s in systems)
|
||||
{
|
||||
if (s.HasSbi())
|
||||
filtered.Add(s);
|
||||
}
|
||||
await rc.DownloadPacks(Constants.PackSbiUrl, filtered.ToArray(), "SBIs", outDir, useSubfolders ? "sbi" : null);
|
||||
#else
|
||||
await rc.DownloadPacks(Constants.PackCuesUrl, systems.Where(s => s.HasCues()).ToArray(), "CUEs", outDir, useSubfolders ? "cue" : null);
|
||||
await rc.DownloadPacks(Constants.PackDatfileUrl, systems.Where(s => s.HasDat()).ToArray(), "DATs", outDir, useSubfolders ? "dat" : null);
|
||||
await rc.DownloadPacks(Constants.PackDkeysUrl, systems.Where(s => s.HasDkeys()).ToArray(), "Decrypted KEYS", outDir, useSubfolders ? "dkey" : null);
|
||||
@@ -31,6 +108,7 @@ namespace SabreTools.RedumpLib.Web
|
||||
await rc.DownloadPacks(Constants.PackKeysUrl, systems.Where(s => s.HasKeys()).ToArray(), "KEYS", outDir, useSubfolders ? "keys" : null);
|
||||
await rc.DownloadPacks(Constants.PackLsdUrl, systems.Where(s => s.HasLsd()).ToArray(), "LSD", outDir, useSubfolders ? "lsd" : null);
|
||||
await rc.DownloadPacks(Constants.PackSbiUrl, systems.Where(s => s.HasSbi()).ToArray(), "SBIs", outDir, useSubfolders ? "sbi" : null);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Net;
|
||||
#if NETCOREAPP
|
||||
using System.Net.Http;
|
||||
@@ -74,22 +76,22 @@ namespace SabreTools.RedumpLib.Web
|
||||
/// <summary>
|
||||
/// Validate supplied credentials
|
||||
/// </summary>
|
||||
public async static Task<(bool?, string?)> ValidateCredentials(string username, string password)
|
||||
public async static Task<bool?> ValidateCredentials(string username, string password)
|
||||
{
|
||||
// If options are invalid or we're missing something key, just return
|
||||
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
|
||||
return (false, null);
|
||||
return false;
|
||||
|
||||
// Try logging in with the supplied credentials otherwise
|
||||
var redumpClient = new RedumpClient();
|
||||
|
||||
bool? loggedIn = await redumpClient.Login(username, password);
|
||||
if (loggedIn == true)
|
||||
return (true, "Redump username and password accepted!");
|
||||
return true;
|
||||
else if (loggedIn == false)
|
||||
return (false, "Redump username and password denied!");
|
||||
return false;
|
||||
else
|
||||
return (null, "An error occurred validating your credentials!");
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -217,7 +219,11 @@ namespace SabreTools.RedumpLib.Web
|
||||
|
||||
// Otherwise, traverse each dump on the page
|
||||
var matches = Constants.DiscRegex.Matches(dumpsPage);
|
||||
#if NET20 || NET35
|
||||
foreach (Match? match in matches)
|
||||
#else
|
||||
foreach (Match? match in matches.Cast<Match?>())
|
||||
#endif
|
||||
{
|
||||
if (match == null)
|
||||
continue;
|
||||
@@ -269,7 +275,11 @@ namespace SabreTools.RedumpLib.Web
|
||||
|
||||
// Otherwise, traverse each dump on the page
|
||||
var matches = Constants.DiscRegex.Matches(dumpsPage);
|
||||
#if NET20 || NET35
|
||||
foreach (Match? match in matches)
|
||||
#else
|
||||
foreach (Match? match in matches.Cast<Match?>())
|
||||
#endif
|
||||
{
|
||||
if (match == null)
|
||||
continue;
|
||||
@@ -311,7 +321,11 @@ namespace SabreTools.RedumpLib.Web
|
||||
|
||||
// Otherwise, traverse each dump on the page
|
||||
var matches = Constants.NewDiscRegex.Matches(dumpsPage);
|
||||
#if NET20 || NET35
|
||||
foreach (Match? match in matches)
|
||||
#else
|
||||
foreach (Match? match in matches.Cast<Match?>())
|
||||
#endif
|
||||
{
|
||||
if (match == null)
|
||||
continue;
|
||||
@@ -349,7 +363,11 @@ namespace SabreTools.RedumpLib.Web
|
||||
|
||||
// Otherwise, traverse each dump on the page
|
||||
var matches = Constants.NewDiscRegex.Matches(dumpsPage);
|
||||
#if NET20 || NET35
|
||||
foreach (Match? match in matches)
|
||||
#else
|
||||
foreach (Match? match in matches.Cast<Match?>())
|
||||
#endif
|
||||
{
|
||||
if (match == null)
|
||||
continue;
|
||||
|
||||
36
publish-nix.sh
Normal file
36
publish-nix.sh
Normal file
@@ -0,0 +1,36 @@
|
||||
#! /bin/bash
|
||||
|
||||
# This batch file assumes the following:
|
||||
# - .NET 8.0 (or newer) SDK is installed and in PATH
|
||||
#
|
||||
# If any of these are not satisfied, the operation may fail
|
||||
# in an unpredictable way and result in an incomplete output.
|
||||
|
||||
# Optional parameters
|
||||
NO_BUILD=false
|
||||
while getopts "uba" OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
b)
|
||||
NO_BUILD=true
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option provided"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Set the current directory as a variable
|
||||
BUILD_FOLDER=$PWD
|
||||
|
||||
# Only build if requested
|
||||
if [ $NO_BUILD = false ]
|
||||
then
|
||||
# Restore Nuget packages for all builds
|
||||
echo "Restoring Nuget packages"
|
||||
dotnet restore
|
||||
|
||||
# Create Nuget Package
|
||||
dotnet pack SabreTools.RedumpLib/SabreTools.RedumpLib.csproj --output $BUILD_FOLDER
|
||||
fi
|
||||
26
publish-win.ps1
Normal file
26
publish-win.ps1
Normal file
@@ -0,0 +1,26 @@
|
||||
# This batch file assumes the following:
|
||||
# - .NET 8.0 (or newer) SDK is installed and in PATH
|
||||
#
|
||||
# If any of these are not satisfied, the operation may fail
|
||||
# in an unpredictable way and result in an incomplete output.
|
||||
|
||||
# Optional parameters
|
||||
param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[Alias("NoBuild")]
|
||||
[switch]$NO_BUILD
|
||||
)
|
||||
|
||||
# Set the current directory as a variable
|
||||
$BUILD_FOLDER = $PSScriptRoot
|
||||
|
||||
# Only build if requested
|
||||
if (!$NO_BUILD.IsPresent)
|
||||
{
|
||||
# Restore Nuget packages for all builds
|
||||
Write-Host "Restoring Nuget packages"
|
||||
dotnet restore
|
||||
|
||||
# Create Nuget Package
|
||||
dotnet pack SabreTools.RedumpLib\SabreTools.RedumpLib.csproj --output $BUILD_FOLDER
|
||||
}
|
||||
Reference in New Issue
Block a user