Compare commits

...

53 Commits
1.05.1 ... 1.10

Author SHA1 Message Date
Matt Nadareski
2175ccfb26 Update CHANGELIST 2018-07-29 12:44:46 -07:00
Matt Nadareski
621923bdba Add new Redump-recongized system 2018-07-24 19:27:45 -07:00
Matt Nadareski
3c216aa309 More accurate detection 2018-07-21 17:02:51 -07:00
Matt Nadareski
d85186e5cd Fix copy protection output again
This doesn't warrant a full PR
2018-07-19 23:40:17 -07:00
Matt Nadareski
1a94ad3d23 Don't try to get fancy 2018-07-19 15:34:16 -07:00
Matt Nadareski
91776d939c AppVeyor and Test (#103)
* Fixes to AppVeyor

* Fix tests
2018-07-19 15:31:25 -07:00
Matt Nadareski
3d058e633f Unblock and Update (#102)
* RAINBOW

* Add to FormatOutputData

* Update BurnOutSharp

* Fix parameter creation

* Minor improvements

* Update package versions
2018-07-19 14:11:58 -07:00
Matt Nadareski
94c0564fe8 Goodbye drive speed finders (#101)
* Goodbye drive speed finders

* More accurate scaling

* Ensure disposal
2018-07-17 16:42:38 -07:00
Matt Nadareski
87ecc7588e Update BurnOutSharp 2018-07-17 10:41:29 -07:00
Matt Nadareski
8a5c114a7e External and Fix (#100)
* Progress report updates log

* Logging additions

* Minor update

* Set halfway point only if nothing can be found

* Better population metrics

* QOL improvements

* More tiny logging updates

* Autoscroll

* Be consistent

* Update packages, use submodules

* Use NuGet

* Not 100% sure why I did it that way...

* Update README.md

* Make copy protect scan prompt an option

* Enhanced-CD might be Win/Mac

* Add unconfirmed formats

* Enhance!
2018-07-17 10:21:37 -07:00
ReignStumble
e307cb217f Fix DPI issue 2018-07-16 22:41:05 -04:00
Matt Nadareski
b8c56bea58 Whole Cleanup (#97)
* Cleanup TODOs

* Remove more TODOs

* Add case-insensitive dictionary for protection scans

* Namespace cleanups

* Space

* Minor fixes

* Oops

* Change layerbreak detect value
2018-07-15 22:26:22 -07:00
Matt Nadareski
564a6af9b8 Protection, Progress, and (Possibly) Empty Drives (#93)
* Include but mark inactive drives (fixes #87)

* Add more checks for the active flag

* Force users to choose on dump

* Fix quotes

* Update SolidShield 1

* Select first active by default

* Add TODO

* Add dumping progress indicator

* Clamp runtime

* Add first textfile scans; EA CdKey

* Slightly better executable detection

* Better file type detection

* Get as much into magic number checks as possible

* Nicer formatting

* Trailing slash

* Add back for benefit of the doubt

* Remove dead code

* Safer cabinet scanning

* Remove iXcomp; Add Unshield

* Fix build, add more comments

* Post-merge cleanup

* Add a new log line

* Make protection scan mechanics easier to see

* Add a space
2018-07-13 16:40:40 -07:00
Jacopo Santoni
5bcde889b3 Log Window enhancements (#95)
* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

* created LogWindow and first tests of output gathering

* integrated all the proof of concept related to stream fetching of DIC output into LogWindow

* working on LogWindow\ncreated more efficient output matching management, improved handling of process termination

* created Tasks file\nmoved some methods there, created DumpEnvironment to manage are arguments

* moved additional methods to Tasks to make it more modular

* changed StartDumping flow to avoid returning if extra tools are not found

* moved main dump workflow into Tasks class

* created specific DumpResult class for better error reporting/management

* fixes

* fixes Dispatcher thread issue with progress bar

* continued refactor
- split EnsureDiscInformation into an additional EnsureCorrectInformationForSystemAndMediaType
- proof of concept of using custom extensions to enum types to give better functionality (and encapsulation)
- changed cmb_MediaType to keep a List<MediaType?> and got rid of Tuple<string, MediaType?>

* restored GetDiscType functionality

* fixed btn_StartStop enabled on EnsureCorrect... error

* fixed whitespace

* fixed indentation

* merged conflicts

* moved log window

* working on LogWindow resize/location behavior

* working on message logging in LogWindow

* added working integration between MenuItem for LogWindow and its visibility status, fixes issues with positioning and visibility, correctly bound Verbose flag to property

* finished integrating LogWindow, added some verbose logs

* added logs

* fixed include order

* added option to show log window at startup, removed useless QuietMode property from MainWindow

* added precise calculation of MainWindow position when LogWindow is shown and fixed topmost cheat
2018-07-13 16:38:50 -07:00
Jacopo Santoni
b39c96cdd2 Log Window (#94)
* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

* created LogWindow and first tests of output gathering

* integrated all the proof of concept related to stream fetching of DIC output into LogWindow

* working on LogWindow\ncreated more efficient output matching management, improved handling of process termination

* created Tasks file\nmoved some methods there, created DumpEnvironment to manage are arguments

* moved additional methods to Tasks to make it more modular

* changed StartDumping flow to avoid returning if extra tools are not found

* moved main dump workflow into Tasks class

* created specific DumpResult class for better error reporting/management

* fixes

* fixes Dispatcher thread issue with progress bar

* continued refactor
- split EnsureDiscInformation into an additional EnsureCorrectInformationForSystemAndMediaType
- proof of concept of using custom extensions to enum types to give better functionality (and encapsulation)
- changed cmb_MediaType to keep a List<MediaType?> and got rid of Tuple<string, MediaType?>

* restored GetDiscType functionality

* fixed btn_StartStop enabled on EnsureCorrect... error

* fixed whitespace

* fixed indentation

* merged conflicts

* moved log window

* working on LogWindow resize/location behavior

* working on message logging in LogWindow

* added working integration between MenuItem for LogWindow and its visibility status, fixes issues with positioning and visibility, correctly bound Verbose flag to property

* finished integrating LogWindow, added some verbose logs

* added logs

* fixed include order

* added option to show log window at startup, removed useless QuietMode property from MainWindow
2018-07-13 15:48:35 -07:00
Matt Nadareski
2cc73a30f5 Protection Is Key (#92)
* Fix some protections, start adding IS scanning

* Fix IS CAB

* Update TODO
2018-07-10 10:23:52 -07:00
Matt Nadareski
be7d745d10 Create Parameters Class (#91)
* Update commented code

* Add Parameters class

This class is currently unused, but represents a set of parameters that can be passed to and from any given method. It has some copied/modified code from Validators.cs, for the time being due to the current overlap.

* Add better documentation

* Add and use DICFlag enumeration

* Port more things to Parameter-specific version

* Add commented code for later

* Added new options (#90)

* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

* added 4 new options: quiet mode, paranoid mode, disable media type detect and c2 reread amount

* added default C2 reread tries to config

* fixed issues for PR

* removed commented leftover

* Update commented code

* Add Parameters class

This class is currently unused, but represents a set of parameters that can be passed to and from any given method. It has some copied/modified code from Validators.cs, for the time being due to the current overlap.

* Add better documentation

* Add and use DICFlag enumeration

* Port more things to Parameter-specific version

* Add commented code for later

* Use Parameters object

* Fix dumping process

* Cleanup Validators
2018-07-09 21:42:02 -07:00
Jacopo Santoni
d51adccab4 Added new options (#90)
* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

* added 4 new options: quiet mode, paranoid mode, disable media type detect and c2 reread amount

* added default C2 reread tries to config

* fixed issues for PR

* removed commented leftover
2018-07-09 16:35:46 -07:00
Matt Nadareski
6141ce8539 Remove Disable Beep; Handle Error Case (#89)
* Disable beep not supported for these

* Remove testing code

This more or less ensures that the current run finishes properly

* Extra fixing for process issues

This, with the last 2 commits, make it so that geting disc speed works again. This was only found because in testing, many MANY instances of DiscImageCreator were made but never killed, polluting the process list. These issues should now be fixed.
2018-07-07 01:00:27 -07:00
Matt Nadareski
96d6e8bd2f Bits and Bobs (#88)
* Finally overhaul UI element naming

* Re-enable disk scan button

* Add cabfile scanning

* Fix csproj

* Fix TODO

* Add a couple more protections, disable one for now

* Fix SecuROM 7 detection

Thanks antimatter for helping test

* No beep for eject and speed check

* Fix Options after renames

* Ensure disc information in  couple places again
2018-07-07 00:08:22 -07:00
Matt Nadareski
c034df4266 More and more cleanup (#86)
* Namespace cleanups

* Make dump validation instanced

* Add note to Tasks

* Move stuff to DumpEnvironment

Most of the stuff in Tasks.cs acted on a single input parameter, namely a DumpEnvironment. Since that's the case, it was more logical to wrap those into DumpEnvironment and make them instance methods rather than keep them static. Due to this change, quite a few methods changed access, and some had to be marked internal due to wanting them to be tested separately.

* Gut Tasks

* One less thing in MainWindow

* Remove explicit cast

* Wrong check

* Create helper method

* Disable scan button on dump

* Remove unnecessary getters/setters

* Method name/description cleanup

* Address TODO

* Namespace cleanups

* Make dump validation instanced

* Add note to Tasks

* Move stuff to DumpEnvironment

Most of the stuff in Tasks.cs acted on a single input parameter, namely a DumpEnvironment. Since that's the case, it was more logical to wrap those into DumpEnvironment and make them instance methods rather than keep them static. Due to this change, quite a few methods changed access, and some had to be marked internal due to wanting them to be tested separately.

* Gut Tasks

* One less thing in MainWindow

* Remove explicit cast

* Wrong check

* Create helper method

* Disable scan button on dump

* Remove unnecessary getters/setters

* Method name/description cleanup

* Address TODO

* Clean up OnContentRendered

* Namespace cleanups

* Make dump validation instanced

* Add note to Tasks

* Move stuff to DumpEnvironment

Most of the stuff in Tasks.cs acted on a single input parameter, namely a DumpEnvironment. Since that's the case, it was more logical to wrap those into DumpEnvironment and make them instance methods rather than keep them static. Due to this change, quite a few methods changed access, and some had to be marked internal due to wanting them to be tested separately.

* Gut Tasks

* One less thing in MainWindow

* Remove explicit cast

* Wrong check

* Create helper method

* Disable scan button on dump

* Remove unnecessary getters/setters

* Method name/description cleanup

* Address TODO

* Clean up OnContentRendered

* Update event handlers
2018-07-05 21:34:04 -07:00
ReignStumble
fe04c6df73 Centered Window + No more resizable 2018-07-06 00:11:11 -04:00
ReignStumble
aff195eb71 Added Exit and About 2018-07-06 00:08:20 -04:00
ReignStumble
3aca999b63 New Menubar 2018-07-06 00:00:16 -04:00
ReignStumble
0e7ce76f01 Wait for UI to render before Populating 2018-07-05 23:43:01 -04:00
Matt Nadareski
6d72417512 Cleanups and mixups (#85)
Cleanups and Mixups
2018-07-05 16:52:34 -07:00
Matt Nadareski
ac89f06843 Separate out from Constants.cs 2018-07-05 13:33:08 -07:00
Matt Nadareski
39ce56d579 Post-merge cleanup 2018-07-05 13:18:01 -07:00
Matt Nadareski
9dbd30adba Merge DumpEnvironment/DumpInformation; Add Copy Protection Scan (#82)
* Merge DumpEnvironment and DumpInformation

* None of these need to be static

* Start adding protection checks

* Convert all BurnOut-related files from VB

* Placeholders for SafeDisc 3 and 4

* Fix some small things

* SubIntention not always output

* Make copy protect scan optional

* Try/catch on disc information to avoid crashes

* Add placeholders for Origin, Steam, UPlay

* Don't use copied method, for safety

* Protection cleanup

* More cleanup on SafeDisc v1/2

* Add area for cabfiles (for later); clean up more protections

* Comment out cabfile path, for now

* Underscores? Really?

* Namespace cleanup

* More Steam variations

* Add an actual UPlay installer name

* Skeleton for GFWL

* Add one for Origin

* More Steam, update note

* Add note kinda like GFWL

* Fix Origin installer name (IDK what I put there before...)

* Remove TODOs for ones with valid checks

* Add first GFWL installer name

* Move online services to last

Physical disc protections should ALWAYS come before an online service is mentioned. This makes sure that the physical media's information is not lost

* Add another TODO

* ...slightly longer comment

* Fix CDCops, start adding file lists

* More paths

* Even more paths

* Last paths for now

* Dictionary is smarter... so more work ahead

* Remind me why I'm doing this?

* Okay, recreated in dictionary now

* Reorganiation

* Alphabetization is fun

* Add unused call to new scan path

* Add TODO

* Remove TODO

* Remove TODO, comment out dummy files check

* Better state for no detected protection

* Make copy protect scan a Task so it can be used elsehwere later

* ScanEx -> Scan; cleanup

* Remove unused protection scan methods

These methods used to be a simple check for if a particular file existed. These are now captured in the "CreateProtectionMapping" dictionary

* Remove SuffixInStr

* Characters to literals, decimal to hex, start of consolidation

* Add remaining string-only mappings, cleanup

* Update summaries, remove unused flag

* Trim out unnecessary variables

These variables used to be used when a DLL or an EXE was found to have something in it but other files were needed to check against for better output. This also assumed a monolithic output in what protections were found. Now that we just list everything and all files are scanned, this should catch everything that comes through

* Remove unused path-based protections

* Accidentally wiped out Sysiphus

* CD Check is... special

* No more internal vars; static shock

* Add region tags

* Remove unused Dummy Files check

* Add scan for copy protection without dump

* Better checking of files

* Better message box

* Add TODO

* Clearer language for SafeDisc

* Fix SafeDisc scanning

Thanks to eientei95 for helping find this one

* Slight EVORE cleanup

* Fix SolidShield

Thanks to eientei95 for helping to fix this one

* Add sector scan note

* Add user-requested TODO

* Refactor of ComboBox underlying types (#84)

* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

* Refactored KnownSystem combobox management

- created KnownSystemComboBoxItem to manage both header and system items
- totally rewrote KnownSystem category (through KnownSystemCategory enum and markers)
- fixed null access in EnsureDiscInformation caused by null _drives
- rewrote cmb_SystemType management to use new classes

* - created Drive class to keep drive letters, volume label and is floppy flag altogether
- changed all the code to use the new Drive class in combobox and in DumpEnvironment

* fixed retrieval of value from cmb_KnownSystem combobox

* removed OrderedDictionary, not needed anymore

* Merge DumpEnvironment and DumpInformation

* None of these need to be static

* Start adding protection checks

* Convert all BurnOut-related files from VB

* Placeholders for SafeDisc 3 and 4

* Fix some small things

* SubIntention not always output

* Make copy protect scan optional

* Try/catch on disc information to avoid crashes

* Add placeholders for Origin, Steam, UPlay

* Don't use copied method, for safety

* Protection cleanup

* More cleanup on SafeDisc v1/2

* Add area for cabfiles (for later); clean up more protections

* Comment out cabfile path, for now

* Underscores? Really?

* Namespace cleanup

* More Steam variations

* Add an actual UPlay installer name

* Skeleton for GFWL

* Add one for Origin

* More Steam, update note

* Add note kinda like GFWL

* Fix Origin installer name (IDK what I put there before...)

* Remove TODOs for ones with valid checks

* Add first GFWL installer name

* Move online services to last

Physical disc protections should ALWAYS come before an online service is mentioned. This makes sure that the physical media's information is not lost

* Add another TODO

* ...slightly longer comment

* Fix CDCops, start adding file lists

* More paths

* Even more paths

* Last paths for now

* Dictionary is smarter... so more work ahead

* Remind me why I'm doing this?

* Okay, recreated in dictionary now

* Reorganiation

* Alphabetization is fun

* Add unused call to new scan path

* Add TODO

* Remove TODO

* Remove TODO, comment out dummy files check

* Better state for no detected protection

* Make copy protect scan a Task so it can be used elsehwere later

* ScanEx -> Scan; cleanup

* Remove unused protection scan methods

These methods used to be a simple check for if a particular file existed. These are now captured in the "CreateProtectionMapping" dictionary

* Remove SuffixInStr

* Characters to literals, decimal to hex, start of consolidation

* Add remaining string-only mappings, cleanup

* Update summaries, remove unused flag

* Trim out unnecessary variables

These variables used to be used when a DLL or an EXE was found to have something in it but other files were needed to check against for better output. This also assumed a monolithic output in what protections were found. Now that we just list everything and all files are scanned, this should catch everything that comes through

* Remove unused path-based protections

* Accidentally wiped out Sysiphus

* CD Check is... special

* No more internal vars; static shock

* Add region tags

* Remove unused Dummy Files check

* Add scan for copy protection without dump

* Better checking of files

* Better message box

* Add TODO

* Clearer language for SafeDisc

* Fix SafeDisc scanning

Thanks to eientei95 for helping find this one

* Slight EVORE cleanup

* Fix SolidShield

Thanks to eientei95 for helping to fix this one

* Add sector scan note

* Add user-requested TODO
2018-07-05 12:58:20 -07:00
Jacopo Santoni
48de63513e Refactor of ComboBox underlying types (#84)
* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

* Refactored KnownSystem combobox management

- created KnownSystemComboBoxItem to manage both header and system items
- totally rewrote KnownSystem category (through KnownSystemCategory enum and markers)
- fixed null access in EnsureDiscInformation caused by null _drives
- rewrote cmb_SystemType management to use new classes

* - created Drive class to keep drive letters, volume label and is floppy flag altogether
- changed all the code to use the new Drive class in combobox and in DumpEnvironment

* fixed retrieval of value from cmb_KnownSystem combobox

* removed OrderedDictionary, not needed anymore
2018-07-05 11:30:52 -07:00
Matt Nadareski
56eaf7c2c5 Add Test Project (#79)
* Add Test project; Migrate so there's not an external folder

* Add Test project; Migrate so that there's not an external folder

* Fix build; Add remaining test classes (skeletons)

* Fix more paths

* Make unit tests runnable, fix issue found by unit tests

* Add more tests, fix more things found by tests

* Add skeleton for ValidatorsTest, fix OrderedDictionary

* Add UIElementsTest

* Add new test classes, slightly update Result

* Implement DumpEnvirionment tests; fix minor things from testing

* Add Tasks testing skeletons; Reorder methods and change access modifiers for some

* Update notes for DumpInformation tests

* Implement a couple Validators tests; fix ValidateParameters

* Implement DetermineFlagsTest

* Make one test more readable

* More cleanup around ValidateParameters

* Split check

* WiiU is not supported by /raw command

* Add TODO question

* Update TODO with a plan
2018-06-28 19:41:18 -07:00
Matt Nadareski
c1bd30e008 Streamline Callbacks and Ensure MediaType (#78)
* Separate drive speeds; better ensuring of media type

This is the first attempt at separating out the drive speeds into separate categories. At the moment, it seems to be working just fine for CD and DVD.
This also includes some updated code to better ensure that the detected (or selected if the user has changed it) media type is kept between all of the regular changes

* Multiple medium

* Add more drive speed prototyping

* Strip out redundant calls

* Separate drive speeds; better ensuring of media type

This is the first attempt at separating out the drive speeds into separate categories. At the moment, it seems to be working just fine for CD and DVD.
This also includes some updated code to better ensure that the detected (or selected if the user has changed it) media type is kept between all of the regular changes

* Multiple medium

* Add more drive speed prototyping

* Strip out redundant calls

* Streamline merge

* Comment patrol; keep BluRay a first-class citizen

* HD-DVD is supported?!
2018-06-27 23:21:52 -07:00
Jacopo Santoni
4176f22d79 Added preferred dump speed option (#77)
* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

* added max dump speed option
- added slider element into OptionsWindow
- moved drive speeds to UIElements from MainWindow
- added setting to Options which is saved

still need to understand how to manage DVD/CD-ROM different speeds

* kept working on max dump speed settings

- rewrote max speed list management in Options
- added second slider in OptionsWindow
- added callback from OptionsWindow to MainWindow on updated options

* final tweaks before PR

* renamed maxDumpSpeed to preferredDumpSpeed

* restored SetCurrentDiscType functionality

* fixes for PR

* fixes for PR
2018-06-27 20:06:19 -07:00
Matt Nadareski
1e16e952cf Update for 1.07 2018-06-27 10:35:40 -07:00
Matt Nadareski
9f493ae27a One last fix for drive speed finding
DIC can sometimes report that a drive has a 0x speed, causing this automatic finder to fail in those cases
2018-06-27 10:35:29 -07:00
Matt Nadareski
2021230836 Quick fix to account for possibly odd speeds 2018-06-27 00:21:53 -07:00
Matt Nadareski
12ba5702fd Minor updates
This mostly takes care of adding a ton of comments and descriptions. Other minor changes include:
- Removing last remnants of psxt001z
- Capitalizing public variables
- Fixing the build that I stupidly broke
- Ensuring whitespace-named discs are handled
- Simplified DumpEnvironment init
2018-06-26 21:08:26 -07:00
Jacopo Santoni
2cf083eb89 Refactor of dump procedure into smaller components (#76)
* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

* created Tasks file\nmoved some methods there, created DumpEnvironment to manage are arguments

* moved additional methods to Tasks to make it more modular

* changed StartDumping flow to avoid returning if extra tools are not found

* moved main dump workflow into Tasks class

* created specific DumpResult class for better error reporting/management

* fixes

* continued refactor
- split EnsureDiscInformation into an additional EnsureCorrectInformationForSystemAndMediaType
- proof of concept of using custom extensions to enum types to give better functionality (and encapsulation)
- changed cmb_MediaType to keep a List<MediaType?> and got rid of Tuple<string, MediaType?>

* restored GetDiscType functionality

* fixed btn_StartStop enabled on EnsureCorrect... error

* fixed whitespace

* fixed indentation

* fixes for PR
2018-06-26 20:18:37 -07:00
Matt Nadareski
c1f22d47dc Remove Redundant Calls and PSX Automation (#75)
* Work with callbacks to increase perf

* Make EDC field for PSX automatic

* Make AntiMod field for PSX automatic

* Make LibCrypt field for PSX automatic

* Remove psxt001z

Now that we have confirmed that DIC outputs the required information for libcrypt, we no longer need the external call to psxt001z to confirm (output was unused anyway)

* We need the subIntention data for LibCrypt

* Let's avoid null for now

* Set default speed in case of error

* Check the layerbreak better

* Remove extraneous header checking

* Add SubIntention field if it exists, always

* Add LibCrypt flag by default for PSX

* SubIntention needs a newline
2018-06-26 10:35:58 -07:00
Matt Nadareski
11287d081d Add system requirements (fixes #72) 2018-06-25 10:18:06 -07:00
Matt Nadareski
8652af5697 Usability Updates (#73)
* Checkpoint

* Add notes

* Rename Validation -> Validators

* Move data to Data folder

* Get current disk type

* Automatically detect disc type

* Comment out WIP code

* Add more prototype

The hope is that having this unhooked prototype code will get either myself or another contributor the right inspiration to get it going properly
2018-06-25 10:00:06 -07:00
Matt Nadareski
69561cb1a0 Bits and Pieces (#70)
* DiscType -> MediaType

* Fix bulk find/replace

* Add OrderedDictionary

* Stage 1 of moving off of Tuples

* Add CHANGELIST.md

* Stage 2 of Tuple removal

* String replacement for output paths

* Stage 3 of Tuple removal

* Slight reordering
2018-06-21 11:46:14 -07:00
Matt Nadareski
d587d2b4b3 Add system and media type to output submission info (#65)
* Add new constants to the template

* Slight reordering

* Add new fields to the output

* Whitespace!

* Minor formatting cleanup

* Add TODO

* Whitepace, 2.0
2018-06-20 22:00:26 -07:00
Matt Nadareski
a19418e46f Remove sg-raw (#64)
* Remove sg-raw from OptionsWindow.xaml.cs

* Remove sg-raw from OptionsWindow.xaml

* Remove sg-raw from Options.cs

* Remove sg-raw from MainWindow.xaml.cs

* Missed the other rows

* Remove sg-raw from App.config
2018-06-20 12:44:39 -07:00
Jacopo Santoni
de22ead07c Enhancement of options management (#63)
* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

* added OptionsFrame that will manage all applicaton settings and implemented path browse buttons

* removed old properties code, added Options to manage all the program options, implemented interactions with OptionsWindow

* fixed margins automatically inserted by MSVS

* fixed margins automatically inserted by MSVS

* removed empty method placed by XAML designer

* added closed callback for OptionsWindows, tweaks

* fixed button in toolbar
2018-06-20 12:30:31 -07:00
Matt Nadareski
f777869103 Formats and Types (#58)
* Combine single/dual-layer disc types

* Add silly formats

* Minor tweaks to disc type population

* Make codepath slightly less complex

* Fix null error on dump

* Update strings that looked wrong in output
2018-06-20 11:38:12 -07:00
reignstumble
aec1131271 Update README.md 2018-06-20 12:23:01 -04:00
Jacopo Santoni
308fad3ed2 Separated of System and Disc Type (#56)
* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox
2018-06-18 12:43:07 -07:00
Matt Nadareski
61ce45667b Update for 1.06 2018-06-15 20:27:34 -07:00
Matt Nadareski
ababfdd2ed XBOX/360 Fixes (#50)
* Better creation of parameters (fixes Xbox/360)

* Split X360 into XDG2/3

* Don't enable drive speed if we're not supposed to

* Add first attempt at Xbox info extraction

* Trim or it never matches
2018-06-15 20:24:43 -07:00
Matt Nadareski
9683074197 Only eject when told 2018-06-14 20:18:01 -07:00
Matt Nadareski
ab2bc8f50c Worst typo ever 2018-06-14 20:11:49 -07:00
reignstumble
aa86ddaf47 Fix incorrectly enabled button 2018-06-14 20:40:41 -04:00
49 changed files with 6666 additions and 3245 deletions

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="dicPath" value="Programs\DiscImageCreator.exe"/>
<add key="psxt001zPath" value="psxt001z.exe"/>
<add key="sgRawPath" value="sg_raw.exe"/>
<add key="subdumpPath" value="subdump.exe"/>
<add key="defaultOutputPath" value="ISO"/>
</appSettings>
</configuration>

82
CHANGELIST.md Normal file
View File

@@ -0,0 +1,82 @@
### 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.

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.NET.Test.Sdk.15.8.0\build\net45\Microsoft.Net.Test.Sdk.props" Condition="Exists('..\packages\Microsoft.NET.Test.Sdk.15.8.0\build\net45\Microsoft.Net.Test.Sdk.props')" />
<Import Project="..\packages\Microsoft.CodeCoverage.15.8.0\build\netstandard1.0\Microsoft.CodeCoverage.props" Condition="Exists('..\packages\Microsoft.CodeCoverage.15.8.0\build\netstandard1.0\Microsoft.CodeCoverage.props')" />
<Import Project="..\packages\xunit.runner.visualstudio.2.3.1\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\packages\xunit.runner.visualstudio.2.3.1\build\net20\xunit.runner.visualstudio.props')" />
<Import Project="..\packages\xunit.runner.console.2.3.1\build\xunit.runner.console.props" Condition="Exists('..\packages\xunit.runner.console.2.3.1\build\xunit.runner.console.props')" />
<Import Project="..\packages\xunit.core.2.3.1\build\xunit.core.props" Condition="Exists('..\packages\xunit.core.2.3.1\build\xunit.core.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{7CC064D2-38AB-4A05-8519-28660DE4562A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DICUI.Test</RootNamespace>
<AssemblyName>DICUI.Test</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<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' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.CodeCoverage.Shim, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeCoverage.15.8.0\lib\net45\Microsoft.VisualStudio.CodeCoverage.Shim.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll</HintPath>
</Reference>
<Reference Include="xunit.assert, Version=2.3.1.3858, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll</HintPath>
</Reference>
<Reference Include="xunit.core, Version=2.3.1.3858, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll</HintPath>
</Reference>
<Reference Include="xunit.execution.desktop, Version=2.3.1.3858, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.execution.2.3.1\lib\net452\xunit.execution.desktop.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="UI\AllowedSpeedsTest.cs" />
<Compile Include="Utilities\DICFlagExtensionsTest.cs" />
<Compile Include="Utilities\DumpEnvironmentTest.cs" />
<Compile Include="ResultTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utilities\DriveTest.cs" />
<Compile Include="Utilities\ConvertersTest.cs" />
<Compile Include="Utilities\DICCommandExtensionsTest.cs" />
<Compile Include="Utilities\KnownSystemExtensionsTest.cs" />
<Compile Include="Utilities\MediaTypeExtensionsTest.cs" />
<Compile Include="Utilities\ParametersTest.cs" />
<Compile Include="Utilities\ValidatorsTest.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DICUI\DICUI.csproj">
<Project>{7b1b75eb-8940-466f-bd51-76471a57f9be}</Project>
<Name>DICUI</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\packages\xunit.analyzers.0.10.0\analyzers\dotnet\cs\xunit.analyzers.dll" />
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\xunit.core.2.3.1\build\xunit.core.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.core.2.3.1\build\xunit.core.props'))" />
<Error Condition="!Exists('..\packages\xunit.core.2.3.1\build\xunit.core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.core.2.3.1\build\xunit.core.targets'))" />
<Error Condition="!Exists('..\packages\xunit.runner.console.2.3.1\build\xunit.runner.console.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.runner.console.2.3.1\build\xunit.runner.console.props'))" />
<Error Condition="!Exists('..\packages\xunit.runner.visualstudio.2.3.1\build\net20\xunit.runner.visualstudio.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.runner.visualstudio.2.3.1\build\net20\xunit.runner.visualstudio.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.CodeCoverage.15.8.0\build\netstandard1.0\Microsoft.CodeCoverage.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeCoverage.15.8.0\build\netstandard1.0\Microsoft.CodeCoverage.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.CodeCoverage.15.8.0\build\netstandard1.0\Microsoft.CodeCoverage.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeCoverage.15.8.0\build\netstandard1.0\Microsoft.CodeCoverage.targets'))" />
<Error Condition="!Exists('..\packages\Microsoft.NET.Test.Sdk.15.8.0\build\net45\Microsoft.Net.Test.Sdk.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.NET.Test.Sdk.15.8.0\build\net45\Microsoft.Net.Test.Sdk.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.NET.Test.Sdk.15.8.0\build\net45\Microsoft.Net.Test.Sdk.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.NET.Test.Sdk.15.8.0\build\net45\Microsoft.Net.Test.Sdk.targets'))" />
</Target>
<Import Project="..\packages\xunit.core.2.3.1\build\xunit.core.targets" Condition="Exists('..\packages\xunit.core.2.3.1\build\xunit.core.targets')" />
<Import Project="..\packages\Microsoft.CodeCoverage.15.8.0\build\netstandard1.0\Microsoft.CodeCoverage.targets" Condition="Exists('..\packages\Microsoft.CodeCoverage.15.8.0\build\netstandard1.0\Microsoft.CodeCoverage.targets')" />
<Import Project="..\packages\Microsoft.NET.Test.Sdk.15.8.0\build\net45\Microsoft.Net.Test.Sdk.targets" Condition="Exists('..\packages\Microsoft.NET.Test.Sdk.15.8.0\build\net45\Microsoft.Net.Test.Sdk.targets')" />
</Project>

View File

@@ -0,0 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("DICUI.Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DICUI.Test")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("7cc064d2-38ab-4a05-8519-28660de4562a")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

40
DICUI.Test/ResultTest.cs Normal file
View 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);
}
}
}

View File

@@ -0,0 +1,22 @@
using System.Linq;
using DICUI.Data;
using DICUI.UI;
using Xunit;
namespace DICUI.Test.Data
{
public class UIElementsTest
{
[Theory]
[InlineData(MediaType.CD, 72)]
[InlineData(MediaType.DVD, 24)]
[InlineData(MediaType.BluRay, 16)]
[InlineData(MediaType.LaserDisc, 72)] // TODO: Update when fully determined
[InlineData(null, 72)] // TODO: Update when fully determined
public void GetAllowedDriveSpeedForMediaTypeTest(MediaType? mediaType, int maxExpected)
{
var actual = AllowedSpeeds.GetForMediaType(mediaType);
Assert.Equal(maxExpected, actual.Last());
}
}
}

View File

@@ -0,0 +1,127 @@
using System;
using DICUI.Data;
using DICUI.Utilities;
using Xunit;
namespace DICUI.Test.Utilities
{
public class ConvertersTest
{
[Theory]
[InlineData(DICCommand.Audio, MediaType.CD)]
[InlineData(DICCommand.BluRay, MediaType.BluRay)]
[InlineData(DICCommand.Close, null)]
[InlineData(DICCommand.CompactDisc, MediaType.CD)]
[InlineData(DICCommand.Data, MediaType.CD)]
[InlineData(DICCommand.DigitalVideoDisc, MediaType.DVD)]
[InlineData(DICCommand.Eject, null)]
[InlineData(DICCommand.Floppy, MediaType.Floppy)]
[InlineData(DICCommand.GDROM, MediaType.GDROM)]
[InlineData(DICCommand.MDS, null)]
[InlineData(DICCommand.Reset, null)]
[InlineData(DICCommand.Start, null)]
[InlineData(DICCommand.Stop, null)]
[InlineData(DICCommand.Sub, null)]
[InlineData(DICCommand.Swap, MediaType.GDROM)]
[InlineData(DICCommand.XBOX, MediaType.DVD)]
public void BaseCommandToMediaTypeTest(DICCommand command, MediaType? expected)
{
MediaType? actual = Converters.BaseCommmandToMediaType(command);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(DICCommand.Audio, KnownSystem.AudioCD)]
[InlineData(DICCommand.BluRay, KnownSystem.SonyPlayStation3)]
[InlineData(DICCommand.Close, null)]
[InlineData(DICCommand.CompactDisc, KnownSystem.IBMPCCompatible)]
[InlineData(DICCommand.Data, KnownSystem.IBMPCCompatible)]
[InlineData(DICCommand.DigitalVideoDisc, KnownSystem.IBMPCCompatible)]
[InlineData(DICCommand.Eject, null)]
[InlineData(DICCommand.Floppy, KnownSystem.IBMPCCompatible)]
[InlineData(DICCommand.GDROM, KnownSystem.SegaDreamcast)]
[InlineData(DICCommand.MDS, null)]
[InlineData(DICCommand.Reset, null)]
[InlineData(DICCommand.Start, null)]
[InlineData(DICCommand.Stop, null)]
[InlineData(DICCommand.Sub, null)]
[InlineData(DICCommand.Swap, KnownSystem.SegaDreamcast)]
[InlineData(DICCommand.XBOX, KnownSystem.MicrosoftXBOX)]
public void BaseCommandToKnownSystemTest(DICCommand command, KnownSystem? expected)
{
KnownSystem? actual = Converters.BaseCommandToKnownSystem(command);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(MediaType.CD, ".bin")]
[InlineData(MediaType.DVD, ".iso")]
[InlineData(MediaType.LaserDisc, ".raw")]
[InlineData(MediaType.WiiUOpticalDisc, ".wud")]
[InlineData(MediaType.Floppy, ".img")]
[InlineData(MediaType.Cassette, ".wav")]
[InlineData(MediaType.NONE, null)]
public void MediaTypeToExtensionTest(MediaType? mediaType, string expected)
{
string actual = Converters.MediaTypeToExtension(mediaType);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(MediaType.CD, "CD-ROM")]
[InlineData(MediaType.LaserDisc, "LaserDisc")]
[InlineData(MediaType.NONE, "Unknown")]
public void MediaTypeToStringTest(MediaType? mediaType, string expected)
{
string actual = Converters.MediaTypeToString(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.Custom, "Custom Input")]
[InlineData(KnownSystem.NONE, "Unknown")]
public void KnownSystemToStringTest(KnownSystem? knownSystem, string expected)
{
string actual = Converters.KnownSystemToString(knownSystem);
Assert.Equal(expected, actual);
}
[Fact]
public void KnownSystemHasValidCategory()
{
var values = Validators.CreateListOfSystems();
KnownSystem[] markers = { KnownSystem.MarkerArcadeEnd, KnownSystem.MarkerConsoleEnd, KnownSystem.MarkerComputerEnd, KnownSystem.MarkerOtherEnd };
values.ForEach(system => {
if (system == KnownSystem.NONE || system == KnownSystem.Custom)
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.Console: marker = KnownSystem.MarkerConsoleEnd; 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);
});
});
}
}
}

View File

@@ -0,0 +1,23 @@
using System;
using DICUI.Data;
using DICUI.Utilities;
using Xunit;
namespace DICUI.Test.Utilities
{
public class DICCommandExtensionsTest
{
[Fact]
public void NameTest()
{
var values = (DICCommand[])Enum.GetValues(typeof(DICCommand));
foreach(var command in values)
{
string expected = Converters.DICCommandToString(command);
string actual = command.Name();
Assert.Equal(expected, actual);
}
}
}
}

View File

@@ -0,0 +1,23 @@
using System;
using DICUI.Data;
using DICUI.Utilities;
using Xunit;
namespace DICUI.Test.Utilities
{
public class DICFlagExtensionsTest
{
[Fact]
public void NameTest()
{
var values = (DICFlag[])Enum.GetValues(typeof(DICFlag));
foreach(var command in values)
{
string expected = Converters.DICFlagToString(command);
string actual = command.Name();
Assert.Equal(expected, actual);
}
}
}
}

View File

@@ -0,0 +1,15 @@
using DICUI.Utilities;
using Xunit;
namespace DICUI.Test.Utilities
{
public class DriveTest
{
[Fact]
public void DriveConstructorsTest()
{
Assert.True(Drive.Floppy('a').IsFloppy);
Assert.False(Drive.Optical('d', "test", true).IsFloppy);
}
}
}

View File

@@ -0,0 +1,149 @@
using System;
using System.Linq;
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.CD, true)]
[InlineData("fd A test.img", 'A', true, MediaType.Floppy, true)]
[InlineData("dvd X test.iso 8 /raw", 'X', false, MediaType.Floppy, false)]
[InlineData("stop D", 'D', false, MediaType.DVD, true)]
public void ParametersValidTest(string parameters, char letter, bool isFloppy, MediaType? mediaType, bool expected)
{
var env = new DumpEnvironment
{
DICParameters = new Parameters(parameters),
Drive = isFloppy ? Drive.Floppy(letter) : Drive.Optical(letter, "", true),
Type = mediaType,
};
bool actual = env.ParametersValid();
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(null, null, null, new char(), null, null)]
[InlineData("", null, null, new char(), null, null)]
[InlineData("cd F test.bin 8 /c2 20", MediaType.CD, KnownSystem.IBMPCCompatible, 'F', "", "test.bin")]
[InlineData("fd A blah\\test.img", MediaType.Floppy, KnownSystem.IBMPCCompatible, 'A', "blah", "test.img")]
[InlineData("dvd X super\\blah\\test.iso 8 /raw", MediaType.GameCubeGameDisc, KnownSystem.NintendoGameCube, 'X', "super\\blah", "test.iso")]
[InlineData("stop D", null, null, 'D', null, null)]
public void AdjustForCustomConfigurationTest(string parameters, MediaType? expectedMediaType, KnownSystem? expectedKnownSystem, char expectedDriveLetter, string expectedOutputDirectory, string expectedOutputFilename)
{
var env = new DumpEnvironment
{
DICParameters = new Parameters(parameters),
System = KnownSystem.Custom,
};
env.AdjustForCustomConfiguration();
Assert.Equal(expectedMediaType, env.Type);
Assert.Equal(expectedKnownSystem, env.System);
Assert.Equal(expectedDriveLetter, env.Drive.Letter);
Assert.Equal(expectedOutputDirectory, env.OutputDirectory);
Assert.Equal(expectedOutputFilename, env.OutputFilename);
}
[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 env = new DumpEnvironment
{
OutputDirectory = outputDirectory,
OutputFilename = outputFilename,
};
env.FixOutputPaths();
Assert.Equal(expectedOutputDirectory, env.OutputDirectory);
Assert.Equal(expectedOutputFilename, env.OutputFilename);
}
[Fact]
public void GetFirstTrackTest()
{
// TODO: Implement
Assert.True(true);
}
[Theory]
[InlineData(MediaType.CD)]
[InlineData(MediaType.DVD)]
[InlineData(MediaType.Floppy)]
[InlineData(MediaType.LaserDisc)]
public void FoundAllFilesTest(MediaType? mediaType)
{
// TODO: Implement
// TODO: Get sample output data for each of the major types
Assert.True(true);
}
[Theory]
[InlineData(KnownSystem.AppleMacintosh, MediaType.CD)]
[InlineData(KnownSystem.PhilipsCDi, MediaType.CD)]
[InlineData(KnownSystem.SegaSaturn, MediaType.CD)]
[InlineData(KnownSystem.SonyPlayStation, MediaType.CD)]
[InlineData(KnownSystem.SonyPlayStation2, MediaType.CD)]
[InlineData(KnownSystem.AppleMacintosh, MediaType.DVD)]
[InlineData(KnownSystem.DVDVideo, MediaType.DVD)]
[InlineData(KnownSystem.MicrosoftXBOX, MediaType.DVD)]
[InlineData(KnownSystem.SonyPlayStation2, MediaType.DVD)]
[InlineData(KnownSystem.BDVideo, MediaType.BluRay)]
[InlineData(KnownSystem.AUSCOMSystem1, MediaType.Cassette)]
public void ExtractOutputInformation(KnownSystem? knownSystem, MediaType? mediaType)
{
// TODO: Implement
// TODO: Get sample output data for each of the major types
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);
}
}
}

View File

@@ -0,0 +1,61 @@
using System;
using DICUI.Data;
using DICUI.Utilities;
using Xunit;
namespace DICUI.Test.Utilities
{
public class KnownSystemExtensionsTest
{
[Fact]
public void NameTest()
{
var values = (KnownSystem[])Enum.GetValues(typeof(KnownSystem));
foreach(var system in values)
{
string expected = Converters.KnownSystemToString(system);
string actual = ((KnownSystem?)system).Name();
Assert.Equal(expected, actual);
}
}
[Theory]
[InlineData(KnownSystem.AppleMacintosh, true)]
[InlineData(KnownSystem.MicrosoftXBOX, false)]
[InlineData(KnownSystem.MicrosoftXBOX360XDG2, false)]
[InlineData(KnownSystem.MicrosoftXBOX360XDG3, false)]
[InlineData(KnownSystem.SonyPlayStation3, true)]
public void DriveSpeedSupportedTest(KnownSystem? knownSystem, bool expected)
{
bool actual = knownSystem.DoesSupportDriveSpeed();
Assert.Equal(expected, actual);
}
[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.MarkerConsoleEnd;
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).Name();
Assert.NotEqual("", actual);
}
}
}
}

View File

@@ -0,0 +1,48 @@
using DICUI.Data;
using DICUI.Utilities;
using Xunit;
namespace DICUI.Test.Utilities
{
public class MediaTypeExtensionsTest
{
[Theory]
[InlineData(MediaType.CD)]
[InlineData(MediaType.LaserDisc)]
[InlineData(MediaType.NONE)]
public void NameTest(MediaType? mediaType)
{
string expected = Converters.MediaTypeToString(mediaType);
string actual = mediaType.Name();
Assert.NotNull(actual);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(MediaType.CD)]
[InlineData(MediaType.DVD)]
[InlineData(MediaType.LaserDisc)]
[InlineData(MediaType.Floppy)]
[InlineData(MediaType.NONE)]
public void ExtensionTest(MediaType? mediaType)
{
string expected = Converters.MediaTypeToExtension(mediaType);
string actual = mediaType.Extension();
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(MediaType.CD, true)]
[InlineData(MediaType.DVD, true)]
[InlineData(MediaType.Floppy, false)]
[InlineData(MediaType.BluRay, false)]
[InlineData(MediaType.LaserDisc, false)]
public void DriveSpeedSupportedTest(MediaType? mediaType, bool expected)
{
bool actual = mediaType.DoesSupportDriveSpeed();
Assert.Equal(expected, actual);
}
}
}

View File

@@ -0,0 +1,85 @@
using System.Collections.Generic;
using System.Linq;
using DICUI.Data;
using DICUI.Utilities;
using Xunit;
namespace DICUI.Test.Utilities
{
public class ParametersTest
{
[Theory]
[InlineData(KnownSystem.MicrosoftXBOX, MediaType.CD, DICCommand.XBOX)]
[InlineData(KnownSystem.MicrosoftXBOX, MediaType.DVD, DICCommand.XBOX)]
[InlineData(KnownSystem.MicrosoftXBOX, MediaType.LaserDisc, DICCommand.NONE)]
[InlineData(KnownSystem.SegaNu, MediaType.BluRay, DICCommand.BluRay)]
[InlineData(KnownSystem.AppleMacintosh, MediaType.Floppy, DICCommand.Floppy)]
[InlineData(KnownSystem.RawThrillsVarious, MediaType.GDROM, DICCommand.NONE)]
public void ParametersFromSystemAndTypeTest(KnownSystem? knownSystem, MediaType? mediaType, DICCommand expected)
{
Parameters actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, true, -1);
Assert.Equal(expected, actual.Command);
}
[Theory]
[InlineData(KnownSystem.AppleMacintosh, MediaType.LaserDisc, true, 20, null, null)]
[InlineData(KnownSystem.NintendoGameCube, MediaType.GameCubeGameDisc, false, 20, null, new DICFlag[] { DICFlag.Raw })]
[InlineData(KnownSystem.IBMPCCompatible, MediaType.DVD, false, 20, null, new DICFlag[] { })]
/* paranoid mode tests */
[InlineData(KnownSystem.IBMPCCompatible, MediaType.CD, true, 1000, 2, new DICFlag[] { DICFlag.C2Opcode, DICFlag.NoFixSubQSecuROM, DICFlag.ScanFileProtect, DICFlag.ScanSectorProtect, DICFlag.SubchannelReadLevel })]
[InlineData(KnownSystem.AppleMacintosh, MediaType.CD, false, 20, null, new DICFlag[] { DICFlag.C2Opcode, DICFlag.NoFixSubQSecuROM, DICFlag.ScanFileProtect })]
[InlineData(KnownSystem.IBMPCCompatible, MediaType.DVD, true, 500, null, new DICFlag[] { DICFlag.CopyrightManagementInformation })]
[InlineData(KnownSystem.HDDVDVideo, MediaType.HDDVD, true, 500, null, new DICFlag[] { DICFlag.CopyrightManagementInformation })]
[InlineData(KnownSystem.IBMPCCompatible, MediaType.DVD, false, 500, null, new DICFlag[] { })]
[InlineData(KnownSystem.HDDVDVideo, MediaType.HDDVD, false, 500, null, new DICFlag[] { })]
/* reread c2 */
[InlineData(KnownSystem.SegaDreamcast, MediaType.GDROM, false, 1000, null, new DICFlag[] { DICFlag.C2Opcode })]
[InlineData(KnownSystem.SegaDreamcast, MediaType.GDROM, false, -1, null, new DICFlag[] { DICFlag.C2Opcode })]
public void ParametersFromOptionsTest(KnownSystem? knownSystem, MediaType? mediaType, bool paranoid, int rereadC2, int? subchannelLevel, DICFlag[] expected)
{
Parameters actual = new Parameters(knownSystem, mediaType, 'D', "disc.bin", 16, paranoid, rereadC2);
HashSet<DICFlag> expectedSet = new HashSet<DICFlag>(expected ?? new DICFlag[0]);
HashSet<DICFlag> actualSet = new HashSet<DICFlag>(actual.Keys ?? new DICFlag[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, null, null, null, null)]
[InlineData("", null, null, null, null)]
[InlineData("cd F test.bin 8 /c2 20", MediaType.CD, KnownSystem.IBMPCCompatible, "F", "test.bin")]
[InlineData("fd A blah\\test.img", MediaType.Floppy, KnownSystem.IBMPCCompatible, "A", "blah\\test.img")]
[InlineData("dvd X super\\blah\\test.iso 8 /raw", MediaType.GameCubeGameDisc, KnownSystem.NintendoGameCube, "X", "super\\blah\\test.iso")]
[InlineData("stop D", null, null, "D", null)]
public void DetermineFlagsTest(string parameters, MediaType? expectedMediaType, KnownSystem? expectedKnownSystem, string expectedDriveLetter, string expectedPath)
{
Parameters actualParams = new Parameters(parameters);
bool actual = actualParams.DetermineFlags(out MediaType? actualMediaType, out KnownSystem? actualKnownSystem, out string actualDriveLetter, out string actualPath);
Assert.Equal(expectedMediaType, actualMediaType);
Assert.Equal(expectedKnownSystem, actualKnownSystem);
Assert.Equal(expectedDriveLetter, actualDriveLetter);
Assert.Equal(expectedPath, actualPath);
}
[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", false)]
[InlineData("stop D", true)]
[InlineData("ls", false)]
public void ValidateParametersTest(string parameters, bool expected)
{
Parameters actual = new Parameters(parameters);
Assert.Equal(expected, actual.IsValid());
}
}
}

View 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.CD)]
[InlineData(KnownSystem.MicrosoftXBOX, MediaType.DVD)]
[InlineData(KnownSystem.NintendoGameCube, MediaType.GameCubeGameDisc)]
[InlineData(KnownSystem.NintendoWii, MediaType.WiiOpticalDisc)]
[InlineData(KnownSystem.NintendoWiiU, MediaType.WiiUOpticalDisc)]
[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);
}
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.CodeCoverage" version="15.8.0" targetFramework="net461" />
<package id="Microsoft.NET.Test.Sdk" version="15.8.0" targetFramework="net461" />
<package id="xunit" version="2.3.1" targetFramework="net461" />
<package id="xunit.abstractions" version="2.0.1" targetFramework="net461" />
<package id="xunit.analyzers" version="0.10.0" targetFramework="net461" />
<package id="xunit.assert" version="2.3.1" targetFramework="net461" />
<package id="xunit.core" version="2.3.1" targetFramework="net461" />
<package id="xunit.extensibility.core" version="2.3.1" targetFramework="net461" />
<package id="xunit.extensibility.execution" version="2.3.1" targetFramework="net461" />
<package id="xunit.runner.console" version="2.3.1" targetFramework="net461" developmentDependency="true" />
<package id="xunit.runner.visualstudio" version="2.3.1" targetFramework="net461" developmentDependency="true" />
</packages>

View File

@@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DICUI", "DICUI.csproj", "{7B1B75EB-8940-466F-BD51-76471A57F9BE}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DICUI", "DICUI\DICUI.csproj", "{7B1B75EB-8940-466F-BD51-76471A57F9BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DICUI.Test", "DICUI.Test\DICUI.Test.csproj", "{7CC064D2-38AB-4A05-8519-28660DE4562A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -15,6 +17,10 @@ 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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

14
DICUI/App.config Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="DICPath" value="Programs\DiscImageCreator.exe"/>
<add key="SubDumpPath" value="subdump.exe"/>
<add key="DefaultOutputPath" value="ISO"/>
<add key="preferredDumpSpeedCD" value="72"/>
<add key="preferredDumpSpeedDVD" value="24"/>
<add key="QuietMode" value="false"/>
<add key="RereadAmountForC2" value="20"/>
<add key="VerboseLogging" value="true"/>
<add key="OpenLogWindowAtStartup" value="true"/>
</appSettings>
</configuration>

View File

@@ -39,6 +39,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -66,9 +67,19 @@
</PropertyGroup>
<PropertyGroup />
<ItemGroup>
<Reference Include="BurnOutSharp, Version=1.3.7.1, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\BurnOutSharp.1.3.7.1\lib\net461\BurnOutSharp.dll</HintPath>
</Reference>
<Reference Include="LessIO, Version=0.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\LessIO.0.5.0\lib\net40\LessIO.dll</HintPath>
</Reference>
<Reference Include="libmspackn, Version=0.8.0.0, Culture=neutral, processorArchitecture=x86">
<HintPath>..\packages\libmspack4n.0.8.0\lib\net40\libmspackn.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Management.Instrumentation" />
<Reference Include="System.Windows.Forms" />
@@ -81,19 +92,42 @@
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="UnshieldSharp, Version=1.4.2.2, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\UnshieldSharp.1.4.2.2\lib\net461\UnshieldSharp.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="zlib.net, Version=1.0.3.0, Culture=neutral, PublicKeyToken=47d7877cb3620160">
<HintPath>..\packages\zlib.net.1.0.4.0\lib\zlib.net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Constants.cs" />
<Compile Include="Utilities\DumpInformation.cs" />
<Compile Include="Utilities\Validation.cs" />
<Compile Include="LogWindow.xaml.cs">
<DependentUpon>LogWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Data\Constants.cs" />
<Compile Include="Options.cs" />
<Compile Include="UI\KnownSystemComboBoxItem.cs" />
<Compile Include="UI\AllowedSpeeds.cs" />
<Compile Include="UI\ViewModels.cs" />
<Compile Include="Utilities\DumpEnvironment.cs" />
<Compile Include="Utilities\Extensions.cs" />
<Compile Include="Utilities\Parameters.cs" />
<Compile Include="Utilities\Result.cs" />
<Compile Include="Utilities\Validators.cs" />
<Compile Include="Utilities\Converters.cs" />
<Compile Include="OptionsWindow.xaml.cs">
<DependentUpon>OptionsWindow.xaml</DependentUpon>
</Compile>
<Page Include="LogWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -102,11 +136,15 @@
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Enumerations.cs" />
<Compile Include="Data\Enumerations.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="OptionsWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
@@ -115,6 +153,7 @@
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
@@ -131,5 +170,30 @@
<ItemGroup>
<Resource Include="Icon.ico" />
</ItemGroup>
<ItemGroup>
<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>
<Content Include="mspack.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -1,18 +1,21 @@
namespace DICUI
namespace DICUI.Data
{
/// <summary>
/// Text for UI elements
/// Variables for UI elements
/// </summary>
public static class UIElements
{
public const string DiscNotDetected = "Disc Not Detected";
public const string StartDumping = "Start Dumping";
public const string StopDumping = "Stop Dumping";
public const int LogWindowMarginFromMainWindow = 10;
}
/// <summary>
/// Top-level commands for DiscImageCreator
/// </summary>
public static class DICCommands
public static class DICCommandStrings
{
public const string Audio = "audio";
public const string BluRay = "bd";
@@ -36,13 +39,13 @@
/// <summary>
/// Dumping flags for DiscImageCreator
/// </summary>
public static class DICFlags
public static class DICFlagStrings
{
public const string AddOffset = "/a";
public const string AMSF = "/p";
public const string BEOpcode = "/be";
public const string C2Opcode = "/c2";
public const string CMI = "/c";
public const string CopyrightManagementInformation = "/c";
public const string D8Opcode = "/d8";
public const string DisableBeep = "/q";
public const string ForceUnitAccess = "/f";
@@ -72,6 +75,8 @@
public const string TitleField = "Title";
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";
@@ -95,19 +100,19 @@
public const string DATField = "DAT";
public const string ErrorCountField = "Error Count";
public const string CuesheetField = "Cuesheet";
public const string SubIntentionField = "SubIntention (SecuROM)";
public const string WriteOffsetField = "WriteOffset";
public const string SubIntentionField = "SubIntention Data (SecuROM/LibCrypt)";
public const string WriteOffsetField = "Write Offset";
public const string LayerbreakField = "Layerbreak";
public const string PlaystationEXEDateField = "EXE Date";
public const string PlayStationEDCField = "EDC"; // TODO: Not automatic yet
public const string PlayStationAntiModchipField = "Anti-modchip"; // TODO: Not automatic yet
public const string PlayStationLibCryptField = "LibCrypt"; // TODO: Not automatic yet
public const string PlayStationEDCField = "EDC";
public const string PlayStationAntiModchipField = "Anti-modchip";
public const string PlayStationLibCryptField = "LibCrypt";
public const string SaturnHeaderField = "Header";
public const string SaturnBuildDateField = "Build Date";
public const string XBOXDMICRC = "DMI.bin CRC32"; // TODO: Not automatic yet
public const string XBOXPFICRC = "PFI.bin CRC32"; // TODO: Not automatic yet
public const string XBOXSSCRC = "SS.bin CRC32"; // TODO: Not automatic yet
public const string XBOXSSRanges = "Security Sector Ranges"; // TODO: Not automatic yet
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";
// Default values

View File

@@ -1,33 +1,63 @@
namespace DICUI
namespace DICUI.Data
{
/// <summary>
/// Known disc types
/// Supported DIC commands
/// </summary>
public enum DiscType
public enum DICCommand
{
NONE = 0,
CD,
DVD5,
DVD9,
Audio,
BluRay,
Close,
CompactDisc,
Data,
DigitalVideoDisc,
DriveSpeed,
Eject,
Floppy,
GDROM,
HDDVD,
BD25,
BD50,
MDS,
Reset,
Start,
Stop,
Sub,
Swap,
XBOX,
}
// Special Formats
GameCubeGameDisc,
WiiOpticalDisc,
WiiUOpticalDisc,
UMD,
// Keeping this separate since it's currently unsupported in the UI
Floppy = 99,
/// <summary>
/// Supported DIC flags
/// </summary>
public enum DICFlag
{
NONE = 0,
AddOffset,
AMSF,
BEOpcode,
C2Opcode,
CopyrightManagementInformation,
D8Opcode,
DisableBeep,
ForceUnitAccess,
MCN,
MultiSession,
NoFixSubP,
NoFixSubQ,
NoFixSubQLibCrypt,
NoFixSubQSecuROM,
NoFixSubRtoW,
Raw,
Reverse,
ScanAntiMod,
ScanFileProtect,
ScanSectorProtect,
SeventyFour,
SubchannelReadLevel,
}
/// <summary>
/// Known systems
/// </summary>
/// <remarks>Ensure that Utilities methods are updated as well</remarks>
public enum KnownSystem
{
NONE = 0,
@@ -40,7 +70,8 @@
CommodoreAmigaCDTV,
MattelHyperscan,
MicrosoftXBOX,
MicrosoftXBOX360,
MicrosoftXBOX360XDG2,
MicrosoftXBOX360XDG3,
MicrosoftXBOXOne,
NECPCEngineTurboGrafxCD,
NECPCFX,
@@ -62,6 +93,8 @@
VTechVFlashVSmilePro,
ZAPiTGamesGameWaveFamilyEntertainmentSystem,
MarkerConsoleEnd,
#endregion
#region Computers
@@ -75,6 +108,8 @@
NECPC98,
SharpX68000,
MarkerComputerEnd,
#endregion
#region Arcade
@@ -92,6 +127,7 @@
ICEPCHardware,
IncredibleTechnologiesEagle,
IncredibleTechnologiesVarious,
KonamieAmusement,
KonamiFirebeat,
KonamiGVSystem,
KonamiM2,
@@ -133,6 +169,8 @@
TandyMemorexVisualInformationSystem,
TsunamiTsuMoMultiGameMotionSystem,
MarkerArcadeEnd,
#endregion
#region Other
@@ -141,14 +179,61 @@
BDVideo,
DVDVideo,
EnhancedCD,
EnhancedDVD,
EnhancedBD,
HDDVDVideo,
PalmOS,
PhilipsCDiDigitalVideo,
PhotoCD,
PlayStationGameSharkUpdates,
RainbowDisc,
TaoiKTV,
TomyKissSite,
VideoCD,
MarkerOtherEnd,
#endregion
Custom,
}
/// <summary>
/// Known system category
/// </summary>
public enum KnownSystemCategory
{
Console = 0,
Computer,
Arcade,
Other,
Custom
};
/// <summary>
/// Known media types
/// </summary>
public enum MediaType
{
// Generic Optical Formats
NONE = 0,
CD,
DVD,
GDROM,
HDDVD,
BluRay,
LaserDisc,
// Special Optical Formats
GameCubeGameDisc,
WiiOpticalDisc,
WiiUOpticalDisc,
UMD,
// Non-Optical Formats
Floppy,
Cartridge,
Cassette,
CED,
}
}

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

54
DICUI/LogWindow.xaml Normal file
View File

@@ -0,0 +1,54 @@
<Window x:Class="DICUI.LogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lui="clr-namespace:DICUI.UI"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
Title="Log Window" Height="350" Width="600" Closed="OnWindowClosed" Loaded="OnWindowLoaded"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Height="22" Margin="10 10 10 0">
<ProgressBar x:Name="progressBar" />
<TextBlock x:Name="progressLabel" Grid.Row="0" Height="22" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="0 2 0 0" />
</Grid>
<Border Grid.Row="1" Background="White" BorderBrush="Gainsboro" BorderThickness="1" Margin="10">
<ScrollViewer Name="outputViewer" SizeChanged="ScrollViewer_SizeChanged">
<RichTextBox Name="output" FontFamily="Consolas" Background="#202020" IsReadOnly="true" TextChanged="OnTextChanged" />
</ScrollViewer>
</Border>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition Width="4*"/>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox Content="Verbose" Margin="10 0 0 10" Grid.Column="0" VerticalAlignment="Center"
ToolTip="Enable verbose logging of tasks"
DataContext="{Binding Source={x:Static lui:ViewModels.OptionsViewModel}}"
IsChecked="{Binding Path=VerboseLogging}"
/>
<CheckBox Content="Open at startup" Margin="10 0 0 10" Grid.Column="1" Grid.ColumnSpan="2" VerticalAlignment="Center"
ToolTip="Open this window at startup"
DataContext="{Binding Source={x:Static lui:ViewModels.OptionsViewModel}}"
IsChecked="{Binding Path=OpenLogWindowAtStartup}"
/>
<Button Margin="0 0 10 10" Grid.Column="3" Height="22" Width="60" Content="Clear" HorizontalAlignment="Right" Click="OnClearButton" />
<Button Margin="0 0 10 10" Grid.Column="4" Height="22" Width="60" Content="Hide" HorizontalAlignment="Right" Click="OnHideButton" />
<Button Visibility="Hidden" Name="AbortButton" Margin="0 0 10 10" Grid.Column="2" Height="22" Width="80" Content="Abort" HorizontalAlignment="Right" Click="OnAbortButton" />
</Grid>
</Grid>
</Window>

387
DICUI/LogWindow.xaml.cs Normal file
View File

@@ -0,0 +1,387 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Interop;
using System.Windows.Media;
using DICUI.Data;
using DICUI.UI;
namespace DICUI
{
public partial class LogWindow : Window
{
private const int GWL_STYLE = -16;
private const int WS_SYSMENU = 0x80000;
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
private MainWindow _mainWindow;
private FlowDocument _document;
private Paragraph _paragraph;
private List<Matcher> _matchers;
volatile Process _process;
public LogWindow(MainWindow mainWindow)
{
InitializeComponent();
this._mainWindow = mainWindow;
_document = new FlowDocument();
_paragraph = new Paragraph();
_document.Blocks.Add(_paragraph);
output.Document = _document;
_matchers = new List<Matcher>();
_matchers.Add(new Matcher(
"Descrambling data sector of img (LBA)",
@"\s*(\d+)\/\s*(\d+)$",
match => {
if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total))
{
float percentProgress = (current / (float)total) * 100;
progressBar.Value = percentProgress;
progressLabel.Text = string.Format("Descrambling image.. ({0:##.##}%)", percentProgress);
}
}));
_matchers.Add(new Matcher(
@"Creating .scm (LBA)",
@"\s*(\d+)\/\s*(\d+)$",
match => {
if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total))
{
float percentProgress = (current / (float)total) * 100;
progressBar.Value = percentProgress;
progressLabel.Text = string.Format("Creating scrambled image.. ({0:##.##}%)", percentProgress);
}
}));
_matchers.Add(new Matcher(
"Checking sectors (LBA)",
@"\s*(\d+)\/\s*(\d+)$",
match => {
if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total))
{
float percentProgress = (current / (float)total) * 100;
progressBar.Value = percentProgress;
progressLabel.Text = string.Format("Checking for errors.. ({0:##.##}%)", percentProgress);
}
}));
_matchers.Add(new Matcher(
"Scanning sector (LBA)",
@"\s*(\d+)\/\s*(\d+)$",
match => {
if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total))
{
float percentProgress = (current / (float)total) * 100;
progressBar.Value = percentProgress;
progressLabel.Text = string.Format("Scanning sectors for protection.. ({0:##.##}%)", percentProgress);
}
}));
}
public void StartDump(string args)
{
AppendToTextBox(string.Format("Launching DIC with args: {0}\r\n", args), Brushes.Orange);
Task.Run(() =>
{
_process = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = @"Programs/DiscImageCreator.exe",
Arguments = args,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
},
};
StreamState stdoutState = new StreamState(false);
StreamState stderrState = new StreamState(true);
//_cmd.ErrorDataReceived += (process, text) => Dispatcher.Invoke(() => UpdateConsole(text.Data, Brushes.Red));
_process.Start();
var _1 = ConsumeOutput(_process.StandardOutput, s => Dispatcher.Invoke(() => UpdateConsole(s, stdoutState)));
var _2 = ConsumeOutput(_process.StandardError, s => Dispatcher.Invoke(() => UpdateConsole(s, stderrState)));
_process.EnableRaisingEvents = true;
_process.Exited += OnProcessExit;
});
}
public void AdjustPositionToMainWindow()
{
this.Left = _mainWindow.Left;
this.Top = _mainWindow.Top + _mainWindow.Height + UIElements.LogWindowMarginFromMainWindow;
}
private void GracefullyTerminateProcess()
{
if (_process != null)
{
_process.Exited -= OnProcessExit;
bool isForced = !_process.HasExited;
if (isForced)
{
AppendToTextBox("\r\nForcefully Killing the process\r\n", Brushes.Red);
_process.Kill();
_process.WaitForExit();
}
AppendToTextBox(string.Format("\r\nExit Code: {0}\r\n", _process.ExitCode), _process.ExitCode == 0 ? Brushes.Green : Brushes.Red);
if (_process.ExitCode == 0)
{
Dispatcher.Invoke(() =>
{
progressLabel.Text = "Done!";
progressBar.Value = 100;
progressBar.Foreground = Brushes.Green;
});
}
else
{
Dispatcher.Invoke(() =>
{
progressLabel.Text = isForced ? "Aborted by user" : "Error, please check log!";
progressBar.Value = 100;
progressBar.Foreground = Brushes.Red;
});
}
_process.Close();
}
_process = null;
}
private void ScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
{
outputViewer.ScrollToBottom();
}
async Task ConsumeOutput(TextReader reader, Action<string> callback)
{
char[] buffer = new char[256];
int cch;
while ((cch = await reader.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
callback(new string(buffer, 0, cch));
}
}
// this is used to optimize the work since we need to process A LOT of text
struct Matcher
{
private readonly String prefix;
private readonly Regex regex;
private readonly int start;
private readonly Action<Match> lambda;
public Matcher(String prefix, String regex, Action<Match> lambda)
{
this.prefix = prefix;
this.regex = new Regex(regex);
this.start = prefix.Length;
this.lambda = lambda;
}
public bool Matches(ref string text) => text.StartsWith(prefix);
public void Apply(ref string text)
{
Match match = regex.Match(text, start);
lambda.Invoke(match);
}
}
private void ProcessStringForProgressBar(string text)
{
foreach (Matcher matcher in _matchers)
{
if (matcher.Matches(ref text))
{
matcher.Apply(ref text);
return;
}
}
}
class StreamState
{
public enum State
{
BEGIN,
READ_CARRIAGE,
};
public State state;
public readonly StringBuilder buffer;
public readonly bool isError;
public StreamState(bool isError)
{
this.state = State.BEGIN;
this.buffer = new StringBuilder();
this.isError = isError;
}
public bool HasData() => buffer.Length > 0;
public string Fetch() => buffer.ToString();
public void Clear() => buffer.Clear();
public void Append(char c) => buffer.Append(c);
public bool Is(State state) => this.state == state;
public void Set(State state) => this.state = state;
}
public void AppendToTextBox(string text, Brush color)
{
if (Application.Current.Dispatcher.CheckAccess())
{
Run run = new Run(text) { Foreground = color };
_paragraph.Inlines.Add(run);
}
else
Dispatcher.Invoke(() =>
{
Run run = new Run(text) { Foreground = color };
_paragraph.Inlines.Add(run);
});
}
private void UpdateConsole(string text, StreamState state)
{
/*if (c == '\r') { output.Inlines.Add(@"\r"); file.Write("\\r"); }
else if (c == '\n') { output.Inlines.Add(@"\n"); file.Write("\\n\n"); }
output.Inlines.Add(""+c);
file.Write(c);
file.Flush();
continue;*/
if (text != null)
{
foreach (char c in text)
{
switch (c)
{
case '\r' when (state.Is(StreamState.State.BEGIN)):
{
state.Set(StreamState.State.READ_CARRIAGE);
break;
}
case '\n' when (state.Is(StreamState.State.READ_CARRIAGE)):
{
if (state.buffer.Length > 0)
{
string buffer = state.Fetch();
AppendToTextBox(buffer, state.isError ? Brushes.Red : Brushes.White);
if (!state.isError)
ProcessStringForProgressBar(buffer);
}
_paragraph.Inlines.Add(new LineBreak());
state.Clear();
state.Set(StreamState.State.BEGIN);
break;
}
default:
if (state.Is(StreamState.State.READ_CARRIAGE) && state.HasData())
{
if (!(_paragraph.Inlines.LastInline is LineBreak))
_paragraph.Inlines.Remove(_paragraph.Inlines.LastInline);
string buffer = state.Fetch();
AppendToTextBox(buffer, state.isError ? Brushes.Red : Brushes.White);
if (!state.isError)
ProcessStringForProgressBar(buffer);
state.Clear();
}
state.Set(StreamState.State.BEGIN);
state.Append(c);
break;
}
}
}
}
#region EventHandlers
private void OnWindowClosed(object sender, EventArgs e)
{
GracefullyTerminateProcess();
}
private void OnWindowLoaded(object sender, EventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
}
void OnProcessExit(object sender, EventArgs e)
{
Dispatcher.Invoke(() => AbortButton.IsEnabled = false);
GracefullyTerminateProcess();
}
private void OnHideButton(object sender, EventArgs e)
{
ViewModels.LoggerViewModel.WindowVisible = false;
//TODO: this should be bound directly to WindowVisible property in two way fashion
// we need to study how to properly do it in XAML
_mainWindow.ShowLogMenuItem.IsChecked = false;
}
private void OnClearButton(object sender, EventArgs e)
{
output.Document.Blocks.Clear();
}
private void OnAbortButton(object sender, EventArgs args)
{
GracefullyTerminateProcess();
}
private void OnStartButton(object sender, EventArgs args)
{
StartDump("cd e Gam.iso 16");
}
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
outputViewer.ScrollToBottom();
}
#endregion
}
}

131
DICUI/MainWindow.xaml Normal file
View File

@@ -0,0 +1,131 @@
<Window x:Class="DICUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DICUI"
xmlns:lui="clr-namespace:DICUI.UI"
xmlns:utilities="clr-namespace:DICUI.Utilities"
mc:Ignorable="d"
Title="Disc Image Creator GUI" Height="450" Width="600" WindowStartupLocation="CenterScreen" ResizeMode="CanMinimize"
LocationChanged="MainWindowLocationChanged" Activated="MainWindowActivated" Closing="MainWindowClosing">
<Window.Resources>
<utilities:EnumDescriptionConverter x:Key="enumConverter" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"/>
<ColumnDefinition Width="13*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="4*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<StackPanel VerticalAlignment="Top" Grid.ColumnSpan="4">
<Menu Width="Auto" Height="20" >
<MenuItem Header="_File">
<MenuItem x:Name="AppExit" Header="E_xit" HorizontalAlignment="Left" Width="140" Click="AppExitClick" />
</MenuItem>
<MenuItem Header="_Tools">
<MenuItem x:Name="OptionsMenuItem" Header="_Options" HorizontalAlignment="Left" Width="140" Click="OptionsClick"/>
<MenuItem x:Name="ShowLogMenuItem" Header="Show _Log Window" IsCheckable="true" HorizontalAlignment="Left"
DataContext="{Binding Source={x:Static lui:ViewModels.LoggerViewModel}}"
IsChecked="{Binding Path=WindowVisible}"
/>
</MenuItem>
<MenuItem Header="_Help">
<MenuItem x:Name="About" Header="_About" HorizontalAlignment="Left" Width="140" Click="AboutClick"/>
</MenuItem>
</Menu>
</StackPanel>
<GroupBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,5,5.2,5.4" HorizontalAlignment="Stretch" Header="Settings"/>
<GroupBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,4.6,5.2,4.8" HorizontalAlignment="Stretch" Header="Controls"/>
<GroupBox Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,5.2,5.2,4.8" HorizontalAlignment="Stretch" Header="Status"/>
<Grid Grid.Row="1" Grid.Column="0" Margin="15,25,15.2,10.4" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2.5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Content="System/Media Type" />
<ComboBox x:Name="SystemTypeComboBox" Grid.Row="0" Grid.Column="1" Height="22" Width="250" HorizontalAlignment="left" SelectionChanged="SystemTypeComboBoxSelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" Foreground="{Binding Path=Foreground}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ComboBox x:Name="MediaTypeComboBox" Grid.Row="0" Grid.Column="1" Height="22" Width="140" HorizontalAlignment="right" SelectionChanged="MediaTypeComboBoxSelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource enumConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center">Output Filename</Label>
<TextBox x:Name="OutputFilenameTextBox" Grid.Row="1" Grid.Column="1" Height="22" TextChanged="OutputFilenameTextBoxTextChanged" />
<Label Grid.Row="2" Grid.Column="0" VerticalAlignment="Center">Output Directory</Label>
<TextBox x:Name="OutputDirectoryTextBox" Grid.Row="2" Grid.Column="1" Height="22" Width="345" HorizontalAlignment="left" TextChanged="OutputDirectoryTextBoxTextChanged" />
<Button x:Name="OutputDirectoryBrowseButton" Grid.Row="2" Grid.Column="1" Height="22" Width="50" HorizontalAlignment="Right" Content="Browse" Click="OutputDirectoryBrowseButtonClick"/>
<Label Grid.Row="3" Grid.Column="0" VerticalAlignment="Center">Drive Letter</Label>
<ComboBox x:Name="DriveLetterComboBox" Grid.Row="3" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="left" SelectionChanged="DriveLetterComboBoxSelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Letter}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Label Grid.Row="4" Grid.Column="0" VerticalAlignment="Center">Drive Speed</Label>
<ComboBox x:Name="DriveSpeedComboBox" Grid.Row="4" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="left" SelectionChanged="DriveSpeedComboBoxSelectionChanged" />
<Label Grid.Row="5" Grid.Column="0" VerticalAlignment="Center">Parameters</Label>
<TextBox x:Name="ParametersTextBox" Grid.Row="5" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" IsEnabled="False" />
</Grid>
<Grid Grid.Row="2" Grid.Column="0" Margin="15,19.6,15.2,9.8" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Button x:Name="StartStopButton" Grid.Row="0" Grid.Column="0" Height="22" Width="125" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Start Dumping" Click="StartStopButtonClick" IsEnabled="False" />
<Button x:Name="DiskScanButton" Grid.Row="0" Grid.Column="1" Height="22" Width="125" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Scan for disks" Click="DiskScanButtonClick" />
<Button x:Name="CopyProtectScanButton" Grid.Row="0" Grid.Column="2" Height="22" Width="125" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Scan for protection" Click="CopyProtectScanButtonClick" />
<CheckBox x:Name="EjectWhenDoneCheckBox" Grid.Row="0" Grid.Column="3" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Eject When Done" IsChecked="False" />
</Grid>
<Grid Grid.Row="3" Grid.Column="0" Margin="15,20.2,15.2,9.8" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Label x:Name="StatusLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Waiting for CD or DVD..." />
</Grid>
</Grid>
</Window>

596
DICUI/MainWindow.xaml.cs Normal file
View File

@@ -0,0 +1,596 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using WinForms = System.Windows.Forms;
using DICUI.Data;
using DICUI.Utilities;
using DICUI.UI;
namespace DICUI
{
public partial class MainWindow : Window
{
// Private UI-related variables
private List<Drive> _drives;
private MediaType? _currentMediaType;
private List<KnownSystem?> _systems;
private List<MediaType?> _mediaTypes;
private bool _alreadyShown;
private DumpEnvironment _env;
// Option related
private Options _options;
private OptionsWindow _optionsWindow;
private LogWindow _logWindow;
public MainWindow()
{
InitializeComponent();
// Initializes and load Options object
_options = new Options();
_options.Load();
ViewModels.OptionsViewModel = new OptionsViewModel(_options);
_logWindow = new LogWindow(this);
ViewModels.LoggerViewModel.SetWindow(_logWindow);
// Disable buttons until we load fully
StartStopButton.IsEnabled = false;
DiskScanButton.IsEnabled = false;
CopyProtectScanButton.IsEnabled = false;
if (_options.OpenLogWindowAtStartup)
{
this.WindowStartupLocation = WindowStartupLocation.Manual;
double combinedHeight = this.Height + _logWindow.Height + UIElements.LogWindowMarginFromMainWindow;
Rectangle bounds = GetScaledCoordinates(WinForms.Screen.PrimaryScreen.WorkingArea);
this.Left = bounds.Left + (bounds.Width - this.Width) / 2;
this.Top = bounds.Top + (bounds.Height - combinedHeight) / 2;
}
}
#region Events
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
if (_alreadyShown)
return;
_alreadyShown = true;
if (_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
ShowLogMenuItem.IsChecked = true;
ViewModels.LoggerViewModel.WindowVisible = true;
}
// Populate the list of systems
StatusLabel.Content = "Creating system list, please wait!";
PopulateSystems();
// Populate the list of drives
StatusLabel.Content = "Creating drive list, please wait!";
PopulateDrives();
}
private void StartStopButtonClick(object sender, RoutedEventArgs e)
{
// Dump or stop the dump
if ((string)StartStopButton.Content == UIElements.StartDumping)
{
StartDumping();
}
else if ((string)StartStopButton.Content == UIElements.StopDumping)
{
_env.CancelDumping();
CopyProtectScanButton.IsEnabled = true;
if (EjectWhenDoneCheckBox.IsChecked == true)
_env.EjectDisc();
}
}
private void OutputDirectoryBrowseButtonClick(object sender, RoutedEventArgs e)
{
BrowseFolder();
EnsureDiscInformation();
}
private void DiskScanButtonClick(object sender, RoutedEventArgs e)
{
PopulateDrives();
}
private void CopyProtectScanButtonClick(object sender, RoutedEventArgs e)
{
ScanAndShowProtection();
}
private void SystemTypeComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
{
// If we're on a separator, go to the next item and return
if ((SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem).IsHeader())
{
SystemTypeComboBox.SelectedIndex++;
return;
}
ViewModels.LoggerViewModel.VerboseLogLn("Changed system to: {0}", (SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem).Name);
PopulateMediaType();
EnsureDiscInformation();
}
private void MediaTypeComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Only change the media type if the selection and not the list has changed
if (e.RemovedItems.Count == 1 && e.AddedItems.Count == 1)
{
_currentMediaType = MediaTypeComboBox.SelectedItem as MediaType?;
SetSupportedDriveSpeed();
}
GetOutputNames();
EnsureDiscInformation();
}
private void DriveLetterComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
{
CacheCurrentDiscType();
SetCurrentDiscType();
GetOutputNames();
SetSupportedDriveSpeed();
}
private void DriveSpeedComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
{
EnsureDiscInformation();
}
private void OutputFilenameTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
EnsureDiscInformation();
}
private void OutputDirectoryTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
EnsureDiscInformation();
}
private void ProgressUpdated(object sender, Result value)
{
StatusLabel.Content = value.Message;
ViewModels.LoggerViewModel.VerboseLogLn(value.Message);
}
private void MainWindowLocationChanged(object sender, EventArgs e)
{
if (_logWindow.IsVisible)
_logWindow.AdjustPositionToMainWindow();
}
private void MainWindowActivated(object sender, EventArgs e)
{
if (_logWindow.IsVisible && !this.Topmost)
{
_logWindow.Topmost = true;
_logWindow.Topmost = false;
}
}
private void MainWindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (_logWindow.IsVisible)
_logWindow.Close();
}
// Toolbar Events
private void AppExitClick(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void AboutClick(object sender, RoutedEventArgs e)
{
MessageBox.Show($"ReignStumble - Project Lead / UI Design{Environment.NewLine}" +
$"darksabre76 - Project Co-Lead / Backend Design{Environment.NewLine}" +
$"Jakz - Feature Contributor{Environment.NewLine}" +
$"NHellFire - Feature Contributor{Environment.NewLine}" +
$"Dizzzy - Concept/Ideas/Beta tester{Environment.NewLine}", "About", MessageBoxButton.OK, MessageBoxImage.Information);
}
private void OptionsClick(object sender, RoutedEventArgs e)
{
// lazy initialization
if (_optionsWindow == null)
{
_optionsWindow = new OptionsWindow(this, _options);
_optionsWindow.Closed += delegate
{
_optionsWindow = null;
};
}
_optionsWindow.Owner = this;
_optionsWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
_optionsWindow.Refresh();
_optionsWindow.Show();
}
public void OnOptionsUpdated()
{
GetOutputNames();
SetSupportedDriveSpeed();
EnsureDiscInformation();
}
#endregion
#region Helpers
/// <summary>
/// Populate media type according to system type
/// </summary>
private void PopulateMediaType()
{
KnownSystem? currentSystem = SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem;
if (currentSystem != null)
{
_mediaTypes = Validators.GetValidMediaTypes(currentSystem).ToList();
MediaTypeComboBox.ItemsSource = _mediaTypes;
MediaTypeComboBox.IsEnabled = _mediaTypes.Count > 1;
MediaTypeComboBox.SelectedIndex = (_mediaTypes.IndexOf(_currentMediaType) >= 0 ? _mediaTypes.IndexOf(_currentMediaType) : 0);
}
else
{
MediaTypeComboBox.IsEnabled = false;
MediaTypeComboBox.ItemsSource = null;
MediaTypeComboBox.SelectedIndex = -1;
}
}
/// <summary>
/// Get a complete list of supported systems and fill the combo box
/// </summary>
private void PopulateSystems()
{
_systems = Validators.CreateListOfSystems();
ViewModels.LoggerViewModel.VerboseLogLn("Populating systems, {0} systems found.", _systems.Count);
Dictionary<KnownSystemCategory, List<KnownSystem?>> mapping = _systems
.GroupBy(s => s.Category())
.ToDictionary(
k => k.Key,
v => v
.OrderBy(s => s.Name())
.ToList()
);
List<KnownSystemComboBoxItem> comboBoxItems = new List<KnownSystemComboBoxItem>();
comboBoxItems.Add(new KnownSystemComboBoxItem(KnownSystem.NONE));
foreach (var group in mapping)
{
comboBoxItems.Add(new KnownSystemComboBoxItem(group.Key));
group.Value.ForEach(system => comboBoxItems.Add(new KnownSystemComboBoxItem(system)));
}
SystemTypeComboBox.ItemsSource = comboBoxItems;
SystemTypeComboBox.SelectedIndex = 0;
StartStopButton.IsEnabled = false;
}
/// <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
DiskScanButton.IsEnabled = true;
// Populate the list of drives and add it to the combo box
_drives = Validators.CreateListOfDrives();
DriveLetterComboBox.ItemsSource = _drives;
if (DriveLetterComboBox.Items.Count > 0)
{
int index = _drives.FindIndex(d => d.MarkedActive);
DriveLetterComboBox.SelectedIndex = (index != -1 ? index : 0);
StatusLabel.Content = "Valid drive found! Choose your Media Type";
StartStopButton.IsEnabled = true;
CopyProtectScanButton.IsEnabled = true;
ViewModels.LoggerViewModel.VerboseLogLn("Found {0} drives: {1}", _drives.Count, String.Join(", ", _drives.Select(d => d.Letter)));
}
else
{
DriveLetterComboBox.SelectedIndex = -1;
StatusLabel.Content = "No valid drive found!";
StartStopButton.IsEnabled = false;
CopyProtectScanButton.IsEnabled = false;
ViewModels.LoggerViewModel.VerboseLogLn("Found no drives");
}
}
/// <summary>
/// Browse for an output folder
/// </summary>
private void BrowseFolder()
{
WinForms.FolderBrowserDialog folderDialog = new WinForms.FolderBrowserDialog { ShowNewFolderButton = false, SelectedPath = System.AppDomain.CurrentDomain.BaseDirectory };
WinForms.DialogResult result = folderDialog.ShowDialog();
if (result == WinForms.DialogResult.OK)
{
OutputDirectoryTextBox.Text = folderDialog.SelectedPath;
}
}
/// <summary>
/// Create a DumpEnvironment with all current settings
/// </summary>
/// <returns>Filled DumpEnvironment instance</returns>
private DumpEnvironment DetermineEnvironment()
{
return new DumpEnvironment()
{
// Paths to tools
SubdumpPath = _options.SubDumpPath,
DICPath = _options.DICPath,
OutputDirectory = OutputDirectoryTextBox.Text,
OutputFilename = OutputFilenameTextBox.Text,
// Get the currently selected options
Drive = DriveLetterComboBox.SelectedItem as Drive,
DICParameters = new Parameters(ParametersTextBox.Text),
QuietMode = _options.QuietMode,
ParanoidMode = _options.ParanoidMode,
ScanForProtection = _options.ScanForProtection,
RereadAmountC2 = _options.RereadAmountForC2,
System = SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem,
Type = MediaTypeComboBox.SelectedItem as MediaType?
};
}
/// <summary>
/// Begin the dumping process using the given inputs
/// </summary>
private async void StartDumping()
{
_env = DetermineEnvironment();
// Check for the firmware first
// TODO: Remove this (and method) once DIC end-to-end logging becomes a thing
if (!await _env.DriveHasLatestFimrware())
return;
StartStopButton.Content = UIElements.StopDumping;
CopyProtectScanButton.IsEnabled = false;
StatusLabel.Content = "Beginning dumping process";
ViewModels.LoggerViewModel.VerboseLogLn("Starting dumping process..");
var progress = new Progress<Result>();
progress.ProgressChanged += ProgressUpdated;
Result result = await _env.StartDumping(progress);
StatusLabel.Content = result ? "Dumping complete!" : result.Message;
ViewModels.LoggerViewModel.VerboseLogLn(result ? "Dumping complete!" : result.Message);
StartStopButton.Content = UIElements.StartDumping;
CopyProtectScanButton.IsEnabled = true;
if (EjectWhenDoneCheckBox.IsChecked == true)
_env.EjectDisc();
}
/// <summary>
/// Ensure information is consistent with the currently selected disc type
/// </summary>
private void EnsureDiscInformation()
{
// Get the current environment information
_env = DetermineEnvironment();
// Take care of null cases
if (_env.System == null)
_env.System = KnownSystem.NONE;
if (_env.Type == null)
_env.Type = MediaType.NONE;
// Get the status to write out
Result result = Validators.GetSupportStatus(_env.System, _env.Type);
StatusLabel.Content = result.Message;
// Set the index for the current disc type
SetCurrentDiscType();
StartStopButton.IsEnabled = result && (_drives != null && _drives.Count > 0 ? true : false);
// If we're in a type that doesn't support drive speeds
DriveSpeedComboBox.IsEnabled = _env.Type.DoesSupportDriveSpeed() && _env.System.DoesSupportDriveSpeed();
// Special case for Custom input
if (_env.System == KnownSystem.Custom)
{
ParametersTextBox.IsEnabled = true;
OutputFilenameTextBox.IsEnabled = false;
OutputDirectoryTextBox.IsEnabled = false;
OutputDirectoryBrowseButton.IsEnabled = false;
DriveLetterComboBox.IsEnabled = false;
DriveSpeedComboBox.IsEnabled = false;
StartStopButton.IsEnabled = (_drives.Count > 0 ? true : false);
StatusLabel.Content = "User input mode";
}
else
{
ParametersTextBox.IsEnabled = false;
OutputFilenameTextBox.IsEnabled = true;
OutputDirectoryTextBox.IsEnabled = true;
OutputDirectoryBrowseButton.IsEnabled = true;
DriveLetterComboBox.IsEnabled = true;
// Generate the full parameters from the environment
string generated = _env.GetFullParameters((int?)DriveSpeedComboBox.SelectedItem);
if (generated != null)
ParametersTextBox.Text = generated;
}
}
/// <summary>
/// Get the default output directory name from the currently selected drive
/// </summary>
private void GetOutputNames()
{
Drive drive = DriveLetterComboBox.SelectedItem as Drive;
KnownSystem? systemType = SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem;
MediaType? mediaType = MediaTypeComboBox.SelectedItem as MediaType?;
OutputDirectoryTextBox.Text = Path.Combine(_options.DefaultOutputPath, drive?.VolumeLabel ?? string.Empty);
OutputFilenameTextBox.Text = (drive?.VolumeLabel ?? "disc") + (mediaType.Extension() ?? ".bin");
}
/// <summary>
/// Scan and show copy protection for the current disc
/// </summary>
private async void ScanAndShowProtection()
{
var env = DetermineEnvironment();
if (env.Drive.Letter != default(char))
{
ViewModels.LoggerViewModel.VerboseLogLn("Scanning for copy protection in {0}", _env.Drive.Letter);
var tempContent = StatusLabel.Content;
StatusLabel.Content = "Scanning for copy protection... this might take a while!";
StartStopButton.IsEnabled = false;
DiskScanButton.IsEnabled = false;
CopyProtectScanButton.IsEnabled = false;
string protections = await Validators.RunProtectionScanOnPath(env.Drive.Letter + ":\\");
if (!ViewModels.LoggerViewModel.WindowVisible)
MessageBox.Show(protections, "Detected Protection", MessageBoxButton.OK, MessageBoxImage.Information);
ViewModels.LoggerViewModel.VerboseLog("Detected the following protections in {0}:\r\n\r\n{1}", env.Drive.Letter, protections);
StatusLabel.Content = tempContent;
StartStopButton.IsEnabled = true;
DiskScanButton.IsEnabled = true;
CopyProtectScanButton.IsEnabled = true;
}
}
/// <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 = AllowedSpeeds.GetForMediaType(_currentMediaType);
DriveSpeedComboBox.ItemsSource = values;
ViewModels.LoggerViewModel.VerboseLogLn("Supported media speeds: {0}", string.Join(",", values));
// Choose the lower of the two speeds between the allowed speeds and the user-defined one
int chosenSpeed = Math.Min(
values.Where(s => s <= values[values.Count / 2]).Last(),
_options.preferredDumpSpeedCD
);
// Set the selected speed
ViewModels.LoggerViewModel.VerboseLogLn("Setting drive speed to: {0}", chosenSpeed);
DriveSpeedComboBox.SelectedValue = chosenSpeed;
}
/// <summary>
/// Cache the current disc type to internal variable
/// </summary>
private void CacheCurrentDiscType()
{
// Get the drive letter from the selected item
Drive drive = DriveLetterComboBox.SelectedItem as Drive;
if (drive == null || drive.IsFloppy)
return;
// Get the current optical disc type
if (!_options.SkipMediaTypeDetection)
{
ViewModels.LoggerViewModel.VerboseLog("Trying to detect media type for drive {0}.. ", drive.Letter);
_currentMediaType = Validators.GetDiscType(drive.Letter);
ViewModels.LoggerViewModel.VerboseLogLn(_currentMediaType != null ? "unable to detect." : ("detected " + _currentMediaType.Name() + "."));
}
}
/// <summary>
/// Set the current disc type in the combo box
/// </summary>
private void SetCurrentDiscType()
{
// If we have an invalid current type, we don't care and return
if (_currentMediaType == null || _currentMediaType == MediaType.NONE)
return;
// Now set the selected item, if possible
int index = _mediaTypes.FindIndex(kvp => kvp.Value == _currentMediaType);
if (index != -1)
MediaTypeComboBox.SelectedIndex = index;
else
StatusLabel.Content = $"Disc of type '{Converters.MediaTypeToString(_currentMediaType)}' found, but the current system does not support it!";
}
#endregion
#region UI Helpers
/// <summary>
/// Get pixel coordinates based on DPI scaling
/// </summary>
/// <param name="bounds">Rectangle representing the bounds to transform</param>
/// <returns>Rectangle representing the scaled bounds</returns>
private Rectangle GetScaledCoordinates(Rectangle bounds)
{
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
{
return new Rectangle(
TransformCoordinate(bounds.Left, g.DpiX),
TransformCoordinate(bounds.Top, g.DpiY),
TransformCoordinate(bounds.Width, g.DpiX),
TransformCoordinate(bounds.Height, g.DpiY));
}
}
/// <summary>
/// Transform an individual coordinate using DPI scaling
/// </summary>
/// <param name="coord">Current integer coordinate</param>
/// <param name="dpi">DPI scaling factor</param>
/// <returns>Scaled integer coordinate</returns>
private int TransformCoordinate(int coord, float dpi)
{
return (int)(coord / ((double)dpi / 96));
}
#endregion
}
}

86
DICUI/Options.cs Normal file
View File

@@ -0,0 +1,86 @@
using System;
using System.Configuration;
using System.Reflection;
using DICUI.Data;
namespace DICUI
{
public class Options
{
public string DefaultOutputPath { get; private set; }
public string DICPath { get; private set; }
public string SubDumpPath { get; private set; }
public int preferredDumpSpeedCD { get; set; }
public int preferredDumpSpeedDVD { get; set; }
public bool QuietMode { get; set; }
public bool ParanoidMode { get; set; }
public bool ScanForProtection { get; set; }
public int RereadAmountForC2 { get; set; }
public bool SkipMediaTypeDetection { get; set; }
public bool VerboseLogging { get; set; }
public bool OpenLogWindowAtStartup { get; set; }
public void Save()
{
Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//TODO: reflection is used
//TODO: is remove needed, doesn't the value get directly overridden
Array.ForEach(
GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance),
p => {
configFile.AppSettings.Settings.Remove(p.Name);
configFile.AppSettings.Settings.Add(p.Name, Convert.ToString(p.GetValue(this)));
}
);
configFile.Save(ConfigurationSaveMode.Modified);
}
public void Load()
{
//TODO: hardcoded, we should find a better way
DICPath = ConfigurationManager.AppSettings["DICPath"] ?? @"Programs\DiscImageCreator.exe";
SubDumpPath = ConfigurationManager.AppSettings["SubDumpPath"] ?? "subdump.exe";
DefaultOutputPath = ConfigurationManager.AppSettings["DefaultOutputPath"] ?? "ISO";
this.preferredDumpSpeedCD = Int32.TryParse(ConfigurationManager.AppSettings["preferredDumpSpeedCD"], out int maxDumpSpeedCD) ? maxDumpSpeedCD : 72;
this.preferredDumpSpeedDVD = Int32.TryParse(ConfigurationManager.AppSettings["preferredDumpSpeedDVD"], out int maxDumpSpeedDVD) ? maxDumpSpeedDVD : 72;
this.QuietMode = Boolean.TryParse(ConfigurationManager.AppSettings["QuietMode"], out bool quietMode) ? quietMode : false;
this.ParanoidMode = Boolean.TryParse(ConfigurationManager.AppSettings["ParanoidMode"], out bool paranoidMode) ? paranoidMode : false;
this.ScanForProtection = Boolean.TryParse(ConfigurationManager.AppSettings["ScanForProtection"], out bool scanForProtection) ? scanForProtection : true;
this.SkipMediaTypeDetection = Boolean.TryParse(ConfigurationManager.AppSettings["SkipMediaTypeDetection"], out bool skipMediaTypeDetection) ? skipMediaTypeDetection : false;
this.RereadAmountForC2 = Int32.TryParse(ConfigurationManager.AppSettings["RereadAmountForC2"], out int rereadAmountForC2) ? rereadAmountForC2 : 20;
this.VerboseLogging = Boolean.TryParse(ConfigurationManager.AppSettings["VerboseLogging"], out bool verboseLogging) ? verboseLogging : true;
this.OpenLogWindowAtStartup = Boolean.TryParse(ConfigurationManager.AppSettings["OpenLogWindowAtStartup"], out bool openLogWindowAtStartup) ? openLogWindowAtStartup : true;
}
//TODO: probably should be generic for non-string options
//TODO: using reflection for Set and Get is orthodox but it works, should be changed to a key,value map probably
public void Set(string key, string value)
{
GetType().GetProperty(key, BindingFlags.Public | BindingFlags.Instance).SetValue(this, value);
}
public string Get(string key)
{
return GetType().GetProperty(key, BindingFlags.Public | BindingFlags.Instance).GetValue(this) as string;
}
public int GetPreferredDumpSpeedForMediaType(MediaType? type)
{
switch (type)
{
case MediaType.CD: return preferredDumpSpeedCD;
case MediaType.DVD: return preferredDumpSpeedDVD;
default: return 8;
}
}
}
}

138
DICUI/OptionsWindow.xaml Normal file
View File

@@ -0,0 +1,138 @@
<Window x:Class="DICUI.OptionsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:lui="clr-namespace:DICUI.UI"
xmlns:l="clr-namespace:DICUI"
mc:Ignorable="d"
Title="Options" Height="400" Width="515.132">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="100"/>
<RowDefinition Height="100"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<GroupBox Grid.Column="0" Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Paths" />
<Grid Margin="10,15,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="2.0*" />
<ColumnDefinition Width="0.2*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="DicImageCreator Path" />
<TextBox x:Name="DICPathTextBox" Grid.Row="0" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
<Button x:Name="DICPathButton" Grid.Row="0" Grid.Column="2" Height="22" Width="22" Content="..." Click="BrowseForPathClick" />
<Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="subdump Path" />
<TextBox x:Name="SubDumpPathTextBox" Grid.Row="1" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
<Button x:Name="SubDumpPathButton" Grid.Row="1" Grid.Column="2" Height="22" Width="22" Content="..." Click="BrowseForPathClick"/>
<Label Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Default Output Path" />
<TextBox x:Name="DefaultOutputPathTextBox" Grid.Row="2" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
<Button x:Name="DefaultOutputPathButton" Grid.Row="2" Grid.Column="2" Height="22" Width="22" Content="..." Click="BrowseForPathClick" />
</Grid>
<GroupBox Grid.Row="1" Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Preferred Dump Speed">
<Grid Height="60">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="2.0*"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="CD-ROM" />
<Slider x:Name="DumpSpeedCDSlider" Grid.Row="0" Grid.Column="1" Minimum="1" Maximum="72" IsSnapToTickEnabled="True" TickPlacement="BottomRight" Ticks="{Binding Source={x:Static lui:AllowedSpeeds.ForCDAsCollection}}" />
<TextBox x:Name="DumpSpeedCDTextBox" Grid.Row="0" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" IsReadOnlyCaretVisible="False" VerticalAlignment="Center" Text="{Binding ElementName=DumpSpeedCDSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}" Background="LightGray" Foreground="Gray"/>
<Label Grid.Row="1" Grid.Column="0" Content="DVD-ROM" />
<Slider x:Name="DumpSpeedDVDSlider" Grid.Row="1" Grid.Column="1" Minimum="1" Maximum="24" IsSnapToTickEnabled="True" TickPlacement="BottomRight" Ticks="{Binding Source={x:Static lui:AllowedSpeeds.ForDVDAsCollection}}" />
<TextBox x:Name="DumpSpeedDVDTextBox" Grid.Row="1" Grid.Column="2" Width="22" Height="22" TextAlignment="Center" IsReadOnly="True" IsReadOnlyCaretVisible="False" VerticalAlignment="Center" Text="{Binding ElementName=DumpSpeedDVDSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}" Background="LightGray" Foreground="Gray"/>
</Grid>
</GroupBox>
<GroupBox Grid.Row="2" Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Options" Padding="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<CheckBox Grid.Column="0" VerticalAlignment="Center" Content="Quiet Mode"
DataContext="{Binding Source={x:Static lui:ViewModels.OptionsViewModel}}"
IsChecked="{Binding Path=QuietMode}"
ToolTip="Disable DiskImageCreator sounds"
/>
<CheckBox Grid.Column="1" VerticalAlignment="Center" Content="Paranoid Mode"
DataContext="{Binding Source={x:Static lui:ViewModels.OptionsViewModel}}"
IsChecked="{Binding Path=ParanoidMode}"
ToolTip="Enable pedandic and super-safe flags"
/>
<Grid Grid.Column="2" Grid.ColumnSpan="2" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="C2 Reread Tries:" />
<TextBox Grid.Column="1" VerticalAlignment="Center"
DataContext="{Binding Source={x:Static lui:ViewModels.OptionsViewModel}}"
Text="{Binding Path=RereadAmountForC2}"
ToolTip="Specifies how many rereads are attempted on C2 error"
/>
</Grid>
<CheckBox Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" VerticalAlignment="Top" Content="Automatically Scan for Protection"
DataContext="{Binding Source={x:Static lui:ViewModels.OptionsViewModel}}"
IsChecked="{Binding Path=ScanForProtection}"
ToolTip="Enable automatic checking for copy protection on dumped media" Margin="0,4,0,0"
/>
<CheckBox Grid.Column="2" Grid.Row="1" Grid.ColumnSpan="2" VerticalAlignment="Center" Content="Skip Media Type Detection"
DataContext="{Binding Source={x:Static lui:ViewModels.OptionsViewModel}}"
IsChecked="{Binding Path=SkipMediaTypeDetection}"
ToolTip="Disable trying to guess media type inserted (may improve performance at startup)"
/>
</Grid>
</GroupBox>
<Grid Height="22" Grid.Row="3" Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Button x:Name="AcceptButton" Grid.Row="0" Grid.Column="1" Height="22" Width="80" Content="Accept" Click="OnAcceptClick" />
<Button x:Name="CancelButton" Grid.Row="0" Grid.Column="2" Height="22" Width="80" Content="Cancel" Click="OnCancelClick" />
</Grid>
</Grid>
</Window>

130
DICUI/OptionsWindow.xaml.cs Normal file
View File

@@ -0,0 +1,130 @@
using System;
using System.IO;
using System.Windows;
using System.Windows.Forms;
using Button = System.Windows.Controls.Button;
using TextBox = System.Windows.Controls.TextBox;
namespace DICUI
{
/// <summary>
/// Interaction logic for OptionsWindow.xaml
/// </summary>
public partial class OptionsWindow : Window
{
private readonly MainWindow _mainWindow;
private readonly Options _options;
public OptionsWindow(MainWindow mainWindow, Options options)
{
InitializeComponent();
_mainWindow = mainWindow;
_options = options;
}
private OpenFileDialog CreateOpenFileDialog()
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
dialog.Filter = "Executables (*.exe)|*.exe";
dialog.FilterIndex = 0;
dialog.RestoreDirectory = true;
return dialog;
}
private FolderBrowserDialog CreateFolderBrowserDialog()
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
return dialog;
}
private string[] PathSettings()
{
string[] pathSettings = { "DefaultOutputPath", "DICPath", "SubDumpPath" };
return pathSettings;
}
private TextBox TextBoxForPathSetting(string name)
{
return FindName(name + "TextBox") as TextBox;
}
private void BrowseForPathClick(object sender, EventArgs e)
{
Button button = sender as Button;
// strips button prefix to obtain the setting name
string pathSettingName = button.Name.Substring(0, button.Name.IndexOf("Button"));
// TODO: hack for now, then we'll see
bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath";
CommonDialog dialog = shouldBrowseForPath ? (CommonDialog)CreateFolderBrowserDialog() : CreateOpenFileDialog();
using (dialog)
{
DialogResult result = dialog.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
string path;
bool exists;
if (shouldBrowseForPath)
{
path = (dialog as FolderBrowserDialog).SelectedPath;
exists = Directory.Exists(path);
}
else
{
path = (dialog as OpenFileDialog).FileName;
exists = File.Exists(path);
}
if (exists)
TextBoxForPathSetting(pathSettingName).Text = path;
else
{
System.Windows.MessageBox.Show(
"Specified path doesn't exists!",
"Error",
MessageBoxButton.OK,
MessageBoxImage.Error
);
}
}
}
}
public void Refresh()
{
Array.ForEach(PathSettings(), setting => TextBoxForPathSetting(setting).Text = _options.Get(setting));
DumpSpeedCDSlider.Value = _options.preferredDumpSpeedCD;
DumpSpeedDVDSlider.Value = _options.preferredDumpSpeedDVD;
}
#region Event Handlers
private void OnAcceptClick(object sender, EventArgs e)
{
Array.ForEach(PathSettings(), setting => _options.Set(setting, TextBoxForPathSetting(setting).Text));
_options.preferredDumpSpeedCD = Convert.ToInt32(DumpSpeedCDSlider.Value);
_options.preferredDumpSpeedDVD = Convert.ToInt32(DumpSpeedDVDSlider.Value);
_options.Save();
Hide();
_mainWindow.OnOptionsUpdated();
}
private void OnCancelClick(object sender, EventArgs e)
{
// just hide the window and don't care
Hide();
}
#endregion
}
}

View File

@@ -53,3 +53,6 @@ using System.Windows;
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Anything marked as internal can be used by the test methods
[assembly: InternalsVisibleTo("DICUI.Test")]

51
DICUI/UI/AllowedSpeeds.cs Normal file
View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
using DICUI.Data;
namespace DICUI.UI
{
/// <summary>
/// Gets allowed drive speeds for a given media type
/// </summary>
public static class AllowedSpeeds
{
// Private lists of known drive speed ranges
private static IReadOnlyList<int> cd { get; } = new List<int> { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 };
private static IReadOnlyList<int> dvd { get; } = cd.Where(s => s <= 24).ToList();
private static IReadOnlyList<int> bd { get; } = cd.Where(s => s <= 16).ToList();
private static IReadOnlyList<int> unknown { get; } = cd; // TODO: All or {1}? Maybe null?
/// <summary>
/// Get list of all drive speeds for a given MediaType
/// </summary>
/// <param name="type">MediaType? that represents the current item</param>
/// <returns>Read-only list of drive speeds</returns>
public static IReadOnlyList<int> GetForMediaType(MediaType? type)
{
switch (type)
{
case MediaType.CD:
case MediaType.GDROM:
return cd;
case MediaType.DVD:
case MediaType.HDDVD:
case MediaType.GameCubeGameDisc:
case MediaType.WiiOpticalDisc:
return dvd;
case MediaType.BluRay:
return bd;
default:
return unknown;
}
}
// Create collections for UI based on known drive speeds
public static DoubleCollection ForCDAsCollection { get; } = GetDoubleCollectionFromIntList(cd);
public static DoubleCollection ForDVDAsCollection { get; } = GetDoubleCollectionFromIntList(dvd);
public static DoubleCollection ForBDAsCollection { get; } = GetDoubleCollectionFromIntList(bd);
private static DoubleCollection GetDoubleCollectionFromIntList(IReadOnlyList<int> list)
=> new DoubleCollection(list.Select(i => Convert.ToDouble(i)).ToList());
}
}

View File

@@ -0,0 +1,35 @@
using System.Windows.Media;
using DICUI.Data;
using DICUI.Utilities;
namespace DICUI.UI
{
/// <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?).Name() + " ----------";
else
return (data as KnownSystem?).Name();
}
}
}
}

