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 ;
using System.Linq ;
2023-10-09 00:13:40 -04:00
using System.Threading.Tasks ;
2023-10-26 00:57:23 -04:00
using BinaryObjectScanner ;
2023-10-08 20:52:29 -04:00
using MPF.Core.Converters ;
2022-04-11 10:32:03 -07:00
using MPF.Core.Data ;
2023-11-20 13:15:06 -05:00
using MPF.Core.Modules ;
2023-10-07 01:30:11 -04:00
using MPF.Core.UI.ComboBoxItems ;
2023-10-30 01:55:56 -04:00
using MPF.Core.Utilities ;
2023-09-05 00:08:09 -04:00
using SabreTools.RedumpLib.Data ;
2021-08-04 14:17:53 -07:00
2023-10-09 11:35:49 -04:00
namespace MPF.Core.UI.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>
2023-10-09 11:35:49 -04:00
public Data . Options Options
2023-09-25 21:29:55 -04:00
{
get = > _options ;
set
{
_options = value ;
OptionsLoader . SaveToConfig ( _options ) ;
}
}
2023-10-09 11:35:49 -04:00
private Data . 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>
2023-10-09 11:35:49 -04:00
private Func < SubmissionInfo ? , ( bool? , SubmissionInfo ? ) > ? _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>
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
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 ;
StartStopButtonText = Interface . StartDumping ;
MediaScanButtonEnabled = 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 = [ ] ;
2023-10-08 20:52:29 -04:00
Systems = RedumpSystemComboBoxItem . GenerateElements ( ) . ToList ( ) ;
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 ,
2023-10-09 11:35:49 -04:00
Func < SubmissionInfo ? , ( bool? , SubmissionInfo ? ) > 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
2023-09-25 21:29:55 -04:00
InitializeUIValues ( removeEventHandlers : false , 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
2023-10-08 22:49:46 -04:00
this . MediaScanButtonEnabled = true ;
this . 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
2023-10-18 01:47:42 -04:00
char? lastSelectedDrive = this . 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
2023-09-25 21:29:55 -04:00
Drives = Drive . CreateListOfDrives ( this . 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
{
2023-11-22 16:26:31 -05:00
VerboseLogLn ( $"Found {Drives.Count} drives: {string.Join(" , ", Drives.Select(d => d.Name).ToArray())}" ) ;
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 ] ) ;
this . Status = "Valid drive found! Choose your Media Type" ;
2023-10-08 22:49:46 -04:00
this . 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
2023-10-08 22:49:46 -04:00
this . StartStopButtonEnabled = ShouldEnableDumpingButton ( ) ;
2021-08-04 14:17:53 -07:00
}
else
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( "Found no drives" ) ;
2023-10-08 20:52:29 -04:00
this . CurrentDrive = null ;
this . Status = "No valid drive found!" ;
2023-10-08 22:49:46 -04:00
this . StartStopButtonEnabled = false ;
this . 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
2023-10-08 20:52:29 -04:00
if ( this . CurrentSystem ! = null )
2021-08-04 14:17:53 -07:00
{
2023-10-08 20:52:29 -04:00
var mediaTypeValues = this . CurrentSystem . MediaTypes ( ) ;
int index = mediaTypeValues . FindIndex ( m = > m = = this . CurrentMediaType ) ;
2023-10-08 23:40:56 -04:00
if ( this . CurrentMediaType ! = null & & index = = - 1 )
VerboseLogLn ( $"Disc of type '{CurrentMediaType.LongName()}' found, but the current system does not support it!" ) ;
2023-10-08 20:52:29 -04:00
2023-10-10 01:52:47 -04:00
MediaTypes = mediaTypeValues . Select ( m = > new Element < MediaType > ( m ? ? MediaType . NONE ) ) . ToList ( ) ;
2023-10-08 22:49:46 -04:00
this . MediaTypeComboBoxEnabled = MediaTypes . Count > 1 ;
2023-10-08 20:52:29 -04:00
this . CurrentMediaType = ( index > - 1 ? MediaTypes [ index ] : MediaTypes [ 0 ] ) ;
2021-08-04 14:17:53 -07:00
}
else
{
2023-10-08 22:49:46 -04:00
this . MediaTypeComboBoxEnabled = false ;
this . MediaTypes = null ;
this . 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
InternalPrograms = Enum . GetValues ( typeof ( InternalProgram ) ) . Cast < InternalProgram > ( ) . Where ( ip = > InternalProgramExists ( ip ) ) . Select ( ip = > new Element < InternalProgram > ( ip ) ) . ToList ( ) ;
2023-04-11 11:15:53 -04:00
// Get the current internal program
2023-09-25 21:29:55 -04:00
InternalProgram internalProgram = this . 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
this . CurrentProgram = InternalProgram . NONE ;
}
else
{
int currentIndex = InternalPrograms . FindIndex ( m = > m = = internalProgram ) ;
this . CurrentProgram = ( currentIndex > - 1 ? InternalPrograms [ currentIndex ] . Value : InternalPrograms [ 0 ] . Value ) ;
}
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
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"Changed dumping program to: {((InternalProgram?)this.CurrentProgram).LongName()}" ) ;
2023-09-25 21:29:55 -04:00
EnsureDiscInformation ( ) ;
GetOutputNames ( false ) ;
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
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"Changed system to: {this.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>
2023-10-09 11:35:49 -04:00
public ( bool , string , string? ) CheckForUpdates ( )
2021-08-04 14:17:53 -07:00
{
2023-10-09 11:35:49 -04:00
( bool different , string message , var url ) = Tools . CheckForNewVersion ( ) ;
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." ;
2023-10-09 00:03:02 -04:00
return ( different , message , url ) ;
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}"
+ $"{Environment.NewLine}Version {Tools.GetCurrentVersion()}" ;
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>
2023-09-25 21:29:55 -04:00
public async void ToggleStartStop ( )
2021-08-04 14:17:53 -07:00
{
// Dump or stop the dump
2023-10-08 22:49:46 -04:00
if ( this . StartStopButtonText as string = = Interface . StartDumping )
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
}
2023-10-08 22:49:46 -04:00
else if ( this . StartStopButtonText as string = = Interface . StopDumping )
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 ( ) ;
2023-10-08 22:49:46 -04:00
this . CopyProtectScanButtonEnabled = true ;
2021-08-04 14:17:53 -07:00
2023-10-09 11:35:49 -04:00
if ( _environment ! = null & & _environment . Options . EjectAfterDump )
2021-08-04 14:17:53 -07:00
{
2023-10-18 01:47:42 -04:00
VerboseLogLn ( $"Ejecting disc in drive {_environment.Drive?.Name}" ) ;
2023-10-08 23:06:17 -04:00
await _environment . EjectDisc ( ) ;
2021-08-04 14:17:53 -07:00
}
2023-10-09 11:35:49 -04:00
if ( _environment ! = null & & this . Options . DICResetDriveAfterDump )
2021-08-04 14:17:53 -07:00
{
2023-10-18 01:47:42 -04:00
VerboseLogLn ( $"Resetting drive {_environment.Drive?.Name}" ) ;
2023-10-08 23:06:17 -04:00
await _environment . ResetDrive ( ) ;
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>
2023-10-11 11:49:56 -04:00
public void UpdateOptions ( bool savedSettings , Data . 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
2023-11-06 23:06:11 -05:00
var continuingOptions = new Data . Options ( optionsToSave ) { FirstRun = false } ;
2023-10-18 02:59:41 -04:00
this . Options = continuingOptions ;
// If settings were changed, reinitialize the UI
2023-10-08 23:40:56 -04:00
if ( savedSettings )
2023-09-25 21:29:55 -04:00
InitializeUIValues ( removeEventHandlers : 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>
/// <param name="rescanDrives">Whether drives should be rescanned or not</param>
2023-10-08 23:06:17 -04:00
public void InitializeUIValues ( bool removeEventHandlers , 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
2021-11-08 20:45:37 -08:00
// Safely uncheck the parameters box, just in case
2023-10-10 22:05:39 -04:00
if ( ParametersCheckBoxEnabled = = true )
2021-11-08 20:45:37 -08:00
{
2023-10-10 22:05:39 -04:00
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged ;
DisableEventHandlers ( ) ;
ParametersCheckBoxEnabled = false ;
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
2023-10-08 22:49:46 -04:00
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
2023-10-08 22:49:46 -04:00
this . StartStopButtonEnabled = false ;
2023-03-04 22:40:10 -05:00
// Safely uncheck the parameters box, just in case
2023-10-08 22:49:46 -04:00
if ( this . ParametersCheckBoxEnabled = = true )
2023-03-04 22:40:10 -05:00
{
2023-10-10 22:05:39 -04:00
bool cachedCanExecuteSelectionChanged = CanExecuteSelectionChanged ;
this . DisableEventHandlers ( ) ;
2023-10-08 22:49:46 -04:00
this . ParametersCheckBoxEnabled = false ;
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
2023-10-08 20:52:29 -04:00
this . 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
2023-10-08 22:49:46 -04:00
this . 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
2023-10-08 20:52:29 -04:00
if ( this . CurrentDrive = = null )
2021-08-04 14:17:53 -07:00
return ;
// Get reasonable default values based on the current system
2023-10-08 20:52:29 -04:00
MediaType ? defaultMediaType = this . CurrentSystem . MediaTypes ( ) . FirstOrDefault ( ) ? ? 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
2023-09-25 21:29:55 -04:00
if ( this . 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
2023-10-08 20:52:29 -04:00
else if ( this . CurrentDrive . MarkedActive )
2021-08-04 14:17:53 -07:00
{
2023-10-18 01:47:42 -04:00
VerboseLog ( $"Trying to detect media type for drive {this.CurrentDrive.Name} [{this.CurrentDrive.DriveFormat}] using size and filesystem.. " ) ;
2023-10-09 11:35:49 -04:00
( MediaType ? detectedMediaType , var errorMessage ) = this . CurrentDrive . GetMediaType ( this . CurrentSystem ) ;
2021-08-04 14:17:53 -07:00
// If we got an error message, post it to the log
2023-10-08 23:40:56 -04:00
if ( errorMessage ! = null )
VerboseLogLn ( $"Message from detecting media type: {errorMessage}" ) ;
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 )
{
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"Unable to detect, 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>
2023-09-25 21:16:43 -04:00
/// <returns>Filled DumpEnvironment this.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 (
this . Options ,
2024-01-11 13:42:34 +13:00
EvaluateOutputPath ( this . OutputPath ) ,
2023-10-08 20:52:29 -04:00
this . CurrentDrive ,
this . CurrentSystem ,
this . CurrentMediaType ,
this . CurrentProgram ,
this . 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
{
2023-10-08 20:52:29 -04:00
if ( Drives = = null | | Drives . Count = = 0 | | this . 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
}
2023-10-08 20:52:29 -04:00
else if ( this . 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
}
2023-09-25 21:29:55 -04:00
else if ( ! this . Options . SkipSystemDetection )
2021-08-04 14:17:53 -07:00
{
2023-10-18 01:47:42 -04:00
VerboseLog ( $"Trying to detect system for drive {this.CurrentDrive.Name}.. " ) ;
2023-10-08 20:52:29 -04:00
var currentSystem = this . CurrentDrive ? . GetRedumpSystem ( this . Options . DefaultSystem ) ? ? this . Options . DefaultSystem ;
2023-10-08 23:40:56 -04:00
VerboseLogLn ( currentSystem = = null ? "unable to detect." : ( $"detected {currentSystem.LongName()}." ) ) ;
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 ) ;
2023-10-08 22:49:46 -04:00
this . CurrentSystem = Systems [ sysIndex ] ;
2021-08-04 14:17:53 -07:00
}
}
2023-09-25 21:29:55 -04:00
else if ( this . Options . SkipSystemDetection & & this . Options . DefaultSystem ! = null )
2021-12-21 21:11:18 -08:00
{
2023-09-25 21:29:55 -04:00
var currentSystem = this . Options . DefaultSystem ;
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"System detection disabled, setting to default of {currentSystem.LongName()}." ) ;
2021-12-21 21:11:18 -08:00
int sysIndex = Systems . FindIndex ( s = > s = = currentSystem ) ;
2023-10-08 22:49:46 -04:00
this . 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 ;
StartStopButtonText = Interface . StopDumping ;
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 ;
StartStopButtonText = Interface . StartDumping ;
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
2023-10-08 23:06:17 -04:00
Result result = Tools . GetSupportStatus ( _environment . System , _environment . Type ) ;
2024-02-22 00:14:39 +09:00
if ( this . CurrentProgram = = InternalProgram . NONE | | _environment . Parameters = = null )
this . Status = "No dumping program found" ;
else
this . Status = result . Message ;
2021-08-04 14:17:53 -07:00
// Enable or disable the button
2023-10-08 22:49:46 -04:00
this . StartStopButtonEnabled = result & & ShouldEnableDumpingButton ( ) ;
2021-08-04 14:17:53 -07:00
// If we're in a type that doesn't support drive speeds
2023-10-08 23:06:17 -04:00
this . DriveSpeedComboBoxEnabled = _environment . Type . DoesSupportDriveSpeed ( ) ;
2021-08-04 14:17:53 -07:00
// If input params are not enabled, generate the full parameters from the environment
2023-10-08 22:49:46 -04:00
if ( ! this . ParametersCheckBoxEnabled )
2021-08-04 14:17:53 -07:00
{
2023-10-09 11:35:49 -04:00
var generated = _environment . GetFullParameters ( this . DriveSpeed ) ;
2021-08-04 14:17:53 -07:00
if ( generated ! = null )
2023-10-08 20:52:29 -04:00
this . 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 )
{
string systemLong = this . _currentSystem . LongName ( ) ? ? "Unknown System" ;
if ( string . IsNullOrEmpty ( systemLong ) )
systemLong = "Unknown System" ;
string systemShort = this . _currentSystem . ShortName ( ) ? ? "unknown" ;
if ( string . IsNullOrEmpty ( systemShort ) )
systemShort = "unknown" ;
string mediaLong = this . _currentMediaType . LongName ( ) ? ? "Unknown Media" ;
if ( string . IsNullOrEmpty ( mediaLong ) )
mediaLong = "Unknown Media" ;
string program = this . _currentProgram . ToString ( ) ? ? "Unknown Program" ;
if ( string . IsNullOrEmpty ( program ) )
program = "Unknown Program" ;
string programShort = program = = "DiscImageCreator" ? "DIC" : program ;
if ( string . IsNullOrEmpty ( programShort ) )
programShort = "Unknown Program" ;
string label = this . _currentDrive ? . FormattedVolumeLabel ? ? "track" ;
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 )
. Replace ( "%SYS%" , systemShort )
. 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
{
2023-10-08 20:52:29 -04:00
if ( Drives = = null | | Drives . Count = = 0 | | this . 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 ;
}
2021-08-04 14:17:53 -07:00
// Get the extension for the file for the next two statements
2023-10-09 11:35:49 -04:00
var extension = _environment ? . Parameters ? . GetDefaultExtension ( this . CurrentMediaType ) ;
2021-08-04 14:17:53 -07:00
2022-12-13 11:48:26 -08:00
// Set the output filename, if it's not already
2023-10-08 20:52:29 -04:00
if ( string . IsNullOrEmpty ( this . OutputPath ) )
2022-12-13 11:48:26 -08:00
{
2023-10-09 11:35:49 -04:00
var label = this . CurrentDrive ? . FormattedVolumeLabel ? ? this . CurrentSystem . LongName ( ) ;
var directory = this . Options . DefaultOutputPath ;
2022-12-13 11:48:26 -08:00
string filename = $"{label}{extension ?? " . bin "}" ;
2021-08-04 14:17:53 -07:00
2023-02-23 12:31:27 -05:00
// If the path ends with the label already
2023-10-09 11:35:49 -04:00
if ( directory ! = null & & label ! = null & & directory . EndsWith ( label , StringComparison . OrdinalIgnoreCase ) )
2023-02-23 12:31:27 -05:00
directory = Path . GetDirectoryName ( directory ) ;
2023-10-09 11:35:49 -04:00
if ( directory ! = null & & label ! = null )
2023-11-22 16:26:31 -05:00
#if NET20 | | NET35
this . OutputPath = Path . Combine ( Path . Combine ( directory , label ) , filename ) ;
#else
2023-10-09 11:35:49 -04:00
this . OutputPath = Path . Combine ( directory , label , filename ) ;
2023-11-22 16:26:31 -05:00
#endif
2023-10-09 11:35:49 -04:00
else
this . OutputPath = filename ;
2022-12-13 11:48:26 -08:00
}
2021-08-04 14:17:53 -07:00
2022-12-13 11:48:26 -08:00
// Set the output filename, if we changed drives
else if ( driveChanged )
{
2023-10-09 11:35:49 -04:00
var label = this . CurrentDrive ? . FormattedVolumeLabel ? ? this . CurrentSystem . LongName ( ) ;
2023-10-08 20:52:29 -04:00
string oldPath = InfoTool . NormalizeOutputPaths ( this . OutputPath , false ) ;
2023-09-26 21:09:53 -04:00
string oldFilename = Path . GetFileNameWithoutExtension ( oldPath ) ;
2023-10-09 11:35:49 -04:00
var directory = Path . GetDirectoryName ( oldPath ) ;
2022-12-13 11:48:26 -08:00
string filename = $"{label}{extension ?? " . bin "}" ;
2021-08-04 14:17:53 -07:00
2023-02-23 12:31:27 -05:00
// If the previous path included the label
2023-10-09 11:35:49 -04:00
if ( directory ! = null & & directory . EndsWith ( oldFilename , StringComparison . OrdinalIgnoreCase ) )
2023-02-23 12:31:27 -05:00
directory = Path . GetDirectoryName ( directory ) ;
// If the path ends with the label already
2023-10-09 11:35:49 -04:00
if ( directory ! = null & & label ! = null & & directory . EndsWith ( label , StringComparison . OrdinalIgnoreCase ) )
2023-02-23 12:31:27 -05:00
directory = Path . GetDirectoryName ( directory ) ;
2023-10-09 11:35:49 -04:00
if ( directory ! = null & & label ! = null )
2023-11-22 16:26:31 -05:00
#if NET20 | | NET35
this . OutputPath = Path . Combine ( Path . Combine ( directory , label ) , filename ) ;
#else
2023-10-09 11:35:49 -04:00
this . OutputPath = Path . Combine ( directory , label , filename ) ;
2023-11-22 16:26:31 -05:00
#endif
2023-10-09 11:35:49 -04:00
else
this . OutputPath = filename ;
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
{
2023-10-08 20:52:29 -04:00
string oldPath = InfoTool . NormalizeOutputPaths ( this . OutputPath , false ) ;
2023-09-26 21:09:53 -04:00
string filename = Path . GetFileNameWithoutExtension ( oldPath ) ;
2023-10-09 11:35:49 -04:00
var directory = Path . GetDirectoryName ( oldPath ) ;
2023-08-28 11:24:58 -04:00
filename = $"{filename}{extension ?? " . bin "}" ;
2023-10-09 11:35:49 -04:00
if ( directory ! = null )
this . OutputPath = Path . Combine ( directory , filename ) ;
else
this . OutputPath = filename ;
2023-08-28 11:24:58 -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
{
2023-10-09 11:35:49 -04:00
_environment ? . SetParameters ( this . Parameters ) ;
if ( _environment ? . Parameters = = null )
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
{
2023-10-18 01:47:42 -04:00
int driveIndex = Drives . Select ( d = > d . Name ? [ 0 ] ? ? '\0' ) . ToList ( ) . IndexOf ( _environment . Parameters ? . InputPath ? [ 0 ] ? ? default ) ;
2023-10-08 20:52:29 -04:00
this . CurrentDrive = ( driveIndex ! = - 1 ? Drives [ driveIndex ] : Drives [ 0 ] ) ;
2022-01-13 10:25:57 -08:00
}
catch { }
2022-03-02 00:43:05 -05:00
2023-10-09 11:35:49 -04:00
int driveSpeed = _environment . Parameters ? . Speed ? ? - 1 ;
2021-08-04 14:17:53 -07:00
if ( driveSpeed > 0 )
2023-10-08 20:52:29 -04:00
this . DriveSpeed = driveSpeed ;
2023-10-09 11:35:49 -04:00
else if ( _environment . Parameters ! = null )
2023-10-08 23:06:17 -04:00
_environment . Parameters . Speed = this . DriveSpeed ;
2021-08-04 14:17:53 -07:00
2023-07-19 12:51:22 -04:00
// Disable change handling
DisableEventHandlers ( ) ;
2023-10-27 02:17:17 +13:00
this . OutputPath = InfoTool . NormalizeOutputPaths ( _environment . Parameters ? . OutputPath , false ) ;
2021-08-04 14:17:53 -07:00
2023-10-09 11:35:49 -04:00
if ( MediaTypes ! = null )
{
MediaType ? mediaType = _environment . Parameters ? . GetMediaType ( ) ;
int mediaTypeIndex = MediaTypes . FindIndex ( m = > m = = mediaType ) ;
this . CurrentMediaType = ( mediaTypeIndex > - 1 ? MediaTypes [ mediaTypeIndex ] : MediaTypes [ 0 ] ) ;
}
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>
2023-11-22 23:38:59 -05:00
#if NET40
2023-11-21 11:13:58 -05:00
public ( string? , string? ) ScanAndShowProtection ( )
#else
2023-10-09 11:35:49 -04:00
public async Task < ( string? , string? ) > ScanAndShowProtection ( )
2023-11-21 11:13:58 -05:00
#endif
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
2023-10-18 01:47:42 -04:00
if ( this . CurrentDrive ? . Name = = null )
2023-10-09 00:03:02 -04:00
return ( null , "No valid drive found!" ) ;
2021-08-04 14:17:53 -07:00
2023-10-18 01:47:42 -04:00
VerboseLogLn ( $"Scanning for copy protection in {this.CurrentDrive.Name}" ) ;
2021-08-04 14:17:53 -07:00
2023-10-09 00:03:02 -04:00
var tempContent = this . Status ;
this . Status = "Scanning for copy protection... this might take a while!" ;
this . StartStopButtonEnabled = false ;
this . MediaScanButtonEnabled = false ;
this . UpdateVolumeLabelEnabled = false ;
this . CopyProtectScanButtonEnabled = false ;
var progress = new Progress < ProtectionProgress > ( ) ;
progress . ProgressChanged + = ProgressUpdated ;
2023-11-22 23:38:59 -05:00
#if NET40
2023-11-21 11:13:58 -05:00
var protectionTask = Protection . RunProtectionScanOnPath ( this . CurrentDrive . Name , this . Options , progress ) ;
protectionTask . Wait ( ) ;
var ( protections , error ) = protectionTask . Result ;
#else
2023-10-18 01:47:42 -04:00
var ( protections , error ) = await Protection . RunProtectionScanOnPath ( this . CurrentDrive . Name , this . Options , progress ) ;
2023-11-21 11:13:58 -05:00
#endif
2023-10-09 11:35:49 -04:00
var output = Protection . FormatProtections ( protections ) ;
2023-10-09 00:03:02 -04:00
// If SmartE is detected on the current disc, remove `/sf` from the flags for DIC only -- Disabled until further notice
//if (Env.InternalProgram == InternalProgram.DiscImageCreator && output.Contains("SmartE"))
//{
// ((Modules.DiscImageCreator.Parameters)Env.Parameters)[Modules.DiscImageCreator.FlagStrings.ScanFileProtect] = false;
// if (this.Options.VerboseLogging)
// this.Logger.VerboseLogLn($"SmartE detected, removing {Modules.DiscImageCreator.FlagStrings.ScanFileProtect} from parameters");
//}
if ( string . IsNullOrEmpty ( error ) )
2023-10-18 01:47:42 -04:00
LogLn ( $"Detected the following protections in {this.CurrentDrive.Name}:\r\n\r\n{output}" ) ;
2023-10-09 00:03:02 -04:00
else
ErrorLogLn ( $"Path could not be scanned! Exception information:\r\n\r\n{error}" ) ;
2021-08-04 14:17:53 -07:00
2023-10-09 00:03:02 -04:00
this . Status = tempContent ;
this . StartStopButtonEnabled = ShouldEnableDumpingButton ( ) ;
this . MediaScanButtonEnabled = true ;
this . UpdateVolumeLabelEnabled = true ;
this . CopyProtectScanButtonEnabled = true ;
2021-08-04 14:17:53 -07:00
2023-10-09 00:03:02 -04:00
return ( output , error ) ;
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 ) ;
2023-10-08 23:40:56 -04:00
if ( this . CurrentMediaType ! = null & & index = = - 1 )
VerboseLogLn ( $"Disc of type '{CurrentMediaType.LongName()}' found, but the current system does not support it!" ) ;
2023-10-08 20:52:29 -04:00
this . 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
2023-10-08 22:49:46 -04:00
this . DriveSpeeds = ( List < int > ) Interface . GetSpeedsForMediaType ( CurrentMediaType ) ;
2023-11-22 16:26:31 -05:00
VerboseLogLn ( $"Supported media speeds: {string.Join(" , ", this.DriveSpeeds.Select(ds => ds.ToString()).ToArray())}" ) ;
2021-08-04 14:17:53 -07:00
// Set the selected speed
2023-10-30 16:42:15 -04:00
int speed = ( CurrentMediaType ) switch
{
// CD dump speed
MediaType . CDROM = > Options . PreferredDumpSpeedCD ,
MediaType . GDROM = > Options . PreferredDumpSpeedCD ,
// DVD dump speed
MediaType . DVD = > Options . PreferredDumpSpeedDVD ,
MediaType . NintendoGameCubeGameDisc = > Options . PreferredDumpSpeedDVD ,
MediaType . NintendoWiiOpticalDisc = > Options . PreferredDumpSpeedDVD ,
// HD-DVD dump speed
MediaType . HDDVD = > Options . PreferredDumpSpeedHDDVD ,
// BD dump speed
MediaType . BluRay = > Options . PreferredDumpSpeedBD ,
// Default
_ = > Options . PreferredDumpSpeedCD ,
} ;
2021-08-04 14:17:53 -07:00
2023-10-08 23:40:56 -04:00
VerboseLogLn ( $"Setting drive speed to: {speed}" ) ;
2023-10-08 20:52:29 -04:00
this . 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
2023-10-08 20:52:29 -04:00
& & this . CurrentSystem ! = null
2023-10-13 08:46:44 +13:00
& & this . CurrentMediaType ! = null
2023-10-14 03:54:10 +13:00
& & Tools . ProgramSupportsMedia ( this . CurrentProgram , this . CurrentMediaType ) ;
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
2023-10-09 11:35:49 -04:00
_environment . Drive ? . 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
2023-10-09 11:35:49 -04:00
if ( this . ParametersCheckBoxEnabled = = true & & _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
{
2023-10-08 22:49:46 -04:00
this . ParametersCheckBoxEnabled = false ;
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
}
2023-04-13 12:33:14 -04:00
// Run path adjustments for DiscImageCreator -- Disabled until further notice
//Env.AdjustPathsForDiscImageCreator();
2022-02-13 22:49:33 -08:00
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
2023-10-08 23:06:17 -04:00
_environment . Drive ? . RefreshDrive ( ) ;
2022-12-13 11:48:26 -08:00
2021-08-04 14:17:53 -07:00
// Output to the label and log
2024-02-23 12:55:10 +09:00
this . Status = "Starting dumping process... please wait!" ;
LogLn ( "Starting dumping process... please wait!" ) ;
2023-09-25 21:29:55 -04:00
if ( this . Options . ToolsInSeparateWindow )
2023-10-08 23:40:56 -04:00
LogLn ( "Look for the separate command window for more details" ) ;
2021-08-04 14:17:53 -07:00
else
2023-10-08 23:40:56 -04:00
LogLn ( "Program outputs may be slow to populate in the log window" ) ;
2021-08-04 14:17:53 -07:00
// Get progress indicators
var resultProgress = new Progress < Result > ( ) ;
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
2023-11-22 23:38:59 -05:00
#if NET40
2023-11-22 15:56:43 -05:00
Result result = _environment . Run ( resultProgress ) ;
#else
2023-10-08 23:06:17 -04:00
Result result = await _environment . Run ( resultProgress ) ;
2023-11-22 15:56:43 -05:00
#endif
2021-08-04 14:17:53 -07:00
// If we didn't execute a dumping command we cannot get submission output
2023-10-09 11:35:49 -04:00
if ( _environment . Parameters ? . IsDumpingCommand ( ) ! = true )
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." ) ;
2023-10-08 20:52:29 -04:00
this . 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 ) ;
2023-10-08 20:52:29 -04:00
this . 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 ( ) ) ;
2023-10-08 20:52:29 -04:00
this . 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 ( )
{
if ( ParametersCheckBoxEnabled = = true )
{
SystemTypeComboBoxEnabled = false ;
MediaTypeComboBoxEnabled = false ;
OutputPathTextBoxEnabled = false ;
OutputPathBrowseButtonEnabled = false ;
MediaScanButtonEnabled = false ;
UpdateVolumeLabelEnabled = false ;
CopyProtectScanButtonEnabled = false ;
}
else
{
ProcessCustomParameters ( ) ;
SystemTypeComboBoxEnabled = true ;
MediaTypeComboBoxEnabled = true ;
OutputPathTextBoxEnabled = true ;
OutputPathBrowseButtonEnabled = true ;
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-02-22 00:14:39 +09:00
if ( Parameters = = null )
return false ;
2022-12-13 11:48:26 -08:00
// Validate that we have an output path of any sort
2023-11-22 15:56:43 -05: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
2023-11-14 23:09:55 -05:00
if ( _environment ? . Drive ? . MarkedActive ! = true & & _displayUserMessage ! = null )
2022-03-05 21:50:18 -08:00
{
string message = "The currently selected drive does not appear to contain a disc! "
2023-11-14 23:09:55 -05:00
+ ( ! _environment ! . System . DetectedByWindows ( ) ? $"This is normal for {_environment.System.LongName()} 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
2023-11-16 15:20:19 -05:00
( bool foundFiles , List < string > _ ) = _environment . Parameters . FoundAllFiles ( outputDirectory , outputFilename , true ) ;
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
InternalProgram ? programFound = null ;
if ( programFound = = null & & _environment . InternalProgram ! = InternalProgram . Aaru )
2024-01-11 16:24:17 +13:00
{
2024-02-23 12:55:10 +09:00
Modules . Aaru . Parameters parameters = new ( "" )
{
Type = _environment . Type ,
System = _environment . System
} ;
( bool foundOtherFiles , _ ) = parameters . FoundAllFiles ( outputDirectory , outputFilename , true ) ;
if ( foundOtherFiles )
programFound = InternalProgram . Aaru ;
}
if ( programFound = = null & & _environment . InternalProgram ! = InternalProgram . DiscImageCreator )
2024-01-11 16:24:17 +13:00
{
2024-02-23 12:55:10 +09:00
Modules . DiscImageCreator . Parameters parameters = new ( "" )
{
Type = _environment . Type ,
System = _environment . System
} ;
( bool foundOtherFiles , _ ) = parameters . FoundAllFiles ( outputDirectory , outputFilename , true ) ;
if ( foundOtherFiles )
programFound = InternalProgram . DiscImageCreator ;
}
if ( programFound = = null & & _environment . InternalProgram ! = InternalProgram . Redumper )
2024-01-11 16:24:17 +13:00
{
2024-02-23 12:55:10 +09:00
Modules . Redumper . Parameters parameters = new ( "" )
{
Type = _environment . Type ,
System = _environment . System
} ;
( bool foundOtherFiles , _ ) = parameters . FoundAllFiles ( outputDirectory , outputFilename , true ) ;
if ( foundOtherFiles )
programFound = InternalProgram . Redumper ;
}
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
{
InternalProgram . Redumper = > File . Exists ( this . Options . RedumperPath ) ,
InternalProgram . Aaru = > File . Exists ( this . Options . AaruPath ) ,
InternalProgram . DiscImageCreator = > File . Exists ( this . Options . DiscImageCreatorPath ) ,
_ = > false ,
} ;
}
catch
{
return false ;
}
}
#endregion
2021-08-04 14:17:53 -07:00
#region Progress Reporting
/// <summary>
/// Handler for Result ProgressChanged event
/// </summary>
2023-11-22 15:56:43 -05:00
#if NET20 | | NET35 | | NET40
2023-11-20 13:15:06 -05:00
private void ProgressUpdated ( object? sender , BaseParameters . StringEventArgs value )
#else
2023-10-09 11:35:49 -04:00
private void ProgressUpdated ( object? sender , string value )
2023-11-20 13:15:06 -05:00
#endif
2021-08-04 14:17:53 -07:00
{
try
{
2023-11-22 15:56:43 -05:00
#if NET20 | | NET35 | | NET40
2023-11-20 13:15:06 -05:00
value . Value ? ? = string . Empty ;
LogLn ( value . Value ) ;
#else
2023-10-11 13:07:45 -04:00
value ? ? = string . Empty ;
2023-10-08 23:40:56 -04:00
LogLn ( value ) ;
2023-11-20 13:15:06 -05:00
#endif
2021-08-04 14:17:53 -07:00
}
catch { }
}
/// <summary>
/// Handler for Result ProgressChanged event
/// </summary>
2023-10-09 11:35:49 -04:00
private void ProgressUpdated ( object? sender , Result 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
2023-10-11 12:26:24 -04:00
if ( message ! = null & & message . Contains ( '\n' ) )
2023-10-09 11:35:49 -04:00
this . Status = value ? . Message ? . Split ( '\n' ) [ 0 ] + " (See log output)" ;
2021-08-04 14:17:53 -07:00
else
2023-10-09 11:35:49 -04:00
this . 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}" ;
2023-10-08 20:52:29 -04:00
this . 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
}
}