Compare commits

..

22 Commits
1.05 ... 1.07

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

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

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

* moved additional methods to Tasks to make it more modular

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

* moved main dump workflow into Tasks class

* created specific DumpResult class for better error reporting/management

* fixes

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

* restored GetDiscType functionality

* fixed btn_StartStop enabled on EnsureCorrect... error

* fixed whitespace

* fixed indentation

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

* Make EDC field for PSX automatic

* Make AntiMod field for PSX automatic

* Make LibCrypt field for PSX automatic

* Remove psxt001z

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

* We need the subIntention data for LibCrypt

* Let's avoid null for now

* Set default speed in case of error

* Check the layerbreak better

* Remove extraneous header checking

* Add SubIntention field if it exists, always

* Add LibCrypt flag by default for PSX

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

* Add notes

* Rename Validation -> Validators

* Move data to Data folder

* Get current disk type

* Automatically detect disc type

* Comment out WIP code

* Add more prototype

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

* Fix bulk find/replace

* Add OrderedDictionary

* Stage 1 of moving off of Tuples

* Add CHANGELIST.md

* Stage 2 of Tuple removal

* String replacement for output paths

* Stage 3 of Tuple removal

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

* Slight reordering

* Add new fields to the output

* Whitespace!

* Minor formatting cleanup

* Add TODO

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

* Remove sg-raw from OptionsWindow.xaml

* Remove sg-raw from Options.cs

* Remove sg-raw from MainWindow.xaml.cs

* Missed the other rows

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

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

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

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

* fixed margins automatically inserted by MSVS

* fixed margins automatically inserted by MSVS

* removed empty method placed by XAML designer

* added closed callback for OptionsWindows, tweaks

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

* Add silly formats

* Minor tweaks to disc type population

* Make codepath slightly less complex

* Fix null error on dump

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

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

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

* Split X360 into XDG2/3

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

* Add first attempt at Xbox info extraction

* Trim or it never matches
2018-06-15 20:24:43 -07:00
Matt Nadareski
9683074197 Only eject when told 2018-06-14 20:18:01 -07:00
Matt Nadareski
ab2bc8f50c Worst typo ever 2018-06-14 20:11:49 -07:00
reignstumble
aa86ddaf47 Fix incorrectly enabled button 2018-06-14 20:40:41 -04:00
Matt Nadareski
68afebace4 Update for 1.05a 2018-06-14 16:37:43 -07:00
Matt Nadareski
bebe3ab8a0 Add specialty checking for PS1, PS2, and Saturn (#47)
* Setup upcoming work

* Add EXE date checking for PS1/PS2

* Add PS2 version checking

* Add Saturn header reading, fix validation again

* Get all Saturn build info
2018-06-14 16:33:40 -07:00
18 changed files with 2446 additions and 1159 deletions

View File

@@ -2,9 +2,7 @@
<configuration>
<appSettings>
<add key="dicPath" value="Programs\DiscImageCreator.exe"/>
<add key="psxt001zPath" value="psxt001z.exe"/>
<add key="sgRawPath" value="sg_raw.exe"/>
<add key="subdumpPath" value="subdump.exe"/>
<add key="defaultOutputPath" value="ISO"/>
</appSettings>
</configuration>
</configuration>

72
CHANGELIST.md Normal file
View File

@@ -0,0 +1,72 @@
### 1.07 (2018-06-27)
- Separated system and media type for easier navigation
- Combined instances of single- and dual-layer discs
- Removed reliance on **sg-raw** and **psxt001z**
- Added system and disc type to the submission info
- First attempt at getting current disc type
- Made the three PSX-specific fields (**EDC**, **Anti-modchip**, and **LibCrypt**) automatically filled in, when possible
- Many, many, many behind the scenes updates for speed, future features, and stability
### 1.06 (2018-06-15)
- Fixed not being able to use the `/c2` flag properly
- Fixed times when the ability to start dumping was improperly allowed
- Added full support for XBOX and XBOX360 (XDG1, XDG2) dumping through DIC (using a Kreon, or presumably a 0800)
### 1.05a (2018-06-14)
- Fixed some ordering and nullability issues
- Added automatic fields for PS1, PS2, Saturn
### 1.05 (2018-06-14)
- Miscellaneous fixes around custom parameter validation, dump information accuracy, settings window, and TODO cleanup
- Add many more supported platforms, mostly arcade (based on publicly available information)
- Add floppy disk dumping support
- Add optional disc eject on completion
- Add subdump for Sega Saturn
- Fully support newest version of DIC including all new flags and commands
- PlayStation and Saturn discs still don't have all internal information automatically generated
### 1.04b (2018-06-13)
- Added subIntention reading
- Fixed extra extensions being appended
- Fixed internationalization error (number formatting)
- Fixed "Custom Input" not working
### 1.04a (2018-06-13)
- Fixed issue with empty trays
- Added settings dialog
### 1.04 (2018-06-13)
- Behind-the-scenes fixes and formatting
- Better checks for external programs
- Automatically changing disc information
- Custom parameters (and parameter validation)
- Automatic drive speed selection
- Automatic submission information creation
- Add ability to stop a dump from the UI
### 1.03 (2018-06-08)
- edccchk now run on all CD-Roms
- Discs unsupported by Windows are now regonized
- Extra \ when accepting default save has been removed.
### 1.02b (2018-05-18)
- Added missing DLL
### 1.02 (2018-05-18)
- Fixed XBOX One and PS4 Drive Speed issue.
- Started implementing DiscImageCreator Path selection.
- Conforming my naming for objects and variable
### 1.01d (2018-05-18)
-Combine IBM PC-CD options, misc fixes.

View File

@@ -39,6 +39,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -90,10 +91,17 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Constants.cs" />
<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="Utilities\Validation.cs" />
<Compile Include="Utilities\Validators.cs" />
<Compile Include="Utilities\Converters.cs" />
<Compile Include="OptionsWindow.xaml.cs">
<DependentUpon>OptionsWindow.xaml</DependentUpon>
</Compile>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -102,11 +110,15 @@
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Enumerations.cs" />
<Compile Include="Data\Enumerations.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="OptionsWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
@@ -131,5 +143,25 @@
<ItemGroup>
<Resource Include="Icon.ico" />
</ItemGroup>
<ItemGroup>
<COMReference Include="IMAPI2">
<Guid>{2735412F-7F64-5B0F-8F00-5D77AFBE261E}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
<COMReference Include="IMAPI2FS">
<Guid>{2C941FD0-975B-59BE-A960-9A2A262853A5}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -1,4 +1,4 @@
namespace DICUI
namespace DICUI.Data
{
/// <summary>
/// Text for UI elements
@@ -7,6 +7,7 @@
{
public const string StartDumping = "Start Dumping";
public const string StopDumping = "Stop Dumping";
public const string FloppyDriveString = "<<FLOPPY>>";
}
/// <summary>
@@ -72,6 +73,8 @@
public const string TitleField = "Title";
public const string DiscNumberField = "Disc Number / Letter";
public const string DiscTitleField = "Disc Title";
public const string SystemField = "System";
public const string MediaTypeField = "Media Type";
public const string CategoryField = "Category";
public const string RegionField = "Region";
public const string LanguagesField = "Languages";
@@ -95,19 +98,19 @@
public const string DATField = "DAT";
public const string ErrorCountField = "Error Count";
public const string CuesheetField = "Cuesheet";
public const string SubIntentionField = "SubIntention (SecuROM)";
public const string WriteOffsetField = "WriteOffset";
public const string SubIntentionField = "SubIntention Data (SecuROM/LibCrypt)";
public const string WriteOffsetField = "Write Offset";
public const string LayerbreakField = "Layerbreak";
public const string PlaystationEXEDateField = "EXE Date"; // TODO: Not automatic yet
public const string PlayStationEDCField = "EDC"; // TODO: Not automatic yet
public const string PlayStationAntiModchipField = "Anti-modchip"; // TODO: Not automatic yet
public const string PlayStationLibCryptField = "LibCrypt"; // TODO: Not automatic yet
public const string SaturnHeaderField = "Header"; // TODO: Not automatic yet
public const string SaturnBuildDateField = "Build Date"; // TODO: Not automatic yet
public const string XBOXDMICRC = "DMI.bin CRC32"; // TODO: Not automatic yet
public const string XBOXPFICRC = "PFI.bin CRC32"; // TODO: Not automatic yet
public const string XBOXSSCRC = "SS.bin CRC32"; // TODO: Not automatic yet
public const string XBOXSSRanges = "Security Sector Ranges"; // TODO: Not automatic yet
public const string PlaystationEXEDateField = "EXE Date";
public const string PlayStationEDCField = "EDC";
public const string PlayStationAntiModchipField = "Anti-modchip";
public const string PlayStationLibCryptField = "LibCrypt";
public const string SaturnHeaderField = "Header";
public const string SaturnBuildDateField = "Build Date";
public const string XBOXDMIHash = "DMI.bin Hashes";
public const string XBOXPFIHash = "PFI.bin Hashes";
public const string XBOXSSHash = "SS.bin Hashes";
public const string XBOXSSRanges = "Security Sector Ranges";
// Default values

View File

@@ -1,29 +1,5 @@
namespace DICUI
namespace DICUI.Data
{
/// <summary>
/// Known disc types
/// </summary>
public enum DiscType
{
NONE = 0,
CD,
DVD5,
DVD9,
GDROM,
HDDVD,
BD25,
BD50,
// Special Formats
GameCubeGameDisc,
WiiOpticalDisc,
WiiUOpticalDisc,
UMD,
// Keeping this separate since it's currently unsupported in the UI
Floppy = 99,
}
/// <summary>
/// Known systems
/// </summary>
@@ -40,7 +16,8 @@
CommodoreAmigaCDTV,
MattelHyperscan,
MicrosoftXBOX,
MicrosoftXBOX360,
MicrosoftXBOX360XDG2,
MicrosoftXBOX360XDG3,
MicrosoftXBOXOne,
NECPCEngineTurboGrafxCD,
NECPCFX,
@@ -141,6 +118,7 @@
BDVideo,
DVDVideo,
EnhancedCD,
HDDVDVideo,
PalmOS,
PhilipsCDiDigitalVideo,
PhotoCD,
@@ -150,5 +128,34 @@
VideoCD,
#endregion
Custom = -1
}
/// <summary>
/// Known media types
/// </summary>
public enum MediaType
{
// Generic Optical Formats
NONE = 0,
CD,
DVD,
GDROM,
HDDVD,
BluRay,
LaserDisc,
// Special Optical Formats
GameCubeGameDisc,
WiiOpticalDisc,
WiiUOpticalDisc,
UMD,
// Non-Optical Formats
Floppy,
Cartridge,
Cassette,
CED,
}
}

10
External/IOrderedDictionary.cs vendored Normal file
View File

@@ -0,0 +1,10 @@
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>
{
}
}

326
External/OrderedDictionary.cs vendored Normal file
View File

@@ -0,0 +1,326 @@
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

@@ -4,9 +4,14 @@
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*"/>
@@ -21,7 +26,7 @@
<ToolBarTray Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Height="30" HorizontalAlignment="Stretch" IsLocked="True">
<ToolBar>
<Button x:Name="tbr_Properties" Content="Properties" Command="Properties" Click="tbr_Properties_Click" CommandManager.CanExecute="tbr_Properties_CanExecute"/>
<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"/>
@@ -42,24 +47,31 @@
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" VerticalAlignment="Center">Disc Type</Label>
<ComboBox x:Name="cmb_DiscType" Grid.Row="0" Grid.Column="1" Height="22" SelectionChanged="cmb_DiscType_SelectionChanged" />
<Label Grid.Row="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"/>
<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"/>
<TextBox x:Name="txt_OutputDirectory" Grid.Row="2" Grid.Column="1" Height="22" Width="345" HorizontalAlignment="left" TextChanged="txt_OutputDirectory_TextChanged" />
<Button x:Name="btn_OutputDirectoryBrowse" Grid.Row="2" Grid.Column="1" Height="22" Width="50" HorizontalAlignment="Right" Content="Browse" Click="btn_OutputDirectoryBrowse_Click"/>
<Label Grid.Row="3" Grid.Column="0" VerticalAlignment="Center">Drive Letter</Label>
<ComboBox x:Name="cmb_DriveLetter" Grid.Row="3" Grid.Column="1" Height="22" Width="397" HorizontalAlignment="left" SelectionChanged="cmb_DriveLetter_SelectionChanged"/>
<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"/>
<ComboBox x:Name="cmb_DriveSpeed" Grid.Row="4" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="left" SelectionChanged="cmb_DriveSpeed_SelectionChanged" />
<Label Grid.Row="5" Grid.Column="0" VerticalAlignment="Center">Parameters</Label>
<TextBox x:Name="txt_Parameters" Grid.Row="5" Grid.Column="1" Height="22" Width="397" HorizontalAlignment="left" IsEnabled="False" />
<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">

View File