106
DICUI/UI/ViewModels.cs Normal file
View File

@@ -0,0 +1,106 @@
using System;
using System.Windows.Media;
namespace DICUI.UI
{
public class OptionsViewModel
{
private Options _options;
public OptionsViewModel(Options options)
{
this._options = options;
}
public bool QuietMode
{
get { return _options.QuietMode; }
set { _options.QuietMode = value; }
}
public bool ParanoidMode
{
get { return _options.ParanoidMode; }
set { _options.ParanoidMode = value; }
}
public bool ScanForProtection
{
get { return _options.ScanForProtection; }
set { _options.ScanForProtection = value; }
}
public bool SkipMediaTypeDetection
{
get { return _options.SkipMediaTypeDetection; }
set { _options.SkipMediaTypeDetection = value; }
}
public string RereadAmountForC2
{
get { return Convert.ToString(_options.RereadAmountForC2); }
set
{
if (Int32.TryParse(value, out int result))
_options.RereadAmountForC2 = result;
}
}
public bool VerboseLogging
{
get { return _options.VerboseLogging; }
set
{
_options.VerboseLogging = value;
_options.Save();
}
}
public bool OpenLogWindowAtStartup
{
get { return _options.OpenLogWindowAtStartup; }
set
{
_options.OpenLogWindowAtStartup = value;
_options.Save();
}
}
}
public class LoggerViewModel
{
private LogWindow _logWindow;
public void SetWindow(LogWindow logWindow) => _logWindow = logWindow;
public bool WindowVisible
{
get => _logWindow != null ? _logWindow.IsVisible : false;
set
{
if (value)
{
_logWindow.AdjustPositionToMainWindow();
_logWindow.Show();
}
else
_logWindow.Hide();
}
}
public void VerboseLog(string text)
{
if (ViewModels.OptionsViewModel.VerboseLogging)
_logWindow.AppendToTextBox(text, Brushes.Yellow);
}
public void VerboseLog(string format, params object[] args) => VerboseLog(string.Format(format, args));
public void VerboseLogLn(string format, params object[] args) => VerboseLog(string.Format(format, args) + "\n");
}
public static class ViewModels
{
public static OptionsViewModel OptionsViewModel { get; set; }
public static LoggerViewModel LoggerViewModel { get; set; } = new LoggerViewModel();
}
}

