Compare commits

...

18 Commits
1.9.0 ... main

Author SHA1 Message Date
Matt Nadareski
30789237f1 Formatting cleanup 2026-02-02 09:14:27 -05:00
Deterous
0b309e1cb8 Return empty list for no ID matches (#14)
* Return empty list for no ID matches

* fix

* Deal with null
2026-02-02 09:02:39 -05:00
Matt Nadareski
e832723b40 Add Psion as non-redump system 2026-01-29 12:27:26 -05:00
Matt Nadareski
d5e013344e Bump version 2026-01-27 13:45:52 -05:00
Matt Nadareski
dfeb8cc269 Use TheoryData type in tests, cleanup 2026-01-26 23:48:23 -05:00
Matt Nadareski
a5190b0a9b Use new null checking syntax 2026-01-25 17:01:14 -05:00
Matt Nadareski
2077eb647a Framework gate pragma disable 2026-01-25 16:41:08 -05:00
Matt Nadareski
4c2303ff25 Add editorconfig, fix issues 2026-01-25 16:32:02 -05:00
Matt Nadareski
43ca04363c Fix whitespace 2026-01-24 09:47:43 -05:00
Matt Nadareski
41883cf4a3 Fix ordering to be alphabetical 2026-01-24 09:23:54 -05:00
HeroponRikiBestest
07b529e9e5 Add Steam AppID and DepotID tags (#13)
* Initial commit

* Fix format

* Fix naming

* Minor formatting fixes
2026-01-24 09:22:39 -05:00
Matt Nadareski
53fd163f82 Add 2K Games ID 2026-01-22 13:37:12 -05:00
Matt Nadareski
a2b9fd1095 Fix extension test 2026-01-19 00:00:57 -05:00
Matt Nadareski
063e9739f0 Add even more non-redump systems 2026-01-18 22:09:05 -05:00
Matt Nadareski
5193300c67 Add Sega Nu 1.1 and 2 as systems 2026-01-17 21:32:43 -05:00
Matt Nadareski
65e34e55cd Add raw cuesheet bytes 2025-12-10 08:39:21 -05:00
Matt Nadareski
f66c81bbf0 Format GHA definitions 2025-11-17 08:37:00 -05:00
Matt Nadareski
6b015f91d6 Fix one property group 2025-11-13 20:38:51 -05:00
27 changed files with 2978 additions and 2660 deletions

167
.editorconfig Normal file
View File

@@ -0,0 +1,167 @@
# top-most EditorConfig file
root = true
# C# files
[*.cs]
# Indentation and spacing
charset = utf-8
indent_size = 4
indent_style = space
tab_width = 4
trim_trailing_whitespace = true
# New line preferences
end_of_line = lf
insert_final_newline = true
max_line_length = unset
# using directive preferences
csharp_using_directive_placement = outside_namespace
dotnet_diagnostic.IDE0005.severity = error
# Code-block preferences
csharp_style_namespace_declarations = block_scoped
csharp_style_prefer_method_group_conversion = true
csharp_style_prefer_top_level_statements = false
# Expression-level preferences
csharp_prefer_simple_default_expression = true
csharp_style_inlined_variable_declaration = true
csharp_style_unused_value_assignment_preference = discard_variable
csharp_style_unused_value_expression_statement_preference = discard_variable
dotnet_diagnostic.IDE0001.severity = warning
dotnet_diagnostic.IDE0002.severity = warning
dotnet_diagnostic.IDE0004.severity = warning
dotnet_diagnostic.IDE0010.severity = error
dotnet_diagnostic.IDE0051.severity = warning
dotnet_diagnostic.IDE0052.severity = warning
dotnet_diagnostic.IDE0072.severity = warning
dotnet_diagnostic.IDE0080.severity = warning
dotnet_diagnostic.IDE0100.severity = error
dotnet_diagnostic.IDE0110.severity = error
dotnet_diagnostic.IDE0120.severity = warning
dotnet_diagnostic.IDE0121.severity = warning
dotnet_diagnostic.IDE0240.severity = error
dotnet_diagnostic.IDE0241.severity = error
dotnet_style_coalesce_expression = true
dotnet_style_namespace_match_folder = false
dotnet_style_null_propagation = true
dotnet_style_prefer_auto_properties = true
dotnet_style_prefer_collection_expression = when_types_loosely_match
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
dotnet_style_prefer_compound_assignment = true
csharp_style_prefer_simple_property_accessors = true
dotnet_style_prefer_simplified_interpolation = true
dotnet_style_prefer_simplified_boolean_expressions = true
csharp_style_prefer_unbound_generic_type_in_nameof = true
# Field preferences
dotnet_diagnostic.IDE0044.severity = warning
dotnet_style_readonly_field = true
# Language keyword vs. framework types preferences
dotnet_diagnostic.IDE0049.severity = error
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
# Modifier preferences
csharp_prefer_static_local_function = true
csharp_style_prefer_readonly_struct = true
dotnet_diagnostic.IDE0036.severity = warning
dotnet_diagnostic.IDE0040.severity = error
dotnet_diagnostic.IDE0380.severity = error
dotnet_style_require_accessibility_modifiers = always
# New-line preferences
dotnet_diagnostic.IDE2000.severity = warning
dotnet_diagnostic.IDE2002.severity = warning
dotnet_diagnostic.IDE2003.severity = warning
dotnet_diagnostic.IDE2004.severity = warning
dotnet_diagnostic.IDE2005.severity = warning
dotnet_diagnostic.IDE2006.severity = warning
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
dotnet_style_allow_multiple_blank_lines_experimental = false
dotnet_style_allow_statement_immediately_after_block_experimental = false
# Null-checking preferences
csharp_style_conditional_delegate_call = true
# Parameter preferences
dotnet_code_quality_unused_parameters = all
dotnet_diagnostic.IDE0280.severity = error
# Parentheses preferences
dotnet_diagnostic.IDE0047.severity = warning
dotnet_diagnostic.IDE0048.severity = warning
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = always_for_clarity
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
# Pattern-matching preferences
dotnet_diagnostic.IDE0019.severity = warning
dotnet_diagnostic.IDE0020.severity = warning
dotnet_diagnostic.IDE0038.severity = warning
dotnet_diagnostic.IDE0066.severity = none
dotnet_diagnostic.IDE0083.severity = warning
dotnet_diagnostic.IDE0260.severity = warning
csharp_style_pattern_matching_over_as_with_null_check = true
csharp_style_pattern_matching_over_is_with_cast_check = true
csharp_style_prefer_not_pattern = true
csharp_style_prefer_pattern_matching = true
# this. and Me. preferences
dotnet_style_qualification_for_event = false
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false
dotnet_style_qualification_for_property = false
# var preferences
csharp_style_var_for_built_in_types = false
csharp_style_var_when_type_is_apparent = true
# .NET formatting options
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = true
# C# formatting options
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = false
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = true
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false

View File

@@ -1,48 +1,48 @@
name: Build and Test
on:
push:
branches: [ "main" ]
push:
branches: ["main"]
jobs:
build:
runs-on: ubuntu-latest
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x
- name: Run tests
run: dotnet test
- name: Run publish script
run: ./publish-nix.sh -d
- name: Run tests
run: dotnet test
- name: Update rolling tag
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -f rolling
git push origin :refs/tags/rolling || true
git push origin rolling --force
- name: Run publish script
run: ./publish-nix.sh -d
- name: Upload to rolling
uses: ncipollo/release-action@v1.20.0
with:
allowUpdates: True
artifacts: "*.nupkg,*.snupkg"
body: 'Last built commit: ${{ github.sha }}'
name: 'Rolling Release'
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True
- name: Update rolling tag
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -f rolling
git push origin :refs/tags/rolling || true
git push origin rolling --force
- name: Upload to rolling
uses: ncipollo/release-action@v1.20.0
with:
allowUpdates: True
artifacts: "*.nupkg,*.snupkg"
body: "Last built commit: ${{ github.sha }}"
name: "Rolling Release"
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True

View File

@@ -3,21 +3,21 @@ name: Build PR
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x
- name: Build
run: dotnet build
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Run tests
run: dotnet test
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x
- name: Build
run: dotnet build
- name: Run tests
run: dotnet test

View File

@@ -7,10 +7,10 @@ namespace RedumpTool
{
public class Program
{
static void Main(string[] args)
public static void Main(string[] args)
{
// Show help if nothing is input
if (args == null || args.Length == 0)
if (args is null || args.Length == 0)
{
Console.WriteLine("At least one argument is required");
ShowHelp();
@@ -28,7 +28,7 @@ namespace RedumpTool
// Create a new Downloader
var downloader = CreateDownloader(feature, args);
if (downloader == null)
if (downloader is null)
{
Console.WriteLine("A downloader could not be created from the inputs");
ShowHelp();

View File

@@ -9,7 +9,7 @@
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.9.0</Version>
<Version>1.9.1</Version>
</PropertyGroup>
<!-- Support All Frameworks -->
@@ -19,7 +19,7 @@
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`))">
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">

View File

@@ -1,5 +1,3 @@
using System;
using System.IO;
using SabreTools.RedumpLib.Data;
@@ -23,7 +21,7 @@ namespace SabreTools.RedumpLib.Test
var si = Builder.CreateFromFile(path);
// Check for an expected result
Assert.Equal(expectNull, si == null);
Assert.Equal(expectNull, si is null);
}
[Fact]

File diff suppressed because it is too large Load Diff

View File

@@ -302,6 +302,7 @@ namespace SabreTools.RedumpLib.Test
{
ClrMameProData = "XXXXXX",
Cuesheet = "XXXXXX",
CuesheetRaw = [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39],
OtherWriteOffsets = "XXXXXX",
};

View File

@@ -1,182 +1,183 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
using Xunit;
namespace SabreTools.RedumpLib.Test
{
public class SubmissionInfoTests
{
[Fact]
public void EmptySerializationTest()
{
var submissionInfo = new SubmissionInfo();
string json = JsonConvert.SerializeObject(submissionInfo, Formatting.Indented);
Assert.NotNull(json);
}
[Fact]
public void PartialSerializationTest()
{
var submissionInfo = new SubmissionInfo()
{
CommonDiscInfo = new CommonDiscInfoSection(),
VersionAndEditions = new VersionAndEditionsSection(),
EDC = new EDCSection(),
ParentCloneRelationship = new ParentCloneRelationshipSection(),
Extras = new ExtrasSection(),
CopyProtection = new CopyProtectionSection(),
DumpersAndStatus = new DumpersAndStatusSection(),
TracksAndWriteOffsets = new TracksAndWriteOffsetsSection(),
SizeAndChecksums = new SizeAndChecksumsSection(),
};
string json = JsonConvert.SerializeObject(submissionInfo, Formatting.Indented);
Assert.NotNull(json);
}
[Fact]
public void FullSerializationTest()
{
var submissionInfo = new SubmissionInfo()
{
SchemaVersion = 1,
FullyMatchedID = 3,
PartiallyMatchedIDs = [0, 1, 2, 3],
Added = DateTime.UtcNow,
LastModified = DateTime.UtcNow,
CommonDiscInfo = new CommonDiscInfoSection()
{
System = RedumpSystem.IBMPCcompatible,
Media = DiscType.CD,
Title = "Game Title",
ForeignTitleNonLatin = "Foreign Game Title",
DiscNumberLetter = "1",
DiscTitle = "Install Disc",
Category = DiscCategory.Games,
Region = Region.World,
Languages = [Language.English, Language.Spanish, Language.French],
LanguageSelection = [LanguageSelection.BiosSettings],
Serial = "Disc Serial",
Layer0MasteringRing = "L0 Mastering Ring",
Layer0MasteringSID = "L0 Mastering SID",
Layer0ToolstampMasteringCode = "L0 Toolstamp",
Layer0MouldSID = "L0 Mould SID",
Layer0AdditionalMould = "L0 Additional Mould",
Layer1MasteringRing = "L1 Mastering Ring",
Layer1MasteringSID = "L1 Mastering SID",
Layer1ToolstampMasteringCode = "L1 Toolstamp",
Layer1MouldSID = "L1 Mould SID",
Layer1AdditionalMould = "L1 Additional Mould",
Layer2MasteringRing = "L2 Mastering Ring",
Layer2MasteringSID = "L2 Mastering SID",
Layer2ToolstampMasteringCode = "L2 Toolstamp",
Layer3MasteringRing = "L3 Mastering Ring",
Layer3MasteringSID = "L3 Mastering SID",
Layer3ToolstampMasteringCode = "L3 Toolstamp",
RingWriteOffset = "+12",
Barcode = "UPC Barcode",
EXEDateBuildDate = "19xx-xx-xx",
ErrorsCount = "0",
Comments = "Comment data line 1\r\nComment data line 2",
CommentsSpecialFields = new Dictionary<SiteCode, string>()
{
[SiteCode.ISBN] = "ISBN",
},
Contents = "Special contents 1\r\nSpecial contents 2",
ContentsSpecialFields = new Dictionary<SiteCode, string>()
{
[SiteCode.PlayableDemos] = "Game Demo 1",
},
},
VersionAndEditions = new VersionAndEditionsSection()
{
Version = "Original",
VersionDatfile = "Alt",
CommonEditions = ["Taikenban"],
OtherEditions = "Rerelease",
},
EDC = new EDCSection()
{
EDC = YesNo.Yes,
},
ParentCloneRelationship = new ParentCloneRelationshipSection()
{
ParentID = "12345",
RegionalParent = false,
},
Extras = new ExtrasSection()
{
PVD = "PVD",
DiscKey = "Disc key",
DiscID = "Disc ID",
PIC = "PIC",
Header = "Header",
BCA = "BCA",
SecuritySectorRanges = "SSv1 Ranges",
},
CopyProtection = new CopyProtectionSection()
{
AntiModchip = YesNo.Yes,
LibCrypt = YesNo.No,
LibCryptData = "LibCrypt data",
Protection = "List of protections",
SecuROMData = "SecuROM data",
},
DumpersAndStatus = new DumpersAndStatusSection()
{
Status = DumpStatus.TwoOrMoreGreen,
Dumpers = ["Dumper1", "Dumper2"],
OtherDumpers = "Dumper3",
},
TracksAndWriteOffsets = new TracksAndWriteOffsetsSection()
{
ClrMameProData = "Datfile",
Cuesheet = "Cuesheet",
CommonWriteOffsets = [0, 12, -12],
OtherWriteOffsets = "-2",
},
SizeAndChecksums = new SizeAndChecksumsSection()
{
Layerbreak = 0,
Layerbreak2 = 1,
Layerbreak3 = 2,
Size = 12345,
CRC32 = "CRC32",
MD5 = "MD5",
SHA1 = "SHA1",
},
DumpingInfo = new DumpingInfoSection()
{
DumpingProgram = "DiscImageCreator 20500101",
DumpingDate = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"),
DumpingParameters = "cd dvd bd sacd fd hdd",
Manufacturer = "ATAPI",
Model = "Optical Drive",
Firmware = "1.23",
ReportedDiscType = "CD-R",
},
Artifacts = new Dictionary<string, string>()
{
["Sample Artifact"] = "Sample Data",
},
};
string json = JsonConvert.SerializeObject(submissionInfo, Formatting.Indented);
Assert.NotNull(json);
}
}
}
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
using Xunit;
namespace SabreTools.RedumpLib.Test
{
public class SubmissionInfoTests
{
[Fact]
public void EmptySerializationTest()
{
var submissionInfo = new SubmissionInfo();
string json = JsonConvert.SerializeObject(submissionInfo, Formatting.Indented);
Assert.NotNull(json);
}
[Fact]
public void PartialSerializationTest()
{
var submissionInfo = new SubmissionInfo()
{
CommonDiscInfo = new CommonDiscInfoSection(),
VersionAndEditions = new VersionAndEditionsSection(),
EDC = new EDCSection(),
ParentCloneRelationship = new ParentCloneRelationshipSection(),
Extras = new ExtrasSection(),
CopyProtection = new CopyProtectionSection(),
DumpersAndStatus = new DumpersAndStatusSection(),
TracksAndWriteOffsets = new TracksAndWriteOffsetsSection(),
SizeAndChecksums = new SizeAndChecksumsSection(),
};
string json = JsonConvert.SerializeObject(submissionInfo, Formatting.Indented);
Assert.NotNull(json);
}
[Fact]
public void FullSerializationTest()
{
var submissionInfo = new SubmissionInfo()
{
SchemaVersion = 1,
FullyMatchedID = 3,
PartiallyMatchedIDs = [0, 1, 2, 3],
Added = DateTime.UtcNow,
LastModified = DateTime.UtcNow,
CommonDiscInfo = new CommonDiscInfoSection()
{
System = RedumpSystem.IBMPCcompatible,
Media = DiscType.CD,
Title = "Game Title",
ForeignTitleNonLatin = "Foreign Game Title",
DiscNumberLetter = "1",
DiscTitle = "Install Disc",
Category = DiscCategory.Games,
Region = Region.World,
Languages = [Language.English, Language.Spanish, Language.French],
LanguageSelection = [LanguageSelection.BiosSettings],
Serial = "Disc Serial",
Layer0MasteringRing = "L0 Mastering Ring",
Layer0MasteringSID = "L0 Mastering SID",
Layer0ToolstampMasteringCode = "L0 Toolstamp",
Layer0MouldSID = "L0 Mould SID",
Layer0AdditionalMould = "L0 Additional Mould",
Layer1MasteringRing = "L1 Mastering Ring",
Layer1MasteringSID = "L1 Mastering SID",
Layer1ToolstampMasteringCode = "L1 Toolstamp",
Layer1MouldSID = "L1 Mould SID",
Layer1AdditionalMould = "L1 Additional Mould",
Layer2MasteringRing = "L2 Mastering Ring",
Layer2MasteringSID = "L2 Mastering SID",
Layer2ToolstampMasteringCode = "L2 Toolstamp",
Layer3MasteringRing = "L3 Mastering Ring",
Layer3MasteringSID = "L3 Mastering SID",
Layer3ToolstampMasteringCode = "L3 Toolstamp",
RingWriteOffset = "+12",
Barcode = "UPC Barcode",
EXEDateBuildDate = "19xx-xx-xx",
ErrorsCount = "0",
Comments = "Comment data line 1\r\nComment data line 2",
CommentsSpecialFields = new Dictionary<SiteCode, string>()
{
[SiteCode.ISBN] = "ISBN",
},
Contents = "Special contents 1\r\nSpecial contents 2",
ContentsSpecialFields = new Dictionary<SiteCode, string>()
{
[SiteCode.PlayableDemos] = "Game Demo 1",
},
},
VersionAndEditions = new VersionAndEditionsSection()
{
Version = "Original",
VersionDatfile = "Alt",
CommonEditions = ["Taikenban"],
OtherEditions = "Rerelease",
},
EDC = new EDCSection()
{
EDC = YesNo.Yes,
},
ParentCloneRelationship = new ParentCloneRelationshipSection()
{
ParentID = "12345",
RegionalParent = false,
},
Extras = new ExtrasSection()
{
PVD = "PVD",
DiscKey = "Disc key",
DiscID = "Disc ID",
PIC = "PIC",
Header = "Header",
BCA = "BCA",
SecuritySectorRanges = "SSv1 Ranges",
},
CopyProtection = new CopyProtectionSection()
{
AntiModchip = YesNo.Yes,
LibCrypt = YesNo.No,
LibCryptData = "LibCrypt data",
Protection = "List of protections",
SecuROMData = "SecuROM data",
},
DumpersAndStatus = new DumpersAndStatusSection()
{
Status = DumpStatus.TwoOrMoreGreen,
Dumpers = ["Dumper1", "Dumper2"],
OtherDumpers = "Dumper3",
},
TracksAndWriteOffsets = new TracksAndWriteOffsetsSection()
{
ClrMameProData = "Datfile",
Cuesheet = "Cuesheet",
CuesheetRaw = [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39],
CommonWriteOffsets = [0, 12, -12],
OtherWriteOffsets = "-2",
},
SizeAndChecksums = new SizeAndChecksumsSection()
{
Layerbreak = 0,
Layerbreak2 = 1,
Layerbreak3 = 2,
Size = 12345,
CRC32 = "CRC32",
MD5 = "MD5",
SHA1 = "SHA1",
},
DumpingInfo = new DumpingInfoSection()
{
DumpingProgram = "DiscImageCreator 20500101",
DumpingDate = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"),
DumpingParameters = "cd dvd bd sacd fd hdd",
Manufacturer = "ATAPI",
Model = "Optical Drive",
Firmware = "1.23",
ReportedDiscType = "CD-R",
},
Artifacts = new Dictionary<string, string>()
{
["Sample Artifact"] = "Sample Data",
},
};
string json = JsonConvert.SerializeObject(submissionInfo, Formatting.Indented);
Assert.NotNull(json);
}
}
}

View File

@@ -285,7 +285,7 @@ namespace SabreTools.RedumpLib.Test
Assert.Equal(expected, si.CommonDiscInfo.Media);
}
[Theory]
[Theory]
[InlineData(DiscType.UMDSL)]
[InlineData(DiscType.UMDDL)]
public void NormalizeDiscType_UMDSL_Fixed(DiscType type)

View File

@@ -12,12 +12,12 @@ namespace SabreTools.RedumpLib.Attributes
public static HumanReadableAttribute? GetAttribute(T value)
{
// Null value in, null value out
if (value == null)
if (value is null)
return null;
// Current enumeration type
var enumType = typeof(T);
if (Nullable.GetUnderlyingType(enumType) != null)
if (Nullable.GetUnderlyingType(enumType) is not null)
enumType = Nullable.GetUnderlyingType(enumType);
// If the value returns a null on ToString, just return null
@@ -27,17 +27,17 @@ namespace SabreTools.RedumpLib.Attributes
// Get the member info array
var memberInfos = enumType?.GetMember(valueStr);
if (memberInfos == null)
if (memberInfos is null)
return null;
// Get the enum value info from the array, if possible
var enumValueMemberInfo = Array.Find(memberInfos, m => m.DeclaringType == enumType);
if (enumValueMemberInfo == null)
if (enumValueMemberInfo is null)
return null;
// Try to get the relevant attribute
var attributes = enumValueMemberInfo.GetCustomAttributes(typeof(HumanReadableAttribute), true);
if (attributes == null || attributes.Length == 0)
if (attributes is null || attributes.Length == 0)
return null;
// Return the first attribute, if possible

View File

@@ -54,6 +54,7 @@ namespace SabreTools.RedumpLib
/// <param name="discData">String containing the HTML disc data</param>
/// <returns>Filled SubmissionInfo object on success, null on error</returns>
/// <remarks>Not currently working</remarks>
#pragma warning disable IDE0051
private static SubmissionInfo? CreateFromID(string discData)
{
var info = new SubmissionInfo()
@@ -78,7 +79,7 @@ namespace SabreTools.RedumpLib
// Get the body node, if possible
var bodyNode = redumpPage["html"]?["body"];
if (bodyNode == null || !bodyNode.HasChildNodes)
if (bodyNode is null || !bodyNode.HasChildNodes)
return null;
// Loop through and get the main node, if possible
@@ -86,7 +87,7 @@ namespace SabreTools.RedumpLib
foreach (XmlNode? tempNode in bodyNode.ChildNodes)
{
// Invalid nodes are skipped
if (tempNode == null)
if (tempNode is null)
continue;
// We only care about div elements
@@ -94,7 +95,7 @@ namespace SabreTools.RedumpLib
continue;
// We only care if it has attributes
if (tempNode.Attributes == null)
if (tempNode.Attributes is null)
continue;
// The main node has a class of "main"
@@ -106,14 +107,14 @@ namespace SabreTools.RedumpLib
}
// If the main node is invalid, we can't do anything
if (mainNode == null || !mainNode.HasChildNodes)
if (mainNode is null || !mainNode.HasChildNodes)
return null;
// Try to find elements as we're going
foreach (XmlNode? childNode in mainNode.ChildNodes)
{
// Invalid nodes are skipped
if (childNode == null)
if (childNode is null)
continue;
// The title is the only thing in h1 tags
@@ -125,7 +126,7 @@ namespace SabreTools.RedumpLib
continue;
// Only 2 of the internal divs have classes attached and one is not used here
if (childNode.Attributes != null && string.Equals(childNode.Attributes["class"]?.Value, "game",
if (childNode.Attributes is not null && string.Equals(childNode.Attributes["class"]?.Value, "game",
StringComparison.OrdinalIgnoreCase))
{
// If we don't have children nodes, skip this one over
@@ -136,14 +137,14 @@ namespace SabreTools.RedumpLib
foreach (XmlNode? gameNode in childNode.ChildNodes)
{
// Invalid nodes are skipped
if (gameNode == null)
if (gameNode is null)
continue;
// Table elements contain multiple other parts of information
if (string.Equals(gameNode.Name, "table", StringComparison.OrdinalIgnoreCase))
{
// All tables have some attribute we can use
if (gameNode.Attributes == null)
if (gameNode.Attributes is null)
continue;
// The gameinfo node contains most of the major information
@@ -158,7 +159,7 @@ namespace SabreTools.RedumpLib
foreach (XmlNode? gameInfoNode in gameNode.ChildNodes)
{
// Invalid nodes are skipped
if (gameInfoNode == null)
if (gameInfoNode is null)
continue;
// If we run into anything not a row, ignore it
@@ -166,13 +167,13 @@ namespace SabreTools.RedumpLib
continue;
// If we don't have the required nodes, ignore it
if (gameInfoNode["th"] == null || gameInfoNode["td"] == null)
if (gameInfoNode["th"] is null || gameInfoNode["td"] is null)
continue;
var gameInfoNodeHeader = gameInfoNode["th"];
var gameInfoNodeData = gameInfoNode["td"];
if (gameInfoNodeHeader == null || gameInfoNodeData == null)
if (gameInfoNodeHeader is null || gameInfoNodeData is null)
{
// No-op for invalid data
}
@@ -244,6 +245,7 @@ namespace SabreTools.RedumpLib
return info;
}
#pragma warning restore IDE0051
/// <summary>
/// Fill out an existing SubmissionInfo object based on a disc page
@@ -252,7 +254,7 @@ namespace SabreTools.RedumpLib
/// <param name="info">Existing SubmissionInfo object to fill</param>
/// <param name="id">Redump disc ID to retrieve</param>
/// <param name="includeAllData">True to include all pullable information, false to do bare minimum</param>
public async static Task<bool> FillFromId(RedumpClient rc, SubmissionInfo info, int id, bool includeAllData)
public static async Task<bool> FillFromId(RedumpClient rc, SubmissionInfo info, int id, bool includeAllData)
{
var discData = await rc.DownloadSingleSiteID(id);
if (string.IsNullOrEmpty(discData))
@@ -266,7 +268,7 @@ namespace SabreTools.RedumpLib
// If we have parenthesis, title is everything before the first one
int firstParenLocation = title?.IndexOf(" (") ?? -1;
if (title != null && firstParenLocation >= 0)
if (title is not null && firstParenLocation >= 0)
{
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
info.CommonDiscInfo!.Title = title[..firstParenLocation];
@@ -276,7 +278,7 @@ namespace SabreTools.RedumpLib
var submatches = Constants.DiscNumberLetterRegex.Matches(title);
foreach (Match? submatch in submatches)
{
if (submatch == null)
if (submatch is null)
continue;
var submatchValue = submatch.Groups[1].Value;
@@ -318,7 +320,7 @@ namespace SabreTools.RedumpLib
info.CommonDiscInfo!.Category = DiscCategory.Games;
// Region
if (info.CommonDiscInfo.Region == null)
if (info.CommonDiscInfo.Region is null)
{
match = Constants.RegionRegex.Match(discData);
if (match.Success)
@@ -332,11 +334,11 @@ namespace SabreTools.RedumpLib
var tempLanguages = new List<Language?>();
foreach (Match? submatch in matches)
{
if (submatch == null)
if (submatch is null)
continue;
var language = Extensions.ToLanguage(submatch.Groups[1].Value);
if (language != null)
if (language is not null)
tempLanguages.Add(language);
}
@@ -361,7 +363,7 @@ namespace SabreTools.RedumpLib
}
// Version
if (info.VersionAndEditions!.Version == null)
if (info.VersionAndEditions!.Version is null)
{
match = Constants.VersionRegex.Match(discData);
if (match.Success)
@@ -374,7 +376,7 @@ namespace SabreTools.RedumpLib
{
// Start with any currently listed dumpers
var tempDumpers = new List<string>();
if (info.DumpersAndStatus!.Dumpers != null && info.DumpersAndStatus.Dumpers.Length > 0)
if (info.DumpersAndStatus!.Dumpers is not null && info.DumpersAndStatus.Dumpers.Length > 0)
{
foreach (string dumper in info.DumpersAndStatus.Dumpers)
tempDumpers.Add(dumper);
@@ -382,11 +384,11 @@ namespace SabreTools.RedumpLib
foreach (Match? submatch in matches)
{
if (submatch == null)
if (submatch is null)
continue;
string? dumper = WebUtility.HtmlDecode(submatch.Groups[1].Value);
if (dumper != null)
if (dumper is not null)
tempDumpers.Add(dumper);
}
@@ -447,12 +449,12 @@ namespace SabreTools.RedumpLib
foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode)))
{
// If we have a null site code, just skip
if (siteCode == null)
if (siteCode is null)
continue;
// If the line doesn't contain this tag, just skip
var shortName = siteCode.ShortName();
if (shortName == null || !commentLine.Contains(shortName))
if (shortName is null || !commentLine.Contains(shortName))
continue;
// Mark as having found a tag
@@ -482,14 +484,14 @@ namespace SabreTools.RedumpLib
// If we didn't find a known tag, just add the line, just in case
if (!foundTag)
{
if (addToLast && lastSiteCode != null && !ShouldSkipSiteCode(lastSiteCode))
if (addToLast && lastSiteCode is not null && !ShouldSkipSiteCode(lastSiteCode))
{
if (!string.IsNullOrEmpty(info.CommonDiscInfo.CommentsSpecialFields![lastSiteCode.Value]))
info.CommonDiscInfo.CommentsSpecialFields[lastSiteCode.Value] += "\n";
info.CommonDiscInfo.CommentsSpecialFields[lastSiteCode.Value] += commentLine;
}
else if (!addToLast || lastSiteCode == null)
else if (!addToLast || lastSiteCode is null)
{
newComments += $"{commentLine}\n";
}
@@ -544,12 +546,12 @@ namespace SabreTools.RedumpLib
foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode)))
{
// If we have a null site code, just skip
if (siteCode == null)
if (siteCode is null)
continue;
// If the line doesn't contain this tag, just skip
var shortName = siteCode.ShortName();
if (shortName == null || !contentLine.Contains(shortName))
if (shortName is null || !contentLine.Contains(shortName))
continue;
// Cache the current site code
@@ -570,14 +572,14 @@ namespace SabreTools.RedumpLib
// If we didn't find a known tag, just add the line, just in case
if (!foundTag)
{
if (addToLast && lastSiteCode != null && !ShouldSkipSiteCode(lastSiteCode))
if (addToLast && lastSiteCode is not null && !ShouldSkipSiteCode(lastSiteCode))
{
if (!string.IsNullOrEmpty(info.CommonDiscInfo.ContentsSpecialFields![lastSiteCode.Value]))
info.CommonDiscInfo.ContentsSpecialFields[lastSiteCode.Value] += "\n";
info.CommonDiscInfo.ContentsSpecialFields[lastSiteCode.Value] += contentLine;
}
else if (!addToLast || lastSiteCode == null)
else if (!addToLast || lastSiteCode is null)
{
newContents += $"{contentLine}\n";
}
@@ -620,7 +622,7 @@ namespace SabreTools.RedumpLib
public static SubmissionInfo? InjectSubmissionInformation(SubmissionInfo? info, SubmissionInfo? seed)
{
// If we have any invalid info
if (seed == null)
if (seed is null)
return info;
// Otherwise, inject information as necessary
@@ -631,16 +633,16 @@ namespace SabreTools.RedumpLib
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.ForeignTitleNonLatin)) info.CommonDiscInfo.ForeignTitleNonLatin = seed.CommonDiscInfo.ForeignTitleNonLatin;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.DiscNumberLetter)) info.CommonDiscInfo.DiscNumberLetter = seed.CommonDiscInfo.DiscNumberLetter;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.DiscTitle)) info.CommonDiscInfo.DiscTitle = seed.CommonDiscInfo.DiscTitle;
if (seed.CommonDiscInfo.Category != null) info.CommonDiscInfo.Category = seed.CommonDiscInfo.Category;
if (seed.CommonDiscInfo.Region != null) info.CommonDiscInfo.Region = seed.CommonDiscInfo.Region;
if (seed.CommonDiscInfo.Languages != null) info.CommonDiscInfo.Languages = seed.CommonDiscInfo.Languages;
if (seed.CommonDiscInfo.LanguageSelection != null) info.CommonDiscInfo.LanguageSelection = seed.CommonDiscInfo.LanguageSelection;
if (seed.CommonDiscInfo.Category is not null) info.CommonDiscInfo.Category = seed.CommonDiscInfo.Category;
if (seed.CommonDiscInfo.Region is not null) info.CommonDiscInfo.Region = seed.CommonDiscInfo.Region;
if (seed.CommonDiscInfo.Languages is not null) info.CommonDiscInfo.Languages = seed.CommonDiscInfo.Languages;
if (seed.CommonDiscInfo.LanguageSelection is not null) info.CommonDiscInfo.LanguageSelection = seed.CommonDiscInfo.LanguageSelection;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Serial)) info.CommonDiscInfo.Serial = seed.CommonDiscInfo.Serial;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Barcode)) info.CommonDiscInfo.Barcode = seed.CommonDiscInfo.Barcode;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Comments)) info.CommonDiscInfo.Comments = seed.CommonDiscInfo.Comments;
if (seed.CommonDiscInfo.CommentsSpecialFields != null) info.CommonDiscInfo.CommentsSpecialFields = seed.CommonDiscInfo.CommentsSpecialFields;
if (seed.CommonDiscInfo.CommentsSpecialFields is not null) info.CommonDiscInfo.CommentsSpecialFields = seed.CommonDiscInfo.CommentsSpecialFields;
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Contents)) info.CommonDiscInfo.Contents = seed.CommonDiscInfo.Contents;
if (seed.CommonDiscInfo.ContentsSpecialFields != null) info.CommonDiscInfo.ContentsSpecialFields = seed.CommonDiscInfo.ContentsSpecialFields;
if (seed.CommonDiscInfo.ContentsSpecialFields is not null) info.CommonDiscInfo.ContentsSpecialFields = seed.CommonDiscInfo.ContentsSpecialFields;
// Info that always overwrites
info.CommonDiscInfo.Layer0MasteringRing = seed.CommonDiscInfo.Layer0MasteringRing;
@@ -678,6 +680,7 @@ namespace SabreTools.RedumpLib
/// </summary>
private static bool ShouldSkipSiteCode(SiteCode? siteCode)
{
#pragma warning disable IDE0072
return siteCode switch
{
// Multiple
@@ -711,6 +714,7 @@ namespace SabreTools.RedumpLib
_ => false,
};
#pragma warning restore IDE0072
}
#endregion

View File

@@ -30,7 +30,7 @@ namespace SabreTools.RedumpLib.Converters
continue;
Language? lang = Data.Extensions.ToLanguage(value);
if (lang != null)
if (lang is not null)
languages.Add(lang.Value);
}
@@ -39,7 +39,7 @@ namespace SabreTools.RedumpLib.Converters
public override void WriteJson(JsonWriter writer, Language?[]? value, JsonSerializer serializer)
{
if (value == null)
if (value is null)
return;
JArray array = [];

View File

@@ -30,7 +30,7 @@ namespace SabreTools.RedumpLib.Converters
continue;
LanguageSelection? sel = Data.Extensions.ToLanguageSelection(value);
if (sel != null)
if (sel is not null)
selections.Add(sel.Value);
}
@@ -39,7 +39,7 @@ namespace SabreTools.RedumpLib.Converters
public override void WriteJson(JsonWriter writer, LanguageSelection?[]? value, JsonSerializer serializer)
{
if (value == null)
if (value is null)
return;
JArray array = [];

View File

@@ -2268,6 +2268,9 @@ namespace SabreTools.RedumpLib.Data
[System(Category = SystemCategory.Arcade, LongName = "funworld Photo Play", ShortName = "fpp", HasCues = true, HasDat = true)]
funworldPhotoPlay,
[System(Category = SystemCategory.Arcade, Available = false, LongName = "FuRyu & Omron Purikura")]
FuRyuOmronPurikura,
[System(Category = SystemCategory.Arcade, Available = false, LongName = "Global VR PC-based Systems")]
GlobalVRVarious,
@@ -2331,6 +2334,9 @@ namespace SabreTools.RedumpLib.Data
[System(Category = SystemCategory.Arcade, Available = false, LongName = "Merit Industries MegaTouch XL")]
MeritIndustriesMegaTouchXL,
[System(Category = SystemCategory.Arcade, Available = false, LongName = "Namco Purikura")]
NamcoPurikura,
[System(Category = SystemCategory.Arcade, LongName = "Namco · Sega · Nintendo Triforce", ShortName = "trf", HasCues = true, HasDat = true, HasGdi = true)]
NamcoSegaNintendoTriforce,
@@ -2379,9 +2385,21 @@ namespace SabreTools.RedumpLib.Data
[System(Category = SystemCategory.Arcade, LongName = "Sega Naomi 2", ShortName = "naomi2", HasCues = true, HasDat = true, HasGdi = true)]
SegaNaomi2,
[System(Category = SystemCategory.Arcade, Available = false, LongName = "Sega NAOMI Satellite Terminal PC")]
SegaNaomiSatelliteTerminalPC,
[System(Category = SystemCategory.Arcade, Available = false, LongName = "Sega Nu")]
SegaNu,
[System(Category = SystemCategory.Arcade, Available = false, LongName = "Sega Nu 1.1")]
SegaNu11,
[System(Category = SystemCategory.Arcade, Available = false, LongName = "Sega Nu 2")]
SegaNu2,
[System(Category = SystemCategory.Arcade, Available = false, LongName = "Sega Nu SX")]
SegaNuSX,
[System(Category = SystemCategory.Arcade, LongName = "Sega RingEdge", ShortName = "sre", HasDat = true)]
SegaRingEdge,
@@ -2449,12 +2467,18 @@ namespace SabreTools.RedumpLib.Data
[System(Category = SystemCategory.Other, LongName = "Pocket PC", ShortName = "ppc", HasCues = true, HasDat = true)]
PocketPC,
[System(Category = SystemCategory.Other, Available = false, LongName = "Psion")]
Psion,
[System(Category = SystemCategory.Other, Available = false, LongName = "Rainbow Disc")]
RainbowDisc,
[System(Category = SystemCategory.Other, LongName = "Sega Prologue 21 Multimedia Karaoke System", ShortName = "sp21", HasCues = true, HasDat = true)]
SegaPrologue21MultimediaKaraokeSystem,
[System(Category = SystemCategory.Other, Available = false, LongName = "Sharp Zaurus")]
SharpZaurus,
[System(Category = SystemCategory.Other, Available = false, LongName = "Sony Electronic Book")]
SonyElectronicBook,
@@ -3725,6 +3749,18 @@ namespace SabreTools.RedumpLib.Data
[HumanReadable(ShortName = "<b>SS version</b>:", LongName = "<b>SS version</b>:")]
SSVersion,
// This doesn't have a site tag yet
[HumanReadable(ShortName = "<b>Steam App ID</b>:", LongName = "<b>Steam AppID</b>:")]
SteamAppID,
// This doesn't have a site tag yet
[HumanReadable(ShortName = "<b>Steam Depot ID (.sis/.csm/.csd)</b>:", LongName = "<b>Steam Depot ID (.sis/.csm/.csd)</b>:")]
SteamCsmCsdDepotID,
// This doesn't have a site tag yet
[HumanReadable(ShortName = "<b>Steam Depot ID (.sis/.sim/.sid)</b>:", LongName = "<b>Steam Depot ID (.sis/.sim/.sid)</b>:")]
SteamSimSidDepotID,
[HumanReadable(ShortName = "[T:TID]", LongName = "<b>Taito ID</b>:")]
TaitoID,
@@ -3735,6 +3771,10 @@ namespace SabreTools.RedumpLib.Data
[HumanReadable(ShortName = "<b>Title ID</b>:", LongName = "<b>Title ID</b>:")]
TitleID,
// This doesn't have a site tag yet
[HumanReadable(ShortName = "<b>2K Games ID</b>:", LongName = "<b>2K Games ID</b>:")]
TwoKGamesID,
[HumanReadable(ShortName = "[T:UID]", LongName = "<b>Ubisoft ID</b>:")]
UbisoftID,

View File

@@ -7,6 +7,8 @@ namespace SabreTools.RedumpLib.Data
/// <summary>
/// Information pertaining to Redump systems
/// </summary>
#pragma warning disable IDE0010
#pragma warning disable IDE0072
public static class Extensions
{
#region Cross-Enumeration
@@ -352,6 +354,12 @@ namespace SabreTools.RedumpLib.Data
types.Add(MediaType.CDROM);
break;
// https://en.wikipedia.org/wiki/FuRyu
case RedumpSystem.FuRyuOmronPurikura:
types.Add(MediaType.CDROM);
types.Add(MediaType.DVD);
break;
// UNKNOWN
case RedumpSystem.GlobalVRVarious:
types.Add(MediaType.CDROM);
@@ -476,6 +484,12 @@ namespace SabreTools.RedumpLib.Data
types.Add(MediaType.CDROM);
break;
// UNKNOWN
case RedumpSystem.NamcoPurikura:
types.Add(MediaType.CDROM);
types.Add(MediaType.DVD);
break;
// http://system16.com/hardware.php?id=543
// http://system16.com/hardware.php?id=546
// http://system16.com/hardware.php?id=872
@@ -572,11 +586,32 @@ namespace SabreTools.RedumpLib.Data
types.Add(MediaType.GDROM); // High density partition
break;
// https://segaretro.org/Sega_NAOMI#NAOMI_Satellite_Terminal
case RedumpSystem.SegaNaomiSatelliteTerminalPC:
types.Add(MediaType.CDROM);
types.Add(MediaType.DVD);
break;
// https://en.wikipedia.org/wiki/List_of_Sega_arcade_system_boards#Sega_Nu
case RedumpSystem.SegaNu:
types.Add(MediaType.DVD);
break;
// https://en.wikipedia.org/wiki/List_of_Sega_arcade_system_boards#Sega_Nu
case RedumpSystem.SegaNu11:
types.Add(MediaType.DVD);
break;
// https://en.wikipedia.org/wiki/List_of_Sega_arcade_system_boards#Sega_Nu
case RedumpSystem.SegaNu2:
types.Add(MediaType.DVD);
break;
// https://segaretro.org/Nu_SX
case RedumpSystem.SegaNuSX:
types.Add(MediaType.DVD);
break;
// http://system16.com/hardware.php?id=910
// https://en.wikipedia.org/wiki/List_of_Sega_arcade_system_boards#Sega_Ring_series
case RedumpSystem.SegaRingEdge:
@@ -687,6 +722,11 @@ namespace SabreTools.RedumpLib.Data
types.Add(MediaType.CDROM);
break;
// UNKNOWN
case RedumpSystem.Psion:
types.Add(MediaType.CDROM);
break;
// https://en.wikipedia.org/wiki/Doors_and_Windows_(EP)
case RedumpSystem.RainbowDisc:
types.Add(MediaType.CDROM);
@@ -697,6 +737,11 @@ namespace SabreTools.RedumpLib.Data
types.Add(MediaType.CDROM);
break;
// UNKNOWN
case RedumpSystem.SharpZaurus:
types.Add(MediaType.CDROM);
break;
// UNKNOWN
case RedumpSystem.SonyElectronicBook:
types.Add(MediaType.CDROM);
@@ -811,7 +856,7 @@ namespace SabreTools.RedumpLib.Data
public static DiscCategory? ToDiscCategory(this string? category)
{
// No value means no match
if (category == null || category.Length == 0)
if (category is null || category.Length == 0)
return null;
category = category?.ToLowerInvariant();
@@ -854,7 +899,7 @@ namespace SabreTools.RedumpLib.Data
public static DiscType? ToDiscType(this string? discType)
{
// No value means no match
if (discType == null || discType.Length == 0)
if (discType is null || discType.Length == 0)
return null;
discType = discType.ToLowerInvariant();
@@ -940,7 +985,7 @@ namespace SabreTools.RedumpLib.Data
public static Language? ToLanguage(this string? lang)
{
// No value means no match
if (lang == null || lang.Length == 0)
if (lang is null || lang.Length == 0)
return null;
lang = lang.ToLowerInvariant();
@@ -1040,7 +1085,7 @@ namespace SabreTools.RedumpLib.Data
public static LanguageSelection? ToLanguageSelection(this string? langSelect)
{
// No value means no match
if (langSelect == null || langSelect.Length == 0)
if (langSelect is null || langSelect.Length == 0)
return null;
langSelect = langSelect?.ToLowerInvariant();
@@ -1068,7 +1113,7 @@ namespace SabreTools.RedumpLib.Data
foreach (var val in Enum.GetValues(typeof(MediaType)))
{
if (val == null || ((MediaType)val) == MediaType.NONE)
if (val is null || ((MediaType)val) == MediaType.NONE)
continue;
mediaTypes.Add($"{((MediaType?)val).ShortName()} - {((MediaType?)val).LongName()}");
@@ -1137,7 +1182,7 @@ namespace SabreTools.RedumpLib.Data
public static Region? ToRegion(this string? region)
{
// No value means no match
if (region == null || region.Length == 0)
if (region is null || region.Length == 0)
return null;
region = region.ToLowerInvariant();
@@ -1178,7 +1223,7 @@ namespace SabreTools.RedumpLib.Data
bool isMultiline = ((SiteCode?)val).IsMultiLine();
// Invalid codes should be skipped
if (shortName == null || longName == null)
if (shortName is null || longName is null)
continue;
// Handle site tags
@@ -1277,6 +1322,7 @@ namespace SabreTools.RedumpLib.Data
SiteCode.Series => true,
SiteCode.SSHash => true,
SiteCode.SSVersion => true,
SiteCode.SteamAppID => true,
SiteCode.TitleID => true,
SiteCode.UniversalHash => true,
SiteCode.VCD => true,
@@ -1286,6 +1332,7 @@ namespace SabreTools.RedumpLib.Data
SiteCode.XMID => true,
// Publisher / Company IDs
SiteCode.TwoKGamesID => true,
SiteCode.AcclaimID => true,
SiteCode.ActivisionID => true,
SiteCode.BandaiID => true,
@@ -1342,6 +1389,8 @@ namespace SabreTools.RedumpLib.Data
SiteCode.PlayableDemos => true,
SiteCode.RollingDemos => true,
SiteCode.Savegames => true,
SiteCode.SteamSimSidDepotID => true,
SiteCode.SteamCsmCsdDepotID => true,
SiteCode.TechDemos => true,
SiteCode.Videos => true,
_ => false,
@@ -1374,6 +1423,8 @@ namespace SabreTools.RedumpLib.Data
SiteCode.PlayableDemos => true,
SiteCode.RollingDemos => true,
SiteCode.Savegames => true,
SiteCode.SteamSimSidDepotID => true,
SiteCode.SteamCsmCsdDepotID => true,
SiteCode.TechDemos => true,
SiteCode.Videos => true,
_ => false,
@@ -1719,7 +1770,7 @@ namespace SabreTools.RedumpLib.Data
public static RedumpSystem? ToRedumpSystem(this string? system)
{
// No value means no match
if (system == null || system.Length == 0)
if (system is null || system.Length == 0)
return null;
system = system.ToLowerInvariant();
@@ -1795,4 +1846,6 @@ namespace SabreTools.RedumpLib.Data
#endregion
}
#pragma warning restore IDE0010
#pragma warning restore IDE0072
}

View File

@@ -33,7 +33,7 @@ namespace SabreTools.RedumpLib.Data.Sections
public object Clone()
{
Dictionary<string, List<string>?>? fullProtections = null;
if (this.FullProtections != null)
if (this.FullProtections is not null)
{
fullProtections = [];
foreach (var kvp in this.FullProtections)

View File

@@ -14,6 +14,9 @@ namespace SabreTools.RedumpLib.Data.Sections
[JsonProperty(PropertyName = "d_cue", NullValueHandling = NullValueHandling.Ignore)]
public string? Cuesheet { get; set; }
[JsonProperty(PropertyName = "d_cue_raw", NullValueHandling = NullValueHandling.Ignore)]
public byte[]? CuesheetRaw { get; set; }
[JsonProperty(PropertyName = "d_offset", NullValueHandling = NullValueHandling.Ignore)]
public int[]? CommonWriteOffsets { get; set; }
@@ -26,6 +29,7 @@ namespace SabreTools.RedumpLib.Data.Sections
{
ClrMameProData = this.ClrMameProData,
Cuesheet = this.Cuesheet,
CuesheetRaw = this.CuesheetRaw?.Clone() as byte[],
CommonWriteOffsets = this.CommonWriteOffsets?.Clone() as int[],
OtherWriteOffsets = this.OtherWriteOffsets,
};

View File

@@ -131,6 +131,7 @@ namespace SabreTools.RedumpLib
case Feature.WIP:
processedIds = await ProcessWIP();
break;
case Feature.NONE:
default:
return [];
}

View File

@@ -58,6 +58,7 @@ namespace SabreTools.RedumpLib
SiteCode.VCD,
// Publisher / Company IDs
SiteCode.TwoKGamesID,
SiteCode.AcclaimID,
SiteCode.ActivisionID,
SiteCode.BandaiID,
@@ -82,6 +83,7 @@ namespace SabreTools.RedumpLib
SiteCode.SegaID,
SiteCode.SelenID,
SiteCode.SierraID,
SiteCode.SteamAppID,
SiteCode.TaitoID,
SiteCode.UbisoftID,
SiteCode.ValveID,
@@ -101,6 +103,8 @@ namespace SabreTools.RedumpLib
// Games
SiteCode.Games,
SiteCode.NetYarozeGames,
SiteCode.SteamSimSidDepotID,
SiteCode.SteamCsmCsdDepotID,
// Demos
SiteCode.PlayableDemos,
@@ -126,7 +130,7 @@ namespace SabreTools.RedumpLib
public static string? FormatOutputData(SubmissionInfo? info, bool enableRedumpCompatibility, out string? status)
{
// Check to see if the inputs are valid
if (info == null)
if (info is null)
{
status = "Submission information was missing";
return null;
@@ -207,11 +211,11 @@ namespace SabreTools.RedumpLib
public static void ProcessSpecialFields(SubmissionInfo info)
{
// If there is no submission info
if (info?.CommonDiscInfo == null)
if (info?.CommonDiscInfo is null)
return;
// Process the comments field
if (info.CommonDiscInfo.CommentsSpecialFields != null && info.CommonDiscInfo.CommentsSpecialFields.Count > 0)
if (info.CommonDiscInfo.CommentsSpecialFields is not null && info.CommonDiscInfo.CommentsSpecialFields.Count > 0)
{
// If the field is missing, add an empty one to fill in
info.CommonDiscInfo.Comments ??= string.Empty;
@@ -231,7 +235,7 @@ namespace SabreTools.RedumpLib
}
// Process the contents field
if (info.CommonDiscInfo.ContentsSpecialFields != null && info.CommonDiscInfo.ContentsSpecialFields.Count > 0)
if (info.CommonDiscInfo.ContentsSpecialFields is not null && info.CommonDiscInfo.ContentsSpecialFields.Count > 0)
{
// If the field is missing, add an empty one to fill in
info.CommonDiscInfo.Contents ??= string.Empty;
@@ -413,14 +417,14 @@ namespace SabreTools.RedumpLib
internal static void FormatOutputData(StringBuilder output, ExtrasSection? section)
{
// Optional sections have to exist to format
if (section == null)
if (section is null)
return;
// Check the section can be added
if (section.PVD == null
&& section.PIC == null
&& section.BCA == null
&& section.SecuritySectorRanges == null)
if (section.PVD is null
&& section.PIC is null
&& section.BCA is null
&& section.SecuritySectorRanges is null)
{
return;
}
@@ -444,13 +448,13 @@ namespace SabreTools.RedumpLib
RedumpSystem? system)
{
// Optional sections have to exist to format
if (section == null)
if (section is null)
return;
// Check the section can be added
if (string.IsNullOrEmpty(section.Protection)
&& (section.AntiModchip == null || section.AntiModchip == YesNo.NULL)
&& (section.LibCrypt == null || section.LibCrypt == YesNo.NULL)
&& (section.AntiModchip is null || section.AntiModchip == YesNo.NULL)
&& (section.LibCrypt is null || section.LibCrypt == YesNo.NULL)
&& string.IsNullOrEmpty(section.LibCryptData)
&& string.IsNullOrEmpty(section.SecuROMData))
{
@@ -479,6 +483,7 @@ namespace SabreTools.RedumpLib
AddIfExists(output, Template.DATField, section.ClrMameProData + "\n", 1);
AddIfExists(output, Template.CuesheetField, section.Cuesheet, 1);
// TODO: Figure out how to emit raw cuesheet field instead of normal cuesheet
var offset = section.OtherWriteOffsets;
if (int.TryParse(offset, out int i))
offset = i.ToString("+#;-#;0");
@@ -499,7 +504,7 @@ namespace SabreTools.RedumpLib
// Gross hack because of automatic layerbreaks in Redump
if (!enableRedumpCompatibility
|| (mediaType != MediaType.BluRay && system.IsXGD() == false))
|| (mediaType != MediaType.BluRay && !system.IsXGD()))
{
AddIfExists(output, Template.LayerbreakField, section?.Layerbreak, 1);
}
@@ -540,7 +545,7 @@ namespace SabreTools.RedumpLib
private static void AddIfExists(StringBuilder output, string key, string? value, int indent)
{
// If there's no valid value to write
if (value == null)
if (value is null)
return;
string prefix = string.Empty;
@@ -603,7 +608,7 @@ namespace SabreTools.RedumpLib
private static void AddIfExists(StringBuilder output, string key, string?[]? value, int indent)
{
// If there's no valid value to write
if (value == null || value.Length == 0)
if (value is null || value.Length == 0)
return;
AddIfExists(output, key, string.Join(", ", value), indent);
@@ -619,7 +624,7 @@ namespace SabreTools.RedumpLib
private static void AddIfExists(StringBuilder output, string key, long? value, int indent)
{
// If there's no valid value to write
if (value == null || value == default(long))
if (value is null || value == default(long))
return;
string prefix = string.Empty;
@@ -641,7 +646,7 @@ namespace SabreTools.RedumpLib
private static void AddIfExists(StringBuilder output, string key, List<int>? value, int indent)
{
// If there's no valid value to write
if (value == null || value.Count == 0)
if (value is null || value.Count == 0)
return;
AddIfExists(output, key, string.Join(", ", [.. value.ConvertAll(o => o.ToString())]), indent);
@@ -686,6 +691,7 @@ namespace SabreTools.RedumpLib
/// <returns>String representation of the media, including layer specification</returns>
internal static string? GetFixedMediaType(MediaType? mediaType, string? picIdentifier, long? size, long? layerbreak, long? layerbreak2, long? layerbreak3)
{
#pragma warning disable IDE0010
switch (mediaType)
{
case MediaType.DVD:
@@ -727,6 +733,7 @@ namespace SabreTools.RedumpLib
default:
return mediaType.LongName();
}
#pragma warning restore IDE0010
}
/// <summary>
@@ -736,7 +743,7 @@ namespace SabreTools.RedumpLib
internal static KeyValuePair<SiteCode, string>[] OrderCommentTags(Dictionary<SiteCode, string> tags)
{
// If the input is invalid, just return an empty set
if (tags == null || tags.Count == 0)
if (tags is null || tags.Count == 0)
return [];
// Loop through the ordered set of codes and add if needed
@@ -766,7 +773,7 @@ namespace SabreTools.RedumpLib
internal static KeyValuePair<SiteCode, string>[] OrderContentTags(Dictionary<SiteCode, string> tags)
{
// If the input is invalid, just return an empty set
if (tags == null || tags.Count == 0)
if (tags is null || tags.Count == 0)
return [];
// Loop through the ordered set of codes and add if needed

View File

@@ -8,7 +8,7 @@
<Nullable>enable</Nullable>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.9.0</Version>
<Version>1.9.1</Version>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>

View File

@@ -16,9 +16,10 @@ namespace SabreTools.RedumpLib
public static void NormalizeDiscType(SubmissionInfo info)
{
// If we have nothing valid, do nothing
if (info.CommonDiscInfo.Media == null || info.SizeAndChecksums == default)
if (info.CommonDiscInfo.Media is null || info.SizeAndChecksums == default)
return;
#pragma warning disable IDE0010
switch (info.CommonDiscInfo.Media)
{
case DiscType.DVD5:
@@ -73,6 +74,7 @@ namespace SabreTools.RedumpLib
default:
break;
}
#pragma warning restore IDE0010
}
/// <summary>
@@ -82,7 +84,7 @@ namespace SabreTools.RedumpLib
/// <param name="query">Query string to attempt to search for</param>
/// <param name="filterForwardSlashes">True to filter forward slashes, false otherwise</param>
/// <returns>All disc IDs for the given query, null on error</returns>
public async static Task<List<int>?> ListSearchResults(RedumpClient rc, string? query, bool filterForwardSlashes = true)
public static async Task<List<int>?> ListSearchResults(RedumpClient rc, string? query, bool filterForwardSlashes = true)
{
// If there is an invalid query
if (string.IsNullOrEmpty(query))
@@ -108,7 +110,10 @@ namespace SabreTools.RedumpLib
int pageNumber = 1;
while (true)
{
List<int> pageIds = await rc.CheckSingleSitePage(string.Format(Constants.QuickSearchUrl, query, pageNumber++));
List<int>? pageIds = await rc.CheckSingleSitePage(string.Format(Constants.QuickSearchUrl, query, pageNumber++));
if (pageIds is null)
return null;
ids.AddRange(pageIds);
if (pageIds.Count <= 1)
break;
@@ -130,21 +135,21 @@ namespace SabreTools.RedumpLib
/// <param name="info">Existing SubmissionInfo object to fill</param>
/// <param name="sha1">SHA-1 hash to check against</param>
/// <returns>List of found values, if possible</returns>
public async static Task<List<int>?> ValidateSingleTrack(RedumpClient rc, SubmissionInfo info, string? sha1)
public static async 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)
if (newIds is null)
return null;
// If no IDs match, just return
// If no IDs match, return an empty list
if (newIds.Count == 0)
return null;
return [];
// Join the list of found IDs to the existing list, if possible
if (info.PartiallyMatchedIDs != null && info.PartiallyMatchedIDs.Count > 0)
if (info.PartiallyMatchedIDs is not null && info.PartiallyMatchedIDs.Count > 0)
info.PartiallyMatchedIDs.AddRange(newIds);
else
info.PartiallyMatchedIDs = newIds;
@@ -158,10 +163,10 @@ namespace SabreTools.RedumpLib
/// <param name="rc">RedumpClient for making the connection</param>
/// <param name="info">Existing SubmissionInfo object to fill</param>
/// <returns>List of found values, if possible</returns>
public async static Task<List<int>?> ValidateUniversalHash(RedumpClient rc, SubmissionInfo info)
public static async Task<List<int>?> ValidateUniversalHash(RedumpClient rc, SubmissionInfo info)
{
// If we don't have special fields
if (info.CommonDiscInfo.CommentsSpecialFields == null)
if (info.CommonDiscInfo.CommentsSpecialFields is null)
return null;
// If we don't have a universal hash
@@ -180,15 +185,15 @@ namespace SabreTools.RedumpLib
var newIds = await ListSearchResults(rc, universalHashQuery, filterForwardSlashes: false);
// If we got null back, there was an error
if (newIds == null)
if (newIds is null)
return null;
// If no IDs match, just return
// If no IDs match, just an empty list
if (newIds.Count == 0)
return null;
return [];
// Join the list of found IDs to the existing list, if possible
if (info.PartiallyMatchedIDs != null && info.PartiallyMatchedIDs.Count > 0)
if (info.PartiallyMatchedIDs is not null && info.PartiallyMatchedIDs.Count > 0)
info.PartiallyMatchedIDs.AddRange(newIds);
else
info.PartiallyMatchedIDs = newIds;
@@ -203,7 +208,7 @@ namespace SabreTools.RedumpLib
/// <param name="id">Redump disc ID to retrieve</param>
/// <param name="localCount">Local count of tracks for the current disc</param>
/// <returns>True if the track count matches, false otherwise</returns>
public async static Task<bool> ValidateTrackCount(RedumpClient rc, int id, int localCount)
public static async Task<bool> ValidateTrackCount(RedumpClient rc, int id, int localCount)
{
// If we can't pull the remote data, we can't match
string? discData = await rc.DownloadSingleSiteID(id);

View File

@@ -1,9 +1,11 @@
using System;
using System.Net;
#pragma warning disable SYSLIB0014 // 'WebClient.WebClient()' is obsolete
namespace SabreTools.RedumpLib.Web
{
#if NET6_0_OR_GREATER
#pragma warning disable SYSLIB0014
#endif
internal class CookieWebClient : WebClient
{
/// <summary>
@@ -20,7 +22,7 @@ namespace SabreTools.RedumpLib.Web
public string? GetLastFilename()
{
// If the response headers are null or empty
if (ResponseHeaders == null || ResponseHeaders.Count == 0)
if (ResponseHeaders is null || ResponseHeaders.Count == 0)
return null;
// If we don't have the response header we care about
@@ -49,4 +51,7 @@ namespace SabreTools.RedumpLib.Web
return request;
}
}
#if NET6_0_OR_GREATER
#pragma warning restore SYSLIB0014
#endif
}

View File

@@ -39,7 +39,7 @@ 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> DownloadPacksForSystem(RedumpClient rc, RedumpSystem? system, string? outDir, bool useSubfolders)
{
if (system == null)
if (system is null)
return false;
var systemAsArray = new RedumpSystem[] { system.Value };

View File

@@ -77,7 +77,7 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Validate supplied credentials
/// </summary>
public async static Task<bool?> ValidateCredentials(string username, string password)
public static async 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))
@@ -150,7 +150,7 @@ namespace SabreTools.RedumpLib.Web
// Send the login request and get the result
var response = await _internalClient.PostAsync(Constants.LoginUrl, postContent);
string? responseContent = null;
if (response?.Content != null)
if (response?.Content is not null)
responseContent = await response.Content.ReadAsStringAsync();
#endif
@@ -241,7 +241,7 @@ namespace SabreTools.RedumpLib.Web
#else
// Make the call to get the file
var response = await _internalClient.GetAsync(uri);
if (response?.Content?.Headers == null || !response.IsSuccessStatusCode)
if (response?.Content?.Headers is null || !response.IsSuccessStatusCode)
{
Console.WriteLine($"Could not download {uri}");
return null;
@@ -299,15 +299,19 @@ namespace SabreTools.RedumpLib.Web
/// </summary>
/// <param name="url">Base URL to download using</param>
/// <returns>List of IDs from the page, empty on error</returns>
public async Task<List<int>> CheckSingleSitePage(string url)
public async Task<List<int>?> CheckSingleSitePage(string url)
{
List<int> ids = [];
// Try to retrieve the data
string? dumpsPage = await DownloadString(url);
// If the web client failed, return null
if (dumpsPage is null)
return null;
// If we have no dumps left
if (dumpsPage == null || dumpsPage.Contains("No discs found."))
if (dumpsPage.Contains("No discs found."))
return ids;
// If we have a single disc page already
@@ -324,7 +328,7 @@ namespace SabreTools.RedumpLib.Web
var matches = Constants.DiscRegex.Matches(dumpsPage);
foreach (Match? match in matches)
{
if (match == null)
if (match is null)
continue;
try
@@ -357,7 +361,7 @@ namespace SabreTools.RedumpLib.Web
string? dumpsPage = await DownloadString(url);
// If we have no dumps left
if (dumpsPage == null || dumpsPage.Contains("No discs found."))
if (dumpsPage is null || dumpsPage.Contains("No discs found."))
return ids;
// If we have a single disc page already
@@ -380,7 +384,7 @@ namespace SabreTools.RedumpLib.Web
var matches = Constants.DiscRegex.Matches(dumpsPage);
foreach (Match? match in matches)
{
if (match == null)
if (match is null)
continue;
try
@@ -417,14 +421,14 @@ namespace SabreTools.RedumpLib.Web
string? dumpsPage = await DownloadString(url);
// If we have no dumps left
if (dumpsPage == null || dumpsPage.Contains("No discs found."))
if (dumpsPage is null || 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)
{
if (match == null)
if (match is null)
continue;
try
@@ -457,14 +461,14 @@ namespace SabreTools.RedumpLib.Web
string? dumpsPage = await DownloadString(url);
// If we have no dumps left
if (dumpsPage == null || dumpsPage.Contains("No discs found."))
if (dumpsPage is null || 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)
{
if (match == null)
if (match is null)
continue;
try
@@ -561,7 +565,7 @@ namespace SabreTools.RedumpLib.Web
string discPageUri = string.Format(Constants.DiscPageUrl, +id);
string? discPage = await DownloadString(discPageUri);
if (discPage == null || discPage.Contains($"Disc with ID \"{id}\" doesn't exist"))
if (discPage is null || discPage.Contains($"Disc with ID \"{id}\" doesn't exist"))
{
Console.WriteLine($"ID {paddedId} could not be found!");
return null;
@@ -599,7 +603,7 @@ namespace SabreTools.RedumpLib.Web
string discPageUri = string.Format(Constants.DiscPageUrl, +id);
string? discPage = await DownloadString(discPageUri);
if (discPage == null || discPage.Contains($"Disc with ID \"{id}\" doesn't exist"))
if (discPage is null || discPage.Contains($"Disc with ID \"{id}\" doesn't exist"))
{
try
{
@@ -723,7 +727,7 @@ namespace SabreTools.RedumpLib.Web
string discPageUri = string.Format(Constants.WipDiscPageUrl, +id);
string? discPage = await DownloadString(discPageUri);
if (discPage == null || discPage.Contains($"WIP disc with ID \"{id}\" doesn't exist"))
if (discPage is null || discPage.Contains($"WIP disc with ID \"{id}\" doesn't exist"))
{
Console.WriteLine($"ID {paddedId} could not be found!");
return null;
@@ -761,7 +765,7 @@ namespace SabreTools.RedumpLib.Web
string discPageUri = string.Format(Constants.WipDiscPageUrl, +id);
string? discPage = await DownloadString(discPageUri);
if (discPage == null || discPage.Contains($"WIP disc with ID \"{id}\" doesn't exist"))
if (discPage is null || discPage.Contains($"WIP disc with ID \"{id}\" doesn't exist"))
{
try
{
@@ -855,7 +859,7 @@ namespace SabreTools.RedumpLib.Web
Console.Write($"\r{longName}{new string(' ', Console.BufferWidth - longName!.Length - 1)}");
byte[]? pack = await DownloadSinglePack(url, system);
if (pack != null)
if (pack is not null)
packsDictionary.Add(system, pack);
}

View File

@@ -43,7 +43,10 @@ namespace SabreTools.RedumpLib.Web
int pageNumber = 1;
while (true)
{
List<int> pageIds = await rc.CheckSingleSitePage(string.Format(Constants.QuickSearchUrl, query, pageNumber++));
var pageIds = await rc.CheckSingleSitePage(string.Format(Constants.QuickSearchUrl, query, pageNumber++));
if (pageIds is null)
return [];
ids.AddRange(pageIds);
if (pageIds.Count <= 1)
break;

View File

@@ -93,6 +93,9 @@ namespace SabreTools.RedumpLib.Web
while (true)
{
var pageIds = await rc.CheckSingleSitePage(string.Format(Constants.UserDumpsUrl, username, pageNumber++));
if (pageIds is null)
return [];
ids.AddRange(pageIds);
if (pageIds.Count <= 1)
break;