mirror of
https://github.com/SabreTools/MPF.git
synced 2026-02-04 05:35:52 +00:00
Compare commits
507 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
3a2bda6fb6 | ||
|
|
aea2403153 | ||
|
|
6e334df42f | ||
|
|
04cb68c9bd | ||
|
|
06060c071b | ||
|
|
02903686ad | ||
|
|
00cbed725d | ||
|
|
dabccd3a8a | ||
|
|
0e1e499a66 | ||
|
|
b4f485a0cc | ||
|
|
5bad68b9ff | ||
|
|
2db686fc47 | ||
|
|
d705a4b316 | ||
|
|
0154ee5bb6 | ||
|
|
29f14f5690 | ||
|
|
dd6f7b0794 | ||
|
|
e5c9591d64 | ||
|
|
df8da8bd46 | ||
|
|
c9b21006d1 | ||
|
|
2b37882322 | ||
|
|
8a2b3f2c89 | ||
|
|
c16a9aeb70 | ||
|
|
d5a0797c92 | ||
|
|
a55a769886 | ||
|
|
fd18c60f28 | ||
|
|
2704d1f88d | ||
|
|
c16c938fa4 | ||
|
|
497e2a09fd | ||
|
|
8bc8887ce6 | ||
|
|
7e5a5586f9 | ||
|
|
eee068db7e | ||
|
|
79e70173fa | ||
|
|
4f732557b9 | ||
|
|
6cbcebd661 | ||
|
|
f74dc01657 | ||
|
|
4735bef7b4 | ||
|
|
52a925df12 | ||
|
|
3e10199cb0 | ||
|
|
470e641a8c | ||
|
|
f61b84d058 | ||
|
|
5e77b43be1 | ||
|
|
46530a9fca | ||
|
|
12610c0d69 | ||
|
|
9bb9d3f407 | ||
|
|
a0ed20042c | ||
|
|
37c253aac2 | ||
|
|
68135c58ae | ||
|
|
f9efa71fcc | ||
|
|
184913ad28 | ||
|
|
ff52767a02 | ||
|
|
34ac5f9ba0 | ||
|
|
7296d109cc | ||
|
|
9be705ae30 | ||
|
|
af8b376f5a | ||
|
|
03f9668048 | ||
|
|
3bb23fa7cc | ||
|
|
f85c9d4e7e | ||
|
|
5de3d209be | ||
|
|
f1b136c817 | ||
|
|
c18829e0b3 | ||
|
|
d114b7f868 | ||
|
|
445cc173ce | ||
|
|
1e28fcad2e | ||
|
|
8d4e5155d9 | ||
|
|
027f562573 | ||
|
|
74caf084ca | ||
|
|
7396b02543 | ||
|
|
8035826b1b | ||
|
|
c6e73582c5 | ||
|
|
ca09d8c703 | ||
|
|
40b6551c7a | ||
|
|
95b664705d | ||
|
|
6bda7b35a2 | ||
|
|
6fedebf2a9 | ||
|
|
02f98c674b | ||
|
|
fb1e4130df | ||
|
|
c507f52b80 | ||
|
|
7b2784f1a2 | ||
|
|
7a7c83e8cf | ||
|
|
b86ef09763 | ||
|
|
71c050edf6 | ||
|
|
988f25b514 | ||
|
|
e878e8b904 | ||
|
|
bd3484cb3d | ||
|
|
3d769ed707 | ||
|
|
613be66f91 | ||
|
|
81e0ffbc3c | ||
|
|
8f3d325e7d | ||
|
|
a63472c6e6 | ||
|
|
8c98005605 | ||
|
|
8062d6cf17 | ||
|
|
78bf6e63ed | ||
|
|
68e0d759f7 | ||
|
|
26e72284af | ||
|
|
0efecd6601 | ||
|
|
9a3c2eb626 | ||
|
|
ca753b4526 | ||
|
|
230b6ca721 | ||
|
|
dc90f9af3f | ||
|
|
b5898c7ea3 | ||
|
|
36f1aea509 | ||
|
|
6742444182 | ||
|
|
e01fd37e6b | ||
|
|
ca7071f82a | ||
|
|
3cb67e3e65 | ||
|
|
e67dd589b5 | ||
|
|
74f491eaaa | ||
|
|
9ebd28ef5a | ||
|
|
2a58052bfd | ||
|
|
5ed73aff2b | ||
|
|
5a6ad09004 | ||
|
|
6a43b74043 | ||
|
|
69dc91aa1a | ||
|
|
f840db5143 | ||
|
|
f33cd41ebb | ||
|
|
da7896e62a | ||
|
|
08b5b4a1aa | ||
|
|
c397701818 | ||
|
|
617eb00f21 | ||
|
|
751fd0cf1e | ||
|
|
84c64e6073 | ||
|
|
ff5bc464ab | ||
|
|
b09a87c7e4 | ||
|
|
4032b48e63 | ||
|
|
12fad35065 | ||
|
|
c28be2da72 | ||
|
|
122cc0d20b | ||
|
|
89db32dd53 | ||
|
|
59040ae0f0 | ||
|
|
d8035745a9 | ||
|
|
c73e13c1f0 | ||
|
|
af75c7c949 | ||
|
|
896eb28308 | ||
|
|
6ca3d39e5f | ||
|
|
a7af0d0d7b | ||
|
|
04f5a7ea8d | ||
|
|
5d82cc5622 | ||
|
|
2f37f51c0c | ||
|
|
4690db61e1 | ||
|
|
672ec42903 | ||
|
|
cb39599a46 | ||
|
|
80b5ff3920 | ||
|
|
f27d3a91d3 | ||
|
|
b18357bff5 | ||
|
|
e3cd5b7082 | ||
|
|
16d7a6224b | ||
|
|
f8e32ec06c | ||
|
|
7073d4e298 | ||
|
|
f7f464920b | ||
|
|
e677dc20e9 | ||
|
|
9871eb9928 | ||
|
|
12b43cf688 | ||
|
|
7dd6db66ee | ||
|
|
d7726a070e | ||
|
|
fbc9d04782 | ||
|
|
24b08dd245 | ||
|
|
c7ebe69b05 | ||
|
|
22ffda4b5a | ||
|
|
b89c051d7d | ||
|
|
8b41f03472 | ||
|
|
700ff50eef | ||
|
|
95ac7236ff | ||
|
|
755f1b8e95 | ||
|
|
d431a4c87f | ||
|
|
04348d2d58 | ||
|
|
6f5214c1a4 | ||
|
|
1fe12be0b5 | ||
|
|
9c9ca16366 | ||
|
|
1702db71d1 | ||
|
|
0ba7ccdb9a | ||
|
|
3ccf65190e | ||
|
|
6b9ee3d5ed | ||
|
|
3ee0355034 | ||
|
|
7074fa1e2c | ||
|
|
44b91a6611 | ||
|
|
b2185dbed9 | ||
|
|
ec4b69b6e6 | ||
|
|
b6db873a00 | ||
|
|
db9222b737 | ||
|
|
b7bfa3ba28 | ||
|
|
ab25687119 | ||
|
|
9bfa0a01ad | ||
|
|
19c99fb7fe | ||
|
|
913244459e | ||
|
|
c66df99e22 | ||
|
|
03f4a6e2e4 | ||
|
|
31a243eeb4 | ||
|
|
043c0eff1c | ||
|
|
ff44313e13 | ||
|
|
e06ed31b21 | ||
|
|
aeaec9e805 | ||
|
|
6df0c76939 | ||
|
|
72efffcec4 | ||
|
|
930e4f7514 | ||
|
|
85f71032b5 | ||
|
|
ead530e2ec | ||
|
|
dc14b1ea52 | ||
|
|
4628be2855 | ||
|
|
1f24c08770 | ||
|
|
4889b9d0bf | ||
|
|
b3d7422a66 | ||
|
|
a0000528de | ||
|
|
2be46ec7a1 | ||
|
|
f2510a08a4 | ||
|
|
2787377250 | ||
|
|
e61ca31a3f | ||
|
|
1b735b5d06 | ||
|
|
ad3d26cdea | ||
|
|
f372ec4ccd | ||
|
|
44e75a50d7 | ||
|
|
6f0ea2de3e | ||
|
|
b4f0f7f4b3 | ||
|
|
5027d67731 | ||
|
|
6c8016345a | ||
|
|
7ba04e63c7 | ||
|
|
77dc1d0029 | ||
|
|
2b6538707f | ||
|
|
902e4e5715 | ||
|
|
28f6d50e5a | ||
|
|
d8ed7d6ad7 | ||
|
|
078d7d0ea3 | ||
|
|
5895a66c7a | ||
|
|
5ccff836e2 | ||
|
|
b2c2e8c4d9 | ||
|
|
890959cfe0 | ||
|
|
8729c7f20c | ||
|
|
74826909f4 | ||
|
|
eb4904afb4 | ||
|
|
06975316b9 | ||
|
|
e0be24e54f | ||
|
|
eb3cbc44a7 | ||
|
|
d6f39bfd4c | ||
|
|
576fa07a2c | ||
|
|
ae2b26f84e | ||
|
|
1d9a2c9be7 | ||
|
|
538c0bba09 | ||
|
|
57c31cad48 | ||
|
|
093db36f44 | ||
|
|
fd4db3f8f0 | ||
|
|
856a3161be | ||
|
|
dfafe9789a | ||
|
|
9f750d01c4 | ||
|
|
705ee82cbb | ||
|
|
d1f80efa41 | ||
|
|
f88e6617e5 | ||
|
|
1401422b08 | ||
|
|
4539066af0 | ||
|
|
ec23502275 | ||
|
|
331f875e7f | ||
|
|
e68f88062f | ||
|
|
d1bb8184d1 | ||
|
|
b7b3f36402 | ||
|
|
859af8efea | ||
|
|
8594d7884c | ||
|
|
946dc929f1 | ||
|
|
1e5b1a205e | ||
|
|
3271cd0ea3 | ||
|
|
647bab8cd3 | ||
|
|
89b2438dac | ||
|
|
1dcd36d640 | ||
|
|
2f63ebcd29 | ||
|
|
316953f38c | ||
|
|
62813ac701 | ||
|
|
22a936e60b | ||
|
|
6412205fa3 | ||
|
|
75c18ea3c4 | ||
|
|
6bdb93208e | ||
|
|
588ed19692 | ||
|
|
d56ab5ab37 | ||
|
|
819d18112e | ||
|
|
2e79cbb0db | ||
|
|
f024611de8 | ||
|
|
48e6283c37 | ||
|
|
fec70f17bc | ||
|
|
257f7ab7df | ||
|
|
c1ed3aca02 | ||
|
|
ace6a78236 | ||
|
|
f1e9f1d433 | ||
|
|
e83190c091 | ||
|
|
82eabc12ca | ||
|
|
76b549d773 | ||
|
|
227688d7dc | ||
|
|
4c9e2359af | ||
|
|
d179d7f464 | ||
|
|
fff19e75fd | ||
|
|
2175ccfb26 | ||
|
|
621923bdba | ||
|
|
3c216aa309 | ||
|
|
d85186e5cd | ||
|
|
1a94ad3d23 | ||
|
|
91776d939c | ||
|
|
3d058e633f | ||
|
|
94c0564fe8 | ||
|
|
87ecc7588e | ||
|
|
8a5c114a7e | ||
|
|
e307cb217f | ||
|
|
b8c56bea58 | ||
|
|
564a6af9b8 | ||
|
|
5bcde889b3 | ||
|
|
b39c96cdd2 | ||
|
|
2cc73a30f5 | ||
|
|
be7d745d10 | ||
|
|
d51adccab4 | ||
|
|
6141ce8539 | ||
|
|
96d6e8bd2f | ||
|
|
c034df4266 | ||
|
|
fe04c6df73 | ||
|
|
aff195eb71 | ||
|
|
3aca999b63 | ||
|
|
0e7ce76f01 | ||
|
|
6d72417512 | ||
|
|
ac89f06843 | ||
|
|
39ce56d579 | ||
|
|
9dbd30adba | ||
|
|
48de63513e | ||
|
|
56eaf7c2c5 | ||
|
|
c1bd30e008 | ||
|
|
4176f22d79 | ||
|
|
1e16e952cf | ||
|
|
9f493ae27a | ||
|
|
2021230836 | ||
|
|
12ba5702fd | ||
|
|
2cf083eb89 | ||
|
|
c1f22d47dc | ||
|
|
11287d081d | ||
|
|
8652af5697 | ||
|
|
69561cb1a0 | ||
|
|
d587d2b4b3 | ||
|
|
a19418e46f | ||
|
|
de22ead07c | ||
|
|
f777869103 | ||
|
|
aec1131271 | ||
|
|
308fad3ed2 | ||
|
|
61ce45667b | ||
|
|
ababfdd2ed | ||
|
|
9683074197 | ||
|
|
ab2bc8f50c | ||
|
|
aa86ddaf47 | ||
|
|
68afebace4 | ||
|
|
bebe3ab8a0 | ||
|
|
1f314df8c1 | ||
|
|
38c3638f21 | ||
|
|
cde4b671fc | ||
|
|
578854cd3b | ||
|
|
1cd7885194 | ||
|
|
c0de39c229 | ||
|
|
a1148f80c8 | ||
|
|
632654d00b | ||
|
|
a6d6b800a5 | ||
|
|
8527cc5746 | ||
|
|
f94f54f4d7 | ||
|
|
2091ef1d92 | ||
|
|
af865bca9e | ||
|
|
23588fa5ae | ||
|
|
e763fec01e | ||
|
|
732ff2ccca | ||
|
|
f960aca8a9 | ||
|
|
335c1388d4 | ||
|
|
87c0d5b44b | ||
|
|
1a44fb5c8a | ||
|
|
285921cae3 | ||
|
|
2255dba640 | ||
|
|
99158f31c9 | ||
|
|
53a2ef227b | ||
|
|
c0efc63741 | ||
|
|
905bd1a7dc | ||
|
|
5d49d4833f | ||
|
|
8fd3e2d405 | ||
|
|
1521a918f3 | ||
|
|
5f580ee025 | ||
|
|
9c7cee0aa3 | ||
|
|
d549609a0f | ||
|
|
207fdbb49c | ||
|
|
63e63a0033 | ||
|
|
73be55a645 | ||
|
|
d913aa247e | ||
|
|
d9a9f3bfd4 | ||
|
|
ea3e040b3f | ||
|
|
ed67522675 | ||
|
|
6e3902bbb1 | ||
|
|
3f802e8548 | ||
|
|
c3c4cf6e5b | ||
|
|
39258c4e85 | ||
|
|
df81259fba | ||
|
|
a835c81951 | ||
|
|
af4f3e8444 | ||
|
|
085916e1e6 | ||
|
|
557354c844 | ||
|
|
a23a74ffa4 | ||
|
|
958aeeae32 | ||
|
|
c73ff42500 | ||
|
|
24a93e298b | ||
|
|
ae81bb0743 | ||
|
|
cf7863fbb2 | ||
|
|
5e0e71120d | ||
|
|
5adbdd29e6 | ||
|
|
fd855b9024 | ||
|
|
17c283ff67 | ||
|
|
a37e6aaf18 | ||
|
|
1dbf23ca95 | ||
|
|
2e52d00107 | ||
|
|
eb69b74b4a | ||
|
|
db4a785558 | ||
|
|
9bdd2d6951 | ||
|
|
de48c8f0f9 | ||
|
|
c59f7c2dae | ||
|
|
2740a6a1c1 | ||
|
|
56e8470069 | ||
|
|
a5f1a12aee | ||
|
|
8749b486a8 | ||
|
|
3446957f68 | ||
|
|
cb9813db3d | ||
|
|
6e6b716c18 | ||
|
|
400ef38c60 | ||
|
|
87d5fc0e66 | ||
|
|
d5d8ae0501 | ||
|
|
fae7a5254d | ||
|
|
97be13f020 | ||
|
|
dd0dfc5cf5 | ||
|
|
a7a295434d | ||
|
|
319f5563cb | ||
|
|
939174d8c4 | ||
|
|
1d5d7b265e | ||
|
|
a2ac7222f9 | ||
|
|
4f0b5904c3 | ||
|
|
7ff848347c | ||
|
|
a1c89d17b8 | ||
|
|
3575c43703 | ||
|
|
928c9966fa | ||
|
|
a404a270f1 | ||
|
|
dfba97685a | ||
|
|
8de2f1c9bb | ||
|
|
f57b29615b | ||
|
|
565a9bb09a | ||
|
|
d9d61cf665 | ||
|
|
8b600a6a35 |
27
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
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/dicui/build/artifacts) to see if the feature already exists.
|
||||
- .NET Core 3.1 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/DICUI/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.
|
||||
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/dicui/build/artifacts) to see if the issue has already been addressed.
|
||||
- .NET Core 3.1 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.7.2 running on (Operating System)
|
||||
- [ ] .NET Framework 4.8 running on (Operating System)
|
||||
- [ ] .NET Core 3.1 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.
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "DICUI.Library/Aaru/CICMMetadata"]
|
||||
path = DICUI.Library/Aaru/CICMMetadata
|
||||
url = https://github.com/claunia/CICMMetadata
|
||||
27
.vscode/launch.json
vendored
Normal file
27
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||
// Use hover for the description of the existing attributes
|
||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (console)",
|
||||
"type": "coreclr",
|
||||
"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",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/DICUI",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
||||
42
.vscode/tasks.json
vendored
Normal file
42
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/DICUI/DICUI.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "publish",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/DICUI/DICUI.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"${workspaceFolder}/DICUI/DICUI.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
||||
19
App.config
19
App.config
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="DICUI.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
||||
</startup>
|
||||
<userSettings>
|
||||
<DICUI.Properties.Settings>
|
||||
<setting name="
|
||||
" serializeAs="String">
|
||||
<value>Release_ANSI\\DiscImageCreator.exe</value>
|
||||
</setting>
|
||||
</DICUI.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
17
App.xaml.cs
17
App.xaml.cs
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
||||
205
CHANGELIST.md
Normal file
205
CHANGELIST.md
Normal file
@@ -0,0 +1,205 @@
|
||||
### 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
|
||||
- Added experimental Avalonia UI
|
||||
- Created wiki
|
||||
- Removed .NET 4.6.2 and .NET Core 3.0 builds
|
||||
- Added .NET 4.8 and .NET Core 3.1 builds
|
||||
- Fix numerous things related to PS1/PS2
|
||||
- Make subdump running optional
|
||||
- Overhaul DICUI.Check with more options
|
||||
- Numerous small bug- and regression-fixes
|
||||
|
||||
### 1.16.1 (2020-05-07)
|
||||
|
||||
- Add preliminary support for DD for Windows (end to end still NW)
|
||||
- Add CNF parsing for Konami Python 2 discs (PS2-based)
|
||||
- Updated included Aaru version
|
||||
- Massive cleanup effort to detangle large chunks of code
|
||||
- Miscellaneous bugfixes that came from the above
|
||||
|
||||
### 1.16 (2020-04-13)
|
||||
|
||||
- Updated to DIC version 20200403
|
||||
- UI updates based on user feedback
|
||||
- Added support for Aaru (formerly DiscImageChef)
|
||||
- Added more support for different output file formats (such as CleanRip)
|
||||
- Add PS1/PS2 serial extraction and matching
|
||||
- Fix PS1 date support when both PSX.EXE and normal executable are both present
|
||||
- Update BurnOutSharp
|
||||
- Many MANY bits of internal cleanup
|
||||
|
||||
### 1.15 (2019-11-16)
|
||||
|
||||
- Updated to DIC version 20191116
|
||||
- Support non-optical, non-floppy stuff better
|
||||
- Update protection scanning and fix some things
|
||||
|
||||
### 1.14 (2019-10-01)
|
||||
|
||||
- Updated to DIC version 20191001
|
||||
- Added builds for .NET 4.6.2, .NET 4.7.2, and .NET Core 3.0
|
||||
- Updated and fixed a bunch of things related to Redump
|
||||
- Fixed path persistence when changing system and media type
|
||||
- Added more system autodetects
|
||||
- Added new, optional, disc information filling window (WIP)
|
||||
|
||||
### 1.13 (2019-07-02)
|
||||
|
||||
- Added new DIC commands and flags
|
||||
- Made DICUI Check more robust
|
||||
- Added and updated systems along with format cleanup
|
||||
- Created a new SubmissionInfo template (and internals)
|
||||
- Added automatic grabbing of Redump information, if possible
|
||||
- Better media format support (BD, UMD)
|
||||
- Initial disc type detection
|
||||
|
||||
### 1.12.2 (2019-04-19)
|
||||
|
||||
- Added DICUI Check, a new standalone tool for parsing DIC output from platforms unsupported by DICUI
|
||||
- Added a few machines/formats
|
||||
- Updated to DIC version 20190326
|
||||
- Added DMI data extraction for Xbox and X360
|
||||
|
||||
### 1.12.1 (2019-01-28)
|
||||
|
||||
- Fixed !submissionInfo.txt output for CD-ROM and GD-ROM
|
||||
|
||||
### 1.12 (2019-01-27)
|
||||
|
||||
- Added a few new systems and formats
|
||||
- Added new DIC commands and flags
|
||||
- Updated the `!submissionInfo.txt` file order
|
||||
- Fixed Audio CD handling
|
||||
- Added Sega CD / Mega CD header extraction
|
||||
- Readded Floppy Disk as a supported format
|
||||
- And more! See the full Git commit list for more details
|
||||
|
||||
### 1.11 (2018-09-20)
|
||||
|
||||
- Fix formatting of XBOX and XBOX 360 security sector output
|
||||
- Add new XBOX swap commands and outputs
|
||||
- Fixes for some PlayStation 2 and 4 outputs
|
||||
- Added external programs to AppVeyor builds
|
||||
- Fixed `.` in path issues with DIC; attempted to fix issues with `&`
|
||||
- Combined XBOX 360 XGD 2/3 due to new DIC support with Kreon drives
|
||||
- Fixed (semi-)longstanding bug with XBOX disc layer detection
|
||||
- Added DVD-Video protection output
|
||||
- Made custom parameters work a little more intuitively
|
||||
- Added *EXPERIMENTAL* Winforms-based UI
|
||||
- And more! See the full Git commit list for more details
|
||||
|
||||
### 1.10 (2018-07-29)
|
||||
|
||||
- Added many new options for user customization
|
||||
- Added unit testing and an AppVeyor build
|
||||
- Many code refactorings
|
||||
- **LOG WINDOW**
|
||||
- Separated out protection scan and Unshield ports to new projects
|
||||
- Added "empty drive" support; should help with 3DO and HFS dumping
|
||||
- And much more! See the full Git commit list for more details
|
||||
|
||||
### 1.07 (2018-06-27)
|
||||
|
||||
- Separated system and media type for easier navigation
|
||||
- Combined instances of single- and dual-layer discs
|
||||
- Removed reliance on **sg-raw** and **psxt001z**
|
||||
- Added system and disc type to the submission info
|
||||
- First attempt at getting current disc type
|
||||
- Made the three PSX-specific fields (**EDC**, **Anti-modchip**, and **LibCrypt**) automatically filled in, when possible
|
||||
- Many, many, many behind the scenes updates for speed, future features, and stability
|
||||
|
||||
### 1.06 (2018-06-15)
|
||||
|
||||
- Fixed not being able to use the `/c2` flag properly
|
||||
- Fixed times when the ability to start dumping was improperly allowed
|
||||
- Added full support for XBOX and XBOX360 (XDG1, XDG2) dumping through DIC (using a Kreon, or presumably a 0800)
|
||||
|
||||
### 1.05a (2018-06-14)
|
||||
|
||||
- Fixed some ordering and nullability issues
|
||||
- Added automatic fields for PS1, PS2, Saturn
|
||||
|
||||
### 1.05 (2018-06-14)
|
||||
|
||||
- Miscellaneous fixes around custom parameter validation, dump information accuracy, settings window, and TODO cleanup
|
||||
- Add many more supported platforms, mostly arcade (based on publicly available information)
|
||||
- Add floppy disk dumping support
|
||||
- Add optional disc eject on completion
|
||||
- Add subdump for Sega Saturn
|
||||
- Fully support newest version of DIC including all new flags and commands
|
||||
- PlayStation and Saturn discs still don't have all internal information automatically generated
|
||||
|
||||
### 1.04b (2018-06-13)
|
||||
|
||||
- Added subIntention reading
|
||||
- Fixed extra extensions being appended
|
||||
- Fixed internationalization error (number formatting)
|
||||
- Fixed "Custom Input" not working
|
||||
|
||||
### 1.04a (2018-06-13)
|
||||
|
||||
- Fixed issue with empty trays
|
||||
- Added settings dialog
|
||||
|
||||
### 1.04 (2018-06-13)
|
||||
|
||||
- Behind-the-scenes fixes and formatting
|
||||
- Better checks for external programs
|
||||
- Automatically changing disc information
|
||||
- Custom parameters (and parameter validation)
|
||||
- Automatic drive speed selection
|
||||
- Automatic submission information creation
|
||||
- Add ability to stop a dump from the UI
|
||||
|
||||
### 1.03 (2018-06-08)
|
||||
|
||||
- edccchk now run on all CD-Roms
|
||||
- Discs unsupported by Windows are now regonized
|
||||
- Extra \ when accepting default save has been removed.
|
||||
|
||||
### 1.02b (2018-05-18)
|
||||
|
||||
- Added missing DLL
|
||||
|
||||
### 1.02 (2018-05-18)
|
||||
|
||||
- Fixed XBOX One and PS4 Drive Speed issue.
|
||||
- Started implementing DiscImageCreator Path selection.
|
||||
- Conforming my naming for objects and variable
|
||||
|
||||
### 1.01d (2018-05-18)
|
||||
|
||||
-Combine IBM PC-CD options, misc fixes.
|
||||
8
DICUI.Avalonia/App.axaml
Normal file
8
DICUI.Avalonia/App.axaml
Normal file
@@ -0,0 +1,8 @@
|
||||
<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>
|
||||
24
DICUI.Avalonia/App.axaml.cs
Normal file
24
DICUI.Avalonia/App.axaml.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
29
DICUI.Avalonia/ComboBoxItems/CategoryComboBoxItem.cs
Normal file
29
DICUI.Avalonia/ComboBoxItems/CategoryComboBoxItem.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
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?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
30
DICUI.Avalonia/ComboBoxItems/InternalProgramComboBoxItem.cs
Normal file
30
DICUI.Avalonia/ComboBoxItems/InternalProgramComboBoxItem.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the Internal Program combo box
|
||||
/// </summary>
|
||||
public class InternalProgramComboBoxItem
|
||||
{
|
||||
private object data;
|
||||
|
||||
public InternalProgramComboBoxItem(InternalProgram? internalProgram) => data = internalProgram;
|
||||
|
||||
public static implicit operator InternalProgram? (InternalProgramComboBoxItem item) => item.data as InternalProgram?;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return (data as InternalProgram?).LongName();
|
||||
}
|
||||
}
|
||||
|
||||
public InternalProgram? Value
|
||||
{
|
||||
get { return data as InternalProgram?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
35
DICUI.Avalonia/ComboBoxItems/KnownSystemComboBoxItem.cs
Normal file
35
DICUI.Avalonia/ComboBoxItems/KnownSystemComboBoxItem.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
DICUI.Avalonia/ComboBoxItems/LanguageComboBoxItem.cs
Normal file
29
DICUI.Avalonia/ComboBoxItems/LanguageComboBoxItem.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
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?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
20
DICUI.Avalonia/ComboBoxItems/MediaTypeComboBoxItem.cs
Normal file
20
DICUI.Avalonia/ComboBoxItems/MediaTypeComboBoxItem.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
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(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
30
DICUI.Avalonia/ComboBoxItems/RegionComboBoxItem.cs
Normal file
30
DICUI.Avalonia/ComboBoxItems/RegionComboBoxItem.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
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?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
27
DICUI.Avalonia/Constants.cs
Normal file
27
DICUI.Avalonia/Constants.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
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 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();
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
57
DICUI.Avalonia/DICUI.Avalonia.csproj
Normal file
57
DICUI.Avalonia/DICUI.Avalonia.csproj
Normal file
@@ -0,0 +1,57 @@
|
||||
<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.18</Version>
|
||||
<AssemblyVersion>1.18</AssemblyVersion>
|
||||
<FileVersion>1.18</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" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="1.5.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="$(PkgBurnOutSharp)\content\**" PackagePath="contentFiles\any\any;content" CopyToOutputDirectory="Always" PackageCopyToOutput="true" />
|
||||
</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>
|
||||
120
DICUI.Avalonia/DiscInformationWindow.axaml
Normal file
120
DICUI.Avalonia/DiscInformationWindow.axaml
Normal file
@@ -0,0 +1,120 @@
|
||||
<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>
|
||||
270
DICUI.Avalonia/DiscInformationWindow.axaml.cs
Normal file
270
DICUI.Avalonia/DiscInformationWindow.axaml.cs
Normal file
@@ -0,0 +1,270 @@
|
||||
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(new SubmissionInfo())
|
||||
{
|
||||
}
|
||||
|
||||
public DiscInformationWindow(SubmissionInfo submissionInfo)
|
||||
{
|
||||
this.SubmissionInfo = submissionInfo;
|
||||
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
|
||||
}
|
||||
}
|
||||
32
DICUI.Avalonia/EnumDescriptionConverter.cs
Normal file
32
DICUI.Avalonia/EnumDescriptionConverter.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
40
DICUI.Avalonia/LogWindow.axaml
Normal file
40
DICUI.Avalonia/LogWindow.axaml
Normal file
@@ -0,0 +1,40 @@
|
||||
<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>
|
||||
82
DICUI.Avalonia/LogWindow.axaml.cs
Normal file
82
DICUI.Avalonia/LogWindow.axaml.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
109
DICUI.Avalonia/MainWindow.axaml
Normal file
109
DICUI.Avalonia/MainWindow.axaml
Normal file
@@ -0,0 +1,109 @@
|
||||
<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>
|
||||
837
DICUI.Avalonia/MainWindow.axaml.cs
Normal file
837
DICUI.Avalonia/MainWindow.axaml.cs
Normal file
@@ -0,0 +1,837 @@
|
||||
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.Options.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 possible
|
||||
if (UIOptions.Options.SkipMediaTypeDetection)
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLog("Media type detection disabled, defaulting to CD-ROM");
|
||||
CurrentMediaType = MediaType.CDROM;
|
||||
}
|
||||
else
|
||||
{
|
||||
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, defaulting to CD-ROM." : ($"detected {CurrentMediaType.LongName()}."));
|
||||
if (CurrentMediaType == null)
|
||||
CurrentMediaType = MediaType.CDROM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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.Options.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.Options.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.Options.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()
|
||||
{
|
||||
// Determine current environment, just in case
|
||||
if (Env == null)
|
||||
Env = DetermineEnvironment();
|
||||
|
||||
// Pull the drive letter from the UI directly, just in case
|
||||
var drive = this.Find<ComboBox>("DriveLetterComboBox").SelectedItem as Drive;
|
||||
if (drive.Letter != default(char))
|
||||
{
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Scanning for copy protection in {0}", 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(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}", 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 = Interface.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>
|
||||
/// Show the disc information window
|
||||
/// </summary>
|
||||
/// <param name="submissionInfo">SubmissionInfo object to display and possibly change</param>
|
||||
/// <returns>Dialog open result</returns>
|
||||
private bool? ShowDiscInformationWindow(SubmissionInfo submissionInfo)
|
||||
{
|
||||
var discInformationWindow = new DiscInformationWindow(submissionInfo);
|
||||
discInformationWindow.Load();
|
||||
discInformationWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
discInformationWindow.ShowDialog(this).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <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 = Interface.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 = Interface.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.Options.ResetDriveAfterDump,
|
||||
ShowDiscInformationWindow
|
||||
);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// No-op, we don't care what it was
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Find<Button>("StartStopButton").Content = Interface.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;
|
||||
optionsWindow.Refresh();
|
||||
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 == Interface.StartDumping)
|
||||
{
|
||||
StartDumping();
|
||||
}
|
||||
else if ((string)this.Find<Button>("StartStopButton").Content == Interface.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.Options.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
|
||||
}
|
||||
}
|
||||
17
DICUI.Avalonia/MessageBox.axaml
Normal file
17
DICUI.Avalonia/MessageBox.axaml
Normal file
@@ -0,0 +1,17 @@
|
||||
<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>
|
||||
83
DICUI.Avalonia/MessageBox.axaml.cs
Normal file
83
DICUI.Avalonia/MessageBox.axaml.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
165
DICUI.Avalonia/OptionsWindow.axaml
Normal file
165
DICUI.Avalonia/OptionsWindow.axaml
Normal file
@@ -0,0 +1,165 @@
|
||||
<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="2" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="dd Path" />
|
||||
<TextBox Name="DDPathTextBox" Grid.Row="2" 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="2" Grid.Column="2" Height="25" Width="25" Content="..." Click="BrowseForPathClick" />
|
||||
-->
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5" Text="Region" />
|
||||
<ComboBox Name="InternalProgramComboBox" Grid.Row="2" 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="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>
|
||||
183
DICUI.Avalonia/OptionsWindow.axaml.cs
Normal file
183
DICUI.Avalonia/OptionsWindow.axaml.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Avalonia
|
||||
{
|
||||
public class OptionsWindow : Window
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Current UI options
|
||||
/// </summary>
|
||||
public UIOptions UIOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of available internal programs
|
||||
/// </summary>
|
||||
public List<InternalProgramComboBoxItem> InternalPrograms { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public OptionsWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
|
||||
PopulateInternalPrograms();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Get a complete list of internal programs and fill the combo box
|
||||
/// </summary>
|
||||
private void PopulateInternalPrograms()
|
||||
{
|
||||
// We only support certain programs for dumping
|
||||
var internalPrograms = new List<InternalProgram> { InternalProgram.DiscImageCreator, InternalProgram.Aaru, InternalProgram.DD };
|
||||
ViewModels.LoggerViewModel.VerboseLogLn("Populating internal programs, {0} internal programs found.", internalPrograms.Count);
|
||||
|
||||
InternalPrograms = new List<InternalProgramComboBoxItem>();
|
||||
foreach (var internalProgram in internalPrograms)
|
||||
{
|
||||
InternalPrograms.Add(new InternalProgramComboBoxItem(internalProgram));
|
||||
}
|
||||
|
||||
this.Find<ComboBox>("InternalProgramComboBox").Items = InternalPrograms;
|
||||
this.Find<ComboBox>("InternalProgramComboBox").SelectedIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh any options-related elements
|
||||
/// </summary>
|
||||
public void Refresh()
|
||||
{
|
||||
// Handle non-bindable fields
|
||||
this.Find<ComboBox>("InternalProgramComboBox").SelectedIndex = InternalPrograms.FindIndex(r => r == Converters.ToInternalProgram(UIOptions.Options.InternalProgram));
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
// Handle non-bindable fields
|
||||
UIOptions.Options.InternalProgram = (this.Find<ComboBox>("InternalProgramComboBox").SelectedItem as InternalProgramComboBoxItem)?.Name ?? InternalProgram.DiscImageCreator.ToString();
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
22
DICUI.Avalonia/Program.cs
Normal file
22
DICUI.Avalonia/Program.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
110
DICUI.Avalonia/UIOptions.cs
Normal file
110
DICUI.Avalonia/UIOptions.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
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; }
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
}
|
||||
227
DICUI.Avalonia/ViewModels.cs
Normal file
227
DICUI.Avalonia/ViewModels.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
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; }
|
||||
}
|
||||
|
||||
#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();
|
||||
}
|
||||
}
|
||||
11
DICUI.Avalonia/nuget.config
Normal file
11
DICUI.Avalonia/nuget.config
Normal file
@@ -0,0 +1,11 @@
|
||||
<?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>
|
||||
6
DICUI.Check/App.config
Normal file
6
DICUI.Check/App.config
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
41
DICUI.Check/DICUI.Check.csproj
Normal file
41
DICUI.Check/DICUI.Check.csproj
Normal file
@@ -0,0 +1,41 @@
|
||||
<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.18</Version>
|
||||
<AssemblyVersion>1.18</AssemblyVersion>
|
||||
<FileVersion>1.18</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="1.5.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="$(PkgBurnOutSharp)\content\**" PackagePath="contentFiles\any\any;content" CopyToOutputDirectory="Always" PackageCopyToOutput="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DICUI.Library\DICUI.Library.csproj">
|
||||
<Project>{51ab0928-13f9-44bf-a407-b6957a43a056}</Project>
|
||||
<Name>DICUI.Library</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
266
DICUI.Check/Program.cs
Normal file
266
DICUI.Check/Program.cs
Normal file
@@ -0,0 +1,266 @@
|
||||
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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
7
DICUI.Check/launchSettings.json
Normal file
7
DICUI.Check/launchSettings.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"profiles": {
|
||||
"DICUI.Check": {
|
||||
"commandName": "Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
1
DICUI.Library/Aaru/CICMMetadata
Submodule
1
DICUI.Library/Aaru/CICMMetadata
Submodule
Submodule DICUI.Library/Aaru/CICMMetadata added at 7944bca8e6
475
DICUI.Library/Aaru/Constants.cs
Normal file
475
DICUI.Library/Aaru/Constants.cs
Normal file
@@ -0,0 +1,475 @@
|
||||
namespace DICUI.Aaru
|
||||
{
|
||||
/// <summary>
|
||||
/// Top-level commands for Aaru
|
||||
/// </summary>
|
||||
public static class CommandStrings
|
||||
{
|
||||
// Database Family
|
||||
public const string DatabasePrefixShort = "db";
|
||||
public const string DatabasePrefixLong = "database";
|
||||
public const string DatabaseStats = "stats";
|
||||
public const string DatabaseUpdate = "update";
|
||||
|
||||
// Device Family
|
||||
public const string DevicePrefixShort = "dev";
|
||||
public const string DevicePrefixLong = "device";
|
||||
public const string DeviceInfo = "info";
|
||||
public const string DeviceList = "list";
|
||||
public const string DeviceReport = "report";
|
||||
|
||||
// Filesystem Family
|
||||
public const string FilesystemPrefixShort = "fi";
|
||||
public const string FilesystemPrefixShortAlt = "fs";
|
||||
public const string FilesystemPrefixLong = "filesystem";
|
||||
public const string FilesystemExtract = "extract";
|
||||
public const string FilesystemListShort = "ls";
|
||||
public const string FilesystemListLong = "list";
|
||||
public const string FilesystemOptions = "options";
|
||||
|
||||
// Image Family
|
||||
public const string ImagePrefixShort = "i";
|
||||
public const string ImagePrefixLong = "image";
|
||||
public const string ImageAnalyze = "analyze";
|
||||
public const string ImageChecksumShort = "chk";
|
||||
public const string ImageChecksumLong = "checksum";
|
||||
public const string ImageCompareShort = "cmp";
|
||||
public const string ImageCompareLong = "compare";
|
||||
public const string ImageConvert = "convert";
|
||||
public const string ImageCreateSidecar = "create-sidecar";
|
||||
public const string ImageDecode = "decode";
|
||||
public const string ImageEntropy = "entropy";
|
||||
public const string ImageInfo = "info";
|
||||
public const string ImageOptions = "options";
|
||||
public const string ImagePrint = "print";
|
||||
public const string ImageVerify = "verify";
|
||||
|
||||
// Media Family
|
||||
public const string MediaPrefixShort = "m";
|
||||
public const string MediaPrefixLong = "media";
|
||||
public const string MediaDump = "dump";
|
||||
public const string MediaInfo = "info";
|
||||
public const string MediaScan = "scan";
|
||||
|
||||
// Standalone Commands
|
||||
public const string Configure = "configure";
|
||||
public const string Formats = "formats";
|
||||
public const string ListEncodings = "list-encodings";
|
||||
public const string ListNamespaces = "list-namespaces";
|
||||
public const string Remote = "remote";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supported encodings for Aaru
|
||||
/// </summary>
|
||||
/// TODO: Use to verify encoding settings
|
||||
public static class EncodingStrings
|
||||
{
|
||||
public const string ArabicMac = "x-mac-arabic";
|
||||
public const string AtariASCII = "atascii";
|
||||
public const string CentralEuropeanMac = "x-mac-ce";
|
||||
public const string CommodorePETSCII = "petscii";
|
||||
public const string CroatianMac = "x-mac-croatian";
|
||||
public const string CyrillicMac = "x-mac-cryillic";
|
||||
public const string FarsiMac = "x-mac-farsi";
|
||||
public const string GreekMac = "x-mac-greek";
|
||||
public const string HebrewMac = "x-mac-hebrew";
|
||||
public const string RomanianMac = "x-mac-romanian";
|
||||
public const string SinclairZXSpectrum = "spectrum";
|
||||
public const string SinclairZX80 = "zx80";
|
||||
public const string SinclairZX81 = "zx81";
|
||||
public const string TurkishMac = "x-mac-turkish";
|
||||
public const string UkrainianMac = "x-mac-ukrainian";
|
||||
public const string Unicode = "utf-16";
|
||||
public const string UnicodeBigEndian = "utf-16BE";
|
||||
public const string UnicodeUTF32BigEndian = "utf-32BE";
|
||||
public const string UnicodeUTF32 = "utf-32";
|
||||
public const string UnicodeUTF7 = "utf-7";
|
||||
public const string UnicodeUTF8 = "utf-8";
|
||||
public const string USASCII = "us-ascii";
|
||||
public const string WesternEuropeanAppleII = "apple2";
|
||||
public const string WesternEuropeanAppleIIc = "apple2c";
|
||||
public const string WesternEuropeanAppleIIe = "apple2e";
|
||||
public const string WesternEuropeanAppleIIgs = "apple2gs";
|
||||
public const string WesternEuropeanAppleLisa = "lisa";
|
||||
public const string WesternEuropeanAtariST = "atarist";
|
||||
public const string WesternEuropeanGEM = "gem";
|
||||
public const string WesternEuropeanGEOS = "geos";
|
||||
public const string WesternEuropeanISO = "iso-8859-1";
|
||||
public const string WesternEuropeanMac = "macintosh";
|
||||
public const string WesternEuropeanRadix50 = "radix50";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dumping flags for Aaru
|
||||
/// </summary>
|
||||
public static class FlagStrings
|
||||
{
|
||||
// Boolean flags
|
||||
public const string Adler32Short = "-a";
|
||||
public const string Adler32Long = "--adler32";
|
||||
public const string ClearLong = "--clear";
|
||||
public const string ClearAllLong = "--clear-all";
|
||||
public const string CRC16Long = "--crc16";
|
||||
public const string CRC32Short = "-c";
|
||||
public const string CRC32Long = "--crc32";
|
||||
public const string CRC64Long = "--crc64";
|
||||
public const string DebugShort = "-d";
|
||||
public const string DebugLong = "--debug";
|
||||
public const string DiskTagsShort = "-f";
|
||||
public const string DiskTagsLong = "--disk-tags";
|
||||
public const string DuplicatedSectorsShort = "-p";
|
||||
public const string DuplicatedSectorsLong = "--duplicated-sectors";
|
||||
public const string EjectLong = "--eject";
|
||||
public const string ExtendedAttributesShort = "-x";
|
||||
public const string ExtendedAttributesLong = "--xattrs";
|
||||
public const string FilesystemsShort = "-f";
|
||||
public const string FilesystemsLong = "--filesystems";
|
||||
public const string FirstPregapLong = "--first-pregap";
|
||||
public const string FixOffsetLong = "--fix-offset";
|
||||
public const string FixSubchannelLong = "--fix-subchannel";
|
||||
public const string FixSubchannelCrcLong = "--fix-subchannel-crc";
|
||||
public const string FixSubchannelPositionLong = "--fix-subchannel-position";
|
||||
public const string Fletcher16Long = "--fletcher16";
|
||||
public const string Fletcher32Long = "--fletcher32";
|
||||
public const string ForceShort = "-f";
|
||||
public const string ForceLong = "--force";
|
||||
public const string GenerateSubchannelsLong = "--generate-subchannels";
|
||||
public const string HelpShort = "-h";
|
||||
public const string HelpShortAlt = "-?";
|
||||
public const string HelpLong = "--help";
|
||||
public const string LongFormatShort = "-l";
|
||||
public const string LongFormatLong = "--long-format";
|
||||
public const string LongSectorsShort = "-r";
|
||||
public const string LongSectorsLong = "--long-sectors";
|
||||
public const string MD5Short = "-m";
|
||||
public const string MD5Long = "--md5";
|
||||
public const string MetadataLong = "--metadata";
|
||||
public const string PartitionsShort = "-p";
|
||||
public const string PartitionsLong = "--partitions";
|
||||
public const string PersistentLong = "--persistent";
|
||||
public const string PrivateLong = "--private";
|
||||
public const string ResumeShort = "-r";
|
||||
public const string ResumeLong = "--resume";
|
||||
public const string RetrySubchannelLong = "--retry-subchannel";
|
||||
public const string SectorTagsShort = "-p";
|
||||
public const string SectorTagsLong = "--sector-tags";
|
||||
public const string SeparatedTracksShort = "-t";
|
||||
public const string SeparatedTracksLong = "--separated-tracks";
|
||||
public const string SHA1Short = "-s";
|
||||
public const string SHA1Long = "--sha1";
|
||||
public const string SHA256Long = "--sha256";
|
||||
public const string SHA384Long = "--sha384";
|
||||
public const string SHA512Long = "--sha512";
|
||||
public const string SkipCdiReadyHoleLong = "--skip-cdiready-hole";
|
||||
public const string SpamSumShort = "-f";
|
||||
public const string SpamSumLong = "--spamsum";
|
||||
public const string StopOnErrorShort = "-s";
|
||||
public const string StopOnErrorLong = "--stop-on-error";
|
||||
public const string TapeShort = "-t";
|
||||
public const string TapeLong = "--tape";
|
||||
public const string TrimLong = "--trim";
|
||||
public const string VerboseShort = "-v";
|
||||
public const string VerboseLong = "--verbose";
|
||||
public const string VerifyDiscShort = "-w";
|
||||
public const string VerifyDiscLong = "--verify-disc";
|
||||
public const string VerifySectorsShort = "-s";
|
||||
public const string VerifySectorsLong = "--verify-sectors";
|
||||
public const string VersionLong = "--version";
|
||||
public const string WholeDiscShort = "-w";
|
||||
public const string WholeDiscLong = "--whole-disc";
|
||||
|
||||
// Int8 flags
|
||||
public const string SpeedLong = "--speed";
|
||||
|
||||
// Int16 flags
|
||||
public const string RetryPassesShort = "-p";
|
||||
public const string RetryPassesLong = "--retry-passes";
|
||||
public const string WidthShort = "-w";
|
||||
public const string WidthLong = "--width";
|
||||
|
||||
// Int32 flags
|
||||
public const string BlockSizeShort = "-b";
|
||||
public const string BlockSizeLong = "--block-size";
|
||||
public const string CountShort = "-c";
|
||||
public const string CountLong = "--count";
|
||||
public const string MediaLastSequenceLong = "--media-lastsequence";
|
||||
public const string MediaSequenceLong = "--media-sequence";
|
||||
public const string SkipShort = "-k";
|
||||
public const string SkipLong = "--skip";
|
||||
|
||||
// Int64 flags
|
||||
public const string LengthShort = "-l"; // or "all"
|
||||
public const string LengthLong = "--length"; // or "all"
|
||||
public const string StartShort = "-s";
|
||||
public const string StartLong = "--start";
|
||||
|
||||
// String flags
|
||||
public const string CommentsLong = "--comments";
|
||||
public const string CreatorLong = "--creator";
|
||||
public const string DriveManufacturerLong = "--drive-manufacturer";
|
||||
public const string DriveModelLong = "--drive-model";
|
||||
public const string DriveRevisionLong = "--drive-revision";
|
||||
public const string DriveSerialLong = "--drive-serial";
|
||||
public const string EncodingShort = "-e";
|
||||
public const string EncodingLong = "--encoding";
|
||||
public const string FormatConvertShort = "-p";
|
||||
public const string FormatConvertLong = "--format";
|
||||
public const string FormatDumpShort = "-t";
|
||||
public const string FormatDumpLong = "--format";
|
||||
public const string ImgBurnLogShort = "-b";
|
||||
public const string ImgBurnLogLong = "--ibg-log";
|
||||
public const string MediaBarcodeLong = "--media-barcode";
|
||||
public const string MediaManufacturerLong = "--media-manufacturer";
|
||||
public const string MediaModelLong = "--media-model";
|
||||
public const string MediaPartNumberLong = "--media-partnumber";
|
||||
public const string MediaSerialLong = "--media-serial";
|
||||
public const string MediaTitleLong = "--media-title";
|
||||
public const string MHDDLogShort = "-m";
|
||||
public const string MHDDLogLong = "--mhdd-log";
|
||||
public const string NamespaceShort = "-n";
|
||||
public const string NamespaceLong = "--namespace";
|
||||
public const string OptionsShort = "-O";
|
||||
public const string OptionsLong = "--options";
|
||||
public const string OutputPrefixShort = "-w";
|
||||
public const string OutputPrefixLong = "--output-prefix";
|
||||
public const string ResumeFileShort = "-r";
|
||||
public const string ResumeFileLong = "--resume-file";
|
||||
public const string SubchannelLong = "--subchannel";
|
||||
public const string XMLSidecarShort = "-x";
|
||||
public const string XMLSidecarLong = "--cicm-xml";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supported formats for Aaru
|
||||
/// </summary>
|
||||
/// TODO: Use to verify format settings
|
||||
public static class FormatStrings
|
||||
{
|
||||
// Supported filters
|
||||
public const string AppleDouble = "AppleDouble";
|
||||
public const string AppleSingle = "AppleSingle";
|
||||
public const string BZip2 = "BZip2";
|
||||
public const string GZip = "GZip";
|
||||
public const string LZip = "LZip";
|
||||
public const string MacBinary = "MacBinary";
|
||||
public const string NoFilter = "No filter";
|
||||
public const string PCExchange = "PCExchange";
|
||||
public const string XZ = "XZ";
|
||||
|
||||
// Read-only media image formats
|
||||
public const string AppleDiskArchivalRetrievalTool = "Apple Disk Archival/Retrieval Tool";
|
||||
public const string AppleNewDiskImageFormat = "Apple New Disk Image Format";
|
||||
public const string AppleNIB = "Apple NIB";
|
||||
public const string BlindWrite4 = "BlindWrite 4";
|
||||
public const string BlindWrite5 = "BlindWrite 5";
|
||||
public const string CPCEMUDiskFileAndExtendedCPCDiskFile = "CPCEMU Disk-File and Extended CPC Disk-File";
|
||||
public const string D2FDiskImage = "d2f disk image";
|
||||
public const string D88DiskImage = "D88 Disk Image";
|
||||
public const string DIMDiskImage = "DIM Disk Image";
|
||||
public const string DiscFerret = "DiscFerret";
|
||||
public const string DiscJuggler = "DiscJuggler";
|
||||
public const string DreamcastGDIImage = "Dreamcast GDI image";
|
||||
public const string DunfieldsIMD = "Dunfield's IMD";
|
||||
public const string HDCopyDiskImage = "HD-Copy disk image";
|
||||
public const string KryoFluxSTREAM = "KryoFlux STREAM";
|
||||
public const string MAMECompressedHunksOfData = "MAME Compressed Hunks of Data";
|
||||
public const string MicrosoftVHDX = "Microsoft VHDX";
|
||||
public const string NeroBurningROMImage = "Nero Burning ROM image";
|
||||
public const string PartCloneDiskImage = "PartClone disk image";
|
||||
public const string PartimageDiskImage = "Partimage disk image";
|
||||
public const string SpectrumFloppyDiskImage = "Spectrum Floppy Disk Image";
|
||||
public const string SuperCardPro = "SuperCardPro";
|
||||
public const string SydexCopyQM = "Sydex CopyQM";
|
||||
public const string SydexTeleDisk = "Sydex TeleDisk";
|
||||
|
||||
// Read/write media image formats
|
||||
public const string AaruFormat = "Aaru Format";
|
||||
public const string ACTApricotDiskImage = "ACT Apricot Disk Image";
|
||||
public const string Alcohol120MediaDescriptorStructure = "Alcohol 120% Media Descriptor Structure";
|
||||
public const string Anex86DiskImage = "Anex86 Disk Image";
|
||||
public const string Apple2InterleavedDiskImage = "Apple ][Interleaved Disk Image";
|
||||
public const string Apple2IMG = "Apple 2IMG";
|
||||
public const string AppleDiskCopy42 = "Apple DiskCopy 4.2";
|
||||
public const string AppleUniversalDiskImageFormat = "Apple Universal Disk Image Format";
|
||||
public const string BasicLisaUtility = "Basic Lisa Utility";
|
||||
public const string CDRDAOTocfile = "CDRDAO tocfile";
|
||||
public const string CDRWinCuesheet = "CDRWin cuesheet";
|
||||
public const string CisCopyDiskImageDCFile = "CisCopy Disk Image(DC-File)";
|
||||
public const string CloneCD = "CloneCD";
|
||||
public const string CopyTape = "CopyTape";
|
||||
public const string DigitalResearchDiskCopy = "Digital Research DiskCopy";
|
||||
public const string IBMSaveDskF = "IBM SaveDskF";
|
||||
public const string MAXIDiskImage = "MAXI Disk image";
|
||||
public const string ParallelsDiskImage = "Parallels disk image";
|
||||
public const string QEMUCopyOnWriteDiskImage = "QEMU Copy-On-Write disk image";
|
||||
public const string QEMUCopyOnWriteDiskImageV2 = "QEMU Copy-On-Write disk image v2";
|
||||
public const string QEMUEnhancedDiskImage = "QEMU Enhanced Disk image";
|
||||
public const string RawDiskImage = "Raw Disk Image";
|
||||
public const string RayAracheliansDiskIMage = "Ray Arachelian's Disk IMage";
|
||||
public const string RSIDEHardDiskImage = "RS-IDE Hard Disk Image";
|
||||
public const string T98HardDiskImage = "T98 Hard Disk Image";
|
||||
public const string T98NextNHDr0DiskImage = "T98-Next NHD r0 Disk Image";
|
||||
public const string Virtual98DiskImage = "Virtual98 Disk Image";
|
||||
public const string VirtualBoxDiskImage = "VirtualBox Disk Image";
|
||||
public const string VirtualPC = "VirtualPC";
|
||||
public const string VMwareDiskImage = "VMware disk image";
|
||||
|
||||
// Supported filesystems for identification and information only
|
||||
public const string AcornAdvancedDiscFilingSystem = "Acorn Advanced Disc Filing System";
|
||||
public const string AlexanderOsipovDOSFileSystem = "Alexander Osipov DOS file system";
|
||||
public const string AmigaDOSFilesystem = "Amiga DOS filesystem";
|
||||
public const string AppleFileSystem = "Apple File System";
|
||||
public const string AppleHFSPlusFilesystem = "Apple HFS+ filesystem";
|
||||
public const string AppleHierarchicalFileSystem = "Apple Hierarchical File System";
|
||||
public const string AppleProDOSFilesystem = "Apple ProDOS filesystem";
|
||||
public const string AtheOSFilesystem = "AtheOS Filesystem";
|
||||
public const string BeFilesystem = "Be Filesystem";
|
||||
public const string BSDFastFileSystem = "BSD Fast File System(aka UNIX File System, UFS)";
|
||||
public const string BTreeFileSystem = "B-tree file system";
|
||||
public const string CommodoreFileSystem = "Commodore file system";
|
||||
public const string CramFilesystem = "Cram filesystem";
|
||||
public const string DumpEightPlugin = "dump(8) Plugin";
|
||||
public const string ECMA67 = "ECMA-67";
|
||||
public const string ExtentFileSystemPlugin = "Extent File System Plugin";
|
||||
public const string F2FSPlugin = "F2FS Plugin";
|
||||
public const string Files11OnDiskStructure = "Files-11 On-Disk Structure";
|
||||
public const string FossilFilesystemPlugin = "Fossil Filesystem Plugin";
|
||||
public const string HAMMERFilesystem = "HAMMER Filesystem";
|
||||
public const string HighPerformanceOpticalFileSystem = "High Performance Optical File System";
|
||||
public const string HPLogicalInterchangeFormatPlugin = "HP Logical Interchange Format Plugin";
|
||||
public const string JFSPlugin = "JFS Plugin";
|
||||
public const string LinuxExtendedFilesystem = "Linux extended Filesystem";
|
||||
public const string LinuxExtendedFilesystem234 = "Linux extended Filesystem 2, 3 and 4";
|
||||
public const string LocusFilesystemPlugin = "Locus Filesystem Plugin";
|
||||
public const string MicroDOSFileSystem = "MicroDOS file system";
|
||||
public const string MicrosoftExtendedFileAllocationTable = "Microsoft Extended File Allocation Table";
|
||||
public const string MinixFilesystem = "Minix Filesystem";
|
||||
public const string NewTechnologyFileSystem = "New Technology File System(NTFS)";
|
||||
public const string NILFS2Plugin = "NILFS2 Plugin";
|
||||
public const string NintendoOpticalFilesystems = "Nintendo optical filesystems";
|
||||
public const string OS2HighPerformanceFileSystem = "OS/2 High Performance File System";
|
||||
public const string OS9RandomBlockFilePlugin = "OS-9 Random Block File Plugin";
|
||||
public const string PCEngineCDPlugin = "PC Engine CD Plugin";
|
||||
public const string PCFXPlugin = "PC-FX Plugin";
|
||||
public const string ProfessionalFileSystem = "Professional File System";
|
||||
public const string QNX4Plugin = "QNX4 Plugin";
|
||||
public const string QNX6Plugin = "QNX6 Plugin";
|
||||
public const string ReiserFilesystemPlugin = "Reiser Filesystem Plugin";
|
||||
public const string Reiser4FilesystemPlugin = "Reiser4 Filesystem Plugin";
|
||||
public const string ResilientFileSystemPlugin = "Resilient File System plugin";
|
||||
public const string RT11FileSystem = "RT-11 file system";
|
||||
public const string SmartFileSystem = "SmartFileSystem";
|
||||
public const string SolarOSFilesystem = "Solar_OS filesystem";
|
||||
public const string SquashFilesystem = "Squash filesystem";
|
||||
public const string UNICOSFilesystemPlugin = "UNICOS Filesystem Plugin";
|
||||
public const string UniversalDiskFormat = "Universal Disk Format";
|
||||
public const string UNIXBootFilesystem = "UNIX Boot filesystem";
|
||||
public const string UNIXSystemVFilesystem = "UNIX System V filesystem";
|
||||
public const string VeritasFilesystem = "Veritas filesystem";
|
||||
public const string VMwareFilesystem = "VMware filesystem";
|
||||
public const string XFSFilesystemPlugin = "XFS Filesystem Plugin";
|
||||
public const string XiaFilesystem = "Xia filesystem";
|
||||
public const string ZFSFilesystemPlugin = "ZFS Filesystem Plugin";
|
||||
|
||||
// Supported filesystems that can read their contents
|
||||
public const string AppleDOSFileSystem = "Apple DOS File System";
|
||||
public const string AppleLisaFileSystem = "Apple Lisa File System";
|
||||
public const string AppleMacintoshFileSystem = "Apple Macintosh File System";
|
||||
public const string CPMFileSystem = "CP/M File System";
|
||||
public const string FATXFilesystemPlugin = "FATX Filesystem Plugin";
|
||||
public const string ISO9660Filesystem = "ISO9660 Filesystem";
|
||||
public const string MicrosoftFileAllocationTable = "Microsoft File Allocation Table";
|
||||
public const string OperaFilesystemPlugin = "Opera Filesystem Plugin";
|
||||
public const string UCSDPascalFilesystem = "U.C.S.D.Pascal filesystem";
|
||||
|
||||
// Supported partitioning schemes
|
||||
public const string AcornFileCorePartitions = "Acorn FileCore partitions";
|
||||
public const string ACTApricotPartitions = "ACT Apricot partitions";
|
||||
public const string AmigaRigidDiskBlock = "Amiga Rigid Disk Block";
|
||||
public const string ApplePartitionMap = "Apple Partition Map";
|
||||
public const string AtariPartitions = "Atari partitions";
|
||||
public const string BSDDisklabel = "BSD disklabel";
|
||||
public const string DECDisklabel = "DEC disklabel";
|
||||
public const string DragonFlyBSD64bitDisklabel = "DragonFly BSD 64-bit disklabel";
|
||||
public const string GUIDPartitionTable = "GUID Partition Table";
|
||||
public const string Human68kPartitions = "Human 68k partitions";
|
||||
public const string MasterBootRecord = "Master Boot Record";
|
||||
public const string NECPC9800PartitionTable = "NEC PC-9800 partition table";
|
||||
public const string NeXTDisklabel = "NeXT Disklabel";
|
||||
public const string Plan9PartitionTable = "Plan9 partition table";
|
||||
public const string RioKarmaPartitioning = "Rio Karma partitioning";
|
||||
public const string SGIDiskVolumeHeader = "SGI Disk Volume Header";
|
||||
public const string SunDisklabel = "Sun Disklabel";
|
||||
public const string UNIXHardwired = "UNIX hardwired";
|
||||
public const string UNIXVTOC = "UNIX VTOC";
|
||||
public const string XboxPartitioning = "Xbox partitioning";
|
||||
public const string XENIX = "XENIX";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supported namespaces for Aaru
|
||||
/// </summary>
|
||||
/// TODO: Use to verify namespace settings
|
||||
public static class NamespaceStrings
|
||||
{
|
||||
// Namespaces for Apple Lisa File System
|
||||
public const string LisaOfficeSystem = "office";
|
||||
public const string LisaPascalWorkshop = "workshop"; // Default
|
||||
|
||||
// Namespaces for ISO9660 Filesystem
|
||||
public const string JolietVolumeDescriptor = "joliet"; // Default
|
||||
public const string PrimaryVolumeDescriptor = "normal";
|
||||
public const string PrimaryVolumeDescriptorwithEncoding = "romeo";
|
||||
public const string RockRidge = "rrip";
|
||||
public const string PrimaryVolumeDescriptorVersionSuffix = "vms";
|
||||
|
||||
// Namespaces for Microsoft File Allocation Table
|
||||
public const string DOS83UpperCase = "dos";
|
||||
public const string LFNWhenAvailableWithFallback = "ecs"; // Default
|
||||
public const string LongFileNames = "lfn";
|
||||
public const string WindowsNT83MixedCase = "nt";
|
||||
public const string OS2Extended = "os2";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supported options for Aaru
|
||||
/// </summary>
|
||||
/// TODO: Use to verify option settings
|
||||
public static class OptionStrings
|
||||
{
|
||||
// Aaru format
|
||||
public const string AaruCompress = "compress"; // boolean, default true;
|
||||
public const string AaruDeduplicate = "deduplicate"; // boolean, default true
|
||||
public const string AaruDictionary = "dictionary"; // number, default 33554432
|
||||
public const string AaruMaxDDTSize = "max_ddt_size"; // number, default 256
|
||||
public const string AaruMD5 = "md5"; // boolean, default false
|
||||
public const string AaruSectorsPerBlock = "sectors_per_block"; // number, default 4096 [power of 2]
|
||||
public const string AaruSHA1 = "sha1"; // boolean, default false
|
||||
public const string AaruSHA256 = "sha256"; // boolean, default false
|
||||
public const string AaruSpamSum = "spamsum"; // boolean, default false
|
||||
|
||||
// ACT Apricot Disk Image
|
||||
public const string ACTApricotDiskImageCompress = "compress"; // boolean, default false
|
||||
|
||||
// Apple DiskCopy 4.2
|
||||
public const string AppleDiskCopyMacOSX = "macosx"; // boolean, default false
|
||||
|
||||
// CDRDAO tocfile
|
||||
public const string CDRDAOTocfileSeparate = "separate"; // boolean, default false
|
||||
|
||||
// CDRWin cuesheet
|
||||
public const string CDRWinCuesheetSeparate = "separate"; // boolean, default false
|
||||
|
||||
// ISO9660 Filesystem
|
||||
public const string ISO9660FSUseEvd = "use_evd"; // boolean, default false
|
||||
public const string ISO9660FSUsePathTable = "use_path_table"; // boolean, default false
|
||||
public const string ISO9660FSUseTransTbl = "use_trans_tbl"; // boolean, default false
|
||||
|
||||
// VMware disk image
|
||||
public const string VMwareDiskImageAdapterType = "adapter_type"; // string, default ide [ide, lsilogic, buslogic, legacyESX]
|
||||
public const string VMwareDiskImageHWVersion = "hwversion"; // number, default 4
|
||||
public const string VMwareDiskImageSparse = "sparse"; // boolean, default false
|
||||
public const string VMwareDiskImageSplit = "split"; // boolean, default false
|
||||
}
|
||||
}
|
||||
424
DICUI.Library/Aaru/Converters.cs
Normal file
424
DICUI.Library/Aaru/Converters.cs
Normal file
@@ -0,0 +1,424 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
149
DICUI.Library/Aaru/Enumerations.cs
Normal file
149
DICUI.Library/Aaru/Enumerations.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
3069
DICUI.Library/Aaru/Parameters.cs
Normal file
3069
DICUI.Library/Aaru/Parameters.cs
Normal file
File diff suppressed because it is too large
Load Diff
4
DICUI.Library/AssemblyInfo.cs
Normal file
4
DICUI.Library/AssemblyInfo.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Anything marked as internal can be used by the test methods
|
||||
[assembly: InternalsVisibleTo("DICUI.Test")]
|
||||
353
DICUI.Library/CleanRIp/Parameters.cs
Normal file
353
DICUI.Library/CleanRIp/Parameters.cs
Normal file
@@ -0,0 +1,353 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.CleanRip
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic set of CleanRip 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.CleanRip;
|
||||
}
|
||||
|
||||
/// <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.DVD: // Only added here to help users; not strictly correct
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
if (!File.Exists($"{basePath}-dumpinfo.txt"))
|
||||
missingFiles += $";{basePath}-dumpinfo.txt";
|
||||
if (!File.Exists($"{basePath}.bca"))
|
||||
missingFiles += $";{basePath}.bca";
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
info.TracksAndWriteOffsets.ClrMameProData = GetCleanripDatfile(basePath + ".iso", basePath + "-dumpinfo.txt");
|
||||
|
||||
// Get the individual hash data, as per internal
|
||||
if (GetISOHashValues(info.TracksAndWriteOffsets.ClrMameProData, out long size, out string crc32, out string md5, out string sha1))
|
||||
{
|
||||
info.SizeAndChecksums.Size = size;
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
info.SizeAndChecksums.MD5 = md5;
|
||||
info.SizeAndChecksums.SHA1 = sha1;
|
||||
|
||||
// Dual-layer discs have the same size and layerbreak
|
||||
if (size == 8511160320)
|
||||
info.SizeAndChecksums.Layerbreak = 2084960;
|
||||
}
|
||||
|
||||
// Extract info based generically on MediaType
|
||||
switch (type)
|
||||
{
|
||||
case MediaType.DVD: // Only added here to help users; not strictly correct
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
if (File.Exists(basePath + ".bca"))
|
||||
info.Extras.BCA = GetFullFile(basePath + ".bca", true);
|
||||
|
||||
if (GetGameCubeWiiInformation(basePath + "-dumpinfo.txt", out Region? gcRegion, out string gcVersion))
|
||||
{
|
||||
info.CommonDiscInfo.Region = gcRegion ?? info.CommonDiscInfo.Region;
|
||||
info.VersionAndEditions.Version = gcVersion ?? info.VersionAndEditions.Version;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#region Information Extraction Methods
|
||||
|
||||
/// <summary>
|
||||
/// Get a formatted datfile from the cleanrip output, if possible
|
||||
/// </summary>
|
||||
/// <param name="iso">Path to ISO file</param>
|
||||
/// <param name="dumpinfo">Path to discinfo file</param>
|
||||
/// <returns></returns>
|
||||
private static string GetCleanripDatfile(string iso, string dumpinfo)
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(dumpinfo))
|
||||
return null;
|
||||
|
||||
using (StreamReader sr = File.OpenText(dumpinfo))
|
||||
{
|
||||
long size = new FileInfo(iso).Length;
|
||||
string crc = string.Empty;
|
||||
string md5 = string.Empty;
|
||||
string sha1 = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
// Make sure this file is a dumpinfo
|
||||
if (!sr.ReadLine().Contains("--File Generated by CleanRip"))
|
||||
return null;
|
||||
|
||||
// Read all lines and gather dat information
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine().Trim();
|
||||
if (line.StartsWith("CRC32"))
|
||||
crc = line.Substring(7).ToLowerInvariant();
|
||||
else if (line.StartsWith("MD5"))
|
||||
md5 = line.Substring(5);
|
||||
else if (line.StartsWith("SHA-1"))
|
||||
sha1 = line.Substring(7);
|
||||
}
|
||||
|
||||
return $"<rom name=\"{Path.GetFileName(iso)}\" size=\"{size}\" crc=\"{crc}\" md5=\"{md5}\" sha1=\"{sha1}\" />";
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the extracted GC and Wii version
|
||||
/// </summary>
|
||||
/// <param name="dumpinfo">Path to discinfo file</param>
|
||||
/// <param name="region">Output region, if possible</param>
|
||||
/// <param name="version">Output internal version of the game</param>
|
||||
/// <returns></returns>
|
||||
private static bool GetGameCubeWiiInformation(string dumpinfo, out Region? region, out string version)
|
||||
{
|
||||
region = null; version = null;
|
||||
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(dumpinfo))
|
||||
return false;
|
||||
|
||||
using (StreamReader sr = File.OpenText(dumpinfo))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Make sure this file is a dumpinfo
|
||||
if (!sr.ReadLine().Contains("--File Generated by CleanRip"))
|
||||
return false;
|
||||
|
||||
// Read all lines and gather dat information
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine().Trim();
|
||||
if (line.StartsWith("Version"))
|
||||
{
|
||||
version = line.Substring(9);
|
||||
}
|
||||
else if (line.StartsWith("Filename"))
|
||||
{
|
||||
string serial = line.Substring(10);
|
||||
|
||||
// char gameType = serial[0];
|
||||
// string gameid = serial[1] + serial[2];
|
||||
// string version = serial[4] + serial[5]
|
||||
|
||||
switch (serial[3])
|
||||
{
|
||||
case 'A':
|
||||
region = Region.World;
|
||||
break;
|
||||
case 'D':
|
||||
region = Region.Germany;
|
||||
break;
|
||||
case 'E':
|
||||
region = Region.USA;
|
||||
break;
|
||||
case 'F':
|
||||
region = Region.France;
|
||||
break;
|
||||
case 'I':
|
||||
region = Region.Italy;
|
||||
break;
|
||||
case 'J':
|
||||
region = Region.Japan;
|
||||
break;
|
||||
case 'K':
|
||||
region = Region.Korea;
|
||||
break;
|
||||
case 'L':
|
||||
region = Region.Europe; // Japanese import to Europe
|
||||
break;
|
||||
case 'M':
|
||||
region = Region.Europe; // American import to Europe
|
||||
break;
|
||||
case 'N':
|
||||
region = Region.USA; // Japanese import to USA
|
||||
break;
|
||||
case 'P':
|
||||
region = Region.Europe;
|
||||
break;
|
||||
case 'R':
|
||||
region = Region.Russia;
|
||||
break;
|
||||
case 'S':
|
||||
region = Region.Spain;
|
||||
break;
|
||||
case 'Q':
|
||||
region = Region.Korea; // Korea with Japanese language
|
||||
break;
|
||||
case 'T':
|
||||
region = Region.Korea; // Korea with English language
|
||||
break;
|
||||
case 'X':
|
||||
region = null; // Not a real region code
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the exception is right now
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
201
DICUI.Library/CueSheets/CueFile.cs
Normal file
201
DICUI.Library/CueSheets/CueFile.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
/// <remarks>
|
||||
/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
|
||||
/// </remarks>
|
||||
namespace DICUI.CueSheets
|
||||
{
|
||||
/// <summary>
|
||||
/// The audio or data file’s filetype
|
||||
/// </summary>
|
||||
public enum CueFileType
|
||||
{
|
||||
/// <summary>
|
||||
/// Intel binary file (least significant byte first). Use for data files.
|
||||
/// </summary>
|
||||
BINARY,
|
||||
|
||||
/// <summary>
|
||||
/// Motorola binary file (most significant byte first). Use for data files.
|
||||
/// </summary>
|
||||
MOTOROLA,
|
||||
|
||||
/// <summary>
|
||||
/// Audio AIFF file (44.1KHz 16-bit stereo)
|
||||
/// </summary>
|
||||
AIFF,
|
||||
|
||||
/// <summary>
|
||||
/// Audio WAVE file (44.1KHz 16-bit stereo)
|
||||
/// </summary>
|
||||
WAVE,
|
||||
|
||||
/// <summary>
|
||||
/// Audio MP3 file (44.1KHz 16-bit stereo)
|
||||
/// </summary>
|
||||
MP3,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single FILE in a cuesheet
|
||||
/// </summary>
|
||||
public class CueFile
|
||||
{
|
||||
/// <summary>
|
||||
/// filename
|
||||
/// </summary>
|
||||
public string FileName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// filetype
|
||||
/// </summary>
|
||||
public CueFileType FileType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of TRACK in FILE
|
||||
/// </summary>
|
||||
public List<CueTrack> Tracks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty FILE
|
||||
/// </summary>
|
||||
public CueFile()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill a FILE from an array of lines
|
||||
/// </summary>
|
||||
/// <param name="fileName">File name to set</param>
|
||||
/// <param name="fileType">File type to set</param>
|
||||
/// <param name="cueLines">Lines array to pull from</param>
|
||||
/// <param name="i">Reference to index in array</param>
|
||||
public CueFile(string fileName, string fileType, string[] cueLines, ref int i)
|
||||
{
|
||||
if (cueLines == null || i < 0 || i > cueLines.Length)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Set the current fields
|
||||
this.FileName = fileName.Trim('"');
|
||||
this.FileType = GetFileType(fileType);
|
||||
|
||||
// Increment to start
|
||||
i++;
|
||||
|
||||
for (; i < cueLines.Length; i++)
|
||||
{
|
||||
string line = cueLines[i].Trim();
|
||||
string[] splitLine = line.Split(' ');
|
||||
|
||||
// If we have an empty line, we skip
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
|
||||
switch (splitLine[0])
|
||||
{
|
||||
// Read comments
|
||||
case "REM":
|
||||
// We ignore all comments for now
|
||||
break;
|
||||
|
||||
// Read track information
|
||||
case "TRACK":
|
||||
if (splitLine.Length < 3)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
if (this.Tracks == null)
|
||||
this.Tracks = new List<CueTrack>();
|
||||
|
||||
var track = new CueTrack(splitLine[1], splitLine[2], cueLines, ref i);
|
||||
if (track == default)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Tracks.Add(track);
|
||||
break;
|
||||
|
||||
// Default means return
|
||||
default:
|
||||
i--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the FILE out to a stream
|
||||
/// </summary>
|
||||
/// <param name="sw">StreamWriter to write to</param>
|
||||
public void Write(StreamWriter sw)
|
||||
{
|
||||
// If we don't have any tracks, it's invalid
|
||||
if (this.Tracks == null || this.Tracks.Count == 0)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
sw.WriteLine($"FILE \"{this.FileName}\" {FromFileType(this.FileType)}");
|
||||
|
||||
foreach (var track in Tracks)
|
||||
{
|
||||
track.Write(sw);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the file type from a given string
|
||||
/// </summary>
|
||||
/// <param name="fileType">String to get value from</param>
|
||||
/// <returns>CueFileType, if possible</returns>
|
||||
private CueFileType GetFileType(string fileType)
|
||||
{
|
||||
switch (fileType.ToLowerInvariant())
|
||||
{
|
||||
case "binary":
|
||||
return CueFileType.BINARY;
|
||||
|
||||
case "motorola":
|
||||
return CueFileType.MOTOROLA;
|
||||
|
||||
case "aiff":
|
||||
return CueFileType.AIFF;
|
||||
|
||||
case "wave":
|
||||
return CueFileType.WAVE;
|
||||
|
||||
case "mp3":
|
||||
return CueFileType.MP3;
|
||||
|
||||
default:
|
||||
return CueFileType.BINARY;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string from a given file type
|
||||
/// </summary>
|
||||
/// <param name="fileType">CueFileType to get value from</param>
|
||||
/// <returns>String, if possible (default BINARY)</returns>
|
||||
private string FromFileType(CueFileType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
{
|
||||
case CueFileType.BINARY:
|
||||
return "BINARY";
|
||||
|
||||
case CueFileType.MOTOROLA:
|
||||
return "MOTOROLA";
|
||||
|
||||
case CueFileType.AIFF:
|
||||
return "AIFF";
|
||||
|
||||
case CueFileType.WAVE:
|
||||
return "WAVE";
|
||||
|
||||
case CueFileType.MP3:
|
||||
return "MP3";
|
||||
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
106
DICUI.Library/CueSheets/CueIndex.cs
Normal file
106
DICUI.Library/CueSheets/CueIndex.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
/// <remarks>
|
||||
/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
|
||||
/// </remarks>
|
||||
namespace DICUI.CueSheets
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single INDEX in a TRACK
|
||||
/// </summary>
|
||||
public class CueIndex
|
||||
{
|
||||
/// <summary>
|
||||
/// INDEX number, between 0 and 99
|
||||
/// </summary>
|
||||
public int Index { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Starting time of INDEX in minutes
|
||||
/// </summary>
|
||||
public int Minutes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Starting time of INDEX in seconds
|
||||
/// </summary>
|
||||
/// <remarks>There are 60 seconds in a minute</remarks>
|
||||
public int Seconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Starting time of INDEX in frames.
|
||||
/// </summary>
|
||||
/// <remarks>There are 75 frames per second</remarks>
|
||||
public int Frames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty INDEX
|
||||
/// </summary>
|
||||
public CueIndex()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill a INDEX from an array of lines
|
||||
/// </summary>
|
||||
/// <param name="index">Index to set</param>
|
||||
/// <param name="startTime">Start time to set</param>
|
||||
public CueIndex(string index, string startTime)
|
||||
{
|
||||
// Set the current fields
|
||||
if (!int.TryParse(index, out int parsedIndex))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (parsedIndex < 0 || parsedIndex > 99)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Ignore empty lines
|
||||
if (string.IsNullOrWhiteSpace(startTime))
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Ignore lines that don't contain the correct information
|
||||
if (startTime.Length != 8 || startTime.Count(c => c == ':') != 2)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Split the line
|
||||
string[] splitTime = startTime.Split(':');
|
||||
if (splitTime.Length != 3)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Parse the lengths
|
||||
int[] lengthSegments = new int[3];
|
||||
|
||||
// Minutes
|
||||
if (!int.TryParse(splitTime[0], out lengthSegments[0]))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (lengthSegments[0] < 0)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Seconds
|
||||
if (!int.TryParse(splitTime[1], out lengthSegments[1]))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (lengthSegments[1] < 0 || lengthSegments[1] > 60)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Frames
|
||||
if (!int.TryParse(splitTime[2], out lengthSegments[2]))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (lengthSegments[2] < 0 || lengthSegments[2] > 75)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Set the values
|
||||
this.Index = parsedIndex;
|
||||
this.Minutes = lengthSegments[0];
|
||||
this.Seconds = lengthSegments[1];
|
||||
this.Frames = lengthSegments[2];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the INDEX out to a stream
|
||||
/// </summary>
|
||||
/// <param name="sw">StreamWriter to write to</param>
|
||||
public void Write(StreamWriter sw)
|
||||
{
|
||||
sw.WriteLine($" INDEX {this.Index:D2} {this.Minutes:D2}:{this.Seconds:D2}:{this.Frames:D2}");
|
||||
}
|
||||
}
|
||||
}
|
||||
201
DICUI.Library/CueSheets/CueSheet.cs
Normal file
201
DICUI.Library/CueSheets/CueSheet.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
/// <remarks>
|
||||
/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
|
||||
/// </remarks>
|
||||
namespace DICUI.CueSheets
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single cuesheet
|
||||
/// </summary>
|
||||
public class CueSheet
|
||||
{
|
||||
/// <summary>
|
||||
/// CATALOG
|
||||
/// </summary>
|
||||
public string Catalog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// CDTEXTFILE
|
||||
/// </summary>
|
||||
public string CdTextFile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// PERFORMER
|
||||
/// </summary>
|
||||
public string Performer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// SONGWRITER
|
||||
/// </summary>
|
||||
public string Songwriter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TITLE
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of FILE in cuesheet
|
||||
/// </summary>
|
||||
public List<CueFile> Files { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty cuesheet
|
||||
/// </summary>
|
||||
public CueSheet()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a cuesheet from a file, if possible
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
public CueSheet(string filename)
|
||||
{
|
||||
// Check that the file exists
|
||||
if (!File.Exists(filename))
|
||||
return;
|
||||
|
||||
// Check the extension
|
||||
string ext = Path.GetExtension(filename).TrimStart('.');
|
||||
if (!string.Equals(ext, "cue", StringComparison.OrdinalIgnoreCase)
|
||||
&& !string.Equals(ext, "txt", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Open the file and begin reading
|
||||
string[] cueLines = File.ReadAllLines(filename);
|
||||
for (int i = 0; i < cueLines.Length; i++)
|
||||
{
|
||||
string line = cueLines[i].Trim();
|
||||
|
||||
// http://stackoverflow.com/questions/554013/regular-expression-to-split-on-spaces-unless-in-quotes
|
||||
string[] splitLine = Regex
|
||||
.Matches(line, @"[^\s""]+|""[^""]*""")
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Groups[0].Value)
|
||||
.ToArray();
|
||||
|
||||
// If we have an empty line, we skip
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
|
||||
switch (splitLine[0])
|
||||
{
|
||||
// Read comments
|
||||
case "REM":
|
||||
// We ignore all comments for now
|
||||
break;
|
||||
|
||||
// Read MCN
|
||||
case "CATALOG":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Catalog = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read external CD-Text file path
|
||||
case "CDTEXTFILE":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.CdTextFile = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced performer
|
||||
case "PERFORMER":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Performer = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced songwriter
|
||||
case "SONGWRITER":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Songwriter = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced title
|
||||
case "TITLE":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Title = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read file information
|
||||
case "FILE":
|
||||
if (splitLine.Length < 3)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
if (this.Files == null)
|
||||
this.Files = new List<CueFile>();
|
||||
|
||||
var file = new CueFile(splitLine[1], splitLine[2], cueLines, ref i);
|
||||
if (file == default)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Files.Add(file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the cuesheet out to a file
|
||||
/// </summary>
|
||||
/// <param name="filename">File path to write to</param>
|
||||
public void Write(string filename)
|
||||
{
|
||||
using (var fs = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
|
||||
{
|
||||
Write(fs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the cuesheet out to a stream
|
||||
/// </summary>
|
||||
/// <param name="stream">Stream to write to</param>
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
// If we don't have any files, it's invalid
|
||||
if (this.Files == null || this.Files.Count == 0)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
using (var sw = new StreamWriter(stream, Encoding.ASCII, 1024, true))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(this.Catalog))
|
||||
sw.WriteLine($"CATALOG {this.Catalog}");
|
||||
|
||||
if (!string.IsNullOrEmpty(this.CdTextFile))
|
||||
sw.WriteLine($"CDTEXTFILE {this.CdTextFile}");
|
||||
|
||||
if (!string.IsNullOrEmpty(this.Performer))
|
||||
sw.WriteLine($"PERFORMER {this.Performer}");
|
||||
|
||||
if (!string.IsNullOrEmpty(this.Songwriter))
|
||||
sw.WriteLine($"SONGWRITER {this.Songwriter}");
|
||||
|
||||
if (!string.IsNullOrEmpty(this.Title))
|
||||
sw.WriteLine($"TITLE {this.Title}");
|
||||
|
||||
foreach (var file in Files)
|
||||
{
|
||||
file.Write(sw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
464
DICUI.Library/CueSheets/CueTrack.cs
Normal file
464
DICUI.Library/CueSheets/CueTrack.cs
Normal file
@@ -0,0 +1,464 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
/// <remarks>
|
||||
/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
|
||||
/// </remarks>
|
||||
namespace DICUI.CueSheets
|
||||
{
|
||||
/// <summary>
|
||||
/// Track datatype
|
||||
/// </summary>
|
||||
public enum CueTrackDataType
|
||||
{
|
||||
/// <summary>
|
||||
/// AUDIO, Audio/Music (2352)
|
||||
/// </summary>
|
||||
AUDIO,
|
||||
|
||||
/// <summary>
|
||||
/// CDG, Karaoke CD+G (2448)
|
||||
/// </summary>
|
||||
CDG,
|
||||
|
||||
/// <summary>
|
||||
/// MODE1/2048, CD-ROM Mode1 Data (cooked)
|
||||
/// </summary>
|
||||
MODE1_2048,
|
||||
|
||||
/// <summary>
|
||||
/// MODE1/2352 CD-ROM Mode1 Data (raw)
|
||||
/// </summary>
|
||||
MODE1_2352,
|
||||
|
||||
/// <summary>
|
||||
/// MODE2/2336, CD-ROM XA Mode2 Data
|
||||
/// </summary>
|
||||
MODE2_2336,
|
||||
|
||||
/// <summary>
|
||||
/// MODE2/2352, CD-ROM XA Mode2 Data
|
||||
/// </summary>
|
||||
MODE2_2352,
|
||||
|
||||
/// <summary>
|
||||
/// CDI/2336, CD-I Mode2 Data
|
||||
/// </summary>
|
||||
CDI_2336,
|
||||
|
||||
/// <summary>
|
||||
/// CDI/2352, CD-I Mode2 Data
|
||||
/// </summary>
|
||||
CDI_2352,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Special subcode flags within a track
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum CueTrackFlag
|
||||
{
|
||||
/// <summary>
|
||||
/// DCP, Digital copy permitted
|
||||
/// </summary>
|
||||
DCP = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// 4CH, Four channel audio
|
||||
/// </summary>
|
||||
FourCH = 1 << 1,
|
||||
|
||||
/// <summary>
|
||||
/// PRE, Pre-emphasis enabled (audio tracks only)
|
||||
/// </summary>
|
||||
PRE = 1 << 2,
|
||||
|
||||
/// <summary>
|
||||
/// SCMS, Serial Copy Management System (not supported by all recorders)
|
||||
/// </summary>
|
||||
SCMS = 1 << 3,
|
||||
|
||||
/// <summary>
|
||||
/// DATA, set for data files. This flag is set automatically based on the track’s filetype
|
||||
/// </summary>
|
||||
DATA = 1 << 4,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single TRACK in a FILE
|
||||
/// </summary>
|
||||
public class CueTrack
|
||||
{
|
||||
/// <summary>
|
||||
/// Track number. The range is 1 to 99.
|
||||
/// </summary>
|
||||
public int Number { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Track datatype
|
||||
/// </summary>
|
||||
public CueTrackDataType DataType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FLAGS
|
||||
/// </summary>
|
||||
public CueTrackFlag Flags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ISRC
|
||||
/// </summary>
|
||||
/// <remarks>12 characters in length</remarks>
|
||||
public string ISRC { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// PERFORMER
|
||||
/// </summary>
|
||||
public string Performer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// SONGWRITER
|
||||
/// </summary>
|
||||
public string Songwriter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TITLE
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// PREGAP
|
||||
/// </summary>
|
||||
public PreGap PreGap { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of INDEX in TRACK
|
||||
/// </summary>
|
||||
/// <remarks>Must start with 0 or 1 and then sequential</remarks>
|
||||
public List<CueIndex> Indices { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// POSTGAP
|
||||
/// </summary>
|
||||
public PostGap PostGap { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty TRACK
|
||||
/// </summary>
|
||||
public CueTrack()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill a TRACK from an array of lines
|
||||
/// </summary>
|
||||
/// <param name="number">Number to set</param>
|
||||
/// <param name="dataType">Data type to set</param>
|
||||
/// <param name="cueLines">Lines array to pull from</param>
|
||||
/// <param name="i">Reference to index in array</param>
|
||||
public CueTrack(string number, string dataType, string[] cueLines, ref int i)
|
||||
{
|
||||
if (cueLines == null || i < 0 || i > cueLines.Length)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Set the current fields
|
||||
if (!int.TryParse(number, out int parsedNumber))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (parsedNumber < 1 || parsedNumber > 99)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
this.Number = parsedNumber;
|
||||
this.DataType = GetDataType(dataType);
|
||||
|
||||
// Increment to start
|
||||
i++;
|
||||
|
||||
for (; i < cueLines.Length; i++)
|
||||
{
|
||||
string line = cueLines[i].Trim();
|
||||
string[] splitLine = line.Split(' ');
|
||||
|
||||
// If we have an empty line, we skip
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
|
||||
switch (splitLine[0])
|
||||
{
|
||||
// Read comments
|
||||
case "REM":
|
||||
// We ignore all comments for now
|
||||
break;
|
||||
|
||||
// Read flag information
|
||||
case "FLAGS":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Flags = GetFlags(splitLine);
|
||||
break;
|
||||
|
||||
// Read International Standard Recording Code
|
||||
case "ISRC":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.ISRC = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced performer
|
||||
case "PERFORMER":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Performer = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced songwriter
|
||||
case "SONGWRITER":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Songwriter = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read CD-Text enhanced title
|
||||
case "TITLE":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Title = splitLine[1];
|
||||
break;
|
||||
|
||||
// Read pregap information
|
||||
case "PREGAP":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
var pregap = new PreGap(splitLine[1]);
|
||||
if (pregap == default)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.PreGap = pregap;
|
||||
break;
|
||||
|
||||
// Read index information
|
||||
case "INDEX":
|
||||
if (splitLine.Length < 3)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
if (this.Indices == null)
|
||||
this.Indices = new List<CueIndex>();
|
||||
|
||||
var index = new CueIndex(splitLine[1], splitLine[2]);
|
||||
if (index == default)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.Indices.Add(index);
|
||||
break;
|
||||
|
||||
// Read postgap information
|
||||
case "POSTGAP":
|
||||
if (splitLine.Length < 2)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
var postgap = new PostGap(splitLine[1]);
|
||||
if (postgap == default)
|
||||
continue; // TODO: Make this throw an exception
|
||||
|
||||
this.PostGap = postgap;
|
||||
break;
|
||||
|
||||
// Default means return
|
||||
default:
|
||||
i--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the TRACK out to a stream
|
||||
/// </summary>
|
||||
/// <param name="sw">StreamWriter to write to</param>
|
||||
public void Write(StreamWriter sw)
|
||||
{
|
||||
// If we don't have any indices, it's invalid
|
||||
if (this.Indices == null || this.Indices.Count == 0)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
sw.WriteLine($" TRACK {this.Number:D2} {FromDataType(this.DataType)}");
|
||||
|
||||
if (this.Flags != 0)
|
||||
sw.WriteLine($" FLAGS {FromFlags(this.Flags)}");
|
||||
|
||||
if (!string.IsNullOrEmpty(this.ISRC))
|
||||
sw.WriteLine($"ISRC {this.ISRC}");
|
||||
|
||||
if (!string.IsNullOrEmpty(this.Performer))
|
||||
sw.WriteLine($"PERFORMER {this.Performer}");
|
||||
|
||||
if (!string.IsNullOrEmpty(this.Songwriter))
|
||||
sw.WriteLine($"SONGWRITER {this.Songwriter}");
|
||||
|
||||
if (!string.IsNullOrEmpty(this.Title))
|
||||
sw.WriteLine($"TITLE {this.Title}");
|
||||
|
||||
if (this.PreGap != null)
|
||||
this.PreGap.Write(sw);
|
||||
|
||||
foreach (var index in Indices)
|
||||
{
|
||||
index.Write(sw);
|
||||
}
|
||||
|
||||
if (this.PostGap != null)
|
||||
this.PostGap.Write(sw);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the data type from a given string
|
||||
/// </summary>
|
||||
/// <param name="dataType">String to get value from</param>
|
||||
/// <returns>CueTrackDataType, if possible (default AUDIO)</returns>
|
||||
private CueTrackDataType GetDataType(string dataType)
|
||||
{
|
||||
switch (dataType.ToLowerInvariant())
|
||||
{
|
||||
case "audio":
|
||||
return CueTrackDataType.AUDIO;
|
||||
|
||||
case "cdg":
|
||||
return CueTrackDataType.CDG;
|
||||
|
||||
case "mode1/2048":
|
||||
return CueTrackDataType.MODE1_2048;
|
||||
|
||||
case "mode1/2352":
|
||||
return CueTrackDataType.MODE1_2352;
|
||||
|
||||
case "mode2/2336":
|
||||
return CueTrackDataType.MODE2_2336;
|
||||
|
||||
case "mode2/2352":
|
||||
return CueTrackDataType.MODE2_2352;
|
||||
|
||||
case "cdi/2336":
|
||||
return CueTrackDataType.CDI_2336;
|
||||
|
||||
case "cdi/2352":
|
||||
return CueTrackDataType.CDI_2352;
|
||||
|
||||
default:
|
||||
return CueTrackDataType.AUDIO;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string from a given data type
|
||||
/// </summary>
|
||||
/// <param name="dataType">CueTrackDataType to get value from</param>
|
||||
/// <returns>string, if possible</returns>
|
||||
private string FromDataType(CueTrackDataType dataType)
|
||||
{
|
||||
switch (dataType)
|
||||
{
|
||||
case CueTrackDataType.AUDIO:
|
||||
return "AUDIO";
|
||||
|
||||
case CueTrackDataType.CDG:
|
||||
return "CDG";
|
||||
|
||||
case CueTrackDataType.MODE1_2048:
|
||||
return "MODE1/2048";
|
||||
|
||||
case CueTrackDataType.MODE1_2352:
|
||||
return "MODE1/2352";
|
||||
|
||||
case CueTrackDataType.MODE2_2336:
|
||||
return "MODE2/2336";
|
||||
|
||||
case CueTrackDataType.MODE2_2352:
|
||||
return "MODE2/2352";
|
||||
|
||||
case CueTrackDataType.CDI_2336:
|
||||
return "CDI/2336";
|
||||
|
||||
case CueTrackDataType.CDI_2352:
|
||||
return "CDI/2352";
|
||||
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the flag value for an array of strings
|
||||
/// </summary>
|
||||
/// <param name="flagStrings">Possible flags as strings</param>
|
||||
/// <returns>CueTrackFlag value representing the strings, if possible</returns>
|
||||
private CueTrackFlag GetFlags(string[] flagStrings)
|
||||
{
|
||||
CueTrackFlag flag = 0;
|
||||
|
||||
foreach (string flagString in flagStrings)
|
||||
{
|
||||
// TODO: Make default throw an exception
|
||||
switch (flagString.ToLowerInvariant())
|
||||
{
|
||||
case "flags":
|
||||
// No-op since this is the start of the line
|
||||
break;
|
||||
|
||||
case "dcp":
|
||||
flag |= CueTrackFlag.DCP;
|
||||
break;
|
||||
|
||||
case "4ch":
|
||||
flag |= CueTrackFlag.FourCH;
|
||||
break;
|
||||
|
||||
case "pre":
|
||||
flag |= CueTrackFlag.PRE;
|
||||
break;
|
||||
|
||||
case "scms":
|
||||
flag |= CueTrackFlag.SCMS;
|
||||
break;
|
||||
|
||||
case "data":
|
||||
flag |= CueTrackFlag.DATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string value for a set of track flags
|
||||
/// </summary>
|
||||
/// <param name="flags">CueTrackFlag to get value from</param>
|
||||
/// <returns>String value representing the CueTrackFlag, if possible</returns>
|
||||
private string FromFlags(CueTrackFlag flags)
|
||||
{
|
||||
string outputFlagString = string.Empty;
|
||||
|
||||
if (flags.HasFlag(CueTrackFlag.DCP))
|
||||
outputFlagString += "DCP ";
|
||||
|
||||
if (flags.HasFlag(CueTrackFlag.FourCH))
|
||||
outputFlagString += "4CH ";
|
||||
|
||||
if (flags.HasFlag(CueTrackFlag.PRE))
|
||||
outputFlagString += "PRE ";
|
||||
|
||||
if (flags.HasFlag(CueTrackFlag.SCMS))
|
||||
outputFlagString += "SCMS ";
|
||||
|
||||
if (flags.HasFlag(CueTrackFlag.DATA))
|
||||
outputFlagString += "DATA ";
|
||||
|
||||
return outputFlagString.Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
92
DICUI.Library/CueSheets/PostGap.cs
Normal file
92
DICUI.Library/CueSheets/PostGap.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
/// <remarks>
|
||||
/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
|
||||
/// </remarks>
|
||||
namespace DICUI.CueSheets
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents POSTGAP information of a track
|
||||
/// </summary>
|
||||
public class PostGap
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of POSTGAP in minutes
|
||||
/// </summary>
|
||||
public int Minutes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of POSTGAP in seconds
|
||||
/// </summary>
|
||||
/// <remarks>There are 60 seconds in a minute</remarks>
|
||||
public int Seconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of POSTGAP in frames.
|
||||
/// </summary>
|
||||
/// <remarks>There are 75 frames per second</remarks>
|
||||
public int Frames { get; set; }
|
||||
|
||||
/// Create an empty POSTGAP
|
||||
/// </summary>
|
||||
public PostGap()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a POSTGAP from a mm:ss:ff length
|
||||
/// </summary>
|
||||
/// <param name="length">String to get length information from</param>
|
||||
public PostGap(string length)
|
||||
{
|
||||
// Ignore empty lines
|
||||
if (string.IsNullOrWhiteSpace(length))
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Ignore lines that don't contain the correct information
|
||||
if (length.Length != 8 || length.Count(c => c == ':') != 2)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Split the line
|
||||
string[] splitLength = length.Split(':');
|
||||
if (splitLength.Length != 3)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Parse the lengths
|
||||
int[] lengthSegments = new int[3];
|
||||
|
||||
// Minutes
|
||||
if (!int.TryParse(splitLength[0], out lengthSegments[0]))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (lengthSegments[0] < 0)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Seconds
|
||||
if (!int.TryParse(splitLength[1], out lengthSegments[1]))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (lengthSegments[1] < 0 || lengthSegments[1] > 60)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Frames
|
||||
if (!int.TryParse(splitLength[2], out lengthSegments[2]))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (lengthSegments[2] < 0 || lengthSegments[2] > 75)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Set the values
|
||||
this.Minutes = lengthSegments[0];
|
||||
this.Seconds = lengthSegments[1];
|
||||
this.Frames = lengthSegments[2];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the POSTGAP out to a stream
|
||||
/// </summary>
|
||||
/// <param name="sw">StreamWriter to write to</param>
|
||||
public void Write(StreamWriter sw)
|
||||
{
|
||||
sw.WriteLine($" POSTGAP {this.Minutes:D2}:{this.Seconds:D2}:{this.Frames:D2}");
|
||||
}
|
||||
}
|
||||
}
|
||||
93
DICUI.Library/CueSheets/PreGap.cs
Normal file
93
DICUI.Library/CueSheets/PreGap.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
/// <remarks>
|
||||
/// Information sourced from http://web.archive.org/web/20070221154246/http://www.goldenhawk.com/download/cdrwin.pdf
|
||||
/// </remarks>
|
||||
namespace DICUI.CueSheets
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents PREGAP information of a track
|
||||
/// </summary>
|
||||
public class PreGap
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of PREGAP in minutes
|
||||
/// </summary>
|
||||
public int Minutes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of PREGAP in seconds
|
||||
/// </summary>
|
||||
/// <remarks>There are 60 seconds in a minute</remarks>
|
||||
public int Seconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of PREGAP in frames.
|
||||
/// </summary>
|
||||
/// <remarks>There are 75 frames per second</remarks>
|
||||
public int Frames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty PREGAP
|
||||
/// </summary>
|
||||
public PreGap()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a PREGAP from a mm:ss:ff length
|
||||
/// </summary>
|
||||
/// <param name="length">String to get length information from</param>
|
||||
public PreGap(string length)
|
||||
{
|
||||
// Ignore empty lines
|
||||
if (string.IsNullOrWhiteSpace(length))
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Ignore lines that don't contain the correct information
|
||||
if (length.Length != 8 || length.Count(c => c == ':') != 2)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Split the line
|
||||
string[] splitLength = length.Split(':');
|
||||
if (splitLength.Length != 3)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Parse the lengths
|
||||
int[] lengthSegments = new int[3];
|
||||
|
||||
// Minutes
|
||||
if (!int.TryParse(splitLength[0], out lengthSegments[0]))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (lengthSegments[0] < 0)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Seconds
|
||||
if (!int.TryParse(splitLength[1], out lengthSegments[1]))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (lengthSegments[1] < 0 || lengthSegments[1] > 60)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Frames
|
||||
if (!int.TryParse(splitLength[2], out lengthSegments[2]))
|
||||
return; // TODO: Make this throw an exception
|
||||
else if (lengthSegments[2] < 0 || lengthSegments[2] > 75)
|
||||
return; // TODO: Make this throw an exception
|
||||
|
||||
// Set the values
|
||||
this.Minutes = lengthSegments[0];
|
||||
this.Seconds = lengthSegments[1];
|
||||
this.Frames = lengthSegments[2];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the PREGAP out to a stream
|
||||
/// </summary>
|
||||
/// <param name="sw">StreamWriter to write to</param>
|
||||
public void Write(StreamWriter sw)
|
||||
{
|
||||
sw.WriteLine($" PREGAP {this.Minutes:D2}:{this.Seconds:D2}:{this.Frames:D2}");
|
||||
}
|
||||
}
|
||||
}
|
||||
31
DICUI.Library/DD/Constants.cs
Normal file
31
DICUI.Library/DD/Constants.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
namespace DICUI.DD
|
||||
{
|
||||
/// <summary>
|
||||
/// Top-level commands for DD
|
||||
/// </summary>
|
||||
public static class CommandStrings
|
||||
{
|
||||
public const string List = "--list";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dumping flags for DD
|
||||
/// </summary>
|
||||
public static class FlagStrings
|
||||
{
|
||||
// Boolean flags
|
||||
public const string Progress = "--progress";
|
||||
public const string Size = "--size";
|
||||
|
||||
// Int64 flags
|
||||
public const string BlockSize = "bs";
|
||||
public const string Count = "count";
|
||||
public const string Seek = "seek";
|
||||
public const string Skip = "skip";
|
||||
|
||||
// String flags
|
||||
public const string Filter = "--filter";
|
||||
public const string InputFile = "if";
|
||||
public const string OutputFile = "of";
|
||||
}
|
||||
}
|
||||
104
DICUI.Library/DD/Converters.cs
Normal file
104
DICUI.Library/DD/Converters.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
34
DICUI.Library/DD/Enumerations.cs
Normal file
34
DICUI.Library/DD/Enumerations.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
668
DICUI.Library/DD/Parameters.cs
Normal file
668
DICUI.Library/DD/Parameters.cs
Normal file
@@ -0,0 +1,668 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
85
DICUI.Library/DICUI.Library.csproj
Normal file
85
DICUI.Library/DICUI.Library.csproj
Normal file
@@ -0,0 +1,85 @@
|
||||
<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.18</Version>
|
||||
<AssemblyVersion>1.18</AssemblyVersion>
|
||||
<FileVersion>1.18</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>
|
||||
<Compile Remove="Aaru\CICMMetadata\CICMMetadataEditor\**" />
|
||||
<Compile Remove="Aaru\CICMMetadata\java\**" />
|
||||
<Compile Remove="Aaru\CICMMetadata\samples\**" />
|
||||
<EmbeddedResource Remove="Aaru\CICMMetadata\CICMMetadataEditor\**" />
|
||||
<EmbeddedResource Remove="Aaru\CICMMetadata\java\**" />
|
||||
<EmbeddedResource Remove="Aaru\CICMMetadata\samples\**" />
|
||||
<None Remove="Aaru\CICMMetadata\CICMMetadataEditor\**" />
|
||||
<None Remove="Aaru\CICMMetadata\java\**" />
|
||||
<None Remove="Aaru\CICMMetadata\samples\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Aaru\CICMMetadata\.editorconfig" />
|
||||
<None Remove="Aaru\CICMMetadata\.git" />
|
||||
<None Remove="Aaru\CICMMetadata\.gitignore" />
|
||||
<None Remove="Aaru\CICMMetadata\.project" />
|
||||
<None Remove="Aaru\CICMMetadata\build.sh" />
|
||||
<None Remove="Aaru\CICMMetadata\cicm.xml" />
|
||||
<None Remove="Aaru\CICMMetadata\cicm.xsd" />
|
||||
<None Remove="Aaru\CICMMetadata\CICMMetadata.iml" />
|
||||
<None Remove="Aaru\CICMMetadata\dotnet\cicm.vb" />
|
||||
<None Remove="Aaru\CICMMetadata\README.md" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="1.5.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Management" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="$(PkgBurnOutSharp)\content\**" PackagePath="contentFiles\any\any;content" CopyToOutputDirectory="Always" PackageCopyToOutput="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Management" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
710
DICUI.Library/Data/BaseParameters.cs
Normal file
710
DICUI.Library/Data/BaseParameters.cs
Normal file
@@ -0,0 +1,710 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
115
DICUI.Library/Data/Constants.cs
Normal file
115
DICUI.Library/Data/Constants.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DICUI.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> 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.HDDVD:
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
return dvd;
|
||||
case MediaType.BluRay:
|
||||
return bd;
|
||||
default:
|
||||
return unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Template field values for submission info
|
||||
/// </summary>
|
||||
public static class Template
|
||||
{
|
||||
// Manual information
|
||||
|
||||
public const string TitleField = "Title";
|
||||
public const string ForeignTitleField = "Foreign Title (Non-latin)";
|
||||
public const string DiscNumberField = "Disc Number / Letter";
|
||||
public const string DiscTitleField = "Disc Title";
|
||||
public const string SystemField = "System";
|
||||
public const string MediaTypeField = "Media Type";
|
||||
public const string CategoryField = "Category";
|
||||
public const string RegionField = "Region";
|
||||
public const string LanguagesField = "Languages";
|
||||
public const string PlaystationLanguageSelectionViaField = "Language Selection Via";
|
||||
public const string DiscSerialField = "Disc Serial";
|
||||
public const string BarcodeField = "Barcode";
|
||||
public const string CommentsField = "Comments";
|
||||
public const string ContentsField = "Contents";
|
||||
public const string VersionField = "Version";
|
||||
public const string EditionField = "Edition/Release";
|
||||
public const string PlayStation3WiiDiscKeyField = "Disc Key";
|
||||
public const string PlayStation3DiscIDField = "Disc ID";
|
||||
public const string GameCubeWiiBCAField = "BCA";
|
||||
public const string CopyProtectionField = "Copy Protection";
|
||||
public const string MasteringRingField = "Mastering Code (laser branded/etched)";
|
||||
public const string MasteringSIDField = "Mastering SID Code";
|
||||
public const string MouldSIDField = "Mould SID Code";
|
||||
public const string AdditionalMouldField = "Additional Mould";
|
||||
public const string ToolstampField = "Toolstamp or Mastering Code (engraved/stamped)";
|
||||
|
||||
// Automatic Information
|
||||
|
||||
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 ErrorCountField = "Error Count";
|
||||
public const string CuesheetField = "Cuesheet";
|
||||
public const string SubIntentionField = "SubIntention Data (SecuROM/LibCrypt)";
|
||||
public const string WriteOffsetField = "Write Offset";
|
||||
public const string LayerbreakField = "Layerbreak";
|
||||
public const string EXEDateBuildDate = "EXE/Build Date";
|
||||
public const string HeaderField = "Header";
|
||||
public const string PICField = "Permanent Information & Control (PIC)";
|
||||
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
|
||||
|
||||
public const string RequiredValue = "(REQUIRED)";
|
||||
public const string RequiredIfExistsValue = "(REQUIRED, IF EXISTS)";
|
||||
public const string OptionalValue = "(OPTIONAL)";
|
||||
public const string DiscNotDetected = "Disc Not Detected";
|
||||
}
|
||||
}
|
||||
492
DICUI.Library/Data/Enumerations.cs
Normal file
492
DICUI.Library/Data/Enumerations.cs
Normal file
@@ -0,0 +1,492 @@
|
||||
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
|
||||
}
|
||||
284
DICUI.Library/Data/Options.cs
Normal file
284
DICUI.Library/Data/Options.cs
Normal file
@@ -0,0 +1,284 @@
|
||||
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; }
|
||||
}
|
||||
|
||||
#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", true); }
|
||||
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>();
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <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;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
72
DICUI.Library/DiscImageCreator/Constants.cs
Normal file
72
DICUI.Library/DiscImageCreator/Constants.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
namespace DICUI.DiscImageCreator
|
||||
{
|
||||
/// <summary>
|
||||
/// Top-level commands for DiscImageCreator
|
||||
/// </summary>
|
||||
public static class CommandStrings
|
||||
{
|
||||
public const string Audio = "audio";
|
||||
public const string BluRay = "bd";
|
||||
public const string Close = "close";
|
||||
public const string CompactDisc = "cd";
|
||||
public const string Data = "data";
|
||||
public const string DigitalVideoDisc = "dvd";
|
||||
public const string Disk = "disk";
|
||||
public const string DriveSpeed = "ls";
|
||||
public const string Eject = "eject";
|
||||
public const string Floppy = "fd";
|
||||
public const string GDROM = "gd";
|
||||
public const string MDS = "mds";
|
||||
public const string Merge = "merge";
|
||||
public const string Reset = "reset";
|
||||
public const string SACD = "sacd";
|
||||
public const string Start = "start";
|
||||
public const string Stop = "stop";
|
||||
public const string Sub = "sub";
|
||||
public const string Swap = "swap";
|
||||
public const string Tape = "tape";
|
||||
public const string XBOX = "xbox";
|
||||
public const string XBOXSwap = "xboxswap";
|
||||
public const string XGD2Swap = "xgd2swap";
|
||||
public const string XGD3Swap = "xgd3swap";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dumping flags for DiscImageCreator
|
||||
/// </summary>
|
||||
public static class FlagStrings
|
||||
{
|
||||
public const string AddOffset = "/a";
|
||||
public const string AMSF = "/p";
|
||||
public const string AtariJaguar = "/aj";
|
||||
public const string BEOpcode = "/be";
|
||||
public const string C2Opcode = "/c2";
|
||||
public const string CopyrightManagementInformation = "/c";
|
||||
public const string D8Opcode = "/d8";
|
||||
public const string DisableBeep = "/q";
|
||||
public const string ExtractMicroSoftCabFile = "/mscf";
|
||||
public const string Fix = "/fix";
|
||||
public const string ForceUnitAccess = "/f";
|
||||
public const string MultiSession = "/ms";
|
||||
public const string NoFixSubP = "/np";
|
||||
public const string NoFixSubQ = "/nq";
|
||||
public const string NoFixSubQLibCrypt = "/nl";
|
||||
public const string NoFixSubRtoW = "/nr";
|
||||
public const string NoFixSubQSecuROM = "/ns";
|
||||
public const string NoSkipSS = "/nss";
|
||||
public const string PadSector = "/ps";
|
||||
public const string Raw = "/raw";
|
||||
public const string Resume = "/re";
|
||||
public const string Reverse = "/r";
|
||||
public const string ScanAntiMod = "/am";
|
||||
public const string ScanFileProtect = "/sf";
|
||||
public const string ScanSectorProtect = "/ss";
|
||||
public const string SeventyFour = "/74";
|
||||
public const string SkipSector = "/sk";
|
||||
public const string SubchannelReadLevel = "/s";
|
||||
public const string UseAnchorVolumeDescriptorPointer = "/avdp";
|
||||
public const string VideoNow = "/vn";
|
||||
public const string VideoNowColor = "/vnc";
|
||||
public const string VideoNowXP = "/vnx";
|
||||
}
|
||||
}
|
||||
339
DICUI.Library/DiscImageCreator/Converters.cs
Normal file
339
DICUI.Library/DiscImageCreator/Converters.cs
Normal file
@@ -0,0 +1,339 @@
|
||||
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.Fix:
|
||||
return FlagStrings.Fix;
|
||||
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.PadSector:
|
||||
return FlagStrings.PadSector;
|
||||
case Flag.Raw:
|
||||
return FlagStrings.Raw;
|
||||
case Flag.Resume:
|
||||
return FlagStrings.Resume;
|
||||
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
|
||||
}
|
||||
}
|
||||
74
DICUI.Library/DiscImageCreator/Enumerations.cs
Normal file
74
DICUI.Library/DiscImageCreator/Enumerations.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
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,
|
||||
Fix,
|
||||
ForceUnitAccess,
|
||||
MultiSession,
|
||||
NoFixSubP,
|
||||
NoFixSubQ,
|
||||
NoFixSubQLibCrypt,
|
||||
NoFixSubRtoW,
|
||||
NoFixSubQSecuROM,
|
||||
NoSkipSS,
|
||||
PadSector,
|
||||
Raw,
|
||||
Resume,
|
||||
Reverse,
|
||||
ScanAntiMod,
|
||||
ScanFileProtect,
|
||||
ScanSectorProtect,
|
||||
SeventyFour,
|
||||
SkipSector,
|
||||
SubchannelReadLevel,
|
||||
UseAnchorVolumeDescriptorPointer,
|
||||
VideoNow,
|
||||
VideoNowColor,
|
||||
VideoNowXP,
|
||||
}
|
||||
}
|
||||
3261
DICUI.Library/DiscImageCreator/Parameters.cs
Normal file
3261
DICUI.Library/DiscImageCreator/Parameters.cs
Normal file
File diff suppressed because it is too large
Load Diff
325
DICUI.Library/UmdImageCreator/Parameters.cs
Normal file
325
DICUI.Library/UmdImageCreator/Parameters.cs
Normal file
@@ -0,0 +1,325 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
2340
DICUI.Library/Utilities/Converters.cs
Normal file
2340
DICUI.Library/Utilities/Converters.cs
Normal file
File diff suppressed because it is too large
Load Diff
102
DICUI.Library/Utilities/Drive.cs
Normal file
102
DICUI.Library/Utilities/Drive.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
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;
|
||||
}
|
||||
|
||||
/// <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.DriveInfo?.Name))
|
||||
return null;
|
||||
|
||||
// We don't support negative sectors
|
||||
if (num < 0)
|
||||
return null;
|
||||
|
||||
// Wrap the following in case of device access errors
|
||||
try
|
||||
{
|
||||
// Open the drive as a device
|
||||
var 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1363
DICUI.Library/Utilities/DumpEnvironment.cs
Normal file
1363
DICUI.Library/Utilities/DumpEnvironment.cs
Normal file
File diff suppressed because it is too large
Load Diff
57
DICUI.Library/Utilities/Extensions.cs
Normal file
57
DICUI.Library/Utilities/Extensions.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
296
DICUI.Library/Utilities/IniFile.cs
Normal file
296
DICUI.Library/Utilities/IniFile.cs
Normal file
@@ -0,0 +1,296 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace DICUI.Utilities
|
||||
{
|
||||
public class IniFile : IDictionary<string, string>
|
||||
{
|
||||
private Dictionary<string, string> _keyValuePairs = new Dictionary<string, string>();
|
||||
|
||||
public string this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_keyValuePairs == null)
|
||||
_keyValuePairs = new Dictionary<string, string>();
|
||||
|
||||
key = key.ToLowerInvariant();
|
||||
if (_keyValuePairs.ContainsKey(key))
|
||||
return _keyValuePairs[key];
|
||||
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_keyValuePairs == null)
|
||||
_keyValuePairs = new Dictionary<string, string>();
|
||||
|
||||
key = key.ToLowerInvariant();
|
||||
_keyValuePairs[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty INI file
|
||||
/// </summary>
|
||||
public IniFile()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate an INI file from path
|
||||
/// </summary>
|
||||
public IniFile(string path)
|
||||
{
|
||||
this.Parse(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate an INI file from stream
|
||||
/// </summary>
|
||||
public IniFile(Stream stream)
|
||||
{
|
||||
this.Parse(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add or update a key and value to the INI file
|
||||
/// </summary>
|
||||
public void AddOrUpdate(string key, string value)
|
||||
{
|
||||
_keyValuePairs[key.ToLowerInvariant()] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a key from the INI file
|
||||
/// </summary>
|
||||
public void Remove(string key)
|
||||
{
|
||||
_keyValuePairs.Remove(key.ToLowerInvariant());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an INI file based on the path
|
||||
/// </summary>
|
||||
public bool Parse(string path)
|
||||
{
|
||||
// If we don't have a file, we can't read it
|
||||
if (!File.Exists(path))
|
||||
return false;
|
||||
|
||||
using (var fileStream = File.OpenRead(path))
|
||||
{
|
||||
return Parse(fileStream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an INI file from a stream
|
||||
/// </summary>
|
||||
public bool Parse(Stream stream)
|
||||
{
|
||||
// If the stream is invalid or unreadable, we can't process it
|
||||
if (stream == null || !stream.CanRead || stream.Position >= stream.Length - 1)
|
||||
return false;
|
||||
|
||||
// Keys are case-insensitive by default
|
||||
try
|
||||
{
|
||||
using (StreamReader sr = new StreamReader(stream))
|
||||
{
|
||||
string section = string.Empty;
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine().Trim();
|
||||
|
||||
// Comments start with ';'
|
||||
if (line.StartsWith(";"))
|
||||
{
|
||||
// No-op, we don't process comments
|
||||
}
|
||||
|
||||
// Section titles are surrounded by square brackets
|
||||
else if (line.StartsWith("["))
|
||||
{
|
||||
section = line.TrimStart('[').TrimEnd(']');
|
||||
}
|
||||
|
||||
// Valid INI lines are in the format key=value
|
||||
else if (line.Contains("="))
|
||||
{
|
||||
// Split the line by '=' for key-value pairs
|
||||
string[] data = line.Split('=');
|
||||
|
||||
// If the value field contains an '=', we need to put them back in
|
||||
string key = data[0].Trim();
|
||||
string value = string.Join("=", data.Skip(1)).Trim();
|
||||
|
||||
// Section names are prepended to the key with a '.' separating
|
||||
if (!string.IsNullOrEmpty(section))
|
||||
key = $"{section}.{key}";
|
||||
|
||||
// Set or overwrite keys in the returned dictionary
|
||||
_keyValuePairs[key.ToLowerInvariant()] = value;
|
||||
}
|
||||
|
||||
// All other lines are ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was, just catch and return
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an INI file to a path
|
||||
/// </summary>
|
||||
public bool Write(string path)
|
||||
{
|
||||
// If we don't have a valid dictionary with values, we can't write out
|
||||
if (_keyValuePairs == null || _keyValuePairs.Count == 0)
|
||||
return false;
|
||||
|
||||
using (var fileStream = File.OpenWrite(path))
|
||||
{
|
||||
return Write(fileStream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an INI file to a stream
|
||||
/// </summary>
|
||||
public bool Write(Stream stream)
|
||||
{
|
||||
// If we don't have a valid dictionary with values, we can't write out
|
||||
if (_keyValuePairs == null || _keyValuePairs.Count == 0)
|
||||
return false;
|
||||
|
||||
// If the stream is invalid or unwritable, we can't output to it
|
||||
if (stream == null || !stream.CanWrite || stream.Position >= stream.Length - 1)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
using (StreamWriter sw = new StreamWriter(stream))
|
||||
{
|
||||
// Order the dictionary by keys to link sections together
|
||||
var orderedKeyValuePairs = _keyValuePairs.OrderBy(kvp => kvp.Key);
|
||||
|
||||
string section = string.Empty;
|
||||
foreach (var keyValuePair in orderedKeyValuePairs)
|
||||
{
|
||||
// Extract the key and value
|
||||
string key = keyValuePair.Key;
|
||||
string value = keyValuePair.Value;
|
||||
|
||||
// We assume '.' is a section name separator
|
||||
if (key.Contains('.'))
|
||||
{
|
||||
// Split the key by '.'
|
||||
string[] data = keyValuePair.Key.Split('.');
|
||||
|
||||
// If the key contains an '.', we need to put them back in
|
||||
string newSection = data[0].Trim();
|
||||
key = string.Join(".", data.Skip(1)).Trim();
|
||||
|
||||
// If we have a new section, write it out
|
||||
if (!string.Equals(newSection, section, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sw.WriteLine($"[{newSection}]");
|
||||
section = newSection;
|
||||
}
|
||||
}
|
||||
|
||||
// Now write out the key and value in a standardized way
|
||||
sw.WriteLine($"{key}={value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was, just catch and return
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region IDictionary Impelementations
|
||||
|
||||
public ICollection<string> Keys => ((IDictionary<string, string>)_keyValuePairs).Keys;
|
||||
|
||||
public ICollection<string> Values => ((IDictionary<string, string>)_keyValuePairs).Values;
|
||||
|
||||
public int Count => ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Count;
|
||||
|
||||
public bool IsReadOnly => ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).IsReadOnly;
|
||||
|
||||
public void Add(string key, string value)
|
||||
{
|
||||
((IDictionary<string, string>)_keyValuePairs).Add(key.ToLowerInvariant(), value);
|
||||
}
|
||||
|
||||
bool IDictionary<string, string>.Remove(string key)
|
||||
{
|
||||
return ((IDictionary<string, string>)_keyValuePairs).Remove(key.ToLowerInvariant());
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out string value)
|
||||
{
|
||||
return ((IDictionary<string, string>)_keyValuePairs).TryGetValue(key.ToLowerInvariant(), out value);
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, string> item)
|
||||
{
|
||||
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
|
||||
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Add(newItem);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Clear();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, string> item)
|
||||
{
|
||||
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
|
||||
return ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Contains(newItem);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return _keyValuePairs.ContainsKey(key.ToLowerInvariant());
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
|
||||
{
|
||||
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, string> item)
|
||||
{
|
||||
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
|
||||
return ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Remove(newItem);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<KeyValuePair<string, string>>)_keyValuePairs).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable)_keyValuePairs).GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
66
DICUI.Library/Utilities/Result.cs
Normal file
66
DICUI.Library/Utilities/Result.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
namespace DICUI.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic success/failure result object, with optional message
|
||||
/// </summary>
|
||||
public class Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal representation of success
|
||||
/// </summary>
|
||||
private readonly bool success;
|
||||
|
||||
/// <summary>
|
||||
/// Optional message for the result
|
||||
/// </summary>
|
||||
public string Message { get; private set; }
|
||||
|
||||
private Result(bool success, string message)
|
||||
{
|
||||
this.success = success;
|
||||
this.Message = message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a default success result with no message
|
||||
/// </summary>
|
||||
public static Result Success() => new Result(true, "");
|
||||
|
||||
/// <summary>
|
||||
/// Create a success result with a custom message
|
||||
/// </summary>
|
||||
/// <param name="message">String to add as a message</param>
|
||||
public static Result Success(string message) => new Result(true, message);
|
||||
|
||||
/// <summary>
|
||||
/// Create a success result with a custom message with format parameters
|
||||
/// </summary>
|
||||
/// <param name="message">String to add as a message</param>
|
||||
/// <param name="args">Formatting parameters for the string</param>
|
||||
public static Result Success(string message, params object[] args) => new Result(true, string.Format(message, args));
|
||||
|
||||
/// <summary>
|
||||
/// Create a default failure result with no message
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Result Failure() => new Result(false, "");
|
||||
|
||||
/// <summary>
|
||||
/// Create a failure result with a custom message
|
||||
/// </summary>
|
||||
/// <param name="message">String to add as a message</param>
|
||||
public static Result Failure(string message) => new Result(false, message);
|
||||
|
||||
/// <summary>
|
||||
/// Create a failure result with a custom message with format parameters
|
||||
/// </summary>
|
||||
/// <param name="message">String to add as a message</param>
|
||||
/// <param name="args">Formatting parameters for the string</param>
|
||||
public static Result Failure(string message, params object[] args) => new Result(false, string.Format(message, args));
|
||||
|
||||
/// <summary>
|
||||
/// Results can be compared to boolean values based on the success value
|
||||
/// </summary>
|
||||
public static implicit operator bool(Result result) => result.success;
|
||||
}
|
||||
}
|
||||
115
DICUI.Library/Utilities/Tools.cs
Normal file
115
DICUI.Library/Utilities/Tools.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using DICUI.Web;
|
||||
|
||||
namespace DICUI.Utilities
|
||||
{
|
||||
public static class Tools
|
||||
{
|
||||
#region Byte Arrays
|
||||
|
||||
/// <summary>
|
||||
/// Search for a byte array in another array
|
||||
/// </summary>
|
||||
public static bool Contains(this byte[] stack, byte[] needle, out int position, int start = 0, int end = -1)
|
||||
{
|
||||
// Initialize the found position to -1
|
||||
position = -1;
|
||||
|
||||
// If either array is null or empty, we can't do anything
|
||||
if (stack == null || stack.Length == 0 || needle == null || needle.Length == 0)
|
||||
return false;
|
||||
|
||||
// If the needle array is larger than the stack array, it can't be contained within
|
||||
if (needle.Length > stack.Length)
|
||||
return false;
|
||||
|
||||
// If start or end are not set properly, set them to defaults
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
if (end < 0)
|
||||
end = stack.Length - needle.Length;
|
||||
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
if (stack.EqualAt(needle, i))
|
||||
{
|
||||
position = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See if a byte array starts with another
|
||||
/// </summary>
|
||||
public static bool StartsWith(this byte[] stack, byte[] needle)
|
||||
{
|
||||
return stack.Contains(needle, out int _, start: 0, end: 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if a stack at a certain index is equal to a needle
|
||||
/// </summary>
|
||||
private static bool EqualAt(this byte[] stack, byte[] needle, int index)
|
||||
{
|
||||
// If we're too close to the end of the stack, return false
|
||||
if (needle.Length >= stack.Length - index)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < needle.Length; i++)
|
||||
{
|
||||
if (stack[i + index] != needle[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Versioning
|
||||
|
||||
/// <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);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
1082
DICUI.Library/Utilities/Validators.cs
Normal file
1082
DICUI.Library/Utilities/Validators.cs
Normal file
File diff suppressed because it is too large
Load Diff
244
DICUI.Library/Web/Enumerations.cs
Normal file
244
DICUI.Library/Web/Enumerations.cs
Normal file
@@ -0,0 +1,244 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
1911
DICUI.Library/Web/Extensions.cs
Normal file
1911
DICUI.Library/Web/Extensions.cs
Normal file
File diff suppressed because it is too large
Load Diff
1560
DICUI.Library/Web/RedumpWebClient.cs
Normal file
1560
DICUI.Library/Web/RedumpWebClient.cs
Normal file
File diff suppressed because it is too large
Load Diff
311
DICUI.Library/Web/SubmissionInfo.cs
Normal file
311
DICUI.Library/Web/SubmissionInfo.cs
Normal file
@@ -0,0 +1,311 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
36
DICUI.Test/DICUI.Test.csproj
Normal file
36
DICUI.Test/DICUI.Test.csproj
Normal file
@@ -0,0 +1,36 @@
|
||||
<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>
|
||||
40
DICUI.Test/ResultTest.cs
Normal file
40
DICUI.Test/ResultTest.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
DICUI.Test/UI/AllowedSpeedsTest.cs
Normal file
21
DICUI.Test/UI/AllowedSpeedsTest.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Linq;
|
||||
using DICUI.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace DICUI.Test.Data
|
||||
{
|
||||
public class UIElementsTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(MediaType.CDROM, 72)]
|
||||
[InlineData(MediaType.DVD, 24)]
|
||||
[InlineData(MediaType.BluRay, 16)]
|
||||
[InlineData(MediaType.LaserDisc, 1)]
|
||||
[InlineData(null, 1)]
|
||||
public void GetAllowedDriveSpeedForMediaTypeTest(MediaType? mediaType, int maxExpected)
|
||||
{
|
||||
var actual = Interface.GetSpeedsForMediaType(mediaType);
|
||||
Assert.Equal(maxExpected, actual.Last());
|
||||
}
|
||||
}
|
||||
}
|
||||
129
DICUI.Test/Utilities/ConvertersTest.cs
Normal file
129
DICUI.Test/Utilities/ConvertersTest.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
91
DICUI.Test/Utilities/DumpEnvironmentTest.cs
Normal file
91
DICUI.Test/Utilities/DumpEnvironmentTest.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
DICUI.Test/Utilities/KnownSystemExtensionsTest.cs
Normal file
37
DICUI.Test/Utilities/KnownSystemExtensionsTest.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
46
DICUI.Test/Utilities/MediaTypeExtensionsTest.cs
Normal file
46
DICUI.Test/Utilities/MediaTypeExtensionsTest.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
DICUI.Test/Utilities/ParametersTest.cs
Normal file
69
DICUI.Test/Utilities/ParametersTest.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
45
DICUI.Test/Utilities/ValidatorsTest.cs
Normal file
45
DICUI.Test/Utilities/ValidatorsTest.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
DICUI.csproj
136
DICUI.csproj
@@ -1,136 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{7B1B75EB-8940-466F-BD51-76471A57F9BE}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>DICUI</RootNamespace>
|
||||
<AssemblyName>DICUI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>C:\Users\admin\Desktop\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>1</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ManifestCertificateThumbprint>654CEE5FEAF46C8C1C369D7ED34DA157828A8D2F</ManifestCertificateThumbprint>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ManifestKeyFile>WpfApp1_TemporaryKey.pfx</ManifestKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<GenerateManifests>true</GenerateManifests>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignManifests>false</SignManifests>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup />
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Icon.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
37
DICUI.sln
37
DICUI.sln
@@ -1,9 +1,24 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2036
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.28803.156
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DICUI", "DICUI.csproj", "{7B1B75EB-8940-466F-BD51-76471A57F9BE}"
|
||||
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
|
||||
@@ -15,6 +30,22 @@ Global
|
||||
{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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DICUI"
|
||||
StartupUri="MainWindow.xaml">
|
||||
StartupUri="Windows\MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
11
DICUI/App.xaml.cs
Normal file
11
DICUI/App.xaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
||||
4
DICUI/AssemblyInfo.cs
Normal file
4
DICUI/AssemblyInfo.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Anything marked as internal can be used by the test methods
|
||||
[assembly: InternalsVisibleTo("DICUI.Test")]
|
||||
29
DICUI/ComboBoxItems/CategoryComboBoxItem.cs
Normal file
29
DICUI/ComboBoxItems/CategoryComboBoxItem.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
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?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
30
DICUI/ComboBoxItems/InternalProgramComboBoxItem.cs
Normal file
30
DICUI/ComboBoxItems/InternalProgramComboBoxItem.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using DICUI.Data;
|
||||
using DICUI.Utilities;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single item in the Internal Program combo box
|
||||
/// </summary>
|
||||
public class InternalProgramComboBoxItem
|
||||
{
|
||||
private object data;
|
||||
|
||||
public InternalProgramComboBoxItem(InternalProgram? internalProgram) => data = internalProgram;
|
||||
|
||||
public static implicit operator InternalProgram? (InternalProgramComboBoxItem item) => item.data as InternalProgram?;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return (data as InternalProgram?).LongName();
|
||||
}
|
||||
}
|
||||
|
||||
public InternalProgram? Value
|
||||
{
|
||||
get { return data as InternalProgram?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
35
DICUI/ComboBoxItems/KnownSystemComboBoxItem.cs
Normal file
35
DICUI/ComboBoxItems/KnownSystemComboBoxItem.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
DICUI/ComboBoxItems/LanguageComboBoxItem.cs
Normal file
29
DICUI/ComboBoxItems/LanguageComboBoxItem.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
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?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
20
DICUI/ComboBoxItems/MediaTypeComboBoxItem.cs
Normal file
20
DICUI/ComboBoxItems/MediaTypeComboBoxItem.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
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(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
30
DICUI/ComboBoxItems/RegionComboBoxItem.cs
Normal file
30
DICUI/ComboBoxItems/RegionComboBoxItem.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
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?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
27
DICUI/Constants.cs
Normal file
27
DICUI/Constants.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace DICUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Variables for UI elements
|
||||
/// </summary>
|
||||
public static class Constants
|
||||
{
|
||||
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();
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
41
DICUI/DICUI.csproj
Normal file
41
DICUI/DICUI.csproj
Normal file
@@ -0,0 +1,41 @@
|
||||
<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.18</Version>
|
||||
<AssemblyVersion>1.18</AssemblyVersion>
|
||||
<FileVersion>1.18</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="1.5.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="$(PkgBurnOutSharp)\content\**" PackagePath="contentFiles\any\any;content" CopyToOutputDirectory="Always" PackageCopyToOutput="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DICUI.Library\DICUI.Library.csproj">
|
||||
<Project>{51ab0928-13f9-44bf-a407-b6957a43a056}</Project>
|
||||
<Name>DICUI.Library</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
32
DICUI/EnumDescriptionConverter.cs
Normal file
32
DICUI/EnumDescriptionConverter.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user