View File

@@ -1,58 +1,91 @@
using System.Collections.Generic;
using System;
using System.Globalization;
using System.Windows.Data;
using IMAPI2;
using DICUI.Data;
namespace DICUI.Utilities
{
/// <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)
{
if (value is DICCommand)
return ((DICCommand)value).Name();
else if (value is DICFlag)
return ((DICFlag)value).Name();
else if (value is MediaType?)
return ((MediaType?)value).Name();
else if (value is KnownSystem?)
return ((KnownSystem?)value).Name();
else
return "";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.Empty;
}
}
public static class Converters
{
/// <summary>
/// Get the DiscType associated with a given base command
/// Get the MediaType associated with a given base command
/// </summary>
/// <param name="baseCommand">String value to check</param>
/// <returns>DiscType if possible, null on error</returns>
/// <param name="baseCommand">DICCommand 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 DiscType? BaseCommmandToDiscType(string baseCommand)
public static MediaType? BaseCommmandToMediaType(DICCommand baseCommand)
{
switch (baseCommand)
{
case DICCommands.CompactDisc:
return DiscType.CD;
case DICCommands.GDROM:
case DICCommands.Swap:
return DiscType.GDROM;
case DICCommands.DigitalVideoDisc:
return DiscType.DVD9;
case DICCommands.BluRay:
return DiscType.BD50;
case DICCommands.XBOX:
return DiscType.DVD5;
case DICCommand.Audio:
case DICCommand.CompactDisc:
case DICCommand.Data:
return MediaType.CD;
case DICCommand.GDROM:
case DICCommand.Swap:
return MediaType.GDROM;
case DICCommand.DigitalVideoDisc:
case DICCommand.XBOX:
return MediaType.DVD;
case DICCommand.BluRay:
return MediaType.BluRay;
// Non-optical
case DICCommands.Floppy:
return DiscType.Floppy;
case DICCommand.Floppy:
return MediaType.Floppy;
default:
return null;
}
}
/// <summary>
/// Get the most common known system for a given DiscType
/// Get the most common known system for a given MediaType
/// </summary>
/// <param name="baseCommand">String value to check</param>
/// <param name="baseCommand">DICCommand value to check</param>
/// <returns>KnownSystem if possible, null on error</returns>
public static KnownSystem? BaseCommandToKnownSystem(string baseCommand)
public static KnownSystem? BaseCommandToKnownSystem(DICCommand baseCommand)
{
switch (baseCommand)
{
case DICCommands.CompactDisc:
case DICCommands.DigitalVideoDisc:
case DICCommands.Floppy:
case DICCommand.Audio:
return KnownSystem.AudioCD;
case DICCommand.CompactDisc:
case DICCommand.Data:
case DICCommand.DigitalVideoDisc:
case DICCommand.Floppy:
return KnownSystem.IBMPCCompatible;
case DICCommands.GDROM:
case DICCommands.Swap:
case DICCommand.GDROM:
case DICCommand.Swap:
return KnownSystem.SegaDreamcast;
case DICCommands.BluRay:
case DICCommand.BluRay:
return KnownSystem.SonyPlayStation3;
case DICCommands.XBOX:
case DICCommand.XBOX:
return KnownSystem.MicrosoftXBOX;
default:
return null;
@@ -60,198 +93,235 @@ namespace DICUI.Utilities
}
/// <summary>
/// Get the DIC command to be used for a given DiscType
/// Get the string representation of the DICCommand enum values
/// </summary>
/// <param name="type">DiscType value to check</param>
/// <returns>String containing the command, null on error</returns>
public static string DiscTypeToBaseCommand(DiscType? type)
/// <param name="command">DICCommand value to convert</param>
/// <returns>String representing the value, if possible</returns>
public static string DICCommandToString(DICCommand command)
{
switch (type)
switch (command)
{
case DiscType.CD:
return DICCommands.CompactDisc;
case DiscType.DVD5:
case DiscType.DVD9:
return DICCommands.DigitalVideoDisc;
case DiscType.GDROM:
return DICCommands.GDROM;
case DiscType.HDDVD:
return null;
case DiscType.BD25:
case DiscType.BD50:
return DICCommands.BluRay;
// Special Formats
case DiscType.GameCubeGameDisc:
return DICCommands.DigitalVideoDisc;
case DiscType.WiiOpticalDisc:
return null;
case DiscType.WiiUOpticalDisc:
return null;
case DiscType.UMD:
return null;
// Non-optical
case DiscType.Floppy:
return DICCommands.Floppy;
case DICCommand.Audio:
return DICCommandStrings.Audio;
case DICCommand.BluRay:
return DICCommandStrings.BluRay;
case DICCommand.Close:
return DICCommandStrings.Close;
case DICCommand.CompactDisc:
return DICCommandStrings.CompactDisc;
case DICCommand.Data:
return DICCommandStrings.Data;
case DICCommand.DigitalVideoDisc:
return DICCommandStrings.DigitalVideoDisc;
case DICCommand.DriveSpeed:
return DICCommandStrings.DriveSpeed;
case DICCommand.Eject:
return DICCommandStrings.Eject;
case DICCommand.Floppy:
return DICCommandStrings.Floppy;
case DICCommand.GDROM:
return DICCommandStrings.GDROM;
case DICCommand.MDS:
return DICCommandStrings.MDS;
case DICCommand.Reset:
return DICCommandStrings.Reset;
case DICCommand.Start:
return DICCommandStrings.Start;
case DICCommand.Stop:
return DICCommandStrings.Stop;
case DICCommand.Sub:
return DICCommandStrings.Sub;
case DICCommand.Swap:
return DICCommandStrings.Swap;
case DICCommand.XBOX:
return DICCommandStrings.XBOX;
case DICCommand.NONE:
default:
return null;
return "";
}
}
/// <summary>
/// Get the string representation of the DICFlag enum values
/// </summary>
/// <param name="command">DICFlag value to convert</param>
/// <returns>String representing the value, if possible</returns>
public static string DICFlagToString(DICFlag flag)
{
switch (flag)
{
case DICFlag.AddOffset:
return DICFlagStrings.AddOffset;
case DICFlag.AMSF:
return DICFlagStrings.AMSF;
case DICFlag.BEOpcode:
return DICFlagStrings.BEOpcode;
case DICFlag.C2Opcode:
return DICFlagStrings.C2Opcode;
case DICFlag.CopyrightManagementInformation:
return DICFlagStrings.CopyrightManagementInformation;
case DICFlag.D8Opcode:
return DICFlagStrings.D8Opcode;
case DICFlag.DisableBeep:
return DICFlagStrings.DisableBeep;
case DICFlag.ForceUnitAccess:
return DICFlagStrings.ForceUnitAccess;
case DICFlag.MCN:
return DICFlagStrings.MCN;
case DICFlag.MultiSession:
return DICFlagStrings.MultiSession;
case DICFlag.NoFixSubP:
return DICFlagStrings.NoFixSubP;
case DICFlag.NoFixSubQ:
return DICFlagStrings.NoFixSubQ;
case DICFlag.NoFixSubQLibCrypt:
return DICFlagStrings.NoFixSubQLibCrypt;
case DICFlag.NoFixSubQSecuROM:
return DICFlagStrings.NoFixSubQSecuROM;
case DICFlag.NoFixSubRtoW:
return DICFlagStrings.NoFixSubRtoW;
case DICFlag.Raw:
return DICFlagStrings.Raw;
case DICFlag.Reverse:
return DICFlagStrings.Reverse;
case DICFlag.ScanAntiMod:
return DICFlagStrings.ScanAntiMod;
case DICFlag.ScanFileProtect:
return DICFlagStrings.ScanFileProtect;
case DICFlag.ScanSectorProtect:
return DICFlagStrings.ScanSectorProtect;
case DICFlag.SeventyFour:
return DICFlagStrings.SeventyFour;
case DICFlag.SubchannelReadLevel:
return DICFlagStrings.SubchannelReadLevel;
case DICFlag.NONE:
default:
return "";
}
}
/// <summary>
/// Convert IMAPI physical media type to a MediaType
/// </summary>
/// <param name="type">IMAPI_MEDIA_PHYSICAL_TYPE value to check</param>
/// <returns>MediaType if possible, null on error</returns>
public static MediaType? IMAPIDiskTypeToMediaType(IMAPI_MEDIA_PHYSICAL_TYPE type)
{
switch (type)
{
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_UNKNOWN:
return MediaType.NONE;
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDROM:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDR:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDRW:
return MediaType.CD;
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDROM:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDRAM:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSR:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSRW:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSR_DUALLAYER:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHR:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHRW:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHR_DUALLAYER:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DISK:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSRW_DUALLAYER:
return MediaType.DVD;
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDROM:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDR:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDRAM:
return MediaType.HDDVD;
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDROM:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDR:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDRE:
return MediaType.BluRay;
default:
return null;
}
}
/// <summary>
/// Get the default extension for a given disc type
/// </summary>
/// <param name="type">DiscType value to check</param>
/// <param name="type">MediaType value to check</param>
/// <returns>Valid extension (with leading '.'), null on error</returns>
public static string DiscTypeToExtension(DiscType? type)
public static string MediaTypeToExtension(MediaType? type)
{
switch (type)
{
case DiscType.CD:
case DiscType.GDROM:
case MediaType.CD:
case MediaType.GDROM:
case MediaType.Cartridge:
return ".bin";
case DiscType.DVD5:
case DiscType.DVD9:
case DiscType.HDDVD:
case DiscType.BD25:
case DiscType.BD50:
case DiscType.WiiOpticalDisc:
case DiscType.UMD:
case MediaType.DVD:
case MediaType.HDDVD:
case MediaType.BluRay:
case MediaType.WiiOpticalDisc:
case MediaType.UMD:
return ".iso";
case DiscType.GameCubeGameDisc:
case MediaType.LaserDisc:
case MediaType.GameCubeGameDisc:
return ".raw";
case DiscType.WiiUOpticalDisc:
case MediaType.WiiUOpticalDisc:
return ".wud";
case DiscType.Floppy:
case MediaType.Floppy:
return ".img";
case DiscType.NONE:
case MediaType.Cassette:
return ".wav";
case MediaType.NONE:
case MediaType.CED:
default:
return null;
}
}
/// <summary>
/// Get the string representation of the DiscType enum values
/// Get the string representation of the MediaType enum values
/// </summary>
/// <param name="type">DiscType value to convert</param>
/// <param name="type">MediaType value to convert</param>
/// <returns>String representing the value, if possible</returns>
public static string DiscTypeToString(DiscType? type)
public static string MediaTypeToString(MediaType? type)
{
switch (type)
{
case DiscType.CD:
case MediaType.CD:
return "CD-ROM";
case DiscType.DVD5:
return "DVD-5 [Single-Layer]";
case DiscType.DVD9:
return "DVD-9 [Dual-Layer]";
case DiscType.GDROM:
case MediaType.DVD:
return "DVD";
case MediaType.GDROM:
return "GD-ROM";
case DiscType.HDDVD:
case MediaType.HDDVD:
return "HD-DVD";
case DiscType.BD25:
return "BluRay-25 [Single-Layer]";
case DiscType.BD50:
return "BluRay-50 [Dual-Layer]";
case MediaType.BluRay:
return "BluRay";
case MediaType.LaserDisc:
return "LaserDisc";
case DiscType.GameCubeGameDisc:
case MediaType.CED:
return "CED";
case MediaType.GameCubeGameDisc:
return "GameCube Game";
case DiscType.WiiOpticalDisc:
case MediaType.WiiOpticalDisc:
return "Wii Optical";
case DiscType.WiiUOpticalDisc:
case MediaType.WiiUOpticalDisc:
return "Wii U Optical";
case DiscType.UMD:
case MediaType.UMD:
return "UMD";
case DiscType.Floppy:
case MediaType.Cartridge:
return "Cartridge";
case MediaType.Cassette:
return "Cassette Tape";
case MediaType.Floppy:
return "Floppy Disk";
case DiscType.NONE:
case MediaType.NONE:
default:
return "Unknown";
}
}
/// <summary>
/// Get list of default parameters for a given system and disc type
/// </summary>
/// <param name="sys">KnownSystem value to check</param>
/// <param name="type">DiscType value to check</param>
/// <returns>List of strings representing the parameters</returns>
public static List<string> KnownSystemAndDiscTypeToParameters(KnownSystem? sys, DiscType? type)
{
// First check to see if the combination of system and disctype is valid
List<DiscType?> validTypes = Validation.GetValidDiscTypes(sys);
if (!validTypes.Contains(type))
{
return null;
}
// Now sort based on disc type
List<string> parameters = new List<string>();
switch (type)
{
case DiscType.CD:
parameters.Add(DICFlags.C2Opcode); parameters.Add("20");
switch (sys)
{
case KnownSystem.AppleMacintosh:
case KnownSystem.IBMPCCompatible:
parameters.Add(DICFlags.NoFixSubQSecuROM);
parameters.Add(DICFlags.ScanFileProtect);
parameters.Add(DICFlags.ScanSectorProtect);
break;
case KnownSystem.NECPCEngineTurboGrafxCD:
parameters.Add(DICFlags.MCN);
break;
case KnownSystem.SonyPlayStation:
parameters.Add(DICFlags.ScanAntiMod);
break;
}
break;
case DiscType.DVD5:
// Currently no defaults set
break;
case DiscType.DVD9:
// Currently no defaults set
break;
case DiscType.GDROM:
parameters.Add(DICFlags.C2Opcode); parameters.Add("20");
break;
case DiscType.HDDVD:
break;
case DiscType.BD25:
// Currently no defaults set
break;
case DiscType.BD50:
// Currently no defaults set
break;
// Special Formats
case DiscType.GameCubeGameDisc:
parameters.Add(DICFlags.Raw);
break;
case DiscType.WiiOpticalDisc:
// Currently no defaults set
break;
case DiscType.WiiUOpticalDisc:
// Currently no defaults set
break;
case DiscType.UMD:
break;
// Non-optical
case DiscType.Floppy:
// Currently no defaults set
break;
}
return parameters;
}
/// <summary>
/// Get the string representation of the KnownSystem enum values
/// </summary>
@@ -275,8 +345,10 @@ namespace DICUI.Utilities
return "Mattel HyperScan";
case KnownSystem.MicrosoftXBOX:
return "Microsoft XBOX";
case KnownSystem.MicrosoftXBOX360:
return "Microsoft XBOX 360";
case KnownSystem.MicrosoftXBOX360XDG2:
return "Microsoft XBOX 360 (XDG2)";
case KnownSystem.MicrosoftXBOX360XDG3:
return "Microsoft XBOX 360 (XDG3)";
case KnownSystem.MicrosoftXBOXOne:
return "Microsoft XBOX One";
case KnownSystem.NECPCEngineTurboGrafxCD:
@@ -369,6 +441,8 @@ namespace DICUI.Utilities
return "Incredible Technologies Eagle";
case KnownSystem.IncredibleTechnologiesVarious:
return "Incredible Technologies PC-based Systems";
case KnownSystem.KonamieAmusement:
return "Konami e-Amusement";
case KnownSystem.KonamiFirebeat:
return "Konami Firebeat";
case KnownSystem.KonamiGVSystem:
@@ -462,6 +536,12 @@ namespace DICUI.Utilities
return "DVD-Video";
case KnownSystem.EnhancedCD:
return "Enhanced CD";
case KnownSystem.EnhancedDVD:
return "Enhanced DVD";
case KnownSystem.EnhancedBD:
return "Enhanced BD";
case KnownSystem.HDDVDVideo:
return "HD-DVD-Video";
case KnownSystem.PalmOS:
return "PalmOS";
case KnownSystem.PhilipsCDiDigitalVideo:
@@ -470,6 +550,8 @@ namespace DICUI.Utilities
return "Photo CD";
case KnownSystem.PlayStationGameSharkUpdates:
return "PlayStation GameShark Updates";
case KnownSystem.RainbowDisc:
return "Rainbow Disc";
case KnownSystem.TaoiKTV:
return "Tao iKTV";
case KnownSystem.TomyKissSite:
@@ -479,10 +561,13 @@ namespace DICUI.Utilities
#endregion
case KnownSystem.Custom:
return "Custom Input";
case KnownSystem.NONE:
default:
return "Unknown";
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
using DICUI.Data;
namespace DICUI.Utilities
{
/// <summary>
/// Extensions for DICCommand for easier calling
/// </summary>
public static class DICCommandExtensions
{
public static string Name(this DICCommand command)
{
return Converters.DICCommandToString(command);
}
}
/// <summary>
/// Extensions for DICFlag for easier calling
/// </summary>
public static class DICFlagExtensions
{
public static string Name(this DICFlag command)
{
return Converters.DICFlagToString(command);
}
}
/// <summary>
/// Extensions for MediaType? for easier calling
/// </summary>
public static class MediaTypeExtensions
{
public static string Name(this MediaType? type)
{
return Converters.MediaTypeToString(type);
}
public static string Extension(this MediaType? type)
{
return Converters.MediaTypeToExtension(type);
}
public static bool DoesSupportDriveSpeed(this MediaType? type)
{
switch (type)
{
case MediaType.CD:
case MediaType.DVD:
case MediaType.GDROM:
case MediaType.HDDVD:
case MediaType.GameCubeGameDisc:
case MediaType.WiiOpticalDisc:
return true;
default:
return false;
}
}
}
/// <summary>
/// Extensions for KnownSystem? for easier calling
/// </summary>
public static class KnownSystemExtensions
{
public static string Name(this KnownSystem? system)
{
return Converters.KnownSystemToString(system);
}
public static bool DoesSupportDriveSpeed(this KnownSystem? system)
{
switch (system)
{
case KnownSystem.MicrosoftXBOX:
case KnownSystem.MicrosoftXBOX360XDG2:
case KnownSystem.MicrosoftXBOX360XDG3:
return false;
default:
return true;
}
}
public static KnownSystemCategory Category(this KnownSystem? system)
{
if (system < KnownSystem.MarkerConsoleEnd)
return KnownSystemCategory.Console;
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.MarkerConsoleEnd:
case KnownSystem.MarkerOtherEnd:
return true;
default:
return false;
}
}
}
/// <summary>
/// Extensions for KnownSystemCategory?
/// </summary>
public static class KnownSystemCategoryExtensions
{
/// <summary>
/// Get the string representation of a KnownSystemCategory
/// </summary>
public static string Name(this KnownSystemCategory? category)
{
switch (category)
{
case KnownSystemCategory.Arcade:
return "Arcade";
case KnownSystemCategory.Computer:
return "Computers";
case KnownSystemCategory.Console:
return "Consoles";
case KnownSystemCategory.Other:
return "Other";
case KnownSystemCategory.Custom:
return "Custom";
default:
return "";
}
}
}
}

File diff suppressed because it is too large Load Diff

27
DICUI/Utilities/Result.cs Normal file
View File

@@ -0,0 +1,27 @@
namespace DICUI.Utilities
{
/// <summary>
/// Generic success/failure result object, with optional message
/// </summary>
public class Result
{
private bool success;
public string Message { get; private set; }
private Result(bool success, string message)
{
this.success = success;
this.Message = message;
}
public static Result Success() => new Result(true, "");
public static Result Success(string message) => new Result(true, message);
public static Result Success(string message, params object[] args) => new Result(true, string.Format(message, args));
public static Result Failure() => new Result(false, "");
public static Result Failure(string message) => new Result(false, message);
public static Result Failure(string message, params object[] args) => new Result(false, string.Format(message, args));
public static implicit operator bool(Result result) => result.success;
}
}

View File

@@ -0,0 +1,587 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management;
using System.Threading.Tasks;
using BurnOutSharp;
using IMAPI2;
using DICUI.Data;
namespace DICUI.Utilities
{
public static class Validators
{
/// <summary>
/// Get a list of valid MediaTypes for a given KnownSystem
/// </summary>
/// <param name="sys">KnownSystem value to check</param>
/// <returns>MediaTypes, if possible</returns>
public static List<MediaType?> GetValidMediaTypes(KnownSystem? sys)
{
var types = new List<MediaType?>();
switch (sys)
{
#region Consoles
case KnownSystem.BandaiPlaydiaQuickInteractiveSystem:
types.Add(MediaType.CD);
break;
case KnownSystem.BandaiApplePippin:
types.Add(MediaType.CD);
break;
case KnownSystem.CommodoreAmigaCD32:
types.Add(MediaType.CD);
break;
case KnownSystem.CommodoreAmigaCDTV:
types.Add(MediaType.CD);
break;
case KnownSystem.MattelHyperscan:
types.Add(MediaType.CD);
break;
case KnownSystem.MicrosoftXBOX:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MicrosoftXBOX360XDG2:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MicrosoftXBOX360XDG3:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MicrosoftXBOXOne:
types.Add(MediaType.BluRay);
break;
case KnownSystem.NECPCEngineTurboGrafxCD:
types.Add(MediaType.CD);
break;
case KnownSystem.NECPCFX:
types.Add(MediaType.CD);
break;
case KnownSystem.NintendoGameCube:
types.Add(MediaType.GameCubeGameDisc);
break;
case KnownSystem.NintendoWii:
types.Add(MediaType.WiiOpticalDisc);
break;
case KnownSystem.NintendoWiiU:
types.Add(MediaType.WiiUOpticalDisc);
break;
case KnownSystem.Panasonic3DOInteractiveMultiplayer:
types.Add(MediaType.CD);
break;
case KnownSystem.PhilipsCDi:
types.Add(MediaType.CD);
break;
case KnownSystem.SegaCDMegaCD:
types.Add(MediaType.CD);
break;
case KnownSystem.SegaDreamcast:
types.Add(MediaType.GDROM);
break;
case KnownSystem.SegaSaturn:
types.Add(MediaType.CD);
break;
case KnownSystem.SNKNeoGeoCD:
types.Add(MediaType.CD);
break;
case KnownSystem.SonyPlayStation:
types.Add(MediaType.CD);
break;
case KnownSystem.SonyPlayStation2:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.SonyPlayStation3:
types.Add(MediaType.BluRay);
types.Add(MediaType.CD); // TODO: Confirm this
break;
case KnownSystem.SonyPlayStation4:
types.Add(MediaType.BluRay);
break;
case KnownSystem.SonyPlayStationPortable:
types.Add(MediaType.UMD);
types.Add(MediaType.DVD); // TODO: Confirm this
break;
case KnownSystem.VMLabsNuon:
types.Add(MediaType.DVD);
break;
case KnownSystem.VTechVFlashVSmilePro:
types.Add(MediaType.CD);
break;
case KnownSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem:
types.Add(MediaType.DVD);
break;
#endregion
#region Computers
case KnownSystem.AcornArchimedes:
types.Add(MediaType.CD);
break;
case KnownSystem.AppleMacintosh:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
types.Add(MediaType.Floppy);
break;
case KnownSystem.CommodoreAmigaCD:
types.Add(MediaType.CD);
break;
case KnownSystem.FujitsuFMTowns:
types.Add(MediaType.CD);
break;
case KnownSystem.IBMPCCompatible:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
types.Add(MediaType.Floppy);
break;
case KnownSystem.NECPC88:
types.Add(MediaType.CD);
break;
case KnownSystem.NECPC98:
types.Add(MediaType.CD);
break;
case KnownSystem.SharpX68000:
types.Add(MediaType.CD);
break;
#endregion
#region Arcade
case KnownSystem.AmigaCUBOCD32:
types.Add(MediaType.CD);
break;
case KnownSystem.AmericanLaserGames3DO:
types.Add(MediaType.CD);
break;
case KnownSystem.Atari3DO:
types.Add(MediaType.CD);
break;
case KnownSystem.Atronic:
types.Add(MediaType.CD);
break;
case KnownSystem.AUSCOMSystem1:
types.Add(MediaType.CD);
break;
case KnownSystem.BallyGameMagic:
types.Add(MediaType.CD);
break;
case KnownSystem.CapcomCPSystemIII:
types.Add(MediaType.CD);
break;
case KnownSystem.GlobalVRVarious:
types.Add(MediaType.CD);
break;
case KnownSystem.GlobalVRVortek:
types.Add(MediaType.CD);
break;
case KnownSystem.GlobalVRVortekV3:
types.Add(MediaType.DVD); // TODO: Confirm
break;
case KnownSystem.ICEPCHardware:
types.Add(MediaType.DVD);
break;
case KnownSystem.IncredibleTechnologiesEagle:
types.Add(MediaType.CD);
break;
case KnownSystem.IncredibleTechnologiesVarious:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.KonamieAmusement:
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiFirebeat:
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiGVSystem:
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiM2:
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiPython:
types.Add(MediaType.DVD); // TODO: Confirm
break;
case KnownSystem.KonamiPython2:
types.Add(MediaType.DVD); // TODO: Confirm
break;
case KnownSystem.KonamiSystem573:
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiTwinkle:
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiVarious:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MeritIndustriesBoardwalk:
types.Add(MediaType.CD); // TODO: Confirm
break;
case KnownSystem.MeritIndustriesMegaTouchAurora:
types.Add(MediaType.CD); // TODO: Confirm
break;
case KnownSystem.MeritIndustriesMegaTouchForce:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MeritIndustriesMegaTouchION:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MeritIndustriesMegaTouchMaxx:
types.Add(MediaType.DVD);
break;
case KnownSystem.MeritIndustriesMegaTouchXL:
types.Add(MediaType.CD);
break;
case KnownSystem.NamcoCapcomSystem256:
types.Add(MediaType.DVD);
break;
case KnownSystem.NamcoCapcomTaitoSystem246:
types.Add(MediaType.DVD);
break;
case KnownSystem.NamcoSegaNintendoTriforce:
types.Add(MediaType.GDROM);
break;
case KnownSystem.NamcoSystem12:
types.Add(MediaType.CD);
break;
case KnownSystem.NamcoSystem357:
types.Add(MediaType.DVD);
types.Add(MediaType.BluRay);
break;
case KnownSystem.NewJatreCDi:
types.Add(MediaType.CD);
break;
case KnownSystem.NichibutsuHighRateSystem:
types.Add(MediaType.CD);
break;
case KnownSystem.NichibutsuSuperCD:
types.Add(MediaType.CD);
break;
case KnownSystem.NichibutsuXRateSystem:
types.Add(MediaType.DVD);
break;
case KnownSystem.PhotoPlayVarious:
types.Add(MediaType.CD);
break;
case KnownSystem.RawThrillsVarious:
types.Add(MediaType.DVD);
break;
case KnownSystem.SegaChihiro:
types.Add(MediaType.GDROM);
break;
case KnownSystem.SegaEuropaR:
types.Add(MediaType.DVD); // TODO: Confirm
break;
case KnownSystem.SegaLindbergh:
types.Add(MediaType.DVD);
break;
case KnownSystem.SegaNaomi:
types.Add(MediaType.GDROM);
break;
case KnownSystem.SegaNaomi2:
types.Add(MediaType.GDROM);
break;
case KnownSystem.SegaNu:
types.Add(MediaType.DVD);
types.Add(MediaType.BluRay);
break;
case KnownSystem.SegaRingEdge:
types.Add(MediaType.DVD);
break;
case KnownSystem.SegaRingEdge2:
types.Add(MediaType.DVD);
break;
case KnownSystem.SegaRingWide:
types.Add(MediaType.DVD);
break;
case KnownSystem.SegaSTV:
types.Add(MediaType.CD);
break;
case KnownSystem.SegaSystem32:
types.Add(MediaType.CD);
break;
case KnownSystem.SeibuCATSSystem:
types.Add(MediaType.DVD);
break;
case KnownSystem.TABAustriaQuizard:
types.Add(MediaType.CD);
break;
case KnownSystem.TandyMemorexVisualInformationSystem:
types.Add(MediaType.CD);
break;
case KnownSystem.TsunamiTsuMoMultiGameMotionSystem:
types.Add(MediaType.CD);
break;
#endregion
#region Others
case KnownSystem.AudioCD:
types.Add(MediaType.CD);
break;
case KnownSystem.BDVideo:
types.Add(MediaType.BluRay);
break;
case KnownSystem.DVDVideo:
types.Add(MediaType.DVD);
break;
case KnownSystem.EnhancedCD:
types.Add(MediaType.CD);
break;
case KnownSystem.EnhancedDVD:
types.Add(MediaType.DVD);
break;
case KnownSystem.EnhancedBD:
types.Add(MediaType.BluRay);
break;
case KnownSystem.HDDVDVideo:
types.Add(MediaType.HDDVD);
break;
case KnownSystem.PalmOS:
types.Add(MediaType.CD);
break;
case KnownSystem.PhilipsCDiDigitalVideo:
types.Add(MediaType.CD);
break;
case KnownSystem.PhotoCD:
types.Add(MediaType.CD);
break;
case KnownSystem.PlayStationGameSharkUpdates:
types.Add(MediaType.CD);
break;
case KnownSystem.RainbowDisc:
types.Add(MediaType.CD);
break;
case KnownSystem.TaoiKTV:
types.Add(MediaType.CD);
break;
case KnownSystem.TomyKissSite:
types.Add(MediaType.CD);
break;
case KnownSystem.VideoCD:
types.Add(MediaType.CD);
break;
#endregion
case KnownSystem.NONE:
default:
types.Add(MediaType.NONE);
break;
}
return types;
}
/// <summary>
/// Create a list of systems
/// </summary>
/// <returns>KnownSystems, if possible</returns>
public static List<KnownSystem?> CreateListOfSystems()
{
return Enum.GetValues(typeof(KnownSystem))
.OfType<KnownSystem?>()
.Where(s => !s.IsMarker() && s != KnownSystem.NONE)
.ToList();
}
/// <summary>
/// Create a list of active drives matched to their volume labels
/// </summary>
/// <returns>Active drives, matched to labels, if possible</returns>
/// <remarks>
/// https://stackoverflow.com/questions/3060796/how-to-distinguish-between-usb-and-floppy-devices?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
/// https://msdn.microsoft.com/en-us/library/aa394173(v=vs.85).aspx
/// </remarks>
public static List<Drive> CreateListOfDrives()
{
var drives = new List<Drive>();
// Get the floppy drives
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_LogicalDisk");
var collection = searcher.Get();
foreach (ManagementObject queryObj in collection)
{
uint? mediaType = (uint?)queryObj["MediaType"];
if (mediaType != null && ((mediaType > 0 && mediaType < 11) || (mediaType > 12 && mediaType < 22)))
{
char devId = queryObj["DeviceID"].ToString()[0];
drives.Add(Drive.Floppy(devId));
}
}
}
catch
{
// No-op
}
// Get the optical disc drives
List<Drive> discDrives = DriveInfo.GetDrives()
.Where(d => d.DriveType == DriveType.CDRom)
.Select(d => Drive.Optical(d.Name[0], (d.IsReady ? d.VolumeLabel : UIElements.DiscNotDetected), d.IsReady))
.ToList();
// Add the two lists together and order
drives.AddRange(discDrives);
drives = drives.OrderBy(i => i.Letter).ToList();
return drives;
}
/// <summary>
/// Get the current disc type from drive letter
/// </summary>
/// <param name="driveLetter"></param>
/// <returns></returns>
/// <remarks>
/// https://stackoverflow.com/questions/11420365/detecting-if-disc-is-in-dvd-drive
/// </remarks>
public static MediaType? GetDiscType(char? driveLetter)
{
// Get the DeviceID from the current drive letter
string deviceId = null;
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_CDROMDrive WHERE Id = '" + driveLetter + ":\'");
var collection = searcher.Get();
foreach (ManagementObject queryObj in collection)
{
deviceId = (string)queryObj["DeviceID"];
}
}
catch
{
// We don't care what the error was
return null;
}
// If we got no valid device, we don't care and just return
if (deviceId == null)
{
return null;
}
// Get all relevant disc information
try
{
MsftDiscMaster2 discMaster = new MsftDiscMaster2();
deviceId = deviceId.ToLower().Replace('\\', '#');
string id = null;
foreach (var disc in discMaster)
{
if (disc.ToString().Contains(deviceId))
{
id = disc.ToString();
}
}
// If we couldn't find the drive, we don't care and return
if (id == null)
{
return null;
}
// Otherwise, we get the media type, if any
MsftDiscRecorder2 recorder = new MsftDiscRecorder2();
recorder.InitializeDiscRecorder(id);
MsftDiscFormat2Data dataWriter = new MsftDiscFormat2Data();
dataWriter.Recorder = recorder;
var media = dataWriter.CurrentPhysicalMediaType;
if (media != IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_UNKNOWN)
{
return Converters.IMAPIDiskTypeToMediaType(media);
}
}
catch
{
// We don't care what the error is
}
return null;
}
/// <summary>
/// Verify that, given a system and a media type, they are correct
/// </summary>
public static Result GetSupportStatus(KnownSystem? system, MediaType? type)
{
// No system chosen, update status
if (system == KnownSystem.NONE)
return Result.Failure("Please select a valid system");
// custom system chosen, then don't check anything
else if (system == KnownSystem.Custom)
return Result.Success("{0} ready to dump", type.Name());
// If we're on an unsupported type, update the status accordingly
switch (type)
{
// Fully supported types
case MediaType.CD:
case MediaType.DVD:
case MediaType.HDDVD:
case MediaType.BluRay:
if (system == KnownSystem.MicrosoftXBOX360XDG3)
{
return Result.Failure("{0} discs are not currently supported by DIC", type.Name());
}
return Result.Success("{0} ready to dump", type.Name());
// Partially supported types
case MediaType.GDROM:
case MediaType.GameCubeGameDisc:
case MediaType.WiiOpticalDisc:
return Result.Success("{0} discs are partially supported by DIC", type.Name());
// Undumpable but recognized types
case MediaType.LaserDisc:
case MediaType.WiiUOpticalDisc:
case MediaType.CED:
case MediaType.UMD:
case MediaType.Cartridge:
case MediaType.Cassette:
return Result.Failure("{0} discs are not currently supported by DIC", type.Name());
// Invalid or unknown types
case MediaType.NONE:
default:
return Result.Failure("Please select a valid disc type");
}
}
/// <summary>
/// Run protection scan on a given dump environment
/// </summary>
/// <param name="env">DumpEnvirionment containing all required information</param>
/// <returns>Copy protection detected in the envirionment, if any</returns>
public static async Task<string> RunProtectionScanOnPath(string path)
{
var found = await Task.Run(() =>
{
return ProtectionFind.Scan(path);
});
if (found == null || found.Count == 0)
return "None found";
return string.Join("\n", found.Select(kvp => kvp.Key + ": " + kvp.Value).ToArray());
}
}
}

