mirror of
https://github.com/SabreTools/MPF.git
synced 2026-02-04 13:45:29 +00:00
Compare commits
926 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7616c6b2ba | ||
|
|
e0742cdfc7 | ||
|
|
a19937d630 | ||
|
|
fa92402bc5 | ||
|
|
cdc3da5839 | ||
|
|
3430f8c1db | ||
|
|
12fd55e76c | ||
|
|
0013606d61 | ||
|
|
4d520d7d63 | ||
|
|
7bfe174680 | ||
|
|
4951e7bf42 | ||
|
|
d7d9c468ae | ||
|
|
32faa33ad3 | ||
|
|
8a5475380a | ||
|
|
1dd5542390 | ||
|
|
5156b89eca | ||
|
|
83ea04c880 | ||
|
|
8695d2981e | ||
|
|
e0c299e6f0 | ||
|
|
16ec54f389 | ||
|
|
998bf5d5fa | ||
|
|
07ec821e9a | ||
|
|
56cf8f3574 | ||
|
|
c6ebfcd6d9 | ||
|
|
6ceffce63d | ||
|
|
f43aafc00d | ||
|
|
ab598d8377 | ||
|
|
dbd876a1c1 | ||
|
|
fd102cb56b | ||
|
|
0afb49b657 | ||
|
|
be980fe0c4 | ||
|
|
08b4e8d602 | ||
|
|
e483e1cdc6 | ||
|
|
5c2dce78e2 | ||
|
|
26ea383775 | ||
|
|
64938fd7f1 | ||
|
|
22318ee3c1 | ||
|
|
b2b54a2706 | ||
|
|
40f04e0321 | ||
|
|
a7638b8063 | ||
|
|
2abcad2a0f | ||
|
|
e088b05de4 | ||
|
|
a31d894b79 | ||
|
|
34fae4572d | ||
|
|
1ecf0ad1fa | ||
|
|
7c7509020f | ||
|
|
7c6b118282 | ||
|
|
c154a844e3 | ||
|
|
088f1b8545 | ||
|
|
fc3c636bdd | ||
|
|
14c807c882 | ||
|
|
d0e9c51786 | ||
|
|
b428bc0ba0 | ||
|
|
6dbbb91438 | ||
|
|
2066d36424 | ||
|
|
29552cd39d | ||
|
|
640e7091cc | ||
|
|
af12c18d2e | ||
|
|
f28cf614c3 | ||
|
|
888cb8ec9f | ||
|
|
04035ac524 | ||
|
|
600374eb2d | ||
|
|
6ecb932a82 | ||
|
|
4cbc9ac109 | ||
|
|
5ee0b7345b | ||
|
|
cc55330fad | ||
|
|
6589380fdf | ||
|
|
bd45482bf7 | ||
|
|
e14c8a8f03 | ||
|
|
4ac00e9a1a | ||
|
|
edf983e304 | ||
|
|
01a69ef9b3 | ||
|
|
a368afc14a | ||
|
|
d83fed16f5 | ||
|
|
949df08690 | ||
|
|
ab3abb5b3e | ||
|
|
d16e73a530 | ||
|
|
3f8c55ca47 | ||
|
|
2e9aaa50f9 | ||
|
|
36951dc5da | ||
|
|
b39c8dd738 | ||
|
|
a1155cf9b7 | ||
|
|
1d151d213e | ||
|
|
6dc0c1438a | ||
|
|
8739569db6 | ||
|
|
0dcba9ce71 | ||
|
|
8d37b85e12 | ||
|
|
43cf8e1a45 | ||
|
|
7317553483 | ||
|
|
0b342e265c | ||
|
|
08359dd45f | ||
|
|
a24415cae6 | ||
|
|
59f8161308 | ||
|
|
51f955a14c | ||
|
|
ddebdef00c | ||
|
|
6a4b6d613a | ||
|
|
97aef5e29c | ||
|
|
9549178c3a | ||
|
|
c531539c87 | ||
|
|
fa04461631 | ||
|
|
83d230dfe1 | ||
|
|
ca18bbb72c | ||
|
|
de0f2c1ad9 | ||
|
|
2f0019282e | ||
|
|
72ca479c9f | ||
|
|
de3c4362e7 | ||
|
|
987348fee8 | ||
|
|
100e012fe6 | ||
|
|
af59ebe1ff | ||
|
|
0762c88655 | ||
|
|
bbe9c94545 | ||
|
|
c7efda7da8 | ||
|
|
5c78f9bc29 | ||
|
|
e7c17c7b4b | ||
|
|
7a2497f168 | ||
|
|
5172f6f253 | ||
|
|
9017472fa4 | ||
|
|
6659c410c6 | ||
|
|
8c7b66a2f5 | ||
|
|
8f57d78200 | ||
|
|
ad2ee9efa8 | ||
|
|
192964f65a | ||
|
|
672f30af35 | ||
|
|
a7a17298f2 | ||
|
|
e17ad8e4a1 | ||
|
|
2a544676e6 | ||
|
|
6abfa9581d | ||
|
|
a6de548e5d | ||
|
|
9dc3e579b5 | ||
|
|
c5be7d7f73 | ||
|
|
70c0da703b | ||
|
|
1cbe81fba6 | ||
|
|
420e356f34 | ||
|
|
0e0ff0cb80 | ||
|
|
9003d05ae2 | ||
|
|
c247225cac | ||
|
|
4bccaa8ecf | ||
|
|
b579fec7ab | ||
|
|
37e4525c98 | ||
|
|
2269537848 | ||
|
|
441fb91222 | ||
|
|
89e0473019 | ||
|
|
3e13b35c84 | ||
|
|
fd4910fc36 | ||
|
|
964685770f | ||
|
|
634d64b5a1 | ||
|
|
19ec1c448f | ||
|
|
e3532d6f02 | ||
|
|
aaf0aabb55 | ||
|
|
575a5936ca | ||
|
|
391d265353 | ||
|
|
f90d19821c | ||
|
|
b79babf57e | ||
|
|
a929bb0022 | ||
|
|
975eb97e27 | ||
|
|
49800cf0ed | ||
|
|
de18609e00 | ||
|
|
9911446bf9 | ||
|
|
a9223211ab | ||
|
|
54c4eeba03 | ||
|
|
a30ee3e6ff | ||
|
|
1fa19489a3 | ||
|
|
f6298dfe89 | ||
|
|
79802a53f6 | ||
|
|
54bf43fd6b | ||
|
|
bb2b2f668b | ||
|
|
ecca27e012 | ||
|
|
fe0699ca48 | ||
|
|
73b2f0921f | ||
|
|
c56230c3af | ||
|
|
919b62822d | ||
|
|
21b0c9a08d | ||
|
|
63fafd05b3 | ||
|
|
0a2493a953 | ||
|
|
87ab750714 | ||
|
|
5cf3eca9eb | ||
|
|
b4a079b65f | ||
|
|
7f2d501edf | ||
|
|
c981f94092 | ||
|
|
afba46b8b0 | ||
|
|
4e416df3c8 | ||
|
|
1b54e52351 | ||
|
|
5e1568a148 | ||
|
|
8f0ac56cf8 | ||
|
|
37f0f9d4a4 | ||
|
|
a48f75c704 | ||
|
|
58a683e3c9 | ||
|
|
907637b128 | ||
|
|
85f3e97a44 | ||
|
|
beae9691fd | ||
|
|
b7876d54cc | ||
|
|
5b24223cb5 | ||
|
|
88cadff9ef | ||
|
|
b92b39e7eb | ||
|
|
8d29a29591 | ||
|
|
daf516bf9c | ||
|
|
115d9857af | ||
|
|
b322146e9e | ||
|
|
b6e3c9da82 | ||
|
|
6abdc632dc | ||
|
|
335ca6d5ac | ||
|
|
8752426694 | ||
|
|
5357ba5900 | ||
|
|
f2686096bd | ||
|
|
c4ef14ea3c | ||
|
|
03668bd6af | ||
|
|
2d90a63ca7 | ||
|
|
11e6e37331 | ||
|
|
b229a2d59e | ||
|
|
c61af9316f | ||
|
|
02e3040e1b | ||
|
|
60bbe29435 | ||
|
|
3274ea08aa | ||
|
|
97a61dea32 | ||
|
|
6cccf20b03 | ||
|
|
0a7e17ed00 | ||
|
|
706f75c0eb | ||
|
|
022e87c4bb | ||
|
|
8b29ac7e47 | ||
|
|
4d5b8baf6f | ||
|
|
e199e5a08c | ||
|
|
6cc2351bf7 | ||
|
|
c391dbd3c8 | ||
|
|
709d980b67 | ||
|
|
0903855d5c | ||
|
|
6ad2505bf8 | ||
|
|
5db8756639 | ||
|
|
5d176408a2 | ||
|
|
ab0b569798 | ||
|
|
ee76d49e56 | ||
|
|
c75d2dcae2 | ||
|
|
7c411d36db | ||
|
|
ca767cf576 | ||
|
|
b57e0bb97e | ||
|
|
5f059253a4 | ||
|
|
e0f8443653 | ||
|
|
4c23a4bbf3 | ||
|
|
0c1486bbce | ||
|
|
6f41c9a331 | ||
|
|
2879dd29d6 | ||
|
|
42e1ef45b4 | ||
|
|
19493fdf0c | ||
|
|
5870ad0673 | ||
|
|
cbd2850d1b | ||
|
|
e7c36c104a | ||
|
|
960840d9ba | ||
|
|
b8ac1bc9d4 | ||
|
|
89edf9a8f6 | ||
|
|
eb8db0b311 | ||
|
|
b10cf8b78a | ||
|
|
1dd5c0d6d0 | ||
|
|
a1e00d23a4 | ||
|
|
1a9d38dd0e | ||
|
|
2f3e7d105d | ||
|
|
a72b3c32b1 | ||
|
|
a479b16ae2 | ||
|
|
a9e7b6f5b3 | ||
|
|
60605d7d00 | ||
|
|
9dc7f726e9 | ||
|
|
46134032d6 | ||
|
|
9847c8f351 | ||
|
|
7b506586cd | ||
|
|
40bbd422b7 | ||
|
|
285fd69ab4 | ||
|
|
b436e19bbb | ||
|
|
bf6e079289 | ||
|
|
b623866b6e | ||
|
|
df7046723c | ||
|
|
3cd3047790 | ||
|
|
abd60612c5 | ||
|
|
02292acee1 | ||
|
|
c923899898 | ||
|
|
fcdd2ad036 | ||
|
|
02d3af0ac1 | ||
|
|
0516bccece | ||
|
|
2d6389d54d | ||
|
|
60d5a117b5 | ||
|
|
9b7e2e35f5 | ||
|
|
ddfb383f23 | ||
|
|
a1707486f4 | ||
|
|
451101ec67 | ||
|
|
83c583b7e6 | ||
|
|
33cb3d3c97 | ||
|
|
3d98f345c1 | ||
|
|
de8ce5c110 | ||
|
|
fd9ed77316 | ||
|
|
d974b73cce | ||
|
|
da8a67fcad | ||
|
|
471bc60ed7 | ||
|
|
fef46be34c | ||
|
|
9a92dbdedb | ||
|
|
d6be0a4154 | ||
|
|
d3ae372903 | ||
|
|
7621ef1a13 | ||
|
|
148fdd0590 | ||
|
|
232256310a | ||
|
|
5e938791ef | ||
|
|
08405dd9b4 | ||
|
|
512c637ea3 | ||
|
|
909ebd72a1 | ||
|
|
123136e90e | ||
|
|
299d25af27 | ||
|
|
9eee2f6444 | ||
|
|
2afb10b73b | ||
|
|
1b016e5915 | ||
|
|
1c403e1748 | ||
|
|
a372a133ca | ||
|
|
08a7df504b | ||
|
|
39f9d9a86d | ||
|
|
bdd5af65ce | ||
|
|
92d7d2ab91 | ||
|
|
8d4d7ce449 | ||
|
|
d2d650cace | ||
|
|
772cefd700 | ||
|
|
e20350160b | ||
|
|
08f4e91b27 | ||
|
|
021237bc38 | ||
|
|
78c36db2f9 | ||
|
|
7fd2562cb5 | ||
|
|
15a3be2e66 | ||
|
|
9b6a540ec6 | ||
|
|
2b51085bc2 | ||
|
|
822134070b | ||
|
|
26cd874779 | ||
|
|
9f21b68541 | ||
|
|
e49d95663b | ||
|
|
2c70392ada | ||
|
|
1b2248b1e7 | ||
|
|
a322dc6353 | ||
|
|
7c78ae47c6 | ||
|
|
a14dec1b7e | ||
|
|
53b5862697 | ||
|
|
83d379c7b5 | ||
|
|
be33db8339 | ||
|
|
97e9924a0b | ||
|
|
7daab55639 | ||
|
|
9d70b7469a | ||
|
|
b5504902c4 | ||
|
|
f5e82ccd75 | ||
|
|
f4c4c21a10 | ||
|
|
661d2440f2 | ||
|
|
f4af8097f6 | ||
|
|
e1822905e7 | ||
|
|
e5154dad5b | ||
|
|
30f8932039 | ||
|
|
c4f0792c77 | ||
|
|
79c7f13ff9 | ||
|
|
dbeeb0c69b | ||
|
|
58c53ff5e2 | ||
|
|
87c441887a | ||
|
|
8ee4dab239 | ||
|
|
e01ebf8d8e | ||
|
|
e92bcd378c | ||
|
|
80156e73d1 | ||
|
|
97803cd860 | ||
|
|
9a5feee095 | ||
|
|
84410056bd | ||
|
|
acd0e41703 | ||
|
|
c7dfb9dca7 | ||
|
|
0efd82bd59 | ||
|
|
426ceff451 | ||
|
|
f2be7ed34c | ||
|
|
5dcc783b95 | ||
|
|
d1c641e934 | ||
|
|
59be63785d | ||
|
|
0bf85ec729 | ||
|
|
b54c2dc254 | ||
|
|
021fcd0641 | ||
|
|
f2dadae7a3 | ||
|
|
7ce7df2625 | ||
|
|
09fcd384ab | ||
|
|
5f8625a384 | ||
|
|
621011af7a | ||
|
|
a0b81941d1 | ||
|
|
e735335773 | ||
|
|
7b62572a56 | ||
|
|
0f921c926b | ||
|
|
4d8a4d23c0 | ||
|
|
9d7eaa46fd | ||
|
|
cc9664f7d6 | ||
|
|
573b3e9d1c | ||
|
|
9808694d89 | ||
|
|
d70d8f5b6e | ||
|
|
b75c2d80bf | ||
|
|
aa747ff651 | ||
|
|
bcbf5daf0d | ||
|
|
aee1c05a45 | ||
|
|
0bb96a8dd3 | ||
|
|
1e1d2c7b63 | ||
|
|
f12375cddc | ||
|
|
ed26e6611a | ||
|
|
98f77eca07 | ||
|
|
1b2b560f8f | ||
|
|
b49cc0c9bd | ||
|
|
4ba58ea861 | ||
|
|
3f52a20c90 | ||
|
|
580089d06e | ||
|
|
1397ab0fa6 | ||
|
|
87400793eb | ||
|
|
45f79d95b1 | ||
|
|
c8a4a61028 | ||
|
|
44091981b2 | ||
|
|
d3352643fc | ||
|
|
114c7fb38a | ||
|
|
dc7da708dc | ||
|
|
72e56aa1c7 | ||
|
|
99ceab07ad | ||
|
|
c0f6c072ce | ||
|
|
e039124f6c | ||
|
|
c96e4a4c7a | ||
|
|
622a08acf3 | ||
|
|
f44b6bf0d0 | ||
|
|
a6d75e15ea | ||
|
|
a02f03c4cb | ||
|
|
d48f5132fb | ||
|
|
ed4ac24efa | ||
|
|
9f3b8a7c2c | ||
|
|
612d4bb1f5 | ||
|
|
b58a50d246 | ||
|
|
af83811d57 | ||
|
|
66835fe6ab | ||
|
|
34cc1d33c6 | ||
|
|
a42d14e3b8 | ||
|
|
87aa165edf | ||
|
|
d217d62007 | ||
|
|
27bcc0d40a | ||
|
|
e1df075cde | ||
|
|
8358692e8d | ||
|
|
e1fae01dab | ||
|
|
d206ab140a | ||
|
|
9d8722ab17 | ||
|
|
c4fa40c403 | ||
|
|
1d0b06bfbe | ||
|
|
2cdf473dcb | ||
|
|
1af9e2c2da | ||
|
|
9a1815fa1e | ||
|
|
f601961c49 | ||
|
|
406acd34c5 | ||
|
|
31cdcbbc25 | ||
|
|
2215ce71c9 | ||
|
|
1872fbb1c8 | ||
|
|
d99f912ac2 | ||
|
|
00a76fb648 | ||
|
|
187e951a47 | ||
|
|
c0b9b27aae | ||
|
|
b76bb17396 | ||
|
|
2efa6d3623 | ||
|
|
3972ce633d | ||
|
|
0dc7901393 | ||
|
|
a25ba6eaa5 | ||
|
|
4ea48dfe57 | ||
|
|
8f7ad8b2ee | ||
|
|
3b9800df07 | ||
|
|
4c80d3234e | ||
|
|
9e4af1d66b | ||
|
|
73555df2ea | ||
|
|
3ca78604fd | ||
|
|
0138046923 | ||
|
|
2129184209 | ||
|
|
dd2116f8a6 | ||
|
|
814c2d9149 | ||
|
|
b3f7276044 | ||
|
|
ad88aa980b | ||
|
|
aca55e9203 | ||
|
|
cc3330bb27 | ||
|
|
1370909db7 | ||
|
|
08cc0c394b | ||
|
|
cb6692aea3 | ||
|
|
b3badb3a55 | ||
|
|
cbf73901d3 | ||
|
|
4822e45d58 | ||
|
|
1d930d36bf | ||
|
|
9effcc403d | ||
|
|
05dcc039bd | ||
|
|
cb08656abc | ||
|
|
69b22fc736 | ||
|
|
bf857f6ce7 | ||
|
|
7ebf2378b3 | ||
|
|
aec25dab37 | ||
|
|
e11969780d | ||
|
|
02c98b1547 | ||
|
|
c864589478 | ||
|
|
bdea1593be | ||
|
|
f6b78c07ca | ||
|
|
982a217d32 | ||
|
|
06588752ad | ||
|
|
9b057d7141 | ||
|
|
93fb3a85b5 | ||
|
|
7320f9ba66 | ||
|
|
a94f43ae0c | ||
|
|
e19a3f02e5 | ||
|
|
375c2c896c | ||
|
|
b151e79aed | ||
|
|
b45901c133 | ||
|
|
fab54ca0ae | ||
|
|
31dd32f19b | ||
|
|
f51c79d282 | ||
|
|
743c943363 | ||
|
|
91f6e266d1 | ||
|
|
8e843647bf | ||
|
|
151402dc50 | ||
|
|
057f340c9c | ||
|
|
f3f9c63156 | ||
|
|
7910a79917 | ||
|
|
cc7acfcd00 | ||
|
|
5580e208f5 | ||
|
|
56ef06d651 | ||
|
|
204dfca126 | ||
|
|
eb337a8aaf | ||
|
|
aa6fd781e8 | ||
|
|
32bcfa1d42 | ||
|
|
3b2e14d0de | ||
|
|
88a0ce38f9 | ||
|
|
110c8337aa | ||
|
|
3dc79fea6b | ||
|
|
fb036385f9 | ||
|
|
428bb2817b | ||
|
|
791caff240 | ||
|
|
d92015d071 | ||
|
|
de98bd9e0b | ||
|
|
67f5a7794a | ||
|
|
fbef94f634 | ||
|
|
0e8363f06e | ||
|
|
a1bafe0426 | ||
|
|
c51461592c | ||
|
|
ef5f996ec4 | ||
|
|
aa5998a52e | ||
|
|
37207c1cb0 | ||
|
|
d1813fdbc7 | ||
|
|
faf9d1d6f8 | ||
|
|
0360df0604 | ||
|
|
fe6487eeb4 | ||
|
|
b9eedd1cf6 | ||
|
|
26281b8f0b | ||
|
|
f0508fdf93 | ||
|
|
166d69c7ec | ||
|
|
fabf08ba55 | ||
|
|
0e5d8af0e9 | ||
|
|
3e1263ebff | ||
|
|
c0ed830241 | ||
|
|
4209158807 | ||
|
|
6d79ebf449 | ||
|
|
88ab691f07 | ||
|
|
37b1dc574c | ||
|
|
ad56e249ed | ||
|
|
f28cfe3d69 | ||
|
|
9643442281 | ||
|
|
dd44ec7ac1 | ||
|
|
801c1126cf | ||
|
|
4fd72efc46 | ||
|
|
9ec045cb21 | ||
|
|
52801ee94c | ||
|
|
2077d53964 | ||
|
|
14046e9217 | ||
|
|
2766debffc | ||
|
|
4f4688899c | ||
|
|
8151db9696 | ||
|
|
227c61b588 | ||
|
|
61224fba7b | ||
|
|
1dbf5516d8 | ||
|
|
10fe6ac32a | ||
|
|
e39ee66726 | ||
|
|
fff2db75d0 | ||
|
|
3a14db53c6 | ||
|
|
8b76b82e0f | ||
|
|
e110c55e1a | ||
|
|
85c30fbad3 | ||
|
|
14e5c74c65 | ||
|
|
b180e31b56 | ||
|
|
d172a45891 | ||
|
|
e74289116e | ||
|
|
68b932bad0 | ||
|
|
c4793e849c | ||
|
|
1c525a6d2e | ||
|
|
c8610ee16a | ||
|
|
0fb3bc1106 | ||
|
|
3cf133d750 | ||
|
|
f0be6b0bc9 | ||
|
|
e0ccb8b10d | ||
|
|
940afae1fd | ||
|
|
94ba339ef2 | ||
|
|
bfead10d87 | ||
|
|
97f9a73fc1 | ||
|
|
7f4921a47c | ||
|
|
07359d2a63 | ||
|
|
e5ba670c04 | ||
|
|
3096c369d3 | ||
|
|
333368675a | ||
|
|
d78d744ae2 | ||
|
|
a8efe056c1 | ||
|
|
9b2475a854 | ||
|
|
33e2b27e6d | ||
|
|
91fe9d9bec | ||
|
|
b1b9b3134f | ||
|
|
ca5386b529 | ||
|
|
347beca874 | ||
|
|
27ca4fd1af | ||
|
|
6d57a05f8c | ||
|
|
4d81449cfa | ||
|
|
76fcb3ae10 | ||
|
|
b913f5f9ae | ||
|
|
68fa1eecfb | ||
|
|
dc84f17ac5 | ||
|
|
c91137130b | ||
|
|
972b07551f | ||
|
|
61562fe995 | ||
|
|
01b6c3cc98 | ||
|
|
b461dc76b9 | ||
|
|
03eeed4113 | ||
|
|
07615cb336 | ||
|
|
9a9a977cc4 | ||
|
|
ab5869331b | ||
|
|
1c9ebfd703 | ||
|
|
a9bc3587a6 | ||
|
|
b1af2b6061 | ||
|
|
2fccd53098 | ||
|
|
a7ad3e41d9 | ||
|
|
1fc6476f71 | ||
|
|
53e5a1b1b1 | ||
|
|
119e9dc4cc | ||
|
|
9263769906 | ||
|
|
ebaf9539b2 | ||
|
|
818fb5ab34 | ||
|
|
2f514082a9 | ||
|
|
5c5379e972 | ||
|
|
c39894d9fc | ||
|
|
2c6cf0e736 | ||
|
|
7e96bbee27 | ||
|
|
f7019546d1 | ||
|
|
086f54abf0 | ||
|
|
143a4149bd | ||
|
|
20aed68d58 | ||
|
|
7a2061a36e | ||
|
|
191c7b080e | ||
|
|
aab0813688 | ||
|
|
9ad564772c | ||
|
|
20bb34c3c7 | ||
|
|
b15ddf390b | ||
|
|
18d1562ad3 | ||
|
|
d6f2ecbd25 | ||
|
|
3620686afa | ||
|
|
1524224bc3 | ||
|
|
35200d53d6 | ||
|
|
4b7d4e05e7 | ||
|
|
7e73f69433 | ||
|
|
9e1a972df5 | ||
|
|
1edac34c1a | ||
|
|
9adc588c9c | ||
|
|
71bfdcba8f | ||
|
|
9854c9970a | ||
|
|
0c68164d6d | ||
|
|
a413357b57 | ||
|
|
5e283c9e80 | ||
|
|
500eb66e30 | ||
|
|
411e5245a5 | ||
|
|
d270501c2d | ||
|
|
f7f924593f | ||
|
|
5126a66eb9 | ||
|
|
7fddef238d | ||
|
|
ace673f90d | ||
|
|
e063df63df | ||
|
|
22b15710d0 | ||
|
|
87199c1b0d | ||
|
|
7e5952bbb8 | ||
|
|
1a52a3a205 | ||
|
|
742db4c854 | ||
|
|
4fd51dbe45 | ||
|
|
096a8a6a06 | ||
|
|
ad5cd5b8f9 | ||
|
|
3230d59f6a | ||
|
|
96fa8d8cef | ||
|
|
01bf3c9efb | ||
|
|
da0bf64e94 | ||
|
|
d39cf5d13f | ||
|
|
7c7e78fd4e | ||
|
|
d2c504898a | ||
|
|
58028b4f18 | ||
|
|
54e835687b | ||
|
|
10f2318541 | ||
|
|
eb4e95e5db | ||
|
|
203418eebc | ||
|
|
136c6c8fbf | ||
|
|
2c216d6a58 | ||
|
|
f7ec19cc5d | ||
|
|
e8c4a97158 | ||
|
|
5e5fc4c812 | ||
|
|
5e0d99ff5d | ||
|
|
e88e67c927 | ||
|
|
d963dbbd5f | ||
|
|
11ce78fca2 | ||
|
|
fd4022ba84 | ||
|
|
f91aecad8e | ||
|
|
709b7d357f | ||
|
|
59980fa160 | ||
|
|
180caf83cc | ||
|
|
7047ee832a | ||
|
|
4b5532e1b0 | ||
|
|
137155d3dc | ||
|
|
793dd8289a | ||
|
|
bcf298e40b | ||
|
|
589aef1e21 | ||
|
|
9ab0b7ab3b | ||
|
|
4c5ea13aac | ||
|
|
0cf48bbdaa | ||
|
|
8fc9cc18a3 | ||
|
|
b1e156eed6 | ||
|
|
a8b3a837ef | ||
|
|
3f3a1c9a44 | ||
|
|
cf4d2f5055 | ||
|
|
2d19d51bc7 | ||
|
|
4842bdd38b | ||
|
|
7cc4f6d6a7 | ||
|
|
b284ffd99d | ||
|
|
81d0cc2cc2 | ||
|
|
70f368d6e9 | ||
|
|
bfbae5cf5c | ||
|
|
7cc231f5fd | ||
|
|
eda34b3477 | ||
|
|
bfb67ec0c9 | ||
|
|
275fd0da48 | ||
|
|
1ad5c25ed0 | ||
|
|
512f7ae016 | ||
|
|
3a00efc7fd | ||
|
|
3068c74ad7 | ||
|
|
9bdead5616 | ||
|
|
0ed5feb96b | ||
|
|
ec80ef2ede | ||
|
|
617591cc26 | ||
|
|
c855aa5cef | ||
|
|
e2a27479f5 | ||
|
|
c8cfe76aa3 | ||
|
|
ecb0234258 | ||
|
|
24ce4bcc51 | ||
|
|
162af3de31 | ||
|
|
7c0af96dc9 | ||
|
|
026f999b46 | ||
|
|
bbbc3e98a0 | ||
|
|
f78ad4e7b6 | ||
|
|
d756ae2163 | ||
|
|
701738ce25 | ||
|
|
620bdc9132 | ||
|
|
71f474c26c | ||
|
|
c48137a5c1 | ||
|
|
e248368484 | ||
|
|
7225b8c32d | ||
|
|
20e475e130 | ||
|
|
88dc005592 | ||
|
|
40792ff0eb | ||
|
|
6ae59e91de | ||
|
|
5c7aa5f7f5 | ||
|
|
aaa1ed674f | ||
|
|
42def3bbe5 | ||
|
|
9cdab52556 | ||
|
|
5c104ebf3d | ||
|
|
7ab72e542c | ||
|
|
3a8420cd2f | ||
|
|
916aa9fd70 | ||
|
|
8809df10b6 | ||
|
|
34d65a9d70 | ||
|
|
2830d7c8a2 | ||
|
|
c702c8b0ac | ||
|
|
e1df9a9754 | ||
|
|
03fe5ce8a5 | ||
|
|
432a9dda16 | ||
|
|
1dfc0f731e | ||
|
|
af515e0adf | ||
|
|
2222b57143 | ||
|
|
d8cfa2e6a4 | ||
|
|
a622cdd4e0 | ||
|
|
2a4ec83d0d | ||
|
|
b1d144d091 | ||
|
|
23a8b66c16 | ||
|
|
381ebd5961 | ||
|
|
b4d1f7d6c3 | ||
|
|
b3eff64275 | ||
|
|
f15c00acca | ||
|
|
a66d0d4722 | ||
|
|
66cdade01b | ||
|
|
9e9f001768 | ||
|
|
3514bdcbc4 | ||
|
|
312df37365 | ||
|
|
6214d91940 | ||
|
|
23d500434b | ||
|
|
7ee5e3ab43 | ||
|
|
6be4bb7c85 | ||
|
|
d620c13e22 | ||
|
|
73b585cdd2 | ||
|
|
2f33581e4a | ||
|
|
f3dba9a026 | ||
|
|
d7d0af369c | ||
|
|
2ab9a45a71 | ||
|
|
dc0bf642a9 | ||
|
|
9e32435972 | ||
|
|
c2b724e949 | ||
|
|
195d3c6ff7 | ||
|
|
04a8079cee | ||
|
|
0b2daf7d30 | ||
|
|
1353ee603b | ||
|
|
e9d272d139 | ||
|
|
0308c7a81e | ||
|
|
4caad10c9b | ||
|
|
85c1623d33 | ||
|
|
5be1825bb5 | ||
|
|
ec5e533bd8 | ||
|
|
c3e4c7fa78 | ||
|
|
bf66a3fcbd | ||
|
|
101193cb78 | ||
|
|
b610c29be6 | ||
|
|
999c4dceb5 | ||
|
|
2957370fac | ||
|
|
5dd36d7b06 | ||
|
|
47b5bbe7e7 | ||
|
|
5a2e4ca77e | ||
|
|
c479ddb80b | ||
|
|
da1f59e0c1 | ||
|
|
9574832e86 | ||
|
|
3df7842d23 | ||
|
|
62a0f6e49a | ||
|
|
60c180e4dd | ||
|
|
343d937362 | ||
|
|
f20b321433 | ||
|
|
ba19b0825f | ||
|
|
5abb44957c | ||
|
|
b9d9cf812f | ||
|
|
d1529f428a | ||
|
|
5061a79c4c | ||
|
|
eab3e25cf2 | ||
|
|
33e73a8992 | ||
|
|
a63972b549 | ||
|
|
bc57df7fc1 | ||
|
|
e16f616286 | ||
|
|
c5497d787b | ||
|
|
64f60004c4 | ||
|
|
020c063177 | ||
|
|
a3e6f8157f | ||
|
|
f27040cd1c | ||
|
|
3a490cfc8d | ||
|
|
1f8c5998c1 | ||
|
|
f96d4ee37e | ||
|
|
d0d15f03af | ||
|
|
eff6407206 | ||
|
|
c1e559568a | ||
|
|
ef030b290c | ||
|
|
71630591a1 | ||
|
|
31505745be | ||
|
|
e40444b60c | ||
|
|
44edf387a6 | ||
|
|
d3d225644d | ||
|
|
3afd9200a9 | ||
|
|
c5c340ff12 | ||
|
|
b28b85f7c6 | ||
|
|
c60684b83c | ||
|
|
a183a1ec91 | ||
|
|
abd8488185 | ||
|
|
e6dea158e5 | ||
|
|
24150c7b3c | ||
|
|
040720a1c2 | ||
|
|
70d30d370f | ||
|
|
a50b99da07 | ||
|
|
2cecbe69ad | ||
|
|
557410660f | ||
|
|
0d75dbaaa2 | ||
|
|
d38f95c73a | ||
|
|
c9d59a90e4 | ||
|
|
fc6a34d987 | ||
|
|
8acabb692f | ||
|
|
61f8871839 | ||
|
|
69d61ad185 | ||
|
|
27391ed31b | ||
|
|
ed56c92101 | ||
|
|
ab8ae1524f | ||
|
|
de7c247583 | ||
|
|
997fd8f7ac | ||
|
|
e39e07246a | ||
|
|
e0b0406d76 | ||
|
|
1efbe9a784 | ||
|
|
fab921c2dd | ||
|
|
56896b4bea | ||
|
|
54eb7d8ecd | ||
|
|
114587b9f6 | ||
|
|
cad33c6c07 | ||
|
|
8154999f1c | ||
|
|
3a30c14085 | ||
|
|
db8b1df480 | ||
|
|
e20cac8a80 | ||
|
|
ce9b4e39f5 | ||
|
|
ddff4b2e58 | ||
|
|
16a470475c | ||
|
|
6e01473e87 | ||
|
|
8682089151 | ||
|
|
f45cb0075f | ||
|
|
afccb48798 | ||
|
|
ce6995fba0 | ||
|
|
3328d1adea | ||
|
|
33d79df9a8 | ||
|
|
4fb64b19d6 | ||
|
|
bf0f495c8b | ||
|
|
5d5f8e8d8c | ||
|
|
91aa248355 | ||
|
|
633c6c1efb | ||
|
|
facb1f673f | ||
|
|
9c8938c7f2 | ||
|
|
17f75f3ce6 | ||
|
|
b99c48afa2 | ||
|
|
9481fada23 | ||
|
|
7efbc5043c | ||
|
|
92880d3148 | ||
|
|
9800f2b8ae | ||
|
|
a5d01604cb | ||
|
|
aaab84f90a | ||
|
|
318a1a303c | ||
|
|
0061de6b2e | ||
|
|
b3db7c547f | ||
|
|
1da29464a8 | ||
|
|
d1d4ff41c6 | ||
|
|
673c2745a9 | ||
|
|
4ad88441cc | ||
|
|
71bb822856 | ||
|
|
2a7789bd12 | ||
|
|
1d0417cc1c | ||
|
|
905c578d90 | ||
|
|
a457c85e53 | ||
|
|
36630fc0ed | ||
|
|
f509ac60da | ||
|
|
bf8aac6f81 | ||
|
|
ceddcc0722 |
28
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
28
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: For when you know better than me what you want
|
||||
title: "[Request]"
|
||||
labels: enhancement
|
||||
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](https://github.com/mnadareski/BurnOutSharp/issues) instead.
|
||||
- .NET 6.0 has known limitations, so make sure that what you're asking for isn't already in another build.
|
||||
- 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...
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
22
.github/ISSUE_TEMPLATE/informational.md
vendored
Normal file
22
.github/ISSUE_TEMPLATE/informational.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: Info
|
||||
about: Something you need to tell me
|
||||
title: "[Info]"
|
||||
labels: question
|
||||
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](https://github.com/mnadareski/BurnOutSharp/issues) instead.
|
||||
- .NET 6.0 has known limitations, so make sure that what you're giving information on isn't already in another build.
|
||||
- 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...
|
||||
|
||||
**Is your information related to one of the dumping programs supported or something that isn't a bug in the code? Please describe.**
|
||||
A clear and concise description of what the information is. Ex. With the latest build of DumpingProgram, it [...]
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the information here.
|
||||
48
.github/ISSUE_TEMPLATE/issue-report.md
vendored
Normal file
48
.github/ISSUE_TEMPLATE/issue-report.md
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
name: Issue Report
|
||||
about: Tell me what's wrong, seriously
|
||||
title: "[Problem]"
|
||||
labels: bug
|
||||
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](https://github.com/mnadareski/BurnOutSharp/issues) instead.
|
||||
- .NET 6.0 has known issues, please try using another build to reproduce the error
|
||||
- Check multiple discs to help narrow down the issue
|
||||
- Check the Options to see if changing any of those affects your issue.
|
||||
|
||||
If all of those fail, then continue...
|
||||
|
||||
**Version**
|
||||
What version are you using?
|
||||
|
||||
- [ ] Stable release (version here)
|
||||
- [ ] WIP release (version here)
|
||||
|
||||
**Build**
|
||||
What runtime version are you using?
|
||||
|
||||
- [ ] .NET Framework 4.8 running on (Operating System)
|
||||
- [ ] .NET 6.0 running on (Operating System)
|
||||
|
||||
**Describe the issue**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
0
.gitmodules
vendored
Normal file
0
.gitmodules
vendored
Normal file
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@@ -10,9 +10,9 @@
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/DICUI/bin/Debug/netcoreapp3.1/DICUI.dll",
|
||||
"program": "${workspaceFolder}/MPF.Check/bin/Debug/net6.0/MPF.Check.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/DICUI",
|
||||
"cwd": "${workspaceFolder}/MPF.Check",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
|
||||
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"omnisharp.projectLoadTimeout": 480
|
||||
}
|
||||
19
.vscode/tasks.json
vendored
19
.vscode/tasks.json
vendored
@@ -3,25 +3,22 @@
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"command": "msbuild",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/DICUI/DICUI.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
"${workspaceFolder}/MPF.sln",
|
||||
"-property:RuntimeIdentifiers=win7-x64"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "publish",
|
||||
"command": "dotnet",
|
||||
"command": "msbuild",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/DICUI/DICUI.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
"${workspaceFolder}/MPF/MPF.csproj",
|
||||
"-target:Publish",
|
||||
"-property:RuntimeIdentifiers=win7-x64"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
@@ -32,7 +29,7 @@
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"${workspaceFolder}/DICUI/DICUI.csproj",
|
||||
"${workspaceFolder}/MPF/MPF.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
|
||||
630
CHANGELIST.md
630
CHANGELIST.md
@@ -1,4 +1,634 @@
|
||||
### 2.6 (2023-07-xx)
|
||||
|
||||
- Update README
|
||||
- Add warning to login tab
|
||||
- Pull hardware info from redumper log (fuzz6001)
|
||||
- Increase the version of AppVeyor (fuzz6001)
|
||||
- Add Windows 7 note to README
|
||||
- Update redumper to build 113
|
||||
- Split MMI invocation in drive listing
|
||||
- Update README
|
||||
- Add Hasbro iON
|
||||
- Get the write offset from the latest redumper (fuzz6001)
|
||||
- Update redumper to build 115
|
||||
- Update to DIC 20230401
|
||||
- Add DIC `.` notice to README
|
||||
- Resync with Redump
|
||||
- Update redumper to build 118
|
||||
- Clarify non-Redump systems
|
||||
- Add UltraCade
|
||||
- Re-enable BD33 and BD66
|
||||
- Add PIC models for BD (unused)
|
||||
- Handle PIC based on disc type
|
||||
- UMDs always have "2 layers"
|
||||
- Add dumping program selection to main UI
|
||||
- Update to DIC 20230413
|
||||
- Comment out `.` handling for DIC
|
||||
- Ensure dumping program box can enable/disable
|
||||
- Disable special SmartE handling for DIC
|
||||
- Remove path from PS1/PS2 serial
|
||||
- Make TOC file optional for CD/GD
|
||||
- Add datafile models
|
||||
- Add datafile helper method
|
||||
- Start migrating to datafile serialization
|
||||
- Prepare for future DIC changes
|
||||
- Add suppl support to Xbox
|
||||
- Support single digit subs
|
||||
- Fix info tool hash finding
|
||||
- Fix missing size for ISO data
|
||||
- Attempt to more accurately parse layerbreaks
|
||||
- Fix upcoming suppl DAT parsing
|
||||
- Ensure blank lines don't interfere
|
||||
- De-indent ringcode data
|
||||
- Be more specific with runtime identifiers
|
||||
- Fix subdump output path in AV config
|
||||
- Fix subdump mkdir path in AV config
|
||||
- Single file packing for .NET 6 again
|
||||
- Add missing BD disc type identifier string
|
||||
- Truncate PIC data for PS4/PS5
|
||||
- Add internal theme support with class
|
||||
- Add PIC identifier to SubmissionInfo
|
||||
- Fix other media type method
|
||||
- Fix non-zero offset text
|
||||
- Add executable listing for XSX
|
||||
- Update redumper to build 151
|
||||
- Add more safety to DAT generation
|
||||
- Get write offset from redumper 119 (fuzz6001)
|
||||
- Update hardware information pull from redumper (fuzz6001)
|
||||
- Add MCD/SS header support for Redumper
|
||||
- Fix MCD region(s) parsing
|
||||
- Update to DIC 20230606
|
||||
- Update redumper to build 166
|
||||
- Unblock Redumper DVD support
|
||||
- Support Redumper DVD layerbreak
|
||||
- Add placeholder and TODOs for Redumper
|
||||
- Add TODO with notes to Redumper
|
||||
- Fix 2-layer DVD support in Redumper
|
||||
- Fix VSCode build
|
||||
- Fix Redumper DAT/layer parsing
|
||||
- Update Redumper PS1 output parsing
|
||||
- Fix previous commit, clean up helpers
|
||||
- Update redumper to build 173
|
||||
- Initial support for Redumper CSS outputs
|
||||
- Hook up CSS output for testing
|
||||
- Update redumper to build 174
|
||||
- Add support for redumper CD synonyms
|
||||
- Adjust CSS title key parsing
|
||||
- Fix non-reading loop
|
||||
- Normalize Redumper CSS outputs
|
||||
- Normalize multi-instance site tags
|
||||
- Add missing Aaru error log to zip
|
||||
- Check Redumper dat section for completeness
|
||||
- Update redumper to build 176
|
||||
- UMDs are Sony discs
|
||||
- Strip colons from Redumper disc key
|
||||
- Use `HashSet` for disc or book type
|
||||
- Add ordering to disc or book type
|
||||
- Update redumper to build 183
|
||||
- Parse and format Redumper CD multisession data
|
||||
- New layerbreak takes precedence
|
||||
- Reduce pulled information for Xbox and X360
|
||||
- Ensure we found the tags we're skipping
|
||||
- Omit pulling universal hash
|
||||
- Update Nuget packages to newest stable
|
||||
|
||||
### 2.5 (2023-03-12)
|
||||
|
||||
- Add _drive file to zip for UIC
|
||||
- Add Xbox Series X and PS5 to list, fix Acorn
|
||||
- Add Xbox Series X short name to list
|
||||
- Remove windows from test target
|
||||
- Remove .NET 6.0 from tests, add TODO
|
||||
- Add .NET 6.0 to tests, remove msbuild args
|
||||
- Add HD-DVD to speed definitions
|
||||
- Add PS3 internal serial and version parsing (tjanas)
|
||||
- Update Nuget packages to newest stable
|
||||
- Simplify path selection in UI
|
||||
- Fix broken normalization test
|
||||
- Update drive info before dumping
|
||||
- Update redumper strings
|
||||
- Add new parameter and mode validation
|
||||
- Add redumper to the UI
|
||||
- Update redumper to build 81
|
||||
- Fix incorrect naming in Options window
|
||||
- Initial attempt at parsing redumper outputs
|
||||
- Update README
|
||||
- Reenable write offset for all CDs
|
||||
- Add missing redumper output file
|
||||
- Force a filename for redumper
|
||||
- Fix incorrect SetParameters
|
||||
- Fix a couple redumper things
|
||||
- Update AppVeyor version
|
||||
- Output security sectors to info
|
||||
- Remove x86 requirement for build
|
||||
- Fix XGD media type outputs
|
||||
- Fix typo in ToInternalProgram
|
||||
- Fix redumper error count parsing
|
||||
- Update to Aaru v5.3.2 LTS
|
||||
- Update options loader with sane defaults
|
||||
- Fix AppVeyor pathing
|
||||
- Skip during detection
|
||||
- Address some UI concerns
|
||||
- Tweak AppVeyor, show Check 6.0 builds
|
||||
- More strict when custom parameters editing
|
||||
- Use msbuild for .NET Framework 4.8
|
||||
- Update nuget packages
|
||||
- ReadAllText not ReadAllLines
|
||||
- Add drive format (fs) to log
|
||||
- Go back to pre .NET 7 Aaru
|
||||
- Be smarter about old paths
|
||||
- Fix relative paths for DIC
|
||||
- Add nicer failure message
|
||||
- Update to DIC 20230201
|
||||
- Use relative path output for DIC
|
||||
- Remove usage of Aaru
|
||||
- Remove Aaru as submodule
|
||||
- Fix Aaru removal
|
||||
- Enable .NET 6 Windows builds
|
||||
- Update Redumper to build_106
|
||||
- Reformat CICM for old .NET versions
|
||||
- Attempt to handle no drives
|
||||
- Handle no drives better
|
||||
- Handle no drives betterer
|
||||
- Packaging requires `-windows` for framework
|
||||
- Fix other `-windows` places for .NET 6
|
||||
- Fix typo in DICMultiSectorReadValue
|
||||
- Semi-unify drive finding
|
||||
- Introduce cross-platform MMI
|
||||
- Remove System.Management
|
||||
- Add Redumper Universal Hash support
|
||||
- Fix Redumper write offset support
|
||||
- Add Redumper non-zero data start
|
||||
- Use media size for type detection on .NET 6
|
||||
- Trim PIC for PS3
|
||||
- Get the version of redumper (fuzz6001)
|
||||
- Update VSCode config files
|
||||
- Can't publish single file for UI
|
||||
- Handle missing extension gracefully
|
||||
- Fix incorrect option slider display
|
||||
- Handle undetected discs on refresh
|
||||
- Originally intended behaviour of the Update Label button (IcySon55)
|
||||
- Update to BurnOutSharp 2.7.0
|
||||
- Get error count from recent redumper log (fuzz6001)
|
||||
- Minor cosmetic changes
|
||||
- Set saner defaults for dumping speeds
|
||||
- Attempt to support Windows 7
|
||||
- Add `win7-x64` to identifier list
|
||||
- Remove unsupported identifiers
|
||||
- Add identifiers in more places
|
||||
- Move drive finding inside of the try/catch
|
||||
- Update to DIC 20230309
|
||||
- Fix errant forward slashes
|
||||
- Add TOC back as optional file
|
||||
- Fix Redumper path generation
|
||||
- Use and trim quotes for Redumper
|
||||
- Fix incorrect image name setting
|
||||
- Ensure Redumper parameters are set
|
||||
- Ensure min values are taken care of
|
||||
- Update parameters with `=` handling
|
||||
- Ensure drive and speed are set
|
||||
- Handle quotes embedded
|
||||
- Return list of missing files for Redumper
|
||||
- Readd accidentally deleted line
|
||||
- Detect EOF during the search for error counts (fuzz6001)
|
||||
|
||||
### 2.4 (2022-10-26)
|
||||
|
||||
- Update to DIC 20211001
|
||||
- Fix Redump disc title pulling
|
||||
- Add /mr default flag options
|
||||
- Make FillFromRedump private again
|
||||
- Fix DVD layer finding corner case
|
||||
- Fix failing module tests
|
||||
- Add option to limit region and language selections
|
||||
- Cap X360 directory check to 500MB
|
||||
- Assign normalized path to parameters
|
||||
- Move path normalization to better place
|
||||
- Specifically include Unsafe Nuget package
|
||||
- Update Nuget packages to newest stable
|
||||
- Add Xbox One system detection
|
||||
- Update to DIC 20220301
|
||||
- Force internal drive refresh
|
||||
- Add single drive refresh button (IcySon55)
|
||||
- Fix "missing" option in window
|
||||
- Track last used drive on refresh
|
||||
- Clean up pre-dump validation
|
||||
- Update to Aaru v5.3.1 LTS
|
||||
- Add upper case `<TAB>` processing
|
||||
- Reorder event handers
|
||||
- Handle sanitized protections edge case
|
||||
- Update Aaru Nuget package
|
||||
- Return faster on empty protection sets
|
||||
- Remove redundant check around volume label
|
||||
- Fix tabs in Games and Videos boxes
|
||||
- Make fully and partially matching IDs more apparent
|
||||
- Add write offset as read-only field
|
||||
- Explicitly clear list, just in case
|
||||
- Add both fully and partially matching to info file
|
||||
- Fix submission info clone
|
||||
- Clear out fully matched IDs from the partial list
|
||||
- Refine copy protection section showing
|
||||
- Update Nuget packages
|
||||
- Normalize newlines in comments and contents
|
||||
- Increase JSON accuracy for disc types
|
||||
- Further separate out protection scan outputs
|
||||
- Compress JSON for artifacts alone
|
||||
- Even stricter output for copy protection section
|
||||
- Report dictionary to InfoTool
|
||||
- Even even stricter copy protection output
|
||||
- Disable PVD creation for Aaru
|
||||
- Explicitly sanitize '?' from path
|
||||
- Combine cases in protection scan
|
||||
- Convert status label to TextBlock
|
||||
- Add option for copy protection file output
|
||||
- Make protection field user-editable
|
||||
- Add warning to tooltip
|
||||
- Create core UI library
|
||||
- Rename MPF.GUI to MPF.UI
|
||||
- Add multisession pseudo-tag
|
||||
- Add multisession helper method skeleton
|
||||
- Move and update options loader; clean up Check
|
||||
- Move helper methods around
|
||||
- Consolidate Redump login testing
|
||||
- Separate common arguments to new helper
|
||||
- Parse and format CD multisession data
|
||||
- Convert triple space to tab
|
||||
- Fix clone issue with copy protection
|
||||
- Be more picky about multisession
|
||||
- Sanitize whitespace around tabs
|
||||
- Convert internal libraries to .NET Standard 2.0
|
||||
- Update AppVeyor to VS2022
|
||||
- Update Nuget packages
|
||||
- Remove needless csproj constants
|
||||
- Update copyright date to 2022
|
||||
- Revert AppVeyor to VS2019 for now
|
||||
- Add size-based media type detection for non-Framework
|
||||
- Gate ManagmentObject use further
|
||||
- Use built-in NETFRAMEWORK directive
|
||||
- Update to BurnOutSharp 2.1.0
|
||||
- .NET 6.0 and Cleanup
|
||||
- Remove .NET Core 3.1 from test project for now
|
||||
- Remove .NET Core 3.1 entirely
|
||||
- Add filesystem logging for .NET 6
|
||||
- Avoid whitespace changes for PVD, Header, and Cuesheet
|
||||
- Sync to newest CICM
|
||||
- Update solution file for VS2022
|
||||
- Add Aaru as a submodule for .NET 6
|
||||
- Multisession is multi-line
|
||||
- Use Aaru for media type retrival (.NET 6)
|
||||
- Fix CD-R multisession info
|
||||
- Better get drive list (.NET 6)
|
||||
- Add optical media support method (.NET 6)
|
||||
- Simplify IsOptical (.NET 6)
|
||||
- Reorganize GetMediaType
|
||||
- Possibly fix tab regex replacement
|
||||
- Add PIC.bin to log zip
|
||||
- Organize projects in solution
|
||||
- Implement Drive.Create for safety
|
||||
- Fix incomplete system name detection
|
||||
- Add Sharp X68k detection
|
||||
- Add Bandai Playdia QIS detection
|
||||
- Framework for XBONE filenames
|
||||
- Add files for XBONE
|
||||
- Update to DIC 20220707
|
||||
- Fix .bin file paths; update internal filename generation
|
||||
- Disable nonstandard BD-ROM sizes
|
||||
- Trim leading file paths for XBONE
|
||||
- Give .NET 6 priority for web calls
|
||||
- Update to BurnOutSharp 2.3.0 (nw)
|
||||
- Add Mattel Fisher-Price iXL detection
|
||||
- Update to BurnOutSharp 2.3.1 (nw)
|
||||
- Fix serial parsing for Dreamcast
|
||||
- Fix missing parenthesis
|
||||
- Add internal name for Cleanrip outputs
|
||||
- Fix psxt001z namespace
|
||||
- Fix missing assignment
|
||||
- Update to new constructor
|
||||
- Update PSX content check
|
||||
- Update Aaru submodule to latest devel
|
||||
- Add Sony Electronic Book system
|
||||
- Verify GD-ROM outputs, finally
|
||||
- Electronic not Electric
|
||||
- Fix ringcode guide images
|
||||
- Add skeleton for Redumper
|
||||
- Download Redumper with AppVeyor
|
||||
- Add Redumper constants
|
||||
- Add Redumper parameter values
|
||||
- Add Redumper command support and reset
|
||||
- Add Redumper dumping command
|
||||
- Add Redumper command validation
|
||||
- Add Redumper command generation
|
||||
- Create Redumper extensions class
|
||||
- Minor Redumper cleanup
|
||||
- Add important Redumper note
|
||||
- Update to DIC 20220909
|
||||
- Possibly fix PIC parsing
|
||||
- Add PS3 folder/file checks for detection
|
||||
- Use default directory for folder browsing, if possible
|
||||
- Add unused command filename parser
|
||||
- Add initial framework for reporting dumping program
|
||||
- Report specific DIC version, if possible
|
||||
- Add dumping info section skeleton
|
||||
- Update Aaru submodules
|
||||
- Fix missing info reference change
|
||||
- Enable separated protection info output by default
|
||||
- Try adding MPF logs to zip
|
||||
- Create MPF log helper and filter for deletion
|
||||
- Fix missing info in Aaru
|
||||
- Add hardware info to DIC and Aaru
|
||||
- Fix hardware info
|
||||
- Add specialized CDS/SafeDisc filter
|
||||
- Add unused article formatter
|
||||
- Add language filtering to formatter
|
||||
- Add multi-language helper for filter
|
||||
- Update Nuget packages
|
||||
- Remove deprecated protection setting
|
||||
- Update BurnOutSharp to 2.3.4
|
||||
- Add compression result reason to log
|
||||
- Add System.Memory package to MPF.Library
|
||||
- Add CodePages package to MPF.Library
|
||||
- Remove extraneous packages
|
||||
- Change location of dumping info
|
||||
- Add MS ZipFile package to MPF.Library
|
||||
- Add + to positive offsets
|
||||
- Disable layerbreak generation for BD
|
||||
- Disable XGD version reporting
|
||||
- Disable XGD layerbreak reporting
|
||||
- Disable XGD1 PVD reporting
|
||||
- Put Redump limitations behind existing flag
|
||||
- Add framework for reported disc type
|
||||
- Add disc type parsing for Aaru and DIC
|
||||
- Fix multiple DiscType for DIC
|
||||
- Fix multiple DiscType* for DIC
|
||||
- Add logging to !submissionInfo writing failure
|
||||
- Add logging to !submissionInfo formatting failure
|
||||
- Update issue templates to be more accurate
|
||||
- Fix NRE with offsets
|
||||
- Fix readonly Filename info display
|
||||
- Fix layerbreak-based checks
|
||||
- Add PS4 serial finding (tjanas)
|
||||
- Add unused notification method
|
||||
- Move to unused Chime class
|
||||
- Add PS5 serial finding (tjanas)
|
||||
- Fix offset formatting (fuzz6001)
|
||||
|
||||
### 2.3 (2022-02-05)
|
||||
|
||||
- Start overhauling Redump information pulling, again
|
||||
- Add internal structure for special site codes
|
||||
- Add new tabs for special site information
|
||||
- Clean up default handling of fields
|
||||
- Try to handle multi-line fields during parsing
|
||||
- Fix CSSKey log handling
|
||||
- Show most read-only fields in new tab
|
||||
- Add horizontal scroll to user input
|
||||
- Tweak new disc information fields and tabs
|
||||
- Allow internal serial and volume label to be hidden
|
||||
- Be smarter about showing update checks
|
||||
- Ensure all fields are read-only on read-only tab
|
||||
- Add model for 2-layer ringcode guide
|
||||
- Add first attempt 2-layer ringcode guide
|
||||
- Add even more safety to clone
|
||||
- Sanitize filename after check
|
||||
- Handle pulled linebreaks better
|
||||
- Skip anti-modchip string in some cases
|
||||
- Handle pulled linebreaks better, again
|
||||
- Tweak more Disc Info window formatting
|
||||
- Skip unnecessary newlines in parsing
|
||||
- Force scroll visibility, tweak text sizes again
|
||||
- Fix newline skipping
|
||||
- Add missing continue statement
|
||||
- Add newlines for mutliline special fields
|
||||
- Omit volume label for "Audio CD"
|
||||
- Remove Enter/Escape registration on disc info window
|
||||
- Logically group more things in disc info window
|
||||
- Remove tab key from disc info window
|
||||
- Add `<tab>` processing
|
||||
- Unban newly opened consoles
|
||||
- Tweak minimalized layout a bit more
|
||||
- Add tab setting
|
||||
- Further disc info window tweaks
|
||||
- Changed IsEnabled to IsReadOnly
|
||||
- Fix scrolling issues in disc info window
|
||||
- Convert postgap and VCD fields to checkboxes
|
||||
- Adjust width ratios for disc info window
|
||||
- Fix IsReadOnly
|
||||
- Only include booleans if the value is true
|
||||
- Add hidden debug option for "ShowDebugViewMenuItem"
|
||||
- Fix incorrect header check
|
||||
- Make protection read-only field multiline
|
||||
- Reformat Saturn internal date
|
||||
- Fix Sega CD internal serial reading
|
||||
- Fix crash on invalid parameters
|
||||
- Differentiate XMID and XeMID
|
||||
- Conditionally pull region from Redump
|
||||
- Be smarter about volume labels
|
||||
- Use volume label in checks, not formatted version
|
||||
- Sync with Redump region and language selection
|
||||
- Try to delete old log archive before writing
|
||||
- Add support for all ISO language codes
|
||||
- Add support for all ISO region codes
|
||||
- Ensure ordering in output site tags
|
||||
- Make site code formatting helper method
|
||||
- Better helper method organization
|
||||
- Start supporting ordered tags and non-tags
|
||||
- Add more non-tag support; rearrange info window
|
||||
- Fix incorrect language three-letter code
|
||||
- Hook up additional Xbox field to disc info window
|
||||
- Fix non-tag tag shortnames
|
||||
- Fix parsing of non-tag tags again
|
||||
- Disable unnecessary cuesheet parsing
|
||||
- Fix incorrect region two-letter code
|
||||
- Adjust long names for some languages
|
||||
- Add Sierra ID to list of pseudo-tags
|
||||
- Add another hand-formatted version of SS tag
|
||||
- Move internal serial before volume label
|
||||
- Check for $SystemUpdate folder for X360 discs
|
||||
- Slightly rename UK and USA regions for UI
|
||||
- Add another hand-formatted version of SS tag
|
||||
- Add verification reminders for pulled tags
|
||||
- Read longer string for Saturn internal serial
|
||||
- Ensure version only pulled if one doesn't exist
|
||||
- Ensure Games pseudo-tag is multi-line
|
||||
- Add alternate pseudo-tag for Playable Demos
|
||||
- Make error clearer if something is unsupported in Check
|
||||
- Ensure drive is not null for volume labels
|
||||
- Check explicitly for no matches on Redump pull
|
||||
- Normalize PS1/PS2 executable names
|
||||
- Adjust paths for DIC just before dumping
|
||||
|
||||
### 2.2 (2021-12-30)
|
||||
|
||||
- Fix Saturn header finding
|
||||
- Add Pocket PC support
|
||||
- Add HD-DVD-Video support
|
||||
- Convert to using separate Redump library code
|
||||
- Update to Aaru v5.3.0-rc1
|
||||
- Update to BurnOutSharp 1.8.0
|
||||
- Update support packages
|
||||
- Add on-startup "check for updates" option
|
||||
- Update to Aaru v5.3.0-rc2
|
||||
- Add .NET 5.0 as build target
|
||||
- Remove .NET Core 3.1 and .NET 5.0 from AppVeyor build artifacts
|
||||
- Null-safeguard RedumpLib conversions
|
||||
- Move cuesheet code to separate DLL
|
||||
- Move CICMMetadata to top-level
|
||||
- Separate out remaining functionality into individual DLLs
|
||||
- Update to Aaru v5.3.0 LTS
|
||||
- Update to DIC 20211001
|
||||
- HTTP encode password for Redump login, again
|
||||
- Fix NullReferenceException in anti-modchip scans
|
||||
- Update arcade metadata (Shizmob)
|
||||
- Add JSON output option for MPF.Check
|
||||
- Fix JSON output serialization
|
||||
- Ensure corrupt directories on media don't throw errors
|
||||
- Add retry to Redump external calls
|
||||
- Make anti-modchip scans even safer
|
||||
- Remove lower bound checking on LBA values for DIC
|
||||
- Remove offset for audio discs on DIC output
|
||||
- Start adding regression tests for DIC
|
||||
- Ensure parameters box is safer during options save
|
||||
- Fix protection sanitization and add regression tests
|
||||
- Update to DIC 20211101
|
||||
- Add protection sanitization for StarForce
|
||||
- Trim filenames for DVD protection from DIC
|
||||
- Fill out internal tests around Redump library
|
||||
- Refine the "missing disc" text
|
||||
- Overhaul XeMID handling
|
||||
- Fix output dialog issues in Options window
|
||||
- Fix saving path settings if set from dialog
|
||||
- Allow default system if skipping system detection enabled
|
||||
- Add internal support for all Redump site codes
|
||||
- Use the Volume Label special site code
|
||||
- Capture newlines in Redump fields
|
||||
- Invert condition for volume label
|
||||
- Fix missing ISN usages
|
||||
- Fix ISN string
|
||||
- Validate track count when matching Redump
|
||||
- Allow for better matching of multi track discs
|
||||
- Temporarily disable pulling comments from Redump pages
|
||||
- Add safety around volume labels
|
||||
|
||||
### 2.1 (2021-07-22)
|
||||
|
||||
- Enum, no more
|
||||
- Sony works backward
|
||||
- Add experimental dark mode
|
||||
- Allow users to customize protection scanning
|
||||
- Fix negative offsets for `/a` flag
|
||||
- Always check for all DIC log files, just in case
|
||||
- Check for the zipped logs for dealing with overwrites
|
||||
- Be smarter about checking for zipped logs
|
||||
- Change offset value for HVN discs
|
||||
- Update to DIC 20210601
|
||||
- Fix Aaru command normalization
|
||||
- Handle carriage returns better
|
||||
- Add logging helper class
|
||||
- Set matcher on carriage return for log formatting
|
||||
- Replace dumping program output processing
|
||||
- Fix volume name detection for XBOX discs
|
||||
- Add new setting for including artifacts in serialzied JSON
|
||||
- Fix logging in to Redump for verifications
|
||||
- Gracefully handle timeouts during login
|
||||
- Update to DIC 20210701
|
||||
- Support `/mr` value parameter
|
||||
- Support new mainInfo header
|
||||
- Add BD to IBM-PC supported discs
|
||||
- Fix launching MPF on Windows 7
|
||||
- Fix log window background turning white
|
||||
- Add DMI/PFI/SS to log zipfile
|
||||
- Update to BurnOutSharp 1.7.0
|
||||
|
||||
### 2.0 (2021-04-23)
|
||||
|
||||
- Rename DICUI to Media Preservation Frontend (MPF)
|
||||
- Add handling for BEh drive _mainInfo.txt changes
|
||||
- Fix multiline regex fields during info pulling
|
||||
- Add preliminary support for user-defined default system
|
||||
- Change labels in media info window depending on media type
|
||||
- Update to Aaru v5.2
|
||||
- Only pull disc information if every track returns at least one ID
|
||||
- Add new supported Redump regions
|
||||
- Remove Philips CD-i Digital Video from supported profiles
|
||||
- Remove experimental Avalonia UI, will wait for MAUI next year
|
||||
- ~~Updated to DIC version 20210102~~
|
||||
- Add support for `/mr` DIC flag
|
||||
- UI initialization code refactored to have more consistent results
|
||||
- Support DIC `.imgtmp`, `.scmtmp`, and `.subtmp` possible output files
|
||||
- Fix BCA formatting for CleanRip outputs
|
||||
- Add hashing for UMDs from UIC outputs
|
||||
- Fix information gathering for UIC outputs
|
||||
- Fix issue with duplicate security sector data in XGD DiscImageCreator outputs
|
||||
- ~~Update to BurnOutSharp 1.5.1~~
|
||||
- ~~Update to DIC version 20210202~~
|
||||
- Add VCD detection
|
||||
- Fix UI not updating properly on drive change
|
||||
- Add Xbox Series and PS5 to supported systems
|
||||
- Add PS5 type detection and version extraction
|
||||
- Add internal support for 3- and 4-layer discs
|
||||
- Revamp disc information window
|
||||
- Add PIC layerbreak extraction
|
||||
- Overhaul main window and logging panel
|
||||
- Overhaul options window
|
||||
- Update attributions and about text
|
||||
- ~~Updated to DIC version 20210301~~
|
||||
- Add user-selectable Language Selection via dropdown in disc submission window for PS2
|
||||
- Separate out Aaru- and DIC-specific settings
|
||||
- Add new options based on original "Paranoid Mode" mega-option
|
||||
- Internal overhaul of options and dump environment
|
||||
- VideoNow discs are audio only
|
||||
- Hook up default system in options
|
||||
- Make inner and outer layers in UI and outputs more clear
|
||||
- Program output to log by default, setting otherwise
|
||||
- DVDs and BDs can have label-side data
|
||||
- Remove .NET Framework 4.7.2 support
|
||||
- Make logging window a bit safer
|
||||
- Support new Redump languages and regions
|
||||
- Implement internal log queue
|
||||
- It's a secret...
|
||||
- Updated to DIC version 20210401
|
||||
- Support log file compression
|
||||
- Add ring code guide button to disc submission window
|
||||
- ~~Update to BurnOutSharp 1.6.0~~
|
||||
- Fix "rewinding" issue when inputting output paths with spaces
|
||||
- Add version to About box
|
||||
- Update to BurnOutSharp 1.6.1
|
||||
|
||||
### 1.18 (2020-11-10)
|
||||
|
||||
- Add more information extraction and generation for Aaru
|
||||
- Remove instances of CD Check from copy protection (again, sorry)
|
||||
- Fix multiline submission info outputs
|
||||
- Fix PVD retrieval for multi-session discs
|
||||
- Updated to DIC version 20200921
|
||||
- Add and fix multiple Sega disc header pieces or submission info
|
||||
- Fixed issues in parsing the alternate mainInfo format
|
||||
- Fixed issue with logging clear not working properly
|
||||
- ~~Updated to BurnOutSharp 1.4.1~~
|
||||
- Added split archives for AppVeyor builds
|
||||
- Remove subdump from both UI and run steps
|
||||
- Removed default config file
|
||||
- Fixed copy protect scan using wrong drive when using UI option
|
||||
- Changed default to skip fixed drives
|
||||
- Fixed default media type when skipping type detection
|
||||
- Attempt sector reading for Saturn system detection
|
||||
- Fixed default media type when detection fails
|
||||
- Add option to allow users to select dumping program
|
||||
- ~~Updated to DIC version 20201101~~
|
||||
- Add support for `/ps` DIC flag
|
||||
- Updated to BurnOutSharp 1.5.0
|
||||
- Added HD-DVD-Video detection
|
||||
|
||||
### 1.17.1 (2020-09-14)
|
||||
|
||||
- Shuffled some shared, internal UI variables
|
||||
- Synced WPF and Avalonia UI internals
|
||||
- Made the disc information window less prone to bugs
|
||||
- Fixed DIC flags based on code (not documentation)
|
||||
- Added support for old(?) DIC flags: `/fix` and `/re`
|
||||
|
||||
### 1.17 (2020-09-12)
|
||||
|
||||
- Updated to Aaru version 5.1
|
||||
- Updated to BurnOutSharp version 1.4.0
|
||||
- Updated to DIC version 20200716
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<Application xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="DICUI.Avalonia.App">
|
||||
<Application.Styles>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
|
||||
</Application.Styles>
|
||||
</Application>
|
||||
@@ -1,24 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
public class App : Application
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
desktop.MainWindow = new MainWindow();
|
||||
}
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the Category combo box
|
||||
/// </summary>
|
||||
public class CategoryComboBoxItem
|
||||
{
|
||||
private object data;
|
||||
|
||||
public CategoryComboBoxItem(DiscCategory? category) => data = category;
|
||||
|
||||
public static implicit operator DiscCategory? (CategoryComboBoxItem item) => item.data as DiscCategory?;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return (data as DiscCategory?).LongName(); }
|
||||
}
|
||||
|
||||
public bool IsChecked { get; set; }
|
||||
|
||||
public DiscCategory? Value
|
||||
{
|
||||
get { return data as DiscCategory?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using Avalonia.Media;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the System combo box
|
||||
/// </summary>
|
||||
public class KnownSystemComboBoxItem
|
||||
{
|
||||
private object data;
|
||||
|
||||
public KnownSystemComboBoxItem(KnownSystem? system) => data = system;
|
||||
public KnownSystemComboBoxItem(KnownSystemCategory? category) => data = category;
|
||||
|
||||
public ISolidColorBrush Foreground { get => IsHeader() ? Brushes.Gray : Brushes.Black; }
|
||||
|
||||
public bool IsHeader() => data is KnownSystemCategory?;
|
||||
public bool IsSystem() => data is KnownSystem?;
|
||||
|
||||
public static implicit operator KnownSystem? (KnownSystemComboBoxItem item) => item.data as KnownSystem?;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsHeader())
|
||||
return "---------- " + (data as KnownSystemCategory?).LongName() + " ----------";
|
||||
else
|
||||
return (data as KnownSystem?).LongName();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the Language combo box
|
||||
/// </summary>
|
||||
public class LanguageComboBoxItem
|
||||
{
|
||||
private object data;
|
||||
|
||||
public LanguageComboBoxItem(Language? region) => data = region;
|
||||
|
||||
public static implicit operator Language? (LanguageComboBoxItem item) => item.data as Language?;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return (data as Language?).LongName(); }
|
||||
}
|
||||
|
||||
public bool IsChecked { get; set; }
|
||||
|
||||
public Language? Value
|
||||
{
|
||||
get { return data as Language?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the MediaType combo box
|
||||
/// </summary>
|
||||
public class MediaTypeComboBoxItem
|
||||
{
|
||||
private MediaType? data;
|
||||
|
||||
public MediaTypeComboBoxItem(MediaType? mediaType) => data = mediaType;
|
||||
|
||||
public static implicit operator MediaType? (MediaTypeComboBoxItem item) => item.data;
|
||||
|
||||
public string Name { get { return data.LongName(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the Region combo box
|
||||
/// </summary>
|
||||
public class RegionComboBoxItem
|
||||
{
|
||||
private object data;
|
||||
|
||||
public RegionComboBoxItem(Region? region) => data = region;
|
||||
|
||||
public static implicit operator Region? (RegionComboBoxItem item) => item.data as Region?;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return (data as Region?).LongName();
|
||||
}
|
||||
}
|
||||
|
||||
public Region? Value
|
||||
{
|
||||
get { return data as Region?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using DICUI.Data;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
/// <summary>
|
||||
/// Variables for UI elements
|
||||
/// </summary>
|
||||
public static class Constants
|
||||
{
|
||||
public const string StartDumping = "Start Dumping";
|
||||
public const string StopDumping = "Stop Dumping";
|
||||
|
||||
public const int LogWindowMarginFromMainWindow = 40;
|
||||
|
||||
// Private lists of known drive speed ranges
|
||||
private static IReadOnlyList<int> cd { get; } = new List<int> { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 };
|
||||
private static IReadOnlyList<int> dvd { get; } = cd.Where(s => s <= 24).ToList();
|
||||
private static IReadOnlyList<int> bd { get; } = cd.Where(s => s <= 16).ToList();
|
||||
private static IReadOnlyList<int> unknown { get; } = cd; // TODO: All or {1}? Maybe null?
|
||||
|
||||
/// <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 IReadOnlyList<int> GetSpeedsForMediaType(MediaType? type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.GDROM:
|
||||
return cd;
|
||||
case MediaType.DVD:
|
||||
case MediaType.HDDVD:
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
return dvd;
|
||||
case MediaType.BluRay:
|
||||
return bd;
|
||||
default:
|
||||
return unknown;
|
||||
}
|
||||
}
|
||||
|
||||
// Create collections for UI based on known drive speeds
|
||||
public static List<double> SpeedsForCDAsCollection { get; } = GetDoubleCollectionFromIntList(cd);
|
||||
public static List<double> SpeedsForDVDAsCollection { get; } = GetDoubleCollectionFromIntList(dvd);
|
||||
public static List<double> SpeedsForBDAsCollection { get; } = GetDoubleCollectionFromIntList(bd);
|
||||
private static List<double> GetDoubleCollectionFromIntList(IReadOnlyList<int> list)
|
||||
=> new List<double>(list.Select(i => Convert.ToDouble(i)).ToList());
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;net48;netcoreapp3.1</TargetFrameworks>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<Title>DICUI</Title>
|
||||
<AssemblyName>DICUI.Avalonia</AssemblyName>
|
||||
<Description>Frontend for various dumping programs</Description>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2020</Copyright>
|
||||
<RepositoryUrl>https://github.com/SabreTools/DICUI</RepositoryUrl>
|
||||
<Version>1.17.0</Version>
|
||||
<AssemblyVersion>1.17.0</AssemblyVersion>
|
||||
<FileVersion>1.17.0</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.9.12" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.9.12" />
|
||||
<PackageReference Include="BurnOutSharp" Version="1.4.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DICUI.Library\DICUI.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="DiscInformationWindow.axaml.cs">
|
||||
<DependentUpon>DiscInformationWindow.axaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="LogWindow.axaml.cs">
|
||||
<DependentUpon>LogWindow.axaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="MainWindow.axaml.cs">
|
||||
<DependentUpon>MainWindow.axaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="OptionsWindow.axaml.cs">
|
||||
<DependentUpon>OptionsWindow.axaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AvaloniaResource Include="Icon.ico" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,120 +0,0 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="515.132" d:DesignHeight="705" Width="515.132" Height="705"
|
||||
x:Class="DICUI.Avalonia.DiscInformationWindow" Icon="Icon.ico" CanResize="False"
|
||||
Title="Disc Information" Closed="OnClosed">
|
||||
|
||||
<Grid RowDefinitions="585,80,25">
|
||||
|
||||
<!-- Common Disc Information -->
|
||||
<Border Grid.Row="0" Margin="5" BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<TextBlock Text="Common Disc Information" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" FontSize="14" Foreground="Gray" />
|
||||
</Border>
|
||||
<Grid Grid.Row="0" Margin="10,15,10,10" ColumnDefinitions="1*,1*" RowDefinitions="1*,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25">
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Title" />
|
||||
<TextBox Name="TitleTextBox" Grid.Row="1" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Foreign Title (Non-Latin)" />
|
||||
<TextBox Name="ForeignTitleTextBox" Grid.Row="2" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Disc Number / Letter" />
|
||||
<TextBox Name="DiscNumberLetterTextBox" Grid.Row="3" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Disc Title" />
|
||||
<TextBox Name="DiscTitleTextBox" Grid.Row="4" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Category" />
|
||||
<ComboBox Name="CategoryComboBox" Grid.Row="5" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Region" />
|
||||
<ComboBox Name="RegionComboBox" Grid.Row="6" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="7" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Languages" />
|
||||
<ComboBox Name="LanguagesComboBox" Grid.Row="7" Grid.Column="1" Height="24" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Path=Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="8" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Serial" />
|
||||
<TextBox Name="SerialTextBox" Grid.Row="8" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<!-- Layer 0 / Data Side -->
|
||||
<TextBlock Grid.Row="9" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Data/L0 Mastering Ring" />
|
||||
<TextBox Name="L0MasteringRingTextBox" Grid.Row="9" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" AcceptsTab="True" />
|
||||
|
||||
<TextBlock Grid.Row="10" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Data/L0 Mastering SID" />
|
||||
<TextBox Name="L0MasteringSIDTextBox" Grid.Row="10" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="11" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Data/L0 Toolstamp/Mastering Code" />
|
||||
<TextBox Name="L0ToolstampTextBox" Grid.Row="11" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="12" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Data/L0 Mould SID" />
|
||||
<TextBox Name="L0MouldSIDTextBox" Grid.Row="12" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="13" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Data/L0 Additional Mould" />
|
||||
<TextBox Name="L0AdditionalMouldTextBox" Grid.Row="13" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<!-- Layer 1 / Label Side -->
|
||||
<TextBlock Grid.Row="14" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Label/L1 Mastering Ring" />
|
||||
<TextBox Name="L1MasteringRingTextBox" Grid.Row="14" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" AcceptsTab="True" />
|
||||
|
||||
<TextBlock Grid.Row="15" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Label/L1 Mastering SID" />
|
||||
<TextBox Name="L1MasteringSIDTextBox" Grid.Row="15" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="16" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Label/L1 Toolstamp/Mastering Code" />
|
||||
<TextBox Name="L1ToolstampTextBox" Grid.Row="16" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="17" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Label/L1 Mould SID" />
|
||||
<TextBox Name="L1MouldSIDTextBox" Grid.Row="17" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="18" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Label/L1 Additional Mould" />
|
||||
<TextBox Name="L1AdditionalMouldTextBox" Grid.Row="18" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="19" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Barcode" />
|
||||
<TextBox Name="BarcodeTextBox" Grid.Row="19" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<!-- This needs to be a multiline textbox -->
|
||||
<TextBlock Grid.Row="20" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Comments" />
|
||||
<TextBox Name="CommentsTextBox" Grid.Row="20" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" AcceptsReturn="True" AcceptsTab="True" />
|
||||
|
||||
<!-- This needs to be a multiline textbox -->
|
||||
<TextBlock Grid.Row="21" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Contents" />
|
||||
<TextBox Name="ContentsTextBox" Grid.Row="21" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" AcceptsReturn="True" AcceptsTab="True"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Version and Editions -->
|
||||
<Border Grid.Row="1" Margin="5" BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<TextBlock Text="Version and Editions" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" FontSize="14" Foreground="Gray" />
|
||||
</Border>
|
||||
<Grid Grid.Row="1" Margin="10,15,10,10" ColumnDefinitions="1*,1*" RowDefinitions="25,25">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Version" />
|
||||
<TextBox Name="VersionTextBox" Grid.Row="0" Grid.Column="1" Height="25" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Edition" />
|
||||
<TextBox Name="EditionTextBox" Grid.Row="1" Grid.Column="1" Height="25" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
</Grid>
|
||||
|
||||
<!-- Accept / Cancel -->
|
||||
<Grid Height="25" Grid.Row="2" Grid.Column="0" ColumnDefinitions="2*,1*,1*">
|
||||
<Button Name="AcceptButton" Grid.Row="0" Grid.Column="1" Height="25" Width="80" Content="Accept" Click="OnAcceptClick" />
|
||||
<Button Name="CancelButton" Grid.Row="0" Grid.Column="2" Height="25" Width="80" Content="Cancel" Click="OnCancelClick" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,264 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
public class DiscInformationWindow : Window
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// List of available disc categories
|
||||
/// </summary>
|
||||
public List<CategoryComboBoxItem> Categories { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// SubmissionInfo object to fill and save
|
||||
/// </summary>
|
||||
public SubmissionInfo SubmissionInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of available regions
|
||||
/// </summary>
|
||||
public List<RegionComboBoxItem> Regions { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of available languages
|
||||
/// </summary>
|
||||
public List<LanguageComboBoxItem> Languages { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public DiscInformationWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
PopulateCategories();
|
||||
PopulateRegions();
|
||||
PopulateLanguages();
|
||||
DisableFieldsIfNeeded();
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Disable fields that aren't applicable to the current disc
|
||||
/// </summary>
|
||||
private void DisableFieldsIfNeeded()
|
||||
{
|
||||
// Only disable for single-layer discs
|
||||
if (SubmissionInfo.SizeAndChecksums?.Layerbreak == default(long))
|
||||
{
|
||||
this.Find<TextBox>("L1MasteringRingTextBox").IsEnabled = false;
|
||||
this.Find<TextBox>("L1MasteringRingTextBox").Background = Brushes.Gray;
|
||||
|
||||
this.Find<TextBox>("L1MasteringSIDTextBox").IsEnabled = false;
|
||||
this.Find<TextBox>("L1MasteringSIDTextBox").Background = Brushes.Gray;
|
||||
|
||||
this.Find<TextBox>("L1ToolstampTextBox").IsEnabled = false;
|
||||
this.Find<TextBox>("L1ToolstampTextBox").Background = Brushes.Gray;
|
||||
|
||||
this.Find<TextBox>("L1MouldSIDTextBox").IsEnabled = false;
|
||||
this.Find<TextBox>("L1MouldSIDTextBox").Background = Brushes.Gray;
|
||||
|
||||
this.Find<TextBox>("L1AdditionalMouldTextBox").IsEnabled = false;
|
||||
this.Find<TextBox>("L1AdditionalMouldTextBox").Background = Brushes.Gray;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the current contents of the base SubmissionInfo to the UI
|
||||
/// </summary>
|
||||
public void Load()
|
||||
{
|
||||
// Common Disc Info
|
||||
if (SubmissionInfo.CommonDiscInfo == null)
|
||||
SubmissionInfo.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
|
||||
this.Find<TextBox>("TitleTextBox").Text = SubmissionInfo.CommonDiscInfo.Title ?? "";
|
||||
this.Find<TextBox>("ForeignTitleTextBox").Text = SubmissionInfo.CommonDiscInfo.ForeignTitleNonLatin ?? "";
|
||||
this.Find<TextBox>("DiscNumberLetterTextBox").Text = SubmissionInfo.CommonDiscInfo.DiscNumberLetter ?? "";
|
||||
this.Find<TextBox>("DiscTitleTextBox").Text = SubmissionInfo.CommonDiscInfo.DiscTitle ?? "";
|
||||
this.Find<ComboBox>("CategoryComboBox").SelectedIndex = Categories.FindIndex(r => r == SubmissionInfo.CommonDiscInfo.Category);
|
||||
this.Find<ComboBox>("RegionComboBox").SelectedIndex = Regions.FindIndex(r => r == SubmissionInfo.CommonDiscInfo.Region);
|
||||
if (SubmissionInfo.CommonDiscInfo.Languages != null)
|
||||
{
|
||||
foreach (var language in SubmissionInfo.CommonDiscInfo.Languages)
|
||||
Languages.Find(l => l == language).IsChecked = true;
|
||||
}
|
||||
|
||||
this.Find<TextBox>("SerialTextBox").Text = SubmissionInfo.CommonDiscInfo.Serial ?? "";
|
||||
this.Find<TextBox>("L0MasteringRingTextBox").Text = SubmissionInfo.CommonDiscInfo.MasteringRingFirstLayerDataSide ?? "";
|
||||
this.Find<TextBox>("L0MasteringSIDTextBox").Text = SubmissionInfo.CommonDiscInfo.MasteringSIDCodeFirstLayerDataSide ?? "";
|
||||
this.Find<TextBox>("L0ToolstampTextBox").Text = SubmissionInfo.CommonDiscInfo.ToolstampMasteringCodeFirstLayerDataSide ?? "";
|
||||
this.Find<TextBox>("L0MouldSIDTextBox").Text = SubmissionInfo.CommonDiscInfo.MouldSIDCodeFirstLayerDataSide ?? "";
|
||||
this.Find<TextBox>("L0AdditionalMouldTextBox").Text = SubmissionInfo.CommonDiscInfo.AdditionalMouldFirstLayerDataSide ?? "";
|
||||
this.Find<TextBox>("L1MasteringRingTextBox").Text = SubmissionInfo.CommonDiscInfo.MasteringRingSecondLayerLabelSide ?? "";
|
||||
this.Find<TextBox>("L1MasteringSIDTextBox").Text = SubmissionInfo.CommonDiscInfo.MasteringSIDCodeSecondLayerLabelSide ?? "";
|
||||
this.Find<TextBox>("L1ToolstampTextBox").Text = SubmissionInfo.CommonDiscInfo.ToolstampMasteringCodeSecondLayerLabelSide ?? "";
|
||||
this.Find<TextBox>("L1MouldSIDTextBox").Text = SubmissionInfo.CommonDiscInfo.MouldSIDCodeSecondLayerLabelSide ?? "";
|
||||
this.Find<TextBox>("L1AdditionalMouldTextBox").Text = SubmissionInfo.CommonDiscInfo.AdditionalMouldSecondLayerLabelSide ?? "";
|
||||
this.Find<TextBox>("BarcodeTextBox").Text = SubmissionInfo.CommonDiscInfo.Barcode ?? "";
|
||||
this.Find<TextBox>("CommentsTextBox").Text = SubmissionInfo.CommonDiscInfo.Comments ?? "";
|
||||
this.Find<TextBox>("ContentsTextBox").Text = SubmissionInfo.CommonDiscInfo.Contents ?? "";
|
||||
|
||||
// Version and Editions
|
||||
if (SubmissionInfo.VersionAndEditions == null)
|
||||
SubmissionInfo.VersionAndEditions = new VersionAndEditionsSection();
|
||||
|
||||
this.Find<TextBox>("VersionTextBox").Text = SubmissionInfo.VersionAndEditions.Version ?? "";
|
||||
this.Find<TextBox>("EditionTextBox").Text = SubmissionInfo.VersionAndEditions.OtherEditions ?? "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of categories and fill the combo box
|
||||
/// </summary>
|
||||
private void PopulateCategories()
|
||||
{
|
||||
var categories = Enum.GetValues(typeof(DiscCategory)).OfType<DiscCategory?>().ToList();
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Populating categories, {0} categories found.", categories.Count);
|
||||
|
||||
Categories = new List<CategoryComboBoxItem>();
|
||||
foreach (var category in categories)
|
||||
{
|
||||
Categories.Add(new CategoryComboBoxItem(category));
|
||||
}
|
||||
|
||||
this.Find<ComboBox>("CategoryComboBox").Items = Categories;
|
||||
this.Find<ComboBox>("CategoryComboBox").SelectedIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of languages and fill the combo box
|
||||
/// </summary>
|
||||
private void PopulateLanguages()
|
||||
{
|
||||
var languages = Enum.GetValues(typeof(Language)).OfType<Language?>().ToList();
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Populating languages, {0} languages found.", languages.Count);
|
||||
|
||||
Languages = new List<LanguageComboBoxItem>();
|
||||
foreach (var language in languages)
|
||||
{
|
||||
Languages.Add(new LanguageComboBoxItem(language));
|
||||
}
|
||||
|
||||
this.Find<ComboBox>("LanguagesComboBox").Items = Languages;
|
||||
this.Find<ComboBox>("LanguagesComboBox").SelectedIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of regions and fill the combo box
|
||||
/// </summary>
|
||||
private void PopulateRegions()
|
||||
{
|
||||
var regions = Enum.GetValues(typeof(Region)).OfType<Region?>().ToList();
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Populating regions, {0} regions found.", regions.Count);
|
||||
|
||||
Regions = new List<RegionComboBoxItem>();
|
||||
foreach (var region in regions)
|
||||
{
|
||||
Regions.Add(new RegionComboBoxItem(region));
|
||||
}
|
||||
|
||||
this.Find<ComboBox>("RegionComboBox").Items = Regions;
|
||||
this.Find<ComboBox>("RegionComboBox").SelectedIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the current contents of the UI to the base SubmissionInfo
|
||||
/// </summary>
|
||||
private void Save()
|
||||
{
|
||||
// Common Disc Info
|
||||
if (SubmissionInfo.CommonDiscInfo == null)
|
||||
SubmissionInfo.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
|
||||
SubmissionInfo.CommonDiscInfo.Title = this.Find<TextBox>("TitleTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.ForeignTitleNonLatin = this.Find<TextBox>("ForeignTitleTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.DiscNumberLetter = this.Find<TextBox>(" DiscNumberLetterTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.DiscTitle = this.Find<TextBox>("DiscTitleTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.Category = (this.Find<ComboBox>("CategoryComboBox").SelectedItem as CategoryComboBoxItem)?.Value ?? DiscCategory.Games;
|
||||
SubmissionInfo.CommonDiscInfo.Region = (this.Find<ComboBox>("RegionComboBox").SelectedItem as RegionComboBoxItem)?.Value ?? Region.World;
|
||||
var languages = new List<Language?>();
|
||||
foreach (var language in Languages)
|
||||
{
|
||||
if (language.IsChecked)
|
||||
languages.Add(language.Value);
|
||||
}
|
||||
if (languages.Count == 0)
|
||||
languages.Add(null);
|
||||
|
||||
SubmissionInfo.CommonDiscInfo.Languages = languages.ToArray();
|
||||
SubmissionInfo.CommonDiscInfo.Serial = this.Find<TextBox>("SerialTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MasteringRingFirstLayerDataSide = this.Find<TextBox>("L0MasteringRingTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MasteringSIDCodeFirstLayerDataSide = this.Find<TextBox>("L0MasteringSIDTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.ToolstampMasteringCodeFirstLayerDataSide = this.Find<TextBox>("L0ToolstampTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MouldSIDCodeFirstLayerDataSide = this.Find<TextBox>("L0MouldSIDTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.AdditionalMouldFirstLayerDataSide = this.Find<TextBox>("L0AdditionalMouldTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MasteringRingSecondLayerLabelSide = this.Find<TextBox>("L1MasteringRingTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MasteringSIDCodeSecondLayerLabelSide = this.Find<TextBox>("L1MasteringSIDTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.ToolstampMasteringCodeSecondLayerLabelSide = this.Find<TextBox>("L1ToolstampTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MouldSIDCodeSecondLayerLabelSide = this.Find<TextBox>("L1MouldSIDTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.AdditionalMouldSecondLayerLabelSide = this.Find<TextBox>("L1AdditionalMouldTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.Barcode = this.Find<TextBox>("BarcodeTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.Comments = this.Find<TextBox>("CommentsTextBox").Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.Contents = this.Find<TextBox>("ContentsTextBox").Text ?? "";
|
||||
|
||||
// Version and Editions
|
||||
if (SubmissionInfo.VersionAndEditions == null)
|
||||
SubmissionInfo.VersionAndEditions = new VersionAndEditionsSection();
|
||||
|
||||
SubmissionInfo.VersionAndEditions.Version = this.Find<TextBox>("VersionTextBox").Text ?? "";
|
||||
SubmissionInfo.VersionAndEditions.OtherEditions = this.Find<TextBox>("EditionTextBox").Text ?? "";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Handler for AcceptButton Click event
|
||||
/// </summary>
|
||||
private void OnAcceptClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Save();
|
||||
Hide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for CancelButton Click event
|
||||
/// </summary>
|
||||
private void OnCancelClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for DiscInformationWindow Closed event
|
||||
/// </summary>
|
||||
private void OnClosed(object sender, EventArgs e)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to provide a converter to XAML files to render comboboxes with enum values
|
||||
/// </summary>
|
||||
public class EnumDescriptionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
// Common
|
||||
if (value is MediaType?)
|
||||
return ((MediaType?)value).LongName();
|
||||
else if (value is KnownSystem?)
|
||||
return ((KnownSystem?)value).LongName();
|
||||
|
||||
// Default
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:DICUI.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="350" Width="600" Height="350"
|
||||
x:Class="DICUI.Avalonia.LogWindow" Icon="Icon.ico" CanResize="False"
|
||||
Title="Log Window">
|
||||
|
||||
<Grid RowDefinitions="40,250,40">
|
||||
|
||||
<!-- Progress Bar -->
|
||||
<Grid Grid.Row="0" Height="25" Margin="10 10 10 0">
|
||||
<ProgressBar Name="ProgressBar" />
|
||||
<TextBlock Name="ProgressLabel" Grid.Row="0" Height="25" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
|
||||
<!-- Log Area -->
|
||||
<Border Grid.Row="1" Background="White" BorderBrush="Gainsboro" BorderThickness="1" Margin="10">
|
||||
<ScrollViewer Name="OutputViewer">
|
||||
<TextBox Name="Output" FontFamily="Consolas" Background="Gray" IsReadOnly="True" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
|
||||
<!-- Options -->
|
||||
<Grid Grid.Row="2" RowDefinitions="Auto" ColumnDefinitions="Auto,Auto,3*,Auto,Auto,Auto">
|
||||
<CheckBox Name="VerboseCheckBox" Grid.Column="0" Height="25" VerticalAlignment="Center" Margin="10 0 0 10"
|
||||
Content="Verbose" DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=VerboseLogging}"
|
||||
ToolTip.Tip="Enable verbose logging of tasks" />
|
||||
<CheckBox Name="OpenAtStartupCheckBox" Grid.Column="1" Grid.ColumnSpan="2" Height="25" VerticalAlignment="Center" Margin="10 0 0 10"
|
||||
Content="Open at startup" DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=OpenLogWindowAtStartup}"
|
||||
ToolTip.Tip="Open this window at startup" />
|
||||
<Button Margin="0 0 10 10" Grid.Column="3" Height="25" Width="60" Content="Clear" HorizontalAlignment="Right" Click="OnClearButton" />
|
||||
<Button Margin="0 0 10 10" Grid.Column="4" Height="25" Width="60" Content="Hide" HorizontalAlignment="Right" Click="OnHideButton" />
|
||||
<Button Margin="0 0 10 10" Grid.Column="5" Height="25" Width="60" Content="Save" HorizontalAlignment="Right" Click="OnSaveButton" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,82 +0,0 @@
|
||||
using System.IO;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
public class LogWindow : Window
|
||||
{
|
||||
public LogWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjust the position of the log window if the main window is moved
|
||||
/// </summary>
|
||||
public void AdjustPositionToMainWindow()
|
||||
{
|
||||
var owner = Owner as Window;
|
||||
Position = new PixelPoint(
|
||||
owner.Position.X,
|
||||
owner.Position.Y + (int)owner.Height + Constants.LogWindowMarginFromMainWindow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append rich text to the scrolling element
|
||||
/// </summary>
|
||||
/// <param name="text">Text to add, including newlines</param>
|
||||
/// <param name="color">Color to format the text</param>
|
||||
public void AppendToTextBox(string text, ISolidColorBrush color)
|
||||
{
|
||||
// TODO: Use brush color
|
||||
this.Find<TextBox>("Output").Text += $"{text}\n";
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ClearButton Click event
|
||||
/// </summary>
|
||||
private void OnClearButton(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Find<TextBox>("Output").Text = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for HideButton Click event
|
||||
/// </summary>
|
||||
private void OnHideButton(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewModels.LoggerViewModel.WindowVisible = false;
|
||||
|
||||
//TODO: this should be bound directly to WindowVisible property in two way fashion
|
||||
// we need to study how to properly do it in XAML
|
||||
(Owner as MainWindow).Find<CheckBox>("ShowLogCheckBox").IsChecked = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for SaveButton Click event
|
||||
/// </summary>
|
||||
private void OnSaveButton(object sender, RoutedEventArgs e)
|
||||
{
|
||||
using (StreamWriter tw = new StreamWriter(File.OpenWrite("console.log")))
|
||||
{
|
||||
tw.Write(this.Find<TextBox>("Output").Text);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:DICUI.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="450" Width="600" Height="450"
|
||||
x:Class="DICUI.Avalonia.MainWindow" Icon="Icon.ico" CanResize="False"
|
||||
Title="DICUI" WindowStartupLocation="CenterScreen"
|
||||
PositionChanged="MainWindowLocationChanged" Activated="MainWindowActivated" Closing="MainWindowClosing">
|
||||
|
||||
<Window.Resources>
|
||||
<local:EnumDescriptionConverter x:Key="enumConverter" />
|
||||
</Window.Resources>
|
||||
|
||||
<Grid ColumnDefinitions="4*,13*" RowDefinitions="30,4*,1*,1*">
|
||||
|
||||
<!-- Menu Bar -->
|
||||
<StackPanel VerticalAlignment="Top" Grid.ColumnSpan="4">
|
||||
<Menu Height="20" >
|
||||
<MenuItem Header="_File">
|
||||
<MenuItem Name="AppExitMenuItem" Header="E_xit" HorizontalAlignment="Left" Width="185" Click="AppExitMenuItemClick" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Tools">
|
||||
<MenuItem Name="OptionsMenuItem" Header="_Options" HorizontalAlignment="Left" Width="185" Click="OptionsMenuItemClick" />
|
||||
<MenuItem Name="ShowLogMenuItem" Header="Show _Log Window" HorizontalAlignment="Left" Width="185">
|
||||
<MenuItem.Icon>
|
||||
<CheckBox Name="ShowLogCheckBox" BorderThickness="0" DataContext="{Binding Source={x:Static local:ViewModels.LoggerViewModel}}" IsChecked="{Binding Path=WindowVisible}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Help">
|
||||
<MenuItem Name="AboutMenuItem" Header="_About" HorizontalAlignment="Left" Width="185" Click="AboutMenuItemClick" />
|
||||
<MenuItem Name="CheckForUpdatesMenuItem" Header="_Check for Updates" HorizontalAlignment="Left" Width="185" Click="CheckForUpdatesMenuItemClick" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Settings -->
|
||||
<Border Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,5,5.2,5.4" BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="Settings" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" FontSize="14" Foreground="Gray" />
|
||||
</Border>
|
||||
<Grid Grid.Row="1" Grid.Column="0" Margin="15,25,15.2,10.4" Grid.ColumnSpan="2" ColumnDefinitions="1*,2.5*" RowDefinitions="1*,1*,1*,1*,1*,1*">
|
||||
|
||||
<!-- System / Media Type Selection -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Text="System/Media Type" />
|
||||
<ComboBox Name="SystemTypeComboBox" Grid.Row="0" Grid.Column="1" Height="25" Width="250" HorizontalAlignment="Left" AutoScrollToSelectedItem="True" SelectionChanged="SystemTypeComboBoxSelectionChanged">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=Name}" Foreground="{Binding Path=Foreground}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<ComboBox Name="MediaTypeComboBox" Grid.Row="0" Grid.Column="1" Height="25" Width="140" HorizontalAlignment="Right" AutoScrollToSelectedItem="True" SelectionChanged="MediaTypeComboBoxSelectionChanged">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={StaticResource enumConverter}}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<!-- Output Filename -->
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Text="Output Filename" />
|
||||
<TextBox Name="OutputFilenameTextBox" Grid.Row="1" Grid.Column="1" Height="25" ScrollViewer.VerticalScrollBarVisibility="Disabled" TextInput="OutputFilenameTextBoxTextChanged" />
|
||||
|
||||
<!-- Output Directory -->
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Text="Output Directory" />
|
||||
<TextBox Name="OutputDirectoryTextBox" Grid.Row="2" Grid.Column="1" Height="25" Width="345" HorizontalAlignment="Left" ScrollViewer.VerticalScrollBarVisibility="Disabled" TextInput="OutputDirectoryTextBoxTextChanged" />
|
||||
<Button Name="OutputDirectoryBrowseButton" Grid.Row="2" Grid.Column="1" Height="25" Width="50" HorizontalAlignment="Right" Content="Browse" Click="OutputDirectoryBrowseButtonClick" />
|
||||
|
||||
<!-- Drive Letter -->
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Text="Drive Letter" />
|
||||
<ComboBox Name="DriveLetterComboBox" Grid.Row="3" Grid.Column="1" Height="25" Width="60" HorizontalAlignment="Left" SelectionChanged="DriveLetterComboBoxSelectionChanged">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=Letter}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<!-- Drive Speed -->
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" Text="Drive Speed" />
|
||||
<ComboBox Name="DriveSpeedComboBox" Grid.Row="4" Grid.Column="1" Height="25" Width="60" HorizontalAlignment="Left" SelectionChanged="DriveSpeedComboBoxSelectionChanged" />
|
||||
|
||||
<!-- Parameters -->
|
||||
<TextBlock Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" Text="Parameters" />
|
||||
<TextBox Name="ParametersTextBox" Grid.Row="5" Grid.Column="1" Height="25" Width="370" HorizontalAlignment="Left" ScrollViewer.VerticalScrollBarVisibility="Disabled" IsEnabled="False" />
|
||||
<CheckBox Name="EnableParametersCheckBox" Grid.Row="5" Grid.Column="1" Height="25" HorizontalAlignment="Right" IsChecked="False" Click="EnableParametersCheckBoxClick" />
|
||||
</Grid>
|
||||
|
||||
<!-- Controls -->
|
||||
<Border Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,4.6,5.2,4.8" BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="Controls" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" FontSize="14" Foreground="Gray" />
|
||||
</Border>
|
||||
<Grid Grid.Row="2" Grid.Column="0" Margin="15,19.6,15.2,9.8" Grid.ColumnSpan="2" ColumnDefinitions="1*,1*,1*,1*" RowDefinitions="1*">
|
||||
<Button Name="StartStopButton" Grid.Row="0" Grid.Column="0" Height="25" Width="125" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Start Dumping" Click="StartStopButtonClick" IsEnabled="False" />
|
||||
<Button Name="MediaScanButton" Grid.Row="0" Grid.Column="1" Height="25" Width="125" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Scan For Media" Click="MediaScanButtonClick" />
|
||||
<Button Name="CopyProtectScanButton" Grid.Row="0" Grid.Column="2" Height="25" Width="125" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Scan For Protection" Click="CopyProtectScanButtonClick" />
|
||||
<CheckBox Name="EjectWhenDoneCheckBox" Grid.Row="0" Grid.Column="3" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Eject When Done" IsChecked="False" />
|
||||
</Grid>
|
||||
|
||||
<!-- Status -->
|
||||
<Border Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,5.2,5.2,4.8" BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="Status" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" FontSize="14" Foreground="Gray" />
|
||||
</Border>
|
||||
<Grid Grid.Row="3" Grid.Column="0" Margin="15,20.2,15.2,9.8" Grid.ColumnSpan="2" ColumnDefinitions="1*" RowDefinitions="1*">
|
||||
<TextBlock Name="StatusLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" Text="Waiting for media..." />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,820 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using BurnOutSharp;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
public class MainWindow : Window
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected or detected media type
|
||||
/// </summary>
|
||||
public MediaType? CurrentMediaType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current list of drives
|
||||
/// </summary>
|
||||
public List<Drive> Drives { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current dumping environment
|
||||
/// </summary>
|
||||
public DumpEnvironment Env { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current list of supported media types
|
||||
/// </summary>
|
||||
public List<MediaType?> MediaTypes { get; private set; } = new List<MediaType?>();
|
||||
|
||||
/// <summary>
|
||||
/// Current list of supported system profiles
|
||||
/// </summary>
|
||||
public List<KnownSystemComboBoxItem> Systems { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current UI options
|
||||
/// </summary>
|
||||
public UIOptions UIOptions { get; private set; } = new UIOptions();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Instance Variables
|
||||
|
||||
/// <summary>
|
||||
/// Current attached LogWindow
|
||||
/// </summary>
|
||||
private LogWindow logWindow;
|
||||
|
||||
#endregion
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
// Load the options
|
||||
ViewModels.OptionsViewModel = new OptionsViewModel(UIOptions);
|
||||
|
||||
// Load the log window
|
||||
logWindow = new LogWindow();
|
||||
logWindow.Owner = this;
|
||||
ViewModels.LoggerViewModel.SetWindow(logWindow);
|
||||
|
||||
// Disable buttons until we load
|
||||
this.Find<Button>("StartStopButton").IsEnabled = false;
|
||||
this.Find<Button>("MediaScanButton").IsEnabled = false;
|
||||
this.Find<Button>("CopyProtectScanButton").IsEnabled = false;
|
||||
|
||||
// TODO: If log window open, "dock" it to the current Window
|
||||
|
||||
if (UIOptions.OpenLogWindowAtStartup)
|
||||
{
|
||||
//TODO: this should be bound directly to WindowVisible property in two way fashion
|
||||
// we need to study how to properly do it in XAML
|
||||
this.Find<CheckBox>("ShowLogCheckBox").IsChecked = true;
|
||||
ViewModels.LoggerViewModel.WindowVisible = true;
|
||||
}
|
||||
|
||||
// Populate the list of systems
|
||||
this.Find<TextBlock>("StatusLabel").Text = "Creating system list, please wait!";
|
||||
PopulateSystems();
|
||||
|
||||
// Populate the list of drives
|
||||
this.Find<TextBlock>("StatusLabel").Text = "Creating drive list, please wait!";
|
||||
PopulateDrives();
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Browse for an output folder
|
||||
/// </summary>
|
||||
private async void BrowseFolder()
|
||||
{
|
||||
OpenFolderDialog folderDialog = new OpenFolderDialog { Directory = AppDomain.CurrentDomain.BaseDirectory };
|
||||
string directory = await folderDialog.ShowAsync(this);
|
||||
if (!string.IsNullOrWhiteSpace(directory))
|
||||
this.Find<TextBox>("OutputDirectoryTextBox").Text = directory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache the current disc type to internal variable
|
||||
/// </summary>
|
||||
private void CacheCurrentDiscType()
|
||||
{
|
||||
// Get the drive letter from the selected item
|
||||
if (this.Find<ComboBox>("DriveLetterComboBox").SelectedItem is Drive drive)
|
||||
{
|
||||
// Get the current media type
|
||||
if (!UIOptions.SkipMediaTypeDetection)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLog("Trying to detect media type for drive {0}.. ", drive.Letter);
|
||||
CurrentMediaType = Validators.GetMediaType(drive);
|
||||
ViewModels.LoggerViewModel.VerboseLogLn(CurrentMediaType == null ? "unable to detect." : ("detected " + CurrentMediaType.LongName() + "."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a DumpEnvironment with all current settings
|
||||
/// </summary>
|
||||
/// <returns>Filled DumpEnvironment instance</returns>
|
||||
private DumpEnvironment DetermineEnvironment()
|
||||
{
|
||||
// Populate the new environment
|
||||
var env = new DumpEnvironment(UIOptions.Options,
|
||||
this.Find<TextBox>("OutputDirectoryTextBox").Text,
|
||||
this.Find<TextBox>("OutputFilenameTextBox").Text,
|
||||
this.Find<ComboBox>("DriveLetterComboBox").SelectedItem as Drive,
|
||||
this.Find<ComboBox>("SystemTypeComboBox").SelectedItem as KnownSystemComboBoxItem,
|
||||
this.Find<ComboBox>("MediaTypeComboBox").SelectedItem as MediaType?,
|
||||
this.Find<TextBox>("ParametersTextBox").Text);
|
||||
|
||||
// Disable automatic reprocessing of the textboxes until we're done
|
||||
this.Find<TextBox>("OutputDirectoryTextBox").TextInput -= OutputDirectoryTextBoxTextChanged;
|
||||
this.Find<TextBox>("OutputFilenameTextBox").TextInput -= OutputFilenameTextBoxTextChanged;
|
||||
|
||||
this.Find<TextBox>("OutputDirectoryTextBox").Text = env.OutputDirectory;
|
||||
this.Find<TextBox>("OutputFilenameTextBox").Text = env.OutputFilename;
|
||||
|
||||
this.Find<TextBox>("OutputDirectoryTextBox").TextInput += OutputDirectoryTextBoxTextChanged;
|
||||
this.Find<TextBox>("OutputFilenameTextBox").TextInput += OutputFilenameTextBoxTextChanged;
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure information is consistent with the currently selected disc type
|
||||
/// </summary>
|
||||
private void EnsureDiscInformation()
|
||||
{
|
||||
// Get the current environment information
|
||||
Env = DetermineEnvironment();
|
||||
|
||||
// Take care of null cases
|
||||
if (Env.System == null)
|
||||
Env.System = KnownSystem.NONE;
|
||||
if (Env.Type == null)
|
||||
Env.Type = MediaType.NONE;
|
||||
|
||||
// Get the status to write out
|
||||
Result result = Validators.GetSupportStatus(Env.System, Env.Type);
|
||||
this.Find<TextBlock>("StatusLabel").Text = result.Message;
|
||||
|
||||
// Set the index for the current disc type
|
||||
SetCurrentDiscType();
|
||||
|
||||
this.Find<Button>("StartStopButton").IsEnabled = result && (Drives != null && Drives.Count > 0 ? true : false);
|
||||
|
||||
// If we're in a type that doesn't support drive speeds
|
||||
this.Find<ComboBox>("DriveSpeedComboBox").IsEnabled = Env.Type.DoesSupportDriveSpeed();
|
||||
|
||||
// If input params are not enabled, generate the full parameters from the environment
|
||||
if (!this.Find<TextBox>("ParametersTextBox").IsEnabled)
|
||||
{
|
||||
string generated = Env.GetFullParameters((int?)this.Find<ComboBox>("DriveSpeedComboBox").SelectedItem);
|
||||
if (generated != null)
|
||||
this.Find<TextBox>("ParametersTextBox").Text = generated;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default output directory name from the currently selected drive
|
||||
/// </summary>
|
||||
/// <param name="driveChanged">Force an updated name if the drive letter changes</param>
|
||||
private void GetOutputNames(bool driveChanged)
|
||||
{
|
||||
Drive drive = this.Find<ComboBox>("DriveLetterComboBox").SelectedItem as Drive;
|
||||
KnownSystem? systemType = this.Find<ComboBox>("SystemTypeComboBox").SelectedItem as KnownSystemComboBoxItem;
|
||||
MediaType? mediaType = this.Find<ComboBox>("MediaTypeComboBox").SelectedItem as MediaType?;
|
||||
|
||||
// Set the output directory, if we changed drives or it's not already
|
||||
if (driveChanged || string.IsNullOrEmpty(this.Find<TextBox>("OutputDirectoryTextBox").Text))
|
||||
this.Find<TextBox>("OutputDirectoryTextBox").Text = Path.Combine(UIOptions.DefaultOutputPath, drive?.VolumeLabel ?? string.Empty);
|
||||
|
||||
// Get the extension for the file for the next two statements
|
||||
string extension = Env?.GetExtension(mediaType);
|
||||
|
||||
// Set the output filename, if we changed drives or it's not already
|
||||
if (driveChanged || string.IsNullOrEmpty(this.Find<TextBox>("OutputFilenameTextBox").Text))
|
||||
this.Find<TextBox>("OutputFilenameTextBox").Text = (drive?.VolumeLabel ?? systemType.LongName()) + (extension ?? ".bin");
|
||||
|
||||
// If the extension for the file changed, update that automatically
|
||||
else if (Path.GetExtension(this.Find<TextBox>("OutputFilenameTextBox").Text) != extension)
|
||||
this.Find<TextBox>("OutputFilenameTextBox").Text = Path.GetFileNameWithoutExtension(this.Find<TextBox>("OutputFilenameTextBox").Text) + (extension ?? ".bin");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of active disc drives and fill the combo box
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Find a way for this to periodically run, or have it hook to a "drive change" event</remarks>
|
||||
private void PopulateDrives()
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Scanning for drives..");
|
||||
|
||||
// Always enable the disk scan
|
||||
this.Find<Button>("MediaScanButton").IsEnabled = true;
|
||||
|
||||
// Populate the list of drives and add it to the combo box
|
||||
Drives = Validators.CreateListOfDrives(UIOptions.IgnoreFixedDrives);
|
||||
this.Find<ComboBox>("DriveLetterComboBox").Items = Drives;
|
||||
|
||||
if (Drives.Any())
|
||||
{
|
||||
// Check for active optical drives first
|
||||
int index = Drives.FindIndex(d => d.MarkedActive && d.InternalDriveType == InternalDriveType.Optical);
|
||||
|
||||
// Then we check for floppy drives
|
||||
if (index == -1)
|
||||
index = Drives.FindIndex(d => d.MarkedActive && d.InternalDriveType == InternalDriveType.Floppy);
|
||||
|
||||
// Then we try all other drive types
|
||||
if (index == -1)
|
||||
index = Drives.FindIndex(d => d.MarkedActive);
|
||||
|
||||
// Set the selected index
|
||||
this.Find<ComboBox>("DriveLetterComboBox").SelectedIndex = (index != -1 ? index : 0);
|
||||
this.Find<TextBlock>("StatusLabel").Text = "Valid drive found! Choose your Media Type";
|
||||
this.Find<Button>("CopyProtectScanButton").IsEnabled = true;
|
||||
|
||||
// Get the current media type
|
||||
if (!UIOptions.SkipSystemDetection && index != -1)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLog("Trying to detect system for drive {0}.. ", Drives[index].Letter);
|
||||
var currentSystem = Validators.GetKnownSystem(Drives[index]);
|
||||
ViewModels.LoggerViewModel.VerboseLogLn(currentSystem == null || currentSystem == KnownSystem.NONE ? "unable to detect." : ("detected " + currentSystem.LongName() + "."));
|
||||
|
||||
if (currentSystem != null && currentSystem != KnownSystem.NONE)
|
||||
{
|
||||
int sysIndex = Systems.FindIndex(s => s == currentSystem);
|
||||
this.Find<ComboBox>("SystemTypeComboBox").SelectedIndex = sysIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// Only enable the start/stop if we don't have the default selected
|
||||
this.Find<Button>("StartStopButton").IsEnabled = (this.Find<ComboBox>("SystemTypeComboBox").SelectedItem as KnownSystemComboBoxItem) != KnownSystem.NONE;
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Found {0} drives: {1}", Drives.Count, string.Join(", ", Drives.Select(d => d.Letter)));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Find<ComboBox>("DriveLetterComboBox").SelectedIndex = -1;
|
||||
this.Find<TextBlock>("StatusLabel").Text = "No valid drive found!";
|
||||
this.Find<Button>("StartStopButton").IsEnabled = false;
|
||||
this.Find<Button>("CopyProtectScanButton").IsEnabled = false;
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Found no drives");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate media type according to system type
|
||||
/// </summary>
|
||||
private void PopulateMediaType()
|
||||
{
|
||||
KnownSystem? currentSystem = this.Find<ComboBox>("SystemTypeComboBox").SelectedItem as KnownSystemComboBoxItem;
|
||||
|
||||
if (currentSystem != null)
|
||||
{
|
||||
MediaTypes = Validators.GetValidMediaTypes(currentSystem);
|
||||
this.Find<ComboBox>("MediaTypeComboBox").Items = MediaTypes;
|
||||
this.Find<ComboBox>("MediaTypeComboBox").IsEnabled = MediaTypes.Count > 1;
|
||||
this.Find<ComboBox>("MediaTypeComboBox").SelectedIndex = (MediaTypes.IndexOf(CurrentMediaType) >= 0 ? MediaTypes.IndexOf(CurrentMediaType) : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Find<ComboBox>("MediaTypeComboBox").Items = null;
|
||||
this.Find<ComboBox>("MediaTypeComboBox").IsEnabled = false;
|
||||
this.Find<ComboBox>("MediaTypeComboBox").SelectedIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of supported systems and fill the combo box
|
||||
/// </summary>
|
||||
private void PopulateSystems()
|
||||
{
|
||||
var knownSystems = Validators.CreateListOfSystems();
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Populating systems, {0} systems found.", knownSystems.Count);
|
||||
|
||||
Dictionary<KnownSystemCategory, List<KnownSystem?>> mapping = knownSystems
|
||||
.GroupBy(s => s.Category())
|
||||
.ToDictionary(
|
||||
k => k.Key,
|
||||
v => v
|
||||
.OrderBy(s => s.LongName())
|
||||
.ToList()
|
||||
);
|
||||
|
||||
Systems = new List<KnownSystemComboBoxItem>()
|
||||
{
|
||||
new KnownSystemComboBoxItem(KnownSystem.NONE),
|
||||
};
|
||||
|
||||
foreach (var group in mapping)
|
||||
{
|
||||
Systems.Add(new KnownSystemComboBoxItem(group.Key));
|
||||
group.Value.ForEach(system => Systems.Add(new KnownSystemComboBoxItem(system)));
|
||||
}
|
||||
|
||||
this.Find<ComboBox>("SystemTypeComboBox").Items = Systems;
|
||||
this.Find<ComboBox>("SystemTypeComboBox").SelectedIndex = 0;
|
||||
|
||||
this.Find<Button>("StartStopButton").IsEnabled = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the current custom parameters back into UI values
|
||||
/// </summary>
|
||||
private void ProcessCustomParameters()
|
||||
{
|
||||
Env.SetParameters(this.Find<TextBox>("ParametersTextBox").Text);
|
||||
if (Env.Parameters == null)
|
||||
return;
|
||||
|
||||
int driveIndex = Drives.Select(d => d.Letter).ToList().IndexOf(Env.Parameters.InputPath()[0]);
|
||||
if (driveIndex > -1)
|
||||
this.Find<ComboBox>("DriveLetterComboBox").SelectedIndex = driveIndex;
|
||||
|
||||
int driveSpeed = Env.Parameters.GetSpeed() ?? -1;
|
||||
if (driveSpeed > 0)
|
||||
this.Find<ComboBox>("DriveSpeedComboBox").SelectedItem = driveSpeed;
|
||||
else
|
||||
Env.Parameters.SetSpeed((int?)this.Find<ComboBox>("DriveSpeedComboBox").SelectedItem);
|
||||
|
||||
string trimmedPath = Env.Parameters.OutputPath()?.Trim('"') ?? string.Empty;
|
||||
string outputDirectory = Path.GetDirectoryName(trimmedPath);
|
||||
string outputFilename = Path.GetFileName(trimmedPath);
|
||||
if (!string.IsNullOrWhiteSpace(outputDirectory))
|
||||
this.Find<TextBox>("OutputDirectoryTextBox").Text = outputDirectory;
|
||||
else
|
||||
outputDirectory = this.Find<TextBox>("OutputDirectoryTextBox").Text;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(outputFilename))
|
||||
this.Find<TextBox>("OutputFilenameTextBox").Text = outputFilename;
|
||||
else
|
||||
outputFilename = this.Find<TextBox>("OutputFilenameTextBox").Text;
|
||||
|
||||
MediaType? mediaType = Env.Parameters.GetMediaType();
|
||||
int mediaTypeIndex = MediaTypes.IndexOf(mediaType);
|
||||
if (mediaTypeIndex > -1)
|
||||
this.Find<ComboBox>("MediaTypeComboBox").SelectedIndex = mediaTypeIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan and show copy protection for the current disc
|
||||
/// </summary>
|
||||
private async void ScanAndShowProtection()
|
||||
{
|
||||
if (Env == null)
|
||||
Env = DetermineEnvironment();
|
||||
|
||||
if (Env.Drive.Letter != default(char))
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Scanning for copy protection in {0}", Env.Drive.Letter);
|
||||
|
||||
var tempContent = this.Find<TextBlock>("StatusLabel").Text;
|
||||
this.Find<TextBlock>("StatusLabel").Text = "Scanning for copy protection... this might take a while!";
|
||||
this.Find<Button>("StartStopButton").IsEnabled = false;
|
||||
this.Find<Button>("MediaScanButton").IsEnabled = false;
|
||||
this.Find<Button>("CopyProtectScanButton").IsEnabled = false;
|
||||
|
||||
var progress = new Progress<FileProtection>();
|
||||
progress.ProgressChanged += ProgressUpdated;
|
||||
string protections = await Validators.RunProtectionScanOnPath(Env.Drive.Letter + ":\\");
|
||||
|
||||
// If SmartE is detected on the current disc, remove `/sf` from the flags for DIC only
|
||||
if (Env.InternalProgram == InternalProgram.DiscImageCreator && protections.Contains("SmartE"))
|
||||
{
|
||||
((DiscImageCreator.Parameters)Env.Parameters)[DiscImageCreator.Flag.ScanFileProtect] = false;
|
||||
ViewModels.LoggerViewModel.VerboseLogLn($"SmartE detected, removing {DiscImageCreator.FlagStrings.ScanFileProtect} from parameters");
|
||||
}
|
||||
|
||||
if (!ViewModels.LoggerViewModel.WindowVisible)
|
||||
{
|
||||
new Window()
|
||||
{
|
||||
Title = "Detected Protection",
|
||||
Content = protections,
|
||||
SizeToContent = SizeToContent.WidthAndHeight,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
}.ShowDialog(this);
|
||||
}
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLog("Detected the following protections in {0}:\r\n\r\n{1}", Env.Drive.Letter, protections);
|
||||
|
||||
this.Find<TextBlock>("StatusLabel").Text = tempContent;
|
||||
this.Find<Button>("StartStopButton").IsEnabled = true;
|
||||
this.Find<Button>("MediaScanButton").IsEnabled = true;
|
||||
this.Find<Button>("CopyProtectScanButton").IsEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the current disc type in the combo box
|
||||
/// </summary>
|
||||
private void SetCurrentDiscType()
|
||||
{
|
||||
// If we have an invalid current type, we don't care and return
|
||||
if (CurrentMediaType == null || CurrentMediaType == MediaType.NONE)
|
||||
return;
|
||||
|
||||
// Now set the selected item, if possible
|
||||
int index = MediaTypes.FindIndex(kvp => kvp.Value == CurrentMediaType);
|
||||
if (index != -1)
|
||||
this.Find<ComboBox>("MediaTypeComboBox").SelectedIndex = index;
|
||||
else
|
||||
this.Find<TextBlock>("StatusLabel").Text = $"Disc of type '{Converters.LongName(CurrentMediaType)}' found, but the current system does not support it!";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the drive speed based on reported maximum and user-defined option
|
||||
/// </summary>
|
||||
private void SetSupportedDriveSpeed()
|
||||
{
|
||||
// Set the drive speed list that's appropriate
|
||||
var values = Constants.GetSpeedsForMediaType(CurrentMediaType);
|
||||
this.Find<ComboBox>("DriveSpeedComboBox").Items = values;
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Supported media speeds: {0}", string.Join(",", values));
|
||||
|
||||
// Set the selected speed
|
||||
int speed = UIOptions.GetPreferredDumpSpeedForMediaType(CurrentMediaType);
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Setting drive speed to: {0}", speed);
|
||||
this.Find<ComboBox>("DriveSpeedComboBox").SelectedItem = speed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begin the dumping process using the given inputs
|
||||
/// </summary>
|
||||
private async void StartDumping()
|
||||
{
|
||||
// One last check to determine environment, just in case
|
||||
Env = DetermineEnvironment();
|
||||
|
||||
// If still in custom parameter mode, check that users meant to continue or not
|
||||
if (this.Find<CheckBox>("EnableParametersCheckBox").IsChecked == true)
|
||||
{
|
||||
MessageBoxResult result = await MessageBox.Show(this, "It looks like you have custom parameters that have not been saved. Would you like to apply those changes before starting to dump?", "Custom Changes", MessageBoxButtons.YesNoCancel);
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
this.Find<CheckBox>("EnableParametersCheckBox").IsChecked = false;
|
||||
this.Find<TextBox>("ParametersTextBox").IsEnabled = false;
|
||||
ProcessCustomParameters();
|
||||
}
|
||||
else if (result == MessageBoxResult.Cancel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// If "No", then we continue with the current known environment
|
||||
}
|
||||
|
||||
// Fix the output paths
|
||||
Env.FixOutputPaths();
|
||||
|
||||
try
|
||||
{
|
||||
// Validate that the user explicitly wants an inactive drive to be considered for dumping
|
||||
if (!Env.Drive.MarkedActive)
|
||||
{
|
||||
MessageBoxResult mbresult = await MessageBox.Show(this, "The currently selected drive does not appear to contain a disc! Are you sure you want to continue?", "Missing Disc", MessageBoxButtons.YesNo);
|
||||
if (mbresult == MessageBoxResult.No || mbresult == MessageBoxResult.Cancel)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Dumping aborted!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If a complete dump already exists
|
||||
if (Env.FoundAllFiles())
|
||||
{
|
||||
MessageBoxResult mbresult = await MessageBox.Show(this, "A complete dump already exists! Are you sure you want to overwrite?", "Overwrite?", MessageBoxButtons.YesNo);
|
||||
if (mbresult == MessageBoxResult.No || mbresult == MessageBoxResult.Cancel)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Dumping aborted!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.Find<Button>("StartStopButton").Content = Constants.StopDumping;
|
||||
this.Find<Button>("CopyProtectScanButton").IsEnabled = false;
|
||||
this.Find<TextBlock>("StatusLabel").Text = "Beginning dumping process";
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Starting dumping process..");
|
||||
|
||||
// Get progress indicators
|
||||
var resultProgress = new Progress<Result>();
|
||||
resultProgress.ProgressChanged += ProgressUpdated;
|
||||
var protectionProgress = new Progress<FileProtection>();
|
||||
protectionProgress.ProgressChanged += ProgressUpdated;
|
||||
|
||||
// Run the program with the parameters
|
||||
Result result = await Env.Run(resultProgress);
|
||||
|
||||
// If we didn't execute a dumping command we cannot get submission output
|
||||
if (!Env.Parameters.IsDumpingCommand())
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("No dumping command was run, submission information will not be gathered.");
|
||||
this.Find<TextBlock>("StatusLabel").Text = "Execution complete!";
|
||||
this.Find<Button>("StartStopButton").Content = Constants.StartDumping;
|
||||
this.Find<Button>("CopyProtectScanButton").IsEnabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
// Verify dump output and save it
|
||||
result = await Env.VerifyAndSaveDumpOutput(resultProgress,
|
||||
protectionProgress,
|
||||
this.Find<CheckBox>("EjectWhenDoneCheckBox").IsChecked,
|
||||
UIOptions.ResetDriveAfterDump,
|
||||
(si) =>
|
||||
{
|
||||
var discInformationWindow = new DiscInformationWindow();
|
||||
discInformationWindow.SubmissionInfo = si;
|
||||
discInformationWindow.Load();
|
||||
discInformationWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
discInformationWindow.ShowDialog(this).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// No-op, we don't care what it was
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Find<Button>("StartStopButton").Content = Constants.StartDumping;
|
||||
this.Find<Button>("CopyProtectScanButton").IsEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Handler for AboutMenuItem Click event
|
||||
/// </summary>
|
||||
private void AboutMenuItemClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MessageBox.Show(this, $"darksabre76 - Project Lead / Backend Design"
|
||||
+ $"{Environment.NewLine}ReignStumble - Former Project Lead / UI Design"
|
||||
+ $"{Environment.NewLine}Jakz - Primary Feature Contributor"
|
||||
+ $"{Environment.NewLine}NHellFire - Feature Contributor", "About", MessageBoxButtons.Ok);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for AppExitMenuItem Click event
|
||||
/// </summary>
|
||||
private void AppExitMenuItemClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
logWindow?.Close();
|
||||
Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for CheckForUpdatesMenuItem Click event
|
||||
/// </summary>
|
||||
private void CheckForUpdatesMenuItemClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
(bool different, string message, string url) = Tools.CheckForNewVersion();
|
||||
|
||||
// If we have a new version, put it in the clipboard
|
||||
if (different)
|
||||
Application.Current.Clipboard.SetTextAsync(url);
|
||||
|
||||
MessageBox.Show(this, message, "Version Update Check", MessageBoxButtons.Ok);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for CopyProtectScanButton Click event
|
||||
/// </summary>
|
||||
private void CopyProtectScanButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ScanAndShowProtection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for DriveLetterComboBox SelectionChanged event
|
||||
/// </summary>
|
||||
private void DriveLetterComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
CacheCurrentDiscType();
|
||||
SetCurrentDiscType();
|
||||
GetOutputNames(true);
|
||||
SetSupportedDriveSpeed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for DriveSpeedComboBox SelectionChanged event
|
||||
/// </summary>
|
||||
private void DriveSpeedComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for EnableParametersCheckBox Click event
|
||||
/// </summary>
|
||||
private void EnableParametersCheckBoxClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (this.Find<CheckBox>("EnableParametersCheckBox").IsChecked == true)
|
||||
this.Find<TextBox>("ParametersTextBox").IsEnabled = true;
|
||||
else
|
||||
{
|
||||
this.Find<TextBox>("ParametersTextBox").IsEnabled = false;
|
||||
ProcessCustomParameters();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MediaTypeComboBox SelectionChanged event
|
||||
/// </summary>
|
||||
private void MediaTypeComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
// Only change the media type if the selection and not the list has changed
|
||||
if (e.RemovedItems.Count == 1 && e.AddedItems.Count == 1)
|
||||
{
|
||||
CurrentMediaType = this.Find<ComboBox>("MediaTypeComboBox").SelectedItem as MediaType?;
|
||||
SetSupportedDriveSpeed();
|
||||
}
|
||||
|
||||
GetOutputNames(false);
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MediaScanButton Click event
|
||||
/// </summary>
|
||||
private void MediaScanButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
PopulateDrives();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MainWindow Activated event
|
||||
/// </summary>
|
||||
private void MainWindowActivated(object sender, EventArgs e)
|
||||
{
|
||||
if (logWindow.IsVisible && !this.Topmost)
|
||||
{
|
||||
logWindow.Topmost = true;
|
||||
logWindow.Topmost = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MainWindow Closing event
|
||||
/// </summary>
|
||||
private void MainWindowClosing(object sender, CancelEventArgs e)
|
||||
{
|
||||
if (logWindow.IsVisible)
|
||||
logWindow?.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MainWindow PositionChanged event
|
||||
/// </summary>
|
||||
private void MainWindowLocationChanged(object sender, PixelPointEventArgs e)
|
||||
{
|
||||
if (logWindow.IsVisible)
|
||||
logWindow.AdjustPositionToMainWindow();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OptionsMenuItem Click event
|
||||
/// </summary>
|
||||
private async void OptionsMenuItemClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Show the window and wait for the response
|
||||
var optionsWindow = new OptionsWindow();
|
||||
optionsWindow.UIOptions = UIOptions;
|
||||
optionsWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||
await optionsWindow.ShowDialog(this);
|
||||
|
||||
// Set any new options
|
||||
PopulateDrives();
|
||||
GetOutputNames(false);
|
||||
SetSupportedDriveSpeed();
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OutputDirectoryBrowseButton Click event
|
||||
/// </summary>
|
||||
private void OutputDirectoryBrowseButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
BrowseFolder();
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OutputFilenameTextBox TextInput event
|
||||
/// </summary>
|
||||
// TODO: Not triggered properly
|
||||
private void OutputDirectoryTextBoxTextChanged(object sender, TextInputEventArgs e)
|
||||
{
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OutputFilenameTextBox TextInput event
|
||||
/// </summary>
|
||||
// TODO: Not triggered properly
|
||||
private void OutputFilenameTextBoxTextChanged(object sender, TextInputEventArgs e)
|
||||
{
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for Result ProgressChanged event
|
||||
/// </summary>
|
||||
private void ProgressUpdated(object sender, Result value)
|
||||
{
|
||||
this.Find<TextBlock>("StatusLabel").Text = value.Message;
|
||||
ViewModels.LoggerViewModel.VerboseLogLn(value.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for FileProtection ProgressChanged event
|
||||
/// </summary>
|
||||
private void ProgressUpdated(object sender, FileProtection value)
|
||||
{
|
||||
string message = $"{value.Percentage * 100:N2}%: {value.Filename} - {value.Protection}";
|
||||
this.Find<TextBlock>("StatusLabel").Text = message;
|
||||
ViewModels.LoggerViewModel.VerboseLogLn(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for StartStopButton Click event
|
||||
/// </summary>
|
||||
private void StartStopButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Dump or stop the dump
|
||||
if ((string)this.Find<Button>("StartStopButton").Content == Constants.StartDumping)
|
||||
{
|
||||
StartDumping();
|
||||
}
|
||||
else if ((string)this.Find<Button>("StartStopButton").Content == Constants.StopDumping)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Canceling dumping process...");
|
||||
Env.CancelDumping();
|
||||
this.Find<Button>("CopyProtectScanButton").IsEnabled = true;
|
||||
|
||||
if (this.Find<CheckBox>("EjectWhenDoneCheckBox").IsChecked == true)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn($"Ejecting disc in drive {Env.Drive.Letter}");
|
||||
Env.EjectDisc();
|
||||
}
|
||||
|
||||
if (UIOptions.ResetDriveAfterDump)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn($"Resetting drive {Env.Drive.Letter}");
|
||||
Env.ResetDrive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for SystemTypeComboBox SelectionChanged event
|
||||
/// </summary>
|
||||
private void SystemTypeComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
// If we're on a separator, go to the next item and return
|
||||
if ((this.Find<ComboBox>("SystemTypeComboBox").SelectedItem as KnownSystemComboBoxItem).IsHeader())
|
||||
{
|
||||
this.Find<ComboBox>("SystemTypeComboBox").SelectedIndex++;
|
||||
return;
|
||||
}
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Changed system to: {0}", (this.Find<ComboBox>("SystemTypeComboBox").SelectedItem as KnownSystemComboBoxItem).Name);
|
||||
PopulateMediaType();
|
||||
GetOutputNames(false);
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" Icon="Icon.ico"
|
||||
x:Class="DICUI.Avalonia.MessageBox" SizeToContent="WidthAndHeight" CanResize="False">
|
||||
<StackPanel HorizontalAlignment="Center">
|
||||
<TextBlock HorizontalAlignment="Center" Name="Text"/>
|
||||
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal" Name="Buttons">
|
||||
<StackPanel.Styles>
|
||||
<Style Selector="Button">
|
||||
<Setter Property="Margin" Value="5"/>
|
||||
</Style>
|
||||
</StackPanel.Styles>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Window>
|
||||
@@ -1,83 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
// https://stackoverflow.com/questions/55706291/how-to-show-a-message-box-in-avaloniaui-beta
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
public enum MessageBoxButtons
|
||||
{
|
||||
Ok,
|
||||
OkCancel,
|
||||
YesNo,
|
||||
YesNoCancel
|
||||
}
|
||||
|
||||
public enum MessageBoxResult
|
||||
{
|
||||
Ok,
|
||||
Cancel,
|
||||
Yes,
|
||||
No
|
||||
}
|
||||
|
||||
public class MessageBox : Window
|
||||
{
|
||||
public MessageBox()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Task<MessageBoxResult> Show(Window parent, string text, string title, MessageBoxButtons buttons)
|
||||
{
|
||||
var msgbox = new MessageBox()
|
||||
{
|
||||
Title = title
|
||||
};
|
||||
msgbox.FindControl<TextBlock>("Text").Text = text;
|
||||
var buttonPanel = msgbox.FindControl<StackPanel>("Buttons");
|
||||
|
||||
var res = MessageBoxResult.Ok;
|
||||
|
||||
void AddButton(string caption, MessageBoxResult r, bool def = false)
|
||||
{
|
||||
var btn = new Button { Content = caption };
|
||||
btn.Click += (_, __) => {
|
||||
res = r;
|
||||
msgbox.Close();
|
||||
};
|
||||
buttonPanel.Children.Add(btn);
|
||||
if (def)
|
||||
res = r;
|
||||
}
|
||||
|
||||
if (buttons == MessageBoxButtons.Ok || buttons == MessageBoxButtons.OkCancel)
|
||||
AddButton("Ok", MessageBoxResult.Ok, true);
|
||||
if (buttons == MessageBoxButtons.YesNo || buttons == MessageBoxButtons.YesNoCancel)
|
||||
{
|
||||
AddButton("Yes", MessageBoxResult.Yes);
|
||||
AddButton("No", MessageBoxResult.No, true);
|
||||
}
|
||||
|
||||
if (buttons == MessageBoxButtons.OkCancel || buttons == MessageBoxButtons.YesNoCancel)
|
||||
AddButton("Cancel", MessageBoxResult.Cancel, true);
|
||||
|
||||
|
||||
var tcs = new TaskCompletionSource<MessageBoxResult>();
|
||||
msgbox.Closed += delegate { tcs.TrySetResult(res); };
|
||||
if (parent != null)
|
||||
msgbox.ShowDialog(parent);
|
||||
else msgbox.Show();
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:DICUI.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="515.132" d:DesignHeight="600" Width="515.132" Height="600"
|
||||
x:Class="DICUI.Avalonia.OptionsWindow" Icon="Icon.ico" CanResize="False"
|
||||
Title="Options">
|
||||
|
||||
<Grid RowDefinitions="150,150,150,80,40">
|
||||
|
||||
<!-- Paths -->
|
||||
<Border Grid.Row="0" Grid.ColumnSpan="2" Margin="5" BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<TextBlock Text="Paths" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" FontSize="14" Foreground="Gray" />
|
||||
</Border>
|
||||
<Grid Grid.Row="0" Grid.ColumnSpan="2" Margin="10,15,10,10" ColumnDefinitions="1*,2*,0.2*" RowDefinitions="Auto,Auto,Auto,Auto">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Aaru Path" />
|
||||
<TextBox Name="AaruPathTextBox" Grid.Row="0" Grid.Column="1" Height="25" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=AaruPath}" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
<Button Name="AaruPathButton" Grid.Row="0" Grid.Column="2" Height="25" Width="25" Content="..." Click="BrowseForPathClick" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="DiscImageCreator Path" />
|
||||
<TextBox Name="CreatorPathTextBox" Grid.Row="1" Grid.Column="1" Height="25" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=CreatorPath}" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
<Button Name="CreatorPathButton" Grid.Row="1" Grid.Column="2" Height="25" Width="25" Content="..." Click="BrowseForPathClick" />
|
||||
|
||||
<!--
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="dd Path" />
|
||||
<TextBox Name="DDPathTextBox" Grid.Row="0" Grid.Column="1" Height="25" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=DDPath}" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
<Button Name="DDPathButton" Grid.Row="0" Grid.Column="2" Height="25" Width="25" Content="..." Click="BrowseForPathClick" />
|
||||
-->
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Subdump Path" />
|
||||
<TextBox Name="SubDumpPathTextBox" Grid.Row="2" Grid.Column="1" Height="25" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=SubDumpPath}" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
<Button Name="SubDumpPathButton" Grid.Row="2" Grid.Column="2" Height="25" Width="25" Content="..." Click="BrowseForPathClick" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Default Output Path" />
|
||||
<TextBox Name="DefaultOutputPathTextBox" Grid.Row="3" Grid.Column="1" Height="25" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=DefaultOutputPath}" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
<Button Name="DefaultOutputPathButton" Grid.Row="3" Grid.Column="2" Height="25" Width="25" Content="..." Click="BrowseForPathClick" />
|
||||
</Grid>
|
||||
|
||||
<!-- Dumping Speeds -->
|
||||
<Border Grid.Row="1" Grid.ColumnSpan="2" Margin="5" BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<TextBlock Text="Preferred Dump Speed" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" FontSize="14" Foreground="Gray" />
|
||||
</Border>
|
||||
<Grid Grid.Row="1" Grid.ColumnSpan="2" Margin="10,15,10,10" ColumnDefinitions="80,2*,40" RowDefinitions="1*,Auto,Auto,Auto">
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="CD-ROM" Margin="5" />
|
||||
<Slider Name="DumpSpeedCDSlider" Grid.Row="1" Grid.Column="1" Minimum="0" Maximum="72" Margin="5"
|
||||
IsSnapToTickEnabled="True" TickFrequency="4"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Value="{Binding Path=PreferredDumpSpeedCD}" />
|
||||
<!-- Ticks="{Binding Source={x:Static local:Constants.SpeedsForCDAsCollection}}" -->
|
||||
<TextBox Name="DumpSpeedCDTextBox" Grid.Row="1" Grid.Column="2" Width="25" Height="25" TextAlignment="Center" VerticalAlignment="Center"
|
||||
IsReadOnly="True" Text="{Binding ElementName=DumpSpeedCDSlider, Path=Value}"
|
||||
Background="LightGray" Foreground="Gray" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="DVD-ROM" Margin="5" />
|
||||
<Slider Name="DumpSpeedDVDSlider" Grid.Row="2" Grid.Column="1" Minimum="0" Maximum="24" Margin="5"
|
||||
IsSnapToTickEnabled="True" TickFrequency="2"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Value="{Binding Path=PreferredDumpSpeedDVD}" />
|
||||
<!-- Ticks="{Binding Source={x:Static local:Constants.SpeedsForDVDAsCollection}}" -->
|
||||
<TextBox Name="DumpSpeedDVDTextBox" Grid.Row="2" Grid.Column="2" Width="25" Height="25" TextAlignment="Center" VerticalAlignment="Center"
|
||||
IsReadOnly="True" Text="{Binding ElementName=DumpSpeedDVDSlider, Path=Value}"
|
||||
Background="LightGray" Foreground="Gray" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="BD-ROM" Margin="5" />
|
||||
<Slider Name="DumpSpeedBDSlider" Grid.Row="3" Grid.Column="1" Minimum="0" Maximum="16" Margin="5"
|
||||
IsSnapToTickEnabled="True" TickFrequency="2"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Value="{Binding Path=PreferredDumpSpeedBD}" />
|
||||
<!-- Ticks="{Binding Source={x:Static local:Constants.SpeedsForBDAsCollection}}" -->
|
||||
<TextBox Name="DumpSpeedBDTextBox" Grid.Row="3" Grid.Column="2" Width="25" Height="25" TextAlignment="Center" VerticalAlignment="Center"
|
||||
IsReadOnly="True" Text="{Binding ElementName=DumpSpeedBDSlider, Path=Value}"
|
||||
Background="LightGray" Foreground="Gray" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
</Grid>
|
||||
|
||||
<!-- Misc. Options -->
|
||||
<Border Grid.Row="2" Grid.ColumnSpan="2" Margin="5" BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<TextBlock Text="Options" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" FontSize="14" Foreground="Gray" />
|
||||
</Border>
|
||||
<Grid Grid.Row="2" Grid.ColumnSpan="2" Margin="10,15,10,10" ColumnDefinitions="1*,1*,1*,1*" RowDefinitions="1*,Auto,Auto,Auto">
|
||||
<CheckBox Grid.Row="1" Grid.Column="0" Margin="0,4" VerticalAlignment="Center" Content="Quiet Mode"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=QuietMode}"
|
||||
ToolTip.Tip="Disable DiscImageCreator sounds" />
|
||||
|
||||
<CheckBox Grid.Row="1" Grid.Column="1" Margin="0,4" VerticalAlignment="Center" Content="Paranoid Mode"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=ParanoidMode}"
|
||||
ToolTip.Tip="Enable pedantic and super-safe flags" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="2" Margin="5" Text="Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="3" Margin="0,4" VerticalAlignment="Center"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=RereadAmountForC2}"
|
||||
ToolTip.Tip="Specifies how many rereads are attempted on C2 error" />
|
||||
|
||||
<CheckBox Grid.Row="2" Grid.Column="0" Margin="0,4" VerticalAlignment="Center" Content="Protection Scan"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=ScanForProtection}"
|
||||
ToolTip.Tip="Enable automatic checking for copy protection on dumped media" />
|
||||
|
||||
<CheckBox Grid.Row="2" Grid.Column="1" Margin="0,4" VerticalAlignment="Center" Content="Skip Type Detect"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=SkipMediaTypeDetection}"
|
||||
ToolTip.Tip="Disable trying to guess media type inserted (may improve performance at startup)" />
|
||||
|
||||
<CheckBox Grid.Row="2" Grid.Column="2" Margin="0,4" VerticalAlignment="Center" Content="Add Placeholders"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=AddPlaceholders}"
|
||||
ToolTip.Tip="Enable adding placeholder text in the submissioninfo output for required and optional fields" />
|
||||
|
||||
<CheckBox Grid.Row="3" Grid.Column="0" Margin="0,4" VerticalAlignment="Center" Content="Show Disc Info"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=PromptForDiscInformation}"
|
||||
ToolTip.Tip="Enable showing the disc information output after dumping" />
|
||||
|
||||
<CheckBox Grid.Row="3" Grid.Column="1" Margin="0,4" VerticalAlignment="Center" Content="No Fixed Drives"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=IgnoreFixedDrives}"
|
||||
ToolTip.Tip="Ignore hard drives and other fixed drives" />
|
||||
|
||||
<CheckBox Grid.Row="3" Grid.Column="2" Margin="0,4" VerticalAlignment="Center" Content="Reset After Dump"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=ResetDriveAfterDump}"
|
||||
ToolTip.Tip="Reset disc drives after dumping; useful for some older machines" />
|
||||
</Grid>
|
||||
|
||||
<!-- Redump -->
|
||||
<Border Grid.Row="3" Grid.ColumnSpan="2" Margin="5" BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<TextBlock Text="Redump Login" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" FontSize="14" Foreground="Gray" />
|
||||
</Border>
|
||||
<Grid Grid.Row="3" Grid.ColumnSpan="2" Margin="10,15,10,10" ColumnDefinitions="1*,1*,1*,1*,1.2*" RowDefinitions="1*,Auto">
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Username" />
|
||||
<TextBox Name="RedumpUsernameTextBox" Grid.Row="1" Grid.Column="1" Height="25" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=Username}" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Username" />
|
||||
<TextBox Name="RedumpPasswordTextBox" Grid.Row="1" Grid.Column="3" Height="25" HorizontalAlignment="Stretch" PasswordChar="*"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=Password}" ScrollViewer.VerticalScrollBarVisibility="Disabled" />
|
||||
|
||||
<Button Name="RedumpLoginTestButton" Grid.Row="1" Grid.Column="5" Height="25" Width="80" Content="Test Login" Click="OnRedumpTestClick" />
|
||||
</Grid>
|
||||
|
||||
<!-- Accept / Cancel -->
|
||||
<Grid Height="25" Grid.Row="4" Grid.Column="0" ColumnDefinitions="2*,1*,1*">
|
||||
<Button Name="AcceptButton" Grid.Row="0" Grid.Column="1" Height="25" Width="80" Content="Accept" Click="OnAcceptClick" />
|
||||
<Button Name="CancelButton" Grid.Row="0" Grid.Column="2" Height="25" Width="80" Content="Cancel" Click="OnCancelClick" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,142 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
public class OptionsWindow : Window
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Current UI options
|
||||
/// </summary>
|
||||
public UIOptions UIOptions { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public OptionsWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Find a TextBox by setting name
|
||||
/// </summary>
|
||||
/// <param name="name">Setting name to find</param>
|
||||
/// <returns>TextBox for that setting</returns>
|
||||
private TextBox TextBoxForPathSetting(string name)
|
||||
{
|
||||
return this.Find<TextBox>(name + "TextBox");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Handler for generic Click event
|
||||
/// </summary>
|
||||
private async void BrowseForPathClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Button button = sender as Button;
|
||||
|
||||
// strips button prefix to obtain the setting name
|
||||
string pathSettingName = button.Name.Substring(0, button.Name.IndexOf("Button"));
|
||||
|
||||
// TODO: hack for now, then we'll see
|
||||
bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath";
|
||||
|
||||
// Directory
|
||||
if (shouldBrowseForPath)
|
||||
{
|
||||
OpenFolderDialog dialog = new OpenFolderDialog();
|
||||
string result = await dialog.ShowAsync(this);
|
||||
if (!string.IsNullOrWhiteSpace(result))
|
||||
{
|
||||
if (Directory.Exists(result))
|
||||
TextBoxForPathSetting(pathSettingName).Text = result;
|
||||
else
|
||||
Console.WriteLine($"Path '{result}' cannot be found!");
|
||||
}
|
||||
}
|
||||
|
||||
// File
|
||||
else
|
||||
{
|
||||
OpenFileDialog dialog = new OpenFileDialog();
|
||||
string[] result = await dialog.ShowAsync(this);
|
||||
if (result != null && result.Length > 0 && !string.IsNullOrWhiteSpace(result[0]))
|
||||
{
|
||||
if (File.Exists(result[0]))
|
||||
TextBoxForPathSetting(pathSettingName).Text = result[0];
|
||||
else
|
||||
Console.WriteLine($"Path '{result[0]}' cannot be found!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for AcceptButton Click event
|
||||
/// </summary>
|
||||
private void OnAcceptClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
UIOptions.Save();
|
||||
Hide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for CancelButton Click event
|
||||
/// </summary>
|
||||
private void OnCancelClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for RedumpLoginTestButton Click event
|
||||
/// </summary>
|
||||
private void OnRedumpTestClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
using (RedumpWebClient wc = new RedumpWebClient())
|
||||
{
|
||||
if (wc.Login(this.Find<TextBox>("RedumpUsernameTextBox").Text, this.Find<TextBox>("RedumpPasswordTextBox").Text))
|
||||
{
|
||||
new Window()
|
||||
{
|
||||
Title = "Success",
|
||||
Content = "Redump login credentials accepted!",
|
||||
SizeToContent = SizeToContent.WidthAndHeight,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen,
|
||||
}.ShowDialog(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
new Window()
|
||||
{
|
||||
Title = "Failure",
|
||||
Content = "Redump login credentials denied!",
|
||||
SizeToContent = SizeToContent.WidthAndHeight,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen,
|
||||
}.ShowDialog(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Logging.Serilog;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
class Program
|
||||
{
|
||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||
// yet and stuff might break.
|
||||
public static void Main(string[] args) => BuildAvaloniaApp()
|
||||
.StartWithClassicDesktopLifetime(args);
|
||||
|
||||
// Avalonia configuration, don't remove; also used by visual designer.
|
||||
public static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.LogToDebug();
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using DICUI.Data;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
public class UIOptions
|
||||
{
|
||||
// TODO: Is there any way that this can be made private?
|
||||
public Options Options { get; set; }
|
||||
|
||||
#region Passthrough readonly values
|
||||
|
||||
// TODO: Can any of these be removed?
|
||||
public string DefaultOutputPath { get { return Options.DefaultOutputPath; } }
|
||||
public bool IgnoreFixedDrives { get { return Options.IgnoreFixedDrives; } }
|
||||
public bool ResetDriveAfterDump { get { return Options.ResetDriveAfterDump; } }
|
||||
public bool SkipMediaTypeDetection { get { return Options.SkipMediaTypeDetection; } }
|
||||
public bool SkipSystemDetection { get { return Options.SkipSystemDetection; } }
|
||||
public bool OpenLogWindowAtStartup { get { return Options.OpenLogWindowAtStartup; } }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
public UIOptions()
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save a configuration from internal Options
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
||||
|
||||
// Loop through all settings in Options and save them, overwriting existing settings
|
||||
foreach (var kvp in Options)
|
||||
{
|
||||
configFile.AppSettings.Settings.Remove(kvp.Key);
|
||||
configFile.AppSettings.Settings.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
configFile.Save(ConfigurationSaveMode.Modified);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load a configuration into internal Options
|
||||
/// </summary>
|
||||
private void Load()
|
||||
{
|
||||
Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
||||
|
||||
var settings = ConvertToDictionary(configFile);
|
||||
Options = new Options(settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a setting value from the base Options
|
||||
/// </summary>
|
||||
/// <param name="key">Key to retrieve the value for</param>
|
||||
/// <returns>String value if possible, null otherwise</returns>
|
||||
public string Get(string key)
|
||||
{
|
||||
return Options[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a setting value in the base Options
|
||||
/// </summary>
|
||||
/// <param name="key">Key to set the value for</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
public void Set(string key, string value)
|
||||
{
|
||||
Options[key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the preferred dumping speed given a media type
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType representing the current selection</param>
|
||||
/// <returns>Int value representing the dump speed</returns>
|
||||
public int GetPreferredDumpSpeedForMediaType(MediaType? type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.GDROM:
|
||||
return this.Options.PreferredDumpSpeedCD;
|
||||
case MediaType.DVD:
|
||||
case MediaType.HDDVD:
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
return this.Options.PreferredDumpSpeedDVD;
|
||||
case MediaType.BluRay:
|
||||
return this.Options.PreferredDumpSpeedBD;
|
||||
default:
|
||||
return this.Options.PreferredDumpSpeedCD;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the configuration app settings to a dictionary
|
||||
/// </summary>
|
||||
/// <param name="configFile">Configuration to load from</param>
|
||||
/// <returns>Dictionary with all values from app settings</returns>
|
||||
private Dictionary<string, string> ConvertToDictionary(Configuration configFile)
|
||||
{
|
||||
var settings = configFile.AppSettings.Settings;
|
||||
var dict = new Dictionary<string, string>();
|
||||
|
||||
foreach (string key in settings.AllKeys)
|
||||
{
|
||||
dict[key] = settings[key]?.Value ?? string.Empty;
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
using System;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
public class OptionsViewModel
|
||||
{
|
||||
private UIOptions _uiOptions;
|
||||
|
||||
#region Internal Program
|
||||
|
||||
public string AaruPath
|
||||
{
|
||||
get { return _uiOptions.Options.AaruPath; }
|
||||
set { _uiOptions.Options.AaruPath = value; }
|
||||
}
|
||||
|
||||
public string CreatorPath
|
||||
{
|
||||
get { return _uiOptions.Options.CreatorPath; }
|
||||
set { _uiOptions.Options.CreatorPath = value; }
|
||||
}
|
||||
|
||||
public string DDPath
|
||||
{
|
||||
get { return _uiOptions.Options.DDPath; }
|
||||
set { _uiOptions.Options.DDPath = value; }
|
||||
}
|
||||
|
||||
public string InternalProgram
|
||||
{
|
||||
get { return _uiOptions.Options.InternalProgram; }
|
||||
set { _uiOptions.Options.InternalProgram = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extra Paths
|
||||
|
||||
public string DefaultOutputPath
|
||||
{
|
||||
get { return _uiOptions.Options.DefaultOutputPath; }
|
||||
set { _uiOptions.Options.DefaultOutputPath = value; }
|
||||
}
|
||||
|
||||
public string SubDumpPath
|
||||
{
|
||||
get { return _uiOptions.Options.SubDumpPath; }
|
||||
set { _uiOptions.Options.SubDumpPath = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dumping Speeds
|
||||
|
||||
public int PreferredDumpSpeedCD
|
||||
{
|
||||
get { return _uiOptions.Options.PreferredDumpSpeedCD; }
|
||||
set { _uiOptions.Options.PreferredDumpSpeedCD = value; }
|
||||
}
|
||||
|
||||
public int PreferredDumpSpeedDVD
|
||||
{
|
||||
get { return _uiOptions.Options.PreferredDumpSpeedDVD; }
|
||||
set { _uiOptions.Options.PreferredDumpSpeedDVD = value; }
|
||||
}
|
||||
|
||||
public int PreferredDumpSpeedBD
|
||||
{
|
||||
get { return _uiOptions.Options.PreferredDumpSpeedBD; }
|
||||
set { _uiOptions.Options.PreferredDumpSpeedBD = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extra Dumping Options
|
||||
|
||||
public bool QuietMode
|
||||
{
|
||||
get { return _uiOptions.Options.QuietMode; }
|
||||
set { _uiOptions.Options.QuietMode = value; }
|
||||
}
|
||||
|
||||
public bool ParanoidMode
|
||||
{
|
||||
get { return _uiOptions.Options.ParanoidMode; }
|
||||
set { _uiOptions.Options.ParanoidMode = value; }
|
||||
}
|
||||
|
||||
public bool ScanForProtection
|
||||
{
|
||||
get { return _uiOptions.Options.ScanForProtection; }
|
||||
set { _uiOptions.Options.ScanForProtection = value; }
|
||||
}
|
||||
|
||||
public string RereadAmountForC2
|
||||
{
|
||||
get { return Convert.ToString(_uiOptions.Options.RereadAmountForC2); }
|
||||
set
|
||||
{
|
||||
if (Int32.TryParse(value, out int result))
|
||||
_uiOptions.Options.RereadAmountForC2 = result;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddPlaceholders
|
||||
{
|
||||
get { return _uiOptions.Options.AddPlaceholders; }
|
||||
set { _uiOptions.Options.AddPlaceholders = value; }
|
||||
}
|
||||
|
||||
public bool PromptForDiscInformation
|
||||
{
|
||||
get { return _uiOptions.Options.PromptForDiscInformation; }
|
||||
set { _uiOptions.Options.PromptForDiscInformation = value; }
|
||||
}
|
||||
|
||||
public bool IgnoreFixedDrives
|
||||
{
|
||||
get { return _uiOptions.Options.IgnoreFixedDrives; }
|
||||
set { _uiOptions.Options.IgnoreFixedDrives = value; }
|
||||
}
|
||||
|
||||
public bool ResetDriveAfterDump
|
||||
{
|
||||
get { return _uiOptions.Options.ResetDriveAfterDump; }
|
||||
set { _uiOptions.Options.ResetDriveAfterDump = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Skip Options
|
||||
|
||||
public bool SkipMediaTypeDetection
|
||||
{
|
||||
get { return _uiOptions.Options.SkipMediaTypeDetection; }
|
||||
set { _uiOptions.Options.SkipMediaTypeDetection = value; }
|
||||
}
|
||||
|
||||
public bool SkipSystemDetection
|
||||
{
|
||||
get { return _uiOptions.Options.SkipSystemDetection; }
|
||||
set { _uiOptions.Options.SkipSystemDetection = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Logging Options
|
||||
|
||||
public bool VerboseLogging
|
||||
{
|
||||
get { return _uiOptions.Options.VerboseLogging; }
|
||||
set
|
||||
{
|
||||
_uiOptions.Options.VerboseLogging = value;
|
||||
_uiOptions.Save(); // TODO: Why does this save here?
|
||||
}
|
||||
}
|
||||
|
||||
public bool OpenLogWindowAtStartup
|
||||
{
|
||||
get { return _uiOptions.Options.OpenLogWindowAtStartup; }
|
||||
set
|
||||
{
|
||||
_uiOptions.Options.OpenLogWindowAtStartup = value;
|
||||
_uiOptions.Save(); // TODO: Why does this save here?
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Redump Login Information
|
||||
|
||||
public string Username
|
||||
{
|
||||
get { return _uiOptions.Options.Username; }
|
||||
set { _uiOptions.Options.Username = value; }
|
||||
}
|
||||
|
||||
public string Password
|
||||
{
|
||||
get { return _uiOptions.Options.Password; }
|
||||
set { _uiOptions.Options.Password = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public OptionsViewModel(UIOptions uiOptions)
|
||||
{
|
||||
this._uiOptions = uiOptions;
|
||||
}
|
||||
}
|
||||
|
||||
public class LoggerViewModel
|
||||
{
|
||||
private LogWindow _logWindow;
|
||||
|
||||
public void SetWindow(LogWindow logWindow) => _logWindow = logWindow;
|
||||
|
||||
public bool WindowVisible
|
||||
{
|
||||
get => _logWindow != null ? _logWindow.IsVisible : false;
|
||||
set
|
||||
{
|
||||
if (_logWindow == null)
|
||||
_logWindow = new LogWindow();
|
||||
|
||||
if (value)
|
||||
{
|
||||
_logWindow.AdjustPositionToMainWindow();
|
||||
_logWindow.Show();
|
||||
}
|
||||
else
|
||||
_logWindow.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
public void VerboseLog(string text)
|
||||
{
|
||||
if (ViewModels.OptionsViewModel.VerboseLogging)
|
||||
_logWindow.AppendToTextBox(text, Brushes.Yellow);
|
||||
}
|
||||
|
||||
public void VerboseLog(string format, params object[] args) => VerboseLog(string.Format(format, args));
|
||||
public void VerboseLogLn(string format, params object[] args) => VerboseLog(string.Format(format, args) + "\n");
|
||||
}
|
||||
|
||||
public static class ViewModels
|
||||
{
|
||||
public static OptionsViewModel OptionsViewModel { get; set; }
|
||||
public static LoggerViewModel LoggerViewModel { get; set; } = new LoggerViewModel();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
To use the Avalonia CI feed to get unstable packages, move this file to the root of your solution.
|
||||
-->
|
||||
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="AvaloniaCI" value="https://www.myget.org/F/avalonia-ci/api/v2" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -1,35 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;net48;netcoreapp3.1</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<Title>DICUI Check</Title>
|
||||
<AssemblyName>DICUI.Check</AssemblyName>
|
||||
<Description>Validator for various dumping programs</Description>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2020</Copyright>
|
||||
<RepositoryUrl>https://github.com/SabreTools/DICUI</RepositoryUrl>
|
||||
<Version>1.17.0</Version>
|
||||
<AssemblyVersion>1.17.0</AssemblyVersion>
|
||||
<FileVersion>1.17.0</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" Version="1.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DICUI.Library\DICUI.Library.csproj">
|
||||
<Project>{51ab0928-13f9-44bf-a407-b6957a43a056}</Project>
|
||||
<Name>DICUI.Library</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,266 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Check
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Help options
|
||||
if (args.Length == 0 || args[0] == "-h" || args[0] == "-?")
|
||||
{
|
||||
DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// List options
|
||||
if (args[0] == "-lm" || args[0] == "--listmedia")
|
||||
{
|
||||
ListMediaTypes();
|
||||
Console.ReadLine();
|
||||
return;
|
||||
}
|
||||
else if (args[0] == "-lp" || args[0] == "--listprograms")
|
||||
{
|
||||
ListPrograms();
|
||||
Console.ReadLine();
|
||||
return;
|
||||
}
|
||||
else if (args[0] == "-ls" || args[0] == "--listsystems")
|
||||
{
|
||||
ListKnownSystems();
|
||||
Console.ReadLine();
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal operation check
|
||||
if (args.Length < 3)
|
||||
{
|
||||
DisplayHelp("Invalid number of arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the MediaType
|
||||
var mediaType = Converters.ToMediaType(args[0].Trim('"'));
|
||||
if (mediaType == MediaType.NONE)
|
||||
{
|
||||
DisplayHelp($"{args[0]} is not a recognized media type");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the KnownSystem
|
||||
var knownSystem = Converters.ToKnownSystem(args[1].Trim('"'));
|
||||
if (knownSystem == KnownSystem.NONE)
|
||||
{
|
||||
DisplayHelp($"{args[1]} is not a recognized system");
|
||||
return;
|
||||
}
|
||||
|
||||
// Default values
|
||||
string username = null, password = null;
|
||||
string internalProgram = "DiscImageCreator";
|
||||
string path = string.Empty;
|
||||
bool scan = false;
|
||||
|
||||
// Loop through and process options
|
||||
int startIndex = 2;
|
||||
for (; startIndex < args.Length; startIndex++)
|
||||
{
|
||||
// Redump login
|
||||
if (args[startIndex].StartsWith("-c=") || args[startIndex].StartsWith("--credentials="))
|
||||
{
|
||||
string[] credentials = args[startIndex].Split('=')[1].Split(';');
|
||||
username = credentials[0];
|
||||
password = credentials[1];
|
||||
}
|
||||
else if (args[startIndex] == "-c" || args[startIndex] == "--credentials")
|
||||
{
|
||||
username = args[startIndex + 1];
|
||||
password = args[startIndex + 2];
|
||||
startIndex += 2;
|
||||
}
|
||||
|
||||
// Use specific program
|
||||
else if (args[startIndex].StartsWith("-u=") || args[startIndex].StartsWith("--use="))
|
||||
{
|
||||
internalProgram = args[startIndex].Split('=')[1];
|
||||
}
|
||||
else if (args[startIndex] == "-u" || args[startIndex] == "--use")
|
||||
{
|
||||
internalProgram = args[startIndex + 1];
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Use a device path for physical checks
|
||||
else if (args[startIndex].StartsWith("-p=") || args[startIndex].StartsWith("--path="))
|
||||
{
|
||||
path = args[startIndex].Split('=')[1];
|
||||
}
|
||||
else if (args[startIndex] == "-p" || args[startIndex] == "--path")
|
||||
{
|
||||
path = args[startIndex + 1];
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Scan for protection (requires device path)
|
||||
else if (args[startIndex].StartsWith("-s") || args[startIndex].StartsWith("--scan"))
|
||||
{
|
||||
scan = true;
|
||||
}
|
||||
|
||||
// Default, we fall out
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make new Progress objects
|
||||
var resultProgress = new Progress<Result>();
|
||||
resultProgress.ProgressChanged += ProgressUpdated;
|
||||
var protectionProgress = new Progress<FileProtection>();
|
||||
protectionProgress.ProgressChanged += ProgressUpdated;
|
||||
|
||||
// If credentials are invalid, alert the user
|
||||
if (!string.IsNullOrWhiteSpace(username) && !string.IsNullOrWhiteSpace(password))
|
||||
{
|
||||
using (RedumpWebClient wc = new RedumpWebClient())
|
||||
{
|
||||
if (wc.Login(username, password))
|
||||
Console.WriteLine("Redump username and password accepted!");
|
||||
else
|
||||
Console.WriteLine("Redump username and password denied!");
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through all the rest of the args
|
||||
for (int i = startIndex; i < args.Length; i++)
|
||||
{
|
||||
// Check for a file
|
||||
if (!File.Exists(args[i].Trim('"')))
|
||||
{
|
||||
DisplayHelp($"{args[i].Trim('"')} does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the full file path
|
||||
string filepath = Path.GetFullPath(args[i].Trim('"'));
|
||||
|
||||
// Now populate an environment
|
||||
// TODO: Replace this with Dictionary constructor
|
||||
var options = new Options
|
||||
{
|
||||
InternalProgram = internalProgram,
|
||||
ScanForProtection = scan && !string.IsNullOrWhiteSpace(path),
|
||||
PromptForDiscInformation = false,
|
||||
|
||||
Username = username,
|
||||
Password = password,
|
||||
};
|
||||
|
||||
Drive drive = null;
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
drive = new Drive(null, new DriveInfo(path));
|
||||
|
||||
var env = new DumpEnvironment(options, "", filepath, drive, knownSystem, mediaType, null);
|
||||
env.FixOutputPaths();
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
var result = env.VerifyAndSaveDumpOutput(resultProgress, protectionProgress).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display help for DICUI.Check
|
||||
/// </summary>
|
||||
/// <param name="error">Error string to prefix the help text with</param>
|
||||
private static void DisplayHelp(string error = null)
|
||||
{
|
||||
if (error != null)
|
||||
Console.WriteLine(error);
|
||||
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine("DICUI.Check.exe <mediatype> <system> [options] </path/to/output.bin> ...");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Standalone Options:");
|
||||
Console.WriteLine("-h, -? Show this help text");
|
||||
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("Check Options:");
|
||||
Console.WriteLine("-c, --credentials <user> <pw> Redump username and password");
|
||||
Console.WriteLine("-u, --use <program> Dumping program output type");
|
||||
Console.WriteLine("-p, --path <drivepath> Physical drive path for additional checks");
|
||||
Console.WriteLine("-s, --scan Enable copy protection scan (requires --path)");
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all media types with their short usable names
|
||||
/// </summary>
|
||||
private static void ListMediaTypes()
|
||||
{
|
||||
Console.WriteLine("Supported Media Types:");
|
||||
foreach (var val in Enum.GetValues(typeof(MediaType)))
|
||||
{
|
||||
if (((MediaType)val) == MediaType.NONE)
|
||||
continue;
|
||||
|
||||
Console.WriteLine($"{((MediaType?)val).ShortName()} - {((MediaType?)val).LongName()}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all programs with their short usable names
|
||||
/// </summary>
|
||||
private static void ListPrograms()
|
||||
{
|
||||
Console.WriteLine("Supported Programs:");
|
||||
foreach (var val in Enum.GetValues(typeof(InternalProgram)))
|
||||
{
|
||||
if (((InternalProgram)val) == InternalProgram.NONE)
|
||||
continue;
|
||||
|
||||
Console.WriteLine($"{((InternalProgram?)val).LongName()}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all known systems with their short usable names
|
||||
/// </summary>
|
||||
private static void ListKnownSystems()
|
||||
{
|
||||
Console.WriteLine("Supported Known Systems:");
|
||||
foreach (var val in Enum.GetValues(typeof(KnownSystem)))
|
||||
{
|
||||
if (((KnownSystem)val) == KnownSystem.NONE)
|
||||
continue;
|
||||
|
||||
Console.WriteLine($"{((KnownSystem?)val).ShortName()} - {((KnownSystem?)val).LongName()}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple process counter to write to console
|
||||
/// </summary>
|
||||
private static void ProgressUpdated(object sender, Result value)
|
||||
{
|
||||
Console.WriteLine(value.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple process counter to write to console
|
||||
/// </summary>
|
||||
private static void ProgressUpdated(object sender, FileProtection value)
|
||||
{
|
||||
Console.WriteLine($"{value.Percentage * 100:N2}%: {value.Filename} - {value.Protection}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,424 +0,0 @@
|
||||
using DICUI.Data;
|
||||
|
||||
namespace DICUI.Aaru
|
||||
{
|
||||
public static class Converters
|
||||
{
|
||||
#region Cross-enumeration conversions
|
||||
|
||||
/// <summary>
|
||||
/// Get the default extension for a given disc type
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType value to check</param>
|
||||
/// <returns>Valid extension (with leading '.'), null on error</returns>
|
||||
public static string Extension(MediaType? type)
|
||||
{
|
||||
// Aaru has a single, unified output format by default
|
||||
return ".aif";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Convert to Long Name
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the Command enum values
|
||||
/// </summary>
|
||||
/// <param name="command">Command value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(Command command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
// Database Family
|
||||
case Command.DatabaseStats:
|
||||
return $"{CommandStrings.DatabasePrefixLong} {CommandStrings.DatabaseStats}";
|
||||
case Command.DatabaseUpdate:
|
||||
return $"{CommandStrings.DatabasePrefixLong} {CommandStrings.DatabaseUpdate}";
|
||||
|
||||
// Device Family
|
||||
case Command.DeviceInfo:
|
||||
return $"{CommandStrings.DevicePrefixLong} {CommandStrings.DeviceInfo}";
|
||||
case Command.DeviceList:
|
||||
return $"{CommandStrings.DevicePrefixLong} {CommandStrings.DeviceList}";
|
||||
case Command.DeviceReport:
|
||||
return $"{CommandStrings.DevicePrefixLong} {CommandStrings.DeviceReport}";
|
||||
|
||||
// Filesystem Family
|
||||
case Command.FilesystemExtract:
|
||||
return $"{CommandStrings.FilesystemPrefixLong} {CommandStrings.FilesystemExtract}";
|
||||
case Command.FilesystemList:
|
||||
return $"{CommandStrings.FilesystemPrefixLong} {CommandStrings.FilesystemListLong}";
|
||||
case Command.FilesystemOptions:
|
||||
return $"{CommandStrings.FilesystemPrefixLong} {CommandStrings.FilesystemOptions}";
|
||||
|
||||
// Image Family
|
||||
case Command.ImageAnalyze:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImageAnalyze}";
|
||||
case Command.ImageChecksum:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImageChecksumLong}";
|
||||
case Command.ImageCompare:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImageCompareLong}";
|
||||
case Command.ImageConvert:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImageConvert}";
|
||||
case Command.ImageCreateSidecar:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImageCreateSidecar}";
|
||||
case Command.ImageDecode:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImageDecode}";
|
||||
case Command.ImageEntropy:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImageEntropy}";
|
||||
case Command.ImageInfo:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImageInfo}";
|
||||
case Command.ImageOptions:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImageOptions}";
|
||||
case Command.ImagePrint:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImagePrint}";
|
||||
case Command.ImageVerify:
|
||||
return $"{CommandStrings.ImagePrefixLong} {CommandStrings.ImageVerify}";
|
||||
|
||||
// Media Family
|
||||
case Command.MediaDump:
|
||||
return $"{CommandStrings.MediaPrefixLong} {CommandStrings.MediaDump}";
|
||||
case Command.MediaInfo:
|
||||
return $"{CommandStrings.MediaPrefixLong} {CommandStrings.MediaInfo}";
|
||||
case Command.MediaScan:
|
||||
return $"{CommandStrings.MediaPrefixLong} {CommandStrings.MediaScan}";
|
||||
|
||||
// Standalone Commands
|
||||
case Command.Configure:
|
||||
return CommandStrings.Configure;
|
||||
case Command.Formats:
|
||||
return CommandStrings.Formats;
|
||||
case Command.ListEncodings:
|
||||
return CommandStrings.ListEncodings;
|
||||
case Command.ListNamespaces:
|
||||
return CommandStrings.ListNamespaces;
|
||||
case Command.Remote:
|
||||
return CommandStrings.Remote;
|
||||
|
||||
case Command.NONE:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the Flag enum values
|
||||
/// </summary>
|
||||
/// <param name="command">Flag value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(Flag flag)
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
// Boolean flags
|
||||
case Flag.Adler32:
|
||||
return FlagStrings.Adler32Long;
|
||||
case Flag.Clear:
|
||||
return FlagStrings.ClearLong;
|
||||
case Flag.ClearAll:
|
||||
return FlagStrings.ClearAllLong;
|
||||
case Flag.CRC16:
|
||||
return FlagStrings.CRC16Long;
|
||||
case Flag.CRC32:
|
||||
return FlagStrings.CRC32Long;
|
||||
case Flag.CRC64:
|
||||
return FlagStrings.CRC64Long;
|
||||
case Flag.Debug:
|
||||
return FlagStrings.DebugLong;
|
||||
case Flag.DiskTags:
|
||||
return FlagStrings.DiskTagsLong;
|
||||
case Flag.DuplicatedSectors:
|
||||
return FlagStrings.DuplicatedSectorsLong;
|
||||
case Flag.Eject:
|
||||
return FlagStrings.EjectLong;
|
||||
case Flag.ExtendedAttributes:
|
||||
return FlagStrings.ExtendedAttributesLong;
|
||||
case Flag.Filesystems:
|
||||
return FlagStrings.FilesystemsLong;
|
||||
case Flag.FirstPregap:
|
||||
return FlagStrings.FirstPregapLong;
|
||||
case Flag.FixOffset:
|
||||
return FlagStrings.FixOffsetLong;
|
||||
case Flag.FixSubchannel:
|
||||
return FlagStrings.FixSubchannelLong;
|
||||
case Flag.FixSubchannelCrc:
|
||||
return FlagStrings.FixSubchannelCrcLong;
|
||||
case Flag.FixSubchannelPosition:
|
||||
return FlagStrings.FixSubchannelPositionLong;
|
||||
case Flag.Fletcher16:
|
||||
return FlagStrings.Fletcher16Long;
|
||||
case Flag.Fletcher32:
|
||||
return FlagStrings.Fletcher32Long;
|
||||
case Flag.Force:
|
||||
return FlagStrings.ForceLong;
|
||||
case Flag.GenerateSubchannels:
|
||||
return FlagStrings.GenerateSubchannelsLong;
|
||||
case Flag.Help:
|
||||
return FlagStrings.HelpLong;
|
||||
case Flag.LongFormat:
|
||||
return FlagStrings.LongFormatLong;
|
||||
case Flag.LongSectors:
|
||||
return FlagStrings.LongSectorsLong;
|
||||
case Flag.MD5:
|
||||
return FlagStrings.MD5Long;
|
||||
case Flag.Metadata:
|
||||
return FlagStrings.MetadataLong;
|
||||
case Flag.Partitions:
|
||||
return FlagStrings.PartitionsLong;
|
||||
case Flag.Persistent:
|
||||
return FlagStrings.PersistentLong;
|
||||
case Flag.Private:
|
||||
return FlagStrings.PrivateLong;
|
||||
case Flag.Resume:
|
||||
return FlagStrings.ResumeLong;
|
||||
case Flag.RetrySubchannel:
|
||||
return FlagStrings.RetrySubchannelLong;
|
||||
case Flag.SectorTags:
|
||||
return FlagStrings.SectorTagsLong;
|
||||
case Flag.SeparatedTracks:
|
||||
return FlagStrings.SeparatedTracksLong;
|
||||
case Flag.SHA1:
|
||||
return FlagStrings.SHA1Long;
|
||||
case Flag.SHA256:
|
||||
return FlagStrings.SHA256Long;
|
||||
case Flag.SHA384:
|
||||
return FlagStrings.SHA384Long;
|
||||
case Flag.SHA512:
|
||||
return FlagStrings.SHA512Long;
|
||||
case Flag.SkipCdiReadyHole:
|
||||
return FlagStrings.SkipCdiReadyHoleLong;
|
||||
case Flag.SpamSum:
|
||||
return FlagStrings.SpamSumLong;
|
||||
case Flag.StopOnError:
|
||||
return FlagStrings.StopOnErrorLong;
|
||||
case Flag.Tape:
|
||||
return FlagStrings.TapeLong;
|
||||
case Flag.Trim:
|
||||
return FlagStrings.TrimLong;
|
||||
case Flag.Verbose:
|
||||
return FlagStrings.VerboseLong;
|
||||
case Flag.VerifyDisc:
|
||||
return FlagStrings.VerifyDiscLong;
|
||||
case Flag.VerifySectors:
|
||||
return FlagStrings.VerifySectorsLong;
|
||||
case Flag.Version:
|
||||
return FlagStrings.VersionLong;
|
||||
case Flag.WholeDisc:
|
||||
return FlagStrings.WholeDiscLong;
|
||||
|
||||
// Int8 flags
|
||||
case Flag.Speed:
|
||||
return FlagStrings.SpeedLong;
|
||||
|
||||
// Int16 flags
|
||||
case Flag.RetryPasses:
|
||||
return FlagStrings.RetryPassesLong;
|
||||
case Flag.Width:
|
||||
return FlagStrings.WidthLong;
|
||||
|
||||
// Int32 flags
|
||||
case Flag.BlockSize:
|
||||
return FlagStrings.BlockSizeLong;
|
||||
case Flag.Count:
|
||||
return FlagStrings.CountLong;
|
||||
case Flag.MediaLastSequence:
|
||||
return FlagStrings.MediaLastSequenceLong;
|
||||
case Flag.MediaSequence:
|
||||
return FlagStrings.MediaSequenceLong;
|
||||
case Flag.Skip:
|
||||
return FlagStrings.SkipLong;
|
||||
|
||||
// Int64 flags
|
||||
case Flag.Length:
|
||||
return FlagStrings.LengthLong;
|
||||
case Flag.Start:
|
||||
return FlagStrings.StartLong;
|
||||
|
||||
// String flags
|
||||
case Flag.Comments:
|
||||
return FlagStrings.CommentsLong;
|
||||
case Flag.Creator:
|
||||
return FlagStrings.CreatorLong;
|
||||
case Flag.DriveManufacturer:
|
||||
return FlagStrings.DriveManufacturerLong;
|
||||
case Flag.DriveModel:
|
||||
return FlagStrings.DriveModelLong;
|
||||
case Flag.DriveRevision:
|
||||
return FlagStrings.DriveRevisionLong;
|
||||
case Flag.DriveSerial:
|
||||
return FlagStrings.DriveSerialLong;
|
||||
case Flag.Encoding:
|
||||
return FlagStrings.EncodingLong;
|
||||
case Flag.FormatConvert:
|
||||
return FlagStrings.FormatConvertLong;
|
||||
case Flag.FormatDump:
|
||||
return FlagStrings.FormatDumpLong;
|
||||
case Flag.ImgBurnLog:
|
||||
return FlagStrings.ImgBurnLogLong;
|
||||
case Flag.MediaBarcode:
|
||||
return FlagStrings.MediaBarcodeLong;
|
||||
case Flag.MediaManufacturer:
|
||||
return FlagStrings.MediaManufacturerLong;
|
||||
case Flag.MediaModel:
|
||||
return FlagStrings.MediaModelLong;
|
||||
case Flag.MediaPartNumber:
|
||||
return FlagStrings.MediaPartNumberLong;
|
||||
case Flag.MediaSerial:
|
||||
return FlagStrings.MediaSerialLong;
|
||||
case Flag.MediaTitle:
|
||||
return FlagStrings.MediaTitleLong;
|
||||
case Flag.MHDDLog:
|
||||
return FlagStrings.MHDDLogLong;
|
||||
case Flag.Namespace:
|
||||
return FlagStrings.NamespaceLong;
|
||||
case Flag.Options:
|
||||
return FlagStrings.OptionsLong;
|
||||
case Flag.OutputPrefix:
|
||||
return FlagStrings.OutputPrefixLong;
|
||||
case Flag.ResumeFile:
|
||||
return FlagStrings.ResumeFileLong;
|
||||
case Flag.Subchannel:
|
||||
return FlagStrings.SubchannelLong;
|
||||
case Flag.XMLSidecar:
|
||||
return FlagStrings.XMLSidecarLong;
|
||||
|
||||
case Flag.NONE:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Convert From String
|
||||
|
||||
/// <summary>
|
||||
/// Get the Command enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="commandOne">First part of String value to convert</param>
|
||||
/// <param name="commandTwo">Second part of String value to convert</param>
|
||||
/// <param name="useSecond">Output bool if the second command was used</param>
|
||||
/// <returns>Command represented by the string(s), if possible</returns>
|
||||
public static Command StringToCommand(string commandOne, string commandTwo, out bool useSecond)
|
||||
{
|
||||
useSecond = false;
|
||||
switch (commandOne)
|
||||
{
|
||||
// Database Family
|
||||
case CommandStrings.DatabasePrefixShort:
|
||||
case CommandStrings.DatabasePrefixLong:
|
||||
useSecond = true;
|
||||
switch (commandTwo)
|
||||
{
|
||||
case CommandStrings.DatabaseStats:
|
||||
return Command.DatabaseStats;
|
||||
case CommandStrings.DatabaseUpdate:
|
||||
return Command.DatabaseUpdate;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Device Family
|
||||
case CommandStrings.DevicePrefixShort:
|
||||
case CommandStrings.DevicePrefixLong:
|
||||
useSecond = true;
|
||||
switch (commandTwo)
|
||||
{
|
||||
case CommandStrings.DeviceInfo:
|
||||
return Command.DeviceInfo;
|
||||
case CommandStrings.DeviceList:
|
||||
return Command.DeviceList;
|
||||
case CommandStrings.DeviceReport:
|
||||
return Command.DeviceReport;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Filesystem Family
|
||||
case CommandStrings.FilesystemPrefixShort:
|
||||
case CommandStrings.FilesystemPrefixShortAlt:
|
||||
case CommandStrings.FilesystemPrefixLong:
|
||||
useSecond = true;
|
||||
switch (commandTwo)
|
||||
{
|
||||
case CommandStrings.FilesystemExtract:
|
||||
return Command.FilesystemExtract;
|
||||
case CommandStrings.FilesystemListShort:
|
||||
case CommandStrings.FilesystemListLong:
|
||||
return Command.FilesystemList;
|
||||
case CommandStrings.DatabaseStats:
|
||||
return Command.FilesystemOptions;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Image Family
|
||||
case CommandStrings.ImagePrefixShort:
|
||||
case CommandStrings.ImagePrefixLong:
|
||||
useSecond = true;
|
||||
switch (commandTwo)
|
||||
{
|
||||
case CommandStrings.ImageAnalyze:
|
||||
return Command.ImageAnalyze;
|
||||
case CommandStrings.ImageChecksumShort:
|
||||
case CommandStrings.ImageChecksumLong:
|
||||
return Command.ImageChecksum;
|
||||
case CommandStrings.ImageCompareShort:
|
||||
case CommandStrings.ImageCompareLong:
|
||||
return Command.ImageCompare;
|
||||
case CommandStrings.ImageConvert:
|
||||
return Command.ImageConvert;
|
||||
case CommandStrings.ImageCreateSidecar:
|
||||
return Command.ImageCreateSidecar;
|
||||
case CommandStrings.ImageDecode:
|
||||
return Command.ImageDecode;
|
||||
case CommandStrings.ImageEntropy:
|
||||
return Command.ImageEntropy;
|
||||
case CommandStrings.ImageInfo:
|
||||
return Command.ImageInfo;
|
||||
case CommandStrings.ImageOptions:
|
||||
return Command.ImageOptions;
|
||||
case CommandStrings.ImagePrint:
|
||||
return Command.ImagePrint;
|
||||
case CommandStrings.ImageVerify:
|
||||
return Command.ImageVerify;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Media Family
|
||||
case CommandStrings.MediaPrefixShort:
|
||||
case CommandStrings.MediaPrefixLong:
|
||||
useSecond = true;
|
||||
switch (commandTwo)
|
||||
{
|
||||
case CommandStrings.MediaDump:
|
||||
return Command.MediaDump;
|
||||
case CommandStrings.MediaInfo:
|
||||
return Command.MediaInfo;
|
||||
case CommandStrings.MediaScan:
|
||||
return Command.MediaScan;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Standalone Commands
|
||||
case CommandStrings.Configure:
|
||||
return Command.Configure;
|
||||
case CommandStrings.Formats:
|
||||
return Command.Formats;
|
||||
case CommandStrings.ListEncodings:
|
||||
return Command.ListEncodings;
|
||||
case CommandStrings.ListNamespaces:
|
||||
return Command.ListNamespaces;
|
||||
case CommandStrings.Remote:
|
||||
return Command.Remote;
|
||||
}
|
||||
|
||||
return Command.NONE;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
namespace DICUI.Aaru
|
||||
{
|
||||
/// <summary>
|
||||
/// Supported Aaru commands
|
||||
/// </summary>
|
||||
public enum Command : int
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
// Database Family
|
||||
DatabaseStats,
|
||||
DatabaseUpdate,
|
||||
|
||||
// Device Family
|
||||
DeviceInfo,
|
||||
DeviceList,
|
||||
DeviceReport,
|
||||
|
||||
// Filesystem Family
|
||||
FilesystemExtract,
|
||||
FilesystemList,
|
||||
FilesystemOptions,
|
||||
|
||||
// Image Family
|
||||
ImageAnalyze,
|
||||
ImageChecksum,
|
||||
ImageCompare,
|
||||
ImageConvert,
|
||||
ImageCreateSidecar,
|
||||
ImageDecode,
|
||||
ImageEntropy,
|
||||
ImageInfo,
|
||||
ImageOptions,
|
||||
ImagePrint,
|
||||
ImageVerify,
|
||||
|
||||
// Media Family
|
||||
MediaDump,
|
||||
MediaInfo,
|
||||
MediaScan,
|
||||
|
||||
// Standalone Commands
|
||||
Configure,
|
||||
Formats,
|
||||
ListEncodings,
|
||||
ListNamespaces,
|
||||
Remote,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supported Aaru flags
|
||||
/// </summary>
|
||||
public enum Flag : int
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
// Boolean flags
|
||||
Adler32,
|
||||
Clear,
|
||||
ClearAll,
|
||||
CRC16,
|
||||
CRC32,
|
||||
CRC64,
|
||||
Debug,
|
||||
DiskTags,
|
||||
DuplicatedSectors,
|
||||
Eject,
|
||||
ExtendedAttributes,
|
||||
Filesystems,
|
||||
FirstPregap,
|
||||
FixOffset,
|
||||
FixSubchannel,
|
||||
FixSubchannelCrc,
|
||||
FixSubchannelPosition,
|
||||
Fletcher16,
|
||||
Fletcher32,
|
||||
Force,
|
||||
GenerateSubchannels,
|
||||
Help,
|
||||
LongFormat,
|
||||
LongSectors,
|
||||
MD5,
|
||||
Metadata,
|
||||
Partitions,
|
||||
Persistent,
|
||||
Private,
|
||||
Resume,
|
||||
RetrySubchannel,
|
||||
SectorTags,
|
||||
SeparatedTracks,
|
||||
SHA1,
|
||||
SHA256,
|
||||
SHA384,
|
||||
SHA512,
|
||||
SkipCdiReadyHole,
|
||||
SpamSum,
|
||||
StopOnError,
|
||||
Tape,
|
||||
Trim,
|
||||
Verbose,
|
||||
VerifyDisc,
|
||||
VerifySectors,
|
||||
Version,
|
||||
WholeDisc,
|
||||
|
||||
// Int8 flags
|
||||
Speed,
|
||||
|
||||
// Int16 flags
|
||||
RetryPasses,
|
||||
Width,
|
||||
|
||||
// Int32 flags
|
||||
BlockSize,
|
||||
Count,
|
||||
MediaLastSequence,
|
||||
MediaSequence,
|
||||
Skip,
|
||||
|
||||
// Int64 flags
|
||||
Length,
|
||||
Start,
|
||||
|
||||
// String flags
|
||||
Comments,
|
||||
Creator,
|
||||
DriveManufacturer,
|
||||
DriveModel,
|
||||
DriveRevision,
|
||||
DriveSerial,
|
||||
Encoding,
|
||||
FormatConvert,
|
||||
FormatDump,
|
||||
ImgBurnLog,
|
||||
MediaBarcode,
|
||||
MediaManufacturer,
|
||||
MediaModel,
|
||||
MediaPartNumber,
|
||||
MediaSerial,
|
||||
MediaTitle,
|
||||
MHDDLog,
|
||||
Namespace,
|
||||
Options,
|
||||
OutputPrefix,
|
||||
ResumeFile,
|
||||
Subchannel,
|
||||
XMLSidecar,
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,104 +0,0 @@
|
||||
using DICUI.Data;
|
||||
|
||||
namespace DICUI.DD
|
||||
{
|
||||
public static class Converters
|
||||
{
|
||||
#region Cross-enumeration conversions
|
||||
|
||||
/// <summary>
|
||||
/// Get the default extension for a given disc type
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType value to check</param>
|
||||
/// <returns>Valid extension (with leading '.'), null on error</returns>
|
||||
public static string Extension(MediaType? type)
|
||||
{
|
||||
// DD has a single, unified output format by default
|
||||
return ".bin";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Convert to Long Name
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the Command enum values
|
||||
/// </summary>
|
||||
/// <param name="command">Command value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(Command command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case Command.List:
|
||||
return CommandStrings.List;
|
||||
|
||||
case Command.NONE:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the Flag enum values
|
||||
/// </summary>
|
||||
/// <param name="command">Flag value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(Flag flag)
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
// Boolean flags
|
||||
case Flag.Progress:
|
||||
return FlagStrings.Progress;
|
||||
case Flag.Size:
|
||||
return FlagStrings.Size;
|
||||
|
||||
// Int64 flags
|
||||
case Flag.BlockSize:
|
||||
return FlagStrings.BlockSize;
|
||||
case Flag.Count:
|
||||
return FlagStrings.Count;
|
||||
case Flag.Seek:
|
||||
return FlagStrings.Seek;
|
||||
case Flag.Skip:
|
||||
return FlagStrings.Skip;
|
||||
|
||||
// String flags
|
||||
case Flag.Filter:
|
||||
return FlagStrings.Filter;
|
||||
case Flag.InputFile:
|
||||
return FlagStrings.InputFile;
|
||||
case Flag.OutputFile:
|
||||
return FlagStrings.OutputFile;
|
||||
|
||||
case Flag.NONE:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Convert From String
|
||||
|
||||
/// <summary>
|
||||
/// Get the Command enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="command">String value to convert</param>
|
||||
/// <returns>Command represented by the string(s), if possible</returns>
|
||||
public static Command StringToCommand(string command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case CommandStrings.List:
|
||||
return Command.List;
|
||||
|
||||
default:
|
||||
return Command.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
namespace DICUI.DD
|
||||
{
|
||||
/// <summary>
|
||||
/// Supported DD commands
|
||||
/// </summary>
|
||||
public enum Command: int
|
||||
{
|
||||
NONE = 0, // For DD, this represents a normal dump
|
||||
List,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supported DD flags
|
||||
/// </summary>
|
||||
public enum Flag : int
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
// Boolean flags
|
||||
Progress,
|
||||
Size,
|
||||
|
||||
// Int64 flags
|
||||
BlockSize,
|
||||
Count,
|
||||
Seek,
|
||||
Skip,
|
||||
|
||||
// String flags
|
||||
Filter,
|
||||
InputFile,
|
||||
OutputFile,
|
||||
}
|
||||
}
|
||||
@@ -1,668 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.DD
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic set of DD parameters
|
||||
/// </summary>
|
||||
public class Parameters : BaseParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Base command to run
|
||||
/// </summary>
|
||||
public Command BaseCommand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set of flags to pass to the executable
|
||||
/// </summary>
|
||||
protected Dictionary<Flag, bool?> _flags = new Dictionary<Flag, bool?>();
|
||||
public bool? this[Flag key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_flags.ContainsKey(key))
|
||||
return _flags[key];
|
||||
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
_flags[key] = value;
|
||||
}
|
||||
}
|
||||
protected internal IEnumerable<Flag> Keys => _flags.Keys;
|
||||
|
||||
#region Flag Values
|
||||
|
||||
public long? BlockSizeValue { get; set; }
|
||||
|
||||
public long? CountValue { get; set; }
|
||||
|
||||
// fixed, removable, disk, partition
|
||||
public string FilterValue { get; set; }
|
||||
|
||||
public string InputFileValue { get; set; }
|
||||
|
||||
public string OutputFileValue { get; set; }
|
||||
|
||||
public long? SeekValue { get; set; }
|
||||
|
||||
public long? SkipValue { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Populate a Parameters object from a param string
|
||||
/// </summary>
|
||||
/// <param name="parameters">String possibly representing a set of parameters</param>
|
||||
public Parameters(string parameters)
|
||||
: base(parameters)
|
||||
{
|
||||
this.InternalProgram = InternalProgram.DD;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate parameters based on a set of known inputs
|
||||
/// </summary>
|
||||
/// <param name="system">KnownSystem value to use</param>
|
||||
/// <param name="type">MediaType value to use</param>
|
||||
/// <param name="driveLetter">Drive letter to use</param>
|
||||
/// <param name="filename">Filename to use</param>
|
||||
/// <param name="driveSpeed">Drive speed to use</param>
|
||||
/// <param name="paranoid">Enable paranoid mode (safer dumping)</param>
|
||||
/// <param name="quietMode">Enable quiet mode (no beeps)</param>
|
||||
/// <param name="retryCount">User-defined reread count</param>
|
||||
public Parameters(KnownSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, bool paranoid, bool quietMode, int retryCount)
|
||||
: base(system, type, driveLetter, filename, driveSpeed, paranoid, quietMode, retryCount)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blindly generate a parameter string based on the inputs
|
||||
/// </summary>
|
||||
/// <returns>Correctly formatted parameter string, null on error</returns>
|
||||
public override string GenerateParameters()
|
||||
{
|
||||
List<string> parameters = new List<string>();
|
||||
|
||||
if (BaseCommand != Command.NONE)
|
||||
parameters.Add(Converters.LongName(BaseCommand));
|
||||
|
||||
#region Boolean flags
|
||||
|
||||
// Progress
|
||||
if (GetSupportedCommands(Flag.Progress).Contains(BaseCommand))
|
||||
{
|
||||
if (this[Flag.Progress] == true)
|
||||
parameters.Add($"{this[Flag.Progress]}");
|
||||
}
|
||||
|
||||
// Size
|
||||
if (GetSupportedCommands(Flag.Size).Contains(BaseCommand))
|
||||
{
|
||||
if (this[Flag.Size] == true)
|
||||
parameters.Add($"{this[Flag.Size]}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Int64 flags
|
||||
|
||||
// Block Size
|
||||
if (GetSupportedCommands(Flag.BlockSize).Contains(BaseCommand))
|
||||
{
|
||||
if (this[Flag.BlockSize] == true && BlockSizeValue != null)
|
||||
parameters.Add($"{Converters.LongName(Flag.BlockSize)}={BlockSizeValue}");
|
||||
}
|
||||
|
||||
// Count
|
||||
if (GetSupportedCommands(Flag.Count).Contains(BaseCommand))
|
||||
{
|
||||
if (this[Flag.Count] == true && CountValue != null)
|
||||
parameters.Add($"{Converters.LongName(Flag.Count)}={CountValue}");
|
||||
}
|
||||
|
||||
// Seek
|
||||
if (GetSupportedCommands(Flag.Seek).Contains(BaseCommand))
|
||||
{
|
||||
if (this[Flag.Seek] == true && SeekValue != null)
|
||||
parameters.Add($"{Converters.LongName(Flag.Seek)}={SeekValue}");
|
||||
}
|
||||
|
||||
// Skip
|
||||
if (GetSupportedCommands(Flag.Skip).Contains(BaseCommand))
|
||||
{
|
||||
if (this[Flag.Skip] == true && SkipValue != null)
|
||||
parameters.Add($"{Converters.LongName(Flag.Skip)}={SkipValue}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region String flags
|
||||
|
||||
// Filter
|
||||
if (GetSupportedCommands(Flag.Filter).Contains(BaseCommand))
|
||||
{
|
||||
if (this[Flag.Filter] == true && FilterValue != null)
|
||||
parameters.Add($"{Converters.LongName(Flag.Filter)}={FilterValue}");
|
||||
}
|
||||
|
||||
// Input File
|
||||
if (GetSupportedCommands(Flag.InputFile).Contains(BaseCommand))
|
||||
{
|
||||
if (this[Flag.InputFile] == true && InputFileValue != null)
|
||||
parameters.Add($"{Converters.LongName(Flag.InputFile)}={InputFileValue}");
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
// Output File
|
||||
if (GetSupportedCommands(Flag.OutputFile).Contains(BaseCommand))
|
||||
{
|
||||
if (this[Flag.OutputFile] == true && OutputFileValue != null)
|
||||
parameters.Add($"{Converters.LongName(Flag.OutputFile)}={OutputFileValue}");
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the input path from the implementation
|
||||
/// </summary>
|
||||
/// <returns>String representing the path, null on error</returns>
|
||||
public override string InputPath() => InputFileValue;
|
||||
|
||||
/// <summary>
|
||||
/// Get the output path from the implementation
|
||||
/// </summary>
|
||||
/// <returns>String representing the path, null on error</returns>
|
||||
public override string OutputPath() => OutputFileValue;
|
||||
|
||||
/// <summary>
|
||||
/// Get the processing speed from the implementation
|
||||
/// </summary>
|
||||
/// <returns>int? representing the speed, null on error</returns>
|
||||
/// <remarks>DD does not support drive speeds</remarks>
|
||||
public override int? GetSpeed() => 1;
|
||||
|
||||
/// <summary>
|
||||
/// Set the processing speed int the implementation
|
||||
/// </summary>
|
||||
/// <param name="speed">int? representing the speed</param>
|
||||
/// <remarks>DD does not support drive speeds</remarks>
|
||||
public override void SetSpeed(int? speed)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the MediaType from the current set of parameters
|
||||
/// </summary>
|
||||
/// <returns>MediaType value if successful, null on error</returns>
|
||||
/// <remarks>DD does not know the difference between media types</remarks>
|
||||
public override MediaType? GetMediaType() => null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the current command is considered a dumping command or not
|
||||
/// </summary>
|
||||
/// <returns>True if it's a dumping command, false otherwise</returns>
|
||||
public override bool IsDumpingCommand()
|
||||
{
|
||||
switch (this.BaseCommand)
|
||||
{
|
||||
case Command.List:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset all special variables to have default values
|
||||
/// </summary>
|
||||
protected override void ResetValues()
|
||||
{
|
||||
BaseCommand = Command.NONE;
|
||||
|
||||
_flags = new Dictionary<Flag, bool?>();
|
||||
|
||||
BlockSizeValue = null;
|
||||
CountValue = null;
|
||||
InputFileValue = null;
|
||||
OutputFileValue = null;
|
||||
SeekValue = null;
|
||||
SkipValue = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set default parameters for a given system and media type
|
||||
/// </summary>
|
||||
/// <param name="system">KnownSystem value to use</param>
|
||||
/// <param name="type">MediaType value to use</param>
|
||||
/// <param name="driveLetter">Drive letter to use</param>
|
||||
/// <param name="filename">Filename to use</param>
|
||||
/// <param name="driveSpeed">Drive speed to use</param>
|
||||
/// <param name="paranoid">Enable paranoid mode (safer dumping)</param>
|
||||
/// <param name="retryCount">User-defined reread count</param>
|
||||
protected override void SetDefaultParameters(
|
||||
KnownSystem? system,
|
||||
MediaType? type,
|
||||
char driveLetter,
|
||||
string filename,
|
||||
int? driveSpeed,
|
||||
bool paranoid,
|
||||
int retryCount)
|
||||
{
|
||||
BaseCommand = Command.NONE;
|
||||
|
||||
this[Flag.InputFile] = true;
|
||||
InputFileValue = $"\\\\?\\{driveLetter}:";
|
||||
|
||||
this[Flag.OutputFile] = true;
|
||||
OutputFileValue = filename;
|
||||
|
||||
// TODO: Add more common block sizes
|
||||
this[Flag.BlockSize] = true;
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.FloppyDisk:
|
||||
BlockSizeValue = 1440 * 1024;
|
||||
break;
|
||||
|
||||
default:
|
||||
BlockSizeValue = 1024 * 1024 * 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
this[Flag.Progress] = true;
|
||||
this[Flag.Size] = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan a possible parameter string and populate whatever possible
|
||||
/// </summary>
|
||||
/// <param name="parameters">String possibly representing parameters</param>
|
||||
/// <returns></returns>
|
||||
protected override bool ValidateAndSetParameters(string parameters)
|
||||
{
|
||||
// The string has to be valid by itself first
|
||||
if (string.IsNullOrWhiteSpace(parameters))
|
||||
return false;
|
||||
|
||||
// Now split the string into parts for easier validation
|
||||
// https://stackoverflow.com/questions/14655023/split-a-string-that-has-white-spaces-unless-they-are-enclosed-within-quotes
|
||||
parameters = parameters.Trim();
|
||||
List<string> parts = Regex.Matches(parameters, @"[\""].+?[\""]|[^ ]+")
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Value)
|
||||
.ToList();
|
||||
|
||||
// Determine what the commandline should look like given the first item
|
||||
int start = 0;
|
||||
BaseCommand = Converters.StringToCommand(parts[0]);
|
||||
if (BaseCommand != Command.NONE)
|
||||
start = 1;
|
||||
|
||||
// Loop through all auxilary flags, if necessary
|
||||
int i = 0;
|
||||
for (i = start; i < parts.Count; i++)
|
||||
{
|
||||
// Flag read-out values
|
||||
long? longValue = null;
|
||||
string stringValue = null;
|
||||
|
||||
// Keep a count of keys to determine if we should break out to filename handling or not
|
||||
int keyCount = Keys.Count();
|
||||
|
||||
#region Boolean flags
|
||||
|
||||
// Progress
|
||||
ProcessBooleanParameter(parts, FlagStrings.Progress, Flag.Progress, ref i);
|
||||
|
||||
// Size
|
||||
ProcessBooleanParameter(parts, FlagStrings.Size, Flag.Size, ref i);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Int64 flags
|
||||
|
||||
// Block Size
|
||||
longValue = ProcessInt64Parameter(parts, FlagStrings.BlockSize, Flag.BlockSize, ref i);
|
||||
if (longValue == Int64.MinValue)
|
||||
return false;
|
||||
else if (longValue != null)
|
||||
BlockSizeValue = longValue;
|
||||
|
||||
// Count
|
||||
longValue = ProcessInt64Parameter(parts, FlagStrings.Count, Flag.Count, ref i);
|
||||
if (longValue == Int64.MinValue)
|
||||
return false;
|
||||
else if (longValue != null)
|
||||
CountValue = longValue;
|
||||
|
||||
// Seek
|
||||
longValue = ProcessInt64Parameter(parts, FlagStrings.Seek, Flag.Seek, ref i);
|
||||
if (longValue == Int64.MinValue)
|
||||
return false;
|
||||
else if (longValue != null)
|
||||
SeekValue = longValue;
|
||||
|
||||
// Skip
|
||||
longValue = ProcessInt64Parameter(parts, FlagStrings.Skip, Flag.Skip, ref i);
|
||||
if (longValue == Int64.MinValue)
|
||||
return false;
|
||||
else if (longValue != null)
|
||||
SkipValue = longValue;
|
||||
|
||||
#endregion
|
||||
|
||||
#region String flags
|
||||
|
||||
// Filter (fixed, removable, disk, partition)
|
||||
stringValue = ProcessStringParameter(parts, FlagStrings.Filter, Flag.Filter, ref i);
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
FilterValue = stringValue;
|
||||
|
||||
// Input File
|
||||
stringValue = ProcessStringParameter(parts, FlagStrings.InputFile, Flag.InputFile, ref i);
|
||||
if (string.Equals(stringValue, string.Empty))
|
||||
return false;
|
||||
else if (stringValue != null)
|
||||
InputFileValue = stringValue;
|
||||
|
||||
// Output File
|
||||
stringValue = ProcessStringParameter(parts, FlagStrings.OutputFile, Flag.OutputFile, ref i);
|
||||
if (string.Equals(stringValue, string.Empty))
|
||||
return false;
|
||||
else if (stringValue != null)
|
||||
OutputFileValue = stringValue;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate if all required output files exist
|
||||
/// </summary>
|
||||
/// <param name="basePath">Base filename and path to use for checking</param>
|
||||
/// <param name="system">KnownSystem type representing the media</param>
|
||||
/// <param name="type">MediaType type representing the media</param>
|
||||
/// <returns></returns>
|
||||
public override bool CheckAllOutputFilesExist(string basePath, KnownSystem? system, MediaType? type, IProgress<Result> progress = null)
|
||||
{
|
||||
// TODO: Figure out what sort of output files are expected... just `.bin`?
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a SubmissionInfo for the output files
|
||||
/// </summary>
|
||||
/// <param name="info">Base submission info to fill in specifics for</param>
|
||||
/// <param name="basePath">Base filename and path to use for checking</param>
|
||||
/// <param name="system">KnownSystem type representing the media</param>
|
||||
/// <param name="type">MediaType type representing the media</param>
|
||||
/// <param name="drive">Drive representing the disc to get information from</param>
|
||||
/// <returns></returns>
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, string basePath, KnownSystem? system, MediaType? type, Drive drive)
|
||||
{
|
||||
// TODO: Fill in submission info specifics for DD
|
||||
string outputDirectory = Path.GetDirectoryName(basePath);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
// Determine type-specific differences
|
||||
}
|
||||
|
||||
switch (system)
|
||||
{
|
||||
case KnownSystem.KonamiPython2:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out Region? pythonTwoRegion, out string pythonTwoDate))
|
||||
{
|
||||
info.CommonDiscInfo.Comments += $"Internal Disc Serial: {pythonTwoSerial}\n";
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = pythonTwoDate;
|
||||
}
|
||||
|
||||
info.VersionAndEditions.Version = GetPlayStation2Version(drive?.Letter) ?? "";
|
||||
break;
|
||||
|
||||
case KnownSystem.SonyPlayStation:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out Region? playstationRegion, out string playstationDate))
|
||||
{
|
||||
info.CommonDiscInfo.Comments += $"Internal Disc Serial: {playstationSerial}\n";
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = playstationDate;
|
||||
}
|
||||
|
||||
info.CopyProtection.AntiModchip = GetPlayStationAntiModchipDetected(drive?.Letter) ? YesNo.Yes : YesNo.No;
|
||||
break;
|
||||
|
||||
case KnownSystem.SonyPlayStation2:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out Region? playstationTwoRegion, out string playstationTwoDate))
|
||||
{
|
||||
info.CommonDiscInfo.Comments += $"Internal Disc Serial: {playstationTwoSerial}\n";
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = playstationTwoDate;
|
||||
}
|
||||
|
||||
info.VersionAndEditions.Version = GetPlayStation2Version(drive?.Letter) ?? "";
|
||||
break;
|
||||
|
||||
case KnownSystem.SonyPlayStation4:
|
||||
info.VersionAndEditions.Version = GetPlayStation4Version(drive?.Letter) ?? "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the list of commands that use a given flag
|
||||
/// </summary>
|
||||
/// <param name="flag">Flag value to get commands for</param>
|
||||
/// <returns>List of Commands, if possible</returns>
|
||||
private static List<Command> GetSupportedCommands(Flag flag)
|
||||
{
|
||||
var commands = new List<Command>();
|
||||
switch (flag)
|
||||
{
|
||||
#region Boolean flags
|
||||
|
||||
case Flag.Progress:
|
||||
commands.Add(Command.NONE);
|
||||
break;
|
||||
case Flag.Size:
|
||||
commands.Add(Command.NONE);
|
||||
break;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Int64 flags
|
||||
|
||||
case Flag.BlockSize:
|
||||
commands.Add(Command.NONE);
|
||||
break;
|
||||
case Flag.Count:
|
||||
commands.Add(Command.NONE);
|
||||
break;
|
||||
case Flag.Seek:
|
||||
commands.Add(Command.NONE);
|
||||
break;
|
||||
case Flag.Skip:
|
||||
commands.Add(Command.NONE);
|
||||
break;
|
||||
|
||||
#endregion
|
||||
|
||||
#region String flags
|
||||
|
||||
case Flag.Filter:
|
||||
commands.Add(Command.NONE);
|
||||
break;
|
||||
case Flag.InputFile:
|
||||
commands.Add(Command.NONE);
|
||||
break;
|
||||
case Flag.OutputFile:
|
||||
commands.Add(Command.NONE);
|
||||
break;
|
||||
|
||||
#endregion
|
||||
|
||||
case Flag.NONE:
|
||||
default:
|
||||
return commands;
|
||||
}
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process a boolean parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="flagString">Flag string to check</param>
|
||||
/// <param name="flag">Flag value corresponding to the flag</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>
|
||||
private bool ProcessBooleanParameter(List<string> parts, string flagString, Flag flag, ref int i)
|
||||
{
|
||||
if (parts == null)
|
||||
return false;
|
||||
|
||||
if (parts[i] == flagString)
|
||||
{
|
||||
if (!GetSupportedCommands(flag).Contains(BaseCommand))
|
||||
return false;
|
||||
|
||||
this[flag] = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process an Int64 parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="flagString">Flag string to check</param>
|
||||
/// <param name="flag">Flag value corresponding to the flag</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <returns>Int64 value if success, Int64.MinValue if skipped, null on error/returns>
|
||||
private long? ProcessInt64Parameter(List<string> parts, string flagString, Flag flag, ref int i)
|
||||
{
|
||||
if (parts == null)
|
||||
return null;
|
||||
|
||||
if (parts[i].StartsWith(flagString))
|
||||
{
|
||||
if (!GetSupportedCommands(flag).Contains(BaseCommand))
|
||||
return null;
|
||||
|
||||
string[] commandParts = parts[i].Split('=');
|
||||
if (commandParts.Length != 2)
|
||||
return null;
|
||||
|
||||
string valuePart = commandParts[1];
|
||||
long factor = 1;
|
||||
|
||||
// Characters
|
||||
if (valuePart.EndsWith("c", StringComparison.Ordinal))
|
||||
{
|
||||
factor = 1;
|
||||
valuePart.TrimEnd('c');
|
||||
}
|
||||
|
||||
// Words
|
||||
else if (valuePart.EndsWith("w", StringComparison.Ordinal))
|
||||
{
|
||||
factor = 2;
|
||||
valuePart.TrimEnd('w');
|
||||
}
|
||||
|
||||
// Double Words
|
||||
else if (valuePart.EndsWith("d", StringComparison.Ordinal))
|
||||
{
|
||||
factor = 4;
|
||||
valuePart.TrimEnd('d');
|
||||
}
|
||||
|
||||
// Quad Words
|
||||
else if (valuePart.EndsWith("q", StringComparison.Ordinal))
|
||||
{
|
||||
factor = 8;
|
||||
valuePart.TrimEnd('q');
|
||||
}
|
||||
|
||||
// Kilobytes
|
||||
else if (valuePart.EndsWith("k", StringComparison.Ordinal))
|
||||
{
|
||||
factor = 1024;
|
||||
valuePart.TrimEnd('k');
|
||||
}
|
||||
|
||||
// Megabytes
|
||||
else if (valuePart.EndsWith("M", StringComparison.Ordinal))
|
||||
{
|
||||
factor = 1024 * 1024;
|
||||
valuePart.TrimEnd('M');
|
||||
}
|
||||
|
||||
// Gigabytes
|
||||
else if (valuePart.EndsWith("G", StringComparison.Ordinal))
|
||||
{
|
||||
factor = 1024 * 1024 * 1024;
|
||||
valuePart.TrimEnd('G');
|
||||
}
|
||||
|
||||
if (!IsValidInt64(valuePart))
|
||||
return null;
|
||||
|
||||
this[flag] = true;
|
||||
return long.Parse(valuePart) * factor;
|
||||
}
|
||||
|
||||
return Int64.MinValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process a string parameter
|
||||
/// </summary>
|
||||
/// <param name="parts">List of parts to be referenced</param>
|
||||
/// <param name="flagString">Flag string to check</param>
|
||||
/// <param name="flag">Flag value corresponding to the flag</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <returns>String value if possible, string.Empty on missing, null on error</returns>
|
||||
private string ProcessStringParameter(List<string> parts, string flagString, Flag flag, ref int i)
|
||||
{
|
||||
if (parts == null)
|
||||
return null;
|
||||
|
||||
if (parts[i] == flagString)
|
||||
{
|
||||
if (!GetSupportedCommands(flag).Contains(BaseCommand))
|
||||
return null;
|
||||
|
||||
string[] commandParts = parts[i].Split('=');
|
||||
if (commandParts.Length != 2)
|
||||
return null;
|
||||
|
||||
string valuePart = commandParts[1];
|
||||
|
||||
this[flag] = true;
|
||||
return valuePart.Trim('"');
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;net48;netcoreapp3.1</TargetFrameworks>
|
||||
<Title>DICUI Library</Title>
|
||||
<AssemblyName>DICUI.Library</AssemblyName>
|
||||
<Description>Library code for DICUI and DICUI.Check</Description>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2020</Copyright>
|
||||
<RepositoryUrl>https://github.com/SabreTools/DICUI</RepositoryUrl>
|
||||
<Version>1.17.0</Version>
|
||||
<AssemblyVersion>1.17.0</AssemblyVersion>
|
||||
<FileVersion>1.17.0</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'!='netcoreapp3.1'">
|
||||
<DefineConstants>NET_FRAMEWORK</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'!='netcoreapp3.1'">
|
||||
<COMReference Include="IMAPI2">
|
||||
<Guid>{2735412F-7F64-5B0F-8F00-5D77AFBE261E}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
<COMReference Include="IMAPI2FS">
|
||||
<Guid>{2C941FD0-975B-59BE-A960-9A2A262853A5}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" Version="1.4.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Management" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Management" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,710 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Data
|
||||
{
|
||||
public abstract class BaseParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Path to the executable
|
||||
/// </summary>
|
||||
public string ExecutablePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Program that this set of parameters represents
|
||||
/// </summary>
|
||||
public InternalProgram InternalProgram { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Process to track external program
|
||||
/// </summary>
|
||||
private Process process;
|
||||
|
||||
/// <summary>
|
||||
/// Populate a Parameters object from a param string
|
||||
/// </summary>
|
||||
/// <param name="parameters">String possibly representing a set of parameters</param>
|
||||
public BaseParameters(string parameters)
|
||||
{
|
||||
// If any parameters are not valid, wipe out everything
|
||||
if (!ValidateAndSetParameters(parameters))
|
||||
{
|
||||
ResetValues();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate parameters based on a set of known inputs
|
||||
/// </summary>
|
||||
/// <param name="system">KnownSystem value to use</param>
|
||||
/// <param name="type">MediaType value to use</param>
|
||||
/// <param name="driveLetter">Drive letter to use</param>
|
||||
/// <param name="filename">Filename to use</param>
|
||||
/// <param name="driveSpeed">Drive speed to use</param>
|
||||
/// <param name="paranoid">Enable paranoid mode (safer dumping)</param>
|
||||
/// <param name="quietMode">Enable quiet mode (no beeps)</param>
|
||||
/// <param name="retryCount">User-defined reread count</param>
|
||||
public BaseParameters(KnownSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, bool paranoid, bool quietMode, int retryCount)
|
||||
{
|
||||
SetDefaultParameters(system, type, driveLetter, filename, driveSpeed, paranoid, retryCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blindly generate a parameter string based on the inputs
|
||||
/// </summary>
|
||||
/// <returns>Correctly formatted parameter string, null on error</returns>
|
||||
public abstract string GenerateParameters();
|
||||
|
||||
/// <summary>
|
||||
/// Get the input path from the implementation
|
||||
/// </summary>
|
||||
/// <returns>String representing the path, null on error</returns>
|
||||
public abstract string InputPath();
|
||||
|
||||
/// <summary>
|
||||
/// Get the output path from the implementation
|
||||
/// </summary>
|
||||
/// <returns>String representing the path, null on error</returns>
|
||||
public abstract string OutputPath();
|
||||
|
||||
/// <summary>
|
||||
/// Get the processing speed from the implementation
|
||||
/// </summary>
|
||||
/// <returns>int? representing the speed, null on error</returns>
|
||||
public abstract int? GetSpeed();
|
||||
|
||||
/// <summary>
|
||||
/// Set the processing speed int the implementation
|
||||
/// </summary>
|
||||
/// <param name="speed">int? representing the speed</param>
|
||||
public abstract void SetSpeed(int? speed);
|
||||
|
||||
/// <summary>
|
||||
/// Get the MediaType from the current set of parameters
|
||||
/// </summary>
|
||||
/// <returns>MediaType value if successful, null on error</returns>
|
||||
public abstract MediaType? GetMediaType();
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the current command is considered a dumping command or not
|
||||
/// </summary>
|
||||
/// <returns>True if it's a dumping command, false otherwise</returns>
|
||||
public abstract bool IsDumpingCommand();
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the current Parameter object is valid
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsValid()
|
||||
{
|
||||
return GenerateParameters() != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset all special variables to have default values
|
||||
/// </summary>
|
||||
protected abstract void ResetValues();
|
||||
|
||||
/// <summary>
|
||||
/// Set default parameters for a given system and media type
|
||||
/// </summary>
|
||||
/// <param name="system">KnownSystem value to use</param>
|
||||
/// <param name="type">MediaType value to use</param>
|
||||
/// <param name="driveLetter">Drive letter to use</param>
|
||||
/// <param name="filename">Filename to use</param>
|
||||
/// <param name="driveSpeed">Drive speed to use</param>
|
||||
/// <param name="paranoid">Enable paranoid mode (safer dumping)</param>
|
||||
/// <param name="retryCount">User-defined reread count</param>
|
||||
protected abstract void SetDefaultParameters(
|
||||
KnownSystem? system,
|
||||
MediaType? type,
|
||||
char driveLetter,
|
||||
string filename,
|
||||
int? driveSpeed,
|
||||
bool paranoid,
|
||||
int retryCount);
|
||||
|
||||
/// <summary>
|
||||
/// Scan a possible parameter string and populate whatever possible
|
||||
/// </summary>
|
||||
/// <param name="parameters">String possibly representing parameters</param>
|
||||
/// <returns></returns>
|
||||
protected abstract bool ValidateAndSetParameters(string parameters);
|
||||
|
||||
/// <summary>
|
||||
/// Validate if all required output files exist
|
||||
/// </summary>
|
||||
/// <param name="basePath">Base filename and path to use for checking</param>
|
||||
/// <param name="system">KnownSystem type representing the media</param>
|
||||
/// <param name="type">MediaType type representing the media</param>
|
||||
/// <param name="progress">Optional result progress callback</param>
|
||||
/// <returns></returns>
|
||||
public abstract bool CheckAllOutputFilesExist(string basePath, KnownSystem? system, MediaType? type, IProgress<Result> progress = null);
|
||||
|
||||
/// <summary>
|
||||
/// Generate a SubmissionInfo for the output files
|
||||
/// </summary>
|
||||
/// <param name="submissionInfo">Base submission info to fill in specifics for</param>
|
||||
/// <param name="basePath">Base filename and path to use for checking</param>
|
||||
/// <param name="system">KnownSystem type representing the media</param>
|
||||
/// <param name="type">MediaType type representing the media</param>
|
||||
/// <param name="drive">Drive representing the disc to get information from</param>
|
||||
public abstract void GenerateSubmissionInfo(SubmissionInfo submissionInfo, string basePath, KnownSystem? system, MediaType? type, Drive drive);
|
||||
|
||||
/// <summary>
|
||||
/// Run internal program
|
||||
/// </summary>
|
||||
public void ExecuteInternalProgram()
|
||||
{
|
||||
process = new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = ExecutablePath,
|
||||
Arguments = GenerateParameters() ?? "",
|
||||
},
|
||||
};
|
||||
|
||||
process.Start();
|
||||
process.WaitForExit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run internal program async with an input set of parameters
|
||||
/// </summary>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns>Standard output from commandline window</returns>
|
||||
public async Task<string> ExecuteInternalProgram(BaseParameters parameters)
|
||||
{
|
||||
Process childProcess;
|
||||
string output = await Task.Run(() =>
|
||||
{
|
||||
childProcess = new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = parameters.ExecutablePath,
|
||||
Arguments = parameters.GenerateParameters(),
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardInput = true,
|
||||
RedirectStandardOutput = true,
|
||||
},
|
||||
};
|
||||
childProcess.Start();
|
||||
childProcess.WaitForExit(1000);
|
||||
|
||||
// Just in case, we want to push a button 5 times to clear any errors
|
||||
for (int i = 0; i < 5; i++)
|
||||
childProcess.StandardInput.WriteLine("Y");
|
||||
|
||||
string stdout = childProcess.StandardOutput.ReadToEnd();
|
||||
childProcess.Dispose();
|
||||
return stdout;
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancel an in-progress dumping process
|
||||
/// </summary>
|
||||
public void KillInternalProgram()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (process != null && !process.HasExited)
|
||||
process.Kill();
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
|
||||
#region Parameter Parsing
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether or not the selected item exists
|
||||
/// </summary>
|
||||
/// <param name="parameters">List of parameters to check against</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)
|
||||
{
|
||||
if (index >= parameters.Count)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the full lines from the input file, if possible
|
||||
/// </summary>
|
||||
/// <param name="filename">file location</param>
|
||||
/// <param name="binary">True if should read as binary, false otherwise (default)</param>
|
||||
/// <returns>Full text of the file, null on error</returns>
|
||||
protected static string GetFullFile(string filename, bool binary = false)
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(filename))
|
||||
return null;
|
||||
|
||||
// If we're reading as binary
|
||||
if (binary)
|
||||
{
|
||||
string hex = string.Empty;
|
||||
using (BinaryReader br = new BinaryReader(File.OpenRead(filename)))
|
||||
{
|
||||
while (br.BaseStream.Position < br.BaseStream.Length)
|
||||
{
|
||||
hex += Convert.ToString(br.ReadByte(), 16);
|
||||
}
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
return string.Join("\n", File.ReadAllLines(filename));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a string is a flag (starts with '/')
|
||||
/// </summary>
|
||||
/// <param name="parameter">String value to check</param>
|
||||
/// <returns>True if it's a flag, false otherwise</returns>
|
||||
protected static bool IsFlag(string parameter)
|
||||
{
|
||||
if (parameter.Trim('\"').StartsWith("/"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <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</returns>
|
||||
protected static bool IsValidDriveLetter(string parameter)
|
||||
{
|
||||
if (!Regex.IsMatch(parameter, @"^[A-Z]:?\\?$"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
return bool.TryParse(parameter, out bool _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a string is a valid byte
|
||||
/// </summary>
|
||||
/// <param name="parameter">String value to check</param>
|
||||
/// <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)
|
||||
{
|
||||
if (!sbyte.TryParse(parameter, out sbyte temp))
|
||||
return false;
|
||||
else if (lowerBound != -1 && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != -1 && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a string is a valid Int16
|
||||
/// </summary>
|
||||
/// <param name="parameter">String value to check</param>
|
||||
/// <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)
|
||||
{
|
||||
if (!short.TryParse(parameter, out short temp))
|
||||
return false;
|
||||
else if (lowerBound != -1 && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != -1 && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a string is a valid Int32
|
||||
/// </summary>
|
||||
/// <param name="parameter">String value to check</param>
|
||||
/// <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)
|
||||
{
|
||||
if (!int.TryParse(parameter, out int temp))
|
||||
return false;
|
||||
else if (lowerBound != -1 && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != -1 && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a string is a valid Int64
|
||||
/// </summary>
|
||||
/// <param name="parameter">String value to check</param>
|
||||
/// <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)
|
||||
{
|
||||
if (!long.TryParse(parameter, out long temp))
|
||||
return false;
|
||||
else if (lowerBound != -1 && temp < lowerBound)
|
||||
return false;
|
||||
else if (upperBound != -1 && temp > upperBound)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Common Information Extraction
|
||||
|
||||
/// <summary>
|
||||
/// Get the split values for ISO-based media
|
||||
/// </summary>
|
||||
/// <param name="hashData">String representing the combined hash data</param>
|
||||
/// <returns>True if extraction was successful, false otherwise</returns>
|
||||
protected static bool GetISOHashValues(string hashData, out long size, out string crc32, out string md5, out string sha1)
|
||||
{
|
||||
size = -1; crc32 = null; md5 = null; sha1 = null;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(hashData))
|
||||
return false;
|
||||
|
||||
Regex hashreg = new Regex(@"<rom name="".*?"" size=""(.*?)"" crc=""(.*?)"" md5=""(.*?)"" sha1=""(.*?)""");
|
||||
Match m = hashreg.Match(hashData);
|
||||
if (m.Success)
|
||||
{
|
||||
Int64.TryParse(m.Groups[1].Value, out size);
|
||||
crc32 = m.Groups[2].Value;
|
||||
md5 = m.Groups[3].Value;
|
||||
sha1 = m.Groups[4].Value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the existance of an anti-modchip string from a PlayStation disc, if possible
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <returns>Anti-modchip existance if possible, false on error</returns>
|
||||
protected static bool GetPlayStationAntiModchipDetected(char? driveLetter)
|
||||
{
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
return false;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
string drivePath = driveLetter + ":\\";
|
||||
if (!Directory.Exists(drivePath))
|
||||
return false;
|
||||
|
||||
string enAntiModString = " SOFTWARE TERMINATED\nCONSOLE MAY HAVE BEEN MODIFIED\n CALL 1-888-780-7690";
|
||||
string jpAntiModString = "強制終了しました。\n本体が改造されている\nおそれがあります。";
|
||||
|
||||
// Scan through each file to check for the anti-modchip strings
|
||||
foreach (string path in Directory.EnumerateFiles(drivePath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: This is a memory hog
|
||||
string fileContents = File.ReadAllText(path);
|
||||
if (fileContents.Contains(enAntiModString) || fileContents.Contains(jpAntiModString))
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// No-op, we don't care what the error was
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the EXE date from a PlayStation disc, if possible
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <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></returns>
|
||||
protected static bool GetPlayStationExecutableInfo(char? driveLetter, out string serial, out Region? region, out string date)
|
||||
{
|
||||
serial = null; region = null; date = null;
|
||||
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
return false;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
string drivePath = driveLetter + ":\\";
|
||||
if (!Directory.Exists(drivePath))
|
||||
return false;
|
||||
|
||||
// Get the two paths that we will need to check
|
||||
string psxExePath = Path.Combine(drivePath, "PSX.EXE");
|
||||
string systemCnfPath = Path.Combine(drivePath, "SYSTEM.CNF");
|
||||
|
||||
// Try both of the common paths that contain information
|
||||
string exeName = null;
|
||||
|
||||
// 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.?:\\?(.*)");
|
||||
if (match != null && match.Groups.Count > 1)
|
||||
{
|
||||
exeName = match.Groups[1].Value;
|
||||
exeName = exeName.Split(';')[0];
|
||||
serial = exeName.Replace('_', '-').Replace(".", string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
// If the SYSTEM.CNF value can't be found, try PSX.EXE
|
||||
if (string.IsNullOrWhiteSpace(exeName) && File.Exists(psxExePath))
|
||||
exeName = "PSX.EXE";
|
||||
|
||||
// If neither can be found, we return false
|
||||
if (string.IsNullOrWhiteSpace(exeName))
|
||||
return false;
|
||||
|
||||
// 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(drivePath, exeName);
|
||||
if (!File.Exists(exePath))
|
||||
return false;
|
||||
|
||||
// Fix the Y2K timestamp issue
|
||||
FileInfo fi = new FileInfo(exePath);
|
||||
DateTime 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>
|
||||
/// Get the version from a PlayStation 2 disc, if possible
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <returns>Game version if possible, null on error</returns>
|
||||
protected static string GetPlayStation2Version(char? driveLetter)
|
||||
{
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
string drivePath = driveLetter + ":\\";
|
||||
if (!Directory.Exists(drivePath))
|
||||
return null;
|
||||
|
||||
// Get the SYSTEM.CNF path to check
|
||||
string systemCnfPath = Path.Combine(drivePath, "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 version from a PlayStation 4 disc, if possible
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <returns>Game version if possible, null on error</returns>
|
||||
protected static string GetPlayStation4Version(char? driveLetter)
|
||||
{
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't do this part
|
||||
string drivePath = driveLetter + ":\\";
|
||||
if (!Directory.Exists(drivePath))
|
||||
return null;
|
||||
|
||||
// If we can't find param.sfo, we don't have a PlayStation 4 disc
|
||||
string paramSfoPath = Path.Combine(drivePath, "bd", "param.sfo");
|
||||
if (!File.Exists(paramSfoPath))
|
||||
return null;
|
||||
|
||||
// Let's try reading param.sfo to find the version at the end of the file
|
||||
try
|
||||
{
|
||||
using (BinaryReader 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;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Category Extraction
|
||||
|
||||
/// <summary>
|
||||
/// Determine the category based on the UMDImageCreator string
|
||||
/// </summary>
|
||||
/// <param name="region">String representing the category</param>
|
||||
/// <returns>Category, if possible</returns>
|
||||
protected static DiscCategory? GetUMDCategory(string category)
|
||||
{
|
||||
switch (category)
|
||||
{
|
||||
case "GAME":
|
||||
return DiscCategory.Games;
|
||||
case "VIDEO":
|
||||
return DiscCategory.Video;
|
||||
case "AUDIO":
|
||||
return DiscCategory.Audio;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Region Extraction
|
||||
|
||||
/// <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>
|
||||
protected static Region? GetPlayStationRegion(string serial)
|
||||
{
|
||||
// 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 'J':
|
||||
return Region.JapanKorea;
|
||||
case 'K':
|
||||
return Region.Korea;
|
||||
case 'P':
|
||||
return Region.Japan;
|
||||
case 'U':
|
||||
return Region.USA;
|
||||
}
|
||||
}
|
||||
|
||||
// Japan-only special serial
|
||||
else if (serial.StartsWith("PAPX"))
|
||||
return Region.Japan;
|
||||
|
||||
// Region appears entirely random
|
||||
else if (serial.StartsWith("PABX"))
|
||||
return null;
|
||||
|
||||
// Japan-only special serial
|
||||
else if (serial.StartsWith("PCBX"))
|
||||
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;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the region based on the XGD serial character
|
||||
/// </summary>
|
||||
/// <param name="region">Character denoting the region</param>
|
||||
/// <returns>Region, if possible</returns>
|
||||
protected static Region? GetXgdRegion(char region)
|
||||
{
|
||||
switch (region)
|
||||
{
|
||||
case 'W':
|
||||
return Region.World;
|
||||
case 'A':
|
||||
return Region.USA;
|
||||
case 'J':
|
||||
return Region.JapanAsia;
|
||||
case 'E':
|
||||
return Region.Europe;
|
||||
case 'K':
|
||||
return Region.USAJapan;
|
||||
case 'L':
|
||||
return Region.USAEurope;
|
||||
case 'H':
|
||||
return Region.JapanEurope;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,492 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace DICUI.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Drive type for dumping
|
||||
/// </summary>
|
||||
public enum InternalDriveType
|
||||
{
|
||||
Optical,
|
||||
Floppy,
|
||||
HardDisk,
|
||||
Removable,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Program that is being used to dump media
|
||||
/// </summary>
|
||||
public enum InternalProgram
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
// Dumping support
|
||||
Aaru,
|
||||
DD,
|
||||
DiscImageCreator,
|
||||
|
||||
// Verification support only
|
||||
CleanRip,
|
||||
DCDumper,
|
||||
UmdImageCreator,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Known systems
|
||||
/// </summary>
|
||||
public enum KnownSystem
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
#region Disc-Based Consoles
|
||||
|
||||
AtariJaguarCD,
|
||||
BandaiPlaydiaQuickInteractiveSystem,
|
||||
BandaiApplePippin,
|
||||
CommodoreAmigaCD32,
|
||||
CommodoreAmigaCDTV,
|
||||
EnvizionsEVOSmartConsole,
|
||||
FujitsuFMTownsMarty,
|
||||
HasbroVideoNow,
|
||||
HasbroVideoNowColor,
|
||||
HasbroVideoNowJr,
|
||||
HasbroVideoNowXP,
|
||||
MattelFisherPriceiXL,
|
||||
MattelHyperscan,
|
||||
MicrosoftXBOX,
|
||||
MicrosoftXBOX360,
|
||||
MicrosoftXBOXOne,
|
||||
NECPCEngineTurboGrafxCD,
|
||||
NECPCFX,
|
||||
NintendoGameCube,
|
||||
NintendoSonySuperNESCDROMSystem,
|
||||
NintendoWii,
|
||||
NintendoWiiU,
|
||||
Panasonic3DOInteractiveMultiplayer, // The 3DO Company 3DO Interactive Multiplayer
|
||||
PhilipsCDi,
|
||||
PioneerLaserActive,
|
||||
SegaCDMegaCD,
|
||||
SegaDreamcast,
|
||||
SegaSaturn,
|
||||
SNKNeoGeoCD,
|
||||
SonyPlayStation,
|
||||
SonyPlayStation2,
|
||||
SonyPlayStation3,
|
||||
SonyPlayStation4,
|
||||
SonyPlayStationPortable,
|
||||
TandyMemorexVisualInformationSystem,
|
||||
VMLabsNuon,
|
||||
VTechVFlashVSmilePro,
|
||||
ZAPiTGamesGameWaveFamilyEntertainmentSystem,
|
||||
|
||||
MarkerDiscBasedConsoleEnd,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cartridge-Based and Other Consoles
|
||||
|
||||
/*
|
||||
AmstradGX4000,
|
||||
APFMicrocomputerSystem,
|
||||
Atari2600VCS,
|
||||
Atari5200,
|
||||
Atari7800,
|
||||
AtariJaguar,
|
||||
AtariXEVideoGameSystem,
|
||||
Audiosonic1292AdvancedProgrammableVideoSystem,
|
||||
BallyAstrocade,
|
||||
BitCorporationDina,
|
||||
CasioLoopy,
|
||||
CasioPV1000,
|
||||
Commodore64GamesSystem,
|
||||
DaewooElectronicsZemmix,
|
||||
EmersonArcadia2001,
|
||||
EpochCassetteVision,
|
||||
EpochSuperCassetteVision,
|
||||
FairchildChannelF,
|
||||
FuntechSuperACan,
|
||||
GeneralConsumerElectricVectrex,
|
||||
HeberBBCBridgeCompanion,
|
||||
IntertonVC4000,
|
||||
JungleTacVii,
|
||||
LeapFrogClickStart,
|
||||
LJNVideoArt,
|
||||
MagnavoxOdyssey2,
|
||||
MattelIntellivision,
|
||||
NECPCEngineTurboGrafx16,
|
||||
NichibutsuMyVision,
|
||||
Nintendo64,
|
||||
Nintendo64DD,
|
||||
NintendoFamilyComputerNintendoEntertainmentSystem,
|
||||
NintendoFamilyComputerDiskSystem,
|
||||
NintendoSuperFamicomSuperNintendoEntertainmentSystem,
|
||||
NintendoSwitch,
|
||||
PhilipsVideopacPlusG7400,
|
||||
RCAStudioII,
|
||||
Sega32X,
|
||||
SegaMarkIIIMasterSystem,
|
||||
SegaMegaDriveGenesis,
|
||||
SegaSG1000,
|
||||
SNKNeoGeo,
|
||||
SSDCOMPANYLIMITEDXaviXPORT,
|
||||
ViewMasterInteractiveVision,
|
||||
VTechCreatiVision,
|
||||
VTechVSmile,
|
||||
VTechSocrates,
|
||||
WorldsOfWonderActionMax,
|
||||
|
||||
MarkerOtherConsoleEnd,
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Computers
|
||||
|
||||
AcornArchimedes,
|
||||
AppleMacintosh,
|
||||
CommodoreAmiga,
|
||||
FujitsuFMTowns,
|
||||
IBMPCCompatible,
|
||||
NECPC88,
|
||||
NECPC98,
|
||||
SharpX68000,
|
||||
|
||||
MarkerComputerEnd,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Arcade
|
||||
|
||||
AmigaCUBOCD32,
|
||||
AmericanLaserGames3DO,
|
||||
Atari3DO,
|
||||
Atronic,
|
||||
AUSCOMSystem1,
|
||||
BallyGameMagic,
|
||||
CapcomCPSystemIII,
|
||||
funworldPhotoPlay,
|
||||
GlobalVRVarious,
|
||||
GlobalVRVortek,
|
||||
GlobalVRVortekV3,
|
||||
ICEPCHardware,
|
||||
IncredibleTechnologiesEagle,
|
||||
IncredibleTechnologiesVarious,
|
||||
KonamieAmusement,
|
||||
KonamiFirebeat,
|
||||
KonamiGVSystem,
|
||||
KonamiM2,
|
||||
KonamiPython,
|
||||
KonamiPython2,
|
||||
KonamiSystem573,
|
||||
KonamiTwinkle,
|
||||
KonamiVarious,
|
||||
MeritIndustriesBoardwalk,
|
||||
MeritIndustriesMegaTouchForce,
|
||||
MeritIndustriesMegaTouchION,
|
||||
MeritIndustriesMegaTouchMaxx,
|
||||
MeritIndustriesMegaTouchXL,
|
||||
NamcoCapcomSystem256,
|
||||
NamcoCapcomTaitoSystem246,
|
||||
NamcoSegaNintendoTriforce,
|
||||
NamcoSystem12,
|
||||
NamcoSystem357,
|
||||
NewJatreCDi,
|
||||
NichibutsuHighRateSystem,
|
||||
NichibutsuSuperCD,
|
||||
NichibutsuXRateSystem,
|
||||
PanasonicM2,
|
||||
PhotoPlayVarious,
|
||||
RawThrillsVarious,
|
||||
SegaChihiro,
|
||||
SegaEuropaR,
|
||||
SegaLindbergh,
|
||||
SegaNaomi,
|
||||
SegaNaomi2,
|
||||
SegaNu,
|
||||
SegaRingEdge,
|
||||
SegaRingEdge2,
|
||||
SegaRingWide,
|
||||
SegaTitanVideo,
|
||||
SegaSystem32,
|
||||
SeibuCATSSystem,
|
||||
TABAustriaQuizard,
|
||||
TsunamiTsuMoMultiGameMotionSystem,
|
||||
|
||||
MarkerArcadeEnd,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
|
||||
AudioCD,
|
||||
BDVideo,
|
||||
DVDAudio,
|
||||
DVDVideo,
|
||||
EnhancedCD,
|
||||
HDDVDVideo,
|
||||
NavisoftNaviken21,
|
||||
PalmOS,
|
||||
PhilipsCDiDigitalVideo,
|
||||
PhotoCD,
|
||||
PlayStationGameSharkUpdates,
|
||||
RainbowDisc,
|
||||
SegaPrologue21,
|
||||
SuperAudioCD,
|
||||
TaoiKTV,
|
||||
TomyKissSite,
|
||||
VideoCD,
|
||||
|
||||
MarkerOtherEnd,
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Known system category
|
||||
/// </summary>
|
||||
public enum KnownSystemCategory
|
||||
{
|
||||
DiscBasedConsole = 0,
|
||||
OtherConsole,
|
||||
Computer,
|
||||
Arcade,
|
||||
Other,
|
||||
Custom
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Known media types
|
||||
/// </summary>
|
||||
public enum MediaType
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
#region Punched Media
|
||||
|
||||
ApertureCard,
|
||||
JacquardLoomCard,
|
||||
MagneticStripeCard,
|
||||
OpticalPhonecard,
|
||||
PunchedCard,
|
||||
PunchedTape,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tape
|
||||
|
||||
Cassette,
|
||||
DataCartridge,
|
||||
OpenReel,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Disc / Disc
|
||||
|
||||
BluRay,
|
||||
CDROM,
|
||||
DVD,
|
||||
FloppyDisk,
|
||||
Floptical,
|
||||
GDROM,
|
||||
HDDVD,
|
||||
HardDisk,
|
||||
IomegaBernoulliDisk,
|
||||
IomegaJaz,
|
||||
IomegaZip,
|
||||
LaserDisc, // LD-ROM and LV-ROM variants
|
||||
Nintendo64DD,
|
||||
NintendoFamicomDiskSystem,
|
||||
NintendoGameCubeGameDisc,
|
||||
NintendoWiiOpticalDisc,
|
||||
NintendoWiiUOpticalDisc,
|
||||
UMD,
|
||||
|
||||
#endregion
|
||||
|
||||
// Unsorted Formats
|
||||
Cartridge,
|
||||
CED,
|
||||
CompactFlash,
|
||||
MMC,
|
||||
SDCard,
|
||||
FlashDrive,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Physical media types
|
||||
/// </summary>
|
||||
/// <see cref="https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cimwin32a/win32-physicalmedia"/>
|
||||
public enum PhysicalMediaType : ushort
|
||||
{
|
||||
Unknown = 0,
|
||||
Other = 1,
|
||||
TapeCartridge = 2,
|
||||
QICCartridge = 3,
|
||||
AITCartridge = 4,
|
||||
DTFCartridge = 5,
|
||||
DATCartridge = 6,
|
||||
EightMillimeterTapeCartridge = 7,
|
||||
NineteenMillimeterTapeCartridge = 8,
|
||||
DLTCartridge = 9,
|
||||
HalfInchMagneticTapeCartridge = 10,
|
||||
CartridgeDisk = 11,
|
||||
JAZDisk = 12,
|
||||
ZIPDisk = 13,
|
||||
SyQuestDisk = 14,
|
||||
WinchesterRemovableDisk = 15,
|
||||
CDROM = 16,
|
||||
CDROMXA = 17,
|
||||
CDI = 18,
|
||||
CDRecordable = 19,
|
||||
WORM = 20,
|
||||
MagnetoOptical = 21,
|
||||
DVD = 22,
|
||||
DVDPlusRW = 23,
|
||||
DVDRAM = 24,
|
||||
DVDROM = 25,
|
||||
DVDVideo = 26,
|
||||
Divx = 27,
|
||||
FloppyDiskette = 28,
|
||||
HardDisk = 29,
|
||||
MemoryCard = 30,
|
||||
HardCopy = 31,
|
||||
ClikDisk = 32,
|
||||
CDRW = 33,
|
||||
CDDA = 34,
|
||||
CDPlus = 35,
|
||||
DVDRecordable = 36,
|
||||
DVDMinusRW = 37,
|
||||
DVDAudio = 38,
|
||||
DVD5 = 39,
|
||||
DVD9 = 40,
|
||||
DVD10 = 41,
|
||||
DVD18 = 42,
|
||||
MagnetoOpticalRewriteable = 43,
|
||||
MagnetoOpticalWriteOnce = 44,
|
||||
MagnetoOpticalRewriteableLIMDOW = 45,
|
||||
PhaseChangeWriteOnce = 46,
|
||||
PhaseChangeRewriteable = 47,
|
||||
PhaseChangeDualRewriteable = 48,
|
||||
AblativeWriteOnce = 49,
|
||||
NearFieldRecording = 50,
|
||||
MiniQic = 51,
|
||||
Travan = 52,
|
||||
EightMillimeterMetalParticle = 53,
|
||||
EightMillimeterAdvancedMetalEvaporate = 54,
|
||||
NCTP = 55,
|
||||
LTOUltrium = 56,
|
||||
LTOAccelis = 57,
|
||||
NineTrackTape = 58,
|
||||
EighteenTrackTape = 59,
|
||||
ThirtySixTrackTape = 60,
|
||||
Magstar3590 = 61,
|
||||
MagstarMP = 62,
|
||||
D2Tape = 63,
|
||||
TapeDSTSmall = 64,
|
||||
TapeDSTMedium = 65,
|
||||
TapeDSTLarge = 66,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic yes/no values for Redump
|
||||
/// </summary>
|
||||
public enum YesNo
|
||||
{
|
||||
NULL = 0,
|
||||
No = 1,
|
||||
Yes = 2,
|
||||
}
|
||||
|
||||
#region Win32_CDROMDrive
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-cdromdrive
|
||||
|
||||
/// <summary>
|
||||
/// Availability and status of the device
|
||||
/// </summary>
|
||||
public enum Availability : ushort
|
||||
{
|
||||
Other = 1,
|
||||
Unknown = 2,
|
||||
RunningFullPower = 3,
|
||||
Warning = 4,
|
||||
InTest = 5,
|
||||
NotApplicable = 6,
|
||||
PowerOff = 7,
|
||||
OffLine = 8,
|
||||
OffDuty = 9,
|
||||
Degraded = 10,
|
||||
NotInstalled = 11,
|
||||
InstallError = 12,
|
||||
PowerSaveUnknown = 13,
|
||||
PowerSaveLowPowerMode = 14,
|
||||
PowerSaveStandby = 15,
|
||||
PowerCycle = 16,
|
||||
PowerSaveWarning = 17,
|
||||
Paused = 18,
|
||||
NotReady = 19,
|
||||
NotConfigured = 20,
|
||||
Quiesced = 21,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optical drive capabilities
|
||||
/// </summary>
|
||||
public enum Capabilities : ushort
|
||||
{
|
||||
Unknown = 0,
|
||||
Other = 1,
|
||||
SequentialAccess = 2,
|
||||
RandomAccess = 3,
|
||||
SupportsWriting = 4,
|
||||
Encryption = 5,
|
||||
Compression = 6,
|
||||
SupportsRemoveableMedia = 7,
|
||||
ManualCleaning = 8,
|
||||
AutomaticCleaning = 9,
|
||||
SMARTNotification = 10,
|
||||
SupportsDualSidedMedia = 11,
|
||||
PredismountEjectNotRequired = 12,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// File system flags
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum FileSystemFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
CaseSensitiveSearch = 1,
|
||||
CasePreservedNames = 2,
|
||||
UnicodeOnDisk = 4,
|
||||
PersistentACLs = 8,
|
||||
FileCompression = 16,
|
||||
VolumeQuotas = 32,
|
||||
SupportsSparseFiles = 64,
|
||||
SupportsReparsePoints = 128,
|
||||
SupportsRemoteStorage = 256,
|
||||
SupportsLongNames = 16384,
|
||||
VolumeIsCompressed = 32768,
|
||||
ReadOnlyVolume = 524289, // TODO: Invesitgate, as this value seems wrong
|
||||
SupportsObjectIDS = 65536,
|
||||
SupportsEncryption = 131072,
|
||||
SupportsNamedStreams = 262144,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specific power-related capabilities of a logical device
|
||||
/// </summary>
|
||||
public enum PowerManagementCapabilities : ushort
|
||||
{
|
||||
Unknown = 0,
|
||||
NotSupported = 1,
|
||||
Disabled = 2,
|
||||
Enabled = 3,
|
||||
PowerSavingModesEnteredAutomatically = 4,
|
||||
PowerStateSettable = 5,
|
||||
PowerCyclingSupported = 6,
|
||||
TimedPowerOnSupported = 7,
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,286 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DICUI.Data
|
||||
{
|
||||
public class Options : IDictionary<string, string>
|
||||
{
|
||||
private Dictionary<string, string> _settings;
|
||||
|
||||
#region Internal Program
|
||||
|
||||
public string AaruPath
|
||||
{
|
||||
get { return GetStringSetting(_settings, "AaruPath", "Programs\\Aaru\\Aaru.exe"); }
|
||||
set { _settings["AaruPath"] = value; }
|
||||
}
|
||||
|
||||
public string CreatorPath
|
||||
{
|
||||
get { return GetStringSetting(_settings, "CreatorPath", "Programs\\Creator\\DiscImageCreator.exe"); }
|
||||
set { _settings["CreatorPath"] = value; }
|
||||
}
|
||||
|
||||
public string DDPath
|
||||
{
|
||||
get { return GetStringSetting(_settings, "DDPath", "Programs\\DD\\dd.exe"); }
|
||||
set { _settings["DDPath"] = value; }
|
||||
}
|
||||
|
||||
public string InternalProgram
|
||||
{
|
||||
get { return GetStringSetting(_settings, "InternalProgram", Data.InternalProgram.DiscImageCreator.ToString()); }
|
||||
set { _settings["InternalProgram"] = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extra Paths
|
||||
|
||||
public string DefaultOutputPath
|
||||
{
|
||||
get { return GetStringSetting(_settings, "DefaultOutputPath", "ISO"); }
|
||||
set { _settings["DefaultOutputPath"] = value; }
|
||||
}
|
||||
|
||||
public string SubDumpPath
|
||||
{
|
||||
get { return GetStringSetting(_settings, "SubDumpPath", "Programs\\Subdump\\subdump.exe"); }
|
||||
set { _settings["SubDumpPath"] = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dumping Speeds
|
||||
|
||||
public int PreferredDumpSpeedCD
|
||||
{
|
||||
get { return GetInt32Setting(_settings, "PreferredDumpSpeedCD", 72); }
|
||||
set { _settings["PreferredDumpSpeedCD"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public int PreferredDumpSpeedDVD
|
||||
{
|
||||
get { return GetInt32Setting(_settings, "PreferredDumpSpeedDVD", 24); }
|
||||
set { _settings["PreferredDumpSpeedDVD"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public int PreferredDumpSpeedBD
|
||||
{
|
||||
get { return GetInt32Setting(_settings, "PreferredDumpSpeedBD", 16); }
|
||||
set { _settings["PreferredDumpSpeedBD"] = value.ToString(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extra Dumping Options
|
||||
|
||||
public bool QuietMode
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "QuietMode", false); }
|
||||
set { _settings["QuietMode"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public bool ParanoidMode
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "ParanoidMode", false); }
|
||||
set { _settings["ParanoidMode"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public bool ScanForProtection
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "ScanForProtection", true); }
|
||||
set { _settings["ScanForProtection"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public int RereadAmountForC2
|
||||
{
|
||||
get { return GetInt32Setting(_settings, "RereadAmountForC2", 20); }
|
||||
set { _settings["RereadAmountForC2"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public bool AddPlaceholders
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "AddPlaceholders", true); }
|
||||
set { _settings["AddPlaceholders"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public bool PromptForDiscInformation
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "PromptForDiscInformation", true); }
|
||||
set { _settings["PromptForDiscInformation"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public bool IgnoreFixedDrives
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "IgnoreFixedDrives", false); }
|
||||
set { _settings["IgnoreFixedDrives"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public bool ResetDriveAfterDump
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "ResetDriveAfterDump", false); }
|
||||
set { _settings["ResetDriveAfterDump"] = value.ToString(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Skip Options
|
||||
|
||||
public bool SkipMediaTypeDetection
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "SkipMediaTypeDetection", false); }
|
||||
set { _settings["SkipMediaTypeDetection"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public bool SkipSystemDetection
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "SkipSystemDetection", false); }
|
||||
set { _settings["SkipSystemDetection"] = value.ToString(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Logging Options
|
||||
|
||||
public bool VerboseLogging
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "VerboseLogging", true); }
|
||||
set { _settings["VerboseLogging"] = value.ToString(); }
|
||||
}
|
||||
|
||||
public bool OpenLogWindowAtStartup
|
||||
{
|
||||
get { return GetBooleanSetting(_settings, "OpenLogWindowAtStartup", true); }
|
||||
set { _settings["OpenLogWindowAtStartup"] = value.ToString(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Redump Login Information
|
||||
|
||||
public string Username
|
||||
{
|
||||
get { return GetStringSetting(_settings, "Username", ""); }
|
||||
set { _settings["Username"] = value; }
|
||||
}
|
||||
|
||||
// TODO: Figure out a way to keep this encrypted in some way, BASE64 to start?
|
||||
public string Password
|
||||
{
|
||||
get { return GetStringSetting(_settings, "Password", ""); }
|
||||
set { _settings["Password"] = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Constructor taking a dictionary for settings
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
public Options(Dictionary<string, string> settings = null)
|
||||
{
|
||||
this._settings = settings ?? new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
/// <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>
|
||||
private bool GetBooleanSetting(Dictionary<string, string> settings, string key, bool defaultValue)
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
{
|
||||
if (Boolean.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>
|
||||
private int GetInt32Setting(Dictionary<string, string> settings, string key, int defaultValue)
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
{
|
||||
if (Int32.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>
|
||||
private string GetStringSetting(Dictionary<string, string> settings, string key, string defaultValue)
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
return settings[key];
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
#region IDictionary implementations
|
||||
|
||||
public ICollection<string> Keys => _settings.Keys;
|
||||
|
||||
public ICollection<string> Values => _settings.Values;
|
||||
|
||||
public int Count => _settings.Count;
|
||||
|
||||
public bool IsReadOnly => ((IDictionary<string, string>)_settings).IsReadOnly;
|
||||
|
||||
public string this[string key]
|
||||
{
|
||||
get { return (_settings.ContainsKey(key) ? _settings[key] : null); }
|
||||
set { _settings[key] = value; }
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key) => _settings.ContainsKey(key);
|
||||
|
||||
public void Add(string key, string value) => _settings.Add(key, value);
|
||||
|
||||
public bool Remove(string key) => _settings.Remove(key);
|
||||
|
||||
public bool TryGetValue(string key, out string value) => _settings.TryGetValue(key, out value);
|
||||
|
||||
public void Add(KeyValuePair<string, string> item) => _settings.Add(item.Key, item.Value);
|
||||
|
||||
public void Clear() => _settings.Clear();
|
||||
|
||||
public bool Contains(KeyValuePair<string, string> item) => ((IDictionary<string, string>)_settings).Contains(item);
|
||||
|
||||
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex) => ((IDictionary<string, string>)_settings).CopyTo(array, arrayIndex);
|
||||
|
||||
public bool Remove(KeyValuePair<string, string> item) => ((IDictionary<string, string>)_settings).Remove(item);
|
||||
|
||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator() => _settings.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => _settings.GetEnumerator();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,333 +0,0 @@
|
||||
using DICUI.Data;
|
||||
|
||||
namespace DICUI.DiscImageCreator
|
||||
{
|
||||
public static class Converters
|
||||
{
|
||||
#region Cross-enumeration conversions
|
||||
|
||||
/// <summary>
|
||||
/// Get the most common known system for a given MediaType
|
||||
/// </summary>
|
||||
/// <param name="baseCommand">Command value to check</param>
|
||||
/// <returns>KnownSystem if possible, null on error</returns>
|
||||
public static KnownSystem? ToKnownSystem(Command baseCommand)
|
||||
{
|
||||
switch (baseCommand)
|
||||
{
|
||||
case Command.Audio:
|
||||
return KnownSystem.AudioCD;
|
||||
case Command.CompactDisc:
|
||||
case Command.Data:
|
||||
case Command.DigitalVideoDisc:
|
||||
case Command.Disk:
|
||||
case Command.Floppy:
|
||||
case Command.Tape:
|
||||
return KnownSystem.IBMPCCompatible;
|
||||
case Command.GDROM:
|
||||
case Command.Swap:
|
||||
return KnownSystem.SegaDreamcast;
|
||||
case Command.BluRay:
|
||||
return KnownSystem.SonyPlayStation3;
|
||||
case Command.SACD:
|
||||
return KnownSystem.SuperAudioCD;
|
||||
case Command.XBOX:
|
||||
case Command.XBOXSwap:
|
||||
return KnownSystem.MicrosoftXBOX;
|
||||
case Command.XGD2Swap:
|
||||
case Command.XGD3Swap:
|
||||
return KnownSystem.MicrosoftXBOX360;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the MediaType associated with a given base command
|
||||
/// </summary>
|
||||
/// <param name="baseCommand">Command value to check</param>
|
||||
/// <returns>MediaType if possible, null on error</returns>
|
||||
/// <remarks>This takes the "safe" route by assuming the larger of any given format</remarks>
|
||||
public static MediaType? ToMediaType(Command baseCommand)
|
||||
{
|
||||
switch (baseCommand)
|
||||
{
|
||||
case Command.Audio:
|
||||
case Command.CompactDisc:
|
||||
case Command.Data:
|
||||
case Command.SACD:
|
||||
return MediaType.CDROM;
|
||||
case Command.GDROM:
|
||||
case Command.Swap:
|
||||
return MediaType.GDROM;
|
||||
case Command.DigitalVideoDisc:
|
||||
case Command.XBOX:
|
||||
case Command.XBOXSwap:
|
||||
case Command.XGD2Swap:
|
||||
case Command.XGD3Swap:
|
||||
return MediaType.DVD;
|
||||
case Command.BluRay:
|
||||
return MediaType.BluRay;
|
||||
|
||||
// Non-optical
|
||||
case Command.Floppy:
|
||||
return MediaType.FloppyDisk;
|
||||
case Command.Disk:
|
||||
return MediaType.HardDisk;
|
||||
case Command.Tape:
|
||||
return MediaType.DataCartridge;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default extension for a given disc type
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType value to check</param>
|
||||
/// <returns>Valid extension (with leading '.'), null on error</returns>
|
||||
public static string Extension(MediaType? type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.GDROM:
|
||||
case MediaType.Cartridge:
|
||||
case MediaType.HardDisk:
|
||||
case MediaType.CompactFlash:
|
||||
case MediaType.MMC:
|
||||
case MediaType.SDCard:
|
||||
case MediaType.FlashDrive:
|
||||
return ".bin";
|
||||
case MediaType.DVD:
|
||||
case MediaType.HDDVD:
|
||||
case MediaType.BluRay:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
return ".iso";
|
||||
case MediaType.LaserDisc:
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
return ".raw";
|
||||
case MediaType.NintendoWiiUOpticalDisc:
|
||||
return ".wud";
|
||||
case MediaType.FloppyDisk:
|
||||
return ".img";
|
||||
case MediaType.Cassette:
|
||||
return ".wav";
|
||||
case MediaType.NONE:
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Convert to Long Name
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the Command enum values
|
||||
/// </summary>
|
||||
/// <param name="command">Command value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(Command command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case Command.Audio:
|
||||
return CommandStrings.Audio;
|
||||
case Command.BluRay:
|
||||
return CommandStrings.BluRay;
|
||||
case Command.Close:
|
||||
return CommandStrings.Close;
|
||||
case Command.CompactDisc:
|
||||
return CommandStrings.CompactDisc;
|
||||
case Command.Data:
|
||||
return CommandStrings.Data;
|
||||
case Command.DigitalVideoDisc:
|
||||
return CommandStrings.DigitalVideoDisc;
|
||||
case Command.Disk:
|
||||
return CommandStrings.Disk;
|
||||
case Command.DriveSpeed:
|
||||
return CommandStrings.DriveSpeed;
|
||||
case Command.Eject:
|
||||
return CommandStrings.Eject;
|
||||
case Command.Floppy:
|
||||
return CommandStrings.Floppy;
|
||||
case Command.GDROM:
|
||||
return CommandStrings.GDROM;
|
||||
case Command.MDS:
|
||||
return CommandStrings.MDS;
|
||||
case Command.Merge:
|
||||
return CommandStrings.Merge;
|
||||
case Command.Reset:
|
||||
return CommandStrings.Reset;
|
||||
case Command.SACD:
|
||||
return CommandStrings.SACD;
|
||||
case Command.Start:
|
||||
return CommandStrings.Start;
|
||||
case Command.Stop:
|
||||
return CommandStrings.Stop;
|
||||
case Command.Sub:
|
||||
return CommandStrings.Sub;
|
||||
case Command.Swap:
|
||||
return CommandStrings.Swap;
|
||||
case Command.Tape:
|
||||
return CommandStrings.Tape;
|
||||
case Command.XBOX:
|
||||
return CommandStrings.XBOX;
|
||||
case Command.XBOXSwap:
|
||||
return CommandStrings.XBOXSwap;
|
||||
case Command.XGD2Swap:
|
||||
return CommandStrings.XGD2Swap;
|
||||
case Command.XGD3Swap:
|
||||
return CommandStrings.XGD3Swap;
|
||||
|
||||
case Command.NONE:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of the Flag enum values
|
||||
/// </summary>
|
||||
/// <param name="command">Flag value to convert</param>
|
||||
/// <returns>String representing the value, if possible</returns>
|
||||
public static string LongName(Flag flag)
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
case Flag.AddOffset:
|
||||
return FlagStrings.AddOffset;
|
||||
case Flag.AMSF:
|
||||
return FlagStrings.AMSF;
|
||||
case Flag.AtariJaguar:
|
||||
return FlagStrings.AtariJaguar;
|
||||
case Flag.BEOpcode:
|
||||
return FlagStrings.BEOpcode;
|
||||
case Flag.C2Opcode:
|
||||
return FlagStrings.C2Opcode;
|
||||
case Flag.CopyrightManagementInformation:
|
||||
return FlagStrings.CopyrightManagementInformation;
|
||||
case Flag.D8Opcode:
|
||||
return FlagStrings.D8Opcode;
|
||||
case Flag.DisableBeep:
|
||||
return FlagStrings.DisableBeep;
|
||||
case Flag.ExtractMicroSoftCabFile:
|
||||
return FlagStrings.ExtractMicroSoftCabFile;
|
||||
case Flag.ForceUnitAccess:
|
||||
return FlagStrings.ForceUnitAccess;
|
||||
case Flag.MultiSession:
|
||||
return FlagStrings.MultiSession;
|
||||
case Flag.NoFixSubP:
|
||||
return FlagStrings.NoFixSubP;
|
||||
case Flag.NoFixSubQ:
|
||||
return FlagStrings.NoFixSubQ;
|
||||
case Flag.NoFixSubQLibCrypt:
|
||||
return FlagStrings.NoFixSubQLibCrypt;
|
||||
case Flag.NoFixSubRtoW:
|
||||
return FlagStrings.NoFixSubRtoW;
|
||||
case Flag.NoFixSubQSecuROM:
|
||||
return FlagStrings.NoFixSubQSecuROM;
|
||||
case Flag.NoSkipSS:
|
||||
return FlagStrings.NoSkipSS;
|
||||
case Flag.Raw:
|
||||
return FlagStrings.Raw;
|
||||
case Flag.Reverse:
|
||||
return FlagStrings.Reverse;
|
||||
case Flag.ScanAntiMod:
|
||||
return FlagStrings.ScanAntiMod;
|
||||
case Flag.ScanFileProtect:
|
||||
return FlagStrings.ScanFileProtect;
|
||||
case Flag.ScanSectorProtect:
|
||||
return FlagStrings.ScanSectorProtect;
|
||||
case Flag.SeventyFour:
|
||||
return FlagStrings.SeventyFour;
|
||||
case Flag.SkipSector:
|
||||
return FlagStrings.SkipSector;
|
||||
case Flag.SubchannelReadLevel:
|
||||
return FlagStrings.SubchannelReadLevel;
|
||||
case Flag.UseAnchorVolumeDescriptorPointer:
|
||||
return FlagStrings.UseAnchorVolumeDescriptorPointer;
|
||||
case Flag.VideoNow:
|
||||
return FlagStrings.VideoNow;
|
||||
case Flag.VideoNowColor:
|
||||
return FlagStrings.VideoNowColor;
|
||||
case Flag.VideoNowXP:
|
||||
return FlagStrings.VideoNowXP;
|
||||
|
||||
case Flag.NONE:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Convert From String
|
||||
|
||||
/// <summary>
|
||||
/// Get the Command enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="command">String value to convert</param>
|
||||
/// <returns>Command represented by the string(s), if possible</returns>
|
||||
public static Command StringToCommand(string command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case CommandStrings.Audio:
|
||||
return Command.Audio;
|
||||
case CommandStrings.BluRay:
|
||||
return Command.BluRay;
|
||||
case CommandStrings.Close:
|
||||
return Command.Close;
|
||||
case CommandStrings.CompactDisc:
|
||||
return Command.CompactDisc;
|
||||
case CommandStrings.Data:
|
||||
return Command.Data;
|
||||
case CommandStrings.DigitalVideoDisc:
|
||||
return Command.DigitalVideoDisc;
|
||||
case CommandStrings.Disk:
|
||||
return Command.Disk;
|
||||
case CommandStrings.DriveSpeed:
|
||||
return Command.DriveSpeed;
|
||||
case CommandStrings.Eject:
|
||||
return Command.Eject;
|
||||
case CommandStrings.Floppy:
|
||||
return Command.Floppy;
|
||||
case CommandStrings.GDROM:
|
||||
return Command.GDROM;
|
||||
case CommandStrings.MDS:
|
||||
return Command.MDS;
|
||||
case CommandStrings.Merge:
|
||||
return Command.Merge;
|
||||
case CommandStrings.Reset:
|
||||
return Command.Reset;
|
||||
case CommandStrings.SACD:
|
||||
return Command.SACD;
|
||||
case CommandStrings.Start:
|
||||
return Command.Start;
|
||||
case CommandStrings.Stop:
|
||||
return Command.Stop;
|
||||
case CommandStrings.Sub:
|
||||
return Command.Sub;
|
||||
case CommandStrings.Swap:
|
||||
return Command.Swap;
|
||||
case CommandStrings.Tape:
|
||||
return Command.Tape;
|
||||
case CommandStrings.XBOX:
|
||||
return Command.XBOX;
|
||||
case CommandStrings.XBOXSwap:
|
||||
return Command.XBOXSwap;
|
||||
case CommandStrings.XGD2Swap:
|
||||
return Command.XGD2Swap;
|
||||
case CommandStrings.XGD3Swap:
|
||||
return Command.XGD3Swap;
|
||||
|
||||
default:
|
||||
return Command.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
namespace DICUI.DiscImageCreator
|
||||
{
|
||||
/// <summary>
|
||||
/// Supported DiscImageCreator commands
|
||||
/// </summary>
|
||||
public enum Command : int
|
||||
{
|
||||
NONE = 0,
|
||||
Audio,
|
||||
BluRay,
|
||||
Close,
|
||||
CompactDisc,
|
||||
Data,
|
||||
DigitalVideoDisc,
|
||||
Disk,
|
||||
DriveSpeed,
|
||||
Eject,
|
||||
Floppy,
|
||||
GDROM,
|
||||
MDS,
|
||||
Merge,
|
||||
Reset,
|
||||
SACD,
|
||||
Start,
|
||||
Stop,
|
||||
Sub,
|
||||
Swap,
|
||||
Tape,
|
||||
XBOX,
|
||||
XBOXSwap,
|
||||
XGD2Swap,
|
||||
XGD3Swap,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supported DiscImageCreator flags
|
||||
/// </summary>
|
||||
public enum Flag : int
|
||||
{
|
||||
NONE = 0,
|
||||
AddOffset,
|
||||
AMSF,
|
||||
AtariJaguar,
|
||||
BEOpcode,
|
||||
C2Opcode,
|
||||
CopyrightManagementInformation,
|
||||
D8Opcode,
|
||||
DisableBeep,
|
||||
ExtractMicroSoftCabFile,
|
||||
ForceUnitAccess,
|
||||
MultiSession,
|
||||
NoFixSubP,
|
||||
NoFixSubQ,
|
||||
NoFixSubQLibCrypt,
|
||||
NoFixSubRtoW,
|
||||
NoFixSubQSecuROM,
|
||||
NoSkipSS,
|
||||
Raw,
|
||||
Reverse,
|
||||
ScanAntiMod,
|
||||
ScanFileProtect,
|
||||
ScanSectorProtect,
|
||||
SeventyFour,
|
||||
SkipSector,
|
||||
SubchannelReadLevel,
|
||||
UseAnchorVolumeDescriptorPointer,
|
||||
VideoNow,
|
||||
VideoNowColor,
|
||||
VideoNowXP,
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,325 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.UmdImageCreator
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic set of UmdImageCreator parameters
|
||||
/// </summary>
|
||||
public class Parameters : BaseParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Populate a Parameters object from a param string
|
||||
/// </summary>
|
||||
/// <param name="parameters">String possibly representing a set of parameters</param>
|
||||
public Parameters(string parameters)
|
||||
: base(parameters)
|
||||
{
|
||||
this.InternalProgram = InternalProgram.UmdImageCreator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate parameters based on a set of known inputs
|
||||
/// </summary>
|
||||
/// <param name="system">KnownSystem value to use</param>
|
||||
/// <param name="type">MediaType value to use</param>
|
||||
/// <param name="driveLetter">Drive letter to use</param>
|
||||
/// <param name="filename">Filename to use</param>
|
||||
/// <param name="driveSpeed">Drive speed to use</param>
|
||||
/// <param name="paranoid">Enable paranoid mode (safer dumping)</param>
|
||||
/// <param name="quietMode">Enable quiet mode (no beeps)</param>
|
||||
/// <param name="retryCount">User-defined reread count</param>
|
||||
public Parameters(KnownSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, bool paranoid, bool quietMode, int retryCount)
|
||||
: base(system, type, driveLetter, filename, driveSpeed, paranoid, quietMode, retryCount)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blindly generate a parameter string based on the inputs
|
||||
/// </summary>
|
||||
/// <returns>Correctly formatted parameter string, null on error</returns>
|
||||
public override string GenerateParameters() => null;
|
||||
|
||||
/// <summary>
|
||||
/// Get the input path from the implementation
|
||||
/// </summary>
|
||||
/// <returns>String representing the path, null on error</returns>
|
||||
public override string InputPath() => null;
|
||||
|
||||
/// <summary>
|
||||
/// Get the output path from the implementation
|
||||
/// </summary>
|
||||
/// <returns>String representing the path, null on error</returns>
|
||||
public override string OutputPath() => null;
|
||||
|
||||
/// <summary>
|
||||
/// Get the processing speed from the implementation
|
||||
/// </summary>
|
||||
/// <returns>int? representing the speed, null on error</returns>
|
||||
public override int? GetSpeed() => null;
|
||||
|
||||
/// <summary>
|
||||
/// Set the processing speed int the implementation
|
||||
/// </summary>
|
||||
/// <param name="speed">int? representing the speed</param>
|
||||
public override void SetSpeed(int? speed) { }
|
||||
|
||||
/// <summary>
|
||||
/// Get the MediaType from the current set of parameters
|
||||
/// </summary>
|
||||
/// <returns>MediaType value if successful, null on error</returns>
|
||||
public override MediaType? GetMediaType() => null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the current command is considered a dumping command or not
|
||||
/// </summary>
|
||||
/// <returns>True if it's a dumping command, false otherwise</returns>
|
||||
public override bool IsDumpingCommand() => true;
|
||||
|
||||
/// <summary>
|
||||
/// Reset all special variables to have default values
|
||||
/// </summary>
|
||||
protected override void ResetValues() { }
|
||||
|
||||
/// <summary>
|
||||
/// Set default parameters for a given system and media type
|
||||
/// </summary>
|
||||
/// <param name="system">KnownSystem value to use</param>
|
||||
/// <param name="type">MediaType value to use</param>
|
||||
/// <param name="driveLetter">Drive letter to use</param>
|
||||
/// <param name="filename">Filename to use</param>
|
||||
/// <param name="driveSpeed">Drive speed to use</param>
|
||||
/// <param name="paranoid">Enable paranoid mode (safer dumping)</param>
|
||||
/// <param name="retryCount">User-defined reread count</param>
|
||||
protected override void SetDefaultParameters(
|
||||
KnownSystem? system,
|
||||
MediaType? type,
|
||||
char driveLetter,
|
||||
string filename,
|
||||
int? driveSpeed,
|
||||
bool paranoid,
|
||||
int retryCount)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan a possible parameter string and populate whatever possible
|
||||
/// </summary>
|
||||
/// <param name="parameters">String possibly representing parameters</param>
|
||||
/// <returns></returns>
|
||||
protected override bool ValidateAndSetParameters(string parameters) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Validate if all required output files exist
|
||||
/// </summary>
|
||||
/// <param name="basePath">Base filename and path to use for checking</param>
|
||||
/// <param name="system">KnownSystem type representing the media</param>
|
||||
/// <param name="type">MediaType type representing the media</param>
|
||||
/// <param name="progress">Optional result progress callback</param>
|
||||
/// <returns></returns>
|
||||
public override bool CheckAllOutputFilesExist(string basePath, KnownSystem? system, MediaType? type, IProgress<Result> progress = null)
|
||||
{
|
||||
string missingFiles = string.Empty;
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.UMD:
|
||||
if (!File.Exists($"{basePath}_disc.txt"))
|
||||
missingFiles += $";{basePath}_disc.txt";
|
||||
if (!File.Exists($"{basePath}_mainError.txt"))
|
||||
missingFiles += $";{basePath}_mainError.txt";
|
||||
if (!File.Exists($"{basePath}_mainInfo.txt"))
|
||||
missingFiles += $";{basePath}_mainInfo.txt";
|
||||
if (!File.Exists($"{basePath}_volDesc.txt"))
|
||||
missingFiles += $";{basePath}_volDesc.txt";
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// Non-dumping commands will usually produce no output, so this is irrelevant
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use the missing files list as an indicator
|
||||
if (string.IsNullOrEmpty(missingFiles))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
progress?.Report(Result.Failure($"The following files were missing: {missingFiles.TrimStart(';')}"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a SubmissionInfo for the output files
|
||||
/// </summary>
|
||||
/// <param name="info">Base submission info to fill in specifics for</param>
|
||||
/// <param name="basePath">Base filename and path to use for checking</param>
|
||||
/// <param name="system">KnownSystem type representing the media</param>
|
||||
/// <param name="type">MediaType type representing the media</param>
|
||||
/// <param name="drive">Drive representing the disc to get information from</param>
|
||||
/// <returns></returns>
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, string basePath, KnownSystem? system, MediaType? type, Drive drive)
|
||||
{
|
||||
// Fill in the hash data
|
||||
info.TracksAndWriteOffsets.ClrMameProData = GetDatfile(basePath + ".dat");
|
||||
|
||||
// Extract info based generically on MediaType
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.UMD:
|
||||
info.Extras.PVD = GetPVD(basePath + "_mainInfo.txt") ?? "";
|
||||
|
||||
if (GetUMDAuxInfo(basePath + "_disc.txt", out string title, out DiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize))
|
||||
{
|
||||
info.CommonDiscInfo.Title = title ?? "";
|
||||
info.CommonDiscInfo.Category = umdcat ?? DiscCategory.Games;
|
||||
info.VersionAndEditions.Version = umdversion ?? "";
|
||||
info.SizeAndChecksums.Size = umdsize;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(umdlayer))
|
||||
info.SizeAndChecksums.Layerbreak = Int64.Parse(umdlayer ?? "-1");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#region Information Extraction Methods
|
||||
|
||||
/// <summary>
|
||||
/// Get the proper datfile from the input file, if possible
|
||||
/// </summary>
|
||||
/// <param name="dat">.dat file location</param>
|
||||
/// <returns>Relevant pieces of the datfile, null on error</returns>
|
||||
private static string GetDatfile(string dat)
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(dat))
|
||||
return null;
|
||||
|
||||
using (StreamReader sr = File.OpenText(dat))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Make sure this file is a .dat
|
||||
if (sr.ReadLine() != "<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
|
||||
return null;
|
||||
if (sr.ReadLine() != "<!DOCTYPE datafile PUBLIC \"-//Logiqx//DTD ROM Management Datafile//EN\" \"http://www.logiqx.com/Dats/datafile.dtd\">")
|
||||
return null;
|
||||
|
||||
// Fast forward to the rom lines
|
||||
while (!sr.ReadLine().TrimStart().StartsWith("<game")) ;
|
||||
sr.ReadLine(); // <category>Games</category>
|
||||
sr.ReadLine(); // <description>Plextor</description>
|
||||
|
||||
// Now that we're at the relevant entries, read each line in and concatenate
|
||||
string pvd = "", line = sr.ReadLine().Trim();
|
||||
while (line.StartsWith("<rom"))
|
||||
{
|
||||
pvd += line + "\n";
|
||||
line = sr.ReadLine().Trim();
|
||||
}
|
||||
|
||||
return pvd.TrimEnd('\n');
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the PVD from the input file, if possible
|
||||
/// </summary>
|
||||
/// <param name="mainInfo">_mainInfo.txt file location</param>
|
||||
/// <returns>Newline-deliminated PVD if possible, null on error</returns>
|
||||
private static string GetPVD(string mainInfo)
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(mainInfo))
|
||||
return null;
|
||||
|
||||
using (StreamReader sr = File.OpenText(mainInfo))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Make sure we're in the right sector
|
||||
while (!sr.ReadLine().StartsWith("========== LBA[000016, 0x00010]: Main Channel ==========")) ;
|
||||
|
||||
// Fast forward to the PVD
|
||||
while (!sr.ReadLine().StartsWith("0310")) ;
|
||||
|
||||
// Now that we're at the PVD, read each line in and concatenate
|
||||
string pvd = "";
|
||||
for (int i = 0; i < 6; i++)
|
||||
pvd += sr.ReadLine() + "\n"; // 320-370
|
||||
|
||||
return pvd;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the UMD auxiliary info from the outputted files, if possible
|
||||
/// </summary>
|
||||
/// <param name="disc">_disc.txt file location</param>
|
||||
/// <returns>True on successful extraction of info, false otherwise</returns>
|
||||
private static bool GetUMDAuxInfo(string disc, out string title, out DiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize)
|
||||
{
|
||||
title = null; umdcat = null; umdversion = null; umdlayer = null; umdsize = -1;
|
||||
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(disc))
|
||||
return false;
|
||||
|
||||
using (StreamReader sr = File.OpenText(disc))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Loop through everything to get the first instance of each required field
|
||||
string line = string.Empty;
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
line = sr.ReadLine().Trim();
|
||||
|
||||
if (line.StartsWith("TITLE") && title == null)
|
||||
title = line.Substring("TITLE: ".Length);
|
||||
else if (line.StartsWith("DISC_VERSION") && umdversion == null)
|
||||
umdversion = line.Split(' ')[1];
|
||||
else if (line.StartsWith("pspUmdTypes"))
|
||||
umdcat = GetUMDCategory(line.Split(' ')[1]);
|
||||
else if (line.StartsWith("L0 length"))
|
||||
umdlayer = line.Split(' ')[2];
|
||||
else if (line.StartsWith("FileSize:"))
|
||||
umdsize = Int64.Parse(line.Split(' ')[1]);
|
||||
}
|
||||
|
||||
// If the L0 length is the size of the full disc, there's no layerbreak
|
||||
if (Int64.Parse(umdlayer) * 2048 == umdsize)
|
||||
umdlayer = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,65 +0,0 @@
|
||||
using System.IO;
|
||||
using DICUI.Data;
|
||||
|
||||
namespace DICUI.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents information for a single drive
|
||||
/// </summary>
|
||||
public class Drive
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents drive type
|
||||
/// </summary>
|
||||
public InternalDriveType? InternalDriveType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DriveInfo object representing the drive, if possible
|
||||
/// </summary>
|
||||
public DriveInfo DriveInfo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Windows drive letter
|
||||
/// </summary>
|
||||
public char Letter { get { return DriveInfo?.Name[0] ?? '\0'; } }
|
||||
|
||||
/// <summary>
|
||||
/// Media label as read by Windows
|
||||
/// </summary>
|
||||
public string VolumeLabel
|
||||
{
|
||||
get
|
||||
{
|
||||
string volumeLabel = Template.DiscNotDetected;
|
||||
if (DriveInfo.IsReady)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(DriveInfo.VolumeLabel))
|
||||
volumeLabel = "track";
|
||||
else
|
||||
volumeLabel = DriveInfo.VolumeLabel;
|
||||
}
|
||||
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
volumeLabel = volumeLabel.Replace(c, '_');
|
||||
|
||||
return volumeLabel;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drive partition format
|
||||
/// </summary>
|
||||
public string DriveFormat { get { return DriveInfo.DriveFormat; } }
|
||||
|
||||
/// <summary>
|
||||
/// Represents if Windows has marked the drive as active
|
||||
/// </summary>
|
||||
public bool MarkedActive { get { return DriveInfo.IsReady; } }
|
||||
|
||||
public Drive(InternalDriveType? driveType, DriveInfo driveInfo)
|
||||
{
|
||||
this.InternalDriveType = driveType;
|
||||
this.DriveInfo = driveInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,57 +0,0 @@
|
||||
using DICUI.Data;
|
||||
|
||||
namespace DICUI.Utilities
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static bool DoesSupportDriveSpeed(this MediaType? type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.DVD:
|
||||
case MediaType.GDROM:
|
||||
case MediaType.HDDVD:
|
||||
case MediaType.BluRay:
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static KnownSystemCategory Category(this KnownSystem? system)
|
||||
{
|
||||
if (system < KnownSystem.MarkerDiscBasedConsoleEnd)
|
||||
return KnownSystemCategory.DiscBasedConsole;
|
||||
/*
|
||||
else if (system < KnownSystem.MarkerOtherConsoleEnd)
|
||||
return KnownSystemCategory.OtherConsole;
|
||||
*/
|
||||
else if (system < KnownSystem.MarkerComputerEnd)
|
||||
return KnownSystemCategory.Computer;
|
||||
else if (system < KnownSystem.MarkerArcadeEnd)
|
||||
return KnownSystemCategory.Arcade;
|
||||
else if (system < KnownSystem.MarkerOtherEnd)
|
||||
return KnownSystemCategory.Other;
|
||||
else
|
||||
return KnownSystemCategory.Custom;
|
||||
}
|
||||
|
||||
public static bool IsMarker(this KnownSystem? system)
|
||||
{
|
||||
switch (system)
|
||||
{
|
||||
case KnownSystem.MarkerArcadeEnd:
|
||||
case KnownSystem.MarkerComputerEnd:
|
||||
case KnownSystem.MarkerDiscBasedConsoleEnd:
|
||||
// case KnownSystem.MarkerOtherConsoleEnd:
|
||||
case KnownSystem.MarkerOtherEnd:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Utilities
|
||||
{
|
||||
public class Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Check for a new DICUI version
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Bool representing if the values are different.
|
||||
/// String representing the message to display the the user.
|
||||
/// String representing the new release URL.
|
||||
/// </returns>
|
||||
public static (bool different, string message, string url) CheckForNewVersion()
|
||||
{
|
||||
// Get current assembly version
|
||||
string version = GetCurrentVersion();
|
||||
|
||||
// Get the latest tag from GitHub
|
||||
using (var client = new RedumpWebClient())
|
||||
{
|
||||
(string tag, string url) = client.GetRemoteVersionAndUrl();
|
||||
bool different = version != tag;
|
||||
|
||||
string message = $"Local version: {version}"
|
||||
+ $"{Environment.NewLine}Remote version: {tag}"
|
||||
+ (different
|
||||
? $"{Environment.NewLine}The update URL has been added copied to your clipboard"
|
||||
: $"{Environment.NewLine}You have the newest version!");
|
||||
|
||||
return (different, message, url);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current assembly version formatted as a string
|
||||
/// </summary>
|
||||
private static string GetCurrentVersion()
|
||||
{
|
||||
var assemblyVersion = Assembly.GetEntryAssembly().GetName().Version;
|
||||
return $"{assemblyVersion.Major}.{assemblyVersion.Minor}" + (assemblyVersion.Build != 0 ? $".{assemblyVersion.Build}" : string.Empty);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,244 +0,0 @@
|
||||
namespace DICUI.Web
|
||||
{
|
||||
/// <summary>
|
||||
/// List of all disc categories
|
||||
/// </summary>
|
||||
public enum DiscCategory
|
||||
{
|
||||
Games = 1,
|
||||
Demos = 2,
|
||||
Video = 3,
|
||||
Audio = 4,
|
||||
Multimedia = 5,
|
||||
Applications = 6,
|
||||
Coverdiscs = 7,
|
||||
Educational = 8,
|
||||
BonusDiscs = 9,
|
||||
Preproduction = 10,
|
||||
AddOns = 11,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dump status
|
||||
/// </summary>
|
||||
public enum DumpStatus
|
||||
{
|
||||
BadDumpRed = 2,
|
||||
PossibleBadDumpYellow = 3,
|
||||
OriginalMediaBlue = 4,
|
||||
TwoOrMoreDumpsGreen = 5,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of all disc langauges
|
||||
/// </summary>
|
||||
public enum Language
|
||||
{
|
||||
Afrikaans,
|
||||
Arabic,
|
||||
Basque,
|
||||
Bulgarian,
|
||||
Catalan,
|
||||
Chinese,
|
||||
Croatian,
|
||||
Czech,
|
||||
Danish,
|
||||
Dutch,
|
||||
English,
|
||||
Finnish,
|
||||
French,
|
||||
Gaelic,
|
||||
German,
|
||||
Greek,
|
||||
Hebrew,
|
||||
Hindi,
|
||||
Hungarian,
|
||||
Italian,
|
||||
Japanese,
|
||||
Korean,
|
||||
Norwegian,
|
||||
Polish,
|
||||
Portuguese,
|
||||
Punjabi,
|
||||
Romanian,
|
||||
Russian,
|
||||
Slovak,
|
||||
Slovenian,
|
||||
Spanish,
|
||||
Swedish,
|
||||
Tamil,
|
||||
Thai,
|
||||
Turkish,
|
||||
Ukrainian,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All possible language selections
|
||||
/// </summary>
|
||||
public enum LanguageSelection
|
||||
{
|
||||
BiosSettings,
|
||||
LanguageSelector,
|
||||
OptionsMenu,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of all known Redump systems
|
||||
/// </summary>
|
||||
public enum RedumpSystem
|
||||
{
|
||||
// Special BIOS sets
|
||||
MicrosoftXboxBIOS,
|
||||
NintendoGameCubeBIOS,
|
||||
SonyPlayStationBIOS,
|
||||
SonyPlayStation2BIOS,
|
||||
|
||||
// Regular systems
|
||||
AcornArchimedes,
|
||||
AppleMacintosh,
|
||||
AtariJaguarCDInteractiveMultimediaSystem,
|
||||
AudioCD,
|
||||
BandaiPippin,
|
||||
BandaiPlaydiaQuickInteractiveSystem,
|
||||
BDVideo,
|
||||
CommodoreAmigaCD,
|
||||
CommodoreAmigaCD32,
|
||||
CommodoreAmigaCDTV,
|
||||
DVDVideo,
|
||||
EnhancedCD,
|
||||
FujitsuFMTownsseries,
|
||||
funworldPhotoPlay,
|
||||
HasbroVideoNow,
|
||||
HasbroVideoNowColor,
|
||||
HasbroVideoNowJr,
|
||||
HasbroVideoNowXP,
|
||||
IBMPCcompatible,
|
||||
IncredibleTechnologiesEagle,
|
||||
KonamieAmusement,
|
||||
KonamiFireBeat,
|
||||
KonamiM2,
|
||||
KonamiSystem573,
|
||||
KonamiSystemGV,
|
||||
KonamiTwinkle,
|
||||
MattelFisherPriceiXL,
|
||||
MattelHyperScan,
|
||||
MemorexVisualInformationSystem,
|
||||
MicrosoftXbox,
|
||||
MicrosoftXbox360,
|
||||
MicrosoftXboxOne,
|
||||
NamcoSegaNintendoTriforce,
|
||||
NamcoSystem12,
|
||||
NamcoSystem246,
|
||||
NavisoftNaviken21,
|
||||
NECPCEngineCDTurboGrafxCD,
|
||||
NECPC88series,
|
||||
NECPC98series,
|
||||
NECPCFXPCFXGA,
|
||||
NintendoGameCube,
|
||||
NintendoWii,
|
||||
NintendoWiiU,
|
||||
PalmOS,
|
||||
Panasonic3DOInteractiveMultiplayer,
|
||||
PanasonicM2,
|
||||
PhilipsCDi,
|
||||
PhilipsCDiDigitalVideo,
|
||||
PhotoCD,
|
||||
PlayStationGameSharkUpdates,
|
||||
SegaChihiro,
|
||||
SegaDreamcast,
|
||||
SegaLindbergh,
|
||||
SegaMegaCDSegaCD,
|
||||
SegaNaomi,
|
||||
SegaNaomi2,
|
||||
SegaPrologue21,
|
||||
SegaRingEdge,
|
||||
SegaRingEdge2,
|
||||
SegaSaturn,
|
||||
SegaTitanVideo,
|
||||
SharpX68000,
|
||||
SNKNeoGeoCD,
|
||||
SonyPlayStation,
|
||||
SonyPlayStation2,
|
||||
SonyPlayStation3,
|
||||
SonyPlayStation4,
|
||||
SonyPlayStationPortable,
|
||||
TABAustriaQuizard,
|
||||
TaoiKTV,
|
||||
TomyKissSite,
|
||||
VideoCD,
|
||||
VMLabsNUON,
|
||||
VTechVFlashVSmilePro,
|
||||
ZAPiTGamesGameWaveFamilyEntertainmentSystem,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of all known Redump regions
|
||||
/// </summary>
|
||||
public enum Region
|
||||
{
|
||||
Argentina,
|
||||
Asia,
|
||||
AsiaEurope,
|
||||
AsiaUSA,
|
||||
Australia,
|
||||
Austria,
|
||||
AustriaSwitzerland,
|
||||
Belgium,
|
||||
BelgiumNetherlands,
|
||||
Brazil,
|
||||
Canada,
|
||||
China,
|
||||
Croatia,
|
||||
Czech,
|
||||
Denmark,
|
||||
Europe,
|
||||
EuropeAsia,
|
||||
EuropeAustralia,
|
||||
Finland,
|
||||
France,
|
||||
FranceSpain,
|
||||
Germany,
|
||||
GreaterChina,
|
||||
Greece,
|
||||
Hungary,
|
||||
India,
|
||||
Ireland,
|
||||
Israel,
|
||||
Italy,
|
||||
Japan,
|
||||
JapanAsia,
|
||||
JapanEurope,
|
||||
JapanKorea,
|
||||
JapanUSA,
|
||||
Korea,
|
||||
LatinAmerica,
|
||||
Netherlands,
|
||||
Norway,
|
||||
Poland,
|
||||
Portugal,
|
||||
Russia,
|
||||
Scandinavia,
|
||||
Singapore,
|
||||
Slovakia,
|
||||
SouthAfrica,
|
||||
Spain,
|
||||
SpainPortugal,
|
||||
Sweden,
|
||||
Switzerland,
|
||||
Taiwan,
|
||||
Thailand,
|
||||
Turkey,
|
||||
UnitedArabEmirates,
|
||||
UK,
|
||||
UKAustralia,
|
||||
Ukraine,
|
||||
USA,
|
||||
USAAsia,
|
||||
USABrazil,
|
||||
USACanada,
|
||||
USAEurope,
|
||||
USAGermany,
|
||||
USAJapan,
|
||||
World,
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,311 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace DICUI.Web
|
||||
{
|
||||
public class SubmissionInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// List of matched Redump IDs
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public List<int> MatchedIDs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DateTime of when the disc was added
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public DateTime? Added { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DateTime of when the disc was last modified
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public DateTime? LastModified { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "common_disc_info", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public CommonDiscInfoSection CommonDiscInfo { get; set; } = new CommonDiscInfoSection();
|
||||
|
||||
[JsonProperty(PropertyName = "versions_and_editions", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public VersionAndEditionsSection VersionAndEditions { get; set; } = new VersionAndEditionsSection();
|
||||
|
||||
[JsonProperty(PropertyName = "edc", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public EDCSection EDC { get; set; } = new EDCSection();
|
||||
|
||||
[JsonProperty(PropertyName = "parent_clone_relationship", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public ParentCloneRelationshipSection ParentCloneRelationship { get; set; } = new ParentCloneRelationshipSection();
|
||||
|
||||
[JsonProperty(PropertyName = "extras", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public ExtrasSection Extras { get; set; } = new ExtrasSection();
|
||||
|
||||
[JsonProperty(PropertyName = "copy_protection", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public CopyProtectionSection CopyProtection { get; set; } = new CopyProtectionSection();
|
||||
|
||||
[JsonProperty(PropertyName = "dumpers_and_status", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public DumpersAndStatusSection DumpersAndStatus { get; set; } = new DumpersAndStatusSection();
|
||||
|
||||
[JsonProperty(PropertyName = "tracks_and_write_offsets", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public TracksAndWriteOffsetsSection TracksAndWriteOffsets { get; set; } = new TracksAndWriteOffsetsSection();
|
||||
|
||||
[JsonProperty(PropertyName = "size_and_checksums", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public SizeAndChecksumsSection SizeAndChecksums { get; set; } = new SizeAndChecksumsSection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Common disc info section of New Disc Form
|
||||
/// </summary>
|
||||
public class CommonDiscInfoSection
|
||||
{
|
||||
// Name not defined by Redump
|
||||
[JsonProperty(PropertyName = "d_system", Required = Required.AllowNull)]
|
||||
[JsonConverter(typeof(KnownSystemConverter))]
|
||||
public KnownSystem? System { get; set; }
|
||||
|
||||
// Name not defined by Redump
|
||||
// TODO: Have this convert to a new `RedumpMedia?` if possible, for submission
|
||||
[JsonProperty(PropertyName = "d_media", Required = Required.AllowNull)]
|
||||
[JsonConverter(typeof(MediaTypeConverter))]
|
||||
public MediaType? Media { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_title", Required = Required.AllowNull)]
|
||||
public string Title { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_title_foreign", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string ForeignTitleNonLatin { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_number", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string DiscNumberLetter { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_label", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string DiscTitle { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_category", Required = Required.AllowNull)]
|
||||
public DiscCategory? Category { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_region", Required = Required.AllowNull)]
|
||||
[JsonConverter(typeof(RegionConverter))]
|
||||
public Region? Region { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_languages", Required = Required.AllowNull)]
|
||||
[JsonConverter(typeof(LanguagesConverter))]
|
||||
public Language?[] Languages { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_languages_selection", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
[JsonConverter(typeof(LanguageSelectionConverter))]
|
||||
public LanguageSelection?[] LanguageSelection { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_serial", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Serial { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Ring { get; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_id", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string RingId { get; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_ma1", Required = Required.AllowNull)]
|
||||
public string MasteringRingFirstLayerDataSide { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_ma1_sid", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string MasteringSIDCodeFirstLayerDataSide { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_ts1", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string ToolstampMasteringCodeFirstLayerDataSide { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_mo1_sid", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string MouldSIDCodeFirstLayerDataSide { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "dr_ring_0_mo1", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string AdditionalMouldFirstLayerDataSide { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_ma2", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string MasteringRingSecondLayerLabelSide { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_ma2_sid", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string MasteringSIDCodeSecondLayerLabelSide { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_ts2", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string ToolstampMasteringCodeSecondLayerLabelSide { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_mo2_sid", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string MouldSIDCodeSecondLayerLabelSide { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "dr_ring_0_mo2", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string AdditionalMouldSecondLayerLabelSide { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_offsets", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string RingOffsetsHidden { get { return "1"; } }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_0_id", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string RingZeroId { get; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_0_density", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string RingZeroDensity { get; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_0_0_value", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string RingWriteOffset { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ring_count", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string RingCount { get { return "1"; } }
|
||||
|
||||
[JsonProperty(PropertyName = "d_barcode", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Barcode { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_date", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string EXEDateBuildDate { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_errors", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string ErrorsCount { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_comments", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Comments { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_contents", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Contents { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Version and editions section of New Disc form
|
||||
/// </summary>
|
||||
public class VersionAndEditionsSection
|
||||
{
|
||||
[JsonProperty(PropertyName = "d_version", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Version { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_version_datfile", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string VersionDatfile { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_editions", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string[] CommonEditions { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_editions_text", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string OtherEditions { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EDC section of New Disc form (PSX only)
|
||||
/// </summary>
|
||||
public class EDCSection
|
||||
{
|
||||
[JsonProperty(PropertyName = "d_edc", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public YesNo EDC { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parent/Clone relationship section of New Disc form
|
||||
/// </summary>
|
||||
public class ParentCloneRelationshipSection
|
||||
{
|
||||
[JsonProperty(PropertyName = "d_parent_id", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string ParentID { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_is_regional_parent", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool RegionalParent { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extras section of New Disc form
|
||||
/// </summary>
|
||||
public class ExtrasSection
|
||||
{
|
||||
[JsonProperty(PropertyName = "d_pvd", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string PVD { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_d1_key", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string DiscKey { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_d2_key", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string DiscID { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_pic_data", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string PIC { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_header", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Header { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_bca", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string BCA { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_ssranges", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string SecuritySectorRanges { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy protection section of New Disc form
|
||||
/// </summary>
|
||||
public class CopyProtectionSection
|
||||
{
|
||||
[JsonProperty(PropertyName = "d_protection_a", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public YesNo AntiModchip { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_protection_1", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public YesNo LibCrypt { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_libcrypt", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string LibCryptData { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_protection", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Protection { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_securom", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string SecuROMData { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dumpers and status section of New Disc form (Moderator only)
|
||||
/// </summary>
|
||||
public class DumpersAndStatusSection
|
||||
{
|
||||
[JsonProperty(PropertyName = "d_status", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public DumpStatus Status { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_dumpers", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string[] Dumpers { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_dumpers_text", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string OtherDumpers { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tracks and write offsets section of New Disc form (CD/GD-based)
|
||||
/// </summary>
|
||||
public class TracksAndWriteOffsetsSection
|
||||
{
|
||||
[JsonProperty(PropertyName = "d_tracks", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string ClrMameProData { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_cue", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Cuesheet { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_offset", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public int[] CommonWriteOffsets { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_offset_text", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string OtherWriteOffsets { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Size & checksums section of New Disc form (DVD/BD/UMD-based)
|
||||
/// </summary>
|
||||
public class SizeAndChecksumsSection
|
||||
{
|
||||
[JsonProperty(PropertyName = "d_layerbreak", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public long Layerbreak { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_size", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public long Size { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_crc32", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string CRC32 { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_md5", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string MD5 { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "d_sha1", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string SHA1 { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;net48;netcoreapp3.1</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DICUI.Library\DICUI.Library.csproj">
|
||||
<Project>{51ab0928-13f9-44bf-a407-b6957a43a056}</Project>
|
||||
<Name>DICUI.Library</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\DICUI\DICUI.csproj">
|
||||
<Project>{7b1b75eb-8940-466f-bd51-76471a57f9be}</Project>
|
||||
<Name>DICUI</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="16.7.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="0.10.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.core" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.extensibility.execution" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,40 +0,0 @@
|
||||
using DICUI.Utilities;
|
||||
using Xunit;
|
||||
|
||||
namespace DICUI.Test
|
||||
{
|
||||
public class ResultTest
|
||||
{
|
||||
[Fact]
|
||||
public void ResultSuccessTest()
|
||||
{
|
||||
Result actual = Result.Success();
|
||||
Assert.Empty(actual.Message);
|
||||
|
||||
string message = "Success!";
|
||||
actual = Result.Success(message);
|
||||
Assert.Equal(message, actual.Message);
|
||||
|
||||
message = "Success! {0}";
|
||||
string parameter = "Parameter";
|
||||
actual = Result.Success(message, parameter);
|
||||
Assert.Equal(string.Format(message, parameter), actual.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResultFailureTest()
|
||||
{
|
||||
Result actual = Result.Failure();
|
||||
Assert.Empty(actual.Message);
|
||||
|
||||
string message = "Failure!";
|
||||
actual = Result.Failure(message);
|
||||
Assert.Equal(message, actual.Message);
|
||||
|
||||
message = "Failure! {0}";
|
||||
string parameter = "Parameter";
|
||||
actual = Result.Failure(message, parameter);
|
||||
Assert.Equal(string.Format(message, parameter), actual.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
using System;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using Xunit;
|
||||
|
||||
namespace DICUI.Test.Utilities
|
||||
{
|
||||
public class ConvertersTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(DiscImageCreator.Command.Audio, MediaType.CDROM)]
|
||||
[InlineData(DiscImageCreator.Command.BluRay, MediaType.BluRay)]
|
||||
[InlineData(DiscImageCreator.Command.Close, null)]
|
||||
[InlineData(DiscImageCreator.Command.CompactDisc, MediaType.CDROM)]
|
||||
[InlineData(DiscImageCreator.Command.Data, MediaType.CDROM)]
|
||||
[InlineData(DiscImageCreator.Command.DigitalVideoDisc, MediaType.DVD)]
|
||||
[InlineData(DiscImageCreator.Command.Eject, null)]
|
||||
[InlineData(DiscImageCreator.Command.Floppy, MediaType.FloppyDisk)]
|
||||
[InlineData(DiscImageCreator.Command.GDROM, MediaType.GDROM)]
|
||||
[InlineData(DiscImageCreator.Command.MDS, null)]
|
||||
[InlineData(DiscImageCreator.Command.Reset, null)]
|
||||
[InlineData(DiscImageCreator.Command.SACD, MediaType.CDROM)]
|
||||
[InlineData(DiscImageCreator.Command.Start, null)]
|
||||
[InlineData(DiscImageCreator.Command.Stop, null)]
|
||||
[InlineData(DiscImageCreator.Command.Sub, null)]
|
||||
[InlineData(DiscImageCreator.Command.Swap, MediaType.GDROM)]
|
||||
[InlineData(DiscImageCreator.Command.XBOX, MediaType.DVD)]
|
||||
public void BaseCommandToMediaTypeTest(DiscImageCreator.Command command, MediaType? expected)
|
||||
{
|
||||
MediaType? actual = DiscImageCreator.Converters.ToMediaType(command);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(DiscImageCreator.Command.Audio, KnownSystem.AudioCD)]
|
||||
[InlineData(DiscImageCreator.Command.BluRay, KnownSystem.SonyPlayStation3)]
|
||||
[InlineData(DiscImageCreator.Command.Close, null)]
|
||||
[InlineData(DiscImageCreator.Command.CompactDisc, KnownSystem.IBMPCCompatible)]
|
||||
[InlineData(DiscImageCreator.Command.Data, KnownSystem.IBMPCCompatible)]
|
||||
[InlineData(DiscImageCreator.Command.DigitalVideoDisc, KnownSystem.IBMPCCompatible)]
|
||||
[InlineData(DiscImageCreator.Command.Eject, null)]
|
||||
[InlineData(DiscImageCreator.Command.Floppy, KnownSystem.IBMPCCompatible)]
|
||||
[InlineData(DiscImageCreator.Command.GDROM, KnownSystem.SegaDreamcast)]
|
||||
[InlineData(DiscImageCreator.Command.MDS, null)]
|
||||
[InlineData(DiscImageCreator.Command.Reset, null)]
|
||||
[InlineData(DiscImageCreator.Command.SACD, KnownSystem.SuperAudioCD)]
|
||||
[InlineData(DiscImageCreator.Command.Start, null)]
|
||||
[InlineData(DiscImageCreator.Command.Stop, null)]
|
||||
[InlineData(DiscImageCreator.Command.Sub, null)]
|
||||
[InlineData(DiscImageCreator.Command.Swap, KnownSystem.SegaDreamcast)]
|
||||
[InlineData(DiscImageCreator.Command.XBOX, KnownSystem.MicrosoftXBOX)]
|
||||
public void BaseCommandToKnownSystemTest(DiscImageCreator.Command command, KnownSystem? expected)
|
||||
{
|
||||
KnownSystem? actual = DiscImageCreator.Converters.ToKnownSystem(command);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(MediaType.CDROM, ".bin")]
|
||||
[InlineData(MediaType.DVD, ".iso")]
|
||||
[InlineData(MediaType.LaserDisc, ".raw")]
|
||||
[InlineData(MediaType.NintendoWiiUOpticalDisc, ".wud")]
|
||||
[InlineData(MediaType.FloppyDisk, ".img")]
|
||||
[InlineData(MediaType.Cassette, ".wav")]
|
||||
[InlineData(MediaType.NONE, null)]
|
||||
public void MediaTypeToExtensionTest(MediaType? mediaType, string expected)
|
||||
{
|
||||
string actual = DiscImageCreator.Converters.Extension(mediaType);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(MediaType.CDROM, "CD-ROM")]
|
||||
[InlineData(MediaType.LaserDisc, "LD-ROM / LV-ROM")]
|
||||
[InlineData(MediaType.NONE, "Unknown")]
|
||||
public void MediaTypeToStringTest(MediaType? mediaType, string expected)
|
||||
{
|
||||
string actual = Converters.LongName(mediaType);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(KnownSystem.MicrosoftXBOX, "Microsoft XBOX")]
|
||||
[InlineData(KnownSystem.NECPC88, "NEC PC-88")]
|
||||
[InlineData(KnownSystem.KonamiPython, "Konami Python")]
|
||||
[InlineData(KnownSystem.HDDVDVideo, "HD-DVD-Video")]
|
||||
[InlineData(KnownSystem.NONE, "Unknown")]
|
||||
public void KnownSystemToStringTest(KnownSystem? knownSystem, string expected)
|
||||
{
|
||||
string actual = Converters.LongName(knownSystem);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KnownSystemHasValidCategory()
|
||||
{
|
||||
var values = Validators.CreateListOfSystems();
|
||||
KnownSystem[] markers = { KnownSystem.MarkerArcadeEnd, KnownSystem.MarkerDiscBasedConsoleEnd, /* KnownSystem.MarkerOtherConsoleEnd, */ KnownSystem.MarkerComputerEnd, KnownSystem.MarkerOtherEnd };
|
||||
|
||||
values.ForEach(system => {
|
||||
if (system == KnownSystem.NONE)
|
||||
return;
|
||||
|
||||
// we check that the category is the first category value higher than the system
|
||||
KnownSystemCategory category = ((KnownSystem?)system).Category();
|
||||
KnownSystem marker = KnownSystem.NONE;
|
||||
|
||||
switch (category)
|
||||
{
|
||||
case KnownSystemCategory.Arcade: marker = KnownSystem.MarkerArcadeEnd; break;
|
||||
case KnownSystemCategory.DiscBasedConsole: marker = KnownSystem.MarkerDiscBasedConsoleEnd; break;
|
||||
/* case KnownSystemCategory.OtherConsole: marker = KnownSystem.MarkerOtherConsoleEnd; break; */
|
||||
case KnownSystemCategory.Computer: marker = KnownSystem.MarkerComputerEnd; break;
|
||||
case KnownSystemCategory.Other: marker = KnownSystem.MarkerOtherEnd; break;
|
||||
}
|
||||
|
||||
Assert.NotEqual(KnownSystem.NONE, marker);
|
||||
Assert.True(marker > system);
|
||||
|
||||
Array.ForEach(markers, mmarker =>
|
||||
{
|
||||
// a marker can be the same of the found one, or one of a category before or a category after but never in the middle between
|
||||
// the system and the mapped category
|
||||
Assert.True(mmarker == marker || mmarker < system || mmarker > marker);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
using System.IO;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using Xunit;
|
||||
|
||||
namespace DICUI.Test
|
||||
{
|
||||
public class DumpEnvironmentTest
|
||||
{
|
||||
[Theory]
|
||||
[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("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)
|
||||
{
|
||||
var options = new Options() { InternalProgram = "dic" };
|
||||
var drive = isFloppy
|
||||
? new Drive(InternalDriveType.Floppy, new DriveInfo(letter.ToString()))
|
||||
: new Drive(InternalDriveType.Optical, new DriveInfo(letter.ToString()));
|
||||
|
||||
var env = new DumpEnvironment(options, string.Empty, string.Empty, drive, KnownSystem.IBMPCCompatible, mediaType, parameters);
|
||||
|
||||
bool actual = env.ParametersValid();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, null, 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 FixOutputPathsTest(string outputDirectory, string outputFilename, string expectedOutputDirectory, string expectedOutputFilename)
|
||||
{
|
||||
var options = new Options() { InternalProgram = "dic" };
|
||||
var env = new DumpEnvironment(options, outputDirectory, outputFilename, null, KnownSystem.IBMPCCompatible, MediaType.CDROM, string.Empty);
|
||||
|
||||
env.FixOutputPaths();
|
||||
Assert.Equal(expectedOutputDirectory, env.OutputDirectory);
|
||||
Assert.Equal(expectedOutputFilename, env.OutputFilename);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetFirstTrackTest()
|
||||
{
|
||||
// TODO: Implement
|
||||
Assert.True(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormatOutputDataTest()
|
||||
{
|
||||
// TODO: Implement
|
||||
Assert.True(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WriteOutputDataTest()
|
||||
{
|
||||
// TODO: Implement
|
||||
Assert.True(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EjectDiscTest()
|
||||
{
|
||||
// TODO: Implement
|
||||
Assert.True(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CancelDumpingTest()
|
||||
{
|
||||
// TODO: Implement
|
||||
Assert.True(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartDumpingTest()
|
||||
{
|
||||
// TODO: Implement
|
||||
Assert.True(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using Xunit;
|
||||
|
||||
namespace DICUI.Test.Utilities
|
||||
{
|
||||
public class KnownSystemExtensionsTest
|
||||
{
|
||||
[Fact]
|
||||
public void IsMarkerTest()
|
||||
{
|
||||
var values = (KnownSystem[])Enum.GetValues(typeof(KnownSystem));
|
||||
foreach(var system in values)
|
||||
{
|
||||
bool expected = system == KnownSystem.MarkerArcadeEnd || system == KnownSystem.MarkerComputerEnd ||
|
||||
system == KnownSystem.MarkerOtherEnd || system == KnownSystem.MarkerDiscBasedConsoleEnd;
|
||||
// || system == KnownSystem.MarkerOtherConsoleEnd;
|
||||
|
||||
bool actual = ((KnownSystem?)system).IsMarker();
|
||||
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CategoryNameNotEmptyTest()
|
||||
{
|
||||
var values = (KnownSystemCategory[])Enum.GetValues(typeof(KnownSystemCategory));
|
||||
foreach (var system in values)
|
||||
{
|
||||
string actual = ((KnownSystem?)system).LongName();
|
||||
Assert.NotEqual("", actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using Xunit;
|
||||
|
||||
namespace DICUI.Test.Utilities
|
||||
{
|
||||
public class MediaTypeExtensionsTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(MediaType.CDROM, "CD-ROM")]
|
||||
[InlineData(MediaType.LaserDisc, "LD-ROM / LV-ROM")]
|
||||
[InlineData(MediaType.NONE, "Unknown")]
|
||||
public void NameTest(MediaType? mediaType, string expected)
|
||||
{
|
||||
string actual = mediaType.LongName();
|
||||
|
||||
Assert.NotNull(actual);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(MediaType.CDROM, ".bin")]
|
||||
[InlineData(MediaType.DVD, ".iso")]
|
||||
[InlineData(MediaType.LaserDisc, ".raw")]
|
||||
[InlineData(MediaType.FloppyDisk, ".img")]
|
||||
[InlineData(MediaType.NONE, null)]
|
||||
public void ExtensionTest(MediaType? mediaType, string expected)
|
||||
{
|
||||
string actual = DiscImageCreator.Converters.Extension(mediaType);
|
||||
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(MediaType.CDROM, true)]
|
||||
[InlineData(MediaType.DVD, true)]
|
||||
[InlineData(MediaType.FloppyDisk, false)]
|
||||
[InlineData(MediaType.BluRay, true)]
|
||||
[InlineData(MediaType.LaserDisc, false)]
|
||||
public void DriveSpeedSupportedTest(MediaType? mediaType, bool expected)
|
||||
{
|
||||
bool actual = mediaType.DoesSupportDriveSpeed();
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using DICUI.Data;
|
||||
using DICUI.DiscImageCreator;
|
||||
using DICUI.Utilities;
|
||||
using Xunit;
|
||||
|
||||
namespace DICUI.Test.Utilities
|
||||
{
|
||||
public class ParametersTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(KnownSystem.MicrosoftXBOX, MediaType.CDROM, Command.CompactDisc)]
|
||||
[InlineData(KnownSystem.MicrosoftXBOX, MediaType.DVD, Command.XBOX)]
|
||||
[InlineData(KnownSystem.MicrosoftXBOX, MediaType.LaserDisc, Command.NONE)]
|
||||
[InlineData(KnownSystem.SegaNu, MediaType.BluRay, Command.BluRay)]
|
||||
[InlineData(KnownSystem.AppleMacintosh, MediaType.FloppyDisk, Command.Floppy)]
|
||||
[InlineData(KnownSystem.RawThrillsVarious, MediaType.GDROM, Command.NONE)]
|
||||
public void ParametersFromSystemAndTypeTest(KnownSystem? knownSystem, MediaType? mediaType, Command expected)
|
||||
{
|
||||
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, true, false, -1);
|
||||
Assert.Equal(expected, actual.BaseCommand);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(KnownSystem.AppleMacintosh, MediaType.LaserDisc, true, 20, null, null)]
|
||||
[InlineData(KnownSystem.NintendoGameCube, MediaType.NintendoGameCubeGameDisc, false, 20, null, new Flag[] { Flag.Raw })]
|
||||
[InlineData(KnownSystem.IBMPCCompatible, MediaType.DVD, false, 20, null, new Flag[] { })]
|
||||
/* paranoid mode tests */
|
||||
[InlineData(KnownSystem.IBMPCCompatible, MediaType.CDROM, true, 1000, 2, new Flag[] { Flag.C2Opcode, Flag.NoFixSubQSecuROM, Flag.ScanFileProtect, Flag.ScanSectorProtect, Flag.SubchannelReadLevel })]
|
||||
[InlineData(KnownSystem.AppleMacintosh, MediaType.CDROM, false, 20, null, new Flag[] { Flag.C2Opcode, Flag.NoFixSubQSecuROM, Flag.ScanFileProtect })]
|
||||
[InlineData(KnownSystem.IBMPCCompatible, MediaType.DVD, true, 500, null, new Flag[] { Flag.CopyrightManagementInformation, Flag.ScanFileProtect })]
|
||||
[InlineData(KnownSystem.HDDVDVideo, MediaType.HDDVD, true, 500, null, new Flag[] { Flag.CopyrightManagementInformation })]
|
||||
[InlineData(KnownSystem.IBMPCCompatible, MediaType.DVD, false, 500, null, new Flag[] { })]
|
||||
[InlineData(KnownSystem.HDDVDVideo, MediaType.HDDVD, false, 500, null, new Flag[] { })]
|
||||
/* reread c2 */
|
||||
[InlineData(KnownSystem.SegaDreamcast, MediaType.GDROM, false, 1000, null, new Flag[] { Flag.C2Opcode })]
|
||||
[InlineData(KnownSystem.SegaDreamcast, MediaType.GDROM, false, -1, null, new Flag[] { Flag.C2Opcode })]
|
||||
|
||||
public void ParametersFromOptionsTest(KnownSystem? knownSystem, MediaType? mediaType, bool paranoid, int rereadC2, int? subchannelLevel, Flag[] expected)
|
||||
{
|
||||
var actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, paranoid, false, rereadC2);
|
||||
|
||||
HashSet<Flag> expectedSet = new HashSet<Flag>(expected ?? new Flag[0]);
|
||||
HashSet<Flag> actualSet = new HashSet<Flag>(actual.Keys.Cast<Flag>() ?? new Flag[0]);
|
||||
Assert.Equal(expectedSet, actualSet);
|
||||
if (rereadC2 == -1 || !Validators.GetValidMediaTypes(knownSystem).Contains(mediaType))
|
||||
Assert.Null(actual.C2OpcodeValue[0]);
|
||||
else
|
||||
Assert.Equal(rereadC2, actual.C2OpcodeValue[0]);
|
||||
Assert.Equal(subchannelLevel, actual.SubchannelReadLevelValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, false)]
|
||||
[InlineData("", false)]
|
||||
[InlineData("cd F test.bin 8 /c2 20", true)]
|
||||
[InlineData("fd A test.img", true)]
|
||||
[InlineData("dvd X super\\test.iso 8 /raw", true)]
|
||||
[InlineData("bd D longer\\path_test.iso 16", true)]
|
||||
[InlineData("stop D", true)]
|
||||
[InlineData("ls", false)]
|
||||
public void ValidateParametersTest(string parameters, bool expected)
|
||||
{
|
||||
var actual = new Parameters(parameters);
|
||||
Assert.Equal(expected, actual.IsValid());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using System;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using Xunit;
|
||||
|
||||
namespace DICUI.Test.Utilities
|
||||
{
|
||||
public class ValidatorsTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(KnownSystem.BandaiApplePippin, MediaType.CDROM)]
|
||||
[InlineData(KnownSystem.MicrosoftXBOX, MediaType.DVD)]
|
||||
[InlineData(KnownSystem.NintendoGameCube, MediaType.NintendoGameCubeGameDisc)]
|
||||
[InlineData(KnownSystem.NintendoWii, MediaType.NintendoWiiOpticalDisc)]
|
||||
[InlineData(KnownSystem.NintendoWiiU, MediaType.NintendoWiiUOpticalDisc)]
|
||||
[InlineData(KnownSystem.SonyPlayStationPortable, MediaType.UMD)]
|
||||
public void GetValidMediaTypesTest(KnownSystem? knownSystem, MediaType? expected)
|
||||
{
|
||||
var actual = Validators.GetValidMediaTypes(knownSystem);
|
||||
Assert.Contains(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateListOfSystemsTest()
|
||||
{
|
||||
int expected = Enum.GetValues(typeof(KnownSystem)).Length - 5; // - 4 -1 for markers categories and KnownSystem.NONE
|
||||
var actual = Validators.CreateListOfSystems();
|
||||
Assert.Equal(expected, actual.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateListOfDrivesTest()
|
||||
{
|
||||
// TODO: Implement
|
||||
Assert.True(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDiscTypeTest()
|
||||
{
|
||||
// TODO: Implement
|
||||
Assert.True(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
DICUI.sln
56
DICUI.sln
@@ -1,56 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.28803.156
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DICUI", "DICUI\DICUI.csproj", "{7B1B75EB-8940-466F-BD51-76471A57F9BE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DICUI.Test", "DICUI.Test\DICUI.Test.csproj", "{7CC064D2-38AB-4A05-8519-28660DE4562A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DICUI.Library", "DICUI.Library\DICUI.Library.csproj", "{51AB0928-13F9-44BF-A407-B6957A43A056}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DICUI.Check", "DICUI.Check\DICUI.Check.csproj", "{8CFDE289-E171-4D49-A40D-5293265C1253}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4D1DCF5A-F0B0-4E81-A05B-F1A7D37C9D9D}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
appveyor.yml = appveyor.yml
|
||||
CHANGELIST.md = CHANGELIST.md
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DICUI.Avalonia", "DICUI.Avalonia\DICUI.Avalonia.csproj", "{2D09902F-D93E-42D9-84C7-E0246A2EF1CD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7B1B75EB-8940-466F-BD51-76471A57F9BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7B1B75EB-8940-466F-BD51-76471A57F9BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7B1B75EB-8940-466F-BD51-76471A57F9BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7B1B75EB-8940-466F-BD51-76471A57F9BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7CC064D2-38AB-4A05-8519-28660DE4562A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7CC064D2-38AB-4A05-8519-28660DE4562A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7CC064D2-38AB-4A05-8519-28660DE4562A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7CC064D2-38AB-4A05-8519-28660DE4562A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{51AB0928-13F9-44BF-A407-B6957A43A056}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{51AB0928-13F9-44BF-A407-B6957A43A056}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{51AB0928-13F9-44BF-A407-B6957A43A056}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{51AB0928-13F9-44BF-A407-B6957A43A056}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8CFDE289-E171-4D49-A40D-5293265C1253}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8CFDE289-E171-4D49-A40D-5293265C1253}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8CFDE289-E171-4D49-A40D-5293265C1253}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8CFDE289-E171-4D49-A40D-5293265C1253}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2D09902F-D93E-42D9-84C7-E0246A2EF1CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2D09902F-D93E-42D9-84C7-E0246A2EF1CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2D09902F-D93E-42D9-84C7-E0246A2EF1CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2D09902F-D93E-42D9-84C7-E0246A2EF1CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {73C62E6A-6584-4D93-83B5-ECB1FBDB469B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="AaruPath" value="Programs\Aaru\Aaru.exe"/>
|
||||
<add key="CreatorPath" value="Programs\Creator\DiscImageCreator.exe"/>
|
||||
<add key="DDPath" value="Programs\DD\dd.exe"/>
|
||||
<add key="SubDumpPath" value="Programs\Subdump\subdump.exe"/>
|
||||
<add key="DefaultOutputPath" value="ISO"/>
|
||||
<add key="InternalProgram" value="DiscImageCreator"/>
|
||||
|
||||
<add key="PreferredDumpSpeedCD" value="48"/>
|
||||
<add key="PreferredDumpSpeedDVD" value="24"/>
|
||||
<add key="PreferredDumpSpeedBD" value="16"/>
|
||||
|
||||
<add key="QuietMode" value="false"/>
|
||||
<add key="ParanoidMode" value="false"/>
|
||||
<add key="ScanForProtection" value="true"/>
|
||||
<add key="SkipMediaTypeDetection" value="false"/>
|
||||
<add key="SkipSystemDetection" value="false"/>
|
||||
<add key="RereadAmountForC2" value="20"/>
|
||||
<add key="VerboseLogging" value="true"/>
|
||||
<add key="OpenLogWindowAtStartup" value="true"/>
|
||||
<add key="AddPlaceholders" value="true"/>
|
||||
<add key="PromptForDiscInformation" value="true"/>
|
||||
<add key="IgnoreFixedDrives" value="false"/>
|
||||
<add key="ResetDriveAfterDump" value="false"/>
|
||||
|
||||
<add key="Username" value=""/>
|
||||
<add key="Password" value=""/>
|
||||
</appSettings>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/></startup></configuration>
|
||||
@@ -1,9 +0,0 @@
|
||||
<Application x:Class="DICUI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DICUI"
|
||||
StartupUri="Windows\MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -1,11 +0,0 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the Category combo box
|
||||
/// </summary>
|
||||
public class CategoryComboBoxItem
|
||||
{
|
||||
private object data;
|
||||
|
||||
public CategoryComboBoxItem(DiscCategory? category) => data = category;
|
||||
|
||||
public static implicit operator DiscCategory? (CategoryComboBoxItem item) => item.data as DiscCategory?;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return (data as DiscCategory?).LongName(); }
|
||||
}
|
||||
|
||||
public bool IsChecked { get; set; }
|
||||
|
||||
public DiscCategory? Value
|
||||
{
|
||||
get { return data as DiscCategory?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.Windows.Media;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the System combo box
|
||||
/// </summary>
|
||||
public class KnownSystemComboBoxItem
|
||||
{
|
||||
private object data;
|
||||
|
||||
public KnownSystemComboBoxItem(KnownSystem? system) => data = system;
|
||||
public KnownSystemComboBoxItem(KnownSystemCategory? category) => data = category;
|
||||
|
||||
public Brush Foreground { get => IsHeader() ? Brushes.Gray : Brushes.Black; }
|
||||
|
||||
public bool IsHeader() => data is KnownSystemCategory?;
|
||||
public bool IsSystem() => data is KnownSystem?;
|
||||
|
||||
public static implicit operator KnownSystem? (KnownSystemComboBoxItem item) => item.data as KnownSystem?;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsHeader())
|
||||
return "---------- " + (data as KnownSystemCategory?).LongName() + " ----------";
|
||||
else
|
||||
return (data as KnownSystem?).LongName();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the Language combo box
|
||||
/// </summary>
|
||||
public class LanguageComboBoxItem
|
||||
{
|
||||
private object data;
|
||||
|
||||
public LanguageComboBoxItem(Language? region) => data = region;
|
||||
|
||||
public static implicit operator Language? (LanguageComboBoxItem item) => item.data as Language?;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return (data as Language?).LongName(); }
|
||||
}
|
||||
|
||||
public bool IsChecked { get; set; }
|
||||
|
||||
public Language? Value
|
||||
{
|
||||
get { return data as Language?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the MediaType combo box
|
||||
/// </summary>
|
||||
public class MediaTypeComboBoxItem
|
||||
{
|
||||
private MediaType? data;
|
||||
|
||||
public MediaTypeComboBoxItem(MediaType? mediaType) => data = mediaType;
|
||||
|
||||
public static implicit operator MediaType? (MediaTypeComboBoxItem item) => item.data;
|
||||
|
||||
public string Name { get { return data.LongName(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the Region combo box
|
||||
/// </summary>
|
||||
public class RegionComboBoxItem
|
||||
{
|
||||
private object data;
|
||||
|
||||
public RegionComboBoxItem(Region? region) => data = region;
|
||||
|
||||
public static implicit operator Region? (RegionComboBoxItem item) => item.data as Region?;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return (data as Region?).LongName();
|
||||
}
|
||||
}
|
||||
|
||||
public Region? Value
|
||||
{
|
||||
get { return data as Region?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Media;
|
||||
using DICUI.Data;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Variables for UI elements
|
||||
/// </summary>
|
||||
public static class Constants
|
||||
{
|
||||
public const string StartDumping = "Start Dumping";
|
||||
public const string StopDumping = "Stop Dumping";
|
||||
|
||||
public const int LogWindowMarginFromMainWindow = 10;
|
||||
|
||||
// Private lists of known drive speed ranges
|
||||
private static IReadOnlyList<int> cd { get; } = new List<int> { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 };
|
||||
private static IReadOnlyList<int> dvd { get; } = cd.Where(s => s <= 24).ToList();
|
||||
private static IReadOnlyList<int> bd { get; } = cd.Where(s => s <= 16).ToList();
|
||||
private static IReadOnlyList<int> unknown { get; } = cd; // TODO: All or {1}? Maybe null?
|
||||
|
||||
/// <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 IReadOnlyList<int> GetSpeedsForMediaType(MediaType? type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.GDROM:
|
||||
return cd;
|
||||
case MediaType.DVD:
|
||||
case MediaType.HDDVD:
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
return dvd;
|
||||
case MediaType.BluRay:
|
||||
return bd;
|
||||
default:
|
||||
return unknown;
|
||||
}
|
||||
}
|
||||
|
||||
// Create collections for UI based on known drive speeds
|
||||
public static DoubleCollection SpeedsForCDAsCollection { get; } = GetDoubleCollectionFromIntList(cd);
|
||||
public static DoubleCollection SpeedsForDVDAsCollection { get; } = GetDoubleCollectionFromIntList(dvd);
|
||||
public static DoubleCollection SpeedsForBDAsCollection { get; } = GetDoubleCollectionFromIntList(bd);
|
||||
private static DoubleCollection GetDoubleCollectionFromIntList(IReadOnlyList<int> list)
|
||||
=> new DoubleCollection(list.Select(i => Convert.ToDouble(i)).ToList());
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;net48;netcoreapp3.1</TargetFrameworks>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<UseWPF>true</UseWPF>
|
||||
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<Title>DICUI</Title>
|
||||
<AssemblyName>DICUI</AssemblyName>
|
||||
<Description>Frontend for various dumping programs</Description>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2020</Copyright>
|
||||
<RepositoryUrl>https://github.com/SabreTools/DICUI</RepositoryUrl>
|
||||
<Version>1.17.0</Version>
|
||||
<AssemblyVersion>1.17.0</AssemblyVersion>
|
||||
<FileVersion>1.17.0</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DICUI.Library\DICUI.Library.csproj">
|
||||
<Project>{51ab0928-13f9-44bf-a407-b6957a43a056}</Project>
|
||||
<Name>DICUI.Library</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to provide a converter to XAML files to render comboboxes with enum values
|
||||
/// </summary>
|
||||
public class EnumDescriptionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
// Common
|
||||
if (value is MediaType?)
|
||||
return ((MediaType?)value).LongName();
|
||||
else if (value is KnownSystem?)
|
||||
return ((KnownSystem?)value).LongName();
|
||||
|
||||
// Default
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
DICUI/Icon.ico
BIN
DICUI/Icon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB |
@@ -1,122 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using DICUI.Data;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
public class UIOptions
|
||||
{
|
||||
// TODO: Is there any way that this can be made private?
|
||||
public Options Options { get; set; }
|
||||
|
||||
#region Passthrough readonly values
|
||||
|
||||
// TODO: Can any of these be removed?
|
||||
public string DefaultOutputPath { get { return Options.DefaultOutputPath; } }
|
||||
public bool IgnoreFixedDrives { get { return Options.IgnoreFixedDrives; } }
|
||||
public bool ResetDriveAfterDump { get { return Options.ResetDriveAfterDump; } }
|
||||
public bool SkipMediaTypeDetection { get { return Options.SkipMediaTypeDetection; } }
|
||||
public bool SkipSystemDetection { get { return Options.SkipSystemDetection; } }
|
||||
public bool OpenLogWindowAtStartup { get { return Options.OpenLogWindowAtStartup; } }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
public UIOptions()
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save a configuration from internal Options
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
||||
|
||||
// Loop through all settings in Options and save them, overwriting existing settings
|
||||
foreach (var kvp in Options)
|
||||
{
|
||||
configFile.AppSettings.Settings.Remove(kvp.Key);
|
||||
configFile.AppSettings.Settings.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
configFile.Save(ConfigurationSaveMode.Modified);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load a configuration into internal Options
|
||||
/// </summary>
|
||||
private void Load()
|
||||
{
|
||||
Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
||||
|
||||
var settings = ConvertToDictionary(configFile);
|
||||
Options = new Options(settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a setting value from the base Options
|
||||
/// </summary>
|
||||
/// <param name="key">Key to retrieve the value for</param>
|
||||
/// <returns>String value if possible, null otherwise</returns>
|
||||
public string Get(string key)
|
||||
{
|
||||
return Options[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a setting value in the base Options
|
||||
/// </summary>
|
||||
/// <param name="key">Key to set the value for</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
public void Set(string key, string value)
|
||||
{
|
||||
Options[key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the preferred dumping speed given a media type
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType representing the current selection</param>
|
||||
/// <returns>Int value representing the dump speed</returns>
|
||||
public int GetPreferredDumpSpeedForMediaType(MediaType? type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.GDROM:
|
||||
return this.Options.PreferredDumpSpeedCD;
|
||||
case MediaType.DVD:
|
||||
case MediaType.HDDVD:
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
return this.Options.PreferredDumpSpeedDVD;
|
||||
case MediaType.BluRay:
|
||||
return this.Options.PreferredDumpSpeedBD;
|
||||
default:
|
||||
return this.Options.PreferredDumpSpeedCD;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the configuration app settings to a dictionary
|
||||
/// </summary>
|
||||
/// <param name="configFile">Configuration to load from</param>
|
||||
/// <returns>Dictionary with all values from app settings</returns>
|
||||
private Dictionary<string, string> ConvertToDictionary(Configuration configFile)
|
||||
{
|
||||
var settings = configFile.AppSettings.Settings;
|
||||
var dict = new Dictionary<string, string>();
|
||||
|
||||
foreach (string key in settings.AllKeys)
|
||||
{
|
||||
dict[key] = settings[key]?.Value ?? string.Empty;
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
using System;
|
||||
using System.Windows.Media;
|
||||
using DICUI.Windows;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
public class OptionsViewModel
|
||||
{
|
||||
private readonly UIOptions _uiOptions;
|
||||
|
||||
#region Internal Program
|
||||
|
||||
public string AaruPath
|
||||
{
|
||||
get { return _uiOptions.Options.AaruPath; }
|
||||
set { _uiOptions.Options.AaruPath = value; }
|
||||
}
|
||||
|
||||
public string CreatorPath
|
||||
{
|
||||
get { return _uiOptions.Options.CreatorPath; }
|
||||
set { _uiOptions.Options.CreatorPath = value; }
|
||||
}
|
||||
|
||||
public string DDPath
|
||||
{
|
||||
get { return _uiOptions.Options.DDPath; }
|
||||
set { _uiOptions.Options.DDPath = value; }
|
||||
}
|
||||
|
||||
public string InternalProgram
|
||||
{
|
||||
get { return _uiOptions.Options.InternalProgram; }
|
||||
set { _uiOptions.Options.InternalProgram = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extra Paths
|
||||
|
||||
public string DefaultOutputPath
|
||||
{
|
||||
get { return _uiOptions.Options.DefaultOutputPath; }
|
||||
set { _uiOptions.Options.DefaultOutputPath = value; }
|
||||
}
|
||||
|
||||
public string SubDumpPath
|
||||
{
|
||||
get { return _uiOptions.Options.SubDumpPath; }
|
||||
set { _uiOptions.Options.SubDumpPath = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dumping Speeds
|
||||
|
||||
public int PreferredDumpSpeedCD
|
||||
{
|
||||
get { return _uiOptions.Options.PreferredDumpSpeedCD; }
|
||||
set { _uiOptions.Options.PreferredDumpSpeedCD = value; }
|
||||
}
|
||||
|
||||
public int PreferredDumpSpeedDVD
|
||||
{
|
||||
get { return _uiOptions.Options.PreferredDumpSpeedDVD; }
|
||||
set { _uiOptions.Options.PreferredDumpSpeedDVD = value; }
|
||||
}
|
||||
|
||||
public int PreferredDumpSpeedBD
|
||||
{
|
||||
get { return _uiOptions.Options.PreferredDumpSpeedBD; }
|
||||
set { _uiOptions.Options.PreferredDumpSpeedBD = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extra Dumping Options
|
||||
|
||||
public bool QuietMode
|
||||
{
|
||||
get { return _uiOptions.Options.QuietMode; }
|
||||
set { _uiOptions.Options.QuietMode = value; }
|
||||
}
|
||||
|
||||
public bool ParanoidMode
|
||||
{
|
||||
get { return _uiOptions.Options.ParanoidMode; }
|
||||
set { _uiOptions.Options.ParanoidMode = value; }
|
||||
}
|
||||
|
||||
public bool ScanForProtection
|
||||
{
|
||||
get { return _uiOptions.Options.ScanForProtection; }
|
||||
set { _uiOptions.Options.ScanForProtection = value; }
|
||||
}
|
||||
|
||||
public string RereadAmountForC2
|
||||
{
|
||||
get { return Convert.ToString(_uiOptions.Options.RereadAmountForC2); }
|
||||
set
|
||||
{
|
||||
if (Int32.TryParse(value, out int result))
|
||||
_uiOptions.Options.RereadAmountForC2 = result;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddPlaceholders
|
||||
{
|
||||
get { return _uiOptions.Options.AddPlaceholders; }
|
||||
set { _uiOptions.Options.AddPlaceholders = value; }
|
||||
}
|
||||
|
||||
public bool PromptForDiscInformation
|
||||
{
|
||||
get { return _uiOptions.Options.PromptForDiscInformation; }
|
||||
set { _uiOptions.Options.PromptForDiscInformation = value; }
|
||||
}
|
||||
|
||||
public bool IgnoreFixedDrives
|
||||
{
|
||||
get { return _uiOptions.Options.IgnoreFixedDrives; }
|
||||
set { _uiOptions.Options.IgnoreFixedDrives = value; }
|
||||
}
|
||||
|
||||
public bool ResetDriveAfterDump
|
||||
{
|
||||
get { return _uiOptions.Options.ResetDriveAfterDump; }
|
||||
set { _uiOptions.Options.ResetDriveAfterDump = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Skip Options
|
||||
|
||||
public bool SkipMediaTypeDetection
|
||||
{
|
||||
get { return _uiOptions.Options.SkipMediaTypeDetection; }
|
||||
set { _uiOptions.Options.SkipMediaTypeDetection = value; }
|
||||
}
|
||||
|
||||
public bool SkipSystemDetection
|
||||
{
|
||||
get { return _uiOptions.Options.SkipSystemDetection; }
|
||||
set { _uiOptions.Options.SkipSystemDetection = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Logging Options
|
||||
|
||||
public bool VerboseLogging
|
||||
{
|
||||
get { return _uiOptions.Options.VerboseLogging; }
|
||||
set
|
||||
{
|
||||
_uiOptions.Options.VerboseLogging = value;
|
||||
_uiOptions.Save(); // TODO: Why does this save here?
|
||||
}
|
||||
}
|
||||
|
||||
public bool OpenLogWindowAtStartup
|
||||
{
|
||||
get { return _uiOptions.Options.OpenLogWindowAtStartup; }
|
||||
set
|
||||
{
|
||||
_uiOptions.Options.OpenLogWindowAtStartup = value;
|
||||
_uiOptions.Save(); // TODO: Why does this save here?
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Redump Login Information
|
||||
|
||||
public string Username
|
||||
{
|
||||
get { return _uiOptions.Options.Username; }
|
||||
set { _uiOptions.Options.Username = value; }
|
||||
}
|
||||
|
||||
public string Password
|
||||
{
|
||||
get { return _uiOptions.Options.Password; }
|
||||
set { _uiOptions.Options.Password = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public OptionsViewModel(UIOptions uiOptions)
|
||||
{
|
||||
this._uiOptions = uiOptions;
|
||||
}
|
||||
}
|
||||
|
||||
public class LoggerViewModel
|
||||
{
|
||||
private LogWindow _logWindow;
|
||||
|
||||
public void SetWindow(LogWindow logWindow) => _logWindow = logWindow;
|
||||
|
||||
public bool WindowVisible
|
||||
{
|
||||
get => _logWindow != null ? _logWindow.IsVisible : false;
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
_logWindow.AdjustPositionToMainWindow();
|
||||
_logWindow.Show();
|
||||
}
|
||||
else
|
||||
_logWindow.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
public void VerboseLog(string text)
|
||||
{
|
||||
if (ViewModels.OptionsViewModel.VerboseLogging)
|
||||
_logWindow.AppendToTextBox(text, Brushes.Yellow);
|
||||
}
|
||||
|
||||
public void VerboseLog(string format, params object[] args) => VerboseLog(string.Format(format, args));
|
||||
public void VerboseLogLn(string format, params object[] args) => VerboseLog(string.Format(format, args) + "\n");
|
||||
}
|
||||
|
||||
public static class ViewModels
|
||||
{
|
||||
public static OptionsViewModel OptionsViewModel { get; set; }
|
||||
public static LoggerViewModel LoggerViewModel { get; set; } = new LoggerViewModel();
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
<Window x:Class="DICUI.Windows.DiscInformationWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:DICUI"
|
||||
mc:Ignorable="d"
|
||||
Title="Disc Information" Height="733" Width="515.132" ResizeMode="NoResize"
|
||||
Closed="OnClosed">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="585"/>
|
||||
<RowDefinition Height="80"/>
|
||||
<RowDefinition Height="25"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<GroupBox Grid.Row="0" Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Common Disc Information">
|
||||
<Grid Margin="10,15,10,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
<RowDefinition Height="25"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Title" />
|
||||
<TextBox x:Name="TitleTextBox" Grid.Row="0" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Foreign Title (Non-Latin)" />
|
||||
<TextBox x:Name="ForeignTitleTextBox" Grid.Row="1" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Disc Number / Letter" />
|
||||
<TextBox x:Name="DiscNumberLetterTextBox" Grid.Row="2" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Disc Title" />
|
||||
<TextBox x:Name="DiscTitleTextBox" Grid.Row="3" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Category" />
|
||||
<ComboBox x:Name="CategoryComboBox" Grid.Row="4" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" >
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<Label Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Region" />
|
||||
<ComboBox x:Name="RegionComboBox" Grid.Row="5" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" >
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<Label Grid.Row="6" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Languages" />
|
||||
<ComboBox x:Name="LanguagesComboBox" Grid.Row="6" Grid.Column="1" Height="24" HorizontalAlignment="Stretch" >
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Path=Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<Label Grid.Row="7" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Serial" />
|
||||
<TextBox x:Name="SerialTextBox" Grid.Row="7" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<!-- Layer 0 / Data Side -->
|
||||
<Label Grid.Row="8" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Data/L0 Mastering Ring" />
|
||||
<TextBox x:Name="L0MasteringRingTextBox" Grid.Row="8" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" AcceptsTab="True" />
|
||||
|
||||
<Label Grid.Row="9" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Data/L0 Mastering SID" />
|
||||
<TextBox x:Name="L0MasteringSIDTextBox" Grid.Row="9" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="10" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Data/L0 Toolstamp/Mastering Code" />
|
||||
<TextBox x:Name="L0ToolstampTextBox" Grid.Row="10" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="11" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Data/L0 Mould SID" />
|
||||
<TextBox x:Name="L0MouldSIDTextBox" Grid.Row="11" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="12" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Data/L0 Additional Mould" />
|
||||
<TextBox x:Name="L0AdditionalMouldTextBox" Grid.Row="12" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<!-- Layer 1 / Label Side -->
|
||||
<Label Grid.Row="13" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Label/L1 Mastering Ring" />
|
||||
<TextBox x:Name="L1MasteringRingTextBox" Grid.Row="13" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" AcceptsTab="True" />
|
||||
|
||||
<Label Grid.Row="14" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Label/L1 Mastering SID" />
|
||||
<TextBox x:Name="L1MasteringSIDTextBox" Grid.Row="14" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="15" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Label/L1 Toolstamp/Mastering Code" />
|
||||
<TextBox x:Name="L1ToolstampTextBox" Grid.Row="15" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="16" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Label/L1 Mould SID" />
|
||||
<TextBox x:Name="L1MouldSIDTextBox" Grid.Row="16" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="17" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Label/L1 Additional Mould" />
|
||||
<TextBox x:Name="L1AdditionalMouldTextBox" Grid.Row="17" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="18" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Barcode" />
|
||||
<TextBox x:Name="BarcodeTextBox" Grid.Row="18" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<!-- This needs to be a multiline textbox -->
|
||||
<Label Grid.Row="19" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Comments" />
|
||||
<TextBox x:Name="CommentsTextBox" Grid.Row="19" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" AcceptsReturn="True" AcceptsTab="True" />
|
||||
|
||||
<!-- This needs to be a multiline textbox -->
|
||||
<Label Grid.Row="20" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Contents" />
|
||||
<TextBox x:Name="ContentsTextBox" Grid.Row="20" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" AcceptsReturn="True" AcceptsTab="True"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Grid.Row="1" Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Version and Editions">
|
||||
<Grid Height="60">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="24"/>
|
||||
<RowDefinition Height="24"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Version" />
|
||||
<TextBox x:Name="VersionTextBox" Grid.Row="0" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Edition" />
|
||||
<TextBox x:Name="EditionTextBox" Grid.Row="1" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<!-- Accept / Cancel -->
|
||||
<Grid Height="28" Grid.Row="2" Grid.Column="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Name="AcceptButton" Grid.Row="0" Grid.Column="1" Height="25" Width="80" Content="Accept" Click="OnAcceptClick" />
|
||||
<Button Name="CancelButton" Grid.Row="0" Grid.Column="2" Height="25" Width="80" Content="Cancel" Click="OnCancelClick" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,231 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for DiscInformationWindow.xaml
|
||||
/// </summary>
|
||||
public partial class DiscInformationWindow : Window
|
||||
{
|
||||
/// <summary>
|
||||
/// List of available disc categories
|
||||
/// </summary>
|
||||
public List<CategoryComboBoxItem> Categories { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// SubmissionInfo object to fill and save
|
||||
/// </summary>
|
||||
public SubmissionInfo SubmissionInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of available regions
|
||||
/// </summary>
|
||||
public List<RegionComboBoxItem> Regions { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of available languages
|
||||
/// </summary>
|
||||
public List<LanguageComboBoxItem> Languages { get; private set; }
|
||||
|
||||
public DiscInformationWindow(SubmissionInfo submissionInfo)
|
||||
{
|
||||
InitializeComponent();
|
||||
SubmissionInfo = submissionInfo;
|
||||
|
||||
PopulateCategories();
|
||||
PopulateRegions();
|
||||
PopulateLanguages();
|
||||
DisableFieldsIfNeeded();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable fields that aren't applicable to the current disc
|
||||
/// </summary>
|
||||
private void DisableFieldsIfNeeded()
|
||||
{
|
||||
// Only disable for single-layer discs
|
||||
if (SubmissionInfo.SizeAndChecksums.Layerbreak == default(long))
|
||||
{
|
||||
L1MasteringRingTextBox.IsEnabled = false;
|
||||
L1MasteringRingTextBox.Background = Brushes.Gray;
|
||||
|
||||
L1MasteringSIDTextBox.IsEnabled = false;
|
||||
L1MasteringSIDTextBox.Background = Brushes.Gray;
|
||||
|
||||
L1ToolstampTextBox.IsEnabled = false;
|
||||
L1ToolstampTextBox.Background = Brushes.Gray;
|
||||
|
||||
L1MouldSIDTextBox.IsEnabled = false;
|
||||
L1MouldSIDTextBox.Background = Brushes.Gray;
|
||||
|
||||
L1AdditionalMouldTextBox.IsEnabled = false;
|
||||
L1AdditionalMouldTextBox.Background = Brushes.Gray;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the current contents of the base SubmissionInfo to the UI
|
||||
/// </summary>
|
||||
public void Load()
|
||||
{
|
||||
TitleTextBox.Text = SubmissionInfo.CommonDiscInfo.Title ?? "";
|
||||
ForeignTitleTextBox.Text = SubmissionInfo.CommonDiscInfo.ForeignTitleNonLatin ?? "";
|
||||
DiscNumberLetterTextBox.Text = SubmissionInfo.CommonDiscInfo.DiscNumberLetter ?? "";
|
||||
DiscTitleTextBox.Text = SubmissionInfo.CommonDiscInfo.DiscTitle ?? "";
|
||||
CategoryComboBox.SelectedIndex = Categories.FindIndex(r => r == SubmissionInfo.CommonDiscInfo.Category);
|
||||
RegionComboBox.SelectedIndex = Regions.FindIndex(r => r == SubmissionInfo.CommonDiscInfo.Region);
|
||||
if (SubmissionInfo.CommonDiscInfo.Languages != null)
|
||||
{
|
||||
foreach (var language in SubmissionInfo.CommonDiscInfo.Languages)
|
||||
Languages.Find(l => l == language).IsChecked = true;
|
||||
}
|
||||
SerialTextBox.Text = SubmissionInfo.CommonDiscInfo.Serial ?? "";
|
||||
L0MasteringRingTextBox.Text = SubmissionInfo.CommonDiscInfo.MasteringRingFirstLayerDataSide ?? "";
|
||||
L0MasteringSIDTextBox.Text = SubmissionInfo.CommonDiscInfo.MasteringSIDCodeFirstLayerDataSide ?? "";
|
||||
L0ToolstampTextBox.Text = SubmissionInfo.CommonDiscInfo.ToolstampMasteringCodeFirstLayerDataSide ?? "";
|
||||
L0MouldSIDTextBox.Text = SubmissionInfo.CommonDiscInfo.MouldSIDCodeFirstLayerDataSide ?? "";
|
||||
L0AdditionalMouldTextBox.Text = SubmissionInfo.CommonDiscInfo.AdditionalMouldFirstLayerDataSide ?? "";
|
||||
L1MasteringRingTextBox.Text = SubmissionInfo.CommonDiscInfo.MasteringRingSecondLayerLabelSide ?? "";
|
||||
L1MasteringSIDTextBox.Text = SubmissionInfo.CommonDiscInfo.MasteringSIDCodeSecondLayerLabelSide ?? "";
|
||||
L1ToolstampTextBox.Text = SubmissionInfo.CommonDiscInfo.ToolstampMasteringCodeSecondLayerLabelSide ?? "";
|
||||
L1MouldSIDTextBox.Text = SubmissionInfo.CommonDiscInfo.MouldSIDCodeSecondLayerLabelSide ?? "";
|
||||
L1AdditionalMouldTextBox.Text = SubmissionInfo.CommonDiscInfo.AdditionalMouldSecondLayerLabelSide ?? "";
|
||||
BarcodeTextBox.Text = SubmissionInfo.CommonDiscInfo.Barcode ?? "";
|
||||
CommentsTextBox.Text = SubmissionInfo.CommonDiscInfo.Comments ?? "";
|
||||
ContentsTextBox.Text = SubmissionInfo.CommonDiscInfo.Contents ?? "";
|
||||
|
||||
VersionTextBox.Text = SubmissionInfo.VersionAndEditions.Version ?? "";
|
||||
EditionTextBox.Text = SubmissionInfo.VersionAndEditions.OtherEditions ?? "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of categories and fill the combo box
|
||||
/// </summary>
|
||||
private void PopulateCategories()
|
||||
{
|
||||
var categories = Enum.GetValues(typeof(DiscCategory)).OfType<DiscCategory?>().ToList();
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Populating categories, {0} categories found.", categories.Count);
|
||||
|
||||
Categories = new List<CategoryComboBoxItem>();
|
||||
foreach (var category in categories)
|
||||
{
|
||||
Categories.Add(new CategoryComboBoxItem(category));
|
||||
}
|
||||
|
||||
CategoryComboBox.ItemsSource = Categories;
|
||||
CategoryComboBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of languages and fill the combo box
|
||||
/// </summary>
|
||||
private void PopulateLanguages()
|
||||
{
|
||||
var languages = Enum.GetValues(typeof(Language)).OfType<Language?>().ToList();
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Populating languages, {0} languages found.", languages.Count);
|
||||
|
||||
Languages = new List<LanguageComboBoxItem>();
|
||||
foreach (var language in languages)
|
||||
{
|
||||
Languages.Add(new LanguageComboBoxItem(language));
|
||||
}
|
||||
|
||||
LanguagesComboBox.ItemsSource = Languages;
|
||||
LanguagesComboBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of regions and fill the combo box
|
||||
/// </summary>
|
||||
private void PopulateRegions()
|
||||
{
|
||||
var regions = Enum.GetValues(typeof(Region)).OfType<Region?>().ToList();
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Populating regions, {0} regions found.", regions.Count);
|
||||
|
||||
Regions = new List<RegionComboBoxItem>();
|
||||
foreach (var region in regions)
|
||||
{
|
||||
Regions.Add(new RegionComboBoxItem(region));
|
||||
}
|
||||
|
||||
RegionComboBox.ItemsSource = Regions;
|
||||
RegionComboBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the current contents of the UI to the base SubmissionInfo
|
||||
/// </summary>
|
||||
private void Save()
|
||||
{
|
||||
SubmissionInfo.CommonDiscInfo.Title = TitleTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.ForeignTitleNonLatin = ForeignTitleTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.DiscNumberLetter = DiscNumberLetterTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.DiscTitle = DiscTitleTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.Category = (CategoryComboBox.SelectedItem as CategoryComboBoxItem)?.Value ?? DiscCategory.Games;
|
||||
SubmissionInfo.CommonDiscInfo.Region = (RegionComboBox.SelectedItem as RegionComboBoxItem)?.Value ?? Region.World;
|
||||
var languages = new List<Language?>();
|
||||
foreach (var language in Languages)
|
||||
{
|
||||
if (language.IsChecked)
|
||||
languages.Add(language.Value);
|
||||
}
|
||||
if (languages.Count == 0)
|
||||
languages.Add(null);
|
||||
SubmissionInfo.CommonDiscInfo.Languages = languages.ToArray();
|
||||
SubmissionInfo.CommonDiscInfo.Serial = SerialTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MasteringRingFirstLayerDataSide = L0MasteringRingTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MasteringSIDCodeFirstLayerDataSide = L0MasteringSIDTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.ToolstampMasteringCodeFirstLayerDataSide = L0ToolstampTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MouldSIDCodeFirstLayerDataSide = L0MouldSIDTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.AdditionalMouldFirstLayerDataSide = L0AdditionalMouldTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MasteringRingSecondLayerLabelSide = L1MasteringRingTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MasteringSIDCodeSecondLayerLabelSide = L1MasteringSIDTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.ToolstampMasteringCodeSecondLayerLabelSide = L1ToolstampTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.MouldSIDCodeSecondLayerLabelSide = L1MouldSIDTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.AdditionalMouldSecondLayerLabelSide = L1AdditionalMouldTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.Barcode = BarcodeTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.Comments = CommentsTextBox.Text ?? "";
|
||||
SubmissionInfo.CommonDiscInfo.Contents = ContentsTextBox.Text ?? "";
|
||||
|
||||
SubmissionInfo.VersionAndEditions.Version = VersionTextBox.Text ?? "";
|
||||
SubmissionInfo.VersionAndEditions.OtherEditions = EditionTextBox.Text ?? "";
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Handler for AcceptButton Click event
|
||||
/// </summary>
|
||||
private void OnAcceptClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Save();
|
||||
Hide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for CancelButton Click event
|
||||
/// </summary>
|
||||
private void OnCancelClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for DiscInformationWindow Closed event
|
||||
/// </summary>
|
||||
private void OnClosed(object sender, EventArgs e)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
<Window x:Class="DICUI.Windows.LogWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DICUI"
|
||||
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
|
||||
Title="Log Window" Height="350" Width="600" Closed="OnWindowClosed" Loaded="OnWindowLoaded"
|
||||
>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="40" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="40" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0" Height="22" Margin="10 10 10 0">
|
||||
<ProgressBar x:Name="progressBar" />
|
||||
<TextBlock x:Name="progressLabel" Grid.Row="0" Height="22" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="0 2 0 0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="White" BorderBrush="Gainsboro" BorderThickness="1" Margin="10">
|
||||
<ScrollViewer Name="outputViewer" SizeChanged="ScrollViewer_SizeChanged">
|
||||
<RichTextBox Name="output" FontFamily="Consolas" Background="#202020" IsReadOnly="true" TextChanged="OnTextChanged" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="3*"/>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<CheckBox Content="Verbose" Margin="10 0 0 10" Grid.Column="0" VerticalAlignment="Center"
|
||||
ToolTip="Enable verbose logging of tasks"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=VerboseLogging}"
|
||||
/>
|
||||
<CheckBox Content="Open at startup" Margin="10 0 0 10" Grid.Column="1" Grid.ColumnSpan="2" VerticalAlignment="Center"
|
||||
ToolTip="Open this window at startup"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=OpenLogWindowAtStartup}"
|
||||
/>
|
||||
<Button Margin="0 0 10 10" Grid.Column="3" Height="22" Width="60" Content="Clear" HorizontalAlignment="Right" Click="OnClearButton" />
|
||||
<Button Margin="0 0 10 10" Grid.Column="4" Height="22" Width="60" Content="Hide" HorizontalAlignment="Right" Click="OnHideButton" />
|
||||
<Button Margin="0 0 10 10" Grid.Column="5" Height="22" Width="60" Content="Save" HorizontalAlignment="Right" Click="OnSaveButton" />
|
||||
<Button Visibility="Hidden" Name="AbortButton" Margin="0 0 10 10" Grid.Column="2" Height="22" Width="80" Content="Abort" HorizontalAlignment="Right" Click="OnAbortButton" />
|
||||
</Grid>
|
||||
|
||||
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,399 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace DICUI.Windows
|
||||
{
|
||||
public partial class LogWindow : Window
|
||||
{
|
||||
private const int GWL_STYLE = -16;
|
||||
private const int WS_SYSMENU = 0x80000;
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||
|
||||
private readonly MainWindow _mainWindow;
|
||||
|
||||
private readonly FlowDocument _document;
|
||||
private readonly Paragraph _paragraph;
|
||||
private readonly List<Matcher> _matchers;
|
||||
|
||||
volatile Process _process;
|
||||
|
||||
public LogWindow(MainWindow mainWindow)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this._mainWindow = mainWindow;
|
||||
|
||||
_document = new FlowDocument();
|
||||
_paragraph = new Paragraph();
|
||||
_document.Blocks.Add(_paragraph);
|
||||
output.Document = _document;
|
||||
|
||||
_matchers = new List<Matcher>();
|
||||
|
||||
_matchers.Add(new Matcher(
|
||||
"Descrambling data sector of img (LBA)",
|
||||
@"\s*(\d+)\/\s*(\d+)$",
|
||||
match => {
|
||||
if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total))
|
||||
{
|
||||
float percentProgress = (current / (float)total) * 100;
|
||||
progressBar.Value = percentProgress;
|
||||
progressLabel.Text = string.Format("Descrambling image.. ({0:##.##}%)", percentProgress);
|
||||
}
|
||||
}));
|
||||
|
||||
_matchers.Add(new Matcher(
|
||||
@"Creating .scm (LBA)",
|
||||
@"\s*(\d+)\/\s*(\d+)$",
|
||||
match => {
|
||||
if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total))
|
||||
{
|
||||
float percentProgress = (current / (float)total) * 100;
|
||||
progressBar.Value = percentProgress;
|
||||
progressLabel.Text = string.Format("Creating scrambled image.. ({0:##.##}%)", percentProgress);
|
||||
}
|
||||
}));
|
||||
|
||||
_matchers.Add(new Matcher(
|
||||
"Checking sectors (LBA)",
|
||||
@"\s*(\d+)\/\s*(\d+)$",
|
||||
match => {
|
||||
if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total))
|
||||
{
|
||||
float percentProgress = (current / (float)total) * 100;
|
||||
progressBar.Value = percentProgress;
|
||||
progressLabel.Text = string.Format("Checking for errors.. ({0:##.##}%)", percentProgress);
|
||||
}
|
||||
}));
|
||||
|
||||
_matchers.Add(new Matcher(
|
||||
"Scanning sector (LBA)",
|
||||
@"\s*(\d+)\/\s*(\d+)$",
|
||||
match => {
|
||||
if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total))
|
||||
{
|
||||
float percentProgress = (current / (float)total) * 100;
|
||||
progressBar.Value = percentProgress;
|
||||
progressLabel.Text = string.Format("Scanning sectors for protection.. ({0:##.##}%)", percentProgress);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void StartDump(string args)
|
||||
{
|
||||
AppendToTextBox(string.Format("Launching DIC with args: {0}\r\n", args), Brushes.Orange);
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
_process = new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = @"Programs/DiscImageCreator.exe",
|
||||
Arguments = args,
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
},
|
||||
};
|
||||
|
||||
StreamState stdoutState = new StreamState(false);
|
||||
StreamState stderrState = new StreamState(true);
|
||||
|
||||
//_cmd.ErrorDataReceived += (process, text) => Dispatcher.Invoke(() => UpdateConsole(text.Data, Brushes.Red));
|
||||
_process.Start();
|
||||
|
||||
var _1 = ConsumeOutput(_process.StandardOutput, s => Dispatcher.Invoke(() => UpdateConsole(s, stdoutState)));
|
||||
var _2 = ConsumeOutput(_process.StandardError, s => Dispatcher.Invoke(() => UpdateConsole(s, stderrState)));
|
||||
|
||||
_process.EnableRaisingEvents = true;
|
||||
_process.Exited += OnProcessExit;
|
||||
});
|
||||
}
|
||||
|
||||
public void AdjustPositionToMainWindow()
|
||||
{
|
||||
this.Left = _mainWindow.Left;
|
||||
this.Top = _mainWindow.Top + _mainWindow.Height + Constants.LogWindowMarginFromMainWindow;
|
||||
}
|
||||
|
||||
private void GracefullyTerminateProcess()
|
||||
{
|
||||
if (_process != null)
|
||||
{
|
||||
_process.Exited -= OnProcessExit;
|
||||
bool isForced = !_process.HasExited;
|
||||
|
||||
if (isForced)
|
||||
{
|
||||
AppendToTextBox("\r\nForcefully Killing the process\r\n", Brushes.Red);
|
||||
_process.Kill();
|
||||
_process.WaitForExit();
|
||||
}
|
||||
|
||||
AppendToTextBox(string.Format("\r\nExit Code: {0}\r\n", _process.ExitCode), _process.ExitCode == 0 ? Brushes.Green : Brushes.Red);
|
||||
|
||||
if (_process.ExitCode == 0)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
progressLabel.Text = "Done!";
|
||||
progressBar.Value = 100;
|
||||
progressBar.Foreground = Brushes.Green;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
progressLabel.Text = isForced ? "Aborted by user" : "Error, please check log!";
|
||||
progressBar.Value = 100;
|
||||
progressBar.Foreground = Brushes.Red;
|
||||
});
|
||||
}
|
||||
|
||||
_process.Close();
|
||||
}
|
||||
|
||||
_process = null;
|
||||
}
|
||||
|
||||
private void ScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
outputViewer.ScrollToBottom();
|
||||
}
|
||||
|
||||
async Task ConsumeOutput(TextReader reader, Action<string> callback)
|
||||
{
|
||||
char[] buffer = new char[256];
|
||||
int cch;
|
||||
|
||||
while ((cch = await reader.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
callback(new string(buffer, 0, cch));
|
||||
}
|
||||
}
|
||||
|
||||
// this is used to optimize the work since we need to process A LOT of text
|
||||
struct Matcher
|
||||
{
|
||||
private readonly string prefix;
|
||||
private readonly Regex regex;
|
||||
private readonly int start;
|
||||
private readonly Action<Match> lambda;
|
||||
|
||||
public Matcher(string prefix, string regex, Action<Match> lambda)
|
||||
{
|
||||
this.prefix = prefix;
|
||||
this.regex = new Regex(regex);
|
||||
this.start = prefix.Length;
|
||||
this.lambda = lambda;
|
||||
}
|
||||
|
||||
public bool Matches(ref string text) => text.StartsWith(prefix);
|
||||
|
||||
public void Apply(ref string text)
|
||||
{
|
||||
Match match = regex.Match(text, start);
|
||||
lambda.Invoke(match);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessStringForProgressBar(string text)
|
||||
{
|
||||
foreach (Matcher matcher in _matchers)
|
||||
{
|
||||
if (matcher.Matches(ref text))
|
||||
{
|
||||
matcher.Apply(ref text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class StreamState
|
||||
{
|
||||
public enum State
|
||||
{
|
||||
BEGIN,
|
||||
READ_CARRIAGE,
|
||||
};
|
||||
|
||||
public State state;
|
||||
public readonly StringBuilder buffer;
|
||||
public readonly bool isError;
|
||||
|
||||
public StreamState(bool isError)
|
||||
{
|
||||
this.state = State.BEGIN;
|
||||
this.buffer = new StringBuilder();
|
||||
this.isError = isError;
|
||||
}
|
||||
|
||||
public bool HasData() => buffer.Length > 0;
|
||||
public string Fetch() => buffer.ToString();
|
||||
public void Clear() => buffer.Clear();
|
||||
public void Append(char c) => buffer.Append(c);
|
||||
|
||||
public bool Is(State state) => this.state == state;
|
||||
public void Set(State state) => this.state = state;
|
||||
}
|
||||
|
||||
public void AppendToTextBox(string text, Brush color)
|
||||
{
|
||||
if (Application.Current.Dispatcher.CheckAccess())
|
||||
{
|
||||
Run run = new Run(text) { Foreground = color };
|
||||
_paragraph.Inlines.Add(run);
|
||||
}
|
||||
else
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
Run run = new Run(text) { Foreground = color };
|
||||
_paragraph.Inlines.Add(run);
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateConsole(string text, StreamState state)
|
||||
{
|
||||
/*if (c == '\r') { output.Inlines.Add(@"\r"); file.Write("\\r"); }
|
||||
else if (c == '\n') { output.Inlines.Add(@"\n"); file.Write("\\n\n"); }
|
||||
output.Inlines.Add(""+c);
|
||||
file.Write(c);
|
||||
file.Flush();
|
||||
continue;*/
|
||||
|
||||
if (text != null)
|
||||
{
|
||||
foreach (char c in text)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\r' when (state.Is(StreamState.State.BEGIN)):
|
||||
{
|
||||
state.Set(StreamState.State.READ_CARRIAGE);
|
||||
break;
|
||||
}
|
||||
|
||||
case '\n' when (state.Is(StreamState.State.READ_CARRIAGE)):
|
||||
{
|
||||
if (state.buffer.Length > 0)
|
||||
{
|
||||
string buffer = state.Fetch();
|
||||
|
||||
AppendToTextBox(buffer, state.isError ? Brushes.Red : Brushes.White);
|
||||
|
||||
if (!state.isError)
|
||||
ProcessStringForProgressBar(buffer);
|
||||
}
|
||||
_paragraph.Inlines.Add(new LineBreak());
|
||||
state.Clear();
|
||||
state.Set(StreamState.State.BEGIN);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (state.Is(StreamState.State.READ_CARRIAGE) && state.HasData())
|
||||
{
|
||||
if (!(_paragraph.Inlines.LastInline is LineBreak))
|
||||
_paragraph.Inlines.Remove(_paragraph.Inlines.LastInline);
|
||||
|
||||
string buffer = state.Fetch();
|
||||
|
||||
AppendToTextBox(buffer, state.isError ? Brushes.Red : Brushes.White);
|
||||
|
||||
if (!state.isError)
|
||||
ProcessStringForProgressBar(buffer);
|
||||
|
||||
state.Clear();
|
||||
}
|
||||
|
||||
state.Set(StreamState.State.BEGIN);
|
||||
state.Append(c);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region EventHandlers
|
||||
|
||||
private void OnWindowClosed(object sender, EventArgs e)
|
||||
{
|
||||
GracefullyTerminateProcess();
|
||||
}
|
||||
|
||||
private void OnWindowLoaded(object sender, EventArgs e)
|
||||
{
|
||||
var hwnd = new WindowInteropHelper(this).Handle;
|
||||
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
|
||||
}
|
||||
|
||||
void OnProcessExit(object sender, EventArgs e)
|
||||
{
|
||||
Dispatcher.Invoke(() => AbortButton.IsEnabled = false);
|
||||
GracefullyTerminateProcess();
|
||||
}
|
||||
|
||||
private void OnHideButton(object sender, EventArgs e)
|
||||
{
|
||||
ViewModels.LoggerViewModel.WindowVisible = false;
|
||||
//TODO: this should be bound directly to WindowVisible property in two way fashion
|
||||
// we need to study how to properly do it in XAML
|
||||
_mainWindow.ShowLogMenuItem.IsChecked = false;
|
||||
}
|
||||
|
||||
private void OnClearButton(object sender, EventArgs e)
|
||||
{
|
||||
output.Document.Blocks.Clear();
|
||||
}
|
||||
|
||||
private void OnSaveButton(object sender, EventArgs e)
|
||||
{
|
||||
using (StreamWriter tw = new StreamWriter(File.OpenWrite("console.log")))
|
||||
{
|
||||
foreach (var inline in _paragraph.Inlines)
|
||||
{
|
||||
if (inline is Run run)
|
||||
{
|
||||
tw.Write(run.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAbortButton(object sender, EventArgs args)
|
||||
{
|
||||
GracefullyTerminateProcess();
|
||||
}
|
||||
|
||||
private void OnStartButton(object sender, EventArgs args)
|
||||
{
|
||||
StartDump("cd e Gam.iso 16");
|
||||
}
|
||||
|
||||
private void OnTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
outputViewer.ScrollToBottom();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
<Window x:Class="DICUI.Windows.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:DICUI"
|
||||
mc:Ignorable="d"
|
||||
Title="DICUI" Height="450" Width="600" WindowStartupLocation="CenterScreen" ResizeMode="CanMinimize"
|
||||
LocationChanged="MainWindowLocationChanged" Activated="MainWindowActivated" Closing="MainWindowClosing">
|
||||
|
||||
<Window.Resources>
|
||||
<local:EnumDescriptionConverter x:Key="enumConverter" />
|
||||
</Window.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="4*"/>
|
||||
<ColumnDefinition Width="13*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="30"/>
|
||||
<RowDefinition Height="4*"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel VerticalAlignment="Top" Grid.ColumnSpan="4">
|
||||
<Menu Width="Auto" Height="20" >
|
||||
<MenuItem Header="_File">
|
||||
<MenuItem x:Name="AppExit" Header="E_xit" HorizontalAlignment="Left" Width="185" Click="AppExitClick" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Tools">
|
||||
<MenuItem x:Name="OptionsMenuItem" Header="_Options" HorizontalAlignment="Left" Width="185" Click="OptionsMenuItemClick" />
|
||||
<MenuItem x:Name="ShowLogMenuItem" Header="Show _Log Window" IsCheckable="true" Width="185" HorizontalAlignment="Left"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.LoggerViewModel}}"
|
||||
IsChecked="{Binding Path=WindowVisible}"
|
||||
/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Help">
|
||||
<MenuItem x:Name="About" Header="_About" HorizontalAlignment="Left" Width="185" Click="AboutClick" />
|
||||
<MenuItem x:Name="CheckForUpdatesMenuItem" Header="_Check for Updates" HorizontalAlignment="Left" Width="185" Click="CheckForUpdatesClick" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</StackPanel>
|
||||
<GroupBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,5,5.2,5.4" HorizontalAlignment="Stretch" Header="Settings"/>
|
||||
<GroupBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,4.6,5.2,4.8" HorizontalAlignment="Stretch" Header="Controls"/>
|
||||
<GroupBox Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,5.2,5.2,4.8" HorizontalAlignment="Stretch" Header="Status"/>
|
||||
|
||||
<Grid Grid.Row="1" Grid.Column="0" Margin="15,25,15.2,10.4" Grid.ColumnSpan="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="2.5*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Content="System/Media Type" />
|
||||
<ComboBox x:Name="SystemTypeComboBox" Grid.Row="0" Grid.Column="1" Height="22" Width="250" HorizontalAlignment="Left" SelectionChanged="SystemTypeComboBoxSelectionChanged">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=Name}" Foreground="{Binding Path=Foreground}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<ComboBox x:Name="MediaTypeComboBox" Grid.Row="0" Grid.Column="1" Height="22" Width="140" HorizontalAlignment="Right" SelectionChanged="MediaTypeComboBoxSelectionChanged">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={StaticResource enumConverter}}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center">Output Filename</Label>
|
||||
<TextBox x:Name="OutputFilenameTextBox" Grid.Row="1" Grid.Column="1" Height="22" TextChanged="OutputFilenameTextBoxTextChanged" />
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0" VerticalAlignment="Center">Output Directory</Label>
|
||||
<TextBox x:Name="OutputDirectoryTextBox" Grid.Row="2" Grid.Column="1" Height="22" Width="345" HorizontalAlignment="Left" TextChanged="OutputDirectoryTextBoxTextChanged" />
|
||||
<Button x:Name="OutputDirectoryBrowseButton" Grid.Row="2" Grid.Column="1" Height="22" Width="50" HorizontalAlignment="Right" Content="Browse" Click="OutputDirectoryBrowseButtonClick"/>
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="0" VerticalAlignment="Center">Drive Letter</Label>
|
||||
<ComboBox x:Name="DriveLetterComboBox" Grid.Row="3" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="Left" SelectionChanged="DriveLetterComboBoxSelectionChanged">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=Letter}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<Label Grid.Row="4" Grid.Column="0" VerticalAlignment="Center">Drive Speed</Label>
|
||||
<ComboBox x:Name="DriveSpeedComboBox" Grid.Row="4" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="Left" SelectionChanged="DriveSpeedComboBoxSelectionChanged" />
|
||||
|
||||
<Label Grid.Row="5" Grid.Column="0" VerticalAlignment="Center">Parameters</Label>
|
||||
<TextBox x:Name="ParametersTextBox" Grid.Row="5" Grid.Column="1" Height="22" Width="370" HorizontalAlignment="Left" IsEnabled="False" />
|
||||
<CheckBox x:Name="EnableParametersCheckBox" Grid.Row="5" Grid.Column="1" Height="22" HorizontalAlignment="Right" IsChecked="False" Click="EnableParametersCheckBoxClick" />
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="2" Grid.Column="0" Margin="15,19.6,15.2,9.8" Grid.ColumnSpan="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Button x:Name="StartStopButton" Grid.Row="0" Grid.Column="0" Height="22" Width="125" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Start Dumping" Click="StartStopButtonClick" IsEnabled="False" />
|
||||
<Button x:Name="MediaScanButton" Grid.Row="0" Grid.Column="1" Height="22" Width="125" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Scan for disks" Click="MediaScanButtonClick" />
|
||||
<Button x:Name="CopyProtectScanButton" Grid.Row="0" Grid.Column="2" Height="22" Width="125" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Scan for protection" Click="CopyProtectScanButtonClick" />
|
||||
<CheckBox x:Name="EjectWhenDoneCheckBox" Grid.Row="0" Grid.Column="3" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Eject When Done" IsChecked="False" />
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="3" Grid.Column="0" Margin="15,20.2,15.2,9.8" Grid.ColumnSpan="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label x:Name="StatusLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Waiting for media..." />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,890 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using WinForms = System.Windows.Forms;
|
||||
using BurnOutSharp;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Windows
|
||||
{
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected or detected media type
|
||||
/// </summary>
|
||||
public MediaType? CurrentMediaType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current list of drives
|
||||
/// </summary>
|
||||
public List<Drive> Drives { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current dumping environment
|
||||
/// </summary>
|
||||
public DumpEnvironment Env { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current list of supported media types
|
||||
/// </summary>
|
||||
public List<MediaType?> MediaTypes { get; private set; } = new List<MediaType?>();
|
||||
|
||||
/// <summary>
|
||||
/// Current list of supported system profiles
|
||||
/// </summary>
|
||||
public List<KnownSystemComboBoxItem> Systems { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current UI options
|
||||
/// </summary>
|
||||
public UIOptions UIOptions { get; private set; } = new UIOptions();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Instance Variables
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the window is already shown or not
|
||||
/// </summary>
|
||||
private bool alreadyShown;
|
||||
|
||||
/// <summary>
|
||||
/// Current attached DiscInformationWindow
|
||||
/// </summary>
|
||||
private DiscInformationWindow discInformationWindow;
|
||||
|
||||
/// <summary>
|
||||
/// Current attached LogWindow
|
||||
/// </summary>
|
||||
private readonly LogWindow logWindow;
|
||||
|
||||
/// <summary>
|
||||
/// Currently attached OptionsWindow
|
||||
/// </summary>
|
||||
private OptionsWindow optionsWindow;
|
||||
|
||||
#endregion
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Load the options
|
||||
ViewModels.OptionsViewModel = new OptionsViewModel(UIOptions);
|
||||
|
||||
// Load the log window
|
||||
logWindow = new LogWindow(this);
|
||||
ViewModels.LoggerViewModel.SetWindow(logWindow);
|
||||
|
||||
// Disable buttons until we load fully
|
||||
StartStopButton.IsEnabled = false;
|
||||
MediaScanButton.IsEnabled = false;
|
||||
CopyProtectScanButton.IsEnabled = false;
|
||||
|
||||
if (UIOptions.OpenLogWindowAtStartup)
|
||||
{
|
||||
this.WindowStartupLocation = WindowStartupLocation.Manual;
|
||||
double combinedHeight = this.Height + logWindow.Height + Constants.LogWindowMarginFromMainWindow;
|
||||
Rectangle bounds = GetScaledCoordinates(WinForms.Screen.PrimaryScreen.WorkingArea);
|
||||
|
||||
this.Left = bounds.Left + (bounds.Width - this.Width) / 2;
|
||||
this.Top = bounds.Top + (bounds.Height - combinedHeight) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Browse for an output folder
|
||||
/// </summary>
|
||||
private void BrowseFolder()
|
||||
{
|
||||
WinForms.FolderBrowserDialog folderDialog = new WinForms.FolderBrowserDialog { ShowNewFolderButton = false, SelectedPath = System.AppDomain.CurrentDomain.BaseDirectory };
|
||||
WinForms.DialogResult result = folderDialog.ShowDialog();
|
||||
|
||||
if (result == WinForms.DialogResult.OK)
|
||||
{
|
||||
OutputDirectoryTextBox.Text = folderDialog.SelectedPath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache the current disc type to internal variable
|
||||
/// </summary>
|
||||
private void CacheCurrentDiscType()
|
||||
{
|
||||
// Get the drive letter from the selected item
|
||||
if (DriveLetterComboBox.SelectedItem is Drive drive)
|
||||
{
|
||||
// Get the current media type
|
||||
if (!UIOptions.SkipMediaTypeDetection)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLog("Trying to detect media type for drive {0}.. ", drive.Letter);
|
||||
CurrentMediaType = Validators.GetMediaType(drive);
|
||||
ViewModels.LoggerViewModel.VerboseLogLn(CurrentMediaType == null ? "unable to detect." : ("detected " + CurrentMediaType.LongName() + "."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a DumpEnvironment with all current settings
|
||||
/// </summary>
|
||||
/// <returns>Filled DumpEnvironment instance</returns>
|
||||
private DumpEnvironment DetermineEnvironment()
|
||||
{
|
||||
// Populate the new environment
|
||||
var env = new DumpEnvironment(UIOptions.Options,
|
||||
OutputDirectoryTextBox.Text,
|
||||
OutputFilenameTextBox.Text,
|
||||
DriveLetterComboBox.SelectedItem as Drive,
|
||||
SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem,
|
||||
MediaTypeComboBox.SelectedItem as MediaType?,
|
||||
ParametersTextBox.Text);
|
||||
|
||||
// Disable automatic reprocessing of the textboxes until we're done
|
||||
OutputDirectoryTextBox.TextChanged -= OutputDirectoryTextBoxTextChanged;
|
||||
OutputFilenameTextBox.TextChanged -= OutputFilenameTextBoxTextChanged;
|
||||
|
||||
OutputDirectoryTextBox.Text = env.OutputDirectory;
|
||||
OutputFilenameTextBox.Text = env.OutputFilename;
|
||||
|
||||
OutputDirectoryTextBox.TextChanged += OutputDirectoryTextBoxTextChanged;
|
||||
OutputFilenameTextBox.TextChanged += OutputFilenameTextBoxTextChanged;
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure information is consistent with the currently selected disc type
|
||||
/// </summary>
|
||||
private void EnsureDiscInformation()
|
||||
{
|
||||
// Get the current environment information
|
||||
Env = DetermineEnvironment();
|
||||
|
||||
// Take care of null cases
|
||||
if (Env.System == null)
|
||||
Env.System = KnownSystem.NONE;
|
||||
if (Env.Type == null)
|
||||
Env.Type = MediaType.NONE;
|
||||
|
||||
// Get the status to write out
|
||||
Result result = Validators.GetSupportStatus(Env.System, Env.Type);
|
||||
StatusLabel.Content = result.Message;
|
||||
|
||||
// Set the index for the current disc type
|
||||
SetCurrentDiscType();
|
||||
|
||||
StartStopButton.IsEnabled = result && (Drives != null && Drives.Count > 0 ? true : false);
|
||||
|
||||
// If we're in a type that doesn't support drive speeds
|
||||
DriveSpeedComboBox.IsEnabled = Env.Type.DoesSupportDriveSpeed();
|
||||
|
||||
// If input params are not enabled, generate the full parameters from the environment
|
||||
if (!ParametersTextBox.IsEnabled)
|
||||
{
|
||||
string generated = Env.GetFullParameters((int?)DriveSpeedComboBox.SelectedItem);
|
||||
if (generated != null)
|
||||
ParametersTextBox.Text = generated;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default output directory name from the currently selected drive
|
||||
/// </summary>
|
||||
/// <param name="driveChanged">Force an updated name if the drive letter changes</param>
|
||||
private void GetOutputNames(bool driveChanged)
|
||||
{
|
||||
Drive drive = DriveLetterComboBox.SelectedItem as Drive;
|
||||
KnownSystem? systemType = SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem;
|
||||
MediaType? mediaType = MediaTypeComboBox.SelectedItem as MediaType?;
|
||||
|
||||
// Set the output directory, if we changed drives or it's not already
|
||||
if (driveChanged || string.IsNullOrEmpty(OutputDirectoryTextBox.Text))
|
||||
OutputDirectoryTextBox.Text = Path.Combine(UIOptions.DefaultOutputPath, drive?.VolumeLabel ?? string.Empty);
|
||||
|
||||
// Get the extension for the file for the next two statements
|
||||
string extension = Env.GetExtension(mediaType);
|
||||
|
||||
// Set the output filename, if we changed drives or it's not already
|
||||
if (driveChanged || string.IsNullOrEmpty(OutputFilenameTextBox.Text))
|
||||
OutputFilenameTextBox.Text = (drive?.VolumeLabel ?? systemType.LongName()) + (extension ?? ".bin");
|
||||
|
||||
// If the extension for the file changed, update that automatically
|
||||
else if (Path.GetExtension(OutputFilenameTextBox.Text) != extension)
|
||||
OutputFilenameTextBox.Text = Path.GetFileNameWithoutExtension(OutputFilenameTextBox.Text) + (extension ?? ".bin");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of active disc drives and fill the combo box
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Find a way for this to periodically run, or have it hook to a "drive change" event</remarks>
|
||||
private void PopulateDrives()
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Scanning for drives..");
|
||||
|
||||
// Always enable the media scan
|
||||
MediaScanButton.IsEnabled = true;
|
||||
|
||||
// Populate the list of drives and add it to the combo box
|
||||
Drives = Validators.CreateListOfDrives(UIOptions.IgnoreFixedDrives);
|
||||
DriveLetterComboBox.ItemsSource = Drives;
|
||||
|
||||
if (DriveLetterComboBox.Items.Count > 0)
|
||||
{
|
||||
// Check for active optical drives first
|
||||
int index = Drives.FindIndex(d => d.MarkedActive && d.InternalDriveType == InternalDriveType.Optical);
|
||||
|
||||
// Then we check for floppy drives
|
||||
if (index == -1)
|
||||
index = Drives.FindIndex(d => d.MarkedActive && d.InternalDriveType == InternalDriveType.Floppy);
|
||||
|
||||
// Then we try all other drive types
|
||||
if (index == -1)
|
||||
index = Drives.FindIndex(d => d.MarkedActive);
|
||||
|
||||
// Set the selected index
|
||||
DriveLetterComboBox.SelectedIndex = (index != -1 ? index : 0);
|
||||
StatusLabel.Content = "Valid drive found! Choose your Media Type";
|
||||
CopyProtectScanButton.IsEnabled = true;
|
||||
|
||||
// Get the current media type
|
||||
if (!UIOptions.SkipSystemDetection && index != -1)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLog("Trying to detect system for drive {0}.. ", Drives[index].Letter);
|
||||
var currentSystem = Validators.GetKnownSystem(Drives[index]);
|
||||
ViewModels.LoggerViewModel.VerboseLogLn(currentSystem == null || currentSystem == KnownSystem.NONE ? "unable to detect." : ("detected " + currentSystem.LongName() + "."));
|
||||
|
||||
if (currentSystem != null && currentSystem != KnownSystem.NONE)
|
||||
{
|
||||
int sysIndex = Systems.FindIndex(s => s == currentSystem);
|
||||
SystemTypeComboBox.SelectedIndex = sysIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// Only enable the start/stop if we don't have the default selected
|
||||
StartStopButton.IsEnabled = (SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem) != KnownSystem.NONE;
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Found {0} drives: {1}", Drives.Count, string.Join(", ", Drives.Select(d => d.Letter)));
|
||||
}
|
||||
else
|
||||
{
|
||||
DriveLetterComboBox.SelectedIndex = -1;
|
||||
StatusLabel.Content = "No valid drive found!";
|
||||
StartStopButton.IsEnabled = false;
|
||||
CopyProtectScanButton.IsEnabled = false;
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Found no drives");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate media type according to system type
|
||||
/// </summary>
|
||||
private void PopulateMediaType()
|
||||
{
|
||||
KnownSystem? currentSystem = SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem;
|
||||
|
||||
if (currentSystem != null)
|
||||
{
|
||||
MediaTypes = Validators.GetValidMediaTypes(currentSystem);
|
||||
MediaTypeComboBox.ItemsSource = MediaTypes;
|
||||
|
||||
MediaTypeComboBox.IsEnabled = MediaTypes.Count > 1;
|
||||
MediaTypeComboBox.SelectedIndex = (MediaTypes.IndexOf(CurrentMediaType) >= 0 ? MediaTypes.IndexOf(CurrentMediaType) : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
MediaTypeComboBox.IsEnabled = false;
|
||||
MediaTypeComboBox.ItemsSource = null;
|
||||
MediaTypeComboBox.SelectedIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of supported systems and fill the combo box
|
||||
/// </summary>
|
||||
private void PopulateSystems()
|
||||
{
|
||||
var knownSystems = Validators.CreateListOfSystems();
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Populating systems, {0} systems found.", knownSystems.Count);
|
||||
|
||||
Dictionary<KnownSystemCategory, List<KnownSystem?>> mapping = knownSystems
|
||||
.GroupBy(s => s.Category())
|
||||
.ToDictionary(
|
||||
k => k.Key,
|
||||
v => v
|
||||
.OrderBy(s => s.LongName())
|
||||
.ToList()
|
||||
);
|
||||
|
||||
Systems = new List<KnownSystemComboBoxItem>()
|
||||
{
|
||||
new KnownSystemComboBoxItem(KnownSystem.NONE),
|
||||
};
|
||||
|
||||
foreach (var group in mapping)
|
||||
{
|
||||
Systems.Add(new KnownSystemComboBoxItem(group.Key));
|
||||
group.Value.ForEach(system => Systems.Add(new KnownSystemComboBoxItem(system)));
|
||||
}
|
||||
|
||||
SystemTypeComboBox.ItemsSource = Systems;
|
||||
SystemTypeComboBox.SelectedIndex = 0;
|
||||
|
||||
StartStopButton.IsEnabled = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the current custom parameters back into UI values
|
||||
/// </summary>
|
||||
private void ProcessCustomParameters()
|
||||
{
|
||||
Env.SetParameters(ParametersTextBox.Text);
|
||||
if (Env.Parameters == null)
|
||||
return;
|
||||
|
||||
int driveIndex = Drives.Select(d => d.Letter).ToList().IndexOf(Env.Parameters.InputPath()[0]);
|
||||
if (driveIndex > -1)
|
||||
DriveLetterComboBox.SelectedIndex = driveIndex;
|
||||
|
||||
int driveSpeed = Env.Parameters.GetSpeed() ?? -1;
|
||||
if (driveSpeed > 0)
|
||||
DriveSpeedComboBox.SelectedValue = driveSpeed;
|
||||
else
|
||||
Env.Parameters.SetSpeed((int?)DriveSpeedComboBox.SelectedValue);
|
||||
|
||||
string trimmedPath = Env.Parameters.OutputPath()?.Trim('"') ?? string.Empty;
|
||||
string outputDirectory = Path.GetDirectoryName(trimmedPath);
|
||||
string outputFilename = Path.GetFileName(trimmedPath);
|
||||
if (!string.IsNullOrWhiteSpace(outputDirectory))
|
||||
OutputDirectoryTextBox.Text = outputDirectory;
|
||||
else
|
||||
outputDirectory = OutputDirectoryTextBox.Text;
|
||||
if (!string.IsNullOrWhiteSpace(outputFilename))
|
||||
OutputFilenameTextBox.Text = outputFilename;
|
||||
else
|
||||
outputFilename = OutputFilenameTextBox.Text;
|
||||
|
||||
MediaType? mediaType = Env.Parameters.GetMediaType();
|
||||
int mediaTypeIndex = MediaTypes.IndexOf(mediaType);
|
||||
if (mediaTypeIndex > -1)
|
||||
MediaTypeComboBox.SelectedIndex = mediaTypeIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan and show copy protection for the current disc
|
||||
/// </summary>
|
||||
private async void ScanAndShowProtection()
|
||||
{
|
||||
if (Env == null)
|
||||
Env = DetermineEnvironment();
|
||||
|
||||
if (Env.Drive.Letter != default(char))
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Scanning for copy protection in {0}", Env.Drive.Letter);
|
||||
|
||||
var tempContent = StatusLabel.Content;
|
||||
StatusLabel.Content = "Scanning for copy protection... this might take a while!";
|
||||
StartStopButton.IsEnabled = false;
|
||||
MediaScanButton.IsEnabled = false;
|
||||
CopyProtectScanButton.IsEnabled = false;
|
||||
|
||||
var progress = new Progress<FileProtection>();
|
||||
progress.ProgressChanged += ProgressUpdated;
|
||||
string protections = await Validators.RunProtectionScanOnPath(Env.Drive.Letter + ":\\", progress);
|
||||
|
||||
// If SmartE is detected on the current disc, remove `/sf` from the flags for DIC only
|
||||
if (Env.InternalProgram == InternalProgram.DiscImageCreator && protections.Contains("SmartE"))
|
||||
{
|
||||
((DiscImageCreator.Parameters)Env.Parameters)[DiscImageCreator.Flag.ScanFileProtect] = false;
|
||||
ViewModels.LoggerViewModel.VerboseLogLn($"SmartE detected, removing {DiscImageCreator.FlagStrings.ScanFileProtect} from parameters");
|
||||
}
|
||||
|
||||
if (!ViewModels.LoggerViewModel.WindowVisible)
|
||||
MessageBox.Show(protections, "Detected Protection", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
ViewModels.LoggerViewModel.VerboseLog("Detected the following protections in {0}:\r\n\r\n{1}", Env.Drive.Letter, protections);
|
||||
|
||||
StatusLabel.Content = tempContent;
|
||||
StartStopButton.IsEnabled = true;
|
||||
MediaScanButton.IsEnabled = true;
|
||||
CopyProtectScanButton.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the current disc type in the combo box
|
||||
/// </summary>
|
||||
private void SetCurrentDiscType()
|
||||
{
|
||||
// If we have an invalid current type, we don't care and return
|
||||
if (CurrentMediaType == null || CurrentMediaType == MediaType.NONE)
|
||||
return;
|
||||
|
||||
// Now set the selected item, if possible
|
||||
int index = MediaTypes.FindIndex(kvp => kvp.Value == CurrentMediaType);
|
||||
if (index != -1)
|
||||
MediaTypeComboBox.SelectedIndex = index;
|
||||
else
|
||||
StatusLabel.Content = $"Disc of type '{Converters.LongName(CurrentMediaType)}' found, but the current system does not support it!";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the drive speed based on reported maximum and user-defined option
|
||||
/// </summary>
|
||||
private void SetSupportedDriveSpeed()
|
||||
{
|
||||
// Set the drive speed list that's appropriate
|
||||
var values = Constants.GetSpeedsForMediaType(CurrentMediaType);
|
||||
DriveSpeedComboBox.ItemsSource = values;
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Supported media speeds: {0}", string.Join(",", values));
|
||||
|
||||
// Set the selected speed
|
||||
int speed = UIOptions.GetPreferredDumpSpeedForMediaType(CurrentMediaType);
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Setting drive speed to: {0}", speed);
|
||||
DriveSpeedComboBox.SelectedValue = speed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begin the dumping process using the given inputs
|
||||
/// </summary>
|
||||
private async void StartDumping()
|
||||
{
|
||||
// One last check to determine environment, just in case
|
||||
Env = DetermineEnvironment();
|
||||
|
||||
// If still in custom parameter mode, check that users meant to continue or not
|
||||
if (EnableParametersCheckBox.IsChecked == true)
|
||||
{
|
||||
MessageBoxResult result = MessageBox.Show("It looks like you have custom parameters that have not been saved. Would you like to apply those changes before starting to dump?", "Custom Changes", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
EnableParametersCheckBox.IsChecked = false;
|
||||
ParametersTextBox.IsEnabled = false;
|
||||
ProcessCustomParameters();
|
||||
}
|
||||
else if (result == MessageBoxResult.Cancel)
|
||||
return;
|
||||
// If "No", then we continue with the current known environment
|
||||
}
|
||||
|
||||
// Fix the output paths
|
||||
Env.FixOutputPaths();
|
||||
|
||||
try
|
||||
{
|
||||
// Validate that the user explicitly wants an inactive drive to be considered for dumping
|
||||
if (!Env.Drive.MarkedActive)
|
||||
{
|
||||
MessageBoxResult mbresult = MessageBox.Show("The currently selected drive does not appear to contain a disc! Are you sure you want to continue?", "Missing Disc", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
|
||||
if (mbresult == MessageBoxResult.No || mbresult == MessageBoxResult.Cancel || mbresult == MessageBoxResult.None)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Dumping aborted!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If a complete dump already exists
|
||||
if (Env.FoundAllFiles())
|
||||
{
|
||||
MessageBoxResult mbresult = MessageBox.Show("A complete dump already exists! Are you sure you want to overwrite?", "Overwrite?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
|
||||
if (mbresult == MessageBoxResult.No || mbresult == MessageBoxResult.Cancel || mbresult == MessageBoxResult.None)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Dumping aborted!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
StartStopButton.Content = Constants.StopDumping;
|
||||
CopyProtectScanButton.IsEnabled = false;
|
||||
StatusLabel.Content = "Beginning dumping process";
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Starting dumping process..");
|
||||
|
||||
// Get progress indicators
|
||||
var resultProgress = new Progress<Result>();
|
||||
resultProgress.ProgressChanged += ProgressUpdated;
|
||||
var protectionProgress = new Progress<FileProtection>();
|
||||
protectionProgress.ProgressChanged += ProgressUpdated;
|
||||
|
||||
// Run the program with the parameters
|
||||
Result result = await Env.Run(resultProgress);
|
||||
|
||||
// If we didn't execute a dumping command we cannot get submission output
|
||||
if (!Env.Parameters.IsDumpingCommand())
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("No dumping command was run, submission information will not be gathered.");
|
||||
StatusLabel.Content = "Execution complete!";
|
||||
StartStopButton.Content = Constants.StartDumping;
|
||||
CopyProtectScanButton.IsEnabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
// Verify dump output and save it
|
||||
result = await Env.VerifyAndSaveDumpOutput(resultProgress,
|
||||
protectionProgress,
|
||||
EjectWhenDoneCheckBox.IsChecked,
|
||||
UIOptions.ResetDriveAfterDump,
|
||||
(si) =>
|
||||
{
|
||||
// lazy initialization
|
||||
if (discInformationWindow == null)
|
||||
{
|
||||
discInformationWindow = new DiscInformationWindow(si);
|
||||
discInformationWindow.Closed += delegate
|
||||
{
|
||||
discInformationWindow = null;
|
||||
};
|
||||
}
|
||||
|
||||
discInformationWindow.Owner = this;
|
||||
discInformationWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
discInformationWindow.Load();
|
||||
return discInformationWindow.ShowDialog();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// No-op, we don't care what it was
|
||||
}
|
||||
finally
|
||||
{
|
||||
StartStopButton.Content = Constants.StartDumping;
|
||||
CopyProtectScanButton.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Handler for AboutMenuItem Click event
|
||||
/// </summary>
|
||||
private void AboutClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MessageBox.Show($"darksabre76 - Project Lead / Backend Design"
|
||||
+ $"{Environment.NewLine}ReignStumble - Former Project Lead / UI Design"
|
||||
+ $"{Environment.NewLine}Jakz - Primary Feature Contributor"
|
||||
+ $"{Environment.NewLine}NHellFire - Feature Contributor", "About", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for AppExitMenuItem Click event
|
||||
/// </summary>
|
||||
private void AppExitClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for CheckForUpdatesMenuItem Click event
|
||||
/// </summary>
|
||||
private void CheckForUpdatesClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
(bool different, string message, string url) = Tools.CheckForNewVersion();
|
||||
|
||||
// If we have a new version, put it in the clipboard
|
||||
if (different)
|
||||
Clipboard.SetText(url);
|
||||
|
||||
MessageBox.Show(message, "Version Update Check", MessageBoxButton.OK, different ? MessageBoxImage.Exclamation : MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for CopyProtectScanButton Click event
|
||||
/// </summary>
|
||||
private void CopyProtectScanButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ScanAndShowProtection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for DriveLetterComboBox SelectionChanged event
|
||||
/// </summary>
|
||||
private void DriveLetterComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
CacheCurrentDiscType();
|
||||
SetCurrentDiscType();
|
||||
GetOutputNames(true);
|
||||
SetSupportedDriveSpeed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for DriveSpeedComboBox SelectionChanged event
|
||||
/// </summary>
|
||||
private void DriveSpeedComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for EnableParametersCheckBox Click event
|
||||
/// </summary>
|
||||
private void EnableParametersCheckBoxClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (EnableParametersCheckBox.IsChecked == true)
|
||||
ParametersTextBox.IsEnabled = true;
|
||||
else
|
||||
{
|
||||
ParametersTextBox.IsEnabled = false;
|
||||
ProcessCustomParameters();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MediaTypeComboBox SelectionChanged event
|
||||
/// </summary>
|
||||
private void MediaTypeComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
// Only change the media type if the selection and not the list has changed
|
||||
if (e.RemovedItems.Count == 1 && e.AddedItems.Count == 1)
|
||||
{
|
||||
CurrentMediaType = MediaTypeComboBox.SelectedItem as MediaType?;
|
||||
SetSupportedDriveSpeed();
|
||||
}
|
||||
|
||||
GetOutputNames(false);
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MediaScanButton Click event
|
||||
/// </summary>
|
||||
private void MediaScanButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
PopulateDrives();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MainWindow Activated event
|
||||
/// </summary>
|
||||
private void MainWindowActivated(object sender, EventArgs e)
|
||||
{
|
||||
if (logWindow.IsVisible && !this.Topmost)
|
||||
{
|
||||
logWindow.Topmost = true;
|
||||
logWindow.Topmost = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MainWindow Closing event
|
||||
/// </summary>
|
||||
private void MainWindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
if (logWindow.IsVisible)
|
||||
logWindow.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MainWindow PositionChanged event
|
||||
/// </summary>
|
||||
private void MainWindowLocationChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (logWindow.IsVisible)
|
||||
logWindow.AdjustPositionToMainWindow();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for MainWindow OnContentRendered event
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnContentRendered(EventArgs e)
|
||||
{
|
||||
base.OnContentRendered(e);
|
||||
|
||||
if (alreadyShown)
|
||||
return;
|
||||
|
||||
alreadyShown = true;
|
||||
|
||||
if (UIOptions.OpenLogWindowAtStartup)
|
||||
{
|
||||
//TODO: this should be bound directly to WindowVisible property in two way fashion
|
||||
// we need to study how to properly do it in XAML
|
||||
ShowLogMenuItem.IsChecked = true;
|
||||
ViewModels.LoggerViewModel.WindowVisible = true;
|
||||
}
|
||||
|
||||
// Populate the list of systems
|
||||
StatusLabel.Content = "Creating system list, please wait!";
|
||||
PopulateSystems();
|
||||
|
||||
// Populate the list of drives
|
||||
StatusLabel.Content = "Creating drive list, please wait!";
|
||||
PopulateDrives();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OptionsWindow OnUpdated event
|
||||
/// </summary>
|
||||
public void OnOptionsUpdated()
|
||||
{
|
||||
PopulateDrives();
|
||||
GetOutputNames(false);
|
||||
SetSupportedDriveSpeed();
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OptionsMenuItem Click event
|
||||
/// </summary>
|
||||
/// TODO: Re-evaluate this based on Avalonia code
|
||||
private void OptionsMenuItemClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// lazy initialization
|
||||
if (optionsWindow == null)
|
||||
{
|
||||
optionsWindow = new OptionsWindow(this, UIOptions);
|
||||
optionsWindow.Closed += delegate
|
||||
{
|
||||
optionsWindow = null;
|
||||
};
|
||||
}
|
||||
|
||||
optionsWindow.Owner = this;
|
||||
optionsWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
optionsWindow.Refresh();
|
||||
optionsWindow.Show();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OutputDirectoryBrowseButton Click event
|
||||
/// </summary>
|
||||
private void OutputDirectoryBrowseButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
BrowseFolder();
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OutputFilenameTextBox TextInput event
|
||||
/// </summary>
|
||||
private void OutputDirectoryTextBoxTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OutputFilenameTextBox TextInput event
|
||||
/// </summary>
|
||||
private void OutputFilenameTextBoxTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for Result ProgressChanged event
|
||||
/// </summary>
|
||||
private void ProgressUpdated(object sender, Result value)
|
||||
{
|
||||
StatusLabel.Content = value.Message;
|
||||
ViewModels.LoggerViewModel.VerboseLogLn(value.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for FileProtection ProgressChanged event
|
||||
/// </summary>
|
||||
private void ProgressUpdated(object sender, FileProtection value)
|
||||
{
|
||||
string message = $"{value.Percentage * 100:N2}%: {value.Filename} - {value.Protection}";
|
||||
StatusLabel.Content = message;
|
||||
ViewModels.LoggerViewModel.VerboseLogLn(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for StartStopButton Click event
|
||||
/// </summary>
|
||||
private void StartStopButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Dump or stop the dump
|
||||
if ((string)StartStopButton.Content == Constants.StartDumping)
|
||||
{
|
||||
StartDumping();
|
||||
}
|
||||
else if ((string)StartStopButton.Content == Constants.StopDumping)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Canceling dumping process...");
|
||||
Env.CancelDumping();
|
||||
CopyProtectScanButton.IsEnabled = true;
|
||||
|
||||
if (EjectWhenDoneCheckBox.IsChecked == true)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn($"Ejecting disc in drive {Env.Drive.Letter}");
|
||||
Env.EjectDisc();
|
||||
}
|
||||
|
||||
if (UIOptions.ResetDriveAfterDump)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn($"Resetting drive {Env.Drive.Letter}");
|
||||
Env.ResetDrive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for SystemTypeComboBox SelectionChanged event
|
||||
/// </summary>
|
||||
private void SystemTypeComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
// If we're on a separator, go to the next item and return
|
||||
if ((SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem).IsHeader())
|
||||
{
|
||||
SystemTypeComboBox.SelectedIndex++;
|
||||
return;
|
||||
}
|
||||
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Changed system to: {0}", (SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem).Name);
|
||||
PopulateMediaType();
|
||||
GetOutputNames(false);
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Get pixel coordinates based on DPI scaling
|
||||
/// </summary>
|
||||
/// <param name="bounds">Rectangle representing the bounds to transform</param>
|
||||
/// <returns>Rectangle representing the scaled bounds</returns>
|
||||
private Rectangle GetScaledCoordinates(Rectangle bounds)
|
||||
{
|
||||
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
|
||||
{
|
||||
return new Rectangle(
|
||||
TransformCoordinate(bounds.Left, g.DpiX),
|
||||
TransformCoordinate(bounds.Top, g.DpiY),
|
||||
TransformCoordinate(bounds.Width, g.DpiX),
|
||||
TransformCoordinate(bounds.Height, g.DpiY));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform an individual coordinate using DPI scaling
|
||||
/// </summary>
|
||||
/// <param name="coord">Current integer coordinate</param>
|
||||
/// <param name="dpi">DPI scaling factor</param>
|
||||
/// <returns>Scaled integer coordinate</returns>
|
||||
private int TransformCoordinate(int coord, float dpi)
|
||||
{
|
||||
return (int)(coord / ((double)dpi / 96));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
<Window x:Class="DICUI.Windows.OptionsWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:DICUI"
|
||||
mc:Ignorable="d"
|
||||
Title="Options" Width="515.132" Height="605">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="150"/>
|
||||
<RowDefinition Height="150"/>
|
||||
<RowDefinition Height="150"/>
|
||||
<RowDefinition Height="80"/>
|
||||
<RowDefinition Height="40"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<GroupBox Grid.Column="0" Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Paths" />
|
||||
|
||||
<Grid Margin="10,15,10,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="2.0*" />
|
||||
<ColumnDefinition Width="0.2*" />
|
||||
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Aaru Path" />
|
||||
<TextBox x:Name="AaruPathTextBox" Grid.Row="0" Grid.Column="1" Height="22" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=AaruPath}" />
|
||||
<Button x:Name="AaruPathButton" Grid.Row="0" Grid.Column="2" Height="22" Width="22" Content="..." Click="BrowseForPathClick" />
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="DiscImageCreator Path" />
|
||||
<TextBox x:Name="CreatorPathTextBox" Grid.Row="1" Grid.Column="1" Height="22" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=CreatorPath}" />
|
||||
<Button x:Name="CreatorPathButton" Grid.Row="1" Grid.Column="2" Height="22" Width="22" Content="..." Click="BrowseForPathClick" />
|
||||
|
||||
<!--
|
||||
<Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="DD Path" />
|
||||
<TextBox x:Name="DDPathTextBox" Grid.Row="1" Grid.Column="1" Height="22" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=DDPath}" />
|
||||
<Button x:Name="DDPathButton" Grid.Row="1" Grid.Column="2" Height="22" Width="22" Content="..." Click="BrowseForPathClick" />
|
||||
-->
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="subdump Path" />
|
||||
<TextBox x:Name="SubDumpPathTextBox" Grid.Row="2" Grid.Column="1" Height="22" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=SubDumpPath}" />
|
||||
<Button x:Name="SubDumpPathButton" Grid.Row="2" Grid.Column="2" Height="22" Width="22" Content="..." Click="BrowseForPathClick"/>
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Default Output Path" />
|
||||
<TextBox x:Name="DefaultOutputPathTextBox" Grid.Row="3" Grid.Column="1" Height="22" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=DefaultOutputPath}" />
|
||||
<Button x:Name="DefaultOutputPathButton" Grid.Row="3" Grid.Column="2" Height="22" Width="22" Content="..." Click="BrowseForPathClick" />
|
||||
</Grid>
|
||||
|
||||
<GroupBox Grid.Row="1" Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Preferred Dump Speed">
|
||||
<Grid Height="100">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80"/>
|
||||
<ColumnDefinition Width="2.0*"/>
|
||||
<ColumnDefinition Width="40"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="CD-ROM" />
|
||||
<Slider x:Name="DumpSpeedCDSlider" Grid.Row="0" Grid.Column="1" Minimum="1" Maximum="72" IsSnapToTickEnabled="True" TickPlacement="BottomRight"
|
||||
Ticks="{Binding Source={x:Static local:Constants.SpeedsForCDAsCollection}}"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Value="{Binding Path=PreferredDumpSpeedCD}" />
|
||||
<TextBox x:Name="DumpSpeedCDTextBox" Grid.Row="0" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" IsReadOnlyCaretVisible="False" VerticalAlignment="Center"
|
||||
Text="{Binding ElementName=DumpSpeedCDSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}" Background="LightGray" Foreground="Gray"/>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="DVD-ROM" />
|
||||
<Slider x:Name="DumpSpeedDVDSlider" Grid.Row="1" Grid.Column="1" Minimum="1" Maximum="24" IsSnapToTickEnabled="True" TickPlacement="BottomRight"
|
||||
Ticks="{Binding Source={x:Static local:Constants.SpeedsForDVDAsCollection}}"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Value="{Binding Path=PreferredDumpSpeedDVD}" />
|
||||
<TextBox x:Name="DumpSpeedDVDTextBox" Grid.Row="1" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" IsReadOnlyCaretVisible="False" VerticalAlignment="Center"
|
||||
Text="{Binding ElementName=DumpSpeedDVDSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}" Background="LightGray" Foreground="Gray"/>
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="BD-ROM" />
|
||||
<Slider x:Name="DumpSpeedBDSlider" Grid.Row="2" Grid.Column="1" Minimum="1" Maximum="16" IsSnapToTickEnabled="True" TickPlacement="BottomRight"
|
||||
Ticks="{Binding Source={x:Static local:Constants.SpeedsForBDAsCollection}}"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Value="{Binding Path=PreferredDumpSpeedBD}" />
|
||||
<TextBox x:Name="DumpSpeedBDTextBox" Grid.Row="2" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" IsReadOnlyCaretVisible="False" VerticalAlignment="Center"
|
||||
Text="{Binding ElementName=DumpSpeedBDSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}" Background="LightGray" Foreground="Gray"/>
|
||||
|
||||
</Grid>
|
||||
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Grid.Row="2" Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Options" Padding="10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<CheckBox Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Content="Quiet Mode"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=QuietMode}"
|
||||
ToolTip="Disable DiscImageCreator sounds" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Content="Paranoid Mode"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=ParanoidMode}"
|
||||
ToolTip="Enable pedantic and super-safe flags" Margin="0,4"
|
||||
/>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="2" Content="Reread Tries:" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="3" VerticalAlignment="Center"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=RereadAmountForC2}"
|
||||
ToolTip="Specifies how many rereads are attempted on C2 error"
|
||||
/>
|
||||
|
||||
<CheckBox Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" Content="Protection Scan"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=ScanForProtection}"
|
||||
ToolTip="Enable automatic checking for copy protection on dumped media" Margin="0,4,0,0"
|
||||
/>
|
||||
|
||||
<CheckBox Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Content="Skip Type Detect"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=SkipMediaTypeDetection}"
|
||||
ToolTip="Disable trying to guess media type inserted (may improve performance at startup)" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" Content="Add Placeholders"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=AddPlaceholders}"
|
||||
ToolTip="Enable adding placeholder text in the submissioninfo output for required and optional fields" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Content="Show Disc Info"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=PromptForDiscInformation}"
|
||||
ToolTip="Enable showing the disc information output after dumping" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Content="No Fixed Drives"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=IgnoreFixedDrives}"
|
||||
ToolTip="Ignore hard drives and other fixed drives" Margin="0,4"
|
||||
/>
|
||||
|
||||
<CheckBox Grid.Row="2" Grid.Column="2" VerticalAlignment="Center" Content="Reset After Dump"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
IsChecked="{Binding Path=ResetDriveAfterDump}"
|
||||
ToolTip="Reset disc drives after dumping; useful for some older machines" Margin="0,4"
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Grid.Row="3" Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Redump Login" Padding="10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1.2*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Username" />
|
||||
<TextBox x:Name="RedumpUsernameTextBox" Grid.Row="0" Grid.Column="1" Height="22" HorizontalAlignment="Stretch"
|
||||
DataContext="{Binding Source={x:Static local:ViewModels.OptionsViewModel}}"
|
||||
Text="{Binding Path=Username}" />
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Password" />
|
||||
<PasswordBox x:Name="RedumpPasswordBox" Grid.Row="0" Grid.Column="3" Height="22" HorizontalAlignment="Stretch" PasswordChar="*" />
|
||||
|
||||
<Button x:Name="RedumpLoginTestButton" Grid.Row="0" Grid.Column="5" Height="22" Width="80" Content="Test Login" Click="OnRedumpTestClick" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<Grid Height="22" Grid.Row="4" Grid.Column="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button x:Name="AcceptButton" Grid.Row="0" Grid.Column="1" Height="22" Width="80" Content="Accept" Click="OnAcceptClick" />
|
||||
<Button x:Name="CancelButton" Grid.Row="0" Grid.Column="2" Height="22" Width="80" Content="Cancel" Click="OnCancelClick" />
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,137 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using DICUI.Web;
|
||||
using Button = System.Windows.Controls.Button;
|
||||
using TextBox = System.Windows.Controls.TextBox;
|
||||
|
||||
namespace DICUI.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for OptionsWindow.xaml
|
||||
/// </summary>
|
||||
public partial class OptionsWindow : Window
|
||||
{
|
||||
private readonly MainWindow _mainWindow;
|
||||
private readonly UIOptions _uiOptions;
|
||||
|
||||
public OptionsWindow(MainWindow mainWindow, UIOptions options)
|
||||
{
|
||||
InitializeComponent();
|
||||
_mainWindow = mainWindow;
|
||||
_uiOptions = options;
|
||||
}
|
||||
|
||||
private OpenFileDialog CreateOpenFileDialog()
|
||||
{
|
||||
OpenFileDialog dialog = new OpenFileDialog();
|
||||
|
||||
dialog.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
dialog.Filter = "Executables (*.exe)|*.exe";
|
||||
dialog.FilterIndex = 0;
|
||||
dialog.RestoreDirectory = true;
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
private FolderBrowserDialog CreateFolderBrowserDialog()
|
||||
{
|
||||
FolderBrowserDialog dialog = new FolderBrowserDialog();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
private TextBox TextBoxForPathSetting(string name)
|
||||
{
|
||||
return FindName(name + "TextBox") as TextBox;
|
||||
}
|
||||
|
||||
private void BrowseForPathClick(object sender, EventArgs e)
|
||||
{
|
||||
Button button = sender as Button;
|
||||
// strips button prefix to obtain the setting name
|
||||
string pathSettingName = button.Name.Substring(0, button.Name.IndexOf("Button"));
|
||||
|
||||
// TODO: hack for now, then we'll see
|
||||
bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath";
|
||||
|
||||
CommonDialog dialog = shouldBrowseForPath ? (CommonDialog)CreateFolderBrowserDialog() : CreateOpenFileDialog();
|
||||
using (dialog)
|
||||
{
|
||||
DialogResult result = dialog.ShowDialog();
|
||||
|
||||
if (result == System.Windows.Forms.DialogResult.OK)
|
||||
{
|
||||
string path;
|
||||
bool exists;
|
||||
|
||||
if (shouldBrowseForPath)
|
||||
{
|
||||
path = (dialog as FolderBrowserDialog).SelectedPath;
|
||||
exists = Directory.Exists(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
path = (dialog as OpenFileDialog).FileName;
|
||||
exists = File.Exists(path);
|
||||
}
|
||||
|
||||
if (exists)
|
||||
{
|
||||
TextBoxForPathSetting(pathSettingName).Text = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Windows.MessageBox.Show(
|
||||
"Specified path doesn't exists!",
|
||||
"Error",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
// Handle non-bindable fields
|
||||
RedumpPasswordBox.Password = _uiOptions.Options.Password;
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OnAcceptClick(object sender, EventArgs e)
|
||||
{
|
||||
// Handle non-bindable fields
|
||||
_uiOptions.Options.Password = RedumpPasswordBox.Password;
|
||||
|
||||
_uiOptions.Save();
|
||||
Hide();
|
||||
|
||||
_mainWindow.OnOptionsUpdated();
|
||||
}
|
||||
|
||||
private void OnCancelClick(object sender, EventArgs e)
|
||||
{
|
||||
// just hide the window and don't care
|
||||
Hide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test Redump credentials for validity
|
||||
/// </summary>
|
||||
private void OnRedumpTestClick(object sender, EventArgs e)
|
||||
{
|
||||
using (RedumpWebClient wc = new RedumpWebClient())
|
||||
{
|
||||
if (wc.Login(RedumpUsernameTextBox.Text, RedumpPasswordBox.Password))
|
||||
System.Windows.MessageBox.Show("Redump login credentials accepted!", "Success", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
else
|
||||
System.Windows.MessageBox.Show("Redump login credentials denied!", "Failure", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
2
LICENSE
2
LICENSE
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
DICUI Copyright (C) 2018 ReignStumble
|
||||
MPF Copyright (C) 2018 ReignStumble
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
50
MPF.Check/MPF.Check.csproj
Normal file
50
MPF.Check/MPF.Check.csproj
Normal file
@@ -0,0 +1,50 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net48;net6.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win7-x64;win8-x64;win81-x64;win10-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Title>MPF Check</Title>
|
||||
<AssemblyName>MPF.Check</AssemblyName>
|
||||
<Description>Validator for various dumping programs</Description>
|
||||
<Authors>Matt Nadareski;ReignStumble;Jakz</Authors>
|
||||
<Copyright>Copyright (c)2019-2023</Copyright>
|
||||
<RepositoryUrl>https://github.com/SabreTools/MPF</RepositoryUrl>
|
||||
<Version>2.6</Version>
|
||||
<AssemblyVersion>$(Version)</AssemblyVersion>
|
||||
<FileVersion>$(Version)</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NrtRevisionFormat>$(Version)-{chash:8}</NrtRevisionFormat>
|
||||
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
|
||||
<NrtShowRevision>false</NrtShowRevision>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.8.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="$(PkgBurnOutSharp)\content\**" PackagePath="contentFiles\any\any;content" CopyToOutputDirectory="Always" PackageCopyToOutput="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MPF.Core\MPF.Core.csproj" />
|
||||
<ProjectReference Include="..\MPF.Library\MPF.Library.csproj" />
|
||||
<ProjectReference Include="..\RedumpLib\RedumpLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
194
MPF.Check/Program.cs
Normal file
194
MPF.Check/Program.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Utilities;
|
||||
using MPF.Library;
|
||||
using RedumpLib.Data;
|
||||
using RedumpLib.Web;
|
||||
|
||||
namespace MPF.Check
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Try processing the standalone arguments
|
||||
if (ProcessStandaloneArguments(args))
|
||||
return;
|
||||
|
||||
// Try processing the common arguments
|
||||
(bool success, MediaType mediaType, RedumpSystem? knownSystem) = ProcessCommonArguments(args);
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
// Loop through and process options
|
||||
(Core.Data.Options options, string path, int startIndex) = OptionsLoader.LoadFromArguments(args, startIndex: 2);
|
||||
|
||||
// Make new Progress objects
|
||||
var resultProgress = new Progress<Result>();
|
||||
resultProgress.ProgressChanged += ProgressUpdated;
|
||||
var protectionProgress = new Progress<ProtectionProgress>();
|
||||
protectionProgress.ProgressChanged += ProgressUpdated;
|
||||
|
||||
// Validate the supplied credentials
|
||||
#if NET48 || NETSTANDARD2_1
|
||||
(bool? _, string message) = RedumpWebClient.ValidateCredentials(options?.RedumpUsername, options?.RedumpPassword);
|
||||
#else
|
||||
(bool? _, string message) = RedumpHttpClient.ValidateCredentials(options?.RedumpUsername, options?.RedumpPassword).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
#endif
|
||||
if (!string.IsNullOrWhiteSpace(message))
|
||||
Console.WriteLine(message);
|
||||
|
||||
// Loop through all the rest of the args
|
||||
for (int i = startIndex; i < args.Length; i++)
|
||||
{
|
||||
// Check for a file
|
||||
if (!File.Exists(args[i].Trim('"')))
|
||||
{
|
||||
DisplayHelp($"{args[i].Trim('"')} does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the full file path
|
||||
string filepath = Path.GetFullPath(args[i].Trim('"'));
|
||||
|
||||
// Now populate an environment
|
||||
Drive drive = null;
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
drive = Drive.Create(null, path);
|
||||
|
||||
var env = new DumpEnvironment(options, filepath, drive, knownSystem, mediaType, internalProgram: null, parameters: null);
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
var result = env.VerifyAndSaveDumpOutput(resultProgress, protectionProgress).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display help for MPF.Check
|
||||
/// </summary>
|
||||
/// <param name="error">Error string to prefix the help text with</param>
|
||||
private static void DisplayHelp(string error = null)
|
||||
{
|
||||
if (error != null)
|
||||
Console.WriteLine(error);
|
||||
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine("MPF.Check.exe <mediatype> <system> [options] </path/to/output.cue/iso> ...");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Standalone Options:");
|
||||
Console.WriteLine("-h, -? Show this help text");
|
||||
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("Check Options:");
|
||||
var supportedArguments = OptionsLoader.PrintSupportedArguments();
|
||||
foreach (string argument in supportedArguments)
|
||||
{
|
||||
Console.WriteLine(argument);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process common arguments for all functionality
|
||||
/// </summary>
|
||||
/// <returns>True if all arguments pass, false otherwise</returns>
|
||||
private static (bool, MediaType, RedumpSystem?) ProcessCommonArguments(string[] args)
|
||||
{
|
||||
// All other use requires at least 3 arguments
|
||||
if (args.Length < 3)
|
||||
{
|
||||
DisplayHelp("Invalid number of arguments");
|
||||
return (false, MediaType.NONE, null);
|
||||
}
|
||||
|
||||
// Check the MediaType
|
||||
var mediaType = EnumConverter.ToMediaType(args[0].Trim('"'));
|
||||
if (mediaType == MediaType.NONE)
|
||||
{
|
||||
DisplayHelp($"{args[0]} is not a recognized media type");
|
||||
return (false, MediaType.NONE, null);
|
||||
}
|
||||
|
||||
// Check the RedumpSystem
|
||||
var knownSystem = Extensions.ToRedumpSystem(args[1].Trim('"'));
|
||||
if (knownSystem == null)
|
||||
{
|
||||
DisplayHelp($"{args[1]} is not a recognized system");
|
||||
return (false, MediaType.NONE, null);
|
||||
}
|
||||
|
||||
return (true, mediaType, knownSystem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process any standalone arguments for the program
|
||||
/// </summary>
|
||||
/// <returns>True if one of the arguments was processed, false otherwise</returns>
|
||||
private static bool ProcessStandaloneArguments(string[] args)
|
||||
{
|
||||
// Help options
|
||||
if (args.Length == 0 || args[0] == "-h" || args[0] == "-?")
|
||||
{
|
||||
DisplayHelp();
|
||||
return true;
|
||||
}
|
||||
|
||||
// List options
|
||||
if (args[0] == "-lm" || args[0] == "--listmedia")
|
||||
{
|
||||
Console.WriteLine("Supported Media Types:");
|
||||
foreach (string mediaType in Extensions.ListMediaTypes())
|
||||
{
|
||||
Console.WriteLine(mediaType);
|
||||
}
|
||||
Console.ReadLine();
|
||||
return true;
|
||||
}
|
||||
else if (args[0] == "-lp" || args[0] == "--listprograms")
|
||||
{
|
||||
Console.WriteLine("Supported Programs:");
|
||||
foreach (string program in EnumExtensions.ListPrograms())
|
||||
{
|
||||
Console.WriteLine(program);
|
||||
}
|
||||
Console.ReadLine();
|
||||
return true;
|
||||
}
|
||||
else if (args[0] == "-ls" || args[0] == "--listsystems")
|
||||
{
|
||||
Console.WriteLine("Supported Systems:");
|
||||
foreach (string system in Extensions.ListSystems())
|
||||
{
|
||||
Console.WriteLine(system);
|
||||
}
|
||||
Console.ReadLine();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple process counter to write to console
|
||||
/// </summary>
|
||||
private static void ProgressUpdated(object sender, Result value)
|
||||
{
|
||||
Console.WriteLine(value.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple process counter to write to console
|
||||
/// </summary>
|
||||
private static void ProgressUpdated(object sender, ProtectionProgress value)
|
||||
{
|
||||
Console.WriteLine($"{value.Percentage * 100:N2}%: {value.Filename} - {value.Protection}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"profiles": {
|
||||
"DICUI.Check": {
|
||||
"MPF.Check": {
|
||||
"commandName": "Project"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Anything marked as internal can be used by the test methods
|
||||
[assembly: InternalsVisibleTo("DICUI.Test")]
|
||||
[assembly: InternalsVisibleTo("MPF.Test")]
|
||||
385
MPF.Core/Converters/EnumConverter.cs
Normal file
385
MPF.Core/Converters/EnumConverter.cs
Normal file
@@ -0,0 +1,385 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
#if NETFRAMEWORK
|
||||
using IMAPI2;
|
||||
#endif
|
||||
using MPF.Core.Data;
|
||||
using RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.Converters
|
||||
{
|
||||
public static class EnumConverter
|
||||
{
|
||||
#region Cross-enumeration conversions
|
||||
|
||||
/// <summary>
|
||||
/// Convert drive type to internal version, if possible
|
||||
/// </summary>
|
||||
/// <param name="driveType">DriveType value to check</param>
|
||||
/// <returns>InternalDriveType, if possible, null on error</returns>
|
||||
public static InternalDriveType? ToInternalDriveType(this DriveType driveType)
|
||||
{
|
||||
switch (driveType)
|
||||
{
|
||||
case DriveType.CDRom:
|
||||
return InternalDriveType.Optical;
|
||||
case DriveType.Fixed:
|
||||
return InternalDriveType.HardDisk;
|
||||
case DriveType.Removable:
|
||||
return InternalDriveType.Removable;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
/// <summary>
|
||||
/// Convert IMAPI physical media type to a MediaType
|
||||
/// </summary>
|
||||
/// <param name="type">IMAPI_MEDIA_PHYSICAL_TYPE value to check</param>
|
||||
/// <returns>MediaType if possible, null on error</returns>
|
||||
public static MediaType? IMAPIToMediaType(this IMAPI_MEDIA_PHYSICAL_TYPE type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_UNKNOWN:
|
||||
return MediaType.NONE;
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDROM:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDR:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDRW:
|
||||
return MediaType.CDROM;
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDROM:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDRAM:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSR:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSRW:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSR_DUALLAYER:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHR:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHRW:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHR_DUALLAYER:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DISK:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSRW_DUALLAYER:
|
||||
return MediaType.DVD;
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDROM:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDR:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDRAM:
|
||||
return MediaType.HDDVD;
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDROM:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDR:
|
||||
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDRE:
|
||||
return MediaType.BluRay;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#region Convert to Long Name
|
||||
|
||||
/// <summary>
|
||||
/// Long name method cache
|
||||
/// </summary>
|
||||
private static readonly ConcurrentDictionary<Type, MethodInfo> LongNameMethods = new ConcurrentDictionary<Type, MethodInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of a generic enumerable value
|
||||
/// </summary>
|
||||
/// <param name="value">Enum value to convert</param>
|
||||
/// <returns>String representation of that value if possible, empty string on error</returns>
|
||||
public static string GetLongName(Enum value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sourceType = value?.GetType();
|
||||
sourceType = Nullable.GetUnderlyingType(sourceType) ?? sourceType;
|
||||
|
||||
if (!LongNameMethods.TryGetValue(sourceType, out MethodInfo method))
|
||||
{
|
||||
method = typeof(RedumpLib.Data.Extensions).GetMethod("LongName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) });
|
||||
if (method == null)
|
||||
method = typeof(EnumConverter).GetMethod("LongName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) });
|
||||
|
||||
LongNameMethods.TryAdd(sourceType, method);
|
||||
}
|
||||
|
||||
if (method != null)
|
||||
return method.Invoke(null, new[] { value }) as string;
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Converter is not implemented for the given type
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
switch (prog)
|
||||
{
|
||||
#region Dumping support
|
||||
|
||||
case InternalProgram.Aaru:
|
||||
return "Aaru";
|
||||
case InternalProgram.DD:
|
||||
return "dd";
|
||||
case InternalProgram.DiscImageCreator:
|
||||
return "DiscImageCreator";
|
||||
case InternalProgram.Redumper:
|
||||
return "redumper";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Verification support only
|
||||
|
||||
case InternalProgram.CleanRip:
|
||||
return "CleanRip";
|
||||
|
||||
case InternalProgram.DCDumper:
|
||||
return "DCDumper";
|
||||
|
||||
case InternalProgram.UmdImageCreator:
|
||||
return "UmdImageCreator";
|
||||
|
||||
#endregion
|
||||
|
||||
case InternalProgram.NONE:
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Convert From String
|
||||
|
||||
/// <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(string internalProgram)
|
||||
{
|
||||
switch (internalProgram.ToLowerInvariant())
|
||||
{
|
||||
// Dumping support
|
||||
case "aaru":
|
||||
case "chef":
|
||||
case "dichef":
|
||||
case "discimagechef":
|
||||
return InternalProgram.Aaru;
|
||||
case "creator":
|
||||
case "dic":
|
||||
case "dicreator":
|
||||
case "discimagecreator":
|
||||
return InternalProgram.DiscImageCreator;
|
||||
case "dd":
|
||||
return InternalProgram.DD;
|
||||
case "rd":
|
||||
case "redumper":
|
||||
return InternalProgram.Redumper;
|
||||
|
||||
// Verification support only
|
||||
case "cleanrip":
|
||||
case "cr":
|
||||
return InternalProgram.CleanRip;
|
||||
case "dc":
|
||||
case "dcd":
|
||||
case "dcdumper":
|
||||
return InternalProgram.DCDumper;
|
||||
case "uic":
|
||||
case "umd":
|
||||
case "umdcreator":
|
||||
case "umdimagecreator":
|
||||
return InternalProgram.UmdImageCreator;
|
||||
|
||||
default:
|
||||
return InternalProgram.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the MediaType enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="type">String value to convert</param>
|
||||
/// <returns>MediaType represented by the string, if possible</returns>
|
||||
public static MediaType ToMediaType(string type)
|
||||
{
|
||||
switch (type.ToLowerInvariant())
|
||||
{
|
||||
#region Punched Media
|
||||
|
||||
case "aperture":
|
||||
case "aperturecard":
|
||||
case "aperture card":
|
||||
return MediaType.ApertureCard;
|
||||
case "jacquardloom":
|
||||
case "jacquardloomcard":
|
||||
case "jacquard loom card":
|
||||
return MediaType.JacquardLoomCard;
|
||||
case "magneticstripe":
|
||||
case "magneticstripecard":
|
||||
case "magnetic stripe card":
|
||||
return MediaType.MagneticStripeCard;
|
||||
case "opticalphone":
|
||||
case "opticalphonecard":
|
||||
case "optical phonecard":
|
||||
return MediaType.OpticalPhonecard;
|
||||
case "punchcard":
|
||||
case "punchedcard":
|
||||
case "punched card":
|
||||
return MediaType.PunchedCard;
|
||||
case "punchtape":
|
||||
case "punchedtape":
|
||||
case "punched tape":
|
||||
return MediaType.PunchedTape;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tape
|
||||
|
||||
case "openreel":
|
||||
case "openreeltape":
|
||||
case "open reel tape":
|
||||
return MediaType.OpenReel;
|
||||
case "datacart":
|
||||
case "datacartridge":
|
||||
case "datatapecartridge":
|
||||
case "data tape cartridge":
|
||||
return MediaType.DataCartridge;
|
||||
case "cassette":
|
||||
case "cassettetape":
|
||||
case "cassette tape":
|
||||
return MediaType.Cassette;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Disc / Disc
|
||||
|
||||
case "bd":
|
||||
case "bdrom":
|
||||
case "bd-rom":
|
||||
case "bluray":
|
||||
return MediaType.BluRay;
|
||||
case "cd":
|
||||
case "cdrom":
|
||||
case "cd-rom":
|
||||
return MediaType.CDROM;
|
||||
case "dvd":
|
||||
case "dvd5":
|
||||
case "dvd-5":
|
||||
case "dvd9":
|
||||
case "dvd-9":
|
||||
case "dvdrom":
|
||||
case "dvd-rom":
|
||||
return MediaType.DVD;
|
||||
case "fd":
|
||||
case "floppy":
|
||||
case "floppydisk":
|
||||
case "floppy disk":
|
||||
case "floppy diskette":
|
||||
return MediaType.FloppyDisk;
|
||||
case "floptical":
|
||||
return MediaType.Floptical;
|
||||
case "gd":
|
||||
case "gdrom":
|
||||
case "gd-rom":
|
||||
return MediaType.GDROM;
|
||||
case "hddvd":
|
||||
case "hd-dvd":
|
||||
case "hddvdrom":
|
||||
case "hd-dvd-rom":
|
||||
return MediaType.HDDVD;
|
||||
case "hdd":
|
||||
case "harddisk":
|
||||
case "hard disk":
|
||||
return MediaType.HardDisk;
|
||||
case "bernoullidisk":
|
||||
case "iomegabernoullidisk":
|
||||
case "bernoulli disk":
|
||||
case "iomega bernoulli disk":
|
||||
return MediaType.IomegaBernoulliDisk;
|
||||
case "jaz":
|
||||
case "iomegajaz":
|
||||
case "iomega jaz":
|
||||
return MediaType.IomegaJaz;
|
||||
case "zip":
|
||||
case "zipdisk":
|
||||
case "iomegazip":
|
||||
case "iomega zip":
|
||||
return MediaType.IomegaZip;
|
||||
case "ldrom":
|
||||
case "lvrom":
|
||||
case "ld-rom":
|
||||
case "lv-rom":
|
||||
case "laserdisc":
|
||||
case "laservision":
|
||||
case "ld-rom / lv-rom":
|
||||
return MediaType.LaserDisc;
|
||||
case "64dd":
|
||||
case "n64dd":
|
||||
case "64dddisk":
|
||||
case "n64dddisk":
|
||||
case "64dd disk":
|
||||
case "n64dd disk":
|
||||
return MediaType.Nintendo64DD;
|
||||
case "fds":
|
||||
case "famicom":
|
||||
case "nfds":
|
||||
case "nintendofamicom":
|
||||
case "famicomdisksystem":
|
||||
case "famicom disk system":
|
||||
case "famicom disk system disk":
|
||||
return MediaType.NintendoFamicomDiskSystem;
|
||||
case "gc":
|
||||
case "gamecube":
|
||||
case "nintendogamecube":
|
||||
case "nintendo gamecube":
|
||||
case "gamecube disc":
|
||||
case "gamecube game disc":
|
||||
return MediaType.NintendoGameCubeGameDisc;
|
||||
case "wii":
|
||||
case "nintendowii":
|
||||
case "nintendo wii":
|
||||
case "nintendo wii disc":
|
||||
case "wii optical disc":
|
||||
return MediaType.NintendoWiiOpticalDisc;
|
||||
case "wiiu":
|
||||
case "nintendowiiu":
|
||||
case "nintendo wiiu":
|
||||
case "nintendo wiiu disc":
|
||||
case "wiiu optical disc":
|
||||
case "wii u optical disc":
|
||||
return MediaType.NintendoWiiUOpticalDisc;
|
||||
case "umd":
|
||||
return MediaType.UMD;
|
||||
|
||||
#endregion
|
||||
|
||||
// Unsorted Formats
|
||||
case "cartridge":
|
||||
return MediaType.Cartridge;
|
||||
case "ced":
|
||||
case "rcaced":
|
||||
case "rca ced":
|
||||
case "videodisc":
|
||||
case "rca videodisc":
|
||||
return MediaType.CED;
|
||||
|
||||
default:
|
||||
return MediaType.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,54 @@
|
||||
namespace DICUI.Data
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Constant values for UI
|
||||
/// </summary>
|
||||
public static class Interface
|
||||
{
|
||||
// Button values
|
||||
public const string StartDumping = "Start Dumping";
|
||||
public const string StopDumping = "Stop Dumping";
|
||||
|
||||
// Byte arrays for signatures
|
||||
public static readonly byte[] SaturnSectorZeroStart = new byte[] { 0x53, 0x45, 0x47, 0x41, 0x20, 0x53, 0x45, 0x47, 0x41, 0x53, 0x41, 0x54, 0x55, 0x52, 0x4E, 0x20 };
|
||||
|
||||
// Private lists of known drive speed ranges
|
||||
private static IReadOnlyList<int> CD { get; } = new List<int> { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 };
|
||||
private static IReadOnlyList<int> DVD { get; } = CD.Where(s => s <= 24).ToList();
|
||||
private static IReadOnlyList<int> HDDVD { get; } = CD.Where(s => s <= 24).ToList();
|
||||
private static IReadOnlyList<int> BD { get; } = CD.Where(s => s <= 16).ToList();
|
||||
private static IReadOnlyList<int> Unknown { get; } = new List<int> { 1 };
|
||||
|
||||
/// <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 IReadOnlyList<int> GetSpeedsForMediaType(MediaType? type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
case MediaType.GDROM:
|
||||
return CD;
|
||||
case MediaType.DVD:
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
return DVD;
|
||||
case MediaType.HDDVD:
|
||||
return HDDVD;
|
||||
case MediaType.BluRay:
|
||||
return BD;
|
||||
default:
|
||||
return Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Template field values for submission info
|
||||
/// </summary>
|
||||
@@ -35,13 +84,19 @@
|
||||
|
||||
// Automatic Information
|
||||
|
||||
public const string DumpingProgramField = "Dumping Program";
|
||||
public const string DumpingDriveManufacturer = "Manufacturer";
|
||||
public const string DumpingDriveModel = "Model";
|
||||
public const string DumpingDriveFirmware = "Firmware";
|
||||
public const string ReportedDiscType = "Reported Disc Type";
|
||||
public const string PVDField = "Primary Volume Descriptor (PVD)";
|
||||
public const string DATField = "DAT";
|
||||
public const string SizeField = "Size";
|
||||
public const string CRC32Field = "CRC32";
|
||||
public const string MD5Field = "MD5";
|
||||
public const string SHA1Field = "SHA1";
|
||||
public const string MatchingIDsField = "Matching IDs";
|
||||
public const string FullyMatchingIDField = "Fully Matching ID";
|
||||
public const string PartiallyMatchingIDsField = "Partially Matching IDs";
|
||||
public const string ErrorCountField = "Error Count";
|
||||
public const string CuesheetField = "Cuesheet";
|
||||
public const string SubIntentionField = "SubIntention Data (SecuROM/LibCrypt)";
|
||||
@@ -53,11 +108,7 @@
|
||||
public const string PlayStationEDCField = "EDC";
|
||||
public const string PlayStationAntiModchipField = "Anti-modchip";
|
||||
public const string PlayStationLibCryptField = "LibCrypt";
|
||||
public const string XBOXDMIHash = "DMI.bin Hashes";
|
||||
public const string XBOXPFIHash = "PFI.bin Hashes";
|
||||
public const string XBOXSSHash = "SS.bin Hashes";
|
||||
public const string XBOXSSRanges = "Security Sector Ranges";
|
||||
public const string XBOXSSVersion = "Security Sector Version";
|
||||
|
||||
// Default values
|
||||
|
||||
650
MPF.Core/Data/Drive.cs
Normal file
650
MPF.Core/Data/Drive.cs
Normal file
@@ -0,0 +1,650 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Management.Infrastructure;
|
||||
using Microsoft.Management.Infrastructure.Generic;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Utilities;
|
||||
using RedumpLib.Data;
|
||||
#if NETFRAMEWORK
|
||||
using IMAPI2;
|
||||
#endif
|
||||
|
||||
namespace MPF.Core.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents information for a single drive
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// TODO: This needs to be less Windows-centric. Devices do not always have a single letter that can be used.
|
||||
/// TODO: Can the Aaru models be used instead of the ones I've created here?
|
||||
/// </remarks>
|
||||
public class Drive
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Represents drive type
|
||||
/// </summary>
|
||||
public InternalDriveType? InternalDriveType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Drive partition format
|
||||
/// </summary>
|
||||
public string DriveFormat { get; private set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Windows drive path
|
||||
/// </summary>
|
||||
public string Name { get; private set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Represents if Windows has marked the drive as active
|
||||
/// </summary>
|
||||
public bool MarkedActive { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the total size of the drive
|
||||
/// </summary>
|
||||
public long TotalSize { get; private set; } = default;
|
||||
|
||||
/// <summary>
|
||||
/// Media label as read by Windows
|
||||
/// </summary>
|
||||
/// <remarks>The try/catch is needed because Windows will throw an exception if the drive is not marked as active</remarks>
|
||||
public string VolumeLabel { get; private set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Derived Fields
|
||||
|
||||
/// <summary>
|
||||
/// Media label as read by Windows, formatted to avoid odd outputs
|
||||
/// </summary>
|
||||
public string FormattedVolumeLabel
|
||||
{
|
||||
get
|
||||
{
|
||||
string volumeLabel = Template.DiscNotDetected;
|
||||
if (this.MarkedActive)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(this.VolumeLabel))
|
||||
volumeLabel = "track";
|
||||
else
|
||||
volumeLabel = this.VolumeLabel;
|
||||
}
|
||||
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
volumeLabel = volumeLabel.Replace(c, '_');
|
||||
|
||||
return volumeLabel;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Windows drive letter
|
||||
/// </summary>
|
||||
public char Letter => this.Name == null || this.Name.Length == 0 ? '\0' : this.Name[0];
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Protected constructor
|
||||
/// </summary>
|
||||
protected Drive() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new Drive object from a drive type and device path
|
||||
/// </summary>
|
||||
/// <param name="driveType">InternalDriveType value representing the drive type</param>
|
||||
/// <param name="devicePath">Path to the device according to the local machine</param>
|
||||
public static Drive Create(InternalDriveType? driveType, string devicePath)
|
||||
{
|
||||
// Create a new, empty drive object
|
||||
var drive = new Drive()
|
||||
{
|
||||
InternalDriveType = driveType,
|
||||
};
|
||||
|
||||
// If we have an invalid device path, return null
|
||||
if (string.IsNullOrWhiteSpace(devicePath))
|
||||
return null;
|
||||
|
||||
// Sanitize a Windows-formatted long device path
|
||||
if (devicePath.StartsWith("\\\\.\\"))
|
||||
devicePath = devicePath.Substring("\\\\.\\".Length);
|
||||
|
||||
// Create and validate the drive info object
|
||||
var driveInfo = new DriveInfo(devicePath);
|
||||
if (driveInfo == null || driveInfo == default)
|
||||
return null;
|
||||
|
||||
// Fill in the rest of the data
|
||||
drive.PopulateFromDriveInfo(driveInfo);
|
||||
|
||||
return drive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate all fields from a DriveInfo object
|
||||
/// </summary>
|
||||
/// <param name="driveInfo">DriveInfo object to populate from</param>
|
||||
private void PopulateFromDriveInfo(DriveInfo driveInfo)
|
||||
{
|
||||
// If we have an invalid DriveInfo, just return
|
||||
if (driveInfo == null || driveInfo == default)
|
||||
return;
|
||||
|
||||
// Populate the data fields
|
||||
this.Name = driveInfo.Name;
|
||||
this.MarkedActive = driveInfo.IsReady;
|
||||
if (this.MarkedActive)
|
||||
{
|
||||
this.DriveFormat = driveInfo.DriveFormat;
|
||||
this.TotalSize = driveInfo.TotalSize;
|
||||
this.VolumeLabel = driveInfo.VolumeLabel;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.DriveFormat = string.Empty;
|
||||
this.TotalSize = default;
|
||||
this.VolumeLabel = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
#region Public Functionality
|
||||
|
||||
/// <summary>
|
||||
/// Create a list of active drives matched to their volume labels
|
||||
/// </summary>
|
||||
/// <param name="ignoreFixedDrives">True to ignore fixed drives from population, false otherwise</param>
|
||||
/// <returns>Active drives, matched to labels, if possible</returns>
|
||||
public static List<Drive> CreateListOfDrives(bool ignoreFixedDrives)
|
||||
{
|
||||
var drives = GetDriveList(ignoreFixedDrives);
|
||||
drives = drives?.OrderBy(i => i.Letter)?.ToList();
|
||||
return drives;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current media type from drive letter
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public (MediaType?, string) GetMediaType()
|
||||
{
|
||||
// Take care of the non-optical stuff first
|
||||
// TODO: See if any of these can be more granular, like Optical is
|
||||
if (this.InternalDriveType == Data.InternalDriveType.Floppy)
|
||||
return (MediaType.FloppyDisk, null);
|
||||
else if (this.InternalDriveType == Data.InternalDriveType.HardDisk)
|
||||
return (MediaType.HardDisk, null);
|
||||
else if (this.InternalDriveType == Data.InternalDriveType.Removable)
|
||||
return (MediaType.FlashDrive, null);
|
||||
#if NET6_0_OR_GREATER
|
||||
else
|
||||
return GetMediaTypeFromSize();
|
||||
#endif
|
||||
|
||||
// Get the current drive information
|
||||
string deviceId = null;
|
||||
bool loaded = false;
|
||||
try
|
||||
{
|
||||
// Get the device ID first
|
||||
CimSession session = CimSession.Create(null);
|
||||
var collection = session.QueryInstances("root\\CIMV2", "WQL", $"SELECT * FROM Win32_CDROMDrive WHERE Id = '{this.Letter}:\'");
|
||||
|
||||
foreach (CimInstance instance in collection)
|
||||
{
|
||||
CimKeyedCollection<CimProperty> properties = instance.CimInstanceProperties;
|
||||
deviceId = (string)properties["DeviceID"]?.Value;
|
||||
loaded = (bool)properties["MediaLoaded"]?.Value;
|
||||
}
|
||||
|
||||
// If we got no valid device, we don't care and just return
|
||||
if (deviceId == null)
|
||||
return (null, "Device could not be found");
|
||||
else if (!loaded)
|
||||
return (null, "Device is not reporting media loaded");
|
||||
|
||||
#if NETFRAMEWORK
|
||||
|
||||
MsftDiscMaster2 discMaster = new MsftDiscMaster2();
|
||||
deviceId = deviceId.ToLower().Replace('\\', '#').Replace('/', '#');
|
||||
string id = null;
|
||||
foreach (var disc in discMaster)
|
||||
{
|
||||
if (disc.ToString().Contains(deviceId))
|
||||
id = disc.ToString();
|
||||
}
|
||||
|
||||
// If we couldn't find the drive, we don't care and return
|
||||
if (id == null)
|
||||
return (null, "Device ID could not be found");
|
||||
|
||||
// Create the required objects for reading from the drive
|
||||
MsftDiscRecorder2 recorder = new MsftDiscRecorder2();
|
||||
recorder.InitializeDiscRecorder(id);
|
||||
MsftDiscFormat2Data dataWriter = new MsftDiscFormat2Data();
|
||||
|
||||
// If the recorder is not supported, just return
|
||||
if (!dataWriter.IsRecorderSupported(recorder))
|
||||
return (null, "IMAPI2 recorder not supported");
|
||||
|
||||
// Otherwise, set the recorder to get information from
|
||||
dataWriter.Recorder = recorder;
|
||||
|
||||
var media = dataWriter.CurrentPhysicalMediaType;
|
||||
return (media.IMAPIToMediaType(), null);
|
||||
|
||||
#else
|
||||
|
||||
return (null, "IMAPI2 recorder not supported");
|
||||
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (null, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current system from drive
|
||||
/// </summary>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public RedumpSystem? GetRedumpSystem(RedumpSystem? defaultValue)
|
||||
{
|
||||
string drivePath = $"{this.Letter}:\\";
|
||||
|
||||
// If we can't read the media in that drive, we can't do anything
|
||||
if (!Directory.Exists(drivePath))
|
||||
return defaultValue;
|
||||
|
||||
// We're going to assume for floppies, HDDs, and removable drives
|
||||
// TODO: Try to be smarter about this
|
||||
if (this.InternalDriveType != Data.InternalDriveType.Optical)
|
||||
return RedumpSystem.IBMPCcompatible;
|
||||
|
||||
// Check volume labels first
|
||||
RedumpSystem? systemFromLabel = GetRedumpSystemFromVolumeLabel();
|
||||
if (systemFromLabel != null)
|
||||
return systemFromLabel;
|
||||
|
||||
// Get a list of files for quicker checking
|
||||
#region Consoles
|
||||
|
||||
// Bandai Playdia Quick Interactive System
|
||||
try
|
||||
{
|
||||
List<string> files = Directory.EnumerateFiles(drivePath, "*", SearchOption.TopDirectoryOnly).ToList();
|
||||
|
||||
if (files.Any(f => f.EndsWith(".AJS", StringComparison.OrdinalIgnoreCase))
|
||||
&& files.Any(f => f.EndsWith(".GLB", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return RedumpSystem.BandaiPlaydiaQuickInteractiveSystem;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Mattel Fisher-Price iXL
|
||||
if (File.Exists(Path.Combine(drivePath, "iXL", "iXLUpdater.exe")))
|
||||
{
|
||||
return RedumpSystem.MattelFisherPriceiXL;
|
||||
}
|
||||
|
||||
// Microsoft Xbox 360
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "$SystemUpdate"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "$SystemUpdate")).Any()
|
||||
&& this.TotalSize <= 500_000_000)
|
||||
{
|
||||
return RedumpSystem.MicrosoftXbox360;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Microsoft Xbox One
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "MSXC"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "MSXC")).Any())
|
||||
{
|
||||
return RedumpSystem.MicrosoftXboxOne;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Sega Dreamcast
|
||||
if (File.Exists(Path.Combine(drivePath, "IP.BIN")))
|
||||
{
|
||||
return RedumpSystem.SegaDreamcast;
|
||||
}
|
||||
|
||||
// Sega Mega-CD / Sega-CD
|
||||
if (File.Exists(Path.Combine(drivePath, "_BOOT", "IP.BIN"))
|
||||
|| File.Exists(Path.Combine(drivePath, "_BOOT", "SP.BIN"))
|
||||
|| File.Exists(Path.Combine(drivePath, "_BOOT", "SP_AS.BIN"))
|
||||
|| File.Exists(Path.Combine(drivePath, "FILESYSTEM.BIN")))
|
||||
{
|
||||
return RedumpSystem.SegaMegaCDSegaCD;
|
||||
}
|
||||
|
||||
// Sega Saturn
|
||||
try
|
||||
{
|
||||
byte[] sector = ReadSector(0);
|
||||
if (sector != null)
|
||||
{
|
||||
if (sector.StartsWith(Interface.SaturnSectorZeroStart))
|
||||
return RedumpSystem.SegaSaturn;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Sony PlayStation and Sony PlayStation 2
|
||||
string psxExePath = Path.Combine(drivePath, "PSX.EXE");
|
||||
string systemCnfPath = Path.Combine(drivePath, "SYSTEM.CNF");
|
||||
if (File.Exists(systemCnfPath))
|
||||
{
|
||||
// Check for either BOOT or BOOT2
|
||||
var systemCnf = new IniFile(systemCnfPath);
|
||||
if (systemCnf.ContainsKey("BOOT"))
|
||||
return RedumpSystem.SonyPlayStation;
|
||||
else if (systemCnf.ContainsKey("BOOT2"))
|
||||
return RedumpSystem.SonyPlayStation2;
|
||||
}
|
||||
else if (File.Exists(psxExePath))
|
||||
{
|
||||
return RedumpSystem.SonyPlayStation;
|
||||
}
|
||||
|
||||
// Sony PlayStation 3
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "PS3_GAME"))
|
||||
|| Directory.Exists(Path.Combine(drivePath, "PS3_UPDATE"))
|
||||
|| File.Exists(Path.Combine(drivePath, "PS3_DISC.SFB")))
|
||||
{
|
||||
return RedumpSystem.SonyPlayStation3;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Sony PlayStation 4
|
||||
// There are more possible paths that could be checked.
|
||||
// There are some entries that can be found on most PS4 discs:
|
||||
// "/app/GAME_SERIAL/app.pkg"
|
||||
// "/bd/param.sfo"
|
||||
// "/license/rif"
|
||||
// There are also extra files that can be found on some discs:
|
||||
// "/patch/GAME_SERIAL/patch.pkg" can be found in Redump entry 66816.
|
||||
// Originally on disc as "/patch/CUSA11302/patch.pkg".
|
||||
// Is used as an on-disc update for the base game app without needing to get update from the internet.
|
||||
// "/addcont/GAME_SERIAL/CONTENT_ID/ac.pkg" can be found in Redump entry 97619.
|
||||
// Originally on disc as "/addcont/CUSA00288/FFXIVEXPS400001A/ac.pkg".
|
||||
if (File.Exists(Path.Combine(drivePath, "PS4", "UPDATE", "PS4UPDATE.PUP")))
|
||||
{
|
||||
return RedumpSystem.SonyPlayStation4;
|
||||
}
|
||||
|
||||
// V.Tech V.Flash / V.Smile Pro
|
||||
if (File.Exists(Path.Combine(drivePath, "0SYSTEM")))
|
||||
{
|
||||
return RedumpSystem.VTechVFlashVSmilePro;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Computers
|
||||
|
||||
// Sharp X68000
|
||||
if (File.Exists(Path.Combine(drivePath, "COMMAND.X")))
|
||||
{
|
||||
return RedumpSystem.SharpX68000;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Video Formats
|
||||
|
||||
// BD-Video
|
||||
if (Directory.Exists(Path.Combine(drivePath, "BDMV")))
|
||||
{
|
||||
// Technically BD-Audio has this as well, but it's hard to split that out right now
|
||||
return RedumpSystem.BDVideo;
|
||||
}
|
||||
|
||||
// DVD-Audio and DVD-Video
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "AUDIO_TS"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "AUDIO_TS")).Any())
|
||||
{
|
||||
return RedumpSystem.DVDAudio;
|
||||
}
|
||||
|
||||
else if (Directory.Exists(Path.Combine(drivePath, "VIDEO_TS"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "VIDEO_TS")).Any())
|
||||
{
|
||||
return RedumpSystem.DVDVideo;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// HD-DVD-Video
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "HVDVD_TS"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "HVDVD_TS")).Any())
|
||||
{
|
||||
return RedumpSystem.HDDVDVideo;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// VCD
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(drivePath, "VCD"))
|
||||
&& Directory.EnumerateFiles(Path.Combine(drivePath, "VCD")).Any())
|
||||
{
|
||||
return RedumpSystem.VideoCD;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
#endregion
|
||||
|
||||
// Default return
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current system from the drive volume label
|
||||
/// </summary>
|
||||
/// <returns>The system based on volume label, null if none detected</returns>
|
||||
public RedumpSystem? GetRedumpSystemFromVolumeLabel()
|
||||
{
|
||||
// If the volume label is empty, we can't do anything
|
||||
if (string.IsNullOrWhiteSpace(this.VolumeLabel))
|
||||
return null;
|
||||
|
||||
// Audio CD
|
||||
if (this.VolumeLabel.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.AudioCD;
|
||||
|
||||
// Microsoft Xbox
|
||||
if (this.VolumeLabel.Equals("SEP13011042", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox;
|
||||
else if (this.VolumeLabel.Equals("SEP13011042072", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox;
|
||||
|
||||
// Microsoft Xbox 360
|
||||
if (this.VolumeLabel.Equals("XBOX360", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox360;
|
||||
else if (this.VolumeLabel.Equals("XGD2DVD_NTSC", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox360;
|
||||
|
||||
// Microsoft Xbox 360 - Too overly broad even if a lot of discs use this
|
||||
//if (this.VolumeLabel.Equals("CD_ROM", StringComparison.OrdinalIgnoreCase))
|
||||
// return RedumpSystem.MicrosoftXbox360; // Also for Xbox One?
|
||||
//if (this.VolumeLabel.Equals("DVD_ROM", StringComparison.OrdinalIgnoreCase))
|
||||
// return RedumpSystem.MicrosoftXbox360;
|
||||
|
||||
// Sega Mega-CD / Sega-CD
|
||||
if (this.VolumeLabel.Equals("Sega_CD", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SegaMegaCDSegaCD;
|
||||
|
||||
// Sony PlayStation 3
|
||||
if (this.VolumeLabel.Equals("PS3VOLUME", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SonyPlayStation3;
|
||||
|
||||
// Sony PlayStation 4
|
||||
if (this.VolumeLabel.Equals("PS4VOLUME", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SonyPlayStation4;
|
||||
|
||||
// Sony PlayStation 5
|
||||
if (this.VolumeLabel.Equals("PS5VOLUME", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SonyPlayStation5;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a sector with a specified size from the drive
|
||||
/// </summary>
|
||||
/// <param name="num">Sector number, non-negative</param>
|
||||
/// <param name="size">Size of a sector in bytes</param>
|
||||
/// <returns>Byte array representing the sector, null on error</returns>
|
||||
public byte[] ReadSector(long num, int size = 2048)
|
||||
{
|
||||
// Missing drive leter is not supported
|
||||
if (string.IsNullOrEmpty(this.Name))
|
||||
return null;
|
||||
|
||||
// We don't support negative sectors
|
||||
if (num < 0)
|
||||
return null;
|
||||
|
||||
// Wrap the following in case of device access errors
|
||||
Stream fs = null;
|
||||
try
|
||||
{
|
||||
// Open the drive as a device
|
||||
fs = File.OpenRead($"\\\\?\\{this.Letter}:");
|
||||
|
||||
// Seek to the start of the sector, if possible
|
||||
long start = num * size;
|
||||
fs.Seek(start, SeekOrigin.Begin);
|
||||
|
||||
// Read and return the sector
|
||||
byte[] buffer = new byte[size];
|
||||
fs.Read(buffer, 0, size);
|
||||
return buffer;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh the current drive information based on path
|
||||
/// </summary>
|
||||
public void RefreshDrive()
|
||||
{
|
||||
var driveInfo = DriveInfo.GetDrives().FirstOrDefault(d => d?.Name == this.Name);
|
||||
this.PopulateFromDriveInfo(driveInfo);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Get the media type for a device path based on size
|
||||
/// </summary>
|
||||
/// <returns>MediaType, null on error</returns>
|
||||
private (MediaType?, string) GetMediaTypeFromSize()
|
||||
{
|
||||
if (this.TotalSize >= 0 && this.TotalSize < 800_000_000 && this.DriveFormat == "CDFS")
|
||||
return (MediaType.CDROM, null);
|
||||
else if (this.TotalSize >= 400_000_000 && this.TotalSize <= 8_540_000_000 && this.DriveFormat == "UDF")
|
||||
return (MediaType.DVD, null);
|
||||
else
|
||||
return (MediaType.BluRay, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all current attached Drives
|
||||
/// </summary>
|
||||
/// <param name="ignoreFixedDrives">True to ignore fixed drives from population, false otherwise</param>
|
||||
/// <returns>List of drives, null on error</returns>
|
||||
/// <remarks>
|
||||
/// https://stackoverflow.com/questions/3060796/how-to-distinguish-between-usb-and-floppy-devices?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
|
||||
/// https://msdn.microsoft.com/en-us/library/aa394173(v=vs.85).aspx
|
||||
/// </remarks>
|
||||
private static List<Drive> GetDriveList(bool ignoreFixedDrives)
|
||||
{
|
||||
var desiredDriveTypes = new List<DriveType>() { DriveType.CDRom };
|
||||
if (!ignoreFixedDrives)
|
||||
{
|
||||
desiredDriveTypes.Add(DriveType.Fixed);
|
||||
desiredDriveTypes.Add(DriveType.Removable);
|
||||
}
|
||||
|
||||
// TODO: Reduce reliance on `DriveInfo`
|
||||
// https://github.com/aaru-dps/Aaru/blob/5164a154e2145941472f2ee0aeb2eff3338ecbb3/Aaru.Devices/Windows/ListDevices.cs#L66
|
||||
|
||||
// Create an output drive list
|
||||
List<Drive> drives = new List<Drive>();
|
||||
|
||||
// Get all standard supported drive types
|
||||
try
|
||||
{
|
||||
drives = DriveInfo.GetDrives()
|
||||
.Where(d => desiredDriveTypes.Contains(d.DriveType))
|
||||
.Select(d => Create(EnumConverter.ToInternalDriveType(d.DriveType), d.Name))
|
||||
.ToList();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return drives;
|
||||
}
|
||||
|
||||
// Find and update all floppy drives
|
||||
try
|
||||
{
|
||||
CimSession session = CimSession.Create(null);
|
||||
var collection = session.QueryInstances("root\\CIMV2", "WQL", "SELECT * FROM Win32_LogicalDisk");
|
||||
|
||||
foreach (CimInstance instance in collection)
|
||||
{
|
||||
CimKeyedCollection<CimProperty> properties = instance.CimInstanceProperties;
|
||||
uint? mediaType = properties["MediaType"]?.Value as uint?;
|
||||
if (mediaType != null && ((mediaType > 0 && mediaType < 11) || (mediaType > 12 && mediaType < 22)))
|
||||
{
|
||||
char devId = (properties["Caption"].Value as string)[0];
|
||||
drives.ForEach(d => { if (d.Letter == devId) { d.InternalDriveType = Data.InternalDriveType.Floppy; } });
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
return drives;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
32
MPF.Core/Data/Enumerations.cs
Normal file
32
MPF.Core/Data/Enumerations.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
namespace MPF.Core.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Drive type for dumping
|
||||
/// </summary>
|
||||
public enum InternalDriveType
|
||||
{
|
||||
Optical,
|
||||
Floppy,
|
||||
HardDisk,
|
||||
Removable,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Program that is being used to dump media
|
||||
/// </summary>
|
||||
public enum InternalProgram
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
// Dumping support
|
||||
Aaru,
|
||||
DD,
|
||||
DiscImageCreator,
|
||||
Redumper,
|
||||
|
||||
// Verification support only
|
||||
CleanRip,
|
||||
DCDumper,
|
||||
UmdImageCreator,
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user