mirror of
https://github.com/SabreTools/MPF.git
synced 2026-02-08 21:31:47 +00:00
Compare commits
717 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39f9199807 | ||
|
|
7c561deb7b | ||
|
|
195d321bbe | ||
|
|
918e4bf1d1 | ||
|
|
1da70014b1 | ||
|
|
ff58e48ce9 | ||
|
|
90f808b63b | ||
|
|
f673a9baea | ||
|
|
56ee536eae | ||
|
|
a4fb368f7e | ||
|
|
abca8b58cf | ||
|
|
a1eef04706 | ||
|
|
a03809c94c | ||
|
|
e5bf218a42 | ||
|
|
992fb507e7 | ||
|
|
9a075ad5de | ||
|
|
5e9ec596ea | ||
|
|
059fc4cab5 | ||
|
|
1fc1288350 | ||
|
|
1c1b5059d8 | ||
|
|
299fafe1f8 | ||
|
|
8f6305a7c4 | ||
|
|
3f61957715 | ||
|
|
57750295fb | ||
|
|
286ec864ab | ||
|
|
e4fd644c61 | ||
|
|
7502d7e8df | ||
|
|
439fb2717c | ||
|
|
089ab1c4a2 | ||
|
|
89a50ea424 | ||
|
|
740d867d7b | ||
|
|
83fa4852c9 | ||
|
|
ecc00a28c2 | ||
|
|
2d90c849e1 | ||
|
|
1d065ffd48 | ||
|
|
ca885c3b89 | ||
|
|
94fd614673 | ||
|
|
9fc5799999 | ||
|
|
61f90a635f | ||
|
|
8cc0ff3829 | ||
|
|
cac6bcc4de | ||
|
|
7ac0089e81 | ||
|
|
48576b38be | ||
|
|
82dedf1ceb | ||
|
|
395cded5ef | ||
|
|
a48f9d1c83 | ||
|
|
3975003686 | ||
|
|
4beae71511 | ||
|
|
f0f41c86c5 | ||
|
|
b1b6eb2c9d | ||
|
|
29754b4c0e | ||
|
|
35cda84308 | ||
|
|
a877397fe6 | ||
|
|
2f0471d596 | ||
|
|
2037ded792 | ||
|
|
5f1a68a5f5 | ||
|
|
87746c8677 | ||
|
|
2665c29918 | ||
|
|
5637cf5201 | ||
|
|
eb1d000e4f | ||
|
|
8db467128d | ||
|
|
dc90e2609d | ||
|
|
e96bd21f1d | ||
|
|
693599b986 | ||
|
|
d482fe926c | ||
|
|
17b5432352 | ||
|
|
ca480f27ed | ||
|
|
4bad66e706 | ||
|
|
abe00fe132 | ||
|
|
ba73479837 | ||
|
|
f2a28dd36b | ||
|
|
928e30a5de | ||
|
|
007fc2f9b9 | ||
|
|
d2d23ebbdf | ||
|
|
e02ab769ec | ||
|
|
3df78def00 | ||
|
|
7eddfc5fed | ||
|
|
f6f154b6db | ||
|
|
47cd133437 | ||
|
|
74c9641a54 | ||
|
|
fc5929db2a | ||
|
|
f53b428075 | ||
|
|
46dc931b3f | ||
|
|
9608cfb700 | ||
|
|
3493238849 | ||
|
|
4c364f519e | ||
|
|
337a7a181c | ||
|
|
071e3a0024 | ||
|
|
ff0c742dee | ||
|
|
7aba0d1c9c | ||
|
|
ac6a77d9da | ||
|
|
6eb976c842 | ||
|
|
ba39a8b22f | ||
|
|
88a6fa71a9 | ||
|
|
584b8c0109 | ||
|
|
c6258b5520 | ||
|
|
d6dbbbe928 | ||
|
|
f22b3c4ac0 | ||
|
|
fae399f8bc | ||
|
|
d2ed2f81ae | ||
|
|
7dbcfce46c | ||
|
|
ebd0552a2a | ||
|
|
343973263c | ||
|
|
e5220a8224 | ||
|
|
146120c210 | ||
|
|
807e4655a6 | ||
|
|
e32ebec197 | ||
|
|
8d8886390d | ||
|
|
5a2aa9d325 | ||
|
|
37aa1645dd | ||
|
|
052d074e92 | ||
|
|
8c551dc990 | ||
|
|
b2fcc190fd | ||
|
|
2325844bd4 | ||
|
|
f63517bb52 | ||
|
|
99d26f177b | ||
|
|
d6b28de586 | ||
|
|
e8d1567d07 | ||
|
|
cd8b484ae3 | ||
|
|
65b9735941 | ||
|
|
22f7e2a0ed | ||
|
|
2c5dc7390a | ||
|
|
c5e01b9578 | ||
|
|
882243316c | ||
|
|
1b62ed0c03 | ||
|
|
edb8c08a39 | ||
|
|
ad93387aea | ||
|
|
9012ff85a9 | ||
|
|
ccc33bebbd | ||
|
|
57b07aee02 | ||
|
|
069d676492 | ||
|
|
a26dfb7e7a | ||
|
|
a9ea457808 | ||
|
|
41bc410452 | ||
|
|
bbfdf462d0 | ||
|
|
5a1d51c05f | ||
|
|
16e80f75cf | ||
|
|
2a6e066707 | ||
|
|
d6102107fb | ||
|
|
79163dcb35 | ||
|
|
c1aa863c91 | ||
|
|
dbd4b55dda | ||
|
|
1f58521f51 | ||
|
|
4da1ab9c29 | ||
|
|
5771add8c0 | ||
|
|
977a71d9cf | ||
|
|
b2d09d04ea | ||
|
|
78df92e5d3 | ||
|
|
9770b7c917 | ||
|
|
1ddb287977 | ||
|
|
b9e4bbf744 | ||
|
|
08829ed811 | ||
|
|
bf181e2294 | ||
|
|
49571c6bfc | ||
|
|
9a0bc868f8 | ||
|
|
bc2c08690d | ||
|
|
493cb80624 | ||
|
|
49b8ecf6c3 | ||
|
|
c9b7ad7819 | ||
|
|
fe76387f6a | ||
|
|
0a60fe5a37 | ||
|
|
baffdb8b29 | ||
|
|
4a3c585a8d | ||
|
|
1ee7ea1948 | ||
|
|
ee08bfe0fc | ||
|
|
896caec9cd | ||
|
|
68932ab473 | ||
|
|
d105d04146 | ||
|
|
7023c78d40 | ||
|
|
81156a3c63 | ||
|
|
7b2b06a36f | ||
|
|
3f974ab336 | ||
|
|
b238616685 | ||
|
|
2984459823 | ||
|
|
ce979b3c3f | ||
|
|
cb8e1fd34b | ||
|
|
cc148735f8 | ||
|
|
8238d14f7b | ||
|
|
a56676501e | ||
|
|
79716ea0b5 | ||
|
|
43477a133f | ||
|
|
8889beef1d | ||
|
|
ac4be751b3 | ||
|
|
69f855fc93 | ||
|
|
cf01095623 | ||
|
|
3236223e3f | ||
|
|
36450cd22b | ||
|
|
6a9b6748d2 | ||
|
|
3bf83378a2 | ||
|
|
bc938fd58c | ||
|
|
f50a110acd | ||
|
|
fcda2a6e3b | ||
|
|
d33526b27e | ||
|
|
0b0427e9c1 | ||
|
|
c34b92bad8 | ||
|
|
89145df0fa | ||
|
|
ee7cde6360 | ||
|
|
8e9edf43ac | ||
|
|
51115430cb | ||
|
|
7cf108828e | ||
|
|
020390af65 | ||
|
|
e04ceb953c | ||
|
|
363b018cb7 | ||
|
|
cf025522ef | ||
|
|
0fb8bf5c29 | ||
|
|
e280745eee | ||
|
|
fb306750e6 | ||
|
|
da5a514482 | ||
|
|
fc288e1c46 | ||
|
|
102acb9ebf | ||
|
|
b76b2a69f5 | ||
|
|
254ad6cfd0 | ||
|
|
f432f438ab | ||
|
|
e890243830 | ||
|
|
6493b462f1 | ||
|
|
54c0716ea9 | ||
|
|
7fbb5133d7 | ||
|
|
993a0fd7d3 | ||
|
|
47878fee1f | ||
|
|
4cb8a31505 | ||
|
|
0685972842 | ||
|
|
5b1cc3c715 | ||
|
|
572f0d5095 | ||
|
|
23bafad3db | ||
|
|
c7b77e4bd7 | ||
|
|
755eee4441 | ||
|
|
fca2c53d6c | ||
|
|
8f6f5f6ef0 | ||
|
|
2e9970ee6a | ||
|
|
4fa1273111 | ||
|
|
d3993a48e4 | ||
|
|
d522bb6c76 | ||
|
|
816672a817 | ||
|
|
f8171da306 | ||
|
|
ce073e5fbf | ||
|
|
28205e42f0 | ||
|
|
0160366530 | ||
|
|
663477d408 | ||
|
|
bd2e012eef | ||
|
|
a514374169 | ||
|
|
f73c0730e2 | ||
|
|
a658c80de7 | ||
|
|
b806bc6cd1 | ||
|
|
cf9675f620 | ||
|
|
ea18051709 | ||
|
|
4fdf8e5dde | ||
|
|
a4616d139d | ||
|
|
0f09a9c913 | ||
|
|
48ffd6f40c | ||
|
|
6612c8ea4d | ||
|
|
68d1a0664a | ||
|
|
86d8590789 | ||
|
|
e23427d7c9 | ||
|
|
cd19a2e4a0 | ||
|
|
000e7d88a8 | ||
|
|
e3beb1ef77 | ||
|
|
a3a75b1c2d | ||
|
|
11850a8d6b | ||
|
|
bf6b58d64b | ||
|
|
1789334625 | ||
|
|
9520f58240 | ||
|
|
48e5e01729 | ||
|
|
8c7959fb08 | ||
|
|
8ef7543cf1 | ||
|
|
f9e39ee4be | ||
|
|
0a4621c963 | ||
|
|
04b4f528ba | ||
|
|
f024e49c21 | ||
|
|
7ca404f9dd | ||
|
|
18fc162cd8 | ||
|
|
b577bbae37 | ||
|
|
02f9509b86 | ||
|
|
8b00e3deed | ||
|
|
3ffea60402 | ||
|
|
f8eab60ecc | ||
|
|
9e8d46fb03 | ||
|
|
3831922f29 | ||
|
|
7f7416c053 | ||
|
|
529ada1b8b | ||
|
|
6260f1a1fe | ||
|
|
a7f6e09226 | ||
|
|
4b49815a7a | ||
|
|
14c17bbdf7 | ||
|
|
0fe30d2d4f | ||
|
|
1c3f65e7f9 | ||
|
|
62ff0f955a | ||
|
|
a942e6142a | ||
|
|
f637e629a3 | ||
|
|
72b00953d8 | ||
|
|
cfac607c7d | ||
|
|
e9a84e5429 | ||
|
|
2f985d0526 | ||
|
|
e1ace14753 | ||
|
|
9c29967f65 | ||
|
|
5612d7989d | ||
|
|
f872a6be29 | ||
|
|
59e7ecfa8a | ||
|
|
79cce37cf6 | ||
|
|
4016b3fc19 | ||
|
|
e5bcada606 | ||
|
|
60d31363e3 | ||
|
|
22a125a838 | ||
|
|
0a86781d61 | ||
|
|
c5649ecdbb | ||
|
|
df22336ba0 | ||
|
|
2d7350cbaf | ||
|
|
6a56a58b7c | ||
|
|
a97c94885c | ||
|
|
9548993982 | ||
|
|
1476972c26 | ||
|
|
85cde67d0a | ||
|
|
bfaf24c237 | ||
|
|
adfa8a9a0c | ||
|
|
3d68d880f6 | ||
|
|
77bc7e7b1a | ||
|
|
23837ee555 | ||
|
|
0553d1256a | ||
|
|
68f0c6cf35 | ||
|
|
32d3996432 | ||
|
|
5af02fe508 | ||
|
|
eba6a7ce4a | ||
|
|
7faedc92e4 | ||
|
|
3de48fc24e | ||
|
|
9400523c4f | ||
|
|
48c945f194 | ||
|
|
d9a8050beb | ||
|
|
6ec179f0ed | ||
|
|
620851af73 | ||
|
|
f5c4b7ebdf | ||
|
|
364ae1b837 | ||
|
|
b4b864cd9f | ||
|
|
acc2f30bd2 | ||
|
|
dc0675d8c6 | ||
|
|
33ce0e4024 | ||
|
|
fa8fdac0ce | ||
|
|
a4d876d273 | ||
|
|
3cc779ba77 | ||
|
|
5c8f4b9cac | ||
|
|
fb2b926986 | ||
|
|
3442a1f5b2 | ||
|
|
1fb9039985 | ||
|
|
0032066363 | ||
|
|
c1ed042190 | ||
|
|
6c0f2415b7 | ||
|
|
ca898c4689 | ||
|
|
3be4378b61 | ||
|
|
c1641d7461 | ||
|
|
aefb5a3778 | ||
|
|
4557017fc5 | ||
|
|
d77e9c1612 | ||
|
|
455fb8228a | ||
|
|
679b40de7c | ||
|
|
fb2b1b7c54 | ||
|
|
ac649af511 | ||
|
|
4fb0e38f54 | ||
|
|
a84904e374 | ||
|
|
7b8becfa40 | ||
|
|
ba0fefca42 | ||
|
|
d7736055a0 | ||
|
|
8e37932b86 | ||
|
|
d2c58d4c39 | ||
|
|
34f3449231 | ||
|
|
31ee29a716 | ||
|
|
c1f2fd5f19 | ||
|
|
172f9afbcf | ||
|
|
19dd4f43e4 | ||
|
|
0ae7352c5e | ||
|
|
e7c11d40ac | ||
|
|
dccd78a01e | ||
|
|
fb05409c5d | ||
|
|
1c9b94341a | ||
|
|
d3e208a332 | ||
|
|
6b8cfb4256 | ||
|
|
f60f26065b | ||
|
|
2ed14a7688 | ||
|
|
071b91f414 | ||
|
|
0ad99cb0f5 | ||
|
|
e51aabddae | ||
|
|
9390699114 | ||
|
|
93d2c2e8b0 | ||
|
|
50d969f08f | ||
|
|
44e87948c7 | ||
|
|
dea011213a | ||
|
|
5b2500637b | ||
|
|
82ede4dac2 | ||
|
|
032ffe75f4 | ||
|
|
ce9c6d1f52 | ||
|
|
8be145127d | ||
|
|
0ce928349c | ||
|
|
79e4f4a142 | ||
|
|
4bd8fc476c | ||
|
|
5b82cdacda | ||
|
|
4106a6261b | ||
|
|
6b006958a6 | ||
|
|
068b92ebac | ||
|
|
4cf2b8a83d | ||
|
|
333043ccae | ||
|
|
0ff1753aa2 | ||
|
|
9ad917e508 | ||
|
|
f3ac31ce1b | ||
|
|
7fdf671273 | ||
|
|
d5dee49f6b | ||
|
|
acdc13efa1 | ||
|
|
8446980919 | ||
|
|
e5e7bf49fc | ||
|
|
8b73ffc4a2 | ||
|
|
ce6ed1e01b | ||
|
|
bc0cd60fc1 | ||
|
|
17f850ecb2 | ||
|
|
ad8a623f16 | ||
|
|
b025898d7b | ||
|
|
b604aefd5e | ||
|
|
1656b50029 | ||
|
|
572b8cfa6b | ||
|
|
c5cd623e75 | ||
|
|
ff2dbd7b81 | ||
|
|
19cedfc5e8 | ||
|
|
3df93fb59d | ||
|
|
62ffd3f6d3 | ||
|
|
69994774f5 | ||
|
|
3a1fc93aac | ||
|
|
6f8d27b9c4 | ||
|
|
42680b9915 | ||
|
|
9033f3a798 | ||
|
|
717590bf41 | ||
|
|
4f48ccc4c6 | ||
|
|
ca59d71e7d | ||
|
|
9207627fb0 | ||
|
|
216c6de970 | ||
|
|
cebbeb264f | ||
|
|
e971ee8550 | ||
|
|
76029d02ea | ||
|
|
0cdf2fc520 | ||
|
|
5ac0055e16 | ||
|
|
7b7e8912a5 | ||
|
|
e055572c67 | ||
|
|
c4d981350f | ||
|
|
5035f2dcc2 | ||
|
|
7c41fe0933 | ||
|
|
2b4fa33e81 | ||
|
|
e8f50a84b8 | ||
|
|
7c0923881e | ||
|
|
eeacb7b3b2 | ||
|
|
d3039af3e1 | ||
|
|
eaa77dbeed | ||
|
|
55696f1f47 | ||
|
|
7d22341d2f | ||
|
|
53c6e47fa8 | ||
|
|
7b7da4db1f | ||
|
|
b9d8e0c125 | ||
|
|
1e2f1280be | ||
|
|
3339ff1c14 | ||
|
|
1e729459a6 | ||
|
|
2d547bd67f | ||
|
|
2bb854e7a5 | ||
|
|
b8e923207f | ||
|
|
3d96379aba | ||
|
|
8c5437983a | ||
|
|
7cad841f39 | ||
|
|
b4e04314a7 | ||
|
|
f1506b284c | ||
|
|
3fde773018 | ||
|
|
2fb8613a85 | ||
|
|
94d59242b1 | ||
|
|
09179810ee | ||
|
|
2061af06c1 | ||
|
|
075a95ef4c | ||
|
|
c8a402ee64 | ||
|
|
a5d7b218b7 | ||
|
|
ebb83a6a1e | ||
|
|
0c327872b5 | ||
|
|
6ef9debac4 | ||
|
|
10c7906e9d | ||
|
|
b922857578 | ||
|
|
dca5235a4a | ||
|
|
07e747f7d3 | ||
|
|
da67c58727 | ||
|
|
0524ad7ac2 | ||
|
|
2a16be2c07 | ||
|
|
a5a048fcb0 | ||
|
|
b2ffa2025b | ||
|
|
0d11e03507 | ||
|
|
c72aeb7f58 | ||
|
|
86eca8dee7 | ||
|
|
5e5360441a | ||
|
|
5392afbf06 | ||
|
|
c7c700e567 | ||
|
|
8c0bbfbf10 | ||
|
|
e7baa7d33f | ||
|
|
724b1b6719 | ||
|
|
ab88f8ffaa | ||
|
|
6feda0e69d | ||
|
|
d704cec97b | ||
|
|
9fe815676f | ||
|
|
129a7ba63f | ||
|
|
4617401e8b | ||
|
|
3cb037b5af | ||
|
|
49b70b7ae1 | ||
|
|
4eb346632a | ||
|
|
56fffb0ed9 | ||
|
|
8adde6f8d5 | ||
|
|
eacd60562c | ||
|
|
f6df7e96c1 | ||
|
|
0e37025150 | ||
|
|
4e338d56cd | ||
|
|
c26253007d | ||
|
|
66b4bb4eb2 | ||
|
|
034494558e | ||
|
|
cc7116a623 | ||
|
|
011ca670e0 | ||
|
|
956d8efcf7 | ||
|
|
ee4e77b208 | ||
|
|
8eff11f0ae | ||
|
|
8d4f22a1c4 | ||
|
|
3829ee1bbe | ||
|
|
61060e98df | ||
|
|
7f061f22e0 | ||
|
|
e72336a835 | ||
|
|
886a0a4f07 | ||
|
|
093435e7b0 | ||
|
|
59a427963d | ||
|
|
19d6006aff | ||
|
|
617b0ba2c5 | ||
|
|
195c83499c | ||
|
|
e5b02c27a8 | ||
|
|
c7b6b08397 | ||
|
|
da6b2f0e24 | ||
|
|
c50c3edcc5 | ||
|
|
d628b2a0dd | ||
|
|
f6baaa6f5e | ||
|
|
b05c82e903 | ||
|
|
65f472c4c9 | ||
|
|
104dd4348b | ||
|
|
2337a2ed86 | ||
|
|
2ce632f8b4 | ||
|
|
ce917f4f61 | ||
|
|
d029cf4164 | ||
|
|
74d52c2f3b | ||
|
|
785786c3a9 | ||
|
|
466d8f58b0 | ||
|
|
bc690614e6 | ||
|
|
d44798b27c | ||
|
|
595cd0d60f | ||
|
|
68fd5a2aa0 | ||
|
|
6da98aa65c | ||
|
|
d8d149446f | ||
|
|
4d0f48be10 | ||
|
|
8a048c8a57 | ||
|
|
d51db072fc | ||
|
|
468c9937da | ||
|
|
206ac76633 | ||
|
|
339b0d93d1 | ||
|
|
fd5da5de74 | ||
|
|
42146f991d | ||
|
|
f3f05eee48 | ||
|
|
61bf2f69aa | ||
|
|
546aa70b69 | ||
|
|
65cd1cede3 | ||
|
|
dffa16139a | ||
|
|
98bacf11fc | ||
|
|
ee0ccecfb2 | ||
|
|
a0825f276b | ||
|
|
66d61e20de | ||
|
|
6455ebd434 | ||
|
|
f4436fddfa | ||
|
|
317777cf93 | ||
|
|
da6dbe136e | ||
|
|
13d7cf8124 | ||
|
|
bb8fea625b | ||
|
|
15a0659867 | ||
|
|
988a5f6d2b | ||
|
|
1941639473 | ||
|
|
d1772f743e | ||
|
|
870c2d1cec | ||
|
|
f7f6ae1eee | ||
|
|
dd9e527592 | ||
|
|
e1122fa976 | ||
|
|
8a44fa3355 | ||
|
|
51a9e3005f | ||
|
|
413b6da24b | ||
|
|
172a0fb5dc | ||
|
|
83a189a5d3 | ||
|
|
60c27ec89b | ||
|
|
51733557cd | ||
|
|
93d964c603 | ||
|
|
2925f2262b | ||
|
|
5b211a7345 | ||
|
|
ed4bd24fcb | ||
|
|
8a7761753b | ||
|
|
1b8cca9999 | ||
|
|
b75391b1c6 | ||
|
|
e9c2fd9245 | ||
|
|
fb24bbd8a5 | ||
|
|
4e3083c8e6 | ||
|
|
05738b7c11 | ||
|
|
f963db67b1 | ||
|
|
de64631c00 | ||
|
|
c8adef78c2 | ||
|
|
7b116e7a04 | ||
|
|
fb7b6ff1be | ||
|
|
7fb8e44c31 | ||
|
|
239ad4c4bc | ||
|
|
9834d0ea3e | ||
|
|
a35c13bd10 | ||
|
|
5e1777a7c7 | ||
|
|
66570300df | ||
|
|
4ac1fb201e | ||
|
|
cba8daa010 | ||
|
|
ba24a4b21a | ||
|
|
91c6fdac82 | ||
|
|
416656c457 | ||
|
|
fdd75818c4 | ||
|
|
ac302626c2 | ||
|
|
428f3cc547 | ||
|
|
66fc36fe3c | ||
|
|
9dddf1c9b6 | ||
|
|
5dbb955d26 | ||
|
|
2f2958bdea | ||
|
|
c91f6ebbce | ||
|
|
22fdd036eb | ||
|
|
3f12c6acb9 | ||
|
|
1dbae18da6 | ||
|
|
6370e2dd6a | ||
|
|
0c8879bc66 | ||
|
|
6be34414fe | ||
|
|
f15fc989c8 | ||
|
|
0fc53cb534 | ||
|
|
dc0909808a | ||
|
|
00401d1282 | ||
|
|
b9d0d5d8f6 | ||
|
|
22a6b77d27 | ||
|
|
bc4fe17fab | ||
|
|
4b4027f285 | ||
|
|
d28257b2b7 | ||
|
|
669ef47f32 | ||
|
|
be224800bc | ||
|
|
8dbb589d42 | ||
|
|
7b2fd5bf35 | ||
|
|
95fa651074 | ||
|
|
a0a155eb9b | ||
|
|
72339b18df | ||
|
|
95c9c7706d | ||
|
|
135bb43cdf | ||
|
|
cfc75ca84d | ||
|
|
33c35b63d7 | ||
|
|
851a43d46f | ||
|
|
a88bef481d | ||
|
|
781fec2b57 | ||
|
|
ee96367a45 | ||
|
|
9f9bfc0888 | ||
|
|
c6cc697320 | ||
|
|
5e3f7f740b | ||
|
|
e17a8f4708 | ||
|
|
ff4771a74a | ||
|
|
426717102d | ||
|
|
126bae33a4 | ||
|
|
11b8dd44bb | ||
|
|
cbbb8aaa8c | ||
|
|
9ee7cd7fd7 | ||
|
|
324c1fcee3 | ||
|
|
06776a6093 | ||
|
|
43a079bb28 | ||
|
|
d45345d338 | ||
|
|
1ff0340cae | ||
|
|
278c86f9f4 | ||
|
|
00089b799c | ||
|
|
0f98f03999 | ||
|
|
22f6f39a91 | ||
|
|
e9a9011dbd | ||
|
|
40bbb3d1c8 | ||
|
|
a48dad817b | ||
|
|
9f76dcc5fd | ||
|
|
4356561a8a | ||
|
|
347c522d62 | ||
|
|
998ecec261 | ||
|
|
ab8e775df0 | ||
|
|
246e6b8bfd | ||
|
|
c7f69de18f | ||
|
|
d4a98d7712 | ||
|
|
2983266e8a | ||
|
|
1baef4440a | ||
|
|
7cd25dae1c | ||
|
|
38f9b7234b | ||
|
|
2d7ea1bed9 | ||
|
|
806a69c280 | ||
|
|
a92159b8cb | ||
|
|
9451629461 | ||
|
|
51a1f0cc8e | ||
|
|
2830641b8a | ||
|
|
7c87a22dcc | ||
|
|
dd5b5d4c7d | ||
|
|
bc5e73d371 | ||
|
|
f47a55b723 | ||
|
|
c4d014e480 | ||
|
|
69b1d2f7ad | ||
|
|
7c295ca2f4 | ||
|
|
5af3aad68a | ||
|
|
f150483e84 | ||
|
|
92ef962f42 | ||
|
|
859e53f843 | ||
|
|
e70d70ca22 | ||
|
|
c2cf8147d3 | ||
|
|
cf32f38c0e | ||
|
|
1f92ff08d6 | ||
|
|
6aaf076434 | ||
|
|
6865b23aa7 | ||
|
|
e1c13982bd | ||
|
|
9cddcc2eae | ||
|
|
33932fad47 | ||
|
|
470e5c69fe | ||
|
|
3aae2990a3 | ||
|
|
503933e67f | ||
|
|
1a99fd9e71 | ||
|
|
affc175bda | ||
|
|
fe4c88d3ad | ||
|
|
9c830c9755 | ||
|
|
fc300465f8 |
169
.editorconfig
169
.editorconfig
@@ -1,4 +1,167 @@
|
||||
[*.cs]
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# SYSLIB1045: Convert to 'GeneratedRegexAttribute'.
|
||||
dotnet_diagnostic.SYSLIB1045.severity = silent
|
||||
# C# files
|
||||
[*.cs]
|
||||
|
||||
# Indentation and spacing
|
||||
charset = utf-8
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
tab_width = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# New line preferences
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
max_line_length = unset
|
||||
|
||||
# using directive preferences
|
||||
csharp_using_directive_placement = outside_namespace
|
||||
dotnet_diagnostic.IDE0005.severity = error
|
||||
|
||||
# Code-block preferences
|
||||
csharp_style_namespace_declarations = block_scoped
|
||||
csharp_style_prefer_method_group_conversion = true
|
||||
csharp_style_prefer_top_level_statements = false
|
||||
|
||||
# Expression-level preferences
|
||||
csharp_prefer_simple_default_expression = true
|
||||
csharp_style_inlined_variable_declaration = true
|
||||
csharp_style_unused_value_assignment_preference = discard_variable
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable
|
||||
dotnet_diagnostic.IDE0001.severity = warning
|
||||
dotnet_diagnostic.IDE0002.severity = warning
|
||||
dotnet_diagnostic.IDE0004.severity = warning
|
||||
dotnet_diagnostic.IDE0010.severity = error
|
||||
dotnet_diagnostic.IDE0051.severity = warning
|
||||
dotnet_diagnostic.IDE0052.severity = warning
|
||||
dotnet_diagnostic.IDE0072.severity = warning
|
||||
dotnet_diagnostic.IDE0080.severity = warning
|
||||
dotnet_diagnostic.IDE0100.severity = error
|
||||
dotnet_diagnostic.IDE0110.severity = error
|
||||
dotnet_diagnostic.IDE0120.severity = warning
|
||||
dotnet_diagnostic.IDE0121.severity = warning
|
||||
dotnet_diagnostic.IDE0240.severity = error
|
||||
dotnet_diagnostic.IDE0241.severity = error
|
||||
dotnet_style_coalesce_expression = true
|
||||
dotnet_style_namespace_match_folder = false
|
||||
dotnet_style_null_propagation = true
|
||||
dotnet_style_prefer_auto_properties = true
|
||||
dotnet_style_prefer_collection_expression = when_types_loosely_match
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
|
||||
dotnet_style_prefer_compound_assignment = true
|
||||
csharp_style_prefer_simple_property_accessors = true
|
||||
dotnet_style_prefer_simplified_interpolation = true
|
||||
dotnet_style_prefer_simplified_boolean_expressions = true
|
||||
csharp_style_prefer_unbound_generic_type_in_nameof = true
|
||||
|
||||
# Field preferences
|
||||
dotnet_diagnostic.IDE0044.severity = warning
|
||||
dotnet_style_readonly_field = true
|
||||
|
||||
# Language keyword vs. framework types preferences
|
||||
dotnet_diagnostic.IDE0049.severity = error
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true
|
||||
dotnet_style_predefined_type_for_member_access = true
|
||||
|
||||
# Modifier preferences
|
||||
csharp_prefer_static_local_function = true
|
||||
csharp_style_prefer_readonly_struct = true
|
||||
dotnet_diagnostic.IDE0036.severity = warning
|
||||
dotnet_diagnostic.IDE0040.severity = error
|
||||
dotnet_diagnostic.IDE0380.severity = error
|
||||
dotnet_style_require_accessibility_modifiers = always
|
||||
|
||||
# New-line preferences
|
||||
dotnet_diagnostic.IDE2000.severity = warning
|
||||
dotnet_diagnostic.IDE2002.severity = warning
|
||||
dotnet_diagnostic.IDE2003.severity = warning
|
||||
dotnet_diagnostic.IDE2004.severity = warning
|
||||
dotnet_diagnostic.IDE2005.severity = warning
|
||||
dotnet_diagnostic.IDE2006.severity = warning
|
||||
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false
|
||||
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false
|
||||
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false
|
||||
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
|
||||
dotnet_style_allow_multiple_blank_lines_experimental = false
|
||||
dotnet_style_allow_statement_immediately_after_block_experimental = false
|
||||
|
||||
# Null-checking preferences
|
||||
csharp_style_conditional_delegate_call = true
|
||||
|
||||
# Parameter preferences
|
||||
dotnet_code_quality_unused_parameters = all
|
||||
dotnet_diagnostic.IDE0280.severity = error
|
||||
|
||||
# Parentheses preferences
|
||||
dotnet_diagnostic.IDE0047.severity = warning
|
||||
dotnet_diagnostic.IDE0048.severity = warning
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
|
||||
dotnet_style_parentheses_in_other_operators = always_for_clarity
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
|
||||
|
||||
# Pattern-matching preferences
|
||||
dotnet_diagnostic.IDE0019.severity = warning
|
||||
dotnet_diagnostic.IDE0020.severity = warning
|
||||
dotnet_diagnostic.IDE0038.severity = warning
|
||||
dotnet_diagnostic.IDE0066.severity = none
|
||||
dotnet_diagnostic.IDE0083.severity = warning
|
||||
dotnet_diagnostic.IDE0260.severity = warning
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true
|
||||
csharp_style_prefer_not_pattern = true
|
||||
csharp_style_prefer_pattern_matching = true
|
||||
|
||||
# this. and Me. preferences
|
||||
dotnet_style_qualification_for_event = false
|
||||
dotnet_style_qualification_for_field = false
|
||||
dotnet_style_qualification_for_method = false
|
||||
dotnet_style_qualification_for_property = false
|
||||
|
||||
# var preferences
|
||||
csharp_style_var_for_built_in_types = false
|
||||
csharp_style_var_when_type_is_apparent = true
|
||||
|
||||
# .NET formatting options
|
||||
dotnet_separate_import_directive_groups = false
|
||||
dotnet_sort_system_directives_first = true
|
||||
|
||||
# C# formatting options
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_case_contents_when_block = false
|
||||
csharp_indent_labels = one_less_than_current
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = true
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_between_square_brackets = false
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/feature-request.md
vendored
4
.github/ISSUE_TEMPLATE/feature-request.md
vendored
@@ -9,8 +9,8 @@ assignees: mnadareski
|
||||
|
||||
**Before You Submit**
|
||||
|
||||
- Remember to try the [latest WIP build](https://ci.appveyor.com/project/mnadareski/mpf/build/artifacts) to see if the feature already exists.
|
||||
- Is it copy protection related? If so, report the issue [here](hhttps://github.com/SabreTools/BinaryObjectScanner/issues) instead.
|
||||
- Remember to try the [latest WIP build](https://github.com/SabreTools/MPF/releases/tag/rolling) to see if the feature already exists.
|
||||
- Is it copy protection related? If so, report the issue [here](https://github.com/SabreTools/BinaryObjectScanner/issues) instead.
|
||||
- Check [previous issues](https://github.com/SabreTools/MPF/issues) to see if any of those are related to what you're about to ask for.
|
||||
|
||||
If none of those apply, then continue...
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/informational.md
vendored
4
.github/ISSUE_TEMPLATE/informational.md
vendored
@@ -9,8 +9,8 @@ assignees: mnadareski
|
||||
|
||||
**Before You Submit**
|
||||
|
||||
- Remember to try the [latest WIP build](https://ci.appveyor.com/project/mnadareski/mpf/build/artifacts) to see if the feature already exists.
|
||||
- Is it copy protection related? If so, report the issue [here](hhttps://github.com/SabreTools/BinaryObjectScanner/issues) instead.
|
||||
- Remember to try the [latest WIP build](https://github.com/SabreTools/MPF/releases/tag/rolling) to see if the feature already exists.
|
||||
- Is it copy protection related? If so, report the issue [here](https://github.com/SabreTools/BinaryObjectScanner/issues) instead.
|
||||
- Check [previous issues](https://github.com/SabreTools/MPF/issues) to see if any of those are related to what you're about to ask for.
|
||||
|
||||
If none of those apply, then continue...
|
||||
|
||||
7
.github/ISSUE_TEMPLATE/issue-report.md
vendored
7
.github/ISSUE_TEMPLATE/issue-report.md
vendored
@@ -9,8 +9,8 @@ assignees: mnadareski
|
||||
|
||||
**Before You Submit**
|
||||
|
||||
- Remember to try the [latest WIP build](https://ci.appveyor.com/project/mnadareski/mpf/build/artifacts) to see if the issue has already been addressed.
|
||||
- Is it copy protection related? If so, report the issue [here](hhttps://github.com/SabreTools/BinaryObjectScanner/issues) instead.
|
||||
- Remember to try the [latest WIP build](https://github.com/SabreTools/MPF/releases/tag/rolling) to see if the issue has already been addressed.
|
||||
- Is it copy protection related? If so, report the issue [here](https://github.com/SabreTools/BinaryObjectScanner/issues) instead.
|
||||
- Check multiple discs to help narrow down the issue
|
||||
- Check the Options to see if changing any of those affects your issue.
|
||||
|
||||
@@ -25,8 +25,7 @@ What version are you using?
|
||||
**Build**
|
||||
What runtime version are you using?
|
||||
|
||||
- [ ] .NET 6.0 running on (Operating System)
|
||||
- [ ] .NET 8.0 running on (Operating System)
|
||||
- [ ] .NET 10 running on (Operating System)
|
||||
|
||||
**Describe the issue**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
59
.github/workflows/build_and_test.yml
vendored
Normal file
59
.github/workflows/build_and_test.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@v1.3.1
|
||||
with:
|
||||
dotnet: false
|
||||
|
||||
- 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
|
||||
50
.github/workflows/build_check.yml
vendored
50
.github/workflows/build_check.yml
vendored
@@ -1,50 +0,0 @@
|
||||
name: MPF Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
project: [MPF.Check]
|
||||
runtime: [win-x86, win-x64, linux-x64, osx-x64] #[win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
|
||||
framework: [net8.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build
|
||||
run: dotnet publish ${{ matrix.project }}/${{ matrix.project }}.csproj -f ${{ matrix.framework }} -r ${{ matrix.runtime }} -c Debug --self-contained true --version-suffix ${{ github.sha }} ${{ (startsWith(matrix.framework, 'net5') || startsWith(matrix.framework, 'net6') || startsWith(matrix.framework, 'net7') || startsWith(matrix.framework, 'net8')) && '-p:PublishSingleFile=true' || ''}}
|
||||
|
||||
- name: Archive build
|
||||
run: zip -r ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug.zip ${{ matrix.project }}/bin/Debug/${{ matrix.framework }}/${{ matrix.runtime }}/publish/
|
||||
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug
|
||||
path: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug.zip
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug.zip
|
||||
body: 'Last built commit: ${{ github.sha }}'
|
||||
name: 'Rolling Release'
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
64
.github/workflows/build_ui.yml
vendored
64
.github/workflows/build_ui.yml
vendored
@@ -1,64 +0,0 @@
|
||||
name: MPF UI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
project: [MPF.UI]
|
||||
runtime: [win-x86, win-x64]
|
||||
framework: [net8.0-windows] #[net40, net452, net472, net48, netcoreapp3.1, net5.0-windows, net6.0-windows, net7.0-windows, net8.0-windows]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build
|
||||
run: dotnet publish ${{ matrix.project }}/${{ matrix.project }}.csproj -f ${{ matrix.framework }} -r ${{ matrix.runtime }} -c Debug --self-contained true --version-suffix ${{ github.sha }} ${{ (startsWith(matrix.framework, 'net5') || startsWith(matrix.framework, 'net6') || startsWith(matrix.framework, 'net7') || startsWith(matrix.framework, 'net8')) && '-p:PublishSingleFile=true' || ''}}
|
||||
|
||||
- name: Bundle DiscImageCreator
|
||||
run: |
|
||||
wget https://github.com/user-attachments/files/15521936/DiscImageCreator_20240601.zip
|
||||
unzip -u DiscImageCreator_20240601.zip
|
||||
mkdir -p MPF.UI/bin/Debug/${{ matrix.framework }}/${{ matrix.runtime }}/publish/Programs/Creator
|
||||
mv Release_ANSI/* MPF.UI/bin/Debug/${{ matrix.framework }}/${{ matrix.runtime }}/publish/Programs/Creator/
|
||||
|
||||
- name: Bundle Redumper
|
||||
run: |
|
||||
wget https://github.com/superg/redumper/releases/download/build_371/redumper-2024.05.27_build371-win64.zip
|
||||
unzip redumper-2024.05.27_build371-win64.zip
|
||||
mkdir -p MPF.UI/bin/Debug/${{ matrix.framework }}/${{ matrix.runtime }}/publish/Programs/Redumper
|
||||
mv redumper-2024.05.27_build371-win64/bin/redumper.exe MPF.UI/bin/Debug/${{ matrix.framework }}/${{ matrix.runtime }}/publish/Programs/Redumper/
|
||||
|
||||
- name: Archive build
|
||||
run: zip -r ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug.zip ${{ matrix.project }}/bin/Debug/${{ matrix.framework }}/${{ matrix.runtime }}/publish/
|
||||
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug
|
||||
path: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug.zip
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_debug.zip
|
||||
body: 'Last built commit: ${{ github.sha }}'
|
||||
name: 'Rolling Release'
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
36
.github/workflows/check_pr.yml
vendored
36
.github/workflows/check_pr.yml
vendored
@@ -3,21 +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: 8.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 --no-restore
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Test
|
||||
run: dotnet test --no-restore --verbosity normal
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
|
||||
- name: Test
|
||||
run: dotnet test
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -68,7 +68,6 @@ artifacts/
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
|
||||
0
.gitmodules
vendored
0
.gitmodules
vendored
32
.vscode/launch.json
vendored
32
.vscode/launch.json
vendored
@@ -5,12 +5,12 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (console)",
|
||||
"name": ".NET Core Launch (Check)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/MPF.Check/bin/Debug/net8.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
|
||||
@@ -18,6 +18,34 @@
|
||||
"stopAtEntry": false,
|
||||
"justMyCode": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Launch (CLI)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"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
|
||||
"console": "internalConsole",
|
||||
"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",
|
||||
|
||||
841
CHANGELIST.md
841
CHANGELIST.md
File diff suppressed because it is too large
Load Diff
333
MPF.CLI/Features/BaseFeature.cs
Normal file
333
MPF.CLI/Features/BaseFeature.cs
Normal file
@@ -0,0 +1,333 @@
|
||||
|
||||
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
|
||||
Options.InternalProgram = InternalProgram.NONE;
|
||||
|
||||
// Protection Scanning Options
|
||||
Options.Processing.ProtectionScanning.ScanForProtection = false;
|
||||
Options.Processing.ProtectionScanning.ScanArchivesForProtection = true;
|
||||
Options.Processing.ProtectionScanning.IncludeDebugProtectionInformation = false;
|
||||
Options.Processing.ProtectionScanning.HideDriveLetters = false;
|
||||
|
||||
// Redump Login Information
|
||||
Options.Processing.Login.PullAllInformation = false;
|
||||
Options.Processing.Login.RedumpUsername = null;
|
||||
Options.Processing.Login.RedumpPassword = null;
|
||||
Options.Processing.Login.RetrieveMatchInformation = true;
|
||||
|
||||
// Media Information
|
||||
Options.Processing.MediaInformation.AddPlaceholders = true;
|
||||
|
||||
// Post-Information Options
|
||||
Options.Processing.AddFilenameSuffix = false;
|
||||
Options.Processing.CreateIRDAfterDumping = false;
|
||||
Options.Processing.OutputSubmissionJSON = false;
|
||||
Options.Processing.IncludeArtifacts = false;
|
||||
Options.Processing.CompressLogFiles = false;
|
||||
Options.Processing.LogCompression = LogCompression.DeflateMaximum;
|
||||
Options.Processing.DeleteUnnecessaryFiles = false;
|
||||
|
||||
}
|
||||
|
||||
/// <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.Processing.Login.RetrieveMatchInformation
|
||||
&& !string.IsNullOrEmpty(Options.Processing.Login.RedumpUsername)
|
||||
&& !string.IsNullOrEmpty(Options.Processing.Login.RedumpPassword))
|
||||
{
|
||||
bool? validated = RedumpClient.ValidateCredentials(Options.Processing.Login.RedumpUsername!, Options.Processing.Login.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.Dumping.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.Dumping.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.Dumping.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.Dumping.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.Dumping.DefaultOutputPath is not null)
|
||||
FilePath = Path.Combine(Options.Dumping.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(processUserInfo: ProcessUserInfo)
|
||||
.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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines how user information is processed, if at all
|
||||
/// </summary>
|
||||
/// <param name="options">Options set that may impact processing</params>
|
||||
/// <param name="info">Submission info that may be overwritten</param>
|
||||
/// <returns>True for successful updating, false or null otherwise</returns>
|
||||
public bool? ProcessUserInfo(Options? options, ref SubmissionInfo? submissionInfo)
|
||||
{
|
||||
// TODO: Somehow use the GUI strings here instead of hardcoding English
|
||||
if (options?.Processing?.ShowDiscEjectReminder == true)
|
||||
Console.WriteLine("It is now safe to eject the disc");
|
||||
|
||||
// TODO: Implement some sort of CLI-based processing of user information
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
196
MPF.CLI/Features/InteractiveFeature.cs
Normal file
196
MPF.CLI/Features/InteractiveFeature.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.CLI.Features
|
||||
{
|
||||
internal sealed class InteractiveFeature : BaseFeature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "interactive";
|
||||
|
||||
private static readonly string[] _flags = ["i", "interactive"];
|
||||
|
||||
private const string _description = "Enable interactive mode";
|
||||
|
||||
#endregion
|
||||
|
||||
public InteractiveFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessArgs(string[] args, int index)
|
||||
{
|
||||
// Cache all args as inputs
|
||||
for (int i = 1; i < args.Length; i++)
|
||||
{
|
||||
Inputs.Add(args[i]);
|
||||
}
|
||||
|
||||
// Read the options from config, if possible
|
||||
Options = OptionsLoader.LoadFromConfig();
|
||||
|
||||
// Create return values
|
||||
MediaType = SabreTools.RedumpLib.Data.MediaType.NONE;
|
||||
string defaultFileName = $"track_{DateTime.Now:yyyyMMdd-HHmm}";
|
||||
#if NET20 || NET35
|
||||
FilePath = Path.Combine(Options.Dumping.DefaultOutputPath ?? "ISO", Path.Combine(defaultFileName, $"{defaultFileName}.bin"));
|
||||
#else
|
||||
FilePath = Path.Combine(Options.Dumping.DefaultOutputPath ?? "ISO", defaultFileName, $"{defaultFileName}.bin");
|
||||
#endif
|
||||
System = Options.Dumping.DefaultSystem;
|
||||
|
||||
// Create state values
|
||||
string? result;
|
||||
|
||||
root:
|
||||
Console.Clear();
|
||||
Console.WriteLine("MPF.CLI Interactive Mode - Main Menu");
|
||||
Console.WriteLine("-------------------------");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"1) Set system (Currently '{System}')");
|
||||
Console.WriteLine($"2) Set dumping program (Currently '{Options.InternalProgram}')");
|
||||
Console.WriteLine($"3) Set media type (Currently '{MediaType}')");
|
||||
Console.WriteLine($"4) Set device path (Currently '{DevicePath}')");
|
||||
Console.WriteLine($"5) Set mounted path (Currently '{MountedPath}')");
|
||||
Console.WriteLine($"6) Set file path (Currently '{FilePath}')");
|
||||
Console.WriteLine($"7) Set override speed (Currently '{DriveSpeed}')");
|
||||
Console.WriteLine($"8) Set custom parameters (Currently '{CustomParams}')");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Q) Exit the program");
|
||||
Console.WriteLine($"X) Start dumping");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
switch (result)
|
||||
{
|
||||
case "1":
|
||||
goto system;
|
||||
case "2":
|
||||
goto dumpingProgram;
|
||||
case "3":
|
||||
goto mediaType;
|
||||
case "4":
|
||||
goto devicePath;
|
||||
case "5":
|
||||
goto mountedPath;
|
||||
case "6":
|
||||
goto filePath;
|
||||
case "7":
|
||||
goto overrideSpeed;
|
||||
case "8":
|
||||
goto customParams;
|
||||
|
||||
case "q":
|
||||
case "Q":
|
||||
Environment.Exit(0);
|
||||
break;
|
||||
case "x":
|
||||
case "X":
|
||||
Console.Clear();
|
||||
goto exit;
|
||||
case "z":
|
||||
case "Z":
|
||||
Console.WriteLine("It is pitch black. You are likely to be eaten by a grue.");
|
||||
Console.Write("> ");
|
||||
Console.ReadLine();
|
||||
goto root;
|
||||
default:
|
||||
Console.WriteLine($"Invalid selection: {result}");
|
||||
Console.ReadLine();
|
||||
goto root;
|
||||
}
|
||||
|
||||
system:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("For possible inputs, use the List Systems commandline option");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the system and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
System = result.ToRedumpSystem();
|
||||
goto root;
|
||||
|
||||
dumpingProgram:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Options:");
|
||||
Console.WriteLine($"{InternalProgram.Redumper.ToString().ToLowerInvariant(),-15} => {InternalProgram.Redumper.LongName()}");
|
||||
Console.WriteLine($"{InternalProgram.DiscImageCreator.ToString().ToLowerInvariant(),-15} => {InternalProgram.DiscImageCreator.LongName()}");
|
||||
Console.WriteLine($"{InternalProgram.Aaru.ToString().ToLowerInvariant(),-15} => {InternalProgram.Aaru.LongName()}");
|
||||
// Console.WriteLine($"{InternalProgram.Dreamdump.ToString().ToLowerInvariant(),-15} => {InternalProgram.Dreamdump.LongName()}");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the dumping program and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
Options.InternalProgram = result.ToInternalProgram();
|
||||
goto root;
|
||||
|
||||
mediaType:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("For possible inputs, use the List Media commandline option");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the media type and press Enter:");
|
||||
Console.Write("> ");
|
||||
result = Console.ReadLine();
|
||||
MediaType = OptionsLoader.ToMediaType(result);
|
||||
goto root;
|
||||
|
||||
devicePath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the device path and press Enter:");
|
||||
Console.Write("> ");
|
||||
DevicePath = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
mountedPath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the mounted path and press Enter:");
|
||||
Console.Write("> ");
|
||||
MountedPath = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
filePath:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the file path and press Enter:");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
if (!string.IsNullOrEmpty(result))
|
||||
result = Path.GetFullPath(result!);
|
||||
|
||||
FilePath = result;
|
||||
goto root;
|
||||
|
||||
overrideSpeed:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the override speed and press Enter:");
|
||||
Console.Write("> ");
|
||||
|
||||
result = Console.ReadLine();
|
||||
if (!int.TryParse(result, out int speed))
|
||||
speed = -1;
|
||||
|
||||
DriveSpeed = speed;
|
||||
goto root;
|
||||
|
||||
customParams:
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Input the custom parameters and press Enter:");
|
||||
Console.Write("> ");
|
||||
CustomParams = Console.ReadLine();
|
||||
goto root;
|
||||
|
||||
exit:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
115
MPF.CLI/Features/MainFeature.cs
Normal file
115
MPF.CLI/Features/MainFeature.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
using MPF.Frontend;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.CLI.Features
|
||||
{
|
||||
internal sealed class MainFeature : BaseFeature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "main";
|
||||
|
||||
/// <remarks>Flags are unused</remarks>
|
||||
private static readonly string[] _flags = [];
|
||||
|
||||
/// <remarks>Description is unused</remarks>
|
||||
private const string _description = "";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inputs
|
||||
|
||||
private const string _customName = "custom";
|
||||
internal readonly StringInput CustomInput = new(_customName, ["-c", "--custom"], "Custom parameters to use");
|
||||
|
||||
private const string _deviceName = "device";
|
||||
internal readonly StringInput DeviceInput = new(_deviceName, ["-d", "--device"], "Physical drive path (Required if no custom parameters set)");
|
||||
|
||||
private const string _fileName = "file";
|
||||
internal readonly StringInput FileInput = new(_fileName, ["-f", "--file"], "Output file path (Required if no custom parameters set)");
|
||||
|
||||
private const string _mediaTypeName = "media-type";
|
||||
internal readonly StringInput MediaTypeInput = new(_mediaTypeName, ["-t", "--mediatype"], "Set media type for dumping (Required for DIC)");
|
||||
|
||||
private const string _mountedName = "mounted";
|
||||
internal readonly StringInput MountedInput = new(_mountedName, ["-m", "--mounted"], "Mounted filesystem path for additional checks");
|
||||
|
||||
private const string _speedName = "speed";
|
||||
internal readonly Int32Input SpeedInput = new(_speedName, ["-s", "--speed"], "Override default dumping speed");
|
||||
|
||||
private const string _useName = "use";
|
||||
internal readonly StringInput UseInput = new(_useName, ["-u", "--use"], "Override configured dumping program name");
|
||||
|
||||
#endregion
|
||||
|
||||
public MainFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
Add(UseInput);
|
||||
Add(MediaTypeInput);
|
||||
Add(DeviceInput);
|
||||
Add(MountedInput);
|
||||
Add(FileInput);
|
||||
Add(SpeedInput);
|
||||
Add(CustomInput);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessArgs(string[] args, int index)
|
||||
{
|
||||
// If we have no arguments, just return
|
||||
if (args is null || args.Length == 0)
|
||||
return true;
|
||||
|
||||
// Read the options from config, if possible
|
||||
Options = OptionsLoader.LoadFromConfig();
|
||||
|
||||
// The first argument is the system type
|
||||
System = args[0].Trim('"').ToRedumpSystem();
|
||||
|
||||
// Loop through the arguments and parse out values
|
||||
for (index = 1; index < args.Length; index++)
|
||||
{
|
||||
// Use specific program
|
||||
if (UseInput.ProcessInput(args, ref index))
|
||||
Options.InternalProgram = UseInput.Value.ToInternalProgram();
|
||||
|
||||
// Set a media type
|
||||
else if (MediaTypeInput.ProcessInput(args, ref index))
|
||||
MediaType = OptionsLoader.ToMediaType(MediaTypeInput.Value?.Trim('"'));
|
||||
|
||||
// Use a device path
|
||||
else if (DeviceInput.ProcessInput(args, ref index))
|
||||
DevicePath = DeviceInput.Value;
|
||||
|
||||
// Use a mounted path for physical checks
|
||||
else if (MountedInput.ProcessInput(args, ref index))
|
||||
MountedPath = MountedInput.Value;
|
||||
|
||||
// Use a file path
|
||||
else if (FileInput.ProcessInput(args, ref index))
|
||||
FilePath = FileInput.Value;
|
||||
|
||||
// Set an override speed
|
||||
else if (SpeedInput.ProcessInput(args, ref index))
|
||||
DriveSpeed = SpeedInput.Value;
|
||||
|
||||
// Use a custom parameters
|
||||
else if (CustomInput.ProcessInput(args, ref index))
|
||||
CustomParams = CustomInput.Value;
|
||||
|
||||
// Default, add to inputs
|
||||
else
|
||||
Inputs.Add(args[index]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
50
MPF.CLI/MPF.CLI.csproj
Normal file
50
MPF.CLI/MPF.CLI.csproj
Normal file
@@ -0,0 +1,50 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<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>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<NoWarn>NU1902;NU1903</NoWarn>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Title>MPF CLI</Title>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Description>CLI frontend for various dumping programs</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2019-2025</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Support All Frameworks -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net4`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<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`)) 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;net10.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MPF.Frontend\MPF.Frontend.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
167
MPF.CLI/Program.cs
Normal file
167
MPF.CLI/Program.cs
Normal file
@@ -0,0 +1,167 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if NET40
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using MPF.CLI.Features;
|
||||
using MPF.Frontend.Features;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.CommandLine;
|
||||
using SabreTools.CommandLine.Features;
|
||||
|
||||
namespace MPF.CLI
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Load options from the config file
|
||||
var options = OptionsLoader.LoadFromConfig();
|
||||
if (options.FirstRun)
|
||||
{
|
||||
// Reset first run
|
||||
options.FirstRun = false;
|
||||
OptionsLoader.SaveToConfig(options);
|
||||
|
||||
// Display non-error message
|
||||
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
|
||||
var topLevel = commandSet.GetTopLevel(featureName);
|
||||
switch (topLevel)
|
||||
{
|
||||
// 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;
|
||||
|
||||
// Interactive Mode
|
||||
case InteractiveFeature interactive:
|
||||
if (interactive.Options.CheckForUpdatesOnStartup)
|
||||
CheckForUpdates();
|
||||
|
||||
if (!interactive.ProcessArgs(args, 0))
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!interactive.Execute())
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Default Behavior
|
||||
default:
|
||||
if (mainFeature.Options.CheckForUpdatesOnStartup)
|
||||
CheckForUpdates();
|
||||
|
||||
if (!mainFeature.ProcessArgs(args, 0))
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mainFeature.Execute())
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check for available updates
|
||||
/// </summary>
|
||||
private static void CheckForUpdates()
|
||||
{
|
||||
FrontendTool.CheckForNewVersion(out bool different, out string message, out string? url);
|
||||
if (url is null)
|
||||
message = $"An exception occurred while checking for remote versions:{Environment.NewLine}{message}";
|
||||
|
||||
Console.WriteLine(message);
|
||||
if (different && url is not null)
|
||||
Console.WriteLine($"Update URL: {url}");
|
||||
else if (!different && url is not null)
|
||||
Console.WriteLine("You have the newest version!");
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the command set for the program
|
||||
/// </summary>
|
||||
private static CommandSet CreateCommands(MainFeature mainFeature)
|
||||
{
|
||||
List<string> header = [
|
||||
"MPF.CLI [standalone|system] [options] <path> ...",
|
||||
string.Empty,
|
||||
];
|
||||
|
||||
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,
|
||||
|
||||
"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,
|
||||
|
||||
"Mounted filesystem path is only recommended on OSes that require block",
|
||||
"device dumping, usually Linux and macOS.",
|
||||
string.Empty,
|
||||
];
|
||||
|
||||
var commandSet = new CommandSet(header, footer);
|
||||
|
||||
// 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());
|
||||
|
||||
// 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);
|
||||
|
||||
return commandSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
204
MPF.Check/Features/BaseFeature.cs
Normal file
204
MPF.Check/Features/BaseFeature.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
|
||||
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
|
||||
Options.InternalProgram = InternalProgram.NONE;
|
||||
|
||||
// Protection Scanning Options
|
||||
Options.Processing.ProtectionScanning.ScanForProtection = false;
|
||||
Options.Processing.ProtectionScanning.ScanArchivesForProtection = true;
|
||||
Options.Processing.ProtectionScanning.IncludeDebugProtectionInformation = false;
|
||||
Options.Processing.ProtectionScanning.HideDriveLetters = false;
|
||||
|
||||
// Redump Login Information
|
||||
Options.Processing.Login.PullAllInformation = false;
|
||||
Options.Processing.Login.RedumpUsername = null;
|
||||
Options.Processing.Login.RedumpPassword = null;
|
||||
Options.Processing.Login.RetrieveMatchInformation = true;
|
||||
|
||||
// Media Information
|
||||
Options.Processing.MediaInformation.AddPlaceholders = true;
|
||||
|
||||
// Post-Information Options
|
||||
Options.Processing.AddFilenameSuffix = false;
|
||||
Options.Processing.CreateIRDAfterDumping = false;
|
||||
Options.Processing.OutputSubmissionJSON = false;
|
||||
Options.Processing.IncludeArtifacts = false;
|
||||
Options.Processing.CompressLogFiles = false;
|
||||
Options.Processing.LogCompression = LogCompression.DeflateMaximum;
|
||||
Options.Processing.DeleteUnnecessaryFiles = false;
|
||||
}
|
||||
|
||||
/// <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.Processing.Login.RetrieveMatchInformation
|
||||
&& !string.IsNullOrEmpty(Options.Processing.Login.RedumpUsername)
|
||||
&& !string.IsNullOrEmpty(Options.Processing.Login.RedumpPassword))
|
||||
{
|
||||
bool? validated = RedumpClient.ValidateCredentials(Options.Processing.Login.RedumpUsername!, Options.Processing.Login.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(processUserInfo: ProcessUserInfo, 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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines how user information is processed, if at all
|
||||
/// </summary>
|
||||
/// <param name="options">Options set that may impact processing</params>
|
||||
/// <param name="info">Submission info that may be overwritten</param>
|
||||
/// <returns>True for successful updating, false or null otherwise</returns>
|
||||
public bool? ProcessUserInfo(Options? options, ref SubmissionInfo? submissionInfo)
|
||||
{
|
||||
// TODO: Somehow use the GUI strings here instead of hardcoding English
|
||||
if (options?.Processing?.ShowDiscEjectReminder == true)
|
||||
Console.WriteLine("It is now safe to eject the disc");
|
||||
|
||||
// TODO: Implement some sort of CLI-based processing of user information
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
289
MPF.Check/Features/InteractiveFeature.cs
Normal file
289
MPF.Check/Features/InteractiveFeature.cs
Normal file
@@ -0,0 +1,289 @@
|
||||
|
||||
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
|
||||
Options.InternalProgram = InternalProgram.NONE;
|
||||
|
||||
// Protection Scanning Options
|
||||
Options.Processing.ProtectionScanning.ScanForProtection = false;
|
||||
Options.Processing.ProtectionScanning.ScanArchivesForProtection = true;
|
||||
Options.Processing.ProtectionScanning.IncludeDebugProtectionInformation = false;
|
||||
Options.Processing.ProtectionScanning.HideDriveLetters = false;
|
||||
|
||||
// Redump Login Information
|
||||
Options.Processing.Login.PullAllInformation = false;
|
||||
Options.Processing.Login.RedumpUsername = null;
|
||||
Options.Processing.Login.RedumpPassword = null;
|
||||
Options.Processing.Login.RetrieveMatchInformation = true;
|
||||
|
||||
// Media Information
|
||||
Options.Processing.MediaInformation.AddPlaceholders = true;
|
||||
|
||||
// Post-Information Options
|
||||
Options.Processing.AddFilenameSuffix = false;
|
||||
Options.Processing.CreateIRDAfterDumping = false;
|
||||
Options.Processing.OutputSubmissionJSON = false;
|
||||
Options.Processing.IncludeArtifacts = false;
|
||||
Options.Processing.CompressLogFiles = false;
|
||||
Options.Processing.LogCompression = LogCompression.DeflateMaximum;
|
||||
Options.Processing.DeleteUnnecessaryFiles = false;
|
||||
}
|
||||
|
||||
// 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.Processing.MediaInformation.AddPlaceholders}')");
|
||||
Console.WriteLine($"5) Create IRD (Currently '{Options.Processing.CreateIRDAfterDumping}')");
|
||||
Console.WriteLine($"6) Attempt Redump matches (Currently '{Options.Processing.Login.RetrieveMatchInformation}')");
|
||||
Console.WriteLine($"7) Redump credentials (Currently '{Options.Processing.Login.RedumpUsername}')");
|
||||
Console.WriteLine($"8) Pull all information (Currently '{Options.Processing.Login.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.Processing.AddFilenameSuffix}')");
|
||||
Console.WriteLine($"F) Output submission JSON (Currently '{Options.Processing.OutputSubmissionJSON}')");
|
||||
Console.WriteLine($"G) Include JSON artifacts (Currently '{Options.Processing.IncludeArtifacts}')");
|
||||
Console.WriteLine($"H) Compress logs (Currently '{Options.Processing.CompressLogFiles}')");
|
||||
Console.WriteLine($"I) Log compression (Currently '{Options.Processing.LogCompression.LongName()}')");
|
||||
Console.WriteLine($"J) Delete unnecessary files (Currently '{Options.Processing.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.Processing.MediaInformation.AddPlaceholders = !Options.Processing.MediaInformation.AddPlaceholders;
|
||||
goto root;
|
||||
case "5":
|
||||
Options.Processing.CreateIRDAfterDumping = !Options.Processing.CreateIRDAfterDumping;
|
||||
goto root;
|
||||
case "6":
|
||||
Options.Processing.Login.RetrieveMatchInformation = !Options.Processing.Login.RetrieveMatchInformation;
|
||||
goto root;
|
||||
case "7":
|
||||
goto redumpCredentials;
|
||||
case "8":
|
||||
Options.Processing.Login.PullAllInformation = !Options.Processing.Login.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.Processing.AddFilenameSuffix = !Options.Processing.AddFilenameSuffix;
|
||||
goto root;
|
||||
case "f":
|
||||
case "F":
|
||||
Options.Processing.OutputSubmissionJSON = !Options.Processing.OutputSubmissionJSON;
|
||||
goto root;
|
||||
case "g":
|
||||
case "G":
|
||||
Options.Processing.IncludeArtifacts = !Options.Processing.IncludeArtifacts;
|
||||
goto root;
|
||||
case "h":
|
||||
case "H":
|
||||
Options.Processing.CompressLogFiles = !Options.Processing.CompressLogFiles;
|
||||
goto root;
|
||||
case "i":
|
||||
case "I":
|
||||
goto logCompression;
|
||||
case "j":
|
||||
case "J":
|
||||
Options.Processing.DeleteUnnecessaryFiles = !Options.Processing.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.Processing.Login.RedumpUsername = Console.ReadLine();
|
||||
|
||||
Console.WriteLine("Enter your Redump password (hidden) and press Enter:");
|
||||
Console.Write("> ");
|
||||
Options.Processing.Login.RedumpPassword = string.Empty;
|
||||
while (true)
|
||||
{
|
||||
var key = Console.ReadKey(true);
|
||||
if (key.Key == ConsoleKey.Enter)
|
||||
break;
|
||||
|
||||
Options.Processing.Login.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.Processing.LogCompression = result.ToLogCompression();
|
||||
goto root;
|
||||
|
||||
exit:
|
||||
// Now deal with the complex options
|
||||
Options.Processing.ProtectionScanning.ScanForProtection = scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.Processing.ProtectionScanning.ScanArchivesForProtection = enableArchives && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.Processing.ProtectionScanning.IncludeDebugProtectionInformation = enableDebug && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.Processing.ProtectionScanning.HideDriveLetters = hideDriveLetters && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => Inputs.Count > 0;
|
||||
}
|
||||
}
|
||||
273
MPF.Check/Features/MainFeature.cs
Normal file
273
MPF.Check/Features/MainFeature.cs
Normal file
@@ -0,0 +1,273 @@
|
||||
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
|
||||
Options.InternalProgram = InternalProgram.NONE;
|
||||
|
||||
// Protection Scanning Options
|
||||
Options.Processing.ProtectionScanning.ScanForProtection = false;
|
||||
Options.Processing.ProtectionScanning.ScanArchivesForProtection = true;
|
||||
Options.Processing.ProtectionScanning.IncludeDebugProtectionInformation = false;
|
||||
Options.Processing.ProtectionScanning.HideDriveLetters = false;
|
||||
|
||||
// Redump Login Information
|
||||
Options.Processing.Login.PullAllInformation = false;
|
||||
Options.Processing.Login.RedumpUsername = null;
|
||||
Options.Processing.Login.RedumpPassword = null;
|
||||
Options.Processing.Login.RetrieveMatchInformation = true;
|
||||
|
||||
// Media Information
|
||||
Options.Processing.MediaInformation.AddPlaceholders = true;
|
||||
|
||||
// Post-Information Options
|
||||
Options.Processing.AddFilenameSuffix = false;
|
||||
Options.Processing.CreateIRDAfterDumping = false;
|
||||
Options.Processing.OutputSubmissionJSON = false;
|
||||
Options.Processing.IncludeArtifacts = false;
|
||||
Options.Processing.CompressLogFiles = false;
|
||||
Options.Processing.LogCompression = LogCompression.DeflateMaximum;
|
||||
Options.Processing.DeleteUnnecessaryFiles = false;
|
||||
}
|
||||
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.Processing.MediaInformation.AddPlaceholders = !Options.Processing.MediaInformation.AddPlaceholders;
|
||||
|
||||
// Create IRD from output files (PS3 only)
|
||||
else if (CreateIrdInput.ProcessInput(args, ref index))
|
||||
Options.Processing.CreateIRDAfterDumping = !Options.Processing.CreateIRDAfterDumping;
|
||||
|
||||
// Set the log compression type (requires compression enabled)
|
||||
else if (LogCompressionInput.ProcessInput(args, ref index))
|
||||
Options.Processing.LogCompression = LogCompressionInput.Value.ToLogCompression();
|
||||
|
||||
// Retrieve Redump match information
|
||||
else if (NoRetrieveInput.ProcessInput(args, ref index))
|
||||
Options.Processing.Login.RetrieveMatchInformation = !Options.Processing.Login.RetrieveMatchInformation;
|
||||
|
||||
// Redump login
|
||||
else if (args[index].StartsWith("-c=") || args[index].StartsWith("--credentials="))
|
||||
{
|
||||
string[] credentials = args[index].Split('=')[1].Split(';');
|
||||
Options.Processing.Login.RedumpUsername = credentials[0];
|
||||
Options.Processing.Login.RedumpPassword = credentials[1];
|
||||
}
|
||||
else if (args[index] == "-c" || args[index] == "--credentials")
|
||||
{
|
||||
Options.Processing.Login.RedumpUsername = args[index + 1];
|
||||
Options.Processing.Login.RedumpPassword = args[index + 2];
|
||||
index += 2;
|
||||
}
|
||||
|
||||
// Redump username
|
||||
else if (UsernameInput.ProcessInput(args, ref index))
|
||||
Options.Processing.Login.RedumpUsername = UsernameInput.Value;
|
||||
|
||||
// Redump password
|
||||
else if (PasswordInput.ProcessInput(args, ref index))
|
||||
Options.Processing.Login.RedumpPassword = PasswordInput.Value;
|
||||
|
||||
// Pull all information (requires Redump login)
|
||||
else if (PullAllInput.ProcessInput(args, ref index))
|
||||
Options.Processing.Login.PullAllInformation = !Options.Processing.Login.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.Processing.AddFilenameSuffix = !Options.Processing.AddFilenameSuffix;
|
||||
|
||||
// Output submission JSON
|
||||
else if (JsonInput.ProcessInput(args, ref index))
|
||||
Options.Processing.OutputSubmissionJSON = !Options.Processing.OutputSubmissionJSON;
|
||||
|
||||
// Include JSON artifacts
|
||||
else if (IncludeArtifactsInput.ProcessInput(args, ref index))
|
||||
Options.Processing.IncludeArtifacts = !Options.Processing.IncludeArtifacts;
|
||||
|
||||
// Compress log and extraneous files
|
||||
else if (ZipInput.ProcessInput(args, ref index))
|
||||
Options.Processing.CompressLogFiles = !Options.Processing.CompressLogFiles;
|
||||
|
||||
// Delete unnecessary files
|
||||
else if (DeleteInput.ProcessInput(args, ref index))
|
||||
Options.Processing.DeleteUnnecessaryFiles = !Options.Processing.DeleteUnnecessaryFiles;
|
||||
|
||||
// Default, add to inputs
|
||||
else
|
||||
Inputs.Add(args[index]);
|
||||
}
|
||||
|
||||
// Now deal with the complex options
|
||||
Options.Processing.ProtectionScanning.ScanForProtection = scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.Processing.ProtectionScanning.ScanArchivesForProtection = enableArchives && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.Processing.ProtectionScanning.IncludeDebugProtectionInformation = enableDebug && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
Options.Processing.ProtectionScanning.HideDriveLetters = hideDriveLetters && scan && !string.IsNullOrEmpty(DevicePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => Inputs.Count > 0;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,50 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
<OutputType>Exe</OutputType>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.2.0</VersionPrefix>
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<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>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<NoWarn>NU1902;NU1903</NoWarn>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Title>MPF Check</Title>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Description>Validator for various dumping programs</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2019-2024</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
<!-- Package Properties -->
|
||||
<Title>MPF Check</Title>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Description>Validator for various dumping programs</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2019-2025</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<!-- Support All Frameworks -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net4`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<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`)) 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;net10.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MPF.Frontend\MPF.Frontend.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MPF.Frontend\MPF.Frontend.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BinaryObjectScanner" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="3.1.13" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.3.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="$(PkgBinaryObjectScanner)\content\**" PackagePath="contentFiles\any\any;content" CopyToOutputDirectory="Always" PackageCopyToOutput="true" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,10 +1,13 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner;
|
||||
using MPF.Frontend;
|
||||
using System.Collections.Generic;
|
||||
#if NET40
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using MPF.Check.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.Check
|
||||
{
|
||||
@@ -12,105 +15,156 @@ namespace MPF.Check
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// 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;
|
||||
|
||||
// Try processing the common arguments
|
||||
(bool success, MediaType mediaType, RedumpSystem? knownSystem, var error) = OptionsLoader.ProcessCommonArguments(args);
|
||||
if (!success)
|
||||
{
|
||||
DisplayHelp(error);
|
||||
return;
|
||||
}
|
||||
// Interactive Mode
|
||||
case InteractiveFeature interactive:
|
||||
if (interactive.Options.CheckForUpdatesOnStartup)
|
||||
CheckForUpdates();
|
||||
|
||||
// Loop through and process options
|
||||
(var options, var seedInfo, var path, int startIndex) = OptionsLoader.LoadFromArguments(args, startIndex: 2);
|
||||
if (options.InternalProgram == InternalProgram.NONE)
|
||||
{
|
||||
DisplayHelp("A program name needs to be provided");
|
||||
return;
|
||||
}
|
||||
if (!interactive.ProcessArgs(args, 0))
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Make new Progress objects
|
||||
var resultProgress = new Progress<ResultEventArgs>();
|
||||
resultProgress.ProgressChanged += ConsoleLogger.ProgressUpdated;
|
||||
var protectionProgress = new Progress<ProtectionProgress>();
|
||||
protectionProgress.ProgressChanged += ConsoleLogger.ProgressUpdated;
|
||||
if (!interactive.VerifyInputs())
|
||||
{
|
||||
Console.Error.WriteLine("At least one input is required");
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate the supplied credentials
|
||||
#if NETFRAMEWORK
|
||||
(bool? _, string? message) = RedumpWebClient.ValidateCredentials(options.RedumpUsername ?? string.Empty, options.RedumpPassword ?? string.Empty);
|
||||
#else
|
||||
(bool? _, string? message) = RedumpHttpClient.ValidateCredentials(options.RedumpUsername ?? string.Empty, options.RedumpPassword ?? string.Empty).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
#endif
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
Console.WriteLine(message);
|
||||
if (!interactive.Execute())
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
break;
|
||||
|
||||
// Get the full file path
|
||||
string filepath = Path.GetFullPath(args[i].Trim('"'));
|
||||
// Default Behavior
|
||||
default:
|
||||
if (mainFeature.Options.CheckForUpdatesOnStartup)
|
||||
CheckForUpdates();
|
||||
|
||||
// Now populate an environment
|
||||
Drive? drive = null;
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
drive = Drive.Create(null, path!);
|
||||
if (!mainFeature.ProcessArgs(args, 0))
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
var env = new DumpEnvironment(options, filepath, drive, knownSystem, mediaType, internalProgram: null, parameters: null);
|
||||
if (!mainFeature.VerifyInputs())
|
||||
{
|
||||
Console.Error.WriteLine("At least one input is required");
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
#if NET40
|
||||
var resultTask = env.VerifyAndSaveDumpOutput(resultProgress, protectionProgress);
|
||||
resultTask.Wait();
|
||||
var result = resultTask.Result;
|
||||
#else
|
||||
var result = env.VerifyAndSaveDumpOutput(resultProgress, protectionProgress).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
#endif
|
||||
Console.WriteLine(result.Message);
|
||||
if (!mainFeature.Execute())
|
||||
{
|
||||
BaseFeature.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display help for MPF.Check
|
||||
/// Check for available updates
|
||||
/// </summary>
|
||||
/// <param name="error">Error string to prefix the help text with</param>
|
||||
private static void DisplayHelp(string? error = null)
|
||||
private static void CheckForUpdates()
|
||||
{
|
||||
if (error != null)
|
||||
Console.WriteLine(error);
|
||||
FrontendTool.CheckForNewVersion(out bool different, out string message, out string? url);
|
||||
if (url is null)
|
||||
message = $"An exception occurred while checking for remote versions:{Environment.NewLine}{message}";
|
||||
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine("MPF.Check.exe <mediatype> <system> [options] </path/to/output.cue/iso> ...");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Standalone Options:");
|
||||
Console.WriteLine("-h, -? Show this help text");
|
||||
Console.WriteLine("-lc, --listcodes List supported comment/content site codes");
|
||||
Console.WriteLine("-lm, --listmedia List supported media types");
|
||||
Console.WriteLine("-ls, --listsystems List supported system types");
|
||||
Console.WriteLine("-lp, --listprograms List supported dumping program outputs");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(message);
|
||||
if (different && url is not null)
|
||||
Console.WriteLine($"Update URL: {url}");
|
||||
else if (!different && url is not null)
|
||||
Console.WriteLine("You have the newest version!");
|
||||
|
||||
Console.WriteLine("Check Options:");
|
||||
var supportedArguments = OptionsLoader.PrintSupportedArguments();
|
||||
foreach (string argument in supportedArguments)
|
||||
{
|
||||
Console.WriteLine(argument);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the command set for the program
|
||||
/// </summary>
|
||||
private static CommandSet CreateCommands(MainFeature mainFeature)
|
||||
{
|
||||
List<string> header = [
|
||||
"MPF.CLI [standalone|system] [options] <path> ...",
|
||||
string.Empty,
|
||||
];
|
||||
|
||||
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,
|
||||
];
|
||||
|
||||
var commandSet = new CommandSet(header, footer);
|
||||
|
||||
// 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());
|
||||
|
||||
// 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);
|
||||
|
||||
return commandSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"profiles": {
|
||||
"MPF.Check": {
|
||||
"commandName": "Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
516
MPF.ExecutionContexts.Test/AaruTests.cs
Normal file
516
MPF.ExecutionContexts.Test/AaruTests.cs
Normal file
@@ -0,0 +1,516 @@
|
||||
using MPF.ExecutionContexts.Aaru;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.ExecutionContexts.Test
|
||||
{
|
||||
public class AaruTests
|
||||
{
|
||||
#region Converters.Extension
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, ".aaruf")]
|
||||
[InlineData(MediaType.CDROM, ".aaruf")]
|
||||
[InlineData(MediaType.GDROM, ".aaruf")]
|
||||
[InlineData(MediaType.DVD, ".aaruf")]
|
||||
[InlineData(MediaType.HDDVD, ".aaruf")]
|
||||
[InlineData(MediaType.BluRay, ".aaruf")]
|
||||
[InlineData(MediaType.FloppyDisk, ".aaruf")]
|
||||
[InlineData(MediaType.HardDisk, ".aaruf")]
|
||||
[InlineData(MediaType.ApertureCard, ".aaruf")]
|
||||
public void ExtensionTest(MediaType? type, string expected)
|
||||
{
|
||||
string actual = Converters.Extension(type);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Default Values
|
||||
|
||||
private static readonly BaseDumpSettings AllOptions = new DumpSettings()
|
||||
{
|
||||
EnableDebug = true,
|
||||
EnableVerbose = true,
|
||||
ForceDumping = true,
|
||||
RereadCount = 1000,
|
||||
StripPersonalData = true,
|
||||
};
|
||||
|
||||
[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 --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 --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 --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,
|
||||
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 Archive Family
|
||||
|
||||
[Theory]
|
||||
[InlineData("arc info filename.bin")]
|
||||
[InlineData("arc info \"filename.bin\"")]
|
||||
[InlineData("archive info filename.bin")]
|
||||
[InlineData("archive info \"filename.bin\"")]
|
||||
public void ArchiveInfoTest(string parameters)
|
||||
{
|
||||
string? expected = "archive info \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Database Family
|
||||
|
||||
[Theory]
|
||||
[InlineData("db stats")]
|
||||
[InlineData("database stats")]
|
||||
public void DatabaseStatsTest(string parameters)
|
||||
{
|
||||
string? expected = "database stats";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("db update --clear --clear-all")]
|
||||
[InlineData("db update --clear true --clear-all true")]
|
||||
[InlineData("database update --clear --clear-all")]
|
||||
[InlineData("database update --clear true --clear-all true")]
|
||||
public void DatabaseUpdateTest(string parameters)
|
||||
{
|
||||
string? expected = "database update --clear True --clear-all True";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Device Family
|
||||
|
||||
[Theory]
|
||||
[InlineData("dev info -w prefix filename.bin")]
|
||||
[InlineData("dev info --output-prefix prefix filename.bin")]
|
||||
[InlineData("device info -w prefix filename.bin")]
|
||||
[InlineData("device info --output-prefix prefix filename.bin")]
|
||||
public void DeviceInfoTest(string parameters)
|
||||
{
|
||||
string? expected = "device info --output-prefix \"prefix\" filename.bin";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("dev list localhost")]
|
||||
[InlineData("device list localhost")]
|
||||
public void DeviceListTest(string parameters)
|
||||
{
|
||||
string? expected = "device list \"localhost\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("dev report -t filename.bin")]
|
||||
[InlineData("dev report -t true filename.bin")]
|
||||
[InlineData("dev report --trap-disc filename.bin")]
|
||||
[InlineData("dev report --trap-disc true filename.bin")]
|
||||
[InlineData("device report -t filename.bin")]
|
||||
[InlineData("device report -t true filename.bin")]
|
||||
[InlineData("device report --trap-disc filename.bin")]
|
||||
[InlineData("device report --trap-disc true filename.bin")]
|
||||
public void DeviceReportTest(string parameters)
|
||||
{
|
||||
string? expected = "device report --trap-disc True filename.bin";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Filesystem Family
|
||||
|
||||
[Theory]
|
||||
[InlineData("fi extract -e enc -x -n ns -O opts input output")]
|
||||
[InlineData("fi extract -e enc -x true -n ns -O opts input output")]
|
||||
[InlineData("fi extract --encoding enc --xattrs --namespace ns --options opts input output")]
|
||||
[InlineData("fi extract --encoding enc --xattrs true --namespace ns --options opts input output")]
|
||||
[InlineData("fs extract -e enc -x -n ns -O opts input output")]
|
||||
[InlineData("fs extract -e enc -x true -n ns -O opts input output")]
|
||||
[InlineData("fs extract --encoding enc --xattrs --namespace ns --options opts input output")]
|
||||
[InlineData("fs extract --encoding enc --xattrs true --namespace ns --options opts input output")]
|
||||
[InlineData("filesystem extract -e enc -x -n ns -O opts input output")]
|
||||
[InlineData("filesystem extract -e enc -x true -n ns -O opts input output")]
|
||||
[InlineData("filesystem extract --encoding enc --xattrs --namespace ns --options opts input output")]
|
||||
[InlineData("filesystem extract --encoding enc --xattrs true --namespace ns --options opts input output")]
|
||||
public void FilesystemExtractTest(string parameters)
|
||||
{
|
||||
string? expected = "filesystem extract --xattrs True --encoding \"enc\" --namespace \"ns\" --options \"opts\" \"input\" \"output\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("fi info -e enc -x -n ns -O opts input")]
|
||||
[InlineData("fi info -e enc -x true -n ns -O opts input")]
|
||||
[InlineData("fi info --encoding enc --xattrs --namespace ns --options opts input")]
|
||||
[InlineData("fi info --encoding enc --xattrs true --namespace ns --options opts input")]
|
||||
[InlineData("fs info -e enc -x -n ns -O opts input")]
|
||||
[InlineData("fs info -e enc -x true -n ns -O opts input")]
|
||||
[InlineData("fs info --encoding enc --xattrs --namespace ns --options opts input")]
|
||||
[InlineData("fs info --encoding enc --xattrs true --namespace ns --options opts input")]
|
||||
[InlineData("filesystem info -e enc -x -n ns -O opts input")]
|
||||
[InlineData("filesystem info -e enc -x true -n ns -O opts input")]
|
||||
[InlineData("filesystem info --encoding enc --xattrs --namespace ns --options opts input")]
|
||||
[InlineData("filesystem info --encoding enc --xattrs true --namespace ns --options opts input")]
|
||||
public void FilesystemInfoTest(string parameters)
|
||||
{
|
||||
string? expected = "filesystem info --xattrs True --encoding \"enc\" --namespace \"ns\" --options \"opts\" \"input\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("fi ls -e enc -f -l -p input")]
|
||||
[InlineData("fi list -e enc -f -l -p input")]
|
||||
[InlineData("fi ls -e enc -f true -l true -p true input")]
|
||||
[InlineData("fi list -e enc -f true -l true -p true input")]
|
||||
[InlineData("fi ls --encoding enc --filesystems --long-format --partitions input")]
|
||||
[InlineData("fi list --encoding enc --filesystems --long-format --partitions input")]
|
||||
[InlineData("fi ls --encoding enc --filesystems true --long-format true --partitions true input")]
|
||||
[InlineData("fi list --encoding enc --filesystems true --long-format true --partitions true input")]
|
||||
[InlineData("fs ls -e enc -f -l -p input")]
|
||||
[InlineData("fs list -e enc -f -l -p input")]
|
||||
[InlineData("fs ls -e enc -f true -l true -p true input")]
|
||||
[InlineData("fs list -e enc -f true -l true -p true input")]
|
||||
[InlineData("fs ls --encoding enc --filesystems --long-format --partitions input")]
|
||||
[InlineData("fs list --encoding enc --filesystems --long-format --partitions input")]
|
||||
[InlineData("fs ls --encoding enc --filesystems true --long-format true --partitions true input")]
|
||||
[InlineData("fs list --encoding enc --filesystems true --long-format true --partitions true input")]
|
||||
[InlineData("filesystem ls -e enc -f -l -p input")]
|
||||
[InlineData("filesystem list -e enc -f -l -p input")]
|
||||
[InlineData("filesystem ls -e enc -f true -l true -p true input")]
|
||||
[InlineData("filesystem list -e enc -f true -l true -p true input")]
|
||||
[InlineData("filesystem ls --encoding enc --filesystems --long-format --partitions input")]
|
||||
[InlineData("filesystem list --encoding enc --filesystems --long-format --partitions input")]
|
||||
[InlineData("filesystem ls --encoding enc --filesystems true --long-format true --partitions true input")]
|
||||
[InlineData("filesystem list --encoding enc --filesystems true --long-format true --partitions true input")]
|
||||
public void FilesystemListTest(string parameters)
|
||||
{
|
||||
string? expected = "filesystem list --filesystems True --long-format True --partitions True --encoding \"enc\" \"input\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("fi options")]
|
||||
[InlineData("fs options")]
|
||||
[InlineData("filesystem options")]
|
||||
public void FilesystemOptionsTest(string parameters)
|
||||
{
|
||||
string? expected = "filesystem options";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Image Family
|
||||
|
||||
[Theory]
|
||||
[InlineData("i chk -a --crc16 -c --crc64 --fletcher16 --fletcher32 -m -t -s --sha256 --sha384 --sha512 -f -w filename.bin")]
|
||||
[InlineData("i chk -a true --crc16 true -c true --crc64 true --fletcher16 true --fletcher32 true -m true -t true -s true --sha256 true --sha384 true --sha512 true -f true -w true filename.bin")]
|
||||
[InlineData("i chk --adler32 --crc16 --crc32 --crc64 --fletcher16 --fletcher32 --md5 --separated-tracks --sha1 --sha256 --sha384 --sha512 --spamsum --whole-disc filename.bin")]
|
||||
[InlineData("i chk --adler32 true --crc16 true --crc32 true --crc64 true --fletcher16 true --fletcher32 true --md5 true --separated-tracks true --sha1 true --sha256 true --sha384 true --sha512 true --spamsum true --whole-disc true filename.bin")]
|
||||
[InlineData("i checksum -a --crc16 -c --crc64 --fletcher16 --fletcher32 -m -t -s --sha256 --sha384 --sha512 -f -w filename.bin")]
|
||||
[InlineData("i checksum -a true --crc16 true -c true --crc64 true --fletcher16 true --fletcher32 true -m true -t true -s true --sha256 true --sha384 true --sha512 true -f true -w true filename.bin")]
|
||||
[InlineData("i checksum --adler32 --crc16 --crc32 --crc64 --fletcher16 --fletcher32 --md5 --separated-tracks --sha1 --sha256 --sha384 --sha512 --spamsum --whole-disc filename.bin")]
|
||||
[InlineData("i checksum --adler32 true --crc16 true --crc32 true --crc64 true --fletcher16 true --fletcher32 true --md5 true --separated-tracks true --sha1 true --sha256 true --sha384 true --sha512 true --spamsum true --whole-disc true filename.bin")]
|
||||
[InlineData("image chk -a --crc16 -c --crc64 --fletcher16 --fletcher32 -m -t -s --sha256 --sha384 --sha512 -f -w filename.bin")]
|
||||
[InlineData("image chk -a true --crc16 true -c true --crc64 true --fletcher16 true --fletcher32 true -m true -t true -s true --sha256 true --sha384 true --sha512 true -f true -w true filename.bin")]
|
||||
[InlineData("image chk --adler32 --crc16 --crc32 --crc64 --fletcher16 --fletcher32 --md5 --separated-tracks --sha1 --sha256 --sha384 --sha512 --spamsum --whole-disc filename.bin")]
|
||||
[InlineData("image chk --adler32 true --crc16 true --crc32 true --crc64 true --fletcher16 true --fletcher32 true --md5 true --separated-tracks true --sha1 true --sha256 true --sha384 true --sha512 true --spamsum true --whole-disc true filename.bin")]
|
||||
[InlineData("image checksum -a --crc16 -c --crc64 --fletcher16 --fletcher32 -m -t -s --sha256 --sha384 --sha512 -f -w filename.bin")]
|
||||
[InlineData("image checksum -a true --crc16 true -c true --crc64 true --fletcher16 true --fletcher32 true -m true -t true -s true --sha256 true --sha384 true --sha512 true -f true -w true filename.bin")]
|
||||
[InlineData("image checksum --adler32 --crc16 --crc32 --crc64 --fletcher16 --fletcher32 --md5 --separated-tracks --sha1 --sha256 --sha384 --sha512 --spamsum --whole-disc filename.bin")]
|
||||
[InlineData("image checksum --adler32 true --crc16 true --crc32 true --crc64 true --fletcher16 true --fletcher32 true --md5 true --separated-tracks true --sha1 true --sha256 true --sha384 true --sha512 true --spamsum true --whole-disc true filename.bin")]
|
||||
public void ImageChecksumTest(string parameters)
|
||||
{
|
||||
string? expected = "image checksum --adler32 True --crc16 True --crc32 True --crc64 True --fletcher16 True --fletcher32 True --md5 True --separated-tracks True --sha1 True --sha256 True --sha384 True --sha512 True --spamsum True --whole-disc True \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("i cmp input1.bin input2.bin")]
|
||||
[InlineData("i compare input1.bin input2.bin")]
|
||||
[InlineData("image cmp input1.bin input2.bin")]
|
||||
[InlineData("image compare input1.bin input2.bin")]
|
||||
public void ImageCompareTest(string parameters)
|
||||
{
|
||||
string? expected = "image compare \"input1.bin\" \"input2.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("i convert --comments co -c 0 --creator cr --drive-manufacturer dm --drive-model dm --drive-revision dr --drive-serial ds --fix-subchannel --fix-subchannel-crc --fix-subchannel-position -f -p fmt --generate-subchannels -g geo --media-barcode mb --media-lastsequence 0 --media-manufacturer mm --media-model mm --media-partnumber mpn --media-sequence 0 --media-serial ms --media-title mt -O opt -r resume -x cicm input1.bin input2.bin")]
|
||||
[InlineData("i convert --comments co -c 0 --creator cr --drive-manufacturer dm --drive-model dm --drive-revision dr --drive-serial ds --fix-subchannel true --fix-subchannel-crc true --fix-subchannel-position true -f true -p fmt --generate-subchannels true -g geo --media-barcode mb --media-lastsequence 0 --media-manufacturer mm --media-model mm --media-partnumber mpn --media-sequence 0 --media-serial ms --media-title mt -O opt -r resume -x cicm input1.bin input2.bin")]
|
||||
[InlineData("i convert --comments co --count 0 --creator cr --drive-manufacturer dm --drive-model dm --drive-revision dr --drive-serial ds --fix-subchannel --fix-subchannel-crc --fix-subchannel-position --force --format fmt --generate-subchannels --geometry geo --media-barcode mb --media-lastsequence 0 --media-manufacturer mm --media-model mm --media-partnumber mpn --media-sequence 0 --media-serial ms --media-title mt --options opt --resume-file resume --cicm-xml cicm input1.bin input2.bin")]
|
||||
[InlineData("i convert --comments co --count 0 --creator cr --drive-manufacturer dm --drive-model dm --drive-revision dr --drive-serial ds --fix-subchannel true --fix-subchannel-crc true --fix-subchannel-position true --force true --format fmt --generate-subchannels true --geometry geo --media-barcode mb --media-lastsequence 0 --media-manufacturer mm --media-model mm --media-partnumber mpn --media-sequence 0 --media-serial ms --media-title mt --options opt --resume-file resume --cicm-xml cicm input1.bin input2.bin")]
|
||||
[InlineData("image convert --comments co -c 0 --creator cr --drive-manufacturer dm --drive-model dm --drive-revision dr --drive-serial ds --fix-subchannel --fix-subchannel-crc --fix-subchannel-position -f -p fmt --generate-subchannels -g geo --media-barcode mb --media-lastsequence 0 --media-manufacturer mm --media-model mm --media-partnumber mpn --media-sequence 0 --media-serial ms --media-title mt -O opt -r resume -x cicm input1.bin input2.bin")]
|
||||
[InlineData("image convert --comments co -c 0 --creator cr --drive-manufacturer dm --drive-model dm --drive-revision dr --drive-serial ds --fix-subchannel true --fix-subchannel-crc true --fix-subchannel-position true -f true -p fmt --generate-subchannels true -g geo --media-barcode mb --media-lastsequence 0 --media-manufacturer mm --media-model mm --media-partnumber mpn --media-sequence 0 --media-serial ms --media-title mt -O opt -r resume -x cicm input1.bin input2.bin")]
|
||||
[InlineData("image convert --comments co --count 0 --creator cr --drive-manufacturer dm --drive-model dm --drive-revision dr --drive-serial ds --fix-subchannel --fix-subchannel-crc --fix-subchannel-position --force --format fmt --generate-subchannels --geometry geo --media-barcode mb --media-lastsequence 0 --media-manufacturer mm --media-model mm --media-partnumber mpn --media-sequence 0 --media-serial ms --media-title mt --options opt --resume-file resume --cicm-xml cicm input1.bin input2.bin")]
|
||||
[InlineData("image convert --comments co --count 0 --creator cr --drive-manufacturer dm --drive-model dm --drive-revision dr --drive-serial ds --fix-subchannel true --fix-subchannel-crc true --fix-subchannel-position true --force true --format fmt --generate-subchannels true --geometry geo --media-barcode mb --media-lastsequence 0 --media-manufacturer mm --media-model mm --media-partnumber mpn --media-sequence 0 --media-serial ms --media-title mt --options opt --resume-file resume --cicm-xml cicm input1.bin input2.bin")]
|
||||
public void ImageConvertTest(string parameters)
|
||||
{
|
||||
string? expected = "image convert --fix-subchannel True --fix-subchannel-crc True --fix-subchannel-position True --force True --generate-subchannels True --count 0 --media-lastsequence 0 --media-sequence 0 --comments \"co\" --creator \"cr\" --drive-manufacturer \"dm\" --drive-model \"dm\" --drive-revision \"dr\" --drive-serial \"ds\" --format \"fmt\" --geometry \"geo\" --media-barcode \"mb\" --media-manufacturer \"mm\" --media-model \"mm\" --media-partnumber \"mpn\" --media-serial \"ms\" --media-title \"mt\" --options \"opt\" --resume-file \"resume\" --cicm-xml \"cicm\" \"input1.bin\" \"input2.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("i create-sidecar -b 0 -e enc -t filename.bin")]
|
||||
[InlineData("i create-sidecar -b 0 -e enc -t true filename.bin")]
|
||||
[InlineData("i create-sidecar --block-size 0 --encoding enc --tape filename.bin")]
|
||||
[InlineData("i create-sidecar --block-size 0 --encoding enc --tape true filename.bin")]
|
||||
[InlineData("image create-sidecar -b 0 -e enc -t filename.bin")]
|
||||
[InlineData("image create-sidecar -b 0 -e enc -t true filename.bin")]
|
||||
[InlineData("image create-sidecar --block-size 0 --encoding enc --tape filename.bin")]
|
||||
[InlineData("image create-sidecar --block-size 0 --encoding enc --tape true filename.bin")]
|
||||
public void ImageCreateSidecarTest(string parameters)
|
||||
{
|
||||
string? expected = "image create-sidecar --tape True --block-size 0 --encoding \"enc\" \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("i decode -f -l all -p -s 0 filename.bin")]
|
||||
[InlineData("i decode -f true -l all -p true -s 0 filename.bin")]
|
||||
[InlineData("i decode --disk-tags --length all --sector-tags --start 0 filename.bin")]
|
||||
[InlineData("i decode --disk-tags true --length all --sector-tags true --start 0 filename.bin")]
|
||||
[InlineData("image decode -f -l all -p -s 0 filename.bin")]
|
||||
[InlineData("image decode -f true -l all -p true -s 0 filename.bin")]
|
||||
[InlineData("image decode --disk-tags --length all --sector-tags --start 0 filename.bin")]
|
||||
[InlineData("image decode --disk-tags true --length all --sector-tags true --start 0 filename.bin")]
|
||||
public void ImageDecodeTest(string parameters)
|
||||
{
|
||||
string? expected = "image decode --disk-tags True --sector-tags True --length all --start 0 \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("i entropy -p -t -w filename.bin")]
|
||||
[InlineData("i entropy -p true -t true -w true filename.bin")]
|
||||
[InlineData("i entropy --duplicated-sectors --separated-tracks --whole-disc filename.bin")]
|
||||
[InlineData("i entropy --duplicated-sectors true --separated-tracks true --whole-disc true filename.bin")]
|
||||
[InlineData("image entropy -p -t -w filename.bin")]
|
||||
[InlineData("image entropy -p true -t true -w true filename.bin")]
|
||||
[InlineData("image entropy --duplicated-sectors --separated-tracks --whole-disc filename.bin")]
|
||||
[InlineData("image entropy --duplicated-sectors true --separated-tracks true --whole-disc true filename.bin")]
|
||||
public void ImageEntropyTest(string parameters)
|
||||
{
|
||||
string? expected = "image entropy --duplicated-sectors True --separated-tracks True --whole-disc True \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("i info filename.bin")]
|
||||
[InlineData("image info filename.bin")]
|
||||
public void ImageInfoTest(string parameters)
|
||||
{
|
||||
string? expected = "image info \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("i options")]
|
||||
[InlineData("image options")]
|
||||
public void ImageOptionsTest(string parameters)
|
||||
{
|
||||
string? expected = "image options";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("i print -l 0 -r -s 0 -w 0 filename.bin")]
|
||||
[InlineData("i print -l 0 -r true -s 0 -w 0 filename.bin")]
|
||||
[InlineData("i print --length 0 --long-sectors --start 0 --width 0 filename.bin")]
|
||||
[InlineData("i print --length 0 --long-sectors true --start 0 --width 0 filename.bin")]
|
||||
[InlineData("image print -l 0 -r -s 0 -w 0 filename.bin")]
|
||||
[InlineData("image print -l 0 -r true -s 0 -w 0 filename.bin")]
|
||||
[InlineData("image print --length 0 --long-sectors --start 0 --width 0 filename.bin")]
|
||||
[InlineData("image print --length 0 --long-sectors true --start 0 --width 0 filename.bin")]
|
||||
public void ImagePrintTest(string parameters)
|
||||
{
|
||||
string? expected = "image print --long-sectors True --width 0 --length 0 --start 0 \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("i verify -w -s filename.bin")]
|
||||
[InlineData("i verify -w true -s true filename.bin")]
|
||||
[InlineData("i verify --verify-disc --verify-sectors filename.bin")]
|
||||
[InlineData("i verify --verify-disc true --verify-sectors true filename.bin")]
|
||||
[InlineData("image verify -w -s filename.bin")]
|
||||
[InlineData("image verify -w true -s true filename.bin")]
|
||||
[InlineData("image verify --verify-disc --verify-sectors filename.bin")]
|
||||
[InlineData("image verify --verify-disc true --verify-sectors true filename.bin")]
|
||||
public void ImageVerifyTest(string parameters)
|
||||
{
|
||||
string? expected = "image verify --verify-disc True --verify-sectors True \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Media Family
|
||||
|
||||
[Theory]
|
||||
[InlineData("m dump --eject -e enc --first-pregap --fix-offset --fix-subchannel --fix-subchannel-crc --fix-subchannel-position -f --generate-subchannels --max-blocks 0 --metadata -O opt --persistent --private -r -p 0 --retry-subchannel -k 0 --skip-cdiready-hole --speed 0 -s --store-encrypted --subchannel any --title-keys --trim --use-buffered-reads -x cicm input output.bin")]
|
||||
[InlineData("m dump --eject true -e enc --first-pregap true --fix-offset true --fix-subchannel true --fix-subchannel-crc true --fix-subchannel-position true -f true --generate-subchannels true --max-blocks 0 --metadata true -O opt --persistent true --private true -r true -p 0 --retry-subchannel true -k 0 --skip-cdiready-hole true --speed 0 -s true --store-encrypted true --subchannel any --title-keys true --trim true --use-buffered-reads true -x cicm input output.bin")]
|
||||
[InlineData("m dump --eject --encoding enc --first-pregap --fix-offset --fix-subchannel --fix-subchannel-crc --fix-subchannel-position --force --generate-subchannels --max-blocks 0 --metadata --options opt --persistent --private --resume --retry-passes 0 --retry-subchannel --skip 0 --skip-cdiready-hole --speed 0 --stop-on-error --store-encrypted --subchannel any --title-keys --trim --use-buffered-reads --cicm-xml cicm input output.bin")]
|
||||
[InlineData("m dump --eject true --encoding enc --first-pregap true --fix-offset true --fix-subchannel true --fix-subchannel-crc true --fix-subchannel-position true --force true --generate-subchannels true --max-blocks 0 --metadata true --options opt --persistent true --private true --resume true --retry-passes 0 --retry-subchannel true --skip 0 --skip-cdiready-hole true --speed 0 --stop-on-error true --store-encrypted true --subchannel any --title-keys true --trim true --use-buffered-reads true --cicm-xml cicm input output.bin")]
|
||||
[InlineData("media dump --eject -e enc --first-pregap --fix-offset --fix-subchannel --fix-subchannel-crc --fix-subchannel-position -f --generate-subchannels --max-blocks 0 --metadata -O opt --persistent --private -r -p 0 --retry-subchannel -k 0 --skip-cdiready-hole --speed 0 -s --store-encrypted --subchannel any --title-keys --trim --use-buffered-reads -x cicm input output.bin")]
|
||||
[InlineData("media dump --eject true -e enc --first-pregap true --fix-offset true --fix-subchannel true --fix-subchannel-crc true --fix-subchannel-position true -f true --generate-subchannels true --max-blocks 0 --metadata true -O opt --persistent true --private true -r true -p 0 --retry-subchannel true -k 0 --skip-cdiready-hole true --speed 0 -s true --store-encrypted true --subchannel any --title-keys true --trim true --use-buffered-reads true -x cicm input output.bin")]
|
||||
[InlineData("media dump --eject --encoding enc --first-pregap --fix-offset --fix-subchannel --fix-subchannel-crc --fix-subchannel-position --force --generate-subchannels --max-blocks 0 --metadata --options opt --persistent --private --resume --retry-passes 0 --retry-subchannel --skip 0 --skip-cdiready-hole --speed 0 --stop-on-error --store-encrypted --subchannel any --title-keys --trim --use-buffered-reads --cicm-xml cicm input output.bin")]
|
||||
[InlineData("media dump --eject true --encoding enc --first-pregap true --fix-offset true --fix-subchannel true --fix-subchannel-crc true --fix-subchannel-position true --force true --generate-subchannels true --max-blocks 0 --metadata true --options opt --persistent true --private true --resume true --retry-passes 0 --retry-subchannel true --skip 0 --skip-cdiready-hole true --speed 0 --stop-on-error true --store-encrypted true --subchannel any --title-keys true --trim true --use-buffered-reads true --cicm-xml cicm input output.bin")]
|
||||
public void MediaDumpTest(string parameters)
|
||||
{
|
||||
string? expected = "media dump --eject True --first-pregap True --fix-offset True --fix-subchannel True --fix-subchannel-crc True --fix-subchannel-position True --force True --generate-subchannels True --metadata True --persistent True --private True --resume True --retry-subchannel True --skip-cdiready-hole True --stop-on-error True --store-encrypted True --title-keys True --trim True --use-buffered-reads True --speed 0 --retry-passes 0 --max-blocks 0 --skip 0 --encoding \"enc\" --options \"opt\" --subchannel \"any\" --cicm-xml \"cicm\" input \"output.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("m info -w prefix input")]
|
||||
[InlineData("m info --output-prefix prefix input")]
|
||||
[InlineData("media info -w prefix input")]
|
||||
[InlineData("media info --output-prefix prefix input")]
|
||||
public void MediaInfoTest(string parameters)
|
||||
{
|
||||
string? expected = "media info --output-prefix \"prefix\" input";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("m scan -b ibg -m mhdd --use-buffered-reads input")]
|
||||
[InlineData("m scan -b ibg -m mhdd --use-buffered-reads true input")]
|
||||
[InlineData("m scan --ibg-log ibg --mhdd-log mhdd --use-buffered-reads input")]
|
||||
[InlineData("m scan --ibg-log ibg --mhdd-log mhdd --use-buffered-reads true input")]
|
||||
[InlineData("media scan -b ibg -m mhdd --use-buffered-reads input")]
|
||||
[InlineData("media scan -b ibg -m mhdd --use-buffered-reads true input")]
|
||||
[InlineData("media scan --ibg-log ibg --mhdd-log mhdd --use-buffered-reads input")]
|
||||
[InlineData("media scan --ibg-log ibg --mhdd-log mhdd --use-buffered-reads true input")]
|
||||
public void MediaScanTest(string parameters)
|
||||
{
|
||||
string? expected = "media scan --use-buffered-reads True --ibg-log \"ibg\" --mhdd-log \"mhdd\" input";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Standalone Commands
|
||||
|
||||
[Theory]
|
||||
[InlineData("--debug --help --verbose --version formats")]
|
||||
[InlineData("--debug true --help true --verbose true --version true formats")]
|
||||
public void PreCommandFlagsTest(string parameters)
|
||||
{
|
||||
string? expected = "--debug True --help True --verbose True --version True formats";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("configure", "configure")]
|
||||
[InlineData("formats", "formats")]
|
||||
[InlineData("list-encodings", "list-encodings")]
|
||||
[InlineData("list-namespaces", "list-namespaces")]
|
||||
[InlineData("remote localhost", "remote \"localhost\"")]
|
||||
public void StandaloneCommandsTest(string parameters, string? expected)
|
||||
{
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
276
MPF.ExecutionContexts.Test/BaseExecutionContextTests.cs
Normal file
276
MPF.ExecutionContexts.Test/BaseExecutionContextTests.cs
Normal file
@@ -0,0 +1,276 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.ExecutionContexts.Test
|
||||
{
|
||||
public class BaseExecutionContextTests
|
||||
{
|
||||
#region SplitParameterString
|
||||
|
||||
[Fact]
|
||||
public void SplitParameterString_Empty_Empty()
|
||||
{
|
||||
string parameters = string.Empty;
|
||||
string[] actual = BaseExecutionContext.SplitParameterString(parameters);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitParameterString_NoSplit_Single()
|
||||
{
|
||||
string expected = "single";
|
||||
string parameters = "single";
|
||||
string[] actual = BaseExecutionContext.SplitParameterString(parameters);
|
||||
|
||||
var p0 = Assert.Single(actual);
|
||||
Assert.Equal(expected, p0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitParameterString_SplitNoEquals_Multiple()
|
||||
{
|
||||
string[] expected = ["-flag1", "value1", "-flag2"];
|
||||
string parameters = "-flag1 value1 -flag2";
|
||||
string[] actual = BaseExecutionContext.SplitParameterString(parameters);
|
||||
Assert.True(expected.SequenceEqual(actual));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitParameterString_SplitEquals_Multiple()
|
||||
{
|
||||
string[] expected = ["-flag1=value1", "-flag2"];
|
||||
string parameters = "-flag1=value1 -flag2";
|
||||
string[] actual = BaseExecutionContext.SplitParameterString(parameters);
|
||||
Assert.True(expected.SequenceEqual(actual));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitParameterString_SplitNoEqualsQuotes_Multiple()
|
||||
{
|
||||
string[] expected = ["-flag1", "\"value1 value2\"", "-flag2"];
|
||||
string parameters = "-flag1 \"value1 value2\" -flag2";
|
||||
string[] actual = BaseExecutionContext.SplitParameterString(parameters);
|
||||
Assert.True(expected.SequenceEqual(actual));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitParameterString_SplitEqualsQuotes_Multiple()
|
||||
{
|
||||
string[] expected = ["-flag1=\"value1 value2\"", "-flag2"];
|
||||
string parameters = "-flag1=\"value1 value2\" -flag2";
|
||||
string[] actual = BaseExecutionContext.SplitParameterString(parameters);
|
||||
Assert.True(expected.SequenceEqual(actual));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DoesExist
|
||||
|
||||
[Fact]
|
||||
public void DoesExist_Empty_False()
|
||||
{
|
||||
string[] parts = [];
|
||||
int index = 0;
|
||||
bool actual = BaseExecutionContext.DoesExist(parts, index);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoesExist_Negative_False()
|
||||
{
|
||||
string[] parts = ["item"];
|
||||
int index = -1;
|
||||
bool actual = BaseExecutionContext.DoesExist(parts, index);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoesExist_Greater_False()
|
||||
{
|
||||
string[] parts = ["item"];
|
||||
int index = 1;
|
||||
bool actual = BaseExecutionContext.DoesExist(parts, index);
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoesExist_Valid_True()
|
||||
{
|
||||
string[] parts = ["item"];
|
||||
int index = 0;
|
||||
bool actual = BaseExecutionContext.DoesExist(parts, index);
|
||||
Assert.True(actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsValidBool
|
||||
|
||||
[Theory]
|
||||
[InlineData("", false)]
|
||||
[InlineData("true", true)]
|
||||
[InlineData("True", true)]
|
||||
[InlineData("TRUE", true)]
|
||||
[InlineData("Yes", false)]
|
||||
[InlineData("false", true)]
|
||||
[InlineData("False", true)]
|
||||
[InlineData("FALSE", true)]
|
||||
[InlineData("No", false)]
|
||||
[InlineData("Invalid", false)]
|
||||
public void IsValidBoolTest(string parameter, bool expected)
|
||||
{
|
||||
bool actual = BaseExecutionContext.IsValidBool(parameter);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsValidInt8
|
||||
|
||||
[Theory]
|
||||
[InlineData("", null, null, false)]
|
||||
[InlineData("", (sbyte)0, (sbyte)1, false)]
|
||||
[InlineData("", (sbyte)0, sbyte.MaxValue, false)]
|
||||
[InlineData("-2", null, null, true)]
|
||||
[InlineData("-2", (sbyte)0, (sbyte)1, false)]
|
||||
[InlineData("-2", (sbyte)0, sbyte.MaxValue, false)]
|
||||
[InlineData("0", null, null, true)]
|
||||
[InlineData("0", (sbyte)0, (sbyte)1, true)]
|
||||
[InlineData("0", (sbyte)0, sbyte.MaxValue, true)]
|
||||
[InlineData("2", null, null, true)]
|
||||
[InlineData("2", (sbyte)0, (sbyte)1, false)]
|
||||
[InlineData("2", (sbyte)0, sbyte.MaxValue, true)]
|
||||
[InlineData("Invalid", null, null, false)]
|
||||
[InlineData("Invalid", (sbyte)0, (sbyte)1, false)]
|
||||
[InlineData("Invalid", (sbyte)0, sbyte.MaxValue, false)]
|
||||
public void IsValidInt8Test(string parameter, sbyte? lowerBound, sbyte? upperBound, bool expected)
|
||||
{
|
||||
bool actual = BaseExecutionContext.IsValidInt8(parameter, lowerBound, upperBound);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsValidInt16
|
||||
|
||||
[Theory]
|
||||
[InlineData("", null, null, false)]
|
||||
[InlineData("", (short)0, (short)1, false)]
|
||||
[InlineData("", (short)0, short.MaxValue, false)]
|
||||
[InlineData("-2", null, null, true)]
|
||||
[InlineData("-2", (short)0, (short)1, false)]
|
||||
[InlineData("-2", (short)0, short.MaxValue, false)]
|
||||
[InlineData("0", null, null, true)]
|
||||
[InlineData("0", (short)0, (short)1, true)]
|
||||
[InlineData("0", (short)0, short.MaxValue, true)]
|
||||
[InlineData("2", null, null, true)]
|
||||
[InlineData("2", (short)0, (short)1, false)]
|
||||
[InlineData("2", (short)0, short.MaxValue, true)]
|
||||
[InlineData("Invalid", null, null, false)]
|
||||
[InlineData("Invalid", (short)0, (short)1, false)]
|
||||
[InlineData("Invalid", (short)0, short.MaxValue, false)]
|
||||
public void IsValidInt16Test(string parameter, short? lowerBound, short? upperBound, bool expected)
|
||||
{
|
||||
bool actual = BaseExecutionContext.IsValidInt16(parameter, lowerBound, upperBound);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsValidInt32
|
||||
|
||||
[Theory]
|
||||
[InlineData("", null, null, false)]
|
||||
[InlineData("", (int)0, (int)1, false)]
|
||||
[InlineData("", (int)0, int.MaxValue, false)]
|
||||
[InlineData("-2", null, null, true)]
|
||||
[InlineData("-2", (int)0, (int)1, false)]
|
||||
[InlineData("-2", (int)0, int.MaxValue, false)]
|
||||
[InlineData("0", null, null, true)]
|
||||
[InlineData("0", (int)0, (int)1, true)]
|
||||
[InlineData("0", (int)0, int.MaxValue, true)]
|
||||
[InlineData("2", null, null, true)]
|
||||
[InlineData("2", (int)0, (int)1, false)]
|
||||
[InlineData("2", (int)0, int.MaxValue, true)]
|
||||
[InlineData("Invalid", null, null, false)]
|
||||
[InlineData("Invalid", (int)0, (int)1, false)]
|
||||
[InlineData("Invalid", (int)0, int.MaxValue, false)]
|
||||
public void IsValidInt32Test(string parameter, int? lowerBound, int? upperBound, bool expected)
|
||||
{
|
||||
bool actual = BaseExecutionContext.IsValidInt32(parameter, lowerBound, upperBound);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsValidInt64
|
||||
|
||||
[Theory]
|
||||
[InlineData("", null, null, false)]
|
||||
[InlineData("", (long)0, (long)1, false)]
|
||||
[InlineData("", (long)0, long.MaxValue, false)]
|
||||
[InlineData("-2", null, null, true)]
|
||||
[InlineData("-2", (long)0, (long)1, false)]
|
||||
[InlineData("-2", (long)0, long.MaxValue, false)]
|
||||
[InlineData("0", null, null, true)]
|
||||
[InlineData("0", (long)0, (long)1, true)]
|
||||
[InlineData("0", (long)0, long.MaxValue, true)]
|
||||
[InlineData("2", null, null, true)]
|
||||
[InlineData("2", (long)0, (long)1, false)]
|
||||
[InlineData("2", (long)0, long.MaxValue, true)]
|
||||
[InlineData("Invalid", null, null, false)]
|
||||
[InlineData("Invalid", (long)0, (long)1, false)]
|
||||
[InlineData("Invalid", (long)0, long.MaxValue, false)]
|
||||
public void IsValidInt64Test(string parameter, long? lowerBound, long? upperBound, bool expected)
|
||||
{
|
||||
bool actual = BaseExecutionContext.IsValidInt64(parameter, lowerBound, upperBound);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ExtractFactorFromValue
|
||||
|
||||
[Theory]
|
||||
[InlineData("1", "1", 1)]
|
||||
[InlineData("1c", "1", 1)]
|
||||
[InlineData("1w", "1", 2)]
|
||||
[InlineData("1d", "1", 4)]
|
||||
[InlineData("1q", "1", 8)]
|
||||
[InlineData("1k", "1", 1024)]
|
||||
[InlineData("1M", "1", 1024 * 1024)]
|
||||
[InlineData("1G", "1", 1024 * 1024 * 1024)]
|
||||
public void ExtractFactorFromValueTest(string value, string expected, long expectedFactor)
|
||||
{
|
||||
string actual = BaseExecutionContext.ExtractFactorFromValue(value, out long factor);
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.Equal(expectedFactor, factor);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RemoveHexIdentifier
|
||||
|
||||
[Theory]
|
||||
[InlineData("", "")]
|
||||
[InlineData("0", "0")]
|
||||
[InlineData("00", "00")]
|
||||
[InlineData("0x", "0x")]
|
||||
[InlineData("0X", "0X")]
|
||||
[InlineData("A", "A")]
|
||||
[InlineData("A0", "A0")]
|
||||
[InlineData("Ax", "Ax")]
|
||||
[InlineData("AX", "AX")]
|
||||
[InlineData("012345", "012345")]
|
||||
[InlineData("0x12345", "12345")]
|
||||
[InlineData("0X12345", "12345")]
|
||||
public void RemoveHexIdentifierTest(string value, string expected)
|
||||
{
|
||||
string actual = BaseExecutionContext.RemoveHexIdentifier(value);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
479
MPF.ExecutionContexts.Test/DiscImageCreatorTests.cs
Normal file
479
MPF.ExecutionContexts.Test/DiscImageCreatorTests.cs
Normal file
@@ -0,0 +1,479 @@
|
||||
using MPF.ExecutionContexts.DiscImageCreator;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.ExecutionContexts.Test
|
||||
{
|
||||
public class DiscImageCreatorTests
|
||||
{
|
||||
// TODO: Add Converters.ToRedumpSystem test
|
||||
// TODO: Add Converters.ToMediaType test
|
||||
|
||||
#region Converters.Extension
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null)]
|
||||
[InlineData(MediaType.CDROM, ".bin")]
|
||||
[InlineData(MediaType.GDROM, ".bin")]
|
||||
[InlineData(MediaType.Cartridge, ".bin")]
|
||||
[InlineData(MediaType.HardDisk, ".bin")]
|
||||
[InlineData(MediaType.CompactFlash, ".bin")]
|
||||
[InlineData(MediaType.MMC, ".bin")]
|
||||
[InlineData(MediaType.SDCard, ".bin")]
|
||||
[InlineData(MediaType.FlashDrive, ".bin")]
|
||||
[InlineData(MediaType.DVD, ".iso")]
|
||||
[InlineData(MediaType.HDDVD, ".iso")]
|
||||
[InlineData(MediaType.BluRay, ".iso")]
|
||||
[InlineData(MediaType.NintendoWiiOpticalDisc, ".iso")]
|
||||
[InlineData(MediaType.LaserDisc, ".raw")]
|
||||
[InlineData(MediaType.NintendoGameCubeGameDisc, ".raw")]
|
||||
[InlineData(MediaType.NintendoWiiUOpticalDisc, ".wud")]
|
||||
[InlineData(MediaType.FloppyDisk, ".img")]
|
||||
[InlineData(MediaType.Cassette, ".wav")]
|
||||
[InlineData(MediaType.ApertureCard, null)]
|
||||
public void ExtensionTest(MediaType? type, string? expected)
|
||||
{
|
||||
string? actual = Converters.Extension(type);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Default Values
|
||||
|
||||
private static readonly BaseDumpSettings AllOptions = new DumpSettings()
|
||||
{
|
||||
DVDRereadCount = 1000,
|
||||
MultiSectorRead = true,
|
||||
MultiSectorReadValue = 1000,
|
||||
ParanoidMode = true,
|
||||
QuietMode = true,
|
||||
RereadCount = 1000,
|
||||
UseCMIFlag = true,
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, null, "filename.bin", null, null)]
|
||||
[InlineData(RedumpSystem.AppleMacintosh, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "cd /dev/sr0 \"filename.bin\" 2 /c2 1000 /q /mr 1000 /ns /sf /ss /s 2")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "cd /dev/sr0 \"filename.bin\" 2 /c2 1000 /q /mr 1000 /ns /sf /ss /s 2")]
|
||||
[InlineData(RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "cd /dev/sr0 \"filename.bin\" 2 /aj /c2 1000 /q /mr 1000")]
|
||||
[InlineData(RedumpSystem.HasbroVideoNow, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "cd /dev/sr0 \"filename.bin\" 2 /a 0 /c2 1000 /q /mr 1000")]
|
||||
[InlineData(RedumpSystem.HasbroVideoNowColor, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "cd /dev/sr0 \"filename.bin\" 2 /a 0 /c2 1000 /q /mr 1000")]
|
||||
[InlineData(RedumpSystem.HasbroVideoNowJr, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "cd /dev/sr0 \"filename.bin\" 2 /a 0 /c2 1000 /q /mr 1000")]
|
||||
[InlineData(RedumpSystem.HasbroVideoNowXP, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "cd /dev/sr0 \"filename.bin\" 2 /a 0 /c2 1000 /q /mr 1000")]
|
||||
[InlineData(RedumpSystem.SonyPlayStation, MediaType.CDROM, "/dev/sr0", "filename.bin", 2, "cd /dev/sr0 \"filename.bin\" 2 /c2 1000 /q /mr 1000 /nl /am")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.DVD, "/dev/sr0", "filename.bin", 2, "dvd /dev/sr0 \"filename.bin\" 2 /c /q /rr 1000 /sf")]
|
||||
[InlineData(RedumpSystem.MicrosoftXbox, MediaType.DVD, "/dev/sr0", "filename.bin", 2, "xbox /dev/sr0 \"filename.bin\" 2 /q /rr 1000")]
|
||||
[InlineData(RedumpSystem.MicrosoftXbox360, MediaType.DVD, "/dev/sr0", "filename.bin", 2, "xbox /dev/sr0 \"filename.bin\" 2 /q /rr 1000")]
|
||||
[InlineData(RedumpSystem.NintendoGameCube, MediaType.NintendoGameCubeGameDisc, "/dev/sr0", "filename.bin", 2, "dvd /dev/sr0 \"filename.bin\" 2 /q /raw")]
|
||||
[InlineData(RedumpSystem.NintendoWii, MediaType.NintendoWiiOpticalDisc, "/dev/sr0", "filename.bin", 2, "dvd /dev/sr0 \"filename.bin\" 2 /q /raw")]
|
||||
[InlineData(RedumpSystem.SegaDreamcast, MediaType.GDROM, "/dev/sr0", "filename.bin", 2, "gd /dev/sr0 \"filename.bin\" 2 /c2 1000 /q")]
|
||||
[InlineData(RedumpSystem.HDDVDVideo, MediaType.HDDVD, "/dev/sr0", "filename.bin", 2, "dvd /dev/sr0 \"filename.bin\" 2 /c /q /rr 1000")]
|
||||
[InlineData(RedumpSystem.BDVideo, MediaType.BluRay, "/dev/sr0", "filename.bin", 2, "bd /dev/sr0 \"filename.bin\" 2 /q /rr 1000")]
|
||||
[InlineData(RedumpSystem.NintendoWiiU, MediaType.NintendoWiiUOpticalDisc, "/dev/sr0", "filename.bin", 2, "bd /dev/sr0 \"filename.bin\" 2 /q")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.FloppyDisk, "/dev/sr0", "filename.bin", 2, "fd /dev/sr0 \"filename.bin\"")]
|
||||
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 Audio
|
||||
|
||||
[Theory]
|
||||
[InlineData("audio F filename.bin 0 1 2 /be raw /c2 1 2 3 1 5 6 /c2new 1 /d8 /d /q /f 0 /np /nq /nr /r /am /sf 1 /ss /sk 1 0 /s 0 /t")]
|
||||
public void AudioTest(string parameters)
|
||||
{
|
||||
string? expected = "audio F \"filename.bin\" 0 1 2 /be raw /c2 1 2 3 1 5 6 /c2new 1 /d8 /d /q /f 0 /np /nq /nr /r /am /sf 1 /ss /sk 1 0 /s 0 /t";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#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]
|
||||
[InlineData("bd F filename.bin 0 /d /q /rr 0 /f 0 /ra /avdp")]
|
||||
public void BluRayTest(string parameters)
|
||||
{
|
||||
string? expected = "bd F \"filename.bin\" 0 /d /q /rr 0 /f 0 /ra /avdp";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Close
|
||||
|
||||
[Theory]
|
||||
[InlineData("close f")]
|
||||
public void CloseTest(string parameters)
|
||||
{
|
||||
string? expected = "close f";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CompactDisc
|
||||
|
||||
[Theory]
|
||||
[InlineData("cd f filename.bin 0 /a 0 /p /aj /be raw /c2 1 2 3 1 5 6 /c2new 1 /d8 /d /q /mscf /fdesc sync edc /f 0 /fulltoc /mr 0 /np /nq /nl /ns /nr /am /sf 1 /ss /74 /s 0 /toc /trp /vn 0 /vnc /vnx")]
|
||||
public void CompactDiscTest(string parameters)
|
||||
{
|
||||
string? expected = "cd f \"filename.bin\" 0 /a 0 /p /aj /be raw /c2 1 2 3 1 5 6 /c2new 1 /d8 /d /q /mscf /fdesc sync edc /f 0 /fulltoc /mr 0 /np /nq /nl /ns /nr /am /sf 1 /ss /74 /s 0 /toc /trp /vn 0 /vnc /vnx";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Data
|
||||
|
||||
[Theory]
|
||||
[InlineData("data F filename.bin 0 1 2 /be raw /c2 1 2 3 1 5 6 /c2new 1 /d8 /d /q /f 0 /np /nq /nr /r /am /sf 1 /ss /sk 1 0 /s 0 /t")]
|
||||
public void DataTest(string parameters)
|
||||
{
|
||||
string? expected = "data F \"filename.bin\" 0 1 2 /be raw /c2 1 2 3 1 5 6 /c2new 1 /d8 /d /q /f 0 /np /nq /nr /r /am /sf 1 /ss /sk 1 0 /s 0 /t";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DigitalVideoDisc
|
||||
|
||||
[Theory]
|
||||
[InlineData("dvd F filename.bin 0 /c /d /q /rr 0 /fix 0 /ps 0 /ra 0 1 /raw /re /r 0 1 /sf 1 /sk 1 0 /avdp")]
|
||||
public void DigitalVideoDiscTest(string parameters)
|
||||
{
|
||||
string? expected = "dvd F \"filename.bin\" 0 /c /d /q /rr 0 /fix 0 /ps 0 /ra 0 1 /raw /re /r 0 1 /sf 1 /sk 1 0 /avdp";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Disk
|
||||
|
||||
[Theory]
|
||||
[InlineData("disk F filename.bin /d")]
|
||||
public void DiskTest(string parameters)
|
||||
{
|
||||
string? expected = "disk F \"filename.bin\" /d";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DriveSpeed
|
||||
|
||||
[Theory]
|
||||
[InlineData("ls f")]
|
||||
public void DriveSpeedTest(string parameters)
|
||||
{
|
||||
string? expected = "ls f";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Eject
|
||||
|
||||
[Theory]
|
||||
[InlineData("eject f")]
|
||||
public void EjectTest(string parameters)
|
||||
{
|
||||
string? expected = "eject f";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Floppy
|
||||
|
||||
[Theory]
|
||||
[InlineData("fd F filename.bin /d")]
|
||||
public void FloppyTest(string parameters)
|
||||
{
|
||||
string? expected = "fd F \"filename.bin\" /d";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GDROM
|
||||
|
||||
[Theory]
|
||||
[InlineData("gd f filename.bin 0 /be raw /c2 1 2 3 1 5 6 /c2new 1 /d8 /d /q /f 0 /np /nq /nr /s 0")]
|
||||
public void GDROMTest(string parameters)
|
||||
{
|
||||
string? expected = "gd f \"filename.bin\" 0 /be raw /c2 1 2 3 1 5 6 /c2new 1 /d8 /d /q /f 0 /np /nq /nr /s 0";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MDS
|
||||
|
||||
[Theory]
|
||||
[InlineData("mds filename.bin")]
|
||||
public void MDSTest(string parameters)
|
||||
{
|
||||
string? expected = "mds \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Merge
|
||||
|
||||
[Theory]
|
||||
[InlineData("merge input1.bin input2.bin")]
|
||||
public void MergeTest(string parameters)
|
||||
{
|
||||
string? expected = "merge \"input1.bin\" \"input2.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Reset
|
||||
|
||||
[Theory]
|
||||
[InlineData("reset f")]
|
||||
public void ResetTest(string parameters)
|
||||
{
|
||||
string? expected = "reset f";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SACD
|
||||
|
||||
[Theory]
|
||||
[InlineData("sacd f filename.bin 0 /d /q")]
|
||||
public void SACDTest(string parameters)
|
||||
{
|
||||
string? expected = "sacd f \"filename.bin\" 0 /d /q";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Start
|
||||
|
||||
[Theory]
|
||||
[InlineData("start f")]
|
||||
public void StartTest(string parameters)
|
||||
{
|
||||
string? expected = "start f";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stop
|
||||
|
||||
[Theory]
|
||||
[InlineData("stop f")]
|
||||
public void StopTest(string parameters)
|
||||
{
|
||||
string? expected = "stop f";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sub
|
||||
|
||||
[Theory]
|
||||
[InlineData("sub filename.bin")]
|
||||
public void SubTest(string parameters)
|
||||
{
|
||||
string? expected = "sub \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Swap
|
||||
|
||||
[Theory]
|
||||
[InlineData("swap f filename.bin 0 /a 0 /be raw /c2 1 2 3 1 5 6 /c2new 1 /d8 /d /q /f 0 /np /nq /nl /ns /nr /am /sf 1 /ss /74 /s 0 /trp /vn 0 /vnc /vnx")]
|
||||
public void SwapTest(string parameters)
|
||||
{
|
||||
string? expected = "swap f \"filename.bin\" 0 /a 0 /be raw /c2 1 2 3 1 5 6 /c2new 1 /d8 /d /q /f 0 /np /nq /nl /ns /nr /am /sf 1 /ss /74 /s 0 /trp /vn 0 /vnc /vnx";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tape
|
||||
|
||||
[Theory]
|
||||
[InlineData("tape filename.bin")]
|
||||
public void TapeTest(string parameters)
|
||||
{
|
||||
string? expected = "tape \"filename.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Version
|
||||
|
||||
[Theory]
|
||||
[InlineData("/v")]
|
||||
public void VersionTest(string parameters)
|
||||
{
|
||||
string? expected = "/v";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region XBOX
|
||||
|
||||
[Theory]
|
||||
[InlineData("xbox f filename.bin 0 /d /q /rr 0 /f 0 /nss 0")]
|
||||
public void XBOXTest(string parameters)
|
||||
{
|
||||
string? expected = "xbox f \"filename.bin\" 0 /d /q /rr 0 /f 0 /nss 0";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region XBOXSwap
|
||||
|
||||
[Theory]
|
||||
[InlineData("xboxswap f filename.bin 0 /d /q /f 0 /nss 0")]
|
||||
public void XBOXSwapTest(string parameters)
|
||||
{
|
||||
string? expected = "xboxswap f \"filename.bin\" 0 /d /q /f 0 /nss 0";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region XGD2Swap
|
||||
|
||||
[Theory]
|
||||
[InlineData("xgd2swap f filename.bin 0 /d /q /f 0 /nss 0")]
|
||||
public void XGD2SwapTest(string parameters)
|
||||
{
|
||||
string? expected = "xgd2swap f \"filename.bin\" 0 /d /q /f 0 /nss 0";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region XGD3Swap
|
||||
|
||||
[Theory]
|
||||
[InlineData("xgd3swap f filename.bin 0 /d /q /f 0 /nss 0")]
|
||||
public void XGD3SwapTest(string parameters)
|
||||
{
|
||||
string? expected = "xgd3swap f \"filename.bin\" 0 /d /q /f 0 /nss 0";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
67
MPF.ExecutionContexts.Test/DreamdumpTests.cs
Normal file
67
MPF.ExecutionContexts.Test/DreamdumpTests.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using MPF.ExecutionContexts.Dreamdump;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.ExecutionContexts.Test
|
||||
{
|
||||
public class DreamdumpTests
|
||||
{
|
||||
#region Default Values
|
||||
|
||||
private static readonly BaseDumpSettings AllOptions = new DumpSettings()
|
||||
{
|
||||
RereadCount = 50,
|
||||
SectorOrder = 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=50 --image-name=\"filename\" --sector-order=DATA_C2_SUB")]
|
||||
[InlineData(RedumpSystem.IBMPCcompatible, MediaType.CDROM, "/dev/sr0", "path/filename.bin", 2, "--retries=50 --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=50 --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=50 --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=50 --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=50 --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=50 --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=50 --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=50 --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=50 --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
|
||||
}
|
||||
}
|
||||
410
MPF.ExecutionContexts.Test/InputTests.cs
Normal file
410
MPF.ExecutionContexts.Test/InputTests.cs
Normal file
@@ -0,0 +1,410 @@
|
||||
using MPF.ExecutionContexts.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.ExecutionContexts.Test
|
||||
{
|
||||
public class InputTests
|
||||
{
|
||||
#region FlagInput
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", new string[0], 0, false, false)]
|
||||
// Invalid index
|
||||
[InlineData("flag", new string[] { "flag" }, -1, false, false)]
|
||||
[InlineData("flag", new string[] { "flag" }, 1, false, false)]
|
||||
// Invalid name
|
||||
[InlineData("flag", new string[] { "" }, 0, false, false)]
|
||||
[InlineData("flag", new string[] { "flag2" }, 0, false, false)]
|
||||
// Valid
|
||||
[InlineData("flag", new string[] { "flag" }, 0, true, true)]
|
||||
public void FlagInputTest(string name, string[] parts, int index, bool success, bool expected)
|
||||
{
|
||||
var input = new FlagInput(name);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BooleanInput
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", true, new string[0], 0, false, null)]
|
||||
// Invalid index
|
||||
[InlineData("flag", true, new string[] { "flag" }, -1, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag" }, 1, false, null)]
|
||||
// Invalid name
|
||||
[InlineData("flag", true, new string[] { "" }, 0, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag2" }, 0, false, null)]
|
||||
// Valid name, no following
|
||||
[InlineData("flag", true, new string[] { "flag" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag" }, 0, true, true)]
|
||||
// Valid name, invalid following
|
||||
[InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, true)]
|
||||
[InlineData("flag", true, new string[] { "flag=invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag=invalid" }, 0, true, true)]
|
||||
// Valid name, valid following
|
||||
[InlineData("flag", true, new string[] { "flag", "true" }, 0, true, true)]
|
||||
[InlineData("flag", true, new string[] { "flag", "false" }, 0, true, false)]
|
||||
[InlineData("flag", true, new string[] { "flag=true" }, 0, true, true)]
|
||||
[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)
|
||||
{
|
||||
var input = new BooleanInput(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Int8Input
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", true, new string[0], 0, false, null)]
|
||||
// Invalid index
|
||||
[InlineData("flag", true, new string[] { "flag" }, -1, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag" }, 1, false, null)]
|
||||
// Invalid name
|
||||
[InlineData("flag", true, new string[] { "" }, 0, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag2" }, 0, false, null)]
|
||||
// Valid name, no following
|
||||
[InlineData("flag", true, new string[] { "flag" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag" }, 0, true, sbyte.MinValue)]
|
||||
// Valid name, invalid following
|
||||
[InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, sbyte.MinValue)]
|
||||
[InlineData("flag", true, new string[] { "flag=invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag=invalid" }, 0, true, sbyte.MinValue)]
|
||||
// Valid name, valid following
|
||||
[InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (sbyte)1)]
|
||||
[InlineData("flag", true, new string[] { "flag", "-1" }, 0, true, (sbyte)-1)]
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (sbyte)1)]
|
||||
[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)
|
||||
{
|
||||
var input = new Int8Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UInt8Input
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", true, new string[0], 0, false, null)]
|
||||
// Invalid index
|
||||
[InlineData("flag", true, new string[] { "flag" }, -1, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag" }, 1, false, null)]
|
||||
// Invalid name
|
||||
[InlineData("flag", true, new string[] { "" }, 0, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag2" }, 0, false, null)]
|
||||
// Valid name, no following
|
||||
[InlineData("flag", true, new string[] { "flag" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag" }, 0, true, byte.MinValue)]
|
||||
// Valid name, invalid following
|
||||
[InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, byte.MinValue)]
|
||||
[InlineData("flag", true, new string[] { "flag=invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag=invalid" }, 0, true, byte.MinValue)]
|
||||
// Valid name, valid following
|
||||
[InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (byte)1)]
|
||||
[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)
|
||||
{
|
||||
var input = new UInt8Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Int16Input
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", true, new string[0], 0, false, null)]
|
||||
// Invalid index
|
||||
[InlineData("flag", true, new string[] { "flag" }, -1, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag" }, 1, false, null)]
|
||||
// Invalid name
|
||||
[InlineData("flag", true, new string[] { "" }, 0, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag2" }, 0, false, null)]
|
||||
// Valid name, no following
|
||||
[InlineData("flag", true, new string[] { "flag" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag" }, 0, true, short.MinValue)]
|
||||
// Valid name, invalid following
|
||||
[InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, short.MinValue)]
|
||||
[InlineData("flag", true, new string[] { "flag=invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag=invalid" }, 0, true, short.MinValue)]
|
||||
// Valid name, valid following
|
||||
[InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (short)1)]
|
||||
[InlineData("flag", true, new string[] { "flag", "-1" }, 0, true, (short)-1)]
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (short)1)]
|
||||
[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)
|
||||
{
|
||||
var input = new Int16Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UInt16Input
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", true, new string[0], 0, false, null)]
|
||||
// Invalid index
|
||||
[InlineData("flag", true, new string[] { "flag" }, -1, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag" }, 1, false, null)]
|
||||
// Invalid name
|
||||
[InlineData("flag", true, new string[] { "" }, 0, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag2" }, 0, false, null)]
|
||||
// Valid name, no following
|
||||
[InlineData("flag", true, new string[] { "flag" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag" }, 0, true, ushort.MinValue)]
|
||||
// Valid name, invalid following
|
||||
[InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, ushort.MinValue)]
|
||||
[InlineData("flag", true, new string[] { "flag=invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag=invalid" }, 0, true, ushort.MinValue)]
|
||||
// Valid name, valid following
|
||||
[InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (ushort)1)]
|
||||
[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)
|
||||
{
|
||||
var input = new UInt16Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Int32Input
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", true, new string[0], 0, false, null)]
|
||||
// Invalid index
|
||||
[InlineData("flag", true, new string[] { "flag" }, -1, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag" }, 1, false, null)]
|
||||
// Invalid name
|
||||
[InlineData("flag", true, new string[] { "" }, 0, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag2" }, 0, false, null)]
|
||||
// Valid name, no following
|
||||
[InlineData("flag", true, new string[] { "flag" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag" }, 0, true, int.MinValue)]
|
||||
// Valid name, invalid following
|
||||
[InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, int.MinValue)]
|
||||
[InlineData("flag", true, new string[] { "flag=invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag=invalid" }, 0, true, int.MinValue)]
|
||||
// Valid name, valid following
|
||||
[InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (int)1)]
|
||||
[InlineData("flag", true, new string[] { "flag", "-1" }, 0, true, (int)-1)]
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (int)1)]
|
||||
[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)
|
||||
{
|
||||
var input = new Int32Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UInt32Input
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", true, new string[0], 0, false, null)]
|
||||
// Invalid index
|
||||
[InlineData("flag", true, new string[] { "flag" }, -1, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag" }, 1, false, null)]
|
||||
// Invalid name
|
||||
[InlineData("flag", true, new string[] { "" }, 0, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag2" }, 0, false, null)]
|
||||
// Valid name, no following
|
||||
[InlineData("flag", true, new string[] { "flag" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag" }, 0, true, uint.MinValue)]
|
||||
// Valid name, invalid following
|
||||
[InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, uint.MinValue)]
|
||||
[InlineData("flag", true, new string[] { "flag=invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag=invalid" }, 0, true, uint.MinValue)]
|
||||
// Valid name, valid following
|
||||
[InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (uint)1)]
|
||||
[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)
|
||||
{
|
||||
var input = new UInt32Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Int64Input
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", true, new string[0], 0, false, null)]
|
||||
// Invalid index
|
||||
[InlineData("flag", true, new string[] { "flag" }, -1, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag" }, 1, false, null)]
|
||||
// Invalid name
|
||||
[InlineData("flag", true, new string[] { "" }, 0, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag2" }, 0, false, null)]
|
||||
// Valid name, no following
|
||||
[InlineData("flag", true, new string[] { "flag" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag" }, 0, true, long.MinValue)]
|
||||
// Valid name, invalid following
|
||||
[InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, long.MinValue)]
|
||||
[InlineData("flag", true, new string[] { "flag=invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag=invalid" }, 0, true, long.MinValue)]
|
||||
// Valid name, valid following
|
||||
[InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (long)1)]
|
||||
[InlineData("flag", true, new string[] { "flag", "-1" }, 0, true, (long)-1)]
|
||||
[InlineData("flag", true, new string[] { "flag=1" }, 0, true, (long)1)]
|
||||
[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)
|
||||
{
|
||||
var input = new Int64Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UInt64Input
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", true, new string[0], 0, false, null)]
|
||||
// Invalid index
|
||||
[InlineData("flag", true, new string[] { "flag" }, -1, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag" }, 1, false, null)]
|
||||
// Invalid name
|
||||
[InlineData("flag", true, new string[] { "" }, 0, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag2" }, 0, false, null)]
|
||||
// Valid name, no following
|
||||
[InlineData("flag", true, new string[] { "flag" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag" }, 0, true, ulong.MinValue)]
|
||||
// Valid name, invalid following
|
||||
[InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, ulong.MinValue)]
|
||||
[InlineData("flag", true, new string[] { "flag=invalid" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag=invalid" }, 0, true, ulong.MinValue)]
|
||||
// Valid name, valid following
|
||||
[InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (ulong)1)]
|
||||
[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)
|
||||
{
|
||||
var input = new UInt64Input(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region StringInput
|
||||
|
||||
[Theory]
|
||||
// Invalid parts
|
||||
[InlineData("flag", true, new string[0], 0, false, null)]
|
||||
// Invalid index
|
||||
[InlineData("flag", true, new string[] { "flag" }, -1, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag" }, 1, false, null)]
|
||||
// Invalid name
|
||||
[InlineData("flag", true, new string[] { "" }, 0, false, null)]
|
||||
[InlineData("flag", true, new string[] { "flag2" }, 0, false, null)]
|
||||
// Valid name, no following
|
||||
[InlineData("flag", true, new string[] { "flag" }, 0, false, null)]
|
||||
[InlineData("flag", false, new string[] { "flag" }, 0, true, "")]
|
||||
// Valid name, following
|
||||
[InlineData("flag", true, new string[] { "flag", "value" }, 0, true, "value")]
|
||||
[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)
|
||||
{
|
||||
var input = new StringInput(name, required);
|
||||
bool actual = input.Process(parts, ref index);
|
||||
|
||||
Assert.Equal(success, actual);
|
||||
Assert.Equal(expected, input.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ExtractFactorFromValue
|
||||
|
||||
[Theory]
|
||||
[InlineData("1", "1", 1)]
|
||||
[InlineData("1c", "1", 1)]
|
||||
[InlineData("1w", "1", 2)]
|
||||
[InlineData("1d", "1", 4)]
|
||||
[InlineData("1q", "1", 8)]
|
||||
[InlineData("1k", "1", 1024)]
|
||||
[InlineData("1M", "1", 1024 * 1024)]
|
||||
[InlineData("1G", "1", 1024 * 1024 * 1024)]
|
||||
public void ExtractFactorFromValueTest(string value, string expected, long expectedFactor)
|
||||
{
|
||||
string actual = Input.ExtractFactorFromValue(value, out long factor);
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.Equal(expectedFactor, factor);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RemoveHexIdentifier
|
||||
|
||||
[Theory]
|
||||
[InlineData("", "")]
|
||||
[InlineData("0", "0")]
|
||||
[InlineData("00", "00")]
|
||||
[InlineData("0x", "0x")]
|
||||
[InlineData("0X", "0X")]
|
||||
[InlineData("A", "A")]
|
||||
[InlineData("A0", "A0")]
|
||||
[InlineData("Ax", "Ax")]
|
||||
[InlineData("AX", "AX")]
|
||||
[InlineData("012345", "012345")]
|
||||
[InlineData("0x12345", "12345")]
|
||||
[InlineData("0X12345", "12345")]
|
||||
public void RemoveHexIdentifierTest(string value, string expected)
|
||||
{
|
||||
string actual = Input.RemoveHexIdentifier(value);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
38
MPF.ExecutionContexts.Test/MPF.ExecutionContexts.Test.csproj
Normal file
38
MPF.ExecutionContexts.Test/MPF.ExecutionContexts.Test.csproj
Normal file
@@ -0,0 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MPF.ExecutionContexts\MPF.ExecutionContexts.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="18.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.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" />
|
||||
<PackageReference Include="xunit.extensibility.execution" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.9.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
377
MPF.ExecutionContexts.Test/RedumperTests.cs
Normal file
377
MPF.ExecutionContexts.Test/RedumperTests.cs
Normal file
@@ -0,0 +1,377 @@
|
||||
using MPF.ExecutionContexts.Redumper;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.ExecutionContexts.Test
|
||||
{
|
||||
public class RedumperTests
|
||||
{
|
||||
#region Converters.Extension
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null)]
|
||||
[InlineData(MediaType.CDROM, ".bin")]
|
||||
[InlineData(MediaType.GDROM, ".bin")]
|
||||
[InlineData(MediaType.DVD, ".iso")]
|
||||
[InlineData(MediaType.HDDVD, ".iso")]
|
||||
[InlineData(MediaType.BluRay, ".iso")]
|
||||
[InlineData(MediaType.NintendoWiiOpticalDisc, ".iso")]
|
||||
[InlineData(MediaType.NintendoGameCubeGameDisc, ".raw")]
|
||||
[InlineData(MediaType.NintendoWiiUOpticalDisc, ".wud")]
|
||||
[InlineData(MediaType.ApertureCard, null)]
|
||||
public void ExtensionTest(MediaType? type, string? expected)
|
||||
{
|
||||
string? actual = Converters.Extension(type);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Default Values
|
||||
|
||||
private static readonly BaseDumpSettings AllOptions = new DumpSettings()
|
||||
{
|
||||
EnableVerbose = true,
|
||||
LeadinRetryCount = 1000,
|
||||
ReadMethod = ReadMethod.BE,
|
||||
RereadCount = 1000,
|
||||
SectorOrder = SectorOrder.DATA_C2_SUB,
|
||||
DriveType = DriveType.GENERIC,
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[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 --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")]
|
||||
[InlineData(RedumpSystem.BDVideo, MediaType.BluRay, "/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.NintendoWiiU, MediaType.NintendoWiiUOpticalDisc, "/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")]
|
||||
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 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 --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 --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);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("disc --drive=dr --image-path=\"directory name\" --image-name=\"image name.bin\"")]
|
||||
public void SpacesTest(string parameters)
|
||||
{
|
||||
string? expected = "disc --drive=dr --image-path=\"directory name\" --image-name=\"image name.bin\"";
|
||||
var context = new ExecutionContext(parameters);
|
||||
string? actual = context.GenerateParameters();
|
||||
Assert.Equal(expected, actual);
|
||||
Assert.True(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
Assert.False(context.IsDumpingCommand());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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 --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 --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);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -7,25 +7,35 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
{
|
||||
public const string NONE = "";
|
||||
|
||||
// Archive Family
|
||||
#region Archive Family
|
||||
|
||||
public const string ArchivePrefixShort = "arc";
|
||||
public const string ArchivePrefixLong = "archive";
|
||||
public const string ArchiveInfo = "info";
|
||||
|
||||
// Database Family
|
||||
#endregion
|
||||
|
||||
#region Database Family
|
||||
|
||||
public const string DatabasePrefixShort = "db";
|
||||
public const string DatabasePrefixLong = "database";
|
||||
public const string DatabaseStats = "stats";
|
||||
public const string DatabaseUpdate = "update";
|
||||
|
||||
// Device Family
|
||||
#endregion
|
||||
|
||||
#region Device Family
|
||||
|
||||
public const string DevicePrefixShort = "dev";
|
||||
public const string DevicePrefixLong = "device";
|
||||
public const string DeviceInfo = "info";
|
||||
public const string DeviceList = "list";
|
||||
public const string DeviceReport = "report";
|
||||
|
||||
// Filesystem Family
|
||||
#endregion
|
||||
|
||||
#region Filesystem Family
|
||||
|
||||
public const string FilesystemPrefixShort = "fi";
|
||||
public const string FilesystemPrefixShortAlt = "fs";
|
||||
public const string FilesystemPrefixLong = "filesystem";
|
||||
@@ -35,7 +45,10 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string FilesystemListLong = "list";
|
||||
public const string FilesystemOptions = "options";
|
||||
|
||||
// Image Family
|
||||
#endregion
|
||||
|
||||
#region Image Family
|
||||
|
||||
public const string ImagePrefixShort = "i";
|
||||
public const string ImagePrefixLong = "image";
|
||||
public const string ImageChecksumShort = "chk";
|
||||
@@ -51,18 +64,26 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string ImagePrint = "print";
|
||||
public const string ImageVerify = "verify";
|
||||
|
||||
// Media Family
|
||||
#endregion
|
||||
|
||||
#region Media Family
|
||||
|
||||
public const string MediaPrefixShort = "m";
|
||||
public const string MediaPrefixLong = "media";
|
||||
public const string MediaDump = "dump";
|
||||
public const string MediaInfo = "info";
|
||||
public const string MediaScan = "scan";
|
||||
|
||||
// Standalone Commands
|
||||
#endregion
|
||||
|
||||
#region Standalone Commands
|
||||
|
||||
public const string Configure = "configure";
|
||||
public const string Formats = "formats";
|
||||
public const string ListEncodings = "list-encodings";
|
||||
public const string ListNamespaces = "list-namespaces";
|
||||
public const string Remote = "remote";
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
MPF.ExecutionContexts/Aaru/DumpSettings.cs
Normal file
38
MPF.ExecutionContexts/Aaru/DumpSettings.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
namespace MPF.ExecutionContexts.Aaru
|
||||
{
|
||||
/// <summary>
|
||||
/// Context-specific settings that can be used by caller
|
||||
/// </summary>
|
||||
public class DumpSettings : BaseDumpSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Enable debug output while dumping by default
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool EnableDebug { get; set; } = SettingConstants.EnableDebugDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Enable verbose output while dumping by default
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool EnableVerbose { get; set; } = SettingConstants.EnableVerboseDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Enable force dumping of media by default
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool ForceDumping { get; set; } = SettingConstants.ForceDumpingDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Default number of sector/subchannel rereads
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public int RereadCount { get; set; } = SettingConstants.RereadCountDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Strip personal data information from Aaru metadata by default
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool StripPersonalData { get; set; } = SettingConstants.StripPersonalDataDefault;
|
||||
}
|
||||
}
|
||||
@@ -40,4 +40,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string WesternEuropeanMac = "macintosh";
|
||||
public const string WesternEuropeanRadix50 = "radix50";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,21 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
/// </summary>
|
||||
public static class FlagStrings
|
||||
{
|
||||
// Boolean flags
|
||||
#region Precommand Flags
|
||||
|
||||
public const string DebugShort = "-d";
|
||||
public const string DebugLong = "--debug";
|
||||
public const string HelpShort = "-h";
|
||||
public const string HelpShortAlt = "-?";
|
||||
public const string HelpLong = "--help";
|
||||
public const string VerboseShort = "-v";
|
||||
public const string VerboseLong = "--verbose";
|
||||
public const string VersionLong = "--version";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Boolean flags
|
||||
|
||||
public const string Adler32Short = "-a";
|
||||
public const string Adler32Long = "--adler32";
|
||||
public const string ClearLong = "--clear";
|
||||
@@ -14,8 +28,6 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string CRC32Short = "-c";
|
||||
public const string CRC32Long = "--crc32";
|
||||
public const string CRC64Long = "--crc64";
|
||||
public const string DebugShort = "-d";
|
||||
public const string DebugLong = "--debug";
|
||||
public const string DiskTagsShort = "-f";
|
||||
public const string DiskTagsLong = "--disk-tags";
|
||||
public const string DuplicatedSectorsShort = "-p";
|
||||
@@ -35,9 +47,6 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string ForceShort = "-f";
|
||||
public const string ForceLong = "--force";
|
||||
public const string GenerateSubchannelsLong = "--generate-subchannels";
|
||||
public const string HelpShort = "-h";
|
||||
public const string HelpShortAlt = "-?";
|
||||
public const string HelpLong = "--help";
|
||||
public const string LongFormatShort = "-l";
|
||||
public const string LongFormatLong = "--long-format";
|
||||
public const string LongSectorsShort = "-r";
|
||||
@@ -75,26 +84,32 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string TrapDiscLong = "--trap-disc";
|
||||
public const string TrimLong = "--trim";
|
||||
public const string UseBufferedReadsLong = "--use-buffered-reads";
|
||||
public const string VerboseShort = "-v";
|
||||
public const string VerboseLong = "--verbose";
|
||||
public const string VerifyDiscShort = "-w";
|
||||
public const string VerifyDiscLong = "--verify-disc";
|
||||
public const string VerifySectorsShort = "-s";
|
||||
public const string VerifySectorsLong = "--verify-sectors";
|
||||
public const string VersionLong = "--version";
|
||||
public const string WholeDiscShort = "-w";
|
||||
public const string WholeDiscLong = "--whole-disc";
|
||||
|
||||
// Int8 flags
|
||||
#endregion
|
||||
|
||||
#region Int8 flags
|
||||
|
||||
public const string SpeedLong = "--speed";
|
||||
|
||||
// Int16 flags
|
||||
#endregion
|
||||
|
||||
#region Int16 flags
|
||||
|
||||
public const string RetryPassesShort = "-p";
|
||||
public const string RetryPassesLong = "--retry-passes";
|
||||
public const string WidthShort = "-w";
|
||||
public const string WidthLong = "--width";
|
||||
|
||||
// Int32 flags
|
||||
#endregion
|
||||
|
||||
#region Int32 flags
|
||||
|
||||
public const string BlockSizeShort = "-b";
|
||||
public const string BlockSizeLong = "--block-size";
|
||||
public const string CountShort = "-c";
|
||||
@@ -105,13 +120,19 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string SkipShort = "-k";
|
||||
public const string SkipLong = "--skip";
|
||||
|
||||
// Int64 flags
|
||||
#endregion
|
||||
|
||||
#region Int64 flags
|
||||
|
||||
public const string LengthShort = "-l"; // or "all"
|
||||
public const string LengthLong = "--length"; // or "all"
|
||||
public const string StartShort = "-s";
|
||||
public const string StartLong = "--start";
|
||||
|
||||
// String flags
|
||||
#endregion
|
||||
|
||||
#region String flags
|
||||
|
||||
public const string CommentsLong = "--comments";
|
||||
public const string CreatorLong = "--creator";
|
||||
public const string DriveManufacturerLong = "--drive-manufacturer";
|
||||
@@ -121,9 +142,8 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string EncodingShort = "-e";
|
||||
public const string EncodingLong = "--encoding";
|
||||
public const string FormatConvertShort = "-p";
|
||||
public const string FormatConvertLong = "--format";
|
||||
public const string FormatDumpShort = "-t";
|
||||
public const string FormatDumpLong = "--format";
|
||||
public const string FormatLong = "--format";
|
||||
public const string GeometryShort = "-g";
|
||||
public const string GeometryLong = "--geometry";
|
||||
public const string ImgBurnLogShort = "-b";
|
||||
@@ -147,5 +167,7 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string SubchannelLong = "--subchannel";
|
||||
public const string XMLSidecarShort = "-x";
|
||||
public const string XMLSidecarLong = "--cicm-xml";
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,4 +166,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string XboxPartitioning = "Xbox partitioning";
|
||||
public const string XENIX = "XENIX";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,4 +24,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string WindowsNT83MixedCase = "nt";
|
||||
public const string OS2Extended = "os2";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string VMwareDiskImageSparse = "sparse"; // boolean, default false
|
||||
public const string VMwareDiskImageSplit = "split"; // boolean, default false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@ namespace MPF.ExecutionContexts.Aaru
|
||||
public const string StripPersonalData = "AaruStripPersonalData";
|
||||
public const bool StripPersonalDataDefault = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
MPF.ExecutionContexts/BaseDumpSettings.cs
Normal file
9
MPF.ExecutionContexts/BaseDumpSettings.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace MPF.ExecutionContexts
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for all dump settings objects, representing an
|
||||
/// arbitrary set of values that can be passed in to change
|
||||
/// default dumping behavior.
|
||||
/// </summary>
|
||||
public abstract class BaseDumpSettings { }
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace MPF.ExecutionContexts
|
||||
/// Set of flags to pass to the executable
|
||||
/// </summary>
|
||||
protected Dictionary<string, bool?> flags = [];
|
||||
protected internal IEnumerable<string> Keys => flags.Keys;
|
||||
protected internal List<string> Keys => [.. flags.Keys];
|
||||
|
||||
/// <summary>
|
||||
/// Safe access to currently set flags
|
||||
@@ -82,12 +82,12 @@ namespace MPF.ExecutionContexts
|
||||
/// <summary>
|
||||
/// Currently represented system
|
||||
/// </summary>
|
||||
public RedumpSystem? System { get; set; }
|
||||
public RedumpSystem? RedumpSystem { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Currently represented media type
|
||||
/// </summary>
|
||||
public MediaType? Type { get; set; }
|
||||
public MediaType? MediaType { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -110,12 +110,17 @@ namespace MPF.ExecutionContexts
|
||||
/// <param name="drivePath">Drive path to use</param>
|
||||
/// <param name="filename">Filename to use</param>
|
||||
/// <param name="driveSpeed">Drive speed to use</param>
|
||||
/// <param name="options">Dictionary object containing all settings that may be used for setting parameters</param>
|
||||
public BaseExecutionContext(RedumpSystem? system, MediaType? type, string? drivePath, string filename, int? driveSpeed, Dictionary<string, string?> options)
|
||||
/// <param name="baseDumpSettings">BaseDumpSettings object containing all settings that may be used for setting parameters</param>
|
||||
public BaseExecutionContext(RedumpSystem? system,
|
||||
MediaType? type,
|
||||
string? drivePath,
|
||||
string filename,
|
||||
int? driveSpeed,
|
||||
BaseDumpSettings baseDumpSettings)
|
||||
{
|
||||
this.System = system;
|
||||
this.Type = type;
|
||||
SetDefaultParameters(drivePath, filename, driveSpeed, options);
|
||||
RedumpSystem = system;
|
||||
MediaType = type;
|
||||
SetDefaultParameters(drivePath, filename, driveSpeed, baseDumpSettings);
|
||||
}
|
||||
|
||||
#region Abstract Methods
|
||||
@@ -155,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
|
||||
@@ -168,8 +173,11 @@ namespace MPF.ExecutionContexts
|
||||
/// <param name="drivePath">Drive path to use</param>
|
||||
/// <param name="filename">Filename to use</param>
|
||||
/// <param name="driveSpeed">Drive speed to use</param>
|
||||
/// <param name="options">Dictionary containing all settings that may be used for setting parameters</param>
|
||||
protected abstract void SetDefaultParameters(string? drivePath, string filename, int? driveSpeed, Dictionary<string, string?> options);
|
||||
/// <param name="baseDumpSettings">BaseDumpSettings containing all settings that may be used for setting parameters</param>
|
||||
protected abstract void SetDefaultParameters(string? drivePath,
|
||||
string filename,
|
||||
int? driveSpeed,
|
||||
BaseDumpSettings baseDumpSettings);
|
||||
|
||||
/// <summary>
|
||||
/// Scan a possible parameter string and populate whatever possible
|
||||
@@ -214,7 +222,7 @@ namespace MPF.ExecutionContexts
|
||||
{
|
||||
try
|
||||
{
|
||||
while (process != null && !process.HasExited)
|
||||
while (process is not null && !process.HasExited)
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
@@ -225,79 +233,33 @@ namespace MPF.ExecutionContexts
|
||||
|
||||
#endregion
|
||||
|
||||
#region Option Processing
|
||||
|
||||
/// <summary>
|
||||
/// Get a Boolean 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>
|
||||
protected static bool GetBooleanSetting(Dictionary<string, string?> settings, string key, bool defaultValue)
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
{
|
||||
if (bool.TryParse(settings[key], out bool value))
|
||||
return value;
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an Int32 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>
|
||||
protected static int GetInt32Setting(Dictionary<string, string?> settings, string key, int defaultValue)
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
{
|
||||
if (int.TryParse(settings[key], out int value))
|
||||
return value;
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a String 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>
|
||||
protected static string? GetStringSetting(Dictionary<string, string?> settings, string key, string? defaultValue)
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
return settings[key];
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parameter Parsing
|
||||
|
||||
/// <summary>
|
||||
/// Split a parameters string into a list while taking quotes into account
|
||||
/// </summary>
|
||||
internal static string[] SplitParameterString(string parameters)
|
||||
{
|
||||
// Ensure the parameter string is trimmed
|
||||
parameters = parameters.Trim();
|
||||
|
||||
// Split the string using Regex
|
||||
var matches = Regex.Matches(parameters, @"([a-zA-Z0-9\-]*=)?[\""].+?[\""]|[^ ]+", RegexOptions.Compiled);
|
||||
|
||||
// Get just the values from the matches
|
||||
var matchArr = new Match[matches.Count];
|
||||
matches.CopyTo(matchArr, 0);
|
||||
return Array.ConvertAll(matchArr, m => m.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether or not the selected item exists
|
||||
/// </summary>
|
||||
/// <param name="parameters">List of parameters to check against</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="index">Current index</param>
|
||||
/// <returns>True if the next item exists, false otherwise</returns>
|
||||
protected static bool DoesExist(List<string> parameters, int index)
|
||||
=> index < parameters.Count;
|
||||
internal static bool DoesExist(string[] parts, int index)
|
||||
=> index >= 0 && index < parts.Length;
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the flag is supported by the current command
|
||||
@@ -306,29 +268,21 @@ 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 (this.BaseCommand == null)
|
||||
if (BaseCommand is null)
|
||||
return false;
|
||||
if (!CommandSupport.TryGetValue(this.BaseCommand, out var supported))
|
||||
if (!CommandSupport.TryGetValue(BaseCommand, out var supported))
|
||||
return false;
|
||||
return supported.Contains(flag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a string is a valid drive letter
|
||||
/// </summary>
|
||||
/// <param name="parameter">String value to check</param>
|
||||
/// <returns>True if it's a valid drive letter, false otherwise</W>
|
||||
protected static bool IsValidDriveLetter(string parameter)
|
||||
=> Regex.IsMatch(parameter, @"^[A-Z]:?\\?$");
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a string is a valid bool
|
||||
/// </summary>
|
||||
/// <param name="parameter">String value to check</param>
|
||||
/// <returns>True if it's a valid bool, false otherwise</returns>
|
||||
protected static bool IsValidBool(string parameter)
|
||||
internal static bool IsValidBool(string parameter)
|
||||
=> bool.TryParse(parameter, out bool _);
|
||||
|
||||
/// <summary>
|
||||
@@ -338,14 +292,14 @@ namespace MPF.ExecutionContexts
|
||||
/// <param name="lowerBound">Lower bound (>=)</param>
|
||||
/// <param name="upperBound">Upper bound (<=)</param>
|
||||
/// <returns>True if it's a valid byte, false otherwise</returns>
|
||||
protected static bool IsValidInt8(string parameter, sbyte lowerBound = -1, sbyte upperBound = -1)
|
||||
internal static bool IsValidInt8(string parameter, sbyte? lowerBound = null, sbyte? upperBound = null)
|
||||
{
|
||||
(string value, long _) = ExtractFactorFromValue(parameter);
|
||||
string value = ExtractFactorFromValue(parameter, out _);
|
||||
if (!sbyte.TryParse(value, out sbyte temp))
|
||||
return false;
|
||||
else if (lowerBound != -1 && temp < lowerBound)
|
||||
else if (lowerBound is not null && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != -1 && temp > upperBound)
|
||||
else if (upperBound is not null && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -358,14 +312,14 @@ namespace MPF.ExecutionContexts
|
||||
/// <param name="lowerBound">Lower bound (>=)</param>
|
||||
/// <param name="upperBound">Upper bound (<=)</param>
|
||||
/// <returns>True if it's a valid Int16, false otherwise</returns>
|
||||
protected static bool IsValidInt16(string parameter, short lowerBound = -1, short upperBound = -1)
|
||||
internal static bool IsValidInt16(string parameter, short? lowerBound = null, short? upperBound = null)
|
||||
{
|
||||
(string value, long _) = ExtractFactorFromValue(parameter);
|
||||
string value = ExtractFactorFromValue(parameter, out _);
|
||||
if (!short.TryParse(value, out short temp))
|
||||
return false;
|
||||
else if (lowerBound != -1 && temp < lowerBound)
|
||||
else if (lowerBound is not null && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != -1 && temp > upperBound)
|
||||
else if (upperBound is not null && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -378,14 +332,14 @@ namespace MPF.ExecutionContexts
|
||||
/// <param name="lowerBound">Lower bound (>=)</param>
|
||||
/// <param name="upperBound">Upper bound (<=)</param>
|
||||
/// <returns>True if it's a valid Int32, false otherwise</returns>
|
||||
protected static bool IsValidInt32(string parameter, int lowerBound = -1, int upperBound = -1)
|
||||
internal static bool IsValidInt32(string parameter, int? lowerBound = null, int? upperBound = null)
|
||||
{
|
||||
(string value, long _) = ExtractFactorFromValue(parameter);
|
||||
string value = ExtractFactorFromValue(parameter, out _);
|
||||
if (!int.TryParse(value, out int temp))
|
||||
return false;
|
||||
else if (lowerBound != -1 && temp < lowerBound)
|
||||
else if (lowerBound is not null && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != -1 && temp > upperBound)
|
||||
else if (upperBound is not null && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -398,14 +352,14 @@ namespace MPF.ExecutionContexts
|
||||
/// <param name="lowerBound">Lower bound (>=)</param>
|
||||
/// <param name="upperBound">Upper bound (<=)</param>
|
||||
/// <returns>True if it's a valid Int64, false otherwise</returns>
|
||||
protected static bool IsValidInt64(string parameter, long lowerBound = -1, long upperBound = -1)
|
||||
internal static bool IsValidInt64(string parameter, long? lowerBound = null, long? upperBound = null)
|
||||
{
|
||||
(string value, long _) = ExtractFactorFromValue(parameter);
|
||||
string value = ExtractFactorFromValue(parameter, out _);
|
||||
if (!long.TryParse(value, out long temp))
|
||||
return false;
|
||||
else if (lowerBound != -1 && temp < lowerBound)
|
||||
else if (lowerBound is not null && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != -1 && temp > upperBound)
|
||||
else if (upperBound is not null && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -414,24 +368,24 @@ namespace MPF.ExecutionContexts
|
||||
/// <summary>
|
||||
/// Process a flag parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="flagString">Flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <returns>True if the parameter was processed successfully or skipped, false otherwise</returns>
|
||||
protected bool ProcessFlagParameter(List<string> parts, string flagString, ref int i)
|
||||
protected bool ProcessFlagParameter(string[] parts, string flagString, ref int i)
|
||||
=> ProcessFlagParameter(parts, null, flagString, ref i);
|
||||
|
||||
/// <summary>
|
||||
/// Process a flag parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="shortFlagString">Short flag string, if available</param>
|
||||
/// <param name="longFlagString">Long flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <returns>True if the parameter was processed successfully or skipped, false otherwise</returns>
|
||||
protected bool ProcessFlagParameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i)
|
||||
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)
|
||||
@@ -448,26 +402,26 @@ namespace MPF.ExecutionContexts
|
||||
/// <summary>
|
||||
/// Process a boolean parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="flagString">Flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>True if the parameter was processed successfully or skipped, false otherwise</returns>
|
||||
protected bool ProcessBooleanParameter(List<string> parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
protected bool ProcessBooleanParameter(string[] parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
=> ProcessBooleanParameter(parts, null, flagString, ref i, missingAllowed);
|
||||
|
||||
/// <summary>
|
||||
/// Process a boolean parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="shortFlagString">Short flag string, if available</param>
|
||||
/// <param name="longFlagString">Long flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>True if the parameter was processed successfully or skipped, false otherwise</returns>
|
||||
protected bool ProcessBooleanParameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
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)
|
||||
@@ -523,26 +477,26 @@ namespace MPF.ExecutionContexts
|
||||
/// <summary>
|
||||
/// Process a sbyte parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="flagString">Flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>SByte value if success, SByte.MinValue if skipped, null on error/returns>
|
||||
protected sbyte? ProcessInt8Parameter(List<string> parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
protected sbyte? ProcessInt8Parameter(string[] parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
=> ProcessInt8Parameter(parts, null, flagString, ref i, missingAllowed);
|
||||
|
||||
/// <summary>
|
||||
/// Process an sbyte parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="shortFlagString">Short flag string, if available</param>
|
||||
/// <param name="longFlagString">Long flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>SByte value if success, SByte.MinValue if skipped, null on error/returns>
|
||||
protected sbyte? ProcessInt8Parameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
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)
|
||||
@@ -576,7 +530,7 @@ namespace MPF.ExecutionContexts
|
||||
this[longFlagString] = true;
|
||||
i++;
|
||||
|
||||
(string value, long factor) = ExtractFactorFromValue(parts[i]);
|
||||
string value = ExtractFactorFromValue(parts[i], out long factor);
|
||||
if (sbyte.TryParse(value, out sbyte sByteValue))
|
||||
return (sbyte)(sByteValue * factor);
|
||||
string hexValue = RemoveHexIdentifier(value);
|
||||
@@ -596,7 +550,7 @@ namespace MPF.ExecutionContexts
|
||||
string valuePart = commandParts[1];
|
||||
|
||||
this[longFlagString] = true;
|
||||
(string value, long factor) = ExtractFactorFromValue(valuePart);
|
||||
string value = ExtractFactorFromValue(valuePart, out long factor);
|
||||
if (sbyte.TryParse(value, out sbyte sByteValue))
|
||||
return (sbyte)(sByteValue * factor);
|
||||
string hexValue = RemoveHexIdentifier(value);
|
||||
@@ -605,32 +559,32 @@ namespace MPF.ExecutionContexts
|
||||
return null;
|
||||
}
|
||||
|
||||
return SByte.MinValue;
|
||||
return sbyte.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process an Int16 parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="flagString">Flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Int16 value if success, Int16.MinValue if skipped, null on error/returns>
|
||||
protected short? ProcessInt16Parameter(List<string> parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
protected short? ProcessInt16Parameter(string[] parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
=> ProcessInt16Parameter(parts, null, flagString, ref i, missingAllowed);
|
||||
|
||||
/// <summary>
|
||||
/// Process an Int16 parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="shortFlagString">Short flag string, if available</param>
|
||||
/// <param name="longFlagString">Long flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Int16 value if success, Int16.MinValue if skipped, null on error/returns>
|
||||
protected short? ProcessInt16Parameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
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)
|
||||
@@ -663,7 +617,7 @@ namespace MPF.ExecutionContexts
|
||||
|
||||
this[longFlagString] = true;
|
||||
i++;
|
||||
(string value, long factor) = ExtractFactorFromValue(parts[i]);
|
||||
string value = ExtractFactorFromValue(parts[i], out long factor);
|
||||
if (short.TryParse(value, out short shortValue))
|
||||
return (short)(shortValue * factor);
|
||||
string hexValue = RemoveHexIdentifier(value);
|
||||
@@ -683,7 +637,7 @@ namespace MPF.ExecutionContexts
|
||||
string valuePart = commandParts[1];
|
||||
|
||||
this[longFlagString] = true;
|
||||
(string value, long factor) = ExtractFactorFromValue(valuePart);
|
||||
string value = ExtractFactorFromValue(valuePart, out long factor);
|
||||
if (short.TryParse(value, out short shortValue))
|
||||
return (short)(shortValue * factor);
|
||||
string hexValue = RemoveHexIdentifier(value);
|
||||
@@ -692,32 +646,32 @@ namespace MPF.ExecutionContexts
|
||||
return null;
|
||||
}
|
||||
|
||||
return Int16.MinValue;
|
||||
return short.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process an Int32 parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="flagString">Flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Int32 value if success, Int32.MinValue if skipped, null on error/returns>
|
||||
protected int? ProcessInt32Parameter(List<string> parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
protected int? ProcessInt32Parameter(string[] parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
=> ProcessInt32Parameter(parts, null, flagString, ref i, missingAllowed);
|
||||
|
||||
/// <summary>
|
||||
/// Process an Int32 parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="shortFlagString">Short flag string, if available</param>
|
||||
/// <param name="longFlagString">Long flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Int32 value if success, Int32.MinValue if skipped, null on error/returns>
|
||||
protected int? ProcessInt32Parameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
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)
|
||||
@@ -750,7 +704,7 @@ namespace MPF.ExecutionContexts
|
||||
|
||||
this[longFlagString] = true;
|
||||
i++;
|
||||
(string value, long factor) = ExtractFactorFromValue(parts[i]);
|
||||
string value = ExtractFactorFromValue(parts[i], out long factor);
|
||||
if (int.TryParse(value, out int intValue))
|
||||
return (int)(intValue * factor);
|
||||
string hexValue = RemoveHexIdentifier(value);
|
||||
@@ -770,7 +724,7 @@ namespace MPF.ExecutionContexts
|
||||
string valuePart = commandParts[1];
|
||||
|
||||
this[longFlagString] = true;
|
||||
(string value, long factor) = ExtractFactorFromValue(valuePart);
|
||||
string value = ExtractFactorFromValue(valuePart, out long factor);
|
||||
if (int.TryParse(value, out int intValue))
|
||||
return (int)(intValue * factor);
|
||||
string hexValue = RemoveHexIdentifier(value);
|
||||
@@ -779,32 +733,32 @@ namespace MPF.ExecutionContexts
|
||||
return null;
|
||||
}
|
||||
|
||||
return Int32.MinValue;
|
||||
return int.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process an Int64 parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="flagString">Flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Int64 value if success, Int64.MinValue if skipped, null on error/returns>
|
||||
protected long? ProcessInt64Parameter(List<string> parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
protected long? ProcessInt64Parameter(string[] parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
=> ProcessInt64Parameter(parts, null, flagString, ref i, missingAllowed);
|
||||
|
||||
/// <summary>
|
||||
/// Process an Int64 parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="shortFlagString">Short flag string, if available</param>
|
||||
/// <param name="longFlagString">Long flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Int64 value if success, Int64.MinValue if skipped, null on error/returns>
|
||||
protected long? ProcessInt64Parameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
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)
|
||||
@@ -837,12 +791,12 @@ namespace MPF.ExecutionContexts
|
||||
|
||||
this[longFlagString] = true;
|
||||
i++;
|
||||
(string value, long factor) = ExtractFactorFromValue(parts[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 + "="))
|
||||
@@ -857,41 +811,41 @@ namespace MPF.ExecutionContexts
|
||||
string valuePart = commandParts[1];
|
||||
|
||||
this[longFlagString] = true;
|
||||
(string value, long factor) = ExtractFactorFromValue(valuePart);
|
||||
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;
|
||||
}
|
||||
|
||||
return Int64.MinValue;
|
||||
return long.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process an string parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="flagString">Flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>String value if possible, string.Empty on missing, null on error</returns>
|
||||
protected string? ProcessStringParameter(List<string> parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
protected string? ProcessStringParameter(string[] parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
=> ProcessStringParameter(parts, null, flagString, ref i, missingAllowed);
|
||||
|
||||
/// <summary>
|
||||
/// Process a string parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="shortFlagString">Short flag string, if available</param>
|
||||
/// <param name="longFlagString">Long flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>String value if possible, string.Empty on missing, null on error</returns>
|
||||
protected string? ProcessStringParameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
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)
|
||||
@@ -945,26 +899,26 @@ namespace MPF.ExecutionContexts
|
||||
/// <summary>
|
||||
/// Process a byte parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="flagString">Flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Byte value if success, Byte.MinValue if skipped, null on error/returns>
|
||||
protected byte? ProcessUInt8Parameter(List<string> parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
protected byte? ProcessUInt8Parameter(string[] parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
=> ProcessUInt8Parameter(parts, null, flagString, ref i, missingAllowed);
|
||||
|
||||
/// <summary>
|
||||
/// Process a byte parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="shortFlagString">Short flag string, if available</param>
|
||||
/// <param name="longFlagString">Long flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Byte value if success, Byte.MinValue if skipped, null on error/returns>
|
||||
protected byte? ProcessUInt8Parameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
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)
|
||||
@@ -998,7 +952,7 @@ namespace MPF.ExecutionContexts
|
||||
this[longFlagString] = true;
|
||||
i++;
|
||||
|
||||
(string value, long factor) = ExtractFactorFromValue(parts[i]);
|
||||
string value = ExtractFactorFromValue(parts[i], out long factor);
|
||||
if (byte.TryParse(value, out byte byteValue))
|
||||
return (byte)(byteValue * factor);
|
||||
string hexValue = RemoveHexIdentifier(value);
|
||||
@@ -1018,7 +972,7 @@ namespace MPF.ExecutionContexts
|
||||
string valuePart = commandParts[1];
|
||||
|
||||
this[longFlagString] = true;
|
||||
(string value, long factor) = ExtractFactorFromValue(valuePart);
|
||||
string value = ExtractFactorFromValue(valuePart, out long factor);
|
||||
if (byte.TryParse(value, out byte byteValue))
|
||||
return (byte)(byteValue * factor);
|
||||
string hexValue = RemoveHexIdentifier(value);
|
||||
@@ -1027,7 +981,7 @@ namespace MPF.ExecutionContexts
|
||||
return null;
|
||||
}
|
||||
|
||||
return Byte.MinValue;
|
||||
return byte.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1035,10 +989,10 @@ namespace MPF.ExecutionContexts
|
||||
/// </summary>
|
||||
/// <param name="value">String value to treat as suffixed number</param>
|
||||
/// <returns>Trimmed value and multiplication factor</returns>
|
||||
private static (string trimmed, long factor) ExtractFactorFromValue(string value)
|
||||
internal static string ExtractFactorFromValue(string value, out long factor)
|
||||
{
|
||||
value = value.Trim('"');
|
||||
long factor = 1;
|
||||
factor = 1;
|
||||
|
||||
// Characters
|
||||
if (value.EndsWith("c", StringComparison.Ordinal))
|
||||
@@ -1089,7 +1043,7 @@ namespace MPF.ExecutionContexts
|
||||
value = value.TrimEnd('G');
|
||||
}
|
||||
|
||||
return (value, factor);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1097,7 +1051,7 @@ namespace MPF.ExecutionContexts
|
||||
/// </summary>
|
||||
/// <param name="value">String with removed leading 0x</param>
|
||||
/// <returns></returns>
|
||||
private static string RemoveHexIdentifier(string value)
|
||||
internal static string RemoveHexIdentifier(string value)
|
||||
{
|
||||
if (value.Length <= 2)
|
||||
return value;
|
||||
|
||||
123
MPF.ExecutionContexts/Data/BooleanInput.cs
Normal file
123
MPF.ExecutionContexts/Data/BooleanInput.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a boolean flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class BooleanInput : Input<bool?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public BooleanInput(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public BooleanInput(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public BooleanInput(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public BooleanInput(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public BooleanInput(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public BooleanInput(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : true;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (!bool.TryParse(parts[index + 1], out bool value))
|
||||
{
|
||||
Value = _required ? null : true;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
index++;
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
if (part.StartsWith($"{Name}=") || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => part.StartsWith($"{n}=")) > -1))
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string key = tempSplit[0];
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : true;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// If the next value is valid
|
||||
if (!bool.TryParse(val, out bool value))
|
||||
{
|
||||
Value = _required ? null : true;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
73
MPF.ExecutionContexts/Data/FlagInput.cs
Normal file
73
MPF.ExecutionContexts/Data/FlagInput.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a boolean flag without a trailing value
|
||||
/// </summary>
|
||||
public class FlagInput : Input<bool>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FlagInput(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FlagInput(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FlagInput(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FlagInput(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FlagInput(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FlagInput(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (!Value)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check the name
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
Value = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
291
MPF.ExecutionContexts/Data/Input.cs
Normal file
291
MPF.ExecutionContexts/Data/Input.cs
Normal file
@@ -0,0 +1,291 @@
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single input for an execution context
|
||||
/// </summary>
|
||||
public abstract class Input
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Primary name for the input
|
||||
/// </summary>
|
||||
public readonly string Name;
|
||||
|
||||
/// <summary>
|
||||
/// Alternative name for the input
|
||||
/// </summary>
|
||||
protected readonly string[] _altNames;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the value following is required or not
|
||||
/// </summary>
|
||||
protected readonly bool _required;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if a value has been set
|
||||
/// </summary>
|
||||
public abstract bool ValueSet { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <param name="name">Flag name / value</param>
|
||||
public Input(string name)
|
||||
{
|
||||
Name = name;
|
||||
_altNames = [];
|
||||
_required = true;
|
||||
}
|
||||
|
||||
/// <param name="name">Flag name / value</param>
|
||||
/// <param name="required">Indicates if a following value is required</param>
|
||||
public Input(string name, bool required)
|
||||
{
|
||||
Name = name;
|
||||
_altNames = [];
|
||||
_required = required;
|
||||
}
|
||||
|
||||
/// <param name="shortName">Flag name / value</param>
|
||||
/// <param name="longName">Verbose flag name / value</param>
|
||||
public Input(string shortName, string longName)
|
||||
{
|
||||
Name = longName;
|
||||
_altNames = [shortName];
|
||||
_required = true;
|
||||
}
|
||||
|
||||
/// <param name="shortName">Flag name / value</param>
|
||||
/// <param name="longName">Verbose flag name / value</param>
|
||||
/// <param name="required">Indicates if a following value is required</param>
|
||||
public Input(string shortName, string longName, bool required)
|
||||
{
|
||||
Name = longName;
|
||||
_altNames = [shortName];
|
||||
_required = required;
|
||||
}
|
||||
|
||||
/// <param name="names">Set of names to use</param>
|
||||
public Input(string[] names)
|
||||
{
|
||||
Name = names.Length > 0 ? names[0] : string.Empty;
|
||||
_altNames = names;
|
||||
_required = true;
|
||||
}
|
||||
|
||||
/// <param name="names">Set of names to use</param>
|
||||
/// <param name="required">Indicates if a following value is required</param>
|
||||
public Input(string[] names, bool required)
|
||||
{
|
||||
Name = names.Length > 0 ? names[0] : string.Empty;
|
||||
_altNames = names;
|
||||
_required = required;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functionality
|
||||
|
||||
/// <summary>
|
||||
/// Clear any accumulated value
|
||||
/// </summary>
|
||||
public abstract void ClearValue();
|
||||
|
||||
/// <summary>
|
||||
/// Create a formatted representation of the input and possible value
|
||||
/// </summary>
|
||||
/// <param name="useEquals">Use an equal sign as a separator on output</param>
|
||||
public abstract string Format(bool useEquals);
|
||||
|
||||
/// <summary>
|
||||
/// Process the current index, if possible
|
||||
/// </summary>
|
||||
/// <param name="parts">Parts array to be referenced</param>
|
||||
/// <param name="index">Reference to the position in the parts</param>
|
||||
/// <returns>True if a value could be determined, false otherwise</returns>
|
||||
public abstract bool Process(string[] parts, ref int index);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Get the trimmed value and multiplication factor from a value
|
||||
/// </summary>
|
||||
/// <param name="value">String value to treat as suffixed number</param>
|
||||
/// <returns>Trimmed value and multiplication factor</returns>
|
||||
internal static string ExtractFactorFromValue(string value, out long factor)
|
||||
{
|
||||
value = value.Trim('"');
|
||||
factor = 1;
|
||||
|
||||
// Characters
|
||||
#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
|
||||
#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
|
||||
#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
|
||||
#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
|
||||
#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
|
||||
#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
|
||||
#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');
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a leading 0x if it exists, case insensitive
|
||||
/// </summary>
|
||||
/// <param name="value">String with removed leading 0x</param>
|
||||
/// <returns></returns>
|
||||
internal static string RemoveHexIdentifier(string value)
|
||||
{
|
||||
if (value.Length <= 2)
|
||||
return value;
|
||||
if (value[0] != '0')
|
||||
return value;
|
||||
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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single input for an execution context
|
||||
/// </summary>
|
||||
public abstract class Input<T> : Input
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Represents the last value stored
|
||||
/// </summary>
|
||||
public T? Value { get; protected set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ValueSet => Value is not null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Input(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Input(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Input(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Input(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Input(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Input(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functionality
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void ClearValue()
|
||||
{
|
||||
Value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a new value
|
||||
/// </summary>
|
||||
public void SetValue(T value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
189
MPF.ExecutionContexts/Data/Int16Input.cs
Normal file
189
MPF.ExecutionContexts/Data/Int16Input.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an Int16 flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class Int16Input : Input<short?>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a minimum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public short? MinValue { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a maximum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public short? MaxValue { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int16Input(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int16Input(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int16Input(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int16Input(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int16Input(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int16Input(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value != short.MinValue))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : short.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
index++;
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
if (part.StartsWith($"{Name}=") || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => part.StartsWith($"{n}=")) > -1))
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string key = tempSplit[0];
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : short.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a value from a string
|
||||
/// </summary>
|
||||
private static bool ParseValue(string str, out short? output)
|
||||
{
|
||||
// If the next value is valid
|
||||
if (short.TryParse(str, out short value))
|
||||
{
|
||||
output = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a formatted string
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (short.TryParse(baseVal, out value))
|
||||
{
|
||||
output = (short)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a hex string
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (short.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = (short)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The value could not be parsed
|
||||
output = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
161
MPF.ExecutionContexts/Data/Int32ArrInput.cs
Normal file
161
MPF.ExecutionContexts/Data/Int32ArrInput.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an Int32 flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class Int32ArrInput : Input<int?[]>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Internal array size
|
||||
/// </summary>
|
||||
public int Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a minimum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public int? MinValue { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a maximum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public int? MaxValue { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32ArrInput(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32ArrInput(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32ArrInput(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32ArrInput(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32ArrInput(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32ArrInput(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value is not null))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
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));
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
Value = new int?[Size];
|
||||
for (int i = 0; i < Size; i++)
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
return !_required;
|
||||
|
||||
// If the next value is valid
|
||||
if (ParseValue(parts[index + 1], out int? value) && value is not null)
|
||||
{
|
||||
index++;
|
||||
Value[i] = value;
|
||||
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;
|
||||
}
|
||||
|
||||
// Return value based on required flag
|
||||
return !_required;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a value from a string
|
||||
/// </summary>
|
||||
private static bool ParseValue(string str, out int? output)
|
||||
{
|
||||
// If the next value is valid
|
||||
if (int.TryParse(str, out int value))
|
||||
{
|
||||
output = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a formatted string
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (int.TryParse(baseVal, out value))
|
||||
{
|
||||
output = (int)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a hex string
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (int.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = (int)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The value could not be parsed
|
||||
output = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
MPF.ExecutionContexts/Data/Int32Input.cs
Normal file
189
MPF.ExecutionContexts/Data/Int32Input.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an Int32 flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class Int32Input : Input<int?>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a minimum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public int? MinValue { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a maximum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public int? MaxValue { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32Input(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32Input(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32Input(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32Input(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32Input(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int32Input(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value != int.MinValue))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : int.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
index++;
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
if (part.StartsWith($"{Name}=") || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => part.StartsWith($"{n}=")) > -1))
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string key = tempSplit[0];
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : int.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a value from a string
|
||||
/// </summary>
|
||||
private static bool ParseValue(string str, out int? output)
|
||||
{
|
||||
// If the next value is valid
|
||||
if (int.TryParse(str, out int value))
|
||||
{
|
||||
output = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a formatted string
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (int.TryParse(baseVal, out value))
|
||||
{
|
||||
output = (int)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a hex string
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (int.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = (int)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The value could not be parsed
|
||||
output = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
MPF.ExecutionContexts/Data/Int64Input.cs
Normal file
189
MPF.ExecutionContexts/Data/Int64Input.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an Int64 flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class Int64Input : Input<long?>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a minimum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public long? MinValue { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a maximum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public long? MaxValue { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int64Input(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int64Input(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int64Input(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int64Input(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int64Input(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int64Input(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value != long.MinValue))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : long.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
index++;
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
if (part.StartsWith($"{Name}=") || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => part.StartsWith($"{n}=")) > -1))
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string key = tempSplit[0];
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : long.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a value from a string
|
||||
/// </summary>
|
||||
private static bool ParseValue(string str, out long? output)
|
||||
{
|
||||
// If the next value is valid
|
||||
if (long.TryParse(str, out long value))
|
||||
{
|
||||
output = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a formatted string
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (long.TryParse(baseVal, out value))
|
||||
{
|
||||
output = value * factor;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a hex string
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (long.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = value * factor;
|
||||
return true;
|
||||
}
|
||||
|
||||
// The value could not be parsed
|
||||
output = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
MPF.ExecutionContexts/Data/Int8Input.cs
Normal file
189
MPF.ExecutionContexts/Data/Int8Input.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an Int8 flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class Int8Input : Input<sbyte?>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a minimum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public sbyte? MinValue { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a maximum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public sbyte? MaxValue { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int8Input(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int8Input(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int8Input(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int8Input(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int8Input(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Int8Input(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value != sbyte.MinValue))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : sbyte.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
index++;
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
if (part.StartsWith($"{Name}=") || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => part.StartsWith($"{n}=")) > -1))
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string key = tempSplit[0];
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : sbyte.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a value from a string
|
||||
/// </summary>
|
||||
private static bool ParseValue(string str, out sbyte? output)
|
||||
{
|
||||
// If the next value is valid
|
||||
if (sbyte.TryParse(str, out sbyte value))
|
||||
{
|
||||
output = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a formatted string
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (sbyte.TryParse(baseVal, out value))
|
||||
{
|
||||
output = (sbyte)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a hex string
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (sbyte.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = (sbyte)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The value could not be parsed
|
||||
output = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
126
MPF.ExecutionContexts/Data/StringInput.cs
Normal file
126
MPF.ExecutionContexts/Data/StringInput.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a string flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class StringInput : Input<string>
|
||||
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether quotes are used in output or not
|
||||
/// </summary>
|
||||
public bool Quotes { get; set; } = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public StringInput(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public StringInput(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public StringInput(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public StringInput(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public StringInput(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public StringInput(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value != string.Empty))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
if (Quotes)
|
||||
builder.Append($"\"{Value}\"");
|
||||
else
|
||||
builder.Append(Value);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : string.Empty;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
index++;
|
||||
Value = parts[index].Trim('"');
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
if (part.StartsWith($"{Name}=") || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => part.StartsWith($"{n}=")) > -1))
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string key = tempSplit[0];
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : string.Empty;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
Value = val.Trim('"');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
MPF.ExecutionContexts/Data/UInt16Input.cs
Normal file
189
MPF.ExecutionContexts/Data/UInt16Input.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an UInt16 flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class UInt16Input : Input<ushort?>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a minimum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public ushort? MinValue { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a maximum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public ushort? MaxValue { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt16Input(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt16Input(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt16Input(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt16Input(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt16Input(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt16Input(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value != ushort.MinValue))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : ushort.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
index++;
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
if (part.StartsWith($"{Name}=") || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => part.StartsWith($"{n}=")) > -1))
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string key = tempSplit[0];
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : ushort.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a value from a string
|
||||
/// </summary>
|
||||
private static bool ParseValue(string str, out ushort? output)
|
||||
{
|
||||
// If the next value is valid
|
||||
if (ushort.TryParse(str, out ushort value))
|
||||
{
|
||||
output = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a formatted string
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (ushort.TryParse(baseVal, out value))
|
||||
{
|
||||
output = (ushort)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a hex string
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (ushort.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = (ushort)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The value could not be parsed
|
||||
output = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
MPF.ExecutionContexts/Data/UInt32Input.cs
Normal file
189
MPF.ExecutionContexts/Data/UInt32Input.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an UInt32 flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class UInt32Input : Input<uint?>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a minimum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public uint? MinValue { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a maximum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public uint? MaxValue { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt32Input(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt32Input(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt32Input(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt32Input(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt32Input(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt32Input(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value != uint.MinValue))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : uint.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
index++;
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
if (part.StartsWith($"{Name}=") || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => part.StartsWith($"{n}=")) > -1))
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string key = tempSplit[0];
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : uint.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a value from a string
|
||||
/// </summary>
|
||||
private static bool ParseValue(string str, out uint? output)
|
||||
{
|
||||
// If the next value is valid
|
||||
if (uint.TryParse(str, out uint value))
|
||||
{
|
||||
output = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a formatted string
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (uint.TryParse(baseVal, out value))
|
||||
{
|
||||
output = (uint)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a hex string
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (uint.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = (uint)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The value could not be parsed
|
||||
output = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
MPF.ExecutionContexts/Data/UInt64Input.cs
Normal file
189
MPF.ExecutionContexts/Data/UInt64Input.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an UInt64 flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class UInt64Input : Input<ulong?>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a minimum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public ulong? MinValue { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a maximum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public ulong? MaxValue { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt64Input(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt64Input(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt64Input(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt64Input(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt64Input(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt64Input(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value != ulong.MinValue))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : ulong.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
index++;
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
if (part.StartsWith($"{Name}=") || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => part.StartsWith($"{n}=")) > -1))
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string key = tempSplit[0];
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : ulong.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a value from a string
|
||||
/// </summary>
|
||||
private static bool ParseValue(string str, out ulong? output)
|
||||
{
|
||||
// If the next value is valid
|
||||
if (ulong.TryParse(str, out ulong value))
|
||||
{
|
||||
output = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a formatted string
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (ulong.TryParse(baseVal, out value))
|
||||
{
|
||||
output = value * (ulong)factor;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a hex string
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (ulong.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = value * (ulong)factor;
|
||||
return true;
|
||||
}
|
||||
|
||||
// The value could not be parsed
|
||||
output = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
MPF.ExecutionContexts/Data/UInt8Input.cs
Normal file
189
MPF.ExecutionContexts/Data/UInt8Input.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace MPF.ExecutionContexts.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an UInt8 flag with an optional trailing value
|
||||
/// </summary>
|
||||
public class UInt8Input : Input<byte?>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a minimum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public byte? MinValue { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a maximum value (inclusive) for the flag
|
||||
/// </summary>
|
||||
public byte? MaxValue { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt8Input(string name)
|
||||
: base(name) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt8Input(string name, bool required)
|
||||
: base(name, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt8Input(string shortName, string longName)
|
||||
: base(shortName, longName) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt8Input(string shortName, string longName, bool required)
|
||||
: base(shortName, longName, required) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt8Input(string[] names)
|
||||
: base(names) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UInt8Input(string[] names, bool required)
|
||||
: base(names, required) { }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Format(bool useEquals)
|
||||
{
|
||||
// Do not output if there is no value
|
||||
if (Value is null)
|
||||
return string.Empty;
|
||||
|
||||
// Build the output format
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Flag name
|
||||
builder.Append(Name);
|
||||
|
||||
// Only output separator and value if needed
|
||||
if (_required || (!_required && Value != byte.MinValue))
|
||||
{
|
||||
// Separator
|
||||
if (useEquals)
|
||||
builder.Append('=');
|
||||
else
|
||||
builder.Append(' ');
|
||||
|
||||
// Value
|
||||
builder.Append(Value.ToString());
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Process(string[] parts, ref int index)
|
||||
{
|
||||
// Check the parts array
|
||||
if (index < 0 || index >= parts.Length)
|
||||
return false;
|
||||
|
||||
// Check for space-separated
|
||||
string part = parts[index];
|
||||
if (part == Name || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => n == part) > -1))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= parts.Length)
|
||||
{
|
||||
Value = _required ? null : byte.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
index++;
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
if (part.StartsWith($"{Name}=") || (_altNames.Length > 0 && Array.FindIndex(_altNames, n => part.StartsWith($"{n}=")) > -1))
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string key = tempSplit[0];
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
Value = _required ? null : byte.MinValue;
|
||||
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 is not null)
|
||||
{
|
||||
Value = 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 is not null && Value < MinValue) ? MinValue : Value;
|
||||
Value = (MaxValue is not null && Value > MaxValue) ? MaxValue : Value;
|
||||
return !_required;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a value from a string
|
||||
/// </summary>
|
||||
private static bool ParseValue(string str, out byte? output)
|
||||
{
|
||||
// If the next value is valid
|
||||
if (byte.TryParse(str, out byte value))
|
||||
{
|
||||
output = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a formatted string
|
||||
string baseVal = ExtractFactorFromValue(str, out long factor);
|
||||
if (byte.TryParse(baseVal, out value))
|
||||
{
|
||||
output = (byte)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to process as a hex string
|
||||
string hexValue = RemoveHexIdentifier(baseVal);
|
||||
if (byte.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
output = (byte)(value * factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The value could not be parsed
|
||||
output = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
{
|
||||
public const string NONE = "";
|
||||
public const string Audio = "audio";
|
||||
public const string AuthPS3 = "authps3";
|
||||
public const string BluRay = "bd";
|
||||
public const string Close = "close";
|
||||
public const string CompactDisc = "cd";
|
||||
@@ -32,4 +33,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string XGD2Swap = "xgd2swap";
|
||||
public const string XGD3Swap = "xgd3swap";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
/// <returns>Valid extension (with leading '.'), null on error</returns>
|
||||
public static string? Extension(MediaType? type)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
return type switch
|
||||
{
|
||||
MediaType.CDROM
|
||||
@@ -93,8 +94,9 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
MediaType.Cassette => ".wav",
|
||||
_ => null,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
55
MPF.ExecutionContexts/DiscImageCreator/DumpSettings.cs
Normal file
55
MPF.ExecutionContexts/DiscImageCreator/DumpSettings.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
{
|
||||
/// <summary>
|
||||
/// Context-specific settings that can be used by caller
|
||||
/// </summary>
|
||||
public class DumpSettings : BaseDumpSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Enable multi-sector read flag by default
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool MultiSectorRead { get; set; } = SettingConstants.MultiSectorReadDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Include a default multi-sector read value
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public int MultiSectorReadValue { get; set; } = SettingConstants.MultiSectorReadValueDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Enable overly-secure dumping flags by default
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Version 1 and greater
|
||||
/// Split this into component parts later. Currently does:
|
||||
/// - Scan sector protection and set subchannel read level to 2 for CD
|
||||
/// - Set scan file protect flag for DVD
|
||||
/// </remarks>
|
||||
public bool ParanoidMode { get; set; } = SettingConstants.ParanoidModeDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Enable the Quiet flag by default
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool QuietMode { get; set; } = SettingConstants.QuietModeDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Default number of C2 rereads
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public int RereadCount { get; set; } = SettingConstants.RereadCountDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Default number of DVD/HD-DVD/BD rereads
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public int DVDRereadCount { get; set; } = SettingConstants.DVDRereadCountDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Use the CMI flag for supported disc types
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool UseCMIFlag { get; set; } = SettingConstants.UseCMIFlagDefault;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string AtariJaguar = "/aj";
|
||||
public const string BEOpcode = "/be";
|
||||
public const string C2Opcode = "/c2";
|
||||
public const string C2OpcodeNew = "/c2new";
|
||||
public const string CopyrightManagementInformation = "/c";
|
||||
public const string D8Opcode = "/d8";
|
||||
public const string DatExpand = "/d";
|
||||
@@ -17,7 +18,9 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string DVDReread = "/rr";
|
||||
public const string ExtractMicroSoftCabFile = "/mscf";
|
||||
public const string Fix = "/fix";
|
||||
public const string ForceDescrambleSector = "/fdesc";
|
||||
public const string ForceUnitAccess = "/f";
|
||||
public const string FullToc = "/fulltoc";
|
||||
public const string MultiSectorRead = "/mr";
|
||||
public const string NoFixSubP = "/np";
|
||||
public const string NoFixSubQ = "/nq";
|
||||
@@ -37,9 +40,11 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string SkipSector = "/sk";
|
||||
public const string SubchannelReadLevel = "/s";
|
||||
public const string Tages = "/t";
|
||||
public const string Toc = "/toc";
|
||||
public const string TryReadingPregap = "/trp";
|
||||
public const string UseAnchorVolumeDescriptorPointer = "/avdp";
|
||||
public const string VideoNow = "/vn";
|
||||
public const string VideoNowColor = "/vnc";
|
||||
public const string VideoNowXP = "/vnx";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,4 @@ namespace MPF.ExecutionContexts.DiscImageCreator
|
||||
public const string UseCMIFlag = "DICUseCMIFlag";
|
||||
public const bool UseCMIFlagDefault = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
MPF.ExecutionContexts/Dreamdump/CommandStrings.cs
Normal file
10
MPF.ExecutionContexts/Dreamdump/CommandStrings.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace MPF.ExecutionContexts.Dreamdump
|
||||
{
|
||||
/// <summary>
|
||||
/// Top-level commands for Dreamdump
|
||||
/// </summary>
|
||||
public static class CommandStrings
|
||||
{
|
||||
public const string NONE = "";
|
||||
}
|
||||
}
|
||||
26
MPF.ExecutionContexts/Dreamdump/DumpSettings.cs
Normal file
26
MPF.ExecutionContexts/Dreamdump/DumpSettings.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace MPF.ExecutionContexts.Dreamdump
|
||||
{
|
||||
/// <summary>
|
||||
/// Context-specific settings that can be used by caller
|
||||
/// </summary>
|
||||
public class DumpSettings : BaseDumpSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Enable options incompatible with redump submissions
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool NonRedumpMode { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected default Dreamdump sector order
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public SectorOrder SectorOrder { get; set; } = SettingConstants.SectorOrderDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Default number of rereads
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public int RereadCount { get; set; } = SettingConstants.RereadCountDefault;
|
||||
}
|
||||
}
|
||||
15
MPF.ExecutionContexts/Dreamdump/Enumerations.cs
Normal file
15
MPF.ExecutionContexts/Dreamdump/Enumerations.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace MPF.ExecutionContexts.Dreamdump
|
||||
{
|
||||
/// <summary>
|
||||
/// Drive sector order option
|
||||
/// </summary>
|
||||
public enum SectorOrder
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
DATA_C2,
|
||||
DATA_SUB,
|
||||
DATA_C2_SUB,
|
||||
DATA_SUB_C2,
|
||||
}
|
||||
}
|
||||
258
MPF.ExecutionContexts/Dreamdump/ExecutionContext.cs
Normal file
258
MPF.ExecutionContexts/Dreamdump/ExecutionContext.cs
Normal file
@@ -0,0 +1,258 @@
|
||||
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,
|
||||
BaseDumpSettings baseDumpSettings)
|
||||
: base(system, type, drivePath, filename, driveSpeed, baseDumpSettings)
|
||||
{
|
||||
}
|
||||
|
||||
#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,
|
||||
BaseDumpSettings baseDumpSettings)
|
||||
{
|
||||
// Get the base settings, if possible
|
||||
var dumpSettings = baseDumpSettings as DumpSettings ?? new DumpSettings();
|
||||
|
||||
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
|
||||
if (dumpSettings.SectorOrder != SectorOrder.NONE)
|
||||
{
|
||||
this[FlagStrings.SectorOrder] = true;
|
||||
(_inputs[FlagStrings.SectorOrder] as StringInput)?.SetValue(dumpSettings.SectorOrder.ToString());
|
||||
}
|
||||
|
||||
// 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!);
|
||||
}
|
||||
}
|
||||
|
||||
if (dumpSettings.RereadCount > 0)
|
||||
{
|
||||
this[FlagStrings.Retries] = true;
|
||||
(_inputs[FlagStrings.Retries] as UInt8Input)?.SetValue((byte)dumpSettings.RereadCount);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool ValidateAndSetParameters(string? parameters)
|
||||
{
|
||||
// The string has to be valid by itself first
|
||||
if (string.IsNullOrEmpty(parameters))
|
||||
return false;
|
||||
|
||||
// Now split the string into parts for easier validation
|
||||
string[] parts = SplitParameterString(parameters!);
|
||||
|
||||
// Setup the modes
|
||||
BaseCommand = null;
|
||||
|
||||
// Loop through all auxiliary flags, if necessary
|
||||
int index = 0;
|
||||
for (int i = index; i < parts.Length; i++)
|
||||
{
|
||||
// Match all possible flags
|
||||
foreach (var kvp in _inputs)
|
||||
{
|
||||
// If the value was not a match
|
||||
if (!kvp.Value.Process(parts, ref i))
|
||||
continue;
|
||||
|
||||
// Set the flag
|
||||
this[kvp.Key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If the image name was not set, set it with a default value
|
||||
if (string.IsNullOrEmpty((_inputs[FlagStrings.ImageName] as StringInput)?.Value))
|
||||
(_inputs[FlagStrings.ImageName] as StringInput)?.SetValue($"track_{DateTime.Now:yyyyMMdd-HHmm}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
33
MPF.ExecutionContexts/Dreamdump/FlagStrings.cs
Normal file
33
MPF.ExecutionContexts/Dreamdump/FlagStrings.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
namespace MPF.ExecutionContexts.Dreamdump
|
||||
{
|
||||
/// <summary>
|
||||
/// Dumping flags for Dreamdump
|
||||
/// </summary>
|
||||
public static class FlagStrings
|
||||
{
|
||||
#region Special
|
||||
|
||||
public const string ForceQTOC = "--force-qtoc";
|
||||
public const string Train = "--train";
|
||||
public const string Retries = "--retries";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Paths
|
||||
|
||||
public const string ImageName = "--image-name";
|
||||
public const string ImagePath = "--image-path";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Drive Part
|
||||
|
||||
public const string ReadOffset = "--read-offset";
|
||||
public const string ReadAtOnce = "--read-at-once"; // [0,40] (Linux), [0,20] (Windows)
|
||||
public const string Speed = "--speed";
|
||||
public const string SectorOrder = "--sector-order";
|
||||
public const string Drive = "--drive";
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
MPF.ExecutionContexts/Dreamdump/SettingConstants.cs
Normal file
11
MPF.ExecutionContexts/Dreamdump/SettingConstants.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace MPF.ExecutionContexts.Dreamdump
|
||||
{
|
||||
public static class SettingConstants
|
||||
{
|
||||
public const string RereadCount = "DreamdumpRereadCount";
|
||||
public const int RereadCountDefault = 20;
|
||||
|
||||
public const string SectorOrder = "DreamdumpSectorOrder";
|
||||
public static readonly SectorOrder SectorOrderDefault = Dreamdump.SectorOrder.NONE;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.2.0</VersionPrefix>
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<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>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<VersionPrefix>3.6.0</VersionPrefix>
|
||||
<WarningsNotAsErrors>NU5104</WarningsNotAsErrors>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Description>Common code for all MPF execution contexts</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2019-2024</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Description>Common code for all MPF execution contexts</Description>
|
||||
<Copyright>Copyright (c) Matt Nadareski 2019-2025</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="MPF.Test" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="README.md" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Support for old .NET versions -->
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))">
|
||||
<PackageReference Include="MinAsyncBridge" Version="0.12.4" />
|
||||
<PackageReference Include="MinTasksExtensionsBridge" Version="0.3.4" />
|
||||
<PackageReference Include="MinThreadingBridge" Version="0.11.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net4`)) AND !$(TargetFramework.StartsWith(`net40`))">
|
||||
<PackageReference Include="IndexRange" Version="1.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))">
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="MPF.ExecutionContexts.Test" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.3.8" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
13
MPF.ExecutionContexts/README.md
Normal file
13
MPF.ExecutionContexts/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# MPF.ExecutionContexts
|
||||
|
||||
This library represents the logic needed to invoke 3 different dumping programs:
|
||||
|
||||
- [Aaru](github.com/aaru-dps/Aaru)
|
||||
- [DiscImageCreator](github.com/saramibreak/DiscImageCreator)
|
||||
- [Redumper](https://github.com/superg/redumper)
|
||||
|
||||
These execution wrappers allow for generating valid parameters for each of the programs as well as provide some helpers that make it easier to determine what those parameters are.
|
||||
|
||||
External options are defined in order to help create reasonable default parameter sets for different combinations of media type and system.
|
||||
|
||||
Paths to the programs need to be provided if they are expected to be invoked as a part of another program. The expected versions of these programs can be found in either the changelog or the publish script in the parent project.
|
||||
@@ -6,23 +6,27 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public static class CommandStrings
|
||||
{
|
||||
public const string NONE = "";
|
||||
public const string CD = "cd";
|
||||
public const string DVD = "dvd"; // Synonym for CD
|
||||
public const string BluRay = "bd"; // Synonym for CD
|
||||
public const string SACD = "sacd"; // Synonym for CD
|
||||
public const string New = "new"; // Synonym for CD; Temporary command, to be removed later
|
||||
public const string Disc = "disc";
|
||||
public const string Rings = "rings";
|
||||
public const string Dump = "dump";
|
||||
public const string DumpNew = "dumpnew"; // Temporary command, to be removed later
|
||||
public const string DumpExtra = "dump::extra";
|
||||
public const string Refine = "refine";
|
||||
public const string RefineNew = "refinenew"; // Temporary command, to be removed later
|
||||
public const string Verify = "verify";
|
||||
public const string DVDKey = "dvdkey";
|
||||
public const string Eject = "eject";
|
||||
public const string DVDIsoKey = "dvdisokey";
|
||||
public const string Protection = "protection";
|
||||
public const string Split = "split";
|
||||
public const string Hash = "hash";
|
||||
public const string Info = "info";
|
||||
public const string Skeleton = "skeleton";
|
||||
public const string FlashMT1339 = "flash::mt1339";
|
||||
public const string FlashSD616 = "flash::sd616";
|
||||
public const string FlashPlextor = "flash::plextor";
|
||||
public const string Subchannel = "subchannel";
|
||||
public const string Debug = "debug";
|
||||
public const string FixMSF = "fixmsf";
|
||||
public const string DebugFlip = "debug::flip";
|
||||
public const string DriveTest = "drive::test";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,16 +13,22 @@ 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 => ".bin",
|
||||
MediaType.CDROM
|
||||
or MediaType.GDROM => ".bin",
|
||||
MediaType.DVD
|
||||
or MediaType.HDDVD
|
||||
or MediaType.BluRay => ".iso",
|
||||
or MediaType.BluRay
|
||||
or MediaType.NintendoWiiOpticalDisc => ".iso",
|
||||
MediaType.NintendoGameCubeGameDisc => ".raw",
|
||||
MediaType.NintendoWiiUOpticalDisc => ".wud",
|
||||
_ => null,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
68
MPF.ExecutionContexts/Redumper/DumpSettings.cs
Normal file
68
MPF.ExecutionContexts/Redumper/DumpSettings.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
namespace MPF.ExecutionContexts.Redumper
|
||||
{
|
||||
/// <summary>
|
||||
/// Context-specific settings that can be used by caller
|
||||
/// </summary>
|
||||
public class DumpSettings : BaseDumpSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Enable skeleton output while dumping by default
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater; This is a hidden setting</remarks>
|
||||
public bool EnableSkeleton { get; set; } = SettingConstants.EnableSkeletonDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Enable verbose output while dumping by default
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool EnableVerbose { get; set; } = SettingConstants.EnableVerboseDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Default number of redumper Plextor leadin retries
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public int LeadinRetryCount { get; set; } = SettingConstants.LeadinRetryCountDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Enable options incompatible with redump submissions
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool NonRedumpMode { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected default redumper drive type
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public DriveType DriveType { get; set; } = SettingConstants.DriveTypeDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected default redumper drive pregap start sector
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public int DrivePregapStart { get; set; } = SettingConstants.DrivePregapStartDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected default redumper read method
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public ReadMethod ReadMethod { get; set; } = SettingConstants.ReadMethodDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected default redumper sector order
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public SectorOrder SectorOrder { get; set; } = SettingConstants.SectorOrderDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Default number of rereads
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public int RereadCount { get; set; } = SettingConstants.RereadCountDefault;
|
||||
|
||||
/// <summary>
|
||||
/// Enable the refine sector mode flag by default
|
||||
/// </summary>
|
||||
/// <remarks>Version 1 and greater</remarks>
|
||||
public bool RefineSectorMode { get; set; } = SettingConstants.RefineSectorModeDefault;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,21 @@
|
||||
namespace MPF.ExecutionContexts.Redumper
|
||||
{
|
||||
/// <summary>
|
||||
/// Drive type option
|
||||
/// </summary>
|
||||
public enum DriveType
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
GENERIC,
|
||||
PLEXTOR,
|
||||
MTK8A,
|
||||
MTK8B,
|
||||
MTK8C,
|
||||
MTK3,
|
||||
MTK2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drive read method option
|
||||
/// </summary>
|
||||
@@ -9,7 +25,6 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
|
||||
BE,
|
||||
D8,
|
||||
BE_CDDA,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -24,4 +39,4 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
DATA_SUB,
|
||||
DATA_C2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,20 +5,28 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
/// </summary>
|
||||
public static class FlagStrings
|
||||
{
|
||||
// General
|
||||
#region General
|
||||
|
||||
public const string HelpLong = "--help";
|
||||
public const string HelpShort = "-h";
|
||||
public const string Version = "--version";
|
||||
public const string Verbose = "--verbose";
|
||||
public const string Debug = "--debug";
|
||||
public const string ListRecommendedDrives = "--list-recommended-drives";
|
||||
public const string ListAllDrives = "--list-all-drives";
|
||||
public const string AutoEject = "--auto-eject";
|
||||
public const string Skeleton = "--skeleton";
|
||||
public const string Drive = "--drive";
|
||||
public const string Speed = "--speed";
|
||||
public const string Retries = "--retries";
|
||||
public const string ImagePath = "--image-path";
|
||||
public const string ImageName = "--image-name";
|
||||
public const string Overwrite = "--overwrite";
|
||||
public const string DiscType = "--disc-type";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Drive Configuration
|
||||
|
||||
// Drive Configuration
|
||||
public const string DriveType = "--drive-type";
|
||||
public const string DriveReadOffset = "--drive-read-offset";
|
||||
public const string DriveC2Shift = "--drive-c2-shift";
|
||||
@@ -26,34 +34,73 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
public const string DriveReadMethod = "--drive-read-method";
|
||||
public const string DriveSectorOrder = "--drive-sector-order";
|
||||
|
||||
// Drive Specific
|
||||
#endregion
|
||||
|
||||
#region Drive Specific
|
||||
|
||||
public const string PlextorSkipLeadin = "--plextor-skip-leadin";
|
||||
public const string PlextorLeadinRetries = "--plextor-leadin-retries";
|
||||
public const string AsusSkipLeadout = "--asus-skip-leadout";
|
||||
public const string PlextorLeadinForceStore = "--plextor-leadin-force-store";
|
||||
public const string KreonPartialSS = "--kreon-partial-ss";
|
||||
public const string MediatekSkipLeadout = "--mediatek-skip-leadout";
|
||||
public const string MediatekLeadoutRetries = "--mediatek-leadout-retries";
|
||||
public const string DisableCDText = "--disable-cdtext";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Offset
|
||||
|
||||
// Offset
|
||||
public const string ForceOffset = "--force-offset";
|
||||
public const string AudioSilenceThreshold = "--audio-silence-threshold";
|
||||
public const string CorrectOffsetShift = "--correct-offset-shift";
|
||||
public const string OffsetShiftRelocate = "--offset-shift-relocate";
|
||||
|
||||
// Split
|
||||
#endregion
|
||||
|
||||
#region Split
|
||||
|
||||
public const string ForceSplit = "--force-split";
|
||||
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";
|
||||
|
||||
// Miscellaneous
|
||||
#endregion
|
||||
|
||||
#region Drive Test
|
||||
|
||||
public const string DriveTestSkipPlextorLeadin = "--drive-test-skip-plextor-leadin";
|
||||
public const string DriveTestSkipCacheRead = "--drive-test-skip-cache-read";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Miscellaneous
|
||||
|
||||
public const string Continue = "--continue";
|
||||
public const string LBAStart = "--lba-start";
|
||||
public const string LBAEnd = "--lba-end";
|
||||
public const string LBAEndBySubcode = "--lba-end-by-subcode";
|
||||
public const string RefineSubchannel = "--refine-subchannel";
|
||||
public const string RefineSectorMode = "--refine-sector-mode";
|
||||
public const string Skip = "--skip";
|
||||
public const string DumpWriteOffset = "--dump-write-offset";
|
||||
public const string DumpReadSize = "--dump-read-size";
|
||||
public const string OverreadLeadout = "--overread-leadout";
|
||||
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 CdrErrorThreshold = "--cdr-error-threshold";
|
||||
public const string ScsiTimeout = "--scsi-timeout";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Undocumented
|
||||
|
||||
public const string Debug = "--debug";
|
||||
public const string LegacySubs = "--legacy-subs";
|
||||
public const string DisableCDText = "--disable-cdtext";
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,28 +2,31 @@ namespace MPF.ExecutionContexts.Redumper
|
||||
{
|
||||
public static class SettingConstants
|
||||
{
|
||||
public const string EnableDebug = "RedumperEnableDebug";
|
||||
public const bool EnableDebugDefault = false;
|
||||
public const string DriveType = "RedumperDriveType";
|
||||
public static readonly DriveType DriveTypeDefault = Redumper.DriveType.NONE;
|
||||
|
||||
public const string EnableLeadinRetry = "RedumperEnableLeadinRetry";
|
||||
public const bool EnableLeadinRetryDefault = false;
|
||||
public const string EnableSkeleton = "RedumperEnableSkeleton";
|
||||
public const bool EnableSkeletonDefault = true;
|
||||
|
||||
public const string EnableVerbose = "RedumperEnableVerbose";
|
||||
public const bool EnableVerboseDefault = true;
|
||||
public const bool EnableVerboseDefault = false;
|
||||
|
||||
public const string LeadinRetryCount = "RedumperLeadinRetryCount";
|
||||
public const int LeadinRetryCountDefault = 4;
|
||||
|
||||
public const string DrivePregapStart = "RedumperDrivePregapStart";
|
||||
public const int DrivePregapStartDefault = 0;
|
||||
|
||||
public const string ReadMethod = "RedumperReadMethod";
|
||||
public static readonly string ReadMethodDefault = Redumper.ReadMethod.NONE.ToString();
|
||||
public static readonly ReadMethod ReadMethodDefault = Redumper.ReadMethod.NONE;
|
||||
|
||||
public const string RefineSectorMode = "RedumperRefineSectorMode";
|
||||
public const bool RefineSectorModeDefault = false;
|
||||
|
||||
public const string RereadCount = "RedumperRereadCount";
|
||||
public const int RereadCountDefault = 20;
|
||||
|
||||
public const string SectorOrder = "RedumperSectorOrder";
|
||||
public static readonly string SectorOrderDefault = Redumper.SectorOrder.NONE.ToString();
|
||||
|
||||
public const string UseGenericDriveType = "RedumperUseGenericDriveType";
|
||||
public const bool UseGenericDriveTypeDefault = false;
|
||||
public static readonly SectorOrder SectorOrderDefault = Redumper.SectorOrder.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using MPF.Frontend;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Test.Frontend
|
||||
namespace MPF.Frontend.Test
|
||||
{
|
||||
public class EnumConverterTests
|
||||
public class DriveTests
|
||||
{
|
||||
#region Cross-enumeration conversions
|
||||
#region ToInternalDriveType
|
||||
|
||||
/// <summary>
|
||||
/// DiscType values that map to InternalDriveType
|
||||
@@ -45,9 +43,9 @@ namespace MPF.Test.Frontend
|
||||
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 (_mappableDriveTypes.Contains(driveType))
|
||||
if (Array.IndexOf(_mappableDriveTypes, driveType) > -1)
|
||||
testData.Add([driveType, false]);
|
||||
else
|
||||
testData.Add([driveType, true]);
|
||||
@@ -57,40 +55,5 @@ namespace MPF.Test.Frontend
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Convert to Long Name
|
||||
|
||||
// TODO: Maybe add a test for the generic "GetLongName" method
|
||||
|
||||
/// <summary>
|
||||
/// Check that every InternalProgram has a long name provided
|
||||
/// </summary>
|
||||
/// <param name="internalProgram">InternalProgram value to check</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(GenerateInternalProgramTestData))]
|
||||
public void InternalProgramLongNameTest(InternalProgram? internalProgram)
|
||||
{
|
||||
string actual = internalProgram.LongName();
|
||||
Assert.NotNull(actual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a test set of InternalProgram values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of InternalProgram values</returns>
|
||||
public static List<object?[]> GenerateInternalProgramTestData()
|
||||
{
|
||||
var testData = new List<object?[]>() { new object?[] { null } };
|
||||
foreach (InternalProgram? internalProgram in Enum.GetValues(typeof(InternalProgram)))
|
||||
{
|
||||
testData.Add([internalProgram]);
|
||||
}
|
||||
|
||||
return testData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: Add from-string tests
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
using MPF.Frontend;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Test.Frontend
|
||||
namespace MPF.Frontend.Test
|
||||
{
|
||||
public class DumpEnvironmentTests
|
||||
{
|
||||
@@ -10,21 +9,29 @@ namespace MPF.Test.Frontend
|
||||
[InlineData(null, 'D', false, MediaType.NONE, false)]
|
||||
[InlineData("", 'D', false, MediaType.NONE, false)]
|
||||
[InlineData("cd F test.bin 8 /c2 20", 'F', false, MediaType.CDROM, true)]
|
||||
[InlineData("cd F test.bin 8 /c2new 20", 'F', false, MediaType.CDROM, true)]
|
||||
[InlineData("fd A test.img", 'A', true, MediaType.FloppyDisk, true)]
|
||||
[InlineData("dvd X test.iso 8 /raw", 'X', false, MediaType.FloppyDisk, false)]
|
||||
[InlineData("stop D", 'D', false, MediaType.DVD, true)]
|
||||
public void ParametersValidTest(string? parameters, char letter, bool isFloppy, MediaType? mediaType, bool expected)
|
||||
public void ParametersValidSegmentedTest(string? parameters, char letter, bool isFloppy, MediaType? mediaType, bool expected)
|
||||
{
|
||||
var options = new Options() { InternalProgram = InternalProgram.DiscImageCreator };
|
||||
var options = new Options();
|
||||
options.InternalProgram = InternalProgram.DiscImageCreator;
|
||||
|
||||
// TODO: This relies on creating real objects for the drive. Can we mock this out instead?
|
||||
var drive = isFloppy
|
||||
? Drive.Create(InternalDriveType.Floppy, letter.ToString())
|
||||
: Drive.Create(InternalDriveType.Optical, letter.ToString());
|
||||
|
||||
var env = new DumpEnvironment(options, string.Empty, drive, RedumpSystem.IBMPCcompatible, mediaType, null, parameters);
|
||||
var env = new DumpEnvironment(options,
|
||||
string.Empty,
|
||||
drive,
|
||||
RedumpSystem.IBMPCcompatible,
|
||||
null);
|
||||
env.SetExecutionContext(mediaType, parameters);
|
||||
env.SetProcessor();
|
||||
|
||||
bool actual = env.ParametersValid();
|
||||
bool actual = env.ParametersValid(mediaType);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
296
MPF.Frontend.Test/EnumExtensionsTests.cs
Normal file
296
MPF.Frontend.Test/EnumExtensionsTests.cs
Normal file
@@ -0,0 +1,296 @@
|
||||
using System;
|
||||
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;
|
||||
|
||||
namespace MPF.Frontend.Test
|
||||
{
|
||||
public class EnumExtensionsTests
|
||||
{
|
||||
#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")]
|
||||
[InlineData(InternalProgram.UmdImageCreator, "UmdImageCreator")]
|
||||
[InlineData(InternalProgram.XboxBackupCreator, "XboxBackupCreator")]
|
||||
public void LongName_InternalProgram(InternalProgram? prog, string? expected)
|
||||
{
|
||||
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]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(RedumperReadMethod.NONE, "Default")]
|
||||
[InlineData(RedumperReadMethod.D8, "D8")]
|
||||
[InlineData(RedumperReadMethod.BE, "BE")]
|
||||
public void LongName_RedumperReadMethod(RedumperReadMethod? method, string? expected)
|
||||
{
|
||||
string? actual = method.LongName();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
if (method is not null)
|
||||
{
|
||||
actual = EnumExtensions.GetLongName(method);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(RedumperSectorOrder.NONE, "Default")]
|
||||
[InlineData(RedumperSectorOrder.DATA_C2_SUB, "DATA_C2_SUB")]
|
||||
[InlineData(RedumperSectorOrder.DATA_SUB_C2, "DATA_SUB_C2")]
|
||||
[InlineData(RedumperSectorOrder.DATA_SUB, "DATA_SUB")]
|
||||
[InlineData(RedumperSectorOrder.DATA_C2, "DATA_C2")]
|
||||
public void LongName_RedumperSectorOrder(RedumperSectorOrder? order, string? expected)
|
||||
{
|
||||
string? actual = order.LongName();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
if (order is not null)
|
||||
{
|
||||
actual = EnumExtensions.GetLongName(order);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, "Unknown")]
|
||||
[InlineData(RedumperDriveType.NONE, "Default")]
|
||||
[InlineData(RedumperDriveType.GENERIC, "GENERIC")]
|
||||
[InlineData(RedumperDriveType.PLEXTOR, "PLEXTOR")]
|
||||
[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")]
|
||||
[InlineData(InternalProgram.UmdImageCreator, "uic")]
|
||||
[InlineData(InternalProgram.XboxBackupCreator, "xbc")]
|
||||
public void ShortName_InternalProgram(InternalProgram? prog, string? expected)
|
||||
{
|
||||
string? actual = prog.ShortName();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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)]
|
||||
[InlineData("uic", InternalProgram.UmdImageCreator)]
|
||||
[InlineData("xbc", InternalProgram.XboxBackupCreator)]
|
||||
public void ToInternalProgramTest(string? internalProgram, InternalProgram expected)
|
||||
{
|
||||
InternalProgram actual = internalProgram.ToInternalProgram();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
// TODO: Write remaining from-string tests
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functionality Support
|
||||
|
||||
private static readonly RedumpSystem?[] _antiModchipSystems =
|
||||
[
|
||||
RedumpSystem.SonyPlayStation,
|
||||
];
|
||||
|
||||
private static readonly RedumpSystem?[] _copyProtectionSystems =
|
||||
[
|
||||
RedumpSystem.AppleMacintosh,
|
||||
RedumpSystem.DVDVideo,
|
||||
RedumpSystem.EnhancedCD ,
|
||||
RedumpSystem.IBMPCcompatible,
|
||||
RedumpSystem.PalmOS,
|
||||
RedumpSystem.PocketPC,
|
||||
RedumpSystem.RainbowDisc,
|
||||
RedumpSystem.SonyElectronicBook,
|
||||
];
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GenerateSupportsAntiModchipScansData))]
|
||||
public void SupportsAntiModchipScansTest(RedumpSystem? redumpSystem, bool expected)
|
||||
{
|
||||
bool actual = redumpSystem.SupportsAntiModchipScans();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GenerateSupportsCopyProtectionScansData))]
|
||||
public void SupportsCopyProtectionScansTest(RedumpSystem? redumpSystem, bool expected)
|
||||
{
|
||||
bool actual = redumpSystem.SupportsCopyProtectionScans();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
public static List<object?[]> GenerateSupportsAntiModchipScansData()
|
||||
{
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues<RedumpSystem>())
|
||||
{
|
||||
if (_antiModchipSystems.Contains(redumpSystem))
|
||||
testData.Add([redumpSystem, true]);
|
||||
else
|
||||
testData.Add([redumpSystem, false]);
|
||||
}
|
||||
|
||||
return testData;
|
||||
}
|
||||
|
||||
public static List<object?[]> GenerateSupportsCopyProtectionScansData()
|
||||
{
|
||||
var testData = new List<object?[]>() { new object?[] { null, false } };
|
||||
foreach (RedumpSystem redumpSystem in Enum.GetValues<RedumpSystem>())
|
||||
{
|
||||
if (_copyProtectionSystems.Contains(redumpSystem))
|
||||
testData.Add([redumpSystem, true]);
|
||||
else
|
||||
testData.Add([redumpSystem, false]);
|
||||
}
|
||||
|
||||
return testData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
24
MPF.Frontend.Test/InterfaceConstantsTests.cs
Normal file
24
MPF.Frontend.Test/InterfaceConstantsTests.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Frontend.Test
|
||||
{
|
||||
public class InterfaceConstantsTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(MediaType.CDROM, 72)]
|
||||
[InlineData(MediaType.DVD, 24)]
|
||||
[InlineData(MediaType.NintendoGameCubeGameDisc, 24)]
|
||||
[InlineData(MediaType.NintendoWiiOpticalDisc, 24)]
|
||||
[InlineData(MediaType.HDDVD, 24)]
|
||||
[InlineData(MediaType.BluRay, 16)]
|
||||
[InlineData(MediaType.NintendoWiiUOpticalDisc, 16)]
|
||||
[InlineData(MediaType.LaserDisc, 72)]
|
||||
[InlineData(null, 72)]
|
||||
public void GetAllowedDriveSpeedForMediaTypeTest(MediaType? mediaType, int maxExpected)
|
||||
{
|
||||
var actual = InterfaceConstants.GetSpeedsForMediaType(mediaType);
|
||||
Assert.Equal(maxExpected, actual[^1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
38
MPF.Frontend.Test/MPF.Frontend.Test.csproj
Normal file
38
MPF.Frontend.Test/MPF.Frontend.Test.csproj
Normal file
@@ -0,0 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MPF.Frontend\MPF.Frontend.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="18.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="SabreTools.RedumpLib" Version="[1.9.1]" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.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" />
|
||||
<PackageReference Include="xunit.extensibility.execution" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.9.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,10 +1,26 @@
|
||||
using MPF.Frontend;
|
||||
using Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Test.Frontend
|
||||
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()
|
||||
{
|
||||
98
MPF.Frontend.Test/Tools/FrontendToolTests.cs
Normal file
98
MPF.Frontend.Test/Tools/FrontendToolTests.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using System.IO;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Frontend.Test.Tools
|
||||
{
|
||||
public class FrontendToolTests
|
||||
{
|
||||
#region GetDefaultSpeedForMediaType
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, 72)]
|
||||
[InlineData(MediaType.CDROM, 72)]
|
||||
[InlineData(MediaType.GDROM, 72)]
|
||||
[InlineData(MediaType.DVD, 24)]
|
||||
[InlineData(MediaType.NintendoGameCubeGameDisc, 24)]
|
||||
[InlineData(MediaType.NintendoWiiOpticalDisc, 24)]
|
||||
[InlineData(MediaType.HDDVD, 24)]
|
||||
[InlineData(MediaType.BluRay, 16)]
|
||||
[InlineData(MediaType.NintendoWiiUOpticalDisc, 16)]
|
||||
public void GetDefaultSpeedForMediaTypeSegmentedTest(MediaType? mediaType, int expected)
|
||||
{
|
||||
var options = new Options();
|
||||
options.Dumping.DumpSpeeds.CD = 72;
|
||||
options.Dumping.DumpSpeeds.DVD = 24;
|
||||
options.Dumping.DumpSpeeds.HDDVD = 24;
|
||||
options.Dumping.DumpSpeeds.Bluray = 16;
|
||||
|
||||
int actual = FrontendTool.GetDefaultSpeedForMediaType(mediaType, options);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetRedumpSystemFromVolumeLabel
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null)]
|
||||
[InlineData("", null)]
|
||||
[InlineData("Audio CD", RedumpSystem.AudioCD)]
|
||||
[InlineData("SEP13011042", RedumpSystem.MicrosoftXbox)]
|
||||
[InlineData("SEP13011042072", RedumpSystem.MicrosoftXbox)]
|
||||
[InlineData("XBOX360", RedumpSystem.MicrosoftXbox360)]
|
||||
[InlineData("XGD2DVD_NTSC", RedumpSystem.MicrosoftXbox360)]
|
||||
[InlineData("Sega_CD", RedumpSystem.SegaMegaCDSegaCD)]
|
||||
[InlineData("PS3VOLUME", RedumpSystem.SonyPlayStation3)]
|
||||
[InlineData("PS4VOLUME", RedumpSystem.SonyPlayStation4)]
|
||||
[InlineData("PS5VOLUME", RedumpSystem.SonyPlayStation5)]
|
||||
public void GetRedumpSystemFromVolumeLabelTest(string? volumeLabel, RedumpSystem? expected)
|
||||
{
|
||||
RedumpSystem? actual = FrontendTool.GetRedumpSystemFromVolumeLabel(volumeLabel);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region NormalizeDiscTitle
|
||||
|
||||
// TODO: Write NormalizeDiscTitle(string?, Language?[]?) test
|
||||
// TODO: Write NormalizeDiscTitle(string?, Language?) test
|
||||
|
||||
#endregion
|
||||
|
||||
#region NormalizeOutputPaths
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, false, "")]
|
||||
[InlineData(null, true, "")]
|
||||
[InlineData("", false, "")]
|
||||
[InlineData("", true, "")]
|
||||
[InlineData("filename.bin", false, "filename.bin")]
|
||||
[InlineData("filename.bin", true, "filename.bin")]
|
||||
[InlineData("\"filename.bin\"", false, "filename.bin")]
|
||||
[InlineData("\"filename.bin\"", true, "filename.bin")]
|
||||
[InlineData("<filename.bin>", false, "filename.bin")]
|
||||
[InlineData("<filename.bin>", true, "filename.bin")]
|
||||
[InlineData("1.2.3.4..bin", false, "1.2.3.4..bin")]
|
||||
[InlineData("1.2.3.4..bin", true, "1.2.3.4..bin")]
|
||||
[InlineData("dir/filename.bin", false, "dir/filename.bin")]
|
||||
[InlineData("dir/filename.bin", true, "dir/filename.bin")]
|
||||
[InlineData(" dir / filename.bin", false, "dir/filename.bin")]
|
||||
[InlineData(" dir / filename.bin", true, "dir/filename.bin")]
|
||||
[InlineData("\0dir/\0filename.bin", false, "_dir/_filename.bin")]
|
||||
[InlineData("\0dir/\0filename.bin", true, "_dir/_filename.bin")]
|
||||
public void NormalizeOutputPathsTest(string? path, bool getFullPath, string expected)
|
||||
{
|
||||
// Modify expected to account for test data if necessary
|
||||
if (getFullPath && !string.IsNullOrEmpty(expected))
|
||||
expected = Path.GetFullPath(expected);
|
||||
|
||||
string actual = FrontendTool.NormalizeOutputPaths(path, getFullPath);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using SabreTools.RedumpLib.Data.Sections;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Test.Frontend.Tools
|
||||
namespace MPF.Frontend.Test.Tools
|
||||
{
|
||||
public class InfoToolTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null, "")]
|
||||
[InlineData(" ", " ")]
|
||||
[InlineData("super\\blah.bin", "super\\blah.bin")]
|
||||
[InlineData("super\\hero\\blah.bin", "super\\hero\\blah.bin")]
|
||||
[InlineData("super.hero\\blah.bin", "super.hero\\blah.bin")]
|
||||
[InlineData("superhero\\blah.rev.bin", "superhero\\blah.rev.bin")]
|
||||
[InlineData("super&hero\\blah.bin", "super&hero\\blah.bin")]
|
||||
[InlineData("superhero\\blah&foo.bin", "superhero\\blah&foo.bin")]
|
||||
public void NormalizeOutputPathsTest(string? outputPath, string? expectedPath)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(expectedPath))
|
||||
expectedPath = Path.GetFullPath(expectedPath);
|
||||
|
||||
string actualPath = FrontendTool.NormalizeOutputPaths(outputPath, true);
|
||||
Assert.Equal(expectedPath, actualPath);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsCompleteTest()
|
||||
public void ProcessSpecialFields_Complete()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
@@ -54,9 +35,9 @@ namespace MPF.Test.Frontend.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');
|
||||
@@ -64,27 +45,11 @@ namespace MPF.Test.Frontend.Tools
|
||||
|
||||
// Validate the lines
|
||||
Assert.Equal(3, splitComments.Length);
|
||||
Assert.Equal(5, splitContents.Length);
|
||||
Assert.Equal(4, splitContents.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsNullObjectTest()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
{
|
||||
CommonDiscInfo = null,
|
||||
};
|
||||
|
||||
// Process the special fields
|
||||
Formatter.ProcessSpecialFields(info);
|
||||
|
||||
// Validate
|
||||
Assert.Null(info.CommonDiscInfo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsNullCommentsContentsTest()
|
||||
public void ProcessSpecialFields_NullStrings()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
@@ -110,9 +75,9 @@ namespace MPF.Test.Frontend.Tools
|
||||
|
||||
// Validate the basics
|
||||
Assert.NotNull(info.CommonDiscInfo.Comments);
|
||||
Assert.Null(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.CommentsSpecialFields);
|
||||
Assert.NotNull(info.CommonDiscInfo.Contents);
|
||||
Assert.Null(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
Assert.Empty(info.CommonDiscInfo.ContentsSpecialFields);
|
||||
|
||||
// Split the values
|
||||
string[] splitComments = info.CommonDiscInfo.Comments.Split('\n');
|
||||
@@ -124,7 +89,7 @@ namespace MPF.Test.Frontend.Tools
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessSpecialFieldsNullDictionariesTest()
|
||||
public void ProcessSpecialFields_EmptyDictionaries()
|
||||
{
|
||||
// Create a new SubmissionInfo object
|
||||
var info = new SubmissionInfo()
|
||||
@@ -132,10 +97,10 @@ namespace MPF.Test.Frontend.Tools
|
||||
CommonDiscInfo = new CommonDiscInfoSection()
|
||||
{
|
||||
Comments = "This is a comments line\n[T:ISBN] ISBN Value",
|
||||
CommentsSpecialFields = null,
|
||||
CommentsSpecialFields = [],
|
||||
|
||||
Contents = "This is a contents line\n[T:GF] Game Footage",
|
||||
ContentsSpecialFields = null,
|
||||
ContentsSpecialFields = [],
|
||||
}
|
||||
};
|
||||
|
||||
@@ -144,9 +109,9 @@ namespace MPF.Test.Frontend.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');
|
||||
837
MPF.Frontend.Test/Tools/ProtectionToolTests.cs
Normal file
837
MPF.Frontend.Test/Tools/ProtectionToolTests.cs
Normal file
@@ -0,0 +1,837 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MPF.Frontend.Tools;
|
||||
using Xunit;
|
||||
|
||||
namespace MPF.Frontend.Test.Tools
|
||||
{
|
||||
public class ProtectionToolTests
|
||||
{
|
||||
#region SanitizeContextSensitiveProtections
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_Empty_NoException()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_NoMatch_NoChange()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_Match_NoSub_NoChange()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
protections["File2"] = ["SecuROM Release Control - ANYTHING", "Protection 2"];
|
||||
protections["File3"] = ["Protection 1", "SecuROM Release Control -"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
Assert.Contains("File2", keys);
|
||||
Assert.Contains("File3", keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_Match_Sub_Change()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
protections["File2"] = ["SecuROM Release Control - ANYTHING"];
|
||||
protections["File2/FileA"] = ["ANYTHING GitHub ANYTHING"];
|
||||
protections["File2/FileB"] = ["SecuROM 7"];
|
||||
protections["File2/FileC"] = ["SecuROM 8"];
|
||||
protections["File2/FileD"] = ["SecuROM Content Activation"];
|
||||
protections["File2/FileE"] = ["SecuROM Data File Activation"];
|
||||
protections["File2/FileF"] = ["Unlock"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
Assert.Contains("File2", keys);
|
||||
Assert.Contains("File2/FileA", keys);
|
||||
Assert.DoesNotContain("File2/FileB", keys);
|
||||
Assert.DoesNotContain("File2/FileC", keys);
|
||||
Assert.DoesNotContain("File2/FileD", keys);
|
||||
Assert.DoesNotContain("File2/FileE", keys);
|
||||
Assert.DoesNotContain("File2/FileF", keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeContextSensitiveProtections_MultiMatch_Sub_Change()
|
||||
{
|
||||
Dictionary<string, List<string>>? protections = [];
|
||||
protections["File1"] = ["Protection 1", "Protection 2"];
|
||||
protections["File2"] = ["SecuROM Release Control - ANYTHING"];
|
||||
protections["File2/FileA"] = ["ANYTHING GitHub ANYTHING"];
|
||||
protections["File2/FileB"] = ["SecuROM 7"];
|
||||
protections["File2/FileC"] = ["SecuROM 8"];
|
||||
protections["File3"] = ["SecuROM Release Control - ANYTHING"];
|
||||
protections["File3/FileD"] = ["SecuROM Content Activation"];
|
||||
protections["File3/FileE"] = ["SecuROM Data File Activation"];
|
||||
protections["File3/FileF"] = ["Unlock"];
|
||||
|
||||
var actual = ProtectionTool.SanitizeContextSensitiveProtections(protections);
|
||||
Assert.NotNull(actual);
|
||||
|
||||
string[] keys = [.. actual.Keys];
|
||||
Assert.Contains("File1", keys);
|
||||
Assert.Contains("File2", keys);
|
||||
Assert.Contains("File2/FileA", keys);
|
||||
Assert.DoesNotContain("File2/FileB", keys);
|
||||
Assert.DoesNotContain("File2/FileC", keys);
|
||||
Assert.Contains("File3", keys);
|
||||
Assert.DoesNotContain("File3/FileD", keys);
|
||||
Assert.DoesNotContain("File3/FileE", keys);
|
||||
Assert.DoesNotContain("File3/FileF", keys);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SanitizeFoundProtections
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_Exception()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Anything Else Protection",
|
||||
"[Access issue when opening file",
|
||||
"[Exception opening file",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Anything Else Protection, Exception occurred while scanning [RESCAN NEEDED]", sanitized);
|
||||
}
|
||||
|
||||
#region Game Engine
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_RenderWare()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"RenderWare",
|
||||
"RenderWare ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Packers
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_dotNetReactor()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
".NET Reactor",
|
||||
".NET Reactor ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_SevenZipSFX()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"7-Zip SFX",
|
||||
"7-Zip SFX ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_ASPack()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"ASPack",
|
||||
"ASPack ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_AutoPlayMediaStudio()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"AutoPlay Media Studio",
|
||||
"AutoPlay Media Studio ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_CaphyonAdvancedInstaller()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Caphyon Advanced Installer",
|
||||
"Caphyon Advanced Installer ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_CExe()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"CExe",
|
||||
"CExe ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_dotFuscator()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"dotFuscator",
|
||||
"dotFuscator ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_EmbeddedArchive()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Embedded 7-zip Archive",
|
||||
"Embedded PKZIP Archive",
|
||||
"Embedded RAR Archive",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_EmbeddedExecutable()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Embedded Executable",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_EXEStealth()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"EXE Stealth",
|
||||
"EXE Stealth ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_GenteeInstaller()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Gentee Installer",
|
||||
"Gentee Installer ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_HyperTechCrackProof()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"HyperTech CrackProof",
|
||||
"HyperTech CrackProof ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_InnoSetup()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Inno Setup",
|
||||
"Inno Setup ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_InstallAnywhere()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"InstallAnywhere",
|
||||
"InstallAnywhere ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_InstallerVISE()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Installer VISE",
|
||||
"Installer VISE ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_IntelInstallationFramework()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Intel Installation Framework",
|
||||
"Intel Installation Framework ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_MicrosoftCABSFX()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Microsoft CAB SFX",
|
||||
"Microsoft CAB SFX ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
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()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"NeoLite",
|
||||
"NeoLite ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_NSIS()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"NSIS",
|
||||
"NSIS ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_PECompact()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"PE Compact",
|
||||
"PE Compact ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_PEtite()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"PEtite",
|
||||
"PEtite ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_SetupFactory()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Setup Factory",
|
||||
"Setup Factory ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_Shrinker()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Shrinker",
|
||||
"Shrinker ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_UPX()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"UPX",
|
||||
"UPX ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_WinRARSFX()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"WinRAR SFX",
|
||||
"WinRAR SFX ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_WinZipSFX()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"WinZip SFX",
|
||||
"WinZip SFX ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_WiseInstaller()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Wise Installation",
|
||||
"Wise Installation ANYTHING",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protections
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_ActiveMARK()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"ActiveMARK",
|
||||
"ActiveMARK 5",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("ActiveMARK 5", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_CactusDataShield()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Cactus Data Shield 200",
|
||||
"Cactus Data Shield 200 (Build 3.0.100a)",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Cactus Data Shield 200 (Build 3.0.100a)", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_CactusDataShieldMacrovision()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Anything Else Protection",
|
||||
"Cactus Data Shield 300 (Confirm presence of other CDS-300 files)",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Anything Else Protection, Cactus Data Shield 300", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_CDCheck()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Anything Else Protection",
|
||||
"Executable-Based CD Check",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Anything Else Protection", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_CDCops()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"CD-Cops",
|
||||
"CD-Cops v1.2.0",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("CD-Cops v1.2.0", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_CDKey()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Anything Else Protection",
|
||||
"CD-Key / Serial",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Anything Else Protection", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_EACdKey()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"EA CdKey Registration Module",
|
||||
"EA CdKey Registration Module v1.2.0",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Empty(sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_EADRM()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"EA DRM Protection",
|
||||
"EA DRM Protection v1.2.0",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("EA DRM Protection v1.2.0", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_GFWL()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Games for Windows LIVE",
|
||||
"Games for Windows LIVE v1.2.0",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Games for Windows LIVE v1.2.0", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_GFWLZDPP()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Games for Windows LIVE",
|
||||
"Games for Windows LIVE Zero Day Piracy Protection",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Games for Windows LIVE, Games for Windows LIVE Zero Day Piracy Protection", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_ImpulseReactor()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Impulse Reactor",
|
||||
"Impulse Reactor Core Module v1.2.0",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Impulse Reactor Core Module v1.2.0", sanitized);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(1)]
|
||||
[InlineData(2)]
|
||||
[InlineData(3)]
|
||||
public void SanitizeFoundProtections_JoWoodXProtTest(int skip)
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"JoWood X-Prot 1.2.0.00",
|
||||
"JoWood X-Prot v2",
|
||||
"JoWood X-Prot v1.4+",
|
||||
"JoWood X-Prot v1.0-v1.3",
|
||||
"JoWood X-Prot",
|
||||
];
|
||||
|
||||
// Safeguard for the future
|
||||
if (skip >= protections.Count)
|
||||
throw new ArgumentException("Invalid skip value", nameof(skip));
|
||||
|
||||
// The list is in order of preference
|
||||
protections = [.. protections.Skip(skip)];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(protections[0], sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_OnlineRegistration()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Anything Else Protection",
|
||||
"Executable-Based Online Registration",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Anything Else Protection", sanitized);
|
||||
}
|
||||
|
||||
[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, "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)")]
|
||||
[InlineData(8, "SafeDisc 2+")]
|
||||
public void SanitizeFoundProtections_SafeDisc(int skip, string expected)
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"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 1.11.111 / SafeDisc 1.11.111",
|
||||
"Macrovision Security Driver",
|
||||
"SafeDisc Lite",
|
||||
"SafeDisc 3+ (DVD)",
|
||||
"SafeDisc 2+",
|
||||
"Macrovision Protection File",
|
||||
];
|
||||
|
||||
// Safeguard for the future
|
||||
if (skip >= protections.Count)
|
||||
throw new ArgumentException("Invalid skip value", nameof(skip));
|
||||
|
||||
// The list is in order of preference
|
||||
protections = [.. protections.Skip(skip)];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(expected, sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtectsion_SafeDisc_MacrovisionSecurityDriver()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Macrovision Protection File [Likely indicates either SafeDisc 1.45.011+ (CD) or CDS-300]",
|
||||
"Macrovision Security Driver 4.00.060 / SafeDisc 4.00.000-4.70.000",
|
||||
"SafeDisc 4.00.000-4.00.003",
|
||||
"SafeDisc 4.00.002, Macrovision Protected Application"
|
||||
];
|
||||
|
||||
string expected = "SafeDisc 4.00.002";
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal(expected, sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_SecuROM()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"SecuROM Release Control",
|
||||
"SecuROM Release Control - ANYTHING",
|
||||
"SecuROM Release Control - ANYTHING ELSE",
|
||||
"SecuROM Release Control - EVEN MORE",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("SecuROM Release Control", sanitized);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(1)]
|
||||
[InlineData(2)]
|
||||
[InlineData(3)]
|
||||
public void SanitizeFoundProtections_StarForce(int skip)
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"StarForce 1.20.000.000",
|
||||
"StarForce 5 [Protected Module]",
|
||||
"StarForce 5",
|
||||
"StarForce 3-5",
|
||||
"StarForce",
|
||||
];
|
||||
|
||||
// Safeguard for the future
|
||||
if (skip >= protections.Count)
|
||||
throw new ArgumentException("Invalid skip value", nameof(skip));
|
||||
|
||||
// The list is in order of preference
|
||||
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()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"Sysiphus",
|
||||
"Sysiphus v1.2.0",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("Sysiphus v1.2.0", sanitized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SanitizeFoundProtections_XCP()
|
||||
{
|
||||
List<string> protections =
|
||||
[
|
||||
"XCP",
|
||||
"XCP v1.2.0",
|
||||
];
|
||||
|
||||
string sanitized = ProtectionTool.SanitizeFoundProtections(protections);
|
||||
Assert.Equal("XCP v1.2.0", sanitized);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
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);
|
||||
@@ -28,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
|
||||
@@ -40,23 +39,22 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
/// Generate all elements associated with the data enum type
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Element<T>> GenerateElements()
|
||||
public static List<Element<TEnum>> GenerateElements()
|
||||
{
|
||||
return Enum.GetValues(typeof(T))
|
||||
.OfType<T>()
|
||||
.Select(e => new Element<T>(e));
|
||||
var enumArr = (TEnum[])Enum.GetValues(typeof(TEnum));
|
||||
return [.. Array.ConvertAll(enumArr, e => new Element<TEnum>(e))];
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return Equals(obj as Element<T>);
|
||||
return Equals(obj as Element<TEnum>);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(Element<T>? other)
|
||||
public bool Equals(Element<TEnum>? other)
|
||||
{
|
||||
if (other == null)
|
||||
if (other is null)
|
||||
return false;
|
||||
|
||||
return Name == other.Name;
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
/// <summary>
|
||||
/// Display name for the combo box element
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
public string Name { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if NET35_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Frontend.ComboBoxItems
|
||||
@@ -50,13 +52,26 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
/// Generate all elements for the known system combo box
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<RedumpSystemComboBoxItem> GenerateElements()
|
||||
public static List<RedumpSystemComboBoxItem> GenerateElements()
|
||||
{
|
||||
var knownSystems = Enum.GetValues(typeof(RedumpSystem))
|
||||
.OfType<RedumpSystem?>()
|
||||
.Where(s => !s.IsMarker() && s.GetCategory() != SystemCategory.NONE)
|
||||
.ToList();
|
||||
var enumArr = (RedumpSystem[])Enum.GetValues(typeof(RedumpSystem));
|
||||
var nullableArr = Array.ConvertAll(enumArr, s => (RedumpSystem?)s);
|
||||
var knownSystems = Array.FindAll(nullableArr,
|
||||
s => !s.IsMarker() && s.GetCategory() != SystemCategory.NONE);
|
||||
|
||||
#if NET20
|
||||
// The resulting dictionary does not have ordered value lists
|
||||
var mapping = new Dictionary<SystemCategory, List<RedumpSystem?>>();
|
||||
foreach (var knownSystem in knownSystems)
|
||||
{
|
||||
var category = knownSystem.GetCategory();
|
||||
if (!mapping.ContainsKey(category))
|
||||
mapping[category] = [];
|
||||
|
||||
mapping[category].Add(knownSystem);
|
||||
}
|
||||
#else
|
||||
// The resulting dictionary has ordered value lists
|
||||
Dictionary<SystemCategory, List<RedumpSystem?>> mapping = knownSystems
|
||||
.GroupBy(s => s.GetCategory())
|
||||
.ToDictionary(
|
||||
@@ -65,10 +80,11 @@ namespace MPF.Frontend.ComboBoxItems
|
||||
.OrderBy(s => s.LongName())
|
||||
.ToList()
|
||||
);
|
||||
#endif
|
||||
|
||||
var systemsValues = new List<RedumpSystemComboBoxItem>
|
||||
{
|
||||
new RedumpSystemComboBoxItem((RedumpSystem?)null),
|
||||
new((RedumpSystem?)null),
|
||||
};
|
||||
|
||||
foreach (var group in mapping)
|
||||
@@ -89,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;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using BinaryObjectScanner;
|
||||
using MPF.Frontend;
|
||||
|
||||
namespace MPF.Check
|
||||
namespace MPF.Frontend
|
||||
{
|
||||
public static class ConsoleLogger
|
||||
{
|
||||
@@ -11,7 +10,14 @@ namespace MPF.Check
|
||||
/// </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>
|
||||
@@ -1,16 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using Microsoft.Management.Infrastructure;
|
||||
using Microsoft.Management.Infrastructure.Generic;
|
||||
#endif
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Frontend
|
||||
@@ -92,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
|
||||
@@ -112,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
|
||||
@@ -142,26 +140,32 @@ namespace MPF.Frontend
|
||||
public static List<Drive> CreateListOfDrives(bool ignoreFixedDrives)
|
||||
{
|
||||
var drives = GetDriveList(ignoreFixedDrives);
|
||||
drives = [.. drives.OrderBy(i => i == null ? "\0" : i.Name)];
|
||||
return drives;
|
||||
drives.Sort((d1, d2) =>
|
||||
{
|
||||
string d1Name = d1?.Name is null ? "\0" : d1.Name;
|
||||
string d2Name = d2?.Name is null ? "\0" : d2.Name;
|
||||
return d1Name.CompareTo(d2Name);
|
||||
});
|
||||
return [.. drives];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current media type from drive letter
|
||||
/// </summary>
|
||||
/// <param name="system"></param>
|
||||
/// <returns></returns>
|
||||
public (MediaType?, string?) GetMediaType(RedumpSystem? system)
|
||||
/// <param name="system">Currently selected system</param>
|
||||
/// <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)
|
||||
{
|
||||
case Frontend.InternalDriveType.Floppy:
|
||||
return (MediaType.FloppyDisk, null);
|
||||
return MediaType.FloppyDisk;
|
||||
case Frontend.InternalDriveType.HardDisk:
|
||||
return (MediaType.HardDisk, null);
|
||||
return MediaType.HardDisk;
|
||||
case Frontend.InternalDriveType.Removable:
|
||||
return (MediaType.FlashDrive, null);
|
||||
return MediaType.FlashDrive;
|
||||
}
|
||||
|
||||
// Some systems should default to certain media types
|
||||
@@ -174,18 +178,18 @@ namespace MPF.Frontend
|
||||
case RedumpSystem.SegaSaturn:
|
||||
case RedumpSystem.SonyPlayStation:
|
||||
case RedumpSystem.VideoCD:
|
||||
return (MediaType.CDROM, null);
|
||||
return MediaType.CDROM;
|
||||
|
||||
// DVD
|
||||
case RedumpSystem.DVDAudio:
|
||||
case RedumpSystem.DVDVideo:
|
||||
case RedumpSystem.MicrosoftXbox:
|
||||
case RedumpSystem.MicrosoftXbox360:
|
||||
return (MediaType.DVD, null);
|
||||
return MediaType.DVD;
|
||||
|
||||
// HD-DVD
|
||||
case RedumpSystem.HDDVDVideo:
|
||||
return (MediaType.HDDVD, null);
|
||||
return MediaType.HDDVD;
|
||||
|
||||
// Blu-ray
|
||||
case RedumpSystem.BDVideo:
|
||||
@@ -194,34 +198,35 @@ namespace MPF.Frontend
|
||||
case RedumpSystem.SonyPlayStation3:
|
||||
case RedumpSystem.SonyPlayStation4:
|
||||
case RedumpSystem.SonyPlayStation5:
|
||||
return (MediaType.BluRay, null);
|
||||
return MediaType.BluRay;
|
||||
|
||||
// GameCube
|
||||
case RedumpSystem.NintendoGameCube:
|
||||
return (MediaType.NintendoGameCubeGameDisc, null);
|
||||
return MediaType.NintendoGameCubeGameDisc;
|
||||
|
||||
// Wii
|
||||
case RedumpSystem.NintendoWii:
|
||||
return (MediaType.NintendoWiiOpticalDisc, null);
|
||||
return MediaType.NintendoWiiOpticalDisc;
|
||||
|
||||
// WiiU
|
||||
case RedumpSystem.NintendoWiiU:
|
||||
return (MediaType.NintendoWiiUOpticalDisc, null);
|
||||
return MediaType.NintendoWiiUOpticalDisc;
|
||||
|
||||
// PSP
|
||||
case RedumpSystem.SonyPlayStationPortable:
|
||||
return (MediaType.UMD, null);
|
||||
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"))
|
||||
return (MediaType.CDROM, null);
|
||||
return MediaType.CDROM;
|
||||
else if (TotalSize > 800_000_000 && TotalSize <= 8_540_000_000 && (DriveFormat == "CDFS" || DriveFormat == "UDF"))
|
||||
return (MediaType.DVD, null);
|
||||
return MediaType.DVD;
|
||||
else if (TotalSize > 8_540_000_000)
|
||||
return (MediaType.BluRay, null);
|
||||
return MediaType.BluRay;
|
||||
|
||||
return (null, "Could not determine media type!");
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -229,554 +234,12 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public void RefreshDrive()
|
||||
{
|
||||
var driveInfo = DriveInfo.GetDrives().FirstOrDefault(d => d?.Name == Name);
|
||||
var driveInfo = Array.Find(DriveInfo.GetDrives(), d => d?.Name == Name);
|
||||
PopulateFromDriveInfo(driveInfo);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Information Extraction
|
||||
|
||||
/// <summary>
|
||||
/// Get the EXE name from a PlayStation disc, if possible
|
||||
/// </summary>
|
||||
/// <returns>Executable name on success, null otherwise</returns>
|
||||
public string? GetPlayStationExecutableName()
|
||||
{
|
||||
// If there's no drive path, we can't get exe name
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't get exe name
|
||||
if (!Directory.Exists(Name))
|
||||
return null;
|
||||
|
||||
// Get the two paths that we will need to check
|
||||
string psxExePath = Path.Combine(Name, "PSX.EXE");
|
||||
string systemCnfPath = Path.Combine(Name, "SYSTEM.CNF");
|
||||
|
||||
// Read the CNF file as an INI file
|
||||
var systemCnf = new IniFile(systemCnfPath);
|
||||
string? bootValue = string.Empty;
|
||||
|
||||
// PlayStation uses "BOOT" as the key
|
||||
if (systemCnf.ContainsKey("BOOT"))
|
||||
bootValue = systemCnf["BOOT"];
|
||||
|
||||
// PlayStation 2 uses "BOOT2" as the key
|
||||
if (systemCnf.ContainsKey("BOOT2"))
|
||||
bootValue = systemCnf["BOOT2"];
|
||||
|
||||
// If we had any boot value, parse it and get the executable name
|
||||
if (!string.IsNullOrEmpty(bootValue))
|
||||
{
|
||||
var match = Regex.Match(bootValue, @"cdrom.?:\\?(.*)", RegexOptions.Compiled);
|
||||
if (match.Groups.Count > 1)
|
||||
{
|
||||
string? serial = match.Groups[1].Value;
|
||||
|
||||
// Some games may have the EXE in a subfolder
|
||||
serial = Path.GetFileName(serial);
|
||||
|
||||
return serial;
|
||||
}
|
||||
}
|
||||
|
||||
// If the SYSTEM.CNF value can't be found, try PSX.EXE
|
||||
if (File.Exists(psxExePath))
|
||||
return "PSX.EXE";
|
||||
|
||||
// If neither can be found, we return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the EXE date from a PlayStation disc, if possible
|
||||
/// </summary>
|
||||
/// <param name="serial">Internal disc serial, if possible</param>
|
||||
/// <param name="region">Output region, if possible</param>
|
||||
/// <param name="date">Output EXE date in "yyyy-mm-dd" format if possible, null on error</param>
|
||||
/// <returns>True if information could be determined, false otherwise</returns>
|
||||
public bool GetPlayStationExecutableInfo(out string? serial, out Region? region, out string? date)
|
||||
{
|
||||
serial = null; region = null; date = null;
|
||||
|
||||
// If there's no drive path, we can't do this part
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return false;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
if (!Directory.Exists(Name))
|
||||
return false;
|
||||
|
||||
// Get the executable name
|
||||
string? exeName = GetPlayStationExecutableName();
|
||||
|
||||
// If no executable found, we can't do this part
|
||||
if (exeName == null)
|
||||
return false;
|
||||
|
||||
// EXE name may have a trailing `;` after
|
||||
// EXE name should always be in all caps
|
||||
exeName = exeName
|
||||
.Split(';')[0]
|
||||
.ToUpperInvariant();
|
||||
|
||||
// Serial is most of the EXE name normalized
|
||||
serial = exeName
|
||||
.Replace('_', '-')
|
||||
.Replace(".", string.Empty);
|
||||
|
||||
// Get the region, if possible
|
||||
region = GetPlayStationRegion(exeName);
|
||||
|
||||
// Now that we have the EXE name, try to get the fileinfo for it
|
||||
string exePath = Path.Combine(Name, exeName);
|
||||
if (!File.Exists(exePath))
|
||||
return false;
|
||||
|
||||
// Fix the Y2K timestamp issue
|
||||
var fi = new FileInfo(exePath);
|
||||
var dt = new DateTime(fi.LastWriteTimeUtc.Year >= 1900 && fi.LastWriteTimeUtc.Year < 1920 ? 2000 + fi.LastWriteTimeUtc.Year % 100 : fi.LastWriteTimeUtc.Year,
|
||||
fi.LastWriteTimeUtc.Month, fi.LastWriteTimeUtc.Day);
|
||||
date = dt.ToString("yyyy-MM-dd");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the region based on the PlayStation serial code
|
||||
/// </summary>
|
||||
/// <param name="serial">PlayStation serial code</param>
|
||||
/// <returns>Region mapped from name, if possible</returns>
|
||||
public static Region? GetPlayStationRegion(string? serial)
|
||||
{
|
||||
// If we have a fully invalid serial
|
||||
if (string.IsNullOrEmpty(serial))
|
||||
return null;
|
||||
|
||||
// Standardized "S" serials
|
||||
if (serial!.StartsWith("S"))
|
||||
{
|
||||
// string publisher = serial[0] + serial[1];
|
||||
// char secondRegion = serial[3];
|
||||
switch (serial[2])
|
||||
{
|
||||
case 'A': return Region.Asia;
|
||||
case 'C': return Region.China;
|
||||
case 'E': return Region.Europe;
|
||||
case 'K': return Region.SouthKorea;
|
||||
case 'U': return Region.UnitedStatesOfAmerica;
|
||||
case 'P':
|
||||
// Region of S_P_ serials may be Japan, Asia, or SouthKorea
|
||||
return serial[3] switch
|
||||
{
|
||||
// Check first two digits of S_PS serial
|
||||
'S' => (Region?)(serial.Substring(5, 2) switch
|
||||
{
|
||||
"46" => Region.SouthKorea,
|
||||
"51" => Region.Asia,
|
||||
"56" => Region.SouthKorea,
|
||||
"55" => Region.Asia,
|
||||
_ => Region.Japan,
|
||||
}),
|
||||
|
||||
// Check first three digits of S_PM serial
|
||||
'M' => (Region?)(serial.Substring(5, 3) switch
|
||||
{
|
||||
"645" => Region.SouthKorea,
|
||||
"675" => Region.SouthKorea,
|
||||
"885" => Region.SouthKorea,
|
||||
_ => Region.Japan, // Remaining S_PM serials may be Japan or Asia
|
||||
}),
|
||||
_ => (Region?)Region.Japan,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Japan-only special serial
|
||||
else if (serial.StartsWith("PAPX"))
|
||||
return Region.Japan;
|
||||
|
||||
// Region appears entirely random
|
||||
else if (serial.StartsWith("PABX"))
|
||||
return null;
|
||||
|
||||
// Region appears entirely random
|
||||
else if (serial.StartsWith("PBPX"))
|
||||
return null;
|
||||
|
||||
// Japan-only special serial
|
||||
else if (serial.StartsWith("PCBX"))
|
||||
return Region.Japan;
|
||||
|
||||
// Japan-only special serial
|
||||
else if (serial.StartsWith("PCXC"))
|
||||
return Region.Japan;
|
||||
|
||||
// Single disc known, Japan
|
||||
else if (serial.StartsWith("PDBX"))
|
||||
return Region.Japan;
|
||||
|
||||
// Single disc known, Europe
|
||||
else if (serial.StartsWith("PEBX"))
|
||||
return Region.Europe;
|
||||
|
||||
// Single disc known, USA
|
||||
else if (serial.StartsWith("PUBX"))
|
||||
return Region.UnitedStatesOfAmerica;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the version from a PlayStation 2 disc, if possible
|
||||
/// </summary>
|
||||
/// <returns>Game version if possible, null on error</returns>
|
||||
public string? GetPlayStation2Version()
|
||||
{
|
||||
// If there's no drive path, we can't do this part
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
if (!Directory.Exists(Name))
|
||||
return null;
|
||||
|
||||
// Get the SYSTEM.CNF path to check
|
||||
string systemCnfPath = Path.Combine(Name, "SYSTEM.CNF");
|
||||
|
||||
// Try to parse the SYSTEM.CNF file
|
||||
var systemCnf = new IniFile(systemCnfPath);
|
||||
if (systemCnf.ContainsKey("VER"))
|
||||
return systemCnf["VER"];
|
||||
|
||||
// If "VER" can't be found, we can't do much
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the internal serial from a PlayStation 3 disc, if possible
|
||||
/// </summary>
|
||||
/// <returns>Internal disc serial if possible, null on error</returns>
|
||||
public string? GetPlayStation3Serial()
|
||||
{
|
||||
// If there's no drive path, we can't do this part
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
if (!Directory.Exists(Name))
|
||||
return null;
|
||||
|
||||
// Attempt to use PS3_DISC.SFB
|
||||
string sfbPath = Path.Combine(Name, "PS3_DISC.SFB");
|
||||
if (File.Exists(sfbPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
using var br = new BinaryReader(File.OpenRead(sfbPath));
|
||||
br.BaseStream.Seek(0x220, SeekOrigin.Begin);
|
||||
return new string(br.ReadChars(0x10)).TrimEnd('\0');
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to use PARAM.SFO
|
||||
#if NET20 || NET35
|
||||
string sfoPath = Path.Combine(Path.Combine(Name, "PS3_GAME"), "PARAM.SFO");
|
||||
#else
|
||||
string sfoPath = Path.Combine(Name, "PS3_GAME", "PARAM.SFO");
|
||||
#endif
|
||||
if (File.Exists(sfoPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
using var br = new BinaryReader(File.OpenRead(sfoPath));
|
||||
br.BaseStream.Seek(-0x18, SeekOrigin.End);
|
||||
return new string(br.ReadChars(9)).TrimEnd('\0').Insert(4, "-");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the version from a PlayStation 3 disc, if possible
|
||||
/// </summary>
|
||||
/// <returns>Game version if possible, null on error</returns>
|
||||
public string? GetPlayStation3Version()
|
||||
{
|
||||
// If there's no drive path, we can't do this part
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
if (!Directory.Exists(Name))
|
||||
return null;
|
||||
|
||||
// Attempt to use PS3_DISC.SFB
|
||||
string sfbPath = Path.Combine(Name, "PS3_DISC.SFB");
|
||||
if (File.Exists(sfbPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
using var br = new BinaryReader(File.OpenRead(sfbPath));
|
||||
br.BaseStream.Seek(0x230, SeekOrigin.Begin);
|
||||
var discVersion = new string(br.ReadChars(0x10)).TrimEnd('\0');
|
||||
if (!string.IsNullOrEmpty(discVersion))
|
||||
return discVersion;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to use PARAM.SFO
|
||||
#if NET20 || NET35
|
||||
string sfoPath = Path.Combine(Path.Combine(Name, "PS3_GAME"), "PARAM.SFO");
|
||||
#else
|
||||
string sfoPath = Path.Combine(Name, "PS3_GAME", "PARAM.SFO");
|
||||
#endif
|
||||
if (File.Exists(sfoPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
using var br = new BinaryReader(File.OpenRead(sfoPath));
|
||||
br.BaseStream.Seek(-0x08, SeekOrigin.End);
|
||||
return new string(br.ReadChars(5)).TrimEnd('\0');
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the firmware version from a PlayStation 3 disc, if possible
|
||||
/// </summary>
|
||||
/// <returns>Firmware version if possible, null on error</returns>
|
||||
public string? GetPlayStation3FirmwareVersion()
|
||||
{
|
||||
// If there's no drive path, we can't do this part
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
if (!Directory.Exists(Name))
|
||||
return null;
|
||||
|
||||
// Attempt to read from /PS3_UPDATE/PS3UPDAT.PUP
|
||||
#if NET20 || NET35
|
||||
string pupPath = Path.Combine(Path.Combine(Name, "PS3_UPDATE"), "PS3UPDAT.PUP");
|
||||
#else
|
||||
string pupPath = Path.Combine(Name, "PS3_UPDATE", "PS3UPDAT.PUP");
|
||||
#endif
|
||||
if (!File.Exists(pupPath))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
using var br = new BinaryReader(File.OpenRead(pupPath));
|
||||
br.BaseStream.Seek(0x3E, SeekOrigin.Begin);
|
||||
byte[] buf = new byte[2];
|
||||
br.Read(buf, 0, 2);
|
||||
Array.Reverse(buf);
|
||||
short location = BitConverter.ToInt16(buf, 0);
|
||||
br.BaseStream.Seek(location, SeekOrigin.Begin);
|
||||
return new string(br.ReadChars(4));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the internal serial from a PlayStation 4 disc, if possible
|
||||
/// </summary>
|
||||
/// <returns>Internal disc serial if possible, null on error</returns>
|
||||
public string? GetPlayStation4Serial()
|
||||
{
|
||||
// If there's no drive path, we can't do this part
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
if (!Directory.Exists(Name))
|
||||
return null;
|
||||
|
||||
// If we can't find param.sfo, we don't have a PlayStation 4 disc
|
||||
#if NET20 || NET35
|
||||
string paramSfoPath = Path.Combine(Path.Combine(Name, "bd"), "param.sfo");
|
||||
#else
|
||||
string paramSfoPath = Path.Combine(Name, "bd", "param.sfo");
|
||||
#endif
|
||||
if (!File.Exists(paramSfoPath))
|
||||
return null;
|
||||
|
||||
// Let's try reading param.sfo to find the serial at the end of the file
|
||||
try
|
||||
{
|
||||
using var br = new BinaryReader(File.OpenRead(paramSfoPath));
|
||||
br.BaseStream.Seek(-0x14, SeekOrigin.End);
|
||||
return new string(br.ReadChars(9)).Insert(4, "-");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the version from a PlayStation 4 disc, if possible
|
||||
/// </summary>
|
||||
/// <returns>Game version if possible, null on error</returns>
|
||||
public string? GetPlayStation4Version()
|
||||
{
|
||||
// If there's no drive path, we can't do this part
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
if (!Directory.Exists(Name))
|
||||
return null;
|
||||
|
||||
// If we can't find param.sfo, we don't have a PlayStation 4 disc
|
||||
#if NET20 || NET35
|
||||
string paramSfoPath = Path.Combine(Path.Combine(Name, "bd"), "param.sfo");
|
||||
#else
|
||||
string paramSfoPath = Path.Combine(Name, "bd", "param.sfo");
|
||||
#endif
|
||||
if (!File.Exists(paramSfoPath))
|
||||
return null;
|
||||
|
||||
// Let's try reading param.sfo to find the version at the end of the file
|
||||
try
|
||||
{
|
||||
using var br = new BinaryReader(File.OpenRead(paramSfoPath));
|
||||
br.BaseStream.Seek(-0x08, SeekOrigin.End);
|
||||
return new string(br.ReadChars(5));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the internal serial from a PlayStation 5 disc, if possible
|
||||
/// </summary>
|
||||
/// <returns>Internal disc serial if possible, null on error</returns>
|
||||
public string? GetPlayStation5Serial()
|
||||
{
|
||||
// Attempt to get the param.json file
|
||||
var json = GetPlayStation5ParamsJsonFromDrive();
|
||||
if (json == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
return json["disc"]?[0]?["masterDataId"]?.Value<string>()?.Insert(4, "-");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// <summary>
|
||||
/// Get the version from a PlayStation 5 disc, if possible
|
||||
/// </summary>
|
||||
/// <returns>Game version if possible, null on error</returns>
|
||||
public string? GetPlayStation5Version()
|
||||
{
|
||||
// Attempt to get the param.json file
|
||||
var json = GetPlayStation5ParamsJsonFromDrive();
|
||||
if (json == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
return json["masterVersion"]?.Value<string>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the params.json file from a drive path, if possible
|
||||
/// </summary>
|
||||
/// <returns>JObject representing the JSON on success, null on error</returns>
|
||||
private JObject? GetPlayStation5ParamsJsonFromDrive()
|
||||
{
|
||||
// If there's no drive path, we can't do this part
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
if (!Directory.Exists(Name))
|
||||
return null;
|
||||
|
||||
// If we can't find param.json, we don't have a PlayStation 5 disc
|
||||
#if NET20 || NET35
|
||||
string paramJsonPath = Path.Combine(Path.Combine(Name, "bd"), "param.json");
|
||||
#else
|
||||
string paramJsonPath = Path.Combine(Name, "bd", "param.json");
|
||||
#endif
|
||||
return GetPlayStation5ParamsJsonFromFile(paramJsonPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the params.json file from a filename, if possible
|
||||
/// </summary>
|
||||
/// <param name="filename">Filename to check</param>
|
||||
/// <returns>JObject representing the JSON on success, null on error</returns>
|
||||
private static JObject? GetPlayStation5ParamsJsonFromFile(string? filename)
|
||||
{
|
||||
// If the file doesn't exist
|
||||
if (string.IsNullOrEmpty(filename) || !File.Exists(filename))
|
||||
return null;
|
||||
|
||||
// Let's try reading param.json to find the version in the unencrypted JSON
|
||||
try
|
||||
{
|
||||
using var br = new BinaryReader(File.OpenRead(filename));
|
||||
br.BaseStream.Seek(0x800, SeekOrigin.Begin);
|
||||
byte[] jsonBytes = br.ReadBytes((int)(br.BaseStream.Length - 0x800));
|
||||
return JsonConvert.DeserializeObject(Encoding.ASCII.GetString(jsonBytes)) as JObject;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
@@ -800,20 +263,18 @@ namespace MPF.Frontend
|
||||
// TODO: Reduce reliance on `DriveInfo`
|
||||
// https://github.com/aaru-dps/Aaru/blob/5164a154e2145941472f2ee0aeb2eff3338ecbb3/Aaru.Devices/Windows/ListDevices.cs#L66
|
||||
|
||||
// Create an output drive list
|
||||
var drives = new List<Drive>();
|
||||
// Create an output drive array
|
||||
Drive[] drives = [];
|
||||
|
||||
// Get all standard supported drive types
|
||||
try
|
||||
{
|
||||
drives = DriveInfo.GetDrives()
|
||||
.Where(d => desiredDriveTypes.Contains(d.DriveType))
|
||||
.Select(d => Create(ToInternalDriveType(d.DriveType), d.Name) ?? new Drive())
|
||||
.ToList();
|
||||
var filteredDrives = Array.FindAll(DriveInfo.GetDrives(), d => desiredDriveTypes.Contains(d.DriveType));
|
||||
drives = Array.ConvertAll(filteredDrives, d => Create(ToInternalDriveType(d.DriveType), d.Name) ?? new Drive());
|
||||
}
|
||||
catch
|
||||
{
|
||||
return drives;
|
||||
return [.. drives];
|
||||
}
|
||||
|
||||
// Find and update all floppy drives
|
||||
@@ -827,10 +288,14 @@ 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];
|
||||
drives.ForEach(d => { if (d?.Name != null && d.Name[0] == devId) { d.InternalDriveType = Frontend.InternalDriveType.Floppy; } });
|
||||
Array.ForEach(drives, d =>
|
||||
{
|
||||
if (d?.Name is not null && d.Name[0] == devId)
|
||||
d.InternalDriveType = Frontend.InternalDriveType.Floppy;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -840,7 +305,7 @@ namespace MPF.Frontend
|
||||
}
|
||||
#endif
|
||||
|
||||
return drives;
|
||||
return [.. drives];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -850,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,
|
||||
@@ -857,6 +323,7 @@ namespace MPF.Frontend
|
||||
DriveType.Removable => (InternalDriveType?)Frontend.InternalDriveType.Removable,
|
||||
_ => null,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,9 @@ 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;
|
||||
|
||||
@@ -48,8 +51,8 @@ namespace MPF.Frontend
|
||||
#endif
|
||||
}
|
||||
|
||||
if (method != null)
|
||||
return method.Invoke(null, new[] { value }) as string ?? string.Empty;
|
||||
if (method is not null)
|
||||
return method.Invoke(null, [value]) as string ?? string.Empty;
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
@@ -60,6 +63,76 @@ namespace MPF.Frontend
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the DreamdumpSectorOrder enum values
|
||||
/// </summary>
|
||||
/// <param name="order">DreamdumpSectorOrder value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this DreamdumpSectorOrder order)
|
||||
=> ((DreamdumpSectorOrder?)order).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the DreamdumpSectorOrder enum values
|
||||
/// </summary>
|
||||
/// <param name="order">DreamdumpSectorOrder value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this DreamdumpSectorOrder? order)
|
||||
{
|
||||
return order switch
|
||||
{
|
||||
DreamdumpSectorOrder.DATA_C2_SUB => "DATA_C2_SUB",
|
||||
DreamdumpSectorOrder.DATA_SUB_C2 => "DATA_SUB_C2",
|
||||
DreamdumpSectorOrder.DATA_SUB => "DATA_SUB",
|
||||
DreamdumpSectorOrder.DATA_C2 => "DATA_C2",
|
||||
|
||||
DreamdumpSectorOrder.NONE => "Default",
|
||||
_ => "Unknown",
|
||||
};
|
||||
}
|
||||
|
||||
/// <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>
|
||||
@@ -67,12 +140,13 @@ namespace MPF.Frontend
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this InternalProgram? prog)
|
||||
{
|
||||
return (prog) switch
|
||||
return prog switch
|
||||
{
|
||||
#region Dumping support
|
||||
|
||||
InternalProgram.Aaru => "Aaru",
|
||||
InternalProgram.DiscImageCreator => "DiscImageCreator",
|
||||
// InternalProgram.Dreamdump => "Dreamdump",
|
||||
InternalProgram.Redumper => "Redumper",
|
||||
|
||||
#endregion
|
||||
@@ -91,6 +165,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>
|
||||
@@ -98,17 +205,24 @@ namespace MPF.Frontend
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this RedumperReadMethod? method)
|
||||
{
|
||||
return (method) switch
|
||||
return method switch
|
||||
{
|
||||
RedumperReadMethod.D8 => "D8",
|
||||
RedumperReadMethod.BE => "BE",
|
||||
RedumperReadMethod.BE_CDDA => "BE_CDDA",
|
||||
|
||||
RedumperReadMethod.NONE => "Default",
|
||||
_ => "Unknown",
|
||||
};
|
||||
}
|
||||
|
||||
/// <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>
|
||||
@@ -116,7 +230,7 @@ namespace MPF.Frontend
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this RedumperSectorOrder? order)
|
||||
{
|
||||
return (order) switch
|
||||
return order switch
|
||||
{
|
||||
RedumperSectorOrder.DATA_C2_SUB => "DATA_C2_SUB",
|
||||
RedumperSectorOrder.DATA_SUB_C2 => "DATA_SUB_C2",
|
||||
@@ -128,10 +242,234 @@ 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>
|
||||
/// <param name="order">RedumperDriveType value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(this RedumperDriveType? type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
RedumperDriveType.GENERIC => "GENERIC",
|
||||
RedumperDriveType.PLEXTOR => "PLEXTOR",
|
||||
RedumperDriveType.MTK8A => "MTK8A",
|
||||
RedumperDriveType.MTK8B => "MTK8B",
|
||||
RedumperDriveType.MTK8C => "MTK8C",
|
||||
RedumperDriveType.MTK3 => "MTK3",
|
||||
RedumperDriveType.MTK2 => "MTK2",
|
||||
|
||||
RedumperDriveType.NONE => "Default",
|
||||
_ => "Unknown",
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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>
|
||||
/// <param name="prog">InternalProgram value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string ShortName(this InternalProgram? prog)
|
||||
{
|
||||
return prog switch
|
||||
{
|
||||
#region Dumping support
|
||||
|
||||
InternalProgram.Aaru => "aaru",
|
||||
InternalProgram.DiscImageCreator => "dic",
|
||||
// InternalProgram.Dreamdump => "dreamdump",
|
||||
InternalProgram.Redumper => "redumper",
|
||||
|
||||
#endregion
|
||||
|
||||
#region Verification support only
|
||||
|
||||
InternalProgram.CleanRip => "cleanrip",
|
||||
InternalProgram.PS3CFW => "ps3cfw",
|
||||
InternalProgram.UmdImageCreator => "uic",
|
||||
InternalProgram.XboxBackupCreator => "xbc",
|
||||
|
||||
#endregion
|
||||
|
||||
InternalProgram.NONE => "Unknown",
|
||||
_ => "Unknown",
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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>
|
||||
/// <param name="internalProgram">String value to convert</param>
|
||||
/// <returns>InternalProgram represented by the string, if possible</returns>
|
||||
public static InternalProgram ToInternalProgram(this string? internalProgram)
|
||||
{
|
||||
return (internalProgram?.ToLowerInvariant()) switch
|
||||
{
|
||||
// Dumping support
|
||||
"aaru"
|
||||
or "chef"
|
||||
or "dichef"
|
||||
or "discimagechef" => InternalProgram.Aaru,
|
||||
"creator"
|
||||
or "dic"
|
||||
or "dicreator"
|
||||
or "discimagecreator" => InternalProgram.DiscImageCreator,
|
||||
// "dreamdump" => InternalProgram.Dreamdump,
|
||||
"rd"
|
||||
or "redumper" => InternalProgram.Redumper,
|
||||
|
||||
// Verification support only
|
||||
"cleanrip"
|
||||
or "cr" => InternalProgram.CleanRip,
|
||||
"ps3cfw"
|
||||
or "ps3"
|
||||
or "getkey"
|
||||
or "managunz"
|
||||
or "multiman" => InternalProgram.PS3CFW,
|
||||
"uic"
|
||||
or "umd"
|
||||
or "umdcreator"
|
||||
or "umdimagecreator" => InternalProgram.UmdImageCreator,
|
||||
"xbc"
|
||||
or "xbox"
|
||||
or "xbox360"
|
||||
or "xboxcreator"
|
||||
or "xboxbackupcreator" => InternalProgram.XboxBackupCreator,
|
||||
|
||||
_ => InternalProgram.NONE,
|
||||
};
|
||||
}
|
||||
|
||||
/// <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>
|
||||
@@ -143,10 +481,6 @@ namespace MPF.Frontend
|
||||
{
|
||||
"d8" => RedumperReadMethod.D8,
|
||||
"be" => RedumperReadMethod.BE,
|
||||
"be_cdda"
|
||||
or "be cdda"
|
||||
or "be-cdda"
|
||||
or "becdda" => RedumperReadMethod.BE_CDDA,
|
||||
|
||||
_ => RedumperReadMethod.NONE,
|
||||
};
|
||||
@@ -182,6 +516,121 @@ namespace MPF.Frontend
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the RedumperDriveType enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="order">String value to convert</param>
|
||||
/// <returns>RedumperDriveType represented by the string, if possible</returns>
|
||||
public static RedumperDriveType ToRedumperDriveType(this string? type)
|
||||
{
|
||||
return (type?.ToLowerInvariant()) switch
|
||||
{
|
||||
"generic" => RedumperDriveType.GENERIC,
|
||||
"plextor" => RedumperDriveType.PLEXTOR,
|
||||
"mtk8a"
|
||||
or "mtk_8a"
|
||||
or "lg_asus8a"
|
||||
or "lg-asus8a"
|
||||
or "lgasus8a"
|
||||
or "lg_asus_8a"
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
or "lg_asu2"
|
||||
or "lg-asu2"
|
||||
or "lgasu2"
|
||||
or "lg_asu_2"
|
||||
or "lg-asu-2" => RedumperDriveType.MTK2,
|
||||
|
||||
_ => RedumperDriveType.NONE,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functionality Support
|
||||
|
||||
/// <summary>
|
||||
/// Get if a system requires an anti-modchip scan
|
||||
/// </summary>
|
||||
public static bool SupportsAntiModchipScans(this RedumpSystem? system)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
return system switch
|
||||
{
|
||||
RedumpSystem.SonyPlayStation => true,
|
||||
_ => false,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if a system requires a copy protection scan
|
||||
/// </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,
|
||||
RedumpSystem.PocketPC => true,
|
||||
RedumpSystem.RainbowDisc => true,
|
||||
RedumpSystem.SonyElectronicBook => true,
|
||||
_ => false,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,32 @@
|
||||
namespace MPF.Frontend
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface language
|
||||
/// </summary>
|
||||
public enum InterfaceLanguage
|
||||
{
|
||||
/// <summary>
|
||||
/// Default to auto-detecting language
|
||||
/// </summary>
|
||||
AutoDetect = 0,
|
||||
|
||||
// Selectable languages (in Manual Window dropdown)
|
||||
English,
|
||||
French,
|
||||
German,
|
||||
Italian,
|
||||
Japanese,
|
||||
Korean,
|
||||
Polish,
|
||||
Russian,
|
||||
Spanish,
|
||||
Swedish,
|
||||
Ukrainian,
|
||||
|
||||
// Hidden languages (not in Main Window dropdown)
|
||||
L337,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drive type for dumping
|
||||
/// </summary>
|
||||
@@ -21,6 +48,7 @@ namespace MPF.Frontend
|
||||
// Dumping support
|
||||
Aaru,
|
||||
DiscImageCreator,
|
||||
// Dreamdump,
|
||||
Redumper,
|
||||
|
||||
// Verification support only
|
||||
@@ -35,9 +63,10 @@ namespace MPF.Frontend
|
||||
/// </summary>
|
||||
public enum LogLevel
|
||||
{
|
||||
USER,
|
||||
USER_GENERIC,
|
||||
USER_SUCCESS,
|
||||
VERBOSE,
|
||||
ERROR,
|
||||
SECRET,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
MPF.Frontend/Features/ListCodesFeature.cs
Normal file
38
MPF.Frontend/Features/ListCodesFeature.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using SabreTools.CommandLine;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class ListCodesFeature : Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "listcodes";
|
||||
|
||||
private static readonly string[] _flags = ["lc", "listcodes"];
|
||||
|
||||
private const string _description = "List supported comment/content site codes";
|
||||
|
||||
#endregion
|
||||
|
||||
public ListCodesFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine("Supported Site Codes:");
|
||||
foreach (string siteCode in SabreTools.RedumpLib.Data.Extensions.ListSiteCodes())
|
||||
{
|
||||
Console.WriteLine(siteCode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
159
MPF.Frontend/Features/ListConfigFeature.cs
Normal file
159
MPF.Frontend/Features/ListConfigFeature.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Root-level
|
||||
Console.WriteLine($"Configuration Version = {options.Version}");
|
||||
Console.WriteLine($"Check for Updates on Startup = {options.CheckForUpdatesOnStartup}");
|
||||
Console.WriteLine($"Verbose Logging = {options.VerboseLogging}");
|
||||
Console.WriteLine();
|
||||
|
||||
// GUI
|
||||
Console.WriteLine("GUI:");
|
||||
Console.WriteLine($" Copy Update URL to Clipboard = {options.GUI.CopyUpdateUrlToClipboard}");
|
||||
Console.WriteLine($" Open Log Window at Startup = {options.GUI.OpenLogWindowAtStartup}");
|
||||
Console.WriteLine($" Default Interface Language = {options.GUI.DefaultInterfaceLanguage.LongName()}");
|
||||
Console.WriteLine($" Show Debug Menu Item = {options.GUI.ShowDebugViewMenuItem}");
|
||||
Console.WriteLine(" Theming:");
|
||||
Console.WriteLine($" Dark Mode = {options.GUI.Theming.EnableDarkMode}");
|
||||
Console.WriteLine($" Purp Mode = {options.GUI.Theming.EnablePurpMode}");
|
||||
Console.WriteLine($" Custom Background Color = {options.GUI.Theming.CustomBackgroundColor}");
|
||||
Console.WriteLine($" Custom Text Color = {options.GUI.Theming.CustomTextColor}");
|
||||
Console.WriteLine($" Fast Label Update = {options.GUI.FastUpdateLabel}");
|
||||
Console.WriteLine($" Ignore Fixed Drives = {options.GUI.IgnoreFixedDrives}");
|
||||
Console.WriteLine($" Skip System Detection = {options.GUI.SkipSystemDetection}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Dump Paths
|
||||
Console.WriteLine("Dump Paths:");
|
||||
Console.WriteLine($" Aaru Path = {options.Dumping.AaruPath}");
|
||||
Console.WriteLine($" DiscImageCreator Path = {options.Dumping.DiscImageCreatorPath}");
|
||||
Console.WriteLine($" Dreamdump Path = {options.Dumping.DreamdumpPath}");
|
||||
Console.WriteLine($" Redumper Path = {options.Dumping.RedumperPath}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Dump Defaults
|
||||
Console.WriteLine("Dump Defaults:");
|
||||
Console.WriteLine($" Default Program = {options.InternalProgram.LongName()}");
|
||||
Console.WriteLine($" Default Output Path = {options.Dumping.DefaultOutputPath}");
|
||||
Console.WriteLine($" Default System = {options.Dumping.DefaultSystem.LongName()}");
|
||||
Console.WriteLine($" Default CD Speed = {options.Dumping.DumpSpeeds.CD}");
|
||||
Console.WriteLine($" Default DVD Speed = {options.Dumping.DumpSpeeds.DVD}");
|
||||
Console.WriteLine($" Default HD-DVD Speed = {options.Dumping.DumpSpeeds.HDDVD}");
|
||||
Console.WriteLine($" Default Blu-ray Speed = {options.Dumping.DumpSpeeds.Bluray}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Aaru
|
||||
Console.WriteLine("Aaru-Specific Options:");
|
||||
Console.WriteLine($" Enable Debug = {options.Dumping.Aaru.EnableDebug}");
|
||||
Console.WriteLine($" Enable Verbose = {options.Dumping.Aaru.EnableVerbose}");
|
||||
Console.WriteLine($" Force Dumping = {options.Dumping.Aaru.ForceDumping}");
|
||||
Console.WriteLine($" Reread Count = {options.Dumping.Aaru.RereadCount}");
|
||||
Console.WriteLine($" Strip Personal Data = {options.Dumping.Aaru.StripPersonalData}");
|
||||
Console.WriteLine();
|
||||
|
||||
// DiscImageCreator
|
||||
Console.WriteLine("DiscImageCreator-Specific Options:");
|
||||
Console.WriteLine($" Multi-Sector Read Flag = {options.Dumping.DIC.MultiSectorRead}");
|
||||
Console.WriteLine($" Multi-Sector Read Value = {options.Dumping.DIC.MultiSectorReadValue}");
|
||||
Console.WriteLine($" Overly-Secure Flags = {options.Dumping.DIC.ParanoidMode}");
|
||||
Console.WriteLine($" Quiet Flag = {options.Dumping.DIC.QuietMode}");
|
||||
Console.WriteLine($" CD Reread Count = {options.Dumping.DIC.RereadCount}");
|
||||
Console.WriteLine($" DVD Reread Count = {options.Dumping.DIC.DVDRereadCount}");
|
||||
Console.WriteLine($" Use CMI Flag = {options.Dumping.DIC.UseCMIFlag}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Dreamdump
|
||||
Console.WriteLine("Dreamdump-Specific Options:");
|
||||
Console.WriteLine($" Non-Redump Mode = {options.Dumping.Dreamdump.NonRedumpMode}");
|
||||
Console.WriteLine($" Sector Order = {options.Dumping.Dreamdump.SectorOrder.LongName()}");
|
||||
Console.WriteLine($" Reread Count = {options.Dumping.Dreamdump.RereadCount}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Redumper
|
||||
Console.WriteLine("Redumper-Specific Options:");
|
||||
Console.WriteLine($" Enable Skeleton = {options.Dumping.Redumper.EnableSkeleton}");
|
||||
Console.WriteLine($" Enable Verbose = {options.Dumping.Redumper.EnableVerbose}");
|
||||
Console.WriteLine($" Lead-in Retry Count = {options.Dumping.Redumper.LeadinRetryCount}");
|
||||
Console.WriteLine($" Non-Redump Mode = {options.Dumping.Redumper.NonRedumpMode}");
|
||||
Console.WriteLine($" Drive Type = {options.Dumping.Redumper.DriveType.LongName()}");
|
||||
Console.WriteLine($" Read Method = {options.Dumping.Redumper.ReadMethod.LongName()}");
|
||||
Console.WriteLine($" Sector Order = {options.Dumping.Redumper.SectorOrder.LongName()}");
|
||||
Console.WriteLine($" Reread Count = {options.Dumping.Redumper.RereadCount}");
|
||||
Console.WriteLine($" Refine Sector Mode = {options.Dumping.Redumper.RefineSectorMode}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Protection Scanning Options
|
||||
Console.WriteLine("Protection Scanning Options:");
|
||||
Console.WriteLine($" Scan for Protection = {options.Processing.ProtectionScanning.ScanForProtection}");
|
||||
Console.WriteLine($" Scan Archives for Protection = {options.Processing.ProtectionScanning.ScanArchivesForProtection}");
|
||||
Console.WriteLine($" Hide Drive Letters = {options.Processing.ProtectionScanning.HideDriveLetters}");
|
||||
Console.WriteLine($" Include Debug Protection Information = {options.Processing.ProtectionScanning.IncludeDebugProtectionInformation}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Redump Login Information
|
||||
Console.WriteLine("Redump Login Information:");
|
||||
Console.WriteLine($" Pull All Information = {options.Processing.Login.PullAllInformation}");
|
||||
Console.WriteLine($" Redump Username = {options.Processing.Login.RedumpUsername}");
|
||||
Console.WriteLine($" Redump Password = {(string.IsNullOrEmpty(options.Processing.Login.RedumpPassword) ? "[UNSET]" : "[SET]")}");
|
||||
Console.WriteLine($" Retrieve Match Information = {options.Processing.Login.RetrieveMatchInformation}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Media Information
|
||||
Console.WriteLine("Media Information:");
|
||||
Console.WriteLine($" Add Placeholders = {options.Processing.MediaInformation.AddPlaceholders}");
|
||||
Console.WriteLine($" Enable Redump Compatibility = {options.Processing.MediaInformation.EnableRedumpCompatibility}");
|
||||
Console.WriteLine($" Enable Tabs in Input Fields = {options.Processing.MediaInformation.EnableTabsInInputFields}");
|
||||
Console.WriteLine($" Prompt for Media Information = {options.Processing.MediaInformation.PromptForDiscInformation}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Post-Information Options
|
||||
Console.WriteLine("Post-Information Options:");
|
||||
Console.WriteLine($" Add Filename Suffix = {options.Processing.AddFilenameSuffix}");
|
||||
Console.WriteLine($" Compress Log Files = {options.Processing.CompressLogFiles}");
|
||||
Console.WriteLine($" Create IRD After Dumping = {options.Processing.CreateIRDAfterDumping}");
|
||||
Console.WriteLine($" Delete Unnecessary Files = {options.Processing.DeleteUnnecessaryFiles}");
|
||||
Console.WriteLine($" Include Artifacts = {options.Processing.IncludeArtifacts}");
|
||||
Console.WriteLine($" Log Compression = {options.Processing.LogCompression.LongName()}");
|
||||
Console.WriteLine($" Output Submission JSON = {options.Processing.OutputSubmissionJSON}");
|
||||
Console.WriteLine($" Show Disc Eject Reminder = {options.Processing.ShowDiscEjectReminder}");
|
||||
Console.WriteLine();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
38
MPF.Frontend/Features/ListMediaTypesFeature.cs
Normal file
38
MPF.Frontend/Features/ListMediaTypesFeature.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using SabreTools.CommandLine;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class ListMediaTypesFeature : Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "listmedia";
|
||||
|
||||
private static readonly string[] _flags = ["lm", "listmedia"];
|
||||
|
||||
private const string _description = "List supported media types";
|
||||
|
||||
#endregion
|
||||
|
||||
public ListMediaTypesFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine("Supported Media Types:");
|
||||
foreach (string mediaType in SabreTools.RedumpLib.Data.Extensions.ListMediaTypes())
|
||||
{
|
||||
Console.WriteLine(mediaType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
57
MPF.Frontend/Features/ListProgramsFeature.cs
Normal file
57
MPF.Frontend/Features/ListProgramsFeature.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.CommandLine;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class ListProgramsFeature : Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "listprograms";
|
||||
|
||||
private static readonly string[] _flags = ["lp", "listprograms"];
|
||||
|
||||
private const string _description = "List supported dumping program outputs";
|
||||
|
||||
#endregion
|
||||
|
||||
public ListProgramsFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine("Supported Programs:");
|
||||
foreach (string program in ListPrograms())
|
||||
{
|
||||
Console.WriteLine(program);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
|
||||
/// <summary>
|
||||
/// List all programs with their short usable names
|
||||
/// </summary>
|
||||
private static List<string> ListPrograms()
|
||||
{
|
||||
var programs = new List<string>();
|
||||
|
||||
foreach (var val in Enum.GetValues(typeof(InternalProgram)))
|
||||
{
|
||||
if (((InternalProgram)val!) == InternalProgram.NONE)
|
||||
continue;
|
||||
|
||||
programs.Add($"{((InternalProgram?)val).ShortName()} - {((InternalProgram?)val).LongName()}");
|
||||
}
|
||||
|
||||
return programs;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
MPF.Frontend/Features/ListSystemsFeature.cs
Normal file
38
MPF.Frontend/Features/ListSystemsFeature.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using SabreTools.CommandLine;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class ListSystemsFeature : Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "listsystems";
|
||||
|
||||
private static readonly string[] _flags = ["ls", "listsystems"];
|
||||
|
||||
private const string _description = "List supported system types";
|
||||
|
||||
#endregion
|
||||
|
||||
public ListSystemsFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine("Supported Systems:");
|
||||
foreach (string system in SabreTools.RedumpLib.Data.Extensions.ListSystems())
|
||||
{
|
||||
Console.WriteLine(system);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
34
MPF.Frontend/Features/VersionFeature.cs
Normal file
34
MPF.Frontend/Features/VersionFeature.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using MPF.Frontend.Tools;
|
||||
using SabreTools.CommandLine;
|
||||
|
||||
namespace MPF.Frontend.Features
|
||||
{
|
||||
public class VersionFeature : Feature
|
||||
{
|
||||
#region Feature Definition
|
||||
|
||||
public const string DisplayName = "version";
|
||||
|
||||
private static readonly string[] _flags = ["version"];
|
||||
|
||||
private const string _description = "Display the program version";
|
||||
|
||||
#endregion
|
||||
|
||||
public VersionFeature()
|
||||
: base(DisplayName, _flags, _description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine(FrontendTool.GetCurrentVersion() ?? "Unknown version");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Frontend
|
||||
@@ -12,40 +11,36 @@ namespace MPF.Frontend
|
||||
/// <summary>
|
||||
/// Set of all accepted speed values
|
||||
/// </summary>
|
||||
private static readonly List<int> _speedValues = [1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72];
|
||||
private static readonly List<int> _speedValues = [0, 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72];
|
||||
|
||||
/// <summary>
|
||||
/// Set of accepted speeds for CD and GD media
|
||||
/// </summary>
|
||||
public static IList<int> CD => _speedValues.Where(s => s <= 72).ToList();
|
||||
public static List<int> CD => _speedValues.FindAll(s => s <= 72);
|
||||
|
||||
/// <summary>
|
||||
/// Set of accepted speeds for DVD media
|
||||
/// </summary>
|
||||
public static IList<int> DVD => _speedValues.Where(s => s <= 24).ToList();
|
||||
public static List<int> DVD => _speedValues.FindAll(s => s <= 24);
|
||||
|
||||
/// <summary>
|
||||
/// Set of accepted speeds for HD-DVD media
|
||||
/// </summary>
|
||||
public static IList<int> HDDVD => _speedValues.Where(s => s <= 24).ToList();
|
||||
public static List<int> HDDVD => _speedValues.FindAll(s => s <= 24);
|
||||
|
||||
/// <summary>
|
||||
/// Set of accepted speeds for BD media
|
||||
/// </summary>
|
||||
public static IList<int> BD => _speedValues.Where(s => s <= 16).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Set of accepted speeds for all other media
|
||||
/// </summary>
|
||||
public static IList<int> Unknown => _speedValues.Where(s => s <= 1).ToList();
|
||||
public static List<int> BD => _speedValues.FindAll(s => s <= 16);
|
||||
|
||||
/// <summary>
|
||||
/// Get list of all drive speeds for a given MediaType
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType? that represents the current item</param>
|
||||
/// <returns>Read-only list of drive speeds</returns>
|
||||
public static IList<int> GetSpeedsForMediaType(MediaType? type)
|
||||
public static List<int> GetSpeedsForMediaType(MediaType? type)
|
||||
{
|
||||
#pragma warning disable IDE0072
|
||||
return type switch
|
||||
{
|
||||
MediaType.CDROM
|
||||
@@ -54,9 +49,13 @@ namespace MPF.Frontend
|
||||
or MediaType.NintendoGameCubeGameDisc
|
||||
or MediaType.NintendoWiiOpticalDisc => DVD,
|
||||
MediaType.HDDVD => HDDVD,
|
||||
MediaType.BluRay => BD,
|
||||
_ => Unknown,
|
||||
MediaType.BluRay
|
||||
or MediaType.NintendoWiiUOpticalDisc => BD,
|
||||
|
||||
// Default to CD speed range
|
||||
_ => CD,
|
||||
};
|
||||
#pragma warning restore IDE0072
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user