BIN
DICUI/mspack.dll Normal file

Binary file not shown.

8
DICUI/packages.config Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BurnOutSharp" version="1.3.7.1" targetFramework="net461" />
<package id="LessIO" version="0.5.0" targetFramework="net461" />
<package id="libmspack4n" version="0.8.0" targetFramework="net461" />
<package id="UnshieldSharp" version="1.4.2.2" targetFramework="net461" />
<package id="zlib.net" version="1.0.4.0" targetFramework="net461" />
</packages>

View File

@@ -1,91 +0,0 @@
<Window x:Class="DICUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DICUI"
mc:Ignorable="d"
Title="Disc Image Creator GUI" Height="450" Width="600">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"/>
<ColumnDefinition Width="13*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="4*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<ToolBarTray Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Height="30" HorizontalAlignment="Stretch" IsLocked="True">
<ToolBar>
<Button x:Name="tbr_Properties" Content="Properties" Command="Properties" Click="tbr_Properties_Click" CommandManager.CanExecute="tbr_Properties_CanExecute"/>
</ToolBar>
</ToolBarTray>
<GroupBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,5,5.2,5.4" HorizontalAlignment="Stretch" Header="Settings"/>
<GroupBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,4.6,5.2,4.8" HorizontalAlignment="Stretch" Header="Controls"/>
<GroupBox Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,5.2,5.2,4.8" HorizontalAlignment="Stretch" Header="Status"/>
<Grid Grid.Row="1" Grid.Column="0" Margin="15,25,15.2,10.4" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2.5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" VerticalAlignment="Center">Disc Type</Label>
<ComboBox x:Name="cmb_DiscType" Grid.Row="0" Grid.Column="1" Height="22" SelectionChanged="cmb_DiscType_SelectionChanged" />
<Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center">Output Filename</Label>
<TextBox x:Name="txt_OutputFilename" Grid.Row="1" Grid.Column="1" Height="22" TextChanged="txt_OutputFilename_TextChanged"/>
<Label Grid.Row="2" Grid.Column="0" VerticalAlignment="Center">Output Directory</Label>
<TextBox x:Name="txt_OutputDirectory" Grid.Row="2" Grid.Column="1" Height="22" Width="345" HorizontalAlignment="left" TextChanged="txt_OutputDirectory_TextChanged"/>
<Button x:Name="btn_OutputDirectoryBrowse" Grid.Row="2" Grid.Column="1" Height="22" Width="50" HorizontalAlignment="Right" Content="Browse" Click="btn_OutputDirectoryBrowse_Click"/>
<Label Grid.Row="3" Grid.Column="0" VerticalAlignment="Center">Drive Letter</Label>
<ComboBox x:Name="cmb_DriveLetter" Grid.Row="3" Grid.Column="1" Height="22" Width="397" HorizontalAlignment="left" SelectionChanged="cmb_DriveLetter_SelectionChanged"/>
<Label Grid.Row="4" Grid.Column="0" VerticalAlignment="Center">Drive Speed</Label>
<ComboBox x:Name="cmb_DriveSpeed" Grid.Row="4" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="left" SelectionChanged="cmb_DriveSpeed_SelectionChanged"/>
<Label Grid.Row="5" Grid.Column="0" VerticalAlignment="Center">Parameters</Label>
<TextBox x:Name="txt_Parameters" Grid.Row="5" Grid.Column="1" Height="22" Width="397" HorizontalAlignment="left" IsEnabled="False" />
</Grid>
<Grid Grid.Row="2" Grid.Column="0" Margin="15,19.6,15.2,9.8" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Button x:Name="btn_StartStop" Grid.Row="0" Grid.Column="0" Height="22" Width="150" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Start Dumping" Click="btn_StartStop_Click" IsEnabled="False" />
<Button x:Name="btn_Search" Grid.Row="0" Grid.Column="1" Height="22" Width="150" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Scan for disks" Click="btn_Search_Click" />
<CheckBox x:Name="chk_EjectWhenDone" Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Eject When Done" IsChecked="False" />
</Grid>
<Grid Grid.Row="3" Grid.Column="0" Margin="15,20.2,15.2,9.8" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Label x:Name="lbl_Status" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Waiting for CD or DVD..." />
</Grid>
</Grid>
</Window>

