Compare commits

..

33 Commits
1.07 ... 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
53 changed files with 5561 additions and 3226 deletions

View File

@@ -1,8 +0,0 @@
<?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"/>
</appSettings>
</configuration>

View File

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

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

@@ -67,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" />
@@ -82,26 +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="LogWindow.xaml.cs">
<DependentUpon>LogWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Data\Constants.cs" />
<Compile Include="External\OrderedDictionary.cs" />
<Compile Include="External\IOrderedDictionary.cs" />
<Compile Include="Options.cs" />
<Compile Include="Tasks.cs" />
<Compile Include="Utilities\DumpInformation.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>
@@ -127,6 +153,7 @@
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
@@ -163,5 +190,10 @@
<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,19 +1,21 @@
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 string FloppyDriveString = "<<FLOPPY>>";
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";
@@ -37,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";

View File

@@ -1,9 +1,63 @@
namespace DICUI.Data
{
/// <summary>
/// Supported DIC commands
/// </summary>
public enum DICCommand
{
NONE = 0,
Audio,
BluRay,
Close,
CompactDisc,
Data,
DigitalVideoDisc,
DriveSpeed,
Eject,
Floppy,
GDROM,
MDS,
Reset,
Start,
Stop,
Sub,
Swap,
XBOX,
}
/// <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,
@@ -39,6 +93,8 @@
VTechVFlashVSmilePro,
ZAPiTGamesGameWaveFamilyEntertainmentSystem,
MarkerConsoleEnd,
#endregion
#region Computers
@@ -52,6 +108,8 @@
NECPC98,
SharpX68000,
MarkerComputerEnd,
#endregion
#region Arcade
@@ -69,6 +127,7 @@
ICEPCHardware,
IncredibleTechnologiesEagle,
IncredibleTechnologiesVarious,
KonamieAmusement,
KonamiFirebeat,
KonamiGVSystem,
KonamiM2,
@@ -110,6 +169,8 @@
TandyMemorexVisualInformationSystem,
TsunamiTsuMoMultiGameMotionSystem,
MarkerArcadeEnd,
#endregion
#region Other
@@ -118,20 +179,37 @@
BDVideo,
DVDVideo,
EnhancedCD,
EnhancedDVD,
EnhancedBD,
HDDVDVideo,
PalmOS,
PhilipsCDiDigitalVideo,
PhotoCD,
PlayStationGameSharkUpdates,
RainbowDisc,
TaoiKTV,
TomyKissSite,
VideoCD,
MarkerOtherEnd,
#endregion
Custom = -1
Custom,
}
/// <summary>
/// Known system category
/// </summary>
public enum KnownSystemCategory
{
Console = 0,
Computer,
Arcade,
Other,
Custom
};
/// <summary>
/// Known media types
/// </summary>

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>

View File

