Compare commits

...

176 Commits

Author SHA1 Message Date
Matt Nadareski
299fafe1f8 Update changelog 2026-02-02 16:24:01 -05:00
Matt Nadareski
8f6305a7c4 Extend logging with a new state (fixes #944) 2026-02-02 16:23:48 -05:00
Matt Nadareski
3f61957715 Log the system being used, in case it came from config 2026-01-30 08:45:13 -05:00
Matt Nadareski
57750295fb Validate a system is provided for CLI applications 2026-01-29 20:36:56 -05:00
Matt Nadareski
286ec864ab Add unused Dreamdump execution context 2026-01-27 16:16:34 -05:00
Matt Nadareski
e4fd644c61 Split path creation in OptionsLoader 2026-01-27 15:07:22 -05:00
Matt Nadareski
7502d7e8df Update RedumpLib to 1.9.1 2026-01-27 14:02:54 -05:00
Matt Nadareski
439fb2717c Add MPRESS to packer filters (fixes #938) 2026-01-27 08:40:17 -05:00
Matt Nadareski
089ab1c4a2 Add editorconfig, fix issues 2026-01-25 18:09:00 -05:00
Deterous
89a50ea424 Update Redumper to build 683 (#933) 2026-01-04 20:13:35 -05:00
Matt Nadareski
740d867d7b Update DIC to 20260101 2026-01-03 21:57:14 -05:00
Matt Nadareski
83fa4852c9 Add default subfolder to CLI outputs 2026-01-01 10:21:19 -05:00
Deterous
ecc00a28c2 Update Redumper to build 681 (Dreamcast support) (#930)
* Update redumper to b678

* Update Redumper to build 681 (Dreamcast support)

* build 682
2025-12-26 21:24:02 -05:00
Matt Nadareski
2d90c849e1 Use default media type if not provided (fixes #925) 2025-12-22 10:10:49 -05:00
Deterous
1d065ffd48 Update Redumper to build 676 (rename asus flags to mediatek) (#927)
* Update Redumper to build 676 (rename asus flags to mediatek)

* Fix ToRedumperDriveType enum extension
2025-12-15 09:56:49 -05:00
Deterous
ca885c3b89 Update Redumper to build 671 (#924)
* Update Redumper to build 669

* Fix tests

* Bump to build 670

* Update to build 671

* Bump changelist

* Fix tests
2025-12-10 20:32:08 -05:00
Matt Nadareski
94fd614673 Check range-specific values in layerbreak 2025-12-02 08:36:57 -05:00
Matt Nadareski
9fc5799999 Check for null or empty layerbreak arrays 2025-12-02 08:30:33 -05:00
Matt Nadareski
61f90a635f Bump version 2025-11-28 09:53:54 -05:00
Matt Nadareski
8cc0ff3829 Reenable Zstd PKZIP outputs 2025-11-27 20:09:43 -05:00
Matt Nadareski
cac6bcc4de Add commented fix for Zstd PKZIP 2025-11-26 20:25:51 -05:00
Matt Nadareski
7ac0089e81 Disable Zstd PKZIP outputs 2025-11-25 19:38:30 -05:00
Matt Nadareski
48576b38be Update Redumper to build 665 2025-11-25 18:14:08 -05:00
Matt Nadareski
82dedf1ceb Add support for .NET 10 2025-11-25 09:14:46 -05:00
Matt Nadareski
395cded5ef Clarify the unmounted device case (fixes #921) 2025-11-24 13:14:24 -05:00
Deterous
a48f9d1c83 New Redumper Drive Pregap Start option (#920)
* Pregap start option

* Fix DriveType names

* Fix options window

* Update changelist
2025-11-24 09:18:28 -05:00
Matt Nadareski
3975003686 Update changelog 2025-11-18 18:42:28 -05:00
HeroponRikiBestest
4beae71511 Remove DPM identifier for StarForce Keyless (#918)
* Redump staff does not deem the DPM identifier useful, so clean it from the submissioninfo output

* Add test for sanitization of StarForce Keyless
2025-11-18 18:41:10 -05:00
Matt Nadareski
f0f41c86c5 Ensure volume label is trimmed if used in filenames 2025-11-14 09:14:14 -05:00
Matt Nadareski
b1b6eb2c9d Clean up informational issues 2025-11-11 15:52:26 -05:00
Matt Nadareski
29754b4c0e Name some type parameters 2025-11-11 12:06:30 -05:00
Matt Nadareski
35cda84308 Update Redumper to build 663 2025-11-10 20:37:41 -05:00
Matt Nadareski
a877397fe6 Path scan after image scan 2025-11-10 19:34:17 -05:00
Matt Nadareski
2f0471d596 Move and rename new protection scan method 2025-11-10 13:52:31 -05:00
Matt Nadareski
2037ded792 Scan multi-track images for protection 2025-11-10 13:37:23 -05:00
Matt Nadareski
5f1a68a5f5 Scan disc image if not multi-track 2025-11-10 13:27:54 -05:00
Matt Nadareski
87746c8677 Update packages 2025-11-10 13:17:10 -05:00
Matt Nadareski
2665c29918 Use dated default output filenames 2025-11-09 20:03:46 -05:00
Matt Nadareski
5637cf5201 Update Redumper to build 660 2025-11-07 22:06:20 -05:00
Matt Nadareski
eb1d000e4f Fix tests 2025-11-07 09:58:28 -05:00
Matt Nadareski
8db467128d Add DVD-Video to list of copy protection scanning systems 2025-11-07 09:52:49 -05:00
Deterous
dc90e2609d Pre-compress all skeletons for multi-track CDs (#915)
* Pre-compress all skeletons for multi-track CDs

* Gate behind file existing

* Full track path

* split

* if base path is root
2025-11-06 07:39:41 -05:00
Deterous
e96bd21f1d Update Redumper to build 658 (#914) 2025-11-05 20:04:20 -05:00
Matt Nadareski
693599b986 Clean up submission info use and log link text 2025-11-03 08:08:51 -05:00
Matt Nadareski
d482fe926c Fix issues with path assembly 2025-10-29 20:11:02 -04:00
Deterous
17b5432352 Fix langs (#913)
* Fix langs

* changelist
2025-10-27 12:24:15 -04:00
Deterous
ca480f27ed Add hidden language (NovaAurora) (#912)
* Add hidden language (NovaAurora)

* add test
2025-10-27 10:04:00 -04:00
Matt Nadareski
4bad66e706 Slight tweak to automatic UI links 2025-10-26 22:01:10 -04:00
Matt Nadareski
abe00fe132 Try to add UI links to rolling release 2025-10-26 21:46:39 -04:00
Deterous
ba73479837 Rolling tag fix (#911)
* Rolling tag fix

* Remove recursive pull
2025-10-25 21:40:40 -04:00
Matt Nadareski
f2a28dd36b Update changelog 2025-10-24 09:24:40 -04:00
Piotr Swat
928e30a5de Updated Polish translation (#910) 2025-10-24 09:01:26 -04:00
Matt Nadareski
007fc2f9b9 Stop using long name for default system setting 2025-10-23 08:39:09 -04:00
Matt Nadareski
d2d23ebbdf Limit visibility of Compatible OS text box 2025-10-22 11:45:10 -04:00
Matt Nadareski
e02ab769ec Update RedumpLib to 1.8.0 2025-10-22 09:16:53 -04:00
Matt Nadareski
3df78def00 Minor Spanish cleanup 2025-10-21 10:59:49 -04:00
Matt Nadareski
7eddfc5fed Possibly fix missing options string 2025-10-21 09:50:54 -04:00
Matt Nadareski
f6f154b6db Free disk space for runners 2025-10-21 09:22:10 -04:00
Matt Nadareski
47cd133437 Change CLI first-run wording 2025-10-21 09:01:33 -04:00
Matt Nadareski
74c9641a54 Simplify first-run CLI experience 2025-10-21 08:58:01 -04:00
Matt Nadareski
fc5929db2a Add per-OS executable names 2025-10-21 08:51:24 -04:00
Matt Nadareski
f53b428075 Separate out default program paths 2025-10-21 08:43:52 -04:00
Matt Nadareski
46dc931b3f Readme updates for accuracy 2025-10-21 08:30:53 -04:00
Deterous
9608cfb700 Be selective on which systems to enable skeleton (#909)
* Be selective on which systems to enable skeleton

* Bring back lost brace

* case

* RedumpSystem
2025-10-19 20:41:15 -04:00
Matt Nadareski
3493238849 Make log archive handling more user-apparent 2025-10-19 13:15:48 -04:00
Matt Nadareski
4c364f519e Regex outputs should not name based on pattern 2025-10-19 12:47:21 -04:00
Matt Nadareski
337a7a181c Fix tests broken by last commit 2025-10-19 12:27:50 -04:00
Matt Nadareski
071e3a0024 Redumper state file is not accessed 2025-10-19 12:21:20 -04:00
Matt Nadareski
ff0c742dee Handle log zip path in information extraction 2025-10-19 11:55:37 -04:00
Matt Nadareski
7aba0d1c9c Make .img not required for DIC outputs 2025-10-19 11:53:51 -04:00
Matt Nadareski
ac6a77d9da Allow placeholder files to be used in Check 2025-10-19 11:45:22 -04:00
Matt Nadareski
6eb976c842 Merge pull request #908 from SabreTools/ui-langs
Support UI Languages
2025-10-19 09:51:41 -04:00
Matt Nadareski
ba39a8b22f Update changelog 2025-10-19 09:46:11 -04:00
Deterous
88a6fa71a9 Fix long translated strings (#907)
* Build branch

* Enable debug media info window by default

* Fix bold options window context menu

* Shorten ukr strings

* More shortened strings

* better short ukr

* revert build changes and debug flag

* fix test login button strings
2025-10-19 09:46:00 -04:00
Matt Nadareski
584b8c0109 Allow files to be zipped but not deleted 2025-10-19 09:25:56 -04:00
Matt Nadareski
c6258b5520 Handle a provided log zip in Check operation 2025-10-18 20:15:47 -04:00
Matt Nadareski
d6dbbbe928 Add list configuration commandline feature (fixes #906) 2025-10-18 18:47:27 -04:00
Matt Nadareski
f22b3c4ac0 Add Ukrainian translation (superg) 2025-10-18 18:10:45 -04:00
Matt Nadareski
fae399f8bc Add console print when Check loads from config 2025-10-18 13:08:32 -04:00
Matt Nadareski
d2ed2f81ae Make Check flags toggle if config used 2025-10-18 12:03:37 -04:00
Deterous
7dbcfce46c Add basic translation for 8 more languages (#902)
* Add langs

* Top menu spacing

* need using

* ToInterfaceLanguage

* fix UI strings

* auto menu width

* cleanup strings

* fix spacing

* better strings

* revert CI change

* more translation work

* test remove System.Windows.Forms

* full namespace for WinForms

* WinForms namespace

* App is in System.Windows

* Fix string bugs

* Better swedish

* Update changelog
2025-10-18 21:12:51 +09:00
Matt Nadareski
ebd0552a2a Add 8 more language menu items 2025-10-17 17:36:12 -04:00
Matt Nadareski
343973263c Add skeleton for 8 more languages 2025-10-17 17:26:56 -04:00
Matt Nadareski
e5220a8224 Update changelog 2025-10-17 13:01:51 -04:00
Deterous
146120c210 Complete translation support (#901)
* Translate options window

* build on branch

* ui-langs-dev

* fix dupe string

* Translate Media Information Window

* Revert CI process
2025-10-17 13:01:31 -04:00
Matt Nadareski
807e4655a6 Update changelog 2025-10-17 09:12:37 -04:00
Matt Nadareski
e32ebec197 Ensure readers and writers dispose 2025-10-17 08:50:50 -04:00
Matt Nadareski
8d8886390d Minor formatting cleanup 2025-10-17 08:10:02 -04:00
Deterous
5a2aa9d325 Continue UI translation work (#900)
* No redundant translation

* semicolon

* rename DefaultUILanguage

* finish rename

* Cleanup

* Fix SetInterfaceLanguage

* Fix LanguageMenuItemClick

* Set resources before window loads

* set lang during init

* Update interface language after setting options

* Check language menuitem when updating options

* Clear checks when loading language from options

* SetInterfaceLanguage clears checks

* obj as MenuItem

* safer unchecking

* type naming

* uncheck menuitem

* var

* don't uncheck within setlanguage

* test

* equals

* top left menu margin

* help menu right margin

* Fix title bar

* Margin on help menu item

* margin on stack panel

* more translations

* Translate message boxes

* fix margin

* only change lang if options was saved

* only update language if it has been updated

* smaller negative margin

* padding

* padding on textblock

* Revert GHA changes
2025-10-17 08:02:09 -04:00
Matt Nadareski
37aa1645dd Add UI by default to launch 2025-10-17 07:50:46 -04:00
Matt Nadareski
052d074e92 Fill in some gaps 2025-10-16 23:02:35 -04:00
Matt Nadareski
8c551dc990 Clean up a bit of element work 2025-10-16 22:35:31 -04:00
Matt Nadareski
b2fcc190fd Clean up nullability 2025-10-16 21:09:42 -04:00
Matt Nadareski
2325844bd4 Slight cleanup to main window language handling 2025-10-16 20:33:43 -04:00
Matt Nadareski
f63517bb52 Move to enum-based model for UI language options 2025-10-16 20:28:37 -04:00
Deterous
99d26f177b Initial UI lang code (#899)
* Test using resources

* Include system namespace in resource xaml

* system namespace name

* rename strings

* Default strings

* Window resources

* add keys

* just one key

* Combo box example

* window resources

* Dropdown in menu bar

* nullable

* non nullable

* string list init

* simple

* English default

* Add menu item for language

* parent is menuitem

* fix

* no null lang

* Only build win-x64, GHA storage limit

* Korean

* test

* Set resource strings at app level

* remove lost endif

* Better UI

* Move langs next to buttons

* update

* fix button

* More translations

* Better menu size

* too many semicolons

* top right menu bar

* Tweaks

* Top bar positioning

* title bar width

* try again

* final

* Back to original publish script

* more windows

* pre-merge test

* Test non-latin underscore

* More strings

* fix

* FindResource is a function

* space

* cast spells

* Log about text

* semicolon

* Good

* cast spells

* using System.Windows in Frontend

* Translate in MainViewModel

* Dynamic GetFormattedVolumeLabel

* Nullability

* Fix

* using for dict

* Translate func in MVM

* Don't translate in init

* Update MVM translations

* closing brace

* Deprecate resource string

* test

* test2

* set current system

* trial field

* field is preview

* default empty string

* default null

* fix build

* empty string

* GIve up on no system selected text

* Fix context menu border

* Revert half fix

* Translate more IRD Window strings

* Loose string

* Detect current locale

* fix

* System.Globalization

* Locale detection for default lang

* break on zh case

* default startup lang

* default lang option

* fix

* fix2

* fix3

* nonnullable

* final fix

* final final fix

* default language option

* use default language on startup

* empty entry

* semicolon
2025-10-16 11:47:36 -04:00
Matt Nadareski
d6b28de586 Reduce chance of empty strings 2025-10-12 22:45:54 -04:00
Deterous
e8d1567d07 Parse XboxOne/SX Title IDs (#897)
* Parse XboxOne/SX Title IDs

* Bump RedumpLib

* Fix build

* Don't use lists because net20
2025-10-12 20:14:50 -04:00
Matt Nadareski
cd8b484ae3 Replace "We" comments 2025-10-11 16:06:53 -04:00
Matt Nadareski
65b9735941 Conditionally require state 2025-10-11 09:41:28 -04:00
Matt Nadareski
22f7e2a0ed Move output file implementations to separate namespace 2025-10-11 09:34:00 -04:00
Matt Nadareski
2c5dc7390a Use WriteToFile extension for zip entries 2025-10-11 09:27:55 -04:00
Deterous
c5e01b9578 Support reparsing of MPF-processed outputs (#896)
* Have a go at extracting files from existing log

* no null output dir

* Extract log from archive if it is zipped during mediatype detection

* imports

* fix variable names

* fix null output dir

* Final fixes

* changelist

* assign null

* fix
2025-10-10 22:03:03 -04:00
Matt Nadareski
882243316c Implement file merging in CleanRip 2025-10-10 11:40:02 -04:00
Matt Nadareski
1b62ed0c03 Add file merge method in CleanRip 2025-10-10 11:37:11 -04:00
Matt Nadareski
edb8c08a39 Move Zstd compression helper to base processor 2025-10-10 10:07:32 -04:00
Matt Nadareski
ad93387aea Add BCA to list of files to select in Check UI 2025-10-10 09:05:54 -04:00
Matt Nadareski
9012ff85a9 Bump version 2025-10-10 08:44:07 -04:00
Matt Nadareski
ccc33bebbd Try to handle Windows-specific compression issue 2025-10-10 08:09:49 -04:00
Matt Nadareski
57b07aee02 Support detecting split Wii for CleanRip 2025-10-09 15:35:38 -04:00
Matt Nadareski
069d676492 Fix test broken by last commit 2025-10-09 15:05:57 -04:00
Matt Nadareski
a26dfb7e7a Enable skeleton output for all CLI runs 2025-10-09 12:06:16 -04:00
Matt Nadareski
a9ea457808 Use block-based reading instead of CopyTo 2025-10-09 10:31:59 -04:00
Matt Nadareski
41bc410452 Pre-compress state files with Zstd 2025-10-09 10:01:24 -04:00
Matt Nadareski
bbfdf462d0 Fix broken file count tests 2025-10-08 12:54:18 -04:00
Matt Nadareski
5a1d51c05f Pre-compress skeleton files with Zstd 2025-10-08 12:48:50 -04:00
Matt Nadareski
16e80f75cf Add preemptive helper for Zstd handling 2025-10-08 12:04:04 -04:00
Matt Nadareski
2a6e066707 Add preemptive new file support 2025-10-08 11:53:19 -04:00
Matt Nadareski
d6102107fb Only allow skeleton creation for CD and DVD
This was a hard decision to limit again, but with the inability to make Zstd the default for log compression, this is not a reasonable thing to enable for most users.
2025-10-08 11:31:12 -04:00
Matt Nadareski
79163dcb35 Fix default value tests 2025-10-08 11:15:16 -04:00
Matt Nadareski
c1aa863c91 Allow skeleton creation for all media types 2025-10-08 11:10:13 -04:00
Matt Nadareski
dbd4b55dda Use ZipWriterOptions instead of generic 2025-10-08 10:59:51 -04:00
Matt Nadareski
1f58521f51 Fix incorrect flagging of a failed check 2025-10-08 10:54:20 -04:00
Matt Nadareski
4da1ab9c29 Guard against unzippable files 2025-10-08 10:35:28 -04:00
Matt Nadareski
5771add8c0 Revert "Use Deflate64 instead of Deflate for compression"
This reverts commit 977a71d9cf.
2025-10-08 10:20:10 -04:00
Matt Nadareski
977a71d9cf Use Deflate64 instead of Deflate for compression 2025-10-08 09:59:41 -04:00
Matt Nadareski
b2d09d04ea Use null or empty instead of just null 2025-10-08 09:49:22 -04:00
Matt Nadareski
78df92e5d3 More gracefully handle "missing" media types 2025-10-08 09:29:34 -04:00
Matt Nadareski
9770b7c917 Add more useful credentials inputs for Check 2025-10-07 20:37:11 -04:00
Matt Nadareski
1ddb287977 Minor cleanup on interactive modes 2025-10-07 20:27:22 -04:00
Matt Nadareski
b9e4bbf744 Finalize wire-through and clean up 2025-10-07 19:43:34 -04:00
Matt Nadareski
08829ed811 Fix minor issues with options loading 2025-10-07 18:27:12 -04:00
Matt Nadareski
bf181e2294 Start wiring through log compression changes 2025-10-07 18:07:46 -04:00
Matt Nadareski
49571c6bfc Use GC.SharpCompress as archive handling library 2025-10-07 17:33:01 -04:00
Matt Nadareski
9a0bc868f8 More consistency in commandline programs 2025-10-07 16:40:30 -04:00
Matt Nadareski
bc2c08690d Update packages 2025-10-07 16:21:02 -04:00
Matt Nadareski
493cb80624 Allow but do not require config for Check 2025-10-07 15:19:50 -04:00
Matt Nadareski
49b8ecf6c3 Fix minor typo in verify inputs check 2025-10-06 18:05:14 -04:00
Matt Nadareski
c9b7ad7819 Exit early on parsing failures 2025-10-06 17:53:15 -04:00
Matt Nadareski
fe76387f6a Remove CommandOptions implementations 2025-10-06 17:49:16 -04:00
Matt Nadareski
0a60fe5a37 Fix strange invocations of extension methods 2025-10-06 16:37:28 -04:00
Matt Nadareski
baffdb8b29 Remove duplicate input declarations 2025-10-06 16:34:19 -04:00
Matt Nadareski
4a3c585a8d Assign inputs for interactive modes 2025-10-06 16:25:41 -04:00
Matt Nadareski
1ee7ea1948 Create and use base feature in CLI 2025-10-06 16:13:51 -04:00
Matt Nadareski
ee08bfe0fc Create and use base feature in Check 2025-10-06 16:06:23 -04:00
Matt Nadareski
896caec9cd Create and use main features for CLI and Check 2025-10-06 15:54:14 -04:00
Matt Nadareski
68932ab473 Reduce unnecessary shared code 2025-10-06 15:25:11 -04:00
Matt Nadareski
d105d04146 Add placeholder command set creation 2025-10-06 11:01:25 -04:00
Matt Nadareski
7023c78d40 Minor cleanup around last added 2025-10-06 10:34:11 -04:00
Matt Nadareski
81156a3c63 Create interactive mode features 2025-10-06 10:32:16 -04:00
Matt Nadareski
7b2b06a36f Use CommandLine library for CLI executables 2025-10-06 10:11:44 -04:00
Matt Nadareski
3f974ab336 Update packages 2025-10-05 17:41:38 -04:00
Matt Nadareski
b238616685 Rename log zip on collision 2025-10-04 20:49:56 -04:00
Matt Nadareski
2984459823 Tweaks to how failure cases are reported 2025-10-04 18:57:25 -04:00
Matt Nadareski
ce979b3c3f Add failure if media type could not be determined 2025-10-02 22:06:22 -04:00
Matt Nadareski
cb8e1fd34b Bump version 2025-09-30 12:02:06 -04:00
Matt Nadareski
cc148735f8 Require exact versions for build 2025-09-30 11:18:59 -04:00
Matt Nadareski
8238d14f7b Fix missed package update 2025-09-30 10:55:57 -04:00
Matt Nadareski
a56676501e Fix starting index for CLI 2025-09-29 22:43:33 -04:00
Matt Nadareski
79716ea0b5 Bump version 2025-09-29 17:54:03 -04:00
Matt Nadareski
43477a133f Update BinaryObjectScanner to 3.4.3 2025-09-29 14:30:52 -04:00
Matt Nadareski
8889beef1d Reduction in media type use for dumping 2025-09-29 11:25:57 -04:00
Matt Nadareski
ac4be751b3 Make media type a named parameter for CLI 2025-09-29 10:56:56 -04:00
Matt Nadareski
69f855fc93 Fix tests 2025-09-29 10:45:53 -04:00
Matt Nadareski
cf01095623 Skip trying to set speeds if no drives 2025-09-29 10:43:12 -04:00
Matt Nadareski
3236223e3f Default to CD speed range 2025-09-29 10:40:59 -04:00
Matt Nadareski
36450cd22b Minor tweaks to frontend code 2025-09-29 10:25:24 -04:00
Deterous
6a9b6748d2 Remove SkipMediaTypeDetection option, cleanup options window (#895)
* Remove SkipMediaTypeDetection option, cleanup options window

* Shrink detection section in options

* always try to guess media type
2025-09-26 10:56:25 -04:00
Matt Nadareski
3bf83378a2 Fix logic from around Macrovision security driver filtering (fixes #811) 2025-09-25 11:38:03 -04:00
Matt Nadareski
bc938fd58c Return full result from dump checks 2025-09-25 10:54:29 -04:00
Matt Nadareski
f50a110acd Update media type visibility on system change 2025-09-25 09:26:11 -04:00
Matt Nadareski
fcda2a6e3b Change label with media type visibility 2025-09-25 09:07:41 -04:00
Matt Nadareski
d33526b27e Set media type visibility when options changed 2025-09-25 08:56:06 -04:00
Matt Nadareski
0b0427e9c1 Limit media type visibility further 2025-09-25 08:54:33 -04:00
Matt Nadareski
c34b92bad8 Default media type box to hidden to avoid visual issues 2025-09-25 08:49:04 -04:00
Matt Nadareski
89145df0fa Experiment with only showing media type box for DIC 2025-09-25 08:32:06 -04:00
171 changed files with 10387 additions and 3573 deletions

View File

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

View File

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

View File

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

View File

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

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

View File

@@ -1,3 +1,179 @@
### 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

View 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();
}
}
}

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

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

View File

@@ -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.4.0</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.7.4" />
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
</ItemGroup>
</Project>

View File

@@ -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,503 +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 in config.json 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 in config.json for DIC, exiting...");
return;
}
break;
case InternalProgram.Redumper:
if (!File.Exists(options.RedumperPath))
{
DisplayHelp("A path needs to be supplied in config.json 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 = FrontendTool.NormalizeOutputPaths(opts.FilePath, getFullPath: true);
// 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,
options.InternalProgram);
env.SetExecutionContext(mediaType, null);
env.SetProcessor();
// Process the parameters
string? paramStr = opts.CustomParams ?? env.GetFullParameters(mediaType, speed);
if (string.IsNullOrEmpty(paramStr))
{
DisplayHelp("No valid environment could be created, exiting...");
return;
}
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)
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,
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);
}
/// <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, -?, --help Show this help text");
Console.WriteLine("--version Print the program version");
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 configured dumping program name");
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("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();
"Mounted filesystem path is only recommended on OSes that require block",
"device dumping, usually Linux and macOS.",
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();
var commandSet = new CommandSet(header, footer);
Console.WriteLine("Mounted filesystem path is only recommended on OSes that require block");
Console.WriteLine("device dumping, usually Linux and macOS.");
Console.WriteLine();
}
// 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());
/// <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
{
FilePath = Path.Combine(options.DefaultOutputPath ?? "ISO", "track.bin"),
};
mediaType = MediaType.NONE;
system = options.DefaultSystem;
// 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);
// Create state values
string? result = string.Empty;
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;
}
}
}

View 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();
}
}
}

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

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

View File

@@ -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.4.0</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.7.4" />
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
</ItemGroup>
</Project>

View File

@@ -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,547 +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;
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 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 knownSystem, out var error);
if (!success)
{
DisplayHelp(error);
return;
}
if (!interactive.Execute())
{
BaseFeature.DisplayHelp();
return;
}
// Loop through and process options
startIndex = 1;
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,
internalProgram: null);
env.SetProcessor();
// 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 <system> [options] </path/to/output.cue/iso> ...");
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("-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 RedumpSystem? system)
{
// Create return values
var opts = new CommandOptions();
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 system (Currently '{system}')");
Console.WriteLine($"2) Set dumping program (Currently '{options.InternalProgram}')");
Console.WriteLine($"3) Set seed path (Currently '{opts.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 '{opts.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) 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":
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;
}
system:
Console.WriteLine();
Console.WriteLine("Input the system and press Enter:");
Console.Write("> ");
result = Console.ReadLine();
system = Extensions.ToRedumpSystem(result);
goto root;
if (!mainFeature.VerifyInputs())
{
Console.Error.WriteLine("At least one input is required");
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;
if (!mainFeature.Execute())
{
BaseFeature.DisplayHelp();
return;
}
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;
}
}
}

View File

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

View File

@@ -461,4 +461,4 @@ namespace MPF.ExecutionContexts.Test
#endregion
}
}
}

View File

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

View 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
}
}

View File

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

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
@@ -14,13 +14,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeCoverage" Version="17.14.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Microsoft.CodeCoverage" Version="18.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.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.24.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.1.4">
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@@ -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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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 --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 --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 --refine-sector-mode --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 --refine-sector-mode --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);

View File

@@ -86,4 +86,4 @@ namespace MPF.ExecutionContexts.Aaru
#endregion
}
}
}

View File

@@ -40,4 +40,4 @@ namespace MPF.ExecutionContexts.Aaru
public const string WesternEuropeanMac = "macintosh";
public const string WesternEuropeanRadix50 = "radix50";
}
}
}

View File

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

View File

@@ -170,4 +170,4 @@ namespace MPF.ExecutionContexts.Aaru
#endregion
}
}
}

