Compare commits

...

44 Commits

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
Matt Nadareski
67ee824e1b Bump version 2025-11-13 08:15:21 -05:00
Matt Nadareski
d256187a0a Add support for .NET 10 2025-11-13 08:09:47 -05:00
Matt Nadareski
6589fec1bc Update rolling tag 2025-10-26 20:28:50 -04:00
Matt Nadareski
c6832a5c2d Bump version 2025-10-22 08:58:57 -04:00
Matt Nadareski
77d922a9bc Minor collection cleanup in tests 2025-10-22 08:50:18 -04:00
Matt Nadareski
7b590e9bba Separate out sections to new files for maintainability 2025-10-22 08:41:57 -04:00
Matt Nadareski
0968bfe786 Ensure adding IDs only after 2025-10-21 18:41:53 -04:00
Matt Nadareski
5acb6ee128 Minor fixes 2025-10-21 18:36:15 -04:00
Matt Nadareski
5dc9ef27ef Update gitignore 2025-10-21 18:32:30 -04:00
Matt Nadareski
d5ccc0c65c Simplify downloader creation 2025-10-21 18:29:04 -04:00
Matt Nadareski
0ef9c6f87a Add console writes on failure cases 2025-10-21 18:11:20 -04:00
Matt Nadareski
638630ccab Disallow some fields from being null 2025-10-21 17:44:15 -04:00
Matt Nadareski
6c3afd25d4 Formatting pass 2025-10-21 17:33:12 -04:00
Matt Nadareski
02572c75fc Make timeout configurable by implementer 2025-10-21 17:30:31 -04:00
Matt Nadareski
cb5b42166d Reduce tab-to-space size to 2 2025-10-16 08:02:09 -04:00
Matt Nadareski
97ea30228e Bump version 2025-10-12 09:00:39 -04:00
Deterous
675af1a619 Add XboxOne/SX TitleID (#12) 2025-10-12 08:56:09 -04:00
Matt Nadareski
28c3f54cc5 Update test packages 2025-10-07 16:21:47 -04:00
Matt Nadareski
51486950fa Bump version 2025-09-24 13:35:03 -04:00
Matt Nadareski
1b1ba94247 Remove reliance on Models library 2025-09-24 13:33:42 -04:00
Matt Nadareski
c4345d0c34 Bump version 2025-09-22 18:00:58 -04:00
Matt Nadareski
b88b877672 Update Nuget packages 2025-09-22 17:58:12 -04:00
Matt Nadareski
f0c5375ac5 There 2025-09-10 21:53:06 -04:00
Matt Nadareski
1f4cca7fa0 Bump version 2025-09-05 10:14:28 -04:00
Matt Nadareski
5161913d96 Update Nuget packages 2025-09-05 09:45:00 -04:00
Deterous
c10b21a485 Add Polymega system (#11)
* Add Polymega system

* Polymega detected by windows
2025-08-31 01:22:51 -04:00
49 changed files with 4151 additions and 3572 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,40 +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@v4
with:
submodules: recursive
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
9.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: Upload to rolling
uses: ncipollo/release-action@v1.14.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: Run publish script
run: ./publish-nix.sh -d
- 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@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
9.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

296
.gitignore vendored
View File

@@ -1,15 +1,7 @@
*.swp
*.*~
project.lock.json
.DS_Store
*.pyc
nupkg/
# Visual Studio Code
.vscode
# Rider
.idea
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
@@ -17,6 +9,9 @@ nupkg/
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
@@ -24,15 +19,280 @@ nupkg/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
msbuild.log
msbuild.err
msbuild.wrn
[Ll]og/
# Visual Studio 2015
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

22
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,22 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/RedumpTool/bin/Debug/net10.0/RedumpTool.dll",
"args": [],
"cwd": "${workspaceFolder}/RedumpTool",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false,
"justMyCode": false
}
]
}

24
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,24 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "shell",
"args": [
"build",
// Ask dotnet build to generate full paths for file names.
"/property:GenerateFullPaths=true",
// Do not generate summary otherwise it leads to duplicate errors in Problems panel
"/consoleloggerparameters:NoSummary"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
]
}

7
LICENSE Normal file
View File