@@ -1,39 +1,39 @@
using System;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
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 paths
private string defaultOutputPath;
private string dicPath;
private string psxtPath;
private string sgRawPath;
private string subdumpPath;
// Private UI-related variables
private List<Tuple<char, string, bool>> _drives { get; set; }
private List<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<Tuple<string, KnownSystem?, DiscType?>> _systems { get; set; }
private Process childProcess { get; set; }
private Window childWindow { get; set; }
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();
// Get all settings
GetSettings();
// Initializes and load Options object
_options = new Options();
_options.Load();
// Populate the list of systems
PopulateSystems();
@@ -57,8 +57,12 @@ namespace DICUI
}
else if ((string)btn_StartStop.Content == UIElements.StopDumping)
{
CancelDumping();
EjectDisc();
Tasks.CancelDumping(_env);
if (chk_EjectWhenDone.IsChecked == true)
{
Tasks.EjectDisc(_env);
}
}
}
@@ -71,18 +75,29 @@ namespace DICUI
private void btn_Search_Click(object sender, RoutedEventArgs e)
{
PopulateDrives();
SetCurrentDiscType();
SetSupportedDriveSpeed();
EnsureDiscInformation();
}
private void cmb_DiscType_SelectionChanged(object sender, SelectionChangedEventArgs e)
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();
@@ -93,26 +108,22 @@ namespace DICUI
EnsureDiscInformation();
}
private void tbr_Properties_Click(object sender, RoutedEventArgs e)
private void tbr_Options_Click(object sender, RoutedEventArgs e)
{
ShowSettings();
}
// lazy initialization
if (_optionsWindow == null)
{
_optionsWindow = new OptionsWindow(_options);
_optionsWindow.Closed += delegate
{
_optionsWindow = null;
};
}
private void tbr_Properties_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void btn_Settings_Accept_Click(object sender, RoutedEventArgs e)
{
SaveSettings();
childWindow.Close();
GetSettings();
}
private void btn_Settings_Cancel_Click(object sender, RoutedEventArgs e)
{
childWindow.Close();
_optionsWindow.Owner = this;
_optionsWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
_optionsWindow.Refresh();
_optionsWindow.Show();
}
private void txt_OutputFilename_TextChanged(object sender, TextChangedEventArgs e)
@@ -129,16 +140,40 @@ namespace DICUI
#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 = Utilities.Validation.CreateListOfSystems();
cmb_DiscType.ItemsSource = _systems;
cmb_DiscType.DisplayMemberPath = "Item1";
cmb_DiscType.SelectedIndex = 0;
cmb_DiscType_SelectionChanged(null, null);
_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;
}
@@ -150,19 +185,21 @@ namespace DICUI
private void PopulateDrives()
{
// Populate the list of drives and add it to the combo box
_drives = Utilities.Validation.CreateListOfDrives();
_drives = Validators.CreateListOfDrives()
.Select(i => new KeyValuePair<char, string>(i.Key, i.Value))
.ToList();
cmb_DriveLetter.ItemsSource = _drives;
cmb_DriveLetter.DisplayMemberPath = "Item1";
cmb_DriveLetter.SelectedIndex = 0;
cmb_DriveLetter_SelectionChanged(null, null);
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;
}
@@ -191,256 +228,54 @@ namespace DICUI
}
}
/// <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;
// Get the currently selected options
var driveLetterTuple = cmb_DriveLetter.SelectedItem as Tuple<char, string, bool>;
char driveLetter = driveLetterTuple.Item1;
bool isFloppy = driveLetterTuple.Item3;
string outputDirectory = txt_OutputDirectory.Text;
string outputFilename = txt_OutputFilename.Text;
var selected = cmb_DiscType.SelectedValue as Tuple<string, KnownSystem?, DiscType?>;
string systemName = selected.Item1;
KnownSystem? system = selected.Item2;
DiscType? type = selected.Item3;
string customParameters = txt_Parameters.Text;
// Validate that everything is good
if (string.IsNullOrWhiteSpace(customParameters)
|| !Utilities.Validation.ValidateParameters(customParameters)
|| (isFloppy ^ type == DiscType.Floppy))
{
lbl_Status.Content = "Error! Current configuration is not supported!";
btn_StartStop.Content = UIElements.StartDumping;
return;
}
// If we have a custom configuration, we need to extract the best possible information from it
if (systemName == "Custom Input" && system == KnownSystem.NONE && type == DiscType.NONE)
{
Utilities.Validation.DetermineFlags(customParameters, out type, out system, out string letter, out string path);
driveLetter = letter[0];
outputDirectory = Path.GetDirectoryName(path);
outputFilename = Path.GetFileName(path);
}
// Validate that the required program exits
if (!File.Exists(dicPath))
{
lbl_Status.Content = "Error! Could not find DiscImageCreator!";
btn_StartStop.Content = UIElements.StartDumping;
return;
}
// If a complete dump already exists
if (DumpInformation.FoundAllFiles(outputDirectory, outputFilename, type))
{
MessageBoxResult result = MessageBox.Show("A complete dump already exists! Are you sure you want to overwrite?", "Overwrite?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
if (result == MessageBoxResult.No || result == MessageBoxResult.Cancel || result == MessageBoxResult.None)
{
lbl_Status.Content = "Dumping aborted!";
btn_StartStop.Content = UIElements.StartDumping;
return;
}
}
lbl_Status.Content = "Beginning dumping process";
string parameters = txt_Parameters.Text;
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = dicPath,
Arguments = parameters,
},
};
childProcess.Start();
childProcess.WaitForExit();
});
if (chk_EjectWhenDone.IsChecked == true)
{
EjectDisc();
}
// Special cases
switch (system)
{
// TODO: May not be needed anymore? DIC claims to have this functionality now
case KnownSystem.MicrosoftXBOXOne:
case KnownSystem.SonyPlayStation4:
if (!File.Exists(sgRawPath))
{
lbl_Status.Content = "Error! Could not find sg-raw!";
break;
}
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = sgRawPath,
Arguments = "-v -r 4100 -R " + driveLetter + ": " + "ad 01 00 00 00 00 00 00 10 04 00 00 -o \"PIC.bin\""
},
};
childProcess.Start();
childProcess.WaitForExit();
});
break;
case KnownSystem.SegaSaturn:
if (!File.Exists(subdumpPath))
{
lbl_Status.Content = "Error! Could not find subdump!";
break;
}
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = subdumpPath,
Arguments = "-i " + driveLetter + ": -f " + Path.Combine(outputDirectory, Path.GetFileNameWithoutExtension(outputFilename) + "_subdump.sub") + "-mode 6 -rereadnum 25 -fix 2",
},
};
childProcess.Start();
childProcess.WaitForExit();
});
break;
case KnownSystem.SonyPlayStation:
if (!File.Exists(psxtPath))
{
lbl_Status.Content = "Error! Could not find psxt001z!";
break;
}
// Invoke the program with all 3 configurations
// TODO: Use these outputs for PSX information
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = psxtPath,
Arguments = "\"" + DumpInformation.GetFirstTrack(outputDirectory, outputFilename) + "\" > " + "\"" + Path.Combine(outputDirectory, "psxt001z.txt"),
},
};
childProcess.Start();
childProcess.WaitForExit();
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = psxtPath,
Arguments = "--libcrypt \"" + Path.Combine(outputDirectory, Path.GetFileNameWithoutExtension(outputFilename) + ".sub") + "\" > \"" + Path.Combine(outputDirectory, "libcrypt.txt"),
},
};
childProcess.Start();
childProcess.WaitForExit();
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = psxtPath,
Arguments = "--libcryptdrvfast " + driveLetter + " > " + "\"" + Path.Combine(outputDirectory, "libcryptdrv.log"),
},
};
childProcess.Start();
childProcess.WaitForExit();
});
break;
}
// Check to make sure that the output had all the correct files
if (!DumpInformation.FoundAllFiles(outputDirectory, outputFilename, type))
{
lbl_Status.Content = "Error! Please check output directory as dump may be incomplete!";
btn_StartStop.Content = UIElements.StartDumping;
if (chk_EjectWhenDone.IsChecked == true)
{
EjectDisc();
}
return;
}
lbl_Status.Content = "Dumping complete!";
if (chk_EjectWhenDone.IsChecked == true)
{
EjectDisc();
}
Dictionary<string, string> templateValues = DumpInformation.ExtractOutputInformation(outputDirectory, outputFilename, system, type);
List<string> formattedValues = DumpInformation.FormatOutputData(templateValues, system, type);
bool success = DumpInformation.WriteOutputData(outputDirectory, outputFilename, formattedValues);
var task = Tasks.StartDumping(_env);
Result result = await task;
lbl_Status.Content = result ? "Dumping complete!" : result.message;
btn_StartStop.Content = UIElements.StartDumping;
}
/// <summary>
/// Cancel an in-progress dumping process
/// </summary>
private void CancelDumping()
{
try
{
childProcess.Kill();
}
catch
{ }
}
/// <summary>
/// Eject the disc using DIC
/// </summary>
private async void EjectDisc()
{
// Validate that the required program exits
if (!File.Exists(dicPath))
{
return;
}
CancelDumping();
var driveTuple = cmb_DriveLetter.SelectedItem as Tuple<char, string, bool>;
if (driveTuple.Item3)
{
return;
}
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = dicPath,
Arguments = DICCommands.Eject + " " + driveTuple.Item1,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
},
};
childProcess.Start();
childProcess.WaitForExit();
});
if (chk_EjectWhenDone.IsChecked == true)
Tasks.EjectDisc(_env);
}
/// <summary>
@@ -448,54 +283,29 @@ namespace DICUI
/// </summary>
private void EnsureDiscInformation()
{
// If we're on a separator, go to the next item
var tuple = cmb_DiscType.SelectedItem as Tuple<string, KnownSystem?, DiscType?>;
if (tuple.Item2 == null && tuple.Item3 == null)
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_DiscType.SelectedIndex++;
tuple = cmb_DiscType.SelectedItem as Tuple<string, KnownSystem?, DiscType?>;
cmb_SystemType.SelectedIndex++;
return;
}
// If we're on an unsupported type, update the status accordingly
switch (tuple.Item3)
{
case DiscType.NONE:
lbl_Status.Content = "Please select a valid disc type";
btn_StartStop.IsEnabled = false;
break;
case DiscType.GameCubeGameDisc:
case DiscType.GDROM:
lbl_Status.Content = string.Format("{0} discs are partially supported by DIC", Converters.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = true;
break;
case DiscType.HDDVD:
case DiscType.UMD:
case DiscType.WiiOpticalDisc:
case DiscType.WiiUOpticalDisc:
lbl_Status.Content = string.Format("{0} discs are not currently supported by DIC", Converters.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = false;
break;
default:
lbl_Status.Content = string.Format("{0} ready to dump", Converters.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = true;
break;
}
// 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
switch (tuple.Item3)
{
case DiscType.Floppy:
case DiscType.BD25:
case DiscType.BD50:
cmb_DriveSpeed.IsEnabled = false;
break;
default:
cmb_DriveSpeed.IsEnabled = true;
break;
}
cmb_DriveSpeed.IsEnabled = selectedMediaType.DoesSupportDriveSpeed() && selectedSystem.DoesSupportDriveSpeed();
// Special case for Custom input
if (tuple.Item1 == "Custom Input" && tuple.Item2 == KnownSystem.NONE && tuple.Item3 == DiscType.NONE)
if (selectedSystem == KnownSystem.Custom)
{
txt_Parameters.IsEnabled = true;
txt_OutputFilename.IsEnabled = false;
@@ -503,7 +313,7 @@ namespace DICUI
btn_OutputDirectoryBrowse.IsEnabled = false;
cmb_DriveLetter.IsEnabled = false;
cmb_DriveSpeed.IsEnabled = false;
btn_StartStop.IsEnabled = true;
btn_StartStop.IsEnabled = (_drives.Count > 0 ? true : false);
lbl_Status.Content = "User input mode";
}
else
@@ -513,45 +323,114 @@ namespace DICUI
txt_OutputDirectory.IsEnabled = true;
btn_OutputDirectoryBrowse.IsEnabled = true;
cmb_DriveLetter.IsEnabled = true;
cmb_DriveSpeed.IsEnabled = true;
// Populate with the correct params for inputs (if we're not on the default option)
if (cmb_DiscType.SelectedIndex > 0)
if (selectedSystem != KnownSystem.NONE && selectedMediaType != MediaType.NONE)
{
var selected = cmb_DiscType.SelectedValue as Tuple<string, KnownSystem?, DiscType?>;
var driveletter = cmb_DriveLetter.SelectedValue as Tuple<char, string, bool>;
string discType = Converters.DiscTypeToBaseCommand(selected.Item3);
List<string> defaultParams = Converters.KnownSystemAndDiscTypeToParameters(selected.Item2, selected.Item3);
txt_Parameters.Text = discType
+ " " + driveletter.Item1
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) + "\" "
+ (selected.Item3 != DiscType.Floppy
&& selected.Item3 != DiscType.BD25
&& selected.Item3 != DiscType.BD50
&& selected.Item2 != KnownSystem.MicrosoftXBOX
&& selected.Item2 != KnownSystem.MicrosoftXBOX360
+ (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 driveTuple = cmb_DriveLetter.SelectedItem as Tuple<char, string, bool>;
var discTuple = cmb_DiscType.SelectedItem as Tuple<string, KnownSystem?, DiscType?>;
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 (driveTuple != null && discTuple != null)
if (driveKvp != null
&& !String.IsNullOrWhiteSpace(driveKvp?.Value)
&& driveKvp?.Value != UIElements.FloppyDriveString
&& systemKvp != null
&& mediaType != null)
{
txt_OutputDirectory.Text = Path.Combine(defaultOutputPath, driveTuple.Item2);
txt_OutputFilename.Text = driveTuple.Item2 + Converters.DiscTypeToExtension(discTuple.Item3);
txt_OutputDirectory.Text = Path.Combine(_options.defaultOutputPath, driveKvp?.Value);
txt_OutputFilename.Text = driveKvp?.Value + mediaType.Extension();
}
else
{
txt_OutputDirectory.Text = defaultOutputPath;
txt_OutputDirectory.Text = _options.defaultOutputPath;
txt_OutputFilename.Text = "disc.bin";
}
}
@@ -561,25 +440,32 @@ namespace DICUI
/// </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 Tuple<char, string, bool>;
if (selected == null || selected.Item3)
var selected = cmb_DriveLetter.SelectedItem as KeyValuePair<char, string>?;
if (selected == null || (selected?.Value == UIElements.FloppyDriveString))
{
return;
}
// Validate that the required program exits
if (!File.Exists(dicPath))
//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 = selected.Item1;
childProcess = new Process()
char driveLetter = (char)selected?.Key;
Process childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = dicPath,
FileName = _options.dicPath,
Arguments = DICCommands.DriveSpeed + " " + driveLetter,
CreateNoWindow = true,
UseShellExecute = false,
@@ -592,210 +478,50 @@ namespace DICUI
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))
if (!Int32.TryParse(readspeed, out int speed) || speed <= 0)
{
return;
}
cmb_DriveSpeed.SelectedValue = speed;
// 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>
/// Show all user-configurable settings in a new window
/// Set the current disc type in the combo box
/// </summary>
private void ShowSettings()
private void SetCurrentDiscType()
{
// Create the child window for settings
childWindow = new Window()
{
ShowInTaskbar = false,
Owner = Application.Current.MainWindow,
Width = 500,
Height = 250,
ResizeMode = ResizeMode.NoResize,
};
// Create the new Grid-based window
var grid = new Grid
{
Margin = new Thickness(5),
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
};
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = (GridLength)(new GridLengthConverter().ConvertFromString(String.Format("{0:n1}*", 1.2))) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = (GridLength)(new GridLengthConverter().ConvertFromString(String.Format("{0:n1}*", 2.5))) });
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
// Create all of the individual items in the panel
Label dicPathLabel = new Label();
dicPathLabel.Content = "DiscImageCreator Path:";
dicPathLabel.FontWeight = (FontWeight)(new FontWeightConverter().ConvertFromString("Bold"));
dicPathLabel.VerticalAlignment = VerticalAlignment.Center;
dicPathLabel.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetRow(dicPathLabel, 0);
Grid.SetColumn(dicPathLabel, 0);
TextBox dicPathSetting = new TextBox();
dicPathSetting.Text = ConfigurationManager.AppSettings["dicPath"];
dicPathSetting.VerticalAlignment = VerticalAlignment.Center;
dicPathSetting.HorizontalAlignment = HorizontalAlignment.Stretch;
Grid.SetRow(dicPathSetting, 0);
Grid.SetColumn(dicPathSetting, 1);
Label psxt001zPathLabel = new Label();
psxt001zPathLabel.Content = "psxt001z Path:";
psxt001zPathLabel.FontWeight = (FontWeight)(new FontWeightConverter().ConvertFromString("Bold"));
psxt001zPathLabel.VerticalAlignment = VerticalAlignment.Center;
psxt001zPathLabel.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetRow(psxt001zPathLabel, 1);
Grid.SetColumn(psxt001zPathLabel, 0);
TextBox psxt001zPathSetting = new TextBox();
psxt001zPathSetting.Text = ConfigurationManager.AppSettings["psxt001zPath"];
psxt001zPathSetting.VerticalAlignment = VerticalAlignment.Center;
psxt001zPathSetting.HorizontalAlignment = HorizontalAlignment.Stretch;
Grid.SetRow(psxt001zPathSetting, 1);
Grid.SetColumn(psxt001zPathSetting, 1);
Label sgRawPathLabel = new Label();
sgRawPathLabel.Content = "sg-raw Path:";
sgRawPathLabel.FontWeight = (FontWeight)(new FontWeightConverter().ConvertFromString("Bold"));
sgRawPathLabel.VerticalAlignment = VerticalAlignment.Center;
sgRawPathLabel.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetRow(sgRawPathLabel, 2);
Grid.SetColumn(sgRawPathLabel, 0);
TextBox sgRawPathSetting = new TextBox();
sgRawPathSetting.Text = ConfigurationManager.AppSettings["sgRawPath"];
sgRawPathSetting.VerticalAlignment = VerticalAlignment.Center;
sgRawPathSetting.HorizontalAlignment = HorizontalAlignment.Stretch;
Grid.SetRow(sgRawPathSetting, 2);
Grid.SetColumn(sgRawPathSetting, 1);
Label subdumpPathLabel = new Label();
subdumpPathLabel.Content = "subdump Path:";
subdumpPathLabel.FontWeight = (FontWeight)(new FontWeightConverter().ConvertFromString("Bold"));
subdumpPathLabel.VerticalAlignment = VerticalAlignment.Center;
subdumpPathLabel.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetRow(subdumpPathLabel, 3);
Grid.SetColumn(subdumpPathLabel, 0);
TextBox subdumpPathSetting = new TextBox();
subdumpPathSetting.Text = ConfigurationManager.AppSettings["subdumpPath"];
subdumpPathSetting.VerticalAlignment = VerticalAlignment.Center;
subdumpPathSetting.HorizontalAlignment = HorizontalAlignment.Stretch;
Grid.SetRow(subdumpPathSetting, 3);
Grid.SetColumn(subdumpPathSetting, 1);
Label defaultOutputPathLabel = new Label();
defaultOutputPathLabel.Content = "Default Output Path:";
defaultOutputPathLabel.FontWeight = (FontWeight)(new FontWeightConverter().ConvertFromString("Bold"));
defaultOutputPathLabel.VerticalAlignment = VerticalAlignment.Center;
defaultOutputPathLabel.HorizontalAlignment = HorizontalAlignment.Right;
Grid.SetRow(defaultOutputPathLabel, 4);
Grid.SetColumn(defaultOutputPathLabel, 0);
TextBox defaultOutputPathSetting = new TextBox();
defaultOutputPathSetting.Text = ConfigurationManager.AppSettings["defaultOutputPath"];
defaultOutputPathSetting.VerticalAlignment = VerticalAlignment.Center;
defaultOutputPathSetting.HorizontalAlignment = HorizontalAlignment.Stretch;
Grid.SetRow(defaultOutputPathSetting, 4);
Grid.SetColumn(defaultOutputPathSetting, 1);
var buttonGrid = new Grid
{
Margin = new Thickness(5),
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
};
buttonGrid.ColumnDefinitions.Add(new ColumnDefinition());
buttonGrid.ColumnDefinitions.Add(new ColumnDefinition());
buttonGrid.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(buttonGrid, 5);
Grid.SetColumn(buttonGrid, 0);
Grid.SetColumnSpan(buttonGrid, 2);
Button acceptButton = new Button();
acceptButton.Name = "btn_Settings_Accept";
acceptButton.Content = "Accept";
acceptButton.Click += btn_Settings_Accept_Click;
acceptButton.VerticalAlignment = VerticalAlignment.Center;
acceptButton.HorizontalAlignment = HorizontalAlignment.Center;
Grid.SetRow(acceptButton, 0);
Grid.SetColumn(acceptButton, 0);
Button cancelButton = new Button();
cancelButton.Name = "btn_Settings_Cancel";
cancelButton.Content = "Cancel";
cancelButton.Click += btn_Settings_Cancel_Click;
cancelButton.VerticalAlignment = VerticalAlignment.Center;
cancelButton.HorizontalAlignment = HorizontalAlignment.Center;
Grid.SetRow(cancelButton, 0);
Grid.SetColumn(cancelButton, 1);
buttonGrid.Children.Add(acceptButton);
buttonGrid.Children.Add(cancelButton);
// Add all of the UI elements
grid.Children.Add(dicPathLabel);
grid.Children.Add(dicPathSetting);
grid.Children.Add(psxt001zPathLabel);
grid.Children.Add(psxt001zPathSetting);
grid.Children.Add(sgRawPathLabel);
grid.Children.Add(sgRawPathSetting);
grid.Children.Add(subdumpPathLabel);
grid.Children.Add(subdumpPathSetting);
grid.Children.Add(defaultOutputPathLabel);
grid.Children.Add(defaultOutputPathSetting);
grid.Children.Add(buttonGrid);
// Now show the child window
childWindow.Content = grid;
childWindow.Show();
}
/// <summary>
/// Save settings from the child window, if possible
/// </summary>
private void SaveSettings()
{
// If the child window is disposed, we don't think about it
if (childWindow == null)
// 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;
}
// Clear the old settings and set new ones
var configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
configFile.AppSettings.Settings.Remove("dicPath");
configFile.AppSettings.Settings.Add("dicPath", ((TextBox)(((Grid)childWindow.Content).Children[1])).Text);
configFile.AppSettings.Settings.Remove("psxt001zPath");
configFile.AppSettings.Settings.Add("psxt001zPath", ((TextBox)(((Grid)childWindow.Content).Children[3])).Text);
configFile.AppSettings.Settings.Remove("sgRawPath");
configFile.AppSettings.Settings.Add("sgRawPath", ((TextBox)(((Grid)childWindow.Content).Children[5])).Text);
configFile.AppSettings.Settings.Remove("subdumpPath");
configFile.AppSettings.Settings.Add("subdumpPath", ((TextBox)(((Grid)childWindow.Content).Children[7])).Text);
configFile.AppSettings.Settings.Remove("defaultOutputPath");
configFile.AppSettings.Settings.Add("defaultOutputPath", ((TextBox)(((Grid)childWindow.Content).Children[9])).Text);
configFile.Save(ConfigurationSaveMode.Modified);
}
// Get the current optical disc type
_currentMediaType = Validators.GetDiscType(selected?.Key);
/// <summary>
/// Get settings from the configuration, if possible
/// </summary>
private void GetSettings()
{
dicPath = ConfigurationManager.AppSettings["dicPath"] ?? "Programs\\DiscImageCreator.exe";
psxtPath = ConfigurationManager.AppSettings["psxt001zPath"] ?? "psxt001z.exe";
sgRawPath = ConfigurationManager.AppSettings["sgRawPath"] ?? "sg_raw.exe";
subdumpPath = ConfigurationManager.AppSettings["subdumpPath"] ?? "subdump.exe";
defaultOutputPath = ConfigurationManager.AppSettings["defaultOutputPath"] ?? "ISO";
// 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

50
Options.cs Normal file
View File

@@ -0,0 +1,50 @@
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;
}
}
}