View File

@@ -166,4 +166,4 @@ namespace MPF.ExecutionContexts.Aaru
public const string XboxPartitioning = "Xbox partitioning";
public const string XENIX = "XENIX";
}
}
}

View File

@@ -24,4 +24,4 @@ namespace MPF.ExecutionContexts.Aaru
public const string WindowsNT83MixedCase = "nt";
public const string OS2Extended = "os2";
}
}
}

View File

@@ -40,4 +40,4 @@ namespace MPF.ExecutionContexts.Aaru
public const string VMwareDiskImageSparse = "sparse"; // boolean, default false
public const string VMwareDiskImageSplit = "split"; // boolean, default false
}
}
}

View File

@@ -17,4 +17,4 @@ namespace MPF.ExecutionContexts.Aaru
public const string StripPersonalData = "AaruStripPersonalData";
public const bool StripPersonalDataDefault = false;
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -47,4 +47,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
public const string VideoNowColor = "/vnc";
public const string VideoNowXP = "/vnx";
}
}
}

View File

@@ -23,4 +23,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
public const string UseCMIFlag = "DICUseCMIFlag";
public const bool UseCMIFlagDefault = false;
}
}
}

View File

@@ -0,0 +1,10 @@
namespace MPF.ExecutionContexts.Dreamdump
{
/// <summary>
/// Top-level commands for Dreamdump
/// </summary>
public static class CommandStrings
{
public const string NONE = "";
}
}