@@ -0,0 +1,7 @@
Copyright (c) 2018-2025 Matt Nadareski
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -7,11 +7,12 @@ 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();
return;
}
@@ -20,14 +21,16 @@ namespace RedumpTool
Feature feature = DeriveFeature(args[0]);
if (feature == Feature.NONE)
{
Console.WriteLine("The feature could not be derived");
ShowHelp();
return;
}
// 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();
return;
}
@@ -45,6 +48,7 @@ namespace RedumpTool
}
else if (downloaderResult.Count == 0 && downloader.Feature != Feature.Packs)
{
Console.WriteLine("No results were found");
ShowHelp();
}
}
@@ -76,20 +80,8 @@ namespace RedumpTool
/// <returns>Initialized Downloader on success, null otherwise</returns>
private static Downloader? CreateDownloader(Feature feature, string[] args)
{
// Set temporary internal variables
string? outDir = null;
string? username = null;
string? password = null;
int minimumId = -1;
int maximumId = -1;
string? queryString = null;
bool useSubfolders = false;
bool onlyNew = false;
bool onlyList = false;
bool noSlash = false;
bool force = false;
// Now loop through all of the arguments
// Loop through all of the arguments
var downloader = new Downloader() { Feature = feature };
try
{
for (int i = 1; i < args.Length; i++)
@@ -99,69 +91,73 @@ namespace RedumpTool
// Output directory
case "-o":
case "--output":
outDir = args[++i].Trim('"');
downloader.OutDir = args[++i].Trim('"');
break;
// Username
case "-u":
case "--username":
username = args[++i];
downloader.Username = args[++i];
break;
// Password
case "-p":
case "--password":
password = args[++i];
downloader.Password = args[++i];
break;
// Minimum Redump ID
case "-min":
case "--minimum":
if (!int.TryParse(args[++i], out minimumId))
if (!int.TryParse(args[++i], out int minimumId))
minimumId = -1;
downloader.MinimumId = minimumId;
break;
// Maximum Redump ID
case "-max":
case "--maximum":
if (!int.TryParse(args[++i], out maximumId))
if (!int.TryParse(args[++i], out int maximumId))
maximumId = -1;
downloader.MaximumId = maximumId;
break;
// Quicksearch text
case "-q":
case "--query":
queryString = args[++i];
downloader.QueryString = args[++i];
break;
// Packs subfolders
case "-s":
case "--subfolders":
useSubfolders = true;
downloader.UseSubfolders = true;
break;
// Use last modified
case "-n":
case "--onlynew":
onlyNew = true;
downloader.OnlyNew = true;
break;
// List instead of download
case "-l":
case "--list":
onlyList = true;
downloader.OnlyList = true;
break;
// Don't filter forward slashes from queries
case "-ns":
case "--noslash":
noSlash = true;
downloader.NoSlash = true;
break;
// Force continuation
case "-f":
case "--force":
force = true;
downloader.Force = true;
break;
// Everything else
@@ -178,18 +174,18 @@ namespace RedumpTool
}
// Output directory validation
if (!onlyList && string.IsNullOrEmpty(outDir))
if (!downloader.OnlyList && string.IsNullOrEmpty(downloader.OutDir))
{
Console.WriteLine("No output directory set!");
return null;
}
else if (!onlyList && !string.IsNullOrEmpty(outDir))
else if (!downloader.OnlyList && !string.IsNullOrEmpty(downloader.OutDir))
{
// Create the output directory, if it doesn't exist
try
{
if (!Directory.Exists(outDir))
Directory.CreateDirectory(outDir);
if (!Directory.Exists(downloader.OutDir))
Directory.CreateDirectory(downloader.OutDir!);
}
catch (Exception ex)
{
@@ -199,40 +195,25 @@ namespace RedumpTool
}
// Range verification
if (feature == Feature.Site && !onlyNew && (minimumId < 0 || maximumId < 0))
if (feature == Feature.Site && !downloader.OnlyNew && (downloader.MinimumId < 0 || downloader.MaximumId < 0))
{
Console.WriteLine("Please enter a valid range of Redump IDs");
return null;
}
else if (feature == Feature.WIP && !onlyNew && (minimumId < 0 || maximumId < 0))
else if (feature == Feature.WIP && !downloader.OnlyNew && (downloader.MinimumId < 0 || downloader.MaximumId < 0))
{
Console.WriteLine("Please enter a valid range of WIP IDs");
return null;
}
// Query verification (and cleanup)
if (feature == Feature.Quicksearch && string.IsNullOrEmpty(queryString))
if (feature == Feature.Quicksearch && string.IsNullOrEmpty(downloader.QueryString))
{
Console.WriteLine("Please enter a query for searching");
return null;
}
// Create and return the downloader
var downloader = new Downloader()
{
Feature = feature,
MinimumId = minimumId,
MaximumId = maximumId,
QueryString = queryString,
OutDir = outDir,
UseSubfolders = useSubfolders,
OnlyNew = onlyNew,
OnlyList = onlyList,
Force = force,
NoSlash = noSlash,
Username = username,
Password = password,
};
// Return the downloader
return downloader;
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
<OutputType>Exe</OutputType>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
@@ -9,7 +9,7 @@
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.7.1</Version>
<Version>1.9.1</Version>
</PropertyGroup>
<!-- Support All Frameworks -->
@@ -19,15 +19,15 @@
<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`))">
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\SabreTools.RedumpLib\SabreTools.RedumpLib.csproj" />
</ItemGroup>
</Project>
</Project>

View File

@@ -1,5 +1,3 @@
using System;
using System.IO;
using SabreTools.RedumpLib.Data;
@@ -23,105 +21,9 @@ 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]
public void EnsureAllSections_Null_Filled()
{
SubmissionInfo? si = null;
var actual = Builder.EnsureAllSections(si);
Assert.NotNull(actual);
Assert.NotNull(actual.CommonDiscInfo);
Assert.NotNull(actual.CommonDiscInfo.CommentsSpecialFields);
Assert.NotNull(actual.CommonDiscInfo.ContentsSpecialFields);
Assert.NotNull(actual.VersionAndEditions);
Assert.NotNull(actual.EDC);
Assert.NotNull(actual.ParentCloneRelationship);
Assert.NotNull(actual.Extras);
Assert.NotNull(actual.CopyProtection);
Assert.NotNull(actual.DumpersAndStatus);
Assert.NotNull(actual.TracksAndWriteOffsets);
Assert.NotNull(actual.SizeAndChecksums);
Assert.NotNull(actual.DumpingInfo);
Assert.NotNull(actual.Artifacts);
}
[Fact]
public void EnsureAllSections_Empty_Filled()
{
SubmissionInfo? si = new SubmissionInfo
{
CommonDiscInfo = null,
VersionAndEditions = null,
EDC = null,
ParentCloneRelationship = null,
Extras = null,
CopyProtection = null,
DumpersAndStatus = null,
TracksAndWriteOffsets = null,
SizeAndChecksums = null,
DumpingInfo = null,
Artifacts = null,
};
var actual = Builder.EnsureAllSections(si);
Assert.NotNull(actual);
Assert.NotNull(actual.CommonDiscInfo);
Assert.NotNull(actual.CommonDiscInfo.CommentsSpecialFields);
Assert.NotNull(actual.CommonDiscInfo.ContentsSpecialFields);
Assert.NotNull(actual.VersionAndEditions);
Assert.NotNull(actual.EDC);
Assert.NotNull(actual.ParentCloneRelationship);
Assert.NotNull(actual.Extras);
Assert.NotNull(actual.CopyProtection);
Assert.NotNull(actual.DumpersAndStatus);
Assert.NotNull(actual.TracksAndWriteOffsets);
Assert.NotNull(actual.SizeAndChecksums);
Assert.NotNull(actual.DumpingInfo);
Assert.NotNull(actual.Artifacts);
}
[Fact]
public void EnsureAllSections_Filled_Filled()
{
SubmissionInfo? si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection
{
CommentsSpecialFields = [],
ContentsSpecialFields = [],
},
VersionAndEditions = new VersionAndEditionsSection(),
EDC = new EDCSection(),
ParentCloneRelationship = new ParentCloneRelationshipSection(),
Extras = new ExtrasSection(),
CopyProtection = new CopyProtectionSection(),
DumpersAndStatus = new DumpersAndStatusSection(),
TracksAndWriteOffsets = new TracksAndWriteOffsetsSection(),
SizeAndChecksums = new SizeAndChecksumsSection(),
DumpingInfo = new DumpingInfoSection(),
Artifacts = [],
};
var actual = Builder.EnsureAllSections(si);
Assert.NotNull(actual);
Assert.NotNull(actual.CommonDiscInfo);
Assert.NotNull(actual.CommonDiscInfo.CommentsSpecialFields);
Assert.NotNull(actual.CommonDiscInfo.ContentsSpecialFields);
Assert.NotNull(actual.VersionAndEditions);
Assert.NotNull(actual.EDC);
Assert.NotNull(actual.ParentCloneRelationship);
Assert.NotNull(actual.Extras);
Assert.NotNull(actual.CopyProtection);
Assert.NotNull(actual.DumpersAndStatus);
Assert.NotNull(actual.TracksAndWriteOffsets);
Assert.NotNull(actual.SizeAndChecksums);
Assert.NotNull(actual.DumpingInfo);
Assert.NotNull(actual.Artifacts);
}
[Fact]
public void InjectSubmissionInformation_BothNull_Null()
{
@@ -135,7 +37,7 @@ namespace SabreTools.RedumpLib.Test
[Fact]
public void InjectSubmissionInformation_ValidInputNullSeed_Valid()
{
SubmissionInfo? si = new SubmissionInfo();
SubmissionInfo? si = new();
SubmissionInfo? seed = null;
var actual = Builder.InjectSubmissionInformation(si, seed);
@@ -145,8 +47,8 @@ namespace SabreTools.RedumpLib.Test
[Fact]
public void InjectSubmissionInformation_BothValid_Valid()
{
SubmissionInfo? si = new SubmissionInfo();
SubmissionInfo? seed = new SubmissionInfo();
SubmissionInfo? si = new();
SubmissionInfo? seed = new();
var actual = Builder.InjectSubmissionInformation(si, seed);
Assert.NotNull(actual);
@@ -188,4 +90,4 @@ namespace SabreTools.RedumpLib.Test
Assert.Equal(expected, actual);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,4 +5,4 @@ namespace SabreTools.RedumpLib.Test
// Tests here will require installing and using the Moq library
// to mock the RedumpClient type.
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
using Xunit;
namespace SabreTools.RedumpLib.Test
@@ -66,7 +67,7 @@ namespace SabreTools.RedumpLib.Test
string expected = "Version and Editions:\n\tVersion: XXXXXX\n\tEdition/Release: XXXXXX\n";
var builder = new StringBuilder();
VersionAndEditionsSection? section = new VersionAndEditionsSection
VersionAndEditionsSection? section = new()
{
Version = "XXXXXX",
OtherEditions = "XXXXXX",
@@ -118,7 +119,7 @@ namespace SabreTools.RedumpLib.Test
string expected = "EDC:\n\tEDC: Yes\n";
var builder = new StringBuilder();
EDCSection? section = new EDCSection { EDC = YesNo.Yes };
EDCSection? section = new() { EDC = YesNo.Yes };
RedumpSystem? system = RedumpSystem.SonyPlayStation;
Formatter.FormatOutputData(builder, section, system);
@@ -151,7 +152,7 @@ namespace SabreTools.RedumpLib.Test
string expected = string.Empty;
var builder = new StringBuilder();
ExtrasSection? section = new ExtrasSection
ExtrasSection? section = new()
{
PVD = null,
PIC = null,
@@ -171,7 +172,7 @@ namespace SabreTools.RedumpLib.Test
string expected = "Extras:\n\tPrimary Volume Descriptor (PVD): XXXXXX\n\tDisc Key: XXXXXX\n\tDisc ID: XXXXXX\n\tPermanent Information & Control (PIC): XXXXXX\n\tHeader: XXXXXX\n\tBCA: XXXXXX\n\tSecurity Sector Ranges: XXXXXX\n";
var builder = new StringBuilder();
ExtrasSection? section = new ExtrasSection
ExtrasSection? section = new()
{
PVD = "XXXXXX",
DiscKey = "XXXXXX",
@@ -213,7 +214,7 @@ namespace SabreTools.RedumpLib.Test
string expected = string.Empty;
var builder = new StringBuilder();
CopyProtectionSection? section = new CopyProtectionSection
CopyProtectionSection? section = new()
{
Protection = null,
AntiModchip = null,
@@ -235,7 +236,7 @@ namespace SabreTools.RedumpLib.Test
string expected = "Copy Protection:\n\tCopy Protection: XXXXXX\n\tSubIntention Data (SecuROM/LibCrypt): XXXXXX\n";
var builder = new StringBuilder();
CopyProtectionSection? section = new CopyProtectionSection
CopyProtectionSection? section = new()
{
AntiModchip = YesNo.Yes,
LibCrypt = YesNo.Yes,
@@ -257,7 +258,7 @@ namespace SabreTools.RedumpLib.Test
string expected = "Copy Protection:\n\tAnti-modchip: Yes\n\tLibCrypt: Yes\n\tSubIntention Data (SecuROM/LibCrypt): XXXXXX\n\tCopy Protection: XXXXXX\n\tSubIntention Data (SecuROM/LibCrypt): XXXXXX\n";
var builder = new StringBuilder();
CopyProtectionSection? section = new CopyProtectionSection
CopyProtectionSection? section = new()
{
AntiModchip = YesNo.Yes,
LibCrypt = YesNo.Yes,
@@ -283,7 +284,7 @@ namespace SabreTools.RedumpLib.Test
string expected = "Tracks and Write Offsets:\n\tDAT:\n\n\n\n\n";
var builder = new StringBuilder();
TracksAndWriteOffsetsSection? section = new TracksAndWriteOffsetsSection();
TracksAndWriteOffsetsSection? section = new();
Formatter.FormatOutputData(builder, section);
@@ -297,10 +298,11 @@ namespace SabreTools.RedumpLib.Test
string expected = "Tracks and Write Offsets:\n\tDAT:\n\nXXXXXX\n\n\n\tCuesheet: XXXXXX\n\tWrite Offset: XXXXXX\n";
var builder = new StringBuilder();
TracksAndWriteOffsetsSection? section = new TracksAndWriteOffsetsSection
TracksAndWriteOffsetsSection? section = new()
{
ClrMameProData = "XXXXXX",
Cuesheet = "XXXXXX",
CuesheetRaw = [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39],
OtherWriteOffsets = "XXXXXX",
};
@@ -340,7 +342,7 @@ namespace SabreTools.RedumpLib.Test
string expected = "Dumping Info:\n\tFrontend Version: XXXXXX\n\tDumping Program: XXXXXX\n\tDate: XXXXXX\n\tParameters: XXXXXX\n\tManufacturer: XXXXXX\n\tModel: XXXXXX\n\tFirmware: XXXXXX\n\tReported Disc Type: XXXXXX\n\tC2 Error Count: XXXXXX\n";
var builder = new StringBuilder();
DumpingInfoSection? section = new DumpingInfoSection
DumpingInfoSection? section = new()
{
FrontendVersion = "XXXXXX",
DumpingProgram = "XXXXXX",
@@ -556,7 +558,7 @@ namespace SabreTools.RedumpLib.Test
string? expected = "BD-ROM-66";
MediaType? mediaType = MediaType.BluRay;
string? picIdentifier = Models.PIC.Constants.DiscTypeIdentifierROMUltra;
string? picIdentifier = "BDU";
long? size = null;
long? layerbreak = 12345;
long? layerbreak2 = null;
@@ -622,7 +624,7 @@ namespace SabreTools.RedumpLib.Test
string? expected = "BD-ROM-33";
MediaType? mediaType = MediaType.BluRay;
string? picIdentifier = Models.PIC.Constants.DiscTypeIdentifierROMUltra;
string? picIdentifier = "BDU";
long? size = null;
long? layerbreak = null;
long? layerbreak2 = null;
@@ -874,4 +876,4 @@ namespace SabreTools.RedumpLib.Test
#endregion
}
}
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
@@ -24,11 +24,11 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeCoverage" Version="17.14.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Microsoft.CodeCoverage" Version="18.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
<PackageReference Include="xunit.analyzers" Version="1.23.0" />
<PackageReference Include="xunit.analyzers" Version="1.25.0" />
<PackageReference Include="xunit.assert" Version="2.9.3" />
<PackageReference Include="xunit.core" Version="2.9.3" />
<PackageReference Include="xunit.extensibility.core" Version="2.9.3" />
@@ -37,7 +37,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3">
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@@ -1,181 +1,183 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Data;
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 = new List<int> { 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 = new Language?[] { Language.English, Language.Spanish, Language.French },
LanguageSelection = new 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 = new string[] { "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 = new string[] { "Dumper1", "Dumper2" },
OtherDumpers = "Dumper3",
},
TracksAndWriteOffsets = new TracksAndWriteOffsetsSection()
{
ClrMameProData = "Datfile",
Cuesheet = "Cuesheet",
CommonWriteOffsets = new int[] { 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

@@ -1,4 +1,5 @@
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
using Xunit;
namespace SabreTools.RedumpLib.Test
@@ -11,7 +12,7 @@ namespace SabreTools.RedumpLib.Test
[Fact]
public void NormalizeDiscType_InvalidMedia_Untouched()
{
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = null }
};
@@ -25,10 +26,10 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_InvalidSizeChecksums_Untouched()
{
DiscType expected = DiscType.CD;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = DiscType.CD },
SizeAndChecksums = null,
SizeAndChecksums = new(),
};
Validator.NormalizeDiscType(si);
@@ -40,7 +41,7 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_UnformattedType_Fixed()
{
DiscType expected = DiscType.CD;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = DiscType.CD },
SizeAndChecksums = new SizeAndChecksumsSection(),
@@ -57,7 +58,7 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_DVD9_Fixed(DiscType type)
{
DiscType expected = DiscType.DVD9;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection { Layerbreak = 12345 },
@@ -74,7 +75,7 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_DVD5_Fixed(DiscType type)
{
DiscType expected = DiscType.DVD5;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection(),
@@ -95,7 +96,7 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_BD128_Fixed(DiscType type)
{
DiscType expected = DiscType.BD128;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection { Layerbreak3 = 12345 },
@@ -116,7 +117,7 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_BD100_Fixed(DiscType type)
{
DiscType expected = DiscType.BD100;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection { Layerbreak2 = 12345 },
@@ -137,13 +138,13 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_BD66PIC_Fixed(DiscType type)
{
DiscType expected = DiscType.BD66;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection
{
Layerbreak = 12345,
PICIdentifier = Models.PIC.Constants.DiscTypeIdentifierROMUltra,
PICIdentifier = "BDU",
},
};
@@ -162,7 +163,7 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_BD66Size_Fixed(DiscType type)
{
DiscType expected = DiscType.BD66;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection
@@ -187,7 +188,7 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_BD50_Fixed(DiscType type)
{
DiscType expected = DiscType.BD50;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection { Layerbreak = 12345 },
@@ -208,12 +209,12 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_BD33PIC_Fixed(DiscType type)
{
DiscType expected = DiscType.BD33;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection
{
PICIdentifier = Models.PIC.Constants.DiscTypeIdentifierROMUltra,
PICIdentifier = "BDU",
},
};
@@ -232,7 +233,7 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_BD33Size_Fixed(DiscType type)
{
DiscType expected = DiscType.BD33;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection
@@ -256,7 +257,7 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_BD25_Fixed(DiscType type)
{
DiscType expected = DiscType.BD25;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection(),
@@ -273,7 +274,7 @@ namespace SabreTools.RedumpLib.Test
public void NormalizeDiscType_UMDDL_Fixed(DiscType type)
{
DiscType expected = DiscType.UMDDL;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection { Layerbreak = 12345 },
@@ -284,13 +285,13 @@ 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)
{
DiscType expected = DiscType.UMDSL;
SubmissionInfo si = new SubmissionInfo
var si = new SubmissionInfo
{
CommonDiscInfo = new CommonDiscInfoSection { Media = type },
SizeAndChecksums = new SizeAndChecksumsSection(),
@@ -301,4 +302,4 @@ namespace SabreTools.RedumpLib.Test
Assert.Equal(expected, si.CommonDiscInfo.Media);
}
}
}
}

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

@@ -10,6 +10,7 @@ using System.Threading.Tasks;
using System.Xml;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
using SabreTools.RedumpLib.Web;
namespace SabreTools.RedumpLib
@@ -53,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()
@@ -77,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
@@ -85,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
@@ -93,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"
@@ -105,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
@@ -124,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
@@ -135,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
@@ -157,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
@@ -165,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
}
@@ -243,6 +245,7 @@ namespace SabreTools.RedumpLib
return info;
}
#pragma warning restore IDE0051
/// <summary>
/// Fill out an existing SubmissionInfo object based on a disc page
@@ -251,10 +254,8 @@ 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)
{
// Ensure that required sections exist
info = EnsureAllSections(info);
var discData = await rc.DownloadSingleSiteID(id);
if (string.IsNullOrEmpty(discData))
return false;
@@ -267,20 +268,28 @@ 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];
#else
info.CommonDiscInfo!.Title = title.Substring(0, firstParenLocation);
#endif
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;
// Disc number or letter
if (submatchValue.StartsWith("Disc"))
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
info.CommonDiscInfo.DiscNumberLetter = submatchValue["Disc ".Length..];
#else
info.CommonDiscInfo.DiscNumberLetter = submatchValue.Remove(0, "Disc ".Length);
#endif
// Issue number
else if (ulong.TryParse(submatchValue, out _))
@@ -311,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)
@@ -325,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);
}
@@ -354,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)
@@ -367,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);
@@ -375,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);
}
@@ -440,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
@@ -475,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";
}
@@ -537,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
@@ -563,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";
}
@@ -605,35 +614,6 @@ namespace SabreTools.RedumpLib
return true;
}
/// <summary>
/// Ensure all required sections in a submission info exist
/// </summary>
/// <param name="info">SubmissionInfo object to verify</param>
public static SubmissionInfo EnsureAllSections(SubmissionInfo? info)
{
// If there's no info, create one
info ??= new SubmissionInfo();
// Ensure all sections
info.CommonDiscInfo ??= new CommonDiscInfoSection();
info.VersionAndEditions ??= new VersionAndEditionsSection();
info.EDC ??= new EDCSection();
info.ParentCloneRelationship ??= new ParentCloneRelationshipSection();
info.Extras ??= new ExtrasSection();
info.CopyProtection ??= new CopyProtectionSection();
info.DumpersAndStatus ??= new DumpersAndStatusSection();
info.TracksAndWriteOffsets ??= new TracksAndWriteOffsetsSection();
info.SizeAndChecksums ??= new SizeAndChecksumsSection();
info.DumpingInfo ??= new DumpingInfoSection();
info.Artifacts ??= [];
// Ensure special dictionaries
info.CommonDiscInfo.CommentsSpecialFields ??= [];
info.CommonDiscInfo.ContentsSpecialFields ??= [];
return info;
}
/// <summary>
/// Inject information from a seed SubmissionInfo into the existing one
/// </summary>
@@ -642,65 +622,55 @@ 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;
// Ensure that required sections exist
info = EnsureAllSections(info);
// Otherwise, inject information as necessary
if (info.CommonDiscInfo != null && seed.CommonDiscInfo != null)
{
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Title)) info.CommonDiscInfo.Title = seed.CommonDiscInfo.Title;
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 (!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 (!string.IsNullOrEmpty(seed.CommonDiscInfo.Contents)) info.CommonDiscInfo.Contents = seed.CommonDiscInfo.Contents;
if (seed.CommonDiscInfo.ContentsSpecialFields != null) info.CommonDiscInfo.ContentsSpecialFields = seed.CommonDiscInfo.ContentsSpecialFields;
info ??= new SubmissionInfo();
// Info that always overwrites
info.CommonDiscInfo.Layer0MasteringRing = seed.CommonDiscInfo.Layer0MasteringRing;
info.CommonDiscInfo.Layer0MasteringSID = seed.CommonDiscInfo.Layer0MasteringSID;
info.CommonDiscInfo.Layer0ToolstampMasteringCode = seed.CommonDiscInfo.Layer0ToolstampMasteringCode;
info.CommonDiscInfo.Layer0MouldSID = seed.CommonDiscInfo.Layer0MouldSID;
info.CommonDiscInfo.Layer0AdditionalMould = seed.CommonDiscInfo.Layer0AdditionalMould;
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.CommonDiscInfo.Title)) info.CommonDiscInfo.Title = seed.CommonDiscInfo.Title;
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 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 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 is not null) info.CommonDiscInfo.ContentsSpecialFields = seed.CommonDiscInfo.ContentsSpecialFields;
info.CommonDiscInfo.Layer1MasteringRing = seed.CommonDiscInfo.Layer1MasteringRing;
info.CommonDiscInfo.Layer1MasteringSID = seed.CommonDiscInfo.Layer1MasteringSID;
info.CommonDiscInfo.Layer1ToolstampMasteringCode = seed.CommonDiscInfo.Layer1ToolstampMasteringCode;
info.CommonDiscInfo.Layer1MouldSID = seed.CommonDiscInfo.Layer1MouldSID;
info.CommonDiscInfo.Layer1AdditionalMould = seed.CommonDiscInfo.Layer1AdditionalMould;
// Info that always overwrites
info.CommonDiscInfo.Layer0MasteringRing = seed.CommonDiscInfo.Layer0MasteringRing;
info.CommonDiscInfo.Layer0MasteringSID = seed.CommonDiscInfo.Layer0MasteringSID;
info.CommonDiscInfo.Layer0ToolstampMasteringCode = seed.CommonDiscInfo.Layer0ToolstampMasteringCode;
info.CommonDiscInfo.Layer0MouldSID = seed.CommonDiscInfo.Layer0MouldSID;
info.CommonDiscInfo.Layer0AdditionalMould = seed.CommonDiscInfo.Layer0AdditionalMould;
info.CommonDiscInfo.Layer2MasteringRing = seed.CommonDiscInfo.Layer2MasteringRing;
info.CommonDiscInfo.Layer2MasteringSID = seed.CommonDiscInfo.Layer2MasteringSID;
info.CommonDiscInfo.Layer2ToolstampMasteringCode = seed.CommonDiscInfo.Layer2ToolstampMasteringCode;
info.CommonDiscInfo.Layer1MasteringRing = seed.CommonDiscInfo.Layer1MasteringRing;
info.CommonDiscInfo.Layer1MasteringSID = seed.CommonDiscInfo.Layer1MasteringSID;
info.CommonDiscInfo.Layer1ToolstampMasteringCode = seed.CommonDiscInfo.Layer1ToolstampMasteringCode;
info.CommonDiscInfo.Layer1MouldSID = seed.CommonDiscInfo.Layer1MouldSID;
info.CommonDiscInfo.Layer1AdditionalMould = seed.CommonDiscInfo.Layer1AdditionalMould;
info.CommonDiscInfo.Layer3MasteringRing = seed.CommonDiscInfo.Layer3MasteringRing;
info.CommonDiscInfo.Layer3MasteringSID = seed.CommonDiscInfo.Layer3MasteringSID;
info.CommonDiscInfo.Layer3ToolstampMasteringCode = seed.CommonDiscInfo.Layer3ToolstampMasteringCode;
}
info.CommonDiscInfo.Layer2MasteringRing = seed.CommonDiscInfo.Layer2MasteringRing;
info.CommonDiscInfo.Layer2MasteringSID = seed.CommonDiscInfo.Layer2MasteringSID;
info.CommonDiscInfo.Layer2ToolstampMasteringCode = seed.CommonDiscInfo.Layer2ToolstampMasteringCode;
if (info.VersionAndEditions != null && seed.VersionAndEditions != null)
{
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.VersionAndEditions.Version)) info.VersionAndEditions.Version = seed.VersionAndEditions.Version;
if (!string.IsNullOrEmpty(seed.VersionAndEditions.OtherEditions)) info.VersionAndEditions.OtherEditions = seed.VersionAndEditions.OtherEditions;
}
info.CommonDiscInfo.Layer3MasteringRing = seed.CommonDiscInfo.Layer3MasteringRing;
info.CommonDiscInfo.Layer3MasteringSID = seed.CommonDiscInfo.Layer3MasteringSID;
info.CommonDiscInfo.Layer3ToolstampMasteringCode = seed.CommonDiscInfo.Layer3ToolstampMasteringCode;
if (info.CopyProtection != null && seed.CopyProtection != null)
{
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.CopyProtection.Protection)) info.CopyProtection.Protection = seed.CopyProtection.Protection;
}
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.VersionAndEditions.Version)) info.VersionAndEditions.Version = seed.VersionAndEditions.Version;
if (!string.IsNullOrEmpty(seed.VersionAndEditions.OtherEditions)) info.VersionAndEditions.OtherEditions = seed.VersionAndEditions.OtherEditions;
// Info that only overwrites if supplied
if (!string.IsNullOrEmpty(seed.CopyProtection.Protection)) info.CopyProtection.Protection = seed.CopyProtection.Protection;
return info;
}
@@ -710,6 +680,7 @@ namespace SabreTools.RedumpLib
/// </summary>
private static bool ShouldSkipSiteCode(SiteCode? siteCode)
{
#pragma warning disable IDE0072
return siteCode switch
{
// Multiple
@@ -733,6 +704,7 @@ namespace SabreTools.RedumpLib
// Microsoft Xbox One and Series X/S
SiteCode.Filename => true,
SiteCode.TitleID => true,
// Nintendo Gamecube
SiteCode.InternalName => true,
@@ -742,6 +714,7 @@ namespace SabreTools.RedumpLib
_ => false,
};
#pragma warning restore IDE0072
}
#endregion

View File

@@ -19,8 +19,7 @@ namespace SabreTools.RedumpLib.Converters
return existingValue;
// Read the value
string? value = reader.Value as string;
if (value == null)
if (reader.Value is not string value)
return null;
// Try to parse the value

View File

@@ -19,8 +19,7 @@ namespace SabreTools.RedumpLib.Converters
return existingValue;
// Read the value
string? value = reader.Value as string;
if (value == null)
if (reader.Value is not string value)
return null;
// Try to parse the value

View File

@@ -26,12 +26,11 @@ namespace SabreTools.RedumpLib.Converters
List<Language> languages = [];
while (reader.Read() && reader.Depth > currentDepth)
{
string? value = reader.Value as string;
if (value == null)
if (reader.Value is not string value)
continue;
Language? lang = Data.Extensions.ToLanguage(value);
if (lang != null)
if (lang is not null)
languages.Add(lang.Value);
}
@@ -40,10 +39,10 @@ namespace SabreTools.RedumpLib.Converters
public override void WriteJson(JsonWriter writer, Language?[]? value, JsonSerializer serializer)
{
if (value == null)
if (value is null)
return;
JArray array = new JArray();
JArray array = [];
foreach (var val in value)
{
JToken t = JToken.FromObject(val.ShortName() ?? string.Empty);

View File

@@ -26,12 +26,11 @@ namespace SabreTools.RedumpLib.Converters
List<LanguageSelection> selections = [];
while (reader.Read() && reader.Depth > currentDepth)
{
string? value = reader.Value as string;
if (value == null)
if (reader.Value is not string value)
continue;
LanguageSelection? sel = Data.Extensions.ToLanguageSelection(value);
if (sel != null)
if (sel is not null)
selections.Add(sel.Value);
}
@@ -40,10 +39,10 @@ namespace SabreTools.RedumpLib.Converters
public override void WriteJson(JsonWriter writer, LanguageSelection?[]? value, JsonSerializer serializer)
{
if (value == null)
if (value is null)
return;
JArray array = new JArray();
JArray array = [];
foreach (var val in value)
{
JToken t = JToken.FromObject(val.LongName() ?? string.Empty);

View File

@@ -19,8 +19,7 @@ namespace SabreTools.RedumpLib.Converters
return existingValue;
// Read the value
string? value = reader.Value as string;
if (value == null)
if (reader.Value is not string value)
return null;
// Try to parse the value

View File

@@ -19,8 +19,7 @@ namespace SabreTools.RedumpLib.Converters
return existingValue;
// Read the value
string? value = reader.Value as string;
if (value == null)
if (reader.Value is not string value)
return null;
// Try to parse the value

View File

@@ -9,17 +9,17 @@ namespace SabreTools.RedumpLib.Data
/// <summary>
/// Regex matching the added field on a disc page
/// </summary>
public static Regex AddedRegex = new(@"<tr><th>Added</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex AddedRegex = new(@"<tr><th>Added</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the barcode field on a disc page
/// </summary>
public static Regex BarcodeRegex = new(@"<tr><th>Barcode</th></tr><tr><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex BarcodeRegex = new(@"<tr><th>Barcode</th></tr><tr><td>(.*?)</td></tr>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the BCA field on a disc page
/// </summary>
public static Regex BcaRegex = new(@"<h3>BCA .*?/></h3></td><td .*?></td></tr>"
public static readonly Regex BcaRegex = new(@"<h3>BCA .*?/></h3></td><td .*?></td></tr>"
+ "<tr><th>Row</th><th>Contents</th><th>ASCII</th></tr>"
+ "<tr><td>(?<row1number>.*?)</td><td>(?<row1contents>.*?)</td><td>(?<row1ascii>.*?)</td></tr>"
+ "<tr><td>(?<row2number>.*?)</td><td>(?<row2contents>.*?)</td><td>(?<row2ascii>.*?)</td></tr>"
@@ -29,87 +29,87 @@ namespace SabreTools.RedumpLib.Data
/// <summary>
/// Regex matching the category field on a disc page
/// </summary>
public static Regex CategoryRegex = new(@"<tr><th>Category</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex CategoryRegex = new(@"<tr><th>Category</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the comments field on a disc page
/// </summary>
public static Regex CommentsRegex = new(@"<tr><th>Comments</th></tr><tr><td>(.*?)</td></tr>", RegexOptions.Compiled | RegexOptions.Singleline);
public static readonly Regex CommentsRegex = new(@"<tr><th>Comments</th></tr><tr><td>(.*?)</td></tr>", RegexOptions.Compiled | RegexOptions.Singleline);
/// <summary>
/// Regex matching the contents field on a disc page
/// </summary>
public static Regex ContentsRegex = new(@"<tr><th>Contents</th></tr><tr .*?><td>(.*?)</td></tr>", RegexOptions.Compiled | RegexOptions.Singleline);
public static readonly Regex ContentsRegex = new(@"<tr><th>Contents</th></tr><tr .*?><td>(.*?)</td></tr>", RegexOptions.Compiled | RegexOptions.Singleline);
/// <summary>
/// Regex matching individual disc links on a results page
/// </summary>
public static Regex DiscRegex = new(@"<a href=""/disc/(\d+)/"">", RegexOptions.Compiled);
public static readonly Regex DiscRegex = new(@"<a href=""/disc/(\d+)/"">", RegexOptions.Compiled);
/// <summary>
/// Regex matching the disc number or letter field on a disc page
/// </summary>
public static Regex DiscNumberLetterRegex = new(@"\((.*?)\)", RegexOptions.Compiled);
public static readonly Regex DiscNumberLetterRegex = new(@"\((.*?)\)", RegexOptions.Compiled);
/// <summary>
/// Regex matching the dumpers on a disc page
/// </summary>
public static Regex DumpersRegex = new(@"<a href=""/discs/dumper/(.*?)/"">", RegexOptions.Compiled);
public static readonly Regex DumpersRegex = new(@"<a href=""/discs/dumper/(.*?)/"">", RegexOptions.Compiled);
/// <summary>
/// Regex matching the edition field on a disc page
/// </summary>
public static Regex EditionRegex = new(@"<tr><th>Edition</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex EditionRegex = new(@"<tr><th>Edition</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the error count field on a disc page
/// </summary>
public static Regex ErrorCountRegex = new(@"<tr><th>Errors count</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex ErrorCountRegex = new(@"<tr><th>Errors count</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the foreign title field on a disc page
/// </summary>
public static Regex ForeignTitleRegex = new(@"<h2>(.*?)</h2>", RegexOptions.Compiled);
public static readonly Regex ForeignTitleRegex = new(@"<h2>(.*?)</h2>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the "full match" ID list from a WIP disc page
/// </summary>
public static Regex FullMatchRegex = new(@"<td class=""static"">full match ids: (.*?)</td>", RegexOptions.Compiled);
public static readonly Regex FullMatchRegex = new(@"<td class=""static"">full match ids: (.*?)</td>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the languages field on a disc page
/// </summary>
public static Regex LanguagesRegex = new(@"<img src=""/images/languages/(.*?)\.png"" alt="".*?"" title="".*?"" />\s*", RegexOptions.Compiled);
public static readonly Regex LanguagesRegex = new(@"<img src=""/images/languages/(.*?)\.png"" alt="".*?"" title="".*?"" />\s*", RegexOptions.Compiled);
/// <summary>
/// Regex matching the last modified field on a disc page
/// </summary>
public static Regex LastModifiedRegex = new(@"<tr><th>Last modified</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex LastModifiedRegex = new(@"<tr><th>Last modified</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the media field on a disc page
/// </summary>
public static Regex MediaRegex = new(@"<tr><th>Media</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex MediaRegex = new(@"<tr><th>Media</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
/// <summary>
/// Regex matching individual WIP disc links on a results page
/// </summary>
public static Regex NewDiscRegex = new(@"<a (style=.*)?href=""/newdisc/(\d+)/"">", RegexOptions.Compiled);
public static readonly Regex NewDiscRegex = new(@"<a (style=.*)?href=""/newdisc/(\d+)/"">", RegexOptions.Compiled);
/// <summary>
/// Regex matching the "partial match" ID list from a WIP disc page
/// </summary>
public static Regex PartialMatchRegex = new(@"<td class=""static"">partial match ids: (.*?)</td>", RegexOptions.Compiled);
public static readonly Regex PartialMatchRegex = new(@"<td class=""static"">partial match ids: (.*?)</td>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the disc key on a PS3 disc page
/// </summary>
public static Regex PS3DiscKey = new(@"<th>Disc Key</th><th>Disc ID</th><th>Permanent Information & Control \(PIC\)</th></tr><tr><td>(.*?)</td><td>", RegexOptions.Compiled);
public static readonly Regex PS3DiscKey = new(@"<th>Disc Key</th><th>Disc ID</th><th>Permanent Information & Control \(PIC\)</th></tr><tr><td>(.*?)</td><td>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the PVD field on a disc page
/// </summary>
public static Regex PvdRegex = new(@"<h3>Primary Volume Descriptor (PVD) <img .*?/></h3></td><td .*?></td></tr>"
public static readonly Regex PvdRegex = new(@"<h3>Primary Volume Descriptor (PVD) <img .*?/></h3></td><td .*?></td></tr>"
+ @"<tr><th>Record / Entry</th><th>Contents</th><th>Date</th><th>Time</th><th>GMT</th></tr>"
+ @"<tr><td>Creation</td><td>(?<creationbytes>.*?)</td><td>(?<creationdate>.*?)</td><td>(?<creationtime>.*?)</td><td>(?<creationtimezone>.*?)</td></tr>"
+ @"<tr><td>Modification</td><td>(?<modificationbytes>.*?)</td><td>(?<modificationdate>.*?)</td><td>(?<modificationtime>.*?)</td><td>(?<modificationtimezone>.*?)</td></tr>"
@@ -119,57 +119,57 @@ namespace SabreTools.RedumpLib.Data
/// <summary>
/// Regex matching the region field on a disc page
/// </summary>
public static Regex RegionRegex = new(@"<tr><th>Region</th><td><a href=""/discs/region/(.*?)/"">", RegexOptions.Compiled);
public static readonly Regex RegionRegex = new(@"<tr><th>Region</th><td><a href=""/discs/region/(.*?)/"">", RegexOptions.Compiled);
/// <summary>
/// Regex matching a double-layer disc ringcode information
/// </summary>
public static Regex RingCodeDoubleRegex = new(@"", RegexOptions.Compiled | RegexOptions.Singleline); // Varies based on available fields, like Addtional Mould
public static readonly Regex RingCodeDoubleRegex = new(@"", RegexOptions.Compiled | RegexOptions.Singleline); // Varies based on available fields, like Addtional Mould
/// <summary>
/// Regex matching a single-layer disc ringcode information
/// </summary>
public static Regex RingCodeSingleRegex = new(@"", RegexOptions.Compiled | RegexOptions.Singleline); // Varies based on available fields, like Addtional Mould
public static readonly Regex RingCodeSingleRegex = new(@"", RegexOptions.Compiled | RegexOptions.Singleline); // Varies based on available fields, like Addtional Mould
/// <summary>
/// Regex matching the serial field on a disc page
/// </summary>
public static Regex SerialRegex = new(@"<tr><th>Serial</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex SerialRegex = new(@"<tr><th>Serial</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the system field on a disc page
/// </summary>
public static Regex SystemRegex = new(@"<tr><th>System</th><td><a href=""/discs/system/(.*?)/"">", RegexOptions.Compiled);
public static readonly Regex SystemRegex = new(@"<tr><th>System</th><td><a href=""/discs/system/(.*?)/"">", RegexOptions.Compiled);
/// <summary>
/// Regex matching the title field on a disc page
/// </summary>
public static Regex TitleRegex = new(@"<h1>(.*?)</h1>", RegexOptions.Compiled);
public static readonly Regex TitleRegex = new(@"<h1>(.*?)</h1>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the current nonce token for login
/// </summary>
public static Regex TokenRegex = new(@"<input type=""hidden"" name=""csrf_token"" value=""(.*?)"" />", RegexOptions.Compiled);
public static readonly Regex TokenRegex = new(@"<input type=""hidden"" name=""csrf_token"" value=""(.*?)"" />", RegexOptions.Compiled);
/// <summary>
/// Regex matching a single track on a disc page
/// </summary>
public static Regex TrackRegex = new(@"<tr><td>(?<number>.*?)</td><td>(?<type>.*?)</td><td>(?<pregap>.*?)</td><td>(?<length>.*?)</td><td>(?<sectors>.*?)</td><td>(?<size>.*?)</td><td>(?<crc32>.*?)</td><td>(?<md5>.*?)</td><td>(?<sha1>.*?)</td></tr>", RegexOptions.Compiled | RegexOptions.Singleline);
public static readonly Regex TrackRegex = new(@"<tr><td>(?<number>.*?)</td><td>(?<type>.*?)</td><td>(?<pregap>.*?)</td><td>(?<length>.*?)</td><td>(?<sectors>.*?)</td><td>(?<size>.*?)</td><td>(?<crc32>.*?)</td><td>(?<md5>.*?)</td><td>(?<sha1>.*?)</td></tr>", RegexOptions.Compiled | RegexOptions.Singleline);
/// <summary>
/// Regex matching the track count on a disc page
/// </summary>
public static Regex TrackCountRegex = new(@"<tr><th>Number of tracks</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex TrackCountRegex = new(@"<tr><th>Number of tracks</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the version field on a disc page
/// </summary>
public static Regex VersionRegex = new(@"<tr><th>Version</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex VersionRegex = new(@"<tr><th>Version</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
/// <summary>
/// Regex matching the write offset field on a disc page
/// </summary>
public static Regex WriteOffsetRegex = new(@"<tr><th>Write offset</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
public static readonly Regex WriteOffsetRegex = new(@"<tr><th>Write offset</th><td>(.*?)</td></tr>", RegexOptions.Compiled);
#endregion

View File

@@ -2008,6 +2008,9 @@ namespace SabreTools.RedumpLib.Data
[System(Category = SystemCategory.DiscBasedConsole, LongName = "Philips CD-i", ShortName = "cdi", HasCues = true, HasDat = true)]
PhilipsCDi,
[System(Category = SystemCategory.DiscBasedConsole, Available = false, LongName = "Playmaji Polymega")]
PlaymajiPolymega,
[System(Category = SystemCategory.DiscBasedConsole, Available = false, LongName = "Pioneer LaserActive")]
PioneerLaserActive,
@@ -2265,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,
@@ -2328,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,
@@ -2376,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,
@@ -2446,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,
@@ -2478,7 +2505,7 @@ namespace SabreTools.RedumpLib.Data
/// </summary>
/// <remarks>
/// https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
///
///
/// Because of how Redump stores region IDs, the second letter of each
/// code is lower-cased. In any other system, both letters would be
/// capitalized properly.
@@ -3379,7 +3406,7 @@ namespace SabreTools.RedumpLib.Data
[HumanReadable(LongName = "Thailand", ShortName = "Th")]
Thailand,
// East Timor was "Tp"
// East Timor was "Tp"
[HumanReadable(LongName = "Timor-Leste (East Timor)", ShortName = "Tl")]
TimorLeste,
@@ -3722,12 +3749,32 @@ 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,
[HumanReadable(ShortName = "[T:TD]", LongName = "<b>Tech Demos</b>:")]
TechDemos,
// This doesn't have a site tag yet
[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
@@ -159,6 +161,12 @@ namespace SabreTools.RedumpLib.Data
types.Add(MediaType.CDROM);
break;
// https://en.wikipedia.org/wiki/Polymega
case RedumpSystem.PlaymajiPolymega:
types.Add(MediaType.CDROM);
types.Add(MediaType.DVD);
break;
// https://en.wikipedia.org/wiki/LaserActive
case RedumpSystem.PioneerLaserActive:
types.Add(MediaType.CDROM);
@@ -346,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);
@@ -470,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
@@ -566,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:
@@ -681,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);
@@ -691,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);
@@ -805,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();
@@ -848,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();
@@ -934,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();
@@ -1034,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();
@@ -1062,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()}");
@@ -1131,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();
@@ -1172,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
@@ -1271,6 +1322,8 @@ 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,
SiteCode.VFCCode => true,
@@ -1279,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,
@@ -1335,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,
@@ -1367,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,
@@ -1712,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();
@@ -1788,4 +1846,6 @@ namespace SabreTools.RedumpLib.Data
#endregion
}
#pragma warning restore IDE0010
#pragma warning restore IDE0072
}

View File

@@ -0,0 +1,202 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Converters;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Common disc info section of New Disc Form
/// </summary>
public class CommonDiscInfoSection : ICloneable
{
// Name not defined by Redump
[JsonProperty(PropertyName = "d_system", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(SystemConverter))]
public RedumpSystem? System { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_media", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(DiscTypeConverter))]
public DiscType? Media { get; set; }
[JsonProperty(PropertyName = "d_title", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Title { get; set; }
[JsonProperty(PropertyName = "d_title_foreign", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string? ForeignTitleNonLatin { get; set; }
[JsonProperty(PropertyName = "d_number", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscNumberLetter { get; set; }
[JsonProperty(PropertyName = "d_label", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscTitle { get; set; }
[JsonProperty(PropertyName = "d_category", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(DiscCategoryConverter))]
public DiscCategory? Category { get; set; }
[JsonProperty(PropertyName = "d_region", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(RegionConverter))]
public Region? Region { get; set; }
[JsonProperty(PropertyName = "d_languages", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(LanguageConverter))]
public Language?[]? Languages { get; set; }
[JsonProperty(PropertyName = "d_languages_selection", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
[JsonConverter(typeof(LanguageSelectionConverter))]
public LanguageSelection?[]? LanguageSelection { get; set; }
[JsonProperty(PropertyName = "d_serial", NullValueHandling = NullValueHandling.Ignore)]
public string? Serial { get; set; }
[JsonProperty(PropertyName = "d_ring", NullValueHandling = NullValueHandling.Ignore)]
public string? Ring { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_id", NullValueHandling = NullValueHandling.Ignore)]
public string? RingId { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_ma1", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer0MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma1_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts1", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo1_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0MouldSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo1", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0AdditionalMould { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma2", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer1MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma2_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts2", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo2_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1MouldSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo2", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1AdditionalMould { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma3", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer2MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma3_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer2MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts3", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer2ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma4", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer3MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma4_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer3MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts4", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer3ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_offsets", NullValueHandling = NullValueHandling.Ignore)]
public string RingOffsetsHidden { get { return "1"; } }
[JsonProperty(PropertyName = "d_ring_0_0_id", NullValueHandling = NullValueHandling.Ignore)]
public string? RingZeroId { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_0_density", NullValueHandling = NullValueHandling.Ignore)]
public string? RingZeroDensity { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_0_value", NullValueHandling = NullValueHandling.Ignore)]
public string? RingWriteOffset { get; set; }
[JsonProperty(PropertyName = "d_ring_count", NullValueHandling = NullValueHandling.Ignore)]
public string RingCount { get { return "1"; } }
[JsonProperty(PropertyName = "d_barcode", NullValueHandling = NullValueHandling.Ignore)]
public string? Barcode { get; set; }
[JsonProperty(PropertyName = "d_date", NullValueHandling = NullValueHandling.Ignore)]
public string? EXEDateBuildDate { get; set; }
[JsonProperty(PropertyName = "d_errors", NullValueHandling = NullValueHandling.Ignore)]
public string? ErrorsCount { get; set; }
[JsonProperty(PropertyName = "d_comments", NullValueHandling = NullValueHandling.Ignore)]
public string? Comments { get; set; }
[JsonIgnore]
public Dictionary<SiteCode, string> CommentsSpecialFields { get; set; } = [];
[JsonProperty(PropertyName = "d_contents", NullValueHandling = NullValueHandling.Ignore)]
public string? Contents { get; set; }
[JsonIgnore]
public Dictionary<SiteCode, string> ContentsSpecialFields { get; set; } = [];
public object Clone()
{
Dictionary<SiteCode, string> commentsSpecialFields = [];
foreach (var kvp in this.CommentsSpecialFields)
{
commentsSpecialFields[kvp.Key] = kvp.Value;
}
Dictionary<SiteCode, string> contentsSpecialFields = [];
foreach (var kvp in this.ContentsSpecialFields)
{
contentsSpecialFields[kvp.Key] = kvp.Value;
}
return new CommonDiscInfoSection
{
System = this.System,
Media = this.Media,
Title = this.Title,
ForeignTitleNonLatin = this.ForeignTitleNonLatin,
DiscNumberLetter = this.DiscNumberLetter,
DiscTitle = this.DiscTitle,
Category = this.Category,
Region = this.Region,
Languages = this.Languages?.Clone() as Language?[],
LanguageSelection = this.LanguageSelection?.Clone() as LanguageSelection?[],
Serial = this.Serial,
Ring = this.Ring,
RingId = this.RingId,
Layer0MasteringRing = this.Layer0MasteringRing,
Layer0MasteringSID = this.Layer0MasteringSID,
Layer0ToolstampMasteringCode = this.Layer0ToolstampMasteringCode,
Layer0MouldSID = this.Layer0MouldSID,
Layer0AdditionalMould = this.Layer0AdditionalMould,
Layer1MasteringRing = this.Layer1MasteringRing,
Layer1MasteringSID = this.Layer1MasteringSID,
Layer1ToolstampMasteringCode = this.Layer1ToolstampMasteringCode,
Layer1MouldSID = this.Layer1MouldSID,
Layer1AdditionalMould = this.Layer1AdditionalMould,
Layer2MasteringRing = this.Layer2MasteringRing,
Layer2MasteringSID = this.Layer2MasteringSID,
Layer2ToolstampMasteringCode = this.Layer2ToolstampMasteringCode,
Layer3MasteringRing = this.Layer3MasteringRing,
Layer3MasteringSID = this.Layer3MasteringSID,
Layer3ToolstampMasteringCode = this.Layer3ToolstampMasteringCode,
RingZeroId = this.RingZeroId,
RingZeroDensity = this.RingZeroDensity,
RingWriteOffset = this.RingWriteOffset,
Barcode = this.Barcode,
EXEDateBuildDate = this.EXEDateBuildDate,
ErrorsCount = this.ErrorsCount,
Comments = this.Comments,
CommentsSpecialFields = commentsSpecialFields,
Contents = this.Contents,
ContentsSpecialFields = contentsSpecialFields,
};
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Converters;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Copy protection section of New Disc form
/// </summary>
public class CopyProtectionSection : ICloneable
{
[JsonProperty(PropertyName = "d_protection_a", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? AntiModchip { get; set; }
[JsonProperty(PropertyName = "d_protection_1", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? LibCrypt { get; set; }
[JsonProperty(PropertyName = "d_libcrypt", NullValueHandling = NullValueHandling.Ignore)]
public string? LibCryptData { get; set; }
[JsonProperty(PropertyName = "d_protection", NullValueHandling = NullValueHandling.Ignore)]
public string? Protection { get; set; }
[JsonIgnore]
public Dictionary<string, List<string>?>? FullProtections { get; set; }
[JsonProperty(PropertyName = "d_securom", NullValueHandling = NullValueHandling.Ignore)]
public string? SecuROMData { get; set; }
public object Clone()
{
Dictionary<string, List<string>?>? fullProtections = null;
if (this.FullProtections is not null)
{
fullProtections = [];
foreach (var kvp in this.FullProtections)
{
fullProtections[kvp.Key] = kvp.Value;
}
}
return new CopyProtectionSection
{
AntiModchip = this.AntiModchip,
LibCrypt = this.LibCrypt,
LibCryptData = this.LibCryptData,
Protection = this.Protection,
FullProtections = fullProtections,
SecuROMData = this.SecuROMData,
};
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Dumpers and status section of New Disc form (Moderator only)
/// </summary>
public class DumpersAndStatusSection : ICloneable
{
[JsonProperty(PropertyName = "d_status", NullValueHandling = NullValueHandling.Ignore)]
public DumpStatus Status { get; set; }
[JsonProperty(PropertyName = "d_dumpers", NullValueHandling = NullValueHandling.Ignore)]
public string[]? Dumpers { get; set; }
[JsonProperty(PropertyName = "d_dumpers_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherDumpers { get; set; }
public object Clone()
{
return new DumpersAndStatusSection
{
Status = this.Status,
Dumpers = this.Dumpers?.Clone() as string[],
OtherDumpers = this.OtherDumpers,
};
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Dumping info section for moderation
/// </summary>
public class DumpingInfoSection : ICloneable
{
// Name not defined by Redump -- Only used with MPF
[JsonProperty(PropertyName = "d_frontend_version", DefaultValueHandling = DefaultValueHandling.Include)]
public string? FrontendVersion { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_program", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingProgram { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_date", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingDate { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_params", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingParameters { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_manufacturer", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Manufacturer { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_model", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Model { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_firmware", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Firmware { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_reported_disc_type", DefaultValueHandling = DefaultValueHandling.Include)]
public string? ReportedDiscType { get; set; }
// Name not defined by Redump -- Only used with Redumper
[JsonProperty(PropertyName = "d_errors_c2", NullValueHandling = NullValueHandling.Ignore)]
public string? C2ErrorsCount { get; set; }
public object Clone()
{
return new DumpingInfoSection
{
FrontendVersion = this.FrontendVersion,
DumpingProgram = this.DumpingProgram,
DumpingDate = this.DumpingDate,
DumpingParameters = this.DumpingParameters,
Manufacturer = this.Manufacturer,
Model = this.Model,
Firmware = this.Firmware,
ReportedDiscType = this.ReportedDiscType,
C2ErrorsCount = this.C2ErrorsCount,
};
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Converters;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// EDC section of New Disc form (PSX only)
/// </summary>
public class EDCSection : ICloneable
{
[JsonProperty(PropertyName = "d_edc", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? EDC { get; set; }
public object Clone()
{
return new EDCSection
{
EDC = this.EDC,
};
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Extras section of New Disc form
/// </summary>
public class ExtrasSection : ICloneable
{
[JsonProperty(PropertyName = "d_pvd", NullValueHandling = NullValueHandling.Ignore)]
public string? PVD { get; set; }
[JsonProperty(PropertyName = "d_d1_key", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscKey { get; set; }
[JsonProperty(PropertyName = "d_d2_key", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscID { get; set; }
[JsonProperty(PropertyName = "d_pic_data", NullValueHandling = NullValueHandling.Ignore)]
public string? PIC { get; set; }
[JsonProperty(PropertyName = "d_header", NullValueHandling = NullValueHandling.Ignore)]
public string? Header { get; set; }
[JsonProperty(PropertyName = "d_bca", NullValueHandling = NullValueHandling.Ignore)]
public string? BCA { get; set; }
[JsonProperty(PropertyName = "d_ssranges", NullValueHandling = NullValueHandling.Ignore)]
public string? SecuritySectorRanges { get; set; }
public object Clone()
{
return new ExtrasSection
{
PVD = this.PVD,
DiscKey = this.DiscKey,
DiscID = this.DiscID,
PIC = this.PIC,
Header = this.Header,
BCA = this.BCA,
SecuritySectorRanges = this.SecuritySectorRanges,
};
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Parent/Clone relationship section of New Disc form
/// </summary>
public class ParentCloneRelationshipSection : ICloneable
{
[JsonProperty(PropertyName = "d_parent_id", NullValueHandling = NullValueHandling.Ignore)]
public string? ParentID { get; set; }
[JsonProperty(PropertyName = "d_is_regional_parent", NullValueHandling = NullValueHandling.Ignore)]
public bool RegionalParent { get; set; }
public object Clone()
{
return new ParentCloneRelationshipSection
{
ParentID = this.ParentID,
RegionalParent = this.RegionalParent,
};
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Size &amp; checksums section of New Disc form (DVD/BD/UMD-based)
/// </summary>
public class SizeAndChecksumsSection : ICloneable
{
[JsonProperty(PropertyName = "d_layerbreak", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak { get; set; }
[JsonProperty(PropertyName = "d_layerbreak_2", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak2 { get; set; }
[JsonProperty(PropertyName = "d_layerbreak_3", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak3 { get; set; }
[JsonProperty(PropertyName = "d_pic_identifier", NullValueHandling = NullValueHandling.Ignore)]
public string? PICIdentifier { get; set; }
[JsonProperty(PropertyName = "d_size", NullValueHandling = NullValueHandling.Ignore)]
public long Size { get; set; }
[JsonProperty(PropertyName = "d_crc32", NullValueHandling = NullValueHandling.Ignore)]
public string? CRC32 { get; set; }
[JsonProperty(PropertyName = "d_md5", NullValueHandling = NullValueHandling.Ignore)]
public string? MD5 { get; set; }
[JsonProperty(PropertyName = "d_sha1", NullValueHandling = NullValueHandling.Ignore)]
public string? SHA1 { get; set; }
public object Clone()
{
return new SizeAndChecksumsSection
{
Layerbreak = this.Layerbreak,
Layerbreak2 = this.Layerbreak2,
Layerbreak3 = this.Layerbreak3,
PICIdentifier = this.PICIdentifier,
Size = this.Size,
CRC32 = this.CRC32,
MD5 = this.MD5,
SHA1 = this.SHA1,
};
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Tracks and write offsets section of New Disc form (CD/GD-based)
/// </summary>
public class TracksAndWriteOffsetsSection : ICloneable
{
[JsonProperty(PropertyName = "d_tracks", NullValueHandling = NullValueHandling.Ignore)]
public string? ClrMameProData { get; set; }
[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; }
[JsonProperty(PropertyName = "d_offset_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherWriteOffsets { get; set; }
public object Clone()
{
return new TracksAndWriteOffsetsSection
{
ClrMameProData = this.ClrMameProData,
Cuesheet = this.Cuesheet,
CuesheetRaw = this.CuesheetRaw?.Clone() as byte[],
CommonWriteOffsets = this.CommonWriteOffsets?.Clone() as int[],
OtherWriteOffsets = this.OtherWriteOffsets,
};
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using Newtonsoft.Json;
namespace SabreTools.RedumpLib.Data.Sections
{
/// <summary>
/// Version and editions section of New Disc form
/// </summary>
public class VersionAndEditionsSection : ICloneable
{
[JsonProperty(PropertyName = "d_version", NullValueHandling = NullValueHandling.Ignore)]
public string? Version { get; set; }
[JsonProperty(PropertyName = "d_version_datfile", NullValueHandling = NullValueHandling.Ignore)]
public string? VersionDatfile { get; set; }
[JsonProperty(PropertyName = "d_editions", NullValueHandling = NullValueHandling.Ignore)]
public string[]? CommonEditions { get; set; }
[JsonProperty(PropertyName = "d_editions_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherEditions { get; set; }
public object Clone()
{
return new VersionAndEditionsSection
{
Version = this.Version,
VersionDatfile = this.VersionDatfile,
CommonEditions = this.CommonEditions,
OtherEditions = this.OtherEditions,
};
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Converters;
using SabreTools.RedumpLib.Data.Sections;
namespace SabreTools.RedumpLib.Data
{
@@ -38,48 +38,44 @@ namespace SabreTools.RedumpLib.Data
public DateTime? LastModified { get; set; }
[JsonProperty(PropertyName = "common_disc_info", DefaultValueHandling = DefaultValueHandling.Ignore)]
public CommonDiscInfoSection? CommonDiscInfo { get; set; } = new CommonDiscInfoSection();
public CommonDiscInfoSection CommonDiscInfo { get; set; } = new CommonDiscInfoSection();
[JsonProperty(PropertyName = "versions_and_editions", DefaultValueHandling = DefaultValueHandling.Ignore)]
public VersionAndEditionsSection? VersionAndEditions { get; set; } = new VersionAndEditionsSection();
public VersionAndEditionsSection VersionAndEditions { get; set; } = new VersionAndEditionsSection();
[JsonProperty(PropertyName = "edc", DefaultValueHandling = DefaultValueHandling.Ignore)]
public EDCSection? EDC { get; set; } = new EDCSection();
public EDCSection EDC { get; set; } = new EDCSection();
[JsonProperty(PropertyName = "parent_clone_relationship", DefaultValueHandling = DefaultValueHandling.Ignore)]
public ParentCloneRelationshipSection? ParentCloneRelationship { get; set; } = new ParentCloneRelationshipSection();
public ParentCloneRelationshipSection ParentCloneRelationship { get; set; } = new ParentCloneRelationshipSection();
[JsonProperty(PropertyName = "extras", DefaultValueHandling = DefaultValueHandling.Ignore)]
public ExtrasSection? Extras { get; set; } = new ExtrasSection();
public ExtrasSection Extras { get; set; } = new ExtrasSection();
[JsonProperty(PropertyName = "copy_protection", DefaultValueHandling = DefaultValueHandling.Ignore)]
public CopyProtectionSection? CopyProtection { get; set; } = new CopyProtectionSection();
public CopyProtectionSection CopyProtection { get; set; } = new CopyProtectionSection();
[JsonProperty(PropertyName = "dumpers_and_status", DefaultValueHandling = DefaultValueHandling.Ignore)]
public DumpersAndStatusSection? DumpersAndStatus { get; set; } = new DumpersAndStatusSection();
public DumpersAndStatusSection DumpersAndStatus { get; set; } = new DumpersAndStatusSection();
[JsonProperty(PropertyName = "tracks_and_write_offsets", DefaultValueHandling = DefaultValueHandling.Ignore)]
public TracksAndWriteOffsetsSection? TracksAndWriteOffsets { get; set; } = new TracksAndWriteOffsetsSection();
public TracksAndWriteOffsetsSection TracksAndWriteOffsets { get; set; } = new TracksAndWriteOffsetsSection();
[JsonProperty(PropertyName = "size_and_checksums", DefaultValueHandling = DefaultValueHandling.Ignore)]
public SizeAndChecksumsSection? SizeAndChecksums { get; set; } = new SizeAndChecksumsSection();
public SizeAndChecksumsSection SizeAndChecksums { get; set; } = new SizeAndChecksumsSection();
[JsonProperty(PropertyName = "dumping_info", DefaultValueHandling = DefaultValueHandling.Ignore)]
public DumpingInfoSection? DumpingInfo { get; set; } = new DumpingInfoSection();
public DumpingInfoSection DumpingInfo { get; set; } = new DumpingInfoSection();
[JsonProperty(PropertyName = "artifacts", DefaultValueHandling = DefaultValueHandling.Ignore)]
public Dictionary<string, string>? Artifacts { get; set; } = [];
public Dictionary<string, string> Artifacts { get; set; } = [];
public object Clone()
{
Dictionary<string, string>? artifacts = null;
if (this.Artifacts != null)
Dictionary<string, string> artifacts = [];
foreach (var kvp in this.Artifacts)
{
artifacts = new Dictionary<string, string>();
foreach (var kvp in this.Artifacts)
{
artifacts[kvp.Key] = kvp.Value;
}
artifacts[kvp.Key] = kvp.Value;
}
return new SubmissionInfo
@@ -89,536 +85,18 @@ namespace SabreTools.RedumpLib.Data
PartiallyMatchedIDs = this.PartiallyMatchedIDs,
Added = this.Added,
LastModified = this.LastModified,
CommonDiscInfo = this.CommonDiscInfo?.Clone() as CommonDiscInfoSection,
VersionAndEditions = this.VersionAndEditions?.Clone() as VersionAndEditionsSection,
EDC = this.EDC?.Clone() as EDCSection,
ParentCloneRelationship = this.ParentCloneRelationship?.Clone() as ParentCloneRelationshipSection,
Extras = this.Extras?.Clone() as ExtrasSection,
CopyProtection = this.CopyProtection?.Clone() as CopyProtectionSection,
DumpersAndStatus = this.DumpersAndStatus?.Clone() as DumpersAndStatusSection,
TracksAndWriteOffsets = this.TracksAndWriteOffsets?.Clone() as TracksAndWriteOffsetsSection,
SizeAndChecksums = this.SizeAndChecksums?.Clone() as SizeAndChecksumsSection,
DumpingInfo = this.DumpingInfo?.Clone() as DumpingInfoSection,
CommonDiscInfo = this.CommonDiscInfo?.Clone() as CommonDiscInfoSection ?? new CommonDiscInfoSection(),
VersionAndEditions = this.VersionAndEditions?.Clone() as VersionAndEditionsSection ?? new VersionAndEditionsSection(),
EDC = this.EDC?.Clone() as EDCSection ?? new EDCSection(),
ParentCloneRelationship = this.ParentCloneRelationship?.Clone() as ParentCloneRelationshipSection ?? new ParentCloneRelationshipSection(),
Extras = this.Extras?.Clone() as ExtrasSection ?? new ExtrasSection(),
CopyProtection = this.CopyProtection?.Clone() as CopyProtectionSection ?? new CopyProtectionSection(),
DumpersAndStatus = this.DumpersAndStatus?.Clone() as DumpersAndStatusSection ?? new DumpersAndStatusSection(),
TracksAndWriteOffsets = this.TracksAndWriteOffsets?.Clone() as TracksAndWriteOffsetsSection ?? new TracksAndWriteOffsetsSection(),
SizeAndChecksums = this.SizeAndChecksums?.Clone() as SizeAndChecksumsSection ?? new SizeAndChecksumsSection(),
DumpingInfo = this.DumpingInfo?.Clone() as DumpingInfoSection ?? new DumpingInfoSection(),
Artifacts = artifacts,
};
}
}
/// <summary>
/// Common disc info section of New Disc Form
/// </summary>
public class CommonDiscInfoSection : ICloneable
{
// Name not defined by Redump
[JsonProperty(PropertyName = "d_system", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(SystemConverter))]
public RedumpSystem? System { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_media", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(DiscTypeConverter))]
public DiscType? Media { get; set; }
[JsonProperty(PropertyName = "d_title", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Title { get; set; }
[JsonProperty(PropertyName = "d_title_foreign", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string? ForeignTitleNonLatin { get; set; }
[JsonProperty(PropertyName = "d_number", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscNumberLetter { get; set; }
[JsonProperty(PropertyName = "d_label", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscTitle { get; set; }
[JsonProperty(PropertyName = "d_category", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(DiscCategoryConverter))]
public DiscCategory? Category { get; set; }
[JsonProperty(PropertyName = "d_region", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(RegionConverter))]
public Region? Region { get; set; }
[JsonProperty(PropertyName = "d_languages", DefaultValueHandling = DefaultValueHandling.Include)]
[JsonConverter(typeof(LanguageConverter))]
public Language?[]? Languages { get; set; }
[JsonProperty(PropertyName = "d_languages_selection", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
[JsonConverter(typeof(LanguageSelectionConverter))]
public LanguageSelection?[]? LanguageSelection { get; set; }
[JsonProperty(PropertyName = "d_serial", NullValueHandling = NullValueHandling.Ignore)]
public string? Serial { get; set; }
[JsonProperty(PropertyName = "d_ring", NullValueHandling = NullValueHandling.Ignore)]
public string? Ring { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_id", NullValueHandling = NullValueHandling.Ignore)]
public string? RingId { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_ma1", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer0MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma1_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts1", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo1_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0MouldSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo1", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer0AdditionalMould { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma2", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer1MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma2_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts2", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo2_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1MouldSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_mo2", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer1AdditionalMould { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma3", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer2MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma3_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer2MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts3", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer2ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma4", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Layer3MasteringRing { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ma4_sid", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer3MasteringSID { get; set; }
[JsonProperty(PropertyName = "d_ring_0_ts4", NullValueHandling = NullValueHandling.Ignore)]
public string? Layer3ToolstampMasteringCode { get; set; }
[JsonProperty(PropertyName = "d_ring_0_offsets", NullValueHandling = NullValueHandling.Ignore)]
public string RingOffsetsHidden { get { return "1"; } }
[JsonProperty(PropertyName = "d_ring_0_0_id", NullValueHandling = NullValueHandling.Ignore)]
public string? RingZeroId { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_0_density", NullValueHandling = NullValueHandling.Ignore)]
public string? RingZeroDensity { get; private set; }
[JsonProperty(PropertyName = "d_ring_0_0_value", NullValueHandling = NullValueHandling.Ignore)]
public string? RingWriteOffset { get; set; }
[JsonProperty(PropertyName = "d_ring_count", NullValueHandling = NullValueHandling.Ignore)]
public string RingCount { get { return "1"; } }
[JsonProperty(PropertyName = "d_barcode", NullValueHandling = NullValueHandling.Ignore)]
public string? Barcode { get; set; }
[JsonProperty(PropertyName = "d_date", NullValueHandling = NullValueHandling.Ignore)]
public string? EXEDateBuildDate { get; set; }
[JsonProperty(PropertyName = "d_errors", NullValueHandling = NullValueHandling.Ignore)]
public string? ErrorsCount { get; set; }
[JsonProperty(PropertyName = "d_comments", NullValueHandling = NullValueHandling.Ignore)]
public string? Comments { get; set; }
[JsonIgnore]
public Dictionary<SiteCode, string>? CommentsSpecialFields { get; set; }
[JsonProperty(PropertyName = "d_contents", NullValueHandling = NullValueHandling.Ignore)]
public string? Contents { get; set; }
[JsonIgnore]
public Dictionary<SiteCode, string>? ContentsSpecialFields { get; set; }
public object Clone()
{
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;
}
}
return new CommonDiscInfoSection
{
System = this.System,
Media = this.Media,
Title = this.Title,
ForeignTitleNonLatin = this.ForeignTitleNonLatin,
DiscNumberLetter = this.DiscNumberLetter,
DiscTitle = this.DiscTitle,
Category = this.Category,
Region = this.Region,
Languages = this.Languages?.Clone() as Language?[],
LanguageSelection = this.LanguageSelection?.Clone() as LanguageSelection?[],
Serial = this.Serial,
Ring = this.Ring,
RingId = this.RingId,
Layer0MasteringRing = this.Layer0MasteringRing,
Layer0MasteringSID = this.Layer0MasteringSID,
Layer0ToolstampMasteringCode = this.Layer0ToolstampMasteringCode,
Layer0MouldSID = this.Layer0MouldSID,
Layer0AdditionalMould = this.Layer0AdditionalMould,
Layer1MasteringRing = this.Layer1MasteringRing,
Layer1MasteringSID = this.Layer1MasteringSID,
Layer1ToolstampMasteringCode = this.Layer1ToolstampMasteringCode,
Layer1MouldSID = this.Layer1MouldSID,
Layer1AdditionalMould = this.Layer1AdditionalMould,
Layer2MasteringRing = this.Layer2MasteringRing,
Layer2MasteringSID = this.Layer2MasteringSID,
Layer2ToolstampMasteringCode = this.Layer2ToolstampMasteringCode,
Layer3MasteringRing = this.Layer3MasteringRing,
Layer3MasteringSID = this.Layer3MasteringSID,
Layer3ToolstampMasteringCode = this.Layer3ToolstampMasteringCode,
RingZeroId = this.RingZeroId,
RingZeroDensity = this.RingZeroDensity,
RingWriteOffset = this.RingWriteOffset,
Barcode = this.Barcode,
EXEDateBuildDate = this.EXEDateBuildDate,
ErrorsCount = this.ErrorsCount,
Comments = this.Comments,
CommentsSpecialFields = commentsSpecialFields,
Contents = this.Contents,
ContentsSpecialFields = contentsSpecialFields,
};
}
}
/// <summary>
/// Version and editions section of New Disc form
/// </summary>
public class VersionAndEditionsSection : ICloneable
{
[JsonProperty(PropertyName = "d_version", NullValueHandling = NullValueHandling.Ignore)]
public string? Version { get; set; }
[JsonProperty(PropertyName = "d_version_datfile", NullValueHandling = NullValueHandling.Ignore)]
public string? VersionDatfile { get; set; }
[JsonProperty(PropertyName = "d_editions", NullValueHandling = NullValueHandling.Ignore)]
public string[]? CommonEditions { get; set; }
[JsonProperty(PropertyName = "d_editions_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherEditions { get; set; }
public object Clone()
{
return new VersionAndEditionsSection
{
Version = this.Version,
VersionDatfile = this.VersionDatfile,
CommonEditions = this.CommonEditions,
OtherEditions = this.OtherEditions,
};
}
}
/// <summary>
/// EDC section of New Disc form (PSX only)
/// </summary>
public class EDCSection : ICloneable
{
[JsonProperty(PropertyName = "d_edc", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? EDC { get; set; }
public object Clone()
{
return new EDCSection
{
EDC = this.EDC,
};
}
}
/// <summary>
/// Parent/Clone relationship section of New Disc form
/// </summary>
public class ParentCloneRelationshipSection : ICloneable
{
[JsonProperty(PropertyName = "d_parent_id", NullValueHandling = NullValueHandling.Ignore)]
public string? ParentID { get; set; }
[JsonProperty(PropertyName = "d_is_regional_parent", NullValueHandling = NullValueHandling.Ignore)]
public bool RegionalParent { get; set; }
public object Clone()
{
return new ParentCloneRelationshipSection
{
ParentID = this.ParentID,
RegionalParent = this.RegionalParent,
};
}
}
/// <summary>
/// Extras section of New Disc form
/// </summary>
public class ExtrasSection : ICloneable
{
[JsonProperty(PropertyName = "d_pvd", NullValueHandling = NullValueHandling.Ignore)]
public string? PVD { get; set; }
[JsonProperty(PropertyName = "d_d1_key", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscKey { get; set; }
[JsonProperty(PropertyName = "d_d2_key", NullValueHandling = NullValueHandling.Ignore)]
public string? DiscID { get; set; }
[JsonProperty(PropertyName = "d_pic_data", NullValueHandling = NullValueHandling.Ignore)]
public string? PIC { get; set; }
[JsonProperty(PropertyName = "d_header", NullValueHandling = NullValueHandling.Ignore)]
public string? Header { get; set; }
[JsonProperty(PropertyName = "d_bca", NullValueHandling = NullValueHandling.Ignore)]
public string? BCA { get; set; }
[JsonProperty(PropertyName = "d_ssranges", NullValueHandling = NullValueHandling.Ignore)]
public string? SecuritySectorRanges { get; set; }
public object Clone()
{
return new ExtrasSection
{
PVD = this.PVD,
DiscKey = this.DiscKey,
DiscID = this.DiscID,
PIC = this.PIC,
Header = this.Header,
BCA = this.BCA,
SecuritySectorRanges = this.SecuritySectorRanges,
};
}
}
/// <summary>
/// Copy protection section of New Disc form
/// </summary>
public class CopyProtectionSection : ICloneable
{
[JsonProperty(PropertyName = "d_protection_a", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? AntiModchip { get; set; }
[JsonProperty(PropertyName = "d_protection_1", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(YesNoConverter))]
public YesNo? LibCrypt { get; set; }
[JsonProperty(PropertyName = "d_libcrypt", NullValueHandling = NullValueHandling.Ignore)]
public string? LibCryptData { get; set; }
[JsonProperty(PropertyName = "d_protection", NullValueHandling = NullValueHandling.Ignore)]
public string? Protection { get; set; }
[JsonIgnore]
public Dictionary<string, List<string>?>? FullProtections { get; set; }
[JsonProperty(PropertyName = "d_securom", NullValueHandling = NullValueHandling.Ignore)]
public string? SecuROMData { get; set; }
public object Clone()
{
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;
}
}
return new CopyProtectionSection
{
AntiModchip = this.AntiModchip,
LibCrypt = this.LibCrypt,
LibCryptData = this.LibCryptData,
Protection = this.Protection,
FullProtections = fullProtections,
SecuROMData = this.SecuROMData,
};
}
}
/// <summary>
/// Dumpers and status section of New Disc form (Moderator only)
/// </summary>
public class DumpersAndStatusSection : ICloneable
{
[JsonProperty(PropertyName = "d_status", NullValueHandling = NullValueHandling.Ignore)]
public DumpStatus Status { get; set; }
[JsonProperty(PropertyName = "d_dumpers", NullValueHandling = NullValueHandling.Ignore)]
public string[]? Dumpers { get; set; }
[JsonProperty(PropertyName = "d_dumpers_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherDumpers { get; set; }
public object Clone()
{
return new DumpersAndStatusSection
{
Status = this.Status,
Dumpers = this.Dumpers?.Clone() as string[],
OtherDumpers = this.OtherDumpers,
};
}
}
/// <summary>
/// Tracks and write offsets section of New Disc form (CD/GD-based)
/// </summary>
public class TracksAndWriteOffsetsSection : ICloneable
{
[JsonProperty(PropertyName = "d_tracks", NullValueHandling = NullValueHandling.Ignore)]
public string? ClrMameProData { get; set; }
[JsonProperty(PropertyName = "d_cue", NullValueHandling = NullValueHandling.Ignore)]
public string? Cuesheet { get; set; }
[JsonProperty(PropertyName = "d_offset", NullValueHandling = NullValueHandling.Ignore)]
public int[]? CommonWriteOffsets { get; set; }
[JsonProperty(PropertyName = "d_offset_text", NullValueHandling = NullValueHandling.Ignore)]
public string? OtherWriteOffsets { get; set; }
public object Clone()
{
return new TracksAndWriteOffsetsSection
{
ClrMameProData = this.ClrMameProData,
Cuesheet = this.Cuesheet,
CommonWriteOffsets = this.CommonWriteOffsets?.Clone() as int[],
OtherWriteOffsets = this.OtherWriteOffsets,
};
}
}
/// <summary>
/// Size &amp; checksums section of New Disc form (DVD/BD/UMD-based)
/// </summary>
public class SizeAndChecksumsSection : ICloneable
{
[JsonProperty(PropertyName = "d_layerbreak", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak { get; set; }
[JsonProperty(PropertyName = "d_layerbreak_2", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak2 { get; set; }
[JsonProperty(PropertyName = "d_layerbreak_3", NullValueHandling = NullValueHandling.Ignore)]
public long Layerbreak3 { get; set; }
[JsonProperty(PropertyName = "d_pic_identifier", NullValueHandling = NullValueHandling.Ignore)]
public string? PICIdentifier { get; set; }
[JsonProperty(PropertyName = "d_size", NullValueHandling = NullValueHandling.Ignore)]
public long Size { get; set; }
[JsonProperty(PropertyName = "d_crc32", NullValueHandling = NullValueHandling.Ignore)]
public string? CRC32 { get; set; }
[JsonProperty(PropertyName = "d_md5", NullValueHandling = NullValueHandling.Ignore)]
public string? MD5 { get; set; }
[JsonProperty(PropertyName = "d_sha1", NullValueHandling = NullValueHandling.Ignore)]
public string? SHA1 { get; set; }
public object Clone()
{
return new SizeAndChecksumsSection
{
Layerbreak = this.Layerbreak,
Layerbreak2 = this.Layerbreak2,
Layerbreak3 = this.Layerbreak3,
PICIdentifier = this.PICIdentifier,
Size = this.Size,
CRC32 = this.CRC32,
MD5 = this.MD5,
SHA1 = this.SHA1,
};
}
}
/// <summary>
/// Dumping info section for moderation
/// </summary>
public class DumpingInfoSection : ICloneable
{
// Name not defined by Redump -- Only used with MPF
[JsonProperty(PropertyName = "d_frontend_version", DefaultValueHandling = DefaultValueHandling.Include)]
public string? FrontendVersion { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_program", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingProgram { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_date", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingDate { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_dumping_params", DefaultValueHandling = DefaultValueHandling.Include)]
public string? DumpingParameters { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_manufacturer", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Manufacturer { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_model", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Model { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_drive_firmware", DefaultValueHandling = DefaultValueHandling.Include)]
public string? Firmware { get; set; }
// Name not defined by Redump
[JsonProperty(PropertyName = "d_reported_disc_type", DefaultValueHandling = DefaultValueHandling.Include)]
public string? ReportedDiscType { get; set; }
// Name not defined by Redump -- Only used with Redumper
[JsonProperty(PropertyName = "d_errors_c2", NullValueHandling = NullValueHandling.Ignore)]
public string? C2ErrorsCount { get; set; }
public object Clone()
{
return new DumpingInfoSection
{
FrontendVersion = this.FrontendVersion,
DumpingProgram = this.DumpingProgram,
DumpingDate = this.DumpingDate,
DumpingParameters = this.DumpingParameters,
Manufacturer = this.Manufacturer,
Model = this.Model,
Firmware = this.Firmware,
ReportedDiscType = this.ReportedDiscType,
C2ErrorsCount = this.C2ErrorsCount,
};
}
}
}

View File

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

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using SabreTools.RedumpLib.Data;
using SabreTools.RedumpLib.Data.Sections;
namespace SabreTools.RedumpLib
{
@@ -38,6 +39,7 @@ namespace SabreTools.RedumpLib
SiteCode.SSVersion,
SiteCode.Filename,
SiteCode.TitleID,
SiteCode.Protection,
@@ -56,6 +58,7 @@ namespace SabreTools.RedumpLib
SiteCode.VCD,
// Publisher / Company IDs
SiteCode.TwoKGamesID,
SiteCode.AcclaimID,
SiteCode.ActivisionID,
SiteCode.BandaiID,
@@ -80,6 +83,7 @@ namespace SabreTools.RedumpLib
SiteCode.SegaID,
SiteCode.SelenID,
SiteCode.SierraID,
SiteCode.SteamAppID,
SiteCode.TaitoID,
SiteCode.UbisoftID,
SiteCode.ValveID,
@@ -99,6 +103,8 @@ namespace SabreTools.RedumpLib
// Games
SiteCode.Games,
SiteCode.NetYarozeGames,
SiteCode.SteamSimSidDepotID,
SiteCode.SteamCsmCsdDepotID,
// Demos
SiteCode.PlayableDemos,
@@ -124,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;
@@ -155,7 +161,7 @@ namespace SabreTools.RedumpLib
output.AppendLine();
// EDC section
FormatOutputData(output, info.EDC, info.CommonDiscInfo?.System);
FormatOutputData(output, info.EDC, info.CommonDiscInfo.System);
output.AppendLine();
// Extras section
@@ -163,11 +169,11 @@ namespace SabreTools.RedumpLib
output.AppendLine();
// Copy Protection section
FormatOutputData(output, info.CopyProtection, info.CommonDiscInfo?.System);
FormatOutputData(output, info.CopyProtection, info.CommonDiscInfo.System);
output.AppendLine();
// Tracks and Write Offsets section
if (!string.IsNullOrEmpty(info.TracksAndWriteOffsets?.ClrMameProData))
if (!string.IsNullOrEmpty(info.TracksAndWriteOffsets.ClrMameProData))
{
FormatOutputData(output, info.TracksAndWriteOffsets!);
output.AppendLine();
@@ -177,8 +183,8 @@ namespace SabreTools.RedumpLib
{
FormatOutputData(output,
info.SizeAndChecksums,
info.CommonDiscInfo?.Media.ToMediaType(),
info.CommonDiscInfo?.System,
info.CommonDiscInfo.Media.ToMediaType(),
info.CommonDiscInfo.System,
enableRedumpCompatibility);
output.AppendLine();
}
@@ -205,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;
@@ -225,11 +231,11 @@ namespace SabreTools.RedumpLib
info.CommonDiscInfo.Comments = info.CommonDiscInfo.Comments.Trim();
// Wipe out the special fields dictionary
info.CommonDiscInfo.CommentsSpecialFields = null;
info.CommonDiscInfo.CommentsSpecialFields.Clear();
}
// 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;
@@ -245,7 +251,7 @@ namespace SabreTools.RedumpLib
info.CommonDiscInfo.Contents = info.CommonDiscInfo.Contents.Trim();
// Wipe out the special fields dictionary
info.CommonDiscInfo.ContentsSpecialFields = null;
info.CommonDiscInfo.ContentsSpecialFields.Clear();
}
}
@@ -411,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;
}
@@ -442,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))
{
@@ -477,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");
@@ -497,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);
}
@@ -538,12 +545,14 @@ 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;
for (int i = 0; i < indent; i++)
{
prefix += "\t";
}
// Skip fields that need to keep internal whitespace intact
if (key != "Primary Volume Descriptor (PVD)"
@@ -558,7 +567,7 @@ namespace SabreTools.RedumpLib
value = value.Replace("<TAB>", "\t");
value = value.Replace("<Tab>", "\t");
#endif
value = value.Replace(" ", "\t");
value = value.Replace(" ", "\t");
// Sanitize whitespace around tabs
value = Regex.Replace(value, @"\s*\t\s*", "\t", RegexOptions.Compiled);
@@ -566,12 +575,18 @@ namespace SabreTools.RedumpLib
// If the value contains a newline
value = value.Replace("\r\n", "\n");
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
if (value.Contains('\n'))
#else
if (value.Contains("\n"))
#endif
{
output.AppendLine(prefix + key + ":"); output.AppendLine();
string[] values = value.Split('\n');
foreach (string val in values)
{
output.AppendLine(val);
}
output.AppendLine();
}
@@ -593,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);
@@ -609,12 +624,14 @@ 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;
for (int i = 0; i < indent; i++)
{
prefix += "\t";
}
output.AppendLine(prefix + key + ": " + value);
}
@@ -629,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);
@@ -674,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:
@@ -687,13 +705,13 @@ namespace SabreTools.RedumpLib
return $"{mediaType.LongName()}-128";
else if (layerbreak2 != default && layerbreak2 != default(long))
return $"{mediaType.LongName()}-100";
else if (layerbreak != default && layerbreak != default(long) && picIdentifier == Models.PIC.Constants.DiscTypeIdentifierROMUltra)
else if (layerbreak != default && layerbreak != default(long) && picIdentifier == "BDU")
return $"{mediaType.LongName()}-66";
else if (layerbreak != default && layerbreak != default(long) && size > 53_687_063_712)
return $"{mediaType.LongName()}-66";
else if (layerbreak != default && layerbreak != default(long))
return $"{mediaType.LongName()}-50";
else if (picIdentifier == Models.PIC.Constants.DiscTypeIdentifierROMUltra)
else if (picIdentifier == "BDU")
return $"{mediaType.LongName()}-33";
else if (size > 26_843_531_856)
return $"{mediaType.LongName()}-33";
@@ -715,6 +733,7 @@ namespace SabreTools.RedumpLib
default:
return mediaType.LongName();
}
#pragma warning restore IDE0010
}
/// <summary>
@@ -724,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
@@ -754,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

@@ -2,13 +2,13 @@
<PropertyGroup>
<!-- Assembly Properties -->
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
<IncludeSymbols>true</IncludeSymbols>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.7.1</Version>
<Version>1.9.1</Version>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
@@ -33,8 +33,7 @@
<ItemGroup>
<PackageReference Include="MinAsyncBridge" Version="0.12.4" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))" />
<PackageReference Include="Net35.Actions" Version="1.4.0" Condition="$(TargetFramework.StartsWith(`net2`))" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="SabreTools.Models" Version="1.6.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>
</Project>
</Project>

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 == null)
if (info.CommonDiscInfo.Media is null || info.SizeAndChecksums == default)
return;
#pragma warning disable IDE0010
switch (info.CommonDiscInfo.Media)
{
case DiscType.DVD5:
@@ -39,13 +40,13 @@ namespace SabreTools.RedumpLib
info.CommonDiscInfo.Media = DiscType.BD128;
else if (info.SizeAndChecksums.Layerbreak2 != default)
info.CommonDiscInfo.Media = DiscType.BD100;
else if (info.SizeAndChecksums.Layerbreak != default && info.SizeAndChecksums.PICIdentifier == Models.PIC.Constants.DiscTypeIdentifierROMUltra)
else if (info.SizeAndChecksums.Layerbreak != default && info.SizeAndChecksums.PICIdentifier == "BDU")
info.CommonDiscInfo.Media = DiscType.BD66;
else if (info.SizeAndChecksums.Layerbreak != default && info.SizeAndChecksums.Size > 50_050_629_632)
info.CommonDiscInfo.Media = DiscType.BD66;
else if (info.SizeAndChecksums.Layerbreak != default)
info.CommonDiscInfo.Media = DiscType.BD50;
else if (info.SizeAndChecksums.PICIdentifier == Models.PIC.Constants.DiscTypeIdentifierROMUltra)
else if (info.SizeAndChecksums.PICIdentifier == "BDU")
info.CommonDiscInfo.Media = DiscType.BD33;
else if (info.SizeAndChecksums.Size > 25_025_314_816)
info.CommonDiscInfo.Media = DiscType.BD33;
@@ -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;
@@ -157,12 +162,11 @@ namespace SabreTools.RedumpLib
/// </summary>
/// <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>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
@@ -171,21 +175,25 @@ namespace SabreTools.RedumpLib
return null;
// Format the universal hash for finding within the comments
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
string universalHashQuery = $"{universalHash[..^1]}/comments/only";
#else
string universalHashQuery = $"{universalHash.Substring(0, universalHash.Length - 1)}/comments/only";
#endif
// Get all matching IDs for the hash
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;
@@ -200,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,11 +1,18 @@
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>
/// The timespan to wait before the request times out.
/// </summary>
public TimeSpan Timeout { get; set; }
// https://stackoverflow.com/questions/1777221/using-cookiecontainer-with-webclient-class
private readonly CookieContainer _container = new();
@@ -15,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
@@ -24,7 +31,11 @@ namespace SabreTools.RedumpLib.Web
return null;
// Extract the filename from the value
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
return headerValue[(headerValue.IndexOf("filename=") + 9)..].Replace("\"", "");
#else
return headerValue.Substring(headerValue.IndexOf("filename=") + 9).Replace("\"", "");
#endif
}
/// <inheritdoc/>
@@ -33,11 +44,14 @@ namespace SabreTools.RedumpLib.Web
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest webRequest)
{
webRequest.Timeout = 30 * 1000; // 30 seconds
webRequest.Timeout = (int)Timeout.TotalMilliseconds;
webRequest.CookieContainer = _container;
}
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

@@ -31,15 +31,20 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Maximum retry count for any operation
/// </summary>
public int RetryCount { get; private set; } = 3;
public int RetryCount { get; }
/// <summary>
/// Maximum number of seconds for a retry
/// </summary>
public int TimeoutSeconds { get; }
/// <summary>
/// Internal client for interaction
/// </summary>
#if NETFRAMEWORK || NETSTANDARD2_0_OR_GREATER
private CookieWebClient _internalClient;
private readonly CookieWebClient _internalClient;
#else
private HttpClient _internalClient;
private readonly HttpClient _internalClient;
#endif
#endregion
@@ -47,25 +52,24 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Constructor
/// </summary>
public RedumpClient()
{
#if NETFRAMEWORK || NETSTANDARD2_0_OR_GREATER
_internalClient = new CookieWebClient();
#else
_internalClient = new HttpClient(new HttpClientHandler { UseCookies = true }) { Timeout = TimeSpan.FromSeconds(30) };
#endif
}
/// <summary>
/// Constructor
/// </summary>
public RedumpClient(int retryCount) : this()
public RedumpClient(int retryCount = 3, int timeoutSeconds = 30)
{
// Ensure there are a positive number of retries
if (retryCount <= 0)
retryCount = 3;
// Ensure a positive timespan
if (timeoutSeconds <= 0)
timeoutSeconds = 30;
RetryCount = retryCount;
TimeoutSeconds = timeoutSeconds;
#if NETFRAMEWORK || NETSTANDARD2_0_OR_GREATER
_internalClient = new CookieWebClient() { Timeout = TimeSpan.FromSeconds(TimeoutSeconds) };
#else
_internalClient = new HttpClient(new HttpClientHandler { UseCookies = true }) { Timeout = TimeSpan.FromSeconds(TimeoutSeconds) };
#endif
}
#region Credentials
@@ -73,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))
@@ -146,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
@@ -237,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;
@@ -295,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
@@ -320,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
@@ -353,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
@@ -362,10 +370,11 @@ namespace SabreTools.RedumpLib.Web
var value = Regex.Match(dumpsPage, @"/disc/(\d+)/sfv/").Groups[1].Value;
if (int.TryParse(value, out int id))
{
ids.Add(id);
bool downloaded = await DownloadSingleSiteID(id, outDir, false);
if (!downloaded && failOnSingle)
return ids;
ids.Add(id);
}
return ids;
@@ -375,17 +384,18 @@ namespace SabreTools.RedumpLib.Web
var matches = Constants.DiscRegex.Matches(dumpsPage);
foreach (Match? match in matches)
{
if (match == null)
if (match is null)
continue;
try
{
if (int.TryParse(match.Groups[1].Value, out int value))
{
ids.Add(value);
bool downloaded = await DownloadSingleSiteID(value, outDir, false);
if (!downloaded && failOnSingle)
return ids;
ids.Add(value);
}
}
catch (Exception ex)
@@ -411,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
@@ -451,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
@@ -555,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;
@@ -593,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
{
@@ -717,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;
@@ -755,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
{
@@ -849,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);
}
@@ -861,7 +871,7 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Download a set of packs
/// </summary>
/// </summary>
/// <param name="url">Base URL to download using</param>
/// <param name="systems">Systems to download packs for</param>
/// <param name="title">Name of the pack that is downloading</param>

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;

View File

@@ -1,7 +1,7 @@
#! /bin/bash
# This batch file assumes the following:
# - .NET 9.0 (or newer) SDK is installed and in PATH
# - .NET 10.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.
@@ -47,19 +47,19 @@ echo " No archive (-a) $NO_ARCHIVE"
echo " "
# Create the build matrix arrays
FRAMEWORKS=("net9.0")
FRAMEWORKS=("net10.0")
RUNTIMES=("win-x86" "win-x64" "win-arm64" "linux-x64" "linux-arm64" "osx-x64" "osx-arm64")
# Use expanded lists, if requested
if [ $USE_ALL = true ]
then
FRAMEWORKS=("net20" "net35" "net40" "net452" "net462" "net472" "net48" "netcoreapp3.1" "net5.0" "net6.0" "net7.0" "net8.0" "net9.0")
FRAMEWORKS=("net20" "net35" "net40" "net452" "net462" "net472" "net48" "netcoreapp3.1" "net5.0" "net6.0" "net7.0" "net8.0" "net9.0" "net10.0")
fi
# Create the filter arrays
SINGLE_FILE_CAPABLE=("net5.0" "net6.0" "net7.0" "net8.0" "net9.0")
VALID_APPLE_FRAMEWORKS=("net6.0" "net7.0" "net8.0" "net9.0")
VALID_CROSS_PLATFORM_FRAMEWORKS=("netcoreapp3.1" "net5.0" "net6.0" "net7.0" "net8.0" "net9.0")
SINGLE_FILE_CAPABLE=("net5.0" "net6.0" "net7.0" "net8.0" "net9.0" "net10.0")
VALID_APPLE_FRAMEWORKS=("net6.0" "net7.0" "net8.0" "net9.0" "net10.0")
VALID_CROSS_PLATFORM_FRAMEWORKS=("netcoreapp3.1" "net5.0" "net6.0" "net7.0" "net8.0" "net9.0" "net10.0")
VALID_CROSS_PLATFORM_RUNTIMES=("win-arm64" "linux-x64" "linux-arm64" "osx-x64" "osx-arm64")
# Only build if requested

View File

@@ -1,5 +1,5 @@
# This batch file assumes the following:
# - .NET 9.0 (or newer) SDK is installed and in PATH
# - .NET 10.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.
@@ -38,19 +38,19 @@ Write-Host " No archive (-NoArchive) $NO_ARCHIVE"
Write-Host " "
# Create the build matrix arrays
$FRAMEWORKS = @('net9.0')
$FRAMEWORKS = @('net10.0')
$RUNTIMES = @('win-x86', 'win-x64', 'win-arm64', 'linux-x64', 'linux-arm64', 'osx-x64', 'osx-arm64')
# Use expanded lists, if requested
if ($USE_ALL.IsPresent)
{
$FRAMEWORKS = @('net20', 'net35', 'net40', 'net452', 'net462', 'net472', 'net48', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0')
$FRAMEWORKS = @('net20', 'net35', 'net40', 'net452', 'net462', 'net472', 'net48', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')
}
# Create the filter arrays
$SINGLE_FILE_CAPABLE = @('net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0')
$VALID_APPLE_FRAMEWORKS = @('net6.0', 'net7.0', 'net8.0', 'net9.0')
$VALID_CROSS_PLATFORM_FRAMEWORKS = @('netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0')
$SINGLE_FILE_CAPABLE = @('net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')
$VALID_APPLE_FRAMEWORKS = @('net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')
$VALID_CROSS_PLATFORM_FRAMEWORKS = @('netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')
$VALID_CROSS_PLATFORM_RUNTIMES = @('win-arm64', 'linux-x64', 'linux-arm64', 'osx-x64', 'osx-arm64')
# Only build if requested