Compare commits

..

17 Commits
1.04a ... 1.06

Author SHA1 Message Date
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
Matt Nadareski
1f314df8c1 Update for 1.05 2018-06-14 14:14:25 -07:00
Matt Nadareski
38c3638f21 Update Commands for new DIC Version (#46)
* Split constants further

* Fix TODOs in the dump information

* Add TODO for sg-raw

* Use DIC flags, add XBOX command

* Add .dat output for floppy disks, add note

* Better custom parameter checking

* Remove postfix from commands, add /74 flag

* Update DIC flag constant names

* Add descripion for Template constants

* Add description for UIElements

* New utilities namespace

* Add XBOX-specific information

* Add more disc-based arcade systems

* Add special check for PSX discs
2018-06-14 14:06:10 -07:00
Matt Nadareski
cde4b671fc Parameter Checking updates (#44)
* Fix custom parameter parsing, rename to just "parameters"

* Consolodate and fix param checking code
2018-06-13 22:15:53 -07:00
Matt Nadareski
578854cd3b Fixes and Floppies (#43)
* Fix button appearance on Settings window

* Add notes for floppy dumping later

* Support floppy disk reading (fixes #12)
2018-06-13 20:14:25 -07:00
Matt Nadareski
1cd7885194 More fixes (#42)
* Make custom parameters react to filename/directory changes

* Add subdump for Saturn (fixes #20)

* Add disc eject, fix minor issue (fixes #17)

* Fix spacing issue
2018-06-13 18:02:45 -07:00
Matt Nadareski
c0de39c229 Miscellaneous Fixes (#41)
* Make error count more accurate

* Extract dump information to separate file

* Remove TODO

* Add subIntention field check to other formats

* Correct Wii and WiiU disc types

* Nuon correction (hard to base on the limited releases)

* Update Sega Lindbergh

* Add two Sega arcade platforms

* Clearer TODO

* Validate "swap" command

* Remove hanging comma from TODO

* Remove TODO
This one I'm removing because technically, the "gd" command is the correct way of dumping via DIC. The "swap" command is a stopgap for drives that only support GD-ROM dumping via hacked TOC discs
2018-06-13 17:07:55 -07:00
Matt Nadareski
a1148f80c8 Updated for 1.04b 2018-06-13 16:11:22 -07:00
Matt Nadareski
632654d00b Fix "Custom Input" not working 2018-06-13 16:09:11 -07:00
Matt Nadareski
a6d6b800a5 Fix order of operations and extra extension 2018-06-13 16:06:18 -07:00
Matt Nadareski
8527cc5746 Add SubIntention (SecuROM) field (#40)
* Add SubIntention (SecuROM) field

* Fix issue with internationalization
2018-06-13 15:56:38 -07:00
11 changed files with 3073 additions and 2057 deletions

View File

@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="dicPath" value="Programs\\DiscImageCreator.exe"/>
<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>

View File

@@ -1,57 +1,70 @@
namespace DICUI
{
/// <summary>
/// Text for UI elements
/// </summary>
public static class UIElements
{
public const string StartDumping = "Start Dumping";
public const string StopDumping = "Stop Dumping";
}
/// <summary>
/// Top-level commands for DiscImageCreator
/// </summary>
public static class DICCommands
{
// Commands
public const string CompactDiscCommand = "cd";
public const string DataCommand = "data";
public const string AudioCommand = "audio";
public const string GDROMCommand = "gd";
public const string GDROMSwapCommand = "swap";
public const string DVDCommand = "dvd";
public const string BDCommand = "bd";
public const string FloppyCommand = "fd";
public const string StopCommand = "stop";
public const string StartCommand = "start";
public const string EjectCommand = "eject";
public const string CloseCommand = "close";
public const string ResetCommand = "reset";
public const string SubCommand = "sub";
public const string MDSCommand = "mds";
public const string DriveSpeedCommand = "ls"; // Unlisted in help text
// DIC Flags
public const string ForceUnitAccessFlag = "/f";
public const string DisableBeepFlag = "/q";
public const string CDAddOffsetFlag = "/a";
public const string CDBEOpcodeFlag = "/be";
public const string CDD8OpcodeFlag = "/d8";
public const string CDC2OpcodeFlag = "/c2";
public const string CDMCNFlag = "/m";
public const string CDAMSFFlag = "/p";
public const string CDReverseFlag = "/r";
public const string CDMultiSessionFlag = "/ms";
public const string CDScanFileProtectFlag = "/sf";
public const string CDScanSectorProtectFlag = "/ss";
public const string CDScanAnitModFlag = "/am";
public const string CDNoFixSubPFlag = "/np";
public const string CDNoFixSubQFlag = "/nq";
public const string CDNoFixSubRtoWFlag = "/nr";
public const string CDNoFixSubQLibCryptFlag = "/nl";
public const string CDNoFixSubQSecuROMFlag = "/ns";
public const string CDSubchannelReadLevelFlag = "/s";
public const string DVDCMIFlag = "/c";
public const string DVDRawFlag = "/raw";
public const string Audio = "audio";
public const string BluRay = "bd";
public const string Close = "close";
public const string CompactDisc = "cd";
public const string Data = "data";
public const string DigitalVideoDisc = "dvd";
public const string DriveSpeed = "ls";
public const string Eject = "eject";
public const string Floppy = "fd";
public const string GDROM = "gd";
public const string MDS = "mds";
public const string Reset = "reset";
public const string Start = "start";
public const string Stop = "stop";
public const string Sub = "sub";
public const string Swap = "swap";
public const string XBOX = "xbox";
}
/// <summary>
/// Dumping flags for DiscImageCreator
/// </summary>
public static class DICFlags
{
public const string AddOffset = "/a";
public const string AMSF = "/p";
public const string BEOpcode = "/be";
public const string C2Opcode = "/c2";
public const string CMI = "/c";
public const string D8Opcode = "/d8";
public const string DisableBeep = "/q";
public const string ForceUnitAccess = "/f";
public const string MCN = "/m";
public const string MultiSession = "/ms";
public const string NoFixSubP = "/np";
public const string NoFixSubQ = "/nq";
public const string NoFixSubQLibCrypt = "/nl";
public const string NoFixSubQSecuROM = "/ns";
public const string NoFixSubRtoW = "/nr";
public const string Raw = "/raw";
public const string Reverse = "/r";
public const string ScanAntiMod = "/am";
public const string ScanFileProtect = "/sf";
public const string ScanSectorProtect = "/ss";
public const string SeventyFour = "/74";
public const string SubchannelReadLevel = "/s";
}
/// <summary>
/// Template field values for submission info
/// </summary>
public static class Template
{
// Manual information
@@ -82,14 +95,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 LayerbreakField = "Layerbreak";
public const string PlaystationEXEDateField = "EXE Date"; // TODO: Not automatic yet
public const string PlaystationEXEDateField = "EXE Date";
public const string PlayStationEDCField = "EDC"; // TODO: Not automatic yet
public const string PlayStationAntiModchipField = "Anti-modchip"; // TODO: Not automatic yet
public const string PlayStationLibCryptField = "LibCrypt"; // TODO: Not automatic yet
public const string SaturnHeaderField = "Header"; // TODO: Not automatic yet
public const string SaturnBuildDateField = "Build Date"; // TODO: Not automatic yet
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

@@ -69,6 +69,8 @@
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Management" />
<Reference Include="System.Management.Instrumentation" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
@@ -89,7 +91,9 @@
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Constants.cs" />
<Compile Include="Utilities.cs" />
<Compile Include="Utilities\DumpInformation.cs" />
<Compile Include="Utilities\Validation.cs" />
<Compile Include="Utilities\Converters.cs" />
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

View File

@@ -16,6 +16,8 @@
// Special Formats
GameCubeGameDisc,
WiiOpticalDisc,
WiiUOpticalDisc,
UMD,
// Keeping this separate since it's currently unsupported in the UI
@@ -38,7 +40,8 @@
CommodoreAmigaCDTV,
MattelHyperscan,
MicrosoftXBOX,
MicrosoftXBOX360,
MicrosoftXBOX360XDG2,
MicrosoftXBOX360XDG3,
MicrosoftXBOXOne,
NECPCEngineTurboGrafxCD,
NECPCFX,
@@ -77,14 +80,59 @@
#region Arcade
AmigaCUBOCD32,
AmericanLaserGames3DO,
Atari3DO,
Atronic,
AUSCOMSystem1,
BallyGameMagic,
CapcomCPSystemIII,
GlobalVRVarious,
GlobalVRVortek,
GlobalVRVortekV3,
ICEPCHardware,
IncredibleTechnologiesEagle,
IncredibleTechnologiesVarious,
KonamiFirebeat,
KonamiGVSystem,
KonamiM2,
KonamiPython,
KonamiPython2,
KonamiSystem573,
KonamiTwinkle,
KonamiVarious,
MeritIndustriesBoardwalk,
MeritIndustriesMegaTouchAurora,
MeritIndustriesMegaTouchForce,
MeritIndustriesMegaTouchION,
MeritIndustriesMegaTouchMaxx,
MeritIndustriesMegaTouchXL,
NamcoCapcomSystem256,
NamcoCapcomTaitoSystem246,
NamcoSegaNintendoTriforce,
NamcoSystem246,
NamcoSystem12,
NamcoSystem357,
NewJatreCDi,
NichibutsuHighRateSystem,
NichibutsuSuperCD,
NichibutsuXRateSystem,
PhotoPlayVarious,
RawThrillsVarious,
SegaChihiro,
SegaEuropaR,
SegaLindbergh,
SegaNaomi,
SegaNaomi2,
SegaNu,
SegaRingEdge,
SegaRingEdge2,
SegaRingWide,
SegaSTV,
SegaSystem32,
SeibuCATSSystem,
TABAustriaQuizard,
TandyMemorexVisualInformationSystem,
TsunamiTsuMoMultiGameMotionSystem,
#endregion

View File

@@ -46,10 +46,10 @@
<ComboBox x:Name="cmb_DiscType" Grid.Row="0" Grid.Column="1" Height="22" SelectionChanged="cmb_DiscType_SelectionChanged" />
<Label Grid.Row="1" Grid.Column="0" VerticalAlignment="Center">Output Filename</Label>
<TextBox x:Name="txt_OutputFilename" Grid.Row="1" Grid.Column="1" Height="22"></TextBox>
<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" Text="ISO" />
<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>
@@ -58,14 +58,15 @@
<Label Grid.Row="4" Grid.Column="0" VerticalAlignment="Center">Drive Speed</Label>
<ComboBox x:Name="cmb_DriveSpeed" Grid.Row="4" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="left" SelectionChanged="cmb_DriveSpeed_SelectionChanged"/>
<Label Grid.Row="5" Grid.Column="0" VerticalAlignment="Center">Custom Parameters</Label>
<TextBox x:Name="txt_CustomParameters" Grid.Row="5" Grid.Column="1" Height="22" Width="397" HorizontalAlignment="left" IsEnabled="False" />
<Label Grid.Row="5" Grid.Column="0" VerticalAlignment="Center">Parameters</Label>
<TextBox x:Name="txt_Parameters" Grid.Row="5" Grid.Column="1" Height="22" Width="397" HorizontalAlignment="left" IsEnabled="False" />
</Grid>
<Grid Grid.Row="2" Grid.Column="0" Margin="15,19.6,15.2,9.8" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
@@ -73,6 +74,7 @@
<Button x:Name="btn_StartStop" Grid.Row="0" Grid.Column="0" Height="22" Width="150" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Start Dumping" Click="btn_StartStop_Click" IsEnabled="False" />
<Button x:Name="btn_Search" Grid.Row="0" Grid.Column="1" Height="22" Width="150" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Scan for disks" Click="btn_Search_Click" />
<CheckBox x:Name="chk_EjectWhenDone" Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Eject When Done" IsChecked="False" />
</Grid>
<Grid Grid.Row="3" Grid.Column="0" Margin="15,20.2,15.2,9.8" Grid.ColumnSpan="2">

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using WinForms = System.Windows.Forms;
using DICUI.Utilities;
namespace DICUI
{
@@ -18,9 +19,10 @@ namespace DICUI
private string dicPath;
private string psxtPath;
private string sgRawPath;
private string subdumpPath;
// Private UI-related variables
private List<Tuple<char, string>> _drives { get; set; }
private List<Tuple<char, string, bool>> _drives { get; set; }
private List<int> _driveSpeeds { get { return new List<int> { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 }; } }
private List<Tuple<string, KnownSystem?, DiscType?>> _systems { get; set; }
private Process childProcess { get; set; }
@@ -48,6 +50,7 @@ namespace DICUI
private void btn_StartStop_Click(object sender, RoutedEventArgs e)
{
// Dump or stop the dump
if ((string)btn_StartStop.Content == UIElements.StartDumping)
{
StartDumping();
@@ -55,6 +58,11 @@ namespace DICUI
else if ((string)btn_StartStop.Content == UIElements.StopDumping)
{
CancelDumping();
if (chk_EjectWhenDone.IsChecked == true)
{
EjectDisc();
}
}
}
@@ -73,8 +81,8 @@ namespace DICUI
private void cmb_DiscType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
EnsureDiscInformation();
GetOutputNames();
EnsureDiscInformation();
}
private void cmb_DriveLetter_SelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -111,6 +119,16 @@ namespace DICUI
childWindow.Close();
}
private void txt_OutputFilename_TextChanged(object sender, TextChangedEventArgs e)
{
EnsureDiscInformation();
}
private void txt_OutputDirectory_TextChanged(object sender, TextChangedEventArgs e)
{
EnsureDiscInformation();
}
#endregion
#region Helpers
@@ -120,7 +138,7 @@ namespace DICUI
/// </summary>
private void PopulateSystems()
{
_systems = Utilities.CreateListOfSystems();
_systems = Utilities.Validation.CreateListOfSystems();
cmb_DiscType.ItemsSource = _systems;
cmb_DiscType.DisplayMemberPath = "Item1";
cmb_DiscType.SelectedIndex = 0;
@@ -136,7 +154,7 @@ namespace DICUI
private void PopulateDrives()
{
// Populate the list of drives and add it to the combo box
_drives = Utilities.CreateListOfDrives();
_drives = Utilities.Validation.CreateListOfDrives();
cmb_DriveLetter.ItemsSource = _drives;
cmb_DriveLetter.DisplayMemberPath = "Item1";
cmb_DriveLetter.SelectedIndex = 0;
@@ -145,7 +163,7 @@ namespace DICUI
if (cmb_DriveLetter.Items.Count > 0)
{
lbl_Status.Content = "Valid optical disc found! Choose your Disc Type";
btn_StartStop.IsEnabled = true;
btn_StartStop.IsEnabled = (_drives.Count > 0 ? true : false);
}
else
{
@@ -182,24 +200,42 @@ namespace DICUI
/// </summary>
private async void StartDumping()
{
// Local variables
string driveLetter = cmb_DriveLetter.Text;
string outputDirectory = txt_OutputDirectory.Text;
string outputFilename = txt_OutputFilename.Text;
btn_StartStop.Content = UIElements.StopDumping;
// Get the currently selected item
// 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(txt_CustomParameters.Text)
|| !Utilities.ValidateParameters(txt_CustomParameters.Text))
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))
{
@@ -209,7 +245,7 @@ namespace DICUI
}
// If a complete dump already exists
if (Utilities.FoundAllFiles(outputDirectory, outputFilename, selected.Item3))
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)
@@ -221,26 +257,26 @@ namespace DICUI
}
lbl_Status.Content = "Beginning dumping process";
string parameters = txt_CustomParameters.Text;
string parameters = txt_Parameters.Text;
await Task.Run(
() =>
await Task.Run(() =>
{
childProcess = new Process()
{
childProcess = new Process()
StartInfo = new ProcessStartInfo()
{
StartInfo = new ProcessStartInfo()
{
FileName = dicPath,
Arguments = parameters,
},
};
childProcess.Start();
childProcess.WaitForExit();
});
FileName = dicPath,
Arguments = parameters,
},
};
childProcess.Start();
childProcess.WaitForExit();
});
// Special cases
switch (selected.Item2)
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))
@@ -249,16 +285,40 @@ namespace DICUI
break;
}
childProcess = new Process()
await Task.Run(() =>
{
StartInfo = new ProcessStartInfo()
childProcess = new Process()
{
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();
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))
@@ -269,56 +329,66 @@ namespace DICUI
// Invoke the program with all 3 configurations
// TODO: Use these outputs for PSX information
childProcess = new Process()
await Task.Run(() =>
{
StartInfo = new ProcessStartInfo()
childProcess = new Process()
{
FileName = psxtPath,
Arguments = "\"" + Utilities.GetFirstTrack(outputDirectory, outputFilename) + "\" > " + "\"" + Path.Combine(outputDirectory, "psxt001z.txt"),
},
};
childProcess.Start();
childProcess.WaitForExit();
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()
childProcess = new Process()
{
FileName = psxtPath,
Arguments = "--libcrypt " + "\"" + Path.Combine(outputDirectory, outputFilename + ".sub") + "\" > " + "\"" + Path.Combine(outputDirectory, "libcrypt.txt"),
},
};
childProcess.Start();
childProcess.WaitForExit();
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()
childProcess = new Process()
{
FileName = psxtPath,
Arguments = "--libcryptdrvfast " + driveLetter + " > " + "\"" + Path.Combine(outputDirectory, "libcryptdrv.log"),
},
};
childProcess.Start();
childProcess.WaitForExit();
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 (!Utilities.FoundAllFiles(outputDirectory, outputFilename, selected.Item3))
if (!DumpInformation.FoundAllFiles(outputDirectory, outputFilename, type))
{
lbl_Status.Content = "Error! Please check output directory as dump may be incomplete!";
btn_StartStop.Content = UIElements.StartDumping;
if (chk_EjectWhenDone.IsChecked == true)
{
EjectDisc();
}
return;
}
Dictionary<string, string> templateValues = DumpInformation.ExtractOutputInformation(outputDirectory, outputFilename, system, type, driveLetter);
List<string> formattedValues = DumpInformation.FormatOutputData(templateValues, system, type);
bool success = DumpInformation.WriteOutputData(outputDirectory, outputFilename, formattedValues);
lbl_Status.Content = "Dumping complete!";
Dictionary<string, string> templateValues = Utilities.ExtractOutputInformation(outputDirectory, outputFilename, selected.Item2, selected.Item3);
List<string> formattedValues = Utilities.FormatOutputData(templateValues, selected.Item2, selected.Item3);
bool success = Utilities.WriteOutputData(outputDirectory, outputFilename, formattedValues);
btn_StartStop.Content = UIElements.StartDumping;
if (chk_EjectWhenDone.IsChecked == true)
{
EjectDisc();
}
}
/// <summary>
@@ -334,6 +404,43 @@ namespace DICUI
{ }
}
/// <summary>
/// Eject the disc using DIC
/// </summary>
private async void EjectDisc()
{
// Validate that the required program exits
if (!File.Exists(dicPath))
{
return;
}
CancelDumping();
var driveTuple = cmb_DriveLetter.SelectedItem as Tuple<char, string, bool>;
if (driveTuple.Item3)
{
return;
}
await Task.Run(() =>
{
childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = dicPath,
Arguments = DICCommands.Eject + " " + driveTuple.Item1,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
},
};
childProcess.Start();
childProcess.WaitForExit();
});
}
/// <summary>
/// Ensure information is consistent with the currently selected disc type
/// </summary>
@@ -356,62 +463,101 @@ namespace DICUI
break;
case DiscType.GameCubeGameDisc:
case DiscType.GDROM:
lbl_Status.Content = string.Format("{0} discs are partially supported by DIC", Utilities.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = true;
lbl_Status.Content = string.Format("{0} discs are partially supported by DIC", Converters.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = (_drives.Count > 0 ? true : false);
break;
case DiscType.HDDVD:
case DiscType.UMD:
lbl_Status.Content = string.Format("{0} discs are not currently supported by DIC", Utilities.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = true;
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;
case DiscType.DVD5:
case DiscType.DVD9:
if (tuple.Item2 == KnownSystem.MicrosoftXBOX360XDG3)
{
lbl_Status.Content = string.Format("{0} discs are not currently supported by DIC", Converters.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = false;
}
else
{
lbl_Status.Content = string.Format("{0} ready to dump", Converters.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = (_drives.Count > 0 ? true : false);
}
break;
default:
lbl_Status.Content = string.Format("{0} ready to dump", Utilities.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = true;
lbl_Status.Content = string.Format("{0} ready to dump", Converters.DiscTypeToString(tuple.Item3));
btn_StartStop.IsEnabled = (_drives.Count > 0 ? true : false);
break;
}
// If we're in a type that doesn't support drive speeds
switch (tuple.Item3)
{
case DiscType.Floppy:
case DiscType.BD25:
case DiscType.BD50:
cmb_DriveSpeed.IsEnabled = false;
break;
default:
cmb_DriveSpeed.IsEnabled = true;
if (tuple.Item2 == KnownSystem.MicrosoftXBOX
|| tuple.Item2 == KnownSystem.MicrosoftXBOX360XDG2
|| tuple.Item2 == KnownSystem.MicrosoftXBOX360XDG3)
{
cmb_DriveSpeed.IsEnabled = false;
}
else
{
cmb_DriveSpeed.IsEnabled = true;
}
break;
}
// Special case for Custom input
if (tuple.Item1 == "Custom Input" && tuple.Item2 == KnownSystem.NONE && tuple.Item3 == DiscType.NONE)
{
txt_CustomParameters.IsEnabled = true;
txt_Parameters.IsEnabled = true;
txt_OutputFilename.IsEnabled = false;
txt_OutputDirectory.IsEnabled = false;
btn_OutputDirectoryBrowse.IsEnabled = false;
cmb_DriveLetter.IsEnabled = false;
cmb_DriveSpeed.IsEnabled = false;
btn_StartStop.IsEnabled = (_drives.Count > 0 ? true : false);
lbl_Status.Content = "User input mode";
}
else
{
txt_CustomParameters.IsEnabled = false;
txt_Parameters.IsEnabled = false;
txt_OutputFilename.IsEnabled = true;
txt_OutputDirectory.IsEnabled = true;
btn_OutputDirectoryBrowse.IsEnabled = true;
cmb_DriveLetter.IsEnabled = true;
cmb_DriveSpeed.IsEnabled = true;
// Populate with the correct params for inputs (if we're not on the default option)
if (cmb_DiscType.SelectedIndex > 0)
{
var selected = cmb_DiscType.SelectedValue as Tuple<string, KnownSystem?, DiscType?>;
string discType = Utilities.GetBaseCommand(selected.Item3);
List<string> defaultParams = Utilities.GetDefaultParameters(selected.Item2, selected.Item3);
txt_CustomParameters.Text = discType
+ " " + cmb_DriveLetter.Text
+ " \"" + Path.Combine(txt_OutputDirectory.Text, txt_OutputFilename.Text + Utilities.GetDefaultExtension(selected.Item3)) + "\" "
+ (selected.Item3 != DiscType.BD25 && selected.Item3 != DiscType.BD50 ? (int)cmb_DriveSpeed.SelectedItem + " " : "")
var driveletter = cmb_DriveLetter.SelectedValue as Tuple<char, string, bool>;
// If either item is invalid, skip this
if (selected == null || driveletter == null)
{
return;
}
string discType = Converters.KnownSystemAndDiscTypeToBaseCommand(selected.Item2, selected.Item3);
List<string> defaultParams = Converters.KnownSystemAndDiscTypeToParameters(selected.Item2, selected.Item3);
txt_Parameters.Text = discType
+ " " + driveletter.Item1
+ " \"" + Path.Combine(txt_OutputDirectory.Text, txt_OutputFilename.Text) + "\" "
+ (selected.Item3 != DiscType.Floppy
&& selected.Item3 != DiscType.BD25
&& selected.Item3 != DiscType.BD50
&& selected.Item2 != KnownSystem.MicrosoftXBOX
&& selected.Item2 != KnownSystem.MicrosoftXBOX360XDG2
&& selected.Item2 != KnownSystem.MicrosoftXBOX360XDG3
? (int)cmb_DriveSpeed.SelectedItem + " " : "")
+ string.Join(" ", defaultParams);
}
}
@@ -422,13 +568,13 @@ namespace DICUI
/// </summary>
private void GetOutputNames()
{
var driveTuple = cmb_DriveLetter.SelectedItem as Tuple<char, string>;
var driveTuple = cmb_DriveLetter.SelectedItem as Tuple<char, string, bool>;
var discTuple = cmb_DiscType.SelectedItem as Tuple<string, KnownSystem?, DiscType?>;
if (driveTuple != null && discTuple != null)
{
txt_OutputDirectory.Text = Path.Combine(defaultOutputPath, driveTuple.Item2);
txt_OutputFilename.Text = driveTuple.Item2 + Utilities.GetDefaultExtension(discTuple.Item3);
txt_OutputFilename.Text = driveTuple.Item2 + Converters.DiscTypeToExtension(discTuple.Item3);
}
else
{
@@ -443,8 +589,8 @@ namespace DICUI
private void SetSupportedDriveSpeed()
{
// Get the drive letter from the selected item
var selected = cmb_DriveLetter.SelectedItem as Tuple<char, string>;
if (selected == null)
var selected = cmb_DriveLetter.SelectedItem as Tuple<char, string, bool>;
if (selected == null || selected.Item3)
{
return;
}
@@ -461,7 +607,7 @@ namespace DICUI
StartInfo = new ProcessStartInfo()
{
FileName = dicPath,
Arguments = DICCommands.DriveSpeedCommand + " " + driveLetter,
Arguments = DICCommands.DriveSpeed + " " + driveLetter,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
@@ -503,8 +649,10 @@ namespace DICUI
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
};
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = (GridLength)(new GridLengthConverter().ConvertFromString("1.2*")) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = (GridLength)(new GridLengthConverter().ConvertFromString("2.5*")) });
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());
@@ -557,35 +705,70 @@ namespace DICUI
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, 3);
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, 3);
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;
Grid.SetRow(acceptButton, 4);
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;
Grid.SetRow(cancelButton, 4);
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);
@@ -593,10 +776,11 @@ namespace DICUI
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(acceptButton);
grid.Children.Add(cancelButton);
grid.Children.Add(buttonGrid);
// Now show the child window
childWindow.Content = grid;
@@ -622,8 +806,10 @@ namespace DICUI
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[7])).Text);
configFile.AppSettings.Settings.Add("defaultOutputPath", ((TextBox)(((Grid)childWindow.Content).Children[9])).Text);
configFile.Save(ConfigurationSaveMode.Modified);
}
@@ -635,6 +821,7 @@ namespace DICUI
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";
}