@@ -12,19 +12,21 @@ namespace DICUI
/// </summary>
public partial class OptionsWindow : Window
{
private readonly MainWindow _mainWindow;
private readonly Options _options;
public OptionsWindow(Options options)
public OptionsWindow(MainWindow mainWindow, Options options)
{
InitializeComponent();
_options = options;
_mainWindow = mainWindow;
_options = options;
}
private OpenFileDialog CreateOpenFileDialog()
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.InitialDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
dialog.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
dialog.Filter = "Executables (*.exe)|*.exe";
dialog.FilterIndex = 0;
dialog.RestoreDirectory = true;
@@ -40,23 +42,23 @@ namespace DICUI
private string[] PathSettings()
{
string[] pathSettings = { "defaultOutputPath", "dicPath", "subdumpPath" };
string[] pathSettings = { "DefaultOutputPath", "DICPath", "SubDumpPath" };
return pathSettings;
}
private TextBox TextBoxForPathSetting(string name)
{
return FindName("txt_" + name) as TextBox;
return FindName(name + "TextBox") as TextBox;
}
private void btn_BrowseForPath_Click(object sender, EventArgs e)
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("btn_".Length);
string pathSettingName = button.Name.Substring(0, button.Name.IndexOf("Button"));
// TODO: hack for now, then we'll see
bool shouldBrowseForPath = pathSettingName == "defaultOutputPath";
bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath";
CommonDialog dialog = shouldBrowseForPath ? (CommonDialog)CreateFolderBrowserDialog() : CreateOpenFileDialog();
using (dialog)
@@ -94,22 +96,35 @@ namespace DICUI
}
}
private void btn_Accept_Click(object sender, EventArgs e)
public void Refresh()
{
Array.ForEach(PathSettings(), setting => _options.Set(setting, TextBoxForPathSetting(setting).Text));
_options.Save();
Hide();
Array.ForEach(PathSettings(), setting => TextBoxForPathSetting(setting).Text = _options.Get(setting));
DumpSpeedCDSlider.Value = _options.preferredDumpSpeedCD;
DumpSpeedDVDSlider.Value = _options.preferredDumpSpeedDVD;
}
private void btn_Cancel_Click(object sender, EventArgs e)
#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();
}
public void Refresh()
{
Array.ForEach(PathSettings(), setting => TextBoxForPathSetting(setting).Text = _options.Get(setting));
}
#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,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Data;
using IMAPI2;
@@ -7,40 +6,6 @@ using DICUI.Data;
namespace DICUI.Utilities
{
/// <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)
{
return type != MediaType.BluRay && type != MediaType.Floppy;
}
}
/// <summary>
/// Extensions for KnownSystem? for easier calling
/// </summary>
public static class KnownSystemExtensions
{
public static bool DoesSupportDriveSpeed(this KnownSystem? system)
{
return system != KnownSystem.MicrosoftXBOX
&& system != KnownSystem.MicrosoftXBOX360XDG2
&& system != KnownSystem.MicrosoftXBOX360XDG3;
}
}
/// <summary>
/// Used to provide a converter to XAML files to render comboboxes with enum values
/// </summary>
@@ -48,8 +13,14 @@ namespace DICUI.Utilities
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is MediaType?)
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 "";
}
@@ -65,26 +36,28 @@ namespace DICUI.Utilities
/// <summary>
/// Get the MediaType associated with a given base command
/// </summary>
/// <param name="baseCommand">String value to check</param>
/// <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 MediaType? BaseCommmandToMediaType(string baseCommand)
public static MediaType? BaseCommmandToMediaType(DICCommand baseCommand)
{
switch (baseCommand)
{
case DICCommands.CompactDisc:
case DICCommand.Audio:
case DICCommand.CompactDisc:
case DICCommand.Data:
return MediaType.CD;
case DICCommands.GDROM:
case DICCommands.Swap:
case DICCommand.GDROM:
case DICCommand.Swap:
return MediaType.GDROM;
case DICCommands.DigitalVideoDisc:
case DICCommands.XBOX:
case DICCommand.DigitalVideoDisc:
case DICCommand.XBOX:
return MediaType.DVD;
case DICCommands.BluRay:
case DICCommand.BluRay:
return MediaType.BluRay;
// Non-optical
case DICCommands.Floppy:
case DICCommand.Floppy:
return MediaType.Floppy;
default:
return null;
@@ -94,34 +67,147 @@ namespace DICUI.Utilities
/// <summary>
/// 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;
}
}
/// <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)
/// <summary>
/// Get the string representation of the DICCommand enum values
/// </summary>
/// <param name="command">DICCommand value to convert</param>
/// <returns>String representing the value, if possible</returns>
public static string DICCommandToString(DICCommand command)
{
switch (command)
{
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 "";
}
}
/// <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)
{
@@ -236,128 +322,6 @@ namespace DICUI.Utilities
}
}
/// <summary>
/// Get the DIC command to be used for a given MediaType
/// </summary>
/// <param name="type">MediaType value to check</param>
/// <returns>String containing the command, null on error</returns>
public static string KnownSystemAndMediaTypeToBaseCommand(KnownSystem? sys, MediaType? type)
{
switch (type)
{
case MediaType.CD:
if (sys == KnownSystem.MicrosoftXBOX)
{
return DICCommands.XBOX;
}
return DICCommands.CompactDisc;
case MediaType.DVD:
if (sys == KnownSystem.MicrosoftXBOX
|| sys == KnownSystem.MicrosoftXBOX360XDG2
|| sys == KnownSystem.MicrosoftXBOX360XDG3)
{
return DICCommands.XBOX;
}
return DICCommands.DigitalVideoDisc;
case MediaType.GDROM:
return DICCommands.GDROM;
case MediaType.HDDVD:
return null;
case MediaType.BluRay:
return DICCommands.BluRay;
// Special Formats
case MediaType.GameCubeGameDisc:
return DICCommands.DigitalVideoDisc;
case MediaType.WiiOpticalDisc:
return null;
case MediaType.WiiUOpticalDisc:
return null;
case MediaType.UMD:
return null;
// Non-optical
case MediaType.Floppy:
return DICCommands.Floppy;
default:
return null;
}
}
/// <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">MediaType value to check</param>
/// <returns>List of strings representing the parameters</returns>
public static List<string> KnownSystemAndMediaTypeToParameters(KnownSystem? sys, MediaType? type)
{
// First check to see if the combination of system and MediaType is valid
var validTypes = Validators.GetValidMediaTypes(sys);
if (!validTypes.Contains(type))
{
return null;
}
// Now sort based on disc type
List<string> parameters = new List<string>();
switch (type)
{
case MediaType.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);
parameters.Add(DICFlags.NoFixSubQLibCrypt);
break;
}
break;
case MediaType.DVD:
// Currently no defaults set
break;
case MediaType.GDROM:
parameters.Add(DICFlags.C2Opcode); parameters.Add("20");
break;
case MediaType.HDDVD:
break;
case MediaType.BluRay:
// Currently no defaults set
break;
// Special Formats
case MediaType.GameCubeGameDisc:
parameters.Add(DICFlags.Raw);
break;
case MediaType.WiiOpticalDisc:
// Currently no defaults set
break;
case MediaType.WiiUOpticalDisc:
// Currently no defaults set
break;
case MediaType.UMD:
break;
// Non-optical
case MediaType.Floppy:
// Currently no defaults set
break;
}
return parameters;
}
/// <summary>
/// Get the string representation of the KnownSystem enum values
/// </summary>
@@ -477,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:
@@ -570,6 +536,10 @@ 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:
@@ -580,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:

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,10 +0,0 @@
using System.Collections.Generic;
using System.Collections.Specialized;
namespace DICUI.External
{
// Adapted from https://www.codeproject.com/Articles/18615/OrderedDictionary-T-A-generic-implementation-of-IO
public interface IOrderedDictionary<TKey, TValue> : IOrderedDictionary, IDictionary<TKey, TValue>
{
}
}

