mirror of
https://github.com/SabreTools/MPF.git
synced 2026-07-02 17:24:48 +00:00
Allow nullability for modern .NET
This commit is contained in:
@@ -22,6 +22,8 @@
|
||||
- Be smarter about media type based on system
|
||||
- Consolidate into MPF.Core
|
||||
- Fix failing tests
|
||||
- Remove debug symbols in release builds (Deterous)
|
||||
- Allow nullability for modern .NET
|
||||
|
||||
### 2.6.6 (2023-10-04)
|
||||
|
||||
|
||||
@@ -38,7 +38,11 @@ namespace MPF.Core.Converters
|
||||
/// <summary>
|
||||
/// Long name method cache
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static readonly ConcurrentDictionary<Type, MethodInfo> LongNameMethods = new ConcurrentDictionary<Type, MethodInfo>();
|
||||
#else
|
||||
private static readonly ConcurrentDictionary<Type, MethodInfo?> LongNameMethods = new ConcurrentDictionary<Type, MethodInfo?>();
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation of a generic enumerable value
|
||||
@@ -49,12 +53,12 @@ namespace MPF.Core.Converters
|
||||
{
|
||||
try
|
||||
{
|
||||
var sourceType = value?.GetType();
|
||||
var sourceType = value.GetType();
|
||||
sourceType = Nullable.GetUnderlyingType(sourceType) ?? sourceType;
|
||||
|
||||
if (!LongNameMethods.TryGetValue(sourceType, out MethodInfo method))
|
||||
if (!LongNameMethods.TryGetValue(sourceType, out var method))
|
||||
{
|
||||
method = typeof(SabreTools.RedumpLib.Data.Extensions).GetMethod("LongName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) });
|
||||
method = typeof(Extensions).GetMethod("LongName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) });
|
||||
if (method == null)
|
||||
method = typeof(EnumConverter).GetMethod("LongName", new[] { typeof(Nullable<>).MakeGenericType(sourceType) });
|
||||
|
||||
@@ -62,7 +66,7 @@ namespace MPF.Core.Converters
|
||||
}
|
||||
|
||||
if (method != null)
|
||||
return method.Invoke(null, new[] { value }) as string;
|
||||
return method.Invoke(null, new[] { value }) as string ?? string.Empty;
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
@@ -112,7 +116,7 @@ namespace MPF.Core.Converters
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Convert From String
|
||||
|
||||
@@ -121,9 +125,13 @@ namespace MPF.Core.Converters
|
||||
/// </summary>
|
||||
/// <param name="internalProgram">String value to convert</param>
|
||||
/// <returns>InternalProgram represented by the string, if possible</returns>
|
||||
#if NET48
|
||||
public static InternalProgram ToInternalProgram(string internalProgram)
|
||||
#else
|
||||
public static InternalProgram ToInternalProgram(string? internalProgram)
|
||||
#endif
|
||||
{
|
||||
switch (internalProgram.ToLowerInvariant())
|
||||
switch (internalProgram?.ToLowerInvariant())
|
||||
{
|
||||
// Dumping support
|
||||
case "aaru":
|
||||
|
||||
@@ -29,12 +29,20 @@ namespace MPF.Core.Data
|
||||
/// <summary>
|
||||
/// Drive partition format
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string DriveFormat { get; private set; } = null;
|
||||
#else
|
||||
public string? DriveFormat { get; private set; } = null;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Windows drive path
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string Name { get; private set; } = null;
|
||||
#else
|
||||
public string? Name { get; private set; } = null;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Represents if Windows has marked the drive as active
|
||||
@@ -50,7 +58,11 @@ namespace MPF.Core.Data
|
||||
/// Media label as read by Windows
|
||||
/// </summary>
|
||||
/// <remarks>The try/catch is needed because Windows will throw an exception if the drive is not marked as active</remarks>
|
||||
#if NET48
|
||||
public string VolumeLabel { get; private set; } = null;
|
||||
#else
|
||||
public string? VolumeLabel { get; private set; } = null;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -59,7 +71,11 @@ namespace MPF.Core.Data
|
||||
/// <summary>
|
||||
/// Media label as read by Windows, formatted to avoid odd outputs
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string FormattedVolumeLabel
|
||||
#else
|
||||
public string? FormattedVolumeLabel
|
||||
#endif
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -96,7 +112,11 @@ namespace MPF.Core.Data
|
||||
/// </summary>
|
||||
/// <param name="driveType">InternalDriveType value representing the drive type</param>
|
||||
/// <param name="devicePath">Path to the device according to the local machine</param>
|
||||
#if NET48
|
||||
public static Drive Create(InternalDriveType? driveType, string devicePath)
|
||||
#else
|
||||
public static Drive? Create(InternalDriveType? driveType, string devicePath)
|
||||
#endif
|
||||
{
|
||||
// Create a new, empty drive object
|
||||
var drive = new Drive()
|
||||
@@ -131,7 +151,11 @@ namespace MPF.Core.Data
|
||||
/// Populate all fields from a DriveInfo object
|
||||
/// </summary>
|
||||
/// <param name="driveInfo">DriveInfo object to populate from</param>
|
||||
#if NET48
|
||||
private void PopulateFromDriveInfo(DriveInfo driveInfo)
|
||||
#else
|
||||
private void PopulateFromDriveInfo(DriveInfo? driveInfo)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid DriveInfo, just return
|
||||
if (driveInfo == null || driveInfo == default)
|
||||
@@ -161,10 +185,14 @@ namespace MPF.Core.Data
|
||||
/// </summary>
|
||||
/// <param name="ignoreFixedDrives">True to ignore fixed drives from population, false otherwise</param>
|
||||
/// <returns>Active drives, matched to labels, if possible</returns>
|
||||
#if NET48
|
||||
public static List<Drive> CreateListOfDrives(bool ignoreFixedDrives)
|
||||
#else
|
||||
public static List<Drive?> CreateListOfDrives(bool ignoreFixedDrives)
|
||||
#endif
|
||||
{
|
||||
var drives = GetDriveList(ignoreFixedDrives);
|
||||
drives = drives?.OrderBy(i => i.Letter)?.ToList();
|
||||
drives = drives.OrderBy(i => i == null ? '\0' : i.Letter).ToList();
|
||||
return drives;
|
||||
}
|
||||
|
||||
@@ -173,7 +201,11 @@ namespace MPF.Core.Data
|
||||
/// </summary>
|
||||
/// <param name="system"></param>
|
||||
/// <returns></returns>
|
||||
#if NET48
|
||||
public (MediaType?, string) GetMediaType(RedumpSystem? system)
|
||||
#else
|
||||
public (MediaType?, string?) GetMediaType(RedumpSystem? system)
|
||||
#endif
|
||||
{
|
||||
// Take care of the non-optical stuff first
|
||||
switch (this.InternalDriveType)
|
||||
@@ -336,7 +368,7 @@ namespace MPF.Core.Data
|
||||
// Sega Saturn
|
||||
try
|
||||
{
|
||||
byte[] sector = ReadSector(0);
|
||||
var sector = ReadSector(0);
|
||||
if (sector != null)
|
||||
{
|
||||
if (sector.StartsWith(Interface.SaturnSectorZeroStart))
|
||||
@@ -520,7 +552,11 @@ namespace MPF.Core.Data
|
||||
/// <param name="num">Sector number, non-negative</param>
|
||||
/// <param name="size">Size of a sector in bytes</param>
|
||||
/// <returns>Byte array representing the sector, null on error</returns>
|
||||
#if NET48
|
||||
public byte[] ReadSector(long num, int size = 2048)
|
||||
#else
|
||||
public byte[]? ReadSector(long num, int size = 2048)
|
||||
#endif
|
||||
{
|
||||
// Missing drive leter is not supported
|
||||
if (string.IsNullOrEmpty(this.Name))
|
||||
@@ -531,7 +567,11 @@ namespace MPF.Core.Data
|
||||
return null;
|
||||
|
||||
// Wrap the following in case of device access errors
|
||||
#if NET48
|
||||
Stream fs = null;
|
||||
#else
|
||||
Stream? fs = null;
|
||||
#endif
|
||||
try
|
||||
{
|
||||
// Open the drive as a device
|
||||
@@ -578,7 +618,11 @@ namespace MPF.Core.Data
|
||||
/// https://stackoverflow.com/questions/3060796/how-to-distinguish-between-usb-and-floppy-devices?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
|
||||
/// https://msdn.microsoft.com/en-us/library/aa394173(v=vs.85).aspx
|
||||
/// </remarks>
|
||||
#if NET48
|
||||
private static List<Drive> GetDriveList(bool ignoreFixedDrives)
|
||||
#else
|
||||
private static List<Drive?> GetDriveList(bool ignoreFixedDrives)
|
||||
#endif
|
||||
{
|
||||
var desiredDriveTypes = new List<DriveType>() { DriveType.CDRom };
|
||||
if (!ignoreFixedDrives)
|
||||
@@ -591,7 +635,11 @@ namespace MPF.Core.Data
|
||||
// https://github.com/aaru-dps/Aaru/blob/5164a154e2145941472f2ee0aeb2eff3338ecbb3/Aaru.Devices/Windows/ListDevices.cs#L66
|
||||
|
||||
// Create an output drive list
|
||||
#if NET48
|
||||
var drives = new List<Drive>();
|
||||
#else
|
||||
var drives = new List<Drive?>();
|
||||
#endif
|
||||
|
||||
// Get all standard supported drive types
|
||||
try
|
||||
@@ -618,8 +666,8 @@ namespace MPF.Core.Data
|
||||
uint? mediaType = properties["MediaType"]?.Value as uint?;
|
||||
if (mediaType != null && ((mediaType > 0 && mediaType < 11) || (mediaType > 12 && mediaType < 22)))
|
||||
{
|
||||
char devId = (properties["Caption"].Value as string)[0];
|
||||
drives.ForEach(d => { if (d.Letter == devId) { d.InternalDriveType = Data.InternalDriveType.Floppy; } });
|
||||
char devId = (properties["Caption"].Value as string ?? string.Empty)[0];
|
||||
drives.ForEach(d => { if (d?.Letter == devId) { d.InternalDriveType = Data.InternalDriveType.Floppy; } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace MPF.Core.Data
|
||||
if (_keyValuePairs.ContainsKey(key))
|
||||
return _keyValuePairs[key];
|
||||
|
||||
return null;
|
||||
return string.Empty;
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -104,10 +104,16 @@ namespace MPF.Core.Data
|
||||
string section = string.Empty;
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine().Trim();
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
|
||||
// Empty lines are skipped
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
// No-op, we don't process empty lines
|
||||
}
|
||||
|
||||
// Comments start with ';'
|
||||
if (line.StartsWith(";"))
|
||||
else if (line.StartsWith(";"))
|
||||
{
|
||||
// No-op, we don't process comments
|
||||
}
|
||||
@@ -245,7 +251,9 @@ namespace MPF.Core.Data
|
||||
|
||||
public bool TryGetValue(string key, out string value)
|
||||
{
|
||||
return ((IDictionary<string, string>)_keyValuePairs).TryGetValue(key.ToLowerInvariant(), out value);
|
||||
bool result = ((IDictionary<string, string>)_keyValuePairs).TryGetValue(key.ToLowerInvariant(), out var temp);
|
||||
value = temp ?? string.Empty;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, string> item)
|
||||
|
||||
@@ -1,24 +1,34 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using MPF.Core.Converters;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core.Data
|
||||
{
|
||||
public class Options : IDictionary<string, string>
|
||||
#if NET48
|
||||
public class Options
|
||||
#else
|
||||
public class Options
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// All settings in the form of a dictionary
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public Dictionary<string, string> Settings { get; private set; }
|
||||
#else
|
||||
public Dictionary<string, string?> Settings { get; private set; }
|
||||
#endif
|
||||
|
||||
#region Internal Program
|
||||
|
||||
/// <summary>
|
||||
/// Path to Aaru
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string AaruPath
|
||||
#else
|
||||
public string? AaruPath
|
||||
#endif
|
||||
{
|
||||
get { return GetStringSetting(Settings, "AaruPath", "Programs\\Aaru\\Aaru.exe"); }
|
||||
set { Settings["AaruPath"] = value; }
|
||||
@@ -27,7 +37,11 @@ namespace MPF.Core.Data
|
||||
/// <summary>
|
||||
/// Path to DiscImageCreator
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string DiscImageCreatorPath
|
||||
#else
|
||||
public string? DiscImageCreatorPath
|
||||
#endif
|
||||
{
|
||||
get { return GetStringSetting(Settings, "DiscImageCreatorPath", "Programs\\Creator\\DiscImageCreator.exe"); }
|
||||
set { Settings["DiscImageCreatorPath"] = value; }
|
||||
@@ -36,7 +50,11 @@ namespace MPF.Core.Data
|
||||
/// <summary>
|
||||
/// Path to Redumper
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string RedumperPath
|
||||
#else
|
||||
public string? RedumperPath
|
||||
#endif
|
||||
{
|
||||
get { return GetStringSetting(Settings, "RedumperPath", "Programs\\Redumper\\redumper.exe"); }
|
||||
set { Settings["RedumperPath"] = value; }
|
||||
@@ -49,7 +67,7 @@ namespace MPF.Core.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
string valueString = GetStringSetting(Settings, "InternalProgram", InternalProgram.DiscImageCreator.ToString());
|
||||
var valueString = GetStringSetting(Settings, "InternalProgram", InternalProgram.DiscImageCreator.ToString());
|
||||
var valueEnum = EnumConverter.ToInternalProgram(valueString);
|
||||
return valueEnum == InternalProgram.NONE ? InternalProgram.DiscImageCreator : valueEnum;
|
||||
}
|
||||
@@ -93,7 +111,11 @@ namespace MPF.Core.Data
|
||||
/// <summary>
|
||||
/// Default output path for dumps
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string DefaultOutputPath
|
||||
#else
|
||||
public string? DefaultOutputPath
|
||||
#endif
|
||||
{
|
||||
get { return GetStringSetting(Settings, "DefaultOutputPath", "ISO"); }
|
||||
set { Settings["DefaultOutputPath"] = value; }
|
||||
@@ -106,8 +128,8 @@ namespace MPF.Core.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
string valueString = GetStringSetting(Settings, "DefaultSystem", null);
|
||||
var valueEnum = Extensions.ToRedumpSystem(valueString);
|
||||
var valueString = GetStringSetting(Settings, "DefaultSystem", null);
|
||||
var valueEnum = Extensions.ToRedumpSystem(valueString ?? string.Empty);
|
||||
return valueEnum;
|
||||
}
|
||||
set
|
||||
@@ -536,16 +558,27 @@ namespace MPF.Core.Data
|
||||
|
||||
#region Redump Login Information
|
||||
|
||||
#if NET48
|
||||
public string RedumpUsername
|
||||
#else
|
||||
public string? RedumpUsername
|
||||
#endif
|
||||
{
|
||||
get { return GetStringSetting(Settings, "RedumpUsername", ""); }
|
||||
set { Settings["RedumpUsername"] = value; }
|
||||
}
|
||||
|
||||
// TODO: Figure out a way to keep this encrypted in some way, BASE64 to start?
|
||||
#if NET48
|
||||
public string RedumpPassword
|
||||
#else
|
||||
public string? RedumpPassword
|
||||
#endif
|
||||
{
|
||||
get { return GetStringSetting(Settings, "RedumpPassword", ""); }
|
||||
get
|
||||
{
|
||||
return GetStringSetting(Settings, "RedumpPassword", "");
|
||||
}
|
||||
set { Settings["RedumpPassword"] = value; }
|
||||
}
|
||||
|
||||
@@ -560,9 +593,17 @@ namespace MPF.Core.Data
|
||||
/// Constructor taking a dictionary for settings
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
#if NET48
|
||||
public Options(Dictionary<string, string> settings = null)
|
||||
#else
|
||||
public Options(Dictionary<string, string?>? settings = null)
|
||||
#endif
|
||||
{
|
||||
#if NET48
|
||||
this.Settings = settings ?? new Dictionary<string, string>();
|
||||
#else
|
||||
this.Settings = settings ?? new Dictionary<string, string?>();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -571,7 +612,24 @@ namespace MPF.Core.Data
|
||||
/// <param name="source"></param>
|
||||
public Options(Options source)
|
||||
{
|
||||
#if NET48
|
||||
Settings = new Dictionary<string, string>(source.Settings);
|
||||
#else
|
||||
Settings = new Dictionary<string, string?>(source.Settings);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accessor for the internal dictionary
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string this[string key]
|
||||
#else
|
||||
public string? this[string key]
|
||||
#endif
|
||||
{
|
||||
get => this.Settings[key];
|
||||
set => this.Settings[key] = value;
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
@@ -583,11 +641,15 @@ namespace MPF.Core.Data
|
||||
/// <param name="key">Setting key to get a value for</param>
|
||||
/// <param name="defaultValue">Default value to return if no value is found</param>
|
||||
/// <returns>Setting value if possible, default value otherwise</returns>
|
||||
#if NET48
|
||||
private bool GetBooleanSetting(Dictionary<string, string> settings, string key, bool defaultValue)
|
||||
#else
|
||||
private bool GetBooleanSetting(Dictionary<string, string?> settings, string key, bool defaultValue)
|
||||
#endif
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
{
|
||||
if (Boolean.TryParse(settings[key], out bool value))
|
||||
if (bool.TryParse(settings[key], out bool value))
|
||||
return value;
|
||||
else
|
||||
return defaultValue;
|
||||
@@ -605,11 +667,15 @@ namespace MPF.Core.Data
|
||||
/// <param name="key">Setting key to get a value for</param>
|
||||
/// <param name="defaultValue">Default value to return if no value is found</param>
|
||||
/// <returns>Setting value if possible, default value otherwise</returns>
|
||||
#if NET48
|
||||
private int GetInt32Setting(Dictionary<string, string> settings, string key, int defaultValue)
|
||||
#else
|
||||
private int GetInt32Setting(Dictionary<string, string?> settings, string key, int defaultValue)
|
||||
#endif
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
{
|
||||
if (Int32.TryParse(settings[key], out int value))
|
||||
if (int.TryParse(settings[key], out int value))
|
||||
return value;
|
||||
else
|
||||
return defaultValue;
|
||||
@@ -627,7 +693,11 @@ namespace MPF.Core.Data
|
||||
/// <param name="key">Setting key to get a value for</param>
|
||||
/// <param name="defaultValue">Default value to return if no value is found</param>
|
||||
/// <returns>Setting value if possible, default value otherwise</returns>
|
||||
#if NET48
|
||||
private string GetStringSetting(Dictionary<string, string> settings, string key, string defaultValue)
|
||||
#else
|
||||
private string? GetStringSetting(Dictionary<string, string?> settings, string key, string? defaultValue)
|
||||
#endif
|
||||
{
|
||||
if (settings.ContainsKey(key))
|
||||
return settings[key];
|
||||
@@ -636,45 +706,5 @@ namespace MPF.Core.Data
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDictionary implementations
|
||||
|
||||
public ICollection<string> Keys => Settings.Keys;
|
||||
|
||||
public ICollection<string> Values => Settings.Values;
|
||||
|
||||
public int Count => Settings.Count;
|
||||
|
||||
public bool IsReadOnly => ((IDictionary<string, string>)Settings).IsReadOnly;
|
||||
|
||||
public string this[string key]
|
||||
{
|
||||
get { return (Settings.ContainsKey(key) ? Settings[key] : null); }
|
||||
set { Settings[key] = value; }
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key) => Settings.ContainsKey(key);
|
||||
|
||||
public void Add(string key, string value) => Settings.Add(key, value);
|
||||
|
||||
public bool Remove(string key) => Settings.Remove(key);
|
||||
|
||||
public bool TryGetValue(string key, out string value) => Settings.TryGetValue(key, out value);
|
||||
|
||||
public void Add(KeyValuePair<string, string> item) => Settings.Add(item.Key, item.Value);
|
||||
|
||||
public void Clear() => Settings.Clear();
|
||||
|
||||
public bool Contains(KeyValuePair<string, string> item) => ((IDictionary<string, string>)Settings).Contains(item);
|
||||
|
||||
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex) => ((IDictionary<string, string>)Settings).CopyTo(array, arrayIndex);
|
||||
|
||||
public bool Remove(KeyValuePair<string, string> item) => ((IDictionary<string, string>)Settings).Remove(item);
|
||||
|
||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator() => Settings.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => Settings.GetEnumerator();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace MPF.Core.Data
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
// Only accept new data when not cancelled
|
||||
if (!this.TokenSource.IsCancellationRequested)
|
||||
if (item != null && !this.TokenSource.IsCancellationRequested)
|
||||
this.InternalQueue.Enqueue(item);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace MPF.Core.Data
|
||||
}
|
||||
|
||||
// Get the next item from the queue
|
||||
if (!this.InternalQueue.TryDequeue(out T nextItem))
|
||||
if (!this.InternalQueue.TryDequeue(out var nextItem))
|
||||
continue;
|
||||
|
||||
// Invoke the lambda, if possible
|
||||
|
||||
@@ -30,7 +30,11 @@
|
||||
/// Create a success result with a custom message
|
||||
/// </summary>
|
||||
/// <param name="message">String to add as a message</param>
|
||||
#if NET48
|
||||
public static Result Success(string message) => new Result(true, message);
|
||||
#else
|
||||
public static Result Success(string? message) => new Result(true, message ?? string.Empty);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Create a default failure result with no message
|
||||
@@ -42,7 +46,11 @@
|
||||
/// Create a failure result with a custom message
|
||||
/// </summary>
|
||||
/// <param name="message">String to add as a message</param>
|
||||
#if NET48
|
||||
public static Result Failure(string message) => new Result(false, message);
|
||||
#else
|
||||
public static Result Failure(string? message) => new Result(false, message ?? string.Empty);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Results can be compared to boolean values based on the success value
|
||||
|
||||
@@ -17,17 +17,29 @@ namespace MPF.Core.Data
|
||||
/// <summary>
|
||||
/// Raw XMID/XeMID string that all other information is derived from
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string RawXMID { get; private set; }
|
||||
#else
|
||||
public string? RawXMID { get; private set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// XGD1 XMID
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public SabreTools.Models.Xbox.XMID XMID { get; private set; }
|
||||
#else
|
||||
public SabreTools.Models.Xbox.XMID? XMID { get; private set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// XGD2/3 XeMID
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public SabreTools.Models.Xbox.XeMID XeMID { get; private set; }
|
||||
#else
|
||||
public SabreTools.Models.Xbox.XeMID? XeMID { get; private set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -58,7 +70,11 @@ namespace MPF.Core.Data
|
||||
/// Get the human-readable serial string
|
||||
/// </summary>
|
||||
/// <returns>Formatted serial string, null on error</returns>
|
||||
#if NET48
|
||||
public string GetSerial()
|
||||
#else
|
||||
public string? GetSerial()
|
||||
#endif
|
||||
{
|
||||
if (!this.Initialized)
|
||||
return null;
|
||||
@@ -86,7 +102,11 @@ namespace MPF.Core.Data
|
||||
/// </summary>
|
||||
/// <returns>Formatted version string, null on error</returns>
|
||||
/// <remarks>This may differ for XGD2/3 in the future</remarks>
|
||||
#if NET48
|
||||
public string GetVersion()
|
||||
#else
|
||||
public string? GetVersion()
|
||||
#endif
|
||||
{
|
||||
if (!this.Initialized)
|
||||
return null;
|
||||
@@ -160,7 +180,7 @@ namespace MPF.Core.Data
|
||||
/// </summary>
|
||||
/// <param name="region">Character denoting the region</param>
|
||||
/// <returns>Region, if possible</returns>
|
||||
public static Region? GetRegion(char region)
|
||||
public static Region? GetRegion(char? region)
|
||||
{
|
||||
switch (region)
|
||||
{
|
||||
|
||||
@@ -51,36 +51,52 @@ namespace MPF.Core
|
||||
/// <summary>
|
||||
/// Options object representing user-defined options
|
||||
/// </summary>
|
||||
public Core.Data.Options Options { get; private set; }
|
||||
public Data.Options Options { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parameters object representing what to send to the internal program
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public BaseParameters Parameters { get; private set; }
|
||||
#else
|
||||
public BaseParameters? Parameters { get; private set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Generic way of reporting a message
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public EventHandler<string> ReportStatus;
|
||||
#else
|
||||
public EventHandler<string>? ReportStatus;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Queue of items that need to be logged
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private ProcessingQueue<string> outputQueue;
|
||||
#else
|
||||
private ProcessingQueue<string>? outputQueue;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Event handler for data returned from a process
|
||||
/// </summary>
|
||||
private void OutputToLog(object proc, string args) => outputQueue.Enqueue(args);
|
||||
#if NET48
|
||||
private void OutputToLog(object proc, string args) => outputQueue?.Enqueue(args);
|
||||
#else
|
||||
private void OutputToLog(object? proc, string args) => outputQueue?.Enqueue(args);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Process the outputs in the queue
|
||||
/// </summary>
|
||||
private void ProcessOutputs(string nextOutput) => ReportStatus.Invoke(this, nextOutput);
|
||||
private void ProcessOutputs(string nextOutput) => ReportStatus?.Invoke(this, nextOutput);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -94,7 +110,7 @@ namespace MPF.Core
|
||||
/// <param name="type"></param>
|
||||
/// <param name="internalProgram"></param>
|
||||
/// <param name="parameters"></param>
|
||||
public DumpEnvironment(Core.Data.Options options,
|
||||
public DumpEnvironment(Data.Options options,
|
||||
string outputPath,
|
||||
Drive drive,
|
||||
RedumpSystem? system,
|
||||
@@ -113,7 +129,7 @@ namespace MPF.Core
|
||||
this.System = system ?? options.DefaultSystem;
|
||||
this.Type = type ?? MediaType.NONE;
|
||||
this.InternalProgram = internalProgram ?? options.InternalProgram;
|
||||
|
||||
|
||||
// Dumping program
|
||||
SetParameters(parameters);
|
||||
}
|
||||
@@ -126,7 +142,7 @@ namespace MPF.Core
|
||||
public void AdjustPathsForDiscImageCreator()
|
||||
{
|
||||
// Only DiscImageCreator has issues with paths
|
||||
if (this.Parameters.InternalProgram != InternalProgram.DiscImageCreator)
|
||||
if (this.Parameters?.InternalProgram != InternalProgram.DiscImageCreator)
|
||||
return;
|
||||
|
||||
try
|
||||
@@ -135,8 +151,8 @@ namespace MPF.Core
|
||||
string outputPath = InfoTool.NormalizeOutputPaths(this.OutputPath, true);
|
||||
|
||||
// Replace all instances in the output directory
|
||||
string outputDirectory = Path.GetDirectoryName(outputPath);
|
||||
outputDirectory = outputDirectory.Replace(".", "_");
|
||||
var outputDirectory = Path.GetDirectoryName(outputPath);
|
||||
outputDirectory = outputDirectory?.Replace(".", "_");
|
||||
|
||||
// Replace all instances in the output filename
|
||||
string outputFilename = Path.GetFileNameWithoutExtension(outputPath);
|
||||
@@ -146,10 +162,20 @@ namespace MPF.Core
|
||||
string outputExtension = Path.GetExtension(outputPath).TrimStart('.');
|
||||
|
||||
// Rebuild the output path
|
||||
if (!string.IsNullOrWhiteSpace(outputExtension))
|
||||
this.OutputPath = Path.Combine(outputDirectory, $"{outputFilename}.{outputExtension}");
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(outputExtension))
|
||||
this.OutputPath = outputFilename;
|
||||
else
|
||||
this.OutputPath = $"{outputFilename}.{outputExtension}";
|
||||
}
|
||||
else
|
||||
this.OutputPath = Path.Combine(outputDirectory, outputFilename);
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(outputExtension))
|
||||
this.OutputPath = Path.Combine(outputDirectory, outputFilename);
|
||||
else
|
||||
this.OutputPath = Path.Combine(outputDirectory, $"{outputFilename}.{outputExtension}");
|
||||
}
|
||||
|
||||
// Assign the path to the filename as well for dumping
|
||||
((Modules.DiscImageCreator.Parameters)this.Parameters).Filename = this.OutputPath;
|
||||
@@ -198,8 +224,11 @@ namespace MPF.Core
|
||||
}
|
||||
|
||||
// Set system and type
|
||||
this.Parameters.System = this.System;
|
||||
this.Parameters.Type = this.Type;
|
||||
if (this.Parameters != null)
|
||||
{
|
||||
this.Parameters.System = this.System;
|
||||
this.Parameters.Type = this.Type;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -207,7 +236,11 @@ namespace MPF.Core
|
||||
/// </summary>
|
||||
/// <param name="driveSpeed">Nullable int representing the drive speed</param>
|
||||
/// <returns>String representing the params, null on error</returns>
|
||||
#if NET48
|
||||
public string GetFullParameters(int? driveSpeed)
|
||||
#else
|
||||
public string? GetFullParameters(int? driveSpeed)
|
||||
#endif
|
||||
{
|
||||
// Populate with the correct params for inputs (if we're not on the default option)
|
||||
if (System != null && Type != MediaType.NONE)
|
||||
@@ -251,26 +284,42 @@ namespace MPF.Core
|
||||
/// <summary>
|
||||
/// Cancel an in-progress dumping process
|
||||
/// </summary>
|
||||
public void CancelDumping() => Parameters.KillInternalProgram();
|
||||
public void CancelDumping() => Parameters?.KillInternalProgram();
|
||||
|
||||
/// <summary>
|
||||
/// Eject the disc using DiscImageCreator
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public async Task<string> EjectDisc() =>
|
||||
await RunStandaloneDiscImageCreatorCommand(Modules.DiscImageCreator.CommandStrings.Eject);
|
||||
#else
|
||||
public async Task<string?> EjectDisc() =>
|
||||
#endif
|
||||
await RunStandaloneDiscImageCreatorCommand(Modules.DiscImageCreator.CommandStrings.Eject);
|
||||
|
||||
/// <summary>
|
||||
/// Reset the current drive using DiscImageCreator
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public async Task<string> ResetDrive() =>
|
||||
#else
|
||||
public async Task<string?> ResetDrive() =>
|
||||
#endif
|
||||
await RunStandaloneDiscImageCreatorCommand(Modules.DiscImageCreator.CommandStrings.Reset);
|
||||
|
||||
/// <summary>
|
||||
/// Execute the initial invocation of the dumping programs
|
||||
/// </summary>
|
||||
/// <param name="progress">Optional result progress callback</param>
|
||||
#if NET48
|
||||
public async Task<Result> Run(IProgress<Result> progress = null)
|
||||
#else
|
||||
public async Task<Result> Run(IProgress<Result>? progress = null)
|
||||
#endif
|
||||
{
|
||||
// If we don't have parameters
|
||||
if (this.Parameters == null)
|
||||
return Result.Failure("Error! Current configuration is not supported!");
|
||||
|
||||
// Check that we have the basics for dumping
|
||||
Result result = IsValidForDump();
|
||||
if (!result)
|
||||
@@ -280,12 +329,17 @@ namespace MPF.Core
|
||||
if (!Options.ToolsInSeparateWindow)
|
||||
{
|
||||
outputQueue = new ProcessingQueue<string>(ProcessOutputs);
|
||||
Parameters.ReportStatus += OutputToLog;
|
||||
if (Parameters.ReportStatus != null)
|
||||
Parameters.ReportStatus += OutputToLog;
|
||||
}
|
||||
|
||||
// Execute internal tool
|
||||
progress?.Report(Result.Success($"Executing {this.InternalProgram}... {(Options.ToolsInSeparateWindow ? "please wait!" : "see log for output!")}"));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath));
|
||||
|
||||
var directoryName = Path.GetDirectoryName(this.OutputPath);
|
||||
if (!string.IsNullOrWhiteSpace(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
await Task.Run(() => Parameters.ExecuteInternalProgram(Options.ToolsInSeparateWindow));
|
||||
progress?.Report(Result.Success($"{this.InternalProgram} has finished!"));
|
||||
|
||||
@@ -297,7 +351,7 @@ namespace MPF.Core
|
||||
// Remove event handler if needed
|
||||
if (!Options.ToolsInSeparateWindow)
|
||||
{
|
||||
outputQueue.Dispose();
|
||||
outputQueue?.Dispose();
|
||||
Parameters.ReportStatus -= OutputToLog;
|
||||
}
|
||||
|
||||
@@ -312,15 +366,21 @@ namespace MPF.Core
|
||||
/// <param name="processUserInfo">Optional user prompt to deal with submission information</param>
|
||||
/// <returns>Result instance with the outcome</returns>
|
||||
public async Task<Result> VerifyAndSaveDumpOutput(
|
||||
#if NET48
|
||||
IProgress<Result> resultProgress = null,
|
||||
IProgress<ProtectionProgress> protectionProgress = null,
|
||||
Func<SubmissionInfo, (bool?, SubmissionInfo)> processUserInfo = null)
|
||||
#else
|
||||
IProgress<Result>? resultProgress = null,
|
||||
IProgress<ProtectionProgress>? protectionProgress = null,
|
||||
Func<SubmissionInfo?, (bool?, SubmissionInfo?)>? processUserInfo = null)
|
||||
#endif
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Gathering submission information... please wait!"));
|
||||
|
||||
// Get the output directory and filename separately
|
||||
string outputDirectory = Path.GetDirectoryName(this.OutputPath);
|
||||
string outputFilename = Path.GetFileName(this.OutputPath);
|
||||
var outputDirectory = Path.GetDirectoryName(this.OutputPath);
|
||||
var outputFilename = Path.GetFileName(this.OutputPath);
|
||||
|
||||
// Check to make sure that the output had all the correct files
|
||||
(bool foundFiles, List<string> missingFiles) = InfoTool.FoundAllFiles(outputDirectory, outputFilename, this.Parameters, false);
|
||||
@@ -332,7 +392,7 @@ namespace MPF.Core
|
||||
|
||||
// Extract the information from the output files
|
||||
resultProgress?.Report(Result.Success("Extracting output information from output files..."));
|
||||
SubmissionInfo submissionInfo = await InfoTool.ExtractOutputInformation(
|
||||
var submissionInfo = await InfoTool.ExtractOutputInformation(
|
||||
this.OutputPath,
|
||||
this.Drive,
|
||||
this.System,
|
||||
@@ -378,7 +438,7 @@ namespace MPF.Core
|
||||
|
||||
// Format the information for the text output
|
||||
resultProgress?.Report(Result.Success("Formatting information..."));
|
||||
(List<string> formattedValues, string formatResult) = InfoTool.FormatOutputData(submissionInfo, this.Options);
|
||||
(var formattedValues, var formatResult) = InfoTool.FormatOutputData(submissionInfo, this.Options);
|
||||
if (formattedValues == null)
|
||||
resultProgress?.Report(Result.Success(formatResult));
|
||||
else
|
||||
@@ -435,7 +495,7 @@ namespace MPF.Core
|
||||
/// <returns>True if the configuration is valid, false otherwise</returns>
|
||||
internal bool ParametersValid()
|
||||
{
|
||||
bool parametersValid = Parameters.IsValid();
|
||||
bool parametersValid = Parameters?.IsValid() ?? false;
|
||||
bool floppyValid = !(Drive.InternalDriveType == InternalDriveType.Floppy ^ Type == MediaType.FloppyDisk);
|
||||
|
||||
// TODO: HardDisk being in the Removable category is a hack, fix this later
|
||||
@@ -495,7 +555,7 @@ namespace MPF.Core
|
||||
private Result IsValidForDump()
|
||||
{
|
||||
// Validate that everything is good
|
||||
if (!ParametersValid())
|
||||
if (this.Parameters == null || !ParametersValid())
|
||||
return Result.Failure("Error! Current configuration is not supported!");
|
||||
|
||||
// Fix the output paths, just in case
|
||||
@@ -540,7 +600,11 @@ namespace MPF.Core
|
||||
/// </summary>
|
||||
/// <param name="command">Command string to run</param>
|
||||
/// <returns>The output of the command on success, null on error</returns>
|
||||
#if NET48
|
||||
private async Task<string> RunStandaloneDiscImageCreatorCommand(string command)
|
||||
#else
|
||||
private async Task<string?> RunStandaloneDiscImageCreatorCommand(string command)
|
||||
#endif
|
||||
{
|
||||
// Validate that DiscImageCreator is all set
|
||||
if (!RequiredProgramsExist())
|
||||
@@ -562,6 +626,6 @@ namespace MPF.Core
|
||||
return await ExecuteInternalProgram(parameters);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,12 @@ namespace MPF.Core.Hashing
|
||||
public class Hasher
|
||||
{
|
||||
public Hash HashType { get; private set; }
|
||||
private object _hasher;
|
||||
|
||||
#if NET48
|
||||
private object _hasher;
|
||||
#else
|
||||
private object? _hasher;
|
||||
#endif
|
||||
|
||||
public Hasher(Hash hashType)
|
||||
{
|
||||
@@ -84,7 +89,7 @@ namespace MPF.Core.Hashing
|
||||
switch (HashType)
|
||||
{
|
||||
case Hash.CRC32:
|
||||
(_hasher as NonCryptographicHashAlgorithm).Append(buffer);
|
||||
(_hasher as NonCryptographicHashAlgorithm)?.Append(buffer);
|
||||
break;
|
||||
|
||||
case Hash.MD5:
|
||||
@@ -92,7 +97,7 @@ namespace MPF.Core.Hashing
|
||||
case Hash.SHA256:
|
||||
case Hash.SHA384:
|
||||
case Hash.SHA512:
|
||||
(_hasher as HashAlgorithm).TransformBlock(buffer, 0, size, null, 0);
|
||||
(_hasher as HashAlgorithm)?.TransformBlock(buffer, 0, size, null, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -106,7 +111,7 @@ namespace MPF.Core.Hashing
|
||||
switch (HashType)
|
||||
{
|
||||
case Hash.CRC32:
|
||||
(_hasher as NonCryptographicHashAlgorithm).Append(emptyBuffer);
|
||||
(_hasher as NonCryptographicHashAlgorithm)?.Append(emptyBuffer);
|
||||
break;
|
||||
|
||||
case Hash.MD5:
|
||||
@@ -114,7 +119,7 @@ namespace MPF.Core.Hashing
|
||||
case Hash.SHA256:
|
||||
case Hash.SHA384:
|
||||
case Hash.SHA512:
|
||||
(_hasher as HashAlgorithm).TransformFinalBlock(emptyBuffer, 0, 0);
|
||||
(_hasher as HashAlgorithm)?.TransformFinalBlock(emptyBuffer, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -122,19 +127,26 @@ namespace MPF.Core.Hashing
|
||||
/// <summary>
|
||||
/// Get internal hash as a byte array
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public byte[] GetHash()
|
||||
#else
|
||||
public byte[]? GetHash()
|
||||
#endif
|
||||
{
|
||||
if (_hasher == null)
|
||||
return null;
|
||||
|
||||
switch (HashType)
|
||||
{
|
||||
case Hash.CRC32:
|
||||
return (_hasher as NonCryptographicHashAlgorithm).GetCurrentHash();
|
||||
return (_hasher as NonCryptographicHashAlgorithm)?.GetCurrentHash();
|
||||
|
||||
case Hash.MD5:
|
||||
case Hash.SHA1:
|
||||
case Hash.SHA256:
|
||||
case Hash.SHA384:
|
||||
case Hash.SHA512:
|
||||
return (_hasher as HashAlgorithm).Hash;
|
||||
return (_hasher as HashAlgorithm)?.Hash;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -143,12 +155,16 @@ namespace MPF.Core.Hashing
|
||||
/// <summary>
|
||||
/// Get internal hash as a string
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string GetHashString()
|
||||
#else
|
||||
public string? GetHashString()
|
||||
#endif
|
||||
{
|
||||
byte[] hash = GetHash();
|
||||
var hash = GetHash();
|
||||
if (hash == null)
|
||||
return null;
|
||||
|
||||
|
||||
return ByteArrayToString(hash);
|
||||
}
|
||||
|
||||
@@ -158,7 +174,11 @@ namespace MPF.Core.Hashing
|
||||
/// <param name="bytes">Byte array to convert</param>
|
||||
/// <returns>Hex string representing the byte array</returns>
|
||||
/// <link>http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa</link>
|
||||
#if NET48
|
||||
private static string ByteArrayToString(byte[] bytes)
|
||||
#else
|
||||
private static string? ByteArrayToString(byte[]? bytes)
|
||||
#endif
|
||||
{
|
||||
// If we get null in, we send null out
|
||||
if (bytes == null)
|
||||
|
||||
@@ -11,7 +11,11 @@ namespace MPF.Core.Hashing
|
||||
private readonly AutoResetEvent _outEvent;
|
||||
private readonly Thread _tWorker;
|
||||
|
||||
#if NET48
|
||||
private byte[] _buffer;
|
||||
#else
|
||||
private byte[]? _buffer;
|
||||
#endif
|
||||
private int _size;
|
||||
private readonly Stream _ds;
|
||||
private bool _finished;
|
||||
@@ -48,7 +52,8 @@ namespace MPF.Core.Hashing
|
||||
}
|
||||
try
|
||||
{
|
||||
SizeRead = _ds.Read(_buffer, 0, _size);
|
||||
if (_buffer != null)
|
||||
SizeRead = _ds.Read(_buffer, 0, _size);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,10 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="MPF.Test" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -26,10 +26,18 @@ namespace MPF.Core.Modules.Aaru
|
||||
#region Generic Dumping Information
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public override string InputPath => InputValue;
|
||||
#else
|
||||
public override string? InputPath => InputValue;
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public override string OutputPath => OutputValue;
|
||||
#else
|
||||
public override string? OutputPath => OutputValue;
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int? Speed
|
||||
@@ -51,69 +59,177 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
public int? BlockSizeValue { get; set; }
|
||||
|
||||
#if NET48
|
||||
public string CommentsValue { get; set; }
|
||||
#else
|
||||
public string? CommentsValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string CreatorValue { get; set; }
|
||||
#else
|
||||
public string? CreatorValue { get; set; }
|
||||
#endif
|
||||
|
||||
public int? CountValue { get; set; }
|
||||
|
||||
#if NET48
|
||||
public string DriveManufacturerValue { get; set; }
|
||||
#else
|
||||
public string? DriveManufacturerValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string DriveModelValue { get; set; }
|
||||
#else
|
||||
public string? DriveModelValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string DriveRevisionValue { get; set; }
|
||||
#else
|
||||
public string? DriveRevisionValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string DriveSerialValue { get; set; }
|
||||
#else
|
||||
public string? DriveSerialValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string EncodingValue { get; set; }
|
||||
#else
|
||||
public string? EncodingValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string FormatConvertValue { get; set; }
|
||||
#else
|
||||
public string? FormatConvertValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string FormatDumpValue { get; set; }
|
||||
#else
|
||||
public string? FormatDumpValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string GeometryValue { get; set; }
|
||||
#else
|
||||
public string? GeometryValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string ImgBurnLogValue { get; set; }
|
||||
#else
|
||||
public string? ImgBurnLogValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string InputValue { get; set; }
|
||||
#else
|
||||
public string? InputValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string Input1Value { get; set; }
|
||||
#else
|
||||
public string? Input1Value { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string Input2Value { get; set; }
|
||||
#else
|
||||
public string? Input2Value { get; set; }
|
||||
#endif
|
||||
|
||||
public long? LengthValue { get; set; }
|
||||
|
||||
public int? MaxBlocksValue { get; set; }
|
||||
|
||||
#if NET48
|
||||
public string MediaBarcodeValue { get; set; }
|
||||
#else
|
||||
public string? MediaBarcodeValue { get; set; }
|
||||
#endif
|
||||
|
||||
public int? MediaLastSequenceValue { get; set; }
|
||||
|
||||
#if NET48
|
||||
public string MediaManufacturerValue { get; set; }
|
||||
#else
|
||||
public string? MediaManufacturerValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string MediaModelValue { get; set; }
|
||||
#else
|
||||
public string? MediaModelValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string MediaPartNumberValue { get; set; }
|
||||
#else
|
||||
public string? MediaPartNumberValue { get; set; }
|
||||
#endif
|
||||
|
||||
public int? MediaSequenceValue { get; set; }
|
||||
|
||||
#if NET48
|
||||
public string MediaSerialValue { get; set; }
|
||||
#else
|
||||
public string? MediaSerialValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string MediaTitleValue { get; set; }
|
||||
#else
|
||||
public string? MediaTitleValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string MHDDLogValue { get; set; }
|
||||
#else
|
||||
public string? MHDDLogValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string NamespaceValue { get; set; }
|
||||
#else
|
||||
public string? NamespaceValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string OptionsValue { get; set; }
|
||||
#else
|
||||
public string? OptionsValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string OutputValue { get; set; }
|
||||
#else
|
||||
public string? OutputValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string OutputPrefixValue { get; set; }
|
||||
#else
|
||||
public string? OutputPrefixValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string RemoteHostValue { get; set; }
|
||||
#else
|
||||
public string? RemoteHostValue { get; set; }
|
||||
#endif
|
||||
|
||||
#if NET48
|
||||
public string ResumeFileValue { get; set; }
|
||||
#else
|
||||
public string? ResumeFileValue { get; set; }
|
||||
#endif
|
||||
|
||||
public short? RetryPassesValue { get; set; }
|
||||
|
||||
@@ -123,11 +239,19 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
public long? StartValue { get; set; }
|
||||
|
||||
#if NET48
|
||||
public string SubchannelValue { get; set; }
|
||||
#else
|
||||
public string? SubchannelValue { get; set; }
|
||||
#endif
|
||||
|
||||
public short? WidthValue { get; set; }
|
||||
|
||||
#if NET48
|
||||
public string XMLSidecarValue { get; set; }
|
||||
#else
|
||||
public string? XMLSidecarValue { get; set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -198,9 +322,10 @@ namespace MPF.Core.Modules.Aaru
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive drive, bool includeArtifacts)
|
||||
{
|
||||
// TODO: Fill in submission info specifics for Aaru
|
||||
string outputDirectory = Path.GetDirectoryName(basePath);
|
||||
var outputDirectory = Path.GetDirectoryName(basePath);
|
||||
|
||||
// TODO: Determine if there's an Aaru version anywhere
|
||||
if (info.DumpingInfo == null) info.DumpingInfo = new DumpingInfoSection();
|
||||
info.DumpingInfo.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
info.DumpingInfo.DumpingDate = GetFileModifiedDate(basePath + ".cicm.xml")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@@ -208,7 +333,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
var sidecar = GenerateSidecar(basePath + ".cicm.xml");
|
||||
|
||||
// Fill in the hardware data
|
||||
if (GetHardwareInfo(sidecar, out string manufacturer, out string model, out string firmware))
|
||||
if (GetHardwareInfo(sidecar, out var manufacturer, out var model, out var firmware))
|
||||
{
|
||||
info.DumpingInfo.Manufacturer = manufacturer;
|
||||
info.DumpingInfo.Model = model;
|
||||
@@ -216,7 +341,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
}
|
||||
|
||||
// Fill in the disc type data
|
||||
if (GetDiscType(sidecar, out string discType, out string discSubType))
|
||||
if (GetDiscType(sidecar, out var discType, out var discSubType))
|
||||
{
|
||||
string fullDiscType = string.Empty;
|
||||
if (!string.IsNullOrWhiteSpace(discType) && !string.IsNullOrWhiteSpace(discSubType))
|
||||
@@ -230,9 +355,10 @@ namespace MPF.Core.Modules.Aaru
|
||||
}
|
||||
|
||||
// Get the Datafile information
|
||||
Datafile datafile = GenerateDatafile(sidecar, basePath);
|
||||
var datafile = GenerateDatafile(sidecar, basePath);
|
||||
|
||||
// Fill in the hash data
|
||||
if (info.TracksAndWriteOffsets == null) info.TracksAndWriteOffsets = new TracksAndWriteOffsetsSection();
|
||||
info.TracksAndWriteOffsets.ClrMameProData = GenerateDatfile(datafile);
|
||||
|
||||
switch (this.Type)
|
||||
@@ -247,6 +373,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
if (File.Exists(basePath + ".resume.xml"))
|
||||
errorCount = GetErrorCount(basePath + ".resume.xml");
|
||||
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
info.CommonDiscInfo.ErrorsCount = (errorCount == -1 ? "Error retrieving error count" : errorCount.ToString());
|
||||
|
||||
info.TracksAndWriteOffsets.Cuesheet = GenerateCuesheet(sidecar, basePath) ?? string.Empty;
|
||||
@@ -259,8 +386,10 @@ namespace MPF.Core.Modules.Aaru
|
||||
case MediaType.DVD:
|
||||
case MediaType.HDDVD:
|
||||
case MediaType.BluRay:
|
||||
if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
|
||||
|
||||
// Get the individual hash data, as per internal
|
||||
if (GetISOHashValues(datafile, out long size, out string crc32, out string md5, out string sha1))
|
||||
if (GetISOHashValues(datafile, out long size, out var crc32, out var md5, out var sha1))
|
||||
{
|
||||
info.SizeAndChecksums.Size = size;
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
@@ -273,7 +402,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
//info.Extras.PVD = GeneratePVD(sidecar) ?? "Disc has no PVD";
|
||||
|
||||
// Deal with the layerbreak
|
||||
#if NET48
|
||||
string layerbreak = null;
|
||||
#else
|
||||
string? layerbreak = null;
|
||||
#endif
|
||||
if (this.Type == MediaType.DVD)
|
||||
layerbreak = GetLayerbreak(sidecar) ?? string.Empty;
|
||||
else if (this.Type == MediaType.BluRay)
|
||||
@@ -307,34 +440,51 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
case RedumpSystem.DVDAudio:
|
||||
case RedumpSystem.DVDVideo:
|
||||
if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
|
||||
info.CopyProtection.Protection = GetDVDProtection(sidecar) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiPython2:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out Region? pythonTwoRegion, out string pythonTwoDate))
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out var pythonTwoSerial, out Region? pythonTwoRegion, out var pythonTwoDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = pythonTwoSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = pythonTwoDate;
|
||||
}
|
||||
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation2Version(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.MicrosoftXbox:
|
||||
if (GetXgdAuxInfo(sidecar, out string xgd1DMIHash, out string xgd1PFIHash, out string xgd1SSHash, out string ss, out string xgd1SSVer))
|
||||
if (GetXgdAuxInfo(sidecar, out var xgd1DMIHash, out var xgd1PFIHash, out var xgd1SSHash, out var ss, out var xgd1SSVer))
|
||||
{
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd1DMIHash;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd1PFIHash;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd1SSHash;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd1SSVer;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd1DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd1PFIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd1SSHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd1SSVer ?? string.Empty;
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
info.Extras.SecuritySectorRanges = ss ?? string.Empty;
|
||||
}
|
||||
|
||||
if (GetXboxDMIInfo(sidecar, out string serial, out string version, out Region? region))
|
||||
if (GetXboxDMIInfo(sidecar, out var serial, out var version, out Region? region))
|
||||
{
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
info.CommonDiscInfo.Serial = serial ?? string.Empty;
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = version ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = region;
|
||||
}
|
||||
@@ -342,27 +492,42 @@ namespace MPF.Core.Modules.Aaru
|
||||
break;
|
||||
|
||||
case RedumpSystem.MicrosoftXbox360:
|
||||
if (GetXgdAuxInfo(sidecar, out string xgd23DMIHash, out string xgd23PFIHash, out string xgd23SSHash, out string ss360, out string xgd23SSVer))
|
||||
if (GetXgdAuxInfo(sidecar, out var xgd23DMIHash, out var xgd23PFIHash, out var xgd23SSHash, out var ss360, out var xgd23SSVer))
|
||||
{
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd23DMIHash;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd23PFIHash;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd23SSHash;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd23SSVer;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd23DMIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd23PFIHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd23SSHash ?? string.Empty;
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd23SSVer ?? string.Empty;
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
info.Extras.SecuritySectorRanges = ss360 ?? string.Empty;
|
||||
}
|
||||
|
||||
if (GetXbox360DMIInfo(sidecar, out string serial360, out string version360, out Region? region360))
|
||||
if (GetXbox360DMIInfo(sidecar, out var serial360, out var version360, out Region? region360))
|
||||
{
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
info.CommonDiscInfo.Serial = serial360 ?? string.Empty;
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = version360 ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = region360;
|
||||
}
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out Region? playstationRegion, out string playstationDate))
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out var playstationSerial, out Region? playstationRegion, out var playstationDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = playstationDate;
|
||||
@@ -371,29 +536,57 @@ namespace MPF.Core.Modules.Aaru
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation2:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out Region? playstationTwoRegion, out string playstationTwoDate))
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out var playstationTwoSerial, out Region? playstationTwoRegion, out var playstationTwoDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationTwoSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = playstationTwoDate;
|
||||
}
|
||||
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation2Version(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation3:
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation3Version(drive?.Letter) ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = GetPlayStation3Serial(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation4:
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation4Version(drive?.Letter) ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = GetPlayStation4Serial(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation5:
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation5Version(drive?.Letter) ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = GetPlayStation5Serial(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
}
|
||||
@@ -401,23 +594,28 @@ namespace MPF.Core.Modules.Aaru
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
if (info.Artifacts == null) info.Artifacts = new Dictionary<string, string>();
|
||||
if (File.Exists(basePath + ".cicm.xml"))
|
||||
info.Artifacts["cicm"] = GetBase64(GetFullFile(basePath + ".cicm.xml"));
|
||||
info.Artifacts["cicm"] = GetBase64(GetFullFile(basePath + ".cicm.xml")) ?? string.Empty;
|
||||
if (File.Exists(basePath + ".ibg"))
|
||||
info.Artifacts["ibg"] = Convert.ToBase64String(File.ReadAllBytes(basePath + ".ibg"));
|
||||
if (File.Exists(basePath + ".log"))
|
||||
info.Artifacts["log"] = GetBase64(GetFullFile(basePath + ".log"));
|
||||
info.Artifacts["log"] = GetBase64(GetFullFile(basePath + ".log")) ?? string.Empty;
|
||||
if (File.Exists(basePath + ".mhddlog.bin"))
|
||||
info.Artifacts["mhddlog_bin"] = Convert.ToBase64String(File.ReadAllBytes(basePath + ".mhddlog.bin"));
|
||||
if (File.Exists(basePath + ".resume.xml"))
|
||||
info.Artifacts["resume"] = GetBase64(GetFullFile(basePath + ".resume.xml"));
|
||||
info.Artifacts["resume"] = GetBase64(GetFullFile(basePath + ".resume.xml")) ?? string.Empty;
|
||||
if (File.Exists(basePath + ".sub.log"))
|
||||
info.Artifacts["sub_log"] = GetBase64(GetFullFile(basePath + ".sub.log"));
|
||||
info.Artifacts["sub_log"] = GetBase64(GetFullFile(basePath + ".sub.log")) ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public override string GenerateParameters()
|
||||
#else
|
||||
public override string? GenerateParameters()
|
||||
#endif
|
||||
{
|
||||
List<string> parameters = new List<string>();
|
||||
|
||||
@@ -1677,7 +1875,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
short? shortValue = null;
|
||||
int? intValue = null;
|
||||
long? longValue = null;
|
||||
#if NET48
|
||||
string stringValue = null;
|
||||
#else
|
||||
string? stringValue = null;
|
||||
#endif
|
||||
|
||||
// Keep a count of keys to determine if we should break out to filename handling or not
|
||||
int keyCount = Keys.Count();
|
||||
@@ -2135,7 +2337,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="baseCommand">Command string to normalize</param>
|
||||
/// <returns>Normalized command</returns>
|
||||
#if NET48
|
||||
private string NormalizeCommand(List<string> parts, ref int start)
|
||||
#else
|
||||
private string? NormalizeCommand(List<string> parts, ref int start)
|
||||
#endif
|
||||
{
|
||||
// Invalid start means invalid command
|
||||
if (start < 0 || start >= parts.Count)
|
||||
@@ -2146,7 +2352,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
if (start + 1 < parts.Count)
|
||||
partTwo = parts[start + 1];
|
||||
|
||||
string normalized = NormalizeCommand($"{partOne} {partTwo}".Trim());
|
||||
var normalized = NormalizeCommand($"{partOne} {partTwo}".Trim());
|
||||
|
||||
// Null normalization means invalid command
|
||||
if (normalized == null)
|
||||
@@ -2164,7 +2370,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="baseCommand">Command string to normalize</param>
|
||||
/// <returns>Normalized command</returns>
|
||||
#if NET48
|
||||
private string NormalizeCommand(string baseCommand)
|
||||
#else
|
||||
private string? NormalizeCommand(string baseCommand)
|
||||
#endif
|
||||
{
|
||||
// If the base command is inavlid, just return nulls
|
||||
if (string.IsNullOrWhiteSpace(baseCommand))
|
||||
@@ -2172,7 +2382,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
|
||||
// Split the command otherwise
|
||||
string[] splitCommand = baseCommand.Split(' ');
|
||||
#if NET48
|
||||
string family, command;
|
||||
#else
|
||||
string? family, command;
|
||||
#endif
|
||||
|
||||
|
||||
// For commands with a family
|
||||
@@ -2436,7 +2650,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <param name="basePath">Base path for determining file names</param>
|
||||
/// <returns>String containing the cuesheet, null on error</returns>
|
||||
#if NET48
|
||||
private string GenerateCuesheet(CICMMetadataType cicmSidecar, string basePath)
|
||||
#else
|
||||
private string? GenerateCuesheet(CICMMetadataType? cicmSidecar, string basePath)
|
||||
#endif
|
||||
{
|
||||
// If the object is null, we can't get information from it
|
||||
if (cicmSidecar == null)
|
||||
@@ -2559,6 +2777,9 @@ namespace MPF.Core.Modules.Aaru
|
||||
if (cueSheet != null && cueSheet != default)
|
||||
{
|
||||
var ms = new SabreTools.Serialization.Streams.CueSheet().Serialize(cueSheet);
|
||||
if (ms == null)
|
||||
return null;
|
||||
|
||||
using (var sr = new StreamReader(ms))
|
||||
{
|
||||
return sr.ReadToEnd();
|
||||
@@ -2574,7 +2795,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <param name="basePath">Base path for determining file names</param>
|
||||
/// <returns>String containing the datfile, null on error</returns>
|
||||
#if NET48
|
||||
private static string GenerateDatfile(CICMMetadataType cicmSidecar, string basePath)
|
||||
#else
|
||||
private static string? GenerateDatfile(CICMMetadataType? cicmSidecar, string basePath)
|
||||
#endif
|
||||
{
|
||||
// If the object is null, we can't get information from it
|
||||
if (cicmSidecar == null)
|
||||
@@ -2682,7 +2907,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <param name="basePath">Base path for determining file names</param>
|
||||
/// <returns>Datafile containing the hash information, null on error</returns>
|
||||
#if NET48
|
||||
private static Datafile GenerateDatafile(CICMMetadataType cicmSidecar, string basePath)
|
||||
#else
|
||||
private static Datafile? GenerateDatafile(CICMMetadataType? cicmSidecar, string basePath)
|
||||
#endif
|
||||
{
|
||||
// If the object is null, we can't get information from it
|
||||
if (cicmSidecar == null)
|
||||
@@ -2819,19 +3048,23 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <returns>String containing the PVD, null on error</returns>
|
||||
#if NET48
|
||||
private static string GeneratePVD(CICMMetadataType cicmSidecar)
|
||||
#else
|
||||
private static string? GeneratePVD(CICMMetadataType? cicmSidecar)
|
||||
#endif
|
||||
{
|
||||
// If the object is null, we can't get information from it
|
||||
if (cicmSidecar == null)
|
||||
return null;
|
||||
|
||||
// Process OpticalDisc, if possible
|
||||
if (cicmSidecar.OpticalDisc != null || cicmSidecar.OpticalDisc.Length > 0)
|
||||
if (cicmSidecar.OpticalDisc != null && cicmSidecar.OpticalDisc.Length > 0)
|
||||
{
|
||||
// Loop through each OpticalDisc in the metadata
|
||||
foreach (OpticalDiscType opticalDisc in cicmSidecar.OpticalDisc)
|
||||
{
|
||||
byte[] pvdData = GeneratePVDData(opticalDisc);
|
||||
var pvdData = GeneratePVDData(opticalDisc);
|
||||
|
||||
// If we got a null value, we skip this disc
|
||||
if (pvdData == null)
|
||||
@@ -2858,7 +3091,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="opticalDisc">OpticalDisc type from CICM Sidecar data</param>
|
||||
/// <returns>Byte array representing the PVD, null on error</returns>
|
||||
#if NET48
|
||||
private static byte[] GeneratePVDData(OpticalDiscType opticalDisc)
|
||||
#else
|
||||
private static byte[]? GeneratePVDData(OpticalDiscType? opticalDisc)
|
||||
#endif
|
||||
{
|
||||
// Required variables
|
||||
DateTime creation = DateTime.MinValue;
|
||||
@@ -2867,7 +3104,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
DateTime effective = DateTime.MinValue;
|
||||
|
||||
// If there are no tracks, we can't get a PVD
|
||||
if (opticalDisc.Track == null || opticalDisc.Track.Length == 0)
|
||||
if (opticalDisc?.Track == null || opticalDisc.Track.Length == 0)
|
||||
return null;
|
||||
|
||||
// Take the first track only
|
||||
@@ -2995,7 +3232,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// <param name="row">Row ID for outputting</param>
|
||||
/// <param name="bytes">Byte span representing the data to write</param>
|
||||
/// <returns>Formatted string representing the sector line</returns>
|
||||
#if NET48
|
||||
private static string GenerateSectorOutputLine(string row, ReadOnlySpan<byte> bytes)
|
||||
#else
|
||||
private static string? GenerateSectorOutputLine(string row, ReadOnlySpan<byte> bytes)
|
||||
#endif
|
||||
{
|
||||
// If the data isn't correct, return null
|
||||
if (bytes == null || bytes.Length != 16)
|
||||
@@ -3017,7 +3258,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <returns>Object containing the data, null on error</returns>
|
||||
#if NET48
|
||||
private static CICMMetadataType GenerateSidecar(string cicmSidecar)
|
||||
#else
|
||||
private static CICMMetadataType? GenerateSidecar(string cicmSidecar)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(cicmSidecar))
|
||||
@@ -3039,9 +3284,7 @@ namespace MPF.Core.Modules.Aaru
|
||||
return null;
|
||||
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(CICMMetadataType));
|
||||
CICMMetadataType obj = serializer.Deserialize(xtr) as CICMMetadataType;
|
||||
|
||||
return obj;
|
||||
return serializer.Deserialize(xtr) as CICMMetadataType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3049,7 +3292,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <returns>True if disc type info was set, false otherwise</returns>
|
||||
#if NET48
|
||||
private static bool GetDiscType(CICMMetadataType cicmSidecar, out string discType, out string discSubType)
|
||||
#else
|
||||
private static bool GetDiscType(CICMMetadataType? cicmSidecar, out string? discType, out string? discSubType)
|
||||
#endif
|
||||
{
|
||||
// Set the default values
|
||||
discType = null; discSubType = null;
|
||||
@@ -3080,7 +3327,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <returns>Formatted string representing the DVD protection, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetDVDProtection(CICMMetadataType cicmSidecar)
|
||||
#else
|
||||
private static string? GetDVDProtection(CICMMetadataType? cicmSidecar)
|
||||
#endif
|
||||
{
|
||||
// If the object is null, we can't get information from it
|
||||
if (cicmSidecar == null)
|
||||
@@ -3146,10 +3397,12 @@ namespace MPF.Core.Modules.Aaru
|
||||
// Read in the error count whenever we find it
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine().Trim();
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
|
||||
// Initialize on seeing the open tag
|
||||
if (line.StartsWith("<BadBlocks>"))
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
else if (line.StartsWith("<BadBlocks>"))
|
||||
totalErrors = 0;
|
||||
else if (line.StartsWith("</BadBlocks>"))
|
||||
return totalErrors ?? -1;
|
||||
@@ -3173,7 +3426,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <returns>True if hardware info was set, false otherwise</returns>
|
||||
#if NET48
|
||||
private static bool GetHardwareInfo(CICMMetadataType cicmSidecar, out string manufacturer, out string model, out string firmware)
|
||||
#else
|
||||
private static bool GetHardwareInfo(CICMMetadataType? cicmSidecar, out string? manufacturer, out string? model, out string? firmware)
|
||||
#endif
|
||||
{
|
||||
// Set the default values
|
||||
manufacturer = null; model = null; firmware = null;
|
||||
@@ -3217,7 +3474,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <returns>Layerbreak if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetLayerbreak(CICMMetadataType cicmSidecar)
|
||||
#else
|
||||
private static string? GetLayerbreak(CICMMetadataType? cicmSidecar)
|
||||
#endif
|
||||
{
|
||||
// If the object is null, we can't get information from it
|
||||
if (cicmSidecar == null)
|
||||
@@ -3228,7 +3489,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
return null;
|
||||
|
||||
// Setup the layerbreak
|
||||
#if NET48
|
||||
string layerbreak = null;
|
||||
#else
|
||||
string? layerbreak = null;
|
||||
#endif
|
||||
|
||||
// Find and return the layerbreak, if possible
|
||||
foreach (OpticalDiscType opticalDisc in cicmSidecar.OpticalDisc)
|
||||
@@ -3248,7 +3513,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <returns>Sample write offset if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetWriteOffset(CICMMetadataType cicmSidecar)
|
||||
#else
|
||||
private static string? GetWriteOffset(CICMMetadataType? cicmSidecar)
|
||||
#endif
|
||||
{
|
||||
// If the object is null, we can't get information from it
|
||||
if (cicmSidecar == null)
|
||||
@@ -3276,7 +3545,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <returns>True on successful extraction of info, false otherwise</returns>
|
||||
#if NET48
|
||||
private static bool GetXgdAuxInfo(CICMMetadataType cicmSidecar, out string dmihash, out string pfihash, out string sshash, out string ss, out string ssver)
|
||||
#else
|
||||
private static bool GetXgdAuxInfo(CICMMetadataType? cicmSidecar, out string? dmihash, out string? pfihash, out string? sshash, out string? ss, out string? ssver)
|
||||
#endif
|
||||
{
|
||||
dmihash = null; pfihash = null; sshash = null; ss = null; ssver = null;
|
||||
|
||||
@@ -3371,7 +3644,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <returns>True on successful extraction of info, false otherwise</returns>
|
||||
#if NET48
|
||||
private static bool GetXboxDMIInfo(CICMMetadataType cicmSidecar, out string serial, out string version, out Region? region)
|
||||
#else
|
||||
private static bool GetXboxDMIInfo(CICMMetadataType? cicmSidecar, out string? serial, out string? version, out Region? region)
|
||||
#endif
|
||||
{
|
||||
serial = null; version = null; region = Region.World;
|
||||
|
||||
@@ -3419,7 +3696,11 @@ namespace MPF.Core.Modules.Aaru
|
||||
/// </summary>
|
||||
/// <param name="cicmSidecar">CICM Sidecar data generated by Aaru</param>
|
||||
/// <returns>True on successful extraction of info, false otherwise</returns>
|
||||
#if NET48
|
||||
private static bool GetXbox360DMIInfo(CICMMetadataType cicmSidecar, out string serial, out string version, out Region? region)
|
||||
#else
|
||||
private static bool GetXbox360DMIInfo(CICMMetadataType? cicmSidecar, out string? serial, out string? version, out Region? region)
|
||||
#endif
|
||||
{
|
||||
serial = null; version = null; region = Region.World;
|
||||
|
||||
|
||||
@@ -25,7 +25,11 @@ namespace MPF.Core.Modules
|
||||
/// Geneeic way of reporting a message
|
||||
/// </summary>
|
||||
/// <param name="message">String value to report</param>
|
||||
#if NET48
|
||||
public EventHandler<string> ReportStatus;
|
||||
#else
|
||||
public EventHandler<string>? ReportStatus;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -34,7 +38,11 @@ namespace MPF.Core.Modules
|
||||
/// <summary>
|
||||
/// Base command to run
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string BaseCommand { get; set; }
|
||||
#else
|
||||
public string? BaseCommand { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Set of flags to pass to the executable
|
||||
@@ -63,7 +71,11 @@ namespace MPF.Core.Modules
|
||||
/// <summary>
|
||||
/// Process to track external program
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private Process process;
|
||||
#else
|
||||
private Process? process;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -72,18 +84,30 @@ namespace MPF.Core.Modules
|
||||
/// <summary>
|
||||
/// Command to flag support mappings
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public Dictionary<string, List<string>> CommandSupport => GetCommandSupport();
|
||||
#else
|
||||
public Dictionary<string, List<string>>? CommandSupport => GetCommandSupport();
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Input path for operations
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public virtual string InputPath => null;
|
||||
#else
|
||||
public virtual string? InputPath => null;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Output path for operations
|
||||
/// </summary>
|
||||
/// <returns>String representing the path, null on error</returns>
|
||||
#if NET48
|
||||
public virtual string OutputPath => null;
|
||||
#else
|
||||
public virtual string? OutputPath => null;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Get the processing speed from the implementation
|
||||
@@ -97,7 +121,11 @@ namespace MPF.Core.Modules
|
||||
/// <summary>
|
||||
/// Path to the executable
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string ExecutablePath { get; set; }
|
||||
#else
|
||||
public string? ExecutablePath { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Program that this set of parameters represents
|
||||
@@ -171,20 +199,32 @@ namespace MPF.Core.Modules
|
||||
/// Get all commands mapped to the supported flags
|
||||
/// </summary>
|
||||
/// <returns>Mappings from command to supported flags</returns>
|
||||
#if NET48
|
||||
public virtual Dictionary<string, List<string>> GetCommandSupport() => null;
|
||||
#else
|
||||
public virtual Dictionary<string, List<string>>? GetCommandSupport() => null;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Blindly generate a parameter string based on the inputs
|
||||
/// </summary>
|
||||
/// <returns>Parameter string for invocation, null on error</returns>
|
||||
#if NET48
|
||||
public virtual string GenerateParameters() => null;
|
||||
#else
|
||||
public virtual string? GenerateParameters() => null;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Get the default extension for a given media type
|
||||
/// </summary>
|
||||
/// <param name="mediaType">MediaType value to check</param>
|
||||
/// <returns>String representing the media type, null on error</returns>
|
||||
#if NET48
|
||||
public virtual string GetDefaultExtension(MediaType? mediaType) => null;
|
||||
#else
|
||||
public virtual string? GetDefaultExtension(MediaType? mediaType) => null;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Generate a list of all log files generated
|
||||
@@ -320,7 +360,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="content">String content to encode</param>
|
||||
/// <returns>Base64-encoded contents, if possible</returns>
|
||||
#if NET48
|
||||
protected static string GetBase64(string content)
|
||||
#else
|
||||
protected static string? GetBase64(string? content)
|
||||
#endif
|
||||
{
|
||||
if (string.IsNullOrEmpty(content))
|
||||
return null;
|
||||
@@ -335,7 +379,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="filename">file location</param>
|
||||
/// <param name="binary">True if should read as binary, false otherwise (default)</param>
|
||||
/// <returns>Full text of the file, null on error</returns>
|
||||
#if NET48
|
||||
protected static string GetFullFile(string filename, bool binary = false)
|
||||
#else
|
||||
protected static string? GetFullFile(string filename, bool binary = false)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(filename))
|
||||
@@ -465,7 +513,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="longFlagString">Long flag string, if available</param>
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <returns>True if the parameter was processed successfully or skipped, false otherwise</returns>
|
||||
#if NET48
|
||||
protected bool ProcessFlagParameter(List<string> parts, string shortFlagString, string longFlagString, ref int i)
|
||||
#else
|
||||
protected bool ProcessFlagParameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i)
|
||||
#endif
|
||||
{
|
||||
if (parts == null)
|
||||
return false;
|
||||
@@ -501,7 +553,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>True if the parameter was processed successfully or skipped, false otherwise</returns>
|
||||
#if NET48
|
||||
protected bool ProcessBooleanParameter(List<string> parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#else
|
||||
protected bool ProcessBooleanParameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#endif
|
||||
{
|
||||
if (parts == null)
|
||||
return false;
|
||||
@@ -576,7 +632,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>SByte value if success, SByte.MinValue if skipped, null on error/returns>
|
||||
#if NET48
|
||||
protected sbyte? ProcessInt8Parameter(List<string> parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#else
|
||||
protected sbyte? ProcessInt8Parameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#endif
|
||||
{
|
||||
if (parts == null)
|
||||
return null;
|
||||
@@ -654,7 +714,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Int16 value if success, Int16.MinValue if skipped, null on error/returns>
|
||||
#if NET48
|
||||
protected short? ProcessInt16Parameter(List<string> parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#else
|
||||
protected short? ProcessInt16Parameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#endif
|
||||
{
|
||||
if (parts == null)
|
||||
return null;
|
||||
@@ -731,7 +795,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Int32 value if success, Int32.MinValue if skipped, null on error/returns>
|
||||
#if NET48
|
||||
protected int? ProcessInt32Parameter(List<string> parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#else
|
||||
protected int? ProcessInt32Parameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#endif
|
||||
{
|
||||
if (parts == null)
|
||||
return null;
|
||||
@@ -808,7 +876,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Int64 value if success, Int64.MinValue if skipped, null on error/returns>
|
||||
#if NET48
|
||||
protected long? ProcessInt64Parameter(List<string> parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#else
|
||||
protected long? ProcessInt64Parameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#endif
|
||||
{
|
||||
if (parts == null)
|
||||
return null;
|
||||
@@ -873,8 +945,12 @@ namespace MPF.Core.Modules
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>String value if possible, string.Empty on missing, null on error</returns>
|
||||
#if NET48
|
||||
protected string ProcessStringParameter(List<string> parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
=> ProcessStringParameter(parts, null, flagString, ref i, missingAllowed);
|
||||
#else
|
||||
protected string? ProcessStringParameter(List<string> parts, string flagString, ref int i, bool missingAllowed = false)
|
||||
#endif
|
||||
=> ProcessStringParameter(parts, null, flagString, ref i, missingAllowed);
|
||||
|
||||
/// <summary>
|
||||
/// Process a string parameter
|
||||
@@ -885,7 +961,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>String value if possible, string.Empty on missing, null on error</returns>
|
||||
#if NET48
|
||||
protected string ProcessStringParameter(List<string> parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#else
|
||||
protected string? ProcessStringParameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#endif
|
||||
{
|
||||
if (parts == null)
|
||||
return null;
|
||||
@@ -960,7 +1040,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="i">Reference to the position in the parts</param>
|
||||
/// <param name="missingAllowed">True if missing values are allowed, false otherwise</param>
|
||||
/// <returns>Byte value if success, Byte.MinValue if skipped, null on error/returns>
|
||||
#if NET48
|
||||
protected byte? ProcessUInt8Parameter(List<string> parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#else
|
||||
protected byte? ProcessUInt8Parameter(List<string> parts, string? shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
|
||||
#endif
|
||||
{
|
||||
if (parts == null)
|
||||
return null;
|
||||
@@ -1089,17 +1173,23 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="datafile">.dat file location</param>
|
||||
/// <returns>Relevant pieces of the datfile, null on error</returns>
|
||||
#if NET48
|
||||
protected static string GenerateDatfile(Datafile datafile)
|
||||
#else
|
||||
protected static string? GenerateDatfile(Datafile? datafile)
|
||||
#endif
|
||||
{
|
||||
// If we don't have a valid datafile, we can't do anything
|
||||
if (datafile?.Games == null || datafile.Games.Length == 0 || datafile.Games[0]?.Roms == null || datafile.Games[0].Roms.Length == 0)
|
||||
if (datafile?.Games == null || datafile.Games.Length == 0)
|
||||
return null;
|
||||
|
||||
var roms = datafile.Games[0].Roms;
|
||||
if (roms == null || roms.Length == 0)
|
||||
return null;
|
||||
|
||||
// Otherwise, reconstruct the hash data with only the required info
|
||||
try
|
||||
{
|
||||
var roms = datafile.Games[0].Roms;
|
||||
|
||||
string datString = string.Empty;
|
||||
for (int i = 0; i < roms.Length; i++)
|
||||
{
|
||||
@@ -1121,7 +1211,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="dat">Path to the DAT file to parse</param>
|
||||
/// <returns>Filled Datafile on success, null on error</returns>
|
||||
#if NET48
|
||||
protected static Datafile GetDatafile(string dat)
|
||||
#else
|
||||
protected static Datafile? GetDatafile(string? dat)
|
||||
#endif
|
||||
{
|
||||
// If there's no path, we can't read the file
|
||||
if (string.IsNullOrWhiteSpace(dat))
|
||||
@@ -1149,9 +1243,7 @@ namespace MPF.Core.Modules
|
||||
return null;
|
||||
|
||||
var serializer = new XmlSerializer(typeof(Datafile));
|
||||
Datafile obj = serializer.Deserialize(xtr) as Datafile;
|
||||
|
||||
return obj;
|
||||
return serializer.Deserialize(xtr) as Datafile;
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -1166,7 +1258,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="pic">Path to a PIC.bin file</param>
|
||||
/// <returns>Filled DiscInformation on success, null on error</returns>
|
||||
/// <remarks>This omits the emergency brake information, if it exists</remarks>
|
||||
#if NET48
|
||||
protected static DiscInformation GetDiscInformation(string pic)
|
||||
#else
|
||||
protected static DiscInformation? GetDiscInformation(string pic)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1184,7 +1280,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="filename">Path to the input file</param>
|
||||
/// <returns>True if hashing was successful, false otherwise</returns>
|
||||
#if NET48
|
||||
protected static bool GetFileHashes(string filename, out long size, out string crc32, out string md5, out string sha1)
|
||||
#else
|
||||
protected static bool GetFileHashes(string filename, out long size, out string? crc32, out string? md5, out string? sha1)
|
||||
#endif
|
||||
{
|
||||
// Set all initial values
|
||||
size = -1; crc32 = null; md5 = null; sha1 = null;
|
||||
@@ -1289,7 +1389,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="filename">Path to the input file</param>
|
||||
/// <returns>Filled DateTime on success, null on failure</returns>
|
||||
#if NET48
|
||||
protected static DateTime? GetFileModifiedDate(string filename, bool fallback = false)
|
||||
#else
|
||||
protected static DateTime? GetFileModifiedDate(string? filename, bool fallback = false)
|
||||
#endif
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(filename))
|
||||
return fallback ? (DateTime?)DateTime.UtcNow : null;
|
||||
@@ -1305,7 +1409,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="hashData">String representing the combined hash data</param>
|
||||
/// <returns>True if extraction was successful, false otherwise</returns>
|
||||
#if NET48
|
||||
protected static bool GetISOHashValues(string hashData, out long size, out string crc32, out string md5, out string sha1)
|
||||
#else
|
||||
protected static bool GetISOHashValues(string? hashData, out long size, out string? crc32, out string? md5, out string? sha1)
|
||||
#endif
|
||||
{
|
||||
size = -1; crc32 = null; md5 = null; sha1 = null;
|
||||
|
||||
@@ -1335,14 +1443,22 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="datafile">Datafile represenging the hash data</param>
|
||||
/// <returns>True if extraction was successful, false otherwise</returns>
|
||||
#if NET48
|
||||
protected static bool GetISOHashValues(Datafile datafile, out long size, out string crc32, out string md5, out string sha1)
|
||||
#else
|
||||
protected static bool GetISOHashValues(Datafile? datafile, out long size, out string? crc32, out string? md5, out string? sha1)
|
||||
#endif
|
||||
{
|
||||
size = -1; crc32 = null; md5 = null; sha1 = null;
|
||||
|
||||
if (datafile?.Games == null || datafile.Games.Length == 0 || datafile.Games[0].Roms.Length == 0)
|
||||
if (datafile?.Games == null || datafile.Games.Length == 0)
|
||||
return false;
|
||||
|
||||
var rom = datafile.Games[0].Roms[0];
|
||||
var roms = datafile.Games[0].Roms;
|
||||
if (roms == null || roms.Length == 0)
|
||||
return false;
|
||||
|
||||
var rom = roms[0];
|
||||
|
||||
_ = Int64.TryParse(rom.Size, out size);
|
||||
crc32 = rom.Crc;
|
||||
@@ -1357,7 +1473,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="di">Disc information containing unformatted data</param>
|
||||
/// <returns>True if layerbreak info was set, false otherwise</returns>
|
||||
#if NET48
|
||||
protected static bool GetLayerbreaks(DiscInformation di, out long? layerbreak1, out long? layerbreak2, out long? layerbreak3)
|
||||
#else
|
||||
protected static bool GetLayerbreaks(DiscInformation? di, out long? layerbreak1, out long? layerbreak2, out long? layerbreak3)
|
||||
#endif
|
||||
{
|
||||
// Set the default values
|
||||
layerbreak1 = null; layerbreak2 = null; layerbreak3 = null;
|
||||
@@ -1369,9 +1489,12 @@ namespace MPF.Core.Modules
|
||||
#if NET48
|
||||
int ReadFromArrayBigEndian(byte[] bytes, int offset)
|
||||
#else
|
||||
static int ReadFromArrayBigEndian(byte[] bytes, int offset)
|
||||
static int ReadFromArrayBigEndian(byte[]? bytes, int offset)
|
||||
#endif
|
||||
{
|
||||
if (bytes == null)
|
||||
return default;
|
||||
|
||||
var span = new ReadOnlySpan<byte>(bytes, offset, 0x04);
|
||||
byte[] rev = span.ToArray();
|
||||
Array.Reverse(rev);
|
||||
@@ -1381,24 +1504,24 @@ namespace MPF.Core.Modules
|
||||
// Layerbreak 1 (2+ layers)
|
||||
if (di.Units.Length >= 2)
|
||||
{
|
||||
long offset = ReadFromArrayBigEndian(di.Units[0].Body.FormatDependentContents, 0x0C);
|
||||
long value = ReadFromArrayBigEndian(di.Units[0].Body.FormatDependentContents, 0x10);
|
||||
long offset = ReadFromArrayBigEndian(di.Units[0]?.Body?.FormatDependentContents, 0x0C);
|
||||
long value = ReadFromArrayBigEndian(di.Units[0]?.Body?.FormatDependentContents, 0x10);
|
||||
layerbreak1 = value - offset + 2;
|
||||
}
|
||||
|
||||
// Layerbreak 2 (3+ layers)
|
||||
if (di.Units.Length >= 3)
|
||||
{
|
||||
long offset = ReadFromArrayBigEndian(di.Units[1].Body.FormatDependentContents, 0x0C);
|
||||
long value = ReadFromArrayBigEndian(di.Units[1].Body.FormatDependentContents, 0x10);
|
||||
long offset = ReadFromArrayBigEndian(di.Units[1]?.Body?.FormatDependentContents, 0x0C);
|
||||
long value = ReadFromArrayBigEndian(di.Units[1]?.Body?.FormatDependentContents, 0x10);
|
||||
layerbreak2 = layerbreak1 + value - offset + 2;
|
||||
}
|
||||
|
||||
// Layerbreak 3 (4 layers)
|
||||
if (di.Units.Length >= 4)
|
||||
{
|
||||
long offset = ReadFromArrayBigEndian(di.Units[2].Body.FormatDependentContents, 0x0C);
|
||||
long value = ReadFromArrayBigEndian(di.Units[2].Body.FormatDependentContents, 0x10);
|
||||
long offset = ReadFromArrayBigEndian(di.Units[2]?.Body?.FormatDependentContents, 0x0C);
|
||||
long value = ReadFromArrayBigEndian(di.Units[2]?.Body?.FormatDependentContents, 0x10);
|
||||
layerbreak3 = layerbreak2 + value - offset + 2;
|
||||
}
|
||||
|
||||
@@ -1410,14 +1533,18 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="di">Disc information containing the data</param>
|
||||
/// <returns>String representing the PIC identifier, null on error</returns>
|
||||
#if NET48
|
||||
protected static string GetPICIdentifier(DiscInformation di)
|
||||
#else
|
||||
protected static string? GetPICIdentifier(DiscInformation? di)
|
||||
#endif
|
||||
{
|
||||
// If we don't have valid disc information, we can't do anything
|
||||
if (di?.Units == null || di.Units.Length <= 1)
|
||||
return null;
|
||||
|
||||
// We assume the identifier is consistent across all units
|
||||
return di.Units[0].Body.DiscTypeIdentifier;
|
||||
return di.Units[0]?.Body?.DiscTypeIdentifier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1428,7 +1555,11 @@ namespace MPF.Core.Modules
|
||||
/// <param name="region">Output region, if possible</param>
|
||||
/// <param name="date">Output EXE date in "yyyy-mm-dd" format if possible, null on error</param>
|
||||
/// <returns></returns>
|
||||
#if NET48
|
||||
protected static bool GetPlayStationExecutableInfo(char? driveLetter, out string serial, out Region? region, out string date)
|
||||
#else
|
||||
protected static bool GetPlayStationExecutableInfo(char? driveLetter, out string? serial, out Region? region, out string? date)
|
||||
#endif
|
||||
{
|
||||
serial = null; region = null; date = null;
|
||||
|
||||
@@ -1446,7 +1577,11 @@ namespace MPF.Core.Modules
|
||||
string systemCnfPath = Path.Combine(drivePath, "SYSTEM.CNF");
|
||||
|
||||
// Try both of the common paths that contain information
|
||||
#if NET48
|
||||
string exeName = null;
|
||||
#else
|
||||
string? exeName = null;
|
||||
#endif
|
||||
|
||||
// Read the CNF file as an INI file
|
||||
var systemCnf = new IniFile(systemCnfPath);
|
||||
@@ -1512,7 +1647,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <returns>Game version if possible, null on error</returns>
|
||||
#if NET48
|
||||
protected static string GetPlayStation2Version(char? driveLetter)
|
||||
#else
|
||||
protected static string? GetPlayStation2Version(char? driveLetter)
|
||||
#endif
|
||||
{
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
@@ -1540,7 +1679,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <returns>Internal disc serial if possible, null on error</returns>
|
||||
#if NET48
|
||||
protected static string GetPlayStation3Serial(char? driveLetter)
|
||||
#else
|
||||
protected static string? GetPlayStation3Serial(char? driveLetter)
|
||||
#endif
|
||||
{
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
@@ -1577,7 +1720,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <returns>Game version if possible, null on error</returns>
|
||||
#if NET48
|
||||
protected static string GetPlayStation3Version(char? driveLetter)
|
||||
#else
|
||||
protected static string? GetPlayStation3Version(char? driveLetter)
|
||||
#endif
|
||||
{
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
@@ -1614,7 +1761,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <returns>Internal disc serial if possible, null on error</returns>
|
||||
#if NET48
|
||||
protected static string GetPlayStation4Serial(char? driveLetter)
|
||||
#else
|
||||
protected static string? GetPlayStation4Serial(char? driveLetter)
|
||||
#endif
|
||||
{
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
@@ -1645,13 +1796,17 @@ namespace MPF.Core.Modules
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the version from a PlayStation 4 disc, if possible
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <returns>Game version if possible, null on error</returns>
|
||||
#if NET48
|
||||
protected static string GetPlayStation4Version(char? driveLetter)
|
||||
#else
|
||||
protected static string? GetPlayStation4Version(char? driveLetter)
|
||||
#endif
|
||||
{
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
@@ -1688,7 +1843,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <returns>Internal disc serial if possible, null on error</returns>
|
||||
#if NET48
|
||||
protected static string GetPlayStation5Serial(char? driveLetter)
|
||||
#else
|
||||
protected static string? GetPlayStation5Serial(char? driveLetter)
|
||||
#endif
|
||||
{
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
@@ -1725,7 +1884,11 @@ namespace MPF.Core.Modules
|
||||
/// </summary>
|
||||
/// <param name="driveLetter">Drive letter to use to check</param>
|
||||
/// <returns>Game version if possible, null on error</returns>
|
||||
#if NET48
|
||||
protected static string GetPlayStation5Version(char? driveLetter)
|
||||
#else
|
||||
protected static string? GetPlayStation5Version(char? driveLetter)
|
||||
#endif
|
||||
{
|
||||
// If there's no drive letter, we can't do this part
|
||||
if (driveLetter == null)
|
||||
@@ -1757,7 +1920,7 @@ namespace MPF.Core.Modules
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Category Extraction
|
||||
|
||||
@@ -1800,7 +1963,7 @@ namespace MPF.Core.Modules
|
||||
case 'E': return Region.Europe;
|
||||
case 'K': return Region.SouthKorea;
|
||||
case 'U': return Region.UnitedStatesOfAmerica;
|
||||
case 'P':
|
||||
case 'P':
|
||||
// Region of S_P_ serials may be Japan, Asia, or SouthKorea
|
||||
switch (serial[3])
|
||||
{
|
||||
|
||||
@@ -63,14 +63,16 @@ namespace MPF.Core.Modules.CleanRip
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive drive, bool includeArtifacts)
|
||||
{
|
||||
// TODO: Determine if there's a CleanRip version anywhere
|
||||
if (info.DumpingInfo == null) info.DumpingInfo = new DumpingInfoSection();
|
||||
info.DumpingInfo.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
info.DumpingInfo.DumpingDate = GetFileModifiedDate(basePath + "-dumpinfo.txt")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
Datafile datafile = GenerateCleanripDatafile(basePath + ".iso", basePath + "-dumpinfo.txt");
|
||||
|
||||
var datafile = GenerateCleanripDatafile(basePath + ".iso", basePath + "-dumpinfo.txt");
|
||||
|
||||
// Get the individual hash data, as per internal
|
||||
if (GetISOHashValues(datafile, out long size, out string crc32, out string md5, out string sha1))
|
||||
if (GetISOHashValues(datafile, out long size, out var crc32, out var md5, out var sha1))
|
||||
{
|
||||
if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
|
||||
info.SizeAndChecksums.Size = size;
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
info.SizeAndChecksums.MD5 = md5;
|
||||
@@ -79,7 +81,7 @@ namespace MPF.Core.Modules.CleanRip
|
||||
// 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)
|
||||
@@ -88,12 +90,22 @@ namespace MPF.Core.Modules.CleanRip
|
||||
case MediaType.NintendoGameCubeGameDisc:
|
||||
case MediaType.NintendoWiiOpticalDisc:
|
||||
if (File.Exists(basePath + ".bca"))
|
||||
info.Extras.BCA = GetBCA(basePath + ".bca");
|
||||
|
||||
if (GetGameCubeWiiInformation(basePath + "-dumpinfo.txt", out Region? gcRegion, out string gcVersion, out string gcName))
|
||||
{
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
info.Extras.BCA = GetBCA(basePath + ".bca");
|
||||
}
|
||||
|
||||
if (GetGameCubeWiiInformation(basePath + "-dumpinfo.txt", out Region? gcRegion, out var gcVersion, out var gcName))
|
||||
{
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
info.CommonDiscInfo.Region = gcRegion ?? info.CommonDiscInfo.Region;
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = gcVersion ?? info.VersionAndEditions.Version;
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalName] = gcName ?? string.Empty;
|
||||
}
|
||||
|
||||
@@ -103,10 +115,11 @@ namespace MPF.Core.Modules.CleanRip
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
if (info.Artifacts == null) info.Artifacts = new Dictionary<string, string>();
|
||||
if (File.Exists(basePath + ".bca"))
|
||||
info.Artifacts["bca"] = GetBase64(GetFullFile(basePath + ".bca", binary: true));
|
||||
info.Artifacts["bca"] = GetBase64(GetFullFile(basePath + ".bca", binary: true)) ?? string.Empty;
|
||||
if (File.Exists(basePath + "-dumpinfo.txt"))
|
||||
info.Artifacts["dumpinfo"] = GetBase64(GetFullFile(basePath + "-dumpinfo.txt"));
|
||||
info.Artifacts["dumpinfo"] = GetBase64(GetFullFile(basePath + "-dumpinfo.txt")) ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +153,11 @@ namespace MPF.Core.Modules.CleanRip
|
||||
/// <param name="iso">Path to ISO file</param>
|
||||
/// <param name="dumpinfo">Path to discinfo file</param>
|
||||
/// <returns></returns>
|
||||
#if NET48
|
||||
private static Datafile GenerateCleanripDatafile(string iso, string dumpinfo)
|
||||
#else
|
||||
private static Datafile? GenerateCleanripDatafile(string iso, string dumpinfo)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(dumpinfo))
|
||||
@@ -156,14 +173,16 @@ namespace MPF.Core.Modules.CleanRip
|
||||
try
|
||||
{
|
||||
// Make sure this file is a dumpinfo
|
||||
if (!sr.ReadLine().Contains("--File Generated by CleanRip"))
|
||||
if (sr.ReadLine()?.Contains("--File Generated by CleanRip") != true)
|
||||
return null;
|
||||
|
||||
// Read all lines and gather dat information
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine().Trim();
|
||||
if (line.StartsWith("CRC32"))
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
else if (line.StartsWith("CRC32"))
|
||||
crc = line.Substring(7).ToLowerInvariant();
|
||||
else if (line.StartsWith("MD5"))
|
||||
md5 = line.Substring(5);
|
||||
@@ -199,7 +218,11 @@ namespace MPF.Core.Modules.CleanRip
|
||||
/// <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>
|
||||
#if NET48
|
||||
private static string GetBCA(string bcaPath)
|
||||
#else
|
||||
private static string? GetBCA(string bcaPath)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get the info
|
||||
if (!File.Exists(bcaPath))
|
||||
@@ -207,7 +230,10 @@ namespace MPF.Core.Modules.CleanRip
|
||||
|
||||
try
|
||||
{
|
||||
string hex = GetFullFile(bcaPath, true);
|
||||
var hex = GetFullFile(bcaPath, true);
|
||||
if (hex == null)
|
||||
return null;
|
||||
|
||||
return Regex.Replace(hex, ".{32}", "$0\n");
|
||||
}
|
||||
catch
|
||||
@@ -223,7 +249,11 @@ namespace MPF.Core.Modules.CleanRip
|
||||
/// <param name="iso">Path to ISO file</param>
|
||||
/// <param name="dumpinfo">Path to discinfo file</param>
|
||||
/// <returns></returns>
|
||||
#if NET48
|
||||
private static string GetCleanripDatfile(string iso, string dumpinfo)
|
||||
#else
|
||||
private static string? GetCleanripDatfile(string iso, string dumpinfo)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(dumpinfo))
|
||||
@@ -239,14 +269,16 @@ namespace MPF.Core.Modules.CleanRip
|
||||
try
|
||||
{
|
||||
// Make sure this file is a dumpinfo
|
||||
if (!sr.ReadLine().Contains("--File Generated by CleanRip"))
|
||||
if (sr.ReadLine()?.Contains("--File Generated by CleanRip") != true)
|
||||
return null;
|
||||
|
||||
// Read all lines and gather dat information
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine().Trim();
|
||||
if (line.StartsWith("CRC32"))
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
else if (line.StartsWith("CRC32"))
|
||||
crc = line.Substring(7).ToLowerInvariant();
|
||||
else if (line.StartsWith("MD5"))
|
||||
md5 = line.Substring(5);
|
||||
@@ -272,7 +304,11 @@ namespace MPF.Core.Modules.CleanRip
|
||||
/// <param name="version">Output internal version of the game</param>
|
||||
/// <param name="name">Output internal name of the game</param>
|
||||
/// <returns></returns>
|
||||
#if NET48
|
||||
private static bool GetGameCubeWiiInformation(string dumpinfo, out Region? region, out string version, out string name)
|
||||
#else
|
||||
private static bool GetGameCubeWiiInformation(string dumpinfo, out Region? region, out string? version, out string? name)
|
||||
#endif
|
||||
{
|
||||
region = null; version = null; name = null;
|
||||
|
||||
@@ -285,14 +321,18 @@ namespace MPF.Core.Modules.CleanRip
|
||||
try
|
||||
{
|
||||
// Make sure this file is a dumpinfo
|
||||
if (!sr.ReadLine().Contains("--File Generated by CleanRip"))
|
||||
if (sr.ReadLine()?.Contains("--File Generated by CleanRip") != true)
|
||||
return false;
|
||||
|
||||
// Read all lines and gather dat information
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine().Trim();
|
||||
if (line.StartsWith("Version"))
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (line.StartsWith("Version"))
|
||||
{
|
||||
version = line.Substring("Version: ".Length);
|
||||
}
|
||||
|
||||
@@ -6,67 +6,139 @@ namespace MPF.Core.Modules
|
||||
public class Datafile
|
||||
{
|
||||
[XmlElement("header")]
|
||||
#if NET48
|
||||
public Header Header;
|
||||
#else
|
||||
public Header? Header;
|
||||
#endif
|
||||
|
||||
[XmlElement("game")]
|
||||
#if NET48
|
||||
public Game[] Games;
|
||||
#else
|
||||
public Game[]? Games;
|
||||
#endif
|
||||
}
|
||||
|
||||
public class Header
|
||||
{
|
||||
[XmlElement("name")]
|
||||
#if NET48
|
||||
public string Name;
|
||||
#else
|
||||
public string? Name;
|
||||
#endif
|
||||
|
||||
[XmlElement("description")]
|
||||
#if NET48
|
||||
public string Description;
|
||||
#else
|
||||
public string? Description;
|
||||
#endif
|
||||
|
||||
[XmlElement("version")]
|
||||
#if NET48
|
||||
public string Version;
|
||||
#else
|
||||
public string? Version;
|
||||
#endif
|
||||
|
||||
[XmlElement("date")]
|
||||
#if NET48
|
||||
public string Date;
|
||||
#else
|
||||
public string? Date;
|
||||
#endif
|
||||
|
||||
[XmlElement("author")]
|
||||
#if NET48
|
||||
public string Author;
|
||||
#else
|
||||
public string? Author;
|
||||
#endif
|
||||
|
||||
[XmlElement("homepage")]
|
||||
#if NET48
|
||||
public string Homepage;
|
||||
#else
|
||||
public string? Homepage;
|
||||
#endif
|
||||
|
||||
[XmlElement("url")]
|
||||
#if NET48
|
||||
public string Url;
|
||||
#else
|
||||
public string? Url;
|
||||
#endif
|
||||
}
|
||||
|
||||
public class Game
|
||||
{
|
||||
[XmlAttribute("name")]
|
||||
#if NET48
|
||||
public string Name;
|
||||
#else
|
||||
public string? Name;
|
||||
#endif
|
||||
|
||||
[XmlElement("category")]
|
||||
#if NET48
|
||||
public string Category;
|
||||
#else
|
||||
public string? Category;
|
||||
#endif
|
||||
|
||||
[XmlElement("description")]
|
||||
#if NET48
|
||||
public string Description;
|
||||
#else
|
||||
public string? Description;
|
||||
#endif
|
||||
|
||||
[XmlElement("rom")]
|
||||
#if NET48
|
||||
public Rom[] Roms;
|
||||
#else
|
||||
public Rom[]? Roms;
|
||||
#endif
|
||||
}
|
||||
|
||||
public class Rom
|
||||
{
|
||||
[XmlAttribute("name")]
|
||||
#if NET48
|
||||
public string Name;
|
||||
#else
|
||||
public string? Name;
|
||||
#endif
|
||||
|
||||
[XmlAttribute("size")]
|
||||
#if NET48
|
||||
public string Size;
|
||||
#else
|
||||
public string? Size;
|
||||
#endif
|
||||
|
||||
[XmlAttribute("crc")]
|
||||
#if NET48
|
||||
public string Crc;
|
||||
#else
|
||||
public string? Crc;
|
||||
#endif
|
||||
|
||||
[XmlAttribute("md5")]
|
||||
#if NET48
|
||||
public string Md5;
|
||||
#else
|
||||
public string? Md5;
|
||||
#endif
|
||||
|
||||
[XmlAttribute("sha1")]
|
||||
#if NET48
|
||||
public string Sha1;
|
||||
#else
|
||||
public string? Sha1;
|
||||
#endif
|
||||
|
||||
// TODO: Add extended hashes here
|
||||
}
|
||||
|
||||
@@ -48,7 +48,11 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
/// <param name="baseCommand">Command value to check</param>
|
||||
/// <returns>MediaType if possible, null on error</returns>
|
||||
/// <remarks>This takes the "safe" route by assuming the larger of any given format</remarks>
|
||||
#if NET48
|
||||
public static MediaType? ToMediaType(string baseCommand)
|
||||
#else
|
||||
public static MediaType? ToMediaType(string? baseCommand)
|
||||
#endif
|
||||
{
|
||||
switch (baseCommand)
|
||||
{
|
||||
@@ -86,7 +90,11 @@ namespace MPF.Core.Modules.DiscImageCreator
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType value to check</param>
|
||||
/// <returns>Valid extension (with leading '.'), null on error</returns>
|
||||
#if NET48
|
||||
public static string Extension(MediaType? type)
|
||||
#else
|
||||
public static string? Extension(MediaType? type)
|
||||
#endif
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="type">MediaType value to check</param>
|
||||
/// <returns>Valid extension (with leading '.'), null on error</returns>
|
||||
#if NET48
|
||||
public static string Extension(MediaType? type)
|
||||
#else
|
||||
public static string? Extension(MediaType? type)
|
||||
#endif
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using BinaryObjectScanner.Protection;
|
||||
using MPF.Core.Converters;
|
||||
using MPF.Core.Data;
|
||||
using MPF.Core.Utilities;
|
||||
@@ -26,10 +27,18 @@ namespace MPF.Core.Modules.Redumper
|
||||
#region Generic Dumping Information
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public override string InputPath => DriveValue;
|
||||
#else
|
||||
public override string? InputPath => DriveValue;
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public override string OutputPath => Path.Combine(ImagePathValue?.Trim('"') ?? string.Empty, ImageNameValue?.Trim('"') ?? string.Empty) + GetDefaultExtension(this.Type);
|
||||
#else
|
||||
public override string? OutputPath => Path.Combine(ImagePathValue?.Trim('"') ?? string.Empty, ImageNameValue?.Trim('"') ?? string.Empty) + GetDefaultExtension(this.Type);
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int? Speed => SpeedValue;
|
||||
@@ -48,14 +57,22 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// <summary>
|
||||
/// List of all modes being run
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public List<string> ModeValues { get; set; }
|
||||
#else
|
||||
public List<string>? ModeValues { get; set; }
|
||||
#endif
|
||||
|
||||
#region General
|
||||
|
||||
/// <summary>
|
||||
/// Drive to use, first available drive with disc, if not provided
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string DriveValue { get; set; }
|
||||
#else
|
||||
public string? DriveValue { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Drive read speed, optimal drive speed will be used if not provided
|
||||
@@ -70,12 +87,20 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// <summary>
|
||||
/// Dump files base directory
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string ImagePathValue { get; set; }
|
||||
#else
|
||||
public string? ImagePathValue { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Dump files prefix, autogenerated in dump mode, if not provided
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string ImageNameValue { get; set; }
|
||||
#else
|
||||
public string? ImageNameValue { get; set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -84,7 +109,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// <summary>
|
||||
/// Override drive type, possible values: GENERIC, PLEXTOR, LG_ASUS
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string DriveTypeValue { get; set; }
|
||||
#else
|
||||
public string? DriveTypeValue { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Override drive read offset
|
||||
@@ -104,12 +133,20 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// <summary>
|
||||
/// Override drive read method, possible values: BE, D8, BE_CDDA
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string DriveReadMethodValue { get; set; }
|
||||
#else
|
||||
public string? DriveReadMethodValue { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Override drive sector order, possible values: DATA_C2_SUB, DATA_SUB_C2
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string DriveSectorOrderValue { get; set; }
|
||||
#else
|
||||
public string? DriveSectorOrderValue { get; set; }
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -151,7 +188,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// <summary>
|
||||
/// LBA ranges of sectors to skip
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public string SkipValue { get; set; }
|
||||
#else
|
||||
public string? SkipValue { get; set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Number of sectors to read at once on initial dump, DVD only (Default 32)
|
||||
@@ -245,11 +286,12 @@ namespace MPF.Core.Modules.Redumper
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive drive, bool includeArtifacts)
|
||||
{
|
||||
// Get the dumping program and version
|
||||
if (info.DumpingInfo == null) info.DumpingInfo = new DumpingInfoSection();
|
||||
info.DumpingInfo.DumpingProgram = $"{EnumConverter.LongName(this.InternalProgram)} {GetVersion($"{basePath}.log") ?? "Unknown Version"}";
|
||||
info.DumpingInfo.DumpingDate = GetFileModifiedDate($"{basePath}.log")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
// Fill in the hardware data
|
||||
if (GetHardwareInfo($"{basePath}.log", out string manufacturer, out string model, out string firmware))
|
||||
if (GetHardwareInfo($"{basePath}.log", out var manufacturer, out var model, out var firmware))
|
||||
{
|
||||
info.DumpingInfo.Manufacturer = manufacturer;
|
||||
info.DumpingInfo.Model = model;
|
||||
@@ -259,12 +301,15 @@ namespace MPF.Core.Modules.Redumper
|
||||
switch (this.Type)
|
||||
{
|
||||
case MediaType.CDROM:
|
||||
info.Extras.PVD = GetPVD($"{basePath}.log") ?? "Disc has no PVD"; ;
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
info.Extras.PVD = GetPVD($"{basePath}.log") ?? "Disc has no PVD";
|
||||
if (info.TracksAndWriteOffsets == null) info.TracksAndWriteOffsets = new TracksAndWriteOffsetsSection();
|
||||
info.TracksAndWriteOffsets.ClrMameProData = GetDatfile($"{basePath}.log");
|
||||
info.TracksAndWriteOffsets.Cuesheet = GetFullFile($"{basePath}.cue") ?? string.Empty;
|
||||
|
||||
// Attempt to get the write offset
|
||||
string cdWriteOffset = GetWriteOffset($"{basePath}.log") ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
info.CommonDiscInfo.RingWriteOffset = cdWriteOffset;
|
||||
info.TracksAndWriteOffsets.OtherWriteOffsets = cdWriteOffset;
|
||||
|
||||
@@ -272,6 +317,12 @@ namespace MPF.Core.Modules.Redumper
|
||||
long errorCount = GetErrorCount($"{basePath}.log");
|
||||
info.CommonDiscInfo.ErrorsCount = (errorCount == -1 ? "Error retrieving error count" : errorCount.ToString());
|
||||
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
|
||||
// Attempt to get multisession data
|
||||
string cdMultiSessionInfo = GetMultisessionInformation($"{basePath}.log") ?? string.Empty;
|
||||
if (!string.IsNullOrWhiteSpace(cdMultiSessionInfo))
|
||||
@@ -294,11 +345,14 @@ namespace MPF.Core.Modules.Redumper
|
||||
break;
|
||||
|
||||
case MediaType.DVD:
|
||||
info.Extras.PVD = GetPVD($"{basePath}.log") ?? "Disc has no PVD"; ;
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
info.Extras.PVD = GetPVD($"{basePath}.log") ?? "Disc has no PVD";
|
||||
if (info.TracksAndWriteOffsets == null) info.TracksAndWriteOffsets = new TracksAndWriteOffsetsSection();
|
||||
info.TracksAndWriteOffsets.ClrMameProData = GetDatfile($"{basePath}.log");
|
||||
|
||||
// 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))
|
||||
if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
|
||||
if (GetISOHashValues(info.TracksAndWriteOffsets.ClrMameProData, out long size, out var crc32, out var md5, out var sha1))
|
||||
{
|
||||
info.SizeAndChecksums.Size = size;
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
@@ -323,18 +377,26 @@ namespace MPF.Core.Modules.Redumper
|
||||
|
||||
case RedumpSystem.DVDAudio:
|
||||
case RedumpSystem.DVDVideo:
|
||||
if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
|
||||
info.CopyProtection.Protection = GetDVDProtection($"{basePath}.log") ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.KonamiPython2:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out string pythonTwoSerial, out Region? pythonTwoRegion, out string pythonTwoDate))
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out var pythonTwoSerial, out Region? pythonTwoRegion, out var pythonTwoDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = pythonTwoSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? pythonTwoRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = pythonTwoDate;
|
||||
}
|
||||
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation2Version(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
|
||||
@@ -351,7 +413,14 @@ namespace MPF.Core.Modules.Redumper
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaMegaCDSegaCD:
|
||||
info.Extras.Header = GetSegaCDHeader($"{basePath}.log", out string scdBuildDate, out string scdSerial, out string _) ?? string.Empty;
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
info.Extras.Header = GetSegaCDHeader($"{basePath}.log", out var scdBuildDate, out var scdSerial, out _) ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = scdSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = scdBuildDate ?? string.Empty;
|
||||
// TODO: Support region setting from parsed value
|
||||
@@ -374,16 +443,24 @@ namespace MPF.Core.Modules.Redumper
|
||||
break;
|
||||
|
||||
case RedumpSystem.SegaSaturn:
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
info.Extras.Header = GetSaturnHeader($"{basePath}.log") ?? string.Empty;
|
||||
|
||||
// Take only the first 16 lines for Saturn
|
||||
if (!string.IsNullOrEmpty(info.Extras.Header))
|
||||
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
|
||||
|
||||
if (GetSaturnBuildInfo(info.Extras.Header, out string saturnSerial, out string saturnVersion, out string buildDate))
|
||||
if (GetSaturnBuildInfo(info.Extras.Header, out var saturnSerial, out var saturnVersion, out var buildDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = saturnSerial ?? string.Empty;
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = saturnVersion ?? string.Empty;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = buildDate ?? string.Empty;
|
||||
}
|
||||
@@ -391,44 +468,80 @@ namespace MPF.Core.Modules.Redumper
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationSerial, out Region? playstationRegion, out string playstationDate))
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out var playstationSerial, out Region? playstationRegion, out var playstationDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = playstationDate;
|
||||
}
|
||||
|
||||
if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
|
||||
info.CopyProtection.AntiModchip = GetPlayStationAntiModchipDetected($"{basePath}.log").ToYesNo();
|
||||
if (info.EDC == null) info.EDC = new EDCSection();
|
||||
info.EDC.EDC = GetPlayStationEDCStatus($"{basePath}.log").ToYesNo();
|
||||
info.CopyProtection.LibCrypt = GetPlayStationLibCryptStatus($"{basePath}.log").ToYesNo();
|
||||
info.CopyProtection.LibCryptData = GetPlayStationLibCryptData($"{basePath}.log");
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation2:
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out string playstationTwoSerial, out Region? playstationTwoRegion, out string playstationTwoDate))
|
||||
if (GetPlayStationExecutableInfo(drive?.Letter, out var playstationTwoSerial, out Region? playstationTwoRegion, out var playstationTwoDate))
|
||||
{
|
||||
// Ensure internal serial is pulled from local data
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationTwoSerial ?? string.Empty;
|
||||
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationTwoRegion;
|
||||
info.CommonDiscInfo.EXEDateBuildDate = playstationTwoDate;
|
||||
}
|
||||
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation2Version(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation3:
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation3Version(drive?.Letter) ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = GetPlayStation3Serial(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation4:
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation4Version(drive?.Letter) ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = GetPlayStation4Serial(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.SonyPlayStation5:
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = GetPlayStation5Version(drive?.Letter) ?? string.Empty;
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
#if NET48
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode?, string>();
|
||||
#else
|
||||
if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary<SiteCode, string>();
|
||||
#endif
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = GetPlayStation5Serial(drive?.Letter) ?? string.Empty;
|
||||
break;
|
||||
}
|
||||
@@ -436,36 +549,37 @@ namespace MPF.Core.Modules.Redumper
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
if (info.Artifacts == null) info.Artifacts = new Dictionary<string, string>();
|
||||
if (File.Exists($"{basePath}.cdtext"))
|
||||
info.Artifacts["cdtext"] = GetBase64(GetFullFile($"{basePath}.cdtext"));
|
||||
info.Artifacts["cdtext"] = GetBase64(GetFullFile($"{basePath}.cdtext")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.cue"))
|
||||
info.Artifacts["cue"] = GetBase64(GetFullFile($"{basePath}.cue"));
|
||||
info.Artifacts["cue"] = GetBase64(GetFullFile($"{basePath}.cue")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.fulltoc"))
|
||||
info.Artifacts["fulltoc"] = GetBase64(GetFullFile($"{basePath}.fulltoc"));
|
||||
info.Artifacts["fulltoc"] = GetBase64(GetFullFile($"{basePath}.fulltoc")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.log"))
|
||||
info.Artifacts["log"] = GetBase64(GetFullFile($"{basePath}.log"));
|
||||
info.Artifacts["log"] = GetBase64(GetFullFile($"{basePath}.log")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.manufacturer"))
|
||||
info.Artifacts["manufacturer"] = GetBase64(GetFullFile($"{basePath}.manufacturer"));
|
||||
info.Artifacts["manufacturer"] = GetBase64(GetFullFile($"{basePath}.manufacturer")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.1.manufacturer"))
|
||||
info.Artifacts["manufacturer1"] = GetBase64(GetFullFile($"{basePath}.1.manufacturer"));
|
||||
info.Artifacts["manufacturer1"] = GetBase64(GetFullFile($"{basePath}.1.manufacturer")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.2.manufacturer"))
|
||||
info.Artifacts["manufacturer2"] = GetBase64(GetFullFile($"{basePath}.2.manufacturer"));
|
||||
info.Artifacts["manufacturer2"] = GetBase64(GetFullFile($"{basePath}.2.manufacturer")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.physical"))
|
||||
info.Artifacts["physical"] = GetBase64(GetFullFile($"{basePath}.physical"));
|
||||
info.Artifacts["physical"] = GetBase64(GetFullFile($"{basePath}.physical")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.1.physical"))
|
||||
info.Artifacts["physical1"] = GetBase64(GetFullFile($"{basePath}.1.physical"));
|
||||
info.Artifacts["physical1"] = GetBase64(GetFullFile($"{basePath}.1.physical")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.2.physical"))
|
||||
info.Artifacts["physical2"] = GetBase64(GetFullFile($"{basePath}.2.physical"));
|
||||
info.Artifacts["physical2"] = GetBase64(GetFullFile($"{basePath}.2.physical")) ?? string.Empty;
|
||||
// if (File.Exists($"{basePath}.scram"))
|
||||
// info.Artifacts["scram"] = GetBase64(GetFullFile($"{basePath}.scram"));
|
||||
// info.Artifacts["scram"] = GetBase64(GetFullFile($"{basePath}.scram")) ?? string.Empty;
|
||||
// if (File.Exists($"{basePath}.scrap"))
|
||||
// info.Artifacts["scrap"] = GetBase64(GetFullFile($"{basePath}.scrap"));
|
||||
// info.Artifacts["scrap"] = GetBase64(GetFullFile($"{basePath}.scrap")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.state"))
|
||||
info.Artifacts["state"] = GetBase64(GetFullFile($"{basePath}.state"));
|
||||
info.Artifacts["state"] = GetBase64(GetFullFile($"{basePath}.state")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.subcode"))
|
||||
info.Artifacts["subcode"] = GetBase64(GetFullFile($"{basePath}.subcode"));
|
||||
info.Artifacts["subcode"] = GetBase64(GetFullFile($"{basePath}.subcode")) ?? string.Empty;
|
||||
if (File.Exists($"{basePath}.toc"))
|
||||
info.Artifacts["toc"] = GetBase64(GetFullFile($"{basePath}.toc"));
|
||||
info.Artifacts["toc"] = GetBase64(GetFullFile($"{basePath}.toc")) ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,7 +877,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public override string GetDefaultExtension(MediaType? mediaType) => Converters.Extension(mediaType);
|
||||
#else
|
||||
public override string? GetDefaultExtension(MediaType? mediaType) => Converters.Extension(mediaType);
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<string> GetLogFilePaths(string basePath)
|
||||
@@ -818,11 +936,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
public override bool IsDumpingCommand()
|
||||
{
|
||||
return this.BaseCommand == CommandStrings.NONE
|
||||
|| this.BaseCommand.Contains(CommandStrings.CD)
|
||||
|| this.BaseCommand.Contains(CommandStrings.DVD)
|
||||
|| this.BaseCommand.Contains(CommandStrings.BluRay)
|
||||
|| this.BaseCommand.Contains(CommandStrings.SACD)
|
||||
|| this.BaseCommand.Contains(CommandStrings.Dump);
|
||||
|| this.BaseCommand?.Contains(CommandStrings.CD) == true
|
||||
|| this.BaseCommand?.Contains(CommandStrings.DVD) == true
|
||||
|| this.BaseCommand?.Contains(CommandStrings.BluRay) == true
|
||||
|| this.BaseCommand?.Contains(CommandStrings.SACD) == true
|
||||
|| this.BaseCommand?.Contains(CommandStrings.Dump) == true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -908,7 +1026,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
// Set the output paths
|
||||
if (!string.IsNullOrWhiteSpace(filename))
|
||||
{
|
||||
string imagePath = Path.GetDirectoryName(filename);
|
||||
var imagePath = Path.GetDirectoryName(filename);
|
||||
if (!string.IsNullOrWhiteSpace(imagePath))
|
||||
{
|
||||
this[FlagStrings.ImagePath] = true;
|
||||
@@ -996,7 +1114,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
// Flag read-out values
|
||||
byte? byteValue = null;
|
||||
int? intValue = null;
|
||||
#if NET48
|
||||
string stringValue = null;
|
||||
#else
|
||||
string? stringValue = null;
|
||||
#endif
|
||||
|
||||
#region General
|
||||
|
||||
@@ -1176,7 +1298,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Newline-delimited cuesheet if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetCuesheet(string log)
|
||||
#else
|
||||
private static string? GetCuesheet(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -1187,16 +1313,20 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Fast forward to the dat line
|
||||
while (!sr.EndOfStream && !sr.ReadLine().TrimStart().StartsWith("CUE [")) ;
|
||||
while (!sr.EndOfStream && sr.ReadLine()?.TrimStart()?.StartsWith("CUE [") == false) ;
|
||||
if (sr.EndOfStream)
|
||||
return null;
|
||||
|
||||
// Now that we're at the relevant entries, read each line in and concatenate
|
||||
string cueString = "", line = sr.ReadLine().Trim();
|
||||
#if NET48
|
||||
string cueString = string.Empty, line = sr.ReadLine()?.Trim();
|
||||
#else
|
||||
string? cueString = string.Empty, line = sr.ReadLine()?.Trim();
|
||||
#endif
|
||||
while (!string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
cueString += line + "\n";
|
||||
line = sr.ReadLine().Trim();
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
|
||||
return cueString.TrimEnd('\n');
|
||||
@@ -1214,7 +1344,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Newline-delimited datfile if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetDatfile(string log)
|
||||
#else
|
||||
private static string? GetDatfile(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -1225,13 +1359,14 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Fast forward to the dat line
|
||||
while (!sr.EndOfStream && !sr.ReadLine().TrimStart().StartsWith("dat:")) ;
|
||||
while (!sr.EndOfStream && sr.ReadLine()?.TrimStart()?.StartsWith("dat:") == false) ;
|
||||
if (sr.EndOfStream)
|
||||
return null;
|
||||
|
||||
// Now that we're at the relevant entries, read each line in and concatenate
|
||||
string datString = "", line = sr.ReadLine().Trim();
|
||||
while (line.StartsWith("<rom"))
|
||||
var datString = string.Empty;
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
while (line?.StartsWith("<rom") == true)
|
||||
{
|
||||
datString += line + "\n";
|
||||
if (sr.EndOfStream)
|
||||
@@ -1255,23 +1390,31 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Formatted string representing the DVD protection, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetDVDProtection(string log)
|
||||
#else
|
||||
private static string? GetDVDProtection(string log)
|
||||
#endif
|
||||
{
|
||||
// If one of the files doesn't exist, we can't get info from them
|
||||
if (!File.Exists(log))
|
||||
return null;
|
||||
|
||||
// Setup all of the individual pieces
|
||||
#if NET48
|
||||
string region = null, rceProtection = null, copyrightProtectionSystemType = null, vobKeys = null, decryptedDiscKey = null;
|
||||
#else
|
||||
string? region = null, rceProtection = null, copyrightProtectionSystemType = null, vobKeys = null, decryptedDiscKey = null;
|
||||
#endif
|
||||
using (StreamReader sr = File.OpenText(log))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Fast forward to the copyright information
|
||||
while (!sr.ReadLine().Trim().StartsWith("copyright:")) ;
|
||||
while (sr.ReadLine()?.Trim().StartsWith("copyright:") == false) ;
|
||||
|
||||
// Now read until we hit the manufacturing information
|
||||
string line = sr.ReadLine()?.Trim();
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
while (line != null && !sr.EndOfStream)
|
||||
{
|
||||
if (line.StartsWith("protection system type"))
|
||||
@@ -1369,7 +1512,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Fast forward to the errors lines
|
||||
while (!sr.EndOfStream && !sr.ReadLine().Trim().StartsWith("CD-ROM [")) ;
|
||||
while (!sr.EndOfStream && sr.ReadLine()?.Trim()?.StartsWith("CD-ROM [") == false) ;
|
||||
if (sr.EndOfStream)
|
||||
return 0;
|
||||
|
||||
@@ -1377,9 +1520,9 @@ namespace MPF.Core.Modules.Redumper
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
// Skip forward to the "REDUMP.ORG" line
|
||||
string line = string.Empty;
|
||||
while (!sr.EndOfStream && !(line = sr.ReadLine().Trim()).StartsWith("REDUMP.ORG errors")) ;
|
||||
if (line == string.Empty)
|
||||
var line = string.Empty;
|
||||
while (!sr.EndOfStream && (line = sr.ReadLine()?.Trim())?.StartsWith("REDUMP.ORG errors") == false) ;
|
||||
if (string.IsNullOrEmpty(line))
|
||||
break;
|
||||
|
||||
// REDUMP.ORG errors: <error count>
|
||||
@@ -1405,7 +1548,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Layerbreak if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetLayerbreak(string log)
|
||||
#else
|
||||
private static string? GetLayerbreak(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -1416,15 +1563,19 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Fast forward to the disc structure lines
|
||||
while (!sr.EndOfStream && !sr.ReadLine().Trim().StartsWith("layer 0")) ;
|
||||
while (!sr.EndOfStream && sr.ReadLine()?.Trim()?.StartsWith("layer 0") == false) ;
|
||||
if (sr.EndOfStream)
|
||||
return null;
|
||||
|
||||
// Now that we're at the relevant lines, find the layerbreak
|
||||
#if NET48
|
||||
string layerbreak = null;
|
||||
#else
|
||||
string? layerbreak = null;
|
||||
#endif
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine()?.Trim();
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
|
||||
// If we have a null line, just break
|
||||
if (line == null)
|
||||
@@ -1476,7 +1627,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Formatted multisession information, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetMultisessionInformation(string log)
|
||||
#else
|
||||
private static string? GetMultisessionInformation(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -1487,15 +1642,19 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Fast forward to the multisession lines
|
||||
while (!sr.EndOfStream && !sr.ReadLine().Trim().StartsWith("multisession:")) ;
|
||||
while (!sr.EndOfStream && sr.ReadLine()?.Trim()?.StartsWith("multisession:") == false) ;
|
||||
if (sr.EndOfStream)
|
||||
return null;
|
||||
|
||||
// Now that we're at the relevant lines, find the session info
|
||||
#if NET48
|
||||
string firstSession = null, secondSession = null;
|
||||
#else
|
||||
string? firstSession = null, secondSession = null;
|
||||
#endif
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine()?.Trim();
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
|
||||
// If we have a null line, just break
|
||||
if (line == null)
|
||||
@@ -1549,7 +1708,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Check for the anti-modchip strings
|
||||
string line = sr.ReadLine().Trim();
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
if (line == null)
|
||||
@@ -1560,7 +1719,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
else if (line.StartsWith("anti-modchip: yes"))
|
||||
return true;
|
||||
|
||||
line = sr.ReadLine().Trim();
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1589,7 +1748,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Check for the EDC strings
|
||||
string line = sr.ReadLine().Trim();
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
if (line == null)
|
||||
@@ -1600,7 +1759,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
else if (line.Contains("EDC: yes"))
|
||||
return true;
|
||||
|
||||
line = sr.ReadLine().Trim();
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1618,7 +1777,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>PS1 LibCrypt data, if possible</returns>
|
||||
#if NET48
|
||||
private static string GetPlayStationLibCryptData(string log)
|
||||
#else
|
||||
private static string? GetPlayStationLibCryptData(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -1629,16 +1792,20 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Fast forward to the LibCrypt line
|
||||
while (!sr.EndOfStream && !sr.ReadLine().TrimStart().StartsWith("libcrypt:")) ;
|
||||
while (!sr.EndOfStream && sr.ReadLine()?.TrimStart()?.StartsWith("libcrypt:") == false) ;
|
||||
if (sr.EndOfStream)
|
||||
return null;
|
||||
|
||||
// Now that we're at the relevant entries, read each line in and concatenate
|
||||
string libCryptString = "", line = sr.ReadLine().Trim();
|
||||
while (line.StartsWith("MSF:"))
|
||||
#if NET48
|
||||
string libCryptString = "", line = sr.ReadLine()?.Trim();
|
||||
#else
|
||||
string? libCryptString = "", line = sr.ReadLine()?.Trim();
|
||||
#endif
|
||||
while (line?.StartsWith("MSF:") == true)
|
||||
{
|
||||
libCryptString += line + "\n";
|
||||
line = sr.ReadLine().Trim();
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
|
||||
return libCryptString.TrimEnd('\n');
|
||||
@@ -1667,7 +1834,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Check for the libcrypt strings
|
||||
string line = sr.ReadLine().Trim();
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
if (line == null)
|
||||
@@ -1678,7 +1845,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
else if (line.StartsWith("libcrypt: yes"))
|
||||
return true;
|
||||
|
||||
line = sr.ReadLine().Trim();
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1696,7 +1863,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Newline-delimited PVD if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetPVD(string log)
|
||||
#else
|
||||
private static string? GetPVD(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -1707,16 +1878,20 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Fast forward to the PVD line
|
||||
while (!sr.EndOfStream && !sr.ReadLine().TrimStart().StartsWith("PVD:")) ;
|
||||
while (!sr.EndOfStream && sr.ReadLine()?.TrimStart()?.StartsWith("PVD:") == false) ;
|
||||
if (sr.EndOfStream)
|
||||
return null;
|
||||
|
||||
// Now that we're at the relevant entries, read each line in and concatenate
|
||||
string pvdString = "", line = sr.ReadLine().Trim();
|
||||
while (line.StartsWith("03"))
|
||||
#if NET48
|
||||
string pvdString = "", line = sr.ReadLine()?.Trim();
|
||||
#else
|
||||
string? pvdString = "", line = sr.ReadLine()?.Trim();
|
||||
#endif
|
||||
while (line?.StartsWith("03") == true)
|
||||
{
|
||||
pvdString += line + "\n";
|
||||
line = sr.ReadLine().Trim();
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
|
||||
return pvdString.TrimEnd('\n');
|
||||
@@ -1734,7 +1909,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Non-zero dta start if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetRingNonZeroDataStart(string log)
|
||||
#else
|
||||
private static string? GetRingNonZeroDataStart(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -1745,11 +1924,15 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// If we find the sample range, return the start value only
|
||||
#if NET48
|
||||
string line;
|
||||
#else
|
||||
string? line;
|
||||
#endif
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
line = sr.ReadLine().TrimStart();
|
||||
if (line.StartsWith("non-zero data sample range"))
|
||||
line = sr.ReadLine()?.TrimStart();
|
||||
if (line?.StartsWith("non-zero data sample range") == true)
|
||||
#if NET48
|
||||
return line.Substring("non-zero data sample range: [".Length).Trim().Split(' ')[0];
|
||||
#else
|
||||
@@ -1773,8 +1956,12 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <<param name="segaHeader">String representing a formatter variant of the Saturn header</param>
|
||||
/// <returns>True on successful extraction of info, false otherwise</returns>
|
||||
/// TODO: Remove when Redumpe gets native reading support
|
||||
/// TODO: Remove when Redumper gets native reading support
|
||||
#if NET48
|
||||
private static bool GetSaturnBuildInfo(string segaHeader, out string serial, out string version, out string date)
|
||||
#else
|
||||
private static bool GetSaturnBuildInfo(string? segaHeader, out string? serial, out string? version, out string? date)
|
||||
#endif
|
||||
{
|
||||
serial = null; version = null; date = null;
|
||||
|
||||
@@ -1814,7 +2001,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Header as a byte array if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetSaturnHeader(string log)
|
||||
#else
|
||||
private static string? GetSaturnHeader(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -1825,21 +2016,25 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Fast forward to the SS line
|
||||
while (!sr.EndOfStream && !sr.ReadLine().TrimStart().StartsWith("SS [")) ;
|
||||
while (!sr.EndOfStream && sr.ReadLine()?.TrimStart()?.StartsWith("SS [") == false) ;
|
||||
if (sr.EndOfStream)
|
||||
return null;
|
||||
|
||||
#if NET48
|
||||
string line, headerString = "";
|
||||
#else
|
||||
string? line, headerString = "";
|
||||
#endif
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
line = sr.ReadLine().TrimStart();
|
||||
if (line.StartsWith("header:"))
|
||||
line = sr.ReadLine()?.TrimStart();
|
||||
if (line?.StartsWith("header:") == true)
|
||||
{
|
||||
line = sr.ReadLine().TrimStart();
|
||||
while (line.StartsWith("00"))
|
||||
line = sr.ReadLine()?.TrimStart();
|
||||
while (line?.StartsWith("00") == true)
|
||||
{
|
||||
headerString += line + "\n";
|
||||
line = sr.ReadLine().Trim();
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1863,7 +2058,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Header as a byte array if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetSegaCDHeader(string log, out string buildDate, out string serial, out string region)
|
||||
#else
|
||||
private static string? GetSegaCDHeader(string log, out string? buildDate, out string? serial, out string? region)
|
||||
#endif
|
||||
{
|
||||
// Set the default values
|
||||
buildDate = null; serial = null; region = null;
|
||||
@@ -1877,14 +2076,21 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// Fast forward to the MCD line
|
||||
while (!sr.EndOfStream && !sr.ReadLine().TrimStart().StartsWith("MCD [")) ;
|
||||
while (!sr.EndOfStream && sr.ReadLine()?.TrimStart()?.StartsWith("MCD [") == false) ;
|
||||
if (sr.EndOfStream)
|
||||
return null;
|
||||
|
||||
string line, headerString = "";
|
||||
#if NET48
|
||||
string line, headerString = string.Empty;
|
||||
#else
|
||||
string? line, headerString = string.Empty;
|
||||
#endif
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
line = sr.ReadLine().TrimStart();
|
||||
line = sr.ReadLine()?.TrimStart();
|
||||
if (line == null)
|
||||
break;
|
||||
|
||||
if (line.StartsWith("build date:"))
|
||||
{
|
||||
#if NET48
|
||||
@@ -1919,11 +2125,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
}
|
||||
else if (line.StartsWith("header:"))
|
||||
{
|
||||
line = sr.ReadLine().TrimStart();
|
||||
while (line.StartsWith("01"))
|
||||
line = sr.ReadLine()?.TrimStart();
|
||||
while (line?.StartsWith("01") == true)
|
||||
{
|
||||
headerString += line + "\n";
|
||||
line = sr.ReadLine().Trim();
|
||||
line = sr.ReadLine()?.Trim();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1947,7 +2153,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Universal hash if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetUniversalHash(string log)
|
||||
#else
|
||||
private static string? GetUniversalHash(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -1958,11 +2168,15 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// If we find the universal hash line, return the hash only
|
||||
#if NET48
|
||||
string line;
|
||||
#else
|
||||
string? line;
|
||||
#endif
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
line = sr.ReadLine().TrimStart();
|
||||
if (line.StartsWith("Universal Hash"))
|
||||
line = sr.ReadLine()?.TrimStart();
|
||||
if (line?.StartsWith("Universal Hash") == true)
|
||||
#if NET48
|
||||
return line.Substring("Universal Hash (SHA-1): ".Length).Trim();
|
||||
#else
|
||||
@@ -1986,7 +2200,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Sample write offset if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetWriteOffset(string log)
|
||||
#else
|
||||
private static string? GetWriteOffset(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -1997,11 +2215,15 @@ namespace MPF.Core.Modules.Redumper
|
||||
try
|
||||
{
|
||||
// If we find the disc write offset line, return the offset
|
||||
#if NET48
|
||||
string line;
|
||||
#else
|
||||
string? line;
|
||||
#endif
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
line = sr.ReadLine().TrimStart();
|
||||
if (line.StartsWith("disc write offset"))
|
||||
line = sr.ReadLine()?.TrimStart();
|
||||
if (line?.StartsWith("disc write offset") == true)
|
||||
#if NET48
|
||||
return line.Substring("disc write offset: ".Length).Trim();
|
||||
#else
|
||||
@@ -2025,7 +2247,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>Version if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetVersion(string log)
|
||||
#else
|
||||
private static string? GetVersion(string log)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(log))
|
||||
@@ -2049,7 +2275,7 @@ namespace MPF.Core.Modules.Redumper
|
||||
//var regex = new Regex(@"^redumper (v\d{4}\.\d{2}\.\d{2}(| build_\d+)) \[.+\]");
|
||||
|
||||
// Extract the version string
|
||||
var match = regex.Match(sr.ReadLine().Trim());
|
||||
var match = regex.Match(sr.ReadLine()?.Trim() ?? string.Empty);
|
||||
var version = match.Groups[1].Value;
|
||||
return string.IsNullOrWhiteSpace(version) ? null : version;
|
||||
}
|
||||
@@ -2066,7 +2292,11 @@ namespace MPF.Core.Modules.Redumper
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>True if hardware info was set, false otherwise</returns>
|
||||
#if NET48
|
||||
private static bool GetHardwareInfo(string log, out string manufacturer, out string model, out string firmware)
|
||||
#else
|
||||
private static bool GetHardwareInfo(string log, out string? manufacturer, out string? model, out string? firmware)
|
||||
#endif
|
||||
{
|
||||
// Set the default values
|
||||
manufacturer = null; model = null; firmware = null;
|
||||
@@ -2085,7 +2315,12 @@ namespace MPF.Core.Modules.Redumper
|
||||
// If we find the hardware info line, return each value
|
||||
// drive: <vendor_id> - <product_id> (revision level: <product_revision_level>, vendor specific: <vendor_specific>)
|
||||
var regex = new Regex(@"drive: (.+) - (.+) \(revision level: (.+), vendor specific: (.+)\)");
|
||||
|
||||
#if NET48
|
||||
string line;
|
||||
#else
|
||||
string? line;
|
||||
#endif
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
var match = regex.Match(line.Trim());
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive drive, bool includeArtifacts)
|
||||
{
|
||||
// TODO: Determine if there's a UMDImageCreator version anywhere
|
||||
if (info.DumpingInfo == null) info.DumpingInfo = new DumpingInfoSection();
|
||||
info.DumpingInfo.DumpingProgram = EnumConverter.LongName(this.InternalProgram);
|
||||
info.DumpingInfo.DumpingDate = GetFileModifiedDate(basePath + "_disc.txt")?.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@@ -71,21 +72,26 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
switch (this.Type)
|
||||
{
|
||||
case MediaType.UMD:
|
||||
if (info.Extras == null) info.Extras = new ExtrasSection();
|
||||
info.Extras.PVD = GetPVD(basePath + "_mainInfo.txt") ?? string.Empty;
|
||||
|
||||
if (GetFileHashes(basePath + ".iso", out long filesize, out string crc32, out string md5, out string sha1))
|
||||
if (GetFileHashes(basePath + ".iso", out long filesize, out var crc32, out var md5, out var sha1))
|
||||
{
|
||||
if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
|
||||
info.SizeAndChecksums.Size = filesize;
|
||||
info.SizeAndChecksums.CRC32 = crc32;
|
||||
info.SizeAndChecksums.MD5 = md5;
|
||||
info.SizeAndChecksums.SHA1 = sha1;
|
||||
}
|
||||
|
||||
if (GetUMDAuxInfo(basePath + "_disc.txt", out string title, out DiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize))
|
||||
if (GetUMDAuxInfo(basePath + "_disc.txt", out var title, out DiscCategory? umdcat, out var umdversion, out var umdlayer, out long umdsize))
|
||||
{
|
||||
if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
|
||||
info.CommonDiscInfo.Title = title ?? string.Empty;
|
||||
info.CommonDiscInfo.Category = umdcat ?? DiscCategory.Games;
|
||||
if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
|
||||
info.VersionAndEditions.Version = umdversion ?? string.Empty;
|
||||
if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
|
||||
info.SizeAndChecksums.Size = umdsize;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(umdlayer))
|
||||
@@ -98,16 +104,17 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
// Fill in any artifacts that exist, Base64-encoded, if we need to
|
||||
if (includeArtifacts)
|
||||
{
|
||||
if (info.Artifacts == null) info.Artifacts = new Dictionary<string, string>();
|
||||
if (File.Exists(basePath + "_disc.txt"))
|
||||
info.Artifacts["disc"] = GetBase64(GetFullFile(basePath + "_disc.txt"));
|
||||
info.Artifacts["disc"] = GetBase64(GetFullFile(basePath + "_disc.txt")) ?? string.Empty;
|
||||
if (File.Exists(basePath + "_drive.txt"))
|
||||
info.Artifacts["drive"] = GetBase64(GetFullFile(basePath + "_drive.txt"));
|
||||
info.Artifacts["drive"] = GetBase64(GetFullFile(basePath + "_drive.txt")) ?? string.Empty;
|
||||
if (File.Exists(basePath + "_mainError.txt"))
|
||||
info.Artifacts["mainError"] = GetBase64(GetFullFile(basePath + "_mainError.txt"));
|
||||
info.Artifacts["mainError"] = GetBase64(GetFullFile(basePath + "_mainError.txt")) ?? string.Empty;
|
||||
if (File.Exists(basePath + "_mainInfo.txt"))
|
||||
info.Artifacts["mainInfo"] = GetBase64(GetFullFile(basePath + "_mainInfo.txt"));
|
||||
info.Artifacts["mainInfo"] = GetBase64(GetFullFile(basePath + "_mainInfo.txt")) ?? string.Empty;
|
||||
if (File.Exists(basePath + "_volDesc.txt"))
|
||||
info.Artifacts["volDesc"] = GetBase64(GetFullFile(basePath + "_volDesc.txt"));
|
||||
info.Artifacts["volDesc"] = GetBase64(GetFullFile(basePath + "_volDesc.txt")) ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +151,11 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
/// </summary>
|
||||
/// <param name="mainInfo">_mainInfo.txt file location</param>
|
||||
/// <returns>Newline-deliminated PVD if possible, null on error</returns>
|
||||
#if NET48
|
||||
private static string GetPVD(string mainInfo)
|
||||
#else
|
||||
private static string? GetPVD(string mainInfo)
|
||||
#endif
|
||||
{
|
||||
// If the file doesn't exist, we can't get info from it
|
||||
if (!File.Exists(mainInfo))
|
||||
@@ -155,10 +166,10 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
try
|
||||
{
|
||||
// Make sure we're in the right sector
|
||||
while (!sr.ReadLine().StartsWith("========== LBA[000016, 0x0000010]: Main Channel ==========")) ;
|
||||
while (sr.ReadLine()?.StartsWith("========== LBA[000016, 0x0000010]: Main Channel ==========") == false) ;
|
||||
|
||||
// Fast forward to the PVD
|
||||
while (!sr.ReadLine().StartsWith("0310")) ;
|
||||
while (sr.ReadLine()?.StartsWith("0310") == false) ;
|
||||
|
||||
// Now that we're at the PVD, read each line in and concatenate
|
||||
string pvd = "";
|
||||
@@ -180,7 +191,11 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
/// </summary>
|
||||
/// <param name="disc">_disc.txt file location</param>
|
||||
/// <returns>True on successful extraction of info, false otherwise</returns>
|
||||
#if NET48
|
||||
private static bool GetUMDAuxInfo(string disc, out string title, out DiscCategory? umdcat, out string umdversion, out string umdlayer, out long umdsize)
|
||||
#else
|
||||
private static bool GetUMDAuxInfo(string disc, out string? title, out DiscCategory? umdcat, out string? umdversion, out string? umdlayer, out long umdsize)
|
||||
#endif
|
||||
{
|
||||
title = null; umdcat = null; umdversion = null; umdlayer = null; umdsize = -1;
|
||||
|
||||
@@ -193,10 +208,12 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
try
|
||||
{
|
||||
// Loop through everything to get the first instance of each required field
|
||||
string line = string.Empty;
|
||||
var line = string.Empty;
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
line = sr.ReadLine().Trim();
|
||||
line = sr.ReadLine()?.Trim();
|
||||
if (line == null)
|
||||
break;
|
||||
|
||||
if (line.StartsWith("TITLE") && title == null)
|
||||
title = line.Substring("TITLE: ".Length);
|
||||
@@ -211,7 +228,7 @@ namespace MPF.Core.Modules.UmdImageCreator
|
||||
}
|
||||
|
||||
// If the L0 length is the size of the full disc, there's no layerbreak
|
||||
if (Int64.Parse(umdlayer) * 2048 == umdsize)
|
||||
if (Int64.TryParse(umdlayer, out long umdlayerValue) && umdlayerValue * 2048 == umdsize)
|
||||
umdlayer = null;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -19,7 +19,11 @@ namespace MPF.Core
|
||||
/// <param name="options">Options object that determines what to scan</param>
|
||||
/// <param name="progress">Optional progress callback</param>
|
||||
/// <returns>Set of all detected copy protections with an optional error string</returns>
|
||||
public static async Task<(Dictionary<string, List<string>>, string)> RunProtectionScanOnPath(string path, Core.Data.Options options, IProgress<ProtectionProgress> progress = null)
|
||||
#if NET48
|
||||
public static async Task<(Dictionary<string, List<string>>, string)> RunProtectionScanOnPath(string path, Data.Options options, IProgress<ProtectionProgress> progress = null)
|
||||
#else
|
||||
public static async Task<(Dictionary<string, List<string>>?, string?)> RunProtectionScanOnPath(string path, Data.Options options, IProgress<ProtectionProgress>? progress = null)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -62,7 +66,11 @@ namespace MPF.Core
|
||||
/// </summary>
|
||||
/// <param name="protections">Dictionary of file to list of protection mappings</param>
|
||||
/// <returns>Detected protections, if any</returns>
|
||||
#if NET48
|
||||
public static string FormatProtections(Dictionary<string, List<string>> protections)
|
||||
#else
|
||||
public static string? FormatProtections(Dictionary<string, List<string>>? protections)
|
||||
#endif
|
||||
{
|
||||
// If the filtered list is empty in some way, return
|
||||
if (protections == null || !protections.Any())
|
||||
|
||||
@@ -14,7 +14,11 @@ namespace MPF.Core.Utilities
|
||||
/// <param name="reader">TextReader representing the input</param>
|
||||
/// <param name="baseClass">Invoking class, passed on to the event handler</param>
|
||||
/// <param name="handler">Event handler to be invoked to write to log</param>
|
||||
#if NET48
|
||||
public static async Task OutputToLog(TextReader reader, object baseClass, EventHandler<string> handler)
|
||||
#else
|
||||
public static async Task OutputToLog(TextReader reader, object baseClass, EventHandler<string>? handler)
|
||||
#endif
|
||||
{
|
||||
// Initialize the required variables
|
||||
char[] buffer = new char[256];
|
||||
@@ -63,7 +67,11 @@ namespace MPF.Core.Utilities
|
||||
/// <param name="line">Current line to process</param>
|
||||
/// <param name="baseClass">Invoking class, passed on to the event handler</param>
|
||||
/// <param name="handler">Event handler to be invoked to write to log</param>
|
||||
#if NET48
|
||||
private static void ProcessNewLines(StringBuilder sb, string line, object baseClass, EventHandler<string> handler)
|
||||
#else
|
||||
private static void ProcessNewLines(StringBuilder sb, string line, object baseClass, EventHandler<string>? handler)
|
||||
#endif
|
||||
{
|
||||
line = line.Replace("\r\n", "\n");
|
||||
var split = line.Split('\n');
|
||||
@@ -105,7 +113,11 @@ namespace MPF.Core.Utilities
|
||||
/// <param name="line">Current line to process</param>
|
||||
/// <param name="baseClass">Invoking class, passed on to the event handler</param>
|
||||
/// <param name="handler">Event handler to be invoked to write to log</param>
|
||||
#if NET48
|
||||
private static void ProcessCarriageReturns(StringBuilder sb, string line, object baseClass, EventHandler<string> handler)
|
||||
#else
|
||||
private static void ProcessCarriageReturns(StringBuilder sb, string line, object baseClass, EventHandler<string>? handler)
|
||||
#endif
|
||||
{
|
||||
var split = line.Split('\r');
|
||||
|
||||
|
||||
@@ -15,7 +15,11 @@ namespace MPF.Core.Utilities
|
||||
/// <summary>
|
||||
/// Load the current set of options from application arguments
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static (Options, string, int) LoadFromArguments(string[] args, int startIndex = 0)
|
||||
#else
|
||||
public static (Options, string?, int) LoadFromArguments(string[] args, int startIndex = 0)
|
||||
#endif
|
||||
{
|
||||
// Create the output values with defaults
|
||||
var options = new Options()
|
||||
@@ -27,7 +31,11 @@ namespace MPF.Core.Utilities
|
||||
CompressLogFiles = false,
|
||||
};
|
||||
|
||||
#if NET48
|
||||
string parsedPath = null;
|
||||
#else
|
||||
string? parsedPath = null;
|
||||
#endif
|
||||
|
||||
// These values require multiple parts to be active
|
||||
bool scan = false, protectFile = false;
|
||||
@@ -154,7 +162,11 @@ namespace MPF.Core.Utilities
|
||||
|
||||
var serializer = JsonSerializer.Create();
|
||||
var reader = new StreamReader(ConfigurationPath);
|
||||
#if NET48
|
||||
var settings = serializer.Deserialize(reader, typeof(Dictionary<string, string>)) as Dictionary<string, string>;
|
||||
#else
|
||||
var settings = serializer.Deserialize(reader, typeof(Dictionary<string, string?>)) as Dictionary<string, string?>;
|
||||
#endif
|
||||
return new Options(settings);
|
||||
}
|
||||
|
||||
|
||||
@@ -130,16 +130,23 @@ namespace MPF.Core.Utilities
|
||||
/// String representing the message to display the the user.
|
||||
/// String representing the new release URL.
|
||||
/// </returns>
|
||||
#if NET48
|
||||
public static (bool different, string message, string url) CheckForNewVersion()
|
||||
#else
|
||||
public static (bool different, string message, string? url) CheckForNewVersion()
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get current assembly version
|
||||
var assemblyVersion = Assembly.GetEntryAssembly().GetName().Version;
|
||||
var assemblyVersion = Assembly.GetEntryAssembly()?.GetName()?.Version;
|
||||
if (assemblyVersion == null)
|
||||
return (false, "Assembly version could not be determined", null);
|
||||
|
||||
string version = $"{assemblyVersion.Major}.{assemblyVersion.Minor}" + (assemblyVersion.Build != 0 ? $".{assemblyVersion.Build}" : string.Empty);
|
||||
|
||||
// Get the latest tag from GitHub
|
||||
(string tag, string url) = GetRemoteVersionAndUrl();
|
||||
var (tag, url) = GetRemoteVersionAndUrl();
|
||||
bool different = version != tag;
|
||||
|
||||
string message = $"Local version: {version}"
|
||||
@@ -159,12 +166,20 @@ namespace MPF.Core.Utilities
|
||||
/// <summary>
|
||||
/// Get the current informational version formatted as a string
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static string GetCurrentVersion()
|
||||
#else
|
||||
public static string? GetCurrentVersion()
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
var assemblyVersion = Attribute.GetCustomAttribute(Assembly.GetEntryAssembly(), typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute;
|
||||
return assemblyVersion.InformationalVersion;
|
||||
var assembly = Assembly.GetEntryAssembly();
|
||||
if (assembly == null)
|
||||
return null;
|
||||
|
||||
var assemblyVersion = Attribute.GetCustomAttribute(assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute;
|
||||
return assemblyVersion?.InformationalVersion;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -175,9 +190,13 @@ namespace MPF.Core.Utilities
|
||||
/// <summary>
|
||||
/// Get the latest version of MPF from GitHub and the release URL
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static (string tag, string url) GetRemoteVersionAndUrl()
|
||||
#else
|
||||
private static (string? tag, string? url) GetRemoteVersionAndUrl()
|
||||
#endif
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
#if NET48
|
||||
using (System.Net.WebClient wc = new System.Net.WebClient())
|
||||
{
|
||||
wc.Headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0";
|
||||
@@ -198,10 +217,16 @@ namespace MPF.Core.Utilities
|
||||
string url = "https://api.github.com/repos/SabreTools/MPF/releases/latest";
|
||||
var message = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url);
|
||||
message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0");
|
||||
string latestReleaseJsonString = hc.Send(message)?.Content?.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
var latestReleaseJsonString = hc.Send(message)?.Content?.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
if (latestReleaseJsonString == null)
|
||||
return (null, null);
|
||||
|
||||
var latestReleaseJson = JObject.Parse(latestReleaseJsonString);
|
||||
string latestTag = latestReleaseJson["tag_name"].ToString();
|
||||
string releaseUrl = latestReleaseJson["html_url"].ToString();
|
||||
if (latestReleaseJson == null)
|
||||
return (null, null);
|
||||
|
||||
var latestTag = latestReleaseJson["tag_name"]?.ToString();
|
||||
var releaseUrl = latestReleaseJson["html_url"]?.ToString();
|
||||
|
||||
return (latestTag, releaseUrl);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user