View 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,
}
}

View 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
}
}

View 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
}
}

View 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();
}
}

View File

@@ -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.4.0</VersionPrefix>
<VersionPrefix>3.6.0</VersionPrefix>
<WarningsNotAsErrors>NU5104</WarningsNotAsErrors>
<!-- Package Properties -->
@@ -32,7 +32,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.4" />
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
</ItemGroup>
</Project>

View File

@@ -29,4 +29,4 @@ namespace MPF.ExecutionContexts.Redumper
public const string DebugFlip = "debug::flip";
public const string DriveTest = "drive::test";
}
}
}

View File

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

View File

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

View File

@@ -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>
@@ -88,8 +84,8 @@ namespace MPF.ExecutionContexts.Redumper
[FlagStrings.PlextorLeadinRetries] = new Int32Input(FlagStrings.PlextorLeadinRetries),
[FlagStrings.PlextorLeadinForceStore] = new FlagInput(FlagStrings.PlextorLeadinForceStore),
[FlagStrings.KreonPartialSS] = new FlagInput(FlagStrings.KreonPartialSS),
[FlagStrings.AsusSkipLeadout] = new FlagInput(FlagStrings.AsusSkipLeadout),
[FlagStrings.AsusLeadoutRetries] = new Int32Input(FlagStrings.AsusLeadoutRetries),
[FlagStrings.MediatekSkipLeadout] = new FlagInput(FlagStrings.MediatekSkipLeadout),
[FlagStrings.MediatekLeadoutRetries] = new Int32Input(FlagStrings.MediatekLeadoutRetries),
[FlagStrings.DisableCDText] = new FlagInput(FlagStrings.DisableCDText),
// Offset
@@ -103,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),
@@ -113,6 +109,7 @@ 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),
@@ -122,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),
@@ -186,8 +185,8 @@ namespace MPF.ExecutionContexts.Redumper
FlagStrings.PlextorLeadinRetries,
FlagStrings.PlextorLeadinForceStore,
FlagStrings.KreonPartialSS,
FlagStrings.AsusSkipLeadout,
FlagStrings.AsusLeadoutRetries,
FlagStrings.MediatekSkipLeadout,
FlagStrings.MediatekLeadoutRetries,
FlagStrings.DisableCDText,
// Offset
@@ -201,7 +200,7 @@ namespace MPF.ExecutionContexts.Redumper
FlagStrings.LeaveUnchanged,
FlagStrings.ForceQTOC,
FlagStrings.SkipFill,
FlagStrings.ISO9660Trim,
FlagStrings.FilesystemTrim,
// Drive Test
FlagStrings.DriveTestSkipPlextorLeadin,
@@ -211,6 +210,7 @@ namespace MPF.ExecutionContexts.Redumper
FlagStrings.Continue,
FlagStrings.LBAStart,
FlagStrings.LBAEnd,
FlagStrings.LBAEndBySubcode,
FlagStrings.RefineSubchannel,
FlagStrings.RefineSectorMode,
FlagStrings.Skip,
@@ -220,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,
@@ -241,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)
@@ -270,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/>
@@ -291,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);
@@ -328,25 +318,51 @@ 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);
@@ -356,6 +372,13 @@ namespace MPF.ExecutionContexts.Redumper
(_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())
{
@@ -412,8 +435,6 @@ namespace MPF.ExecutionContexts.Redumper
/// <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;
@@ -422,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;
@@ -457,15 +478,19 @@ namespace MPF.ExecutionContexts.Redumper
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;
@@ -498,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;
}