59
OptionsWindow.xaml Normal file
View File

@@ -0,0 +1,59 @@
<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>

115
OptionsWindow.xaml.cs Normal file
View File

@@ -0,0 +1,115 @@
using System;
using System.IO;
using System.Windows;
using System.Windows.Forms;
using Button = System.Windows.Controls.Button;
using TextBox = System.Windows.Controls.TextBox;
namespace DICUI
{
/// <summary>
/// Interaction logic for OptionsWindow.xaml
/// </summary>
public partial class OptionsWindow : Window
{
private readonly Options _options;
public OptionsWindow(Options options)
{
InitializeComponent();
_options = options;
}
private OpenFileDialog CreateOpenFileDialog()
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.InitialDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
dialog.Filter = "Executables (*.exe)|*.exe";
dialog.FilterIndex = 0;
dialog.RestoreDirectory = true;
return dialog;
}
private FolderBrowserDialog CreateFolderBrowserDialog()
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
return dialog;
}
private string[] PathSettings()
{
string[] pathSettings = { "defaultOutputPath", "dicPath", "subdumpPath" };
return pathSettings;
}
private TextBox TextBoxForPathSetting(string name)
{
return FindName("txt_" + name) as TextBox;
}
private void btn_BrowseForPath_Click(object sender, EventArgs e)
{
Button button = sender as Button;
// strips button prefix to obtain the setting name
string pathSettingName = button.Name.Substring("btn_".Length);
// TODO: hack for now, then we'll see
bool shouldBrowseForPath = pathSettingName == "defaultOutputPath";
CommonDialog dialog = shouldBrowseForPath ? (CommonDialog)CreateFolderBrowserDialog() : CreateOpenFileDialog();
using (dialog)
{
DialogResult result = dialog.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
string path;
bool exists;
if (shouldBrowseForPath)
{
path = (dialog as FolderBrowserDialog).SelectedPath;
exists = Directory.Exists(path);
}
else
{
path = (dialog as OpenFileDialog).FileName;
exists = File.Exists(path);
}
if (exists)
TextBoxForPathSetting(pathSettingName).Text = path;
else
{
System.Windows.MessageBox.Show(
"Specified path doesn't exists!",
"Error",
MessageBoxButton.OK,
MessageBoxImage.Error
);
}
}
}
}
private void btn_Accept_Click(object sender, EventArgs e)
{
Array.ForEach(PathSettings(), setting => _options.Set(setting, TextBoxForPathSetting(setting).Text));
_options.Save();
Hide();
}
private void btn_Cancel_Click(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));
}
}
}

View File

