mirror of
https://github.com/SabreTools/MPF.git
synced 2026-07-02 17:24:48 +00:00
862 lines
31 KiB
C#
862 lines
31 KiB
C#
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using MPF.Core.Converters;
|
|
using MPF.Core.Data;
|
|
using RedumpLib.Data;
|
|
|
|
namespace MPF.Modules.Redumper
|
|
{
|
|
/// <summary>
|
|
/// Represents a generic set of Redumper parameters
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// TODO: Redumper natively supports multiple, chained commands but MPF
|
|
/// doesn't have an easy way of dealing with that right now. Maybe have
|
|
/// BaseCommand be a space-deliminated list of the commands?
|
|
/// TODO: With chained commands, how do we tell what parameters are
|
|
/// actually supported? Do we go one by one and if it doesn't match
|
|
/// any, then it's incorrect?
|
|
/// </remarks>
|
|
public class Parameters : BaseParameters
|
|
{
|
|
#region Generic Dumping Information
|
|
|
|
/// <inheritdoc/>
|
|
public override string InputPath => DriveValue;
|
|
|
|
/// <inheritdoc/>
|
|
public override string OutputPath => Path.Combine(ImagePathValue ?? string.Empty, ImageNameValue ?? string.Empty);
|
|
|
|
/// <inheritdoc/>
|
|
public override int? Speed => SpeedValue;
|
|
|
|
#endregion
|
|
|
|
#region Metadata
|
|
|
|
/// <inheritdoc/>
|
|
public override InternalProgram InternalProgram => InternalProgram.Redumper;
|
|
|
|
#endregion
|
|
|
|
#region Flag Values
|
|
|
|
/// <summary>
|
|
/// Maximum absolute sample value to treat it as silence (default: 32)
|
|
/// </summary>
|
|
public int? AudioSilenceThresholdValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// Drive to use, first available drive with disc, if not provided
|
|
/// </summary>
|
|
public string DriveValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// Override offset autodetection and use supplied value
|
|
/// </summary>
|
|
public int? ForceOffsetValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// Dump files prefix, autogenerated in dump mode, if not provided
|
|
/// </summary>
|
|
public string ImageNameValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// Dump files base directory
|
|
/// </summary>
|
|
public string ImagePathValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// Number of sector retries in case of SCSI/C2 error (default: 0)
|
|
/// </summary>
|
|
public int? RetriesValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// Rings mode, maximum ring size to stop subdivision (rings, default: 1024)
|
|
/// </summary>
|
|
public int? RingSizeValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// LBA ranges of sectors to skip
|
|
/// </summary>
|
|
public string SkipValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// Fill byte value for skipped sectors (default: 0x55)
|
|
/// </summary>
|
|
public byte? SkipFillValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// Rings mode, number of sectors to skip on SCSI error (default: 4096)
|
|
/// </summary>
|
|
public int? SkipSizeValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// Drive read speed, optimal drive speed will be used if not provided
|
|
/// </summary>
|
|
public int? SpeedValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// LBA to stop dumping at (everything before the value, useful for discs with fake TOC
|
|
/// </summary>
|
|
public int? StopLBAValue { get; set; }
|
|
|
|
#endregion
|
|
|
|
/// <inheritdoc/>
|
|
public Parameters(string parameters) : base(parameters) { }
|
|
|
|
/// <inheritdoc/>
|
|
public Parameters(RedumpSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, Options options)
|
|
: base(system, type, driveLetter, filename, driveSpeed, options)
|
|
{
|
|
}
|
|
|
|
#region BaseParameters Implementations
|
|
|
|
/// <inheritdoc/>
|
|
public override (bool, List<string>) CheckAllOutputFilesExist(string basePath, bool preCheck)
|
|
{
|
|
// TODO: Fill out
|
|
return (true, new List<string>());
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override void GenerateSubmissionInfo(SubmissionInfo info, string basePath, Drive drive, bool includeArtifacts)
|
|
{
|
|
// TODO: Fill in submission info specifics for Redumper
|
|
string outputDirectory = Path.GetDirectoryName(basePath);
|
|
|
|
// TODO: Determine if there's a Redumper version anywhere
|
|
info.DumpingInfo.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
|
|
|
switch (this.Type)
|
|
{
|
|
// Determine type-specific differences
|
|
}
|
|
|
|
switch (this.System)
|
|
{
|
|
case RedumpSystem.KonamiPython2:
|
|
if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out Region? pythonTwoRegion, out string pythonTwoDate))
|
|
{
|
|
// Ensure internal serial is pulled from local data
|
|
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = pythonTwoSerial ?? string.Empty;
|
|
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion;
|
|
info.CommonDiscInfo.EXEDateBuildDate = pythonTwoDate;
|
|
}
|
|
|
|
info.VersionAndEditions.Version = GetPlayStation2Version(drive?.Letter) ?? "";
|
|
break;
|
|
|
|
case RedumpSystem.SonyPlayStation:
|
|
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out Region? playstationRegion, out string playstationDate))
|
|
{
|
|
// Ensure internal serial is pulled from local data
|
|
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationSerial ?? string.Empty;
|
|
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion;
|
|
info.CommonDiscInfo.EXEDateBuildDate = playstationDate;
|
|
}
|
|
|
|
break;
|
|
|
|
case RedumpSystem.SonyPlayStation2:
|
|
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out Region? playstationTwoRegion, out string playstationTwoDate))
|
|
{
|
|
// Ensure internal serial is pulled from local data
|
|
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationTwoSerial ?? string.Empty;
|
|
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion;
|
|
info.CommonDiscInfo.EXEDateBuildDate = playstationTwoDate;
|
|
}
|
|
|
|
info.VersionAndEditions.Version = GetPlayStation2Version(drive?.Letter) ?? "";
|
|
break;
|
|
|
|
case RedumpSystem.SonyPlayStation4:
|
|
info.VersionAndEditions.Version = GetPlayStation4Version(drive?.Letter) ?? "";
|
|
break;
|
|
|
|
case RedumpSystem.SonyPlayStation5:
|
|
info.VersionAndEditions.Version = GetPlayStation5Version(drive?.Letter) ?? "";
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override string GenerateParameters()
|
|
{
|
|
List<string> parameters = new List<string>();
|
|
|
|
if (BaseCommand == null)
|
|
BaseCommand = CommandStrings.NONE;
|
|
|
|
if (!string.IsNullOrWhiteSpace(BaseCommand))
|
|
parameters.Add(BaseCommand);
|
|
else
|
|
return null;
|
|
|
|
// Audio Silence Threshold
|
|
if (IsFlagSupported(FlagStrings.AudioSilenceThreshold))
|
|
{
|
|
if (this[FlagStrings.AudioSilenceThreshold] == true)
|
|
{
|
|
if (AudioSilenceThresholdValue != null && AudioSilenceThresholdValue >= 0)
|
|
parameters.Add($"{FlagStrings.AudioSilenceThreshold}={AudioSilenceThresholdValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// CD-i Correct Offset
|
|
if (IsFlagSupported(FlagStrings.CDiCorrectOffset))
|
|
{
|
|
if (this[FlagStrings.CDiCorrectOffset] == true)
|
|
parameters.Add(FlagStrings.CDiCorrectOffset);
|
|
}
|
|
|
|
// CD-i Ready Normalize
|
|
if (IsFlagSupported(FlagStrings.CDiReadyNormalize))
|
|
{
|
|
if (this[FlagStrings.CDiReadyNormalize] == true)
|
|
parameters.Add(FlagStrings.CDiReadyNormalize);
|
|
}
|
|
|
|
// Descramble New
|
|
if (IsFlagSupported(FlagStrings.DescrambleNew))
|
|
{
|
|
if (this[FlagStrings.DescrambleNew] == true)
|
|
parameters.Add(FlagStrings.DescrambleNew);
|
|
}
|
|
|
|
// Drive
|
|
if (IsFlagSupported(FlagStrings.Drive))
|
|
{
|
|
if (this[FlagStrings.Drive] == true)
|
|
{
|
|
if (DriveValue != null)
|
|
parameters.Add($"{FlagStrings.Drive}={DriveValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// ForceOffset
|
|
if (IsFlagSupported(FlagStrings.ForceOffset))
|
|
{
|
|
if (this[FlagStrings.ForceOffset] == true)
|
|
{
|
|
if (ForceOffsetValue != null)
|
|
parameters.Add($"{FlagStrings.ForceOffset}={ForceOffsetValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Force QTOC
|
|
if (IsFlagSupported(FlagStrings.ForceQTOC))
|
|
{
|
|
if (this[FlagStrings.ForceQTOC] == true)
|
|
parameters.Add(FlagStrings.ForceQTOC);
|
|
}
|
|
|
|
// Force Split
|
|
if (IsFlagSupported(FlagStrings.ForceSplit))
|
|
{
|
|
if (this[FlagStrings.ForceSplit] == true)
|
|
parameters.Add(FlagStrings.ForceSplit);
|
|
}
|
|
|
|
// Force TOC
|
|
if (IsFlagSupported(FlagStrings.ForceTOC))
|
|
{
|
|
if (this[FlagStrings.ForceTOC] == true)
|
|
parameters.Add(FlagStrings.ForceTOC);
|
|
}
|
|
|
|
// Help
|
|
if (IsFlagSupported(FlagStrings.HelpLong))
|
|
{
|
|
if (this[FlagStrings.HelpLong] == true)
|
|
parameters.Add(FlagStrings.HelpLong);
|
|
}
|
|
|
|
// ISO9660 Trim
|
|
if (IsFlagSupported(FlagStrings.ISO9660Trim))
|
|
{
|
|
if (this[FlagStrings.ISO9660Trim] == true)
|
|
parameters.Add(FlagStrings.ISO9660Trim);
|
|
}
|
|
|
|
// Image Name
|
|
if (IsFlagSupported(FlagStrings.ImageName))
|
|
{
|
|
if (this[FlagStrings.ImageName] == true)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(ImageNameValue))
|
|
parameters.Add($"{FlagStrings.ImageName}={ImageNameValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Image Path
|
|
if (IsFlagSupported(FlagStrings.ImagePath))
|
|
{
|
|
if (this[FlagStrings.ImagePath] == true)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(ImagePathValue))
|
|
parameters.Add($"{FlagStrings.ImagePath}={ImagePathValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Leave Unchanged
|
|
if (IsFlagSupported(FlagStrings.LeaveUnchanged))
|
|
{
|
|
if (this[FlagStrings.LeaveUnchanged] == true)
|
|
parameters.Add(FlagStrings.LeaveUnchanged);
|
|
}
|
|
|
|
// Overwrite
|
|
if (IsFlagSupported(FlagStrings.Overwrite))
|
|
{
|
|
if (this[FlagStrings.Overwrite] == true)
|
|
parameters.Add(FlagStrings.Overwrite);
|
|
}
|
|
|
|
// Refine Subchannel
|
|
if (IsFlagSupported(FlagStrings.RefineSubchannel))
|
|
{
|
|
if (this[FlagStrings.RefineSubchannel] == true)
|
|
parameters.Add(FlagStrings.RefineSubchannel);
|
|
}
|
|
|
|
// Retries
|
|
if (IsFlagSupported(FlagStrings.Retries))
|
|
{
|
|
if (this[FlagStrings.Retries] == true)
|
|
{
|
|
if (RetriesValue != null && RetriesValue >= 0)
|
|
parameters.Add($"{FlagStrings.Retries}={RetriesValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Ring Size
|
|
if (IsFlagSupported(FlagStrings.RingSize))
|
|
{
|
|
if (this[FlagStrings.RingSize] == true)
|
|
{
|
|
if (RingSizeValue != null && RingSizeValue >= 0)
|
|
parameters.Add($"{FlagStrings.RingSize}={RingSizeValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Skip
|
|
if (IsFlagSupported(FlagStrings.Skip))
|
|
{
|
|
if (this[FlagStrings.Skip] == true)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(SkipValue))
|
|
parameters.Add($"{FlagStrings.Skip}={SkipValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Skip Fill
|
|
if (IsFlagSupported(FlagStrings.SkipFill))
|
|
{
|
|
if (this[FlagStrings.SkipFill] == true)
|
|
{
|
|
if (SkipFillValue != null && SkipFillValue >= 0)
|
|
parameters.Add($"{FlagStrings.SkipFill}={SkipFillValue:x}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Skip Lead-In
|
|
if (IsFlagSupported(FlagStrings.SkipLeadIn))
|
|
{
|
|
if (this[FlagStrings.SkipLeadIn] == true)
|
|
parameters.Add(FlagStrings.SkipLeadIn);
|
|
}
|
|
|
|
// Skip Size
|
|
if (IsFlagSupported(FlagStrings.SkipSize))
|
|
{
|
|
if (this[FlagStrings.SkipSize] == true)
|
|
{
|
|
if (SkipSizeValue != null && SkipSizeValue >= 0)
|
|
parameters.Add($"{FlagStrings.SkipSize}={SkipSizeValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Speed
|
|
if (IsFlagSupported(FlagStrings.Speed))
|
|
{
|
|
if (this[FlagStrings.Speed] == true)
|
|
{
|
|
if (SpeedValue != null && SkipSizeValue >= 1)
|
|
parameters.Add($"{FlagStrings.Speed}={SpeedValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Stop LBA
|
|
if (IsFlagSupported(FlagStrings.StopLBA))
|
|
{
|
|
if (this[FlagStrings.StopLBA] == true)
|
|
{
|
|
if (StopLBAValue != null)
|
|
parameters.Add($"{FlagStrings.StopLBA}={StopLBAValue}");
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Unsupported
|
|
if (IsFlagSupported(FlagStrings.Unsupported))
|
|
{
|
|
if (this[FlagStrings.Unsupported] == true)
|
|
parameters.Add(FlagStrings.Unsupported);
|
|
}
|
|
|
|
// Verbose
|
|
if (IsFlagSupported(FlagStrings.Verbose))
|
|
{
|
|
if (this[FlagStrings.Verbose] == true)
|
|
parameters.Add(FlagStrings.Verbose);
|
|
}
|
|
|
|
return string.Join(" ", parameters);
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override Dictionary<string, List<string>> GetCommandSupport()
|
|
{
|
|
// TODO: Figure out actual support for each flag
|
|
return new Dictionary<string, List<string>>()
|
|
{
|
|
[CommandStrings.NONE] = new List<string>()
|
|
{
|
|
FlagStrings.HelpLong,
|
|
FlagStrings.HelpShort,
|
|
},
|
|
[CommandStrings.CD] = new List<string>()
|
|
{
|
|
FlagStrings.AudioSilenceThreshold,
|
|
FlagStrings.CDiCorrectOffset,
|
|
FlagStrings.CDiReadyNormalize,
|
|
FlagStrings.DescrambleNew,
|
|
FlagStrings.Drive,
|
|
FlagStrings.ForceOffset,
|
|
FlagStrings.ForceQTOC,
|
|
FlagStrings.ForceSplit,
|
|
FlagStrings.ForceTOC,
|
|
FlagStrings.ISO9660Trim,
|
|
FlagStrings.ImageName,
|
|
FlagStrings.ImagePath,
|
|
FlagStrings.LeaveUnchanged,
|
|
FlagStrings.Overwrite,
|
|
FlagStrings.RefineSubchannel,
|
|
FlagStrings.Retries,
|
|
FlagStrings.RingSize,
|
|
FlagStrings.Skip,
|
|
FlagStrings.SkipFill,
|
|
FlagStrings.SkipLeadIn,
|
|
FlagStrings.SkipSize,
|
|
FlagStrings.Speed,
|
|
FlagStrings.StopLBA,
|
|
FlagStrings.Unsupported,
|
|
FlagStrings.Verbose,
|
|
},
|
|
[CommandStrings.Dump] = new List<string>()
|
|
{
|
|
FlagStrings.AudioSilenceThreshold,
|
|
FlagStrings.CDiCorrectOffset,
|
|
FlagStrings.CDiReadyNormalize,
|
|
FlagStrings.DescrambleNew,
|
|
FlagStrings.Drive,
|
|
FlagStrings.ForceOffset,
|
|
FlagStrings.ForceQTOC,
|
|
FlagStrings.ForceSplit,
|
|
FlagStrings.ForceTOC,
|
|
FlagStrings.ISO9660Trim,
|
|
FlagStrings.ImageName,
|
|
FlagStrings.ImagePath,
|
|
FlagStrings.LeaveUnchanged,
|
|
FlagStrings.Overwrite,
|
|
FlagStrings.RefineSubchannel,
|
|
FlagStrings.Retries,
|
|
FlagStrings.RingSize,
|
|
FlagStrings.Skip,
|
|
FlagStrings.SkipFill,
|
|
FlagStrings.SkipLeadIn,
|
|
FlagStrings.SkipSize,
|
|
FlagStrings.Speed,
|
|
FlagStrings.StopLBA,
|
|
FlagStrings.Unsupported,
|
|
FlagStrings.Verbose,
|
|
},
|
|
[CommandStrings.Info] = new List<string>()
|
|
{
|
|
FlagStrings.AudioSilenceThreshold,
|
|
FlagStrings.CDiCorrectOffset,
|
|
FlagStrings.CDiReadyNormalize,
|
|
FlagStrings.DescrambleNew,
|
|
FlagStrings.Drive,
|
|
FlagStrings.ForceOffset,
|
|
FlagStrings.ForceQTOC,
|
|
FlagStrings.ForceSplit,
|
|
FlagStrings.ForceTOC,
|
|
FlagStrings.ISO9660Trim,
|
|
FlagStrings.ImageName,
|
|
FlagStrings.ImagePath,
|
|
FlagStrings.LeaveUnchanged,
|
|
FlagStrings.Overwrite,
|
|
FlagStrings.RefineSubchannel,
|
|
FlagStrings.Retries,
|
|
FlagStrings.RingSize,
|
|
FlagStrings.Skip,
|
|
FlagStrings.SkipFill,
|
|
FlagStrings.SkipLeadIn,
|
|
FlagStrings.SkipSize,
|
|
FlagStrings.Speed,
|
|
FlagStrings.StopLBA,
|
|
FlagStrings.Unsupported,
|
|
FlagStrings.Verbose,
|
|
},
|
|
[CommandStrings.Protection] = new List<string>()
|
|
{
|
|
FlagStrings.AudioSilenceThreshold,
|
|
FlagStrings.CDiCorrectOffset,
|
|
FlagStrings.CDiReadyNormalize,
|
|
FlagStrings.DescrambleNew,
|
|
FlagStrings.Drive,
|
|
FlagStrings.ForceOffset,
|
|
FlagStrings.ForceQTOC,
|
|
FlagStrings.ForceSplit,
|
|
FlagStrings.ForceTOC,
|
|
FlagStrings.ISO9660Trim,
|
|
FlagStrings.ImageName,
|
|
FlagStrings.ImagePath,
|
|
FlagStrings.LeaveUnchanged,
|
|
FlagStrings.Overwrite,
|
|
FlagStrings.RefineSubchannel,
|
|
FlagStrings.Retries,
|
|
FlagStrings.RingSize,
|
|
FlagStrings.Skip,
|
|
FlagStrings.SkipFill,
|
|
FlagStrings.SkipLeadIn,
|
|
FlagStrings.SkipSize,
|
|
FlagStrings.Speed,
|
|
FlagStrings.StopLBA,
|
|
FlagStrings.Unsupported,
|
|
FlagStrings.Verbose,
|
|
},
|
|
[CommandStrings.Refine] = new List<string>()
|
|
{
|
|
FlagStrings.AudioSilenceThreshold,
|
|
FlagStrings.CDiCorrectOffset,
|
|
FlagStrings.CDiReadyNormalize,
|
|
FlagStrings.DescrambleNew,
|
|
FlagStrings.Drive,
|
|
FlagStrings.ForceOffset,
|
|
FlagStrings.ForceQTOC,
|
|
FlagStrings.ForceSplit,
|
|
FlagStrings.ForceTOC,
|
|
FlagStrings.ISO9660Trim,
|
|
FlagStrings.ImageName,
|
|
FlagStrings.ImagePath,
|
|
FlagStrings.LeaveUnchanged,
|
|
FlagStrings.Overwrite,
|
|
FlagStrings.RefineSubchannel,
|
|
FlagStrings.Retries,
|
|
FlagStrings.RingSize,
|
|
FlagStrings.Skip,
|
|
FlagStrings.SkipFill,
|
|
FlagStrings.SkipLeadIn,
|
|
FlagStrings.SkipSize,
|
|
FlagStrings.Speed,
|
|
FlagStrings.StopLBA,
|
|
FlagStrings.Unsupported,
|
|
FlagStrings.Verbose,
|
|
},
|
|
[CommandStrings.Split] = new List<string>()
|
|
{
|
|
FlagStrings.AudioSilenceThreshold,
|
|
FlagStrings.CDiCorrectOffset,
|
|
FlagStrings.CDiReadyNormalize,
|
|
FlagStrings.DescrambleNew,
|
|
FlagStrings.Drive,
|
|
FlagStrings.ForceOffset,
|
|
FlagStrings.ForceQTOC,
|
|
FlagStrings.ForceSplit,
|
|
FlagStrings.ForceTOC,
|
|
FlagStrings.ISO9660Trim,
|
|
FlagStrings.ImageName,
|
|
FlagStrings.ImagePath,
|
|
FlagStrings.LeaveUnchanged,
|
|
FlagStrings.Overwrite,
|
|
FlagStrings.RefineSubchannel,
|
|
FlagStrings.Retries,
|
|
FlagStrings.RingSize,
|
|
FlagStrings.Skip,
|
|
FlagStrings.SkipFill,
|
|
FlagStrings.SkipLeadIn,
|
|
FlagStrings.SkipSize,
|
|
FlagStrings.Speed,
|
|
FlagStrings.StopLBA,
|
|
FlagStrings.Unsupported,
|
|
FlagStrings.Verbose,
|
|
},
|
|
};
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override string GetDefaultExtension(MediaType? mediaType) => Converters.Extension(mediaType);
|
|
|
|
/// <inheritdoc/>
|
|
public override List<string> GetLogFilePaths(string basePath)
|
|
{
|
|
List<string> logFiles = new List<string>();
|
|
|
|
// TODO: Determine output logfiles for Redumper
|
|
|
|
return logFiles;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override bool IsDumpingCommand()
|
|
{
|
|
switch (this.BaseCommand)
|
|
{
|
|
case CommandStrings.CD:
|
|
case CommandStrings.Dump:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
protected override void ResetValues()
|
|
{
|
|
BaseCommand = CommandStrings.NONE;
|
|
|
|
flags = new Dictionary<string, bool?>();
|
|
|
|
AudioSilenceThresholdValue = null;
|
|
DriveValue = null;
|
|
ForceOffsetValue = null;
|
|
ImageNameValue = null;
|
|
ImagePathValue = null;
|
|
RetriesValue = null;
|
|
RingSizeValue = null;
|
|
SkipValue = null;
|
|
SkipFillValue = null;
|
|
SkipSizeValue = null;
|
|
SpeedValue = null;
|
|
StopLBAValue = null;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
protected override void SetDefaultParameters(char driveLetter, string filename, int? driveSpeed, Options options)
|
|
{
|
|
// TODO: Fill out
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
protected override bool ValidateAndSetParameters(string parameters)
|
|
{
|
|
BaseCommand = CommandStrings.NONE;
|
|
|
|
// The string has to be valid by itself first
|
|
if (string.IsNullOrWhiteSpace(parameters))
|
|
return false;
|
|
|
|
// Now split the string into parts for easier validation
|
|
// https://stackoverflow.com/questions/14655023/split-a-string-that-has-white-spaces-unless-they-are-enclosed-within-quotes
|
|
parameters = parameters.Trim();
|
|
List<string> parts = Regex.Matches(parameters, @"[\""].+?[\""]|[^ ]+")
|
|
.Cast<Match>()
|
|
.Select(m => m.Value)
|
|
.ToList();
|
|
|
|
// Determine what the commandline should look like given the first item
|
|
BaseCommand = parts[0];
|
|
|
|
int index = 0;
|
|
switch (BaseCommand)
|
|
{
|
|
// These two are technically CommandStrings.NONE
|
|
case FlagStrings.HelpLong:
|
|
case FlagStrings.HelpShort:
|
|
|
|
// Normal commands
|
|
case CommandStrings.CD:
|
|
case CommandStrings.Dump:
|
|
case CommandStrings.Info:
|
|
case CommandStrings.Protection:
|
|
case CommandStrings.Refine:
|
|
case CommandStrings.Split:
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
// Loop through all auxiliary flags, if necessary
|
|
for (int i = index; i < parts.Count; i++)
|
|
{
|
|
// Flag read-out values
|
|
byte? byteValue = null;
|
|
int? intValue = null;
|
|
string stringValue = null;
|
|
|
|
// Audio Silence Threshold
|
|
intValue = ProcessInt32Parameter(parts, FlagStrings.AudioSilenceThreshold, ref i);
|
|
if (intValue != null)
|
|
{
|
|
if (intValue >= 0)
|
|
AudioSilenceThresholdValue = intValue;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
// CD-i Correct Offset
|
|
ProcessFlagParameter(parts, FlagStrings.CDiCorrectOffset, ref i);
|
|
|
|
// CD-i Ready Normalize
|
|
ProcessFlagParameter(parts, FlagStrings.CDiReadyNormalize, ref i);
|
|
|
|
// Descramble New
|
|
ProcessFlagParameter(parts, FlagStrings.DescrambleNew, ref i);
|
|
|
|
// Drive -- TODO: No drive is technically supported
|
|
stringValue = ProcessStringParameter(parts, FlagStrings.Drive, ref i);
|
|
if (!string.IsNullOrEmpty(stringValue))
|
|
DriveValue = stringValue;
|
|
|
|
// Force Offset
|
|
intValue = ProcessInt32Parameter(parts, FlagStrings.ForceOffset, ref i);
|
|
if (intValue != null)
|
|
ForceOffsetValue = intValue;
|
|
|
|
// Force QTOC
|
|
ProcessFlagParameter(parts, FlagStrings.ForceQTOC, ref i);
|
|
|
|
// Force Split
|
|
ProcessFlagParameter(parts, FlagStrings.ForceSplit, ref i);
|
|
|
|
// Force TOC
|
|
ProcessFlagParameter(parts, FlagStrings.ForceTOC, ref i);
|
|
|
|
// Help
|
|
ProcessFlagParameter(parts, FlagStrings.HelpShort, FlagStrings.HelpLong, ref i);
|
|
|
|
// ISO9660 Trim
|
|
ProcessFlagParameter(parts, FlagStrings.ISO9660Trim, ref i);
|
|
|
|
// Image Name -- TODO: Empty image name technically supported
|
|
stringValue = ProcessStringParameter(parts, FlagStrings.ImageName, ref i);
|
|
if (!string.IsNullOrEmpty(stringValue))
|
|
ImageNameValue = stringValue;
|
|
|
|
// Image Path -- TODO: Empty image path technically supported
|
|
stringValue = ProcessStringParameter(parts, FlagStrings.ImagePath, ref i);
|
|
if (!string.IsNullOrEmpty(stringValue))
|
|
ImagePathValue = stringValue;
|
|
|
|
// Leave Unchanged
|
|
ProcessFlagParameter(parts, FlagStrings.LeaveUnchanged, ref i);
|
|
|
|
// Overwrite
|
|
ProcessFlagParameter(parts, FlagStrings.Overwrite, ref i);
|
|
|
|
// Refine Subchannel
|
|
ProcessFlagParameter(parts, FlagStrings.RefineSubchannel, ref i);
|
|
|
|
// Retries
|
|
intValue = ProcessInt32Parameter(parts, FlagStrings.Retries, ref i);
|
|
if (intValue != null)
|
|
{
|
|
if (intValue >= 0)
|
|
RetriesValue = intValue;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
// Ring Size
|
|
intValue = ProcessInt32Parameter(parts, FlagStrings.RingSize, ref i);
|
|
if (intValue != null)
|
|
{
|
|
if (intValue >= 0)
|
|
RetriesValue = intValue;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
// Skip -- TODO: Validate how this value should look
|
|
stringValue = ProcessStringParameter(parts, FlagStrings.Skip, ref i);
|
|
if (!string.IsNullOrEmpty(stringValue))
|
|
SkipValue = stringValue;
|
|
|
|
// Skip Fill
|
|
byteValue = ProcessUInt8Parameter(parts, FlagStrings.RingSize, ref i);
|
|
if (byteValue != null)
|
|
SkipFillValue = byteValue;
|
|
|
|
// Skip Lead-In
|
|
ProcessFlagParameter(parts, FlagStrings.SkipLeadIn, ref i);
|
|
|
|
// Skip Size
|
|
intValue = ProcessInt32Parameter(parts, FlagStrings.SkipSize, ref i);
|
|
if (intValue != null)
|
|
{
|
|
if (intValue >= 0)
|
|
SkipSizeValue = intValue;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
// Speed
|
|
intValue = ProcessInt32Parameter(parts, FlagStrings.Speed, ref i);
|
|
if (intValue != null)
|
|
{
|
|
if (intValue >= 1)
|
|
Speed = intValue;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
// Stop LBA
|
|
intValue = ProcessInt32Parameter(parts, FlagStrings.StopLBA, ref i);
|
|
if (intValue != null)
|
|
StopLBAValue = intValue;
|
|
|
|
// Unsupported
|
|
ProcessFlagParameter(parts, FlagStrings.Unsupported, ref i);
|
|
|
|
// Verbose
|
|
ProcessFlagParameter(parts, FlagStrings.Verbose, ref i);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|