View File

@@ -42,8 +42,8 @@ namespace MPF.ExecutionContexts.Redumper
public const string PlextorLeadinRetries = "--plextor-leadin-retries";
public const string PlextorLeadinForceStore = "--plextor-leadin-force-store";
public const string KreonPartialSS = "--kreon-partial-ss";
public const string AsusSkipLeadout = "--asus-skip-leadout";
public const string AsusLeadoutRetries = "--asus-leadout-retries";
public const string MediatekSkipLeadout = "--mediatek-skip-leadout";
public const string MediatekLeadoutRetries = "--mediatek-leadout-retries";
public const string DisableCDText = "--disable-cdtext";
#endregion
@@ -63,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
@@ -79,6 +79,7 @@ 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";
@@ -88,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

View File

@@ -14,6 +14,9 @@ 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();

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
@@ -14,13 +14,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeCoverage" Version="17.14.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Microsoft.CodeCoverage" Version="18.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="SabreTools.RedumpLib" Version="1.7.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.24.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.1.4">
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@@ -44,4 +44,4 @@ namespace MPF.Frontend.Test
Assert.Equal(expectedValue, actual);
}
}
}
}

View File

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

View File

@@ -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,
@@ -97,4 +97,4 @@ namespace MPF.Frontend.Test.Tools
#endregion
}
}
}