View File

@@ -1,326 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace DICUI.External
{
// Adapted from https://www.codeproject.com/Articles/18615/OrderedDictionary-T-A-generic-implementation-of-IO
public class OrderedDictionary<TKey, TValue> : IOrderedDictionary<TKey, TValue>
{
private List<KeyValuePair<TKey, TValue>> _list;
private Dictionary<TKey, TValue> _dictionary;
#region Interface properties
public int Count { get; }
int ICollection.Count => Count;
int ICollection<KeyValuePair<TKey, TValue>>.Count => Count;
ICollection IDictionary.Keys => _dictionary.Keys;
ICollection<TKey> IDictionary<TKey, TValue>.Keys => _dictionary.Keys;
ICollection IDictionary.Values => _dictionary.Values;
ICollection<TValue> IDictionary<TKey, TValue>.Values => _dictionary.Values;
bool IDictionary.IsReadOnly => false;
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
bool IDictionary.IsFixedSize => false;
object ICollection.SyncRoot => new object();
bool ICollection.IsSynchronized => true;
public TValue this[int index]
{
get
{
return _list[index].Value;
}
set
{
if (index >= Count || index < 0)
throw new ArgumentOutOfRangeException("index",
"'index' must be non-negative and less than" +
" the size of the collection");
TKey key = _list[index].Key;
_list[index] = new KeyValuePair<TKey, TValue>(key, value);
_dictionary[key] = value;
}
}
object IOrderedDictionary.this[int index]
{
get
{
return _list[index].Value;
}
set
{
if (index >= Count || index < 0)
throw new ArgumentOutOfRangeException("index",
"'index' must be non-negative and less than" +
" the size of the collection");
var valueObj = (TValue)value;
if (valueObj == null)
throw new ArgumentException($"Value must be of type {typeof(TValue)}");
TKey key = _list[index].Key;
_list[index] = new KeyValuePair<TKey, TValue>(key, valueObj);
_dictionary[key] = valueObj;
}
}
object IDictionary.this[object key]
{
get
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
return _dictionary[keyObj];
}
set
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
var valueObj = (TValue)value;
if (valueObj == null)
throw new ArgumentException($"Value must be of type {typeof(TValue)}");
if (_dictionary.ContainsKey(keyObj))
{
_dictionary[keyObj] = valueObj;
_list[IndexOfKey(keyObj)] = new KeyValuePair<TKey, TValue>(keyObj, valueObj);
}
else
{
Add(keyObj, valueObj);
}
}
}
TValue IDictionary<TKey, TValue>.this[TKey key]
{
get
{
return _dictionary[key];
}
set
{
if (_dictionary.ContainsKey(key))
{
_dictionary[key] = value;
_list[IndexOfKey(key)] = new KeyValuePair<TKey, TValue>(key, value);
}
else
{
Add(key, value);
}
}
}
#endregion
public OrderedDictionary()
{
_list = new List<KeyValuePair<TKey, TValue>>();
_dictionary = new Dictionary<TKey, TValue>();
Count = 0;
}
public int Add(TKey key, TValue value)
{
_dictionary.Add(key, value);
_list.Add(new KeyValuePair<TKey, TValue>(key, value));
return Count - 1;
}
public void Insert(int index, TKey key, TValue value)
{
if (index > Count || index < 0)
throw new ArgumentOutOfRangeException("index");
_dictionary.Add(key, value);
_list.Insert(index, new KeyValuePair<TKey, TValue>(key, value));
}
void IOrderedDictionary.RemoveAt(int index)
{
if (index >= Count || index < 0)
throw new ArgumentOutOfRangeException("index",
"'index' must be non-negative and less than " +
"the size of the collection");
TKey key = _list[index].Key;
_list.RemoveAt(index);
_dictionary.Remove(key);
}
public bool Remove(TKey key)
{
if (null == key)
throw new ArgumentNullException("key");
int index = IndexOfKey(key);
if (index >= 0)
{
if (_dictionary.Remove(key))
{
_list.RemoveAt(index);
return true;
}
}
return false;
}
public bool ContainsKey(TKey key)
{
return _dictionary.ContainsKey(key);
}
private int IndexOfKey(TKey key)
{
return _list.FindIndex(kvp => kvp.Key.Equals(key));
}
#region Interface methods
IDictionaryEnumerator IOrderedDictionary.GetEnumerator()
{
return _dictionary.GetEnumerator();
}
void IOrderedDictionary.Insert(int index, object key, object value)
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
var valueObj = (TValue)value;
if (valueObj == null)
throw new ArgumentException($"Value must be of type {typeof(TValue)}");
Insert(index, keyObj, valueObj);
}
bool IDictionary.Contains(object key)
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
return _dictionary.ContainsKey(keyObj);
}
void IDictionary.Add(object key, object value)
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
var valueObj = (TValue)value;
if (valueObj == null)
throw new ArgumentException($"Value must be of type {typeof(TValue)}");
Add(keyObj, valueObj);
}
void IDictionary.Clear()
{
_dictionary.Clear();
_list.Clear();
}
IDictionaryEnumerator IDictionary.GetEnumerator()
{
return _dictionary.GetEnumerator();
}
void IDictionary.Remove(object key)
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
Remove(keyObj);
}
void ICollection.CopyTo(Array array, int index)
{
var arrayObj = array as KeyValuePair<TKey, TValue>[];
if (arrayObj == null)
throw new ArgumentException($"Key must be of type {typeof(KeyValuePair<TKey, TValue>[])}");
_list.CopyTo(arrayObj, index);
}
bool IDictionary<TKey, TValue>.ContainsKey(TKey key)
{
return ContainsKey(key);
}
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
Add(key, value);
}
bool IDictionary<TKey, TValue>.Remove(TKey key)
{
return Remove(key);
}
bool IDictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value)
{
return _dictionary.TryGetValue(key, out value);
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
_dictionary.Clear();
_list.Clear();
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
return _list.Contains(item);
}
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
_list.CopyTo(array, arrayIndex);
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
return Remove(item.Key);
}
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _list.GetEnumerator();
}
#endregion
}
}

