mirror of
https://github.com/SabreTools/MPF.git
synced 2026-02-04 05:35:52 +00:00
Compare commits
246 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
299fafe1f8 | ||
|
|
8f6305a7c4 | ||
|
|
3f61957715 | ||
|
|
57750295fb | ||
|
|
286ec864ab | ||
|
|
e4fd644c61 | ||
|
|
7502d7e8df | ||
|
|
439fb2717c | ||
|
|
089ab1c4a2 | ||
|
|
89a50ea424 | ||
|
|
740d867d7b | ||
|
|
83fa4852c9 | ||
|
|
ecc00a28c2 | ||
|
|
2d90c849e1 | ||
|
|
1d065ffd48 | ||
|
|
ca885c3b89 | ||
|
|
94fd614673 | ||
|
|
9fc5799999 | ||
|
|
61f90a635f | ||
|
|
8cc0ff3829 | ||
|
|
cac6bcc4de | ||
|
|
7ac0089e81 | ||
|
|
48576b38be | ||
|
|
82dedf1ceb | ||
|
|
395cded5ef | ||
|
|
a48f9d1c83 | ||
|
|
3975003686 | ||
|
|
4beae71511 | ||
|
|
f0f41c86c5 | ||
|
|
b1b6eb2c9d | ||
|
|
29754b4c0e | ||
|
|
35cda84308 | ||
|
|
a877397fe6 | ||
|
|
2f0471d596 | ||
|
|
2037ded792 | ||
|
|
5f1a68a5f5 | ||
|
|
87746c8677 | ||
|
|
2665c29918 | ||
|
|
5637cf5201 | ||
|
|
eb1d000e4f | ||
|
|
8db467128d | ||
|
|
dc90e2609d | ||
|
|
e96bd21f1d | ||
|
|
693599b986 | ||
|
|
d482fe926c | ||
|
|
17b5432352 | ||
|
|
ca480f27ed | ||
|
|
4bad66e706 | ||
|
|
abe00fe132 | ||
|
|
ba73479837 | ||
|
|
f2a28dd36b | ||
|
|
928e30a5de | ||
|
|
007fc2f9b9 | ||
|
|
d2d23ebbdf | ||
|
|
e02ab769ec | ||
|
|
3df78def00 | ||
|
|
7eddfc5fed | ||
|
|
f6f154b6db | ||
|
|
47cd133437 | ||
|
|
74c9641a54 | ||
|
|
fc5929db2a | ||
|
|
f53b428075 | ||
|
|
46dc931b3f | ||
|
|
9608cfb700 | ||
|
|
3493238849 | ||
|
|
4c364f519e | ||
|
|
337a7a181c | ||
|
|
071e3a0024 | ||
|
|
ff0c742dee | ||
|
|
7aba0d1c9c | ||
|
|
ac6a77d9da | ||
|
|
6eb976c842 | ||
|
|
ba39a8b22f | ||
|
|
88a6fa71a9 | ||
|
|
584b8c0109 | ||
|
|
c6258b5520 | ||
|
|
d6dbbbe928 | ||
|
|
f22b3c4ac0 | ||
|
|
fae399f8bc | ||
|
|
d2ed2f81ae | ||
|
|
7dbcfce46c | ||
|
|
ebd0552a2a | ||
|
|
343973263c | ||
|
|
e5220a8224 | ||
|
|
146120c210 | ||
|
|
807e4655a6 | ||
|
|
e32ebec197 | ||
|
|
8d8886390d | ||
|
|
5a2aa9d325 | ||
|
|
37aa1645dd | ||
|
|
052d074e92 | ||
|
|
8c551dc990 | ||
|
|
b2fcc190fd | ||
|
|
2325844bd4 | ||
|
|
f63517bb52 | ||
|
|
99d26f177b | ||
|
|
d6b28de586 | ||
|
|
e8d1567d07 | ||
|
|
cd8b484ae3 | ||
|
|
65b9735941 | ||
|
|
22f7e2a0ed | ||
|
|
2c5dc7390a | ||
|
|
c5e01b9578 | ||
|
|
882243316c | ||
|
|
1b62ed0c03 | ||
|
|
edb8c08a39 | ||
|
|
ad93387aea | ||
|
|
9012ff85a9 | ||
|
|
ccc33bebbd | ||
|
|
57b07aee02 | ||
|
|
069d676492 | ||
|
|
a26dfb7e7a | ||
|
|
a9ea457808 | ||
|
|
41bc410452 | ||
|
|
bbfdf462d0 | ||
|
|
5a1d51c05f | ||
|
|
16e80f75cf | ||
|
|
2a6e066707 | ||
|
|
d6102107fb | ||
|
|
79163dcb35 | ||
|
|
c1aa863c91 | ||
|
|
dbd4b55dda | ||
|
|
1f58521f51 | ||
|
|
4da1ab9c29 | ||
|
|
5771add8c0 | ||
|
|
977a71d9cf | ||
|
|
b2d09d04ea | ||
|
|
78df92e5d3 | ||
|
|
9770b7c917 | ||
|
|
1ddb287977 | ||
|
|
b9e4bbf744 | ||
|
|
08829ed811 | ||
|
|
bf181e2294 | ||
|
|
49571c6bfc | ||
|
|
9a0bc868f8 | ||
|
|
bc2c08690d | ||
|
|
493cb80624 | ||
|
|
49b8ecf6c3 | ||
|
|
c9b7ad7819 | ||
|
|
fe76387f6a | ||
|
|
0a60fe5a37 | ||
|
|
baffdb8b29 | ||
|
|
4a3c585a8d | ||
|
|
1ee7ea1948 | ||
|
|
ee08bfe0fc | ||
|
|
896caec9cd | ||
|
|
68932ab473 | ||
|
|
d105d04146 | ||
|
|
7023c78d40 | ||
|
|
81156a3c63 | ||
|
|
7b2b06a36f | ||
|
|
3f974ab336 | ||
|
|
b238616685 | ||
|
|
2984459823 | ||
|
|
ce979b3c3f | ||
|
|
cb8e1fd34b | ||
|
|
cc148735f8 | ||
|
|
8238d14f7b | ||
|
|
a56676501e | ||
|
|
79716ea0b5 | ||
|
|
43477a133f | ||
|
|
8889beef1d | ||
|
|
ac4be751b3 | ||
|
|
69f855fc93 | ||
|
|
cf01095623 | ||
|
|
3236223e3f | ||
|
|
36450cd22b | ||
|
|
6a9b6748d2 | ||
|
|
3bf83378a2 | ||
|
|
bc938fd58c | ||
|
|
f50a110acd | ||
|
|
fcda2a6e3b | ||
|
|
d33526b27e | ||
|
|
0b0427e9c1 | ||
|
|
c34b92bad8 | ||
|
|
89145df0fa | ||
|
|
ee7cde6360 | ||
|
|
8e9edf43ac | ||
|
|
51115430cb | ||
|
|
7cf108828e | ||
|
|
020390af65 | ||
|
|
e04ceb953c | ||
|
|
363b018cb7 | ||
|
|
cf025522ef | ||
|
|
0fb8bf5c29 | ||
|
|
e280745eee | ||
|
|
fb306750e6 | ||
|
|
da5a514482 | ||
|
|
fc288e1c46 | ||
|
|
102acb9ebf | ||
|
|
b76b2a69f5 | ||
|
|
254ad6cfd0 | ||
|
|
f432f438ab | ||
|
|
e890243830 | ||
|
|
6493b462f1 | ||
|
|
54c0716ea9 | ||
|
|
7fbb5133d7 | ||
|
|
993a0fd7d3 | ||
|
|
47878fee1f | ||
|
|
4cb8a31505 | ||
|
|
0685972842 | ||
|
|
5b1cc3c715 | ||
|
|
572f0d5095 | ||
|
|
23bafad3db | ||
|
|
c7b77e4bd7 | ||
|
|
755eee4441 | ||
|
|
fca2c53d6c | ||
|
|
8f6f5f6ef0 | ||
|
|
2e9970ee6a | ||
|
|
4fa1273111 | ||
|
|
d3993a48e4 | ||
|
|
d522bb6c76 | ||
|
|
816672a817 | ||
|
|
f8171da306 | ||
|
|
ce073e5fbf | ||
|
|
28205e42f0 | ||
|
|
0160366530 | ||
|
|
663477d408 | ||
|
|
bd2e012eef | ||
|
|
a514374169 | ||
|
|
f73c0730e2 | ||
|
|
a658c80de7 | ||
|
|
b806bc6cd1 | ||
|
|
cf9675f620 | ||
|
|
ea18051709 | ||
|
|
4fdf8e5dde | ||
|
|
a4616d139d | ||
|
|
0f09a9c913 | ||
|
|
48ffd6f40c | ||
|
|
6612c8ea4d | ||
|
|
68d1a0664a | ||
|
|
86d8590789 | ||
|
|
e23427d7c9 | ||
|
|
cd19a2e4a0 | ||
|
|
000e7d88a8 | ||
|
|
e3beb1ef77 | ||
|
|
a3a75b1c2d | ||
|
|
11850a8d6b | ||
|
|
bf6b58d64b | ||
|
|
1789334625 | ||
|
|
9520f58240 | ||
|
|
48e5e01729 | ||
|
|
8c7959fb08 | ||
|
|
8ef7543cf1 | ||
|
|
f9e39ee4be | ||
|
|
0a4621c963 |
169
.editorconfig
169
.editorconfig
@@ -1,4 +1,167 @@
|
||||
[*.cs]
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# SYSLIB1045: Convert to 'GeneratedRegexAttribute'.
|
||||
dotnet_diagnostic.SYSLIB1045.severity = silent
|
||||
# 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
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/issue-report.md
vendored
2
.github/ISSUE_TEMPLATE/issue-report.md
vendored
@@ -25,7 +25,7 @@ What version are you using?
|
||||
**Build**
|
||||
What runtime version are you using?
|
||||
|
||||
- [ ] .NET 9.0 running on (Operating System)
|
||||
- [ ] .NET 10 running on (Operating System)
|
||||
|
||||
**Describe the issue**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
85
.github/workflows/build_and_test.yml
vendored
85
.github/workflows/build_and_test.yml
vendored
@@ -1,40 +1,59 @@
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
push:
|
||||
branches: ["master"]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
- name: Run publish script
|
||||
run: ./publish-nix.sh -dp
|
||||
steps:
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@v1.3.1
|
||||
with:
|
||||
dotnet: false
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: "*.nupkg,*.snupkg,*.zip"
|
||||
body: 'Last built commit: ${{ github.sha }}'
|
||||
name: 'Rolling Release'
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
9.0.x
|
||||
10.0.x
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
- name: Run publish script
|
||||
run: ./publish-nix.sh -dp
|
||||
|
||||
- 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,*.zip"
|
||||
body: "Last built commit: ${{ github.sha }}
|
||||
|
||||
## UI Builds
|
||||
|
||||
[Windows x64 UI Release](https://github.com/SabreTools/MPF/releases/download/rolling/MPF.UI_net10.0-windows_win-x64_release.zip)
|
||||
|
||||
[Windows x64 UI Debug](https://github.com/SabreTools/MPF/releases/download/rolling/MPF.UI_net10.0-windows_win-x64_debug.zip)"
|
||||
name: "Rolling Release"
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
|
||||
39
.github/workflows/check_pr.yml
vendored
39
.github/workflows/check_pr.yml
vendored
@@ -3,24 +3,29 @@ name: Build PR
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@v1.3.1
|
||||
with:
|
||||
dotnet: false
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- 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: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Test
|
||||
run: dotnet test
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
|
||||
- name: Test
|
||||
run: dotnet test
|
||||
|
||||
18
.vscode/launch.json
vendored
18
.vscode/launch.json
vendored
@@ -10,7 +10,7 @@
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/MPF.Check/bin/Debug/net9.0/MPF.Check.dll",
|
||||
"program": "${workspaceFolder}/MPF.Check/bin/Debug/net10.0/MPF.Check.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/MPF.Check",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
@@ -24,7 +24,7 @@
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/MPF.CLI/bin/Debug/net9.0/MPF.CLI.dll",
|
||||
"program": "${workspaceFolder}/MPF.CLI/bin/Debug/net10.0/MPF.CLI.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/MPF.CLI",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
@@ -32,6 +32,20 @@
|
||||
"stopAtEntry": false,
|
||||
"justMyCode": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Launch (UI)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/MPF.UI/bin/Debug/net10.0-windows/MPF.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/MPF.UI",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false,
|
||||
"justMyCode": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
|
||||
248
CHANGELIST.md
248
CHANGELIST.md
@@ -1,3 +1,251 @@
|
||||
### WIP (xxxx-xx-xx)
|
||||
|
||||
- Check for null or empty layerbreak arrays
|
||||
- Check range-specific values in layerbreak
|
||||
- Update Redumper to build 671
|
||||
- Update Redumper to build 676 (rename asus flags to mediatek)
|
||||
- Use default media type if not provided
|
||||
- Update Redumper to build 682 (Dreamcast support)
|
||||
- Add default subfolder to CLI outputs
|
||||
- Update DIC to 20260101
|
||||
- Update Redumper to build 683
|
||||
- Add editorconfig, fix issues
|
||||
- Add MPRESS to packer filters
|
||||
- Update RedumpLib to 1.9.1
|
||||
- Split path creation in OptionsLoader
|
||||
- Add unused Dreamdump execution context
|
||||
- Validate a system is provided for CLI applications
|
||||
- Log the system being used, in case it came from config
|
||||
- Extend logging with a new state
|
||||
|
||||
### 3.6.0 (2025-11-28)
|
||||
|
||||
- Add BCA to list of files to select in Check UI
|
||||
- Move Zstd compression helper to base processor
|
||||
- Add file merge method in CleanRip
|
||||
- Implement file merging in CleanRip
|
||||
- Support reparsing of MPF-processed outputs
|
||||
- Use WriteToFile extension for zip entries
|
||||
- Move output file implementations to separate namespace
|
||||
- Conditionally require state
|
||||
- Replace "We" comments
|
||||
- Parse XboxOne/SX Title IDs
|
||||
- Reduce chance of empty strings
|
||||
- Initial UI lang code
|
||||
- Move to enum-based model for UI language options
|
||||
- Slight cleanup to main window language handling
|
||||
- Clean up nullability
|
||||
- Clean up a bit of element work
|
||||
- Fill in some gaps
|
||||
- Add UI by default to launch
|
||||
- Continue UI translation work
|
||||
- Minor formatting cleanup
|
||||
- Ensure readers and writers dispose
|
||||
- Complete translation support
|
||||
- Add skeleton for 8 more languages
|
||||
- Add 8 more language menu items
|
||||
- Add basic translation for 8 more languages
|
||||
- Make Check flags toggle if config used
|
||||
- Add console print when Check loads from config
|
||||
- Add Ukrainian translation (superg)
|
||||
- Add list configuration commandline feature
|
||||
- Handle a provided log zip in Check operation
|
||||
- Allow files to be zipped but not deleted
|
||||
- Fix long translated strings
|
||||
- Allow placeholder files to be used in Check
|
||||
- Make .img not required for DIC outputs
|
||||
- Handle log zip path in information extraction
|
||||
- Redumper state file is not accessed
|
||||
- Fix tests broken by last commit
|
||||
- Regex outputs should not name based on pattern
|
||||
- Make log archive handling more user-apparent
|
||||
- Be selective on which systems to enable skeleton
|
||||
- Readme updates for accuracy
|
||||
- Separate out default program paths
|
||||
- Add per-OS executable names
|
||||
- Simplify first-run CLI experience
|
||||
- Change CLI first-run wording
|
||||
- Free disk space for runners
|
||||
- Possibly fix missing options string
|
||||
- Minor Spanish cleanup
|
||||
- Update RedumpLib to 1.8.0
|
||||
- Limit visibility of Compatible OS text box
|
||||
- Stop using long name for default system setting
|
||||
- Updated Polish translation
|
||||
- Fix rolling tag
|
||||
- Try to add UI links to rolling release
|
||||
- Slight tweak to automatic UI links
|
||||
- Add hidden language (NovaAurora)
|
||||
- Fix langs
|
||||
- Fix issues with path assembly
|
||||
- Clean up submission info use and log link text
|
||||
- Update Redumper to build 658
|
||||
- Pre-compress all skeletons for multi-track CDs
|
||||
- Add DVD-Video to list of copy protection scanning systems
|
||||
- Update Redumper to build 660
|
||||
- Use dated default output filenames
|
||||
- Update packages
|
||||
- Scan disc image if not multi-track
|
||||
- Scan multi-track images for protection
|
||||
- Move and rename new protection scan method
|
||||
- Path scan after image scan
|
||||
- Update Redumper to build 663
|
||||
- Name some type parameters
|
||||
- Ensure volume label is trimmed if used in filenames
|
||||
- Remove DPM identifier for StarForce Keyless
|
||||
- New Redumper Drive Pregap Start option
|
||||
- Clarify the unmounted device case
|
||||
- Add support for .NET 10
|
||||
- Update Redumper to build 665
|
||||
- Disable Zstd PKZIP outputs
|
||||
- Add commented fix for Zstd PKZIP
|
||||
- Reenable Zstd PKZIP outputs
|
||||
|
||||
### 3.5.0 (2025-10-10)
|
||||
|
||||
- Add failure if media type could not be determined
|
||||
- Tweaks to how failure cases are reported
|
||||
- Rename log zip on collision
|
||||
- Update packages
|
||||
- Use CommandLine library for CLI executables
|
||||
- Create interactive mode features
|
||||
- Minor cleanup around last added
|
||||
- Add placeholder command set creation
|
||||
- Reduce unnecessary shared code
|
||||
- Create and use main features for CLI and Check
|
||||
- Create and use base feature in Check
|
||||
- Create and use base feature in CLI
|
||||
- Assign inputs for interactive modes
|
||||
- Remove duplicate input declarations
|
||||
- Fix strange invocations of extension methods
|
||||
- Remove CommandOptions implementations
|
||||
- Exit early on parsing failures
|
||||
- Fix minor typo in verify inputs check
|
||||
- Allow but do not require config for Check
|
||||
- Update packages
|
||||
- More consistency in commandline programs
|
||||
- Use GC.SharpCompress as archive handling library
|
||||
- Start wiring through log compression changes
|
||||
- Fix minor issues with options loading
|
||||
- Finalize wire-through and clean up
|
||||
- Minor cleanup on interactive modes
|
||||
- Add more useful credentials inputs for Check
|
||||
- More gracefully handle "missing" media types
|
||||
- Use null or empty instead of just null
|
||||
- Guard against unzippable files
|
||||
- Fix incorrect flagging of a failed check
|
||||
- Use ZipWriterOptions instead of generic
|
||||
- Allow skeleton creation for all media types
|
||||
- Fix default value tests
|
||||
- Only allow skeleton creation for CD and DVD
|
||||
- Add preemptive new file support
|
||||
- Add preemptive helper for Zstd handling
|
||||
- Pre-compress skeleton files with Zstd
|
||||
- Fix broken file count tests
|
||||
- Pre-compress state files with Zstd
|
||||
- Use block-based reading instead of CopyTo
|
||||
- Enable skeleton output for all CLI runs
|
||||
- Fix test broken by last commit
|
||||
- Support detecting split Wii for CleanRip
|
||||
- Try to handle Windows-specific compression issue
|
||||
|
||||
### 3.4.2 (2025-09-30)
|
||||
|
||||
- Fix starting index for CLI
|
||||
- Fix missed package update
|
||||
- Require exact versions for build
|
||||
|
||||
### 3.4.1 (2025-09-29)
|
||||
|
||||
- Experiment with only showing media type box for DIC
|
||||
- Default media type box to hidden to avoid visual issues
|
||||
- Limit media type visibility further
|
||||
- Set media type visibility when options changed
|
||||
- Change label with media type visibility
|
||||
- Update media type visibility on system change
|
||||
- Return full result from dump checks
|
||||
- Fix logic from around Macrovision security driver filtering
|
||||
- Remove SkipMediaTypeDetection option, cleanup options window
|
||||
- Minor tweaks to frontend code
|
||||
- Default to CD speed range
|
||||
- Skip trying to set speeds if no drives
|
||||
- Fix tests
|
||||
- Make media type a named parameter for CLI
|
||||
- Reduction in media type use for dumping
|
||||
- Update BinaryObjectScanner to 3.4.3
|
||||
|
||||
### 3.4.0 (2025-09-25)
|
||||
|
||||
- Remove media type from Check Dump UI
|
||||
- Always trust the output files for processing
|
||||
- UI consistency when parameters are editable
|
||||
- Let the processor always deal with unsupported
|
||||
- Put a try/catch around GenerateArtifacts
|
||||
- Reduce preprocessing in DumpEnvironment
|
||||
- Update RedumpLib to 1.6.9
|
||||
- Treat all UMD as DL visually
|
||||
- Add CopyUpdateUrlToClipboard option
|
||||
- Fix inconsistency with newlines
|
||||
- Update Aaru to build 5.4.1
|
||||
- Fix for C2 error doubling issue (fuzz6001)
|
||||
- Update RedumpLib and LibIRD
|
||||
- Update LibIRD
|
||||
- Update redumper to build 653
|
||||
- Minor cleanup
|
||||
- Update test Nuget packages
|
||||
- Update RedumpLib to 1.7.1
|
||||
- Support multisession cache files
|
||||
- Update DIC to 20250901 (Windows/Linux only)
|
||||
- Fix UIC processing logic
|
||||
- Update RedumpLib, detect Playmaji Polymega system
|
||||
- Update redumper to b655
|
||||
- Support new versioning format in redumper (fuzz6001)
|
||||
- Add RedumperRefineSectorMode setting
|
||||
- Update BinaryObjectScanner to 3.4.0
|
||||
- Add context-sensitive protections helper method
|
||||
- Further flesh out framework
|
||||
- Add filters to handle Release Control output (Bestest)
|
||||
- Cleanup last commits, add tests
|
||||
- Update BinaryObjectScanner to 3.4.2
|
||||
- Update RedumpLib to 1.7.4
|
||||
|
||||
### 3.3.3 (2025-07-18)
|
||||
|
||||
- Handle layers for PS3CFW
|
||||
- Further clarify configuration requirements for CLI
|
||||
- Ignore volume labels with path separators
|
||||
- Reduce media-specific checks where unnecessary
|
||||
- Add DetermineMediaType scaffolding and tests
|
||||
- Fill out DetermineMediaType for Redumper
|
||||
- Fill out DetermineMediaType for Aaru
|
||||
- Fill out DetermineMediaType for DiscImageCreator
|
||||
- Enable Check to determine media type automatically
|
||||
- Fix missed test updates
|
||||
- Rename disc info to media info
|
||||
- Fix start index in Check
|
||||
- Use the correct base path for Check
|
||||
- Update redumper to build 611
|
||||
- IsAudio cleanup
|
||||
- IsAudio cleanup cleanup
|
||||
- Remove dead code in DIC processor
|
||||
- Set some default values for CLI
|
||||
- Address nullable default value
|
||||
- Better handling of Xbox/360, redumper build 613
|
||||
- Use reasonable default names for PlayStation systems
|
||||
- Swap PS1/2 back to original name handling
|
||||
- Only use serial for PS3/4/5 if no custom volume label
|
||||
- Fix unnecessary null assignment
|
||||
- Empty should be null (fuzz6001)
|
||||
- Remove legacy codes from info window
|
||||
- Net Yaroze only for PS1
|
||||
- Update RedumpLib to 1.6.8
|
||||
- Add new help and version flags for CLI and Check
|
||||
- Strip errant whitespace during path normalization
|
||||
- Simplify code from previous commit
|
||||
- Better handle mixed-separator paths
|
||||
- Slightly better IRD organization
|
||||
- Update redumper to build 631
|
||||
|
||||
### 3.3.2 (2025-06-12)
|
||||
|
||||
- Include Aaru in automatic builds
|
||||
|
||||
315
MPF.CLI/Features/BaseFeature.cs
Normal file
315
MPF.CLI/Features/BaseFeature.cs
Normal file
@@ -0,0 +1,315 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
#if NET40
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Web;
|
||||
using LogCompression = MPF.Processors.LogCompression;
|
||||
|
||||
namespace MPF.CLI.Features
|
||||
{
|
||||
internal abstract class BaseFeature : SabreTools.CommandLine.Feature
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// User-defined options
|
||||
/// </summary>
|
||||
public Options Options { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Currently-selected system
|
||||
/// </summary>
|
||||
public RedumpSystem? System { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Media type to dump
|
||||
/// </summary>
|
||||
/// <remarks>Required for DIC and if custom parameters not set</remarks>
|
||||
public MediaType? MediaType { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to the device to dump
|
||||
/// </summary>
|
||||
/// <remarks>Required if custom parameters are not set</remarks>
|
||||
public string? DevicePath { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to the mounted filesystem to check
|
||||
/// </summary>
|
||||
/// <remarks>Should only be used when the device path is not readable</remarks>
|
||||
public string? MountedPath { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to the output file
|
||||
/// </summary>
|
||||
/// <remarks>Required if custom parameters are not set</remarks>
|
||||
public string? FilePath { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Override drive speed
|
||||
/// </summary>
|
||||
public int? DriveSpeed { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Custom parameters for dumping
|
||||
/// </summary>
|
||||
public string? CustomParams { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
protected BaseFeature(string name, string[] flags, string description, string? detailed = null)
|
||||
: base(name, flags, description, detailed)
|
||||
{
|
||||
Options = new Options()
|
||||
{
|
||||
// Internal Program
|
||||
InternalProgram = InternalProgram.NONE,
|
||||
|
||||
// Extra Dumping Options
|
||||
ScanForProtection = false,
|
||||
AddPlaceholders = true,
|
||||
PullAllInformation = false,
|
||||
AddFilenameSuffix = false,
|
||||
OutputSubmissionJSON = false,
|
||||
IncludeArtifacts = false,
|
||||
CompressLogFiles = false,
|
||||
LogCompression = LogCompression.DeflateMaximum,
|
||||
DeleteUnnecessaryFiles = false,
|
||||
CreateIRDAfterDumping = false,
|
||||
|
||||
// Protection Scanning Options
|
||||
ScanArchivesForProtection = true,
|
||||
IncludeDebugProtectionInformation = false,
|
||||
HideDriveLetters = false,
|
||||
|
||||
// Redump Login Information
|
||||
RetrieveMatchInformation = true,
|
||||
RedumpUsername = null,
|
||||
RedumpPassword = null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
// Validate a system type is provided
|
||||
if (System == null)
|
||||
{
|
||||
Console.Error.WriteLine("A system name needs to be provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log the system being used, in case it came from config
|
||||
Console.WriteLine($"Using system: {System.LongName()}");
|
||||
|
||||
// Validate the supplied credentials
|
||||
if (Options.RetrieveMatchInformation
|
||||
&& !string.IsNullOrEmpty(Options.RedumpUsername)
|
||||
&& !string.IsNullOrEmpty(Options.RedumpPassword))
|
||||
{
|
||||
bool? validated = RedumpClient.ValidateCredentials(Options.RedumpUsername!, Options.RedumpPassword!).GetAwaiter().GetResult();
|
||||
string message = validated switch
|
||||
{
|
||||
true => "Redump username and password accepted!",
|
||||
false => "Redump username and password denied!",
|
||||
null => "An error occurred validating your credentials!",
|
||||
};
|
||||
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
|
||||
// Validate the internal program
|
||||
#pragma warning disable IDE0010
|
||||
switch (Options.InternalProgram)
|
||||
{
|
||||
case InternalProgram.Aaru:
|
||||
if (!File.Exists(Options.AaruPath))
|
||||
{
|
||||
Console.Error.WriteLine("A path needs to be supplied in config.json for Aaru, exiting...");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case InternalProgram.DiscImageCreator:
|
||||
if (!File.Exists(Options.DiscImageCreatorPath))
|
||||
{
|
||||
Console.Error.WriteLine("A path needs to be supplied in config.json for DIC, exiting...");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// case InternalProgram.Dreamdump:
|
||||
// if (!File.Exists(Options.DreamdumpPath))
|
||||
// {
|
||||
// Console.Error.WriteLine("A path needs to be supplied in config.json for Dreamdump, exiting...");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// break;
|
||||
|
||||
case InternalProgram.Redumper:
|
||||
if (!File.Exists(Options.RedumperPath))
|
||||
{
|
||||
Console.Error.WriteLine("A path needs to be supplied in config.json for Redumper, exiting...");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
Console.Error.WriteLine($"{Options.InternalProgram} is not a supported dumping program, exiting...");
|
||||
break;
|
||||
}
|
||||
#pragma warning restore IDE0010
|
||||
|
||||
// Ensure we have the values we need
|
||||
if (CustomParams is null && DevicePath is null)
|
||||
{
|
||||
Console.Error.WriteLine("Either custom parameters or a device path need to be provided, exiting...");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Options.InternalProgram == InternalProgram.DiscImageCreator
|
||||
&& CustomParams is null
|
||||
&& (MediaType is null || MediaType == SabreTools.RedumpLib.Data.MediaType.NONE))
|
||||
{
|
||||
Console.Error.WriteLine("Media type is required for DiscImageCreator, exiting...");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If no media type is provided, use a default
|
||||
if (CustomParams is null && (MediaType is null || MediaType == SabreTools.RedumpLib.Data.MediaType.NONE))
|
||||
{
|
||||
// Get reasonable default values based on the current system
|
||||
var mediaTypes = System.MediaTypes();
|
||||
MediaType = mediaTypes.Count > 0 ? mediaTypes[0] : SabreTools.RedumpLib.Data.MediaType.CDROM;
|
||||
if (MediaType == SabreTools.RedumpLib.Data.MediaType.NONE)
|
||||
MediaType = SabreTools.RedumpLib.Data.MediaType.CDROM;
|
||||
|
||||
Console.WriteLine($"No media type was provided, using {MediaType.LongName()}");
|
||||
}
|
||||
|
||||
// Normalize the file path
|
||||
if (DevicePath is not null && FilePath is null)
|
||||
{
|
||||
string defaultFileName = $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
FilePath = Path.Combine(defaultFileName, $"{defaultFileName}.bin");
|
||||
if (Options.DefaultOutputPath is not null)
|
||||
FilePath = Path.Combine(Options.DefaultOutputPath, FilePath);
|
||||
}
|
||||
|
||||
if (FilePath is not null)
|
||||
FilePath = FrontendTool.NormalizeOutputPaths(FilePath, getFullPath: true);
|
||||
|
||||
// Get the speed from the options
|
||||
int speed = DriveSpeed ?? FrontendTool.GetDefaultSpeedForMediaType(MediaType, Options);
|
||||
|
||||
// Populate an environment
|
||||
var drive = Drive.Create(null, DevicePath ?? string.Empty);
|
||||
var env = new DumpEnvironment(Options,
|
||||
FilePath,
|
||||
drive,
|
||||
System,
|
||||
Options.InternalProgram);
|
||||
env.SetExecutionContext(MediaType, null);
|
||||
env.SetProcessor();
|
||||
|
||||
// Process the parameters
|
||||
string? paramStr = CustomParams ?? env.GetFullParameters(MediaType, speed);
|
||||
if (string.IsNullOrEmpty(paramStr))
|
||||
{
|
||||
Console.Error.WriteLine("No valid environment could be created, exiting...");
|
||||
return false;
|
||||
}
|
||||
|
||||
env.SetExecutionContext(MediaType, paramStr);
|
||||
|
||||
// Invoke the dumping program
|
||||
Console.WriteLine($"Invoking {Options.InternalProgram} using '{paramStr}'");
|
||||
var dumpResult = env.Run(MediaType).GetAwaiter().GetResult();
|
||||
Console.WriteLine(dumpResult.Message);
|
||||
if (dumpResult == false)
|
||||
return false;
|
||||
|
||||
// If it was not a dumping command
|
||||
if (!env.IsDumpingCommand())
|
||||
{
|
||||
Console.Error.WriteLine();
|
||||
Console.WriteLine("Execution not recognized as dumping command, skipping processing...");
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we have a mounted path, replace the environment
|
||||
if (MountedPath is not null && Directory.Exists(MountedPath))
|
||||
{
|
||||
drive = Drive.Create(null, MountedPath);
|
||||
env = new DumpEnvironment(Options,
|
||||
FilePath,
|
||||
drive,
|
||||
System,
|
||||
internalProgram: null);
|
||||
env.SetExecutionContext(MediaType, null);
|
||||
env.SetProcessor();
|
||||
}
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
var verifyResult = env.VerifyAndSaveDumpOutput()
|
||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
Console.WriteLine(verifyResult.Message);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display help for MPF.CLI
|
||||
/// </summary>
|
||||
/// <param name="error">Error string to prefix the help text with</param>
|
||||
public static void DisplayHelp()
|
||||
{
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine("MPF.CLI <system> [options]");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Standalone Options:");
|
||||
Console.WriteLine("?, h, help Show this help text");
|
||||
Console.WriteLine("version Print the program version");
|
||||
Console.WriteLine("lc, listcodes List supported comment/content site codes");
|
||||
Console.WriteLine("lo, listconfig List current configuration values");
|
||||
Console.WriteLine("lm, listmedia List supported media types");
|
||||
Console.WriteLine("ls, listsystems List supported system types");
|
||||
Console.WriteLine("lp, listprograms List supported dumping program outputs");
|
||||
Console.WriteLine("i, interactive Enable interactive mode");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("CLI Options:");
|
||||
Console.WriteLine("-u, --use <program> Override configured dumping program name");
|
||||
Console.WriteLine("-t, --mediatype <mediatype> Set media type for dumping (Required for DIC)");
|
||||
Console.WriteLine("-d, --device <devicepath> Physical drive path (Required if no custom parameters set)");
|
||||
Console.WriteLine("-m, --mounted <dirpath> Mounted filesystem path for additional checks");
|
||||
Console.WriteLine("-f, --file \"<filepath>\" Output file path (Recommended, uses defaults otherwise)");
|
||||
Console.WriteLine("-s, --speed <speed> Override default dumping speed");
|
||||
Console.WriteLine("-c, --custom \"<params>\" Custom parameters to use");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("Dumping program paths and other settings can be found in the config.json file");
|
||||
Console.WriteLine("generated next to the program by default. Ensure that all settings are to user");
|
||||
Console.WriteLine("preference before running MPF.CLI.");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("Custom dumping parameters, if used, will fully replace the default parameters.");
|
||||
Console.WriteLine("All dumping parameters need to be supplied if doing this.");
|
||||
Console.WriteLine("Otherwise, a drive path is required.");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("Mounted filesystem path is only recommended on OSes that require block");
|
||||
Console.WriteLine("device dumping, usually Linux and macOS.");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
196
MPF.CLI/Features/InteractiveFeature.cs
Normal file
196
MPF.CLI/Features/InteractiveFeature.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.CLI.Features
|
||||
{
|
||||
internal sealed class InteractiveFeature : BaseFeature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "interactive";
|
||||
|
||||
private static readonly string[] _flags = ["i", "interactive"];
|
||||
|
||||
private const string _description = "Enable interactive mode";
|
||||
|
||||
#endregion
|
||||
|
||||
public InteractiveFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessArgs(string[] args, int index)
|
||||
{
|
||||
// Cache all args as inputs
|
||||
for (int i = 1; i < args.Length; i++)
|
||||
{
|
||||
Inputs.Add(args[i]);
|
||||
}
|
||||
|
||||
// Read the options from config, if possible
|
||||
Options = OptionsLoader.LoadFromConfig();
|
||||
|
||||
// Create return values
|
||||
MediaType = SabreTools.RedumpLib.Data.MediaType.NONE;
|
||||
string defaultFileName = $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
#if NET20 || NET35
|
||||
FilePath = Path.Combine(Options.DefaultOutputPath ?? "ISO", Path.Combine(defaultFileName, $"{defaultFileName}.bin"));
|
||||
#else
|
||||
FilePath = Path.Combine(Options.DefaultOutputPath ?? "ISO", defaultFileName, $"{defaultFileName}.bin");
|
||||
#endif
|
||||
System = Options.DefaultSystem;
|
||||
|
||||
// Create state values
|
||||
string? result;
|
||||
|
||||
root:
|
||||
Console.Clear();
|
||||
Console.WriteLine("MPF.CLI Interactive Mode - Main Menu");
|
||||
Console.WriteLine("-------------------------");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"1) Set system (Currently '{System}')");
|
||||
Console.WriteLine($"2) Set dumping program (Currently '{Options.InternalProgram}')");
|
||||
Console.WriteLine($"3) Set media type (Currently '{MediaType}')");
|
||||
Console.WriteLine($"4) Set device path (Currently '{DevicePath}')");
|
||||
Console.WriteLine($"5) Set mounted path (Currently '{MountedPath}')");
|
||||
Console.WriteLine($"6) Set file path (Currently '{FilePath}')");
|
||||
Console.WriteLine($"7) Set override speed (Currently '{DriveSpeed}')");
|
||||
Console.WriteLine($"8) Set custom parameters (Currently '{CustomParams}')");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Q) Exit the program");
|
||||
Console.WriteLine($"X) Start dumping");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
switch (result)
|
||||
{
|
||||
case "1":
|
||||
goto system;
|
||||
case "2":
|
||||
goto dumpingProgram;
|
||||
case "3":
|
||||
goto mediaType;
|
||||
case "4":
|
||||
goto devicePath;
|
||||
case "5":
|
||||
goto mountedPath;
|
||||
case "6":
|
||||
goto filePath;
|
||||
case "7":
|
||||
goto overrideSpeed;
|
||||
case "8":
|
||||
goto customParams;
|
||||
|
||||
case "q":
|
||||
case "Q":
|
||||
Environment.Exit(0);
|
||||
break;
|
||||
case "x":
|
||||
case "X":
|
||||
Console.Clear();
|
||||
goto exit;
|
||||
case "z":
|
||||
case "Z":
|
||||
Console.WriteLine("It is pitch black. You are likely to be eaten by a grue.");
|
||||
Console.Write("> ");
|
||||
Console.ReadLine();
|
||||
goto root;
|
||||
default:
|
||||
Console.WriteLine($"Invalid selection: {result}");
|
||||
Console.ReadLine();
|
||||
goto root;
|
||||
}
|
||||
|
||||
system:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("For possible inputs, use the List Systems commandline option");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the system and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
System = result.ToRedumpSystem();
|
||||
goto root;
|
||||
|
||||
dumpingProgram:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Options:");
|
||||
Console.WriteLine($"{InternalProgram.Redumper.ToString().ToLowerInvariant(),-15} => {InternalProgram.Redumper.LongName()}");
|
||||
Console.WriteLine($"{InternalProgram.DiscImageCreator.ToString().ToLowerInvariant(),-15} => {InternalProgram.DiscImageCreator.LongName()}");
|
||||
Console.WriteLine($"{InternalProgram.Aaru.ToString().ToLowerInvariant(),-15} => {InternalProgram.Aaru.LongName()}");
|
||||
// Console.WriteLine($"{InternalProgram.Dreamdump.ToString().ToLowerInvariant(),-15} => {InternalProgram.Dreamdump.LongName()}");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the dumping program and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
Options.InternalProgram = result.ToInternalProgram();
|
||||
goto root;
|
||||
|
||||
mediaType:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("For possible inputs, use the List Media commandline option");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the media type and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
MediaType = OptionsLoader.ToMediaType(result);
|
||||
goto root;
|
||||
|
||||
devicePath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the device path and press Enter:");
|
||||
Console.Write("> ");
|
||||
DevicePath = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
mountedPath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the mounted path and press Enter:");
|
||||
Console.Write("> ");
|
||||
MountedPath = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
filePath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the file path and press Enter:");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
if (!string.IsNullOrEmpty(result))
|
||||
result = Path.GetFullPath(result!);
|
||||
|
||||
FilePath = result;
|
||||
goto root;
|
||||
|
||||
overrideSpeed:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the override speed and press Enter:");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
if (!int.TryParse(result, out int speed))
|
||||
speed = -1;
|
||||
|
||||
DriveSpeed = speed;
|
||||
goto root;
|
||||
|
||||
customParams:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the custom parameters and press Enter:");
|
||||
Console.Write("> ");
|
||||
CustomParams = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
exit:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
115
MPF.CLI/Features/MainFeature.cs
Normal file
115
MPF.CLI/Features/MainFeature.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.CLI.Features
|
||||
{
|
||||
internal sealed class MainFeature : BaseFeature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "main";
|
||||
|
||||
/// <remarks>Flags are unused</remarks>
|
||||
private static readonly string[] _flags = [];
|
||||
|
||||
/// <remarks>Description is unused</remarks>
|
||||
private const string _description = "";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inputs
|
||||
|
||||
private const string _customName = "custom";
|
||||
internal readonly StringInput CustomInput = new(_customName, ["-c", "--custom"], "Custom parameters to use");
|
||||
|
||||
private const string _deviceName = "device";
|
||||
internal readonly StringInput DeviceInput = new(_deviceName, ["-d", "--device"], "Physical drive path (Required if no custom parameters set)");
|
||||
|
||||
private const string _fileName = "file";
|
||||
internal readonly StringInput FileInput = new(_fileName, ["-f", "--file"], "Output file path (Required if no custom parameters set)");
|
||||
|
||||
private const string _mediaTypeName = "media-type";
|
||||
internal readonly StringInput MediaTypeInput = new(_mediaTypeName, ["-t", "--mediatype"], "Set media type for dumping (Required for DIC)");
|
||||
|
||||
private const string _mountedName = "mounted";
|
||||
internal readonly StringInput MountedInput = new(_mountedName, ["-m", "--mounted"], "Mounted filesystem path for additional checks");
|
||||
|
||||
private const string _speedName = "speed";
|
||||
internal readonly Int32Input SpeedInput = new(_speedName, ["-s", "--speed"], "Override default dumping speed");
|
||||
|
||||
private const string _useName = "use";
|
||||
internal readonly StringInput UseInput = new(_useName, ["-u", "--use"], "Override configured dumping program name");
|
||||
|
||||
#endregion
|
||||
|
||||
public MainFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
Add(UseInput);
|
||||
Add(MediaTypeInput);
|
||||
Add(DeviceInput);
|
||||
Add(MountedInput);
|
||||
Add(FileInput);
|
||||
Add(SpeedInput);
|
||||
Add(CustomInput);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessArgs(string[] args, int index)
|
||||
{
|
||||
// If we have no arguments, just return
|
||||
if (args is null || args.Length == 0)
|
||||
return true;
|
||||
|
||||
// Read the options from config, if possible
|
||||
Options = OptionsLoader.LoadFromConfig();
|
||||
|
||||
// The first argument is the system type
|
||||
System = args[0].Trim('"').ToRedumpSystem();
|
||||
|
||||
// Loop through the arguments and parse out values
|
||||
for (index = 1; index < args.Length; index++)
|
||||
{
|
||||
// Use specific program
|
||||
if (UseInput.ProcessInput(args, ref index))
|
||||
Options.InternalProgram = UseInput.Value.ToInternalProgram();
|
||||
|
||||
// Set a media type
|
||||
else if (MediaTypeInput.ProcessInput(args, ref index))
|
||||
MediaType = OptionsLoader.ToMediaType(MediaTypeInput.Value?.Trim('"'));
|
||||
|
||||
// Use a device path
|
||||
else if (DeviceInput.ProcessInput(args, ref index))
|
||||
DevicePath = DeviceInput.Value;
|
||||
|
||||
// Use a mounted path for physical checks
|
||||
else if (MountedInput.ProcessInput(args, ref index))
|
||||
MountedPath = MountedInput.Value;
|
||||
|
||||
// Use a file path
|
||||
else if (FileInput.ProcessInput(args, ref index))
|
||||
FilePath = FileInput.Value;
|
||||
|
||||
// Set an override speed
|
||||
else if (SpeedInput.ProcessInput(args, ref index))
|
||||
DriveSpeed = SpeedInput.Value;
|
||||
|
||||
// Use a custom parameters
|
||||
else if (CustomInput.ProcessInput(args, ref index))
|
||||
CustomParams = CustomInput.Value;
|
||||
|
||||
// Default, add to inputs
|
||||
else
|
||||
Inputs.Add(args[index]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<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>
|
||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||
@@ -12,7 +12,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.3.2</VersionPrefix>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Title>MPF CLI</Title>
|
||||
@@ -31,11 +31,11 @@
|
||||
<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>
|
||||
@@ -43,7 +43,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.7" />
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
#if NET40
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using MPF.Frontend;
|
||||
using MPF.CLI.Features;
|
||||
using MPF.Frontend.Features;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Web;
|
||||
using SabreTools.CommandLine;
|
||||
using SabreTools.CommandLine.Features;
|
||||
|
||||
namespace MPF.CLI
|
||||
{
|
||||
@@ -18,494 +19,125 @@ namespace MPF.CLI
|
||||
var options = OptionsLoader.LoadFromConfig();
|
||||
if (options.FirstRun)
|
||||
{
|
||||
// Application paths
|
||||
options.AaruPath = "FILL ME IN";
|
||||
options.DiscImageCreatorPath = "FILL ME IN";
|
||||
options.RedumperPath = "FILL ME IN";
|
||||
options.InternalProgram = InternalProgram.NONE;
|
||||
|
||||
// Reset first run
|
||||
options.FirstRun = false;
|
||||
OptionsLoader.SaveToConfig(options);
|
||||
|
||||
// Display non-error message
|
||||
DisplayHelp("First-run detected! Please fill out config.json and run again.");
|
||||
Console.WriteLine("First-run detected! Please verify the generated config.json and run again.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the command set
|
||||
var mainFeature = new MainFeature();
|
||||
var commandSet = CreateCommands(mainFeature);
|
||||
|
||||
// If we have no args, show the help and quit
|
||||
if (args is null || args.Length == 0)
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the first argument as a feature flag
|
||||
string featureName = args[0];
|
||||
|
||||
// Try processing the standalone arguments
|
||||
bool? standaloneProcessed = OptionsLoader.ProcessStandaloneArguments(args);
|
||||
if (standaloneProcessed != false)
|
||||
var topLevel = commandSet.GetTopLevel(featureName);
|
||||
switch (topLevel)
|
||||
{
|
||||
if (standaloneProcessed == null)
|
||||
DisplayHelp();
|
||||
return;
|
||||
}
|
||||
// Standalone Options
|
||||
case Help: BaseFeature.DisplayHelp(); return;
|
||||
case VersionFeature version: version.Execute(); return;
|
||||
case ListCodesFeature lc: lc.Execute(); return;
|
||||
case ListConfigFeature lc: lc.Execute(); return;
|
||||
case ListMediaTypesFeature lm: lm.Execute(); return;
|
||||
case ListProgramsFeature lp: lp.Execute(); return;
|
||||
case ListSystemsFeature ls: ls.Execute(); return;
|
||||
|
||||
// Setup common outputs
|
||||
CommandOptions opts;
|
||||
MediaType mediaType;
|
||||
RedumpSystem? knownSystem;
|
||||
|
||||
// Use interactive mode
|
||||
if (args.Length > 0 && (args[0] == "-i" || args[0] == "--interactive"))
|
||||
{
|
||||
opts = InteractiveMode(options, out mediaType, out knownSystem);
|
||||
}
|
||||
|
||||
// Use normal commandline parameters
|
||||
else
|
||||
{
|
||||
// Try processing the common arguments
|
||||
bool success = OptionsLoader.ProcessCommonArguments(args, out mediaType, out knownSystem, out var error);
|
||||
if (!success)
|
||||
{
|
||||
DisplayHelp(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate the supplied credentials
|
||||
if (options.RetrieveMatchInformation
|
||||
&& !string.IsNullOrEmpty(options.RedumpUsername)
|
||||
&& !string.IsNullOrEmpty(options.RedumpPassword))
|
||||
{
|
||||
bool? validated = RedumpClient.ValidateCredentials(options.RedumpUsername!, options.RedumpPassword!).GetAwaiter().GetResult();
|
||||
string message = validated switch
|
||||
// Interactive Mode
|
||||
case InteractiveFeature interactive:
|
||||
if (!interactive.ProcessArgs(args, 0))
|
||||
{
|
||||
true => "Redump username and password accepted!",
|
||||
false => "Redump username and password denied!",
|
||||
null => "An error occurred validating your credentials!",
|
||||
};
|
||||
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
|
||||
// Process any custom parameters
|
||||
int startIndex = 2;
|
||||
opts = LoadFromArguments(args, options, ref startIndex);
|
||||
}
|
||||
|
||||
// Validate the internal program
|
||||
switch (options.InternalProgram)
|
||||
{
|
||||
case InternalProgram.Aaru:
|
||||
if (!File.Exists(options.AaruPath))
|
||||
{
|
||||
DisplayHelp("A path needs to be supplied for Aaru, exiting...");
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case InternalProgram.DiscImageCreator:
|
||||
if (!File.Exists(options.DiscImageCreatorPath))
|
||||
if (!interactive.Execute())
|
||||
{
|
||||
DisplayHelp("A path needs to be supplied for DIC, exiting...");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case InternalProgram.Redumper:
|
||||
if (!File.Exists(options.RedumperPath))
|
||||
{
|
||||
DisplayHelp("A path needs to be supplied for Redumper, exiting...");
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Default Behavior
|
||||
default:
|
||||
DisplayHelp($"{options.InternalProgram} is not a supported dumping program, exiting...");
|
||||
if (!mainFeature.ProcessArgs(args, 0))
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mainFeature.Execute())
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Ensure we have the values we need
|
||||
if (opts.CustomParams == null && (opts.DevicePath == null || opts.FilePath == null))
|
||||
{
|
||||
DisplayHelp("Both a device path and file path need to be supplied, exiting...");
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize the file path
|
||||
if (opts.FilePath != null)
|
||||
opts.FilePath = Path.GetFullPath(opts.FilePath);
|
||||
|
||||
// Get the speed from the options
|
||||
int speed = opts.DriveSpeed ?? FrontendTool.GetDefaultSpeedForMediaType(mediaType, options);
|
||||
|
||||
// Populate an environment
|
||||
var drive = Drive.Create(null, opts.DevicePath ?? string.Empty);
|
||||
var env = new DumpEnvironment(options,
|
||||
opts.FilePath,
|
||||
drive,
|
||||
knownSystem,
|
||||
mediaType,
|
||||
options.InternalProgram,
|
||||
parameters: null);
|
||||
|
||||
// Process the parameters
|
||||
string? paramStr = opts.CustomParams ?? env.GetFullParameters(speed);
|
||||
if (string.IsNullOrEmpty(paramStr))
|
||||
{
|
||||
DisplayHelp("No valid environment could be created, exiting...");
|
||||
return;
|
||||
}
|
||||
|
||||
env.SetExecutionContext(paramStr);
|
||||
|
||||
// Invoke the dumping program
|
||||
Console.WriteLine($"Invoking {options.InternalProgram} using '{paramStr}'");
|
||||
var dumpResult = env.Run().GetAwaiter().GetResult();
|
||||
Console.WriteLine(dumpResult.Message);
|
||||
if (!dumpResult)
|
||||
return;
|
||||
|
||||
// If it was not a dumping command
|
||||
if (!env.IsDumpingCommand())
|
||||
{
|
||||
Console.WriteLine("Execution not recognized as dumping command, skipping processing...");
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a mounted path, replace the environment
|
||||
if (opts.MountedPath != null && Directory.Exists(opts.MountedPath))
|
||||
{
|
||||
drive = Drive.Create(null, opts.MountedPath);
|
||||
env = new DumpEnvironment(options,
|
||||
opts.FilePath,
|
||||
drive,
|
||||
knownSystem,
|
||||
mediaType,
|
||||
internalProgram: null,
|
||||
parameters: null);
|
||||
}
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
var verifyResult = env.VerifyAndSaveDumpOutput()
|
||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
Console.WriteLine(verifyResult.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display help for MPF.CLI
|
||||
/// Create the command set for the program
|
||||
/// </summary>
|
||||
/// <param name="error">Error string to prefix the help text with</param>
|
||||
private static void DisplayHelp(string? error = null)
|
||||
private static CommandSet CreateCommands(MainFeature mainFeature)
|
||||
{
|
||||
if (error != null)
|
||||
Console.WriteLine(error);
|
||||
List<string> header = [
|
||||
"MPF.CLI [standalone|system] [options] <path> ...",
|
||||
string.Empty,
|
||||
];
|
||||
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine("MPF.CLI <mediatype> <system> [options]");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Standalone Options:");
|
||||
Console.WriteLine("-h, -? Show this help text");
|
||||
Console.WriteLine("-lc, --listcodes List supported comment/content site codes");
|
||||
Console.WriteLine("-lm, --listmedia List supported media types");
|
||||
Console.WriteLine("-ls, --listsystems List supported system types");
|
||||
Console.WriteLine("-lp, --listprograms List supported dumping program outputs");
|
||||
Console.WriteLine("-i, --interactive Enable interactive mode");
|
||||
Console.WriteLine();
|
||||
List<string> footer = [
|
||||
string.Empty,
|
||||
"Dumping program paths and other settings can be found in the config.json file",
|
||||
"generated next to the program by default. Ensure that all settings are to user",
|
||||
"preference before running MPF.CLI.",
|
||||
string.Empty,
|
||||
|
||||
Console.WriteLine("CLI Options:");
|
||||
Console.WriteLine("-u, --use <program> Override default dumping program");
|
||||
Console.WriteLine("-d, --device <devicepath> Physical drive path (Required if no custom parameters set)");
|
||||
Console.WriteLine("-m, --mounted <dirpath> Mounted filesystem path for additional checks");
|
||||
Console.WriteLine("-f, --file \"<filepath>\" Output file path (Required if no custom parameters set)");
|
||||
Console.WriteLine("-s, --speed <speed> Override default dumping speed");
|
||||
Console.WriteLine("-c, --custom \"<params>\" Custom parameters to use");
|
||||
Console.WriteLine();
|
||||
"Custom dumping parameters, if used, will fully replace the default parameters.",
|
||||
"All dumping parameters need to be supplied if doing this.",
|
||||
"Otherwise, both a drive path and output file path are required.",
|
||||
string.Empty,
|
||||
|
||||
Console.WriteLine("Custom dumping parameters, if used, will fully replace the default parameters.");
|
||||
Console.WriteLine("All dumping parameters need to be supplied if doing this.");
|
||||
Console.WriteLine("Otherwise, both a drive path and output file path are required.");
|
||||
Console.WriteLine();
|
||||
"Mounted filesystem path is only recommended on OSes that require block",
|
||||
"device dumping, usually Linux and macOS.",
|
||||
string.Empty,
|
||||
];
|
||||
|
||||
Console.WriteLine("Mounted filesystem path is only recommended on OSes that require block");
|
||||
Console.WriteLine("device dumping, usually Linux and macOS.");
|
||||
Console.WriteLine();
|
||||
}
|
||||
var commandSet = new CommandSet(header, footer);
|
||||
|
||||
/// <summary>
|
||||
/// Enable interactive mode for entering information
|
||||
/// </summary>
|
||||
private static CommandOptions InteractiveMode(Options options, out MediaType mediaType, out RedumpSystem? system)
|
||||
{
|
||||
// Create return values
|
||||
var opts = new CommandOptions();
|
||||
mediaType = MediaType.NONE;
|
||||
system = null;
|
||||
// Standalone Options
|
||||
commandSet.Add(new Help());
|
||||
commandSet.Add(new VersionFeature());
|
||||
commandSet.Add(new ListCodesFeature());
|
||||
commandSet.Add(new ListConfigFeature());
|
||||
commandSet.Add(new ListMediaTypesFeature());
|
||||
commandSet.Add(new ListSystemsFeature());
|
||||
commandSet.Add(new ListProgramsFeature());
|
||||
commandSet.Add(new InteractiveFeature());
|
||||
|
||||
// Create state values
|
||||
string? result = string.Empty;
|
||||
// CLI Options
|
||||
commandSet.Add(mainFeature.UseInput);
|
||||
commandSet.Add(mainFeature.MediaTypeInput);
|
||||
commandSet.Add(mainFeature.DeviceInput);
|
||||
commandSet.Add(mainFeature.MountedInput);
|
||||
commandSet.Add(mainFeature.FileInput);
|
||||
commandSet.Add(mainFeature.SpeedInput);
|
||||
commandSet.Add(mainFeature.CustomInput);
|
||||
|
||||
root:
|
||||
Console.Clear();
|
||||
Console.WriteLine("MPF.CLI Interactive Mode - Main Menu");
|
||||
Console.WriteLine("-------------------------");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"1) Set media type (Currently '{mediaType}')");
|
||||
Console.WriteLine($"2) Set system (Currently '{system}')");
|
||||
Console.WriteLine($"3) Set dumping program (Currently '{options.InternalProgram}')");
|
||||
Console.WriteLine($"4) Set device path (Currently '{opts.DevicePath}')");
|
||||
Console.WriteLine($"5) Set mounted path (Currently '{opts.MountedPath}')");
|
||||
Console.WriteLine($"6) Set file path (Currently '{opts.FilePath}')");
|
||||
Console.WriteLine($"7) Set override speed (Currently '{opts.DriveSpeed}')");
|
||||
Console.WriteLine($"8) Set custom parameters (Currently '{opts.CustomParams}')");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Q) Exit the program");
|
||||
Console.WriteLine($"X) Start dumping");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
switch (result)
|
||||
{
|
||||
case "1":
|
||||
goto mediaType;
|
||||
case "2":
|
||||
goto system;
|
||||
case "3":
|
||||
goto dumpingProgram;
|
||||
case "4":
|
||||
goto devicePath;
|
||||
case "5":
|
||||
goto mountedPath;
|
||||
case "6":
|
||||
goto filePath;
|
||||
case "7":
|
||||
goto overrideSpeed;
|
||||
case "8":
|
||||
goto customParams;
|
||||
|
||||
case "q":
|
||||
case "Q":
|
||||
Environment.Exit(0);
|
||||
break;
|
||||
case "x":
|
||||
case "X":
|
||||
Console.Clear();
|
||||
goto exit;
|
||||
case "z":
|
||||
case "Z":
|
||||
Console.WriteLine("It is pitch black. You are likely to be eaten by a grue.");
|
||||
Console.Write("> ");
|
||||
Console.ReadLine();
|
||||
goto root;
|
||||
default:
|
||||
Console.WriteLine($"Invalid selection: {result}");
|
||||
Console.ReadLine();
|
||||
goto root;
|
||||
}
|
||||
|
||||
mediaType:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the media type and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
mediaType = OptionsLoader.ToMediaType(result);
|
||||
goto root;
|
||||
|
||||
system:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the system and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
system = Extensions.ToRedumpSystem(result);
|
||||
goto root;
|
||||
|
||||
dumpingProgram:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the dumping program and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
options.InternalProgram = result.ToInternalProgram();
|
||||
goto root;
|
||||
|
||||
devicePath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the device path and press Enter:");
|
||||
Console.Write("> ");
|
||||
opts.DevicePath = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
mountedPath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the mounted path and press Enter:");
|
||||
Console.Write("> ");
|
||||
opts.MountedPath = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
filePath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the file path and press Enter:");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
if (!string.IsNullOrEmpty(result))
|
||||
result = Path.GetFullPath(result!);
|
||||
|
||||
opts.FilePath = result;
|
||||
goto root;
|
||||
|
||||
overrideSpeed:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the override speed and press Enter:");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
if (!int.TryParse(result, out int speed))
|
||||
speed = -1;
|
||||
|
||||
opts.DriveSpeed = speed;
|
||||
goto root;
|
||||
|
||||
customParams:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the custom parameters and press Enter:");
|
||||
Console.Write("> ");
|
||||
opts.CustomParams = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
exit:
|
||||
return opts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the current set of options from application arguments
|
||||
/// </summary>
|
||||
private static CommandOptions LoadFromArguments(string[] args, Options options, ref int startIndex)
|
||||
{
|
||||
// Create return values
|
||||
var opts = new CommandOptions();
|
||||
|
||||
// If we have no arguments, just return
|
||||
if (args == null || args.Length == 0)
|
||||
{
|
||||
startIndex = 0;
|
||||
return opts;
|
||||
}
|
||||
|
||||
// If we have an invalid start index, just return
|
||||
if (startIndex < 0 || startIndex >= args.Length)
|
||||
return opts;
|
||||
|
||||
// Loop through the arguments and parse out values
|
||||
for (; startIndex < args.Length; startIndex++)
|
||||
{
|
||||
// Use specific program
|
||||
if (args[startIndex].StartsWith("-u=") || args[startIndex].StartsWith("--use="))
|
||||
{
|
||||
string internalProgram = args[startIndex].Split('=')[1];
|
||||
options.InternalProgram = internalProgram.ToInternalProgram();
|
||||
}
|
||||
else if (args[startIndex] == "-u" || args[startIndex] == "--use")
|
||||
{
|
||||
string internalProgram = args[startIndex + 1];
|
||||
options.InternalProgram = internalProgram.ToInternalProgram();
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Use a device path
|
||||
else if (args[startIndex].StartsWith("-d=") || args[startIndex].StartsWith("--device="))
|
||||
{
|
||||
opts.DevicePath = args[startIndex].Split('=')[1].Trim('"');
|
||||
}
|
||||
else if (args[startIndex] == "-d" || args[startIndex] == "--device")
|
||||
{
|
||||
opts.DevicePath = args[startIndex + 1].Trim('"');
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Use a mounted path for physical checks
|
||||
else if (args[startIndex].StartsWith("-m=") || args[startIndex].StartsWith("--mounted="))
|
||||
{
|
||||
opts.MountedPath = args[startIndex].Split('=')[1];
|
||||
}
|
||||
else if (args[startIndex] == "-m" || args[startIndex] == "--mounted")
|
||||
{
|
||||
opts.MountedPath = args[startIndex + 1];
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Use a file path
|
||||
else if (args[startIndex].StartsWith("-f=") || args[startIndex].StartsWith("--file="))
|
||||
{
|
||||
opts.FilePath = args[startIndex].Split('=')[1].Trim('"');
|
||||
}
|
||||
else if (args[startIndex] == "-f" || args[startIndex] == "--file")
|
||||
{
|
||||
opts.FilePath = args[startIndex + 1].Trim('"');
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Set an override speed
|
||||
else if (args[startIndex].StartsWith("-s=") || args[startIndex].StartsWith("--speed="))
|
||||
{
|
||||
if (!int.TryParse(args[startIndex].Split('=')[1].Trim('"'), out int speed))
|
||||
speed = -1;
|
||||
|
||||
opts.DriveSpeed = speed;
|
||||
}
|
||||
else if (args[startIndex] == "-s" || args[startIndex] == "--speed")
|
||||
{
|
||||
if (!int.TryParse(args[startIndex + 1].Trim('"'), out int speed))
|
||||
speed = -1;
|
||||
|
||||
opts.DriveSpeed = speed;
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Use a custom parameters
|
||||
else if (args[startIndex].StartsWith("-c=") || args[startIndex].StartsWith("--custom="))
|
||||
{
|
||||
opts.CustomParams = args[startIndex].Split('=')[1].Trim('"');
|
||||
}
|
||||
else if (args[startIndex] == "-c" || args[startIndex] == "--custom")
|
||||
{
|
||||
opts.CustomParams = args[startIndex + 1].Trim('"');
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Default, we fall out
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents commandline options
|
||||
/// </summary>
|
||||
private class CommandOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Path to the device to dump
|
||||
/// </summary>
|
||||
/// <remarks>Required if custom parameters are not set</remarks>
|
||||
public string? DevicePath { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Path to the mounted filesystem to check
|
||||
/// </summary>
|
||||
/// <remarks>Should only be used when the device path is not readable</remarks>
|
||||
public string? MountedPath { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Path to the output file
|
||||
/// </summary>
|
||||
/// <remarks>Required if custom parameters are not set</remarks>
|
||||
public string? FilePath { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Override drive speed
|
||||
/// </summary>
|
||||
public int? DriveSpeed { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Custom parameters for dumping
|
||||
/// </summary>
|
||||
public string? CustomParams { get; set; } = null;
|
||||
return commandSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
187
MPF.Check/Features/BaseFeature.cs
Normal file
187
MPF.Check/Features/BaseFeature.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
#if NET40
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using MPF.Frontend;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Web;
|
||||
using LogCompression = MPF.Processors.LogCompression;
|
||||
|
||||
namespace MPF.Check.Features
|
||||
{
|
||||
internal abstract class BaseFeature : SabreTools.CommandLine.Feature
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// User-defined options
|
||||
/// </summary>
|
||||
public Options Options { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Currently-selected system
|
||||
/// </summary>
|
||||
public RedumpSystem? System { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Seed submission info from an input file
|
||||
/// </summary>
|
||||
public SubmissionInfo? Seed { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to the device to scan
|
||||
/// </summary>
|
||||
public string? DevicePath { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
protected BaseFeature(string name, string[] flags, string description, string? detailed = null)
|
||||
: base(name, flags, description, detailed)
|
||||
{
|
||||
Options = new Options()
|
||||
{
|
||||
// Internal Program
|
||||
InternalProgram = InternalProgram.NONE,
|
||||
|
||||
// Extra Dumping Options
|
||||
ScanForProtection = false,
|
||||
AddPlaceholders = true,
|
||||
PullAllInformation = false,
|
||||
AddFilenameSuffix = false,
|
||||
OutputSubmissionJSON = false,
|
||||
IncludeArtifacts = false,
|
||||
CompressLogFiles = false,
|
||||
LogCompression = LogCompression.DeflateMaximum,
|
||||
DeleteUnnecessaryFiles = false,
|
||||
CreateIRDAfterDumping = false,
|
||||
|
||||
// Protection Scanning Options
|
||||
ScanArchivesForProtection = true,
|
||||
IncludeDebugProtectionInformation = false,
|
||||
HideDriveLetters = false,
|
||||
|
||||
// Redump Login Information
|
||||
RetrieveMatchInformation = true,
|
||||
RedumpUsername = null,
|
||||
RedumpPassword = null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
// Validate a system type is provided
|
||||
if (System == null)
|
||||
{
|
||||
Console.Error.WriteLine("A system name needs to be provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log the system being used, in case it came from config
|
||||
Console.WriteLine($"Using system: {System.LongName()}");
|
||||
|
||||
// Validate a program is provided
|
||||
if (Options.InternalProgram == InternalProgram.NONE)
|
||||
{
|
||||
Console.Error.WriteLine("A program name needs to be provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate the supplied credentials
|
||||
if (Options.RetrieveMatchInformation
|
||||
&& !string.IsNullOrEmpty(Options.RedumpUsername)
|
||||
&& !string.IsNullOrEmpty(Options.RedumpPassword))
|
||||
{
|
||||
bool? validated = RedumpClient.ValidateCredentials(Options.RedumpUsername!, Options.RedumpPassword!).GetAwaiter().GetResult();
|
||||
string message = validated switch
|
||||
{
|
||||
true => "Redump username and password accepted!",
|
||||
false => "Redump username and password denied!",
|
||||
null => "An error occurred validating your credentials!",
|
||||
};
|
||||
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
|
||||
// Loop through all the rest of the args
|
||||
for (int i = 0; i < Inputs.Count; i++)
|
||||
{
|
||||
// Get the full file path
|
||||
string filepath = Path.GetFullPath(Inputs[i].Trim('"'));
|
||||
|
||||
// Now populate an environment
|
||||
Drive? drive = null;
|
||||
if (!string.IsNullOrEmpty(DevicePath))
|
||||
drive = Drive.Create(null, DevicePath!);
|
||||
|
||||
var env = new DumpEnvironment(Options,
|
||||
filepath,
|
||||
drive,
|
||||
System,
|
||||
internalProgram: null);
|
||||
env.SetProcessor();
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
var result = env.VerifyAndSaveDumpOutput(seedInfo: Seed)
|
||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display help for MPF.Check
|
||||
/// </summary>
|
||||
/// <param name="error">Error string to prefix the help text with</param>
|
||||
public static void DisplayHelp()
|
||||
{
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine("MPF.Check <system> [options] </path/to/output.cue|iso|_logs.zip> ...");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Standalone Options:");
|
||||
Console.WriteLine("?, h, help Show this help text");
|
||||
Console.WriteLine("version Print the program version");
|
||||
Console.WriteLine("lc, listcodes List supported comment/content site codes");
|
||||
Console.WriteLine("lo, listconfig List current configuration values");
|
||||
Console.WriteLine("lm, listmedia List supported media types");
|
||||
Console.WriteLine("ls, listsystems List supported system types");
|
||||
Console.WriteLine("lp, listprograms List supported dumping program outputs");
|
||||
Console.WriteLine("i, interactive Enable interactive mode");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("Check Options:");
|
||||
Console.WriteLine("-u, --use <program> Dumping program output type [REQUIRED]");
|
||||
Console.WriteLine(" --load-seed <path> Load a seed submission JSON for user information");
|
||||
Console.WriteLine(" --no-placeholders Disable placeholder values in submission info");
|
||||
Console.WriteLine(" --create-ird Create IRD from output files (PS3 only)");
|
||||
Console.WriteLine(" --no-retrieve Disable retrieving match information from Redump");
|
||||
Console.WriteLine("-c, --credentials <user> <pw> Redump username and password (incompatible with --no-retrieve) [WILL BE REMOVED]");
|
||||
Console.WriteLine("-U, --username <user> Redump username (incompatible with --no-retrieve)");
|
||||
Console.WriteLine("-P, --password <pw> Redump password (incompatible with --no-retrieve)");
|
||||
Console.WriteLine(" --pull-all Pull all information from Redump (requires --username and --password)");
|
||||
Console.WriteLine("-p, --path <drivepath> Physical drive path for additional checks");
|
||||
Console.WriteLine("-s, --scan Enable copy protection scan (requires --path)");
|
||||
Console.WriteLine(" --disable-archives Disable scanning archives (requires --scan)");
|
||||
Console.WriteLine(" --enable-debug Enable debug protection information (requires --scan)");
|
||||
Console.WriteLine(" --hide-drive-letters Hide drive letters from scan output (requires --scan)");
|
||||
Console.WriteLine("-x, --suffix Enable adding filename suffix");
|
||||
Console.WriteLine("-j, --json Enable submission JSON output");
|
||||
Console.WriteLine(" --include-artifacts Include artifacts in JSON (requires --json)");
|
||||
Console.WriteLine("-z, --zip Enable log file compression");
|
||||
Console.WriteLine(" --log-compression Set the log compression type (requires compression enabled)");
|
||||
Console.WriteLine("-d, --delete Enable unnecessary file deletion");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("WARNING: If using a configuration file alongside any of the above options");
|
||||
Console.WriteLine("then flag options will act as toggles instead of always enabling.");
|
||||
Console.WriteLine("For example, if log compression is enabled in your configuration file, then");
|
||||
Console.WriteLine("providing the --zip option would disable compression.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("WARNING: Check will overwrite both any existing submission information files as well");
|
||||
Console.WriteLine("as any log archives. Please make backups of those if you need to before running Check.");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
288
MPF.Check/Features/InteractiveFeature.cs
Normal file
288
MPF.Check/Features/InteractiveFeature.cs
Normal file
@@ -0,0 +1,288 @@
|
||||
|
||||
using System;
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using LogCompression = MPF.Processors.LogCompression;
|
||||
|
||||
namespace MPF.Check.Features
|
||||
{
|
||||
internal sealed class InteractiveFeature : BaseFeature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "interactive";
|
||||
|
||||
private static readonly string[] _flags = ["i", "interactive"];
|
||||
|
||||
private const string _description = "Enable interactive mode";
|
||||
|
||||
#endregion
|
||||
|
||||
public InteractiveFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessArgs(string[] args, int index)
|
||||
{
|
||||
// Cache all args as inputs
|
||||
for (int i = 1; i < args.Length; i++)
|
||||
{
|
||||
Inputs.Add(args[i]);
|
||||
}
|
||||
|
||||
// Read the options from config, if possible
|
||||
Options = OptionsLoader.LoadFromConfig();
|
||||
if (Options.FirstRun)
|
||||
{
|
||||
Options = new Options()
|
||||
{
|
||||
// Internal Program
|
||||
InternalProgram = InternalProgram.NONE,
|
||||
|
||||
// Extra Dumping Options
|
||||
ScanForProtection = false,
|
||||
AddPlaceholders = true,
|
||||
PullAllInformation = false,
|
||||
AddFilenameSuffix = false,
|
||||
OutputSubmissionJSON = false,
|
||||
IncludeArtifacts = false,
|
||||
CompressLogFiles = false,
|
||||
LogCompression = LogCompression.DeflateMaximum,
|
||||
DeleteUnnecessaryFiles = false,
|
||||
CreateIRDAfterDumping = false,
|
||||
|
||||
// Protection Scanning Options
|
||||
ScanArchivesForProtection = true,
|
||||
IncludeDebugProtectionInformation = false,
|
||||
HideDriveLetters = false,
|
||||
|
||||
// Redump Login Information
|
||||
RetrieveMatchInformation = true,
|
||||
RedumpUsername = null,
|
||||
RedumpPassword = null,
|
||||
};
|
||||
}
|
||||
|
||||
// Create return values
|
||||
System = null;
|
||||
|
||||
// These values require multiple parts to be active
|
||||
bool scan = false,
|
||||
enableArchives = true,
|
||||
enableDebug = false,
|
||||
hideDriveLetters = false;
|
||||
|
||||
// Create state values
|
||||
string? result;
|
||||
|
||||
root:
|
||||
Console.Clear();
|
||||
Console.WriteLine("MPF.Check Interactive Mode - Main Menu");
|
||||
Console.WriteLine("-------------------------");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"1) Set system (Currently '{System}')");
|
||||
Console.WriteLine($"2) Set dumping program (Currently '{Options.InternalProgram}')");
|
||||
Console.WriteLine($"3) Set seed path (Currently '{Seed}')");
|
||||
Console.WriteLine($"4) Add placeholders (Currently '{Options.AddPlaceholders}')");
|
||||
Console.WriteLine($"5) Create IRD (Currently '{Options.CreateIRDAfterDumping}')");
|
||||
Console.WriteLine($"6) Attempt Redump matches (Currently '{Options.RetrieveMatchInformation}')");
|
||||
Console.WriteLine($"7) Redump credentials (Currently '{Options.RedumpUsername}')");
|
||||
Console.WriteLine($"8) Pull all information (Currently '{Options.PullAllInformation}')");
|
||||
Console.WriteLine($"9) Set device path (Currently '{DevicePath}')");
|
||||
Console.WriteLine($"A) Scan for protection (Currently '{scan}')");
|
||||
Console.WriteLine($"B) Scan archives for protection (Currently '{enableArchives}')");
|
||||
Console.WriteLine($"C) Debug protection scan output (Currently '{enableDebug}')");
|
||||
Console.WriteLine($"D) Hide drive letters in protection output (Currently '{hideDriveLetters}')");
|
||||
Console.WriteLine($"E) Hide filename suffix (Currently '{Options.AddFilenameSuffix}')");
|
||||
Console.WriteLine($"F) Output submission JSON (Currently '{Options.OutputSubmissionJSON}')");
|
||||
Console.WriteLine($"G) Include JSON artifacts (Currently '{Options.IncludeArtifacts}')");
|
||||
Console.WriteLine($"H) Compress logs (Currently '{Options.CompressLogFiles}')");
|
||||
Console.WriteLine($"I) Log compression (Currently '{Options.LogCompression.LongName()}')");
|
||||
Console.WriteLine($"J) Delete unnecessary files (Currently '{Options.DeleteUnnecessaryFiles}')");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Q) Exit the program");
|
||||
Console.WriteLine($"X) Start checking");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
switch (result)
|
||||
{
|
||||
case "1":
|
||||
goto system;
|
||||
case "2":
|
||||
goto dumpingProgram;
|
||||
case "3":
|
||||
goto seedPath;
|
||||
case "4":
|
||||
Options.AddPlaceholders = !Options.AddPlaceholders;
|
||||
goto root;
|
||||
case "5":
|
||||
Options.CreateIRDAfterDumping = !Options.CreateIRDAfterDumping;
|
||||
goto root;
|
||||
case "6":
|
||||
Options.RetrieveMatchInformation = !Options.RetrieveMatchInformation;
|
||||
goto root;
|
||||
case "7":
|
||||
goto redumpCredentials;
|
||||
case "8":
|
||||
Options.PullAllInformation = !Options.PullAllInformation;
|
||||
goto root;
|
||||
case "9":
|
||||
goto devicePath;
|
||||
case "a":
|
||||
case "A":
|
||||
scan = !scan;
|
||||
goto root;
|
||||
case "b":
|
||||
case "B":
|
||||
enableArchives = !enableArchives;
|
||||
goto root;
|
||||
case "c":
|
||||
case "C":
|
||||
enableDebug = !enableDebug;
|
||||
goto root;
|
||||
case "d":
|
||||
case "D":
|
||||
hideDriveLetters = !hideDriveLetters;
|
||||
goto root;
|
||||
case "e":
|
||||
case "E":
|
||||
Options.AddFilenameSuffix = !Options.AddFilenameSuffix;
|
||||
goto root;
|
||||
case "f":
|
||||
case "F":
|
||||
Options.OutputSubmissionJSON = !Options.OutputSubmissionJSON;
|
||||
goto root;
|
||||
case "g":
|
||||
case "G":
|
||||
Options.IncludeArtifacts = !Options.IncludeArtifacts;
|
||||
goto root;
|
||||
case "h":
|
||||
case "H":
|
||||
Options.CompressLogFiles = !Options.CompressLogFiles;
|
||||
goto root;
|
||||
case "i":
|
||||
case "I":
|
||||
goto logCompression;
|
||||
case "j":
|
||||
case "J":
|
||||
Options.DeleteUnnecessaryFiles = !Options.DeleteUnnecessaryFiles;
|
||||
goto root;
|
||||
|
||||
case "q":
|
||||
case "Q":
|
||||
Environment.Exit(0);
|
||||
break;
|
||||
case "x":
|
||||
case "X":
|
||||
Console.Clear();
|
||||
goto exit;
|
||||
case "z":
|
||||
case "Z":
|
||||
Console.WriteLine("It is pitch black. You are likely to be eaten by a grue.");
|
||||
Console.Write("> ");
|
||||
Console.ReadLine();
|
||||
goto root;
|
||||
default:
|
||||
Console.WriteLine($"Invalid selection: {result}");
|
||||
Console.ReadLine();
|
||||
goto root;
|
||||
}
|
||||
|
||||
system:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("For possible inputs, use the List Systems commandline option");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the system and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
System = result.ToRedumpSystem();
|
||||
goto root;
|
||||
|
||||
dumpingProgram:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Options:");
|
||||
foreach (var program in (InternalProgram[])Enum.GetValues(typeof(InternalProgram)))
|
||||
{
|
||||
// Skip the placeholder values
|
||||
if (program == InternalProgram.NONE)
|
||||
continue;
|
||||
|
||||
Console.WriteLine($"{program.ToString().ToLowerInvariant(),-15} => {program.LongName()}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the dumping program and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
Options.InternalProgram = result.ToInternalProgram();
|
||||
goto root;
|
||||
|
||||
seedPath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the seed path and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
Seed = Builder.CreateFromFile(result);
|
||||
goto root;
|
||||
|
||||
redumpCredentials:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Enter your Redump username and press Enter:");
|
||||
Console.Write("> ");
|
||||
Options.RedumpUsername = Console.ReadLine();
|
||||
|
||||
Console.WriteLine("Enter your Redump password (hidden) and press Enter:");
|
||||
Console.Write("> ");
|
||||
Options.RedumpPassword = string.Empty;
|
||||
while (true)
|
||||
{
|
||||
var key = Console.ReadKey(true);
|
||||
if (key.Key == ConsoleKey.Enter)
|
||||
break;
|
||||
|
||||
Options.RedumpPassword += key.KeyChar;
|
||||
}
|
||||
|
||||
goto root;
|
||||
|
||||
devicePath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the device path and press Enter:");
|
||||
Console.Write("> ");
|
||||
DevicePath = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
logCompression:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Options:");
|
||||
foreach (var compressionType in (LogCompression[])Enum.GetValues(typeof(LogCompression)))
|
||||
{
|
||||
Console.WriteLine($"{compressionType.ToString().ToLowerInvariant(),-15} => {compressionType.LongName()}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the log compression type and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
Options.LogCompression = result.ToLogCompression();
|
||||
goto root;
|
||||
|
||||
exit:
|
||||
// Now deal with the complex options
|
||||
Options.ScanForProtection = scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.ScanArchivesForProtection = enableArchives && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.IncludeDebugProtectionInformation = enableDebug && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.HideDriveLetters = hideDriveLetters && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => Inputs.Count > 0;
|
||||
}
|
||||
}
|
||||
272
MPF.Check/Features/MainFeature.cs
Normal file
272
MPF.Check/Features/MainFeature.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
using System;
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using LogCompression = MPF.Processors.LogCompression;
|
||||
|
||||
namespace MPF.Check.Features
|
||||
{
|
||||
internal sealed class MainFeature : BaseFeature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "main";
|
||||
|
||||
/// <remarks>Flags are unused</remarks>
|
||||
private static readonly string[] _flags = [];
|
||||
|
||||
/// <remarks>Description is unused</remarks>
|
||||
private const string _description = "";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inputs
|
||||
|
||||
private const string _createIrdName = "create-ird";
|
||||
internal readonly FlagInput CreateIrdInput = new(_createIrdName, "--create-ird", "Create IRD from output files (PS3 only)");
|
||||
|
||||
private const string _deleteName = "delete";
|
||||
internal readonly FlagInput DeleteInput = new(_deleteName, ["-d", "--delete"], "Enable unnecessary file deletion");
|
||||
|
||||
private const string _disableArchivesName = "disable-archives";
|
||||
internal readonly FlagInput DisableArchivesInput = new(_disableArchivesName, "--disable-archives", "Disable scanning archives (requires --scan)");
|
||||
|
||||
private const string _enableDebugName = "enable-debug";
|
||||
internal readonly FlagInput EnableDebugInput = new(_enableDebugName, "--enable-debug", "Enable debug protection information (requires --scan)");
|
||||
|
||||
private const string _hideDriveLettersName = "hide-drive-letters";
|
||||
internal readonly FlagInput HideDriveLettersInput = new(_hideDriveLettersName, "--hide-drive-letters", "Hide drive letters from scan output (requires --scan)");
|
||||
|
||||
private const string _includeArtifactsName = "include-artifacts";
|
||||
internal readonly FlagInput IncludeArtifactsInput = new(_includeArtifactsName, "--include-artifacts", "Include artifacts in JSON (requires --json)");
|
||||
|
||||
private const string _jsonName = "json";
|
||||
internal readonly FlagInput JsonInput = new(_jsonName, ["-j", "--json"], "Enable submission JSON output");
|
||||
|
||||
private const string _loadSeedName = "load-seed";
|
||||
internal readonly StringInput LoadSeedInput = new(_loadSeedName, "--load-seed", "Load a seed submission JSON for user information");
|
||||
|
||||
private const string _logCompressionName = "log-compression";
|
||||
internal readonly StringInput LogCompressionInput = new(_logCompressionName, "--log-compression", "Set the log compression type (requires compression enabled)");
|
||||
|
||||
private const string _noPlaceholdersName = "no-placeholders";
|
||||
internal readonly FlagInput NoPlaceholdersInput = new(_noPlaceholdersName, "--no-placeholders", "Disable placeholder values in submission info");
|
||||
|
||||
private const string _noRetrieveName = "no-retrieve";
|
||||
internal readonly FlagInput NoRetrieveInput = new(_noRetrieveName, "--no-retrieve", "Disable retrieving match information from Redump");
|
||||
|
||||
private const string _passwordName = "password";
|
||||
internal readonly StringInput PasswordInput = new(_passwordName, ["-P", "--password"], "Redump password (incompatible with --no-retrieve)");
|
||||
|
||||
private const string _pathName = "path";
|
||||
internal readonly StringInput PathInput = new(_pathName, ["-p", "--path"], "Physical drive path for additional checks");
|
||||
|
||||
private const string _pullAllName = "pull-all";
|
||||
internal readonly FlagInput PullAllInput = new(_pullAllName, "--pull-all", "Pull all information from Redump (requires --username and --password)");
|
||||
|
||||
private const string _scanName = "scan";
|
||||
internal readonly FlagInput ScanInput = new(_scanName, ["-s", "--scan"], "Enable copy protection scan (requires --path)");
|
||||
|
||||
private const string _suffixName = "suffix";
|
||||
internal readonly FlagInput SuffixInput = new(_suffixName, ["-x", "--suffix"], "Enable adding filename suffix");
|
||||
|
||||
private const string _useName = "use";
|
||||
internal readonly StringInput UseInput = new(_useName, ["-u", "--use"], "Override configured dumping program name");
|
||||
|
||||
private const string _usernameName = "username";
|
||||
internal readonly StringInput UsernameInput = new(_usernameName, ["-U", "--username"], "Redump username (incompatible with --no-retrieve)");
|
||||
|
||||
private const string _zipName = "zip";
|
||||
internal readonly FlagInput ZipInput = new(_zipName, ["-z", "--zip"], "Enable log file compression");
|
||||
|
||||
#endregion
|
||||
|
||||
public MainFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
Add(UseInput);
|
||||
Add(LoadSeedInput);
|
||||
Add(NoPlaceholdersInput);
|
||||
Add(CreateIrdInput);
|
||||
Add(NoRetrieveInput);
|
||||
// TODO: Figure out how to work with the credentials input
|
||||
Add(PullAllInput);
|
||||
Add(PathInput);
|
||||
Add(ScanInput);
|
||||
Add(DisableArchivesInput);
|
||||
Add(EnableDebugInput);
|
||||
Add(HideDriveLettersInput);
|
||||
Add(SuffixInput);
|
||||
Add(JsonInput);
|
||||
Add(IncludeArtifactsInput);
|
||||
Add(ZipInput);
|
||||
Add(LogCompressionInput);
|
||||
Add(DeleteInput);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessArgs(string[] args, int index)
|
||||
{
|
||||
// These values require multiple parts to be active
|
||||
bool scan = false,
|
||||
enableArchives = true,
|
||||
enableDebug = false,
|
||||
hideDriveLetters = false;
|
||||
|
||||
// If we have no arguments, just return
|
||||
if (args is null || args.Length == 0)
|
||||
return true;
|
||||
|
||||
// Read the options from config, if possible
|
||||
Options = OptionsLoader.LoadFromConfig();
|
||||
if (Options.FirstRun)
|
||||
{
|
||||
Options = new Options()
|
||||
{
|
||||
// Internal Program
|
||||
InternalProgram = InternalProgram.NONE,
|
||||
|
||||
// Extra Dumping Options
|
||||
ScanForProtection = false,
|
||||
AddPlaceholders = true,
|
||||
PullAllInformation = false,
|
||||
AddFilenameSuffix = false,
|
||||
OutputSubmissionJSON = false,
|
||||
IncludeArtifacts = false,
|
||||
CompressLogFiles = false,
|
||||
LogCompression = LogCompression.DeflateMaximum,
|
||||
DeleteUnnecessaryFiles = false,
|
||||
CreateIRDAfterDumping = false,
|
||||
|
||||
// Protection Scanning Options
|
||||
ScanArchivesForProtection = true,
|
||||
IncludeDebugProtectionInformation = false,
|
||||
HideDriveLetters = false,
|
||||
|
||||
// Redump Login Information
|
||||
RetrieveMatchInformation = true,
|
||||
RedumpUsername = null,
|
||||
RedumpPassword = null,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Options will be loaded from found configuration file!");
|
||||
}
|
||||
|
||||
// The first argument is the system type
|
||||
System = args[0].Trim('"').ToRedumpSystem();
|
||||
|
||||
// Loop through the arguments and parse out values
|
||||
for (index = 1; index < args.Length; index++)
|
||||
{
|
||||
// Use specific program
|
||||
if (UseInput.ProcessInput(args, ref index))
|
||||
Options.InternalProgram = UseInput.Value.ToInternalProgram();
|
||||
|
||||
// Include seed info file
|
||||
else if (LoadSeedInput.ProcessInput(args, ref index))
|
||||
Seed = Builder.CreateFromFile(LoadSeedInput.Value);
|
||||
|
||||
// Disable placeholder values in submission info
|
||||
else if (NoPlaceholdersInput.ProcessInput(args, ref index))
|
||||
Options.AddPlaceholders = !Options.AddPlaceholders;
|
||||
|
||||
// Create IRD from output files (PS3 only)
|
||||
else if (CreateIrdInput.ProcessInput(args, ref index))
|
||||
Options.CreateIRDAfterDumping = !Options.CreateIRDAfterDumping;
|
||||
|
||||
// Set the log compression type (requires compression enabled)
|
||||
else if (LogCompressionInput.ProcessInput(args, ref index))
|
||||
Options.LogCompression = LogCompressionInput.Value.ToLogCompression();
|
||||
|
||||
// Retrieve Redump match information
|
||||
else if (NoRetrieveInput.ProcessInput(args, ref index))
|
||||
Options.RetrieveMatchInformation = !Options.RetrieveMatchInformation;
|
||||
|
||||
// Redump login
|
||||
else if (args[index].StartsWith("-c=") || args[index].StartsWith("--credentials="))
|
||||
{
|
||||
string[] credentials = args[index].Split('=')[1].Split(';');
|
||||
Options.RedumpUsername = credentials[0];
|
||||
Options.RedumpPassword = credentials[1];
|
||||
}
|
||||
else if (args[index] == "-c" || args[index] == "--credentials")
|
||||
{
|
||||
Options.RedumpUsername = args[index + 1];
|
||||
Options.RedumpPassword = args[index + 2];
|
||||
index += 2;
|
||||
}
|
||||
|
||||
// Redump username
|
||||
else if (UsernameInput.ProcessInput(args, ref index))
|
||||
Options.RedumpUsername = UsernameInput.Value;
|
||||
|
||||
// Redump password
|
||||
else if (PasswordInput.ProcessInput(args, ref index))
|
||||
Options.RedumpPassword = PasswordInput.Value;
|
||||
|
||||
// Pull all information (requires Redump login)
|
||||
else if (PullAllInput.ProcessInput(args, ref index))
|
||||
Options.PullAllInformation = !Options.PullAllInformation;
|
||||
|
||||
// Use a device path for physical checks
|
||||
else if (PathInput.ProcessInput(args, ref index))
|
||||
DevicePath = PathInput.Value;
|
||||
|
||||
// Scan for protection (requires device path)
|
||||
else if (ScanInput.ProcessInput(args, ref index))
|
||||
scan = true;
|
||||
|
||||
// Disable scanning archives (requires --scan)
|
||||
else if (ScanInput.ProcessInput(args, ref index))
|
||||
enableArchives = false;
|
||||
|
||||
// Enable debug protection information (requires --scan)
|
||||
else if (EnableDebugInput.ProcessInput(args, ref index))
|
||||
enableDebug = true;
|
||||
|
||||
// Hide drive letters from scan output (requires --scan)
|
||||
else if (HideDriveLettersInput.ProcessInput(args, ref index))
|
||||
hideDriveLetters = true;
|
||||
|
||||
// Add filename suffix
|
||||
else if (SuffixInput.ProcessInput(args, ref index))
|
||||
Options.AddFilenameSuffix = !Options.AddFilenameSuffix;
|
||||
|
||||
// Output submission JSON
|
||||
else if (JsonInput.ProcessInput(args, ref index))
|
||||
Options.OutputSubmissionJSON = !Options.OutputSubmissionJSON;
|
||||
|
||||
// Include JSON artifacts
|
||||
else if (IncludeArtifactsInput.ProcessInput(args, ref index))
|
||||
Options.IncludeArtifacts = !Options.IncludeArtifacts;
|
||||
|
||||
// Compress log and extraneous files
|
||||
else if (ZipInput.ProcessInput(args, ref index))
|
||||
Options.CompressLogFiles = !Options.CompressLogFiles;
|
||||
|
||||
// Delete unnecessary files
|
||||
else if (DeleteInput.ProcessInput(args, ref index))
|
||||
Options.DeleteUnnecessaryFiles = !Options.DeleteUnnecessaryFiles;
|
||||
|
||||
// Default, add to inputs
|
||||
else
|
||||
Inputs.Add(args[index]);
|
||||
}
|
||||
|
||||
// Now deal with the complex options
|
||||
Options.ScanForProtection = scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.ScanArchivesForProtection = enableArchives && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.IncludeDebugProtectionInformation = enableDebug && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.HideDriveLetters = hideDriveLetters && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => Inputs.Count > 0;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<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>
|
||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||
@@ -12,7 +12,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.3.2</VersionPrefix>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Title>MPF Check</Title>
|
||||
@@ -31,11 +31,11 @@
|
||||
<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>
|
||||
@@ -43,7 +43,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.7" />
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,13 +1,12 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
#if NET40
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Web;
|
||||
using MPF.Check.Features;
|
||||
using MPF.Frontend.Features;
|
||||
using SabreTools.CommandLine;
|
||||
using SabreTools.CommandLine.Features;
|
||||
|
||||
namespace MPF.Check
|
||||
{
|
||||
@@ -15,555 +14,132 @@ namespace MPF.Check
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Create a default options object
|
||||
var options = new Options()
|
||||
// Create the command set
|
||||
var mainFeature = new MainFeature();
|
||||
var commandSet = CreateCommands(mainFeature);
|
||||
|
||||
// If we have no args, show the help and quit
|
||||
if (args is null || args.Length == 0)
|
||||
{
|
||||
// Internal Program
|
||||
InternalProgram = InternalProgram.NONE,
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Extra Dumping Options
|
||||
ScanForProtection = false,
|
||||
AddPlaceholders = true,
|
||||
PullAllInformation = false,
|
||||
AddFilenameSuffix = false,
|
||||
OutputSubmissionJSON = false,
|
||||
IncludeArtifacts = false,
|
||||
CompressLogFiles = false,
|
||||
DeleteUnnecessaryFiles = false,
|
||||
CreateIRDAfterDumping = false,
|
||||
|
||||
// Protection Scanning Options
|
||||
ScanArchivesForProtection = true,
|
||||
IncludeDebugProtectionInformation = false,
|
||||
HideDriveLetters = false,
|
||||
|
||||
// Redump Login Information
|
||||
RetrieveMatchInformation = true,
|
||||
RedumpUsername = null,
|
||||
RedumpPassword = null,
|
||||
};
|
||||
// Get the first argument as a feature flag
|
||||
string featureName = args[0];
|
||||
|
||||
// Try processing the standalone arguments
|
||||
bool? standaloneProcessed = OptionsLoader.ProcessStandaloneArguments(args);
|
||||
if (standaloneProcessed != false)
|
||||
var topLevel = commandSet.GetTopLevel(featureName);
|
||||
switch (topLevel)
|
||||
{
|
||||
if (standaloneProcessed == null)
|
||||
DisplayHelp();
|
||||
return;
|
||||
}
|
||||
// Standalone Options
|
||||
case Help: BaseFeature.DisplayHelp(); return;
|
||||
case VersionFeature version: version.Execute(); return;
|
||||
case ListCodesFeature lc: lc.Execute(); return;
|
||||
case ListConfigFeature lc: lc.Execute(); return;
|
||||
case ListMediaTypesFeature lm: lm.Execute(); return;
|
||||
case ListProgramsFeature lp: lp.Execute(); return;
|
||||
case ListSystemsFeature ls: ls.Execute(); return;
|
||||
|
||||
// Setup common outputs
|
||||
CommandOptions opts;
|
||||
MediaType mediaType;
|
||||
RedumpSystem? knownSystem;
|
||||
int startIndex;
|
||||
// Interactive Mode
|
||||
case InteractiveFeature interactive:
|
||||
if (!interactive.ProcessArgs(args, 0))
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Use interactive mode
|
||||
if (args.Length > 0 && (args[0] == "-i" || args[0] == "--interactive"))
|
||||
{
|
||||
startIndex = 1;
|
||||
opts = InteractiveMode(options, out mediaType, out knownSystem);
|
||||
}
|
||||
if (!interactive.VerifyInputs())
|
||||
{
|
||||
Console.Error.WriteLine("At least one input is required");
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Use normal commandline parameters
|
||||
else
|
||||
{
|
||||
// Try processing the common arguments
|
||||
bool success = OptionsLoader.ProcessCommonArguments(args, out mediaType, out knownSystem, out var error);
|
||||
if (!success)
|
||||
{
|
||||
DisplayHelp(error);
|
||||
return;
|
||||
}
|
||||
if (!interactive.Execute())
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop through and process options
|
||||
startIndex = 2;
|
||||
opts = LoadFromArguments(args, options, ref startIndex);
|
||||
}
|
||||
|
||||
if (options.InternalProgram == InternalProgram.NONE)
|
||||
{
|
||||
DisplayHelp("A program name needs to be provided");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate the supplied credentials
|
||||
if (options.RetrieveMatchInformation
|
||||
&& !string.IsNullOrEmpty(options.RedumpUsername)
|
||||
&& !string.IsNullOrEmpty(options.RedumpPassword))
|
||||
{
|
||||
bool? validated = RedumpClient.ValidateCredentials(options.RedumpUsername!, options.RedumpPassword!).GetAwaiter().GetResult();
|
||||
string message = validated switch
|
||||
{
|
||||
true => "Redump username and password accepted!",
|
||||
false => "Redump username and password denied!",
|
||||
null => "An error occurred validating your credentials!",
|
||||
};
|
||||
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
|
||||
// Loop through all the rest of the args
|
||||
for (int i = startIndex; i < args.Length; i++)
|
||||
{
|
||||
// Check for a file
|
||||
if (!File.Exists(args[i].Trim('"')))
|
||||
{
|
||||
DisplayHelp($"{args[i].Trim('"')} does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the full file path
|
||||
string filepath = Path.GetFullPath(args[i].Trim('"'));
|
||||
|
||||
// Now populate an environment
|
||||
Drive? drive = null;
|
||||
if (!string.IsNullOrEmpty(opts.DevicePath))
|
||||
drive = Drive.Create(null, opts.DevicePath!);
|
||||
|
||||
var env = new DumpEnvironment(options, filepath, drive, knownSystem, mediaType, internalProgram: null, parameters: null);
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
var result = env.VerifyAndSaveDumpOutput(seedInfo: opts.Seed)
|
||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display help for MPF.Check
|
||||
/// </summary>
|
||||
/// <param name="error">Error string to prefix the help text with</param>
|
||||
private static void DisplayHelp(string? error = null)
|
||||
{
|
||||
if (error != null)
|
||||
Console.WriteLine(error);
|
||||
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine("MPF.Check <mediatype> <system> [options] </path/to/output.cue/iso> ...");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Standalone Options:");
|
||||
Console.WriteLine("-h, -? Show this help text");
|
||||
Console.WriteLine("-lc, --listcodes List supported comment/content site codes");
|
||||
Console.WriteLine("-lm, --listmedia List supported media types");
|
||||
Console.WriteLine("-ls, --listsystems List supported system types");
|
||||
Console.WriteLine("-lp, --listprograms List supported dumping program outputs");
|
||||
Console.WriteLine("-i, --interactive Enable interactive mode");
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("Check Options:");
|
||||
Console.WriteLine("-u, --use <program> Dumping program output type [REQUIRED]");
|
||||
Console.WriteLine(" --load-seed <path> Load a seed submission JSON for user information");
|
||||
Console.WriteLine(" --no-placeholders Disable placeholder values in submission info");
|
||||
Console.WriteLine(" --create-ird Create IRD from output files (PS3 only)");
|
||||
Console.WriteLine(" --no-retrieve Disable retrieving match information from Redump");
|
||||
Console.WriteLine("-c, --credentials <user> <pw> Redump username and password (incompatible with --no-retrieve)");
|
||||
Console.WriteLine(" --pull-all Pull all information from Redump (requires --credentials)");
|
||||
Console.WriteLine("-p, --path <drivepath> Physical drive path for additional checks");
|
||||
Console.WriteLine("-s, --scan Enable copy protection scan (requires --path)");
|
||||
Console.WriteLine(" --disable-archives Disable scanning archives (requires --scan)");
|
||||
Console.WriteLine(" --enable-debug Enable debug protection information (requires --scan)");
|
||||
Console.WriteLine(" --hide-drive-letters Hide drive letters from scan output (requires --scan)");
|
||||
Console.WriteLine("-x, --suffix Enable adding filename suffix");
|
||||
Console.WriteLine("-j, --json Enable submission JSON output");
|
||||
Console.WriteLine(" --include-artifacts Include artifacts in JSON (requires --json)");
|
||||
Console.WriteLine("-z, --zip Enable log file compression");
|
||||
Console.WriteLine("-d, --delete Enable unnecessary file deletion");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("WARNING: Check will overwrite both any existing submission information files as well");
|
||||
Console.WriteLine("as any log archives. Please make backups of those if you need to before running Check.");
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable interactive mode for entering information
|
||||
/// </summary>
|
||||
private static CommandOptions InteractiveMode(Options options, out MediaType mediaType, out RedumpSystem? system)
|
||||
{
|
||||
// Create return values
|
||||
var opts = new CommandOptions();
|
||||
mediaType = MediaType.NONE;
|
||||
system = null;
|
||||
|
||||
// These values require multiple parts to be active
|
||||
bool scan = false,
|
||||
enableArchives = true,
|
||||
enableDebug = false,
|
||||
hideDriveLetters = false;
|
||||
|
||||
// Create state values
|
||||
string? result = string.Empty;
|
||||
|
||||
root:
|
||||
Console.Clear();
|
||||
Console.WriteLine("MPF.Check Interactive Mode - Main Menu");
|
||||
Console.WriteLine("-------------------------");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"1) Set media type (Currently '{mediaType}')");
|
||||
Console.WriteLine($"2) Set system (Currently '{system}')");
|
||||
Console.WriteLine($"3) Set dumping program (Currently '{options.InternalProgram}')");
|
||||
Console.WriteLine($"4) Set seed path (Currently '{opts.Seed}')");
|
||||
Console.WriteLine($"5) Add placeholders (Currently '{options.AddPlaceholders}')");
|
||||
Console.WriteLine($"6) Create IRD (Currently '{options.CreateIRDAfterDumping}')");
|
||||
Console.WriteLine($"7) Attempt Redump matches (Currently '{options.RetrieveMatchInformation}')");
|
||||
Console.WriteLine($"8) Redump credentials (Currently '{options.RedumpUsername}')");
|
||||
Console.WriteLine($"9) Pull all information (Currently '{options.PullAllInformation}')");
|
||||
Console.WriteLine($"A) Set device path (Currently '{opts.DevicePath}')");
|
||||
Console.WriteLine($"B) Scan for protection (Currently '{scan}')");
|
||||
Console.WriteLine($"C) Scan archives for protection (Currently '{enableArchives}')");
|
||||
Console.WriteLine($"D) Debug protection scan output (Currently '{enableDebug}')");
|
||||
Console.WriteLine($"E) Hide drive letters in protection output (Currently '{hideDriveLetters}')");
|
||||
Console.WriteLine($"F) Hide filename suffix (Currently '{options.AddFilenameSuffix}')");
|
||||
Console.WriteLine($"G) Output submission JSON (Currently '{options.OutputSubmissionJSON}')");
|
||||
Console.WriteLine($"H) Include JSON artifacts (Currently '{options.IncludeArtifacts}')");
|
||||
Console.WriteLine($"I) Compress logs (Currently '{options.CompressLogFiles}')");
|
||||
Console.WriteLine($"J) Delete unnecessary files (Currently '{options.DeleteUnnecessaryFiles}')");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Q) Exit the program");
|
||||
Console.WriteLine($"X) Start checking");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
switch (result)
|
||||
{
|
||||
case "1":
|
||||
goto mediaType;
|
||||
case "2":
|
||||
goto system;
|
||||
case "3":
|
||||
goto dumpingProgram;
|
||||
case "4":
|
||||
goto seedPath;
|
||||
case "5":
|
||||
options.AddPlaceholders = !options.AddPlaceholders;
|
||||
goto root;
|
||||
case "6":
|
||||
options.CreateIRDAfterDumping = !options.CreateIRDAfterDumping;
|
||||
goto root;
|
||||
case "7":
|
||||
options.RetrieveMatchInformation = !options.RetrieveMatchInformation;
|
||||
goto root;
|
||||
case "8":
|
||||
goto redumpCredentials;
|
||||
case "9":
|
||||
options.PullAllInformation = !options.PullAllInformation;
|
||||
goto root;
|
||||
case "a":
|
||||
case "A":
|
||||
goto devicePath;
|
||||
case "b":
|
||||
case "B":
|
||||
scan = !scan;
|
||||
goto root;
|
||||
case "c":
|
||||
case "C":
|
||||
enableArchives = !enableArchives;
|
||||
goto root;
|
||||
case "d":
|
||||
case "D":
|
||||
enableDebug = !enableDebug;
|
||||
goto root;
|
||||
case "e":
|
||||
case "E":
|
||||
hideDriveLetters = !hideDriveLetters;
|
||||
goto root;
|
||||
case "f":
|
||||
case "F":
|
||||
options.AddFilenameSuffix = !options.AddFilenameSuffix;
|
||||
goto root;
|
||||
case "g":
|
||||
case "G":
|
||||
options.OutputSubmissionJSON = !options.OutputSubmissionJSON;
|
||||
goto root;
|
||||
case "h":
|
||||
case "H":
|
||||
options.IncludeArtifacts = !options.IncludeArtifacts;
|
||||
goto root;
|
||||
case "i":
|
||||
case "I":
|
||||
options.CompressLogFiles = !options.CompressLogFiles;
|
||||
goto root;
|
||||
case "j":
|
||||
case "J":
|
||||
options.DeleteUnnecessaryFiles = !options.DeleteUnnecessaryFiles;
|
||||
goto root;
|
||||
|
||||
case "q":
|
||||
case "Q":
|
||||
Environment.Exit(0);
|
||||
break;
|
||||
case "x":
|
||||
case "X":
|
||||
Console.Clear();
|
||||
goto exit;
|
||||
case "z":
|
||||
case "Z":
|
||||
Console.WriteLine("It is pitch black. You are likely to be eaten by a grue.");
|
||||
Console.Write("> ");
|
||||
Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
// Default Behavior
|
||||
default:
|
||||
Console.WriteLine($"Invalid selection: {result}");
|
||||
Console.ReadLine();
|
||||
goto root;
|
||||
}
|
||||
if (!mainFeature.ProcessArgs(args, 0))
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
mediaType:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the media type and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
mediaType = OptionsLoader.ToMediaType(result);
|
||||
goto root;
|
||||
if (!mainFeature.VerifyInputs())
|
||||
{
|
||||
Console.Error.WriteLine("At least one input is required");
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
system:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the system and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
system = Extensions.ToRedumpSystem(result);
|
||||
goto root;
|
||||
if (!mainFeature.Execute())
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
dumpingProgram:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the dumping program and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
options.InternalProgram = result.ToInternalProgram();
|
||||
goto root;
|
||||
|
||||
seedPath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the seed path and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
opts.Seed = Builder.CreateFromFile(result);
|
||||
goto root;
|
||||
|
||||
redumpCredentials:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Enter your Redumper username and press Enter:");
|
||||
Console.Write("> ");
|
||||
options.RedumpUsername = Console.ReadLine();
|
||||
|
||||
Console.WriteLine("Enter your Redumper password (hidden) and press Enter:");
|
||||
Console.Write("> ");
|
||||
options.RedumpPassword = string.Empty;
|
||||
while (true)
|
||||
{
|
||||
var key = Console.ReadKey(true);
|
||||
if (key.Key == ConsoleKey.Enter)
|
||||
break;
|
||||
|
||||
options.RedumpPassword += key.KeyChar;
|
||||
}
|
||||
|
||||
goto root;
|
||||
|
||||
devicePath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the device path and press Enter:");
|
||||
Console.Write("> ");
|
||||
opts.DevicePath = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
exit:
|
||||
// Now deal with the complex options
|
||||
options.ScanForProtection = scan && !string.IsNullOrEmpty(opts.DevicePath);
|
||||
options.ScanArchivesForProtection = enableArchives && scan && !string.IsNullOrEmpty(opts.DevicePath);
|
||||
options.IncludeDebugProtectionInformation = enableDebug && scan && !string.IsNullOrEmpty(opts.DevicePath);
|
||||
options.HideDriveLetters = hideDriveLetters && scan && !string.IsNullOrEmpty(opts.DevicePath);
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the current set of options from application arguments
|
||||
/// Create the command set for the program
|
||||
/// </summary>
|
||||
private static CommandOptions LoadFromArguments(string[] args, Options options, ref int startIndex)
|
||||
private static CommandSet CreateCommands(MainFeature mainFeature)
|
||||
{
|
||||
// Create return values
|
||||
var opts = new CommandOptions();
|
||||
List<string> header = [
|
||||
"MPF.CLI [standalone|system] [options] <path> ...",
|
||||
string.Empty,
|
||||
];
|
||||
|
||||
// These values require multiple parts to be active
|
||||
bool scan = false,
|
||||
enableArchives = true,
|
||||
enableDebug = false,
|
||||
hideDriveLetters = false;
|
||||
List<string> footer = [
|
||||
string.Empty,
|
||||
"WARNING: Check will overwrite both any existing submission information files as well",
|
||||
"as any log archives. Please make backups of those if you need to before running Check.",
|
||||
string.Empty,
|
||||
];
|
||||
|
||||
// If we have no arguments, just return
|
||||
if (args == null || args.Length == 0)
|
||||
{
|
||||
startIndex = 0;
|
||||
return opts;
|
||||
}
|
||||
var commandSet = new CommandSet(header, footer);
|
||||
|
||||
// If we have an invalid start index, just return
|
||||
if (startIndex < 0 || startIndex >= args.Length)
|
||||
return opts;
|
||||
// Standalone Options
|
||||
commandSet.Add(new Help());
|
||||
commandSet.Add(new VersionFeature());
|
||||
commandSet.Add(new ListCodesFeature());
|
||||
commandSet.Add(new ListConfigFeature());
|
||||
commandSet.Add(new ListMediaTypesFeature());
|
||||
commandSet.Add(new ListSystemsFeature());
|
||||
commandSet.Add(new ListProgramsFeature());
|
||||
commandSet.Add(new InteractiveFeature());
|
||||
|
||||
// Loop through the arguments and parse out values
|
||||
for (; startIndex < args.Length; startIndex++)
|
||||
{
|
||||
// Use specific program
|
||||
if (args[startIndex].StartsWith("-u=") || args[startIndex].StartsWith("--use="))
|
||||
{
|
||||
string internalProgram = args[startIndex].Split('=')[1];
|
||||
options.InternalProgram = internalProgram.ToInternalProgram();
|
||||
}
|
||||
else if (args[startIndex] == "-u" || args[startIndex] == "--use")
|
||||
{
|
||||
string internalProgram = args[startIndex + 1];
|
||||
options.InternalProgram = internalProgram.ToInternalProgram();
|
||||
startIndex++;
|
||||
}
|
||||
// Check Options
|
||||
commandSet.Add(mainFeature.UseInput);
|
||||
commandSet.Add(mainFeature.LoadSeedInput);
|
||||
commandSet.Add(mainFeature.NoPlaceholdersInput);
|
||||
commandSet.Add(mainFeature.CreateIrdInput);
|
||||
commandSet.Add(mainFeature.NoRetrieveInput);
|
||||
commandSet.Add(mainFeature.UsernameInput);
|
||||
commandSet.Add(mainFeature.PasswordInput);
|
||||
commandSet.Add(mainFeature.PullAllInput);
|
||||
commandSet.Add(mainFeature.PathInput);
|
||||
commandSet.Add(mainFeature.ScanInput);
|
||||
commandSet.Add(mainFeature.DisableArchivesInput);
|
||||
commandSet.Add(mainFeature.EnableDebugInput);
|
||||
commandSet.Add(mainFeature.HideDriveLettersInput);
|
||||
commandSet.Add(mainFeature.SuffixInput);
|
||||
commandSet.Add(mainFeature.JsonInput);
|
||||
commandSet.Add(mainFeature.IncludeArtifactsInput);
|
||||
commandSet.Add(mainFeature.ZipInput);
|
||||
commandSet.Add(mainFeature.LogCompressionInput);
|
||||
commandSet.Add(mainFeature.DeleteInput);
|
||||
|
||||
// Include seed info file
|
||||
else if (args[startIndex].StartsWith("--load-seed="))
|
||||
{
|
||||
string seedInfo = args[startIndex].Split('=')[1];
|
||||
opts.Seed = Builder.CreateFromFile(seedInfo);
|
||||
}
|
||||
else if (args[startIndex] == "--load-seed")
|
||||
{
|
||||
string seedInfo = args[startIndex + 1];
|
||||
opts.Seed = Builder.CreateFromFile(seedInfo);
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Disable placeholder values in submission info
|
||||
else if (args[startIndex].Equals("--no-placeholders"))
|
||||
{
|
||||
options.AddPlaceholders = false;
|
||||
}
|
||||
|
||||
// Create IRD from output files (PS3 only)
|
||||
else if (args[startIndex].Equals("--create-ird"))
|
||||
{
|
||||
options.CreateIRDAfterDumping = true;
|
||||
}
|
||||
|
||||
// Retrieve Redump match information
|
||||
else if (args[startIndex] == "--no-retrieve")
|
||||
{
|
||||
options.RetrieveMatchInformation = false;
|
||||
}
|
||||
|
||||
// Redump login
|
||||
else if (args[startIndex].StartsWith("-c=") || args[startIndex].StartsWith("--credentials="))
|
||||
{
|
||||
string[] credentials = args[startIndex].Split('=')[1].Split(';');
|
||||
options.RedumpUsername = credentials[0];
|
||||
options.RedumpPassword = credentials[1];
|
||||
}
|
||||
else if (args[startIndex] == "-c" || args[startIndex] == "--credentials")
|
||||
{
|
||||
options.RedumpUsername = args[startIndex + 1];
|
||||
options.RedumpPassword = args[startIndex + 2];
|
||||
startIndex += 2;
|
||||
}
|
||||
|
||||
// Pull all information (requires Redump login)
|
||||
else if (args[startIndex].Equals("--pull-all"))
|
||||
{
|
||||
options.PullAllInformation = true;
|
||||
}
|
||||
|
||||
// Use a device path for physical checks
|
||||
else if (args[startIndex].StartsWith("-p=") || args[startIndex].StartsWith("--path="))
|
||||
{
|
||||
opts.DevicePath = args[startIndex].Split('=')[1];
|
||||
}
|
||||
else if (args[startIndex] == "-p" || args[startIndex] == "--path")
|
||||
{
|
||||
opts.DevicePath = args[startIndex + 1];
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Scan for protection (requires device path)
|
||||
else if (args[startIndex].Equals("-s") || args[startIndex].Equals("--scan"))
|
||||
{
|
||||
scan = true;
|
||||
}
|
||||
|
||||
// Disable scanning archives (requires --scan)
|
||||
else if (args[startIndex].Equals("--disable-archives"))
|
||||
{
|
||||
enableArchives = false;
|
||||
}
|
||||
|
||||
// Enable debug protection information (requires --scan)
|
||||
else if (args[startIndex].Equals("--enable-debug"))
|
||||
{
|
||||
enableDebug = true;
|
||||
}
|
||||
|
||||
// Hide drive letters from scan output (requires --scan)
|
||||
else if (args[startIndex].Equals("--hide-drive-letters"))
|
||||
{
|
||||
hideDriveLetters = true;
|
||||
}
|
||||
|
||||
// Add filename suffix
|
||||
else if (args[startIndex].Equals("-x") || args[startIndex].Equals("--suffix"))
|
||||
{
|
||||
options.AddFilenameSuffix = true;
|
||||
}
|
||||
|
||||
// Output submission JSON
|
||||
else if (args[startIndex].Equals("-j") || args[startIndex].Equals("--json"))
|
||||
{
|
||||
options.OutputSubmissionJSON = true;
|
||||
}
|
||||
|
||||
// Include JSON artifacts
|
||||
else if (args[startIndex].Equals("--include-artifacts"))
|
||||
{
|
||||
options.IncludeArtifacts = true;
|
||||
}
|
||||
|
||||
// Compress log and extraneous files
|
||||
else if (args[startIndex].Equals("-z") || args[startIndex].Equals("--zip"))
|
||||
{
|
||||
options.CompressLogFiles = true;
|
||||
}
|
||||
|
||||
// Delete unnecessary files
|
||||
else if (args[startIndex].Equals("-d") || args[startIndex].Equals("--delete"))
|
||||
{
|
||||
options.DeleteUnnecessaryFiles = true;
|
||||
}
|
||||
|
||||
// Default, we fall out
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now deal with the complex options
|
||||
options.ScanForProtection = scan && !string.IsNullOrEmpty(opts.DevicePath);
|
||||
options.ScanArchivesForProtection = enableArchives && scan && !string.IsNullOrEmpty(opts.DevicePath);
|
||||
options.IncludeDebugProtectionInformation = enableDebug && scan && !string.IsNullOrEmpty(opts.DevicePath);
|
||||
options.HideDriveLetters = hideDriveLetters && scan && !string.IsNullOrEmpty(opts.DevicePath);
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents commandline options
|
||||
/// </summary>
|
||||
private class CommandOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Seed submission info from an input file
|
||||
/// </summary>
|
||||
public SubmissionInfo? Seed { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Path to the device to scan
|
||||
/// </summary>
|
||||
public string? DevicePath { get; set; } = null;
|
||||
return commandSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#region Default Values
|
||||
|
||||
private static Dictionary<string, string?> AllOptions = new()
|
||||
private static readonly Dictionary<string, string?> AllOptions = new()
|
||||
{
|
||||
[SettingConstants.EnableDebug] = "true",
|
||||
[SettingConstants.EnableVerbose] = "true",
|
||||
@@ -40,15 +40,15 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, null, "filename.bin", null, null)]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.DVD, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.SegaDreamcast, MediaType.GDROM, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.SegaDreamcast, MediaType.GDROM, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.HDDVDVideo, MediaType.HDDVD, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.BDVideo, MediaType.BluRay, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoGameCube, MediaType.NintendoGameCubeGameDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoWii, MediaType.NintendoWiiOpticalDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoWiiU, MediaType.NintendoWiiUOpticalDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.FloppyDisk, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoGameCube, MediaType.NintendoGameCubeGameDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoWii, MediaType.NintendoWiiOpticalDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.NintendoWiiU, MediaType.NintendoWiiUOpticalDisc, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.FloppyDisk, "/dev/sr0", "filename.bin", 2, "--debug True --verbose True media dump --force True --private True --store-encrypted True --title-keys False --trim True --speed 2 --retry-passes 1000 /dev/sr0 \"filename.bin\"")]
|
||||
public void DefaultValueTest(RedumpSystem? system,
|
||||
MediaType? type,
|
||||
string? drivePath,
|
||||
@@ -514,4 +514,4 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,4 +461,4 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#region Default Values
|
||||
|
||||
private static Dictionary<string, string?> AllOptions = new()
|
||||
private static readonly Dictionary<string, string?> AllOptions = new()
|
||||
{
|
||||
[SettingConstants.DVDRereadCount] = "1000",
|
||||
[SettingConstants.MultiSectorRead] = "true",
|
||||
@@ -102,6 +102,21 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#endregion
|
||||
|
||||
#region AuthPS3
|
||||
|
||||
[Theory]
|
||||
[InlineData("authps3 f")]
|
||||
public void AuthPS3Test(string parameters)
|
||||
{
|
||||
string? expected = "authps3 f";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BluRay
|
||||
|
||||
[Theory]
|
||||
|
||||
68
MPF.ExecutionContexts.Test/DreamdumpTests.cs
Normal file
68
MPF.ExecutionContexts.Test/DreamdumpTests.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System.Collections.Generic;
|
||||
using MPF.ExecutionContexts.Dreamdump;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.ExecutionContexts.Test
|
||||
{
|
||||
public class DreamdumpTests
|
||||
{
|
||||
#region Default Values
|
||||
|
||||
private static readonly Dictionary<string, string?> AllOptions = new()
|
||||
{
|
||||
[SettingConstants.RereadCount] = "1000",
|
||||
[SettingConstants.SectorOrder] = "DATA_C2_SUB",
|
||||
};
|
||||
|
||||
// None of these scenarios are actually supported as all are treated like GD-ROM
|
||||
[Theory]
|
||||
[InlineData(null, null, null, "filename.bin", null, "--retries=20 --image-name=\"filename\" --sector-order=DATA_C2_SUB")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.CDROM, "/dev/sr0", "path/filename.bin", 2, "--retries=20 --image-name=\"filename\" --image-path=\"path\" --speed=2 --sector-order=DATA_C2_SUB --drive=/dev/sr0")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.DVD, "/dev/sr0", "path/filename.bin", 2, "--retries=20 --image-name=\"filename\" --image-path=\"path\" --speed=2 --sector-order=DATA_C2_SUB --drive=/dev/sr0")]
|
||||
[InlineData(RedumpSystem.NintendoGameCube, MediaType.NintendoGameCubeGameDisc, "/dev/sr0", "path/filename.bin", 2, "--retries=20 --image-name=\"filename\" --image-path=\"path\" --speed=2 --sector-order=DATA_C2_SUB --drive=/dev/sr0")]
|
||||
[InlineData(RedumpSystem.NintendoWii, MediaType.NintendoWiiOpticalDisc, "/dev/sr0", "path/filename.bin", 2, "--retries=20 --image-name=\"filename\" --image-path=\"path\" --speed=2 --sector-order=DATA_C2_SUB --drive=/dev/sr0")]
|
||||
[InlineData(RedumpSystem.HDDVDVideo, MediaType.HDDVD, "/dev/sr0", "path/filename.bin", 2, "--retries=20 --image-name=\"filename\" --image-path=\"path\" --speed=2 --sector-order=DATA_C2_SUB --drive=/dev/sr0")]
|
||||
[InlineData(RedumpSystem.BDVideo, MediaType.BluRay, "/dev/sr0", "path/filename.bin", 2, "--retries=20 --image-name=\"filename\" --image-path=\"path\" --speed=2 --sector-order=DATA_C2_SUB --drive=/dev/sr0")]
|
||||
[InlineData(RedumpSystem.NintendoWiiU, MediaType.NintendoWiiUOpticalDisc, "/dev/sr0", "path/filename.bin", 2, "--retries=20 --image-name=\"filename\" --image-path=\"path\" --speed=2 --sector-order=DATA_C2_SUB --drive=/dev/sr0")]
|
||||
public void DefaultValueTest(RedumpSystem? system,
|
||||
MediaType? type,
|
||||
string? drivePath,
|
||||
string filename,
|
||||
int? driveSpeed,
|
||||
string? expected)
|
||||
{
|
||||
var context = new ExecutionContext(system, type, drivePath, filename, driveSpeed, AllOptions);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Default
|
||||
|
||||
[Theory]
|
||||
[InlineData("--force-qtoc --train --retries=20 --image-name=image --image-path=path --read-offset=0 --read-at-once=0 --speed=8 --sector-order=so --drive=/dev/sr0")]
|
||||
public void DiscTest(string parameters)
|
||||
{
|
||||
string? expected = "--force-qtoc --train --retries=20 --image-name=\"image\" --image-path=\"path\" --read-offset=0 --read-at-once=0 --speed=8 --sector-order=so --drive=/dev/sr0";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--image-name=\"image name.bin\" --image-path=\"directory name\"")]
|
||||
public void SpacesTest(string parameters)
|
||||
{
|
||||
string? expected = "--image-name=\"image name.bin\" --image-path=\"directory name\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", new string[] { "flag" }, 0, true, true)]
|
||||
public void FlagInputTest(string name, string[] parts, int index, bool success, bool expected)
|
||||
{
|
||||
FlagInput input = new FlagInput(name);
|
||||
var input = new FlagInput(name);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -55,7 +55,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=false" }, 0, true, false)]
|
||||
public void BooleanInputTest(string name, bool required, string[] parts, int index, bool success, bool? expected)
|
||||
{
|
||||
BooleanInput input = new BooleanInput(name, required);
|
||||
var input = new BooleanInput(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -90,7 +90,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=-1" }, 0, true, (sbyte)-1)]
|
||||
public void Int8InputTest(string name, bool required, string[] parts, int index, bool success, sbyte? expected)
|
||||
{
|
||||
Int8Input input = new Int8Input(name, required);
|
||||
var input = new Int8Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -123,7 +123,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (byte)1)]
|
||||
public void UInt8InputTest(string name, bool required, string[] parts, int index, bool success, byte? expected)
|
||||
{
|
||||
UInt8Input input = new UInt8Input(name, required);
|
||||
var input = new UInt8Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -158,7 +158,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=-1" }, 0, true, (short)-1)]
|
||||
public void Int16InputTest(string name, bool required, string[] parts, int index, bool success, short? expected)
|
||||
{
|
||||
Int16Input input = new Int16Input(name, required);
|
||||
var input = new Int16Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -191,7 +191,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (ushort)1)]
|
||||
public void UInt16InputTest(string name, bool required, string[] parts, int index, bool success, ushort? expected)
|
||||
{
|
||||
UInt16Input input = new UInt16Input(name, required);
|
||||
var input = new UInt16Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -226,7 +226,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=-1" }, 0, true, (int)-1)]
|
||||
public void Int32InputTest(string name, bool required, string[] parts, int index, bool success, int? expected)
|
||||
{
|
||||
Int32Input input = new Int32Input(name, required);
|
||||
var input = new Int32Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -259,7 +259,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (uint)1)]
|
||||
public void UInt32InputTest(string name, bool required, string[] parts, int index, bool success, uint? expected)
|
||||
{
|
||||
UInt32Input input = new UInt32Input(name, required);
|
||||
var input = new UInt32Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -294,7 +294,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=-1" }, 0, true, (long)-1)]
|
||||
public void Int64InputTest(string name, bool required, string[] parts, int index, bool success, long? expected)
|
||||
{
|
||||
Int64Input input = new Int64Input(name, required);
|
||||
var input = new Int64Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -327,7 +327,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (ulong)1)]
|
||||
public void UInt64InputTest(string name, bool required, string[] parts, int index, bool success, ulong? expected)
|
||||
{
|
||||
UInt64Input input = new UInt64Input(name, required);
|
||||
var input = new UInt64Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -355,7 +355,7 @@ namespace MPF.ExecutionContexts.Test
|
||||
[InlineData("flag", true, new string[] { "flag=value" }, 0, true, "value")]
|
||||
public void StringInputTest(string name, bool required, string[] parts, int index, bool success, string? expected)
|
||||
{
|
||||
StringInput input = new StringInput(name, required);
|
||||
var input = new StringInput(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
@@ -407,4 +407,4 @@ namespace MPF.ExecutionContexts.Test
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -14,13 +14,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.13.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.7" />
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="18.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.21.0" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.27.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" />
|
||||
@@ -29,7 +29,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -27,10 +27,10 @@ namespace MPF.ExecutionContexts.Test
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Default Values
|
||||
|
||||
private static Dictionary<string, string?> AllOptions = new()
|
||||
private static readonly Dictionary<string, string?> AllOptions = new()
|
||||
{
|
||||
[SettingConstants.EnableVerbose] = "true",
|
||||
[SettingConstants.LeadinRetryCount] = "1000",
|
||||
@@ -41,9 +41,9 @@ namespace MPF.ExecutionContexts.Test
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, null, "filename.bin", null, "")]
|
||||
[InlineData(null, null, null, "filename.bin", null, "disc --verbose --skeleton --retries=1000 --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.CDROM, "/dev/sr0", "path/filename.bin", 2, "disc --verbose --skeleton --drive=/dev/sr0 --speed=2 --retries=1000 --image-path=\"path\" --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.DVD, "/dev/sr0", "path/filename.bin", 2, "disc --verbose --drive=/dev/sr0 --speed=2 --retries=1000 --image-path=\"path\" --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.DVD, "/dev/sr0", "path/filename.bin", 2, "disc --verbose --skeleton --drive=/dev/sr0 --speed=2 --retries=1000 --image-path=\"path\" --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
[InlineData(RedumpSystem.NintendoGameCube, MediaType.NintendoGameCubeGameDisc, "/dev/sr0", "path/filename.bin", 2, "disc --verbose --drive=/dev/sr0 --speed=2 --retries=1000 --image-path=\"path\" --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
[InlineData(RedumpSystem.NintendoWii, MediaType.NintendoWiiOpticalDisc, "/dev/sr0", "path/filename.bin", 2, "disc --verbose --drive=/dev/sr0 --speed=2 --retries=1000 --image-path=\"path\" --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
[InlineData(RedumpSystem.HDDVDVideo, MediaType.HDDVD, "/dev/sr0", "path/filename.bin", 2, "disc --verbose --drive=/dev/sr0 --speed=2 --retries=1000 --image-path=\"path\" --image-name=\"filename\" --drive-type=GENERIC --drive-read-method=BE --drive-sector-order=DATA_C2_SUB --plextor-leadin-retries=1000")]
|
||||
@@ -66,11 +66,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Disc
|
||||
|
||||
[Theory]
|
||||
[InlineData("disc -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("disc --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("disc -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("disc --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void DiscTest(string parameters)
|
||||
{
|
||||
string? expected = "disc --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "disc --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -93,11 +93,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Rings
|
||||
|
||||
[Theory]
|
||||
[InlineData("rings -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("rings --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("rings -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("rings --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void RingsTest(string parameters)
|
||||
{
|
||||
string? expected = "rings --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "rings --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -109,11 +109,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Dump
|
||||
|
||||
[Theory]
|
||||
[InlineData("dump -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dump --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dump -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dump --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void DumpTest(string parameters)
|
||||
{
|
||||
string? expected = "dump --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "dump --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -125,11 +125,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region DumpExtra
|
||||
|
||||
[Theory]
|
||||
[InlineData("dump::extra -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dump::extra --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dump::extra -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dump::extra --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void DumpExtraTest(string parameters)
|
||||
{
|
||||
string? expected = "dump::extra --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "dump::extra --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -141,11 +141,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Refine
|
||||
|
||||
[Theory]
|
||||
[InlineData("refine -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("refine --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("refine -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("refine --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void RefineTest(string parameters)
|
||||
{
|
||||
string? expected = "refine --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "refine --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -157,11 +157,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Verify
|
||||
|
||||
[Theory]
|
||||
[InlineData("verify -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("verify --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("verify -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("verify --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void VerifyTest(string parameters)
|
||||
{
|
||||
string? expected = "verify --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "verify --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -173,11 +173,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region DVDKey
|
||||
|
||||
[Theory]
|
||||
[InlineData("dvdkey -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dvdkey --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dvdkey -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dvdkey --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void DVDKeyTest(string parameters)
|
||||
{
|
||||
string? expected = "dvdkey --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "dvdkey --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -189,11 +189,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Eject
|
||||
|
||||
[Theory]
|
||||
[InlineData("eject -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("eject --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("eject -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("eject --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void EjectTest(string parameters)
|
||||
{
|
||||
string? expected = "eject --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "eject --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -205,11 +205,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region DVDIsoKey
|
||||
|
||||
[Theory]
|
||||
[InlineData("dvdisokey -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dvdisokey --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dvdisokey -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("dvdisokey --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void DVDIsoKeyTest(string parameters)
|
||||
{
|
||||
string? expected = "dvdisokey --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "dvdisokey --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -221,11 +221,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Protection
|
||||
|
||||
[Theory]
|
||||
[InlineData("protection -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("protection --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs --disable-cdtext")]
|
||||
[InlineData("protection -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("protection --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs --disable-cdtext")]
|
||||
public void ProtectionTest(string parameters)
|
||||
{
|
||||
string? expected = "protection --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "protection --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -237,11 +237,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Split
|
||||
|
||||
[Theory]
|
||||
[InlineData("split -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("split --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("split -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("split --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void SplitTest(string parameters)
|
||||
{
|
||||
string? expected = "split --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "split --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -253,11 +253,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Hash
|
||||
|
||||
[Theory]
|
||||
[InlineData("hash -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("hash --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("hash -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("hash --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void HashTest(string parameters)
|
||||
{
|
||||
string? expected = "hash --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "hash --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -269,11 +269,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Info
|
||||
|
||||
[Theory]
|
||||
[InlineData("info -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("info --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("info -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("info --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void InfoTest(string parameters)
|
||||
{
|
||||
string? expected = "info --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "info --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -285,11 +285,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Skeleton
|
||||
|
||||
[Theory]
|
||||
[InlineData("skeleton -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("skeleton --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("skeleton -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("skeleton --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void SkeletonTest(string parameters)
|
||||
{
|
||||
string? expected = "skeleton --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "skeleton --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -301,11 +301,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Subchannel
|
||||
|
||||
[Theory]
|
||||
[InlineData("subchannel -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("subchannel --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("subchannel -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("subchannel --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void SubchannelTest(string parameters)
|
||||
{
|
||||
string? expected = "subchannel --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "subchannel --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -317,11 +317,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region Debug
|
||||
|
||||
[Theory]
|
||||
[InlineData("debug -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("debug --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("debug -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("debug --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void DebugTest(string parameters)
|
||||
{
|
||||
string? expected = "debug --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "debug --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -333,11 +333,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region FixMSF
|
||||
|
||||
[Theory]
|
||||
[InlineData("fixmsf -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("fixmsf --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("fixmsf -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("fixmsf --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void FixMSFTest(string parameters)
|
||||
{
|
||||
string? expected = "fixmsf --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "fixmsf --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -348,11 +348,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region DebugFlip
|
||||
|
||||
[Theory]
|
||||
[InlineData("debug::flip -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("debug::flip --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("debug::flip -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("debug::flip --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void DebugFlipTest(string parameters)
|
||||
{
|
||||
string? expected = "debug::flip --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "debug::flip --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
@@ -363,11 +363,11 @@ namespace MPF.ExecutionContexts.Test
|
||||
#region DriveTest
|
||||
|
||||
[Theory]
|
||||
[InlineData("drive::test -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("drive::test --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("drive::test -h --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
[InlineData("drive::test --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=path --image-name=image --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs")]
|
||||
public void DriveTestTest(string parameters)
|
||||
{
|
||||
string? expected = "drive::test --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --asus-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --iso9660-trim --lba-start=0 --lba-end=0 --refine-subchannel --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
string? expected = "drive::test --help --version --verbose --auto-eject --skeleton --drive=dr --speed=8 --retries=0 --image-path=\"path\" --image-name=\"image\" --overwrite --drive-type=dt --drive-read-offset=0 --drive-c2-shift=0 --drive-pregap-start=0 --drive-read-method=drm --drive-sector-order=dso --plextor-skip-leadin --plextor-leadin-retries=0 --mediatek-skip-leadout --disable-cdtext --force-offset=0 --audio-silence-threshold=0 --correct-offset-shift --offset-shift-relocate --force-split --leave-unchanged --force-qtoc --skip-fill=0 --filesystem-trim --lba-start=0 --lba-end=0 --refine-subchannel --refine-sector-mode --skip=0 --dump-write-offset=0 --dump-read-size=0 --overread-leadout --force-unscrambled --legacy-subs";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
@@ -86,4 +86,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string WesternEuropeanMac = "macintosh";
|
||||
public const string WesternEuropeanRadix50 = "radix50";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,6 +511,7 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
}
|
||||
|
||||
// Handle filenames based on command, if necessary
|
||||
#pragma warning disable IDE0010
|
||||
switch (BaseCommand)
|
||||
{
|
||||
// Input value only (file path)
|
||||
@@ -538,7 +539,11 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
if (string.IsNullOrEmpty(InputValue))
|
||||
return null;
|
||||
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (InputValue!.Contains(' '))
|
||||
#else
|
||||
if (InputValue!.Contains(" "))
|
||||
#endif
|
||||
parameters.Append($"\"{InputValue!.TrimEnd('\\')}\" ");
|
||||
else
|
||||
parameters.Append($"{InputValue!.TrimEnd('\\')} ");
|
||||
@@ -582,6 +587,7 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
parameters.Append($"\"{RemoteHostValue}\" ");
|
||||
break;
|
||||
}
|
||||
#pragma warning restore IDE0010
|
||||
|
||||
return parameters.ToString().TrimEnd();
|
||||
}
|
||||
@@ -632,17 +638,12 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
InputValue = drivePath;
|
||||
OutputValue = filename;
|
||||
|
||||
if (driveSpeed != null)
|
||||
if (driveSpeed is not null)
|
||||
{
|
||||
this[FlagStrings.SpeedLong] = true;
|
||||
(_inputs[FlagStrings.SpeedLong] as Int8Input)?.SetValue((sbyte)driveSpeed);
|
||||
}
|
||||
|
||||
// First check to see if the combination of system and MediaType is valid
|
||||
var validTypes = RedumpSystem.MediaTypes();
|
||||
if (!validTypes.Contains(MediaType))
|
||||
return;
|
||||
|
||||
// Set retry count
|
||||
int rereadCount = GetInt32Setting(options, SettingConstants.RereadCount, SettingConstants.RereadCountDefault);
|
||||
if (rereadCount > 0)
|
||||
@@ -657,73 +658,32 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
this[FlagStrings.DebugLong] = true;
|
||||
_preCommandInputs[FlagStrings.DebugLong].SetValue(true);
|
||||
}
|
||||
|
||||
if (GetBooleanSetting(options, SettingConstants.EnableVerbose, SettingConstants.EnableVerboseDefault))
|
||||
{
|
||||
this[FlagStrings.VerboseLong] = true;
|
||||
_preCommandInputs[FlagStrings.VerboseLong].SetValue(true);
|
||||
}
|
||||
|
||||
if (GetBooleanSetting(options, SettingConstants.ForceDumping, SettingConstants.ForceDumpingDefault))
|
||||
{
|
||||
this[FlagStrings.ForceLong] = true;
|
||||
(_inputs[FlagStrings.ForceLong] as BooleanInput)?.SetValue(true);
|
||||
}
|
||||
|
||||
if (GetBooleanSetting(options, SettingConstants.StripPersonalData, SettingConstants.StripPersonalDataDefault))
|
||||
{
|
||||
this[FlagStrings.PrivateLong] = true;
|
||||
(_inputs[FlagStrings.PrivateLong] as BooleanInput)?.SetValue(true);
|
||||
}
|
||||
|
||||
// TODO: Look at dump-media formats and the like and see what options there are there to fill in defaults
|
||||
// Now sort based on disc type
|
||||
switch (MediaType)
|
||||
{
|
||||
case SabreTools.RedumpLib.Data.MediaType.CDROM:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.DVD:
|
||||
this[FlagStrings.StoreEncryptedLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.StoreEncryptedLong] as BooleanInput)?.SetValue(true);
|
||||
this[FlagStrings.TitleKeysLong] = false; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TitleKeysLong] as BooleanInput)?.SetValue(false);
|
||||
this[FlagStrings.TrimLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TrimLong] as BooleanInput)?.SetValue(true);
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.GDROM:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.HDDVD:
|
||||
this[FlagStrings.StoreEncryptedLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.StoreEncryptedLong] as BooleanInput)?.SetValue(true);
|
||||
this[FlagStrings.TitleKeysLong] = false; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TitleKeysLong] as BooleanInput)?.SetValue(false);
|
||||
this[FlagStrings.TrimLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TrimLong] as BooleanInput)?.SetValue(true);
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.BluRay:
|
||||
this[FlagStrings.StoreEncryptedLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.StoreEncryptedLong] as BooleanInput)?.SetValue(true);
|
||||
this[FlagStrings.TitleKeysLong] = false; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TitleKeysLong] as BooleanInput)?.SetValue(false);
|
||||
this[FlagStrings.TrimLong] = true; // TODO: Make this configurable
|
||||
(_inputs[FlagStrings.TrimLong] as BooleanInput)?.SetValue(true);
|
||||
break;
|
||||
|
||||
// Special Formats
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoGameCubeGameDisc:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoWiiOpticalDisc:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoWiiUOpticalDisc:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
|
||||
// Non-optical
|
||||
case SabreTools.RedumpLib.Data.MediaType.FloppyDisk:
|
||||
// Currently no defaults set
|
||||
break;
|
||||
}
|
||||
// Set generic, sane defaults to cover all bases
|
||||
this[FlagStrings.StoreEncryptedLong] = true;
|
||||
(_inputs[FlagStrings.StoreEncryptedLong] as BooleanInput)?.SetValue(true);
|
||||
this[FlagStrings.TitleKeysLong] = false;
|
||||
(_inputs[FlagStrings.TitleKeysLong] as BooleanInput)?.SetValue(false);
|
||||
this[FlagStrings.TrimLong] = true;
|
||||
(_inputs[FlagStrings.TrimLong] as BooleanInput)?.SetValue(true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -802,6 +762,7 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
}
|
||||
|
||||
// Handle filenames based on command, if necessary
|
||||
#pragma warning disable IDE0010
|
||||
switch (BaseCommand)
|
||||
{
|
||||
// Input value only
|
||||
@@ -868,6 +829,7 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
#pragma warning restore IDE0010
|
||||
|
||||
// If we didn't reach the end for some reason, it failed
|
||||
if (i != parts.Length)
|
||||
@@ -899,7 +861,7 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
var normalized = NormalizeCommand($"{partOne} {partTwo}".Trim());
|
||||
|
||||
// Null normalization means invalid command
|
||||
if (normalized == null)
|
||||
if (normalized is null)
|
||||
return null;
|
||||
|
||||
// Determine if start should be incremented
|
||||
|
||||
@@ -170,4 +170,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,4 +166,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string XboxPartitioning = "Xbox partitioning";
|
||||
public const string XENIX = "XENIX";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,4 +24,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string WindowsNT83MixedCase = "nt";
|
||||
public const string OS2Extended = "os2";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string VMwareDiskImageSparse = "sparse"; // boolean, default false
|
||||
public const string VMwareDiskImageSplit = "split"; // boolean, default false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string StripPersonalData = "AaruStripPersonalData";
|
||||
public const bool StripPersonalDataDefault = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace MPF.ExecutionContexts
|
||||
/// Returns if the current Parameter object is valid
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsValid() => GenerateParameters() != null;
|
||||
public bool IsValid() => GenerateParameters() is not null;
|
||||
|
||||
/// <summary>
|
||||
/// Reset all special variables to have default values
|
||||
@@ -222,7 +222,7 @@ namespace MPF.ExecutionContexts
|
||||
{
|
||||
try
|
||||
{
|
||||
while (process != null && !process.HasExited)
|
||||
while (process is not null && !process.HasExited)
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
@@ -294,6 +294,28 @@ namespace MPF.ExecutionContexts
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an UInt8 setting from a settings, dictionary
|
||||
/// </summary>
|
||||
/// <param name="settings">Dictionary representing the settings</param>
|
||||
/// <param name="key">Setting key to get a value for</param>
|
||||
/// <param name="defaultValue">Default value to return if no value is found</param>
|
||||
/// <returns>Setting value if possible, default value otherwise</returns>
|
||||
internal static byte GetUInt8Setting(Dictionary<string, string?> settings, string key, byte defaultValue)
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
{
|
||||
if (byte.TryParse(settings[key], out byte value))
|
||||
return value;
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parameter Parsing
|
||||
@@ -331,9 +353,9 @@ namespace MPF.ExecutionContexts
|
||||
/// <returns>True if the flag value is supported, false otherwise</returns>
|
||||
protected bool IsFlagSupported(string flag)
|
||||
{
|
||||
if (CommandSupport == null)
|
||||
if (CommandSupport is null)
|
||||
return false;
|
||||
if (BaseCommand == null)
|
||||
if (BaseCommand is null)
|
||||
return false;
|
||||
if (!CommandSupport.TryGetValue(BaseCommand, out var supported))
|
||||
return false;
|
||||
@@ -360,9 +382,9 @@ namespace MPF.ExecutionContexts
|
||||
string value = ExtractFactorFromValue(parameter, out _);
|
||||
if (!sbyte.TryParse(value, out sbyte temp))
|
||||
return false;
|
||||
else if (lowerBound != null && temp < lowerBound)
|
||||
else if (lowerBound is not null && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != null && temp > upperBound)
|
||||
else if (upperBound is not null && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -380,9 +402,9 @@ namespace MPF.ExecutionContexts
|
||||
string value = ExtractFactorFromValue(parameter, out _);
|
||||
if (!short.TryParse(value, out short temp))
|
||||
return false;
|
||||
else if (lowerBound != null && temp < lowerBound)
|
||||
else if (lowerBound is not null && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != null && temp > upperBound)
|
||||
else if (upperBound is not null && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -400,9 +422,9 @@ namespace MPF.ExecutionContexts
|
||||
string value = ExtractFactorFromValue(parameter, out _);
|
||||
if (!int.TryParse(value, out int temp))
|
||||
return false;
|
||||
else if (lowerBound != null && temp < lowerBound)
|
||||
else if (lowerBound is not null && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != null && temp > upperBound)
|
||||
else if (upperBound is not null && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -420,9 +442,9 @@ namespace MPF.ExecutionContexts
|
||||
string value = ExtractFactorFromValue(parameter, out _);
|
||||
if (!long.TryParse(value, out long temp))
|
||||
return false;
|
||||
else if (lowerBound != null && temp < lowerBound)
|
||||
else if (lowerBound is not null && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != null && temp > upperBound)
|
||||
else if (upperBound is not null && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -448,7 +470,7 @@ namespace MPF.ExecutionContexts
|
||||
/// <returns>True if the parameter was processed successfully or skipped, false otherwise</returns>
|
||||
protected bool ProcessFlagParameter(string[] parts, string? shortFlagString, string longFlagString, ref int i)
|
||||
{
|
||||
if (parts == null)
|
||||
if (parts is null)
|
||||
return false;
|
||||
|
||||
if (parts[i] == shortFlagString || parts[i] == longFlagString)
|
||||
@@ -484,7 +506,7 @@ namespace MPF.ExecutionContexts
|
||||
/// <returns>True if the parameter was processed successfully or skipped, false otherwise</returns>
|
||||
protected bool ProcessBooleanParameter(string[] parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
{
|
||||
if (parts == null)
|
||||
if (parts is null)
|
||||
return false;
|
||||
|
||||
if (parts[i] == shortFlagString || parts[i] == longFlagString)
|
||||
@@ -559,7 +581,7 @@ namespace MPF.ExecutionContexts
|
||||
/// <returns>SByte value if success, SByte.MinValue if skipped, null on error/returns>
|
||||
protected sbyte? ProcessInt8Parameter(string[] parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
{
|
||||
if (parts == null)
|
||||
if (parts is null)
|
||||
return null;
|
||||
|
||||
if (parts[i] == shortFlagString || parts[i] == longFlagString)
|
||||
@@ -622,7 +644,7 @@ namespace MPF.ExecutionContexts
|
||||
return null;
|
||||
}
|
||||
|
||||
return SByte.MinValue;
|
||||
return sbyte.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -647,7 +669,7 @@ namespace MPF.ExecutionContexts
|
||||
/// <returns>Int16 value if success, Int16.MinValue if skipped, null on error/returns>
|
||||
protected short? ProcessInt16Parameter(string[] parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
{
|
||||
if (parts == null)
|
||||
if (parts is null)
|
||||
return null;
|
||||
|
||||
if (parts[i] == shortFlagString || parts[i] == longFlagString)
|
||||
@@ -709,7 +731,7 @@ namespace MPF.ExecutionContexts
|
||||
return null;
|
||||
}
|
||||
|
||||
return Int16.MinValue;
|
||||
return short.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -734,7 +756,7 @@ namespace MPF.ExecutionContexts
|
||||
/// <returns>Int32 value if success, Int32.MinValue if skipped, null on error/returns>
|
||||
protected int? ProcessInt32Parameter(string[] parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
{
|
||||
if (parts == null)
|
||||
if (parts is null)
|
||||
return null;
|
||||
|
||||
if (parts[i] == shortFlagString || parts[i] == longFlagString)
|
||||
@@ -821,7 +843,7 @@ namespace MPF.ExecutionContexts
|
||||
/// <returns>Int64 value if success, Int64.MinValue if skipped, null on error/returns>
|
||||
protected long? ProcessInt64Parameter(string[] parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
{
|
||||
if (parts == null)
|
||||
if (parts is null)
|
||||
return null;
|
||||
|
||||
if (parts[i] == shortFlagString || parts[i] == longFlagString)
|
||||
@@ -856,10 +878,10 @@ namespace MPF.ExecutionContexts
|
||||
i++;
|
||||
string value = ExtractFactorFromValue(parts[i], out long factor);
|
||||
if (long.TryParse(value, out long longValue))
|
||||
return (long)(longValue * factor);
|
||||
return longValue * factor;
|
||||
string hexValue = RemoveHexIdentifier(value);
|
||||
if (long.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out long longHexValue))
|
||||
return (long)(longHexValue * factor);
|
||||
return longHexValue * factor;
|
||||
return null;
|
||||
}
|
||||
else if (parts[i].StartsWith(shortFlagString + "=") || parts[i].StartsWith(longFlagString + "="))
|
||||
@@ -876,10 +898,10 @@ namespace MPF.ExecutionContexts
|
||||
this[longFlagString] = true;
|
||||
string value = ExtractFactorFromValue(valuePart, out long factor);
|
||||
if (long.TryParse(value, out long longValue))
|
||||
return (long)(longValue * factor);
|
||||
return longValue * factor;
|
||||
string hexValue = RemoveHexIdentifier(value);
|
||||
if (long.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out long longHexValue))
|
||||
return (long)(longHexValue * factor);
|
||||
return longHexValue * factor;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -908,7 +930,7 @@ namespace MPF.ExecutionContexts
|
||||
/// <returns>String value if possible, string.Empty on missing, null on error</returns>
|
||||
protected string? ProcessStringParameter(string[] parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
{
|
||||
if (parts == null)
|
||||
if (parts is null)
|
||||
return null;
|
||||
|
||||
if (parts[i] == shortFlagString || parts[i] == longFlagString)
|
||||
@@ -981,7 +1003,7 @@ namespace MPF.ExecutionContexts
|
||||
/// <returns>Byte value if success, Byte.MinValue if skipped, null on error/returns>
|
||||
protected byte? ProcessUInt8Parameter(string[] parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
{
|
||||
if (parts == null)
|
||||
if (parts is null)
|
||||
return null;
|
||||
|
||||
if (parts[i] == shortFlagString || parts[i] == longFlagString)
|
||||
@@ -1044,7 +1066,7 @@ namespace MPF.ExecutionContexts
|
||||
return null;
|
||||
}
|
||||
|
||||
return Byte.MinValue;
|
||||
return byte.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -51,9 +51,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -120,4 +120,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == false)
|
||||
if (!Value)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -70,4 +70,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
@@ -124,49 +122,77 @@ namespace MPF.ExecutionContexts.Data
|
||||
factor = 1;
|
||||
|
||||
// Characters
|
||||
if (value.EndsWith("c", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (value.EndsWith('c'))
|
||||
#else
|
||||
if (value.EndsWith("c", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 1;
|
||||
value = value.TrimEnd('c');
|
||||
}
|
||||
|
||||
// Words
|
||||
else if (value.EndsWith("w", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('w'))
|
||||
#else
|
||||
else if (value.EndsWith("w", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 2;
|
||||
value = value.TrimEnd('w');
|
||||
}
|
||||
|
||||
// Double Words
|
||||
else if (value.EndsWith("d", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('d'))
|
||||
#else
|
||||
else if (value.EndsWith("d", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 4;
|
||||
value = value.TrimEnd('d');
|
||||
}
|
||||
|
||||
// Quad Words
|
||||
else if (value.EndsWith("q", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('q'))
|
||||
#else
|
||||
else if (value.EndsWith("q", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 8;
|
||||
value = value.TrimEnd('q');
|
||||
}
|
||||
|
||||
// Kilobytes
|
||||
else if (value.EndsWith("k", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('k'))
|
||||
#else
|
||||
else if (value.EndsWith("k", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 1024;
|
||||
value = value.TrimEnd('k');
|
||||
}
|
||||
|
||||
// Megabytes
|
||||
else if (value.EndsWith("M", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('M'))
|
||||
#else
|
||||
else if (value.EndsWith("M", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 1024 * 1024;
|
||||
value = value.TrimEnd('M');
|
||||
}
|
||||
|
||||
// Gigabytes
|
||||
else if (value.EndsWith("G", StringComparison.Ordinal))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
else if (value.EndsWith('G'))
|
||||
#else
|
||||
else if (value.EndsWith("G", System.StringComparison.Ordinal))
|
||||
#endif
|
||||
{
|
||||
factor = 1024 * 1024 * 1024;
|
||||
value = value.TrimEnd('G');
|
||||
@@ -189,7 +215,11 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (value[1] != 'x' && value[1] != 'X')
|
||||
return value;
|
||||
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
return value[2..];
|
||||
#else
|
||||
return value.Substring(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -208,7 +238,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public T? Value { get; protected set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ValueSet => Value != null;
|
||||
public override bool ValueSet => Value is not null;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -258,4 +288,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -95,25 +95,25 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : short.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(parts[index + 1], out short? value) && value != null)
|
||||
if (ParseValue(parts[index + 1], out short? value) && value is not null)
|
||||
{
|
||||
index++;
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : short.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -129,24 +129,24 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : short.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(val, out short? value) && value != null)
|
||||
if (ParseValue(val, out short? value) && value is not null)
|
||||
{
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : short.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -70,16 +70,16 @@ namespace MPF.ExecutionContexts.Data
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value != null))
|
||||
if (_required || (!_required && Value is not null))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
int?[] nonNull = Array.FindAll(Value, i => i != null);
|
||||
int?[] nonNull = Array.FindAll(Value, i => i is not null);
|
||||
string[] stringValues = Array.ConvertAll(nonNull, i => i.ToString() ?? string.Empty);
|
||||
builder.Append(string.Join(" ", stringValues));
|
||||
}
|
||||
@@ -106,12 +106,12 @@ namespace MPF.ExecutionContexts.Data
|
||||
return !_required;
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(parts[index + 1], out int? value) && value != null)
|
||||
if (ParseValue(parts[index + 1], out int? value) && value is not null)
|
||||
{
|
||||
index++;
|
||||
Value[i] = value;
|
||||
Value[i] = (MinValue != null && Value[i] < MinValue) ? MinValue : Value[i];
|
||||
Value[i] = (MaxValue != null && Value[i] > MaxValue) ? MaxValue : Value[i];
|
||||
Value[i] = (MinValue is not null && Value[i] < MinValue) ? MinValue : Value[i];
|
||||
Value[i] = (MaxValue is not null && Value[i] > MaxValue) ? MaxValue : Value[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -158,4 +158,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -95,25 +95,25 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : int.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(parts[index + 1], out int? value) && value != null)
|
||||
if (ParseValue(parts[index + 1], out int? value) && value is not null)
|
||||
{
|
||||
index++;
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : int.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -129,24 +129,24 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : int.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(val, out int? value) && value != null)
|
||||
if (ParseValue(val, out int? value) && value is not null)
|
||||
{
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : int.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -95,25 +95,25 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : long.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(parts[index + 1], out long? value) && value != null)
|
||||
if (ParseValue(parts[index + 1], out long? value) && value is not null)
|
||||
{
|
||||
index++;
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : long.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -129,24 +129,24 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : long.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(val, out long? value) && value != null)
|
||||
if (ParseValue(val, out long? value) && value is not null)
|
||||
{
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : long.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (long.TryParse(baseVal, out value))
|
||||
{
|
||||
output = (long)(value * factor);
|
||||
output = value * factor;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (long.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = (long)(value * factor);
|
||||
output = value * factor;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -95,25 +95,25 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : sbyte.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(parts[index + 1], out sbyte? value) && value != null)
|
||||
if (ParseValue(parts[index + 1], out sbyte? value) && value is not null)
|
||||
{
|
||||
index++;
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : sbyte.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -129,24 +129,24 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : sbyte.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(val, out sbyte? value) && value != null)
|
||||
if (ParseValue(val, out sbyte? value) && value is not null)
|
||||
{
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : sbyte.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -64,9 +64,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
if (Quotes)
|
||||
@@ -123,4 +123,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -95,25 +95,25 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : ushort.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(parts[index + 1], out ushort? value) && value != null)
|
||||
if (ParseValue(parts[index + 1], out ushort? value) && value is not null)
|
||||
{
|
||||
index++;
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : ushort.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -129,24 +129,24 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : ushort.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(val, out ushort? value) && value != null)
|
||||
if (ParseValue(val, out ushort? value) && value is not null)
|
||||
{
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : ushort.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -95,25 +95,25 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : uint.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(parts[index + 1], out uint? value) && value != null)
|
||||
if (ParseValue(parts[index + 1], out uint? value) && value is not null)
|
||||
{
|
||||
index++;
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : uint.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -129,24 +129,24 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : uint.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(val, out uint? value) && value != null)
|
||||
if (ParseValue(val, out uint? value) && value is not null)
|
||||
{
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : uint.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -95,25 +95,25 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : ulong.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(parts[index + 1], out ulong? value) && value != null)
|
||||
if (ParseValue(parts[index + 1], out ulong? value) && value is not null)
|
||||
{
|
||||
index++;
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : ulong.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -129,24 +129,24 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : ulong.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(val, out ulong? value) && value != null)
|
||||
if (ParseValue(val, out ulong? value) && value is not null)
|
||||
{
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : ulong.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (ulong.TryParse(baseVal, out value))
|
||||
{
|
||||
output = (ulong)(value * (ulong)factor);
|
||||
output = value * (ulong)factor;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (ulong.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = (ulong)(value * (ulong)factor);
|
||||
output = value * (ulong)factor;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace MPF.ExecutionContexts.Data
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value == null)
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
@@ -69,9 +69,9 @@ namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append("=");
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(" ");
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
@@ -95,25 +95,25 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : byte.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(parts[index + 1], out byte? value) && value != null)
|
||||
if (ParseValue(parts[index + 1], out byte? value) && value is not null)
|
||||
{
|
||||
index++;
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : byte.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -129,24 +129,24 @@ namespace MPF.ExecutionContexts.Data
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : byte.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(val, out byte? value) && value != null)
|
||||
if (ParseValue(val, out byte? value) && value is not null)
|
||||
{
|
||||
Value = value;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
Value = _required ? null : byte.MinValue;
|
||||
Value = (MinValue != null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue != null && Value > MaxValue) ? MaxValue : Value;
|
||||
Value = (MinValue is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
@@ -186,4 +186,4 @@ namespace MPF.ExecutionContexts.Data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
{
|
||||
public const string NONE = "";
|
||||
public const string Audio = "audio";
|
||||
public const string AuthPS3 = "authps3";
|
||||
public const string BluRay = "bd";
|
||||
public const string Close = "close";
|
||||
public const string CompactDisc = "cd";
|
||||
@@ -32,4 +33,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string XGD2Swap = "xgd2swap";
|
||||
public const string XGD3Swap = "xgd3swap";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
/// <returns>Valid extension (with leading '.'), null on error</returns>
|
||||
public static string? Extension(MediaType? type)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
return type switch
|
||||
{
|
||||
MediaType.CDROM
|
||||
@@ -93,8 +94,9 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
MediaType.Cassette => ".wav",
|
||||
_ => null,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
@@ -209,6 +208,8 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
FlagStrings.Tages,
|
||||
],
|
||||
|
||||
[CommandStrings.AuthPS3] = [],
|
||||
|
||||
[CommandStrings.BluRay] =
|
||||
[
|
||||
FlagStrings.DatExpand,
|
||||
@@ -419,6 +420,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
// Drive Letter
|
||||
if (BaseCommand == CommandStrings.Audio
|
||||
|| BaseCommand == CommandStrings.AuthPS3
|
||||
|| BaseCommand == CommandStrings.BluRay
|
||||
|| BaseCommand == CommandStrings.Close
|
||||
|| BaseCommand == CommandStrings.CompactDisc
|
||||
@@ -439,9 +441,13 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|| BaseCommand == CommandStrings.XGD2Swap
|
||||
|| BaseCommand == CommandStrings.XGD3Swap)
|
||||
{
|
||||
if (DrivePath != null)
|
||||
if (DrivePath is not null)
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (DrivePath.Contains(' '))
|
||||
#else
|
||||
if (DrivePath.Contains(" "))
|
||||
#endif
|
||||
parameters.Append($"\"{DrivePath}\" ");
|
||||
else
|
||||
parameters.Append($"{DrivePath} ");
|
||||
@@ -472,7 +478,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|| BaseCommand == CommandStrings.XGD2Swap
|
||||
|| BaseCommand == CommandStrings.XGD3Swap)
|
||||
{
|
||||
if (Filename != null)
|
||||
if (Filename is not null)
|
||||
parameters.Append($"\"{Filename.Trim('"')}\" ");
|
||||
else
|
||||
return null;
|
||||
@@ -481,7 +487,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
// Optiarc Filename
|
||||
if (BaseCommand == CommandStrings.Merge)
|
||||
{
|
||||
if (OptiarcFilename != null)
|
||||
if (OptiarcFilename is not null)
|
||||
parameters.Append($"\"{OptiarcFilename.Trim('"')}\" ");
|
||||
else
|
||||
return null;
|
||||
@@ -501,7 +507,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|| BaseCommand == CommandStrings.XGD2Swap
|
||||
|| BaseCommand == CommandStrings.XGD3Swap)
|
||||
{
|
||||
if (DriveSpeed != null)
|
||||
if (DriveSpeed is not null)
|
||||
parameters.Append($"{DriveSpeed} ");
|
||||
else
|
||||
return null;
|
||||
@@ -511,7 +517,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (BaseCommand == CommandStrings.Audio
|
||||
|| BaseCommand == CommandStrings.Data)
|
||||
{
|
||||
if (StartLBAValue != null && EndLBAValue != null)
|
||||
if (StartLBAValue is not null && EndLBAValue is not null)
|
||||
{
|
||||
parameters.Append($"{StartLBAValue} ");
|
||||
parameters.Append($"{EndLBAValue} ");
|
||||
@@ -526,7 +532,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.AddOffset] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.AddOffset} ");
|
||||
if (AddOffsetValue != null)
|
||||
if (AddOffsetValue is not null)
|
||||
parameters.Append($"{AddOffsetValue} ");
|
||||
}
|
||||
}
|
||||
@@ -551,7 +557,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.BEOpcode] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.BEOpcode} ");
|
||||
if (BEOpcodeValue != null)
|
||||
if (BEOpcodeValue is not null)
|
||||
parameters.Append($"{BEOpcodeValue} ");
|
||||
}
|
||||
}
|
||||
@@ -562,22 +568,25 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.C2Opcode] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.C2Opcode} ");
|
||||
if (C2OpcodeValue[0] != null)
|
||||
if (C2OpcodeValue[0] is not null)
|
||||
{
|
||||
if (C2OpcodeValue[0] > 0)
|
||||
parameters.Append($"{C2OpcodeValue[0]} ");
|
||||
else
|
||||
return null;
|
||||
}
|
||||
if (C2OpcodeValue[1] != null)
|
||||
|
||||
if (C2OpcodeValue[1] is not null)
|
||||
{
|
||||
parameters.Append($"{C2OpcodeValue[1]} ");
|
||||
}
|
||||
if (C2OpcodeValue[2] != null)
|
||||
|
||||
if (C2OpcodeValue[2] is not null)
|
||||
{
|
||||
parameters.Append($"{C2OpcodeValue[2]} ");
|
||||
}
|
||||
if (C2OpcodeValue[3] != null)
|
||||
|
||||
if (C2OpcodeValue[3] is not null)
|
||||
{
|
||||
if (C2OpcodeValue[3] == 0)
|
||||
{
|
||||
@@ -586,7 +595,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
else if (C2OpcodeValue[3] == 1)
|
||||
{
|
||||
parameters.Append($"{C2OpcodeValue[3]} ");
|
||||
if (C2OpcodeValue[4] != null && C2OpcodeValue[5] != null)
|
||||
if (C2OpcodeValue[4] is not null && C2OpcodeValue[5] is not null)
|
||||
{
|
||||
if (C2OpcodeValue[4] > 0 && C2OpcodeValue[5] > 0)
|
||||
{
|
||||
@@ -613,7 +622,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.C2OpcodeNew] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.C2OpcodeNew} ");
|
||||
if (C2OpcodeValue[0] != null)
|
||||
if (C2OpcodeValue[0] is not null)
|
||||
{
|
||||
if (C2OpcodeValue[0] > 0)
|
||||
parameters.Append($"{C2OpcodeValue[0]} ");
|
||||
@@ -657,7 +666,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.DVDReread] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.DVDReread} ");
|
||||
if (DVDRereadValue != null)
|
||||
if (DVDRereadValue is not null)
|
||||
parameters.Append($"{DVDRereadValue} ");
|
||||
}
|
||||
}
|
||||
@@ -675,7 +684,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.Fix] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.Fix} ");
|
||||
if (FixValue != null)
|
||||
if (FixValue is not null)
|
||||
parameters.Append($"{FixValue} ");
|
||||
else
|
||||
return null;
|
||||
@@ -688,7 +697,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.ForceDescrambleSector] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.ForceDescrambleSector} ");
|
||||
if (ForceDescrambleSectorValue != null)
|
||||
if (ForceDescrambleSectorValue is not null)
|
||||
parameters.Append($"{ForceDescrambleSectorValue} ");
|
||||
else
|
||||
return null;
|
||||
@@ -701,7 +710,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.ForceUnitAccess] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.ForceUnitAccess} ");
|
||||
if (ForceUnitAccessValue != null)
|
||||
if (ForceUnitAccessValue is not null)
|
||||
parameters.Append($"{ForceUnitAccessValue} ");
|
||||
}
|
||||
}
|
||||
@@ -719,7 +728,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.MultiSectorRead] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.MultiSectorRead} ");
|
||||
if (MultiSectorReadValue != null)
|
||||
if (MultiSectorReadValue is not null)
|
||||
parameters.Append($"{MultiSectorReadValue} ");
|
||||
}
|
||||
}
|
||||
@@ -765,7 +774,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.NoSkipSS] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.NoSkipSS} ");
|
||||
if (NoSkipSecuritySectorValue != null)
|
||||
if (NoSkipSecuritySectorValue is not null)
|
||||
parameters.Append($"{NoSkipSecuritySectorValue} ");
|
||||
}
|
||||
}
|
||||
@@ -776,7 +785,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.PadSector] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.PadSector} ");
|
||||
if (PadSectorValue != null)
|
||||
if (PadSectorValue is not null)
|
||||
parameters.Append($"{PadSectorValue} ");
|
||||
}
|
||||
}
|
||||
@@ -790,7 +799,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
if (BaseCommand == CommandStrings.DigitalVideoDisc)
|
||||
{
|
||||
if (RangeStartLBAValue == null || RangeEndLBAValue == null)
|
||||
if (RangeStartLBAValue is null || RangeEndLBAValue is null)
|
||||
return null;
|
||||
|
||||
parameters.Append($"{RangeStartLBAValue} ");
|
||||
@@ -822,7 +831,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
if (BaseCommand == CommandStrings.DigitalVideoDisc)
|
||||
{
|
||||
if (ReverseStartLBAValue == null || ReverseEndLBAValue == null)
|
||||
if (ReverseStartLBAValue is null || ReverseEndLBAValue is null)
|
||||
return null;
|
||||
|
||||
parameters.Append($"{ReverseStartLBAValue} ");
|
||||
@@ -844,7 +853,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.ScanFileProtect] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.ScanFileProtect} ");
|
||||
if (ScanFileProtectValue != null)
|
||||
if (ScanFileProtectValue is not null)
|
||||
{
|
||||
if (ScanFileProtectValue > 0)
|
||||
parameters.Append($"{ScanFileProtectValue} ");
|
||||
@@ -874,14 +883,15 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.SkipSector] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.SkipSector} ");
|
||||
if (SkipSectorValue[0] != null)
|
||||
if (SkipSectorValue[0] is not null)
|
||||
{
|
||||
if (SkipSectorValue[0] > 0)
|
||||
parameters.Append($"{SkipSectorValue[0]} ");
|
||||
else
|
||||
return null;
|
||||
}
|
||||
if (SkipSectorValue[1] != null)
|
||||
|
||||
if (SkipSectorValue[1] is not null)
|
||||
{
|
||||
if (SkipSectorValue[1] == 0)
|
||||
parameters.Append($"{SkipSectorValue[1]} ");
|
||||
@@ -895,7 +905,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.SubchannelReadLevel] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.SubchannelReadLevel} ");
|
||||
if (SubchannelReadLevelValue != null)
|
||||
if (SubchannelReadLevelValue is not null)
|
||||
{
|
||||
if (SubchannelReadLevelValue >= 0 && SubchannelReadLevelValue <= 2)
|
||||
parameters.Append($"{SubchannelReadLevelValue} ");
|
||||
@@ -939,7 +949,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
if (this[FlagStrings.VideoNow] == true)
|
||||
{
|
||||
parameters.Append($"{FlagStrings.VideoNow} ");
|
||||
if (VideoNowValue != null)
|
||||
if (VideoNowValue is not null)
|
||||
{
|
||||
if (VideoNowValue >= 0)
|
||||
parameters.Append($"{VideoNowValue} ");
|
||||
@@ -1064,6 +1074,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
};
|
||||
|
||||
// Now sort based on disc type
|
||||
#pragma warning disable IDE0010
|
||||
switch (MediaType)
|
||||
{
|
||||
case SabreTools.RedumpLib.Data.MediaType.CDROM:
|
||||
@@ -1099,6 +1110,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
this[FlagStrings.NoFixSubQLibCrypt] = true;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case SabreTools.RedumpLib.Data.MediaType.DVD:
|
||||
this[FlagStrings.CopyrightManagementInformation] = GetBooleanSetting(options, SettingConstants.UseCMIFlag, SettingConstants.UseCMIFlagDefault);
|
||||
@@ -1132,6 +1144,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
// Currently no defaults set
|
||||
break;
|
||||
}
|
||||
#pragma warning restore IDE0010
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -1183,6 +1196,14 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
index = 6;
|
||||
break;
|
||||
|
||||
case CommandStrings.AuthPS3:
|
||||
if (parts.Length != 2)
|
||||
return false;
|
||||
|
||||
// Blindly assume the path exists
|
||||
DrivePath = parts[1];
|
||||
break;
|
||||
|
||||
case CommandStrings.BluRay:
|
||||
if (parts.Length < 4)
|
||||
return false;
|
||||
@@ -1529,7 +1550,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
// Add Offset
|
||||
intValue = ProcessInt32Parameter(parts, FlagStrings.AddOffset, ref i, missingAllowed: true);
|
||||
if (intValue != null && intValue != int.MinValue)
|
||||
if (intValue is not null && intValue != int.MinValue)
|
||||
AddOffsetValue = intValue;
|
||||
|
||||
// AMSF
|
||||
@@ -1607,7 +1628,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
// DVD/HD-DVD/BD Reread
|
||||
intValue = ProcessInt32Parameter(parts, FlagStrings.DVDReread, ref i, missingAllowed: true);
|
||||
if (intValue != null && intValue != int.MinValue)
|
||||
if (intValue is not null && intValue != int.MinValue)
|
||||
DVDRereadValue = intValue;
|
||||
|
||||
// Extract MS-CAB
|
||||
@@ -1615,7 +1636,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
// Fix
|
||||
intValue = ProcessInt32Parameter(parts, FlagStrings.Fix, ref i);
|
||||
if (intValue != null && intValue != int.MinValue)
|
||||
if (intValue is not null && intValue != int.MinValue)
|
||||
FixValue = intValue;
|
||||
|
||||
// Force Descramble Sector
|
||||
@@ -1677,7 +1698,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
// Force Unit Access
|
||||
intValue = ProcessInt32Parameter(parts, FlagStrings.ForceUnitAccess, ref i, missingAllowed: true);
|
||||
if (intValue != null && intValue != int.MinValue && intValue >= 0)
|
||||
if (intValue is not null && intValue != int.MinValue && intValue >= 0)
|
||||
ForceUnitAccessValue = intValue;
|
||||
|
||||
// Full TOC
|
||||
@@ -1685,7 +1706,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
// Multi-Sector Read
|
||||
intValue = ProcessInt32Parameter(parts, FlagStrings.MultiSectorRead, ref i, missingAllowed: true);
|
||||
if (intValue != null && intValue != int.MinValue && intValue >= 0)
|
||||
if (intValue is not null && intValue != int.MinValue && intValue >= 0)
|
||||
MultiSectorReadValue = intValue;
|
||||
|
||||
// NoFixSubP
|
||||
@@ -1705,12 +1726,12 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
// NoSkipSS
|
||||
intValue = ProcessInt32Parameter(parts, FlagStrings.NoSkipSS, ref i, missingAllowed: true);
|
||||
if (intValue != null && intValue != int.MinValue && intValue >= 0)
|
||||
if (intValue is not null && intValue != int.MinValue && intValue >= 0)
|
||||
NoSkipSecuritySectorValue = intValue;
|
||||
|
||||
// PadSector
|
||||
byteValue = ProcessUInt8Parameter(parts, FlagStrings.PadSector, ref i, missingAllowed: true);
|
||||
if (byteValue != null)
|
||||
if (byteValue is not null)
|
||||
PadSectorValue = byteValue;
|
||||
|
||||
// Range
|
||||
@@ -1762,7 +1783,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
// ScanFileProtect
|
||||
intValue = ProcessInt32Parameter(parts, FlagStrings.ScanFileProtect, ref i, missingAllowed: true);
|
||||
if (intValue != null && intValue != int.MinValue && intValue >= 0)
|
||||
if (intValue is not null && intValue != int.MinValue && intValue >= 0)
|
||||
ScanFileProtectValue = intValue;
|
||||
|
||||
// ScanSectorProtect
|
||||
@@ -1803,7 +1824,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
// SubchannelReadLevel
|
||||
intValue = ProcessInt32Parameter(parts, FlagStrings.SubchannelReadLevel, ref i, missingAllowed: true);
|
||||
if (intValue != null && intValue != int.MinValue && intValue >= 0 && intValue <= 2)
|
||||
if (intValue is not null && intValue != int.MinValue && intValue >= 0 && intValue <= 2)
|
||||
SubchannelReadLevelValue = intValue;
|
||||
|
||||
// Tages
|
||||
@@ -1820,7 +1841,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
|
||||
// VideoNow
|
||||
intValue = ProcessInt32Parameter(parts, FlagStrings.VideoNow, ref i, missingAllowed: true);
|
||||
if (intValue != null && intValue != int.MinValue && intValue >= 0)
|
||||
if (intValue is not null && intValue != int.MinValue && intValue >= 0)
|
||||
VideoNowValue = intValue;
|
||||
|
||||
// VideoNowColor
|
||||
@@ -1852,6 +1873,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0010
|
||||
switch (type)
|
||||
{
|
||||
case SabreTools.RedumpLib.Data.MediaType.CDROM:
|
||||
@@ -1867,6 +1889,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
BaseCommand = CommandStrings.XBOX;
|
||||
return;
|
||||
}
|
||||
|
||||
BaseCommand = CommandStrings.DigitalVideoDisc;
|
||||
return;
|
||||
case SabreTools.RedumpLib.Data.MediaType.GDROM:
|
||||
@@ -1901,6 +1924,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
BaseCommand = null;
|
||||
return;
|
||||
}
|
||||
#pragma warning restore IDE0010
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -47,4 +47,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string VideoNowColor = "/vnc";
|
||||
public const string VideoNowXP = "/vnx";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string UseCMIFlag = "DICUseCMIFlag";
|
||||
public const bool UseCMIFlagDefault = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
MPF.ExecutionContexts/Dreamdump/CommandStrings.cs
Normal file
10
MPF.ExecutionContexts/Dreamdump/CommandStrings.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace MPF.ExecutionContexts.Dreamdump
|
||||
{
|
||||
/// <summary>
|
||||
/// Top-level commands for Dreamdump
|
||||
/// </summary>
|
||||
public static class CommandStrings
|
||||
{
|
||||
public const string NONE = "";
|
||||
}
|
||||
}
|
||||
15
MPF.ExecutionContexts/Dreamdump/Enumerations.cs
Normal file
15
MPF.ExecutionContexts/Dreamdump/Enumerations.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace MPF.ExecutionContexts.Dreamdump
|
||||
{
|
||||
/// <summary>
|
||||
/// Drive sector order option
|
||||
/// </summary>
|
||||
public enum SectorOrder
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
DATA_C2,
|
||||
DATA_SUB,
|
||||
DATA_C2_SUB,
|
||||
DATA_SUB_C2,
|
||||
}
|
||||
}
|
||||
257
MPF.ExecutionContexts/Dreamdump/ExecutionContext.cs
Normal file
257
MPF.ExecutionContexts/Dreamdump/ExecutionContext.cs
Normal file
@@ -0,0 +1,257 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using MPF.ExecutionContexts.Data;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.ExecutionContexts.Dreamdump
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic set of Dreamdump parameters
|
||||
/// </summary>
|
||||
public sealed class ExecutionContext : BaseExecutionContext
|
||||
{
|
||||
#region Generic Dumping Information
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string? InputPath
|
||||
=> (_inputs[FlagStrings.Drive] as StringInput)?.Value?.Trim('"');
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string? OutputPath => Path.Combine(
|
||||
(_inputs[FlagStrings.ImagePath] as StringInput)?.Value?.Trim('"') ?? string.Empty,
|
||||
(_inputs[FlagStrings.ImageName] as StringInput)?.Value?.Trim('"') ?? string.Empty)
|
||||
+ GetDefaultExtension(MediaType);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int? Speed
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_inputs[FlagStrings.Speed] as Int32Input)?.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value is not null && value > 0)
|
||||
{
|
||||
this[FlagStrings.Speed] = true;
|
||||
(_inputs[FlagStrings.Speed] as Int32Input)?.SetValue(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
this[FlagStrings.Speed] = false;
|
||||
(_inputs[FlagStrings.Speed] as Int32Input)?.SetValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Flag Values
|
||||
|
||||
/// <summary>
|
||||
/// Set of all command flags
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, Input> _inputs = new()
|
||||
{
|
||||
// Special
|
||||
[FlagStrings.ForceQTOC] = new FlagInput(FlagStrings.ForceQTOC),
|
||||
[FlagStrings.Train] = new FlagInput(FlagStrings.Train),
|
||||
[FlagStrings.Retries] = new UInt8Input(FlagStrings.Retries),
|
||||
|
||||
// Paths
|
||||
[FlagStrings.ImageName] = new StringInput(FlagStrings.ImageName) { Quotes = true },
|
||||
[FlagStrings.ImagePath] = new StringInput(FlagStrings.ImagePath) { Quotes = true },
|
||||
|
||||
// Drive Part
|
||||
[FlagStrings.ReadOffset] = new Int16Input(FlagStrings.ReadOffset),
|
||||
[FlagStrings.ReadAtOnce] = new UInt8Input(FlagStrings.ReadAtOnce),
|
||||
[FlagStrings.Speed] = new UInt16Input(FlagStrings.Speed),
|
||||
[FlagStrings.SectorOrder] = new StringInput(FlagStrings.SectorOrder),
|
||||
[FlagStrings.Drive] = new StringInput(FlagStrings.Drive),
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ExecutionContext(string? parameters) : base(parameters) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ExecutionContext(RedumpSystem? system,
|
||||
MediaType? type,
|
||||
string? drivePath,
|
||||
string filename,
|
||||
int? driveSpeed,
|
||||
Dictionary<string, string?> options)
|
||||
: base(system, type, drivePath, filename, driveSpeed, options)
|
||||
{
|
||||
}
|
||||
|
||||
#region BaseExecutionContext Implementations
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <remarks>Command support is irrelevant for Dreamdump</remarks>
|
||||
public override Dictionary<string, List<string>> GetCommandSupport()
|
||||
{
|
||||
return new Dictionary<string, List<string>>()
|
||||
{
|
||||
[CommandStrings.NONE] =
|
||||
[
|
||||
// Special
|
||||
FlagStrings.ForceQTOC,
|
||||
FlagStrings.Train,
|
||||
FlagStrings.Retries,
|
||||
|
||||
// Paths
|
||||
FlagStrings.ImageName,
|
||||
FlagStrings.ImagePath,
|
||||
|
||||
// Drive Part
|
||||
FlagStrings.ReadOffset,
|
||||
FlagStrings.ReadAtOnce,
|
||||
FlagStrings.Speed,
|
||||
FlagStrings.SectorOrder,
|
||||
FlagStrings.Drive,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GenerateParameters()
|
||||
{
|
||||
var parameters = new StringBuilder();
|
||||
|
||||
// Loop though and append all existing
|
||||
foreach (var kvp in _inputs)
|
||||
{
|
||||
// If the value doesn't exist
|
||||
string formatted = kvp.Value.Format(useEquals: true);
|
||||
if (formatted.Length == 0)
|
||||
continue;
|
||||
|
||||
// Append the parameter
|
||||
parameters.Append($"{formatted} ");
|
||||
}
|
||||
|
||||
return parameters.ToString().TrimEnd();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string? GetDefaultExtension(MediaType? mediaType) => ".bin";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override MediaType? GetMediaType() => SabreTools.RedumpLib.Data.MediaType.GDROM;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsDumpingCommand() => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ResetValues()
|
||||
{
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
|
||||
flags = [];
|
||||
|
||||
foreach (var kvp in _inputs)
|
||||
kvp.Value.ClearValue();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetDefaultParameters(string? drivePath,
|
||||
string filename,
|
||||
int? driveSpeed,
|
||||
Dictionary<string, string?> options)
|
||||
{
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
|
||||
if (drivePath is not null)
|
||||
{
|
||||
this[FlagStrings.Drive] = true;
|
||||
(_inputs[FlagStrings.Drive] as StringInput)?.SetValue(drivePath);
|
||||
}
|
||||
|
||||
if (driveSpeed is not null && driveSpeed > 0)
|
||||
{
|
||||
this[FlagStrings.Speed] = true;
|
||||
(_inputs[FlagStrings.Speed] as UInt16Input)?.SetValue((ushort)driveSpeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
this[FlagStrings.Speed] = false;
|
||||
(_inputs[FlagStrings.Speed] as UInt16Input)?.SetValue(null);
|
||||
}
|
||||
|
||||
// Set user-defined options
|
||||
string? sectorOrder = GetStringSetting(options, SettingConstants.SectorOrder, SettingConstants.SectorOrderDefault);
|
||||
if (!string.IsNullOrEmpty(sectorOrder) && sectorOrder != SectorOrder.NONE.ToString())
|
||||
{
|
||||
this[FlagStrings.SectorOrder] = true;
|
||||
(_inputs[FlagStrings.SectorOrder] as StringInput)?.SetValue(sectorOrder!);
|
||||
}
|
||||
|
||||
// Set the output paths
|
||||
if (!string.IsNullOrEmpty(filename))
|
||||
{
|
||||
var imagePath = Path.GetDirectoryName(filename);
|
||||
if (!string.IsNullOrEmpty(imagePath))
|
||||
{
|
||||
this[FlagStrings.ImagePath] = true;
|
||||
(_inputs[FlagStrings.ImagePath] as StringInput)?.SetValue(imagePath!);
|
||||
}
|
||||
|
||||
string imageName = Path.GetFileNameWithoutExtension(filename);
|
||||
if (!string.IsNullOrEmpty(imageName))
|
||||
{
|
||||
this[FlagStrings.ImageName] = true;
|
||||
(_inputs[FlagStrings.ImageName] as StringInput)?.SetValue(imageName!);
|
||||
}
|
||||
}
|
||||
|
||||
byte retries = GetUInt8Setting(options, SettingConstants.RereadCount, SettingConstants.RereadCountDefault);
|
||||
if (retries > 0)
|
||||
{
|
||||
this[FlagStrings.Retries] = true;
|
||||
(_inputs[FlagStrings.Retries] as UInt8Input)?.SetValue(retries);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool ValidateAndSetParameters(string? parameters)
|
||||
{
|
||||
// The string has to be valid by itself first
|
||||
if (string.IsNullOrEmpty(parameters))
|
||||
return false;
|
||||
|
||||
// Now split the string into parts for easier validation
|
||||
string[] parts = SplitParameterString(parameters!);
|
||||
|
||||
// Setup the modes
|
||||
BaseCommand = null;
|
||||
|
||||
// Loop through all auxiliary flags, if necessary
|
||||
int index = 0;
|
||||
for (int i = index; i < parts.Length; i++)
|
||||
{
|
||||
// Match all possible flags
|
||||
foreach (var kvp in _inputs)
|
||||
{
|
||||
// If the value was not a match
|
||||
if (!kvp.Value.Process(parts, ref i))
|
||||
continue;
|
||||
|
||||
// Set the flag
|
||||
this[kvp.Key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If the image name was not set, set it with a default value
|
||||
if (string.IsNullOrEmpty((_inputs[FlagStrings.ImageName] as StringInput)?.Value))
|
||||
(_inputs[FlagStrings.ImageName] as StringInput)?.SetValue($"track_{DateTime.Now:yyyyMMdd-HHmm}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
33
MPF.ExecutionContexts/Dreamdump/FlagStrings.cs
Normal file
33
MPF.ExecutionContexts/Dreamdump/FlagStrings.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
namespace MPF.ExecutionContexts.Dreamdump
|
||||
{
|
||||
/// <summary>
|
||||
/// Dumping flags for Dreamdump
|
||||
/// </summary>
|
||||
public static class FlagStrings
|
||||
{
|
||||
#region Special
|
||||
|
||||
public const string ForceQTOC = "--force-qtoc";
|
||||
public const string Train = "--train";
|
||||
public const string Retries = "--retries";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Paths
|
||||
|
||||
public const string ImageName = "--image-name";
|
||||
public const string ImagePath = "--image-path";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Drive Part
|
||||
|
||||
public const string ReadOffset = "--read-offset";
|
||||
public const string ReadAtOnce = "--read-at-once"; // [0,40] (Linux), [0,20] (Windows)
|
||||
public const string Speed = "--speed";
|
||||
public const string SectorOrder = "--sector-order";
|
||||
public const string Drive = "--drive";
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
MPF.ExecutionContexts/Dreamdump/SettingConstants.cs
Normal file
11
MPF.ExecutionContexts/Dreamdump/SettingConstants.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace MPF.ExecutionContexts.Dreamdump
|
||||
{
|
||||
public static class SettingConstants
|
||||
{
|
||||
public const string RereadCount = "DreamdumpRereadCount";
|
||||
public const int RereadCountDefault = 20;
|
||||
|
||||
public const string SectorOrder = "DreamdumpSectorOrder";
|
||||
public static readonly string SectorOrderDefault = Dreamdump.SectorOrder.NONE.ToString();
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<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>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
@@ -11,7 +11,7 @@
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.3.2</VersionPrefix>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
<WarningsNotAsErrors>NU5104</WarningsNotAsErrors>
|
||||
|
||||
<!-- Package Properties -->
|
||||
@@ -32,7 +32,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.7" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -21,10 +21,12 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string Info = "info";
|
||||
public const string Skeleton = "skeleton";
|
||||
public const string FlashMT1339 = "flash::mt1339";
|
||||
public const string FlashSD616 = "flash::sd616";
|
||||
public const string FlashPlextor = "flash::plextor";
|
||||
public const string Subchannel = "subchannel";
|
||||
public const string Debug = "debug";
|
||||
public const string FixMSF = "fixmsf";
|
||||
public const string DebugFlip = "debug::flip";
|
||||
public const string DriveTest = "drive::test";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
/// <returns>Valid extension (with leading '.'), null on error</returns>
|
||||
public static string? Extension(MediaType? type)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
return type switch
|
||||
{
|
||||
MediaType.CDROM
|
||||
@@ -25,8 +26,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
MediaType.NintendoWiiUOpticalDisc => ".wud",
|
||||
_ => null,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
|
||||
GENERIC,
|
||||
PLEXTOR,
|
||||
LG_ASU8A,
|
||||
LG_ASU8B,
|
||||
LG_ASU8C,
|
||||
LG_ASU3,
|
||||
LG_ASU2,
|
||||
MTK8A,
|
||||
MTK8B,
|
||||
MTK8C,
|
||||
MTK3,
|
||||
MTK2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@@ -32,7 +33,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != null && value > 0)
|
||||
if (value is not null && value > 0)
|
||||
{
|
||||
this[FlagStrings.Speed] = true;
|
||||
(_inputs[FlagStrings.Speed] as Int32Input)?.SetValue(value);
|
||||
@@ -49,11 +50,6 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
|
||||
#region Flag Values
|
||||
|
||||
/// <summary>
|
||||
/// Mode being run
|
||||
/// </summary>
|
||||
public string? ModeValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set of all command flags
|
||||
/// </summary>
|
||||
@@ -87,8 +83,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
[FlagStrings.PlextorSkipLeadin] = new FlagInput(FlagStrings.PlextorSkipLeadin),
|
||||
[FlagStrings.PlextorLeadinRetries] = new Int32Input(FlagStrings.PlextorLeadinRetries),
|
||||
[FlagStrings.PlextorLeadinForceStore] = new FlagInput(FlagStrings.PlextorLeadinForceStore),
|
||||
[FlagStrings.AsusSkipLeadout] = new FlagInput(FlagStrings.AsusSkipLeadout),
|
||||
[FlagStrings.AsusLeadoutRetries] = new Int32Input(FlagStrings.AsusLeadoutRetries),
|
||||
[FlagStrings.KreonPartialSS] = new FlagInput(FlagStrings.KreonPartialSS),
|
||||
[FlagStrings.MediatekSkipLeadout] = new FlagInput(FlagStrings.MediatekSkipLeadout),
|
||||
[FlagStrings.MediatekLeadoutRetries] = new Int32Input(FlagStrings.MediatekLeadoutRetries),
|
||||
[FlagStrings.DisableCDText] = new FlagInput(FlagStrings.DisableCDText),
|
||||
|
||||
// Offset
|
||||
@@ -102,7 +99,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
[FlagStrings.LeaveUnchanged] = new FlagInput(FlagStrings.LeaveUnchanged),
|
||||
[FlagStrings.ForceQTOC] = new FlagInput(FlagStrings.ForceQTOC),
|
||||
[FlagStrings.SkipFill] = new UInt8Input(FlagStrings.SkipFill),
|
||||
[FlagStrings.ISO9660Trim] = new FlagInput(FlagStrings.ISO9660Trim),
|
||||
[FlagStrings.FilesystemTrim] = new FlagInput(FlagStrings.FilesystemTrim),
|
||||
|
||||
// Drive Test
|
||||
[FlagStrings.DriveTestSkipPlextorLeadin] = new FlagInput(FlagStrings.DriveTestSkipPlextorLeadin),
|
||||
@@ -112,7 +109,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
[FlagStrings.Continue] = new StringInput(FlagStrings.Continue),
|
||||
[FlagStrings.LBAStart] = new Int32Input(FlagStrings.LBAStart),
|
||||
[FlagStrings.LBAEnd] = new Int32Input(FlagStrings.LBAEnd),
|
||||
[FlagStrings.LBAEndBySubcode] = new Int32Input(FlagStrings.LBAEndBySubcode),
|
||||
[FlagStrings.RefineSubchannel] = new FlagInput(FlagStrings.RefineSubchannel),
|
||||
[FlagStrings.RefineSectorMode] = new FlagInput(FlagStrings.RefineSectorMode),
|
||||
[FlagStrings.Skip] = new StringInput(FlagStrings.Skip),
|
||||
[FlagStrings.DumpWriteOffset] = new Int32Input(FlagStrings.DumpWriteOffset),
|
||||
[FlagStrings.DumpReadSize] = new Int32Input(FlagStrings.DumpReadSize),
|
||||
@@ -120,8 +119,10 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
[FlagStrings.ForceUnscrambled] = new FlagInput(FlagStrings.ForceUnscrambled),
|
||||
[FlagStrings.ForceRefine] = new FlagInput(FlagStrings.ForceRefine),
|
||||
//[FlagStrings.Firmware] = new StringInput(FlagStrings.Firmware) { Quotes = true },
|
||||
[FlagStrings.ForceFlash] = new FlagInput(FlagStrings.ForceFlash),
|
||||
[FlagStrings.SkipSubcodeDesync] = new FlagInput(FlagStrings.SkipSubcodeDesync),
|
||||
[FlagStrings.Rings] = new FlagInput(FlagStrings.Rings),
|
||||
[FlagStrings.CdrErrorThreshold] = new Int32Input(FlagStrings.CdrErrorThreshold),
|
||||
[FlagStrings.ScsiTimeout] = new Int32Input(FlagStrings.ScsiTimeout),
|
||||
|
||||
// Undocumented
|
||||
[FlagStrings.Debug] = new FlagInput(FlagStrings.Debug),
|
||||
@@ -183,8 +184,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
FlagStrings.PlextorSkipLeadin,
|
||||
FlagStrings.PlextorLeadinRetries,
|
||||
FlagStrings.PlextorLeadinForceStore,
|
||||
FlagStrings.AsusSkipLeadout,
|
||||
FlagStrings.AsusLeadoutRetries,
|
||||
FlagStrings.KreonPartialSS,
|
||||
FlagStrings.MediatekSkipLeadout,
|
||||
FlagStrings.MediatekLeadoutRetries,
|
||||
FlagStrings.DisableCDText,
|
||||
|
||||
// Offset
|
||||
@@ -198,7 +200,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
FlagStrings.LeaveUnchanged,
|
||||
FlagStrings.ForceQTOC,
|
||||
FlagStrings.SkipFill,
|
||||
FlagStrings.ISO9660Trim,
|
||||
FlagStrings.FilesystemTrim,
|
||||
|
||||
// Drive Test
|
||||
FlagStrings.DriveTestSkipPlextorLeadin,
|
||||
@@ -208,7 +210,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
FlagStrings.Continue,
|
||||
FlagStrings.LBAStart,
|
||||
FlagStrings.LBAEnd,
|
||||
FlagStrings.LBAEndBySubcode,
|
||||
FlagStrings.RefineSubchannel,
|
||||
FlagStrings.RefineSectorMode,
|
||||
FlagStrings.Skip,
|
||||
FlagStrings.DumpWriteOffset,
|
||||
FlagStrings.DumpReadSize,
|
||||
@@ -216,8 +220,10 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
FlagStrings.ForceUnscrambled,
|
||||
FlagStrings.ForceRefine,
|
||||
//FlagStrings.Firmware,
|
||||
FlagStrings.ForceFlash,
|
||||
FlagStrings.SkipSubcodeDesync,
|
||||
FlagStrings.Rings,
|
||||
FlagStrings.CdrErrorThreshold,
|
||||
FlagStrings.ScsiTimeout,
|
||||
|
||||
// Undocumented
|
||||
FlagStrings.Debug,
|
||||
@@ -237,9 +243,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
var parameters = new StringBuilder();
|
||||
|
||||
// Command Mode
|
||||
ModeValue ??= CommandStrings.NONE;
|
||||
if (ModeValue != CommandStrings.NONE)
|
||||
parameters.Append($"{ModeValue} ");
|
||||
BaseCommand ??= CommandStrings.NONE;
|
||||
if (BaseCommand != CommandStrings.NONE)
|
||||
parameters.Append($"{BaseCommand} ");
|
||||
|
||||
// Loop though and append all existing
|
||||
foreach (var kvp in _inputs)
|
||||
@@ -266,8 +272,8 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public override bool IsDumpingCommand()
|
||||
{
|
||||
// `dump` command does not provide hashes so will error out after dump if run via MPF
|
||||
return ModeValue == CommandStrings.NONE
|
||||
|| ModeValue == CommandStrings.Disc;
|
||||
return BaseCommand == CommandStrings.NONE
|
||||
|| BaseCommand == CommandStrings.Disc;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -287,27 +293,15 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
int? driveSpeed,
|
||||
Dictionary<string, string?> options)
|
||||
{
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
switch (MediaType)
|
||||
BaseCommand = CommandStrings.Disc;
|
||||
|
||||
if (drivePath is not null)
|
||||
{
|
||||
case SabreTools.RedumpLib.Data.MediaType.CDROM:
|
||||
case SabreTools.RedumpLib.Data.MediaType.DVD:
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoGameCubeGameDisc:
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoWiiOpticalDisc:
|
||||
case SabreTools.RedumpLib.Data.MediaType.HDDVD:
|
||||
case SabreTools.RedumpLib.Data.MediaType.BluRay:
|
||||
case SabreTools.RedumpLib.Data.MediaType.NintendoWiiUOpticalDisc:
|
||||
ModeValue = CommandStrings.Disc;
|
||||
break;
|
||||
default:
|
||||
BaseCommand = null;
|
||||
return;
|
||||
this[FlagStrings.Drive] = true;
|
||||
(_inputs[FlagStrings.Drive] as StringInput)?.SetValue(drivePath);
|
||||
}
|
||||
|
||||
this[FlagStrings.Drive] = true;
|
||||
(_inputs[FlagStrings.Drive] as StringInput)?.SetValue(drivePath ?? string.Empty);
|
||||
|
||||
if (driveSpeed != null && driveSpeed > 0)
|
||||
if (driveSpeed is not null && driveSpeed > 0)
|
||||
{
|
||||
this[FlagStrings.Speed] = true;
|
||||
(_inputs[FlagStrings.Speed] as Int32Input)?.SetValue(driveSpeed);
|
||||
@@ -324,35 +318,67 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
this[FlagStrings.Verbose] = true;
|
||||
(_inputs[FlagStrings.Verbose] as FlagInput)?.SetValue(true);
|
||||
}
|
||||
|
||||
if (GetBooleanSetting(options, SettingConstants.EnableSkeleton, SettingConstants.EnableSkeletonDefault))
|
||||
{
|
||||
// Enable skeleton for CD dumps only by default
|
||||
switch (MediaType)
|
||||
#pragma warning disable IDE0010
|
||||
switch (RedumpSystem)
|
||||
{
|
||||
case SabreTools.RedumpLib.Data.MediaType.CDROM:
|
||||
switch (RedumpSystem)
|
||||
// Systems known to have significant data outside the ISO9660 filesystem
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.MicrosoftXbox:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.MicrosoftXbox360:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.PlaymajiPolymega:
|
||||
// Skeletons from newer BD-based consoles unnecessary
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.MicrosoftXboxOne:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.MicrosoftXboxSeriesXS:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.SonyPlayStation3:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.SonyPlayStation4:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.SonyPlayStation5:
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.NintendoWiiU:
|
||||
break;
|
||||
|
||||
default:
|
||||
// Enable skeleton for CD and DVD only, by default
|
||||
switch (MediaType)
|
||||
{
|
||||
case SabreTools.RedumpLib.Data.RedumpSystem.SuperAudioCD:
|
||||
break;
|
||||
default:
|
||||
case SabreTools.RedumpLib.Data.MediaType.CDROM:
|
||||
case SabreTools.RedumpLib.Data.MediaType.DVD:
|
||||
{
|
||||
this[FlagStrings.Skeleton] = true;
|
||||
(_inputs[FlagStrings.Skeleton] as FlagInput)?.SetValue(true);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// If the type is unknown, also enable
|
||||
case null:
|
||||
this[FlagStrings.Skeleton] = true;
|
||||
(_inputs[FlagStrings.Skeleton] as FlagInput)?.SetValue(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
#pragma warning restore IDE0010
|
||||
}
|
||||
|
||||
string? readMethod = GetStringSetting(options, SettingConstants.ReadMethod, SettingConstants.ReadMethodDefault);
|
||||
|
||||
if (!string.IsNullOrEmpty(readMethod) && readMethod != ReadMethod.NONE.ToString())
|
||||
{
|
||||
this[FlagStrings.DriveReadMethod] = true;
|
||||
(_inputs[FlagStrings.DriveReadMethod] as StringInput)?.SetValue(readMethod!);
|
||||
}
|
||||
|
||||
int drivePregapStart = GetInt32Setting(options, SettingConstants.DrivePregapStart, SettingConstants.DrivePregapStartDefault);
|
||||
if (drivePregapStart != SettingConstants.DrivePregapStartDefault)
|
||||
{
|
||||
this[FlagStrings.DrivePregapStart] = true;
|
||||
(_inputs[FlagStrings.DrivePregapStart] as Int32Input)?.SetValue(drivePregapStart);
|
||||
}
|
||||
|
||||
string? sectorOrder = GetStringSetting(options, SettingConstants.SectorOrder, SettingConstants.SectorOrderDefault);
|
||||
if (!string.IsNullOrEmpty(sectorOrder) && sectorOrder != SectorOrder.NONE.ToString())
|
||||
{
|
||||
@@ -386,7 +412,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
}
|
||||
|
||||
int retries = GetInt32Setting(options, SettingConstants.RereadCount, SettingConstants.RereadCountDefault);
|
||||
if(retries > 0)
|
||||
if (retries > 0)
|
||||
{
|
||||
this[FlagStrings.Retries] = true;
|
||||
(_inputs[FlagStrings.Retries] as Int32Input)?.SetValue(retries);
|
||||
@@ -398,13 +424,17 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
this[FlagStrings.PlextorLeadinRetries] = true;
|
||||
(_inputs[FlagStrings.PlextorLeadinRetries] as Int32Input)?.SetValue(leadinRetries);
|
||||
}
|
||||
|
||||
if (GetBooleanSetting(options, SettingConstants.RefineSectorMode, SettingConstants.RefineSectorModeDefault))
|
||||
{
|
||||
this[FlagStrings.RefineSectorMode] = true;
|
||||
(_inputs[FlagStrings.RefineSectorMode] as FlagInput)?.SetValue(true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool ValidateAndSetParameters(string? parameters)
|
||||
{
|
||||
BaseCommand = CommandStrings.NONE;
|
||||
|
||||
// The string has to be valid by itself first
|
||||
if (string.IsNullOrEmpty(parameters))
|
||||
return false;
|
||||
@@ -413,7 +443,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
string[] parts = SplitParameterString(parameters!);
|
||||
|
||||
// Setup the modes
|
||||
ModeValue = null;
|
||||
BaseCommand = null;
|
||||
|
||||
// All modes should be cached separately
|
||||
int index = 0;
|
||||
@@ -440,21 +470,27 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
case CommandStrings.Info:
|
||||
case CommandStrings.Skeleton:
|
||||
case CommandStrings.FlashMT1339:
|
||||
case CommandStrings.FlashSD616:
|
||||
case CommandStrings.FlashPlextor:
|
||||
case CommandStrings.Subchannel:
|
||||
case CommandStrings.Debug:
|
||||
case CommandStrings.FixMSF:
|
||||
case CommandStrings.DebugFlip:
|
||||
case CommandStrings.DriveTest:
|
||||
// Only allow one mode per command
|
||||
if (ModeValue != null)
|
||||
if (BaseCommand is not null)
|
||||
continue;
|
||||
|
||||
ModeValue = part;
|
||||
BaseCommand = part;
|
||||
break;
|
||||
|
||||
// Default is either a flag or an invalid mode
|
||||
default:
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (part.StartsWith('-'))
|
||||
#else
|
||||
if (part.StartsWith("-"))
|
||||
#endif
|
||||
{
|
||||
isFlag = true;
|
||||
break;
|
||||
@@ -487,7 +523,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
|
||||
// If the image name was not set, set it with a default value
|
||||
if (string.IsNullOrEmpty((_inputs[FlagStrings.ImageName] as StringInput)?.Value))
|
||||
(_inputs[FlagStrings.ImageName] as StringInput)?.SetValue("track");
|
||||
(_inputs[FlagStrings.ImageName] as StringInput)?.SetValue($"track_{DateTime.Now:yyyyMMdd-HHmm}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -41,8 +41,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string PlextorSkipLeadin = "--plextor-skip-leadin";
|
||||
public const string PlextorLeadinRetries = "--plextor-leadin-retries";
|
||||
public const string PlextorLeadinForceStore = "--plextor-leadin-force-store";
|
||||
public const string AsusSkipLeadout = "--asus-skip-leadout";
|
||||
public const string AsusLeadoutRetries = "--asus-leadout-retries";
|
||||
public const string KreonPartialSS = "--kreon-partial-ss";
|
||||
public const string MediatekSkipLeadout = "--mediatek-skip-leadout";
|
||||
public const string MediatekLeadoutRetries = "--mediatek-leadout-retries";
|
||||
public const string DisableCDText = "--disable-cdtext";
|
||||
|
||||
#endregion
|
||||
@@ -62,7 +63,7 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string LeaveUnchanged = "--leave-unchanged";
|
||||
public const string ForceQTOC = "--force-qtoc";
|
||||
public const string SkipFill = "--skip-fill";
|
||||
public const string ISO9660Trim = "--iso9660-trim";
|
||||
public const string FilesystemTrim = "--filesystem-trim";
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -78,7 +79,9 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string Continue = "--continue";
|
||||
public const string LBAStart = "--lba-start";
|
||||
public const string LBAEnd = "--lba-end";
|
||||
public const string LBAEndBySubcode = "--lba-end-by-subcode";
|
||||
public const string RefineSubchannel = "--refine-subchannel";
|
||||
public const string RefineSectorMode = "--refine-sector-mode";
|
||||
public const string Skip = "--skip";
|
||||
public const string DumpWriteOffset = "--dump-write-offset";
|
||||
public const string DumpReadSize = "--dump-read-size";
|
||||
@@ -86,8 +89,10 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string ForceUnscrambled = "--force-unscrambled";
|
||||
public const string ForceRefine = "--force-refine";
|
||||
public const string Firmware = "--firmware";
|
||||
public const string ForceFlash = "--force-flash";
|
||||
public const string SkipSubcodeDesync = "--skip-subcode-desync";
|
||||
public const string Rings = "--rings";
|
||||
public const string CdrErrorThreshold = "--cdr-error-threshold";
|
||||
public const string ScsiTimeout = "--scsi-timeout";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -14,9 +14,15 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string LeadinRetryCount = "RedumperLeadinRetryCount";
|
||||
public const int LeadinRetryCountDefault = 4;
|
||||
|
||||
public const string DrivePregapStart = "RedumperDrivePregapStart";
|
||||
public const int DrivePregapStartDefault = 0;
|
||||
|
||||
public const string ReadMethod = "RedumperReadMethod";
|
||||
public static readonly string ReadMethodDefault = Redumper.ReadMethod.NONE.ToString();
|
||||
|
||||
public const string RefineSectorMode = "RedumperRefineSectorMode";
|
||||
public const bool RefineSectorModeDefault = false;
|
||||
|
||||
public const string RereadCount = "RedumperRereadCount";
|
||||
public const int RereadCountDefault = 20;
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace MPF.Frontend.Test
|
||||
public static List<object?[]> GenerateDriveTypeMappingTestData()
|
||||
{
|
||||
var testData = new List<object?[]>() { new object?[] { null, true } };
|
||||
foreach (DriveType driveType in Enum.GetValues(typeof(DriveType)))
|
||||
foreach (DriveType driveType in Enum.GetValues<DriveType>())
|
||||
{
|
||||
if (Array.IndexOf(_mappableDriveTypes, driveType) > -1)
|
||||
testData.Add([driveType, false]);
|
||||
|
||||
@@ -22,9 +22,15 @@ namespace MPF.Frontend.Test
|
||||
? Drive.Create(InternalDriveType.Floppy, letter.ToString())
|
||||
: Drive.Create(InternalDriveType.Optical, letter.ToString());
|
||||
|
||||
var env = new DumpEnvironment(options, string.Empty, drive, RedumpSystem.IBMPCcompatible, mediaType, null, parameters);
|
||||
var env = new DumpEnvironment(options,
|
||||
string.Empty,
|
||||
drive,
|
||||
RedumpSystem.IBMPCcompatible,
|
||||
null);
|
||||
env.SetExecutionContext(mediaType, parameters);
|
||||
env.SetProcessor();
|
||||
|
||||
bool actual = env.ParametersValid();
|
||||
bool actual = env.ParametersValid(mediaType);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
using LogCompression = MPF.Processors.LogCompression;
|
||||
using RedumperDriveType = MPF.ExecutionContexts.Redumper.DriveType;
|
||||
using RedumperReadMethod = MPF.ExecutionContexts.Redumper.ReadMethod;
|
||||
using RedumperSectorOrder = MPF.ExecutionContexts.Redumper.SectorOrder;
|
||||
@@ -13,11 +14,39 @@ namespace MPF.Frontend.Test
|
||||
{
|
||||
#region Long Name
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(InterfaceLanguage.AutoDetect, "Auto Detect")]
|
||||
[InlineData(InterfaceLanguage.English, "English")]
|
||||
[InlineData(InterfaceLanguage.French, "Français")]
|
||||
[InlineData(InterfaceLanguage.German, "Deutsch")]
|
||||
[InlineData(InterfaceLanguage.Italian, "Italiano")]
|
||||
[InlineData(InterfaceLanguage.Japanese, "日本語")]
|
||||
[InlineData(InterfaceLanguage.Korean, "한국어")]
|
||||
[InlineData(InterfaceLanguage.Polish, "Polski")]
|
||||
[InlineData(InterfaceLanguage.Russian, "Русский")]
|
||||
[InlineData(InterfaceLanguage.Spanish, "Español")]
|
||||
[InlineData(InterfaceLanguage.Swedish, "Svenska")]
|
||||
[InlineData(InterfaceLanguage.Ukrainian, "Українська")]
|
||||
[InlineData(InterfaceLanguage.L337, "L337")]
|
||||
public void LongName_InterfaceLanguage(InterfaceLanguage? lang, string? expected)
|
||||
{
|
||||
string? actual = lang.LongName();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
if (lang is not null)
|
||||
{
|
||||
actual = EnumExtensions.GetLongName(lang);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(InternalProgram.NONE, "Unknown")]
|
||||
[InlineData(InternalProgram.Aaru, "Aaru")]
|
||||
[InlineData(InternalProgram.DiscImageCreator, "DiscImageCreator")]
|
||||
// [InlineData(InternalProgram.Dreamdump, "Dreamdump")]
|
||||
[InlineData(InternalProgram.Redumper, "Redumper")]
|
||||
[InlineData(InternalProgram.CleanRip, "CleanRip")]
|
||||
[InlineData(InternalProgram.PS3CFW, "PS3 CFW")]
|
||||
@@ -27,6 +56,29 @@ namespace MPF.Frontend.Test
|
||||
{
|
||||
string? actual = prog.LongName();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
if (prog is not null)
|
||||
{
|
||||
actual = EnumExtensions.GetLongName(prog);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(LogCompression.DeflateDefault, "ZIP using Deflate (Level 5)")]
|
||||
[InlineData(LogCompression.DeflateMaximum, "ZIP using Deflate (Level 9)")]
|
||||
[InlineData(LogCompression.Zstd19, "ZIP using Zstd (Level 19)")]
|
||||
public void LongName_LogCompression(LogCompression? comp, string? expected)
|
||||
{
|
||||
string? actual = comp.LongName();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
if (comp is not null)
|
||||
{
|
||||
actual = EnumExtensions.GetLongName(comp);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -38,6 +90,12 @@ namespace MPF.Frontend.Test
|
||||
{
|
||||
string? actual = method.LongName();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
if (method is not null)
|
||||
{
|
||||
actual = EnumExtensions.GetLongName(method);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -51,6 +109,12 @@ namespace MPF.Frontend.Test
|
||||
{
|
||||
string? actual = order.LongName();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
if (order is not null)
|
||||
{
|
||||
actual = EnumExtensions.GetLongName(order);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -58,26 +122,54 @@ namespace MPF.Frontend.Test
|
||||
[InlineData(RedumperDriveType.NONE, "Default")]
|
||||
[InlineData(RedumperDriveType.GENERIC, "GENERIC")]
|
||||
[InlineData(RedumperDriveType.PLEXTOR, "PLEXTOR")]
|
||||
[InlineData(RedumperDriveType.LG_ASU8A, "LG_ASU8A")]
|
||||
[InlineData(RedumperDriveType.LG_ASU8B, "LG_ASU8B")]
|
||||
[InlineData(RedumperDriveType.LG_ASU8C, "LG_ASU8C")]
|
||||
[InlineData(RedumperDriveType.LG_ASU3, "LG_ASU3")]
|
||||
[InlineData(RedumperDriveType.LG_ASU2, "LG_ASU2")]
|
||||
[InlineData(RedumperDriveType.MTK8A, "MTK8A")]
|
||||
[InlineData(RedumperDriveType.MTK8B, "MTK8B")]
|
||||
[InlineData(RedumperDriveType.MTK8C, "MTK8C")]
|
||||
[InlineData(RedumperDriveType.MTK3, "MTK3")]
|
||||
[InlineData(RedumperDriveType.MTK2, "MTK2")]
|
||||
public void LongName_RedumperDriveType(RedumperDriveType? type, string? expected)
|
||||
{
|
||||
string? actual = type.LongName();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
if (type is not null)
|
||||
{
|
||||
actual = EnumExtensions.GetLongName(type);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Short Name
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(InterfaceLanguage.AutoDetect, "auto")]
|
||||
[InlineData(InterfaceLanguage.English, "eng")]
|
||||
[InlineData(InterfaceLanguage.French, "fra")]
|
||||
[InlineData(InterfaceLanguage.German, "deu")]
|
||||
[InlineData(InterfaceLanguage.Italian, "ita")]
|
||||
[InlineData(InterfaceLanguage.Japanese, "jpn")]
|
||||
[InlineData(InterfaceLanguage.Korean, "kor")]
|
||||
[InlineData(InterfaceLanguage.Polish, "pol")]
|
||||
[InlineData(InterfaceLanguage.Russian, "rus")]
|
||||
[InlineData(InterfaceLanguage.Spanish, "spa")]
|
||||
[InlineData(InterfaceLanguage.Swedish, "swe")]
|
||||
[InlineData(InterfaceLanguage.Ukrainian, "ukr")]
|
||||
[InlineData(InterfaceLanguage.L337, "l37")]
|
||||
public void ShortName_InterfaceLanguage(InterfaceLanguage? lang, string? expected)
|
||||
{
|
||||
string? actual = lang.ShortName();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(InternalProgram.NONE, "Unknown")]
|
||||
[InlineData(InternalProgram.Aaru, "aaru")]
|
||||
[InlineData(InternalProgram.DiscImageCreator, "dic")]
|
||||
// [InlineData(InternalProgram.Dreamdump, "dreamdump")]
|
||||
[InlineData(InternalProgram.Redumper, "redumper")]
|
||||
[InlineData(InternalProgram.CleanRip, "cleanrip")]
|
||||
[InlineData(InternalProgram.PS3CFW, "ps3cfw")]
|
||||
@@ -93,11 +185,34 @@ namespace MPF.Frontend.Test
|
||||
|
||||
#region From String
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, InterfaceLanguage.AutoDetect)]
|
||||
[InlineData("", InterfaceLanguage.AutoDetect)]
|
||||
[InlineData("auto", InterfaceLanguage.AutoDetect)]
|
||||
[InlineData("eng", InterfaceLanguage.English)]
|
||||
[InlineData("fra", InterfaceLanguage.French)]
|
||||
[InlineData("deu", InterfaceLanguage.German)]
|
||||
[InlineData("ita", InterfaceLanguage.Italian)]
|
||||
[InlineData("jpn", InterfaceLanguage.Japanese)]
|
||||
[InlineData("kor", InterfaceLanguage.Korean)]
|
||||
[InlineData("pol", InterfaceLanguage.Polish)]
|
||||
[InlineData("rus", InterfaceLanguage.Russian)]
|
||||
[InlineData("spa", InterfaceLanguage.Spanish)]
|
||||
[InlineData("swe", InterfaceLanguage.Swedish)]
|
||||
[InlineData("ukr", InterfaceLanguage.Ukrainian)]
|
||||
[InlineData("l37", InterfaceLanguage.L337)]
|
||||
public void ToInterfaceLanguageTest(string? interfaceLanguage, InterfaceLanguage expected)
|
||||
{
|
||||
InterfaceLanguage actual = interfaceLanguage.ToInterfaceLanguage();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, InternalProgram.NONE)]
|
||||
[InlineData("", InternalProgram.NONE)]
|
||||
[InlineData("aaru", InternalProgram.Aaru)]
|
||||
[InlineData("dic", InternalProgram.DiscImageCreator)]
|
||||
// [InlineData("dreamdump", InternalProgram.Dreamdump)]
|
||||
[InlineData("redumper", InternalProgram.Redumper)]
|
||||
[InlineData("cleanrip", InternalProgram.CleanRip)]
|
||||
[InlineData("ps3cfw", InternalProgram.PS3CFW)]
|
||||
@@ -123,6 +238,7 @@ namespace MPF.Frontend.Test
|
||||
private static readonly RedumpSystem?[] _copyProtectionSystems =
|
||||
[
|
||||
RedumpSystem.AppleMacintosh,
|
||||
RedumpSystem.DVDVideo,
|
||||
RedumpSystem.EnhancedCD ,
|
||||
RedumpSystem.IBMPCcompatible,
|
||||
RedumpSystem.PalmOS,
|
||||
@@ -150,7 +266,7 @@ namespace MPF.Frontend.Test
|
||||
public static List<object?[]> GenerateSupportsAntiModchipScansData()
|
||||
{
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues<RedumpSystem>())
|
||||
{
|
||||
if (_antiModchipSystems.Contains(redumpSystem))
|
||||
testData.Add([redumpSystem, true]);
|
||||
@@ -164,7 +280,7 @@ namespace MPF.Frontend.Test
|
||||
public static List<object?[]> GenerateSupportsCopyProtectionScansData()
|
||||
{
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues(typeof(RedumpSystem)))
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues<RedumpSystem>())
|
||||
{
|
||||
if (_copyProtectionSystems.Contains(redumpSystem))
|
||||
testData.Add([redumpSystem, true]);
|
||||
|
||||
@@ -13,12 +13,12 @@ namespace MPF.Frontend.Test
|
||||
[InlineData(MediaType.HDDVD, 24)]
|
||||
[InlineData(MediaType.BluRay, 16)]
|
||||
[InlineData(MediaType.NintendoWiiUOpticalDisc, 16)]
|
||||
[InlineData(MediaType.LaserDisc, 1)]
|
||||
[InlineData(null, 1)]
|
||||
[InlineData(MediaType.LaserDisc, 72)]
|
||||
[InlineData(null, 72)]
|
||||
public void GetAllowedDriveSpeedForMediaTypeTest(MediaType? mediaType, int maxExpected)
|
||||
{
|
||||
var actual = InterfaceConstants.GetSpeedsForMediaType(mediaType);
|
||||
Assert.Equal(maxExpected, actual[actual.Count - 1]);
|
||||
Assert.Equal(maxExpected, actual[^1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -14,13 +14,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.13.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.7" />
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="18.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.21.0" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.27.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" />
|
||||
@@ -29,7 +29,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -44,4 +44,4 @@ namespace MPF.Frontend.Test
|
||||
Assert.Equal(expectedValue, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,23 @@ namespace MPF.Frontend.Test
|
||||
{
|
||||
public class ResultEventArgsTests
|
||||
{
|
||||
[Fact]
|
||||
public void EmptyNeutralTest()
|
||||
{
|
||||
var actual = ResultEventArgs.Neutral();
|
||||
Assert.Null((bool?)actual);
|
||||
Assert.Empty(actual.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CustomMessageNeutralTest()
|
||||
{
|
||||
string message = "Success!";
|
||||
var actual = ResultEventArgs.Neutral(message);
|
||||
Assert.Null((bool?)actual);
|
||||
Assert.Equal(message, actual.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptySuccessTest()
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
[InlineData(MediaType.NintendoWiiUOpticalDisc, 16)]
|
||||
public void GetDefaultSpeedForMediaTypeTest(MediaType? mediaType, int expected)
|
||||
{
|
||||
Options options = new Options
|
||||
var options = new Options
|
||||
{
|
||||
PreferredDumpSpeedCD = 72,
|
||||
PreferredDumpSpeedDVD = 24,
|
||||
@@ -81,6 +81,8 @@ namespace MPF.Frontend.Test.Tools
|
||||
[InlineData("1.2.3.4..bin", true, "1.2.3.4..bin")]
|
||||
[InlineData("dir/filename.bin", false, "dir/filename.bin")]
|
||||
[InlineData("dir/filename.bin", true, "dir/filename.bin")]
|
||||
[InlineData(" dir / filename.bin", false, "dir/filename.bin")]
|
||||
[InlineData(" dir / filename.bin", true, "dir/filename.bin")]
|
||||
[InlineData("\0dir/\0filename.bin", false, "_dir/_filename.bin")]
|
||||
[InlineData("\0dir/\0filename.bin", true, "_dir/_filename.bin")]
|
||||
public void NormalizeOutputPathsTest(string? path, bool getFullPath, string expected)
|
||||
@@ -95,4 +97,4 @@ namespace MPF.Frontend.Test.Tools
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Data.Sections;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Frontend.Test.Tools
|
||||
{
|
||||
public class InfoToolTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null, "")]
|
||||
[InlineData(" ", " ")]
|
||||
[InlineData("super\\blah.bin", "super\\blah.bin")]
|
||||
[InlineData("super\\hero\\blah.bin", "super\\hero\\blah.bin")]
|
||||
[InlineData("super.hero\\blah.bin", "super.hero\\blah.bin")]
|
||||
[InlineData("superhero\\blah.rev.bin", "superhero\\blah.rev.bin")]
|
||||
[InlineData("super&hero\\blah.bin", "super&hero\\blah.bin")]
|
||||
[InlineData("superhero\\blah&foo.bin", "superhero\\blah&foo.bin")]
|
||||
public void NormalizeOutputPathsTest(string? outputPath, string? expectedPath)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(expectedPath))
|
||||
expectedPath = Path.GetFullPath(expectedPath);
|
||||
|
||||
string actualPath = FrontendTool.NormalizeOutputPaths(outputPath, true);
|
||||
Assert.Equal(expectedPath, actualPath);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsCompleteTest()
|
||||
public void ProcessSpecialFields_Complete()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
@@ -54,9 +35,9 @@ namespace MPF.Frontend.Test.Tools
|
||||
|
||||
// Validate the basics
|
||||
Assert.NotNull(info.CommonDiscInfo.Comments);
|
||||
Assert.Null(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.NotNull(info.CommonDiscInfo.Contents);
|
||||
Assert.Null(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
|
||||
// Split the values
|
||||
string[] splitComments = info.CommonDiscInfo.Comments.Split('\n');
|
||||
@@ -68,23 +49,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsNullObjectTest()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
{
|
||||
CommonDiscInfo = null,
|
||||
};
|
||||
|
||||
// Process the special fields
|
||||
Formatter.ProcessSpecialFields(info);
|
||||
|
||||
// Validate
|
||||
Assert.Null(info.CommonDiscInfo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsNullCommentsContentsTest()
|
||||
public void ProcessSpecialFields_NullStrings()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
@@ -110,9 +75,9 @@ namespace MPF.Frontend.Test.Tools
|
||||
|
||||
// Validate the basics
|
||||
Assert.NotNull(info.CommonDiscInfo.Comments);
|
||||
Assert.Null(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.NotNull(info.CommonDiscInfo.Contents);
|
||||
Assert.Null(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
|
||||
// Split the values
|
||||
string[] splitComments = info.CommonDiscInfo.Comments.Split('\n');
|
||||
@@ -124,7 +89,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsNullDictionariesTest()
|
||||
public void ProcessSpecialFields_EmptyDictionaries()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
@@ -132,10 +97,10 @@ namespace MPF.Frontend.Test.Tools
|
||||
CommonDiscInfo = new CommonDiscInfoSection()
|
||||
{
|
||||
Comments = "This is a comments line\n[T:ISBN] ISBN Value",
|
||||
CommentsSpecialFields = null,
|
||||
CommentsSpecialFields = [],
|
||||
|
||||
Contents = "This is a contents line\n[T:GF] Game Footage",
|
||||
ContentsSpecialFields = null,
|
||||
ContentsSpecialFields = [],
|
||||
}
|
||||
};
|
||||
|
||||
@@ -144,9 +109,9 @@ namespace MPF.Frontend.Test.Tools
|
||||
|
||||
// Validate the basics
|
||||
Assert.NotNull(info.CommonDiscInfo.Comments);
|
||||
Assert.Null(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.NotNull(info.CommonDiscInfo.Contents);
|
||||
Assert.Null(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
|
||||
// Split the values
|
||||
string[] splitComments = info.CommonDiscInfo.Comments.Split('\n');
|
||||
|
||||
@@ -8,12 +8,114 @@ namespace MPF.Frontend.Test.Tools
|
||||
{
|
||||
public class ProtectionToolTests
|
||||
{
|
||||
#region SanitizeContextSensitiveProtections
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_Empty_NoException()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_NoMatch_NoChange()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_Match_NoSub_NoChange()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
protections["File2"] = ["SecuROM Release Control - ANYTHING", "Protection 2"];
|
||||
protections["File3"] = ["Protection 1", "SecuROM Release Control -"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
Assert.Contains("File2", keys);
|
||||
Assert.Contains("File3", keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_Match_Sub_Change()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
protections["File2"] = ["SecuROM Release Control - ANYTHING"];
|
||||
protections["File2/FileA"] = ["ANYTHING GitHub ANYTHING"];
|
||||
protections["File2/FileB"] = ["SecuROM 7"];
|
||||
protections["File2/FileC"] = ["SecuROM 8"];
|
||||
protections["File2/FileD"] = ["SecuROM Content Activation"];
|
||||
protections["File2/FileE"] = ["SecuROM Data File Activation"];
|
||||
protections["File2/FileF"] = ["Unlock"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
Assert.Contains("File2", keys);
|
||||
Assert.Contains("File2/FileA", keys);
|
||||
Assert.DoesNotContain("File2/FileB", keys);
|
||||
Assert.DoesNotContain("File2/FileC", keys);
|
||||
Assert.DoesNotContain("File2/FileD", keys);
|
||||
Assert.DoesNotContain("File2/FileE", keys);
|
||||
Assert.DoesNotContain("File2/FileF", keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_MultiMatch_Sub_Change()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
protections["File2"] = ["SecuROM Release Control - ANYTHING"];
|
||||
protections["File2/FileA"] = ["ANYTHING GitHub ANYTHING"];
|
||||
protections["File2/FileB"] = ["SecuROM 7"];
|
||||
protections["File2/FileC"] = ["SecuROM 8"];
|
||||
protections["File3"] = ["SecuROM Release Control - ANYTHING"];
|
||||
protections["File3/FileD"] = ["SecuROM Content Activation"];
|
||||
protections["File3/FileE"] = ["SecuROM Data File Activation"];
|
||||
protections["File3/FileF"] = ["Unlock"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
Assert.Contains("File2", keys);
|
||||
Assert.Contains("File2/FileA", keys);
|
||||
Assert.DoesNotContain("File2/FileB", keys);
|
||||
Assert.DoesNotContain("File2/FileC", keys);
|
||||
Assert.Contains("File3", keys);
|
||||
Assert.DoesNotContain("File3/FileD", keys);
|
||||
Assert.DoesNotContain("File3/FileE", keys);
|
||||
Assert.DoesNotContain("File3/FileF", keys);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SanitizeFoundProtections
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_Exception()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Anything Else Protection",
|
||||
"[Access issue when opening file",
|
||||
"[Exception opening file",
|
||||
];
|
||||
|
||||
@@ -261,6 +363,19 @@ namespace MPF.Frontend.Test.Tools
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_MPRESS()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"MPRESS",
|
||||
"MPRESS ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_NeoLite()
|
||||
{
|
||||
@@ -559,7 +674,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
throw new ArgumentException("Invalid skip value", nameof(skip));
|
||||
|
||||
// The list is in order of preference
|
||||
protections = protections.Skip(skip).ToList();
|
||||
protections = [.. protections.Skip(skip)];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(protections[0], sanitized);
|
||||
@@ -581,9 +696,9 @@ namespace MPF.Frontend.Test.Tools
|
||||
[Theory]
|
||||
[InlineData(0, "Macrovision Protected Application [SafeDisc 0.00.000], SafeDisc 0.00.000, SafeDisc Lite")]
|
||||
[InlineData(1, "Macrovision Protected Application [SafeDisc 0.00.000 / SRV Tool APP], SafeDisc 0.00.000, SafeDisc Lite")]
|
||||
[InlineData(2, "Macrovision Security Driver, Macrovision Security Driver [SafeDisc 1.11.111], SafeDisc 0.00.000, SafeDisc 0.00.000-1.11.111, SafeDisc Lite")]
|
||||
[InlineData(3, "Macrovision Security Driver, Macrovision Security Driver [SafeDisc 1.11.111], SafeDisc 0.00.000, SafeDisc Lite")]
|
||||
[InlineData(4, "Macrovision Security Driver, Macrovision Security Driver [SafeDisc 1.11.111], SafeDisc Lite")]
|
||||
[InlineData(2, "SafeDisc 0.00.000, SafeDisc 0.00.000-1.11.111, SafeDisc 3+ (DVD), SafeDisc Lite")]
|
||||
[InlineData(3, "SafeDisc 0.00.000, SafeDisc 3+ (DVD), SafeDisc Lite")]
|
||||
[InlineData(4, "SafeDisc 3+ (DVD), SafeDisc Lite")]
|
||||
[InlineData(5, "Macrovision Security Driver, SafeDisc Lite")]
|
||||
[InlineData(6, "Macrovision Protection File, SafeDisc 2+, SafeDisc 3+ (DVD), SafeDisc Lite")]
|
||||
[InlineData(7, "SafeDisc 3+ (DVD)")]
|
||||
@@ -592,11 +707,11 @@ namespace MPF.Frontend.Test.Tools
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Macrovision Protected Application [SafeDisc 0.00.000]",
|
||||
"Macrovision Protected Application [SafeDisc 0.00.000]",
|
||||
"Macrovision Protected Application [SafeDisc 0.00.000 / SRV Tool APP]",
|
||||
"SafeDisc 0.00.000-1.11.111",
|
||||
"SafeDisc 0.00.000",
|
||||
"Macrovision Security Driver [SafeDisc 1.11.111]",
|
||||
"Macrovision Security Driver 1.11.111 / SafeDisc 1.11.111",
|
||||
"Macrovision Security Driver",
|
||||
"SafeDisc Lite",
|
||||
"SafeDisc 3+ (DVD)",
|
||||
@@ -609,12 +724,44 @@ namespace MPF.Frontend.Test.Tools
|
||||
throw new ArgumentException("Invalid skip value", nameof(skip));
|
||||
|
||||
// The list is in order of preference
|
||||
protections = protections.Skip(skip).ToList();
|
||||
protections = [.. protections.Skip(skip)];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(expected, sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectsion_SafeDisc_MacrovisionSecurityDriver()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Macrovision Protection File [Likely indicates either SafeDisc 1.45.011+ (CD) or CDS-300]",
|
||||
"Macrovision Security Driver 4.00.060 / SafeDisc 4.00.000-4.70.000",
|
||||
"SafeDisc 4.00.000-4.00.003",
|
||||
"SafeDisc 4.00.002, Macrovision Protected Application"
|
||||
];
|
||||
|
||||
string expected = "SafeDisc 4.00.002";
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(expected, sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_SecuROM()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"SecuROM Release Control",
|
||||
"SecuROM Release Control - ANYTHING",
|
||||
"SecuROM Release Control - ANYTHING ELSE",
|
||||
"SecuROM Release Control - EVEN MORE",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("SecuROM Release Control", sanitized);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(1)]
|
||||
@@ -636,12 +783,27 @@ namespace MPF.Frontend.Test.Tools
|
||||
throw new ArgumentException("Invalid skip value", nameof(skip));
|
||||
|
||||
// The list is in order of preference
|
||||
protections = protections.Skip(skip).ToList();
|
||||
protections = [.. protections.Skip(skip)];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(protections[0], sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_StarForce_Keyless()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"StarForce Keyless",
|
||||
"StarForce Keyless - ",
|
||||
"StarForce Keyless - ESPY97LS8FHNYR52JDWL8D6FJ",
|
||||
"StarForce Keyless - UAYA-RPMVHJ-ZRY45G-ETUJ36-WL922B",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("StarForce Keyless", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_Sysiphus()
|
||||
{
|
||||
@@ -669,5 +831,7 @@ namespace MPF.Frontend.Test.Tools
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,18 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
/// <summary>
|
||||
/// A generic combo box element
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Enum type representing the possible values</typeparam>
|
||||
public class Element<T> : IEquatable<Element<T>>, IElement where T : struct, Enum
|
||||
/// <typeparam name="TEnum">Enum type representing the possible values</typeparam>
|
||||
public class Element<TEnum> : IEquatable<Element<TEnum>>, IElement where TEnum : struct, Enum
|
||||
{
|
||||
private readonly T Data;
|
||||
private readonly TEnum Data;
|
||||
|
||||
public Element(T data) => Data = data;
|
||||
public Element(TEnum data) => Data = data;
|
||||
|
||||
/// <summary>
|
||||
/// Allow elements to be used as their internal enum type
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public static implicit operator T? (Element<T> item) => item?.Data;
|
||||
public static implicit operator TEnum?(Element<TEnum> item) => item?.Data;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string Name => EnumExtensions.GetLongName(Data);
|
||||
@@ -27,7 +27,7 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
/// <summary>
|
||||
/// Internal enum value
|
||||
/// </summary>
|
||||
public T Value => Data;
|
||||
public TEnum Value => Data;
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the item is selected or not
|
||||
@@ -39,22 +39,22 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
/// Generate all elements associated with the data enum type
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<Element<T>> GenerateElements()
|
||||
public static List<Element<TEnum>> GenerateElements()
|
||||
{
|
||||
var enumArr = (T[])Enum.GetValues(typeof(T));
|
||||
return [.. Array.ConvertAll(enumArr, e => new Element<T>(e))];
|
||||
var enumArr = (TEnum[])Enum.GetValues(typeof(TEnum));
|
||||
return [.. Array.ConvertAll(enumArr, e => new Element<TEnum>(e))];
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return Equals(obj as Element<T>);
|
||||
return Equals(obj as Element<TEnum>);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(Element<T>? other)
|
||||
public bool Equals(Element<TEnum>? other)
|
||||
{
|
||||
if (other == null)
|
||||
if (other is null)
|
||||
return false;
|
||||
|
||||
return Name == other.Name;
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
/// <summary>
|
||||
/// Display name for the combo box element
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
public string Name { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
|
||||
var systemsValues = new List<RedumpSystemComboBoxItem>
|
||||
{
|
||||
new RedumpSystemComboBoxItem((RedumpSystem?)null),
|
||||
new((RedumpSystem?)null),
|
||||
};
|
||||
|
||||
foreach (var group in mapping)
|
||||
@@ -105,7 +105,7 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(RedumpSystemComboBoxItem? other)
|
||||
{
|
||||
if (other == null)
|
||||
if (other is null)
|
||||
return false;
|
||||
|
||||
return Value == other.Value;
|
||||
|
||||
@@ -10,7 +10,14 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public static void ProgressUpdated(object? sender, ResultEventArgs value)
|
||||
{
|
||||
Console.WriteLine(value.Message);
|
||||
string prefix = (bool?)value switch
|
||||
{
|
||||
true => "SUCCESS: ",
|
||||
false => "FAILURE: ",
|
||||
_ => "",
|
||||
};
|
||||
|
||||
Console.WriteLine($"{prefix}{value.Message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -86,11 +86,15 @@ namespace MPF.Frontend
|
||||
|
||||
// Sanitize a Windows-formatted long device path
|
||||
if (devicePath.StartsWith("\\\\.\\"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
devicePath = devicePath["\\\\.\\".Length..];
|
||||
#else
|
||||
devicePath = devicePath.Substring("\\\\.\\".Length);
|
||||
#endif
|
||||
|
||||
// Create and validate the drive info object
|
||||
var driveInfo = new DriveInfo(devicePath);
|
||||
if (driveInfo == null || driveInfo == default)
|
||||
if (driveInfo is null || driveInfo == default)
|
||||
return null;
|
||||
|
||||
// Fill in the rest of the data
|
||||
@@ -106,7 +110,7 @@ namespace MPF.Frontend
|
||||
private void PopulateFromDriveInfo(DriveInfo? driveInfo)
|
||||
{
|
||||
// If we have an invalid DriveInfo, just return
|
||||
if (driveInfo == null || driveInfo == default)
|
||||
if (driveInfo is null || driveInfo == default)
|
||||
return;
|
||||
|
||||
// Populate the data fields
|
||||
@@ -138,8 +142,8 @@ namespace MPF.Frontend
|
||||
var drives = GetDriveList(ignoreFixedDrives);
|
||||
drives.Sort((d1, d2) =>
|
||||
{
|
||||
string d1Name = d1?.Name == null ? "\0" : d1.Name;
|
||||
string d2Name = d2?.Name == null ? "\0" : d2.Name;
|
||||
string d1Name = d1?.Name is null ? "\0" : d1.Name;
|
||||
string d2Name = d2?.Name is null ? "\0" : d2.Name;
|
||||
return d1Name.CompareTo(d2Name);
|
||||
});
|
||||
return [.. drives];
|
||||
@@ -152,6 +156,7 @@ namespace MPF.Frontend
|
||||
/// <returns>The detected media type, if possible</returns>
|
||||
public MediaType? GetMediaType(RedumpSystem? system)
|
||||
{
|
||||
#pragma warning disable IDE0010
|
||||
// Take care of the non-optical stuff first
|
||||
switch (InternalDriveType)
|
||||
{
|
||||
@@ -211,6 +216,7 @@ namespace MPF.Frontend
|
||||
case RedumpSystem.SonyPlayStationPortable:
|
||||
return MediaType.UMD;
|
||||
}
|
||||
#pragma warning restore IDE0010
|
||||
|
||||
// Handle optical media by size and filesystem
|
||||
if (TotalSize >= 0 && TotalSize <= 800_000_000 && (DriveFormat == "CDFS" || DriveFormat == "UDF"))
|
||||
@@ -282,12 +288,12 @@ namespace MPF.Frontend
|
||||
{
|
||||
CimKeyedCollection<CimProperty> properties = instance.CimInstanceProperties;
|
||||
uint? mediaType = properties["MediaType"]?.Value as uint?;
|
||||
if (mediaType != null && ((mediaType > 0 && mediaType < 11) || (mediaType > 12 && mediaType < 22)))
|
||||
if (mediaType is not null && ((mediaType > 0 && mediaType < 11) || (mediaType > 12 && mediaType < 22)))
|
||||
{
|
||||
char devId = (properties["Caption"].Value as string ?? string.Empty)[0];
|
||||
Array.ForEach(drives, d =>
|
||||
{
|
||||
if (d?.Name != null && d.Name[0] == devId)
|
||||
if (d?.Name is not null && d.Name[0] == devId)
|
||||
d.InternalDriveType = Frontend.InternalDriveType.Floppy;
|
||||
});
|
||||
}
|
||||
@@ -309,6 +315,7 @@ namespace MPF.Frontend
|
||||
/// <returns>InternalDriveType, if possible, null on error</returns>
|
||||
internal static InternalDriveType? ToInternalDriveType(DriveType driveType)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
return driveType switch
|
||||
{
|
||||
DriveType.CDRom => (InternalDriveType?)Frontend.InternalDriveType.Optical,
|
||||
@@ -316,6 +323,7 @@ namespace MPF.Frontend
|
||||
DriveType.Removable => (InternalDriveType?)Frontend.InternalDriveType.Removable,
|
||||
_ => null,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -61,11 +61,6 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
private readonly RedumpSystem? _system;
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected media type
|
||||
/// </summary>
|
||||
private readonly MediaType? _type;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Passthrough Fields
|
||||
@@ -86,11 +81,7 @@ namespace MPF.Frontend
|
||||
public int? Speed
|
||||
{
|
||||
get => _executionContext?.Speed;
|
||||
set
|
||||
{
|
||||
if (_executionContext != null)
|
||||
_executionContext.Speed = value;
|
||||
}
|
||||
set => _executionContext?.Speed = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Extensions.LongName(RedumpSystem?)/>
|
||||
@@ -114,16 +105,12 @@ namespace MPF.Frontend
|
||||
/// <param name="outputPath"></param>
|
||||
/// <param name="drive"></param>
|
||||
/// <param name="system"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="internalProgram"></param>
|
||||
/// <param name="parameters"></param>
|
||||
public DumpEnvironment(Options options,
|
||||
string? outputPath,
|
||||
Drive? drive,
|
||||
RedumpSystem? system,
|
||||
MediaType? type,
|
||||
InternalProgram? internalProgram,
|
||||
string? parameters)
|
||||
InternalProgram? internalProgram)
|
||||
{
|
||||
// Set options object
|
||||
_options = options;
|
||||
@@ -134,12 +121,7 @@ namespace MPF.Frontend
|
||||
// UI information
|
||||
_drive = drive;
|
||||
_system = system ?? options.DefaultSystem;
|
||||
_type = type ?? MediaType.NONE;
|
||||
_internalProgram = internalProgram ?? options.InternalProgram;
|
||||
|
||||
// Dumping program
|
||||
SetExecutionContext(parameters);
|
||||
SetProcessor();
|
||||
}
|
||||
|
||||
#region Internal Program Management
|
||||
@@ -147,93 +129,116 @@ namespace MPF.Frontend
|
||||
/// <summary>
|
||||
/// Check output path for matching logs from all dumping programs
|
||||
/// </summary>
|
||||
public InternalProgram? CheckForMatchingProgram(string? outputDirectory, string outputFilename)
|
||||
public InternalProgram? CheckForMatchingProgram(MediaType? mediaType, string? outputDirectory, string outputFilename)
|
||||
{
|
||||
// If a complete dump exists from a different program
|
||||
InternalProgram? programFound = null;
|
||||
if (programFound == null && _internalProgram != InternalProgram.Redumper)
|
||||
if (programFound is null && _internalProgram != InternalProgram.Redumper)
|
||||
{
|
||||
var processor = new Processors.Redumper(_system, _type);
|
||||
var missingFiles = processor.FoundAllFiles(outputDirectory, outputFilename);
|
||||
var processor = new Redumper(_system);
|
||||
var missingFiles = processor.FoundAllFiles(mediaType, outputDirectory, outputFilename);
|
||||
if (missingFiles.Count == 0)
|
||||
programFound = InternalProgram.Redumper;
|
||||
}
|
||||
if (programFound == null && _internalProgram != InternalProgram.DiscImageCreator)
|
||||
|
||||
if (programFound is null && _internalProgram != InternalProgram.DiscImageCreator)
|
||||
{
|
||||
var processor = new Processors.DiscImageCreator(_system, _type);
|
||||
var missingFiles = processor.FoundAllFiles(outputDirectory, outputFilename);
|
||||
var processor = new DiscImageCreator(_system);
|
||||
var missingFiles = processor.FoundAllFiles(mediaType, outputDirectory, outputFilename);
|
||||
if (missingFiles.Count == 0)
|
||||
programFound = InternalProgram.DiscImageCreator;
|
||||
}
|
||||
if (programFound == null && _internalProgram != InternalProgram.Aaru)
|
||||
|
||||
if (programFound is null && _internalProgram != InternalProgram.Aaru)
|
||||
{
|
||||
var processor = new Processors.Aaru(_system, _type);
|
||||
var missingFiles = processor.FoundAllFiles(outputDirectory, outputFilename);
|
||||
var processor = new Aaru(_system);
|
||||
var missingFiles = processor.FoundAllFiles(mediaType, outputDirectory, outputFilename);
|
||||
if (missingFiles.Count == 0)
|
||||
programFound = InternalProgram.Aaru;
|
||||
}
|
||||
|
||||
// if (programFound is null && _internalProgram != InternalProgram.Dreamdump)
|
||||
// {
|
||||
// var processor = new Dreamdump(_system);
|
||||
// var missingFiles = processor.FoundAllFiles(mediaType, outputDirectory, outputFilename);
|
||||
// if (missingFiles.Count == 0)
|
||||
// programFound = InternalProgram.Dreamdump;
|
||||
// }
|
||||
|
||||
return programFound;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check output path for partial logs from all dumping programs
|
||||
/// </summary>
|
||||
public InternalProgram? CheckForPartialProgram(string? outputDirectory, string outputFilename)
|
||||
public InternalProgram? CheckForPartialProgram(MediaType? mediaType, string? outputDirectory, string outputFilename)
|
||||
{
|
||||
// If a complete dump exists from a different program
|
||||
InternalProgram? programFound = null;
|
||||
if (programFound == null && _internalProgram != InternalProgram.Redumper)
|
||||
if (programFound is null && _internalProgram != InternalProgram.Redumper)
|
||||
{
|
||||
var processor = new Processors.Redumper(_system, _type);
|
||||
if (processor.FoundAnyFiles(outputDirectory, outputFilename))
|
||||
var processor = new Redumper(_system);
|
||||
if (processor.FoundAnyFiles(mediaType, outputDirectory, outputFilename))
|
||||
programFound = InternalProgram.Redumper;
|
||||
}
|
||||
if (programFound == null && _internalProgram != InternalProgram.DiscImageCreator)
|
||||
|
||||
if (programFound is null && _internalProgram != InternalProgram.DiscImageCreator)
|
||||
{
|
||||
var processor = new Processors.DiscImageCreator(_system, _type);
|
||||
if (processor.FoundAnyFiles(outputDirectory, outputFilename))
|
||||
var processor = new DiscImageCreator(_system);
|
||||
if (processor.FoundAnyFiles(mediaType, outputDirectory, outputFilename))
|
||||
programFound = InternalProgram.DiscImageCreator;
|
||||
}
|
||||
if (programFound == null && _internalProgram != InternalProgram.Aaru)
|
||||
|
||||
if (programFound is null && _internalProgram != InternalProgram.Aaru)
|
||||
{
|
||||
var processor = new Processors.Aaru(_system, _type);
|
||||
if (processor.FoundAnyFiles(outputDirectory, outputFilename))
|
||||
var processor = new Aaru(_system);
|
||||
if (processor.FoundAnyFiles(mediaType, outputDirectory, outputFilename))
|
||||
programFound = InternalProgram.Aaru;
|
||||
}
|
||||
|
||||
// if (programFound is null && _internalProgram != InternalProgram.Dreamdump)
|
||||
// {
|
||||
// var processor = new Dreamdump(_system);
|
||||
// if (processor.FoundAnyFiles(mediaType, outputDirectory, outputFilename))
|
||||
// programFound = InternalProgram.Dreamdump;
|
||||
// }
|
||||
|
||||
return programFound;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the parameters object based on the internal program and parameters string
|
||||
/// </summary>
|
||||
/// <param name="mediaType">MediaType for specialized dumping parameters</param>
|
||||
/// <param name="parameters">String representation of the parameters</param>
|
||||
public bool SetExecutionContext(string? parameters)
|
||||
public bool SetExecutionContext(MediaType? mediaType, string? parameters)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
_executionContext = _internalProgram switch
|
||||
{
|
||||
InternalProgram.Aaru => new ExecutionContexts.Aaru.ExecutionContext(parameters) { ExecutablePath = _options.AaruPath },
|
||||
InternalProgram.DiscImageCreator => new ExecutionContexts.DiscImageCreator.ExecutionContext(parameters) { ExecutablePath = _options.DiscImageCreatorPath },
|
||||
// InternalProgram.Dreamdump => new ExecutionContexts.Dreamdump.ExecutionContext(parameters) { ExecutablePath = _options.DreamdumpPath },
|
||||
InternalProgram.Redumper => new ExecutionContexts.Redumper.ExecutionContext(parameters) { ExecutablePath = _options.RedumperPath },
|
||||
|
||||
// If no dumping program found, set to null
|
||||
InternalProgram.NONE => null,
|
||||
_ => null,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
|
||||
// Set system, type, and drive
|
||||
if (_executionContext != null)
|
||||
if (_executionContext is not null)
|
||||
{
|
||||
_executionContext.RedumpSystem = _system;
|
||||
_executionContext.MediaType = _type;
|
||||
_executionContext.MediaType = mediaType;
|
||||
|
||||
// Set some parameters, if not already set
|
||||
OutputPath ??= _executionContext.OutputPath!;
|
||||
_drive ??= Drive.Create(InternalDriveType.Optical, _executionContext.InputPath!);
|
||||
}
|
||||
|
||||
return _executionContext != null;
|
||||
return _executionContext is not null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -243,47 +248,52 @@ namespace MPF.Frontend
|
||||
{
|
||||
_processor = _internalProgram switch
|
||||
{
|
||||
InternalProgram.Aaru => new Processors.Aaru(_system, _type),
|
||||
InternalProgram.CleanRip => new CleanRip(_system, _type),
|
||||
InternalProgram.DiscImageCreator => new DiscImageCreator(_system, _type),
|
||||
InternalProgram.PS3CFW => new PS3CFW(_system, _type),
|
||||
InternalProgram.Redumper => new Redumper(_system, _type),
|
||||
InternalProgram.UmdImageCreator => new UmdImageCreator(_system, _type),
|
||||
InternalProgram.XboxBackupCreator => new XboxBackupCreator(_system, _type),
|
||||
InternalProgram.Aaru => new Aaru(_system),
|
||||
InternalProgram.CleanRip => new CleanRip(_system),
|
||||
InternalProgram.DiscImageCreator => new DiscImageCreator(_system),
|
||||
// InternalProgram.Dreamdump => new Dreamdump(_system),
|
||||
InternalProgram.PS3CFW => new PS3CFW(_system),
|
||||
InternalProgram.Redumper => new Redumper(_system),
|
||||
InternalProgram.UmdImageCreator => new UmdImageCreator(_system),
|
||||
InternalProgram.XboxBackupCreator => new XboxBackupCreator(_system),
|
||||
|
||||
// If no dumping program found, set to null
|
||||
InternalProgram.NONE => null,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
return _processor != null;
|
||||
return _processor is not null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the full parameter string for either DiscImageCreator or Aaru
|
||||
/// </summary>
|
||||
/// <param name="mediaType">MediaType for specialized dumping parameters</param>
|
||||
/// <param name="driveSpeed">Nullable int representing the drive speed</param>
|
||||
/// <returns>String representing the params, null on error</returns>
|
||||
public string? GetFullParameters(int? driveSpeed)
|
||||
public string? GetFullParameters(MediaType? mediaType, int? driveSpeed)
|
||||
{
|
||||
// Populate with the correct params for inputs (if we're not on the default option)
|
||||
if (_system != null && _type != MediaType.NONE)
|
||||
if (_system is not null && mediaType != MediaType.NONE)
|
||||
{
|
||||
// If drive letter is invalid, skip this
|
||||
if (_drive == null)
|
||||
if (_drive is null)
|
||||
return null;
|
||||
|
||||
#pragma warning disable IDE0072
|
||||
// Set the proper parameters
|
||||
_executionContext = _internalProgram switch
|
||||
{
|
||||
InternalProgram.Aaru => new ExecutionContexts.Aaru.ExecutionContext(_system, _type, _drive.Name, OutputPath, driveSpeed, _options.Settings),
|
||||
InternalProgram.DiscImageCreator => new ExecutionContexts.DiscImageCreator.ExecutionContext(_system, _type, _drive.Name, OutputPath, driveSpeed, _options.Settings),
|
||||
InternalProgram.Redumper => new ExecutionContexts.Redumper.ExecutionContext(_system, _type, _drive.Name, OutputPath, driveSpeed, _options.Settings),
|
||||
InternalProgram.Aaru => new ExecutionContexts.Aaru.ExecutionContext(_system, mediaType, _drive.Name, OutputPath, driveSpeed, _options.Settings),
|
||||
InternalProgram.DiscImageCreator => new ExecutionContexts.DiscImageCreator.ExecutionContext(_system, mediaType, _drive.Name, OutputPath, driveSpeed, _options.Settings),
|
||||
// InternalProgram.Dreamdump => new ExecutionContexts.Dreamdump.ExecutionContext(_system, mediaType, _drive.Name, OutputPath, driveSpeed, _options.Settings),
|
||||
InternalProgram.Redumper => new ExecutionContexts.Redumper.ExecutionContext(_system, mediaType, _drive.Name, OutputPath, driveSpeed, _options.Settings),
|
||||
|
||||
// If no dumping program found, set to null
|
||||
InternalProgram.NONE => null,
|
||||
_ => null,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
|
||||
// Generate and return the param string
|
||||
return _executionContext?.GenerateParameters();
|
||||
@@ -304,9 +314,10 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType value to check</param>
|
||||
/// <returns>True if the media has variable dumping speeds, false otherwise</returns>
|
||||
public bool DoesSupportDriveSpeed()
|
||||
public static bool DoesSupportDriveSpeed(MediaType? mediaType)
|
||||
{
|
||||
return _type switch
|
||||
#pragma warning disable IDE0072
|
||||
return mediaType switch
|
||||
{
|
||||
MediaType.CDROM
|
||||
or MediaType.DVD
|
||||
@@ -318,30 +329,31 @@ namespace MPF.Frontend
|
||||
or MediaType.NintendoWiiUOpticalDisc => true,
|
||||
_ => false,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="BaseProcessor.FoundAllFiles(string?, string)"/>
|
||||
public bool FoundAllFiles(string? outputDirectory, string outputFilename)
|
||||
/// <inheritdoc cref="BaseProcessor.FoundAllFiles(MediaType?, string?, string)"/>
|
||||
public bool FoundAllFiles(MediaType? mediaType, string? outputDirectory, string outputFilename)
|
||||
{
|
||||
if (_processor == null)
|
||||
if (_processor is null)
|
||||
return false;
|
||||
|
||||
return _processor.FoundAllFiles(outputDirectory, outputFilename).Count == 0;
|
||||
return _processor.FoundAllFiles(mediaType, outputDirectory, outputFilename).Count == 0;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="BaseProcessor.FoundAnyFiles(string?, string)"/>
|
||||
public bool FoundAnyFiles(string? outputDirectory, string outputFilename)
|
||||
/// <inheritdoc cref="BaseProcessor.FoundAnyFiles(MediaType?, string?, string)"/>
|
||||
public bool FoundAnyFiles(MediaType? mediaType, string? outputDirectory, string outputFilename)
|
||||
{
|
||||
if (_processor == null)
|
||||
if (_processor is null)
|
||||
return false;
|
||||
|
||||
return _processor.FoundAnyFiles(outputDirectory, outputFilename);
|
||||
return _processor.FoundAnyFiles(mediaType, outputDirectory, outputFilename);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="BaseExecutionContext.GetDefaultExtension(MediaType?)"/>
|
||||
public string? GetDefaultExtension(MediaType? mediaType)
|
||||
{
|
||||
if (_executionContext == null)
|
||||
if (_executionContext is null)
|
||||
return null;
|
||||
|
||||
return _executionContext.GetDefaultExtension(mediaType);
|
||||
@@ -350,7 +362,7 @@ namespace MPF.Frontend
|
||||
/// <inheritdoc cref="BaseExecutionContext.GetMediaType()"/>
|
||||
public MediaType? GetMediaType()
|
||||
{
|
||||
if (_executionContext == null)
|
||||
if (_executionContext is null)
|
||||
return null;
|
||||
|
||||
return _executionContext.GetMediaType();
|
||||
@@ -359,15 +371,19 @@ namespace MPF.Frontend
|
||||
/// <summary>
|
||||
/// Verify that, given a system and a media type, they are correct
|
||||
/// </summary>
|
||||
public ResultEventArgs GetSupportStatus()
|
||||
public ResultEventArgs GetSupportStatus(MediaType? mediaType)
|
||||
{
|
||||
// No system chosen, update status
|
||||
if (_system == null)
|
||||
if (_system is null)
|
||||
return ResultEventArgs.Failure("Please select a valid system");
|
||||
|
||||
#pragma warning disable IDE0072
|
||||
// If we're on an unsupported type, update the status accordingly
|
||||
return _type switch
|
||||
return mediaType switch
|
||||
{
|
||||
// Null means it will be handled by the program
|
||||
null => ResultEventArgs.Success("Ready to dump"),
|
||||
|
||||
// Fully supported types
|
||||
MediaType.BluRay
|
||||
or MediaType.CDROM
|
||||
@@ -377,29 +393,30 @@ namespace MPF.Frontend
|
||||
or MediaType.CompactFlash
|
||||
or MediaType.SDCard
|
||||
or MediaType.FlashDrive
|
||||
or MediaType.HDDVD => ResultEventArgs.Success($"{_type.LongName()} ready to dump"),
|
||||
or MediaType.HDDVD => ResultEventArgs.Success($"{mediaType.LongName()} ready to dump"),
|
||||
|
||||
// Partially supported types
|
||||
MediaType.GDROM
|
||||
or MediaType.NintendoGameCubeGameDisc
|
||||
or MediaType.NintendoWiiOpticalDisc
|
||||
or MediaType.NintendoWiiUOpticalDisc => ResultEventArgs.Success($"{_type.LongName()} partially supported for dumping"),
|
||||
or MediaType.NintendoWiiUOpticalDisc => ResultEventArgs.Success($"{mediaType.LongName()} partially supported for dumping"),
|
||||
|
||||
// Special case for other supported tools
|
||||
MediaType.UMD => ResultEventArgs.Failure($"{_type.LongName()} supported for submission info parsing"),
|
||||
MediaType.UMD => ResultEventArgs.Failure($"{mediaType.LongName()} supported for submission info parsing"),
|
||||
|
||||
// Specifically unknown type
|
||||
MediaType.NONE => ResultEventArgs.Failure($"Please select a valid media type"),
|
||||
MediaType.NONE => ResultEventArgs.Failure("Please select a valid media type"),
|
||||
|
||||
// Undumpable but recognized types
|
||||
_ => ResultEventArgs.Failure($"{_type.LongName()} media are not supported for dumping"),
|
||||
_ => ResultEventArgs.Failure($"{mediaType.LongName()} media are not supported for dumping"),
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="BaseExecutionContext.IsDumpingCommand()"/>
|
||||
public bool IsDumpingCommand()
|
||||
{
|
||||
if (_executionContext == null)
|
||||
if (_executionContext is null)
|
||||
return false;
|
||||
|
||||
return _executionContext.IsDumpingCommand();
|
||||
@@ -420,15 +437,16 @@ namespace MPF.Frontend
|
||||
/// <summary>
|
||||
/// Execute the initial invocation of the dumping programs
|
||||
/// </summary>
|
||||
/// <param name="mediaType">MediaType for specialized dumping parameters</param>
|
||||
/// <param name="progress">Optional result progress callback</param>
|
||||
public async Task<ResultEventArgs> Run(IProgress<ResultEventArgs>? progress = null)
|
||||
public async Task<ResultEventArgs> Run(MediaType? mediaType, IProgress<ResultEventArgs>? progress = null)
|
||||
{
|
||||
// If we don't have parameters
|
||||
if (_executionContext == null)
|
||||
if (_executionContext is null)
|
||||
return ResultEventArgs.Failure("Error! Current configuration is not supported!");
|
||||
|
||||
// Build default console progress indicators if none exist
|
||||
if (progress == null)
|
||||
if (progress is null)
|
||||
{
|
||||
var temp = new Progress<ResultEventArgs>();
|
||||
temp.ProgressChanged += ConsoleLogger.ProgressUpdated;
|
||||
@@ -436,12 +454,12 @@ namespace MPF.Frontend
|
||||
}
|
||||
|
||||
// Check that we have the basics for dumping
|
||||
ResultEventArgs result = IsValidForDump();
|
||||
if (!result)
|
||||
ResultEventArgs result = IsValidForDump(mediaType);
|
||||
if (result == false)
|
||||
return result;
|
||||
|
||||
// Execute internal tool
|
||||
progress?.Report(ResultEventArgs.Success($"Executing {_internalProgram}... please wait!"));
|
||||
progress?.Report(ResultEventArgs.Neutral($"Executing {_internalProgram}... please wait!"));
|
||||
|
||||
var directoryName = Path.GetDirectoryName(OutputPath);
|
||||
if (!string.IsNullOrEmpty(directoryName))
|
||||
@@ -471,78 +489,90 @@ namespace MPF.Frontend
|
||||
ProcessUserInfoDelegate? processUserInfo = null,
|
||||
SubmissionInfo? seedInfo = null)
|
||||
{
|
||||
if (_processor == null)
|
||||
if (_processor is null)
|
||||
return ResultEventArgs.Failure("Error! Current configuration is not supported!");
|
||||
|
||||
// Build default console progress indicators if none exist
|
||||
if (resultProgress == null)
|
||||
if (resultProgress is null)
|
||||
{
|
||||
var temp = new Progress<ResultEventArgs>();
|
||||
temp.ProgressChanged += ConsoleLogger.ProgressUpdated;
|
||||
resultProgress = temp;
|
||||
}
|
||||
if (protectionProgress == null)
|
||||
|
||||
if (protectionProgress is null)
|
||||
{
|
||||
var temp = new Progress<ProtectionProgress>();
|
||||
temp.ProgressChanged += ConsoleLogger.ProgressUpdated;
|
||||
protectionProgress = temp;
|
||||
}
|
||||
|
||||
resultProgress.Report(ResultEventArgs.Success("Gathering submission information... please wait!"));
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Gathering submission information... please wait!"));
|
||||
|
||||
// Get the output directory and filename separately
|
||||
var outputDirectory = Path.GetDirectoryName(OutputPath);
|
||||
var outputFilename = Path.GetFileName(OutputPath);
|
||||
|
||||
// Check to make sure that the output had all the correct files
|
||||
List<string> missingFiles = _processor.FoundAllFiles(outputDirectory, outputFilename);
|
||||
if (missingFiles.Count > 0)
|
||||
// If a standard log zip was provided, replace the suffix with ".tmp" for easier processing
|
||||
if (outputFilename.EndsWith("_logs.zip", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Failure($"There were files missing from the output:\n{string.Join("\n", [.. missingFiles])}"));
|
||||
return ResultEventArgs.Failure("Error! Please check output directory as dump may be incomplete!");
|
||||
int zipSuffixIndex = outputFilename.LastIndexOf("_logs.zip", StringComparison.OrdinalIgnoreCase);
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
outputFilename = outputFilename[..zipSuffixIndex] + ".tmp";
|
||||
#else
|
||||
outputFilename = outputFilename.Substring(0, zipSuffixIndex) + ".tmp";
|
||||
#endif
|
||||
}
|
||||
|
||||
// Determine the media type from the processor
|
||||
MediaType? mediaType = _processor.DetermineMediaType(outputDirectory, outputFilename);
|
||||
if (mediaType is null)
|
||||
return ResultEventArgs.Failure("Could not determine the media type from output files...");
|
||||
|
||||
// Extract the information from the output files
|
||||
resultProgress.Report(ResultEventArgs.Success("Extracting output information from output files..."));
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Extracting output information from output files..."));
|
||||
var submissionInfo = await SubmissionGenerator.ExtractOutputInformation(
|
||||
OutputPath,
|
||||
_drive,
|
||||
_system,
|
||||
_type,
|
||||
mediaType,
|
||||
_options,
|
||||
_processor,
|
||||
resultProgress,
|
||||
protectionProgress);
|
||||
resultProgress.Report(ResultEventArgs.Success("Extracting information complete!"));
|
||||
if (submissionInfo is null)
|
||||
return ResultEventArgs.Failure("There was an issue extracting information!");
|
||||
else
|
||||
resultProgress.Report(ResultEventArgs.Success("Extracting information complete!"));
|
||||
|
||||
// Inject seed submission info data, if necessary
|
||||
if (seedInfo != null)
|
||||
if (seedInfo is not null)
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Success("Injecting user-supplied information..."));
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Injecting user-supplied information..."));
|
||||
submissionInfo = Builder.InjectSubmissionInformation(submissionInfo, seedInfo);
|
||||
resultProgress.Report(ResultEventArgs.Success("Information injection complete!"));
|
||||
}
|
||||
|
||||
// Get user-modifiable information if configured to
|
||||
if (_options.PromptForDiscInformation && processUserInfo != null)
|
||||
if (_options.PromptForDiscInformation && processUserInfo is not null)
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Success("Waiting for additional disc information..."));
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Waiting for additional media information..."));
|
||||
bool? filledInfo = processUserInfo.Invoke(_options, ref submissionInfo);
|
||||
if (filledInfo == true)
|
||||
resultProgress.Report(ResultEventArgs.Success("Additional disc information added!"));
|
||||
resultProgress.Report(ResultEventArgs.Success("Additional media information added!"));
|
||||
else
|
||||
resultProgress.Report(ResultEventArgs.Success("Disc information skipped!"));
|
||||
resultProgress.Report(ResultEventArgs.Success("Media information skipped!"));
|
||||
}
|
||||
|
||||
// Process special fields for site codes
|
||||
resultProgress.Report(ResultEventArgs.Success("Processing site codes..."));
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Processing site codes..."));
|
||||
Formatter.ProcessSpecialFields(submissionInfo!);
|
||||
resultProgress.Report(ResultEventArgs.Success("Processing complete!"));
|
||||
|
||||
// Format the information for the text output
|
||||
resultProgress.Report(ResultEventArgs.Success("Formatting information..."));
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Formatting information..."));
|
||||
var formattedValues = Formatter.FormatOutputData(submissionInfo, _options.EnableRedumpCompatibility, out string? formatResult);
|
||||
if (formattedValues == null)
|
||||
if (formattedValues is null)
|
||||
resultProgress.Report(ResultEventArgs.Failure(formatResult));
|
||||
else
|
||||
resultProgress.Report(ResultEventArgs.Success(formatResult));
|
||||
@@ -551,7 +581,7 @@ namespace MPF.Frontend
|
||||
var filenameSuffix = _options.AddFilenameSuffix ? Path.GetFileNameWithoutExtension(outputFilename) : null;
|
||||
|
||||
// Write the text output
|
||||
resultProgress.Report(ResultEventArgs.Success("Writing submission information file..."));
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Writing submission information file..."));
|
||||
bool txtSuccess = WriteOutputData(outputDirectory, filenameSuffix, formattedValues, out string txtResult);
|
||||
if (txtSuccess)
|
||||
resultProgress.Report(ResultEventArgs.Success(txtResult));
|
||||
@@ -559,11 +589,11 @@ namespace MPF.Frontend
|
||||
resultProgress.Report(ResultEventArgs.Failure(txtResult));
|
||||
|
||||
// Write the copy protection output
|
||||
if (submissionInfo?.CopyProtection?.FullProtections != null && submissionInfo.CopyProtection.FullProtections.Count > 0)
|
||||
if (submissionInfo?.CopyProtection?.FullProtections is not null && submissionInfo.CopyProtection.FullProtections.Count > 0)
|
||||
{
|
||||
if (_options.ScanForProtection)
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Success("Writing protection information file..."));
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Writing protection information file..."));
|
||||
bool scanSuccess = WriteProtectionData(outputDirectory, filenameSuffix, submissionInfo, _options.HideDriveLetters);
|
||||
if (scanSuccess)
|
||||
resultProgress.Report(ResultEventArgs.Success("Writing complete!"));
|
||||
@@ -575,7 +605,7 @@ namespace MPF.Frontend
|
||||
// Write the JSON output, if required
|
||||
if (_options.OutputSubmissionJSON)
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Success($"Writing submission information JSON file{(_options.IncludeArtifacts ? " with artifacts" : string.Empty)}..."));
|
||||
resultProgress.Report(ResultEventArgs.Neutral($"Writing submission information JSON file{(_options.IncludeArtifacts ? " with artifacts" : string.Empty)}..."));
|
||||
bool jsonSuccess = WriteOutputData(outputDirectory, filenameSuffix, submissionInfo, _options.IncludeArtifacts);
|
||||
if (jsonSuccess)
|
||||
resultProgress.Report(ResultEventArgs.Success("Writing complete!"));
|
||||
@@ -586,14 +616,14 @@ namespace MPF.Frontend
|
||||
// Compress the logs, if required
|
||||
if (_options.CompressLogFiles)
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Success("Compressing log files..."));
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Compressing log files..."));
|
||||
#if NET40
|
||||
await Task.Factory.StartNew(() =>
|
||||
#else
|
||||
await Task.Run(() =>
|
||||
#endif
|
||||
{
|
||||
bool compressSuccess = _processor.CompressLogFiles(outputDirectory, outputFilename, filenameSuffix, out string compressResult);
|
||||
bool compressSuccess = _processor.CompressLogFiles(mediaType, _options.LogCompression, outputDirectory, outputFilename, filenameSuffix, out string compressResult);
|
||||
if (compressSuccess)
|
||||
resultProgress.Report(ResultEventArgs.Success(compressResult));
|
||||
else
|
||||
@@ -606,8 +636,8 @@ namespace MPF.Frontend
|
||||
// Delete unnecessary files, if required
|
||||
if (_options.DeleteUnnecessaryFiles)
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Success("Deleting unnecessary files..."));
|
||||
bool deleteSuccess = _processor.DeleteUnnecessaryFiles(outputDirectory, outputFilename, out string deleteResult);
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Deleting unnecessary files..."));
|
||||
bool deleteSuccess = _processor.DeleteUnnecessaryFiles(mediaType, outputDirectory, outputFilename, out string deleteResult);
|
||||
if (deleteSuccess)
|
||||
resultProgress.Report(ResultEventArgs.Success(deleteResult));
|
||||
else
|
||||
@@ -615,10 +645,10 @@ namespace MPF.Frontend
|
||||
}
|
||||
|
||||
// Create PS3 IRD, if required
|
||||
if (_options.CreateIRDAfterDumping && _system == RedumpSystem.SonyPlayStation3 && _type == MediaType.BluRay)
|
||||
if (_options.CreateIRDAfterDumping && _system == RedumpSystem.SonyPlayStation3 && mediaType == MediaType.BluRay)
|
||||
{
|
||||
resultProgress.Report(ResultEventArgs.Success("Creating IRD... please wait!"));
|
||||
bool deleteSuccess = await WriteIRD(OutputPath, submissionInfo?.Extras?.DiscKey, submissionInfo?.Extras?.DiscID, submissionInfo?.Extras?.PIC, submissionInfo?.SizeAndChecksums?.Layerbreak, submissionInfo?.SizeAndChecksums?.CRC32);
|
||||
resultProgress.Report(ResultEventArgs.Neutral("Creating IRD... please wait!"));
|
||||
bool deleteSuccess = await IRDTool.WriteIRD(OutputPath, submissionInfo?.Extras?.DiscKey, submissionInfo?.Extras?.DiscID, submissionInfo?.Extras?.PIC, submissionInfo?.SizeAndChecksums.Layerbreak, submissionInfo?.SizeAndChecksums.CRC32);
|
||||
if (deleteSuccess)
|
||||
resultProgress.Report(ResultEventArgs.Success("IRD created!"));
|
||||
else
|
||||
@@ -633,18 +663,18 @@ namespace MPF.Frontend
|
||||
/// Checks if the parameters are valid
|
||||
/// </summary>
|
||||
/// <returns>True if the configuration is valid, false otherwise</returns>
|
||||
internal bool ParametersValid()
|
||||
internal bool ParametersValid(MediaType? mediaType)
|
||||
{
|
||||
// Missing drive means it can never be valid
|
||||
if (_drive == null)
|
||||
if (_drive is null)
|
||||
return false;
|
||||
|
||||
bool parametersValid = _executionContext?.IsValid() ?? false;
|
||||
bool floppyValid = !(_drive.InternalDriveType == InternalDriveType.Floppy ^ _type == MediaType.FloppyDisk);
|
||||
bool floppyValid = !(_drive.InternalDriveType == InternalDriveType.Floppy ^ mediaType == MediaType.FloppyDisk);
|
||||
|
||||
// TODO: HardDisk being in the Removable category is a hack, fix this later
|
||||
bool removableDiskValid = !((_drive.InternalDriveType == InternalDriveType.Removable || _drive.InternalDriveType == InternalDriveType.HardDisk)
|
||||
^ (_type == MediaType.CompactFlash || _type == MediaType.SDCard || _type == MediaType.FlashDrive || _type == MediaType.HardDisk));
|
||||
^ (mediaType == MediaType.CompactFlash || mediaType == MediaType.SDCard || mediaType == MediaType.FlashDrive || mediaType == MediaType.HardDisk));
|
||||
|
||||
return parametersValid && floppyValid && removableDiskValid;
|
||||
}
|
||||
@@ -653,17 +683,17 @@ namespace MPF.Frontend
|
||||
/// Validate the current environment is ready for a dump
|
||||
/// </summary>
|
||||
/// <returns>Result instance with the outcome</returns>
|
||||
private ResultEventArgs IsValidForDump()
|
||||
private ResultEventArgs IsValidForDump(MediaType? mediaType)
|
||||
{
|
||||
// Validate that everything is good
|
||||
if (_executionContext == null || !ParametersValid())
|
||||
if (_executionContext is null || !ParametersValid(mediaType))
|
||||
return ResultEventArgs.Failure("Error! Current configuration is not supported!");
|
||||
|
||||
// Fix the output paths, just in case
|
||||
OutputPath = FrontendTool.NormalizeOutputPaths(OutputPath, false);
|
||||
|
||||
// Validate that the output path isn't on the dumping drive
|
||||
if (_drive?.Name != null && OutputPath.StartsWith(_drive.Name))
|
||||
if (_drive?.Name is not null && OutputPath.StartsWith(_drive.Name))
|
||||
return ResultEventArgs.Failure("Error! Cannot output to same drive that is being dumped!");
|
||||
|
||||
// Validate that the required program exists
|
||||
@@ -672,11 +702,11 @@ namespace MPF.Frontend
|
||||
|
||||
// Validate that the dumping drive doesn't contain the executable
|
||||
string fullExecutablePath = Path.GetFullPath(_executionContext.ExecutablePath!);
|
||||
if (_drive?.Name != null && fullExecutablePath.StartsWith(_drive.Name))
|
||||
if (_drive?.Name is not null && fullExecutablePath.StartsWith(_drive.Name))
|
||||
return ResultEventArgs.Failure("Error! Cannot dump same drive that executable resides on!");
|
||||
|
||||
// Validate that the current configuration is supported
|
||||
return GetSupportStatus();
|
||||
return GetSupportStatus(mediaType);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -693,7 +723,7 @@ namespace MPF.Frontend
|
||||
private static bool WriteOutputData(string? outputDirectory, string? filenameSuffix, string? lines, out string status)
|
||||
{
|
||||
// Check to see if the inputs are valid
|
||||
if (lines == null)
|
||||
if (lines is null)
|
||||
{
|
||||
status = "No formatted data found to write!";
|
||||
return false;
|
||||
@@ -738,7 +768,7 @@ namespace MPF.Frontend
|
||||
private static bool WriteOutputData(string? outputDirectory, string? filenameSuffix, SubmissionInfo? info, bool includedArtifacts)
|
||||
{
|
||||
// Check to see if the input is valid
|
||||
if (info == null)
|
||||
if (info is null)
|
||||
return false;
|
||||
|
||||
try
|
||||
@@ -779,7 +809,7 @@ namespace MPF.Frontend
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -798,7 +828,7 @@ namespace MPF.Frontend
|
||||
private static bool WriteProtectionData(string? outputDirectory, string? filenameSuffix, SubmissionInfo? info, bool hideDriveLetters)
|
||||
{
|
||||
// Check to see if the inputs are valid
|
||||
if (info?.CopyProtection?.FullProtections == null || info.CopyProtection.FullProtections.Count == 0)
|
||||
if (info?.CopyProtection?.FullProtections is null || info.CopyProtection.FullProtections.Count == 0)
|
||||
return true;
|
||||
|
||||
// Now write out to a generic file
|
||||
@@ -823,11 +853,15 @@ namespace MPF.Frontend
|
||||
{
|
||||
string scanPath = key;
|
||||
if (hideDriveLetters)
|
||||
scanPath = Path.DirectorySeparatorChar + key.Substring((Path.GetPathRoot(key) ?? String.Empty).Length);
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
scanPath = Path.DirectorySeparatorChar + key[(Path.GetPathRoot(key) ?? string.Empty).Length..];
|
||||
#else
|
||||
scanPath = Path.DirectorySeparatorChar + key.Substring((Path.GetPathRoot(key) ?? string.Empty).Length);
|
||||
#endif
|
||||
|
||||
List<string>? scanResult = info.CopyProtection.FullProtections[key];
|
||||
|
||||
if (scanResult == null)
|
||||
if (scanResult is null)
|
||||
sw.WriteLine($"{scanPath}: None");
|
||||
else
|
||||
sw.WriteLine($"{scanPath}: {string.Join(", ", [.. scanResult])}");
|
||||
@@ -835,73 +869,13 @@ namespace MPF.Frontend
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an IRD and write it to the specified output directory with optional filename suffix
|
||||
/// </summary>
|
||||
/// <param name="outputDirectory">Output folder to use as the base path</param>
|
||||
/// <param name="filenameSuffix">Optional suffix to append to the filename</param>
|
||||
/// <param name="outputFilename">Output filename to use as the base path</param>
|
||||
/// <returns>True on success, false on error</returns>
|
||||
private static async Task<bool> WriteIRD(string isoPath,
|
||||
string? discKeyString,
|
||||
string? discIDString,
|
||||
string? picString,
|
||||
long? layerbreak,
|
||||
string? crc32)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Output IRD file path
|
||||
string irdPath = Path.ChangeExtension(isoPath, ".ird");
|
||||
|
||||
// Parse disc key from submission info (Required)
|
||||
byte[]? discKey = ProcessingTool.ParseHexKey(discKeyString);
|
||||
if (discKey == null)
|
||||
return false;
|
||||
|
||||
// Parse Disc ID from submission info (Optional)
|
||||
byte[]? discID = ProcessingTool.ParseDiscID(discIDString);
|
||||
|
||||
// Parse PIC from submission info (Optional)
|
||||
byte[]? pic = ProcessingTool.ParsePIC(picString);
|
||||
|
||||
// Parse CRC32 strings into ISO hash for Unique ID field (Optional)
|
||||
uint? uid = ProcessingTool.ParseCRC32(crc32);
|
||||
|
||||
// Ensure layerbreak value is valid (Optional)
|
||||
layerbreak = ProcessingTool.ParseLayerbreak(layerbreak);
|
||||
|
||||
// Create Redump-style reproducible IRD
|
||||
#if NET40
|
||||
LibIRD.ReIRD ird = await Task.Factory.StartNew(() =>
|
||||
#else
|
||||
LibIRD.ReIRD ird = await Task.Run(() =>
|
||||
#endif
|
||||
new LibIRD.ReIRD(isoPath, discKey, layerbreak, uid));
|
||||
if (pic != null)
|
||||
ird.PIC = pic;
|
||||
if (discID != null && ird.DiscID[15] != 0x00)
|
||||
ird.DiscID = discID;
|
||||
|
||||
// Write IRD to file
|
||||
ird.Write(irdPath);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// We don't care what the error is
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Reflection;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using DreamdumpSectorOrder = MPF.ExecutionContexts.Dreamdump.SectorOrder;
|
||||
using LogCompression = MPF.Processors.LogCompression;
|
||||
using RedumperDriveType = MPF.ExecutionContexts.Redumper.DriveType;
|
||||
using RedumperReadMethod = MPF.ExecutionContexts.Redumper.ReadMethod;
|
||||
using RedumperSectorOrder = MPF.ExecutionContexts.Redumper.SectorOrder;
|
||||
@@ -49,7 +51,7 @@ namespace MPF.Frontend
|
||||
#endif
|
||||
}
|
||||
|
||||
if (method != null)
|
||||
if (method is not null)
|
||||
return method.Invoke(null, [value]) as string ?? string.Empty;
|
||||
else
|
||||
return string.Empty;
|
||||
@@ -61,6 +63,49 @@ namespace MPF.Frontend
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the InterfaceLanguage enum values
|
||||
/// </summary>
|
||||
/// <param name="lang">InterfaceLanguage value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this InterfaceLanguage lang)
|
||||
=> ((InterfaceLanguage?)lang).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the InterfaceLanguage enum values
|
||||
/// </summary>
|
||||
/// <param name="lang">InterfaceLanguage value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this InterfaceLanguage? lang)
|
||||
{
|
||||
return lang switch
|
||||
{
|
||||
InterfaceLanguage.AutoDetect => "Auto Detect",
|
||||
InterfaceLanguage.English => "English",
|
||||
InterfaceLanguage.French => "Français",
|
||||
InterfaceLanguage.German => "Deutsch",
|
||||
InterfaceLanguage.Italian => "Italiano",
|
||||
InterfaceLanguage.Japanese => "日本語",
|
||||
InterfaceLanguage.Korean => "한국어",
|
||||
InterfaceLanguage.Polish => "Polski",
|
||||
InterfaceLanguage.Russian => "Русский",
|
||||
InterfaceLanguage.Spanish => "Español",
|
||||
InterfaceLanguage.Swedish => "Svenska",
|
||||
InterfaceLanguage.Ukrainian => "Українська",
|
||||
InterfaceLanguage.L337 => "L337",
|
||||
|
||||
_ => "Unknown",
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the InternalProgram enum values
|
||||
/// </summary>
|
||||
/// <param name="prog">InternalProgram value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this InternalProgram prog)
|
||||
=> ((InternalProgram?)prog).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the InternalProgram enum values
|
||||
/// </summary>
|
||||
@@ -74,6 +119,7 @@ namespace MPF.Frontend
|
||||
|
||||
InternalProgram.Aaru => "Aaru",
|
||||
InternalProgram.DiscImageCreator => "DiscImageCreator",
|
||||
// InternalProgram.Dreamdump => "Dreamdump",
|
||||
InternalProgram.Redumper => "Redumper",
|
||||
|
||||
#endregion
|
||||
@@ -92,6 +138,39 @@ namespace MPF.Frontend
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the LogCompression enum values
|
||||
/// </summary>
|
||||
/// <param name="comp">LogCompression value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this LogCompression comp)
|
||||
=> ((LogCompression?)comp).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the LogCompression enum values
|
||||
/// </summary>
|
||||
/// <param name="comp">LogCompression value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this LogCompression? comp)
|
||||
{
|
||||
return comp switch
|
||||
{
|
||||
LogCompression.DeflateDefault => "ZIP using Deflate (Level 5)",
|
||||
LogCompression.DeflateMaximum => "ZIP using Deflate (Level 9)",
|
||||
LogCompression.Zstd19 => "ZIP using Zstd (Level 19)",
|
||||
|
||||
_ => "Unknown",
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperReadMethod enum values
|
||||
/// </summary>
|
||||
/// <param name="method">RedumperReadMethod value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this RedumperReadMethod method)
|
||||
=> ((RedumperReadMethod?)method).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperReadMethod enum values
|
||||
/// </summary>
|
||||
@@ -109,6 +188,14 @@ namespace MPF.Frontend
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperSectorOrder enum values
|
||||
/// </summary>
|
||||
/// <param name="order">RedumperSectorOrder value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this RedumperSectorOrder order)
|
||||
=> ((RedumperSectorOrder?)order).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperSectorOrder enum values
|
||||
/// </summary>
|
||||
@@ -128,6 +215,14 @@ namespace MPF.Frontend
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperDriveType enum values
|
||||
/// </summary>
|
||||
/// <param name="type">RedumperDriveType value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this RedumperDriveType type)
|
||||
=> ((RedumperDriveType?)type).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the RedumperDriveType enum values
|
||||
/// </summary>
|
||||
@@ -139,11 +234,11 @@ namespace MPF.Frontend
|
||||
{
|
||||
RedumperDriveType.GENERIC => "GENERIC",
|
||||
RedumperDriveType.PLEXTOR => "PLEXTOR",
|
||||
RedumperDriveType.LG_ASU8A => "LG_ASU8A",
|
||||
RedumperDriveType.LG_ASU8B => "LG_ASU8B",
|
||||
RedumperDriveType.LG_ASU8C => "LG_ASU8C",
|
||||
RedumperDriveType.LG_ASU3 => "LG_ASU3",
|
||||
RedumperDriveType.LG_ASU2 => "LG_ASU2",
|
||||
RedumperDriveType.MTK8A => "MTK8A",
|
||||
RedumperDriveType.MTK8B => "MTK8B",
|
||||
RedumperDriveType.MTK8C => "MTK8C",
|
||||
RedumperDriveType.MTK3 => "MTK3",
|
||||
RedumperDriveType.MTK2 => "MTK2",
|
||||
|
||||
RedumperDriveType.NONE => "Default",
|
||||
_ => "Unknown",
|
||||
@@ -154,6 +249,41 @@ namespace MPF.Frontend
|
||||
|
||||
#region Convert to Short Name
|
||||
|
||||
/// <summary>
|
||||
/// Get the short string representation of the InterfaceLanguage enum values
|
||||
/// </summary>
|
||||
/// <param name="lang">InterfaceLanguage value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string ShortName(this InterfaceLanguage lang)
|
||||
=> ((InterfaceLanguage?)lang).ShortName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the short string representation of the InterfaceLanguage enum values
|
||||
/// </summary>
|
||||
/// <param name="lang">InterfaceLanguage value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string ShortName(this InterfaceLanguage? lang)
|
||||
{
|
||||
return lang switch
|
||||
{
|
||||
InterfaceLanguage.AutoDetect => "auto",
|
||||
InterfaceLanguage.English => "eng",
|
||||
InterfaceLanguage.French => "fra",
|
||||
InterfaceLanguage.German => "deu",
|
||||
InterfaceLanguage.Italian => "ita",
|
||||
InterfaceLanguage.Japanese => "jpn",
|
||||
InterfaceLanguage.Korean => "kor",
|
||||
InterfaceLanguage.Polish => "pol",
|
||||
InterfaceLanguage.Russian => "rus",
|
||||
InterfaceLanguage.Spanish => "spa",
|
||||
InterfaceLanguage.Swedish => "swe",
|
||||
InterfaceLanguage.Ukrainian => "ukr",
|
||||
InterfaceLanguage.L337 => "l37",
|
||||
|
||||
_ => "Unknown",
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the short string representation of the InternalProgram enum values
|
||||
/// </summary>
|
||||
@@ -167,6 +297,7 @@ namespace MPF.Frontend
|
||||
|
||||
InternalProgram.Aaru => "aaru",
|
||||
InternalProgram.DiscImageCreator => "dic",
|
||||
// InternalProgram.Dreamdump => "dreamdump",
|
||||
InternalProgram.Redumper => "redumper",
|
||||
|
||||
#endregion
|
||||
@@ -189,6 +320,63 @@ namespace MPF.Frontend
|
||||
|
||||
#region Convert from String
|
||||
|
||||
/// <summary>
|
||||
/// Get the DreamdumpSectorOrder enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="order">String value to convert</param>
|
||||
/// <returns>DreamdumpSectorOrder represented by the string, if possible</returns>
|
||||
public static DreamdumpSectorOrder ToDreamdumpSectorOrder(this string? order)
|
||||
{
|
||||
return (order?.ToLowerInvariant()) switch
|
||||
{
|
||||
"data_c2_sub"
|
||||
or "data c2 sub"
|
||||
or "data-c2-sub"
|
||||
or "datac2sub" => DreamdumpSectorOrder.DATA_C2_SUB,
|
||||
"data_sub_c2"
|
||||
or "data sub c2"
|
||||
or "data-sub-c2"
|
||||
or "datasubc2" => DreamdumpSectorOrder.DATA_SUB_C2,
|
||||
"data_sub"
|
||||
or "data sub"
|
||||
or "data-sub"
|
||||
or "datasub" => DreamdumpSectorOrder.DATA_SUB,
|
||||
"data_c2"
|
||||
or "data c2"
|
||||
or "data-c2"
|
||||
or "datac2" => DreamdumpSectorOrder.DATA_C2,
|
||||
|
||||
_ => DreamdumpSectorOrder.NONE,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the InterfaceLanguage enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="internalLanguage">String value to convert</param>
|
||||
/// <returns>InterfaceLanguage represented by the string, if possible</returns>
|
||||
public static InterfaceLanguage ToInterfaceLanguage(this string? internalLanguage)
|
||||
{
|
||||
return (internalLanguage?.ToLowerInvariant()) switch
|
||||
{
|
||||
"auto" or "autodetect" or "auto detect" => InterfaceLanguage.AutoDetect,
|
||||
"eng" or "english" => InterfaceLanguage.English,
|
||||
"fra" or "french" or "français" => InterfaceLanguage.French,
|
||||
"deu" or "german" or "deutsch" => InterfaceLanguage.German,
|
||||
"ita" or "italian" or "italiano" => InterfaceLanguage.Italian,
|
||||
"jpn" or "japanese" or "日本語" => InterfaceLanguage.Japanese,
|
||||
"kor" or "korean" or "한국어" => InterfaceLanguage.Korean,
|
||||
"pol" or "polish" or "polski" => InterfaceLanguage.Polish,
|
||||
"rus" or "russian" or "русский" => InterfaceLanguage.Russian,
|
||||
"spa" or "spanish" or "español" => InterfaceLanguage.Spanish,
|
||||
"swe" or "swedish" or "svenska" => InterfaceLanguage.Swedish,
|
||||
"ukr" or "ukranian" or "українська" => InterfaceLanguage.Ukrainian,
|
||||
"l37" or "l337" => InterfaceLanguage.L337,
|
||||
|
||||
_ => InterfaceLanguage.AutoDetect,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the InternalProgram enum value for a given string
|
||||
/// </summary>
|
||||
@@ -207,6 +395,7 @@ namespace MPF.Frontend
|
||||
or "dic"
|
||||
or "dicreator"
|
||||
or "discimagecreator" => InternalProgram.DiscImageCreator,
|
||||
// "dreamdump" => InternalProgram.Dreamdump,
|
||||
"rd"
|
||||
or "redumper" => InternalProgram.Redumper,
|
||||
|
||||
@@ -232,6 +421,28 @@ namespace MPF.Frontend
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the LogCompression enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="logCompression">String value to convert</param>
|
||||
/// <returns>LogCompression represented by the string, if possible</returns>
|
||||
public static LogCompression ToLogCompression(this string? logCompression)
|
||||
{
|
||||
return (logCompression?.ToLowerInvariant()) switch
|
||||
{
|
||||
"deflate"
|
||||
or "deflatedefault"
|
||||
or "zip" => LogCompression.DeflateDefault,
|
||||
"deflatemaximum"
|
||||
or "max"
|
||||
or "maximum" => LogCompression.DeflateMaximum,
|
||||
"zstd"
|
||||
or "zstd19" => LogCompression.Zstd19,
|
||||
|
||||
_ => LogCompression.DeflateDefault,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the RedumperReadMethod enum value for a given string
|
||||
/// </summary>
|
||||
@@ -289,31 +500,66 @@ namespace MPF.Frontend
|
||||
{
|
||||
"generic" => RedumperDriveType.GENERIC,
|
||||
"plextor" => RedumperDriveType.PLEXTOR,
|
||||
"lg_asus8a"
|
||||
"mtk8a"
|
||||
or "mtk_8a"
|
||||
or "lg_asus8a"
|
||||
or "lg-asus8a"
|
||||
or "lgasus8a"
|
||||
or "lg_asus_8a"
|
||||
or "lg-asus-8a" => RedumperDriveType.LG_ASU8A,
|
||||
"lg_asus8b"
|
||||
or "lg-asus-8a"
|
||||
or "lg_asu8a"
|
||||
or "lg-asu8a"
|
||||
or "lgasu8a"
|
||||
or "lg_asu_8a"
|
||||
or "lg-asu-8a" => RedumperDriveType.MTK8A,
|
||||
"mtk8b"
|
||||
or "mtk_8b"
|
||||
or "lg_asus8b"
|
||||
or "lg-asus8b"
|
||||
or "lgasus8b"
|
||||
or "lg_asus_8b"
|
||||
or "lg-asus-8b" => RedumperDriveType.LG_ASU8B,
|
||||
"lg_asus8c"
|
||||
or "lg-asus-8b"
|
||||
or "lg_asu8b"
|
||||
or "lg-asu8b"
|
||||
or "lgasu8b"
|
||||
or "lg_asu_8b"
|
||||
or "lg-asu-8b" => RedumperDriveType.MTK8B,
|
||||
"mtk8c"
|
||||
or "mtk_8c"
|
||||
or "lg_asus8c"
|
||||
or "lg-asus8c"
|
||||
or "lgasus8c"
|
||||
or "lg_asus_8c"
|
||||
or "lg-asus-8c" => RedumperDriveType.LG_ASU8C,
|
||||
"lg_asus3"
|
||||
or "lg-asus-8c"
|
||||
or "lg_asu8c"
|
||||
or "lg-asu8c"
|
||||
or "lgasu8c"
|
||||
or "lg_asu_8c"
|
||||
or "lg-asu-8c" => RedumperDriveType.MTK8C,
|
||||
"mtk3"
|
||||
or "mtk3"
|
||||
or "lg_asus3"
|
||||
or "lg-asus3"
|
||||
or "lgasus3"
|
||||
or "lg_asus_3"
|
||||
or "lg-asus-3" => RedumperDriveType.LG_ASU3,
|
||||
"lg_asus2"
|
||||
or "lg-asus-3"
|
||||
or "lg_asu3"
|
||||
or "lg-asu3"
|
||||
or "lgasu3"
|
||||
or "lg_asu_3"
|
||||
or "lg-asu-3" => RedumperDriveType.MTK3,
|
||||
"mtk2"
|
||||
or "mtk2"
|
||||
or "lg_asus2"
|
||||
or "lg-asus2"
|
||||
or "lgasus2"
|
||||
or "lg_asus_2"
|
||||
or "lg-asus-2" => RedumperDriveType.LG_ASU2,
|
||||
or "lg-asus-2"
|
||||
or "lg_asu2"
|
||||
or "lg-asu2"
|
||||
or "lgasu2"
|
||||
or "lg_asu_2"
|
||||
or "lg-asu-2" => RedumperDriveType.MTK2,
|
||||
|
||||
_ => RedumperDriveType.NONE,
|
||||
};
|
||||
@@ -328,11 +574,13 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public static bool SupportsAntiModchipScans(this RedumpSystem? system)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
return system switch
|
||||
{
|
||||
RedumpSystem.SonyPlayStation => true,
|
||||
_ => false,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -340,9 +588,11 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public static bool SupportsCopyProtectionScans(this RedumpSystem? system)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
return system switch
|
||||
{
|
||||
RedumpSystem.AppleMacintosh => true,
|
||||
RedumpSystem.DVDVideo => true,
|
||||
RedumpSystem.EnhancedCD => true,
|
||||
RedumpSystem.IBMPCcompatible => true,
|
||||
RedumpSystem.PalmOS => true,
|
||||
@@ -351,6 +601,7 @@ namespace MPF.Frontend
|
||||
RedumpSystem.SonyElectronicBook => true,
|
||||
_ => false,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,5 +1,32 @@
|
||||
namespace MPF.Frontend
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface language
|
||||
/// </summary>
|
||||
public enum InterfaceLanguage
|
||||
{
|
||||
/// <summary>
|
||||
/// Default to auto-detecting language
|
||||
/// </summary>
|
||||
AutoDetect = 0,
|
||||
|
||||
// Selectable languages (in Manual Window dropdown)
|
||||
English,
|
||||
French,
|
||||
German,
|
||||
Italian,
|
||||
Japanese,
|
||||
Korean,
|
||||
Polish,
|
||||
Russian,
|
||||
Spanish,
|
||||
Swedish,
|
||||
Ukrainian,
|
||||
|
||||
// Hidden languages (not in Main Window dropdown)
|
||||
L337,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drive type for dumping
|
||||
/// </summary>
|
||||
@@ -21,6 +48,7 @@ namespace MPF.Frontend
|
||||
// Dumping support
|
||||
Aaru,
|
||||
DiscImageCreator,
|
||||
// Dreamdump,
|
||||
Redumper,
|
||||
|
||||
// Verification support only
|
||||
@@ -35,9 +63,10 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public enum LogLevel
|
||||
{
|
||||
USER,
|
||||
USER_GENERIC,
|
||||
USER_SUCCESS,
|
||||
VERBOSE,
|
||||
ERROR,
|
||||
SECRET,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
MPF.Frontend/Features/ListCodesFeature.cs
Normal file
38
MPF.Frontend/Features/ListCodesFeature.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using SabreTools.CommandLine;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class ListCodesFeature : Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "listcodes";
|
||||
|
||||
private static readonly string[] _flags = ["lc", "listcodes"];
|
||||
|
||||
private const string _description = "List supported comment/content site codes";
|
||||
|
||||
#endregion
|
||||
|
||||
public ListCodesFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine("Supported Site Codes:");
|
||||
foreach (string siteCode in SabreTools.RedumpLib.Data.Extensions.ListSiteCodes())
|
||||
{
|
||||
Console.WriteLine(siteCode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
150
MPF.Frontend/Features/ListConfigFeature.cs
Normal file
150
MPF.Frontend/Features/ListConfigFeature.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class ListConfigFeature : SabreTools.CommandLine.Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "listconfig";
|
||||
|
||||
private static readonly string[] _flags = ["lo", "listconfig"];
|
||||
|
||||
private const string _description = "List current configuration values";
|
||||
|
||||
#endregion
|
||||
|
||||
public ListConfigFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
// Try to load the current config
|
||||
var options = OptionsLoader.LoadFromConfig();
|
||||
if (options.FirstRun)
|
||||
{
|
||||
Console.WriteLine("No valid configuration found!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Paths
|
||||
Console.WriteLine("Paths:");
|
||||
Console.WriteLine($" Aaru Path = {options.AaruPath}");
|
||||
Console.WriteLine($" DiscImageCreator Path = {options.DiscImageCreatorPath}");
|
||||
Console.WriteLine($" Redumper Path = {options.RedumperPath}");
|
||||
Console.WriteLine($" Default Program = {options.InternalProgram.LongName()}");
|
||||
Console.WriteLine();
|
||||
|
||||
// UI Defaults
|
||||
Console.WriteLine("UI Defaults:");
|
||||
Console.WriteLine($" Dark Mode = {options.EnableDarkMode}");
|
||||
Console.WriteLine($" Purp Mode = {options.EnablePurpMode}");
|
||||
Console.WriteLine($" Custom Background Color = {options.CustomBackgroundColor}");
|
||||
Console.WriteLine($" Custom Text Color = {options.CustomTextColor}");
|
||||
Console.WriteLine($" Check for Updates on Startup = {options.CheckForUpdatesOnStartup}");
|
||||
Console.WriteLine($" Copy Update URL to Clipboard = {options.CopyUpdateUrlToClipboard}");
|
||||
Console.WriteLine($" Fast Label Update = {options.FastUpdateLabel}");
|
||||
Console.WriteLine($" Default Interface Language = {options.DefaultInterfaceLanguage.LongName()}");
|
||||
Console.WriteLine($" Default Output Path = {options.DefaultOutputPath}");
|
||||
Console.WriteLine($" Default System = {options.DefaultSystem.LongName()}");
|
||||
Console.WriteLine($" Show Debug Menu Item = {options.ShowDebugViewMenuItem}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Dumping Speeds
|
||||
Console.WriteLine("Dumping Speeds:");
|
||||
Console.WriteLine($" Default CD Speed = {options.PreferredDumpSpeedCD}");
|
||||
Console.WriteLine($" Default DVD Speed = {options.PreferredDumpSpeedDVD}");
|
||||
Console.WriteLine($" Default HD-DVD Speed = {options.PreferredDumpSpeedHDDVD}");
|
||||
Console.WriteLine($" Default Blu-ray Speed = {options.PreferredDumpSpeedBD}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Aaru
|
||||
Console.WriteLine("Aaru-Specific Options:");
|
||||
Console.WriteLine($" Enable Debug = {options.AaruEnableDebug}");
|
||||
Console.WriteLine($" Enable Verbose = {options.AaruEnableVerbose}");
|
||||
Console.WriteLine($" Force Dumping = {options.AaruForceDumping}");
|
||||
Console.WriteLine($" Reread Count = {options.AaruRereadCount}");
|
||||
Console.WriteLine($" Strip Personal Data = {options.AaruStripPersonalData}");
|
||||
Console.WriteLine();
|
||||
|
||||
// DiscImageCreator
|
||||
Console.WriteLine("DiscImageCreator-Specific Options:");
|
||||
Console.WriteLine($" Multi-Sector Read Flag = {options.DICMultiSectorRead}");
|
||||
Console.WriteLine($" Multi-Sector Read Value = {options.DICMultiSectorReadValue}");
|
||||
Console.WriteLine($" Overly-Secure Flags = {options.DICParanoidMode}");
|
||||
Console.WriteLine($" Quiet Flag = {options.DICQuietMode}");
|
||||
Console.WriteLine($" CD Reread Count = {options.DICRereadCount}");
|
||||
Console.WriteLine($" DVD Reread Count = {options.DICDVDRereadCount}");
|
||||
Console.WriteLine($" Use CMI Flag = {options.DICUseCMIFlag}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Redumper
|
||||
Console.WriteLine("Redumper-Specific Options:");
|
||||
Console.WriteLine($" Enable Skeleton = {options.RedumperEnableSkeleton}");
|
||||
Console.WriteLine($" Enable Verbose = {options.RedumperEnableVerbose}");
|
||||
Console.WriteLine($" Lead-in Retry Count = {options.RedumperLeadinRetryCount}");
|
||||
Console.WriteLine($" Non-Redump Mode = {options.RedumperNonRedumpMode}");
|
||||
Console.WriteLine($" Drive Type = {options.RedumperDriveType.LongName()}");
|
||||
Console.WriteLine($" Read Method = {options.RedumperReadMethod.LongName()}");
|
||||
Console.WriteLine($" Sector Order = {options.RedumperSectorOrder.LongName()}");
|
||||
Console.WriteLine($" Reread Count = {options.RedumperRereadCount}");
|
||||
Console.WriteLine($" Refine Sector Mode = {options.RedumperRefineSectorMode}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Extra Dumping Options
|
||||
Console.WriteLine("Extra Dumping Options:");
|
||||
Console.WriteLine($" Scan for Protection = {options.ScanForProtection}");
|
||||
Console.WriteLine($" Add Placeholders = {options.AddPlaceholders}");
|
||||
Console.WriteLine($" Prompt for Media Information = {options.PromptForDiscInformation}");
|
||||
Console.WriteLine($" Pull All Information = {options.PullAllInformation}");
|
||||
Console.WriteLine($" Enable Tabs in Input Fields = {options.EnableTabsInInputFields}");
|
||||
Console.WriteLine($" Enable Redump Compatibility = {options.EnableRedumpCompatibility}");
|
||||
Console.WriteLine($" Show Disc Eject Reminder = {options.ShowDiscEjectReminder}");
|
||||
Console.WriteLine($" Ignore Fixed Drives = {options.IgnoreFixedDrives}");
|
||||
Console.WriteLine($" Add Filename Suffix = {options.AddFilenameSuffix}");
|
||||
Console.WriteLine($" Output Submission JSON = {options.OutputSubmissionJSON}");
|
||||
Console.WriteLine($" Include Artifacts = {options.IncludeArtifacts}");
|
||||
Console.WriteLine($" Compress Log Files = {options.CompressLogFiles}");
|
||||
Console.WriteLine($" Log Compression = {options.LogCompression.LongName()}");
|
||||
Console.WriteLine($" Delete Unnecessary Files = {options.DeleteUnnecessaryFiles}");
|
||||
Console.WriteLine($" Create IRD After Dumping = {options.CreateIRDAfterDumping}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Skip Options
|
||||
Console.WriteLine("Skip Options:");
|
||||
Console.WriteLine($" Skip System Detection = {options.SkipSystemDetection}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Protection Scanning Options
|
||||
Console.WriteLine("Protection Scanning Options:");
|
||||
Console.WriteLine($" Scan Archives for Protection = {options.ScanArchivesForProtection}");
|
||||
Console.WriteLine($" Include Debug Protection Information = {options.IncludeDebugProtectionInformation}");
|
||||
Console.WriteLine($" Hide Drive Letters = {options.HideDriveLetters}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Logging Options
|
||||
Console.WriteLine("Logging Options:");
|
||||
Console.WriteLine($" Verbose Logging = {options.VerboseLogging}");
|
||||
Console.WriteLine($" Open Log Window at Startup = {options.OpenLogWindowAtStartup}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Redump Login Information
|
||||
Console.WriteLine("Redump Login Information:");
|
||||
Console.WriteLine($" Retrieve Match Information = {options.RetrieveMatchInformation}");
|
||||
Console.WriteLine($" Redump Username = {options.RedumpUsername}");
|
||||
Console.WriteLine($" Redump Password = {(string.IsNullOrEmpty(options.RedumpPassword) ? "[UNSET]" : "[SET]")}");
|
||||
Console.WriteLine();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
38
MPF.Frontend/Features/ListMediaTypesFeature.cs
Normal file
38
MPF.Frontend/Features/ListMediaTypesFeature.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using SabreTools.CommandLine;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class ListMediaTypesFeature : Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "listmedia";
|
||||
|
||||
private static readonly string[] _flags = ["lm", "listmedia"];
|
||||
|
||||
private const string _description = "List supported media types";
|
||||
|
||||
#endregion
|
||||
|
||||
public ListMediaTypesFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine("Supported Media Types:");
|
||||
foreach (string mediaType in SabreTools.RedumpLib.Data.Extensions.ListMediaTypes())
|
||||
{
|
||||
Console.WriteLine(mediaType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
57
MPF.Frontend/Features/ListProgramsFeature.cs
Normal file
57
MPF.Frontend/Features/ListProgramsFeature.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.CommandLine;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class ListProgramsFeature : Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "listprograms";
|
||||
|
||||
private static readonly string[] _flags = ["lp", "listprograms"];
|
||||
|
||||
private const string _description = "List supported dumping program outputs";
|
||||
|
||||
#endregion
|
||||
|
||||
public ListProgramsFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine("Supported Programs:");
|
||||
foreach (string program in ListPrograms())
|
||||
{
|
||||
Console.WriteLine(program);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
|
||||
/// <summary>
|
||||
/// List all programs with their short usable names
|
||||
/// </summary>
|
||||
private static List<string> ListPrograms()
|
||||
{
|
||||
var programs = new List<string>();
|
||||
|
||||
foreach (var val in Enum.GetValues(typeof(InternalProgram)))
|
||||
{
|
||||
if (((InternalProgram)val!) == InternalProgram.NONE)
|
||||
continue;
|
||||
|
||||
programs.Add($"{((InternalProgram?)val).ShortName()} - {((InternalProgram?)val).LongName()}");
|
||||
}
|
||||
|
||||
return programs;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
MPF.Frontend/Features/ListSystemsFeature.cs
Normal file
38
MPF.Frontend/Features/ListSystemsFeature.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using SabreTools.CommandLine;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class ListSystemsFeature : Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "listsystems";
|
||||
|
||||
private static readonly string[] _flags = ["ls", "listsystems"];
|
||||
|
||||
private const string _description = "List supported system types";
|
||||
|
||||
#endregion
|
||||
|
||||
public ListSystemsFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine("Supported Systems:");
|
||||
foreach (string system in SabreTools.RedumpLib.Data.Extensions.ListSystems())
|
||||
{
|
||||
Console.WriteLine(system);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
34
MPF.Frontend/Features/VersionFeature.cs
Normal file
34
MPF.Frontend/Features/VersionFeature.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.CommandLine;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class VersionFeature : Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "version";
|
||||
|
||||
private static readonly string[] _flags = ["version"];
|
||||
|
||||
private const string _description = "Display the program version";
|
||||
|
||||
#endregion
|
||||
|
||||
public VersionFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine(FrontendTool.GetCurrentVersion() ?? "Unknown version");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
@@ -33,11 +33,6 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public static List<int> BD => _speedValues.FindAll(s => s <= 16);
|
||||
|
||||
/// <summary>
|
||||
/// Set of accepted speeds for all other media
|
||||
/// </summary>
|
||||
public static List<int> Unknown => [1];
|
||||
|
||||
/// <summary>
|
||||
/// Get list of all drive speeds for a given MediaType
|
||||
/// </summary>
|
||||
@@ -45,6 +40,7 @@ namespace MPF.Frontend
|
||||
/// <returns>Read-only list of drive speeds</returns>
|
||||
public static List<int> GetSpeedsForMediaType(MediaType? type)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
return type switch
|
||||
{
|
||||
MediaType.CDROM
|
||||
@@ -55,8 +51,11 @@ namespace MPF.Frontend
|
||||
MediaType.HDDVD => HDDVD,
|
||||
MediaType.BluRay
|
||||
or MediaType.NintendoWiiUOpticalDisc => BD,
|
||||
_ => Unknown,
|
||||
|
||||
// Default to CD speed range
|
||||
_ => CD,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<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>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
@@ -10,7 +10,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.3.2</VersionPrefix>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
@@ -31,12 +31,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BinaryObjectScanner" Version="3.3.4" />
|
||||
<PackageReference Include="LibIRD" Version="0.9.3" />
|
||||
<PackageReference Include="BinaryObjectScanner" Version="[3.5.0]" />
|
||||
<PackageReference Include="LibIRD" Version="[1.0.1]" />
|
||||
<PackageReference Include="Microsoft.Management.Infrastructure" Version="3.0.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="Microsoft.Net.Http" Version="2.2.29" Condition="$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.6.7" />
|
||||
<PackageReference Include="MinThreadingBridge" Version="0.11.4" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -42,4 +42,4 @@ namespace MPF.Frontend
|
||||
IEnumerator IEnumerable.GetEnumerator() => _queue.GetEnumerator();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using AaruSettings = MPF.ExecutionContexts.Aaru.SettingConstants;
|
||||
using DICSettings = MPF.ExecutionContexts.DiscImageCreator.SettingConstants;
|
||||
// using DreamdumpSectorOrder = MPF.ExecutionContexts.Dreamdump.SectorOrder;
|
||||
// using DreamdumpSettings = MPF.ExecutionContexts.Dreamdump.SettingConstants;
|
||||
using LogCompression = MPF.Processors.LogCompression;
|
||||
using RedumperDriveType = MPF.ExecutionContexts.Redumper.DriveType;
|
||||
using RedumperReadMethod = MPF.ExecutionContexts.Redumper.ReadMethod;
|
||||
using RedumperSectorOrder = MPF.ExecutionContexts.Redumper.SectorOrder;
|
||||
@@ -11,6 +16,108 @@ namespace MPF.Frontend
|
||||
{
|
||||
public class Options
|
||||
{
|
||||
#region Default Paths
|
||||
|
||||
/// <summary>
|
||||
/// Default Aaru path
|
||||
/// </summary>
|
||||
private static string DefaultAaruPath
|
||||
{
|
||||
get
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
string executableName = Environment.OSVersion.Platform switch
|
||||
{
|
||||
PlatformID.Unix => "aaru",
|
||||
PlatformID.MacOSX => "aaru",
|
||||
_ => "aaru.exe"
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
|
||||
#if NET20 || NET35
|
||||
return Path.Combine("Programs", Path.Combine("Aaru", executableName));
|
||||
#else
|
||||
return Path.Combine("Programs", "Aaru", executableName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default DiscImageCreator path
|
||||
/// </summary>
|
||||
private static string DefaultDiscImageCreatorPath
|
||||
{
|
||||
get
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
string executableName = Environment.OSVersion.Platform switch
|
||||
{
|
||||
PlatformID.Unix => "DiscImageCreator.out",
|
||||
PlatformID.MacOSX => "DiscImageCreator",
|
||||
_ => "DiscImageCreator.exe"
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
|
||||
#if NET20 || NET35
|
||||
return Path.Combine("Programs", Path.Combine("Creator", executableName));
|
||||
#else
|
||||
return Path.Combine("Programs", "Creator", executableName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0051
|
||||
/// <summary>
|
||||
/// Default Dreamdump path
|
||||
/// </summary>
|
||||
private static string DefaultDreamdumpPath
|
||||
{
|
||||
get
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
string executableName = Environment.OSVersion.Platform switch
|
||||
{
|
||||
PlatformID.Unix => "dreamdump",
|
||||
PlatformID.MacOSX => "dreamdump",
|
||||
_ => "dreamdump.exe"
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
|
||||
#if NET20 || NET35
|
||||
return Path.Combine("Programs", Path.Combine("Dreamdump", executableName));
|
||||
#else
|
||||
return Path.Combine("Programs", "Dreamdump", executableName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
|
||||
/// <summary>
|
||||
/// Default Redumper path
|
||||
/// </summary>
|
||||
private static string DefaultRedumperPath
|
||||
{
|
||||
get
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
string executableName = Environment.OSVersion.Platform switch
|
||||
{
|
||||
PlatformID.Unix => "redumper",
|
||||
PlatformID.MacOSX => "redumper",
|
||||
_ => "redumper.exe"
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
|
||||
#if NET20 || NET35
|
||||
return Path.Combine("Programs", Path.Combine("Redumper", executableName));
|
||||
#else
|
||||
return Path.Combine("Programs", "Redumper", executableName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// All settings in the form of a dictionary
|
||||
/// </summary>
|
||||
@@ -32,7 +139,7 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public string? AaruPath
|
||||
{
|
||||
get { return GetStringSetting(Settings, "AaruPath", "Programs\\Aaru\\Aaru.exe"); }
|
||||
get { return GetStringSetting(Settings, "AaruPath", DefaultAaruPath); }
|
||||
set { Settings["AaruPath"] = value; }
|
||||
}
|
||||
|
||||
@@ -41,16 +148,25 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public string? DiscImageCreatorPath
|
||||
{
|
||||
get { return GetStringSetting(Settings, "DiscImageCreatorPath", "Programs\\Creator\\DiscImageCreator.exe"); }
|
||||
get { return GetStringSetting(Settings, "DiscImageCreatorPath", DefaultDiscImageCreatorPath); }
|
||||
set { Settings["DiscImageCreatorPath"] = value; }
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Path to Dreamdump
|
||||
// /// </summary>
|
||||
// public string? DreamdumpPath
|
||||
// {
|
||||
// get { return GetStringSetting(Settings, "DreamdumpPath", DefaultDreamdumpPath); }
|
||||
// set { Settings["DreamdumpPath"] = value; }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Path to Redumper
|
||||
/// </summary>
|
||||
public string? RedumperPath
|
||||
{
|
||||
get { return GetStringSetting(Settings, "RedumperPath", "Programs\\Redumper\\redumper.exe"); }
|
||||
get { return GetStringSetting(Settings, "RedumperPath", DefaultRedumperPath); }
|
||||
set { Settings["RedumperPath"] = value; }
|
||||
}
|
||||
|
||||
@@ -123,6 +239,15 @@ namespace MPF.Frontend
|
||||
set { Settings["CheckForUpdatesOnStartup"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to copy the update URL to the clipboard if one is found
|
||||
/// </summary>
|
||||
public bool CopyUpdateUrlToClipboard
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, "CopyUpdateUrlToClipboard", true); }
|
||||
set { Settings["CopyUpdateUrlToClipboard"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fast update label - Skips disc checks and updates path only
|
||||
/// </summary>
|
||||
@@ -132,6 +257,22 @@ namespace MPF.Frontend
|
||||
set { Settings["FastUpdateLabel"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default interface language to launch MPF into
|
||||
/// </summary>
|
||||
public InterfaceLanguage DefaultInterfaceLanguage
|
||||
{
|
||||
get
|
||||
{
|
||||
var valueString = GetStringSetting(Settings, "DefaultInterfaceLanguage", InterfaceLanguage.AutoDetect.ShortName());
|
||||
return valueString.ToInterfaceLanguage();
|
||||
}
|
||||
set
|
||||
{
|
||||
Settings["DefaultInterfaceLanguage"] = value.ShortName();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default output path for dumps
|
||||
/// </summary>
|
||||
@@ -148,13 +289,13 @@ namespace MPF.Frontend
|
||||
{
|
||||
get
|
||||
{
|
||||
var valueString = GetStringSetting(Settings, "DefaultSystem", RedumpSystem.IBMPCcompatible.LongName());
|
||||
var valueEnum = Extensions.ToRedumpSystem(valueString ?? string.Empty);
|
||||
var valueString = GetStringSetting(Settings, "DefaultSystem", RedumpSystem.IBMPCcompatible.ToString());
|
||||
var valueEnum = (valueString ?? string.Empty).ToRedumpSystem();
|
||||
return valueEnum;
|
||||
}
|
||||
set
|
||||
{
|
||||
Settings["DefaultSystem"] = value.LongName();
|
||||
Settings["DefaultSystem"] = value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,6 +472,44 @@ namespace MPF.Frontend
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dreamdump
|
||||
|
||||
// /// <summary>
|
||||
// /// Enable options incompatible with redump submissions
|
||||
// /// </summary>
|
||||
// public bool DreamdumpNonRedumpMode
|
||||
// {
|
||||
// get { return GetBooleanSetting(Settings, "DreamdumpNonRedumpMode", false); }
|
||||
// set { Settings["DreamdumpNonRedumpMode"] = value.ToString(); }
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Currently selected default Dreamdump sector order
|
||||
// /// </summary>
|
||||
// public DreamdumpSectorOrder DreamdumpSectorOrder
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// var valueString = GetStringSetting(Settings, DreamdumpSettings.SectorOrder, DreamdumpSettings.SectorOrderDefault);
|
||||
// return valueString.ToDreamdumpSectorOrder();
|
||||
// }
|
||||
// set
|
||||
// {
|
||||
// Settings[DreamdumpSettings.SectorOrder] = value.ToString();
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Default number of rereads
|
||||
// /// </summary>
|
||||
// public int DreamdumpRereadCount
|
||||
// {
|
||||
// get { return GetInt32Setting(Settings, DreamdumpSettings.RereadCount, DreamdumpSettings.RereadCountDefault); }
|
||||
// set { Settings[DreamdumpSettings.RereadCount] = value.ToString(); }
|
||||
// }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Redumper
|
||||
|
||||
/// <summary>
|
||||
@@ -386,6 +565,15 @@ namespace MPF.Frontend
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected default redumper drive pregap start sector
|
||||
/// </summary>
|
||||
public int RedumperDrivePregapStart
|
||||
{
|
||||
get { return GetInt32Setting(Settings, RedumperSettings.DrivePregapStart, RedumperSettings.DrivePregapStartDefault); }
|
||||
set { Settings[RedumperSettings.DrivePregapStart] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected default redumper read method
|
||||
/// </summary>
|
||||
@@ -427,6 +615,15 @@ namespace MPF.Frontend
|
||||
set { Settings[RedumperSettings.RereadCount] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable the refine sector mode flag by default
|
||||
/// </summary>
|
||||
public bool RedumperRefineSectorMode
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, RedumperSettings.RefineSectorMode, RedumperSettings.RefineSectorModeDefault); }
|
||||
set { Settings[RedumperSettings.RefineSectorMode] = value.ToString(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extra Dumping Options
|
||||
@@ -450,7 +647,7 @@ namespace MPF.Frontend
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the disc information window after dumping
|
||||
/// Show the media information window after dumping
|
||||
/// </summary>
|
||||
public bool PromptForDiscInformation
|
||||
{
|
||||
@@ -486,7 +683,7 @@ namespace MPF.Frontend
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show disc eject reminder before the disc information window is shown
|
||||
/// Show disc eject reminder before the media information window is shown
|
||||
/// </summary>
|
||||
public bool ShowDiscEjectReminder
|
||||
{
|
||||
@@ -539,6 +736,22 @@ namespace MPF.Frontend
|
||||
set { Settings["CompressLogFiles"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compression type used during log compression
|
||||
/// </summary>
|
||||
public LogCompression LogCompression
|
||||
{
|
||||
get
|
||||
{
|
||||
var valueString = GetStringSetting(Settings, "LogCompression", LogCompression.DeflateMaximum.ToString());
|
||||
return valueString.ToLogCompression();
|
||||
}
|
||||
set
|
||||
{
|
||||
Settings["LogCompression"] = value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete unnecessary files to reduce space
|
||||
/// </summary>
|
||||
@@ -561,15 +774,6 @@ namespace MPF.Frontend
|
||||
|
||||
#region Skip Options
|
||||
|
||||
/// <summary>
|
||||
/// Skip detecting media type on disc scan
|
||||
/// </summary>
|
||||
public bool SkipMediaTypeDetection
|
||||
{
|
||||
get { return GetBooleanSetting(Settings, "SkipMediaTypeDetection", false); }
|
||||
set { Settings["SkipMediaTypeDetection"] = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skip detecting known system on disc scan
|
||||
/// </summary>
|
||||
|
||||
@@ -9,4 +9,4 @@ namespace MPF.Frontend
|
||||
/// <param name="info">Submission info that may be overwritten</param>
|
||||
/// <returns>True for successful updating, false or null otherwise</returns>
|
||||
public delegate bool? ProcessUserInfoDelegate(Options? options, ref SubmissionInfo? info);
|
||||
}
|
||||
}
|
||||
|
||||
108
MPF.Frontend/Progress.cs
Normal file
108
MPF.Frontend/Progress.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
#if NET20 || NET35 || NET40
|
||||
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace MPF.Frontend
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an IProgress{T} that invokes callbacks for each reported progress value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Specifies the type of the progress report value.</typeparam>
|
||||
/// <remarks>
|
||||
/// Any handler provided to the constructor or event handlers registered with
|
||||
/// the <see cref="ProgressChanged"/> event are invoked through a
|
||||
/// <see cref="SynchronizationContext"/> instance captured
|
||||
/// when the instance is constructed. If there is no current SynchronizationContext
|
||||
/// at the time of construction, the callbacks will be invoked on the ThreadPool.
|
||||
/// </remarks>
|
||||
/// <see href="https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Progress.cs"/>
|
||||
internal class Progress<T> : IProgress<T> where T : EventArgs
|
||||
{
|
||||
/// <summary>The synchronization context captured upon construction. This will never be null.</summary>
|
||||
private readonly SynchronizationContext? _synchronizationContext;
|
||||
/// <summary>The handler specified to the constructor. This may be null.</summary>
|
||||
private readonly Action<T>? _handler;
|
||||
/// <summary>A cached delegate used to post invocation to the synchronization context.</summary>
|
||||
private readonly SendOrPostCallback _invokeHandlers;
|
||||
|
||||
/// <summary>Initializes the <see cref="Progress{T}"/>.</summary>
|
||||
public Progress()
|
||||
{
|
||||
// Capture the current synchronization context.
|
||||
// If there is no current context, we use a default instance targeting the ThreadPool.
|
||||
_synchronizationContext = SynchronizationContext.Current ?? ProgressStatics.DefaultContext;
|
||||
Debug.Assert(_synchronizationContext is not null);
|
||||
_invokeHandlers = new SendOrPostCallback(InvokeHandlers);
|
||||
}
|
||||
|
||||
/// <summary>Initializes the <see cref="Progress{T}"/> with the specified callback.</summary>
|
||||
/// <param name="handler">
|
||||
/// A handler to invoke for each reported progress value. This handler will be invoked
|
||||
/// in addition to any delegates registered with the <see cref="ProgressChanged"/> event.
|
||||
/// Depending on the <see cref="SynchronizationContext"/> instance captured by
|
||||
/// the <see cref="Progress{T}"/> at construction, it's possible that this handler instance
|
||||
/// could be invoked concurrently with itself.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="handler"/> is null (<see langword="Nothing" /> in Visual Basic).</exception>
|
||||
public Progress(Action<T> handler) : this()
|
||||
{
|
||||
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
|
||||
}
|
||||
|
||||
/// <summary>Raised for each reported progress value.</summary>
|
||||
/// <remarks>
|
||||
/// Handlers registered with this event will be invoked on the
|
||||
/// <see cref="SynchronizationContext"/> captured when the instance was constructed.
|
||||
/// </remarks>
|
||||
public event EventHandler<T>? ProgressChanged;
|
||||
|
||||
/// <summary>Reports a progress change.</summary>
|
||||
/// <param name="value">The value of the updated progress.</param>
|
||||
protected virtual void OnReport(T value)
|
||||
{
|
||||
// If there's no handler, don't bother going through the sync context.
|
||||
// Inside the callback, we'll need to check again, in case
|
||||
// an event handler is removed between now and then.
|
||||
Action<T>? handler = _handler;
|
||||
EventHandler<T>? changedEvent = ProgressChanged;
|
||||
if (handler is not null || changedEvent is not null)
|
||||
{
|
||||
// Post the processing to the sync context.
|
||||
// (If T is a value type, it will get boxed here.)
|
||||
_synchronizationContext?.Post(_invokeHandlers, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Reports a progress change.</summary>
|
||||
/// <param name="value">The value of the updated progress.</param>
|
||||
void IProgress<T>.Report(T value) { OnReport(value); }
|
||||
|
||||
/// <summary>Invokes the action and event callbacks.</summary>
|
||||
/// <param name="state">The progress value.</param>
|
||||
private void InvokeHandlers(object? state)
|
||||
{
|
||||
T value = (T)state!;
|
||||
|
||||
Action<T>? handler = _handler;
|
||||
EventHandler<T>? changedEvent = ProgressChanged;
|
||||
|
||||
handler?.Invoke(value);
|
||||
changedEvent?.Invoke(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Holds static values for <see cref="Progress{T}"/>.</summary>
|
||||
/// <remarks>This avoids one static instance per type T.</remarks>
|
||||
internal static class ProgressStatics
|
||||
{
|
||||
/// <summary>A default synchronization context that targets the ThreadPool.</summary>
|
||||
internal static readonly SynchronizationContext DefaultContext = new();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -10,19 +10,30 @@ namespace MPF.Frontend
|
||||
/// <summary>
|
||||
/// Internal representation of success
|
||||
/// </summary>
|
||||
private readonly bool _success;
|
||||
private readonly bool? _success;
|
||||
|
||||
/// <summary>
|
||||
/// Optional message for the result
|
||||
/// </summary>
|
||||
public string Message { get; }
|
||||
|
||||
private ResultEventArgs(bool success, string message)
|
||||
private ResultEventArgs(bool? success, string message)
|
||||
{
|
||||
_success = success;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a default neutral result with no message
|
||||
/// </summary>
|
||||
public static ResultEventArgs Neutral() => new(null, string.Empty);
|
||||
|
||||
/// <summary>
|
||||
/// Create a neutral result with a custom message
|
||||
/// </summary>
|
||||
/// <param name="message">String to add as a message</param>
|
||||
public static ResultEventArgs Neutral(string? message) => new(null, message ?? string.Empty);
|
||||
|
||||
/// <summary>
|
||||
/// Create a default success result with no message
|
||||
/// </summary>
|
||||
@@ -49,7 +60,7 @@ namespace MPF.Frontend
|
||||
/// <summary>
|
||||
/// Results can be compared to boolean values based on the success value
|
||||
/// </summary>
|
||||
public static implicit operator bool(ResultEventArgs result) => result._success;
|
||||
public static implicit operator bool?(ResultEventArgs result) => result._success;
|
||||
|
||||
/// <summary>
|
||||
/// Results can be compared to boolean values based on the success value
|
||||
|
||||
@@ -49,4 +49,4 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public static implicit operator StringEventArgs(StringBuilder? sb) => new(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Frontend.Tools
|
||||
@@ -15,6 +16,7 @@ namespace MPF.Frontend.Tools
|
||||
/// </summary>
|
||||
public static int GetDefaultSpeedForMediaType(MediaType? mediaType, Options options)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
return mediaType switch
|
||||
{
|
||||
// CD dump speed
|
||||
@@ -36,6 +38,7 @@ namespace MPF.Frontend.Tools
|
||||
// Default
|
||||
_ => options.PreferredDumpSpeedCD,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -48,6 +51,9 @@ namespace MPF.Frontend.Tools
|
||||
if (string.IsNullOrEmpty(volumeLabel))
|
||||
return null;
|
||||
|
||||
// Trim the volume label
|
||||
volumeLabel = volumeLabel!.Trim();
|
||||
|
||||
// Audio CD
|
||||
if (volumeLabel!.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.AudioCD;
|
||||
@@ -113,7 +119,7 @@ namespace MPF.Frontend.Tools
|
||||
public static string? NormalizeDiscTitle(string? title, Language?[]? languages)
|
||||
{
|
||||
// If we have no set languages, then assume English
|
||||
if (languages == null || languages.Length == 0)
|
||||
if (languages is null || languages.Length == 0)
|
||||
languages = [Language.English];
|
||||
|
||||
// Loop through all of the given languages
|
||||
@@ -150,8 +156,7 @@ namespace MPF.Frontend.Tools
|
||||
return title;
|
||||
|
||||
// If we have an invalid language, assume Language.English
|
||||
if (language == null)
|
||||
language = Language.English;
|
||||
language ??= Language.English;
|
||||
|
||||
// Get the title split into parts
|
||||
string[] splitTitle = Array.FindAll(title!.Split(' '), s => !string.IsNullOrEmpty(s));
|
||||
@@ -495,12 +500,20 @@ namespace MPF.Frontend.Tools
|
||||
else if (!itemInserted && segment.EndsWith(":"))
|
||||
{
|
||||
itemInserted = true;
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
newTitleBuilder.Append($" {segment[..^1]}, {firstItem}:");
|
||||
#else
|
||||
newTitleBuilder.Append($" {segment.Substring(0, segment.Length - 1)}, {firstItem}:");
|
||||
#endif
|
||||
}
|
||||
else if (!itemInserted && segment.EndsWith("-"))
|
||||
{
|
||||
itemInserted = true;
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
newTitleBuilder.Append($" {segment[..^1]}, {firstItem}-");
|
||||
#else
|
||||
newTitleBuilder.Append($" {segment.Substring(0, segment.Length - 1)}, {firstItem}-");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -522,7 +535,6 @@ namespace MPF.Frontend.Tools
|
||||
/// <param name="path">Path value to normalize</param>
|
||||
public static string NormalizeOutputPaths(string? path, bool getFullPath)
|
||||
{
|
||||
// The easy way
|
||||
try
|
||||
{
|
||||
// If we have an invalid path
|
||||
@@ -536,21 +548,27 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Remove invalid path characters
|
||||
foreach (char c in Path.GetInvalidPathChars())
|
||||
{
|
||||
path = path.Replace(c, '_');
|
||||
}
|
||||
|
||||
// Try getting the combined path and returning that directly
|
||||
string fullPath = getFullPath ? Path.GetFullPath(path) : path;
|
||||
var fullDirectory = Path.GetDirectoryName(fullPath);
|
||||
string fullFile = Path.GetFileName(fullPath);
|
||||
var fullDirectory = Path.GetDirectoryName(fullPath)?.Trim();
|
||||
string fullFile = Path.GetFileName(fullPath).Trim();
|
||||
|
||||
// Remove invalid filename characters
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
{
|
||||
fullFile = fullFile.Replace(c, '_');
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(fullDirectory))
|
||||
return fullFile;
|
||||
else
|
||||
return Path.Combine(fullDirectory, fullFile);
|
||||
// Rebuild the path, if necessary
|
||||
if (!string.IsNullOrEmpty(fullDirectory))
|
||||
fullFile = Path.Combine(fullDirectory, fullFile);
|
||||
|
||||
// Remove spaces before and after separators
|
||||
return Regex.Replace(fullFile, @"\s*([\\|/])\s*", @"$1");
|
||||
}
|
||||
catch { }
|
||||
|
||||
@@ -575,7 +593,7 @@ namespace MPF.Frontend.Tools
|
||||
{
|
||||
// Get current assembly version
|
||||
var assemblyVersion = Assembly.GetEntryAssembly()?.GetName()?.Version;
|
||||
if (assemblyVersion == null)
|
||||
if (assemblyVersion is null)
|
||||
{
|
||||
different = false;
|
||||
message = "Assembly version could not be determined";
|
||||
@@ -587,7 +605,7 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Get the latest tag from GitHub
|
||||
_ = GetRemoteVersionAndUrl(out string? tag, out url);
|
||||
different = version != tag && tag != null;
|
||||
different = version != tag && tag is not null;
|
||||
|
||||
message = $"Local version: {version}"
|
||||
+ $"{Environment.NewLine}Remote version: {tag}"
|
||||
@@ -611,7 +629,7 @@ namespace MPF.Frontend.Tools
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.GetEntryAssembly();
|
||||
if (assembly == null)
|
||||
if (assembly is null)
|
||||
return null;
|
||||
|
||||
var assemblyVersion = Attribute.GetCustomAttribute(assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute;
|
||||
@@ -644,11 +662,11 @@ namespace MPF.Frontend.Tools
|
||||
message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0");
|
||||
var latestReleaseJsonString = hc.SendAsync(message)?.ConfigureAwait(false).GetAwaiter().GetResult()
|
||||
.Content?.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
if (latestReleaseJsonString == null)
|
||||
if (latestReleaseJsonString is null)
|
||||
return false;
|
||||
|
||||
var latestReleaseJson = Newtonsoft.Json.Linq.JObject.Parse(latestReleaseJsonString);
|
||||
if (latestReleaseJson == null)
|
||||
if (latestReleaseJson is null)
|
||||
return false;
|
||||
|
||||
tag = latestReleaseJson["tag_name"]?.ToString();
|
||||
@@ -660,4 +678,4 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
99
MPF.Frontend/Tools/IRDTool.cs
Normal file
99
MPF.Frontend/Tools/IRDTool.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using MPF.Processors;
|
||||
|
||||
namespace MPF.Frontend.Tools
|
||||
{
|
||||
internal static class IRDTool
|
||||
{
|
||||
/// <summary>
|
||||
/// Create an IRD and write it next to the input ISO path
|
||||
/// </summary>
|
||||
/// <param name="isoPath">Path to the original ISO</param>
|
||||
/// <param name="discKeyString">Required hexadecimal disc key as a string</param>
|
||||
/// <param name="discIDString">Optional hexadecimal disc ID as a string</param>
|
||||
/// <param name="picString">Optional string representation of the PIC information</param>
|
||||
/// <param name="layerbreak">Optional disc layerbreak value</param>
|
||||
/// <param name="crc32">Optional ISO CRC-32 value for the Unique ID field</param>
|
||||
/// <returns>True on success, false on error</returns>
|
||||
public static async Task<bool> WriteIRD(string isoPath,
|
||||
string? discKeyString,
|
||||
string? discIDString,
|
||||
string? picString,
|
||||
long? layerbreak,
|
||||
string? crc32)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse string values into required formats
|
||||
byte[]? discKey = ProcessingTool.ParseHexKey(discKeyString);
|
||||
byte[]? discID = ProcessingTool.ParseDiscID(discIDString);
|
||||
byte[]? pic = ProcessingTool.ParsePIC(picString);
|
||||
uint? uid = ProcessingTool.ParseCRC32(crc32);
|
||||
|
||||
return await WriteIRD(isoPath, discKey, discID, pic, layerbreak, uid);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an IRD and write it next to the input ISO path
|
||||
/// </summary>
|
||||
/// <param name="isoPath">Path to the original ISO</param>
|
||||
/// <param name="discKey">Required hexadecimal disc key as a byte array</param>
|
||||
/// <param name="discID">Optional hexadecimal disc ID as a byte array</param>
|
||||
/// <param name="pic">Optional byte array representation of the PIC information</param>
|
||||
/// <param name="layerbreak">Optional disc layerbreak value</param>
|
||||
/// <param name="uid">Optional ISO CRC-32 value for the Unique ID field</param>
|
||||
/// <returns>True on success, false on error</returns>
|
||||
public static async Task<bool> WriteIRD(string isoPath,
|
||||
byte[]? discKey,
|
||||
byte[]? discID,
|
||||
byte[]? pic,
|
||||
long? layerbreak,
|
||||
uint? uid)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Fail on a missing disc key
|
||||
if (discKey is null)
|
||||
return false;
|
||||
|
||||
// Output IRD file path
|
||||
string irdPath = Path.ChangeExtension(isoPath, ".ird");
|
||||
|
||||
// Ensure layerbreak value is valid
|
||||
layerbreak = ProcessingTool.ParseLayerbreak(layerbreak);
|
||||
|
||||
// Create Redump-style reproducible IRD
|
||||
#if NET40
|
||||
LibIRD.ReIRD ird = await Task.Factory.StartNew(() =>
|
||||
#else
|
||||
LibIRD.ReIRD ird = await Task.Run(() =>
|
||||
#endif
|
||||
new LibIRD.ReIRD(isoPath, discKey, layerbreak, uid));
|
||||
|
||||
// Set optional fields if valid
|
||||
if (pic is not null)
|
||||
ird.PIC = pic;
|
||||
if (discID is not null && ird.DiscID[15] != 0x00)
|
||||
ird.DiscID = discID;
|
||||
|
||||
// Write IRD to file
|
||||
ird.Write(irdPath);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ namespace MPF.Frontend.Tools
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_configPath != null)
|
||||
if (_configPath is not null)
|
||||
return _configPath;
|
||||
|
||||
_configPath = GetConfigurationPath();
|
||||
@@ -32,97 +32,6 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
#region Arguments
|
||||
|
||||
/// <summary>
|
||||
/// Process any standalone arguments for the program
|
||||
/// </summary>
|
||||
/// <returns>True if one of the arguments was processed, false otherwise</returns>
|
||||
public static bool? ProcessStandaloneArguments(string[] args)
|
||||
{
|
||||
// Help options
|
||||
if (args.Length == 0 || args[0] == "-h" || args[0] == "-?")
|
||||
return null;
|
||||
|
||||
// List options
|
||||
if (args[0] == "-lc" || args[0] == "--listcodes")
|
||||
{
|
||||
Console.WriteLine("Supported Site Codes:");
|
||||
foreach (string siteCode in Extensions.ListSiteCodes())
|
||||
{
|
||||
Console.WriteLine(siteCode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (args[0] == "-lm" || args[0] == "--listmedia")
|
||||
{
|
||||
Console.WriteLine("Supported Media Types:");
|
||||
foreach (string mediaType in Extensions.ListMediaTypes())
|
||||
{
|
||||
Console.WriteLine(mediaType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (args[0] == "-lp" || args[0] == "--listprograms")
|
||||
{
|
||||
Console.WriteLine("Supported Programs:");
|
||||
foreach (string program in ListPrograms())
|
||||
{
|
||||
Console.WriteLine(program);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (args[0] == "-ls" || args[0] == "--listsystems")
|
||||
{
|
||||
Console.WriteLine("Supported Systems:");
|
||||
foreach (string system in Extensions.ListSystems())
|
||||
{
|
||||
Console.WriteLine(system);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process common arguments for all functionality
|
||||
/// </summary>
|
||||
/// <returns>True if all arguments pass, false otherwise</returns>
|
||||
public static bool ProcessCommonArguments(string[] args, out MediaType mediaType, out RedumpSystem? system, out string? message)
|
||||
{
|
||||
// All other use requires at least 3 arguments
|
||||
if (args.Length < 3)
|
||||
{
|
||||
mediaType = MediaType.NONE;
|
||||
system = null;
|
||||
message = "Invalid number of arguments";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the MediaType
|
||||
mediaType = ToMediaType(args[0].Trim('"'));
|
||||
if (mediaType == MediaType.NONE)
|
||||
{
|
||||
system = null;
|
||||
message = $"{args[0]} is not a recognized media type";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the RedumpSystem
|
||||
system = Extensions.ToRedumpSystem(args[1].Trim('"'));
|
||||
if (system == null)
|
||||
{
|
||||
message = $"{args[1]} is not a recognized system";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the MediaType enum value for a given string
|
||||
/// </summary>
|
||||
@@ -266,24 +175,6 @@ namespace MPF.Frontend.Tools
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all programs with their short usable names
|
||||
/// </summary>
|
||||
private static List<string> ListPrograms()
|
||||
{
|
||||
var programs = new List<string>();
|
||||
|
||||
foreach (var val in Enum.GetValues(typeof(InternalProgram)))
|
||||
{
|
||||
if (((InternalProgram)val!) == InternalProgram.NONE)
|
||||
continue;
|
||||
|
||||
programs.Add($"{((InternalProgram?)val).ShortName()} - {((InternalProgram?)val).LongName()}");
|
||||
}
|
||||
|
||||
return programs;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Configuration
|
||||
@@ -297,18 +188,15 @@ namespace MPF.Frontend.Tools
|
||||
if (string.IsNullOrEmpty(ConfigurationPath))
|
||||
return new Options();
|
||||
|
||||
// Ensure the file exists
|
||||
// If the file does not exist
|
||||
if (!File.Exists(ConfigurationPath) || new FileInfo(ConfigurationPath).Length == 0)
|
||||
{
|
||||
File.Create(ConfigurationPath).Dispose();
|
||||
return new Options();
|
||||
}
|
||||
|
||||
var serializer = JsonSerializer.Create();
|
||||
var stream = File.Open(ConfigurationPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
var reader = new StreamReader(stream);
|
||||
var stream = File.Open(ConfigurationPath, FileMode.Open, FileAccess.Read, FileShare.None);
|
||||
using var reader = new StreamReader(stream);
|
||||
var settings = serializer.Deserialize(reader, typeof(Dictionary<string, string?>)) as Dictionary<string, string?>;
|
||||
reader.Dispose();
|
||||
|
||||
return new Options(settings);
|
||||
}
|
||||
|
||||
@@ -337,13 +225,11 @@ namespace MPF.Frontend.Tools
|
||||
property.SetValue(options, val, null);
|
||||
}
|
||||
|
||||
// Handle a very strange edge case
|
||||
if (!File.Exists(ConfigurationPath))
|
||||
File.Create(ConfigurationPath).Dispose();
|
||||
|
||||
var serializer = JsonSerializer.Create();
|
||||
var sw = new StreamWriter(ConfigurationPath) { AutoFlush = true };
|
||||
var stream = File.Open(ConfigurationPath, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
using var sw = new StreamWriter(stream) { AutoFlush = true };
|
||||
var writer = new JsonTextWriter(sw) { Formatting = Formatting.Indented };
|
||||
|
||||
serializer.Serialize(writer, options.Settings, typeof(Dictionary<string, string>));
|
||||
}
|
||||
|
||||
@@ -352,27 +238,17 @@ namespace MPF.Frontend.Tools
|
||||
/// </summary>
|
||||
private static string GetConfigurationPath()
|
||||
{
|
||||
// User home directory
|
||||
#if NET20 || NET35
|
||||
string homeDir = Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%");
|
||||
homeDir = Path.Combine(Path.Combine(homeDir, ".config"), "mpf");
|
||||
#else
|
||||
string homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
homeDir = Path.Combine(homeDir, ".config", "mpf");
|
||||
#endif
|
||||
// User configuration
|
||||
string homeDir = GetUserConfigurationPath();
|
||||
if (File.Exists(Path.Combine(homeDir, ConfigurationFileName)))
|
||||
return Path.Combine(homeDir, ConfigurationFileName);
|
||||
|
||||
// Local folder
|
||||
#if NET20 || NET35 || NET40 || NET452
|
||||
string runtimeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
#else
|
||||
string runtimeDir = AppContext.BaseDirectory;
|
||||
#endif
|
||||
// Portable configuration
|
||||
string runtimeDir = GetRuntimeConfigurationPath();
|
||||
if (File.Exists(Path.Combine(runtimeDir, ConfigurationFileName)))
|
||||
return Path.Combine(runtimeDir, ConfigurationFileName);
|
||||
|
||||
// Attempt to use local folder
|
||||
// Attempt portable configuration
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(runtimeDir);
|
||||
@@ -381,7 +257,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Attempt to use home directory
|
||||
// Attempt user configuration
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(homeDir);
|
||||
@@ -394,6 +270,34 @@ namespace MPF.Frontend.Tools
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the runtime configuration path
|
||||
/// </summary>
|
||||
private static string GetRuntimeConfigurationPath()
|
||||
{
|
||||
#if NET20 || NET35 || NET40 || NET452
|
||||
return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
#else
|
||||
return AppContext.BaseDirectory;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the user configuration path
|
||||
/// </summary>
|
||||
/// <remarks>Typically this is located in the profile or home directory</remarks>
|
||||
private static string GetUserConfigurationPath()
|
||||
{
|
||||
#if NET20 || NET35
|
||||
string homeDir = Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%");
|
||||
homeDir = Path.Combine(Path.Combine(homeDir, ".config"), "mpf");
|
||||
#else
|
||||
string homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
homeDir = Path.Combine(homeDir, ".config", "mpf");
|
||||
#endif
|
||||
return homeDir;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -49,7 +50,7 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Fix the Y2K timestamp issue, if required
|
||||
if (fixTwoDigitYear)
|
||||
year = year >= 1900 && year < 1920 ? 2000 + year % 100 : year;
|
||||
year = year >= 1900 && year < 1920 ? 2000 + (year % 100) : year;
|
||||
|
||||
// Format and return the string
|
||||
var dt = new DateTime(year, month, day);
|
||||
@@ -57,7 +58,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -70,7 +71,7 @@ namespace MPF.Frontend.Tools
|
||||
/// <returns>Byte array of first sector of data, null on error</returns>
|
||||
public static byte[]? GetFirstBytes(Drive? drive, int numBytes)
|
||||
{
|
||||
if (drive == null || drive.Letter == null || drive.Letter == '\0')
|
||||
if (drive is null || drive.Letter is null || drive.Letter == '\0')
|
||||
return null;
|
||||
|
||||
// Must read between 1 and 2048 bytes
|
||||
@@ -93,7 +94,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -149,7 +150,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -205,7 +206,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is, assume SYSTEM.CNF doesn't exist
|
||||
// Absorb the exception, assume SYSTEM.CNF doesn't exist
|
||||
}
|
||||
|
||||
// If the SYSTEM.CNF value can't be found, try PSX.EXE
|
||||
@@ -274,7 +275,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -306,7 +307,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -327,7 +328,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -364,7 +365,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -385,7 +386,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -430,7 +431,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -468,7 +469,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -506,7 +507,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -545,11 +546,11 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Read the app.pkg header
|
||||
using var fileStream = new FileStream(appPkgPath, FileMode.Open, FileAccess.Read);
|
||||
var appPkgHeaderDeserializer = new SabreTools.Serialization.Deserializers.AppPkgHeader();
|
||||
var appPkgHeaderDeserializer = new SabreTools.Serialization.Readers.AppPkgHeader();
|
||||
var appPkgHeader = appPkgHeaderDeserializer.Deserialize(fileStream);
|
||||
|
||||
if (appPkgHeader != null)
|
||||
pkgInfo += $"{appPkgHeader.ContentID}" + Environment.NewLine;
|
||||
if (appPkgHeader is not null)
|
||||
pkgInfo += $"{appPkgHeader.ContentID}{Environment.NewLine}";
|
||||
}
|
||||
|
||||
if (pkgInfo == "")
|
||||
@@ -559,7 +560,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -573,7 +574,7 @@ namespace MPF.Frontend.Tools
|
||||
{
|
||||
// Attempt to get the param.json file
|
||||
var json = GetPlayStation5ParamsJsonFromDrive(drive);
|
||||
if (json == null)
|
||||
if (json is null)
|
||||
return null;
|
||||
|
||||
try
|
||||
@@ -582,7 +583,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -596,7 +597,7 @@ namespace MPF.Frontend.Tools
|
||||
{
|
||||
// Attempt to get the param.json file
|
||||
var json = GetPlayStation5ParamsJsonFromDrive(drive);
|
||||
if (json == null)
|
||||
if (json is null)
|
||||
return null;
|
||||
|
||||
try
|
||||
@@ -605,7 +606,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -657,7 +658,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -696,11 +697,11 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Read the app_sc.pkg header
|
||||
using var fileStream = new FileStream(appPkgPath, FileMode.Open, FileAccess.Read);
|
||||
var appPkgHeaderDeserializer = new SabreTools.Serialization.Deserializers.AppPkgHeader();
|
||||
var appPkgHeaderDeserializer = new SabreTools.Serialization.Readers.AppPkgHeader();
|
||||
var appPkgHeader = appPkgHeaderDeserializer.Deserialize(fileStream);
|
||||
|
||||
if (appPkgHeader != null)
|
||||
pkgInfo += $"{appPkgHeader.ContentID}" + Environment.NewLine;
|
||||
if (appPkgHeader is not null)
|
||||
pkgInfo += $"{appPkgHeader.ContentID}{Environment.NewLine}";
|
||||
}
|
||||
|
||||
if (pkgInfo == "")
|
||||
@@ -710,7 +711,7 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -726,11 +727,11 @@ namespace MPF.Frontend.Tools
|
||||
/// <returns>Filenames if possible, null on error</returns>
|
||||
public static string? GetXboxFilenames(Drive? drive)
|
||||
{
|
||||
// If there's no drive path, we can't get BEE flag
|
||||
// If there's no drive path, can't do anything
|
||||
if (string.IsNullOrEmpty(drive?.Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't get exe name
|
||||
// If the folder no longer exists, can't do anything
|
||||
if (!Directory.Exists(drive!.Name))
|
||||
return null;
|
||||
|
||||
@@ -747,7 +748,59 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error is
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Title ID(s) for Xbox One and Xbox Series X
|
||||
/// </summary>
|
||||
/// <param name="drive">Drive to extract information from</param>
|
||||
/// <returns>Title ID(s) if possible, null on error</returns>
|
||||
public static string? GetXboxTitleID(Drive? drive)
|
||||
{
|
||||
// If there's no drive path, can't do anything
|
||||
if (string.IsNullOrEmpty(drive?.Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, can't do anything
|
||||
if (!Directory.Exists(drive!.Name))
|
||||
return null;
|
||||
|
||||
// Get the catalog.js path
|
||||
#if NET20 || NET35
|
||||
string catalogjs = Path.Combine(drive.Name, Path.Combine("MSXC", Path.Combine("Metadata", "catalog.js")));
|
||||
#else
|
||||
string catalogjs = Path.Combine(drive.Name, "MSXC", "Metadata", "catalog.js");
|
||||
#endif
|
||||
// Check catalog.js exists
|
||||
if (!File.Exists(catalogjs))
|
||||
return null;
|
||||
|
||||
// Deserialize catalog.js and extract Title ID(s)
|
||||
try
|
||||
{
|
||||
var catalog = new SabreTools.Serialization.Readers.Catalog().Deserialize(catalogjs);
|
||||
if (catalog is null)
|
||||
return null;
|
||||
if (!string.IsNullOrEmpty(catalog.TitleID))
|
||||
return catalog.TitleID;
|
||||
if (catalog.Packages is null)
|
||||
return null;
|
||||
|
||||
List<string> titleIDs = [];
|
||||
foreach (var package in catalog.Packages)
|
||||
{
|
||||
if (package?.TitleID is not null)
|
||||
titleIDs.Add(package.TitleID);
|
||||
}
|
||||
|
||||
return string.Join(", ", [.. titleIDs]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -763,11 +816,11 @@ namespace MPF.Frontend.Tools
|
||||
/// <returns>Detected RedumpSystem if detected, null otherwise</returns>
|
||||
public static RedumpSystem? DetectSegaSystem(Drive? drive)
|
||||
{
|
||||
if (drive == null)
|
||||
if (drive is null)
|
||||
return null;
|
||||
|
||||
byte[]? firstSector = GetFirstBytes(drive, 0x10);
|
||||
if (firstSector == null || firstSector.Length < 0x10)
|
||||
if (firstSector is null || firstSector.Length < 0x10)
|
||||
return null;
|
||||
|
||||
string systemType = Encoding.ASCII.GetString(firstSector, 0x00, 0x10);
|
||||
@@ -797,11 +850,11 @@ namespace MPF.Frontend.Tools
|
||||
/// <returns>RedumpSystem.Panasonic3DOInteractiveMultiplayer if detected, null otherwise</returns>
|
||||
public static RedumpSystem? Detect3DOSystem(Drive? drive)
|
||||
{
|
||||
if (drive == null)
|
||||
if (drive is null)
|
||||
return null;
|
||||
|
||||
byte[]? firstSector = GetFirstBytes(drive, 0xC0);
|
||||
if (firstSector == null || firstSector.Length < 0xC0)
|
||||
if (firstSector is null || firstSector.Length < 0xC0)
|
||||
return null;
|
||||
|
||||
string systemType = Encoding.ASCII.GetString(firstSector, 0xB0, 0x10);
|
||||
@@ -815,4 +868,4 @@ namespace MPF.Frontend.Tools
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
||||
using BinaryObjectScanner;
|
||||
using SabreTools.IO.Extensions;
|
||||
|
||||
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||
namespace MPF.Frontend.Tools
|
||||
{
|
||||
public static class ProtectionTool
|
||||
@@ -42,6 +43,7 @@ namespace MPF.Frontend.Tools
|
||||
"Installer VISE",
|
||||
"Intel Installation Framework",
|
||||
"Microsoft CAB SFX",
|
||||
"MPRESS",
|
||||
"NeoLite",
|
||||
"NSIS",
|
||||
"PE Compact",
|
||||
@@ -65,6 +67,72 @@ namespace MPF.Frontend.Tools
|
||||
#endregion
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Run comprehensive protection scans based on both the
|
||||
/// physical media as well as the image
|
||||
/// </summary>
|
||||
/// <param name="basePath">Base output image path</param>
|
||||
/// <param name="drive">Drive object representing the current drive</param>
|
||||
/// <param name="options">Options object that determines what to scan</param>
|
||||
/// <param name="progress">Optional progress callback</param>
|
||||
public static async Task<Dictionary<string, List<string>>> RunCombinedProtectionScans(string basePath,
|
||||
Drive? drive,
|
||||
Options options,
|
||||
IProgress<ProtectionProgress>? protectionProgress = null)
|
||||
{
|
||||
// Setup the output protections dictionary
|
||||
Dictionary<string, List<string>> protections = [];
|
||||
|
||||
// Scan the disc image, if possible
|
||||
if (File.Exists($"{basePath}.iso"))
|
||||
{
|
||||
var imageProtections = await RunProtectionScanOnImage($"{basePath}.iso", options, protectionProgress);
|
||||
MergeDictionaries(protections, imageProtections);
|
||||
}
|
||||
else if (File.Exists($"{basePath}.bin"))
|
||||
{
|
||||
var imageProtections = await RunProtectionScanOnImage($"{basePath}.bin", options, protectionProgress);
|
||||
MergeDictionaries(protections, imageProtections);
|
||||
}
|
||||
else if (File.Exists($"{basePath}.cue"))
|
||||
{
|
||||
string[] cueLines = File.ReadAllLines($"{basePath}.cue");
|
||||
foreach (string cueLine in cueLines)
|
||||
{
|
||||
// Skip all non-FILE lines
|
||||
if (!cueLine.StartsWith("FILE"))
|
||||
continue;
|
||||
|
||||
// Extract the information
|
||||
var match = Regex.Match(cueLine, @"FILE ""(.*?)"" BINARY");
|
||||
if (!match.Success || match.Groups.Count == 0)
|
||||
continue;
|
||||
|
||||
// Get the track name from the matches
|
||||
string trackName = match.Groups[1].Value;
|
||||
trackName = Path.GetFileNameWithoutExtension(trackName);
|
||||
string baseDir = Path.GetDirectoryName(basePath) ?? string.Empty;
|
||||
string trackPath = Path.Combine(baseDir, trackName);
|
||||
|
||||
// Scan the track for protections, if it exists
|
||||
if (File.Exists($"{trackPath}.bin"))
|
||||
{
|
||||
var trackProtections = await RunProtectionScanOnImage($"{trackPath}.bin", options, protectionProgress);
|
||||
MergeDictionaries(protections, trackProtections);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scan the mounted drive path
|
||||
if (drive?.Name is not null)
|
||||
{
|
||||
var driveProtections = await RunProtectionScanOnPath(drive.Name, options, protectionProgress);
|
||||
MergeDictionaries(protections, driveProtections);
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run protection scan on a given path
|
||||
/// </summary>
|
||||
@@ -72,7 +140,7 @@ namespace MPF.Frontend.Tools
|
||||
/// <param name="options">Options object that determines what to scan</param>
|
||||
/// <param name="progress">Optional progress callback</param>
|
||||
/// <returns>Set of all detected copy protections with an optional error string</returns>
|
||||
public static async Task<ProtectionDictionary> RunProtectionScanOnPath(string path,
|
||||
public static async Task<Dictionary<string, List<string>>> RunProtectionScanOnPath(string path,
|
||||
Options options,
|
||||
IProgress<ProtectionProgress>? progress = null)
|
||||
{
|
||||
@@ -94,11 +162,44 @@ namespace MPF.Frontend.Tools
|
||||
});
|
||||
|
||||
// If nothing was returned, return
|
||||
if (found == null || found.Count == 0)
|
||||
if (found is null || found.Count == 0)
|
||||
return [];
|
||||
|
||||
// Filter out any empty protections
|
||||
found.ClearEmptyKeys();
|
||||
// Return the filtered set of protections
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run protection scan on a disc image
|
||||
/// </summary>
|
||||
/// <param name="image">Image path to scan for protection</param>
|
||||
/// <param name="options">Options object that determines what to scan</param>
|
||||
/// <param name="progress">Optional progress callback</param>
|
||||
/// <returns>Set of all detected copy protections with an optional error string</returns>
|
||||
public static async Task<Dictionary<string, List<string>>> RunProtectionScanOnImage(string image,
|
||||
Options options,
|
||||
IProgress<ProtectionProgress>? progress = null)
|
||||
{
|
||||
#if NET40
|
||||
var found = await Task.Factory.StartNew(() =>
|
||||
#else
|
||||
var found = await Task.Run(() =>
|
||||
#endif
|
||||
{
|
||||
var scanner = new Scanner(
|
||||
scanArchives: false, // Disable extracting disc images for now
|
||||
scanContents: false, // Disabled for image scanning
|
||||
scanPaths: false, // Disabled for image scanning
|
||||
scanSubdirectories: false, // Disabled for image scanning
|
||||
options.IncludeDebugProtectionInformation,
|
||||
progress);
|
||||
|
||||
return scanner.GetProtections(image);
|
||||
});
|
||||
|
||||
// If nothing was returned, return
|
||||
if (found is null || found.Count == 0)
|
||||
return [];
|
||||
|
||||
// Return the filtered set of protections
|
||||
return found;
|
||||
@@ -108,15 +209,21 @@ namespace MPF.Frontend.Tools
|
||||
/// Format found protections to a deduplicated, ordered string
|
||||
/// </summary>
|
||||
/// <param name="protections">Dictionary of file to list of protection mappings</param>
|
||||
/// <param name="drive">Drive object representing the current drive</param>
|
||||
/// <returns>Detected protections, if any</returns>
|
||||
public static string? FormatProtections(ProtectionDictionary? protections)
|
||||
public static string? FormatProtections(Dictionary<string, List<string>>? protections, Drive? drive)
|
||||
{
|
||||
// If the filtered list is empty in some way, return
|
||||
if (protections == null)
|
||||
return "(CHECK WITH PROTECTIONID)";
|
||||
else if (protections.Count == 0)
|
||||
if (protections is null)
|
||||
return "[EXTERNAL SCAN NEEDED]";
|
||||
else if (protections.Count == 0 && drive?.Name is null)
|
||||
return "Mounted disc path missing [EXTERNAL SCAN NEEDED]";
|
||||
else if (protections.Count == 0 && drive?.Name is not null)
|
||||
return "None found [OMIT FROM SUBMISSION]";
|
||||
|
||||
// Sanitize context-sensitive protections
|
||||
protections = SanitizeContextSensitiveProtections(protections);
|
||||
|
||||
// Get a list of distinct found protections
|
||||
#if NET20
|
||||
var protectionValues = new List<string>();
|
||||
@@ -124,7 +231,7 @@ namespace MPF.Frontend.Tools
|
||||
{
|
||||
if (value.Count == 0)
|
||||
continue;
|
||||
|
||||
|
||||
foreach (var prot in value)
|
||||
{
|
||||
if (!protectionValues.Contains(prot))
|
||||
@@ -166,7 +273,7 @@ namespace MPF.Frontend.Tools
|
||||
try
|
||||
{
|
||||
var antiModchip = new BinaryObjectScanner.Protection.PSXAntiModchip();
|
||||
foreach (string file in IOExtensions.SafeGetFiles(path!, "*", SearchOption.AllDirectories))
|
||||
foreach (string file in path!.SafeGetFiles("*", SearchOption.AllDirectories))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -184,6 +291,66 @@ namespace MPF.Frontend.Tools
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sanitize unnecessary protections where context matters
|
||||
/// </summary>
|
||||
/// <param name="protections">Dictionary of file to list of protection mappings</param>
|
||||
/// <returns>Dictionary with all necessary items filtered out</returns>
|
||||
public static Dictionary<string, List<string>> SanitizeContextSensitiveProtections(Dictionary<string, List<string>> protections)
|
||||
{
|
||||
// Setup the output dictionary
|
||||
Dictionary<string, List<string>> filtered = [];
|
||||
|
||||
// Setup a list for keys that need additional processing
|
||||
List<string> foundKeys = [];
|
||||
|
||||
// Loop through the keys and add relevant ones
|
||||
string[] paths = [.. protections.Keys];
|
||||
foreach (var path in paths)
|
||||
{
|
||||
if (!protections.TryGetValue(path, out var values) || values is null || values.Count == 0)
|
||||
continue;
|
||||
|
||||
// Always copy the values if they're valid
|
||||
filtered[path] = values;
|
||||
|
||||
if (values.Exists(s => s.StartsWith("SecuROM Release Control -")))
|
||||
foundKeys.Add(path);
|
||||
}
|
||||
|
||||
// If there are no keys found
|
||||
if (foundKeys.Count == 0)
|
||||
return filtered;
|
||||
|
||||
// Process the keys as necessary
|
||||
foreach (var key in foundKeys)
|
||||
{
|
||||
// Get all matching paths
|
||||
var matchingPaths = Array.FindAll(paths, s => s != key && s.StartsWith(key));
|
||||
if (matchingPaths.Length == 0)
|
||||
continue;
|
||||
|
||||
// Loop through the matching paths
|
||||
foreach (var path in matchingPaths)
|
||||
{
|
||||
if (!filtered.TryGetValue(path, out var values) || values is null || values.Count == 0)
|
||||
continue;
|
||||
|
||||
if (values.Exists(s => !s.Contains("GitHub") &&
|
||||
(s.Contains("SecuROM 7")
|
||||
|| s.Contains("SecuROM 8")
|
||||
|| s.Contains("SecuROM Content Activation")
|
||||
|| s.Contains("SecuROM Data File Activation")
|
||||
|| s.Contains("Unlock"))))
|
||||
{
|
||||
filtered.Remove(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sanitize unnecessary protection duplication from output
|
||||
/// </summary>
|
||||
@@ -200,7 +367,13 @@ namespace MPF.Frontend.Tools
|
||||
// EXCEPTIONS
|
||||
if (foundProtections.Exists(p => p.StartsWith("[Exception opening file")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("[Exception opening file"));
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("[Exception opening file") && !p.StartsWith("[Access issue when opening file"));
|
||||
foundProtections.Add("Exception occurred while scanning [RESCAN NEEDED]");
|
||||
}
|
||||
|
||||
if (foundProtections.Exists(p => p.StartsWith("[Access issue when opening file")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("[Exception opening file") && !p.StartsWith("[Access issue when opening file"));
|
||||
foundProtections.Add("Exception occurred while scanning [RESCAN NEEDED]");
|
||||
}
|
||||
|
||||
@@ -310,9 +483,8 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Best case scenario for SafeDisc 2+: A full SafeDisc version is found in a line starting with "Macrovision Protected Application".
|
||||
// All other SafeDisc detections can be safely scrubbed.
|
||||
// TODO: Scrub "Macrovision Protected Application, " from before the SafeDisc version.
|
||||
if (foundProtections.Exists(p => Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)
|
||||
&& p.StartsWith("Macrovision Protected Application")
|
||||
&& p.Contains("Macrovision Protected Application")
|
||||
&& !p.Contains("SRV Tool APP")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("Macrovision Protection File"))
|
||||
@@ -326,11 +498,14 @@ namespace MPF.Frontend.Tools
|
||||
.FindAll(p => p != "SafeDisc 1/Lite")
|
||||
.FindAll(p => p != "SafeDisc 2+")
|
||||
.FindAll(p => p != "SafeDisc 3+ (DVD)");
|
||||
foundProtections = foundProtections.ConvertAll(p => p
|
||||
.Replace("Macrovision Protected Application, ", string.Empty)
|
||||
.Replace(", Macrovision Protected Application", string.Empty));
|
||||
}
|
||||
|
||||
// Next best case for SafeDisc 2+: A full SafeDisc version is found from the "SafeDisc SRV Tool APP".
|
||||
else if (foundProtections.Exists(p => Regex.IsMatch(p, @"SafeDisc [0-9]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)
|
||||
&& p.StartsWith("Macrovision Protected Application")
|
||||
&& p.Contains("Macrovision Protected Application")
|
||||
&& p.Contains("SRV Tool APP")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("Macrovision Protection File"))
|
||||
@@ -360,7 +535,7 @@ namespace MPF.Frontend.Tools
|
||||
.FindAll(p => p != "SafeDisc 2+");
|
||||
}
|
||||
|
||||
// Best case for SafeDisc 1.X: A full SafeDisc version is found that isn't part of a version range.
|
||||
// Best case for SafeDisc 1.X: A full SafeDisc version is found that isn't part of a version range.
|
||||
else if (foundProtections.Exists(p => Regex.IsMatch(p, @"SafeDisc 1\.[0-9]{2}\.[0-9]{3}$", RegexOptions.Compiled)
|
||||
&& !Regex.IsMatch(p, @"SafeDisc 1\.[0-9]{2}\.[0-9]{3}-[0-9]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)))
|
||||
{
|
||||
@@ -374,9 +549,8 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
|
||||
// Next best case for SafeDisc 1: A SafeDisc version range is found from "SECDRV.SYS".
|
||||
// TODO: Scrub "Macrovision Security Driver {Version}" from before the SafeDisc version.
|
||||
else if (foundProtections.Exists(p => p.StartsWith("Macrovision Security Driver")
|
||||
&& Regex.IsMatch(p, @"SafeDisc 1\.[0-9]{2}\.[0-9]{3}-[1-2]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled)
|
||||
else if (foundProtections.Exists(p => (p.StartsWith("Macrovision Security Driver")
|
||||
&& Regex.IsMatch(p, @"SafeDisc 1\.[0-9]{2}\.[0-9]{3}-[1-2]\.[0-9]{2}\.[0-9]{3}", RegexOptions.Compiled))
|
||||
|| Regex.IsMatch(p, @"SafeDisc 1\.[0-9]{2}\.[0-9]{3}$")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("Macrovision Protection File"))
|
||||
@@ -386,10 +560,12 @@ namespace MPF.Frontend.Tools
|
||||
.FindAll(p => p != "SafeDisc")
|
||||
.FindAll(p => p != "SafeDisc 1")
|
||||
.FindAll(p => p != "SafeDisc 1/Lite");
|
||||
foundProtections = foundProtections.ConvertAll(p => p.StartsWith("Macrovision Security Driver") && p.Split('/').Length > 1
|
||||
? p.Split('/')[1].TrimStart()
|
||||
: p);
|
||||
}
|
||||
|
||||
// Next best case for SafeDisc 2+: A SafeDisc version range is found from "SECDRV.SYS".
|
||||
// TODO: Scrub "Macrovision Security Driver {Version}" from before the SafeDisc version.
|
||||
else if (foundProtections.Exists(p => p.StartsWith("Macrovision Security Driver")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("Macrovision Protection File"))
|
||||
@@ -401,6 +577,9 @@ namespace MPF.Frontend.Tools
|
||||
.FindAll(p => p != "SafeDisc 1/Lite")
|
||||
.FindAll(p => p != "SafeDisc 2+")
|
||||
.FindAll(p => p != "SafeDisc 3+ (DVD)");
|
||||
foundProtections = foundProtections.ConvertAll(p => p.StartsWith("Macrovision Security Driver") && p.Split('/').Length > 1
|
||||
? p.Split('/')[1].TrimStart()
|
||||
: p);
|
||||
}
|
||||
|
||||
// Only SafeDisc Lite is found.
|
||||
@@ -429,7 +608,11 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
|
||||
// SecuROM
|
||||
// TODO: Figure this one out
|
||||
if (foundProtections.Exists(p => p.StartsWith("SecuROM Release Control")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("SecuROM Release Control"));
|
||||
foundProtections.Add("SecuROM Release Control");
|
||||
}
|
||||
|
||||
// SolidShield
|
||||
// TODO: Figure this one out
|
||||
@@ -461,6 +644,12 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
}
|
||||
|
||||
if (foundProtections.Exists(p => p.StartsWith("StarForce Keyless")))
|
||||
{
|
||||
foundProtections = foundProtections.FindAll(p => !p.StartsWith("StarForce Keyless"));
|
||||
foundProtections.Add("StarForce Keyless");
|
||||
}
|
||||
|
||||
// Sysiphus
|
||||
if (foundProtections.Exists(p => p == "Sysiphus")
|
||||
&& foundProtections.Exists(p => p.StartsWith("Sysiphus") && p.Length > "Sysiphus".Length))
|
||||
@@ -482,5 +671,31 @@ namespace MPF.Frontend.Tools
|
||||
foundProtections.Sort();
|
||||
return string.Join(", ", [.. foundProtections]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merge two dictionaries together based on keys
|
||||
/// </summary>
|
||||
/// <param name="original">Source dictionary to add to</param>
|
||||
/// <param name="add">Second dictionary to add from</param>
|
||||
/// TODO: Remove from here when IO is updated
|
||||
private static void MergeDictionaries(Dictionary<string, List<string>> original, Dictionary<string, List<string>> add)
|
||||
{
|
||||
// Ignore if there are no values to append
|
||||
if (add.Count == 0)
|
||||
return;
|
||||
|
||||
// Loop through and add from the new dictionary
|
||||
foreach (var kvp in add)
|
||||
{
|
||||
// Ignore empty values
|
||||
if (kvp.Value.Count == 0)
|
||||
continue;
|
||||
|
||||
if (!original.ContainsKey(kvp.Key))
|
||||
original[kvp.Key] = [];
|
||||
|
||||
original[kvp.Key].AddRange(kvp.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using BinaryObjectScanner;
|
||||
using MPF.Processors;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Data.Sections;
|
||||
using SabreTools.RedumpLib.Web;
|
||||
|
||||
namespace MPF.Frontend.Tools
|
||||
@@ -51,23 +52,34 @@ namespace MPF.Frontend.Tools
|
||||
IProgress<ResultEventArgs>? resultProgress = null,
|
||||
IProgress<ProtectionProgress>? protectionProgress = null)
|
||||
{
|
||||
// Ensure the current disc combination should exist
|
||||
if (!system.MediaTypes().Contains(mediaType))
|
||||
return null;
|
||||
|
||||
// Split the output path for easier use
|
||||
var outputDirectory = Path.GetDirectoryName(outputPath);
|
||||
string outputFilename = Path.GetFileName(outputPath);
|
||||
|
||||
// If a standard log zip was provided, replace the suffix with ".tmp" for easier processing
|
||||
if (outputFilename.EndsWith("_logs.zip", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
int zipSuffixIndex = outputFilename.LastIndexOf("_logs.zip", StringComparison.OrdinalIgnoreCase);
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
outputFilename = outputFilename[..zipSuffixIndex] + ".tmp";
|
||||
#else
|
||||
outputFilename = outputFilename.Substring(0, zipSuffixIndex) + ".tmp";
|
||||
#endif
|
||||
}
|
||||
|
||||
// Check that all of the relevant files are there
|
||||
List<string> missingFiles = processor.FoundAllFiles(outputDirectory, outputFilename);
|
||||
List<string> missingFiles = processor.FoundAllFiles(mediaType, outputDirectory, outputFilename);
|
||||
if (missingFiles.Count > 0)
|
||||
{
|
||||
resultProgress?.Report(ResultEventArgs.Failure($"There were files missing from the output:\n{string.Join("\n", [.. missingFiles])}"));
|
||||
resultProgress?.Report(ResultEventArgs.Failure($"This may indicate an issue with the hardware or media, including unsupported devices.\nPlease see dumping program documentation for more details."));
|
||||
resultProgress?.Report(ResultEventArgs.Failure($"There were files missing from the output:\n{string.Join("\n", [.. missingFiles])}\nThis may indicate an issue with the hardware or media, including unsupported devices.\nPlease see dumping program documentation for more details."));
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract files from existing log archive, if it exists
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
processor.ExtractFromLogs(mediaType, outputDirectory, outputFilename);
|
||||
#endif
|
||||
|
||||
// Assemble a base path
|
||||
string basePath = Path.GetFileNameWithoutExtension(outputFilename);
|
||||
if (!string.IsNullOrEmpty(outputDirectory))
|
||||
@@ -77,25 +89,28 @@ namespace MPF.Frontend.Tools
|
||||
SubmissionInfo info = CreateDefaultSubmissionInfo(processor, system, mediaType, options.AddPlaceholders);
|
||||
|
||||
// Get specific tool output handling
|
||||
processor?.GenerateSubmissionInfo(info, basePath, options.EnableRedumpCompatibility);
|
||||
processor.GenerateSubmissionInfo(info, mediaType, basePath, options.EnableRedumpCompatibility);
|
||||
if (options.IncludeArtifacts)
|
||||
info.Artifacts = processor?.GenerateArtifacts(outputDirectory, outputFilename);
|
||||
|
||||
// Add a placeholder for the logs link
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.LogsLink] = "[Please provide a link to your logs here]";
|
||||
info.Artifacts = processor.GenerateArtifacts(mediaType, outputDirectory, outputFilename);
|
||||
|
||||
// Get a list of matching IDs for each line in the DAT
|
||||
if (!string.IsNullOrEmpty(info.TracksAndWriteOffsets!.ClrMameProData))
|
||||
_ = await FillFromRedump(options, info, resultProgress);
|
||||
if (!string.IsNullOrEmpty(info.TracksAndWriteOffsets.ClrMameProData))
|
||||
{
|
||||
bool filledInfo = await FillFromRedump(options, info, resultProgress);
|
||||
|
||||
// Add a placeholder for the logs link if not a verification
|
||||
if (!filledInfo)
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.LogsLink] = "[Please provide a link to your logs here]";
|
||||
}
|
||||
|
||||
// If we have both ClrMamePro and Size and Checksums data, remove the ClrMamePro
|
||||
if (!string.IsNullOrEmpty(info.SizeAndChecksums?.CRC32))
|
||||
if (!string.IsNullOrEmpty(info.SizeAndChecksums.CRC32))
|
||||
info.TracksAndWriteOffsets.ClrMameProData = null;
|
||||
|
||||
// Add the volume label to comments, if possible or necessary
|
||||
string? volLabels = FormatVolumeLabels(drive?.VolumeLabel, processor?.VolumeLabels);
|
||||
if (volLabels != null)
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.VolumeLabel] = volLabels;
|
||||
string? volLabels = FormatVolumeLabels(drive?.VolumeLabel, processor.VolumeLabels);
|
||||
if (volLabels is not null)
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.VolumeLabel] = volLabels;
|
||||
|
||||
// Extract info based generically on MediaType
|
||||
ProcessMediaType(info, mediaType, options.AddPlaceholders);
|
||||
@@ -104,9 +119,9 @@ namespace MPF.Frontend.Tools
|
||||
ProcessSystem(info, system, drive, options.AddPlaceholders, processor is DiscImageCreator, basePath);
|
||||
|
||||
// Run anti-modchip check, if necessary
|
||||
if (drive != null && system.SupportsAntiModchipScans() && info.CopyProtection!.AntiModchip == YesNo.NULL)
|
||||
if (drive is not null && system.SupportsAntiModchipScans() && info.CopyProtection.AntiModchip == YesNo.NULL)
|
||||
{
|
||||
resultProgress?.Report(ResultEventArgs.Success("Checking for anti-modchip strings... this might take a while!"));
|
||||
resultProgress?.Report(ResultEventArgs.Neutral("Checking for anti-modchip strings... this might take a while!"));
|
||||
info.CopyProtection.AntiModchip = await ProtectionTool.GetPlayStationAntiModchipDetected(drive?.Name) ? YesNo.Yes : YesNo.No;
|
||||
resultProgress?.Report(ResultEventArgs.Success("Anti-modchip string scan complete!"));
|
||||
}
|
||||
@@ -114,17 +129,23 @@ namespace MPF.Frontend.Tools
|
||||
// Run copy protection, if possible or necessary
|
||||
if (system.SupportsCopyProtectionScans())
|
||||
{
|
||||
resultProgress?.Report(ResultEventArgs.Success("Running copy protection scan... this might take a while!"));
|
||||
resultProgress?.Report(ResultEventArgs.Neutral("Running copy protection scan... this might take a while!"));
|
||||
|
||||
ProtectionDictionary? protections = null;
|
||||
try
|
||||
{
|
||||
if (options.ScanForProtection && drive?.Name != null)
|
||||
protections = await ProtectionTool.RunProtectionScanOnPath(drive.Name, options, protectionProgress);
|
||||
Dictionary<string, List<string>>? protections = null;
|
||||
if (options.ScanForProtection)
|
||||
{
|
||||
// Explicitly note missing/invalid device paths
|
||||
if (drive?.Name is null)
|
||||
resultProgress?.Report(ResultEventArgs.Success("No mounted device path found, protection outputs may be incomplete!"));
|
||||
|
||||
var protectionString = ProtectionTool.FormatProtections(protections);
|
||||
protections = await ProtectionTool.RunCombinedProtectionScans(basePath, drive, options, protectionProgress);
|
||||
}
|
||||
|
||||
info.CopyProtection!.Protection += protectionString;
|
||||
var protectionString = ProtectionTool.FormatProtections(protections, drive);
|
||||
|
||||
info.CopyProtection.Protection += protectionString;
|
||||
info.CopyProtection.FullProtections = ReformatProtectionDictionary(protections);
|
||||
resultProgress?.Report(ResultEventArgs.Success("Copy protection scan complete!"));
|
||||
}
|
||||
@@ -135,8 +156,8 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
|
||||
// Set fields that may have automatic filling otherwise
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Games;
|
||||
info.VersionAndEditions!.Version ??= options.AddPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Games;
|
||||
info.VersionAndEditions.Version ??= options.AddPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
|
||||
// Comments and contents have odd handling
|
||||
if (string.IsNullOrEmpty(info.CommonDiscInfo.Comments))
|
||||
@@ -156,7 +177,7 @@ namespace MPF.Frontend.Tools
|
||||
/// <param name="options">Options object representing user-defined options</param>
|
||||
/// <param name="info">Existing SubmissionInfo object to fill</param>
|
||||
/// <param name="resultProgress">Optional result progress callback</param>
|
||||
public async static Task<bool> FillFromRedump(Options options,
|
||||
public static async Task<bool> FillFromRedump(Options options,
|
||||
SubmissionInfo info,
|
||||
IProgress<ResultEventArgs>? resultProgress = null)
|
||||
{
|
||||
@@ -165,16 +186,15 @@ namespace MPF.Frontend.Tools
|
||||
return false;
|
||||
|
||||
// Set the current dumper based on username
|
||||
info.DumpersAndStatus ??= new DumpersAndStatusSection();
|
||||
info.DumpersAndStatus.Dumpers = [options.RedumpUsername ?? "Anonymous User"];
|
||||
info.PartiallyMatchedIDs = [];
|
||||
|
||||
// Login to Redump, if possible
|
||||
var wc = new RedumpClient();
|
||||
if (options.RedumpUsername != null && options.RedumpPassword != null)
|
||||
if (!string.IsNullOrEmpty(options.RedumpUsername) && !string.IsNullOrEmpty(options.RedumpPassword))
|
||||
{
|
||||
bool? loggedIn = await wc.Login(options.RedumpUsername, options.RedumpPassword);
|
||||
if (loggedIn == null)
|
||||
bool? loggedIn = await wc.Login(options.RedumpUsername!, options.RedumpPassword!);
|
||||
if (loggedIn is null)
|
||||
{
|
||||
resultProgress?.Report(ResultEventArgs.Failure("There was an unknown error connecting to Redump, skipping..."));
|
||||
return false;
|
||||
@@ -190,8 +210,8 @@ namespace MPF.Frontend.Tools
|
||||
List<int[]> foundIdSets = [];
|
||||
|
||||
// Loop through all of the hashdata to find matching IDs
|
||||
resultProgress?.Report(ResultEventArgs.Success("Finding disc matches on Redump..."));
|
||||
var splitData = info.TracksAndWriteOffsets?.ClrMameProData?.TrimEnd('\n')?.Split('\n');
|
||||
resultProgress?.Report(ResultEventArgs.Neutral("Finding disc matches on Redump..."));
|
||||
var splitData = info.TracksAndWriteOffsets.ClrMameProData?.TrimEnd('\n')?.Split('\n');
|
||||
int trackCount = splitData?.Length ?? 0;
|
||||
foreach (string hashData in splitData ?? [])
|
||||
{
|
||||
@@ -199,7 +219,7 @@ namespace MPF.Frontend.Tools
|
||||
if (string.IsNullOrEmpty(hashData))
|
||||
{
|
||||
trackCount--;
|
||||
resultProgress?.Report(ResultEventArgs.Success("Blank line found, skipping!"));
|
||||
resultProgress?.Report(ResultEventArgs.Neutral("Blank line found, skipping!"));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -234,7 +254,7 @@ namespace MPF.Frontend.Tools
|
||||
|| hashData.Contains("(Track AA.5).bin"))
|
||||
{
|
||||
trackCount--;
|
||||
resultProgress?.Report(ResultEventArgs.Success("Extra track found, skipping!"));
|
||||
resultProgress?.Report(ResultEventArgs.Neutral("Extra track found, skipping!"));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -246,9 +266,9 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
|
||||
var foundIds = await Validator.ValidateSingleTrack(wc, info, sha1);
|
||||
if (foundIds != null && foundIds.Count == 1)
|
||||
if (foundIds is not null && foundIds.Count == 1)
|
||||
resultProgress?.Report(ResultEventArgs.Success($"Single match found for {sha1}"));
|
||||
else if (foundIds != null && foundIds.Count != 1)
|
||||
else if (foundIds is not null && foundIds.Count != 1)
|
||||
resultProgress?.Report(ResultEventArgs.Success($"Multiple matches found for {sha1}"));
|
||||
else
|
||||
resultProgress?.Report(ResultEventArgs.Failure($"No matches found for {sha1}"));
|
||||
@@ -257,7 +277,7 @@ namespace MPF.Frontend.Tools
|
||||
foundIdSets.Add(foundIds?.ToArray() ?? []);
|
||||
|
||||
// Ensure that all tracks are found
|
||||
allFound &= (foundIds != null && foundIds.Count >= 1);
|
||||
allFound &= foundIds is not null && foundIds.Count >= 1;
|
||||
}
|
||||
|
||||
// If all tracks were found, check if there are any fully-matched IDs
|
||||
@@ -268,7 +288,7 @@ namespace MPF.Frontend.Tools
|
||||
foreach (var set in foundIdSets)
|
||||
{
|
||||
// First track is always all IDs
|
||||
if (fullyMatchedIdsSet == null)
|
||||
if (fullyMatchedIdsSet is null)
|
||||
{
|
||||
fullyMatchedIdsSet = [.. set];
|
||||
continue;
|
||||
@@ -286,25 +306,25 @@ namespace MPF.Frontend.Tools
|
||||
{
|
||||
string sha1 = info.CommonDiscInfo.CommentsSpecialFields[SiteCode.UniversalHash];
|
||||
var foundIds = await Validator.ValidateUniversalHash(wc, info);
|
||||
if (foundIds != null && foundIds.Count == 1)
|
||||
if (foundIds is not null && foundIds.Count == 1)
|
||||
resultProgress?.Report(ResultEventArgs.Success($"Single match found for universal hash {sha1}"));
|
||||
else if (foundIds != null && foundIds.Count != 1)
|
||||
else if (foundIds is not null && foundIds.Count != 1)
|
||||
resultProgress?.Report(ResultEventArgs.Success($"Multiple matches found for universal hash {sha1}"));
|
||||
else
|
||||
resultProgress?.Report(ResultEventArgs.Failure($"No matches found for universal hash {sha1}"));
|
||||
|
||||
// Ensure that the hash is found
|
||||
allFound = (foundIds != null && foundIds.Count == 1);
|
||||
allFound = foundIds is not null && foundIds.Count == 1;
|
||||
|
||||
// If we found a match, then the disc is a match
|
||||
if (foundIds != null && foundIds.Count == 1)
|
||||
if (foundIds is not null && foundIds.Count == 1)
|
||||
fullyMatchedIdsSet = [.. foundIds];
|
||||
else
|
||||
fullyMatchedIdsSet = [];
|
||||
}
|
||||
|
||||
// Get a list version of the fully matched IDs
|
||||
List<int> fullyMatchedIdsList = fullyMatchedIdsSet != null ? [.. fullyMatchedIdsSet] : [];
|
||||
List<int> fullyMatchedIdsList = fullyMatchedIdsSet is not null ? [.. fullyMatchedIdsSet] : [];
|
||||
|
||||
// Make sure we only have unique IDs
|
||||
var partiallyMatchedIds = new HashSet<int>();
|
||||
@@ -312,12 +332,12 @@ namespace MPF.Frontend.Tools
|
||||
info.PartiallyMatchedIDs = [.. partiallyMatchedIds];
|
||||
info.PartiallyMatchedIDs.Sort();
|
||||
|
||||
resultProgress?.Report(ResultEventArgs.Success("Match finding complete! " + (fullyMatchedIdsList != null && fullyMatchedIdsList.Count > 0
|
||||
resultProgress?.Report(ResultEventArgs.Success("Match finding complete! " + (fullyMatchedIdsList is not null && fullyMatchedIdsList.Count > 0
|
||||
? "Fully Matched IDs: " + string.Join(",", [.. fullyMatchedIdsList.ConvertAll(i => i.ToString())])
|
||||
: "No matches found")));
|
||||
|
||||
// Exit early if one failed or there are no matched IDs
|
||||
if (!allFound || fullyMatchedIdsList == null || fullyMatchedIdsList.Count == 0)
|
||||
if (!allFound || fullyMatchedIdsList is null || fullyMatchedIdsList.Count == 0)
|
||||
return false;
|
||||
|
||||
// Find the first matched ID where the track count matches, we can grab a bunch of info from it
|
||||
@@ -329,7 +349,7 @@ namespace MPF.Frontend.Tools
|
||||
continue;
|
||||
|
||||
// Fill in the fields from the existing ID
|
||||
resultProgress?.Report(ResultEventArgs.Success($"Filling fields from existing ID {fullyMatchedIdsList[i]}..."));
|
||||
resultProgress?.Report(ResultEventArgs.Neutral($"Filling fields from existing ID {fullyMatchedIdsList[i]}..."));
|
||||
_ = await Builder.FillFromId(wc, info, fullyMatchedIdsList[i], options.PullAllInformation);
|
||||
resultProgress?.Report(ResultEventArgs.Success("Information filling complete!"));
|
||||
|
||||
@@ -388,8 +408,6 @@ namespace MPF.Frontend.Tools
|
||||
},
|
||||
};
|
||||
|
||||
// Ensure that required sections exist
|
||||
info = Builder.EnsureAllSections(info);
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -403,9 +421,10 @@ namespace MPF.Frontend.Tools
|
||||
// Map to the internal program
|
||||
InternalProgram? internalProgram = processor switch
|
||||
{
|
||||
Processors.Aaru => InternalProgram.Aaru,
|
||||
Aaru => InternalProgram.Aaru,
|
||||
CleanRip => InternalProgram.CleanRip,
|
||||
DiscImageCreator => InternalProgram.DiscImageCreator,
|
||||
// Dreamdump => InternalProgram.Dreamdump,
|
||||
PS3CFW => InternalProgram.PS3CFW,
|
||||
Redumper => InternalProgram.Redumper,
|
||||
UmdImageCreator => InternalProgram.UmdImageCreator,
|
||||
@@ -425,7 +444,7 @@ namespace MPF.Frontend.Tools
|
||||
private static string? SimplifyVolumeLabel(string? label)
|
||||
{
|
||||
// Ignore empty labels
|
||||
if (label == null || label.Length == 0)
|
||||
if (label is null || label.Length == 0)
|
||||
return null;
|
||||
|
||||
// Take only ASCII alphanumeric characters
|
||||
@@ -442,7 +461,7 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Ignore non-ASCII labels
|
||||
string? simpleLabel = labelBuilder.ToString();
|
||||
if (simpleLabel == null || simpleLabel.Length == 0)
|
||||
if (simpleLabel is null || simpleLabel.Length == 0)
|
||||
return null;
|
||||
|
||||
return simpleLabel;
|
||||
@@ -456,18 +475,23 @@ namespace MPF.Frontend.Tools
|
||||
private static string? FormatVolumeLabels(string? driveLabel, Dictionary<string, List<string>>? labels)
|
||||
{
|
||||
// Treat empty label as null
|
||||
if (driveLabel != null && driveLabel.Length == 0)
|
||||
if (driveLabel is not null && driveLabel.Length == 0)
|
||||
driveLabel = null;
|
||||
|
||||
// Treat "path" labels as null -- Indicates a mounted path
|
||||
// This can over-match if a label contains a directory separator somehow
|
||||
if (driveLabel is not null && (driveLabel.Contains("/") || driveLabel.Contains("\\")))
|
||||
driveLabel = null;
|
||||
|
||||
// Must have at least one label to format
|
||||
if (driveLabel == null && (labels == null || labels.Count == 0))
|
||||
if (driveLabel is null && (labels is null || labels.Count == 0))
|
||||
return null;
|
||||
|
||||
// If no labels given, use drive label
|
||||
if (labels == null || labels.Count == 0)
|
||||
if (labels is null || labels.Count == 0)
|
||||
{
|
||||
// Ignore common volume labels
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(driveLabel) != null)
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(driveLabel) is not null)
|
||||
return null;
|
||||
|
||||
return driveLabel;
|
||||
@@ -476,7 +500,7 @@ namespace MPF.Frontend.Tools
|
||||
// Get the default label to compare against
|
||||
// TODO: Full pairwise comparison of all labels, not just comparing against drive/UDF label.
|
||||
string? defaultLabel = null;
|
||||
if (driveLabel != null && driveLabel.Length != 0)
|
||||
if (driveLabel is not null && driveLabel.Length != 0)
|
||||
{
|
||||
defaultLabel = SimplifyVolumeLabel(driveLabel);
|
||||
}
|
||||
@@ -491,7 +515,7 @@ namespace MPF.Frontend.Tools
|
||||
#endif
|
||||
|
||||
// Remove duplicate/useless volume labels
|
||||
if (defaultLabel != null && defaultLabel.Length != 0)
|
||||
if (defaultLabel is not null && defaultLabel.Length != 0)
|
||||
{
|
||||
List<string> keys = [.. labels.Keys];
|
||||
foreach (var label in keys)
|
||||
@@ -505,7 +529,7 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Get upper-case ASCII variant of the label
|
||||
string? tempLabel = SimplifyVolumeLabel(label);
|
||||
if (tempLabel == null)
|
||||
if (tempLabel is null)
|
||||
continue;
|
||||
|
||||
// Remove duplicate volume labels
|
||||
@@ -515,10 +539,10 @@ namespace MPF.Frontend.Tools
|
||||
}
|
||||
|
||||
// If no labels are left, use drive label
|
||||
if (labels == null || labels.Count == 0)
|
||||
if (labels is null || labels.Count == 0)
|
||||
{
|
||||
// Ignore common volume labels
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(driveLabel) != null)
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(driveLabel) is not null)
|
||||
return null;
|
||||
|
||||
return driveLabel;
|
||||
@@ -531,10 +555,10 @@ namespace MPF.Frontend.Tools
|
||||
#else
|
||||
string firstLabel = labels.First().Key;
|
||||
#endif
|
||||
if (labels.Count == 1 && (firstLabel == driveLabel || driveLabel == null))
|
||||
if (labels.Count == 1 && (firstLabel == driveLabel || driveLabel is null))
|
||||
{
|
||||
// Ignore common volume labels
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(firstLabel) != null)
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(firstLabel) is not null)
|
||||
return null;
|
||||
|
||||
return firstLabel;
|
||||
@@ -544,14 +568,14 @@ namespace MPF.Frontend.Tools
|
||||
List<string> volLabels = [];
|
||||
|
||||
// Begin formatted output with the label from Windows, if it is unique and not a common volume label
|
||||
if (driveLabel != null && !labels.TryGetValue(driveLabel, out List<string>? value) && FrontendTool.GetRedumpSystemFromVolumeLabel(driveLabel) == null)
|
||||
if (driveLabel is not null && !labels.TryGetValue(driveLabel, out List<string>? value) && FrontendTool.GetRedumpSystemFromVolumeLabel(driveLabel) is null)
|
||||
volLabels.Add(driveLabel);
|
||||
|
||||
// Add remaining labels with their corresponding filesystems
|
||||
foreach (var kvp in labels)
|
||||
{
|
||||
// Ignore common volume labels
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(kvp.Key) == null)
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(kvp.Key) is null)
|
||||
volLabels.Add($"{kvp.Key} ({string.Join(", ", [.. kvp.Value])})");
|
||||
}
|
||||
|
||||
@@ -570,11 +594,12 @@ namespace MPF.Frontend.Tools
|
||||
/// </summary>
|
||||
private static bool ProcessMediaType(SubmissionInfo info, MediaType? mediaType, bool addPlaceholders)
|
||||
{
|
||||
#pragma warning disable IDE0010
|
||||
switch (mediaType)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.GDROM:
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -587,9 +612,9 @@ namespace MPF.Frontend.Tools
|
||||
case MediaType.BluRay:
|
||||
|
||||
// If we have a single-layer disc
|
||||
if (info.SizeAndChecksums!.Layerbreak == default)
|
||||
if (info.SizeAndChecksums.Layerbreak == default)
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -597,9 +622,9 @@ namespace MPF.Frontend.Tools
|
||||
info.CommonDiscInfo.Layer0AdditionalMould = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
}
|
||||
// If we have a dual-layer disc
|
||||
else if (info.SizeAndChecksums!.Layerbreak2 == default)
|
||||
else if (info.SizeAndChecksums.Layerbreak2 == default)
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -611,9 +636,9 @@ namespace MPF.Frontend.Tools
|
||||
info.CommonDiscInfo.Layer1MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
}
|
||||
// If we have a triple-layer disc
|
||||
else if (info.SizeAndChecksums!.Layerbreak3 == default)
|
||||
else if (info.SizeAndChecksums.Layerbreak3 == default)
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -631,7 +656,7 @@ namespace MPF.Frontend.Tools
|
||||
// If we have a quad-layer disc
|
||||
else
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -654,22 +679,22 @@ namespace MPF.Frontend.Tools
|
||||
break;
|
||||
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer1MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0AdditionalMould = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.Extras!.BCA ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.Extras.BCA ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
case MediaType.NintendoWiiUOpticalDisc:
|
||||
|
||||
// If we have a single-layer disc
|
||||
if (info.SizeAndChecksums!.Layerbreak == default)
|
||||
if (info.SizeAndChecksums.Layerbreak == default)
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -679,7 +704,7 @@ namespace MPF.Frontend.Tools
|
||||
// If we have a dual-layer disc
|
||||
else
|
||||
{
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -691,14 +716,14 @@ namespace MPF.Frontend.Tools
|
||||
info.CommonDiscInfo.Layer1MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
}
|
||||
|
||||
info.Extras!.DiscKey = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.Extras.DiscKey = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.Extras.BCA ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
|
||||
break;
|
||||
|
||||
case MediaType.UMD:
|
||||
// Both single- and dual-layer discs have two "layers" for the ring
|
||||
info.CommonDiscInfo!.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringRing = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer0MouldSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
@@ -707,12 +732,13 @@ namespace MPF.Frontend.Tools
|
||||
info.CommonDiscInfo.Layer1MasteringSID = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Layer1ToolstampMasteringCode = addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
|
||||
info.SizeAndChecksums!.CRC32 ??= (addPlaceholders ? RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
|
||||
info.SizeAndChecksums.CRC32 ??= (addPlaceholders ? RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
|
||||
info.SizeAndChecksums.MD5 ??= (addPlaceholders ? RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
|
||||
info.SizeAndChecksums.SHA1 ??= (addPlaceholders ? RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
|
||||
info.TracksAndWriteOffsets!.ClrMameProData = null;
|
||||
info.TracksAndWriteOffsets.ClrMameProData = null;
|
||||
break;
|
||||
}
|
||||
#pragma warning restore IDE0010
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -722,89 +748,90 @@ namespace MPF.Frontend.Tools
|
||||
/// </summary>
|
||||
private static bool ProcessSystem(SubmissionInfo info, RedumpSystem? system, Drive? drive, bool addPlaceholders, bool isDiscImageCreator, string basePath)
|
||||
{
|
||||
#pragma warning disable IDE0010
|
||||
// Extract info based specifically on RedumpSystem
|
||||
switch (system)
|
||||
{
|
||||
case RedumpSystem.AcornArchimedes:
|
||||
info.CommonDiscInfo!.Region ??= Region.UnitedKingdom;
|
||||
info.CommonDiscInfo.Region ??= Region.UnitedKingdom;
|
||||
break;
|
||||
|
||||
case RedumpSystem.AudioCD:
|
||||
case RedumpSystem.DVDAudio:
|
||||
case RedumpSystem.EnhancedCD:
|
||||
case RedumpSystem.SuperAudioCD:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Audio;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Audio;
|
||||
break;
|
||||
|
||||
case RedumpSystem.BandaiPlaydiaQuickInteractiveSystem:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= info.CommonDiscInfo.Region ?? Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.BDVideo:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Video;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Video;
|
||||
bool bee = PhysicalTool.GetBusEncryptionEnabled(drive);
|
||||
if (bee && string.IsNullOrEmpty(info.CopyProtection!.Protection))
|
||||
if (bee && string.IsNullOrEmpty(info.CopyProtection.Protection))
|
||||
info.CopyProtection.Protection = "Bus encryption enabled flag set";
|
||||
else if (bee)
|
||||
info.CopyProtection!.Protection += "\nBus encryption enabled flag set";
|
||||
info.CopyProtection.Protection += "\nBus encryption enabled flag set";
|
||||
else
|
||||
info.CopyProtection!.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CopyProtection.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
|
||||
break;
|
||||
|
||||
case RedumpSystem.DVDVideo:
|
||||
case RedumpSystem.HDDVDVideo:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Video;
|
||||
info.CopyProtection!.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Video;
|
||||
info.CopyProtection.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.CommodoreAmigaCD:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.CommodoreAmigaCD32:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= Region.Europe;
|
||||
break;
|
||||
|
||||
case RedumpSystem.CommodoreAmigaCDTV:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= Region.Europe;
|
||||
break;
|
||||
|
||||
case RedumpSystem.FujitsuFMTownsseries:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.FujitsuFMTownsMarty:
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.HasbroVideoNow:
|
||||
case RedumpSystem.HasbroVideoNowColor:
|
||||
case RedumpSystem.HasbroVideoNowJr:
|
||||
case RedumpSystem.VideoCD:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Video;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Video;
|
||||
break;
|
||||
|
||||
case RedumpSystem.HasbroVideoNowXP:
|
||||
case RedumpSystem.PhotoCD:
|
||||
case RedumpSystem.SonyElectronicBook:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Multimedia;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Multimedia;
|
||||
break;
|
||||
|
||||
case RedumpSystem.IncredibleTechnologiesEagle:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamieAmusement:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiFireBeat:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiPython2:
|
||||
@@ -812,89 +839,91 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// TODO: Remove this hack when DIC supports build date output
|
||||
if (isDiscImageCreator)
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", kp2Exe);
|
||||
info.CommonDiscInfo.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", kp2Exe);
|
||||
|
||||
SetCommentFieldIfNotExists(info, SiteCode.InternalSerialName, drive, PhysicalTool.GetPlayStationSerial);
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, kp2Exe, fixTwoDigitYear: true);
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, kp2Exe, fixTwoDigitYear: true);
|
||||
|
||||
if (CommentFieldExists(info, SiteCode.InternalSerialName, out kp2Exe))
|
||||
info.CommonDiscInfo!.Region = ProcessingTool.GetPlayStationRegion(kp2Exe);
|
||||
info.CommonDiscInfo.Region = ProcessingTool.GetPlayStationRegion(kp2Exe);
|
||||
|
||||
SetVersionIfNotExists(info, drive, PhysicalTool.GetPlayStation2Version);
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiSystemGV:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiSystem573:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiTwinkle:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.MattelHyperScan:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.MicrosoftXboxOne:
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.Filename] = PhysicalTool.GetXboxFilenames(drive) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.Filename] = PhysicalTool.GetXboxFilenames(drive) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.TitleID] = PhysicalTool.GetXboxTitleID(drive) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.MicrosoftXboxSeriesXS:
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.Filename] = PhysicalTool.GetXboxFilenames(drive) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.Filename] = PhysicalTool.GetXboxFilenames(drive) ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.TitleID] = PhysicalTool.GetXboxTitleID(drive) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.NamcoSegaNintendoTriforce:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.NavisoftNaviken21:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.NECPC88series:
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.NECPC98series:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.NECPCFXPCFXGA:
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaChihiro:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaDreamcast:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaNaomi:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaNaomi2:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaTitanVideo:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SharpX68000:
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SNKNeoGeoCD:
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation:
|
||||
@@ -902,26 +931,26 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// TODO: Remove this hack when DIC supports build date output
|
||||
if (isDiscImageCreator)
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", ps1Exe, psx: true);
|
||||
info.CommonDiscInfo.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", ps1Exe, psx: true);
|
||||
|
||||
SetCommentFieldIfNotExists(info, SiteCode.InternalSerialName, drive, PhysicalTool.GetPlayStationSerial);
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, ps1Exe, fixTwoDigitYear: true);
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, ps1Exe, fixTwoDigitYear: true);
|
||||
|
||||
if (CommentFieldExists(info, SiteCode.InternalSerialName, out ps1Exe))
|
||||
info.CommonDiscInfo!.Region = ProcessingTool.GetPlayStationRegion(ps1Exe);
|
||||
info.CommonDiscInfo.Region = ProcessingTool.GetPlayStationRegion(ps1Exe);
|
||||
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation2:
|
||||
info.CommonDiscInfo!.LanguageSelection ??= [];
|
||||
info.CommonDiscInfo.LanguageSelection ??= [];
|
||||
string? ps2Exe = PhysicalTool.GetPlayStationExecutableName(drive);
|
||||
|
||||
// TODO: Remove this hack when DIC supports build date output
|
||||
if (isDiscImageCreator)
|
||||
info.CommonDiscInfo!.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", ps2Exe);
|
||||
info.CommonDiscInfo.EXEDateBuildDate = DiscImageCreator.GetPlayStationEXEDate($"{basePath}_volDesc.txt", ps2Exe);
|
||||
|
||||
SetCommentFieldIfNotExists(info, SiteCode.InternalSerialName, drive, PhysicalTool.GetPlayStationSerial);
|
||||
info.CommonDiscInfo!.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, ps2Exe, fixTwoDigitYear: true);
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= PhysicalTool.GetFileDate(drive, ps2Exe, fixTwoDigitYear: true);
|
||||
|
||||
if (CommentFieldExists(info, SiteCode.InternalSerialName, out ps2Exe))
|
||||
info.CommonDiscInfo.Region = ProcessingTool.GetPlayStationRegion(ps2Exe);
|
||||
@@ -930,7 +959,7 @@ namespace MPF.Frontend.Tools
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation3:
|
||||
info.Extras!.DiscKey ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.Extras.DiscKey ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
info.Extras.DiscID ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
|
||||
SetCommentFieldIfNotExists(info, SiteCode.InternalSerialName, drive, PhysicalTool.GetPlayStation3Serial);
|
||||
@@ -951,14 +980,15 @@ namespace MPF.Frontend.Tools
|
||||
break;
|
||||
|
||||
case RedumpSystem.TomyKissSite:
|
||||
info.CommonDiscInfo!.Category ??= DiscCategory.Video;
|
||||
info.CommonDiscInfo!.Region ??= Region.Japan;
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Video;
|
||||
info.CommonDiscInfo.Region ??= Region.Japan;
|
||||
break;
|
||||
|
||||
case RedumpSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem:
|
||||
info.CopyProtection!.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
info.CopyProtection.Protection ??= addPlaceholders ? RequiredIfExistsValue : string.Empty;
|
||||
break;
|
||||
}
|
||||
#pragma warning restore IDE0010
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -981,7 +1011,7 @@ namespace MPF.Frontend.Tools
|
||||
private static bool CommentFieldExists(SubmissionInfo info, SiteCode key, out string? value)
|
||||
{
|
||||
// Ensure the comments fields exist
|
||||
if (info.CommonDiscInfo!.CommentsSpecialFields == null)
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields is null)
|
||||
info.CommonDiscInfo.CommentsSpecialFields = [];
|
||||
|
||||
// Check if the field exists
|
||||
@@ -1005,8 +1035,8 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Set the value
|
||||
string? value = valueFunc(drive);
|
||||
if (value != null)
|
||||
info.CommonDiscInfo!.CommentsSpecialFields![key] = value;
|
||||
if (value is not null)
|
||||
info.CommonDiscInfo.CommentsSpecialFields[key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1015,7 +1045,7 @@ namespace MPF.Frontend.Tools
|
||||
private static bool ContentFieldExists(SubmissionInfo info, SiteCode key, out string? value)
|
||||
{
|
||||
// Ensure the contents fields exist
|
||||
if (info.CommonDiscInfo!.ContentsSpecialFields == null)
|
||||
if (info.CommonDiscInfo.ContentsSpecialFields is null)
|
||||
info.CommonDiscInfo.ContentsSpecialFields = [];
|
||||
|
||||
// Check if the field exists
|
||||
@@ -1039,8 +1069,8 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
// Set the value
|
||||
string? value = valueFunc(drive);
|
||||
if (value != null)
|
||||
info.CommonDiscInfo!.ContentsSpecialFields![key] = value;
|
||||
if (value is not null)
|
||||
info.CommonDiscInfo.ContentsSpecialFields![key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1049,7 +1079,7 @@ namespace MPF.Frontend.Tools
|
||||
private static void SetVersionIfNotExists(SubmissionInfo info, Drive? drive, Func<Drive?, string?> valueFunc)
|
||||
{
|
||||
// If the version already exists, skip
|
||||
if (!string.IsNullOrEmpty(info.VersionAndEditions!.Version))
|
||||
if (!string.IsNullOrEmpty(info.VersionAndEditions.Version))
|
||||
return;
|
||||
|
||||
// Set the version
|
||||
@@ -1061,10 +1091,10 @@ namespace MPF.Frontend.Tools
|
||||
/// </summary>
|
||||
/// <param name="oldDict">ProtectionDictionary to format</param>
|
||||
/// <returns>Reformatted dictionary on success, empty on error</returns>
|
||||
private static Dictionary<string, List<string>?> ReformatProtectionDictionary(ProtectionDictionary? oldDict)
|
||||
private static Dictionary<string, List<string>?> ReformatProtectionDictionary(Dictionary<string, List<string>>? oldDict)
|
||||
{
|
||||
// Null or empty protections return empty
|
||||
if (oldDict == null || oldDict.Count == 0)
|
||||
if (oldDict is null || oldDict.Count == 0)
|
||||
return [];
|
||||
|
||||
// Reformat each set into a List
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user