View File

@@ -1,8 +1,7 @@
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
@@ -10,7 +9,7 @@ namespace MPF.Frontend.Test.Tools
public class InfoToolTests
{
[Fact]
public void ProcessSpecialFieldsCompleteTest()
public void ProcessSpecialFields_Complete()
{
// Create a new SubmissionInfo object
var info = new SubmissionInfo()
@@ -36,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');
@@ -50,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()
@@ -92,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');
@@ -106,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()
@@ -114,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 = [],
}
};
@@ -126,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');

View File

@@ -363,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()
{
@@ -661,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);
@@ -683,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)")]
@@ -694,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)",
@@ -711,7 +724,24 @@ 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);
@@ -753,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()
{

View File

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

View File

@@ -5,6 +5,6 @@
/// <summary>
/// Display name for the combo box element
/// </summary>
string Name { get; }
public string Name { get; }
}
}

View File

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

View File

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

View File

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

View File

@@ -81,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?)/>
@@ -137,28 +133,38 @@ namespace MPF.Frontend
{
// 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);
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);
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);
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;
}
@@ -169,25 +175,34 @@ namespace MPF.Frontend
{
// 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);
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);
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);
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;
}
@@ -198,19 +213,22 @@ namespace MPF.Frontend
/// <param name="parameters">String representation of the parameters</param>
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 = mediaType;
@@ -220,7 +238,7 @@ namespace MPF.Frontend
_drive ??= Drive.Create(InternalDriveType.Optical, _executionContext.InputPath!);
}
return _executionContext != null;
return _executionContext is not null;
}
/// <summary>
@@ -230,9 +248,10 @@ namespace MPF.Frontend
{
_processor = _internalProgram switch
{
InternalProgram.Aaru => new Processors.Aaru(_system),
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),
@@ -243,7 +262,7 @@ namespace MPF.Frontend
_ => null,
};
return _processor != null;
return _processor is not null;
}
/// <summary>
@@ -255,23 +274,26 @@ namespace MPF.Frontend
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 && mediaType != 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, 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();
@@ -292,8 +314,9 @@ 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(MediaType? mediaType)
public static bool DoesSupportDriveSpeed(MediaType? mediaType)
{
#pragma warning disable IDE0072
return mediaType switch
{
MediaType.CDROM
@@ -306,12 +329,13 @@ namespace MPF.Frontend
or MediaType.NintendoWiiUOpticalDisc => true,
_ => false,
};
#pragma warning restore IDE0072
}
/// <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(mediaType, outputDirectory, outputFilename).Count == 0;
@@ -320,7 +344,7 @@ namespace MPF.Frontend
/// <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(mediaType, outputDirectory, outputFilename);
@@ -329,7 +353,7 @@ namespace MPF.Frontend
/// <inheritdoc cref="BaseExecutionContext.GetDefaultExtension(MediaType?)"/>
public string? GetDefaultExtension(MediaType? mediaType)
{
if (_executionContext == null)
if (_executionContext is null)
return null;
return _executionContext.GetDefaultExtension(mediaType);
@@ -338,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();
@@ -350,12 +374,16 @@ namespace MPF.Frontend
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 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,17 +405,18 @@ namespace MPF.Frontend
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($"{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();
@@ -413,11 +442,11 @@ namespace MPF.Frontend
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;
@@ -426,11 +455,11 @@ namespace MPF.Frontend
// Check that we have the basics for dumping
ResultEventArgs result = IsValidForDump(mediaType);
if (!result)
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))
@@ -460,34 +489,48 @@ 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);
// 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
}
// 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,
@@ -497,28 +540,23 @@ namespace MPF.Frontend
_processor,
resultProgress,
protectionProgress);
if (submissionInfo == null)
{
resultProgress.Report(ResultEventArgs.Failure("There was an issue extracting information!"));
return ResultEventArgs.Failure();
}
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 media 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 media information added!"));
@@ -527,14 +565,14 @@ namespace MPF.Frontend
}
// 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));
@@ -543,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));
@@ -551,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!"));
@@ -567,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!"));
@@ -578,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(mediaType, 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
@@ -598,7 +636,7 @@ namespace MPF.Frontend
// Delete unnecessary files, if required
if (_options.DeleteUnnecessaryFiles)
{
resultProgress.Report(ResultEventArgs.Success("Deleting unnecessary files..."));
resultProgress.Report(ResultEventArgs.Neutral("Deleting unnecessary files..."));
bool deleteSuccess = _processor.DeleteUnnecessaryFiles(mediaType, outputDirectory, outputFilename, out string deleteResult);
if (deleteSuccess)
resultProgress.Report(ResultEventArgs.Success(deleteResult));
@@ -609,8 +647,8 @@ namespace MPF.Frontend
// Create PS3 IRD, if required
if (_options.CreateIRDAfterDumping && _system == RedumpSystem.SonyPlayStation3 && mediaType == MediaType.BluRay)
{
resultProgress.Report(ResultEventArgs.Success("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);
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
@@ -628,7 +666,7 @@ namespace MPF.Frontend
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;
@@ -648,14 +686,14 @@ namespace MPF.Frontend
private ResultEventArgs IsValidForDump(MediaType? mediaType)
{
// Validate that everything is good
if (_executionContext == null || !ParametersValid(mediaType))
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
@@ -664,7 +702,7 @@ 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
@@ -685,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;
@@ -730,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
@@ -771,7 +809,7 @@ namespace MPF.Frontend
}
catch
{
// We don't care what the error is
// Absorb the exception
return false;
}
@@ -790,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
@@ -815,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])}");
@@ -827,7 +869,7 @@ namespace MPF.Frontend
}
catch
{
// We don't care what the error is
// Absorb the exception
return false;
}

View File

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

View File

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

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

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

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

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

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

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

View File

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

View File

@@ -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.4.0</VersionPrefix>
<VersionPrefix>3.6.0</VersionPrefix>
<!-- Package Properties -->
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
@@ -31,13 +31,14 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BinaryObjectScanner" Version="3.4.2" />
<PackageReference Include="LibIRD" Version="1.0.0" />
<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="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.RedumpLib" Version="1.7.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>

View File

@@ -42,4 +42,4 @@ namespace MPF.Frontend
IEnumerator IEnumerable.GetEnumerator() => _queue.GetEnumerator();
}
}
#endif
#endif