View File

@@ -21,19 +21,59 @@ NHellFire - Contributer
Dizzzy - Concept/Ideas/Beta tester
## Changelist
Download the latest release here:
[https://github.com/reignstumble/DICUI/releases](https://github.com/reignstumble/DICUI/releases)
--------------------------------------------------------------------------
2018-06-15
--------------------------------------------------------------------------
Version 1.06 released:
- 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)
--------------------------------------------------------------------------
2018-06-14
--------------------------------------------------------------------------
Version 1.05a released:
- Fixed some ordering and nullability issues
- Added automatic fields for PS1, PS2, Saturn
Version 1.05 released:
- 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
**Known Issues:**
- PlayStation and Saturn discs still don't have all internal information automatically generated
--------------------------------------------------------------------------
2018-06-13
--------------------------------------------------------------------------
Version 1.04b released:
- Added subIntention reading
- Fixed extra extensions being appended
- Fixed internationalization error (number formatting)
- Fixed "Custom Input" not working
Version 1.04a released:
- Fixed issue with empty trays
- Added settings dialog
--------------------------------------------------------------------------
2018-06-13
--------------------------------------------------------------------------
Version 1.04 released:
- Behind-the-scenes fixes and formatting
@@ -54,7 +94,6 @@ Version 1.03 released:
- Discs unsupported by Windows are now regonized
- Extra \ when accepting default save has been removed.
--------------------------------------------------------------------------
2018-05-18
--------------------------------------------------------------------------
@@ -69,8 +108,5 @@ Version 1.02b released:
--------------------------------------------------------------------------
2018-05-14
--------------------------------------------------------------------------
Version 1.01d released:
Download the latest release here:
https://github.com/reignstumble/DICUI/releases
Version 1.01d released