@@ -1,97 +1,41 @@
# DICUI
This is my current progress on my C# Disc Image Creator UI.
I am using Disc Image Creator, created by Sarami, and would like to thanks him for this great software.
DiscImageCreator UI in C#
You can get the latest code and released on his github right here:
https://github.com/saramibreak/DiscImageCreator
This is a community project, so if you have some time and knowledge to give, we'll be glad to add you to the contributor of this project :)
I'm a hobbyist programmer, so this code might not be optimal, feel free to make your recommendation / Pull request.
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)
I would like this project to be a community project, so if you have some time and knowledge to give, I'll be glad to add you to the contributor of this project :)
## System Requirements
--------------------------------------------------------------------------
Currently working on the project:
ReignStumble - Co-Lead Programmer
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.
darksabre76 - Co-Lead Programmer
- Windows 7 (newest version of Windows recommended)
- .NET Framework 4.6.1 Runtimes
- 128 MB of free RAM
- As much hard drive space as amount of discs you will be dumping (20+ GB recommended)
NHellFire - Contributer
Ensure that your operating system is as up-to-date as possible, since some features may rely on those updates.
Dizzzy - Concept/Ideas/Beta tester
## Changelist
## Releases
Download the latest release here:
[https://github.com/reignstumble/DICUI/releases](https://github.com/reignstumble/DICUI/releases)
--------------------------------------------------------------------------
2018-06-14
--------------------------------------------------------------------------
## Changelist
Version 1.05 released:
A list of all changes can now be found [here](https://github.com/reignstumble/DICUI/blob/master/CHANGELIST.md).
- Miscellaneous fixes around custom parameter validation, dump information accuracy, settings window, and TODO cleanup
- Add many more supported platforms, mostly arcade (based on publicly available information)
- Add floppy disk dumping support
- Add optional disc eject on completion
- Add subdump for Sega Saturn
- Fully support newest version of DIC including all new flags and commands
## Contributors
**Known Issues:**
Here are the talented people who have contributed to the project so far:
- PlayStation and Saturn discs still don't have all internal information automatically generated
**ReignStumble** - Project Lead / UI Design
--------------------------------------------------------------------------
2018-06-13
--------------------------------------------------------------------------
**darksabre76** - Project Co-Lead / Backend Design
Version 1.04b released:
**Jakz** - Feature Contributor
- Added subIntention reading
- Fixed extra extensions being appended
- Fixed internationalization error (number formatting)
- Fixed "Custom Input" not working
**NHellFire** - Feature Contributor
Version 1.04a released:
- Fixed issue with empty trays
- Added settings dialog
Version 1.04 released:
- Behind-the-scenes fixes and formatting
- Better checks for external programs
- Automatically changing disc information
- Custom parameters (and parameter validation)
- Automatic drive speed selection
- Automatic submission information creation
- Add ability to stop a dump from the UI
--------------------------------------------------------------------------
2018-06-08
--------------------------------------------------------------------------
Version 1.03 released:
- edccchk now run on all CD-Roms
- Discs unsupported by Windows are now regonized
- Extra \ when accepting default save has been removed.
--------------------------------------------------------------------------
2018-05-18
--------------------------------------------------------------------------
Version 1.02b released:
- Fixed XBOX One and PS4 Drive Speed issue. (1.02)
- Started implementing DiscImageCreator Path selection. (1.02)
- Conforming my naming for objects and variable. (1.02)
- Added missing DLL (1.02b)
--------------------------------------------------------------------------
2018-05-14
--------------------------------------------------------------------------
Version 1.01d released
**Dizzzy** - Concept/Ideas/Beta tester

291
Tasks.cs Normal file
View File

@@ -0,0 +1,291 @@
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;
}
}
}

View File

@@ -1,41 +1,98 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Data;
using IMAPI2;
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>
public class EnumDescriptionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is MediaType?)
return ((MediaType?)value).Name();
else
return "";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.Empty;
}
}
public static class Converters
{
/// <summary>
/// Get the DiscType associated with a given base command
/// Get the MediaType associated with a given base command
/// </summary>
/// <param name="baseCommand">String value to check</param>
/// <returns>DiscType if possible, null on error</returns>
/// <returns>MediaType if possible, null on error</returns>
/// <remarks>This takes the "safe" route by assuming the larger of any given format</remarks>
public static DiscType? BaseCommmandToDiscType(string baseCommand)
public static MediaType? BaseCommmandToMediaType(string baseCommand)
{
switch (baseCommand)
{
case DICCommands.CompactDisc:
return DiscType.CD;
return MediaType.CD;
case DICCommands.GDROM:
case DICCommands.Swap:
return DiscType.GDROM;
return MediaType.GDROM;
case DICCommands.DigitalVideoDisc:
return DiscType.DVD9;
case DICCommands.BluRay:
return DiscType.BD50;
case DICCommands.XBOX:
return DiscType.DVD5;
return MediaType.DVD;
case DICCommands.BluRay:
return MediaType.BluRay;
// Non-optical
case DICCommands.Floppy:
return DiscType.Floppy;
return MediaType.Floppy;
default:
return null;
}
}
/// <summary>
/// Get the most common known system for a given DiscType
/// Get the most common known system for a given MediaType
/// </summary>
/// <param name="baseCommand">String value to check</param>
/// <returns>KnownSystem if possible, null on error</returns>
@@ -59,40 +116,168 @@ namespace DICUI.Utilities
}
}
/// <summary>
/// Convert IMAPI physical media type to a MediaType
/// </summary>
/// <param name="type">IMAPI_MEDIA_PHYSICAL_TYPE value to check</param>
/// <returns>MediaType if possible, null on error</returns>
public static MediaType? IMAPIDiskTypeToMediaType(IMAPI_MEDIA_PHYSICAL_TYPE type)
{
switch (type)
{
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_UNKNOWN:
return MediaType.NONE;
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDROM:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDR:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDRW:
return MediaType.CD;
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDROM:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDRAM:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSR:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSRW:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSR_DUALLAYER:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHR:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHRW:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHR_DUALLAYER:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DISK:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSRW_DUALLAYER:
return MediaType.DVD;
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDROM:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDR:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDRAM:
return MediaType.HDDVD;
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDROM:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDR:
case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDRE:
return MediaType.BluRay;
default:
return null;
}
}
/// <summary>
/// Get the DIC command to be used for a given DiscType
/// Get the default extension for a given disc type
/// </summary>
/// <param name="type">DiscType value to check</param>
/// <returns>String containing the command, null on error</returns>
public static string DiscTypeToBaseCommand(DiscType? type)
/// <param name="type">MediaType value to check</param>
/// <returns>Valid extension (with leading '.'), null on error</returns>
public static string MediaTypeToExtension(MediaType? type)
{
switch (type)
{
case DiscType.CD:
return DICCommands.CompactDisc;
case DiscType.DVD5:
case DiscType.DVD9:
return DICCommands.DigitalVideoDisc;
case DiscType.GDROM:
return DICCommands.GDROM;
case DiscType.HDDVD:
case MediaType.CD:
case MediaType.GDROM:
case MediaType.Cartridge:
return ".bin";
case MediaType.DVD:
case MediaType.HDDVD:
case MediaType.BluRay:
case MediaType.WiiOpticalDisc:
case MediaType.UMD:
return ".iso";
case MediaType.LaserDisc:
case MediaType.GameCubeGameDisc:
return ".raw";
case MediaType.WiiUOpticalDisc:
return ".wud";
case MediaType.Floppy:
return ".img";
case MediaType.Cassette:
return ".wav";
case MediaType.NONE:
case MediaType.CED:
default:
return null;
case DiscType.BD25:
case DiscType.BD50:
}
}
/// <summary>
/// Get the string representation of the MediaType enum values
/// </summary>
/// <param name="type">MediaType value to convert</param>
/// <returns>String representing the value, if possible</returns>
public static string MediaTypeToString(MediaType? type)
{
switch (type)
{
case MediaType.CD:
return "CD-ROM";
case MediaType.DVD:
return "DVD";
case MediaType.GDROM:
return "GD-ROM";
case MediaType.HDDVD:
return "HD-DVD";
case MediaType.BluRay:
return "BluRay";
case MediaType.LaserDisc:
return "LaserDisc";
case MediaType.CED:
return "CED";
case MediaType.GameCubeGameDisc:
return "GameCube Game";
case MediaType.WiiOpticalDisc:
return "Wii Optical";
case MediaType.WiiUOpticalDisc:
return "Wii U Optical";
case MediaType.UMD:
return "UMD";
case MediaType.Cartridge:
return "Cartridge";
case MediaType.Cassette:
return "Cassette Tape";
case MediaType.Floppy:
return "Floppy Disk";
case MediaType.NONE:
default:
return "Unknown";
}
}
/// <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 DiscType.GameCubeGameDisc:
case MediaType.GameCubeGameDisc:
return DICCommands.DigitalVideoDisc;
case DiscType.WiiOpticalDisc:
case MediaType.WiiOpticalDisc:
return null;
case DiscType.WiiUOpticalDisc:
case MediaType.WiiUOpticalDisc:
return null;
case DiscType.UMD:
case MediaType.UMD:
return null;
// Non-optical
case DiscType.Floppy:
case MediaType.Floppy:
return DICCommands.Floppy;
default:
@@ -100,90 +285,16 @@ namespace DICUI.Utilities
}
}
/// <summary>
/// Get the default extension for a given disc type
/// </summary>
/// <param name="type">DiscType value to check</param>
/// <returns>Valid extension (with leading '.'), null on error</returns>
public static string DiscTypeToExtension(DiscType? type)
{
switch (type)
{
case DiscType.CD:
case DiscType.GDROM:
return ".bin";
case DiscType.DVD5:
case DiscType.DVD9:
case DiscType.HDDVD:
case DiscType.BD25:
case DiscType.BD50:
case DiscType.WiiOpticalDisc:
case DiscType.UMD:
return ".iso";
case DiscType.GameCubeGameDisc:
return ".raw";
case DiscType.WiiUOpticalDisc:
return ".wud";
case DiscType.Floppy:
return ".img";
case DiscType.NONE:
default:
return null;
}
}
/// <summary>
/// Get the string representation of the DiscType enum values
/// </summary>
/// <param name="type">DiscType value to convert</param>
/// <returns>String representing the value, if possible</returns>
public static string DiscTypeToString(DiscType? type)
{
switch (type)
{
case DiscType.CD:
return "CD-ROM";
case DiscType.DVD5:
return "DVD-5 [Single-Layer]";
case DiscType.DVD9:
return "DVD-9 [Dual-Layer]";
case DiscType.GDROM:
return "GD-ROM";
case DiscType.HDDVD:
return "HD-DVD";
case DiscType.BD25:
return "BluRay-25 [Single-Layer]";
case DiscType.BD50:
return "BluRay-50 [Dual-Layer]";
case DiscType.GameCubeGameDisc:
return "GameCube Game";
case DiscType.WiiOpticalDisc:
return "Wii Optical";
case DiscType.WiiUOpticalDisc:
return "Wii U Optical";
case DiscType.UMD:
return "UMD";
case DiscType.Floppy:
return "Floppy Disk";
case DiscType.NONE:
default:
return "Unknown";
}
}
/// <summary>
/// Get list of default parameters for a given system and disc type
/// </summary>
/// <param name="sys">KnownSystem value to check</param>
/// <param name="type">DiscType value to check</param>
/// <param name="type">MediaType value to check</param>
/// <returns>List of strings representing the parameters</returns>
public static List<string> KnownSystemAndDiscTypeToParameters(KnownSystem? sys, DiscType? type)
public static List<string> KnownSystemAndMediaTypeToParameters(KnownSystem? sys, MediaType? type)
{
// First check to see if the combination of system and disctype is valid
List<DiscType?> validTypes = Validation.GetValidDiscTypes(sys);
// First check to see if the combination of system and MediaType is valid
var validTypes = Validators.GetValidMediaTypes(sys);
if (!validTypes.Contains(type))
{
return null;
@@ -193,7 +304,7 @@ namespace DICUI.Utilities
List<string> parameters = new List<string>();
switch (type)
{
case DiscType.CD:
case MediaType.CD:
parameters.Add(DICFlags.C2Opcode); parameters.Add("20");
switch (sys)
@@ -209,42 +320,37 @@ namespace DICUI.Utilities
break;
case KnownSystem.SonyPlayStation:
parameters.Add(DICFlags.ScanAntiMod);
parameters.Add(DICFlags.NoFixSubQLibCrypt);
break;
}
break;
case DiscType.DVD5:
case MediaType.DVD:
// Currently no defaults set
break;
case DiscType.DVD9:
// Currently no defaults set
break;
case DiscType.GDROM:
case MediaType.GDROM:
parameters.Add(DICFlags.C2Opcode); parameters.Add("20");
break;
case DiscType.HDDVD:
case MediaType.HDDVD:
break;
case DiscType.BD25:
// Currently no defaults set
break;
case DiscType.BD50:
case MediaType.BluRay:
// Currently no defaults set
break;
// Special Formats
case DiscType.GameCubeGameDisc:
case MediaType.GameCubeGameDisc:
parameters.Add(DICFlags.Raw);
break;
case DiscType.WiiOpticalDisc:
case MediaType.WiiOpticalDisc:
// Currently no defaults set
break;
case DiscType.WiiUOpticalDisc:
case MediaType.WiiUOpticalDisc:
// Currently no defaults set
break;
case DiscType.UMD:
case MediaType.UMD:
break;
// Non-optical
case DiscType.Floppy:
case MediaType.Floppy:
// Currently no defaults set
break;
}
@@ -275,8 +381,10 @@ namespace DICUI.Utilities
return "Mattel HyperScan";
case KnownSystem.MicrosoftXBOX:
return "Microsoft XBOX";
case KnownSystem.MicrosoftXBOX360:
return "Microsoft XBOX 360";
case KnownSystem.MicrosoftXBOX360XDG2:
return "Microsoft XBOX 360 (XDG2)";
case KnownSystem.MicrosoftXBOX360XDG3:
return "Microsoft XBOX 360 (XDG3)";
case KnownSystem.MicrosoftXBOXOne:
return "Microsoft XBOX One";
case KnownSystem.NECPCEngineTurboGrafxCD:
@@ -462,6 +570,8 @@ namespace DICUI.Utilities
return "DVD-Video";
case KnownSystem.EnhancedCD:
return "Enhanced CD";
case KnownSystem.HDDVDVideo:
return "HD-DVD-Video";
case KnownSystem.PalmOS:
return "PalmOS";
case KnownSystem.PhilipsCDiDigitalVideo:
@@ -479,10 +589,13 @@ namespace DICUI.Utilities
#endregion
case KnownSystem.Custom:
return "Custom Input";
case KnownSystem.NONE:
default:
return "Unknown";
}
}
}
}
}