View File

@@ -1,804 +0,0 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using WinForms = System.Windows.Forms;
using DICUI.Utilities;
namespace DICUI
{
public partial class MainWindow : Window
{
// Private paths
private string defaultOutputPath;
private string dicPath;
private string psxtPath;
private string sgRawPath;
private string subdumpPath;
// Private UI-related variables
private List<Tuple<char, string, bool>> _drives { get; set; }
private List<int> _driveSpeeds { get { return new List<int> { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 }; } }
private List<Tuple<string, KnownSystem?, DiscType?>> _systems { get; set; }
private Process childProcess { get; set; }
private Window childWindow { get; set; }
public MainWindow()
{
InitializeComponent();
// Get all settings
GetSettings();
// Populate the list of systems
PopulateSystems();
// Populate the list of drives
PopulateDrives();
// Populate the list of drive speeds
PopulateDriveSpeeds();
SetSupportedDriveSpeed();
}
#region Events
private void btn_StartStop_Click(object sender, RoutedEventArgs e)
{
// Dump or stop the dump
if ((string)btn_StartStop.Content == UIElements.StartDumping)
{
StartDumping();
}
else if ((string)btn_StartStop.Content == UIElements.StopDumping)
{
CancelDumping();
EjectDisc();
}
}
private void btn_OutputDirectoryBrowse_Click(object sender, RoutedEventArgs e)
{
BrowseFolder();
EnsureDiscInformation();
}
private void btn_Search_Click(object sender, RoutedEventArgs e)
{
PopulateDrives();
SetSupportedDriveSpeed();
EnsureDiscInformation();
}
private void cmb_DiscType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
GetOutputNames();
EnsureDiscInformation();
}
private void cmb_DriveLetter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SetSupportedDriveSpeed();
GetOutputNames();
EnsureDiscInformation();
}
private void cmb_DriveSpeed_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
EnsureDiscInformation();
}
private void tbr_Properties_Click(object sender, RoutedEventArgs e)
{
ShowSettings();
}
private void tbr_Properties_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void btn_Settings_Accept_Click(object sender, RoutedEventArgs e)
{
SaveSettings();
childWindow.Close();
GetSettings();
}
private void btn_Settings_Cancel_Click(object sender, RoutedEventArgs e)
{
childWindow.Close();
}
private void txt_OutputFilename_TextChanged(object sender, TextChangedEventArgs e)
{
EnsureDiscInformation();
}
private void txt_OutputDirectory_TextChanged(object sender, TextChangedEventArgs e)
{
EnsureDiscInformation();
}
#endregion
#region Helpers
/// <summary>
/// Get a complete list of supported systems and fill the combo box
/// </summary>
private void PopulateSystems()
{
_systems = Utilities.Validation.CreateListOfSystems();
cmb_DiscType.ItemsSource = _systems;
cmb_DiscType.DisplayMemberPath = "Item1";
cmb_DiscType.SelectedIndex = 0;
cmb_DiscType_SelectionChanged(null, null);
btn_StartStop.IsEnabled = false;
}
/// <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()
{
// Populate the list of drives and add it to the combo box
_drives = Utilities.Validation.CreateListOfDrives();
cmb_DriveLetter.ItemsSource = _drives;
cmb_DriveLetter.DisplayMemberPath = "Item1";
cmb_DriveLetter.SelectedIndex = 0;
cmb_DriveLetter_SelectionChanged(null, null);
if (cmb_DriveLetter.Items.Count > 0)
{
lbl_Status.Content = "Valid optical disc found! Choose your Disc Type";
btn_StartStop.IsEnabled = true;
}
else
{
lbl_Status.Content = "No valid optical disc found!";
btn_StartStop.IsEnabled = false;
}
}
/// <summary>
/// Get a complete list of (possible) disc drive speeds, and fill the combo box
/// </summary>
private void PopulateDriveSpeeds()
{
cmb_DriveSpeed.ItemsSource = _driveSpeeds;
cmb_DriveSpeed.SelectedItem = 8;
}
/// <summary>
/// Browse for an output folder
/// </summary>
private void BrowseFolder()
{
WinForms.FolderBrowserDialog folderDialog = new WinForms.FolderBrowserDialog { ShowNewFolderButton = false, SelectedPath = System.AppDomain.CurrentDomain.BaseDirectory };
WinForms.DialogResult result = folderDialog.ShowDialog();
if (result == WinForms.DialogResult.OK)
{
txt_OutputDirectory.Text = folderDialog.SelectedPath;
}
}
/// <summary>
/// Begin the dumping process using the given inputs
/// </summary>
private async void StartDumping()
{
btn_StartStop.Content = UIElements.StopDumping;
// Get the currently selected options
var driveLetterTuple = cmb_DriveLetter.SelectedItem as Tuple<char, string, bool>;
char driveLetter = driveLetterTuple.Item1;
bool isFloppy = driveLetterTuple.Item3;
string outputDirectory = txt_OutputDirectory.Text;
string outputFilename = txt_OutputFilename.Text;
var selected = cmb_DiscType.SelectedValue as Tuple<string, KnownSystem?, DiscType?>;
string systemName = selected.Item1;
KnownSystem? system = selected.Item2;
DiscType? type = selected.Item3;
string customParameters = txt_Parameters.Text;
// Validate that everything is good
if (string.IsNullOrWhiteSpace(customParameters)
|| !Utilities.Validation.ValidateParameters(customParameters)
|| (isFloppy ^ type == DiscType.Floppy))
{
lbl_Status.Content = "Error! Current configuration is not supported!";
btn_StartStop.Content = UIElements.StartDumping;
return;
}
// If we have a custom configuration, we need to extract the best possible information from it
if (systemName == "Custom Input" && system == KnownSystem.NONE && type == DiscType.NONE)
{
Utilities.Validation.DetermineFlags(customParameters, out type, out system, out string letter, out string path);
driveLetter = letter[0];
outputDirectory = Path.GetDirectoryName(path);
outputFilename = Path.GetFileName(path);
}
// Validate that the required program exits
if (!File.Exists(dicPath))
{
lbl_Status.Content = "Error! Could not find DiscImageCreator!";
btn_StartStop.Content = UIElements.StartDumping;
return;
}
// If a complete dump already exists
if (DumpInformation.FoundAllFiles(outputDirectory, outputFilename, type))
{
MessageBoxResult result = MessageBox.Show("A complete dump already exists! Are you sure you want to overwrite?", "Overwrite?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
if (result == MessageBoxResult.No || result == MessageBoxResult.Cancel || result == MessageBoxResult.None)
{
lbl_Status.Content = "Dumping aborted!";
btn_StartStop.Content = UIElements.StartDumping;
return;
}
}
lbl_Status.Content = "Beginning dumping process";
string parameters = txt_Parameters.Text;
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = dicPath,
Arguments = parameters,
},
};
childProcess.Start();
childProcess.WaitForExit();
});
// Special cases
switch (system)
{
// TODO: May not be needed anymore? DIC claims to have this functionality now
case KnownSystem.MicrosoftXBOXOne:
case KnownSystem.SonyPlayStation4:
if (!File.Exists(sgRawPath))
{
lbl_Status.Content = "Error! Could not find sg-raw!";
break;
}
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = sgRawPath,
Arguments = "-v -r 4100 -R " + driveLetter + ": " + "ad 01 00 00 00 00 00 00 10 04 00 00 -o \"PIC.bin\""
},
};
childProcess.Start();
childProcess.WaitForExit();
});
break;
case KnownSystem.SegaSaturn:
if (!File.Exists(subdumpPath))
{
lbl_Status.Content = "Error! Could not find subdump!";
break;
}
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = subdumpPath,
Arguments = "-i " + driveLetter + ": -f " + Path.Combine(outputDirectory, Path.GetFileNameWithoutExtension(outputFilename) + "_subdump.sub") + "-mode 6 -rereadnum 25 -fix 2",
},
};
childProcess.Start();
childProcess.WaitForExit();
});
break;
case KnownSystem.SonyPlayStation:
if (!File.Exists(psxtPath))
{
lbl_Status.Content = "Error! Could not find psxt001z!";
break;
}
// Invoke the program with all 3 configurations
// TODO: Use these outputs for PSX information
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = psxtPath,
Arguments = "\"" + DumpInformation.GetFirstTrack(outputDirectory, outputFilename) + "\" > " + "\"" + Path.Combine(outputDirectory, "psxt001z.txt"),
},
};
childProcess.Start();
childProcess.WaitForExit();
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = psxtPath,
Arguments = "--libcrypt \"" + Path.Combine(outputDirectory, Path.GetFileNameWithoutExtension(outputFilename) + ".sub") + "\" > \"" + Path.Combine(outputDirectory, "libcrypt.txt"),
},
};
childProcess.Start();
childProcess.WaitForExit();
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = psxtPath,
Arguments = "--libcryptdrvfast " + driveLetter + " > " + "\"" + Path.Combine(outputDirectory, "libcryptdrv.log"),
},
};
childProcess.Start();
childProcess.WaitForExit();
});
break;
}
// Check to make sure that the output had all the correct files
if (!DumpInformation.FoundAllFiles(outputDirectory, outputFilename, type))
{
lbl_Status.Content = "Error! Please check output directory as dump may be incomplete!";
btn_StartStop.Content = UIElements.StartDumping;
if (chk_EjectWhenDone.IsChecked == true)
{
EjectDisc();
}
return;
}
Dictionary<string, string> templateValues = DumpInformation.ExtractOutputInformation(outputDirectory, outputFilename, system, type, driveLetter);
List<string> formattedValues = DumpInformation.FormatOutputData(templateValues, system, type);
bool success = DumpInformation.WriteOutputData(outputDirectory, outputFilename, formattedValues);
lbl_Status.Content = "Dumping complete!";
btn_StartStop.Content = UIElements.StartDumping;
if (chk_EjectWhenDone.IsChecked == true)
{
EjectDisc();
}
}
/// <summary>
/// Cancel an in-progress dumping process
/// </summary>
private void CancelDumping()
{
try
{
childProcess.Kill();
}
catch
{ }
}
/// <summary>
/// Eject the disc using DIC
/// </summary>
private async void EjectDisc()
{
// Validate that the required program exits
if (!File.Exists(dicPath))
{
return;
}
CancelDumping();
var driveTuple = cmb_DriveLetter.SelectedItem as Tuple<char, string, bool>;
if (driveTuple.Item3)
{
return;
}
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = dicPath,
Arguments = DICCommands.Eject + " " + driveTuple.Item1,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
},
};
childProcess.Start();
childProcess.WaitForExit();
});
}
/// <summary>
/// Ensure information is consistent with the currently selected disc type
/// </summary>
private void EnsureDiscInformation()
{
// If we're on a separator, go to the next item
var tuple = cmb_DiscType.SelectedItem as Tuple<string, KnownSystem?, DiscType?>;
if (tuple.Item2 == null && tuple.Item3 == null)
{
cmb_DiscType.SelectedIndex++;
tuple = cmb_DiscType.SelectedItem as Tuple<string, KnownSystem?, DiscType?>;
}
// If we're on an unsupported type, update the status accordingly
switch (tuple.Item3)
{
case DiscType.NONE:
lbl_Status.Content = "Please select a valid disc type";
btn_StartStop.IsEnabled = false;
break;
case DiscType.GameCubeGameDisc:
case DiscType.GDROM:
lbl_Status.Content = string.Format("{0} discs are partially supported by DIC", Converters.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = true;
break;
case DiscType.HDDVD:
case DiscType.UMD:
case DiscType.WiiOpticalDisc:
case DiscType.WiiUOpticalDisc:
lbl_Status.Content = string.Format("{0} discs are not currently supported by DIC", Converters.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = false;
break;
default:
lbl_Status.Content = string.Format("{0} ready to dump", Converters.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = true;
break;
}
// If we're in a type that doesn't support drive speeds
switch (tuple.Item3)
{
case DiscType.Floppy:
case DiscType.BD25:
case DiscType.BD50:
cmb_DriveSpeed.IsEnabled = false;
break;
default:
cmb_DriveSpeed.IsEnabled = true;
break;
}
// Special case for Custom input
if (tuple.Item1 == "Custom Input" && tuple.Item2 == KnownSystem.NONE && tuple.Item3 == DiscType.NONE)
{
txt_Parameters.IsEnabled = true;
txt_OutputFilename.IsEnabled = false;
txt_OutputDirectory.IsEnabled = false;
btn_OutputDirectoryBrowse.IsEnabled = false;
cmb_DriveLetter.IsEnabled = false;
cmb_DriveSpeed.IsEnabled = false;
btn_StartStop.IsEnabled = true;
lbl_Status.Content = "User input mode";
}
else
{
txt_Parameters.IsEnabled = false;
txt_OutputFilename.IsEnabled = true;
txt_OutputDirectory.IsEnabled = true;
btn_OutputDirectoryBrowse.IsEnabled = true;
cmb_DriveLetter.IsEnabled = true;
cmb_DriveSpeed.IsEnabled = true;
// Populate with the correct params for inputs (if we're not on the default option)
if (cmb_DiscType.SelectedIndex > 0)
{
var selected = cmb_DiscType.SelectedValue as Tuple<string, KnownSystem?, DiscType?>;
var driveletter = cmb_DriveLetter.SelectedValue as Tuple<char, string, bool>;
// If either item is invalid, skip this
if (selected == null || driveletter == null)
{
return;
}
string discType = Converters.DiscTypeToBaseCommand(selected.Item3);
List<string> defaultParams = Converters.KnownSystemAndDiscTypeToParameters(selected.Item2, selected.Item3);
txt_Parameters.Text = discType
+ " " + driveletter.Item1
+ " \"" + Path.Combine(txt_OutputDirectory.Text, txt_OutputFilename.Text) + "\" "
+ (selected.Item3 != DiscType.Floppy
&& selected.Item3 != DiscType.BD25
&& selected.Item3 != DiscType.BD50
&& selected.Item2 != KnownSystem.MicrosoftXBOX
&& selected.Item2 != KnownSystem.MicrosoftXBOX360
? (int)cmb_DriveSpeed.SelectedItem + " " : "")
+ string.Join(" ", defaultParams);
}
}
}
/// <summary>
/// Get the default output directory name from the currently selected drive
/// </summary>
private void GetOutputNames()
{
var driveTuple = cmb_DriveLetter.SelectedItem as Tuple<char, string, bool>;
var discTuple = cmb_DiscType.SelectedItem as Tuple<string, KnownSystem?, DiscType?>;
if (driveTuple != null && discTuple != null)
{
txt_OutputDirectory.Text = Path.Combine(defaultOutputPath, driveTuple.Item2);
txt_OutputFilename.Text = driveTuple.Item2 + Converters.DiscTypeToExtension(discTuple.Item3);
}
else
{
txt_OutputDirectory.Text = defaultOutputPath;
txt_OutputFilename.Text = "disc.bin";
}
}
/// <summary>
/// Get the highest supported drive speed as reported by DiscImageCreator
/// </summary>
private void SetSupportedDriveSpeed()
{
// Get the drive letter from the selected item
var selected = cmb_DriveLetter.SelectedItem as Tuple<char, string, bool>;
if (selected == null || selected.Item3)
{
return;
}
// Validate that the required program exits
if (!File.Exists(dicPath))
{
return;
}
char driveLetter = selected.Item1;
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = dicPath,
Arguments = DICCommands.DriveSpeed + " " + driveLetter,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
},
};
childProcess.Start();
childProcess.WaitForExit();
string output = childProcess.StandardOutput.ReadToEnd();
int index = output.IndexOf("ReadSpeedMaximum:");
string readspeed = Regex.Match(output.Substring(index), @"ReadSpeedMaximum: [0-9]+KB/sec \(([0-9]*)x\)").Groups[1].Value;
if (!Int32.TryParse(readspeed, out int speed))
{
return;
}
cmb_DriveSpeed.SelectedValue = speed;
}
/// <summary>
/// Show all user-configurable settings in a new window
/// </summary>
private void ShowSettings()
{
// Create the child window for settings
childWindow = new Window()
{
ShowInTaskbar = false,
Owner = Application.Current.MainWindow,
Width = 500,
Height = 250,
ResizeMode = ResizeMode.NoResize,
};
// Create the new Grid-based window
var grid = new Grid
{
Margin = new Thickness(5),
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
};
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = (GridLength)(new GridLengthConverter().ConvertFromString(String.Format("{0:n1}*", 1.2))) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = (GridLength)(new GridLengthConverter().ConvertFromString(String.Format("{0:n1}*", 2.5))) });
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
// Create all of the individual items in the panel
Label dicPathLabel = new Label();
dicPathLabel.Content = "DiscImageCreator Path:";
dicPathLabel.FontWeight = (FontWeight)(new FontWeightConverter().ConvertFromString("Bold"));
dicPathLabel.VerticalAlignment = VerticalAlignment.Center;
dicPathLabel.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetRow(dicPathLabel, 0);
Grid.SetColumn(dicPathLabel, 0);
TextBox dicPathSetting = new TextBox();
dicPathSetting.Text = ConfigurationManager.AppSettings["dicPath"];
dicPathSetting.VerticalAlignment = VerticalAlignment.Center;
dicPathSetting.HorizontalAlignment = HorizontalAlignment.Stretch;
Grid.SetRow(dicPathSetting, 0);
Grid.SetColumn(dicPathSetting, 1);
Label psxt001zPathLabel = new Label();
psxt001zPathLabel.Content = "psxt001z Path:";
psxt001zPathLabel.FontWeight = (FontWeight)(new FontWeightConverter().ConvertFromString("Bold"));
psxt001zPathLabel.VerticalAlignment = VerticalAlignment.Center;
psxt001zPathLabel.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetRow(psxt001zPathLabel, 1);
Grid.SetColumn(psxt001zPathLabel, 0);
TextBox psxt001zPathSetting = new TextBox();
psxt001zPathSetting.Text = ConfigurationManager.AppSettings["psxt001zPath"];
psxt001zPathSetting.VerticalAlignment = VerticalAlignment.Center;
psxt001zPathSetting.HorizontalAlignment = HorizontalAlignment.Stretch;
Grid.SetRow(psxt001zPathSetting, 1);
Grid.SetColumn(psxt001zPathSetting, 1);
Label sgRawPathLabel = new Label();
sgRawPathLabel.Content = "sg-raw Path:";
sgRawPathLabel.FontWeight = (FontWeight)(new FontWeightConverter().ConvertFromString("Bold"));
sgRawPathLabel.VerticalAlignment = VerticalAlignment.Center;
sgRawPathLabel.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetRow(sgRawPathLabel, 2);
Grid.SetColumn(sgRawPathLabel, 0);
TextBox sgRawPathSetting = new TextBox();
sgRawPathSetting.Text = ConfigurationManager.AppSettings["sgRawPath"];
sgRawPathSetting.VerticalAlignment = VerticalAlignment.Center;
sgRawPathSetting.HorizontalAlignment = HorizontalAlignment.Stretch;
Grid.SetRow(sgRawPathSetting, 2);
Grid.SetColumn(sgRawPathSetting, 1);
Label subdumpPathLabel = new Label();
subdumpPathLabel.Content = "subdump Path:";
subdumpPathLabel.FontWeight = (FontWeight)(new FontWeightConverter().ConvertFromString("Bold"));
subdumpPathLabel.VerticalAlignment = VerticalAlignment.Center;
subdumpPathLabel.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetRow(subdumpPathLabel, 3);
Grid.SetColumn(subdumpPathLabel, 0);
TextBox subdumpPathSetting = new TextBox();
subdumpPathSetting.Text = ConfigurationManager.AppSettings["subdumpPath"];
subdumpPathSetting.VerticalAlignment = VerticalAlignment.Center;
subdumpPathSetting.HorizontalAlignment = HorizontalAlignment.Stretch;
Grid.SetRow(subdumpPathSetting, 3);
Grid.SetColumn(subdumpPathSetting, 1);
Label defaultOutputPathLabel = new Label();
defaultOutputPathLabel.Content = "Default Output Path:";
defaultOutputPathLabel.FontWeight = (FontWeight)(new FontWeightConverter().ConvertFromString("Bold"));
defaultOutputPathLabel.VerticalAlignment = VerticalAlignment.Center;
defaultOutputPathLabel.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetRow(defaultOutputPathLabel, 4);
Grid.SetColumn(defaultOutputPathLabel, 0);
TextBox defaultOutputPathSetting = new TextBox();
defaultOutputPathSetting.Text = ConfigurationManager.AppSettings["defaultOutputPath"];
defaultOutputPathSetting.VerticalAlignment = VerticalAlignment.Center;
defaultOutputPathSetting.HorizontalAlignment = HorizontalAlignment.Stretch;
Grid.SetRow(defaultOutputPathSetting, 4);
Grid.SetColumn(defaultOutputPathSetting, 1);
var buttonGrid = new Grid
{
Margin = new Thickness(5),
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
};
buttonGrid.ColumnDefinitions.Add(new ColumnDefinition());
buttonGrid.ColumnDefinitions.Add(new ColumnDefinition());
buttonGrid.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(buttonGrid, 5);
Grid.SetColumn(buttonGrid, 0);
Grid.SetColumnSpan(buttonGrid, 2);
Button acceptButton = new Button();
acceptButton.Name = "btn_Settings_Accept";
acceptButton.Content = "Accept";
acceptButton.Click += btn_Settings_Accept_Click;
acceptButton.VerticalAlignment = VerticalAlignment.Center;
acceptButton.HorizontalAlignment = HorizontalAlignment.Center;
Grid.SetRow(acceptButton, 0);
Grid.SetColumn(acceptButton, 0);
Button cancelButton = new Button();
cancelButton.Name = "btn_Settings_Cancel";
cancelButton.Content = "Cancel";
cancelButton.Click += btn_Settings_Cancel_Click;
cancelButton.VerticalAlignment = VerticalAlignment.Center;
cancelButton.HorizontalAlignment = HorizontalAlignment.Center;
Grid.SetRow(cancelButton, 0);
Grid.SetColumn(cancelButton, 1);
buttonGrid.Children.Add(acceptButton);
buttonGrid.Children.Add(cancelButton);
// Add all of the UI elements
grid.Children.Add(dicPathLabel);
grid.Children.Add(dicPathSetting);
grid.Children.Add(psxt001zPathLabel);
grid.Children.Add(psxt001zPathSetting);
grid.Children.Add(sgRawPathLabel);
grid.Children.Add(sgRawPathSetting);
grid.Children.Add(subdumpPathLabel);
grid.Children.Add(subdumpPathSetting);
grid.Children.Add(defaultOutputPathLabel);
grid.Children.Add(defaultOutputPathSetting);
grid.Children.Add(buttonGrid);
// Now show the child window
childWindow.Content = grid;
childWindow.Show();
}
/// <summary>
/// Save settings from the child window, if possible
/// </summary>
private void SaveSettings()
{
// If the child window is disposed, we don't think about it
if (childWindow == null)
{
return;
}
// Clear the old settings and set new ones
var configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
configFile.AppSettings.Settings.Remove("dicPath");
configFile.AppSettings.Settings.Add("dicPath", ((TextBox)(((Grid)childWindow.Content).Children[1])).Text);
configFile.AppSettings.Settings.Remove("psxt001zPath");
configFile.AppSettings.Settings.Add("psxt001zPath", ((TextBox)(((Grid)childWindow.Content).Children[3])).Text);
configFile.AppSettings.Settings.Remove("sgRawPath");
configFile.AppSettings.Settings.Add("sgRawPath", ((TextBox)(((Grid)childWindow.Content).Children[5])).Text);
configFile.AppSettings.Settings.Remove("subdumpPath");
configFile.AppSettings.Settings.Add("subdumpPath", ((TextBox)(((Grid)childWindow.Content).Children[7])).Text);
configFile.AppSettings.Settings.Remove("defaultOutputPath");
configFile.AppSettings.Settings.Add("defaultOutputPath", ((TextBox)(((Grid)childWindow.Content).Children[9])).Text);
configFile.Save(ConfigurationSaveMode.Modified);
}
/// <summary>
/// Get settings from the configuration, if possible
/// </summary>
private void GetSettings()
{
dicPath = ConfigurationManager.AppSettings["dicPath"] ?? "Programs\\DiscImageCreator.exe";
psxtPath = ConfigurationManager.AppSettings["psxt001zPath"] ?? "psxt001z.exe";
sgRawPath = ConfigurationManager.AppSettings["sgRawPath"] ?? "sg_raw.exe";
subdumpPath = ConfigurationManager.AppSettings["subdumpPath"] ?? "subdump.exe";
defaultOutputPath = ConfigurationManager.AppSettings["defaultOutputPath"] ?? "ISO";
}
#endregion
}
}