View File

@@ -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; }
}
@@ -141,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>
@@ -157,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();
}
}
@@ -340,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>
@@ -395,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>
@@ -557,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>
@@ -579,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>

View File

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

View File

@@ -36,7 +36,7 @@ namespace MPF.Frontend
// 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 != null);
Debug.Assert(_synchronizationContext is not null);
_invokeHandlers = new SendOrPostCallback(InvokeHandlers);
}
@@ -70,7 +70,7 @@ namespace MPF.Frontend
// an event handler is removed between now and then.
Action<T>? handler = _handler;
EventHandler<T>? changedEvent = ProgressChanged;
if (handler != null || changedEvent != null)
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.)

View File

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

View File

@@ -49,4 +49,4 @@ namespace MPF.Frontend
/// </summary>
public static implicit operator StringEventArgs(StringBuilder? sb) => new(sb);
}
}
}

View File

@@ -16,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
@@ -37,6 +38,7 @@ namespace MPF.Frontend.Tools
// Default
_ => options.PreferredDumpSpeedCD,
};
#pragma warning restore IDE0072
}
/// <summary>
@@ -49,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;
@@ -114,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
@@ -151,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));
@@ -496,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
{
@@ -581,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";
@@ -593,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}"
@@ -617,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;
@@ -650,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();
@@ -666,4 +678,4 @@ namespace MPF.Frontend.Tools
#endregion
}
}
}