View File

@@ -2,6 +2,9 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using DICUI.Data;
namespace DICUI.Utilities
{
@@ -50,9 +53,9 @@ namespace DICUI.Utilities
/// </summary>
/// <param name="outputDirectory">Base directory to use</param>
/// <param name="outputFilename">Base filename to use</param>
/// <param name="type">DiscType value to check</param>
/// <param name="type">MediaType value to check</param>
/// <returns></returns>
public static bool FoundAllFiles(string outputDirectory, string outputFilename, DiscType? type)
public static bool FoundAllFiles(string outputDirectory, string outputFilename, MediaType? type)
{
// First, sanitized the output filename to strip off any potential extension
outputFilename = Path.GetFileNameWithoutExtension(outputFilename);
@@ -61,8 +64,8 @@ namespace DICUI.Utilities
string combinedBase = Path.Combine(outputDirectory, outputFilename);
switch (type)
{
case DiscType.CD:
case DiscType.GDROM: // TODO: Verify GD-ROM outputs this
case MediaType.CD:
case MediaType.GDROM: // TODO: Verify GD-ROM outputs this
return File.Exists(combinedBase + ".c2")
&& File.Exists(combinedBase + ".ccd")
&& File.Exists(combinedBase + ".cue")
@@ -83,15 +86,13 @@ namespace DICUI.Utilities
&& File.Exists(combinedBase + "_subIntention.txt")
&& File.Exists(combinedBase + "_subReadable.txt")
&& File.Exists(combinedBase + "_volDesc.txt");
case DiscType.DVD5:
case DiscType.DVD9:
case DiscType.HDDVD:
case DiscType.BD25:
case DiscType.BD50:
case DiscType.GameCubeGameDisc:
case DiscType.WiiOpticalDisc:
case DiscType.WiiUOpticalDisc:
case DiscType.UMD:
case MediaType.DVD:
case MediaType.HDDVD:
case MediaType.BluRay:
case MediaType.GameCubeGameDisc:
case MediaType.WiiOpticalDisc:
case MediaType.WiiUOpticalDisc:
case MediaType.UMD:
return File.Exists(combinedBase + ".dat")
&& File.Exists(combinedBase + "_cmd.txt")
&& File.Exists(combinedBase + "_disc.txt")
@@ -99,7 +100,7 @@ namespace DICUI.Utilities
&& File.Exists(combinedBase + "_mainError.txt")
&& File.Exists(combinedBase + "_mainInfo.txt")
&& File.Exists(combinedBase + "_volDesc.txt");
case DiscType.Floppy:
case MediaType.Floppy:
return File.Exists(combinedBase + ".dat")
&& File.Exists(combinedBase + "_cmd.txt")
&& File.Exists(combinedBase + "_disc.txt");
@@ -115,10 +116,11 @@ namespace DICUI.Utilities
/// <param name="outputDirectory">Base directory to use</param>
/// <param name="outputFilename">Base filename to use</param>
/// <param name="sys">KnownSystem value to check</param>
/// <param name="type">DiscType value to check</param>
/// <param name="type">MediaType value to check</param>
/// <param name="driveLetter">Drive letter to check</param>
/// <returns>Dictionary containing mapped output values, null on error</returns>
/// <remarks>TODO: Make sure that all special formats are accounted for</remarks>
public static Dictionary<string, string> ExtractOutputInformation(string outputDirectory, string outputFilename, KnownSystem? sys, DiscType? type)
public static Dictionary<string, string> ExtractOutputInformation(string outputDirectory, string outputFilename, KnownSystem? sys, MediaType? type, char driveLetter)
{
// First, sanitized the output filename to strip off any potential extension
outputFilename = Path.GetFileNameWithoutExtension(outputFilename);
@@ -136,6 +138,8 @@ namespace DICUI.Utilities
{ Template.TitleField, Template.RequiredValue },
{ Template.DiscNumberField, Template.OptionalValue },
{ Template.DiscTitleField, Template.OptionalValue },
{ Template.SystemField, Converters.KnownSystemToString(sys) },
{ Template.MediaTypeField, Converters.MediaTypeToString(type) },
{ Template.CategoryField, "Games" },
{ Template.RegionField, "World (CHANGE THIS)" },
{ Template.LanguagesField, "Klingon (CHANGE THIS)" },
@@ -148,22 +152,22 @@ namespace DICUI.Utilities
{ Template.DATField, GetDatfile(combinedBase + ".dat") },
};
// Now we want to do a check by DiscType and extract all required info
// Now we want to do a check by MediaType and extract all required info
switch (type)
{
case DiscType.CD:
case DiscType.GDROM: // TODO: Verify GD-ROM outputs this
case MediaType.CD:
case MediaType.GDROM: // TODO: Verify GD-ROM outputs this
mappings[Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings[Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings[Template.MouldSIDField] = Template.RequiredIfExistsValue;
mappings[Template.AdditionalMouldField] = Template.RequiredIfExistsValue;
mappings[Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings[Template.PVDField] = GetPVD(combinedBase + "_mainInfo.txt");
mappings[Template.PVDField] = GetPVD(combinedBase + "_mainInfo.txt") ?? "";
mappings[Template.ErrorCountField] = GetErrorCount(combinedBase + ".img_EdcEcc.txt",
combinedBase + "_c2Error.txt",
combinedBase + "_mainError.txt").ToString();
mappings[Template.CuesheetField] = GetFullFile(combinedBase + ".cue");
mappings[Template.WriteOffsetField] = GetWriteOffset(combinedBase + "_disc.txt");
mappings[Template.CuesheetField] = GetFullFile(combinedBase + ".cue") ?? "";
mappings[Template.WriteOffsetField] = GetWriteOffset(combinedBase + "_disc.txt") ?? "";
// System-specific options
switch (sys)
@@ -177,35 +181,89 @@ namespace DICUI.Utilities
FileInfo fi = new FileInfo(combinedBase + "_subIntention.txt");
if (fi.Length > 0)
{
mappings[Template.SubIntentionField] = GetFullFile(combinedBase + "_subIntention.txt");
mappings[Template.SubIntentionField] = GetFullFile(combinedBase + "_subIntention.txt") ?? "";
}
}
break;
case KnownSystem.SegaSaturn:
mappings[Template.SaturnHeaderField] = Template.RequiredValue; // GetSaturnHeader(GetFirstTrack(outputDirectory, outputFilename));
mappings[Template.SaturnBuildDateField] = Template.RequiredValue; //GetSaturnBuildDate(GetFirstTrack(outputDirectory, outputFilename));
mappings[Template.SaturnHeaderField] = GetSaturnHeader(GetFirstTrack(outputDirectory, outputFilename)) ?? "";
if (GetSaturnBuildInfo(mappings[Template.SaturnHeaderField], out string serial, out string version, out string buildDate))
{
mappings[Template.DiscSerialField] = serial ?? "";
mappings[Template.VersionField] = version ?? "";
mappings[Template.SaturnBuildDateField] = buildDate ?? "";
}
break;
case KnownSystem.SonyPlayStation:
mappings[Template.PlaystationEXEDateField] = Template.RequiredValue; // GetPlaysStationEXEDate(combinedBase + "_mainInfo.txt");
mappings[Template.PlayStationEDCField] = Template.YesNoValue;
mappings[Template.PlayStationAntiModchipField] = Template.YesNoValue;
mappings[Template.PlayStationLibCryptField] = Template.YesNoValue;
mappings[Template.PlaystationEXEDateField] = GetPlayStationEXEDate(driveLetter) ?? "";
mappings[Template.PlayStationEDCField] = GetMissingEDCCount(combinedBase + ".img_eccEdc.txt") > 0 ? "No" : "Yes";
mappings[Template.PlayStationAntiModchipField] = GetAntiModchipDetected(combinedBase + "_disc.txt") ? "Yes" : "No";
mappings[Template.PlayStationLibCryptField] = "No";
if (File.Exists(combinedBase + "_subIntention.txt"))
{
FileInfo fi = new FileInfo(combinedBase + "_subIntention.txt");
if (fi.Length > 0)
{
mappings[Template.PlayStationLibCryptField] = "Yes";
mappings[Template.SubIntentionField] = GetFullFile(combinedBase + "_subIntention.txt") ?? "";
}
}
break;
case KnownSystem.SonyPlayStation2:
mappings[Template.PlaystationEXEDateField] = Template.RequiredValue; // GetPlaysStationEXEDate(combinedBase + "_mainInfo.txt");
mappings[Template.PlaystationEXEDateField] = GetPlayStationEXEDate(driveLetter) ?? "";
mappings[Template.VersionField] = GetPlayStation2Version(driveLetter) ?? "";
break;
}
break;
case DiscType.DVD5: // TODO: Add XBOX360-specific outputs to this
case DiscType.HDDVD:
case DiscType.BD25:
mappings[Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings[Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings[Template.MouldSIDField] = Template.RequiredIfExistsValue;
mappings[Template.AdditionalMouldField] = Template.RequiredIfExistsValue;
mappings[Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings[Template.PVDField] = GetPVD(combinedBase + "_mainInfo.txt");
case MediaType.DVD:
case MediaType.HDDVD:
case MediaType.BluRay:
string layerbreak = GetLayerbreak(combinedBase + "_disc.txt") ?? "";
// If we have a single-layer disc
if (String.IsNullOrWhiteSpace(layerbreak))
{
switch (type)
{
case MediaType.DVD:
mappings[Template.MediaTypeField] += "-5";
break;
case MediaType.BluRay:
mappings[Template.MediaTypeField] += "-25";
break;
}
mappings[Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings[Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings[Template.MouldSIDField] = Template.RequiredIfExistsValue;
mappings[Template.AdditionalMouldField] = Template.RequiredIfExistsValue;
mappings[Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings[Template.PVDField] = GetPVD(combinedBase + "_mainInfo.txt") ?? "";
}
// If we have a dual-layer disc
else
{
switch (type)
{
case MediaType.DVD:
mappings[Template.MediaTypeField] += "-9";
break;
case MediaType.BluRay:
mappings[Template.MediaTypeField] += "-50";
break;
}
mappings["Outer " + Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings["Inner " + Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings["Outer " + Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings["Inner " + Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings[Template.MouldSIDField] = Template.RequiredIfExistsValue;
mappings[Template.AdditionalMouldField] = Template.RequiredIfExistsValue;
mappings["Outer " + Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings["Inner " + Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings[Template.PVDField] = GetPVD(combinedBase + "_mainInfo.txt") ?? "";
mappings[Template.LayerbreakField] = layerbreak;
}
// System-specific options
switch (sys)
@@ -219,62 +277,26 @@ namespace DICUI.Utilities
FileInfo fi = new FileInfo(combinedBase + "_subIntention.txt");
if (fi.Length > 0)
{
mappings[Template.SubIntentionField] = GetFullFile(combinedBase + "_subIntention.txt");
mappings[Template.SubIntentionField] = GetFullFile(combinedBase + "_subIntention.txt") ?? "";
}
}
break;
case KnownSystem.MicrosoftXBOX:
mappings[Template.XBOXDMICRC] = Template.RequiredValue;
mappings[Template.XBOXPFICRC] = Template.RequiredValue;
mappings[Template.XBOXSSCRC] = Template.RequiredValue;
mappings[Template.XBOXSSRanges] = Template.RequiredValue;
break;
case KnownSystem.SonyPlayStation2:
mappings[Template.PlaystationEXEDateField] = Template.RequiredValue; // GetPlaysStationEXEDate(combinedBase + "_mainInfo.txt");
break;
}
break;
case DiscType.DVD9: // TODO: Add XBOX360-specific outputs to this
case DiscType.BD50:
mappings["Outer " + Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings["Inner " + Template.MasteringRingField] = Template.RequiredIfExistsValue;
mappings["Outer " + Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings["Inner " + Template.MasteringSIDField] = Template.RequiredIfExistsValue;
mappings[Template.MouldSIDField] = Template.RequiredIfExistsValue;
mappings[Template.AdditionalMouldField] = Template.RequiredIfExistsValue;
mappings["Outer " + Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings["Inner " + Template.ToolstampField] = Template.RequiredIfExistsValue;
mappings[Template.PVDField] = GetPVD(combinedBase + "_mainInfo.txt");
mappings[Template.LayerbreakField] = GetLayerbreak(combinedBase + "_disc.txt");
// System-specific options
switch (sys)
{
case KnownSystem.AppleMacintosh:
case KnownSystem.IBMPCCompatible:
mappings[Template.ISBNField] = Template.OptionalValue;
mappings[Template.CopyProtectionField] = Template.RequiredIfExistsValue;
if (File.Exists(combinedBase + "_subIntention.txt"))
case KnownSystem.MicrosoftXBOX360XDG2:
case KnownSystem.MicrosoftXBOX360XDG3:
if (GetXBOXAuxInfo(combinedBase + "_disc.txt", out string dmihash, out string pfihash, out string sshash, out string ss))
{
FileInfo fi = new FileInfo(combinedBase + "_subIntention.txt");
if (fi.Length > 0)
{
mappings[Template.SubIntentionField] = GetFullFile(combinedBase + "_subIntention.txt");
}
mappings[Template.XBOXDMIHash] = dmihash ?? "";
mappings[Template.XBOXPFIHash] = pfihash ?? "";
mappings[Template.XBOXSSHash] = sshash ?? "";
mappings[Template.XBOXSSRanges] = ss ?? "";
}
break;
case KnownSystem.MicrosoftXBOX:
mappings[Template.XBOXDMICRC] = Template.RequiredValue;
mappings[Template.XBOXPFICRC] = Template.RequiredValue;
mappings[Template.XBOXSSCRC] = Template.RequiredValue;
mappings[Template.XBOXSSRanges] = Template.RequiredValue;
break;
case KnownSystem.SonyPlayStation2:
mappings[Template.PlaystationEXEDateField] = Template.RequiredValue; // GetPlaysStationEXEDate(combinedBase + "_mainInfo.txt");
mappings[Template.PlaystationEXEDateField] = GetPlayStationEXEDate(driveLetter) ?? "";
mappings[Template.VersionField] = GetPlayStation2Version(driveLetter) ?? "";
break;
}
break;
}
@@ -388,7 +410,7 @@ namespace DICUI.Utilities
}
else if (line.StartsWith("Total errors:"))
{
return Int64.Parse(line.Remove(0, 14));
return Int64.Parse(line.Remove(0, "Total errors:".Length).Trim());
}
return -1;
@@ -401,6 +423,49 @@ namespace DICUI.Utilities
}
}
/// <summary>
/// Get the existance of an anti-modchip string from the input file, if possible
/// </summary>
/// <param name="disc">_disc.txt file location</param>
/// <returns>Antimodchip existance if possible, false on error</returns>
private static bool GetAntiModchipDetected(string disc)
{
// If the file doesn't exist, we can't get info from it
if (!File.Exists(disc))
{
return false;
}
using (StreamReader sr = File.OpenText(disc))
{
try
{
// Check for either antimod string
string line = sr.ReadLine().Trim();
while (!sr.EndOfStream)
{
if (line.StartsWith("Detected anti-mod string"))
{
return true;
}
else if (line.StartsWith("No anti-mod string"))
{
return false;
}
line = sr.ReadLine().Trim();
}
return false;
}
catch
{
// We don't care what the exception is right now
return false;
}
}
}
/// <summary>
/// Get the layerbreak from the input file, if possible
/// </summary>
@@ -418,12 +483,6 @@ namespace DICUI.Utilities
{
try
{
// Make sure this file is a _disc.txt
if (sr.ReadLine() != "========== DiscStructure ==========")
{
return null;
}
// Fast forward to the layerbreak
while (!sr.ReadLine().Trim().StartsWith("EndDataSector")) ;
@@ -438,6 +497,41 @@ namespace DICUI.Utilities
}
}
/// <summary>
/// Get the detected missing EDC count from the input files, if possible
/// </summary>
/// <param name="edcecc">.img_EdcEcc.txt file location</param>
/// <returns>Missing EDC count if possible, -1 on error</returns>
private static long GetMissingEDCCount(string edcecc)
{
// If one of the files doesn't exist, we can't get info from them
if (!File.Exists(edcecc))
{
return -1;
}
// First line of defense is the EdcEcc error file
using (StreamReader sr = File.OpenText(edcecc))
{
try
{
// Fast forward to the PVD
string line = sr.ReadLine();
while (!line.StartsWith("[INFO]"))
{
line = sr.ReadLine();
}
return Int64.Parse(line.Remove(0, "[INFO] Number of sector(s) where EDC doesn't exist: ".Length).Trim());
}
catch
{
// We don't care what the exception is right now
return -1;
}
}
}
/// <summary>
/// Get the PVD from the input file, if possible
/// </summary>
@@ -455,22 +549,15 @@ namespace DICUI.Utilities
{
try
{
// Make sure this file is a _mainInfo.txt
if (sr.ReadLine() != "========== LBA[000016, 0x00010]: Main Channel ==========")
{
return null;
}
// Fast forward to the PVD
while (!sr.ReadLine().StartsWith("0310")) ;
// Now that we're at the PVD, read each line in and concatenate
string pvd = sr.ReadLine() + "\n"; // 0320
pvd += sr.ReadLine() + "\n"; // 0330
pvd += sr.ReadLine() + "\n"; // 0340
pvd += sr.ReadLine() + "\n"; // 0350
pvd += sr.ReadLine() + "\n"; // 0360
pvd += sr.ReadLine() + "\n"; // 0370
string pvd = "";
for (int i = 0; i < 6; i++)
{
pvd += sr.ReadLine() + "\n"; // 320-370
}
return pvd;
}
@@ -482,6 +569,234 @@ namespace DICUI.Utilities
}
}
/// <summary>
/// Get the EXE date from a PlayStation disc, if possible
/// </summary>
/// <param name="driveLetter">Drive letter to use to check</param>
/// <returns>EXE date in "yyyy-mm-dd" format if possible, null on error</returns>
private static string GetPlayStationEXEDate(char driveLetter)
{
// If the folder no longer exists, we can't do this part
string drivePath = driveLetter + ":\\";
if (!Directory.Exists(drivePath))
{
return null;
}
// If we can't find SYSTEM.CNF, we don't have a PlayStation disc
string systemCnfPath = Path.Combine(drivePath, "SYSTEM.CNF");
if (!File.Exists(systemCnfPath))
{
return null;
}
// Let's try reading SYSTEM.CNF to find the "BOOT" value
string exeName = null;
try
{
using (StreamReader sr = File.OpenText(systemCnfPath))
{
// Not assuming proper ordering, just in case
string line = sr.ReadLine();
while (!line.StartsWith("BOOT"))
{
line = sr.ReadLine();
}
// Once it finds the "BOOT" line, extract the name
exeName = Regex.Match(line, @"BOOT.? = cdrom.?:\\(.*?);.*").Groups[1].Value;
}
}
catch
{
// We don't care what the error was
return null;
}
// Now that we have the EXE name, try to get the fileinfo for it
string exePath = Path.Combine(drivePath, exeName);
if (!File.Exists(exePath))
{
return null;
}
FileInfo fi = new FileInfo(exePath);
return fi.LastWriteTimeUtc.ToString("yyyy-MM-dd");
}
/// <summary>
/// Get the version from a PlayStation 2 disc, if possible
/// </summary>
/// <param name="driveLetter">Drive letter to use to check</param>
/// <returns>Game version if possible, null on error</returns>
private static string GetPlayStation2Version(char driveLetter)
{
// If the folder no longer exists, we can't do this part
string drivePath = driveLetter + ":\\";
if (!Directory.Exists(drivePath))
{
return null;
}
// If we can't find SYSTEM.CNF, we don't have a PlayStation disc
string systemCnfPath = Path.Combine(drivePath, "SYSTEM.CNF");
if (!File.Exists(systemCnfPath))
{
return null;
}
// Let's try reading SYSTEM.CNF to find the "VER" value
try
{
using (StreamReader sr = File.OpenText(systemCnfPath))
{
// Not assuming proper ordering, just in case
string line = sr.ReadLine();
while (!line.StartsWith("VER"))
{
line = sr.ReadLine();
}
// Once it finds the "VER" line, extract the version
return Regex.Match(line, @"VER = (.*)").Groups[1].Value;
}
}
catch
{
// We don't care what the error was
return null;
}
}
/// <summary>
/// Get the header from a Saturn disc, if possible
/// </summary>
/// <param name="firstTrackPath">Path to the first track to check</param>
/// <returns>Header as a byte array if possible, null on error</returns>
private static string GetSaturnHeader(string firstTrackPath)
{
// If the file doesn't exist, we can't get the header
if (!File.Exists(firstTrackPath))
{
return null;
}
// Try to open the file and read the correct number of bytes
try
{
using (BinaryReader br = new BinaryReader(File.OpenRead(firstTrackPath)))
{
br.ReadBytes(0x10);
byte[] headerBytes = br.ReadBytes(0x100);
// Now format the bytes in a way we like
string headerString = "";
int ptr = 0;
while (ptr < headerBytes.Length)
{
byte[] sub = new byte[16];
Array.Copy(headerBytes, ptr, sub, 0, 16);
headerString += ptr.ToString("X").PadLeft(4, '0') + " : "
+ BitConverter.ToString(sub).Replace("-", " ") + " "
+ Encoding.ASCII.GetString(sub) + "\n";
ptr += 16;
}
return headerString.TrimEnd('\n');
}
}
catch
{
// We don't care what the error was
return null;
}
}
/// <summary>
/// Get the build info from a Saturn disc, if possible
/// </summary>
/// <<param name="saturnHeader">String representing a formatter variant of the Saturn header</param>
/// <returns>True on successful extraction of info, false otherwise</returns>
private static bool GetSaturnBuildInfo(string saturnHeader, out string serial, out string version, out string date)
{
serial = null; version = null; date = null;
// If the input header is null, we can't do a thing
if (String.IsNullOrWhiteSpace(saturnHeader))
{
return false;
}
// Now read it in cutting it into lines for easier parsing
try
{
string[] header = saturnHeader.Split('\n');
string serialVersionLine = header[2].Substring(57);
string dateLine = header[3].Substring(57);
serial = serialVersionLine.Substring(0, 8);
version = serialVersionLine.Substring(10, 6);
date = dateLine.Substring(0, 8);
return true;
}
catch
{
// We don't care what the error is
return false;
}
}
/// <summary>
/// Get the XBOX/360 auxiliary info from the outputted files, if possible
/// </summary>
/// <param name="disc">_disc.txt file location</param>
/// <returns>True on successful extraction of info, false otherwise</returns>
private static bool GetXBOXAuxInfo(string disc, out string dmihash, out string pfihash, out string sshash, out string ss)
{
dmihash = null; pfihash = null; sshash = null; ss = null;
// If the file doesn't exist, we can't get info from it
if (!File.Exists(disc))
{
return false;
}
using (StreamReader sr = File.OpenText(disc))
{
try
{
// Fast forward to the Security Sector Ranges
while (!sr.ReadLine().Trim().StartsWith("Number of security sector ranges:")) ;
// Now that we're at the ranges, read each line in and concatenate
// TODO: Make this output like the old method (startlba-endlba)
string line = sr.ReadLine();
while (!line.Trim().StartsWith("========== Unlock 2 state(wxripper) =========="))
{
ss += line + "\n";
line = sr.ReadLine();
}
// Fast forward to the aux hashes
while (!line.Trim().StartsWith("<rom"))
{
line = sr.ReadLine();
}
// Read in the hashes to the proper parts
sshash = line.Trim();
pfihash = sr.ReadLine().Trim();
dmihash = sr.ReadLine().Trim();
return true;
}
catch
{
// We don't care what the exception is right now
return false;
}
}
}
/// <summary>
/// Get the write offset from the input file, if possible
/// </summary>
@@ -499,12 +814,6 @@ namespace DICUI.Utilities
{
try
{
// Make sure this file is a _disc.txt
if (sr.ReadLine() != "========== TOC ==========")
{
return null;
}
// Fast forward to the offsets
while (!sr.ReadLine().Trim().StartsWith("========== Offset")) ;
sr.ReadLine(); // Combined Offset
@@ -527,10 +836,10 @@ namespace DICUI.Utilities
/// </summary>
/// <param name="info">Information dictionary that should contain normalized values</param>
/// <param name="sys">KnownSystem value to check</param>
/// <param name="type">DiscType value to check</param>
/// <param name="type">MediaType value to check</param>
/// <returns>List of strings representing each line of an output file, null on error</returns>
/// <remarks>TODO: Get full list of customizable stuff for other systems</remarks>
public static List<string> FormatOutputData(Dictionary<string, string> info, KnownSystem? sys, DiscType? type)
public static List<string> FormatOutputData(Dictionary<string, string> info, KnownSystem? sys, MediaType? type)
{
// Check to see if the inputs are valid
if (info == null)
@@ -545,6 +854,8 @@ namespace DICUI.Utilities
output.Add(Template.TitleField + ": " + info[Template.TitleField]);
output.Add(Template.DiscNumberField + ": " + info[Template.DiscNumberField]);
output.Add(Template.DiscTitleField + ": " + info[Template.DiscTitleField]);
output.Add(Template.SystemField + ": " + info[Template.SystemField]);
output.Add(Template.MediaTypeField + ": " + info[Template.MediaTypeField]);
output.Add(Template.CategoryField + ": " + info[Template.CategoryField]);
output.Add(Template.RegionField + ": " + info[Template.RegionField]);
output.Add(Template.LanguagesField + ": " + info[Template.LanguagesField]);
@@ -562,35 +873,46 @@ namespace DICUI.Utilities
output.Add("Ringcode Information:");
switch (type)
{
case DiscType.CD:
case DiscType.GDROM:
case DiscType.DVD5:
case DiscType.HDDVD:
case DiscType.BD25:
output.Add("\t" + Template.MasteringRingField + ": " + info[Template.MasteringRingField]);
output.Add("\t" + Template.MasteringSIDField + ": " + info[Template.MasteringSIDField]);
output.Add("\t" + Template.MouldSIDField + ": " + info[Template.MouldSIDField]);
output.Add("\t" + Template.AdditionalMouldField + ": " + info[Template.AdditionalMouldField]);
output.Add("\t" + Template.ToolstampField + ": " + info[Template.ToolstampField]);
break;
case DiscType.DVD9:
case DiscType.BD50:
output.Add("\tOuter " + Template.MasteringRingField + ": " + info["Outer " + Template.MasteringRingField]);
output.Add("\tInner " + Template.MasteringRingField + ": " + info["Inner " + Template.MasteringRingField]);
output.Add("\tOuter " + Template.MasteringSIDField + ": " + info["Outer " + Template.MasteringSIDField]);
output.Add("\tInner " + Template.MasteringSIDField + ": " + info["Inner " + Template.MasteringSIDField]);
output.Add("\t" + Template.MouldSIDField + ": " + info[Template.MouldSIDField]);
output.Add("\t" + Template.AdditionalMouldField + ": " + info[Template.AdditionalMouldField]);
output.Add("\tOuter " + Template.ToolstampField + ": " + info["Outer " + Template.ToolstampField]);
output.Add("\tInner " + Template.ToolstampField + ": " + info["Inner " + Template.ToolstampField]);
case MediaType.CD:
case MediaType.GDROM:
case MediaType.DVD:
case MediaType.HDDVD:
case MediaType.BluRay:
// If we have a dual-layer disc
if (info.ContainsKey(Template.LayerbreakField))
{
output.Add("\tOuter " + Template.MasteringRingField + ": " + info["Outer " + Template.MasteringRingField]);
output.Add("\tInner " + Template.MasteringRingField + ": " + info["Inner " + Template.MasteringRingField]);
output.Add("\tOuter " + Template.MasteringSIDField + ": " + info["Outer " + Template.MasteringSIDField]);
output.Add("\tInner " + Template.MasteringSIDField + ": " + info["Inner " + Template.MasteringSIDField]);
output.Add("\t" + Template.MouldSIDField + ": " + info[Template.MouldSIDField]);
output.Add("\t" + Template.AdditionalMouldField + ": " + info[Template.AdditionalMouldField]);
output.Add("\tOuter " + Template.ToolstampField + ": " + info["Outer " + Template.ToolstampField]);
output.Add("\tInner " + Template.ToolstampField + ": " + info["Inner " + Template.ToolstampField]);
}
// If we have a single-layer disc
else
{
output.Add("\t" + Template.MasteringRingField + ": " + info[Template.MasteringRingField]);
output.Add("\t" + Template.MasteringSIDField + ": " + info[Template.MasteringSIDField]);
output.Add("\t" + Template.MouldSIDField + ": " + info[Template.MouldSIDField]);
output.Add("\t" + Template.AdditionalMouldField + ": " + info[Template.AdditionalMouldField]);
output.Add("\t" + Template.ToolstampField + ": " + info[Template.ToolstampField]);
}
break;
}
output.Add(Template.BarcodeField + ": " + info[Template.BarcodeField]);
output.Add(Template.ISBNField + ": " + info[Template.ISBNField]);
switch (sys)
{
case KnownSystem.AppleMacintosh:
case KnownSystem.IBMPCCompatible:
output.Add(Template.ISBNField + ": " + info[Template.ISBNField]);
break;
}
switch (type)
{
case DiscType.CD:
case DiscType.GDROM:
case MediaType.CD:
case MediaType.GDROM:
output.Add(Template.ErrorCountField + ": " + info[Template.ErrorCountField]);
break;
}
@@ -612,9 +934,13 @@ namespace DICUI.Utilities
}
switch (type)
{
case DiscType.DVD9:
case DiscType.BD50:
output.Add(Template.LayerbreakField + ": " + info[Template.LayerbreakField]);
case MediaType.DVD:
case MediaType.BluRay:
// If we have a dual-layer disc
if (info.ContainsKey(Template.LayerbreakField))
{
output.Add(Template.LayerbreakField + ": " + info[Template.LayerbreakField]);
}
break;
}
output.Add(Template.PVDField + ":"); output.Add("");
@@ -624,25 +950,26 @@ namespace DICUI.Utilities
case KnownSystem.AppleMacintosh:
case KnownSystem.IBMPCCompatible:
output.Add(Template.CopyProtectionField + ": " + info[Template.CopyProtectionField]); output.Add("");
if (info.ContainsKey(Template.SubIntentionField))
{
output.Add(Template.SubIntentionField + ":"); output.Add("");
output.AddRange(info[Template.SubIntentionField].Split('\n'));
}
break;
case KnownSystem.MicrosoftXBOX:
output.Add(Template.XBOXDMICRC + ": " + info[Template.XBOXDMICRC]);
output.Add(Template.XBOXPFICRC + ": " + info[Template.XBOXPFICRC]);
output.Add(Template.XBOXSSCRC + ": " + info[Template.XBOXSSCRC]); output.Add("");
case KnownSystem.MicrosoftXBOX360XDG2:
case KnownSystem.MicrosoftXBOX360XDG3:
output.Add(Template.XBOXDMIHash + ": " + info[Template.XBOXDMIHash]);
output.Add(Template.XBOXPFIHash + ": " + info[Template.XBOXPFIHash]);
output.Add(Template.XBOXSSHash + ": " + info[Template.XBOXSSHash]); output.Add("");
output.Add(Template.XBOXSSRanges + ":"); output.Add("");
output.AddRange(info[Template.XBOXSSRanges].Split('\n'));
break;
}
if (info.ContainsKey(Template.SubIntentionField))
{
output.Add(Template.SubIntentionField + ":"); output.Add("");
output.AddRange(info[Template.SubIntentionField].Split('\n')); output.Add("");
}
switch (type)
{
case DiscType.CD:
case DiscType.GDROM:
case MediaType.CD:
case MediaType.GDROM:
output.Add(Template.CuesheetField + ":"); output.Add("");
output.AddRange(info[Template.CuesheetField].Split('\n')); output.Add("");
output.Add(Template.WriteOffsetField + ": " + info[Template.WriteOffsetField]); output.Add("");

View File

@@ -3,114 +3,117 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using IMAPI2;
using DICUI.Data;
using DICUI.External;
namespace DICUI.Utilities
{
public static class Validation
public static class Validators
{
/// <summary>
/// Get a list of valid DiscTypes for a given system
/// Get a list of valid MediaTypes for a given KnownSystem
/// </summary>
/// <param name="sys">KnownSystem value to check</param>
/// <returns>List of DiscTypes</returns>
public static List<DiscType?> GetValidDiscTypes(KnownSystem? sys)
/// <returns>MediaTypes, if possible</returns>
public static List<MediaType?> GetValidMediaTypes(KnownSystem? sys)
{
List<DiscType?> types = new List<DiscType?>();
var types = new List<MediaType?>();
switch (sys)
{
#region Consoles
case KnownSystem.BandaiPlaydiaQuickInteractiveSystem:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.BandaiApplePippin:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.CommodoreAmigaCD32:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.CommodoreAmigaCDTV:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.MattelHyperscan:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.MicrosoftXBOX:
types.Add(DiscType.CD);
types.Add(DiscType.DVD5);
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MicrosoftXBOX360:
types.Add(DiscType.CD);
types.Add(DiscType.DVD9);
types.Add(DiscType.HDDVD);
case KnownSystem.MicrosoftXBOX360XDG2:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MicrosoftXBOX360XDG3:
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
types.Add(MediaType.HDDVD);
break;
case KnownSystem.MicrosoftXBOXOne:
types.Add(DiscType.BD25);
types.Add(DiscType.BD50);
types.Add(MediaType.BluRay);
break;
case KnownSystem.NECPCEngineTurboGrafxCD:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.NECPCFX:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.NintendoGameCube:
types.Add(DiscType.GameCubeGameDisc);
types.Add(MediaType.GameCubeGameDisc);
break;
case KnownSystem.NintendoWii:
types.Add(DiscType.WiiOpticalDisc);
types.Add(MediaType.WiiOpticalDisc);
break;
case KnownSystem.NintendoWiiU:
types.Add(DiscType.WiiUOpticalDisc);
types.Add(MediaType.WiiUOpticalDisc);
break;
case KnownSystem.Panasonic3DOInteractiveMultiplayer:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.PhilipsCDi:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.SegaCDMegaCD:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.SegaDreamcast:
types.Add(DiscType.GDROM);
types.Add(MediaType.GDROM);
break;
case KnownSystem.SegaSaturn:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.SNKNeoGeoCD:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.SonyPlayStation:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.SonyPlayStation2:
types.Add(DiscType.CD);
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.SonyPlayStation3:
types.Add(DiscType.BD25);
types.Add(DiscType.BD50);
types.Add(MediaType.BluRay);
break;
case KnownSystem.SonyPlayStation4:
types.Add(DiscType.BD25);
types.Add(DiscType.BD50);
types.Add(MediaType.BluRay);
break;
case KnownSystem.SonyPlayStationPortable:
types.Add(DiscType.UMD);
types.Add(MediaType.UMD);
break;
case KnownSystem.VMLabsNuon:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.VTechVFlashVSmilePro:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem:
types.Add(DiscType.DVD5);
types.Add(MediaType.DVD);
break;
#endregion
@@ -118,34 +121,32 @@ namespace DICUI.Utilities
#region Computers
case KnownSystem.AcornArchimedes:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.AppleMacintosh:
types.Add(DiscType.CD);
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(DiscType.Floppy);
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
types.Add(MediaType.Floppy);
break;
case KnownSystem.CommodoreAmigaCD:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.FujitsuFMTowns:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.IBMPCCompatible:
types.Add(DiscType.CD);
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(DiscType.Floppy);
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
types.Add(MediaType.Floppy);
break;
case KnownSystem.NECPC88:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.NECPC98:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.SharpX68000:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
#endregion
@@ -153,192 +154,169 @@ namespace DICUI.Utilities
#region Arcade
case KnownSystem.AmigaCUBOCD32:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.AmericanLaserGames3DO:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.Atari3DO:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.Atronic:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.AUSCOMSystem1:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.BallyGameMagic:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.CapcomCPSystemIII:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.GlobalVRVarious:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.GlobalVRVortek:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.GlobalVRVortekV3:
types.Add(DiscType.DVD5); // TODO: Confirm
types.Add(DiscType.DVD9); // TODO: Confirm
types.Add(MediaType.DVD); // TODO: Confirm
break;
case KnownSystem.ICEPCHardware:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.IncredibleTechnologiesEagle:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.IncredibleTechnologiesVarious:
types.Add(DiscType.CD);
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.KonamiFirebeat:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiGVSystem:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiM2:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiPython:
types.Add(DiscType.DVD5); // TODO: Confirm
types.Add(DiscType.DVD9); // TODO: Confirm
types.Add(MediaType.DVD); // TODO: Confirm
break;
case KnownSystem.KonamiPython2:
types.Add(DiscType.DVD5); // TODO: Confirm
types.Add(DiscType.DVD9); // TODO: Confirm
types.Add(MediaType.DVD); // TODO: Confirm
break;
case KnownSystem.KonamiSystem573:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiTwinkle:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.KonamiVarious:
types.Add(DiscType.CD);
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MeritIndustriesBoardwalk:
types.Add(DiscType.CD); // TODO: Confirm
types.Add(MediaType.CD); // TODO: Confirm
break;
case KnownSystem.MeritIndustriesMegaTouchAurora:
types.Add(DiscType.CD); // TODO: Confirm
types.Add(MediaType.CD); // TODO: Confirm
break;
case KnownSystem.MeritIndustriesMegaTouchForce:
types.Add(DiscType.CD);
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MeritIndustriesMegaTouchION:
types.Add(DiscType.CD);
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.CD);
types.Add(MediaType.DVD);
break;
case KnownSystem.MeritIndustriesMegaTouchMaxx:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.MeritIndustriesMegaTouchXL:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.NamcoCapcomSystem256:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.NamcoCapcomTaitoSystem246:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.NamcoSegaNintendoTriforce:
types.Add(DiscType.GDROM);
types.Add(MediaType.GDROM);
break;
case KnownSystem.NamcoSystem12:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.NamcoSystem357:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(DiscType.BD25);
types.Add(DiscType.BD50);
types.Add(MediaType.DVD);
types.Add(MediaType.BluRay);
break;
case KnownSystem.NewJatreCDi:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.NichibutsuHighRateSystem:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.NichibutsuSuperCD:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.NichibutsuXRateSystem:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.PhotoPlayVarious:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.RawThrillsVarious:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.SegaChihiro:
types.Add(DiscType.GDROM);
types.Add(MediaType.GDROM);
break;
case KnownSystem.SegaEuropaR:
types.Add(DiscType.DVD5); // TODO: Confirm
types.Add(DiscType.DVD9); // TODO: Confirm
types.Add(MediaType.DVD); // TODO: Confirm
break;
case KnownSystem.SegaLindbergh:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.SegaNaomi:
types.Add(DiscType.GDROM);
types.Add(MediaType.GDROM);
break;
case KnownSystem.SegaNaomi2:
types.Add(DiscType.GDROM);
types.Add(MediaType.GDROM);
break;
case KnownSystem.SegaNu:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(DiscType.BD25);
types.Add(DiscType.BD50);
types.Add(MediaType.DVD);
types.Add(MediaType.BluRay);
break;
case KnownSystem.SegaRingEdge:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.SegaRingEdge2:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.SegaRingWide:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.SegaSTV:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.SegaSystem32:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.SeibuCATSSystem:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.TABAustriaQuizard:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.TandyMemorexVisualInformationSystem:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.TsunamiTsuMoMultiGameMotionSystem:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
#endregion
@@ -346,46 +324,47 @@ namespace DICUI.Utilities
#region Others
case KnownSystem.AudioCD:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.BDVideo:
types.Add(DiscType.BD25);
types.Add(DiscType.BD50);
types.Add(MediaType.BluRay);
break;
case KnownSystem.DVDVideo:
types.Add(DiscType.DVD5);
types.Add(DiscType.DVD9);
types.Add(MediaType.DVD);
break;
case KnownSystem.EnhancedCD:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.HDDVDVideo:
types.Add(MediaType.HDDVD);
break;
case KnownSystem.PalmOS:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.PhilipsCDiDigitalVideo:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.PhotoCD:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.PlayStationGameSharkUpdates:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.TaoiKTV:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.TomyKissSite:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
case KnownSystem.VideoCD:
types.Add(DiscType.CD);
types.Add(MediaType.CD);
break;
#endregion
case KnownSystem.NONE:
default:
types.Add(DiscType.NONE);
types.Add(MediaType.NONE);
break;
}
@@ -397,15 +376,12 @@ namespace DICUI.Utilities
/// </summary>
/// <returns>Systems matched to enums, if possible</returns>
/// <remarks>
/// This returns a List of Tuples whose structure is as follows:
/// Item 1: Printable name
/// Item 2: KnownSystem mapping
/// Item 3: DiscType mapping
/// If something has a "string, null, null" value, it should be assumed that it is a separator
/// If something has a "string, null" value, it should be assumed that it is a separator
/// </remarks>
public static List<Tuple<string, KnownSystem?, DiscType?>> CreateListOfSystems()
/// TODO: Figure out a way that the sections can be generated more automatically
public static OrderedDictionary<string, KnownSystem?> CreateListOfSystems()
{
List<Tuple<string, KnownSystem?, DiscType?>> mapping = new List<Tuple<string, KnownSystem?, DiscType?>>();
var systemsDict = new OrderedDictionary<string, KnownSystem?>();
foreach (KnownSystem system in Enum.GetValues(typeof(KnownSystem)))
{
@@ -414,47 +390,29 @@ namespace DICUI.Utilities
{
// Consoles section
case KnownSystem.BandaiPlaydiaQuickInteractiveSystem:
mapping.Add(new Tuple<string, KnownSystem?, DiscType?>("---------- Consoles ----------", null, null));
systemsDict.Add("---------- Consoles ----------", null);
break;
// Computers section
case KnownSystem.AcornArchimedes:
mapping.Add(new Tuple<string, KnownSystem?, DiscType?>("---------- Computers ----------", null, null));
systemsDict.Add("---------- Computers ----------", null);
break;
// Arcade section
case KnownSystem.AmigaCUBOCD32:
mapping.Add(new Tuple<string, KnownSystem?, DiscType?>("---------- Arcade ----------", null, null));
systemsDict.Add("---------- Arcade ----------", null);
break;
// Other section
case KnownSystem.AudioCD:
mapping.Add(new Tuple<string, KnownSystem?, DiscType?>("---------- Others ----------", null, null));
systemsDict.Add("---------- Others ----------", null);
break;
}
// First, get a list of all DiscTypes for a given KnownSystem
List<DiscType?> types = GetValidDiscTypes(system);
// If we have a single type, we don't want to postfix the system name with it
if (types.Count == 1)
{
mapping.Add(new Tuple<string, KnownSystem?, DiscType?>(Converters.KnownSystemToString(system), system, types[0]));
}
// Otherwise, postfix the system name properly
else
{
foreach (DiscType type in types)
{
mapping.Add(new Tuple<string, KnownSystem?, DiscType?>(Converters.KnownSystemToString(system) + " (" + Converters.DiscTypeToString(type) + ")", system, type));
}
}
systemsDict.Add(Converters.KnownSystemToString(system), system);
}
// Add final mapping for "Custom"
mapping.Add(new Tuple<string, KnownSystem?, DiscType?>("Custom Input", KnownSystem.NONE, DiscType.NONE));
return mapping;
return systemsDict;
}
/// <summary>
@@ -464,28 +422,25 @@ namespace DICUI.Utilities
/// <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
/// This returns a List of Tuples whose structure is as follows:
/// Item 1: Drive letter
/// Item 2: Volume label
/// Item 3: (True for floppy drive, false otherwise)
/// </remarks>
public static List<Tuple<char, string, bool>> CreateListOfDrives()
public static OrderedDictionary<char, string> CreateListOfDrives()
{
// Get the floppy drives
List<Tuple<char, string, bool>> floppyDrives = new List<Tuple<char, string, bool>>();
var floppyDrives = new List<KeyValuePair<char, string>>();
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_LogicalDisk");
foreach (ManagementObject queryObj in searcher.Get())
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];
floppyDrives.Add(new Tuple<char, string, bool>(devId, "FLOPPY", true));
floppyDrives.Add(new KeyValuePair<char, string>(devId, UIElements.FloppyDriveString));
}
}
}
@@ -495,14 +450,223 @@ namespace DICUI.Utilities
}
// Get the optical disc drives
List<Tuple<char, string, bool>> discDrives = DriveInfo.GetDrives()
List<KeyValuePair<char, string>> discDrives = DriveInfo.GetDrives()
.Where(d => d.DriveType == DriveType.CDRom && d.IsReady)
.Select(d => new Tuple<char, string, bool>(d.Name[0], d.VolumeLabel, false))
.Select(d => new KeyValuePair<char, string>(d.Name[0], d.VolumeLabel))
.ToList();
// Add the two lists together, order, and return
// Add the two lists together and order
floppyDrives.AddRange(discDrives);
return floppyDrives.OrderBy(i => i.Item1).ToList();
floppyDrives = floppyDrives.OrderBy(i => i.Key).ToList();
// Add to the ordered dictionary and return
var drivesDict = new OrderedDictionary<char, string>();
foreach (var drive in floppyDrives)
{
drivesDict.Add(drive.Key, drive.Value);
}
return drivesDict;
}
/// <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
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);
}
return null;
}
/// <summary>
/// Get the drive speed of the currently selected drive
/// </summary>
/// <returns>Speed of the drive converted from kbps</returns>
/// <remarks>
/// DIC uses the SCSI_MODE_SENSE command to check this, so does QPXTool (a different one, but still)
/// See if SCSI_MODE_SENSE can be used here
/// Currently, the calculations get something that is technically accurate, but is different than the advertisised
/// capabilities of the drives (according to QPXTool)
/// </remarks>
public static int GetDriveSpeed(char driveLetter)
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_CDROMDrive WHERE Id = '" + driveLetter + ":\'");
var collection = searcher.Get();
double? transferRate = -1;
foreach (ManagementObject queryObj in collection)
{
var obj = queryObj["TransferRate"];
transferRate = (double?)queryObj["TransferRate"];
}
// Transfer Rates (bps)
double cdTransfer = 150 * 1024;
double dvdTransfer = 1353 * 1024;
double cdTransferTest = ((transferRate ?? -1) * 1024) / cdTransfer;
double cdTransferTestKilo = ((transferRate ?? -1) * 1000) / cdTransfer;
double dvdTransferTest = ((transferRate ?? -1) * 1024) / dvdTransfer;
double dvdTransferTestKilo = ((transferRate ?? -1) * 1000) / dvdTransfer;
return 0;
}
public static int GetDriveSpeedEx(char driveLetter, MediaType? mediaType)
{
// 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 -1;
}
// If we got no valid device, we don't care and just return
if (deviceId == null)
{
return -1;
}
// Get all relevant disc information
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 -1;
}
// Now we initialize the recorder to get disc info
MsftDiscRecorder2 recorder = new MsftDiscRecorder2();
recorder.InitializeDiscRecorder(id);
IDiscRecorder2Ex recorderEx = recorder as IDiscRecorder2Ex;
IMAPI_FEATURE_PAGE_TYPE ifpt = IMAPI_FEATURE_PAGE_TYPE.IMAPI_FEATURE_PAGE_TYPE_PROFILE_LIST;
switch(mediaType)
{
case MediaType.CD:
ifpt = IMAPI_FEATURE_PAGE_TYPE.IMAPI_FEATURE_PAGE_TYPE_CD_READ;
break;
case MediaType.DVD:
ifpt = IMAPI_FEATURE_PAGE_TYPE.IMAPI_FEATURE_PAGE_TYPE_DVD_READ;
break;
case MediaType.HDDVD:
ifpt = IMAPI_FEATURE_PAGE_TYPE.IMAPI_FEATURE_PAGE_TYPE_HD_DVD_READ;
break;
case MediaType.BluRay:
ifpt = IMAPI_FEATURE_PAGE_TYPE.IMAPI_FEATURE_PAGE_TYPE_BD_READ;
break;
}
// If we couldn't determine the media type properly, we don't care and return
if (ifpt == IMAPI_FEATURE_PAGE_TYPE.IMAPI_FEATURE_PAGE_TYPE_PROFILE_LIST)
{
return -1;
}
// Now we get the requested mode data
IntPtr modeData = Marshal.AllocHGlobal(256 * sizeof(byte));
recorderEx.GetModePage(
IMAPI_MODE_PAGE_TYPE.IMAPI_MODE_PAGE_TYPE_LEGACY_CAPABILITIES,
IMAPI_MODE_PAGE_REQUEST_TYPE.IMAPI_MODE_PAGE_REQUEST_TYPE_CURRENT_VALUES,
modeData,
out uint modeDataSize);
byte[] outModeArray = new byte[modeDataSize];
Marshal.Copy(modeData, outModeArray, 0, (int)modeDataSize);
// Now we get the requested feature page
IntPtr featureData = Marshal.AllocHGlobal(32 * sizeof(byte));
recorderEx.GetFeaturePage(
ifpt,
(sbyte)1,
featureData,
out uint byteSize);
byte[] outArray = new byte[byteSize];
Marshal.Copy(featureData, outArray, 0, (int)byteSize);
return -1;
}
/// <summary>
@@ -707,7 +871,7 @@ namespace DICUI.Utilities
{
for (int i = index; i < parts.Count; i++)
{
switch(parts[i])
switch (parts[i])
{
case DICFlags.DisableBeep:
if (parts[0] != DICCommands.CompactDisc
@@ -813,7 +977,7 @@ namespace DICUI.Utilities
{
return false;
}
// If the next item doesn't exist, it's good
if (!DoesNextExist(parts, i))
{
@@ -831,7 +995,7 @@ namespace DICUI.Utilities
}
i++;
break;
case DICFlags.ForceUnitAccess: // CD, GDROM, Data, Audio
case DICFlags.ForceUnitAccess:
if (parts[0] != DICCommands.CompactDisc
&& parts[0] != DICCommands.GDROM
&& parts[0] != DICCommands.Data
@@ -913,21 +1077,23 @@ namespace DICUI.Utilities
for (int j = 1; j < 4; j++)
{
// If the next item doesn't exist, it's good
if (!DoesNextExist(parts, i + j - 1))
if (!DoesNextExist(parts, i + 1))
{
i++;
break;
}
// If the next item is a flag, it's good
if (IsFlag(parts[i + j]))
if (IsFlag(parts[i + 1]))
{
i += (j - 1);
i++;
break;
}
// If the next item isn't a valid number
else if (!IsValidNumber(parts[i + j], lowerBound: 0))
else if (!IsValidNumber(parts[i + 1], lowerBound: 0))
{
return false;
}
i++;
}
break;
case DICFlags.SubchannelReadLevel:
@@ -1045,12 +1211,12 @@ namespace DICUI.Utilities
/// Determine the base flags to use for checking a commandline
/// </summary>
/// <param name="parameters">Parameters as a string to check</param>
/// <param name="type">Output nullable DiscType containing the found DiscType, if possible</param>
/// <param name="type">Output nullable MediaType containing the found MediaType, if possible</param>
/// <param name="system">Output nullable KnownSystem containing the found KnownSystem, if possible</param>
/// <param name="letter">Output string containing the found drive letter</param>
/// <param name="path">Output string containing the found path</param>
/// <returns>False on error (and all outputs set to null), true otherwise</returns>
public static bool DetermineFlags(string parameters, out DiscType? type, out KnownSystem? system, out string letter, out string path)
public static bool DetermineFlags(string parameters, out MediaType? type, out KnownSystem? system, out string letter, out string path)
{
// Populate all output variables with null
type = null; system = null; letter = null; path = null;
@@ -1069,7 +1235,7 @@ namespace DICUI.Utilities
.Select(m => m.Value)
.ToList();
type = Converters.BaseCommmandToDiscType(parts[0]);
type = Converters.BaseCommmandToMediaType(parts[0]);
system = Converters.BaseCommandToKnownSystem(parts[0]);
// Determine what the commandline should look like given the first item
@@ -1099,20 +1265,20 @@ namespace DICUI.Utilities
// Special case for GameCube/Wii
if (parts.Contains(DICFlags.Raw))
{
type = DiscType.GameCubeGameDisc;
type = MediaType.GameCubeGameDisc;
system = KnownSystem.NintendoGameCube;
}
// Special case for PlayStation
else if (parts.Contains(DICFlags.NoFixSubQLibCrypt)
|| parts.Contains(DICFlags.ScanAntiMod))
{
type = DiscType.CD;
type = MediaType.CD;
system = KnownSystem.SonyPlayStation;
}
// Special case for Saturn
else if (parts.Contains(DICFlags.SeventyFour))
{
type = DiscType.CD;
type = MediaType.CD;
system = KnownSystem.SegaSaturn;
}

36
appveyor.yml Normal file
View File

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