109
README.md
View File

@@ -1,102 +1,49 @@
# DICUI
This is my current progress on my C# Disc Image Creator UI.
I am using Disc Image Creator, created by Sarami, and would like to thanks him for this great software.
DiscImageCreator UI in C#
You can get the latest code and released on his github right here:
https://github.com/saramibreak/DiscImageCreator
[![Build status](https://ci.appveyor.com/api/projects/status/3ldav3v0c373jeqa?svg=true)](https://ci.appveyor.com/project/mnadareski/dicui)
I'm a hobbyist programmer, so this code might not be optimal, feel free to make your recommendation / Pull request.
This is a community project, so if you have some time and knowledge to give, we'll be glad to add you to the contributor of this project :)
I would like this project to be a community project, so if you have some time and knowledge to give, I'll be glad to add you to the contributor of this project :)
We are using DiscImageCreator (DIC), created by Sarami, and we would like to thanks him for his great software. The latest release of DIC can be found on [the GitHub page](https://github.com/saramibreak/DiscImageCreator)
--------------------------------------------------------------------------
Currently working on the project:
ReignStumble - Co-Lead Programmer
This project relies on two open-source code ports to help perform copy protection scanning: [BurnOutSharp](https://github.com/mnadareski/BurnOutSharp) and [UnshieldSharp](https://github.com/mnadareski/UnshieldSharp)
darksabre76 - Co-Lead Programmer
## System Requirements
NHellFire - Contributer
Even though this is written in C#, this program can only be used on Windows systems due to the base program, DiscImageCreator, being Windows-only.
Dizzzy - Concept/Ideas/Beta tester
- Windows 7 (newest version of Windows recommended)
- .NET Framework 4.6.1 Runtimes
- 128 MB of free RAM
- As much hard drive space as amount of discs you will be dumping (20+ GB recommended)
## Changelist
Ensure that your operating system is as up-to-date as possible, since some features may rely on those updates.
## Releases
Download the latest release here:
[https://github.com/reignstumble/DICUI/releases](https://github.com/reignstumble/DICUI/releases)
--------------------------------------------------------------------------
2018-06-14
--------------------------------------------------------------------------
## Changelist
Version 1.05a released:
A list of all changes can now be found [here](https://github.com/reignstumble/DICUI/blob/master/CHANGELIST.md).
- Fixed some ordering and nullability issues
- Added automatic fields for PS1, PS2, Saturn
## Contributors
Version 1.05 released:
Here are the talented people who have contributed to the project so far:
- 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
- **ReignStumble** - Project Lead / UI Design
- **darksabre76** - Project Co-Lead / Backend Design
- **Jakz** - Primary Feature Contributor
- **NHellFire** - Feature Contributor
**Known Issues:**
## Notable Testers
- PlayStation and Saturn discs still don't have all internal information automatically generated
These are the tireless individuals who have dedicated countless hours to help test the many features of DICUI and have worked with the development team closely:
--------------------------------------------------------------------------
2018-06-13
--------------------------------------------------------------------------
Version 1.04b released:
- Added subIntention reading
- Fixed extra extensions being appended
- Fixed internationalization error (number formatting)
- Fixed "Custom Input" not working
Version 1.04a released:
- Fixed issue with empty trays
- Added settings dialog
Version 1.04 released:
- 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
--------------------------------------------------------------------------
2018-06-08
--------------------------------------------------------------------------
Version 1.03 released:
- edccchk now run on all CD-Roms
- Discs unsupported by Windows are now regonized
- Extra \ when accepting default save has been removed.
--------------------------------------------------------------------------
2018-05-18
--------------------------------------------------------------------------
Version 1.02b released:
- Fixed XBOX One and PS4 Drive Speed issue. (1.02)
- Started implementing DiscImageCreator Path selection. (1.02)
- Conforming my naming for objects and variable. (1.02)
- Added missing DLL (1.02b)
--------------------------------------------------------------------------
2018-05-14
--------------------------------------------------------------------------
Version 1.01d released
- **Dizzzy/user7** - Concept, ideas, tester
- **Kludge** - Primary stress tester
- **ajshell1** - Tester
- **eientei95** - Tester

View File

@@ -1,894 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace DICUI.Utilities
{
public static class DumpInformation
{
/// <summary>
/// Attempts to find the first track of a dumped disc based on the inputs
/// </summary>
/// <param name="outputDirectory">Base directory to use</param>
/// <param name="outputFilename">Base filename to use</param>
/// <returns>Proper path to first track, null on error</returns>
/// <remarks>
/// By default, this assumes that the outputFilename doesn't contain a proper path, and just a name.
/// This can lead to a situation where the outputFilename contains a path, but only the filename gets
/// used in the processing and can lead to a "false null" return
/// </remarks>
public static string GetFirstTrack(string outputDirectory, string outputFilename)
{
// First, sanitized the output filename to strip off any potential extension
outputFilename = Path.GetFileNameWithoutExtension(outputFilename);
// Go through all standard output naming schemes
string combinedBase = Path.Combine(outputDirectory, outputFilename);
if (File.Exists(combinedBase + ".bin"))
{
return combinedBase + ".bin";
}
if (File.Exists(combinedBase + " (Track 1).bin"))
{
return combinedBase + " (Track 1).bin";
}
if (File.Exists(combinedBase + " (Track 01).bin"))
{
return combinedBase + " (Track 01).bin";
}
if (File.Exists(combinedBase + ".iso"))
{
return Path.Combine(combinedBase + ".iso");
}
return null;
}
/// <summary>
/// Ensures that all required output files have been created
/// </summary>
/// <param name="outputDirectory">Base directory to use</param>
/// <param name="outputFilename">Base filename to use</param>
/// <param name="type">DiscType value to check</param>
/// <returns></returns>
public static bool FoundAllFiles(string outputDirectory, string outputFilename, DiscType? type)
{
// First, sanitized the output filename to strip off any potential extension
outputFilename = Path.GetFileNameWithoutExtension(outputFilename);
// Now ensure that all required files exist
string combinedBase = Path.Combine(outputDirectory, outputFilename);
switch (type)
{
case DiscType.CD:
case DiscType.GDROM: // TODO: Verify GD-ROM outputs this
return File.Exists(combinedBase + ".c2")
&& File.Exists(combinedBase + ".ccd")
&& File.Exists(combinedBase + ".cue")
&& File.Exists(combinedBase + ".dat")
&& File.Exists(combinedBase + ".img")
&& File.Exists(combinedBase + ".img_EdcEcc.txt")
&& File.Exists(combinedBase + ".scm")
&& File.Exists(combinedBase + ".sub")
&& File.Exists(combinedBase + "_c2Error.txt")
&& File.Exists(combinedBase + "_cmd.txt")
&& File.Exists(combinedBase + "_disc.txt")
&& File.Exists(combinedBase + "_drive.txt")
&& File.Exists(combinedBase + "_img.cue")
&& File.Exists(combinedBase + "_mainError.txt")
&& File.Exists(combinedBase + "_mainInfo.txt")
&& File.Exists(combinedBase + "_subError.txt")
&& File.Exists(combinedBase + "_subInfo.txt")
&& File.Exists(combinedBase + "_subIntention.txt")
&& File.Exists(combinedBase + "_subReadable.txt")
&& File.Exists(combinedBase + "_volDesc.txt");
case DiscType.DVD5:
case DiscType.DVD9:
case DiscType.HDDVD:
case DiscType.BD25:
case DiscType.BD50:
case DiscType.GameCubeGameDisc:
case DiscType.WiiOpticalDisc:
case DiscType.WiiUOpticalDisc:
case DiscType.UMD:
return File.Exists(combinedBase + ".dat")
&& File.Exists(combinedBase + "_cmd.txt")
&& File.Exists(combinedBase + "_disc.txt")
&& File.Exists(combinedBase + "_drive.txt")
&& File.Exists(combinedBase + "_mainError.txt")
&& File.Exists(combinedBase + "_mainInfo.txt")
&& File.Exists(combinedBase + "_volDesc.txt");
case DiscType.Floppy:
return File.Exists(combinedBase + ".dat")
&& File.Exists(combinedBase + "_cmd.txt")
&& File.Exists(combinedBase + "_disc.txt");
default:
// Non-dumping commands will usually produce no output, so this is irrelevant
return true;
}
}
/// <summary>
/// Extract all of the possible information from a given input combination
/// </summary>
/// <param name="outputDirectory">Base directory to use</param>
/// <param name="outputFilename">Base filename to use</param>
/// <param name="sys">KnownSystem value to check</param>
/// <param name="type">DiscType value to check</param>
/// <param name="driveLetter">Drive letter to check</param>
/// <returns>Dictionary containing mapped output values, null on error</returns>
/// <remarks>TODO: Make sure that all special formats are accounted for</remarks>
public static Dictionary<string, string> ExtractOutputInformation(string outputDirectory, string outputFilename, KnownSystem? sys, DiscType? type, char driveLetter)
{
// First, sanitized the output filename to strip off any potential extension
outputFilename = Path.GetFileNameWithoutExtension(outputFilename);
// First, we want to check that all of the relevant files are there
if (!FoundAllFiles(outputDirectory, outputFilename, type))
{
return null;
}
// Create the output dictionary with all user-inputted values by default
string combinedBase = Path.Combine(outputDirectory, outputFilename);
Dictionary<string, string> mappings = new Dictionary<string, string>
{
{ Template.TitleField, Template.RequiredValue },
{ Template.DiscNumberField, Template.OptionalValue },
{ Template.DiscTitleField, Template.OptionalValue },
{ Template.CategoryField, "Games" },
{ Template.RegionField, "World (CHANGE THIS)" },
{ Template.LanguagesField, "Klingon (CHANGE THIS)" },
{ Template.DiscSerialField, Template.RequiredIfExistsValue },
{ Template.BarcodeField, Template.OptionalValue},
{ Template.CommentsField, Template.OptionalValue },
{ Template.ContentsField, Template.OptionalValue },
{ Template.VersionField, Template.RequiredIfExistsValue },
{ Template.EditionField, "Original (VERIFY THIS)" },
{ Template.DATField, GetDatfile(combinedBase + ".dat") },
};
// Now we want to do a check by DiscType and extract all required info
switch (type)
{
case DiscType.CD:
case DiscType.GDROM: // TODO: Verify GD-ROM outputs this
mappings[Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings[Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings[Template.MouldSIDField] = Template.RequiredIfExistsValue;
mappings[Template.AdditionalMouldField] = Template.RequiredIfExistsValue;
mappings[Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings[Template.PVDField] = GetPVD(combinedBase + "_mainInfo.txt");
mappings[Template.ErrorCountField] = GetErrorCount(combinedBase + ".img_EdcEcc.txt",
combinedBase + "_c2Error.txt",
combinedBase + "_mainError.txt").ToString();
mappings[Template.CuesheetField] = GetFullFile(combinedBase + ".cue");
mappings[Template.WriteOffsetField] = GetWriteOffset(combinedBase + "_disc.txt");
// System-specific options
switch (sys)
{
case KnownSystem.AppleMacintosh:
case KnownSystem.IBMPCCompatible:
mappings[Template.ISBNField] = Template.OptionalValue;
mappings[Template.CopyProtectionField] = Template.RequiredIfExistsValue;
if (File.Exists(combinedBase + "_subIntention.txt"))
{
FileInfo fi = new FileInfo(combinedBase + "_subIntention.txt");
if (fi.Length > 0)
{
mappings[Template.SubIntentionField] = GetFullFile(combinedBase + "_subIntention.txt");
}
}
break;
case KnownSystem.SegaSaturn:
mappings[Template.SaturnHeaderField] = GetSaturnHeader(GetFirstTrack(outputDirectory, outputFilename)).ToString();
if (GetSaturnBuildInfo(mappings[Template.SaturnHeaderField], out string serial, out string version, out string buildDate))
{
mappings[Template.DiscSerialField] = serial;
mappings[Template.VersionField] = version;
mappings[Template.SaturnBuildDateField] = buildDate;
}
break;
case KnownSystem.SonyPlayStation:
mappings[Template.PlaystationEXEDateField] = GetPlayStationEXEDate(driveLetter);
mappings[Template.PlayStationEDCField] = Template.YesNoValue;
mappings[Template.PlayStationAntiModchipField] = Template.YesNoValue;
mappings[Template.PlayStationLibCryptField] = Template.YesNoValue;
break;
case KnownSystem.SonyPlayStation2:
mappings[Template.PlaystationEXEDateField] = GetPlayStationEXEDate(driveLetter);
mappings[Template.VersionField] = GetPlayStation2Version(driveLetter);
break;
}
break;
case DiscType.DVD5: // TODO: Add XBOX360-specific outputs to this
case DiscType.HDDVD:
case DiscType.BD25:
mappings[Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings[Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings[Template.MouldSIDField] = Template.RequiredIfExistsValue;
mappings[Template.AdditionalMouldField] = Template.RequiredIfExistsValue;
mappings[Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings[Template.PVDField] = GetPVD(combinedBase + "_mainInfo.txt");
// System-specific options
switch (sys)
{
case KnownSystem.AppleMacintosh:
case KnownSystem.IBMPCCompatible:
mappings[Template.ISBNField] = Template.OptionalValue;
mappings[Template.CopyProtectionField] = Template.RequiredIfExistsValue;
if (File.Exists(combinedBase + "_subIntention.txt"))
{
FileInfo fi = new FileInfo(combinedBase + "_subIntention.txt");
if (fi.Length > 0)
{
mappings[Template.SubIntentionField] = GetFullFile(combinedBase + "_subIntention.txt");
}
}
break;
case KnownSystem.MicrosoftXBOX:
mappings[Template.XBOXDMICRC] = Template.RequiredValue;
mappings[Template.XBOXPFICRC] = Template.RequiredValue;
mappings[Template.XBOXSSCRC] = Template.RequiredValue;
mappings[Template.XBOXSSRanges] = Template.RequiredValue;
break;
case KnownSystem.SonyPlayStation2:
mappings[Template.PlaystationEXEDateField] = GetPlayStationEXEDate(driveLetter);
mappings[Template.VersionField] = GetPlayStation2Version(driveLetter);
break;
}
break;
case DiscType.DVD9: // TODO: Add XBOX360-specific outputs to this
case DiscType.BD50:
mappings["Outer " + Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings["Inner " + Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings["Outer " + Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings["Inner " + Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings[Template.MouldSIDField] = Template.RequiredIfExistsValue;
mappings[Template.AdditionalMouldField] = Template.RequiredIfExistsValue;
mappings["Outer " + Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings["Inner " + Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings[Template.PVDField] = GetPVD(combinedBase + "_mainInfo.txt");
mappings[Template.LayerbreakField] = GetLayerbreak(combinedBase + "_disc.txt");
// System-specific options
switch (sys)
{
case KnownSystem.AppleMacintosh:
case KnownSystem.IBMPCCompatible:
mappings[Template.ISBNField] = Template.OptionalValue;
mappings[Template.CopyProtectionField] = Template.RequiredIfExistsValue;
if (File.Exists(combinedBase + "_subIntention.txt"))
{
FileInfo fi = new FileInfo(combinedBase + "_subIntention.txt");
if (fi.Length > 0)
{
mappings[Template.SubIntentionField] = GetFullFile(combinedBase + "_subIntention.txt");
}
}
break;
case KnownSystem.MicrosoftXBOX:
mappings[Template.XBOXDMICRC] = Template.RequiredValue;
mappings[Template.XBOXPFICRC] = Template.RequiredValue;
mappings[Template.XBOXSSCRC] = Template.RequiredValue;
mappings[Template.XBOXSSRanges] = Template.RequiredValue;
break;
case KnownSystem.SonyPlayStation2:
mappings[Template.PlaystationEXEDateField] = GetPlayStationEXEDate(driveLetter);
mappings[Template.VersionField] = GetPlayStation2Version(driveLetter);
break;
}
break;
}
return mappings;
}
/// <summary>
/// Get the full lines from the input file, if possible
/// </summary>
/// <param name="filename">file location</param>
/// <returns>Full text of the file, null on error</returns>
private static string GetFullFile(string filename)
{
// If the file doesn't exist, we can't get info from it
if (!File.Exists(filename))
{
return null;
}
return string.Join("\n", File.ReadAllLines(filename));
}
/// <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 detected error count from the input files, if possible
/// </summary>
/// <param name="edcecc">.img_EdcEcc.txt file location</param>
/// <param name="c2Error">_c2Error.txt file location</param>
/// <param name="mainError">_mainError.txt file location</param>
/// <returns>Error count if possible, -1 on error</returns>
private static long GetErrorCount(string edcecc, string c2Error, string mainError)
{
// If one of the files doesn't exist, we can't get info from them
if (!File.Exists(edcecc) || !File.Exists(c2Error) || !File.Exists(mainError))
{
return -1;
}
// First off, if the mainError file has any contents, we have an uncorrectable error
if (new FileInfo(mainError).Length > 0)
{
return -1;
}
// First line of defense is the EdcEcc error file
using (StreamReader sr = File.OpenText(edcecc))
{
try
{
// Fast forward to the PVD
string line = sr.ReadLine();
while (!line.StartsWith("[NO ERROR]")
&& !line.StartsWith("Total errors:"))
{
line = sr.ReadLine();
}
// Now that we're at the error line, determine what the value should be
if (line.StartsWith("[NO ERROR]"))
{
return 0;
}
else if (line.StartsWith("Total errors:"))
{
return Int64.Parse(line.Remove(0, 14));
}
return -1;
}
catch
{
// We don't care what the exception is right now
return -1;
}
}
}
/// <summary>
/// Get the layerbreak from the input file, if possible
/// </summary>
/// <param name="disc">_disc.txt file location</param>
/// <returns>Layerbreak if possible, null on error</returns>
private static string GetLayerbreak(string disc)
{
// If the file doesn't exist, we can't get info from it
if (!File.Exists(disc))
{
return null;
}
using (StreamReader sr = File.OpenText(disc))
{
try
{
// Make sure this file is a _disc.txt
if (sr.ReadLine() != "========== DiscStructure ==========")
{
return null;
}
// Fast forward to the layerbreak
while (!sr.ReadLine().Trim().StartsWith("EndDataSector")) ;
// Now that we're at the layerbreak line, attempt to get the decimal version
return sr.ReadLine().Split(' ')[1];
}
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 this file is a _mainInfo.txt
if (sr.ReadLine() != "========== LBA[000016, 0x00010]: Main Channel ==========")
{
return null;
}
// 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 = sr.ReadLine() + "\n"; // 0320
pvd += sr.ReadLine() + "\n"; // 0330
pvd += sr.ReadLine() + "\n"; // 0340
pvd += sr.ReadLine() + "\n"; // 0350
pvd += sr.ReadLine() + "\n"; // 0360
pvd += sr.ReadLine() + "\n"; // 0370
return pvd;
}
catch
{
// We don't care what the exception is right now
return null;
}
}
}
/// <summary>
/// Get the EXE date from a PlayStation disc, if possible
/// </summary>
/// <param name="driveLetter">Drive letter to use to check</param>
/// <returns>EXE date in "yyyy-mm-dd" format if possible, null on error</returns>
private static string GetPlayStationEXEDate(char driveLetter)
{
// 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 SYSTEM.CNF, we don't have a PlayStation disc
string systemCnfPath = Path.Combine(drivePath, "SYSTEM.CNF");
if (!File.Exists(systemCnfPath))
{
return null;
}
// Let's try reading SYSTEM.CNF to find the "BOOT" value
string exeName = null;
try
{
using (StreamReader sr = File.OpenText(systemCnfPath))
{
// Not assuming proper ordering, just in case
string line = sr.ReadLine();
while (!line.StartsWith("BOOT"))
{
line = sr.ReadLine();
}
// Once it finds the "BOOT" line, extract the name
exeName = Regex.Match(line, @"BOOT.? = cdrom.?:\\(.*?);.*").Groups[1].Value;
}
}
catch
{
// We don't care what the error was
return null;
}
// 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 null;
}
FileInfo fi = new FileInfo(exePath);
return fi.LastWriteTimeUtc.ToString("yyyy-MM-dd");
}
/// <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>
private static string GetPlayStation2Version(char driveLetter)
{
// 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 SYSTEM.CNF, we don't have a PlayStation disc
string systemCnfPath = Path.Combine(drivePath, "SYSTEM.CNF");
if (!File.Exists(systemCnfPath))
{
return null;
}
// Let's try reading SYSTEM.CNF to find the "VER" value
try
{
using (StreamReader sr = File.OpenText(systemCnfPath))
{
// Not assuming proper ordering, just in case
string line = sr.ReadLine();
while (!line.StartsWith("VER"))
{
line = sr.ReadLine();
}
// Once it finds the "VER" line, extract the version
return Regex.Match(line, @"VER = (.*)").Groups[1].Value;
}
}
catch
{
// We don't care what the error was
return null;
}
}
/// <summary>
/// Get the header from a Saturn disc, if possible
/// </summary>
/// <param name="firstTrackPath">Path to the first track to check</param>
/// <returns>Header as a byte array if possible, null on error</returns>
private static string GetSaturnHeader(string firstTrackPath)
{
// If the file doesn't exist, we can't get the header
if (!File.Exists(firstTrackPath))
{
return null;
}
// Try to open the file and read the correct number of bytes
try
{
using (BinaryReader br = new BinaryReader(File.OpenRead(firstTrackPath)))
{
br.ReadBytes(0x10);
byte[] headerBytes = br.ReadBytes(0x100);
// Now format the bytes in a way we like
string headerString = "";
int ptr = 0;
while (ptr < headerBytes.Length)
{
byte[] sub = new byte[16];
Array.Copy(headerBytes, ptr, sub, 0, 16);
headerString += ptr.ToString("X").PadLeft(4, '0') + " : "
+ BitConverter.ToString(sub).Replace("-", " ") + " "
+ Encoding.ASCII.GetString(sub) + "\n";
ptr += 16;
}
return headerString.TrimEnd('\n');
}
}
catch
{
// We don't care what the error was
return null;
}
}
/// <summary>
/// Get the build info from a Saturn disc, if possible
/// </summary>
/// <<param name="saturnHeader">String representing a formatter variant of the Saturn header</param>
/// <returns>True on successful extraction of info, false otherwise</returns>
private static bool GetSaturnBuildInfo(string saturnHeader, out string serial, out string version, out string date)
{
serial = null; version = null; date = null;
// If the input header is null, we can't do a thing
if (String.IsNullOrWhiteSpace(saturnHeader))
{
return false;
}
// Now read it in cutting it into lines for easier parsing
try
{
string[] header = saturnHeader.Split('\n');
string serialVersionLine = header[2].Substring(57);
string dateLine = header[3].Substring(57);
serial = serialVersionLine.Substring(0, 8);
version = serialVersionLine.Substring(10, 6);
date = dateLine.Substring(0, 8);
return true;
}
catch
{
// We don't care what the error is
return false;
}
}
/// <summary>
/// Get the write offset from the input file, if possible
/// </summary>
/// <param name="disc">_disc.txt file location</param>
/// <returns>Sample write offset if possible, null on error</returns>
private static string GetWriteOffset(string disc)
{
// If the file doesn't exist, we can't get info from it
if (!File.Exists(disc))
{
return null;
}
using (StreamReader sr = File.OpenText(disc))
{
try
{
// Make sure this file is a _disc.txt
if (sr.ReadLine() != "========== TOC ==========")
{
return null;
}
// Fast forward to the offsets
while (!sr.ReadLine().Trim().StartsWith("========== Offset")) ;
sr.ReadLine(); // Combined Offset
sr.ReadLine(); // Drive Offset
sr.ReadLine(); // Separator line
// Now that we're at the offsets, attempt to get the sample offset
return sr.ReadLine().Split(' ').LastOrDefault();
}
catch
{
// We don't care what the exception is right now
return null;
}
}
}
/// <summary>
/// Format the output data in a human readable way, separating each printed line into a new item in the list
/// </summary>
/// <param name="info">Information dictionary that should contain normalized values</param>
/// <param name="sys">KnownSystem value to check</param>
/// <param name="type">DiscType value to check</param>
/// <returns>List of strings representing each line of an output file, null on error</returns>
/// <remarks>TODO: Get full list of customizable stuff for other systems</remarks>
public static List<string> FormatOutputData(Dictionary<string, string> info, KnownSystem? sys, DiscType? type)
{
// Check to see if the inputs are valid
if (info == null)
{
return null;
}
try
{
List<string> output = new List<string>();
output.Add(Template.TitleField + ": " + info[Template.TitleField]);
output.Add(Template.DiscNumberField + ": " + info[Template.DiscNumberField]);
output.Add(Template.DiscTitleField + ": " + info[Template.DiscTitleField]);
output.Add(Template.CategoryField + ": " + info[Template.CategoryField]);
output.Add(Template.RegionField + ": " + info[Template.RegionField]);
output.Add(Template.LanguagesField + ": " + info[Template.LanguagesField]);
output.Add(Template.DiscSerialField + ": " + info[Template.DiscSerialField]);
switch (sys)
{
case KnownSystem.SegaSaturn:
output.Add(Template.SaturnBuildDateField + ": " + info[Template.SaturnBuildDateField]);
break;
case KnownSystem.SonyPlayStation:
case KnownSystem.SonyPlayStation2:
output.Add(Template.PlaystationEXEDateField + ": " + info[Template.PlaystationEXEDateField]);
break;
}
output.Add("Ringcode Information:");
switch (type)
{
case DiscType.CD:
case DiscType.GDROM:
case DiscType.DVD5:
case DiscType.HDDVD:
case DiscType.BD25:
output.Add("\t" + Template.MasteringRingField + ": " + info[Template.MasteringRingField]);
output.Add("\t" + Template.MasteringSIDField + ": " + info[Template.MasteringSIDField]);
output.Add("\t" + Template.MouldSIDField + ": " + info[Template.MouldSIDField]);
output.Add("\t" + Template.AdditionalMouldField + ": " + info[Template.AdditionalMouldField]);
output.Add("\t" + Template.ToolstampField + ": " + info[Template.ToolstampField]);
break;
case DiscType.DVD9:
case DiscType.BD50:
output.Add("\tOuter " + Template.MasteringRingField + ": " + info["Outer " + Template.MasteringRingField]);
output.Add("\tInner " + Template.MasteringRingField + ": " + info["Inner " + Template.MasteringRingField]);
output.Add("\tOuter " + Template.MasteringSIDField + ": " + info["Outer " + Template.MasteringSIDField]);
output.Add("\tInner " + Template.MasteringSIDField + ": " + info["Inner " + Template.MasteringSIDField]);
output.Add("\t" + Template.MouldSIDField + ": " + info[Template.MouldSIDField]);
output.Add("\t" + Template.AdditionalMouldField + ": " + info[Template.AdditionalMouldField]);
output.Add("\tOuter " + Template.ToolstampField + ": " + info["Outer " + Template.ToolstampField]);
output.Add("\tInner " + Template.ToolstampField + ": " + info["Inner " + Template.ToolstampField]);
break;
}
output.Add(Template.BarcodeField + ": " + info[Template.BarcodeField]);
switch(sys)
{
case KnownSystem.AppleMacintosh:
case KnownSystem.IBMPCCompatible:
output.Add(Template.ISBNField + ": " + info[Template.ISBNField]);
break;
}
switch (type)
{
case DiscType.CD:
case DiscType.GDROM:
output.Add(Template.ErrorCountField + ": " + info[Template.ErrorCountField]);
break;
}
output.Add(Template.CommentsField + ": " + info[Template.CommentsField]);
output.Add(Template.ContentsField + ": " + info[Template.ContentsField]);
output.Add(Template.VersionField + ": " + info[Template.VersionField]);
output.Add(Template.EditionField + ": " + info[Template.EditionField]);
switch (sys)
{
case KnownSystem.SegaSaturn:
output.Add(Template.SaturnHeaderField + ":"); output.Add("");
output.AddRange(info[Template.SaturnHeaderField].Split('\n')); output.Add("");
break;
case KnownSystem.SonyPlayStation:
output.Add(Template.PlayStationEDCField + ": " + info[Template.PlayStationEDCField]);
output.Add(Template.PlayStationAntiModchipField + ": " + info[Template.PlayStationAntiModchipField]);
output.Add(Template.PlayStationLibCryptField + ": " + info[Template.PlayStationLibCryptField]);
break;
}
switch (type)
{
case DiscType.DVD9:
case DiscType.BD50:
output.Add(Template.LayerbreakField + ": " + info[Template.LayerbreakField]);
break;
}
output.Add(Template.PVDField + ":"); output.Add("");
output.AddRange(info[Template.PVDField].Split('\n'));
switch (sys)
{
case KnownSystem.AppleMacintosh:
case KnownSystem.IBMPCCompatible:
output.Add(Template.CopyProtectionField + ": " + info[Template.CopyProtectionField]); output.Add("");
if (info.ContainsKey(Template.SubIntentionField))
{
output.Add(Template.SubIntentionField + ":"); output.Add("");
output.AddRange(info[Template.SubIntentionField].Split('\n'));
}
break;
case KnownSystem.MicrosoftXBOX:
output.Add(Template.XBOXDMICRC + ": " + info[Template.XBOXDMICRC]);
output.Add(Template.XBOXPFICRC + ": " + info[Template.XBOXPFICRC]);
output.Add(Template.XBOXSSCRC + ": " + info[Template.XBOXSSCRC]); output.Add("");
output.Add(Template.XBOXSSRanges + ":"); output.Add("");
output.AddRange(info[Template.XBOXSSRanges].Split('\n'));
break;
}
switch (type)
{
case DiscType.CD:
case DiscType.GDROM:
output.Add(Template.CuesheetField + ":"); output.Add("");
output.AddRange(info[Template.CuesheetField].Split('\n')); output.Add("");
output.Add(Template.WriteOffsetField + ": " + info[Template.WriteOffsetField]); output.Add("");
break;
}
output.Add(Template.DATField + ":"); output.Add("");
output.AddRange(info[Template.DATField].Split('\n'));
return output;
}
catch
{
// We don't care what the error is
return null;
}
}
/// <summary>
/// Write the data to the output folder
/// </summary>
/// <param name="outputDirectory">Base directory to use</param>
/// <param name="outputFilename">Base filename to use</param>
/// <param name="lines">Preformatted list of lines to write out to the file</param>
/// <returns>True on success, false on error</returns>
public static bool WriteOutputData(string outputDirectory, string outputFilename, List<string> lines)
{
// Check to see if the inputs are valid
if (lines == null)
{
return false;
}
// Then, sanitized the output filename to strip off any potential extension
outputFilename = Path.GetFileNameWithoutExtension(outputFilename);
// Now write out to a generic file
try
{
using (StreamWriter sw = new StreamWriter(File.Open(Path.Combine(outputDirectory, "!submissionInfo.txt"), FileMode.Create, FileAccess.Write)))
{
foreach (string line in lines)
{
sw.WriteLine(line);
}
}
}
catch
{
// We don't care what the error is right now
return false;
}
return true;
}
}
}

File diff suppressed because it is too large Load Diff

36
appveyor.yml Normal file
View File

@@ -0,0 +1,36 @@
# version format
version: 1.06_{build}
# vm template
image: Visual Studio 2017
# environment variables
environment:
EnableNuGetPackageRestore: true
# msbuild configuration
platform:
- Any CPU
configuration:
- Debug
# install dependencies
install:
- ps: appveyor DownloadFile https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
# pre-build script
before_build:
- nuget restore
# build step
build:
verbosity: minimal
# post-build step
after_build:
- 7z a DICUI.zip DICUI\bin\Debug
# artifact linking
artifacts:
- path: DICUI.zip
name: DICUI