using System;
using System.IO;
using DICUI.Data;
using DICUI.Utilities;
using DICUI.Web;
namespace DICUI.CleanRip
{
///
/// Represents a generic set of CleanRip parameters
///
public class Parameters : BaseParameters
{
///
/// Populate a Parameters object from a param string
///
/// String possibly representing a set of parameters
public Parameters(string parameters)
: base(parameters)
{
this.InternalProgram = InternalProgram.CleanRip;
}
///
/// Generate parameters based on a set of known inputs
///
/// KnownSystem value to use
/// MediaType value to use
/// Drive letter to use
/// Filename to use
/// Drive speed to use
/// Enable paranoid mode (safer dumping)
/// Enable quiet mode (no beeps)
/// User-defined reread count
public Parameters(KnownSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, bool paranoid, bool quietMode, int retryCount)
: base(system, type, driveLetter, filename, driveSpeed, paranoid, quietMode, retryCount)
{
}
///
/// Blindly generate a parameter string based on the inputs
///
/// Correctly formatted parameter string, null on error
public override string GenerateParameters() => null;
///
/// Get the input path from the implementation
///
/// String representing the path, null on error
public override string InputPath() => null;
///
/// Get the output path from the implementation
///
/// String representing the path, null on error
public override string OutputPath() => null;
///
/// Get the processing speed from the implementation
///
/// int? representing the speed, null on error
public override int? GetSpeed() => null;
///
/// Set the processing speed int the implementation
///
/// int? representing the speed
public override void SetSpeed(int? speed) { }
///
/// Get the MediaType from the current set of parameters
///
/// MediaType value if successful, null on error
public override MediaType? GetMediaType() => null;
///
/// Gets if the current command is considered a dumping command or not
///
/// True if it's a dumping command, false otherwise
public override bool IsDumpingCommand() => true;
///
/// Reset all special variables to have default values
///
protected override void ResetValues() { }
///
/// Set default parameters for a given system and media type
///
/// KnownSystem value to use
/// MediaType value to use
/// Drive letter to use
/// Filename to use
/// Drive speed to use
/// Enable paranoid mode (safer dumping)
/// User-defined reread count
protected override void SetDefaultParameters(
KnownSystem? system,
MediaType? type,
char driveLetter,
string filename,
int? driveSpeed,
bool paranoid,
int retryCount)
{
}
///
/// Scan a possible parameter string and populate whatever possible
///
/// String possibly representing parameters
///
protected override bool ValidateAndSetParameters(string parameters) => true;
///
/// Validate if all required output files exist
///
/// Base filename and path to use for checking
/// KnownSystem type representing the media
/// MediaType type representing the media
/// Optional result progress callback
///
public override bool CheckAllOutputFilesExist(string basePath, KnownSystem? system, MediaType? type, IProgress progress = null)
{
string missingFiles = string.Empty;
switch (type)
{
case MediaType.DVD: // Only added here to help users; not strictly correct
case MediaType.NintendoGameCubeGameDisc:
case MediaType.NintendoWiiOpticalDisc:
if (!File.Exists($"{basePath}-dumpinfo.txt"))
missingFiles += $";{basePath}-dumpinfo.txt";
if (!File.Exists($"{basePath}.bca"))
missingFiles += $";{basePath}.bca";
break;
default:
return false;
}
// Use the missing files list as an indicator
if (string.IsNullOrEmpty(missingFiles))
{
return true;
}
else
{
progress?.Report(Result.Failure($"The following files were missing: {missingFiles.TrimStart(';')}"));
return false;
}
}
///
/// Generate a SubmissionInfo for the output files
///
/// Base submission info to fill in specifics for
/// Base filename and path to use for checking
/// KnownSystem type representing the media
/// MediaType type representing the media
/// Drive representing the disc to get information from
///
public override void GenerateSubmissionInfo(SubmissionInfo info, string basePath, KnownSystem? system, MediaType? type, Drive drive)
{
info.TracksAndWriteOffsets.ClrMameProData = GetCleanripDatfile(basePath + ".iso", basePath + "-dumpinfo.txt");
// Get the individual hash data, as per internal
if (GetISOHashValues(info.TracksAndWriteOffsets.ClrMameProData, out long size, out string crc32, out string md5, out string sha1))
{
info.SizeAndChecksums.Size = size;
info.SizeAndChecksums.CRC32 = crc32;
info.SizeAndChecksums.MD5 = md5;
info.SizeAndChecksums.SHA1 = sha1;
// Dual-layer discs have the same size and layerbreak
if (size == 8511160320)
info.SizeAndChecksums.Layerbreak = 2084960;
}
// Extract info based generically on MediaType
switch (type)
{
case MediaType.DVD: // Only added here to help users; not strictly correct
case MediaType.NintendoGameCubeGameDisc:
case MediaType.NintendoWiiOpticalDisc:
if (File.Exists(basePath + ".bca"))
info.Extras.BCA = GetFullFile(basePath + ".bca", true);
if (GetGameCubeWiiInformation(basePath + "-dumpinfo.txt", out Region? gcRegion, out string gcVersion))
{
info.CommonDiscInfo.Region = gcRegion ?? info.CommonDiscInfo.Region;
info.VersionAndEditions.Version = gcVersion ?? info.VersionAndEditions.Version;
}
break;
}
}
#region Information Extraction Methods
///
/// Get a formatted datfile from the cleanrip output, if possible
///
/// Path to ISO file
/// Path to discinfo file
///
private static string GetCleanripDatfile(string iso, string dumpinfo)
{
// If the file doesn't exist, we can't get info from it
if (!File.Exists(dumpinfo))
return null;
using (StreamReader sr = File.OpenText(dumpinfo))
{
long size = new FileInfo(iso).Length;
string crc = string.Empty;
string md5 = string.Empty;
string sha1 = string.Empty;
try
{
// Make sure this file is a dumpinfo
if (!sr.ReadLine().Contains("--File Generated by CleanRip"))
return null;
// Read all lines and gather dat information
while (!sr.EndOfStream)
{
string line = sr.ReadLine().Trim();
if (line.StartsWith("CRC32"))
crc = line.Substring(7).ToLowerInvariant();
else if (line.StartsWith("MD5"))
md5 = line.Substring(5);
else if (line.StartsWith("SHA-1"))
sha1 = line.Substring(7);
}
return $"";
}
catch
{
// We don't care what the exception is right now
return null;
}
}
}
///
/// Get the extracted GC and Wii version
///
/// Path to discinfo file
/// Output region, if possible
/// Output internal version of the game
///
private static bool GetGameCubeWiiInformation(string dumpinfo, out Region? region, out string version)
{
region = null; version = null;
// If the file doesn't exist, we can't get info from it
if (!File.Exists(dumpinfo))
return false;
using (StreamReader sr = File.OpenText(dumpinfo))
{
try
{
// Make sure this file is a dumpinfo
if (!sr.ReadLine().Contains("--File Generated by CleanRip"))
return false;
// Read all lines and gather dat information
while (!sr.EndOfStream)
{
string line = sr.ReadLine().Trim();
if (line.StartsWith("Version"))
{
version = line.Substring(9);
}
else if (line.StartsWith("Filename"))
{
string serial = line.Substring(10);
// char gameType = serial[0];
// string gameid = serial[1] + serial[2];
// string version = serial[4] + serial[5]
switch (serial[3])
{
case 'A':
region = Region.World;
break;
case 'D':
region = Region.Germany;
break;
case 'E':
region = Region.USA;
break;
case 'F':
region = Region.France;
break;
case 'I':
region = Region.Italy;
break;
case 'J':
region = Region.Japan;
break;
case 'K':
region = Region.Korea;
break;
case 'L':
region = Region.Europe; // Japanese import to Europe
break;
case 'M':
region = Region.Europe; // American import to Europe
break;
case 'N':
region = Region.USA; // Japanese import to USA
break;
case 'P':
region = Region.Europe;
break;
case 'R':
region = Region.Russia;
break;
case 'S':
region = Region.Spain;
break;
case 'Q':
region = Region.Korea; // Korea with Japanese language
break;
case 'T':
region = Region.Korea; // Korea with English language
break;
case 'X':
region = null; // Not a real region code
break;
}
}
}
return true;
}
catch
{
// We don't care what the exception is right now
return false;
}
}
}
#endregion
}
}