mirror of
https://github.com/SabreTools/MPF.git
synced 2026-07-02 17:24:48 +00:00
This builds heavily upon the work that Jack put into capturing and processing DIC outputs. For now, there are only matchers for DIC outputs. All other programs will still direct to the log window, but may not be processed as neatly
274 lines
11 KiB
C#
274 lines
11 KiB
C#
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using MPF.Data;
|
|
using MPF.Utilities;
|
|
|
|
namespace MPF.CleanRip
|
|
{
|
|
/// <summary>
|
|
/// Represents a generic set of CleanRip parameters
|
|
/// </summary>
|
|
public class Parameters : BaseParameters
|
|
{
|
|
/// <inheritdoc/>
|
|
public Parameters(string parameters)
|
|
: base(parameters)
|
|
{
|
|
this.InternalProgram = InternalProgram.CleanRip;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public Parameters(KnownSystem? system, MediaType? type, char driveLetter, string filename, int? driveSpeed, Options options)
|
|
: base(system, type, driveLetter, filename, driveSpeed, options)
|
|
{
|
|
this.InternalProgram = InternalProgram.CleanRip;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override (bool, List<string>) CheckAllOutputFilesExist(string basePath)
|
|
{
|
|
List<string> missingFiles = new List<string>();
|
|
switch (this.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.Add($"{basePath}-dumpinfo.txt");
|
|
if (!File.Exists($"{basePath}.bca"))
|
|
missingFiles.Add($"{basePath}.bca");
|
|
|
|
break;
|
|
|
|
default:
|
|
return (false, missingFiles);
|
|
}
|
|
|
|
return (!missingFiles.Any(), missingFiles);
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override void GenerateSubmissionInfo(SubmissionInfo info, string basePath, 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 (this.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 = GetBCA(basePath + ".bca");
|
|
|
|
if (GetGameCubeWiiInformation(basePath + "-dumpinfo.txt", out RedumpRegion? gcRegion, out string gcVersion))
|
|
{
|
|
info.CommonDiscInfo.Region = gcRegion ?? info.CommonDiscInfo.Region;
|
|
info.VersionAndEditions.Version = gcVersion ?? info.VersionAndEditions.Version;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// Fill in any artifacts that exist, Base64-encoded
|
|
if (File.Exists(basePath + ".bca"))
|
|
info.Artifacts["bca"] = GetBase64(GetFullFile(basePath + ".bca", binary: true));
|
|
if (File.Exists(basePath + "-dumpinfo.txt"))
|
|
info.Artifacts["dumpinfo"] = GetBase64(GetFullFile(basePath + "-dumpinfo.txt"));
|
|
}
|
|
|
|
#region Information Extraction Methods
|
|
|
|
/// <summary>
|
|
/// Get the hex contents of the BCA file
|
|
/// </summary>
|
|
/// <param name="bcaPath">Path to the BCA file associated with the dump</param>
|
|
/// <returns>BCA data as a hex string if possible, null on error</returns>
|
|
/// <remarks>https://stackoverflow.com/questions/9932096/add-separator-to-string-at-every-n-characters</remarks>
|
|
private static string GetBCA(string bcaPath)
|
|
{
|
|
// If the file doesn't exist, we can't get the info
|
|
if (!File.Exists(bcaPath))
|
|
return null;
|
|
|
|
try
|
|
{
|
|
string hex = GetFullFile(bcaPath, true);
|
|
return Regex.Replace(hex, ".{32}", "$0\n");
|
|
}
|
|
catch
|
|
{
|
|
// We don't care what the error was right now
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a formatted datfile from the cleanrip output, if possible
|
|
/// </summary>
|
|
/// <param name="iso">Path to ISO file</param>
|
|
/// <param name="dumpinfo">Path to discinfo file</param>
|
|
/// <returns></returns>
|
|
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 $"<rom name=\"{Path.GetFileName(iso)}\" size=\"{size}\" crc=\"{crc}\" md5=\"{md5}\" sha1=\"{sha1}\" />";
|
|
}
|
|
catch
|
|
{
|
|
// We don't care what the exception is right now
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the extracted GC and Wii version
|
|
/// </summary>
|
|
/// <param name="dumpinfo">Path to discinfo file</param>
|
|
/// <param name="region">Output region, if possible</param>
|
|
/// <param name="version">Output internal version of the game</param>
|
|
/// <returns></returns>
|
|
private static bool GetGameCubeWiiInformation(string dumpinfo, out RedumpRegion? 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 = RedumpRegion.World;
|
|
break;
|
|
case 'D':
|
|
region = RedumpRegion.Germany;
|
|
break;
|
|
case 'E':
|
|
region = RedumpRegion.USA;
|
|
break;
|
|
case 'F':
|
|
region = RedumpRegion.France;
|
|
break;
|
|
case 'I':
|
|
region = RedumpRegion.Italy;
|
|
break;
|
|
case 'J':
|
|
region = RedumpRegion.Japan;
|
|
break;
|
|
case 'K':
|
|
region = RedumpRegion.Korea;
|
|
break;
|
|
case 'L':
|
|
region = RedumpRegion.Europe; // Japanese import to Europe
|
|
break;
|
|
case 'M':
|
|
region = RedumpRegion.Europe; // American import to Europe
|
|
break;
|
|
case 'N':
|
|
region = RedumpRegion.USA; // Japanese import to USA
|
|
break;
|
|
case 'P':
|
|
region = RedumpRegion.Europe;
|
|
break;
|
|
case 'R':
|
|
region = RedumpRegion.Russia;
|
|
break;
|
|
case 'S':
|
|
region = RedumpRegion.Spain;
|
|
break;
|
|
case 'Q':
|
|
region = RedumpRegion.Korea; // Korea with Japanese language
|
|
break;
|
|
case 'T':
|
|
region = RedumpRegion.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
|
|
}
|
|
}
|