View File

@@ -1,103 +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"
xmlns:utilities="clr-namespace:DICUI.Utilities"
mc:Ignorable="d"
Title="Disc Image Creator GUI" Height="450" Width="600">
<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>
<ToolBarTray Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Height="30" HorizontalAlignment="Stretch" IsLocked="True">
<ToolBar>
<Button x:Name="tbr_Options" Content="Options" Click="tbr_Options_Click" />
</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" Content="System/Media Type" />
<ComboBox x:Name="cmb_SystemType" Grid.Row="0" Grid.Column="1" Height="22" Width="250" HorizontalAlignment="left" SelectionChanged="cmb_SystemType_SelectionChanged" />
<ComboBox x:Name="cmb_MediaType" Grid.Row="0" Grid.Column="1" Height="22" Width="140" HorizontalAlignment="right" SelectionChanged="cmb_MediaType_SelectionChanged">
<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="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="60" 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" 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*"/>
</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,529 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using WinForms = System.Windows.Forms;
using DICUI.Data;
using DICUI.Utilities;
namespace DICUI
{
public partial class MainWindow : Window
{
// Private UI-related variables
private List<KeyValuePair<char, string>> _drives { get; set; }
private MediaType? _currentMediaType { 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<KeyValuePair<string, KnownSystem?>> _systems { get; set; }
private List<MediaType?> _mediaTypes { get; set; }
private DumpEnvironment _env;
// Option related
private Options _options;
private OptionsWindow _optionsWindow;
public MainWindow()
{
InitializeComponent();
// Initializes and load Options object
_options = new Options();
_options.Load();
// 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)
{
Tasks.CancelDumping(_env);
if (chk_EjectWhenDone.IsChecked == true)
{
Tasks.EjectDisc(_env);
}
}
}
private void btn_OutputDirectoryBrowse_Click(object sender, RoutedEventArgs e)
{
BrowseFolder();
EnsureDiscInformation();
}
private void btn_Search_Click(object sender, RoutedEventArgs e)
{
PopulateDrives();
SetCurrentDiscType();
SetSupportedDriveSpeed();
EnsureDiscInformation();
}
private void cmb_SystemType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
PopulateMediaTypeAccordingToChosenSystem();
GetOutputNames();
EnsureDiscInformation();
}
private void cmb_MediaType_SelectionChanged(object sencder, SelectionChangedEventArgs e)
{
// TODO: This is giving people the benefit of the doubt that their change is valid
_currentMediaType = cmb_MediaType.SelectedItem as MediaType?;
GetOutputNames();
EnsureDiscInformation();
}
private void cmb_DriveLetter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SetCurrentDiscType();
SetSupportedDriveSpeed();
GetOutputNames();
EnsureDiscInformation();
}
private void cmb_DriveSpeed_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
EnsureDiscInformation();
}
private void tbr_Options_Click(object sender, RoutedEventArgs e)
{
// lazy initialization
if (_optionsWindow == null)
{
_optionsWindow = new OptionsWindow(_options);
_optionsWindow.Closed += delegate
{
_optionsWindow = null;
};
}
_optionsWindow.Owner = this;
_optionsWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
_optionsWindow.Refresh();
_optionsWindow.Show();
}
private void txt_OutputFilename_TextChanged(object sender, TextChangedEventArgs e)
{
EnsureDiscInformation();
}
private void txt_OutputDirectory_TextChanged(object sender, TextChangedEventArgs e)
{
EnsureDiscInformation();
}
#endregion
#region Helpers
/// <summary>
/// Populate disc type according to system type
/// </summary>
private void PopulateMediaTypeAccordingToChosenSystem()
{
var currentSystem = cmb_SystemType.SelectedItem as KeyValuePair<string, KnownSystem?>?;
if (currentSystem != null)
{
_mediaTypes = Validators.GetValidMediaTypes(currentSystem?.Value).ToList();
cmb_MediaType.ItemsSource = _mediaTypes;
cmb_MediaType.IsEnabled = _mediaTypes.Count > 1;
cmb_MediaType.SelectedIndex = 0;
}
else
{
cmb_MediaType.IsEnabled = false;
cmb_MediaType.ItemsSource = null;
cmb_MediaType.SelectedIndex = -1;
}
}
/// <summary>
/// Get a complete list of supported systems and fill the combo box
/// </summary>
private void PopulateSystems()
{
_systems = Validators.CreateListOfSystems()
.Select(i => new KeyValuePair<string, KnownSystem?>(i.Key, i.Value))
.ToList();
cmb_SystemType.ItemsSource = _systems;
cmb_SystemType.DisplayMemberPath = "Key";
cmb_SystemType.SelectedIndex = 0;
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 = Validators.CreateListOfDrives()
.Select(i => new KeyValuePair<char, string>(i.Key, i.Value))
.ToList();
cmb_DriveLetter.ItemsSource = _drives;
cmb_DriveLetter.DisplayMemberPath = "Key";
if (cmb_DriveLetter.Items.Count > 0)
{
cmb_DriveLetter.SelectedIndex = 0;
lbl_Status.Content = "Valid optical disc found! Choose your Disc Type";
btn_StartStop.IsEnabled = true;
}
else
{
cmb_DriveLetter.SelectedIndex = -1;
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>
/// Create a DumpEnvironment with all current settings
/// </summary>
/// <returns>Filled DumpEnvironment instance</returns>
private DumpEnvironment DetermineEnvironment()
{
// Populate all KVPs
var driveKvp = cmb_DriveLetter.SelectedItem as KeyValuePair<char, string>?;
var systemKvp = cmb_SystemType.SelectedValue as KeyValuePair<string, KnownSystem?>?;
return new DumpEnvironment()
{
// Paths to tools
SubdumpPath = _options.subdumpPath,
DICPath = _options.dicPath,
OutputDirectory = txt_OutputDirectory.Text,
OutputFilename = txt_OutputFilename.Text,
// Get the currently selected options
DriveLetter = (char)driveKvp?.Key,
IsFloppy = (driveKvp?.Value == UIElements.FloppyDriveString),
DICParameters = txt_Parameters.Text,
System = systemKvp?.Value,
Type = cmb_MediaType.SelectedItem as MediaType?
};
}
/// <summary>
/// Begin the dumping process using the given inputs
/// </summary>
private async void StartDumping()
{
_env = DetermineEnvironment();
btn_StartStop.Content = UIElements.StopDumping;
lbl_Status.Content = "Beginning dumping process";
var task = Tasks.StartDumping(_env);
Result result = await task;
lbl_Status.Content = result ? "Dumping complete!" : result.message;
btn_StartStop.Content = UIElements.StartDumping;
if (chk_EjectWhenDone.IsChecked == true)
Tasks.EjectDisc(_env);
}
/// <summary>
/// Ensure information is consistent with the currently selected disc type
/// </summary>
private void EnsureDiscInformation()
{
var systemKvp = cmb_SystemType.SelectedItem as KeyValuePair<string, KnownSystem?>?;
// If we're on a separator, go to the next item and return
if (systemKvp?.Value == null)
{
cmb_SystemType.SelectedIndex++;
return;
}
// Get the selected system info
var selectedSystem = systemKvp?.Value;
MediaType? selectedMediaType = cmb_MediaType.SelectedItem as MediaType? ?? MediaType.NONE;
Result result = GetSupportStatus(selectedSystem, selectedMediaType);
lbl_Status.Content = result.message;
btn_StartStop.IsEnabled = result && (_drives.Count > 0 ? true : false);
// If we're in a type that doesn't support drive speeds
cmb_DriveSpeed.IsEnabled = selectedMediaType.DoesSupportDriveSpeed() && selectedSystem.DoesSupportDriveSpeed();
// Special case for Custom input
if (selectedSystem == KnownSystem.Custom)
{
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 = (_drives.Count > 0 ? true : false);
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;
// Populate with the correct params for inputs (if we're not on the default option)
if (selectedSystem != KnownSystem.NONE && selectedMediaType != MediaType.NONE)
{
var driveletter = cmb_DriveLetter.SelectedValue as KeyValuePair<char, string>?;
// If drive letter is invalid, skip this
if (driveletter == null)
return;
string command = Converters.KnownSystemAndMediaTypeToBaseCommand(selectedSystem, selectedMediaType);
List<string> defaultParams = Converters.KnownSystemAndMediaTypeToParameters(selectedSystem, selectedMediaType);
txt_Parameters.Text = command
+ " " + driveletter?.Key
+ " \"" + Path.Combine(txt_OutputDirectory.Text, txt_OutputFilename.Text) + "\" "
+ (selectedMediaType != MediaType.Floppy
&& selectedMediaType != MediaType.BluRay
&& selectedSystem != KnownSystem.MicrosoftXBOX
&& selectedSystem != KnownSystem.MicrosoftXBOX360XDG2
&& selectedSystem != KnownSystem.MicrosoftXBOX360XDG3
? (int)cmb_DriveSpeed.SelectedItem + " " : "")
+ string.Join(" ", defaultParams);
}
}
}
/// <summary>
/// Verify that, given a system and a media type, they are correct
/// </summary>
private 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)
{
case MediaType.NONE:
return Result.Failure("Please select a valid disc type");
case MediaType.GameCubeGameDisc:
case MediaType.GDROM:
return Result.Success("{0} discs are partially supported by DIC", type.Name());
case MediaType.HDDVD:
case MediaType.LaserDisc:
case MediaType.CED:
case MediaType.UMD:
case MediaType.WiiOpticalDisc:
case MediaType.WiiUOpticalDisc:
case MediaType.Cartridge:
case MediaType.Cassette:
return Result.Failure("{0} discs are not currently supported by DIC", type.Name());
default:
if (system == KnownSystem.MicrosoftXBOX360XDG3)
{
return Result.Failure("{0} discs are not currently supported by DIC", type.Name());
}
else
{
// TODO: this code should adjust things in a method which is meant to verify values so maybe we can find a better fit
// Take care of the selected item
if (_currentMediaType != null && _currentMediaType != MediaType.NONE)
{
int index = _mediaTypes.IndexOf(_currentMediaType);
if (index != -1)
{
if (cmb_MediaType.SelectedIndex != index)
{
cmb_MediaType.SelectedIndex = index;
}
}
else
{
return Result.Success("Disc of type {0} found, but the current system does not support it!", type.Name());
}
}
}
break;
}
return Result.Success("{0} ready to dump", type.Name());
}
/// <summary>
/// Get the default output directory name from the currently selected drive
/// </summary>
private void GetOutputNames()
{
var driveKvp = cmb_DriveLetter.SelectedItem as KeyValuePair<char, string>?;
var systemKvp = cmb_SystemType.SelectedItem as KeyValuePair<string, KnownSystem?>?;
MediaType? mediaType = cmb_MediaType.SelectedItem as MediaType?;
if (driveKvp != null
&& !String.IsNullOrWhiteSpace(driveKvp?.Value)
&& driveKvp?.Value != UIElements.FloppyDriveString
&& systemKvp != null
&& mediaType != null)
{
txt_OutputDirectory.Text = Path.Combine(_options.defaultOutputPath, driveKvp?.Value);
txt_OutputFilename.Text = driveKvp?.Value + mediaType.Extension();
}
else
{
txt_OutputDirectory.Text = _options.defaultOutputPath;
txt_OutputFilename.Text = "disc.bin";
}
}
/// <summary>
/// Get the highest supported drive speed as reported by DiscImageCreator
/// </summary>
private void SetSupportedDriveSpeed()
{
// Set generic drive speed just in case
cmb_DriveSpeed.SelectedItem = 8;
// Get the drive letter from the selected item
var selected = cmb_DriveLetter.SelectedItem as KeyValuePair<char, string>?;
if (selected == null || (selected?.Value == UIElements.FloppyDriveString))
{
return;
}
//Validators.GetDriveSpeed((char)selected?.Key);
//Validators.GetDriveSpeedEx((char)selected?.Key, MediaType.CD);
// Validate that the required program exists and it's not DICUI itself
if (!File.Exists(_options.dicPath) ||
Path.GetFullPath(_options.dicPath) == Path.GetFullPath(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName))
{
return;
}
char driveLetter = (char)selected?.Key;
Process childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = _options.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) || speed <= 0)
{
return;
}
// If the value is in the list, we can set it immediately
if (_driveSpeeds.Contains(speed))
cmb_DriveSpeed.SelectedValue = speed;
// Otherwise, we need to set the next lowest value
else
cmb_DriveSpeed.SelectedValue = _driveSpeeds.Where(s => s < speed).Last();
}
/// <summary>
/// Set the current disc type in the combo box
/// </summary>
private void SetCurrentDiscType()
{
// Get the drive letter from the selected item
var selected = cmb_DriveLetter.SelectedItem as KeyValuePair<char, string>?;
if (selected == null || (selected?.Value == UIElements.FloppyDriveString))
{
return;
}
// Get the current optical disc type
_currentMediaType = Validators.GetDiscType(selected?.Key);
// 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)
{
cmb_MediaType.SelectedIndex = index;
}
else
{
lbl_Status.Content = $"Disc of type '{Converters.MediaTypeToString(_currentMediaType)}' found, but the current system does not support it!";
}
}
#endregion
}
}

