2022-04-11 10:32:03 -07:00
using System ;
2021-08-04 14:17:53 -07:00
using System.Collections.Generic ;
2023-10-08 20:52:29 -04:00
using System.ComponentModel ;
2021-08-04 14:17:53 -07:00
using System.IO ;
2023-10-09 00:13:40 -04:00
using System.Threading.Tasks ;
2023-10-26 00:57:23 -04:00
using BinaryObjectScanner ;
2024-05-23 15:40:12 -04:00
using MPF.Frontend.ComboBoxItems ;
2024-05-28 14:19:59 -04:00
using MPF.Frontend.Tools ;
2024-05-23 14:12:50 -04:00
using SabreTools.IO ;
2024-11-16 01:07:47 -05:00
using SabreTools.IO.Extensions ;
2023-09-05 00:08:09 -04:00
using SabreTools.RedumpLib.Data ;
2021-08-04 14:17:53 -07:00
2024-05-23 15:40:12 -04:00
namespace MPF.Frontend.ViewModels
2021-08-04 14:17:53 -07:00
{
2023-10-08 20:52:29 -04:00
public class MainViewModel : INotifyPropertyChanged
2021-08-04 14:17:53 -07:00
{
#region Fields
2023-09-25 21:29:55 -04:00
/// <summary>
/// Access to the current options
/// </summary>
2024-12-06 00:35:25 -05:00
public Options Options
2023-09-25 21:29:55 -04:00
{
get = > _options ;
set
{
_options = value ;
OptionsLoader . SaveToConfig ( _options ) ;
}
}
2024-12-06 00:35:25 -05:00
private Options _options ;
2023-09-25 21:29:55 -04:00
2021-08-04 14:17:53 -07:00
/// <summary>
2023-10-08 23:06:17 -04:00
/// Indicates if SelectionChanged events can be executed
2021-08-04 14:17:53 -07:00
/// </summary>
2023-10-08 23:06:17 -04:00
public bool CanExecuteSelectionChanged { get ; private set ; } = false ;
/// <inheritdoc/>
2023-10-09 11:35:49 -04:00
public event PropertyChangedEventHandler ? PropertyChanged ;
2021-08-04 14:17:53 -07:00
2023-09-25 21:29:55 -04:00
/// <summary>
2023-10-08 23:40:56 -04:00
/// Action to process logging statements
2023-09-25 21:29:55 -04:00
/// </summary>
2023-10-09 11:35:49 -04:00
private Action < LogLevel , string > ? _logger ;
2023-09-25 21:29:55 -04:00
2023-10-09 11:01:43 -04:00
/// <summary>
/// Display a message to a user
/// </summary>
/// <remarks>
/// T1 - Title to display to the user
2024-01-11 16:24:17 +13:00
/// T2 - Message to display to the user
2023-10-09 11:01:43 -04:00
/// T3 - Number of default options to display
/// T4 - true for inquiry, false otherwise
/// TResult - true for positive, false for negative, null for neutral
/// </remarks>
2023-10-09 11:35:49 -04:00
private Func < string , string , int , bool , bool? > ? _displayUserMessage ;
2023-10-09 11:01:43 -04:00
2023-10-09 10:35:44 -04:00
/// <summary>
/// Detected media type, distinct from the selected one
/// </summary>
private MediaType ? _detectedMediaType ;
2023-10-08 23:06:17 -04:00
/// <summary>
/// Current dumping environment
/// </summary>
2023-10-09 11:35:49 -04:00
private DumpEnvironment ? _environment ;
2023-10-08 20:52:29 -04:00
2023-10-08 23:15:24 -04:00
/// <summary>
/// Function to process user information
/// </summary>
2024-11-03 22:29:26 -05:00
private ProcessUserInfoDelegate ? _processUserInfo ;
2023-10-08 23:15:24 -04:00
2021-08-04 14:17:53 -07:00
#endregion
2023-10-08 20:52:29 -04:00
#region Properties
2021-08-04 14:17:53 -07:00
2024-01-25 08:57:21 +13:00
/// <summary>
/// Indicates the status of the check dump menu item
/// </summary>
public bool CheckDumpMenuItemEnabled
{
get = > _checkDumpMenuItemEnabled ;
set
{
_checkDumpMenuItemEnabled = value ;
TriggerPropertyChanged ( nameof ( CheckDumpMenuItemEnabled ) ) ;
}
}
private bool _checkDumpMenuItemEnabled ;
2024-02-19 10:38:28 +09:00
/// <summary>
/// Indicates the status of the create IRD menu item
/// </summary>
public bool CreateIRDMenuItemEnabled
{
get = > _createIRDMenuItemEnabled ;
set
{
_createIRDMenuItemEnabled = value ;
TriggerPropertyChanged ( nameof ( CreateIRDMenuItemEnabled ) ) ;
}
}
private bool _createIRDMenuItemEnabled ;
2023-10-08 22:49:46 -04:00
/// <summary>
/// Indicates the status of the options menu item
/// </summary>
public bool OptionsMenuItemEnabled
{
get = > _optionsMenuItemEnabled ;
set
{
_optionsMenuItemEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( OptionsMenuItemEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _optionsMenuItemEnabled ;
2021-08-04 14:17:53 -07:00
/// <summary>
2023-10-08 20:52:29 -04:00
/// Currently selected system value
2021-08-04 14:17:53 -07:00
/// </summary>
2023-10-08 20:52:29 -04:00
public RedumpSystem ? CurrentSystem
{
get = > _currentSystem ;
set
{
_currentSystem = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( CurrentSystem ) ) ;
2023-10-08 20:52:29 -04:00
}
}
private RedumpSystem ? _currentSystem ;
2021-08-04 14:17:53 -07:00
2023-10-08 22:49:46 -04:00
/// <summary>
/// Indicates the status of the system type combo box
/// </summary>
public bool SystemTypeComboBoxEnabled
{
get = > _systemTypeComboBoxEnabled ;
set
{
_systemTypeComboBoxEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( SystemTypeComboBoxEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _systemTypeComboBoxEnabled ;
2021-08-04 14:17:53 -07:00
/// <summary>
2023-10-08 20:52:29 -04:00
/// Currently selected media type value
2021-08-04 14:17:53 -07:00
/// </summary>
2023-10-08 20:52:29 -04:00
public MediaType ? CurrentMediaType
{
get = > _currentMediaType ;
set
{
_currentMediaType = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( CurrentMediaType ) ) ;
2023-10-08 20:52:29 -04:00
}
}
private MediaType ? _currentMediaType ;
2021-08-04 14:17:53 -07:00
2023-10-08 22:49:46 -04:00
/// <summary>
/// Indicates the status of the media type combo box
/// </summary>
public bool MediaTypeComboBoxEnabled
{
get = > _mediaTypeComboBoxEnabled ;
set
{
_mediaTypeComboBoxEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( MediaTypeComboBoxEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _mediaTypeComboBoxEnabled ;
2023-04-11 11:15:53 -04:00
/// <summary>
2023-10-08 20:52:29 -04:00
/// Currently provided output path
2024-01-11 13:42:34 +13:00
/// Not guaranteed to be a valid path
2023-10-08 20:52:29 -04:00
/// </summary>
public string OutputPath
{
get = > _outputPath ;
set
{
_outputPath = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( OutputPath ) ) ;
2023-10-08 20:52:29 -04:00
}
}
private string _outputPath ;
2023-10-08 22:49:46 -04:00
/// <summary>
/// Indicates the status of the output path text box
/// </summary>
public bool OutputPathTextBoxEnabled
{
get = > _outputPathTextBoxEnabled ;
set
{
_outputPathTextBoxEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( OutputPathTextBoxEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _outputPathTextBoxEnabled ;
/// <summary>
/// Indicates the status of the output path browse button
/// </summary>
public bool OutputPathBrowseButtonEnabled
{
get = > _outputPathBrowseButtonEnabled ;
set
{
_outputPathBrowseButtonEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( OutputPathBrowseButtonEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _outputPathBrowseButtonEnabled ;
2023-10-08 20:52:29 -04:00
/// <summary>
/// Currently selected drive value
2023-04-11 11:15:53 -04:00
/// </summary>
2023-10-09 11:35:49 -04:00
public Drive ? CurrentDrive
2023-10-08 20:52:29 -04:00
{
get = > _currentDrive ;
set
{
_currentDrive = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( CurrentDrive ) ) ;
2023-10-08 20:52:29 -04:00
}
}
2023-10-09 11:35:49 -04:00
private Drive ? _currentDrive ;
2023-10-08 20:52:29 -04:00
2023-10-08 22:49:46 -04:00
/// <summary>
/// Indicates the status of the drive combo box
/// </summary>
public bool DriveLetterComboBoxEnabled
{
get = > _driveLetterComboBoxEnabled ;
set
{
_driveLetterComboBoxEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( DriveLetterComboBoxEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _driveLetterComboBoxEnabled ;
2023-10-08 20:52:29 -04:00
/// <summary>
/// Currently selected drive speed value
/// </summary>
public int DriveSpeed
{
get = > _driveSpeed ;
set
{
_driveSpeed = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( DriveSpeed ) ) ;
2023-10-08 20:52:29 -04:00
}
}
private int _driveSpeed ;
2023-10-08 22:49:46 -04:00
/// <summary>
/// Indicates the status of the drive speed combo box
/// </summary>
public bool DriveSpeedComboBoxEnabled
{
get = > _driveSpeedComboBoxEnabled ;
set
{
_driveSpeedComboBoxEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( DriveSpeedComboBoxEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _driveSpeedComboBoxEnabled ;
2023-10-08 20:52:29 -04:00
/// <summary>
/// Currently selected dumping program
/// </summary>
public InternalProgram CurrentProgram
{
get = > _currentProgram ;
set
{
_currentProgram = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( CurrentProgram ) ) ;
2023-10-08 20:52:29 -04:00
}
}
private InternalProgram _currentProgram ;
2023-10-08 22:49:46 -04:00
/// <summary>
/// Indicates the status of the dumping program combo box
/// </summary>
public bool DumpingProgramComboBoxEnabled
{
get = > _dumpingProgramComboBoxEnabled ;
set
{
_dumpingProgramComboBoxEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( DumpingProgramComboBoxEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _dumpingProgramComboBoxEnabled ;
2023-10-08 20:52:29 -04:00
/// <summary>
/// Currently provided parameters
/// </summary>
public string Parameters
{
get = > _parameters ;
set
{
_parameters = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( Parameters ) ) ;
2023-10-08 20:52:29 -04:00
}
}
private string _parameters ;
2023-10-08 22:49:46 -04:00
/// <summary>
/// Indicates the status of the parameters text box
/// </summary>
2024-12-20 22:31:10 -05:00
public bool ParametersTextBoxEnabled
{
get = > _parametersTextBoxEnabled ;
set
{
_parametersTextBoxEnabled = value ;
TriggerPropertyChanged ( nameof ( ParametersTextBoxEnabled ) ) ;
}
}
private bool _parametersTextBoxEnabled ;
/// <summary>
/// Indicates the status of the parameters check box
/// </summary>
2023-10-08 22:49:46 -04:00
public bool ParametersCheckBoxEnabled
{
get = > _parametersCheckBoxEnabled ;
set
{
_parametersCheckBoxEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( ParametersCheckBoxEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _parametersCheckBoxEnabled ;
/// <summary>
/// Indicates the status of the parameters check box
/// </summary>
public bool EnableParametersCheckBoxEnabled
{
get = > _enableParametersCheckBoxEnabled ;
set
{
_enableParametersCheckBoxEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( EnableParametersCheckBoxEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _enableParametersCheckBoxEnabled ;
/// <summary>
/// Indicates the status of the start/stop button
/// </summary>
public bool StartStopButtonEnabled
{
get = > _startStopButtonEnabled ;
set
{
_startStopButtonEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( StartStopButtonEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _startStopButtonEnabled ;
/// <summary>
/// Current value for the start/stop dumping button
/// </summary>
public object StartStopButtonText
{
get = > _startStopButtonText ;
set
{
2023-10-09 11:35:49 -04:00
_startStopButtonText = ( value as string ) ? ? string . Empty ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( StartStopButtonText ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private string _startStopButtonText ;
/// <summary>
/// Indicates the status of the media scan button
/// </summary>
public bool MediaScanButtonEnabled
{
get = > _mediaScanButtonEnabled ;
set
{
_mediaScanButtonEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( MediaScanButtonEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _mediaScanButtonEnabled ;
/// <summary>
/// Indicates the status of the update volume label button
/// </summary>
public bool UpdateVolumeLabelEnabled
{
get = > _updateVolumeLabelEnabled ;
set
{
_updateVolumeLabelEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( UpdateVolumeLabelEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _updateVolumeLabelEnabled ;
/// <summary>
/// Indicates the status of the copy protect scan button
/// </summary>
public bool CopyProtectScanButtonEnabled
{
get = > _copyProtectScanButtonEnabled ;
set
{
_copyProtectScanButtonEnabled = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( CopyProtectScanButtonEnabled ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _copyProtectScanButtonEnabled ;
2023-10-08 20:52:29 -04:00
/// <summary>
/// Currently displayed status
/// </summary>
public string Status
{
get = > _status ;
set
{
_status = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( Status ) ) ;
2023-10-08 20:52:29 -04:00
}
}
private string _status ;
2023-04-11 11:15:53 -04:00
2023-10-08 22:49:46 -04:00
/// <summary>
/// Indicates the status of the log panel
/// </summary>
public bool LogPanelExpanded
{
get = > _logPanelExpanded ;
set
{
_logPanelExpanded = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( LogPanelExpanded ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private bool _logPanelExpanded ;
2021-08-04 14:17:53 -07:00
#endregion
2023-10-08 20:52:29 -04:00
#region List Properties
2021-08-04 14:17:53 -07:00
/// <summary>
2023-10-08 20:52:29 -04:00
/// Current list of drives
2021-08-04 14:17:53 -07:00
/// </summary>
2023-10-08 20:52:29 -04:00
public List < Drive > Drives
{
get = > _drives ;
set
{
_drives = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( Drives ) ) ;
2023-10-08 20:52:29 -04:00
}
}
private List < Drive > _drives ;
2023-10-08 22:49:46 -04:00
/// <summary>
/// Current list of drive speeds
/// </summary>
public List < int > DriveSpeeds
{
get = > _driveSpeeds ;
set
{
_driveSpeeds = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( DriveSpeeds ) ) ;
2023-10-08 22:49:46 -04:00
}
}
private List < int > _driveSpeeds ;
2023-10-08 20:52:29 -04:00
/// <summary>
/// Current list of supported media types
/// </summary>
2023-10-09 11:35:49 -04:00
public List < Element < MediaType > > ? MediaTypes
2023-10-08 20:52:29 -04:00
{
get = > _mediaTypes ;
set
{
_mediaTypes = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( MediaTypes ) ) ;
2023-10-08 20:52:29 -04:00
}
}
2023-10-09 11:35:49 -04:00
private List < Element < MediaType > > ? _mediaTypes ;
2023-10-08 20:52:29 -04:00
/// <summary>
/// Current list of supported system profiles
/// </summary>
public List < RedumpSystemComboBoxItem > Systems
{
get = > _systems ;
set
{
_systems = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( Systems ) ) ;
2023-10-08 20:52:29 -04:00
}
}
private List < RedumpSystemComboBoxItem > _systems ;
/// <summary>
/// List of available internal programs
/// </summary>
public List < Element < InternalProgram > > InternalPrograms
{
get = > _internalPrograms ;
set
{
_internalPrograms = value ;
2023-10-11 12:26:24 -04:00
TriggerPropertyChanged ( nameof ( InternalPrograms ) ) ;
2023-10-08 20:52:29 -04:00
}
}
private List < Element < InternalProgram > > _internalPrograms ;
2021-08-04 14:17:53 -07:00
#endregion
2024-05-21 20:57:57 -04:00
#region Constants
2024-05-23 14:07:42 -04:00
private const string DiscNotDetectedValue = "Disc Not Detected" ;
2024-05-21 20:57:57 -04:00
private const string StartDumpingValue = "Start Dumping" ;
2024-05-23 14:07:42 -04:00
private const string StopDumpingValue = "Stop Dumping" ;
2024-05-21 20:57:57 -04:00
#endregion
2023-09-25 21:29:55 -04:00
/// <summary>
/// Generic constructor
/// </summary>
public MainViewModel ( )
{
_options = OptionsLoader . LoadFromConfig ( ) ;
2023-10-08 22:49:46 -04:00
2023-10-09 11:35:49 -04:00
// Added to clear warnings, all are set externally
2023-11-14 23:40:41 -05:00
_drives = [ ] ;
_driveSpeeds = [ ] ;
_internalPrograms = [ ] ;
2023-10-09 11:35:49 -04:00
_outputPath = string . Empty ;
_parameters = string . Empty ;
_startStopButtonText = string . Empty ;
_status = string . Empty ;
2023-11-14 23:40:41 -05:00
_systems = [ ] ;
2023-10-09 11:35:49 -04:00
2023-10-08 22:49:46 -04:00
OptionsMenuItemEnabled = true ;
2024-01-25 08:57:21 +13:00
CheckDumpMenuItemEnabled = true ;
2024-02-19 10:38:28 +09:00
CreateIRDMenuItemEnabled = true ;
2023-10-08 22:49:46 -04:00
SystemTypeComboBoxEnabled = true ;
MediaTypeComboBoxEnabled = true ;
2023-10-09 10:35:44 -04:00
OutputPathTextBoxEnabled = true ;
2023-10-11 13:13:36 -04:00
OutputPathBrowseButtonEnabled = true ;
2023-10-08 22:49:46 -04:00
DriveLetterComboBoxEnabled = true ;
DumpingProgramComboBoxEnabled = true ;
StartStopButtonEnabled = true ;
2024-05-21 20:57:57 -04:00
StartStopButtonText = StartDumpingValue ;
2023-10-08 22:49:46 -04:00
MediaScanButtonEnabled = true ;
2024-12-20 22:38:08 -05:00
ParametersCheckBoxEnabled = true ;
2023-10-15 15:33:18 -04:00
EnableParametersCheckBoxEnabled = true ;
2023-10-08 22:49:46 -04:00
LogPanelExpanded = _options . OpenLogWindowAtStartup ;
2023-11-14 23:40:41 -05:00
MediaTypes = [ ] ;
2024-11-21 11:55:00 -05:00
Systems = RedumpSystemComboBoxItem . GenerateElements ( ) ;
2023-11-14 23:40:41 -05:00
InternalPrograms = [ ] ;
2023-09-25 21:29:55 -04:00
}
2021-08-04 14:17:53 -07:00
/// <summary>
/// Initialize the main window after loading
/// </summary>
2023-10-09 11:01:43 -04:00
public void Init (
Action < LogLevel , string > loggerAction ,
Func < string , string , int , bool , bool? > displayUserMessage ,
2024-11-03 22:29:26 -05:00
ProcessUserInfoDelegate processUserInfo )
2021-08-04 14:17:53 -07:00
{
2023-10-08 23:40:56 -04:00
// Set the callbacks
_logger = loggerAction ;
2023-10-09 11:01:43 -04:00
_displayUserMessage = displayUserMessage ;
2023-10-08 23:15:24 -04:00
_processUserInfo = processUserInfo ;
2022-01-07 13:25:46 -08:00
2021-08-04 14:17:53 -07:00
// Finish initializing the rest of the values
2024-12-20 21:46:03 -05:00
InitializeUIValues ( removeEventHandlers : false , rebuildPrograms : true , rescanDrives : true ) ;
2021-08-04 14:17:53 -07:00
}
2023-10-08 20:52:29 -04:00
#region Property Updates
/// <summary>
/// Trigger a property changed event
/// </summary>
private void TriggerPropertyChanged ( string propertyName )
{
// Disable event handlers temporarily
2023-10-10 22:05:39 -04:00
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged ;
DisableEventHandlers ( ) ;
2023-10-08 20:52:29 -04:00
// If the property change event is initialized
2023-10-11 13:07:45 -04:00
PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( propertyName ) ) ;
2023-10-08 20:52:29 -04:00
2023-10-10 22:05:39 -04:00
// Reenable event handlers, if necessary
if ( cachedCanExecuteSelectionChanged ) EnableEventHandlers ( ) ;
2023-10-08 20:52:29 -04:00
}
#endregion
2021-08-04 14:17:53 -07:00
#region Population
/// <summary>
/// Get a complete list of active disc drives and fill the combo box
/// </summary>
/// <remarks>TODO: Find a way for this to periodically run, or have it hook to a "drive change" event</remarks>
2023-09-25 21:29:55 -04:00
private void PopulateDrives ( )
2021-08-04 14:17:53 -07:00
{
2023-10-08 20:52:29 -04:00
// Disable other UI updates
2023-10-10 22:05:39 -04:00
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged ;
DisableEventHandlers ( ) ;
2023-10-08 20:52:29 -04:00
2023-10-08 23:40:56 -04:00
VerboseLogLn ( "Scanning for drives.." ) ;
2021-08-04 14:17:53 -07:00
// Always enable the media scan
2024-11-12 22:18:08 -05:00
MediaScanButtonEnabled = true ;
UpdateVolumeLabelEnabled = true ;
2021-08-04 14:17:53 -07:00
2022-03-05 21:50:18 -08:00
// If we have a selected drive, keep track of it
2024-11-12 22:18:08 -05:00
char? lastSelectedDrive = CurrentDrive ? . Name ? [ 0 ] ? ? null ;
2022-03-05 21:50:18 -08:00
2021-08-04 14:17:53 -07:00
// Populate the list of drives and add it to the combo box
2024-11-12 22:18:08 -05:00
Drives = Drive . CreateListOfDrives ( Options . IgnoreFixedDrives ) ;
2021-08-04 14:17:53 -07:00
2023-10-08 20:52:29 -04:00
if ( Drives . Count > 0 )
2021-08-04 14:17:53 -07:00
{
2024-11-12 22:18:08 -05:00
VerboseLogLn ( $"Found {Drives.Count} drives: {string.Join(" , ", [.. Drives.ConvertAll(d => d.Name)])}" ) ;
2021-08-04 14:17:53 -07:00
2022-03-05 21:50:18 -08:00
// Check for the last selected drive, if possible
int index = - 1 ;
if ( lastSelectedDrive ! = null )
2023-10-18 01:47:42 -04:00
index = Drives . FindIndex ( d = > d . MarkedActive & & ( d . Name ? [ 0 ] ? ? '\0' ) = = lastSelectedDrive ) ;
2022-03-05 21:50:18 -08:00
// Check for active optical drives
if ( index = = - 1 )
index = Drives . FindIndex ( d = > d . MarkedActive & & d . InternalDriveType = = InternalDriveType . Optical ) ;
2021-08-04 14:17:53 -07:00
2022-03-05 21:50:18 -08:00
// Check for active floppy drives
2021-08-04 14:17:53 -07:00
if ( index = = - 1 )
index = Drives . FindIndex ( d = > d . MarkedActive & & d . InternalDriveType = = InternalDriveType . Floppy ) ;
2022-03-05 21:50:18 -08:00
// Check for any active drives
2021-08-04 14:17:53 -07:00
if ( index = = - 1 )
index = Drives . FindIndex ( d = > d . MarkedActive ) ;
// Set the selected index
2023-10-08 20:52:29 -04:00
CurrentDrive = ( index ! = - 1 ? Drives [ index ] : Drives [ 0 ] ) ;
2024-11-12 22:18:08 -05:00
Status = "Valid drive found! Choose your Media Type" ;
CopyProtectScanButtonEnabled = true ;
2021-08-04 14:17:53 -07:00
// Get the current system type
if ( index ! = - 1 )
2023-09-25 21:29:55 -04:00
DetermineSystemType ( ) ;
2021-08-04 14:17:53 -07:00
// Only enable the start/stop if we don't have the default selected
2024-11-12 22:18:08 -05:00
StartStopButtonEnabled = ShouldEnableDumpingButton ( ) ;
2021-08-04 14:17:53 -07:00
}
else
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( "Found no drives" ) ;
2024-11-12 22:18:08 -05:00
CurrentDrive = null ;
Status = "No valid drive found!" ;
StartStopButtonEnabled = false ;
CopyProtectScanButtonEnabled = false ;
2021-08-04 14:17:53 -07:00
}
2023-10-10 22:05:39 -04:00
// Reenable event handlers, if necessary
if ( cachedCanExecuteSelectionChanged ) EnableEventHandlers ( ) ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
/// Populate media type according to system type
/// </summary>
2023-09-25 21:16:43 -04:00
private void PopulateMediaType ( )
2021-08-04 14:17:53 -07:00
{
2023-10-08 20:52:29 -04:00
// Disable other UI updates
2023-10-10 22:05:39 -04:00
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged ;
DisableEventHandlers ( ) ;
2021-08-04 14:17:53 -07:00
2024-11-12 22:18:08 -05:00
if ( CurrentSystem ! = null )
2021-08-04 14:17:53 -07:00
{
2024-11-12 22:18:08 -05:00
var mediaTypeValues = CurrentSystem . MediaTypes ( ) ;
int index = mediaTypeValues . FindIndex ( m = > m = = CurrentMediaType ) ;
if ( CurrentMediaType ! = null & & index = = - 1 )
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"Disc of type '{CurrentMediaType.LongName()}' found, but the current system does not support it!" ) ;
2023-10-08 20:52:29 -04:00
2024-11-12 22:18:08 -05:00
MediaTypes = mediaTypeValues . ConvertAll ( m = > new Element < MediaType > ( m ? ? MediaType . NONE ) ) ;
MediaTypeComboBoxEnabled = MediaTypes . Count > 1 ;
CurrentMediaType = ( index > - 1 ? MediaTypes [ index ] : MediaTypes [ 0 ] ) ;
2021-08-04 14:17:53 -07:00
}
else
{
2024-11-12 22:18:08 -05:00
MediaTypeComboBoxEnabled = false ;
MediaTypes = null ;
CurrentMediaType = null ;
2021-08-04 14:17:53 -07:00
}
2023-10-10 22:05:39 -04:00
// Reenable event handlers, if necessary
if ( cachedCanExecuteSelectionChanged ) EnableEventHandlers ( ) ;
2021-08-04 14:17:53 -07:00
}
2023-04-11 11:15:53 -04:00
/// <summary>
/// Populate media type according to system type
/// </summary>
2023-09-25 21:29:55 -04:00
private void PopulateInternalPrograms ( )
2023-04-11 11:15:53 -04:00
{
2023-10-08 20:52:29 -04:00
// Disable other UI updates
2023-10-10 22:05:39 -04:00
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged ;
DisableEventHandlers ( ) ;
2023-10-08 20:52:29 -04:00
2024-02-22 00:14:39 +09:00
// Create a static list of supported programs, not everything
2024-11-16 01:07:47 -05:00
var ipArr = ( InternalProgram [ ] ) Enum . GetValues ( typeof ( InternalProgram ) ) ;
ipArr = Array . FindAll ( ipArr , ip = > InternalProgramExists ( ip ) ) ;
InternalPrograms = [ . . Array . ConvertAll ( ipArr , ip = > new Element < InternalProgram > ( ip ) ) ] ;
2024-02-22 00:14:39 +09:00
2023-04-11 11:15:53 -04:00
// Get the current internal program
2024-11-12 22:18:08 -05:00
InternalProgram internalProgram = Options . InternalProgram ;
2023-04-11 11:15:53 -04:00
// Select the current default dumping program
2024-02-22 00:14:39 +09:00
if ( InternalPrograms . Count = = 0 )
{
// If no programs are found, default to InternalProgram.NONE
2024-11-12 22:18:08 -05:00
CurrentProgram = InternalProgram . NONE ;
2024-02-22 00:14:39 +09:00
}
else
2024-05-23 14:07:42 -04:00
{
2024-02-22 00:14:39 +09:00
int currentIndex = InternalPrograms . FindIndex ( m = > m = = internalProgram ) ;
2024-11-12 22:18:08 -05:00
CurrentProgram = ( currentIndex > - 1 ? InternalPrograms [ currentIndex ] . Value : InternalPrograms [ 0 ] . Value ) ;
2024-02-22 00:14:39 +09:00
}
2023-10-08 20:52:29 -04:00
2023-10-10 22:05:39 -04:00
// Reenable event handlers, if necessary
if ( cachedCanExecuteSelectionChanged ) EnableEventHandlers ( ) ;
2023-04-11 11:15:53 -04:00
}
2021-08-04 14:17:53 -07:00
#endregion
#region UI Commands
2023-08-26 23:17:49 -04:00
/// <summary>
/// Change the currently selected dumping program
/// </summary>
2023-09-25 21:29:55 -04:00
public void ChangeDumpingProgram ( )
2023-08-26 23:17:49 -04:00
{
2024-11-12 22:18:08 -05:00
VerboseLogLn ( $"Changed dumping program to: {((InternalProgram?)CurrentProgram).LongName()}" ) ;
2023-09-25 21:29:55 -04:00
EnsureDiscInformation ( ) ;
2024-07-07 12:48:34 +09:00
// New output name depends on new environment
2023-09-25 21:29:55 -04:00
GetOutputNames ( false ) ;
2024-07-07 12:48:34 +09:00
// New environment depends on new output name
EnsureDiscInformation ( ) ;
2023-08-26 23:17:49 -04:00
}
2021-08-04 14:17:53 -07:00
/// <summary>
/// Change the currently selected media type
/// </summary>
2023-10-09 00:13:40 -04:00
public void ChangeMediaType ( System . Collections . IList removedItems , System . Collections . IList addedItems )
2021-08-04 14:17:53 -07:00
{
// Only change the media type if the selection and not the list has changed
2023-10-09 11:35:49 -04:00
if ( ( removedItems = = null | | removedItems . Count = = 1 ) & & ( addedItems = = null | | addedItems . Count = = 1 ) )
2023-09-25 21:29:55 -04:00
SetSupportedDriveSpeed ( ) ;
2021-08-04 14:17:53 -07:00
2023-09-25 21:29:55 -04:00
GetOutputNames ( false ) ;
EnsureDiscInformation ( ) ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
/// Change the currently selected system
/// </summary>
2023-09-25 21:29:55 -04:00
public void ChangeSystem ( )
2021-08-04 14:17:53 -07:00
{
2024-11-12 22:18:08 -05:00
VerboseLogLn ( $"Changed system to: {CurrentSystem.LongName()}" ) ;
2023-09-25 21:16:43 -04:00
PopulateMediaType ( ) ;
2023-09-25 21:29:55 -04:00
GetOutputNames ( false ) ;
EnsureDiscInformation ( ) ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
/// Check for available updates
/// </summary>
2024-11-03 22:51:24 -05:00
public void CheckForUpdates ( out bool different , out string message , out string? url )
2021-08-04 14:17:53 -07:00
{
2024-11-03 22:51:24 -05:00
FrontendTool . CheckForNewVersion ( out different , out message , out url ) ;
2021-08-04 14:17:53 -07:00
2023-10-08 23:40:56 -04:00
SecretLogLn ( message ) ;
2021-09-28 11:46:37 -07:00
if ( url = = null )
message = "An exception occurred while checking for versions, please try again later. See the log window for more details." ;
2021-08-04 14:17:53 -07:00
}
2022-01-07 13:25:46 -08:00
/// <summary>
2023-10-09 00:03:02 -04:00
/// Build the about text
/// </summary>
/// <returns></returns>
public string CreateAboutText ( )
{
string aboutText = $"Media Preservation Frontend (MPF)"
+ $"{Environment.NewLine}"
+ $"{Environment.NewLine}A community preservation frontend developed in C#."
+ $"{Environment.NewLine}Supports Redumper, Aaru, and DiscImageCreator."
+ $"{Environment.NewLine}Originally created to help the Redump project."
+ $"{Environment.NewLine}"
+ $"{Environment.NewLine}Thanks to everyone who has supported this project!"
+ $"{Environment.NewLine}"
2024-05-28 11:57:53 -04:00
+ $"{Environment.NewLine}Version {FrontendTool.GetCurrentVersion()}" ;
2023-10-09 00:03:02 -04:00
SecretLogLn ( aboutText ) ;
return aboutText ;
}
/// <summary>
/// Build a dummy SubmissionInfo
2022-01-07 13:25:46 -08:00
/// </summary>
2023-10-11 12:26:24 -04:00
public static SubmissionInfo CreateDebugSubmissionInfo ( )
2022-01-07 13:25:46 -08:00
{
2023-10-08 23:06:17 -04:00
return new SubmissionInfo ( )
2022-01-07 13:25:46 -08:00
{
SchemaVersion = 1 ,
2022-03-12 21:09:51 -08:00
FullyMatchedID = 3 ,
2023-11-14 23:40:41 -05:00
PartiallyMatchedIDs = [ 0 , 1 , 2 , 3 ] ,
2022-01-07 13:25:46 -08:00
Added = DateTime . UtcNow ,
LastModified = DateTime . UtcNow ,
CommonDiscInfo = new CommonDiscInfoSection ( )
{
2023-10-08 20:52:29 -04:00
System = SabreTools . RedumpLib . Data . RedumpSystem . IBMPCcompatible ,
2022-04-04 21:46:13 -07:00
Media = DiscType . BD128 ,
2022-01-07 13:25:46 -08:00
Title = "Game Title" ,
ForeignTitleNonLatin = "Foreign Game Title" ,
DiscNumberLetter = "1" ,
DiscTitle = "Install Disc" ,
Category = DiscCategory . Games ,
Region = Region . World ,
2023-11-14 23:40:41 -05:00
Languages = [ Language . English , Language . Spanish , Language . French ] ,
LanguageSelection = [ LanguageSelection . BiosSettings ] ,
2022-01-07 13:25:46 -08:00
Serial = "Disc Serial" ,
Layer0MasteringRing = "L0 Mastering Ring" ,
Layer0MasteringSID = "L0 Mastering SID" ,
Layer0ToolstampMasteringCode = "L0 Toolstamp" ,
Layer0MouldSID = "L0 Mould SID" ,
Layer0AdditionalMould = "L0 Additional Mould" ,
Layer1MasteringRing = "L1 Mastering Ring" ,
Layer1MasteringSID = "L1 Mastering SID" ,
Layer1ToolstampMasteringCode = "L1 Toolstamp" ,
Layer1MouldSID = "L1 Mould SID" ,
Layer1AdditionalMould = "L1 Additional Mould" ,
Layer2MasteringRing = "L2 Mastering Ring" ,
Layer2MasteringSID = "L2 Mastering SID" ,
Layer2ToolstampMasteringCode = "L2 Toolstamp" ,
Layer3MasteringRing = "L3 Mastering Ring" ,
Layer3MasteringSID = "L3 Mastering SID" ,
Layer3ToolstampMasteringCode = "L3 Toolstamp" ,
RingWriteOffset = "+12" ,
Barcode = "UPC Barcode" ,
EXEDateBuildDate = "19xx-xx-xx" ,
ErrorsCount = "0" ,
Comments = "Comment data line 1\r\nComment data line 2" ,
2023-09-05 00:08:09 -04:00
CommentsSpecialFields = new Dictionary < SiteCode , string > ( )
2022-01-07 13:25:46 -08:00
{
[SiteCode.ISBN] = "ISBN" ,
} ,
Contents = "Special contents 1\r\nSpecial contents 2" ,
2023-09-05 00:08:09 -04:00
ContentsSpecialFields = new Dictionary < SiteCode , string > ( )
2022-01-07 13:25:46 -08:00
{
[SiteCode.PlayableDemos] = "Game Demo 1" ,
} ,
} ,
VersionAndEditions = new VersionAndEditionsSection ( )
{
Version = "Original" ,
VersionDatfile = "Alt" ,
2023-11-14 23:40:41 -05:00
CommonEditions = [ "Taikenban" ] ,
2022-01-07 13:25:46 -08:00
OtherEditions = "Rerelease" ,
} ,
EDC = new EDCSection ( )
{
EDC = YesNo . Yes ,
} ,
ParentCloneRelationship = new ParentCloneRelationshipSection ( )
{
ParentID = "12345" ,
RegionalParent = false ,
} ,
Extras = new ExtrasSection ( )
{
PVD = "PVD with a stupidly long line and nothing else but a little more\nPVD with a stupidly long line and nothing else but a little more\nPVD with a stupidly long line and nothing else but a little more\nPVD with a stupidly long line and nothing else but a little more\nPVD with a stupidly long line and nothing else but a little more\nPVD with a stupidly long line and nothing else but a little more\n" ,
DiscKey = "Disc key" ,
DiscID = "Disc ID" ,
PIC = "PIC" ,
Header = "Header" ,
BCA = "BCA" ,
SecuritySectorRanges = "SSv1 Ranges" ,
} ,
CopyProtection = new CopyProtectionSection ( )
{
AntiModchip = YesNo . Yes ,
LibCrypt = YesNo . No ,
LibCryptData = "LibCrypt data" ,
Protection = "List of protections" ,
SecuROMData = "SecuROM data" ,
} ,
DumpersAndStatus = new DumpersAndStatusSection ( )
{
2022-04-04 21:46:13 -07:00
Status = DumpStatus . TwoOrMoreGreen ,
2023-11-14 23:40:41 -05:00
Dumpers = [ "Dumper1" , "Dumper2" ] ,
2022-01-07 13:25:46 -08:00
OtherDumpers = "Dumper3" ,
} ,
TracksAndWriteOffsets = new TracksAndWriteOffsetsSection ( )
{
ClrMameProData = "Datfile" ,
Cuesheet = "Cuesheet" ,
2023-11-14 23:40:41 -05:00
CommonWriteOffsets = [ 0 , 12 , - 12 ] ,
2022-01-07 13:25:46 -08:00
OtherWriteOffsets = "-2" ,
} ,
SizeAndChecksums = new SizeAndChecksumsSection ( )
{
Layerbreak = 0 ,
Layerbreak2 = 1 ,
Layerbreak3 = 2 ,
Size = 12345 ,
CRC32 = "CRC32" ,
MD5 = "MD5" ,
SHA1 = "SHA1" ,
} ,
2022-10-17 20:56:28 -07:00
DumpingInfo = new DumpingInfoSection ( )
{
DumpingProgram = "DiscImageCreator 20500101" ,
2023-09-18 21:36:29 +02:00
DumpingDate = DateTime . UtcNow . ToString ( "yyyy-MM-dd HH:mm:ss" ) ,
2022-10-17 20:56:28 -07:00
Manufacturer = "ATAPI" ,
Model = "Optical Drive" ,
Firmware = "1.23" ,
2022-10-19 12:34:40 -07:00
ReportedDiscType = "CD-R" ,
2022-10-17 20:56:28 -07:00
} ,
2022-01-07 13:25:46 -08:00
Artifacts = new Dictionary < string , string > ( )
{
["Sample Artifact"] = "Sample Data" ,
} ,
} ;
2023-10-08 23:06:17 -04:00
}
2022-01-07 13:25:46 -08:00
2021-08-04 14:17:53 -07:00
/// <summary>
/// Toggle the Start/Stop button
/// </summary>
2024-05-22 20:46:17 -04:00
public void ToggleStartStop ( )
2021-08-04 14:17:53 -07:00
{
// Dump or stop the dump
2024-11-12 22:18:08 -05:00
if ( StartStopButtonText as string = = StartDumpingValue )
2021-08-04 14:17:53 -07:00
{
2023-09-25 21:29:55 -04:00
StartDumping ( ) ;
2021-08-04 14:17:53 -07:00
}
2024-11-12 22:18:08 -05:00
else if ( StartStopButtonText as string = = StopDumpingValue )
2021-08-04 14:17:53 -07:00
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( "Canceling dumping process..." ) ;
2023-10-09 11:35:49 -04:00
_environment ? . CancelDumping ( ) ;
2024-11-12 22:18:08 -05:00
CopyProtectScanButtonEnabled = true ;
2021-08-04 14:17:53 -07:00
}
}
/// <summary>
/// Update the internal options from a closed OptionsWindow
/// </summary>
2023-10-08 23:40:56 -04:00
/// <param name="savedSettings">Indicates if the settings were saved or not</param>
/// <param name="newOptions">Options representing the new, saved values</param>
2024-12-06 00:35:25 -05:00
public void UpdateOptions ( bool savedSettings , Options ? newOptions )
2021-08-04 14:17:53 -07:00
{
2023-10-18 02:59:41 -04:00
// Get which options to save
var optionsToSave = savedSettings ? newOptions : Options ;
// Ensure the first run flag is unset
2024-12-06 00:35:25 -05:00
var continuingOptions = new Options ( optionsToSave ) { FirstRun = false } ;
2024-11-12 22:18:08 -05:00
Options = continuingOptions ;
2023-10-18 02:59:41 -04:00
// If settings were changed, reinitialize the UI
2023-10-08 23:40:56 -04:00
if ( savedSettings )
2024-12-20 21:46:03 -05:00
InitializeUIValues ( removeEventHandlers : true , rebuildPrograms : true , rescanDrives : true ) ;
2021-08-04 14:17:53 -07:00
}
2023-10-11 12:26:24 -04:00
#endregion
2021-08-04 14:17:53 -07:00
#region UI Functionality
/// <summary>
/// Performs UI value setup end to end
/// </summary>
/// <param name="removeEventHandlers">Whether event handlers need to be removed first</param>
2024-12-20 21:46:03 -05:00
/// <param name="rebuildPrograms">Whether the available program list should be rebuilt</param>
2021-08-04 14:17:53 -07:00
/// <param name="rescanDrives">Whether drives should be rescanned or not</param>
2024-12-20 21:46:03 -05:00
public void InitializeUIValues ( bool removeEventHandlers , bool rebuildPrograms , bool rescanDrives )
2021-08-04 14:17:53 -07:00
{
// Disable the dumping button
2023-10-10 22:05:39 -04:00
StartStopButtonEnabled = false ;
2021-12-21 21:11:18 -08:00
2024-12-20 22:31:10 -05:00
// Safely check the parameters box, just in case
if ( ParametersCheckBoxEnabled = = false )
2021-11-08 20:45:37 -08:00
{
2023-10-10 22:05:39 -04:00
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged ;
DisableEventHandlers ( ) ;
2024-12-20 22:31:10 -05:00
ParametersCheckBoxEnabled = true ;
2023-10-10 22:05:39 -04:00
if ( cachedCanExecuteSelectionChanged ) EnableEventHandlers ( ) ;
2021-11-08 20:45:37 -08:00
}
2021-08-04 14:17:53 -07:00
// Remove event handlers to ensure ordering
if ( removeEventHandlers )
DisableEventHandlers ( ) ;
// Populate the list of drives and determine the system
if ( rescanDrives )
{
2023-10-10 22:05:39 -04:00
Status = "Creating drive list, please wait!" ;
2023-10-08 22:49:46 -04:00
PopulateDrives ( ) ;
2021-08-04 14:17:53 -07:00
}
else
{
2023-10-08 22:49:46 -04:00
DetermineSystemType ( ) ;
2021-08-04 14:17:53 -07:00
}
// Determine current media type, if possible
2023-10-08 22:49:46 -04:00
PopulateMediaType ( ) ;
2023-09-25 21:29:55 -04:00
CacheCurrentDiscType ( ) ;
2023-09-25 21:16:43 -04:00
SetCurrentDiscType ( ) ;
2021-08-04 14:17:53 -07:00
2023-04-11 11:15:53 -04:00
// Set the dumping program
2024-12-20 21:46:03 -05:00
if ( rebuildPrograms )
PopulateInternalPrograms ( ) ;
2023-04-11 11:15:53 -04:00
2021-08-04 14:17:53 -07:00
// Set the initial environment and UI values
2023-09-25 21:29:55 -04:00
SetSupportedDriveSpeed ( ) ;
2023-10-08 23:06:17 -04:00
_environment = DetermineEnvironment ( ) ;
2023-09-25 21:29:55 -04:00
GetOutputNames ( true ) ;
EnsureDiscInformation ( ) ;
2021-08-04 14:17:53 -07:00
// Enable event handlers
EnableEventHandlers ( ) ;
// Enable the dumping button, if necessary
2023-10-10 22:05:39 -04:00
StartStopButtonEnabled = ShouldEnableDumpingButton ( ) ;
2021-08-04 14:17:53 -07:00
}
2023-03-04 22:40:10 -05:00
/// <summary>
/// Performs a fast update of the output path while skipping disc checks
/// </summary>
/// <param name="removeEventHandlers">Whether event handlers need to be removed first</param>
2023-10-08 20:52:29 -04:00
public void FastUpdateLabel ( bool removeEventHandlers )
2023-03-04 22:40:10 -05:00
{
// Disable the dumping button
2024-11-12 22:18:08 -05:00
StartStopButtonEnabled = false ;
2023-03-04 22:40:10 -05:00
2024-12-20 22:31:10 -05:00
// Safely check the parameters box, just in case
if ( ParametersCheckBoxEnabled = = false )
2023-03-04 22:40:10 -05:00
{
2023-10-10 22:05:39 -04:00
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged ;
2024-11-12 22:18:08 -05:00
DisableEventHandlers ( ) ;
2024-12-20 22:31:10 -05:00
ParametersCheckBoxEnabled = true ;
2023-10-10 22:05:39 -04:00
if ( cachedCanExecuteSelectionChanged ) EnableEventHandlers ( ) ;
2023-03-04 22:40:10 -05:00
}
// Remove event handlers to ensure ordering
if ( removeEventHandlers )
DisableEventHandlers ( ) ;
// Refresh the drive info
2024-11-12 22:18:08 -05:00
CurrentDrive ? . RefreshDrive ( ) ;
2023-03-04 22:40:10 -05:00
// Set the initial environment and UI values
2023-10-08 23:06:17 -04:00
_environment = DetermineEnvironment ( ) ;
2023-09-25 21:29:55 -04:00
GetOutputNames ( true ) ;
EnsureDiscInformation ( ) ;
2023-03-04 22:40:10 -05:00
// Enable event handlers
EnableEventHandlers ( ) ;
// Enable the dumping button, if necessary
2024-11-12 22:18:08 -05:00
StartStopButtonEnabled = ShouldEnableDumpingButton ( ) ;
2023-03-04 22:40:10 -05:00
}
2021-08-04 14:17:53 -07:00
/// <summary>
/// Enable all textbox and combobox event handlers
/// </summary>
private void EnableEventHandlers ( )
{
2023-10-08 20:52:29 -04:00
CanExecuteSelectionChanged = true ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
/// Disable all textbox and combobox event handlers
/// </summary>
private void DisableEventHandlers ( )
{
2023-10-08 20:52:29 -04:00
CanExecuteSelectionChanged = false ;
2021-08-04 14:17:53 -07:00
}
#endregion
2023-10-08 23:40:56 -04:00
#region Logging
/// <summary>
/// Enqueue text to the log
/// </summary>
/// <param name="text">Text to write to the log</param>
2023-10-09 11:35:49 -04:00
private void Log ( string text )
{
2023-10-11 13:07:45 -04:00
_logger ? . Invoke ( LogLevel . USER , text ) ;
2023-10-09 11:35:49 -04:00
}
2023-10-08 23:40:56 -04:00
/// <summary>
/// Enqueue text with a newline to the log
/// </summary>
/// <param name="text">Text to write to the log</param>
private void LogLn ( string text ) = > Log ( text + "\n" ) ;
/// <summary>
/// Enqueue error text to the log
/// </summary>
/// <param name="text">Text to write to the log</param>
2023-10-09 11:35:49 -04:00
private void ErrorLog ( string text )
{
2023-10-11 13:07:45 -04:00
_logger ? . Invoke ( LogLevel . ERROR , text ) ;
2023-10-09 11:35:49 -04:00
}
2023-10-08 23:40:56 -04:00
/// <summary>
/// Enqueue error text with a newline to the log
/// </summary>
/// <param name="text">Text to write to the log</param>
private void ErrorLogLn ( string text ) = > ErrorLog ( text + "\n" ) ;
/// <summary>
/// Enqueue secret text to the log
/// </summary>
/// <param name="text">Text to write to the log</param>
2023-10-09 11:35:49 -04:00
private void SecretLog ( string text )
{
2023-10-11 13:07:45 -04:00
_logger ? . Invoke ( LogLevel . SECRET , text ) ;
2023-10-09 11:35:49 -04:00
}
2023-10-08 23:40:56 -04:00
/// <summary>
/// Enqueue secret text with a newline to the log
/// </summary>
/// <param name="text">Text to write to the log</param>
private void SecretLogLn ( string text ) = > SecretLog ( text + "\n" ) ;
/// <summary>
/// Enqueue verbose text to the log
/// </summary>
/// <param name="text">Text to write to the log</param>
private void VerboseLog ( string text )
{
2023-10-09 11:35:49 -04:00
if ( _logger ! = null & & Options . VerboseLogging )
2023-10-08 23:40:56 -04:00
_logger ( LogLevel . VERBOSE , text ) ;
}
/// <summary>
/// Enqueue verbose text with a newline to the log
/// </summary>
/// <param name="text">Text to write to the log</param>
private void VerboseLogLn ( string text )
{
if ( Options . VerboseLogging )
VerboseLog ( text + "\n" ) ;
}
#endregion
2021-08-04 14:17:53 -07:00
#region Helpers
/// <summary>
/// Cache the current disc type to internal variable
/// </summary>
2023-09-25 21:29:55 -04:00
private void CacheCurrentDiscType ( )
2021-08-04 14:17:53 -07:00
{
// If the selected item is invalid, we just skip
2024-11-12 22:18:08 -05:00
if ( CurrentDrive = = null )
2021-08-04 14:17:53 -07:00
return ;
// Get reasonable default values based on the current system
2024-11-12 22:18:08 -05:00
var mediaTypes = CurrentSystem . MediaTypes ( ) ;
MediaType ? defaultMediaType = mediaTypes . Count > 0 ? mediaTypes [ 0 ] : MediaType . CDROM ;
2021-08-04 14:17:53 -07:00
if ( defaultMediaType = = MediaType . NONE )
defaultMediaType = MediaType . CDROM ;
// If we're skipping detection, set the default value
2024-11-12 22:18:08 -05:00
if ( Options . SkipMediaTypeDetection )
2021-08-04 14:17:53 -07:00
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"Media type detection disabled, defaulting to {defaultMediaType.LongName()}." ) ;
2021-08-04 14:17:53 -07:00
CurrentMediaType = defaultMediaType ;
}
// If the drive is marked active, try to read from it
2024-11-12 22:18:08 -05:00
else if ( CurrentDrive . MarkedActive )
2021-08-04 14:17:53 -07:00
{
2024-11-12 22:18:08 -05:00
VerboseLog ( $"Trying to detect media type for drive {CurrentDrive.Name} [{CurrentDrive.DriveFormat}] using size and filesystem.. " ) ;
MediaType ? detectedMediaType = CurrentDrive . GetMediaType ( CurrentSystem ) ;
2021-08-04 14:17:53 -07:00
// If we got either an error or no media, default to the current System default
if ( detectedMediaType = = null )
{
2024-11-03 21:55:04 -05:00
VerboseLogLn ( $"Could not detect media type, defaulting to {defaultMediaType.LongName()}." ) ;
2021-08-04 14:17:53 -07:00
CurrentMediaType = defaultMediaType ;
}
else
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"Detected {detectedMediaType.LongName()}." ) ;
2023-10-09 10:35:44 -04:00
_detectedMediaType = detectedMediaType ;
2021-08-04 14:17:53 -07:00
CurrentMediaType = detectedMediaType ;
}
}
// All other cases, just use the default
else
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"Drive marked as empty, defaulting to {defaultMediaType.LongName()}." ) ;
2021-08-04 14:17:53 -07:00
CurrentMediaType = defaultMediaType ;
}
}
/// <summary>
/// Create a DumpEnvironment with all current settings
/// </summary>
2024-11-12 22:18:08 -05:00
/// <returns>Filled DumpEnvironment Parent</returns>
2023-09-25 21:29:55 -04:00
private DumpEnvironment DetermineEnvironment ( )
2021-08-04 14:17:53 -07:00
{
2023-10-08 20:52:29 -04:00
return new DumpEnvironment (
2024-11-12 22:18:08 -05:00
Options ,
EvaluateOutputPath ( OutputPath ) ,
CurrentDrive ,
CurrentSystem ,
CurrentMediaType ,
CurrentProgram ,
Parameters ) ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
2023-02-23 16:50:00 -05:00
/// Determine and set the current system type, if allowed
2021-08-04 14:17:53 -07:00
/// </summary>
2023-09-25 21:29:55 -04:00
private void DetermineSystemType ( )
2021-08-04 14:17:53 -07:00
{
2024-11-12 22:18:08 -05:00
if ( Drives = = null | | Drives . Count = = 0 | | CurrentDrive = = null )
2023-02-23 16:50:00 -05:00
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( "Skipping system type detection because no valid drives found!" ) ;
2023-10-02 01:17:14 -04:00
}
2024-11-12 22:18:08 -05:00
else if ( CurrentDrive ? . MarkedActive ! = true )
2023-10-02 01:17:14 -04:00
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( "Skipping system type detection because drive not marked as active!" ) ;
2023-02-23 16:50:00 -05:00
}
2024-11-12 22:18:08 -05:00
else if ( ! Options . SkipSystemDetection )
2021-08-04 14:17:53 -07:00
{
2024-11-12 22:18:08 -05:00
VerboseLog ( $"Trying to detect system for drive {CurrentDrive.Name}.. " ) ;
2024-12-20 23:11:29 -05:00
var currentSystem = GetRedumpSystem ( CurrentDrive ) ;
VerboseLogLn ( currentSystem = = null ? $"unable to detect, defaulting to {Options.DefaultSystem.LongName()}" : ( $"detected {currentSystem.LongName()}." ) ) ;
currentSystem ? ? = Options . DefaultSystem ;
2021-08-04 14:17:53 -07:00
2021-08-18 22:13:38 -07:00
if ( currentSystem ! = null )
2021-08-04 14:17:53 -07:00
{
int sysIndex = Systems . FindIndex ( s = > s = = currentSystem ) ;
2024-11-12 22:18:08 -05:00
CurrentSystem = Systems [ sysIndex ] ;
2021-08-04 14:17:53 -07:00
}
}
2024-11-12 22:18:08 -05:00
else if ( Options . SkipSystemDetection & & Options . DefaultSystem ! = null )
2021-12-21 21:11:18 -08:00
{
2024-11-12 22:18:08 -05:00
var currentSystem = Options . DefaultSystem ;
2024-12-05 22:45:53 -05:00
VerboseLogLn ( $"System detection disabled, defaulting to {currentSystem.LongName()}." ) ;
2021-12-21 21:11:18 -08:00
int sysIndex = Systems . FindIndex ( s = > s = = currentSystem ) ;
2024-11-12 22:18:08 -05:00
CurrentSystem = Systems [ sysIndex ] ;
2021-12-21 21:11:18 -08:00
}
2023-10-08 22:49:46 -04:00
}
/// <summary>
/// Disable all UI elements during dumping
/// </summary>
public void DisableAllUIElements ( )
{
OptionsMenuItemEnabled = false ;
2024-02-19 10:38:28 +09:00
CheckDumpMenuItemEnabled = false ;
CreateIRDMenuItemEnabled = false ;
2023-10-08 22:49:46 -04:00
SystemTypeComboBoxEnabled = false ;
MediaTypeComboBoxEnabled = false ;
OutputPathTextBoxEnabled = false ;
OutputPathBrowseButtonEnabled = false ;
DriveLetterComboBoxEnabled = false ;
DriveSpeedComboBoxEnabled = false ;
DumpingProgramComboBoxEnabled = false ;
EnableParametersCheckBoxEnabled = false ;
2024-05-21 20:57:57 -04:00
StartStopButtonText = StopDumpingValue ;
2023-10-08 22:49:46 -04:00
MediaScanButtonEnabled = false ;
UpdateVolumeLabelEnabled = false ;
CopyProtectScanButtonEnabled = false ;
}
2021-08-04 14:17:53 -07:00
2023-10-08 22:49:46 -04:00
/// <summary>
/// Enable all UI elements after dumping
/// </summary>
public void EnableAllUIElements ( )
{
OptionsMenuItemEnabled = true ;
2024-02-19 10:38:28 +09:00
CheckDumpMenuItemEnabled = true ;
CreateIRDMenuItemEnabled = true ;
2023-10-08 22:49:46 -04:00
SystemTypeComboBoxEnabled = true ;
MediaTypeComboBoxEnabled = true ;
OutputPathTextBoxEnabled = true ;
OutputPathBrowseButtonEnabled = true ;
DriveLetterComboBoxEnabled = true ;
DriveSpeedComboBoxEnabled = true ;
DumpingProgramComboBoxEnabled = true ;
EnableParametersCheckBoxEnabled = true ;
2024-05-21 20:57:57 -04:00
StartStopButtonText = StartDumpingValue ;
2023-10-08 22:49:46 -04:00
MediaScanButtonEnabled = true ;
UpdateVolumeLabelEnabled = true ;
CopyProtectScanButtonEnabled = true ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
/// Ensure information is consistent with the currently selected disc type
/// </summary>
2023-09-25 21:29:55 -04:00
public void EnsureDiscInformation ( )
2021-08-04 14:17:53 -07:00
{
// Get the current environment information
2023-10-08 23:06:17 -04:00
_environment = DetermineEnvironment ( ) ;
2021-08-04 14:17:53 -07:00
// Get the status to write out
2024-05-22 16:16:56 -04:00
ResultEventArgs result = _environment . GetSupportStatus ( ) ;
2024-11-12 22:18:08 -05:00
if ( CurrentProgram = = InternalProgram . NONE )
Status = "No dumping program found" ;
2024-02-22 00:14:39 +09:00
else
2024-11-12 22:18:08 -05:00
Status = result . Message ;
2021-08-04 14:17:53 -07:00
// Enable or disable the button
2024-11-12 22:18:08 -05:00
StartStopButtonEnabled = result & & ShouldEnableDumpingButton ( ) ;
2021-08-04 14:17:53 -07:00
// If we're in a type that doesn't support drive speeds
2024-11-12 22:18:08 -05:00
DriveSpeedComboBoxEnabled = _environment . DoesSupportDriveSpeed ( ) ;
2021-08-04 14:17:53 -07:00
2024-12-20 22:31:10 -05:00
// If input params are enabled, generate the full parameters from the environment
if ( ParametersCheckBoxEnabled )
2021-08-04 14:17:53 -07:00
{
2024-11-12 22:18:08 -05:00
var generated = _environment . GetFullParameters ( DriveSpeed ) ;
2021-08-04 14:17:53 -07:00
if ( generated ! = null )
2024-11-12 22:18:08 -05:00
Parameters = generated ;
2021-08-04 14:17:53 -07:00
}
}
2024-01-11 13:42:34 +13:00
/// <summary>
/// Replaces %-delimited variables inside a path string with their values
/// </summary>
/// <param name="outputPath">Path to be evaluated</param>
/// <returns>String with %-delimited variables evaluated</returns>
public string EvaluateOutputPath ( string outputPath )
{
2024-11-12 22:18:08 -05:00
string systemLong = _currentSystem . LongName ( ) ? ? "Unknown System" ;
2024-01-11 13:42:34 +13:00
if ( string . IsNullOrEmpty ( systemLong ) )
systemLong = "Unknown System" ;
2024-11-12 22:18:08 -05:00
string systemShort = _currentSystem . ShortName ( ) ? ? "unknown" ;
2024-01-11 13:42:34 +13:00
if ( string . IsNullOrEmpty ( systemShort ) )
systemShort = "unknown" ;
2024-11-12 22:18:08 -05:00
string mediaLong = _currentMediaType . LongName ( ) ? ? "Unknown Media" ;
2024-01-11 13:42:34 +13:00
if ( string . IsNullOrEmpty ( mediaLong ) )
mediaLong = "Unknown Media" ;
2024-11-12 22:18:08 -05:00
string program = _currentProgram . ToString ( ) ? ? "Unknown Program" ;
2024-01-11 13:42:34 +13:00
if ( string . IsNullOrEmpty ( program ) )
program = "Unknown Program" ;
string programShort = program = = "DiscImageCreator" ? "DIC" : program ;
if ( string . IsNullOrEmpty ( programShort ) )
programShort = "Unknown Program" ;
2024-05-23 14:07:42 -04:00
string label = GetFormattedVolumeLabel ( _currentDrive ) ? ? "track" ;
2024-01-11 13:42:34 +13:00
if ( string . IsNullOrEmpty ( label ) )
label = "track" ;
string date = DateTime . Today . ToString ( "yyyyMMdd" ) ;
if ( string . IsNullOrEmpty ( date ) )
date = "UNKNOWN" ;
string datetime = DateTime . Now . ToString ( "yyyyMMdd-HHmmss" ) ;
if ( string . IsNullOrEmpty ( datetime ) )
datetime = "UNKNOWN" ;
return outputPath
. Replace ( "%SYSTEM%" , systemLong )
2024-11-23 00:55:20 +09:00
. Replace ( "%SYS%" , systemShort . ToUpperInvariant ( ) )
. Replace ( "%sys%" , systemShort )
2024-01-11 13:42:34 +13:00
. Replace ( "%MEDIA%" , mediaLong )
. Replace ( "%PROGRAM%" , program )
. Replace ( "%PROG%" , programShort )
. Replace ( "%LABEL%" , label )
. Replace ( "%DATE%" , date )
. Replace ( "%DATETIME%" , datetime ) ;
}
2021-08-04 14:17:53 -07:00
/// <summary>
/// Get the default output directory name from the currently selected drive
/// </summary>
/// <param name="driveChanged">Force an updated name if the drive letter changes</param>
2023-09-25 21:29:55 -04:00
public void GetOutputNames ( bool driveChanged )
2021-08-04 14:17:53 -07:00
{
2024-11-12 22:18:08 -05:00
if ( Drives = = null | | Drives . Count = = 0 | | CurrentDrive = = null )
2023-02-23 16:50:00 -05:00
{
2023-10-09 00:42:33 -04:00
VerboseLogLn ( "Skipping output name building because no valid drives found!" ) ;
2023-02-23 16:50:00 -05:00
return ;
}
2024-12-20 21:30:31 -05:00
// Get path pieces that are used in all branches
string defaultOutputPath = Options . DefaultOutputPath ? ? "ISO" ;
string extension = _environment ? . GetDefaultExtension ( CurrentMediaType ) ? ? ".bin" ;
string label = GetFormattedVolumeLabel ( CurrentDrive ) ? ? CurrentSystem . LongName ( ) ? ? "track" ;
string defaultFilename = $"{label}{extension}" ;
2021-08-04 14:17:53 -07:00
2024-12-20 21:30:31 -05:00
// If no path exists, set one using default values
2024-11-12 22:18:08 -05:00
if ( string . IsNullOrEmpty ( OutputPath ) )
2022-12-13 11:48:26 -08:00
{
2023-11-22 16:26:31 -05:00
#if NET20 | | NET35
2024-12-20 21:30:31 -05:00
OutputPath = Path . Combine ( Path . Combine ( defaultOutputPath , label ) , defaultFilename ) ;
2023-11-22 16:26:31 -05:00
#else
2024-12-20 21:30:31 -05:00
OutputPath = Path . Combine ( defaultOutputPath , label , defaultFilename ) ;
2023-11-22 16:26:31 -05:00
#endif
2024-12-20 21:30:31 -05:00
return ;
2022-12-13 11:48:26 -08:00
}
2021-08-04 14:17:53 -07:00
2024-12-20 21:30:31 -05:00
// For all other cases, separate the last path
string lastPath = FrontendTool . NormalizeOutputPaths ( OutputPath , false ) ;
string lastDirectory = Path . GetDirectoryName ( lastPath ) ? ? string . Empty ;
string lastFilename = Path . GetFileNameWithoutExtension ( lastPath ) ;
2022-12-13 11:48:26 -08:00
// Set the output filename, if we changed drives
2024-12-20 21:30:31 -05:00
if ( driveChanged )
2022-12-13 11:48:26 -08:00
{
2024-12-20 21:30:31 -05:00
// If the previous path is exactly the default path and last filename
if ( lastDirectory . EndsWith ( Path . Combine ( defaultOutputPath , lastFilename ) ) )
2024-12-20 21:35:49 -05:00
lastDirectory = Path . GetDirectoryName ( lastDirectory ) ? ? string . Empty ;
2023-02-23 12:31:27 -05:00
2024-12-20 21:30:31 -05:00
// Create the output path
if ( lastDirectory = = defaultOutputPath )
2023-11-22 16:26:31 -05:00
#if NET20 | | NET35
2024-12-20 21:30:31 -05:00
OutputPath = Path . Combine ( Path . Combine ( lastDirectory , label ) , defaultFilename ) ;
2023-11-22 16:26:31 -05:00
#else
2024-12-20 21:30:31 -05:00
OutputPath = Path . Combine ( lastDirectory , label , defaultFilename ) ;
2023-11-22 16:26:31 -05:00
#endif
2023-10-09 11:35:49 -04:00
else
2024-12-20 21:30:31 -05:00
OutputPath = Path . Combine ( lastDirectory , defaultFilename ) ;
2022-12-13 11:48:26 -08:00
}
2021-08-04 14:17:53 -07:00
2023-08-28 11:24:58 -04:00
// Otherwise, reset the extension of the currently set path
else
{
2024-12-20 21:30:31 -05:00
lastFilename = $"{lastFilename}{extension}" ;
OutputPath = Path . Combine ( lastDirectory , lastFilename ) ;
2023-08-28 11:24:58 -04:00
}
2021-08-04 14:17:53 -07:00
}
2024-05-23 14:12:50 -04:00
/// <summary>
/// Get the current system from drive
/// </summary>
2024-12-20 23:11:29 -05:00
private static RedumpSystem ? GetRedumpSystem ( Drive ? drive )
2024-05-23 14:12:50 -04:00
{
// If the drive does not exist, we can't do anything
if ( drive = = null )
2024-12-20 23:11:29 -05:00
return null ;
2024-05-23 14:12:50 -04:00
// If we can't read the media in that drive, we can't do anything
if ( string . IsNullOrEmpty ( drive . Name ) | | ! Directory . Exists ( drive . Name ) )
2024-12-20 23:11:29 -05:00
return null ;
2024-05-23 14:12:50 -04:00
// We're going to assume for floppies, HDDs, and removable drives
if ( drive . InternalDriveType ! = InternalDriveType . Optical )
return RedumpSystem . IBMPCcompatible ;
// Check volume labels first
2024-05-28 11:51:10 -04:00
RedumpSystem ? systemFromLabel = FrontendTool . GetRedumpSystemFromVolumeLabel ( drive . VolumeLabel ) ;
2024-05-23 14:12:50 -04:00
if ( systemFromLabel ! = null )
return systemFromLabel ;
// Get a list of files for quicker checking
#region Arcade
// funworld Photo Play
if ( File . Exists ( Path . Combine ( drive . Name , "PP.INF" ) )
& & Directory . Exists ( Path . Combine ( drive . Name , "PPINC" ) ) )
{
return RedumpSystem . funworldPhotoPlay ;
}
// Konami Python 2
if ( Directory . Exists ( Path . Combine ( drive . Name , "PY2.D" ) ) )
{
return RedumpSystem . KonamiPython2 ;
}
#endregion
#region Consoles
// Bandai Playdia Quick Interactive System
try
{
List < string > files = [ . . Directory . GetFiles ( drive . Name , "*" , SearchOption . TopDirectoryOnly ) ] ;
2024-11-12 22:18:08 -05:00
if ( files . Exists ( f = > f . EndsWith ( ".AJS" , StringComparison . OrdinalIgnoreCase ) )
& & files . Exists ( f = > f . EndsWith ( ".GLB" , StringComparison . OrdinalIgnoreCase ) ) )
2024-05-23 14:12:50 -04:00
{
return RedumpSystem . BandaiPlaydiaQuickInteractiveSystem ;
}
}
catch { }
// Bandai Pippin
if ( File . Exists ( Path . Combine ( drive . Name , "PippinAuthenticationFile" ) ) )
{
return RedumpSystem . BandaiPippin ;
}
// Commodore CDTV/CD32
#if NET20 | | NET35
if ( File . Exists ( Path . Combine ( Path . Combine ( drive . Name , "S" ) , "STARTUP-SEQUENCE" ) ) )
#else
if ( File . Exists ( Path . Combine ( drive . Name , "S" , "STARTUP-SEQUENCE" ) ) )
#endif
{
if ( File . Exists ( Path . Combine ( drive . Name , "CDTV.TM" ) ) )
return RedumpSystem . CommodoreAmigaCDTV ;
else
return RedumpSystem . CommodoreAmigaCD32 ;
}
// Mattel HyperScan -- TODO: May need case-insensitivity added
if ( File . Exists ( Path . Combine ( drive . Name , "hyper.exe" ) ) )
{
return RedumpSystem . MattelHyperScan ;
}
// Mattel Fisher-Price iXL
#if NET20 | | NET35
if ( File . Exists ( Path . Combine ( Path . Combine ( drive . Name , "iXL" ) , "iXLUpdater.exe" ) ) )
#else
if ( File . Exists ( Path . Combine ( drive . Name , "iXL" , "iXLUpdater.exe" ) ) )
#endif
{
return RedumpSystem . MattelFisherPriceiXL ;
}
// Microsoft Xbox 360
try
{
if ( Directory . Exists ( Path . Combine ( drive . Name , "$SystemUpdate" ) )
2024-11-16 01:07:47 -05:00
& & IOExtensions . SafeGetFiles ( Path . Combine ( drive . Name , "$SystemUpdate" ) ) . Length > 0
2024-05-23 14:12:50 -04:00
& & drive . TotalSize < = 500_000_000 )
{
return RedumpSystem . MicrosoftXbox360 ;
}
}
catch { }
// Microsoft Xbox One and Series X
try
{
if ( Directory . Exists ( Path . Combine ( drive . Name , "MSXC" ) ) )
{
try
{
#if NET20 | | NET35
string catalogjs = Path . Combine ( drive . Name , Path . Combine ( "MSXC" , Path . Combine ( "Metadata" , "catalog.js" ) ) ) ;
#else
string catalogjs = Path . Combine ( drive . Name , "MSXC" , "Metadata" , "catalog.js" ) ;
#endif
if ( ! File . Exists ( catalogjs ) )
return RedumpSystem . MicrosoftXboxOne ;
SabreTools . Models . Xbox . Catalog ? catalog = SabreTools . Serialization . Deserializers . Catalog . DeserializeFile ( catalogjs ) ;
if ( catalog ! = null & & catalog . Version ! = null & & catalog . Packages ! = null )
{
if ( ! double . TryParse ( catalog . Version , out double version ) )
return RedumpSystem . MicrosoftXboxOne ;
if ( version < 4 )
return RedumpSystem . MicrosoftXboxOne ;
foreach ( var package in catalog . Packages )
{
if ( package . Generation ! = "9" )
return RedumpSystem . MicrosoftXboxOne ;
}
return RedumpSystem . MicrosoftXboxSeriesXS ;
}
}
catch
{
return RedumpSystem . MicrosoftXboxOne ;
}
}
}
catch { }
// Sega Dreamcast
if ( File . Exists ( Path . Combine ( drive . Name , "IP.BIN" ) ) )
{
return RedumpSystem . SegaDreamcast ;
}
// Sega Mega-CD / Sega-CD
#if NET20 | | NET35
if ( File . Exists ( Path . Combine ( Path . Combine ( drive . Name , "_BOOT" ) , "IP.BIN" ) )
| | File . Exists ( Path . Combine ( Path . Combine ( drive . Name , "_BOOT" ) , "SP.BIN" ) )
| | File . Exists ( Path . Combine ( Path . Combine ( drive . Name , "_BOOT" ) , "SP_AS.BIN" ) )
| | File . Exists ( Path . Combine ( drive . Name , "FILESYSTEM.BIN" ) ) )
#else
if ( File . Exists ( Path . Combine ( drive . Name , "_BOOT" , "IP.BIN" ) )
| | File . Exists ( Path . Combine ( drive . Name , "_BOOT" , "SP.BIN" ) )
| | File . Exists ( Path . Combine ( drive . Name , "_BOOT" , "SP_AS.BIN" ) )
| | File . Exists ( Path . Combine ( drive . Name , "FILESYSTEM.BIN" ) ) )
#endif
{
return RedumpSystem . SegaMegaCDSegaCD ;
}
// Sony PlayStation and Sony PlayStation 2
string psxExePath = Path . Combine ( drive . Name , "PSX.EXE" ) ;
string systemCnfPath = Path . Combine ( drive . Name , "SYSTEM.CNF" ) ;
if ( File . Exists ( systemCnfPath ) )
{
// Check for either BOOT or BOOT2
var systemCnf = new IniFile ( systemCnfPath ) ;
if ( systemCnf . ContainsKey ( "BOOT" ) )
return RedumpSystem . SonyPlayStation ;
else if ( systemCnf . ContainsKey ( "BOOT2" ) )
return RedumpSystem . SonyPlayStation2 ;
}
else if ( File . Exists ( psxExePath ) )
{
return RedumpSystem . SonyPlayStation ;
}
// Sony PlayStation 3
try
{
if ( Directory . Exists ( Path . Combine ( drive . Name , "PS3_GAME" ) )
| | Directory . Exists ( Path . Combine ( drive . Name , "PS3_UPDATE" ) )
| | File . Exists ( Path . Combine ( drive . Name , "PS3_DISC.SFB" ) ) )
{
return RedumpSystem . SonyPlayStation3 ;
}
}
catch { }
// Sony PlayStation 4
// There are more possible paths that could be checked.
// There are some entries that can be found on most PS4 discs:
// "/app/GAME_SERIAL/app.pkg"
// "/bd/param.sfo"
// "/license/rif"
// There are also extra files that can be found on some discs:
// "/patch/GAME_SERIAL/patch.pkg" can be found in Redump entry 66816.
// Originally on disc as "/patch/CUSA11302/patch.pkg".
// Is used as an on-disc update for the base game app without needing to get update from the internet.
// "/addcont/GAME_SERIAL/CONTENT_ID/ac.pkg" can be found in Redump entry 97619.
// Originally on disc as "/addcont/CUSA00288/FFXIVEXPS400001A/ac.pkg".
#if NET20 | | NET35
if ( File . Exists ( Path . Combine ( Path . Combine ( Path . Combine ( drive . Name , "PS4" ) , "UPDATE" ) , "PS4UPDATE.PUP" ) ) )
#else
if ( File . Exists ( Path . Combine ( drive . Name , "PS4" , "UPDATE" , "PS4UPDATE.PUP" ) ) )
#endif
{
return RedumpSystem . SonyPlayStation4 ;
}
// V.Tech V.Flash / V.Smile Pro
if ( File . Exists ( Path . Combine ( drive . Name , "0SYSTEM" ) ) )
{
return RedumpSystem . VTechVFlashVSmilePro ;
}
#endregion
#region Computers
// Sharp X68000
if ( File . Exists ( Path . Combine ( drive . Name , "COMMAND.X" ) ) )
{
return RedumpSystem . SharpX68000 ;
}
#endregion
#region Video Formats
// BD-Video
if ( Directory . Exists ( Path . Combine ( drive . Name , "BDMV" ) ) )
{
// Technically BD-Audio has this as well, but it's hard to split that out right now
return RedumpSystem . BDVideo ;
}
// DVD-Audio and DVD-Video
try
{
if ( Directory . Exists ( Path . Combine ( drive . Name , "AUDIO_TS" ) )
2024-11-16 01:07:47 -05:00
& & IOExtensions . SafeGetFiles ( Path . Combine ( drive . Name , "AUDIO_TS" ) ) . Length > 0 )
2024-05-23 14:12:50 -04:00
{
return RedumpSystem . DVDAudio ;
}
else if ( Directory . Exists ( Path . Combine ( drive . Name , "VIDEO_TS" ) )
2024-11-16 01:07:47 -05:00
& & IOExtensions . SafeGetFiles ( Path . Combine ( drive . Name , "VIDEO_TS" ) ) . Length > 0 )
2024-05-23 14:12:50 -04:00
{
return RedumpSystem . DVDVideo ;
}
}
catch { }
// HD-DVD-Video
try
{
if ( Directory . Exists ( Path . Combine ( drive . Name , "HVDVD_TS" ) )
2024-11-16 01:07:47 -05:00
& & IOExtensions . SafeGetFiles ( Path . Combine ( drive . Name , "HVDVD_TS" ) ) . Length > 0 )
2024-05-23 14:12:50 -04:00
{
return RedumpSystem . HDDVDVideo ;
}
}
catch { }
// Photo CD
try
{
if ( Directory . Exists ( Path . Combine ( drive . Name , "PHOTO_CD" ) )
2024-11-16 01:07:47 -05:00
& & IOExtensions . SafeGetFiles ( Path . Combine ( drive . Name , "PHOTO_CD" ) ) . Length > 0 )
2024-05-23 14:12:50 -04:00
{
return RedumpSystem . PhotoCD ;
}
}
catch { }
// VCD
try
{
if ( Directory . Exists ( Path . Combine ( drive . Name , "VCD" ) )
2024-11-16 01:07:47 -05:00
& & IOExtensions . SafeGetFiles ( Path . Combine ( drive . Name , "VCD" ) ) . Length > 0 )
2024-05-23 14:12:50 -04:00
{
return RedumpSystem . VideoCD ;
}
}
catch { }
#endregion
// Default return
2024-12-20 23:11:29 -05:00
return null ;
2024-05-23 14:12:50 -04:00
}
2021-08-04 14:17:53 -07:00
/// <summary>
/// Process the current custom parameters back into UI values
/// </summary>
2023-09-25 21:16:43 -04:00
public void ProcessCustomParameters ( )
2021-08-04 14:17:53 -07:00
{
2024-05-22 15:59:43 -04:00
// Set the execution context and processor
2024-11-12 22:18:08 -05:00
if ( _environment ? . SetExecutionContext ( Parameters ) ! = true )
2024-05-22 15:59:43 -04:00
return ;
if ( _environment ? . SetProcessor ( ) ! = true )
2021-08-04 14:17:53 -07:00
return ;
2022-01-13 10:25:57 -08:00
// Catch this in case there's an input path issue
try
{
2024-11-12 22:18:08 -05:00
int driveIndex = Drives . ConvertAll ( d = > d . Name ? [ 0 ] ? ? '\0' )
. IndexOf ( _environment . ContextInputPath ? [ 0 ] ? ? default ) ;
CurrentDrive = ( driveIndex ! = - 1 ? Drives [ driveIndex ] : Drives [ 0 ] ) ;
2022-01-13 10:25:57 -08:00
}
catch { }
2022-03-02 00:43:05 -05:00
2024-05-22 16:13:14 -04:00
int driveSpeed = _environment . Speed ? ? - 1 ;
2021-08-04 14:17:53 -07:00
if ( driveSpeed > 0 )
2024-11-12 22:18:08 -05:00
DriveSpeed = driveSpeed ;
2024-05-22 16:13:14 -04:00
else
2024-11-12 22:18:08 -05:00
_environment . Speed = DriveSpeed ;
2021-08-04 14:17:53 -07:00
2023-07-19 12:51:22 -04:00
// Disable change handling
DisableEventHandlers ( ) ;
2024-11-12 22:18:08 -05:00
OutputPath = FrontendTool . NormalizeOutputPaths ( _environment . ContextOutputPath , false ) ;
2021-08-04 14:17:53 -07:00
2023-10-09 11:35:49 -04:00
if ( MediaTypes ! = null )
{
2024-05-22 16:13:14 -04:00
MediaType ? mediaType = _environment . GetMediaType ( ) ;
2024-07-07 11:28:04 +09:00
if ( mediaType ! = null )
{
int mediaTypeIndex = MediaTypes . FindIndex ( m = > m = = mediaType ) ;
2024-11-12 22:18:08 -05:00
CurrentMediaType = ( mediaTypeIndex > - 1 ? MediaTypes [ mediaTypeIndex ] : MediaTypes [ 0 ] ) ;
2024-07-07 11:28:04 +09:00
}
2023-10-09 11:35:49 -04:00
}
2023-07-19 12:51:22 -04:00
// Reenable change handling
EnableEventHandlers ( ) ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
/// Scan and show copy protection for the current disc
/// </summary>
2024-11-03 23:09:54 -05:00
public async Task < string? > ScanAndShowProtection ( )
2021-08-04 14:17:53 -07:00
{
// Determine current environment, just in case
2023-10-11 13:07:45 -04:00
_environment ? ? = DetermineEnvironment ( ) ;
2021-08-04 14:17:53 -07:00
2023-10-09 00:03:02 -04:00
// If we don't have a valid drive
2024-11-12 22:18:08 -05:00
if ( CurrentDrive ? . Name = = null )
2024-11-03 23:09:54 -05:00
{
ErrorLogLn ( "No valid drive found!" ) ;
return null ;
}
2021-08-04 14:17:53 -07:00
2024-11-12 22:18:08 -05:00
VerboseLogLn ( $"Scanning for copy protection in {CurrentDrive.Name}" ) ;
2021-08-04 14:17:53 -07:00
2024-11-12 22:18:08 -05:00
var tempContent = Status ;
Status = "Scanning for copy protection... this might take a while!" ;
2024-12-21 13:33:12 -05:00
// Disable UI elements
2024-12-21 20:30:23 -05:00
OptionsMenuItemEnabled = false ;
2024-12-21 13:33:12 -05:00
SystemTypeComboBoxEnabled = false ;
MediaTypeComboBoxEnabled = false ;
OutputPathTextBoxEnabled = false ;
OutputPathBrowseButtonEnabled = false ;
DriveLetterComboBoxEnabled = false ;
DriveSpeedComboBoxEnabled = false ;
DumpingProgramComboBoxEnabled = false ;
EnableParametersCheckBoxEnabled = false ;
2024-11-12 22:18:08 -05:00
StartStopButtonEnabled = false ;
MediaScanButtonEnabled = false ;
UpdateVolumeLabelEnabled = false ;
CopyProtectScanButtonEnabled = false ;
2023-10-09 00:03:02 -04:00
var progress = new Progress < ProtectionProgress > ( ) ;
progress . ProgressChanged + = ProgressUpdated ;
2024-11-03 23:09:54 -05:00
try
{
2024-11-12 22:18:08 -05:00
var protections = await ProtectionTool . RunProtectionScanOnPath ( CurrentDrive . Name , Options , progress ) ;
2024-11-03 23:09:54 -05:00
var output = ProtectionTool . FormatProtections ( protections ) ;
2021-08-04 14:17:53 -07:00
2024-12-21 13:33:12 -05:00
LogLn ( $"Detected the following protections in {CurrentDrive.Name}:\r\n\r\n{output}" ) ;
2024-11-03 23:09:54 -05:00
return output ;
}
catch ( Exception ex )
{
ErrorLogLn ( $"Path could not be scanned! Exception information:\r\n\r\n{ex}" ) ;
return null ;
}
2024-12-21 13:33:12 -05:00
finally
{
// Reset the status
Status = tempContent ;
// Enable UI elements
2024-12-21 20:30:23 -05:00
OptionsMenuItemEnabled = true ;
2024-12-21 13:33:12 -05:00
SystemTypeComboBoxEnabled = true ;
MediaTypeComboBoxEnabled = true ;
OutputPathTextBoxEnabled = true ;
OutputPathBrowseButtonEnabled = true ;
DriveLetterComboBoxEnabled = true ;
DriveSpeedComboBoxEnabled = true ;
DumpingProgramComboBoxEnabled = true ;
EnableParametersCheckBoxEnabled = true ;
StartStopButtonEnabled = ShouldEnableDumpingButton ( ) ;
MediaScanButtonEnabled = true ;
UpdateVolumeLabelEnabled = true ;
CopyProtectScanButtonEnabled = true ;
}
2021-08-04 14:17:53 -07:00
}
2024-05-23 14:07:42 -04:00
/// <summary>
/// Media label as read by Windows, formatted to avoid odd outputs
/// If no volume label present, use PSX or PS2 serial if valid
/// Otherwise, use "track" as volume label
/// </summary>
private static string? GetFormattedVolumeLabel ( Drive ? drive )
{
if ( drive = = null )
return null ;
string? volumeLabel = DiscNotDetectedValue ;
if ( ! drive . MarkedActive )
return volumeLabel ;
if ( ! string . IsNullOrEmpty ( drive . VolumeLabel ) )
{
volumeLabel = drive . VolumeLabel ;
}
else
{
// No Volume Label found, fallback to something sensible
2024-12-20 23:11:29 -05:00
switch ( GetRedumpSystem ( drive ) )
2024-05-23 14:07:42 -04:00
{
case RedumpSystem . SonyPlayStation :
case RedumpSystem . SonyPlayStation2 :
2024-08-21 00:35:54 -04:00
string? serial = PhysicalTool . GetPlayStationSerial ( drive ) ;
2024-05-23 14:07:42 -04:00
volumeLabel = serial ? ? "track" ;
break ;
default :
volumeLabel = "track" ;
break ;
}
}
foreach ( char c in Path . GetInvalidFileNameChars ( ) )
2024-12-20 21:30:31 -05:00
{
2024-05-23 14:07:42 -04:00
volumeLabel = volumeLabel ? . Replace ( c , '_' ) ;
2024-12-20 21:30:31 -05:00
}
2024-05-23 14:07:42 -04:00
return volumeLabel ;
}
2021-08-04 14:17:53 -07:00
/// <summary>
/// Set the current disc type in the combo box
/// </summary>
2023-09-25 21:16:43 -04:00
private void SetCurrentDiscType ( )
2021-08-04 14:17:53 -07:00
{
2023-10-09 00:42:33 -04:00
// If we don't have any selected media types, we don't care and return
if ( MediaTypes = = null )
return ;
2023-10-09 10:35:44 -04:00
// If we have a detected media type, use that first
if ( _detectedMediaType ! = null )
{
int detectedIndex = MediaTypes . FindIndex ( kvp = > kvp . Value = = _detectedMediaType ) ;
if ( detectedIndex > - 1 )
{
CurrentMediaType = _detectedMediaType ;
return ;
}
}
2021-08-04 14:17:53 -07:00
// 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 ) ;
2024-11-12 22:18:08 -05:00
if ( CurrentMediaType ! = null & & index = = - 1 )
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"Disc of type '{CurrentMediaType.LongName()}' found, but the current system does not support it!" ) ;
2023-10-08 20:52:29 -04:00
2024-11-12 22:18:08 -05:00
CurrentMediaType = ( index > - 1 ? MediaTypes [ index ] : MediaTypes [ 0 ] ) ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
/// Set the drive speed based on reported maximum and user-defined option
/// </summary>
2023-09-25 21:29:55 -04:00
public void SetSupportedDriveSpeed ( )
2021-08-04 14:17:53 -07:00
{
// Set the drive speed list that's appropriate
2024-12-05 22:45:53 -05:00
DriveSpeeds = InterfaceConstants . GetSpeedsForMediaType ( CurrentMediaType ) ;
2024-11-12 22:18:08 -05:00
VerboseLogLn ( $"Supported media speeds: {string.Join(" , ", [.. DriveSpeeds.ConvertAll(ds => ds.ToString())])}" ) ;
2021-08-04 14:17:53 -07:00
// Set the selected speed
2024-06-25 16:42:23 -04:00
int speed = FrontendTool . GetDefaultSpeedForMediaType ( CurrentMediaType , Options ) ;
2021-08-04 14:17:53 -07:00
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"Setting drive speed to: {speed}" ) ;
2024-11-12 22:18:08 -05:00
DriveSpeed = speed ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
/// Determine if the dumping button should be enabled
/// </summary>
2023-09-25 21:16:43 -04:00
private bool ShouldEnableDumpingButton ( )
2021-08-04 14:17:53 -07:00
{
2023-02-23 16:55:27 -05:00
return Drives ! = null
2021-08-04 14:17:53 -07:00
& & Drives . Count > 0
2024-11-12 22:18:08 -05:00
& & CurrentSystem ! = null
& & CurrentMediaType ! = null
2024-05-28 11:36:58 -04:00
& & ProgramSupportsMedia ( ) ;
}
/// <summary>
/// Returns false if a given InternalProgram does not support a given MediaType
/// </summary>
private bool ProgramSupportsMedia ( )
{
// If the media type is not set, return false
if ( CurrentMediaType = = null | | CurrentMediaType = = MediaType . NONE )
return false ;
2024-12-05 22:45:53 -05:00
return CurrentProgram switch
2024-05-28 11:36:58 -04:00
{
// Aaru
InternalProgram . Aaru when CurrentMediaType = = MediaType . BluRay = > true ,
InternalProgram . Aaru when CurrentMediaType = = MediaType . CDROM = > true ,
InternalProgram . Aaru when CurrentMediaType = = MediaType . CompactFlash = > true ,
InternalProgram . Aaru when CurrentMediaType = = MediaType . DVD = > true ,
InternalProgram . Aaru when CurrentMediaType = = MediaType . GDROM = > true ,
InternalProgram . Aaru when CurrentMediaType = = MediaType . FlashDrive = > true ,
InternalProgram . Aaru when CurrentMediaType = = MediaType . FloppyDisk = > true ,
InternalProgram . Aaru when CurrentMediaType = = MediaType . HardDisk = > true ,
InternalProgram . Aaru when CurrentMediaType = = MediaType . HDDVD = > true ,
InternalProgram . Aaru when CurrentMediaType = = MediaType . NintendoGameCubeGameDisc = > true ,
InternalProgram . Aaru when CurrentMediaType = = MediaType . NintendoWiiOpticalDisc = > true ,
2024-12-05 22:45:53 -05:00
InternalProgram . Aaru when CurrentMediaType = = MediaType . NintendoWiiUOpticalDisc = > true ,
2024-05-28 11:36:58 -04:00
InternalProgram . Aaru when CurrentMediaType = = MediaType . SDCard = > true ,
// DiscImageCreator
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . BluRay = > true ,
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . CDROM = > true ,
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . CompactFlash = > true ,
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . DVD = > true ,
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . GDROM = > true ,
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . FlashDrive = > true ,
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . FloppyDisk = > true ,
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . HardDisk = > true ,
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . HDDVD = > true ,
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . NintendoGameCubeGameDisc = > true ,
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . NintendoWiiOpticalDisc = > true ,
2024-12-05 22:45:53 -05:00
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . NintendoWiiUOpticalDisc = > true ,
2024-05-28 11:36:58 -04:00
InternalProgram . DiscImageCreator when CurrentMediaType = = MediaType . SDCard = > true ,
// Redumper
InternalProgram . Redumper when CurrentMediaType = = MediaType . BluRay = > true ,
InternalProgram . Redumper when CurrentMediaType = = MediaType . CDROM = > true ,
InternalProgram . Redumper when CurrentMediaType = = MediaType . DVD = > true ,
InternalProgram . Redumper when CurrentMediaType = = MediaType . GDROM = > true ,
InternalProgram . Redumper when CurrentMediaType = = MediaType . HDDVD = > true ,
2024-12-05 22:45:53 -05:00
InternalProgram . Redumper when CurrentMediaType = = MediaType . NintendoGameCubeGameDisc = > true ,
InternalProgram . Redumper when CurrentMediaType = = MediaType . NintendoWiiOpticalDisc = > true ,
InternalProgram . Redumper when CurrentMediaType = = MediaType . NintendoWiiUOpticalDisc = > true ,
2024-05-28 11:36:58 -04:00
// Default
_ = > false ,
} ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
/// Begin the dumping process using the given inputs
/// </summary>
2023-09-25 21:29:55 -04:00
public async void StartDumping ( )
2021-08-04 14:17:53 -07:00
{
// One last check to determine environment, just in case
2023-10-08 23:06:17 -04:00
_environment = DetermineEnvironment ( ) ;
2021-08-04 14:17:53 -07:00
2022-03-01 16:41:54 -08:00
// Force an internal drive refresh in case the user entered things manually
2024-05-22 16:24:01 -04:00
_environment . RefreshDrive ( ) ;
2022-03-01 16:41:54 -08:00
2021-08-04 14:17:53 -07:00
// If still in custom parameter mode, check that users meant to continue or not
2024-12-20 22:31:10 -05:00
if ( ParametersCheckBoxEnabled = = false & & _displayUserMessage ! = null )
2021-08-04 14:17:53 -07:00
{
2023-10-09 11:01:43 -04:00
bool? result = _displayUserMessage ( "Custom Changes" , "It looks like you have custom parameters that have not been saved. Would you like to apply those changes before starting to dump?" , 3 , true ) ;
if ( result = = true )
2021-08-04 14:17:53 -07:00
{
2024-12-20 22:31:10 -05:00
ParametersCheckBoxEnabled = true ;
2023-09-25 21:16:43 -04:00
ProcessCustomParameters ( ) ;
2021-08-04 14:17:53 -07:00
}
2023-10-09 11:01:43 -04:00
else if ( result = = null )
2023-09-25 16:58:14 -04:00
{
2021-08-04 14:17:53 -07:00
return ;
2023-09-25 16:58:14 -04:00
}
2023-10-09 11:01:43 -04:00
// If false, then we continue with the current known environment
2021-08-04 14:17:53 -07:00
}
try
{
2022-03-05 21:50:18 -08:00
// Run pre-dumping validation checks
2023-09-25 21:21:51 -04:00
if ( ! ValidateBeforeDumping ( ) )
2022-03-05 21:50:18 -08:00
return ;
2021-08-04 14:17:53 -07:00
// Disable all UI elements apart from dumping button
2023-10-08 22:49:46 -04:00
DisableAllUIElements ( ) ;
2021-08-04 14:17:53 -07:00
2022-12-13 11:48:26 -08:00
// Refresh the drive, if it wasn't null
2024-05-22 16:24:01 -04:00
_environment . RefreshDrive ( ) ;
2022-12-13 11:48:26 -08:00
2021-08-04 14:17:53 -07:00
// Output to the label and log
2024-11-12 22:18:08 -05:00
Status = "Starting dumping process... please wait!" ;
2024-02-23 12:55:10 +09:00
LogLn ( "Starting dumping process... please wait!" ) ;
2024-05-27 23:34:42 -04:00
LogLn ( "Look for the separate command window for more details" ) ;
2021-08-04 14:17:53 -07:00
// Get progress indicators
2024-05-22 14:49:45 -04:00
var resultProgress = new Progress < ResultEventArgs > ( ) ;
2021-08-04 14:17:53 -07:00
resultProgress . ProgressChanged + = ProgressUpdated ;
var protectionProgress = new Progress < ProtectionProgress > ( ) ;
protectionProgress . ProgressChanged + = ProgressUpdated ;
2023-10-08 23:06:17 -04:00
_environment . ReportStatus + = ProgressUpdated ;
2021-08-04 14:17:53 -07:00
// Run the program with the parameters
2024-05-22 14:49:45 -04:00
ResultEventArgs result = await _environment . Run ( resultProgress ) ;
2021-08-04 14:17:53 -07:00
// If we didn't execute a dumping command we cannot get submission output
2024-05-22 16:13:14 -04:00
if ( ! _environment . IsDumpingCommand ( ) )
2021-08-04 14:17:53 -07:00
{
2023-10-08 23:40:56 -04:00
LogLn ( "No dumping command was run, submission information will not be gathered." ) ;
2024-11-12 22:18:08 -05:00
Status = "Execution complete!" ;
2021-08-04 14:17:53 -07:00
// Reset all UI elements
2023-10-08 22:49:46 -04:00
EnableAllUIElements ( ) ;
2021-08-04 14:17:53 -07:00
return ;
}
// Verify dump output and save it
if ( result )
{
2023-10-08 23:15:24 -04:00
result = await _environment . VerifyAndSaveDumpOutput ( resultProgress , protectionProgress , _processUserInfo ) ;
2021-08-04 14:17:53 -07:00
}
else
{
2023-10-08 23:40:56 -04:00
ErrorLogLn ( result . Message ) ;
2024-11-12 22:18:08 -05:00
Status = "Execution failed!" ;
2021-08-04 14:17:53 -07:00
}
}
catch ( Exception ex )
{
2023-10-08 23:40:56 -04:00
ErrorLogLn ( ex . ToString ( ) ) ;
2024-11-12 22:18:08 -05:00
Status = "An exception occurred!" ;
2021-08-04 14:17:53 -07:00
}
finally
{
// Reset all UI elements
2023-10-08 22:49:46 -04:00
EnableAllUIElements ( ) ;
}
}
/// <summary>
/// Toggle the parameters input box
/// </summary>
public void ToggleParameters ( )
{
2024-12-20 22:31:10 -05:00
if ( ParametersCheckBoxEnabled = = false )
2023-10-08 22:49:46 -04:00
{
2024-12-21 20:30:23 -05:00
OptionsMenuItemEnabled = false ;
2023-10-08 22:49:46 -04:00
SystemTypeComboBoxEnabled = false ;
MediaTypeComboBoxEnabled = false ;
OutputPathTextBoxEnabled = false ;
OutputPathBrowseButtonEnabled = false ;
2024-12-20 22:33:24 -05:00
DriveLetterComboBoxEnabled = false ;
DriveSpeedComboBoxEnabled = false ;
2024-12-20 22:31:10 -05:00
DumpingProgramComboBoxEnabled = false ;
2024-12-20 22:33:24 -05:00
ParametersTextBoxEnabled = true ;
2024-12-20 22:31:10 -05:00
2023-10-08 22:49:46 -04:00
MediaScanButtonEnabled = false ;
UpdateVolumeLabelEnabled = false ;
CopyProtectScanButtonEnabled = false ;
}
else
{
ProcessCustomParameters ( ) ;
2024-12-21 20:30:23 -05:00
OptionsMenuItemEnabled = true ;
2023-10-08 22:49:46 -04:00
SystemTypeComboBoxEnabled = true ;
MediaTypeComboBoxEnabled = true ;
OutputPathTextBoxEnabled = true ;
OutputPathBrowseButtonEnabled = true ;
2024-12-20 22:33:24 -05:00
DriveLetterComboBoxEnabled = true ;
DriveSpeedComboBoxEnabled = true ;
2024-12-20 22:31:10 -05:00
DumpingProgramComboBoxEnabled = true ;
2024-12-20 22:33:24 -05:00
ParametersTextBoxEnabled = false ;
2024-12-20 22:31:10 -05:00
2023-10-08 22:49:46 -04:00
MediaScanButtonEnabled = true ;
UpdateVolumeLabelEnabled = true ;
CopyProtectScanButtonEnabled = true ;
2021-08-04 14:17:53 -07:00
}
}
2022-03-05 21:50:18 -08:00
/// <summary>
/// Perform validation, including user input, before attempting to start dumping
/// </summary>
/// <returns>True if dumping should start, false otherwise</returns>
2023-09-25 21:21:51 -04:00
private bool ValidateBeforeDumping ( )
2022-03-05 21:50:18 -08:00
{
2024-05-22 16:24:01 -04:00
if ( Parameters = = null | | _environment = = null )
2024-02-22 00:14:39 +09:00
return false ;
2022-12-13 11:48:26 -08:00
// Validate that we have an output path of any sort
2024-05-22 16:24:01 -04:00
if ( string . IsNullOrEmpty ( _environment . OutputPath ) )
2022-12-13 11:48:26 -08:00
{
2023-10-09 11:35:49 -04:00
if ( _displayUserMessage ! = null )
_ = _displayUserMessage ( "Missing Path" , "No output path was provided so dumping cannot continue." , 1 , false ) ;
2023-10-08 23:40:56 -04:00
LogLn ( "Dumping aborted!" ) ;
2022-12-13 11:48:26 -08:00
return false ;
}
2022-03-05 21:50:18 -08:00
// Validate that the user explicitly wants an inactive drive to be considered for dumping
2024-05-22 16:24:01 -04:00
if ( ! _environment . DriveMarkedActive & & _displayUserMessage ! = null )
2022-03-05 21:50:18 -08:00
{
string message = "The currently selected drive does not appear to contain a disc! "
2024-05-22 16:20:17 -04:00
+ ( ! _environment ! . DetectedByWindows ( ) ? $"This is normal for {_environment.SystemName} as the discs may not be readable on Windows. " : string . Empty )
2022-03-05 21:50:18 -08:00
+ "Do you want to continue?" ;
2023-10-09 11:01:43 -04:00
bool? mbresult = _displayUserMessage ( "No Disc Detected" , message , 2 , false ) ;
if ( mbresult ! = true )
2022-03-05 21:50:18 -08:00
{
2023-10-08 23:40:56 -04:00
LogLn ( "Dumping aborted!" ) ;
2022-03-05 21:50:18 -08:00
return false ;
}
}
2022-12-13 11:48:26 -08:00
// Pre-split the output path
2023-11-14 23:09:55 -05:00
var outputDirectory = Path . GetDirectoryName ( _environment ! . OutputPath ) ;
2023-10-08 23:06:17 -04:00
string outputFilename = Path . GetFileName ( _environment . OutputPath ) ;
2022-12-13 11:48:26 -08:00
2022-03-05 21:50:18 -08:00
// If a complete dump already exists
2024-08-23 20:58:55 -04:00
bool foundFiles = _environment . FoundAllFiles ( outputDirectory , outputFilename ) ;
2023-10-09 11:35:49 -04:00
if ( foundFiles & & _displayUserMessage ! = null )
2022-03-05 21:50:18 -08:00
{
2023-10-09 11:01:43 -04:00
bool? mbresult = _displayUserMessage ( "Overwrite?" , "A complete dump already exists! Are you sure you want to overwrite?" , 2 , true ) ;
if ( mbresult ! = true )
2022-03-05 21:50:18 -08:00
{
2023-10-08 23:40:56 -04:00
LogLn ( "Dumping aborted!" ) ;
2022-03-05 21:50:18 -08:00
return false ;
}
}
2024-02-23 12:55:10 +09:00
else
2024-01-11 16:24:17 +13:00
{
2024-02-23 12:55:10 +09:00
// If a complete dump exists from a different program
2024-05-22 16:13:14 -04:00
InternalProgram ? programFound = _environment . CheckForMatchingProgram ( outputDirectory , outputFilename ) ;
2024-02-23 12:55:10 +09:00
if ( programFound ! = null & & _displayUserMessage ! = null )
2024-01-11 16:24:17 +13:00
{
2024-02-23 12:55:10 +09:00
bool? mbresult = _displayUserMessage ( "Overwrite?" , $"A complete dump from {programFound} already exists! Dumping here may cause issues. Are you sure you want to overwrite?" , 2 , true ) ;
if ( mbresult ! = true )
{
LogLn ( "Dumping aborted!" ) ;
return false ;
}
2024-01-11 16:24:17 +13:00
}
}
2022-03-05 21:50:18 -08:00
// Validate that at least some space exists
// TODO: Tie this to the size of the disc, type of disc, etc.
2023-10-09 11:35:49 -04:00
string fullPath ;
2023-11-22 15:56:43 -05:00
if ( string . IsNullOrEmpty ( outputDirectory ) )
2023-10-09 11:35:49 -04:00
fullPath = Path . GetFullPath ( _environment . OutputPath ) ;
else
fullPath = Path . GetFullPath ( outputDirectory ) ;
var driveInfo = new DriveInfo ( Path . GetPathRoot ( fullPath ) ? ? string . Empty ) ;
if ( driveInfo . AvailableFreeSpace < Math . Pow ( 2 , 30 ) & & _displayUserMessage ! = null )
2022-03-05 21:50:18 -08:00
{
2023-10-09 11:01:43 -04:00
bool? mbresult = _displayUserMessage ( "Low Space" , "There is less than 1gb of space left on the target drive. Are you sure you want to continue?" , 2 , true ) ;
if ( mbresult ! = true )
2022-03-05 21:50:18 -08:00
{
2023-10-08 23:40:56 -04:00
LogLn ( "Dumping aborted!" ) ;
2022-03-05 21:50:18 -08:00
return false ;
}
}
// If nothing above fails, we want to continue
return true ;
}
2024-02-22 00:14:39 +09:00
/// <summary>
/// Checks whether a internal program is found in its path
/// </summary>
/// <param name="program">Program to check for</param>
/// <returns>True if the program is found, false otherwise</returns>
private bool InternalProgramExists ( InternalProgram program )
{
try
{
return program switch
{
2024-11-12 22:18:08 -05:00
InternalProgram . Redumper = > File . Exists ( Options . RedumperPath ) ,
InternalProgram . Aaru = > File . Exists ( Options . AaruPath ) ,
InternalProgram . DiscImageCreator = > File . Exists ( Options . DiscImageCreatorPath ) ,
2024-02-22 00:14:39 +09:00
_ = > false ,
} ;
}
catch
{
return false ;
}
}
#endregion
2021-08-04 14:17:53 -07:00
#region Progress Reporting
/// <summary>
/// Handler for Result ProgressChanged event
/// </summary>
2024-05-22 14:24:16 -04:00
private void ProgressUpdated ( object? sender , StringEventArgs value )
2021-08-04 14:17:53 -07:00
{
try
{
2024-05-22 14:29:37 -04:00
LogLn ( value ) ;
2021-08-04 14:17:53 -07:00
}
catch { }
}
/// <summary>
/// Handler for Result ProgressChanged event
/// </summary>
2024-05-22 14:49:45 -04:00
private void ProgressUpdated ( object? sender , ResultEventArgs value )
2021-08-04 14:17:53 -07:00
{
2023-10-09 11:35:49 -04:00
var message = value ? . Message ;
2021-08-04 14:17:53 -07:00
// Update the label with only the first line of output
2024-11-12 22:18:08 -05:00
if ( message ! = null & & message . Contains ( "\n" ) )
Status = value ? . Message ? . Split ( '\n' ) [ 0 ] + " (See log output)" ;
2021-08-04 14:17:53 -07:00
else
2024-11-12 22:18:08 -05:00
Status = value ? . Message ? ? string . Empty ;
2021-08-04 14:17:53 -07:00
// Log based on success or failure
2023-10-09 11:35:49 -04:00
if ( value ! = null & & value )
VerboseLogLn ( message ? ? string . Empty ) ;
else if ( value ! = null & & ! value )
ErrorLogLn ( message ? ? string . Empty ) ;
2021-08-04 14:17:53 -07:00
}
/// <summary>
/// Handler for ProtectionProgress ProgressChanged event
/// </summary>
2023-10-09 11:35:49 -04:00
private void ProgressUpdated ( object? sender , ProtectionProgress value )
2021-08-04 14:17:53 -07:00
{
string message = $"{value.Percentage * 100:N2}%: {value.Filename} - {value.Protection}" ;
2024-11-12 22:18:08 -05:00
Status = message ;
2023-10-08 23:40:56 -04:00
VerboseLogLn ( message ) ;
2021-08-04 14:17:53 -07:00
}
2023-11-06 22:07:40 -05:00
#endregion
2021-08-04 14:17:53 -07:00
}
}