File diff suppressed because it is too large Load Diff

507
Utilities/Converters.cs Normal file
View File

@@ -0,0 +1,507 @@
using System.Collections.Generic;
namespace DICUI.Utilities
{
public static class Converters
{
/// <summary>
/// Get the DiscType associated with a given base command
/// </summary>
/// <param name="baseCommand">String value to check</param>
/// <returns>DiscType 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)
{
switch (baseCommand)
{
case DICCommands.CompactDisc:
return DiscType.CD;
case DICCommands.GDROM:
case DICCommands.Swap:
return DiscType.GDROM;
case DICCommands.DigitalVideoDisc:
return DiscType.DVD9;
case DICCommands.BluRay:
return DiscType.BD50;
case DICCommands.XBOX:
return DiscType.DVD5;
// Non-optical
case DICCommands.Floppy:
return DiscType.Floppy;
default:
return null;
}
}
/// <summary>
/// Get the most common known system for a given DiscType
/// </summary>
/// <param name="baseCommand">String value to check</param>
/// <returns>KnownSystem if possible, null on error</returns>
public static KnownSystem? BaseCommandToKnownSystem(string baseCommand)
{
switch (baseCommand)
{
case DICCommands.CompactDisc:
case DICCommands.DigitalVideoDisc:
case DICCommands.Floppy:
return KnownSystem.IBMPCCompatible;
case DICCommands.GDROM:
case DICCommands.Swap:
return KnownSystem.SegaDreamcast;
case DICCommands.BluRay:
return KnownSystem.SonyPlayStation3;
case DICCommands.XBOX:
return KnownSystem.MicrosoftXBOX;
default:
return null;
}
}
/// <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 the DIC command to be used for a given DiscType
/// </summary>
/// <param name="type">DiscType value to check</param>
/// <returns>String containing the command, null on error</returns>
public static string KnownSystemAndDiscTypeToBaseCommand(KnownSystem? sys, DiscType? type)
{
switch (type)
{
case DiscType.CD:
if (sys == KnownSystem.MicrosoftXBOX)
{
return DICCommands.XBOX;
}
return DICCommands.CompactDisc;
case DiscType.DVD5:
if (sys == KnownSystem.MicrosoftXBOX
|| sys == KnownSystem.MicrosoftXBOX360XDG2
|| sys == KnownSystem.MicrosoftXBOX360XDG3)
{
return DICCommands.XBOX;
}
return DICCommands.DigitalVideoDisc;
case DiscType.DVD9:
if (sys == KnownSystem.MicrosoftXBOX
|| sys == KnownSystem.MicrosoftXBOX360XDG2
|| sys == KnownSystem.MicrosoftXBOX360XDG3)
{
return DICCommands.XBOX;
}
return DICCommands.DigitalVideoDisc;
case DiscType.GDROM:
return DICCommands.GDROM;
case DiscType.HDDVD:
return null;
case DiscType.BD25:
case DiscType.BD50:
return DICCommands.BluRay;
// Special Formats
case DiscType.GameCubeGameDisc:
return DICCommands.DigitalVideoDisc;
case DiscType.WiiOpticalDisc:
return null;
case DiscType.WiiUOpticalDisc:
return null;
case DiscType.UMD:
return null;
// Non-optical
case DiscType.Floppy:
return DICCommands.Floppy;
default:
return null;
}
}
/// <summary>
/// Get list of default parameters for a given system and disc type
/// </summary>
/// <param name="sys">KnownSystem value to check</param>
/// <param name="type">DiscType value to check</param>
/// <returns>List of strings representing the parameters</returns>
public static List<string> KnownSystemAndDiscTypeToParameters(KnownSystem? sys, DiscType? type)
{
// First check to see if the combination of system and disctype is valid
List<DiscType?> validTypes = Validation.GetValidDiscTypes(sys);
if (!validTypes.Contains(type))
{
return null;
}
// Now sort based on disc type
List<string> parameters = new List<string>();
switch (type)
{
case DiscType.CD:
parameters.Add(DICFlags.C2Opcode); parameters.Add("20");
switch (sys)
{
case KnownSystem.AppleMacintosh:
case KnownSystem.IBMPCCompatible:
parameters.Add(DICFlags.NoFixSubQSecuROM);
parameters.Add(DICFlags.ScanFileProtect);
parameters.Add(DICFlags.ScanSectorProtect);
break;
case KnownSystem.NECPCEngineTurboGrafxCD:
parameters.Add(DICFlags.MCN);
break;
case KnownSystem.SonyPlayStation:
parameters.Add(DICFlags.ScanAntiMod);
break;
}
break;
case DiscType.DVD5:
// Currently no defaults set
break;
case DiscType.DVD9:
// Currently no defaults set
break;
case DiscType.GDROM:
parameters.Add(DICFlags.C2Opcode); parameters.Add("20");
break;
case DiscType.HDDVD:
break;
case DiscType.BD25:
// Currently no defaults set
break;
case DiscType.BD50:
// Currently no defaults set
break;
// Special Formats
case DiscType.GameCubeGameDisc:
parameters.Add(DICFlags.Raw);
break;
case DiscType.WiiOpticalDisc:
// Currently no defaults set
break;
case DiscType.WiiUOpticalDisc:
// Currently no defaults set
break;
case DiscType.UMD:
break;
// Non-optical
case DiscType.Floppy:
// Currently no defaults set
break;
}
return parameters;
}
/// <summary>
/// Get the string representation of the KnownSystem enum values
/// </summary>
/// <param name="sys">KnownSystem value to convert</param>
/// <returns>String representing the value, if possible</returns>
public static string KnownSystemToString(KnownSystem? sys)
{
switch (sys)
{
#region Consoles
case KnownSystem.BandaiPlaydiaQuickInteractiveSystem:
return "Bandai Playdia Quick Interactive System";
case KnownSystem.BandaiApplePippin:
return "Bandai / Apple Pippin";
case KnownSystem.CommodoreAmigaCD32:
return "Commodore Amiga CD32";
case KnownSystem.CommodoreAmigaCDTV:
return "Commodore Amiga CDTV";
case KnownSystem.MattelHyperscan:
return "Mattel HyperScan";
case KnownSystem.MicrosoftXBOX:
return "Microsoft XBOX";
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:
return "NEC PC-Engine / TurboGrafx CD";
case KnownSystem.NECPCFX:
return "NEC PC-FX / PC-FXGA";
case KnownSystem.NintendoGameCube:
return "Nintendo GameCube";
case KnownSystem.NintendoWii:
return "Nintendo Wii";
case KnownSystem.NintendoWiiU:
return "Nintendo Wii U";
case KnownSystem.Panasonic3DOInteractiveMultiplayer:
return "Panasonic 3DO Interactive Multiplayer";
case KnownSystem.PhilipsCDi:
return "Philips CD-i";
case KnownSystem.SegaCDMegaCD:
return "Sega CD / Mega CD";
case KnownSystem.SegaDreamcast:
return "Sega Dreamcast";
case KnownSystem.SegaSaturn:
return "Sega Saturn";
case KnownSystem.SNKNeoGeoCD:
return "SNK Neo Geo CD";
case KnownSystem.SonyPlayStation:
return "Sony PlayStation";
case KnownSystem.SonyPlayStation2:
return "Sony PlayStation 2";
case KnownSystem.SonyPlayStation3:
return "Sony PlayStation 3";
case KnownSystem.SonyPlayStation4:
return "Sony PlayStation 4";
case KnownSystem.SonyPlayStationPortable:
return "Sony PlayStation Portable";
case KnownSystem.VMLabsNuon:
return "VM Labs NUON";
case KnownSystem.VTechVFlashVSmilePro:
return "VTech V.Flash - V.Smile Pro";
case KnownSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem:
return "ZAPiT Games Game Wave Family Entertainment System";
#endregion
#region Computers
case KnownSystem.AcornArchimedes:
return "Acorn Archimedes";
case KnownSystem.AppleMacintosh:
return "Apple Macintosh";
case KnownSystem.CommodoreAmigaCD:
return "Commodore Amiga CD";
case KnownSystem.FujitsuFMTowns:
return "Fujitsu FM Towns series";
case KnownSystem.IBMPCCompatible:
return "IBM PC Compatible";
case KnownSystem.NECPC88:
return "NEC PC-88";
case KnownSystem.NECPC98:
return "NEC PC-98";
case KnownSystem.SharpX68000:
return "Sharp X68000";
#endregion
#region Arcade
case KnownSystem.AmigaCUBOCD32:
return "Amiga CUBO CD32";
case KnownSystem.AmericanLaserGames3DO:
return "American Laser Games 3DO";
case KnownSystem.Atari3DO:
return "Atari 3DO";
case KnownSystem.Atronic:
return "Atronic";
case KnownSystem.AUSCOMSystem1:
return "AUSCOM System 1";
case KnownSystem.BallyGameMagic:
return "Bally Game Magic";
case KnownSystem.CapcomCPSystemIII:
return "Capcom CP System III";
case KnownSystem.GlobalVRVarious:
return "Global VR PC-based Systems";
case KnownSystem.GlobalVRVortek:
return "Global VR Vortek";
case KnownSystem.GlobalVRVortekV3:
return "Global VR Vortek V3";
case KnownSystem.ICEPCHardware:
return "ICE PC-based Hardware";
case KnownSystem.IncredibleTechnologiesEagle:
return "Incredible Technologies Eagle";
case KnownSystem.IncredibleTechnologiesVarious:
return "Incredible Technologies PC-based Systems";
case KnownSystem.KonamiFirebeat:
return "Konami Firebeat";
case KnownSystem.KonamiGVSystem:
return "Konami GV System";
case KnownSystem.KonamiM2:
return "Konami M2";
case KnownSystem.KonamiPython:
return "Konami Python";
case KnownSystem.KonamiPython2:
return "Konami Python 2";
case KnownSystem.KonamiSystem573:
return "Konami System 573";
case KnownSystem.KonamiTwinkle:
return "Konami Twinkle";
case KnownSystem.KonamiVarious:
return "Konami PC-based Systems";
case KnownSystem.MeritIndustriesBoardwalk:
return "Merit Industries Boardwalk";
case KnownSystem.MeritIndustriesMegaTouchAurora:
return "Merit Industries MegaTouch Aurora";
case KnownSystem.MeritIndustriesMegaTouchForce:
return "Merit Industries MegaTouch Force";
case KnownSystem.MeritIndustriesMegaTouchION:
return "Merit Industries MegaTouch ION";
case KnownSystem.MeritIndustriesMegaTouchMaxx:
return "Merit Industries MegaTouch Maxx";
case KnownSystem.MeritIndustriesMegaTouchXL:
return "Merit Industries MegaTouch XL";
case KnownSystem.NamcoCapcomSystem256:
return "Namco / Capcom System 256/Super System 256";
case KnownSystem.NamcoCapcomTaitoSystem246:
return "Namco / Capcom / Taito System 246";
case KnownSystem.NamcoSegaNintendoTriforce:
return "Namco / Sega / Nintendo Triforce";
case KnownSystem.NamcoSystem12:
return "Namco System 12";
case KnownSystem.NamcoSystem357:
return "Namco System 357";
case KnownSystem.NewJatreCDi:
return "New Jatre CD-i";
case KnownSystem.NichibutsuHighRateSystem:
return "Nichibutsu High Rate System";
case KnownSystem.NichibutsuSuperCD:
return "Nichibutsu Super CD";
case KnownSystem.NichibutsuXRateSystem:
return "NichibutsuX-Rate System";
case KnownSystem.PhotoPlayVarious:
return "PhotoPlay PC-based Systems";
case KnownSystem.RawThrillsVarious:
return "Raw Thrills PC-based Systems";
case KnownSystem.SegaChihiro:
return "Sega Chihiro";
case KnownSystem.SegaEuropaR:
return "Sega Europa-R";
case KnownSystem.SegaLindbergh:
return "Sega Lindbergh";
case KnownSystem.SegaNaomi:
return "Sega Naomi";
case KnownSystem.SegaNaomi2:
return "Sega Naomi 2";
case KnownSystem.SegaNu:
return "Sega Nu";
case KnownSystem.SegaRingEdge:
return "Sega RingEdge";
case KnownSystem.SegaRingEdge2:
return "Sega RingEdge 2";
case KnownSystem.SegaRingWide:
return "Sega RingWide";
case KnownSystem.SegaSTV:
return "Sega STV";
case KnownSystem.SegaSystem32:
return "Sega System 32";
case KnownSystem.SeibuCATSSystem:
return "Seibu CATS System";
case KnownSystem.TABAustriaQuizard:
return "TAB-Austria Quizard";
case KnownSystem.TandyMemorexVisualInformationSystem:
return "Tandy / Memorex Visual Information System";
case KnownSystem.TsunamiTsuMoMultiGameMotionSystem:
return "Tsunami TsuMo Multi-Game Motion System";
#endregion
#region Others
case KnownSystem.AudioCD:
return "Audio CD";
case KnownSystem.BDVideo:
return "BD-Video";
case KnownSystem.DVDVideo:
return "DVD-Video";
case KnownSystem.EnhancedCD:
return "Enhanced CD";
case KnownSystem.PalmOS:
return "PalmOS";
case KnownSystem.PhilipsCDiDigitalVideo:
return "Philips CD-i Digital Video";
case KnownSystem.PhotoCD:
return "Photo CD";
case KnownSystem.PlayStationGameSharkUpdates:
return "PlayStation GameShark Updates";
case KnownSystem.TaoiKTV:
return "Tao iKTV";
case KnownSystem.TomyKissSite:
return "Tomy Kiss-Site";
case KnownSystem.VideoCD:
return "Video CD";
#endregion
case KnownSystem.NONE:
default:
return "Unknown";
}
}
}
}

View File

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

1157
Utilities/Validation.cs Normal file

File diff suppressed because it is too large Load Diff