View File

@@ -1,50 +0,0 @@
using System;
using System.Configuration;
using System.Reflection;
namespace DICUI
{
public class Options
{
public string defaultOutputPath { get; private set; }
public string dicPath { get; private set; }
public string subdumpPath { get; private set; }
public void Save()
{
Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//TODO: reflection is used
Array.ForEach(
GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance),
p => {
configFile.AppSettings.Settings.Remove(p.Name);
configFile.AppSettings.Settings.Add(p.Name, p.GetValue(this) as string);
}
);
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";
}
//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;
}
}
}

View File

@@ -1,59 +0,0 @@
<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:local="clr-namespace:DICUI"
mc:Ignorable="d"
Title="Options" Height="260" Width="515.132">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<GroupBox Grid.Column="0" Margin="5,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Header="Paths">
<Grid Margin="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:" FontWeight="Bold"/>
<TextBox x:Name="txt_dicPath" Grid.Row="0" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
<Button x:Name="btn_dicPath" Grid.Row="0" Grid.Column="2" Height="22" Width="22" Content="..." Click="btn_BrowseForPath_Click" />
<Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="subdump Path:" FontWeight="Bold"/>
<TextBox x:Name="txt_subdumpPath" Grid.Row="1" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
<Button x:Name="btn_subdumpPath" Grid.Row="1" Grid.Column="2" Height="22" Width="22" Content="..." Click="btn_BrowseForPath_Click"/>
<Label Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Content="Default Output Path:" FontWeight="Bold"/>
<TextBox x:Name="txt_defaultOutputPath" Grid.Row="2" Grid.Column="1" Height="22" HorizontalAlignment="Stretch" />
<Button x:Name="btn_defaultOutputPath" Grid.Row="2" Grid.Column="2" Height="22" Width="22" Content="..." Click="btn_BrowseForPath_Click" />
</Grid>
</GroupBox>
<Grid Height="22" Grid.Row="1" Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Button x:Name="btn_Accept" Grid.Row="0" Grid.Column="1" Height="22" Width="80" Content="Accept" Click="btn_Accept_Click" />
<Button x:Name="btn_Cancel" Grid.Row="0" Grid.Column="2" Height="22" Width="80" Content="Cancel" Click="btn_Cancel_Click" />
</Grid>
</Grid>
</Window>