View File

@@ -36,7 +36,7 @@ namespace MPF.Frontend.Tools
}
catch (Exception)
{
// We don't care what the error is
// Absorb the exception
return false;
}
}
@@ -61,7 +61,7 @@ namespace MPF.Frontend.Tools
try
{
// Fail on a missing disc key
if (discKey == null)
if (discKey is null)
return false;
// Output IRD file path
@@ -79,9 +79,9 @@ namespace MPF.Frontend.Tools
new LibIRD.ReIRD(isoPath, discKey, layerbreak, uid));
// Set optional fields if valid
if (pic != null)
if (pic is not null)
ird.PIC = pic;
if (discID != null && ird.DiscID[15] != 0x00)
if (discID is not null && ird.DiscID[15] != 0x00)
ird.DiscID = discID;
// Write IRD to file
@@ -91,9 +91,9 @@ namespace MPF.Frontend.Tools
}
catch (Exception)
{
// We don't care what the error is
// Absorb the exception
return false;
}
}
}
}
}

View File

@@ -21,7 +21,7 @@ namespace MPF.Frontend.Tools
{
get
{
if (_configPath != null)
if (_configPath is not null)
return _configPath;
_configPath = GetConfigurationPath();
@@ -32,129 +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] == "-?" || args[0] == "--help")
return null;
if (args[0] == "--version")
{
Console.WriteLine(FrontendTool.GetCurrentVersion() ?? "Unknown version");
return true;
}
// 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 RedumpSystem? system, out string? message)
{
// All other use requires at least 3 arguments
if (args.Length < 2)
{
system = null;
message = "Invalid number of arguments";
return false;
}
// Check the RedumpSystem
system = Extensions.ToRedumpSystem(args[0].Trim('"'));
if (system == null)
{
message = $"{args[0]} is not a recognized system";
return false;
}
message = null;
return true;
}
/// <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>
@@ -298,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
@@ -329,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);
}
@@ -369,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>));
}
@@ -384,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);
@@ -413,7 +257,7 @@ namespace MPF.Frontend.Tools
}
catch { }
// Attempt to use home directory
// Attempt user configuration
try
{
Directory.CreateDirectory(homeDir);
@@ -426,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
}
}

View File

@@ -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,10 +546,10 @@ 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)
if (appPkgHeader is not null)
pkgInfo += $"{appPkgHeader.ContentID}{Environment.NewLine}";
}
@@ -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,10 +697,10 @@ 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)
if (appPkgHeader is not null)
pkgInfo += $"{appPkgHeader.ContentID}{Environment.NewLine}";
}
@@ -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
}
}
}

View File

@@ -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>
@@ -94,7 +162,43 @@ namespace MPF.Frontend.Tools
});
// If nothing was returned, return
if (found == null || found.Count == 0)
if (found is null || found.Count == 0)
return [];
// 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
@@ -105,13 +209,16 @@ 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(Dictionary<string, List<string>>? 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
@@ -124,7 +231,7 @@ namespace MPF.Frontend.Tools
{
if (value.Count == 0)
continue;
foreach (var prot in value)
{
if (!protectionValues.Contains(prot))
@@ -137,7 +244,7 @@ namespace MPF.Frontend.Tools
.Distinct()
.ToList();
#endif
// Sanitize and join protections for writing
string protectionString = SanitizeFoundProtections(protectionValues);
if (string.IsNullOrEmpty(protectionString))
@@ -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
{
@@ -201,7 +308,7 @@ namespace MPF.Frontend.Tools
string[] paths = [.. protections.Keys];
foreach (var path in paths)
{
if (!protections.TryGetValue(path, out var values) || values == null || values.Count == 0)
if (!protections.TryGetValue(path, out var values) || values is null || values.Count == 0)
continue;
// Always copy the values if they're valid
@@ -226,7 +333,7 @@ namespace MPF.Frontend.Tools
// Loop through the matching paths
foreach (var path in matchingPaths)
{
if (!filtered.TryGetValue(path, out var values) || values == null || values.Count == 0)
if (!filtered.TryGetValue(path, out var values) || values is null || values.Count == 0)
continue;
if (values.Exists(s => !s.Contains("GitHub") &&
@@ -263,6 +370,7 @@ namespace MPF.Frontend.Tools
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"));
@@ -375,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"))
@@ -391,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"))
@@ -425,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)))
{
@@ -439,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"))
@@ -451,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"))
@@ -466,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.
@@ -530,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))
@@ -551,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);
}
}
}
}

View File

@@ -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
@@ -55,15 +56,30 @@ namespace MPF.Frontend.Tools
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(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,21 +93,24 @@ namespace MPF.Frontend.Tools
if (options.IncludeArtifacts)
info.Artifacts = processor.GenerateArtifacts(mediaType, outputDirectory, outputFilename);
// Add a placeholder for the logs link
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.LogsLink] = "[Please provide a link to your logs here]";
// 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;
if (volLabels is not null)
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.VolumeLabel] = volLabels;
// Extract info based generically on MediaType
ProcessMediaType(info, mediaType, options.AddPlaceholders);
@@ -100,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!"));
}
@@ -110,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!"));
Dictionary<string, List<string>>? 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!"));
}
@@ -131,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))
@@ -152,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)
{
@@ -161,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;
@@ -186,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 ?? [])
{
@@ -195,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;
}
@@ -230,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;
}
@@ -242,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}"));
@@ -253,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
@@ -264,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;
@@ -282,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>();
@@ -308,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
@@ -325,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!"));
@@ -384,8 +408,6 @@ namespace MPF.Frontend.Tools
},
};
// Ensure that required sections exist
info = Builder.EnsureAllSections(info);
return info;
}
@@ -399,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,
@@ -421,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
@@ -438,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;
@@ -452,23 +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 != null && (driveLabel.Contains("/") || driveLabel.Contains("\\")))
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;
@@ -477,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);
}
@@ -492,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)
@@ -506,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
@@ -516,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;
@@ -532,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;
@@ -545,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])})");
}
@@ -571,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;
@@ -588,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;
@@ -598,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;
@@ -612,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;
@@ -632,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;
@@ -655,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;
@@ -680,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;
@@ -692,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;
@@ -708,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;
}
@@ -723,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:
@@ -813,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:
@@ -903,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);
@@ -931,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);
@@ -952,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;
}
@@ -982,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
@@ -998,7 +1027,7 @@ namespace MPF.Frontend.Tools
/// <summary>
/// Set a comment field if it doesn't already have a value
/// </summary>
private static void SetCommentFieldIfNotExists(SubmissionInfo info, SiteCode key, Drive? drive, System.Func<Drive?, string?> valueFunc)
private static void SetCommentFieldIfNotExists(SubmissionInfo info, SiteCode key, Drive? drive, Func<Drive?, string?> valueFunc)
{
// If the field has a valid value, skip
if (CommentFieldExists(info, key, out _))
@@ -1006,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>
@@ -1016,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
@@ -1040,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>
@@ -1050,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
@@ -1065,7 +1094,7 @@ namespace MPF.Frontend.Tools
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

View File

@@ -1,4 +1,6 @@
using System;
#if !(NET20 || NET35 || NET40)
using System;
#endif
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
@@ -349,12 +351,22 @@ namespace MPF.Frontend.ViewModels
InternalProgram internalProgram = Options.InternalProgram;
// Create a static list of supported Check programs, not everything
var internalPrograms = new List<InternalProgram> { InternalProgram.Redumper, InternalProgram.Aaru, InternalProgram.DiscImageCreator, InternalProgram.CleanRip, InternalProgram.PS3CFW, InternalProgram.UmdImageCreator, InternalProgram.XboxBackupCreator };
var internalPrograms = new List<InternalProgram>
{
InternalProgram.Redumper,
InternalProgram.Aaru,
InternalProgram.DiscImageCreator,
// InternalProgram.Dreamdump,
InternalProgram.CleanRip,
InternalProgram.PS3CFW,
InternalProgram.UmdImageCreator,
InternalProgram.XboxBackupCreator
};
InternalPrograms = internalPrograms.ConvertAll(ip => new Element<InternalProgram>(ip));
// Select the current default dumping program
int currentIndex = InternalPrograms.FindIndex(m => m == internalProgram);
CurrentProgram = (currentIndex > -1 ? InternalPrograms[currentIndex].Value : InternalPrograms[0].Value);
CurrentProgram = currentIndex > -1 ? InternalPrograms[currentIndex].Value : InternalPrograms[0].Value;
// Reenable event handlers, if necessary
if (cachedCanExecuteSelectionChanged) EnableEventHandlers();
@@ -366,7 +378,7 @@ namespace MPF.Frontend.ViewModels
private bool ShouldEnableCheckDumpButton()
{
return CurrentSystem != null && !string.IsNullOrEmpty(InputPath);
return CurrentSystem is not null && !string.IsNullOrEmpty(InputPath);
}
/// <summary>
@@ -393,13 +405,13 @@ namespace MPF.Frontend.ViewModels
/// Performs MPF.Check functionality
/// </summary>
/// <returns>An error message if failed, otherwise string.Empty/null</returns>
public async Task<string?> CheckDump(ProcessUserInfoDelegate processUserInfo)
public async Task<ResultEventArgs> CheckDump(ProcessUserInfoDelegate processUserInfo)
{
if (string.IsNullOrEmpty(InputPath))
return "Invalid Input path";
return ResultEventArgs.Failure("Invalid Input path");
if (!File.Exists(InputPath!.Trim('"')))
return "Input Path is not a valid file";
return ResultEventArgs.Failure("Input Path is not a valid file");
// Disable UI while Check is running
DisableUIElements();
@@ -431,7 +443,7 @@ namespace MPF.Frontend.ViewModels
if (cachedCanExecuteSelectionChanged)
EnableEventHandlers();
return result.Message;
return result;
}
/// <summary>

Some files were not shown because too many files have changed in this diff Show More