View File

@@ -2,10 +2,14 @@
DiscImageCreator UI in C#
[![Build status](https://ci.appveyor.com/api/projects/status/3ldav3v0c373jeqa?svg=true)](https://ci.appveyor.com/project/mnadareski/dicui)
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 :)
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)
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)
## System Requirements
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.
@@ -30,12 +34,16 @@ A list of all changes can now be found [here](https://github.com/reignstumble/DI
Here are the talented people who have contributed to the project so far:
**ReignStumble** - Project Lead / UI Design
- **ReignStumble** - Project Lead / UI Design
- **darksabre76** - Project Co-Lead / Backend Design
- **Jakz** - Primary Feature Contributor
- **NHellFire** - Feature Contributor
**darksabre76** - Project Co-Lead / Backend Design
## Notable Testers
**Jakz** - Feature Contributor
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:
**NHellFire** - Feature Contributor
**Dizzzy** - Concept/Ideas/Beta tester
- **Dizzzy/user7** - Concept, ideas, tester
- **Kludge** - Primary stress tester
- **ajshell1** - Tester
- **eientei95** - Tester

291
Tasks.cs
View File

@@ -1,291 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using DICUI.Data;
using DICUI.Utilities;
namespace DICUI
{
/// <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(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;
}
/// <summary>
/// Represents the state of all settings to be used during dumping
/// </summary>
public class DumpEnvironment
{
// Tool paths
public string DICPath;
public string SubdumpPath;
// Output paths
public string OutputDirectory;
public string OutputFilename;
// UI information
public char DriveLetter;
public KnownSystem? System;
public MediaType? Type;
public bool IsFloppy;
public string DICParameters;
// External process information
public Process dicProcess;
/// <summary>
/// Checks if the configuration is valid
/// </summary>
/// <returns>True if the configuration is valid, false otherwise</returns>
public bool IsConfigurationValid()
{
return !((string.IsNullOrWhiteSpace(DICParameters)
|| !Validators.ValidateParameters(DICParameters)
|| (IsFloppy ^ Type == Data.MediaType.Floppy)));
}
/// <summary>
/// Adjust the current environment if we are given custom parameters
/// </summary>
public void AdjustForCustomConfiguration()
{
// If we have a custom configuration, we need to extract the best possible information from it
if (System == KnownSystem.Custom)
{
Validators.DetermineFlags(DICParameters, out Type, out System, out string letter, out string path);
DriveLetter = letter[0];
OutputDirectory = Path.GetDirectoryName(path);
OutputFilename = Path.GetFileName(path);
}
}
/// <summary>
/// Fix the output paths to remove characters that DiscImageCreator can't handle
/// </summary>
/// <remarks>
/// TODO: Investigate why the `&` replacement is needed
/// </remarks>
public void FixOutputPaths()
{
OutputDirectory = OutputDirectory.Replace('.', '_').Replace('&', '_');
OutputFilename = new StringBuilder(OutputFilename.Replace('&', '_')).Replace('.', '_', 0, OutputFilename.LastIndexOf('.')).ToString();
}
}
/// <summary>
/// Class containing dumping tasks
/// </summary>
public class Tasks
{
/// <summary>
/// Validate the current DumpEnvironment
/// </summary>
/// <param name="env">DumpEnvirionment containing all required information</param>
/// <returns>Result instance with the outcome</returns>
public static Result ValidateEnvironment(DumpEnvironment env)
{
// Validate that everything is good
if (!env.IsConfigurationValid())
return Result.Failure("Error! Current configuration is not supported!");
env.AdjustForCustomConfiguration();
env.FixOutputPaths();
// Validate that the required program exists
if (!File.Exists(env.DICPath))
return Result.Failure("Error! Could not find DiscImageCreator!");
// If a complete dump already exists
if (DumpInformation.FoundAllFiles(env.OutputDirectory, env.OutputFilename, env.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)
{
return Result.Failure("Dumping aborted!");
}
}
return Result.Success();
}
/// <summary>
/// Run DiscImageCreator with the given DumpEnvironment
/// </summary>
/// <param name="env">DumpEnvirionment containing all required information</param>
public static void ExecuteDiskImageCreator(DumpEnvironment env)
{
env.dicProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = env.DICPath,
Arguments = env.DICParameters,
},
};
env.dicProcess.Start();
env.dicProcess.WaitForExit();
}
/// <summary>
/// Execute subdump for a (potential) Sega Saturn dump
/// </summary>
/// <param name="env">DumpEnvirionment containing all required information</param>
public static async void ExecuteSubdump(DumpEnvironment env)
{
await Task.Run(() =>
{
Process childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = env.SubdumpPath,
Arguments = "-i " + env.DriveLetter + ": -f " + Path.Combine(env.OutputDirectory, Path.GetFileNameWithoutExtension(env.OutputFilename) + "_subdump.sub") + "-mode 6 -rereadnum 25 -fix 2",
},
};
childProcess.Start();
childProcess.WaitForExit();
});
}
/// <summary>
/// Run any additional tools given a DumpEnvironment
/// </summary>
/// <param name="env">DumpEnvirionment containing all required information</param>
/// <returns>Result instance with the outcome</returns>
public static Result ExecuteAdditionalToolsAfterDIC(DumpEnvironment env)
{
// Special cases
switch (env.System)
{
case KnownSystem.SegaSaturn:
if (!File.Exists(env.SubdumpPath))
return Result.Failure("Error! Could not find subdump!");
ExecuteSubdump(env);
break;
}
return Result.Success();
}
/// <summary>
/// Verify that the current environment has a complete dump and create submission info is possible
/// </summary>
/// <param name="env">DumpEnvirionment containing all required information</param>
/// <returns>Result instance with the outcome</returns>
public static Result VerifyAndSaveDumpOutput(DumpEnvironment env)
{
// Check to make sure that the output had all the correct files
if (!DumpInformation.FoundAllFiles(env.OutputDirectory, env.OutputFilename, env.Type))
return Result.Failure("Error! Please check output directory as dump may be incomplete!");
Dictionary<string, string> templateValues = DumpInformation.ExtractOutputInformation(env.OutputDirectory, env.OutputFilename, env.System, env.Type, env.DriveLetter);
List<string> formattedValues = DumpInformation.FormatOutputData(templateValues, env.System, env.Type);
bool success = DumpInformation.WriteOutputData(env.OutputDirectory, env.OutputFilename, formattedValues);
return Result.Success();
}
/// <summary>
/// Eject the disc using DIC
/// </summary>
public static async void EjectDisc(DumpEnvironment env)
{
// Validate that the required program exists
if (!File.Exists(env.DICPath))
return;
CancelDumping(env);
if (env.IsFloppy)
return;
Process childProcess;
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = env.DICPath,
Arguments = DICCommands.Eject + " " + env.DriveLetter,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
},
};
childProcess.Start();
childProcess.WaitForExit();
});
}
/// <summary>
/// Cancel an in-progress dumping process
/// </summary>
public static void CancelDumping(DumpEnvironment env)
{
try
{
if (env.dicProcess != null && !env.dicProcess.HasExited)
env.dicProcess.Kill();
}
catch
{ }
}
/// <summary>
/// This executes the complete dump workflow on a DumpEnvironment
/// </summary>
public static async Task<Result> StartDumping(DumpEnvironment env)
{
Result result = Tasks.ValidateEnvironment(env);
// is something is wrong in environment return
if (!result)
return result;
// execute DIC
await Task.Run(() => Tasks.ExecuteDiskImageCreator(env));
// execute additional tools
result = Tasks.ExecuteAdditionalToolsAfterDIC(env);
// is something is wrong with additional tools report and return
// TODO: don't return, just keep generating output from DIC
/*if (!result.Item1)
{
lbl_Status.Content = result.Item2;
btn_StartStop.Content = UIElements.StartDumping;
return;
}*/
// verify dump output and save it
result = Tasks.VerifyAndSaveDumpOutput(env);
return result;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ environment:
# msbuild configuration
platform:
- AnyCPU
- Any CPU
configuration:
- Debug
@@ -28,9 +28,9 @@ build:
# post-build step
after_build:
- 7z a dicui_%APPVEYOR_BUILD_VERSION%.zip bin\Debug
- 7z a DICUI.zip DICUI\bin\Debug
# artifact linking
artifacts:
- path: dicui_$(version).zip
- path: DICUI.zip
name: DICUI