diff --git a/CHANGELIST.md b/CHANGELIST.md
index 72f97d7e..9812ef05 100644
--- a/CHANGELIST.md
+++ b/CHANGELIST.md
@@ -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)
diff --git a/MPF.Core/Converters/EnumConverter.cs b/MPF.Core/Converters/EnumConverter.cs
index 771bf2b9..8c91efbf 100644
--- a/MPF.Core/Converters/EnumConverter.cs
+++ b/MPF.Core/Converters/EnumConverter.cs
@@ -38,7 +38,11 @@ namespace MPF.Core.Converters
///
/// Long name method cache
///
+#if NET48
private static readonly ConcurrentDictionary LongNameMethods = new ConcurrentDictionary();
+#else
+ private static readonly ConcurrentDictionary LongNameMethods = new ConcurrentDictionary();
+#endif
///
/// 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
///
/// String value to convert
/// InternalProgram represented by the string, if possible
+#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":
diff --git a/MPF.Core/Data/Drive.cs b/MPF.Core/Data/Drive.cs
index 8918c6b7..d4061268 100644
--- a/MPF.Core/Data/Drive.cs
+++ b/MPF.Core/Data/Drive.cs
@@ -29,12 +29,20 @@ namespace MPF.Core.Data
///
/// Drive partition format
///
+#if NET48
public string DriveFormat { get; private set; } = null;
+#else
+ public string? DriveFormat { get; private set; } = null;
+#endif
///
/// Windows drive path
///
+#if NET48
public string Name { get; private set; } = null;
+#else
+ public string? Name { get; private set; } = null;
+#endif
///
/// Represents if Windows has marked the drive as active
@@ -50,7 +58,11 @@ namespace MPF.Core.Data
/// Media label as read by Windows
///
/// The try/catch is needed because Windows will throw an exception if the drive is not marked as active
+#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
///
/// Media label as read by Windows, formatted to avoid odd outputs
///
+#if NET48
public string FormattedVolumeLabel
+#else
+ public string? FormattedVolumeLabel
+#endif
{
get
{
@@ -96,7 +112,11 @@ namespace MPF.Core.Data
///
/// InternalDriveType value representing the drive type
/// Path to the device according to the local machine
+#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
///
/// DriveInfo object to populate from
+#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
///
/// True to ignore fixed drives from population, false otherwise
/// Active drives, matched to labels, if possible
+#if NET48
public static List CreateListOfDrives(bool ignoreFixedDrives)
+#else
+ public static List 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
///
///
///
+#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
/// Sector number, non-negative
/// Size of a sector in bytes
/// Byte array representing the sector, null on error
+#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
///
+#if NET48
private static List GetDriveList(bool ignoreFixedDrives)
+#else
+ private static List GetDriveList(bool ignoreFixedDrives)
+#endif
{
var desiredDriveTypes = new List() { 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();
+#else
+ var drives = new List();
+#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; } });
}
}
}
diff --git a/MPF.Core/Data/IniFile.cs b/MPF.Core/Data/IniFile.cs
index 953c09a9..40c082fc 100644
--- a/MPF.Core/Data/IniFile.cs
+++ b/MPF.Core/Data/IniFile.cs
@@ -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)_keyValuePairs).TryGetValue(key.ToLowerInvariant(), out value);
+ bool result = ((IDictionary)_keyValuePairs).TryGetValue(key.ToLowerInvariant(), out var temp);
+ value = temp ?? string.Empty;
+ return result;
}
public void Add(KeyValuePair item)
diff --git a/MPF.Core/Data/Options.cs b/MPF.Core/Data/Options.cs
index cfdab2d1..fbc3b55b 100644
--- a/MPF.Core/Data/Options.cs
+++ b/MPF.Core/Data/Options.cs
@@ -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
+#if NET48
+ public class Options
+#else
+ public class Options
+#endif
{
///
/// All settings in the form of a dictionary
///
+#if NET48
public Dictionary Settings { get; private set; }
+#else
+ public Dictionary Settings { get; private set; }
+#endif
#region Internal Program
///
/// Path to Aaru
///
+#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
///
/// Path to DiscImageCreator
///
+#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
///
/// Path to Redumper
///
+#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
///
/// Default output path for dumps
///
+#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
///
///
+#if NET48
public Options(Dictionary settings = null)
+#else
+ public Options(Dictionary? settings = null)
+#endif
{
+#if NET48
this.Settings = settings ?? new Dictionary();
+#else
+ this.Settings = settings ?? new Dictionary();
+#endif
}
///
@@ -571,7 +612,24 @@ namespace MPF.Core.Data
///
public Options(Options source)
{
+#if NET48
Settings = new Dictionary(source.Settings);
+#else
+ Settings = new Dictionary(source.Settings);
+#endif
+ }
+
+ ///
+ /// Accessor for the internal dictionary
+ ///
+#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
/// Setting key to get a value for
/// Default value to return if no value is found
/// Setting value if possible, default value otherwise
+#if NET48
private bool GetBooleanSetting(Dictionary settings, string key, bool defaultValue)
+#else
+ private bool GetBooleanSetting(Dictionary 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
/// Setting key to get a value for
/// Default value to return if no value is found
/// Setting value if possible, default value otherwise
+#if NET48
private int GetInt32Setting(Dictionary settings, string key, int defaultValue)
+#else
+ private int GetInt32Setting(Dictionary 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
/// Setting key to get a value for
/// Default value to return if no value is found
/// Setting value if possible, default value otherwise
+#if NET48
private string GetStringSetting(Dictionary settings, string key, string defaultValue)
+#else
+ private string? GetStringSetting(Dictionary 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 Keys => Settings.Keys;
-
- public ICollection Values => Settings.Values;
-
- public int Count => Settings.Count;
-
- public bool IsReadOnly => ((IDictionary)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 item) => Settings.Add(item.Key, item.Value);
-
- public void Clear() => Settings.Clear();
-
- public bool Contains(KeyValuePair item) => ((IDictionary)Settings).Contains(item);
-
- public void CopyTo(KeyValuePair[] array, int arrayIndex) => ((IDictionary)Settings).CopyTo(array, arrayIndex);
-
- public bool Remove(KeyValuePair item) => ((IDictionary)Settings).Remove(item);
-
- public IEnumerator> GetEnumerator() => Settings.GetEnumerator();
-
- IEnumerator IEnumerable.GetEnumerator() => Settings.GetEnumerator();
-
- #endregion
}
}
diff --git a/MPF.Core/Data/ProcessingQueue.cs b/MPF.Core/Data/ProcessingQueue.cs
index f2522722..128e3ec3 100644
--- a/MPF.Core/Data/ProcessingQueue.cs
+++ b/MPF.Core/Data/ProcessingQueue.cs
@@ -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
diff --git a/MPF.Core/Data/Result.cs b/MPF.Core/Data/Result.cs
index e6dacea1..d025838d 100644
--- a/MPF.Core/Data/Result.cs
+++ b/MPF.Core/Data/Result.cs
@@ -30,7 +30,11 @@
/// Create a success result with a custom message
///
/// String to add as a message
+#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
///
/// Create a default failure result with no message
@@ -42,7 +46,11 @@
/// Create a failure result with a custom message
///
/// String to add as a message
+#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
///
/// Results can be compared to boolean values based on the success value
diff --git a/MPF.Core/Data/XgdInfo.cs b/MPF.Core/Data/XgdInfo.cs
index ecb943fe..aafd24ae 100644
--- a/MPF.Core/Data/XgdInfo.cs
+++ b/MPF.Core/Data/XgdInfo.cs
@@ -17,17 +17,29 @@ namespace MPF.Core.Data
///
/// Raw XMID/XeMID string that all other information is derived from
///
+#if NET48
public string RawXMID { get; private set; }
+#else
+ public string? RawXMID { get; private set; }
+#endif
///
/// XGD1 XMID
///
+#if NET48
public SabreTools.Models.Xbox.XMID XMID { get; private set; }
+#else
+ public SabreTools.Models.Xbox.XMID? XMID { get; private set; }
+#endif
///
/// XGD2/3 XeMID
///
+#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
///
/// Formatted serial string, null on error
+#if NET48
public string GetSerial()
+#else
+ public string? GetSerial()
+#endif
{
if (!this.Initialized)
return null;
@@ -86,7 +102,11 @@ namespace MPF.Core.Data
///
/// Formatted version string, null on error
/// This may differ for XGD2/3 in the future
+#if NET48
public string GetVersion()
+#else
+ public string? GetVersion()
+#endif
{
if (!this.Initialized)
return null;
@@ -160,7 +180,7 @@ namespace MPF.Core.Data
///
/// Character denoting the region
/// Region, if possible
- public static Region? GetRegion(char region)
+ public static Region? GetRegion(char? region)
{
switch (region)
{
diff --git a/MPF.Core/DumpEnvironment.cs b/MPF.Core/DumpEnvironment.cs
index f1884505..850f9f89 100644
--- a/MPF.Core/DumpEnvironment.cs
+++ b/MPF.Core/DumpEnvironment.cs
@@ -51,36 +51,52 @@ namespace MPF.Core
///
/// Options object representing user-defined options
///
- public Core.Data.Options Options { get; private set; }
+ public Data.Options Options { get; private set; }
///
/// Parameters object representing what to send to the internal program
///
+#if NET48
public BaseParameters Parameters { get; private set; }
+#else
+ public BaseParameters? Parameters { get; private set; }
+#endif
#endregion
-
+
#region Event Handlers
///
/// Generic way of reporting a message
///
+#if NET48
public EventHandler ReportStatus;
+#else
+ public EventHandler? ReportStatus;
+#endif
///
/// Queue of items that need to be logged
///
+#if NET48
private ProcessingQueue outputQueue;
+#else
+ private ProcessingQueue? outputQueue;
+#endif
///
/// Event handler for data returned from a process
///
- 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
///
/// Process the outputs in the queue
///
- 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
///
///
///
- 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;
+ }
}
///
@@ -207,7 +236,11 @@ namespace MPF.Core
///
/// Nullable int representing the drive speed
/// String representing the params, null on error
+#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
///
/// Cancel an in-progress dumping process
///
- public void CancelDumping() => Parameters.KillInternalProgram();
+ public void CancelDumping() => Parameters?.KillInternalProgram();
///
/// Eject the disc using DiscImageCreator
///
+#if NET48
public async Task EjectDisc() =>
- await RunStandaloneDiscImageCreatorCommand(Modules.DiscImageCreator.CommandStrings.Eject);
+#else
+ public async Task EjectDisc() =>
+#endif
+ await RunStandaloneDiscImageCreatorCommand(Modules.DiscImageCreator.CommandStrings.Eject);
///
/// Reset the current drive using DiscImageCreator
///
+#if NET48
public async Task ResetDrive() =>
+#else
+ public async Task ResetDrive() =>
+#endif
await RunStandaloneDiscImageCreatorCommand(Modules.DiscImageCreator.CommandStrings.Reset);
///
/// Execute the initial invocation of the dumping programs
///
/// Optional result progress callback
+#if NET48
public async Task Run(IProgress progress = null)
+#else
+ public async Task Run(IProgress? 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(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
/// Optional user prompt to deal with submission information
/// Result instance with the outcome
public async Task VerifyAndSaveDumpOutput(
+#if NET48
IProgress resultProgress = null,
IProgress protectionProgress = null,
Func processUserInfo = null)
+#else
+ IProgress? resultProgress = null,
+ IProgress? protectionProgress = null,
+ Func? 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 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 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
/// True if the configuration is valid, false otherwise
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
///
/// Command string to run
/// The output of the command on success, null on error
+#if NET48
private async Task RunStandaloneDiscImageCreatorCommand(string command)
+#else
+ private async Task 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
}
}
diff --git a/MPF.Core/Hashing/Hasher.cs b/MPF.Core/Hashing/Hasher.cs
index 80d52ff0..d179a9db 100644
--- a/MPF.Core/Hashing/Hasher.cs
+++ b/MPF.Core/Hashing/Hasher.cs
@@ -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
///
/// Get internal hash as a byte array
///
+#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
///
/// Get internal hash as a string
///
+#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
/// Byte array to convert
/// Hex string representing the byte array
/// http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa
+#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)
diff --git a/MPF.Core/Hashing/ThreadLoadBuffer.cs b/MPF.Core/Hashing/ThreadLoadBuffer.cs
index 535c95b7..00ac15df 100644
--- a/MPF.Core/Hashing/ThreadLoadBuffer.cs
+++ b/MPF.Core/Hashing/ThreadLoadBuffer.cs
@@ -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)
{
diff --git a/MPF.Core/InfoTool.cs b/MPF.Core/InfoTool.cs
index 6dcc2c8f..e8220078 100644
--- a/MPF.Core/InfoTool.cs
+++ b/MPF.Core/InfoTool.cs
@@ -35,30 +35,40 @@ namespace MPF.Core
/// Optional result progress callback
/// Optional protection progress callback
/// SubmissionInfo populated based on outputs, null on error
+#if NET48
public static async Task ExtractOutputInformation(
- string outputPath,
+#else
+ public static async Task ExtractOutputInformation(
+#endif
+ string outputPath,
Drive drive,
RedumpSystem? system,
MediaType? mediaType,
- Core.Data.Options options,
+ Data.Options options,
+#if NET48
BaseParameters parameters,
IProgress resultProgress = null,
IProgress protectionProgress = null)
+#else
+ BaseParameters? parameters,
+ IProgress? resultProgress = null,
+ IProgress? protectionProgress = null)
+#endif
{
// Ensure the current disc combination should exist
if (!system.MediaTypes().Contains(mediaType))
return null;
// Split the output path for easier use
- string outputDirectory = Path.GetDirectoryName(outputPath);
+ var outputDirectory = Path.GetDirectoryName(outputPath);
string outputFilename = Path.GetFileName(outputPath);
// Check that all of the relevant files are there
(bool foundFiles, List missingFiles) = FoundAllFiles(outputDirectory, outputFilename, parameters, false);
if (!foundFiles)
{
- resultProgress.Report(Result.Failure($"There were files missing from the output:\n{string.Join("\n", missingFiles)}"));
- resultProgress.Report(Result.Failure($"This may indicate an issue with the hardware or media, including unsupported devices.\nPlease see dumping program documentation for more details."));
+ resultProgress?.Report(Result.Failure($"There were files missing from the output:\n{string.Join("\n", missingFiles)}"));
+ resultProgress?.Report(Result.Failure($"This may indicate an issue with the hardware or media, including unsupported devices.\nPlease see dumping program documentation for more details."));
return null;
}
@@ -66,7 +76,12 @@ namespace MPF.Core
outputFilename = Path.GetFileNameWithoutExtension(outputFilename);
// Create the SubmissionInfo object with all user-inputted values by default
- string combinedBase = Path.Combine(outputDirectory, outputFilename);
+ string combinedBase;
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ combinedBase = outputFilename;
+ else
+ combinedBase = Path.Combine(outputDirectory, outputFilename);
+
var info = new SubmissionInfo()
{
CommonDiscInfo = new CommonDiscInfoSection()
@@ -104,7 +119,7 @@ namespace MPF.Core
};
// Get specific tool output handling
- parameters.GenerateSubmissionInfo(info, options, combinedBase, drive, options.IncludeArtifacts);
+ parameters?.GenerateSubmissionInfo(info, options, combinedBase, drive, options.IncludeArtifacts);
// Get a list of matching IDs for each line in the DAT
if (!string.IsNullOrEmpty(info.TracksAndWriteOffsets.ClrMameProData) && options.HasRedumpLogin)
@@ -115,11 +130,11 @@ namespace MPF.Core
#endif
// If we have both ClrMamePro and Size and Checksums data, remove the ClrMamePro
- if (!string.IsNullOrWhiteSpace(info.SizeAndChecksums.CRC32))
+ if (!string.IsNullOrWhiteSpace(info.SizeAndChecksums?.CRC32))
info.TracksAndWriteOffsets.ClrMameProData = null;
// Add the volume label to comments, if possible or necessary
- if (drive != null && drive.GetRedumpSystemFromVolumeLabel() == null)
+ if (drive?.VolumeLabel != null && drive.GetRedumpSystemFromVolumeLabel() == null)
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.VolumeLabel] = drive.VolumeLabel;
// Extract info based generically on MediaType
@@ -138,6 +153,8 @@ namespace MPF.Core
case MediaType.DVD:
case MediaType.HDDVD:
case MediaType.BluRay:
+ if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
+
// If we have a single-layer disc
if (info.SizeAndChecksums.Layerbreak == default)
{
@@ -172,10 +189,13 @@ namespace MPF.Core
info.CommonDiscInfo.Layer0MouldSID = options.AddPlaceholders ? Template.RequiredIfExistsValue : string.Empty;
info.CommonDiscInfo.Layer1MouldSID = options.AddPlaceholders ? Template.RequiredIfExistsValue : string.Empty;
info.CommonDiscInfo.Layer0AdditionalMould = options.AddPlaceholders ? Template.RequiredIfExistsValue : string.Empty;
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.BCA = info.Extras.BCA ?? (options.AddPlaceholders ? Template.RequiredValue : string.Empty);
break;
case MediaType.NintendoWiiOpticalDisc:
+ if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
+
// If we have a single-layer disc
if (info.SizeAndChecksums.Layerbreak == default)
{
@@ -201,6 +221,7 @@ namespace MPF.Core
info.CommonDiscInfo.Layer1MouldSID = options.AddPlaceholders ? Template.RequiredIfExistsValue : string.Empty;
}
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.DiscKey = options.AddPlaceholders ? Template.RequiredValue : string.Empty;
info.Extras.BCA = info.Extras.BCA ?? (options.AddPlaceholders ? Template.RequiredValue : string.Empty);
@@ -217,6 +238,7 @@ namespace MPF.Core
info.CommonDiscInfo.Layer1MasteringSID = options.AddPlaceholders ? Template.RequiredIfExistsValue : string.Empty;
info.CommonDiscInfo.Layer1ToolstampMasteringCode = options.AddPlaceholders ? Template.RequiredIfExistsValue : string.Empty;
+ if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
info.SizeAndChecksums.CRC32 = info.SizeAndChecksums.CRC32 ?? (options.AddPlaceholders ? Template.RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
info.SizeAndChecksums.MD5 = info.SizeAndChecksums.MD5 ?? (options.AddPlaceholders ? Template.RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
info.SizeAndChecksums.SHA1 = info.SizeAndChecksums.SHA1 ?? (options.AddPlaceholders ? Template.RequiredValue + " [Not automatically generated for UMD]" : string.Empty);
@@ -239,9 +261,15 @@ namespace MPF.Core
case RedumpSystem.RainbowDisc:
case RedumpSystem.SonyElectronicBook:
resultProgress?.Report(Result.Success("Running copy protection scan... this might take a while!"));
- (string protectionString, Dictionary> fullProtections) = await GetCopyProtection(drive, options, protectionProgress);
+ var (protectionString, fullProtections) = await GetCopyProtection(drive, options, protectionProgress);
+
+ if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
info.CopyProtection.Protection = protectionString;
- info.CopyProtection.FullProtections = fullProtections;
+#if NET48
+ info.CopyProtection.FullProtections = fullProtections ?? new Dictionary>();
+#else
+ info.CopyProtection.FullProtections = fullProtections as Dictionary?> ?? new Dictionary?>();
+#endif
resultProgress?.Report(Result.Success("Copy protection scan complete!"));
break;
@@ -259,6 +287,7 @@ namespace MPF.Core
case RedumpSystem.BDVideo:
info.CommonDiscInfo.Category = info.CommonDiscInfo.Category ?? DiscCategory.BonusDiscs;
+ if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
info.CopyProtection.Protection = options.AddPlaceholders ? Template.RequiredIfExistsValue : string.Empty;
break;
@@ -318,21 +347,27 @@ namespace MPF.Core
break;
case RedumpSystem.MicrosoftXboxOne:
- string xboxOneMsxcPath = Path.Combine($"{drive.Letter}:\\", "MSXC");
- if (drive != null && Directory.Exists(xboxOneMsxcPath))
+ if (drive != null)
{
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.Filename] = string.Join("\n",
- Directory.GetFiles(xboxOneMsxcPath, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName));
+ string xboxOneMsxcPath = Path.Combine($"{drive.Letter}:\\", "MSXC");
+ if (drive != null && Directory.Exists(xboxOneMsxcPath))
+ {
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.Filename] = string.Join("\n",
+ Directory.GetFiles(xboxOneMsxcPath, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName));
+ }
}
break;
case RedumpSystem.MicrosoftXboxSeriesXS:
- string xboxSeriesXMsxcPath = Path.Combine($"{drive.Letter}:\\", "MSXC");
- if (drive != null && Directory.Exists(xboxSeriesXMsxcPath))
+ if (drive != null)
{
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.Filename] = string.Join("\n",
- Directory.GetFiles(xboxSeriesXMsxcPath, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName));
+ string xboxSeriesXMsxcPath = Path.Combine($"{drive.Letter}:\\", "MSXC");
+ if (drive != null && Directory.Exists(xboxSeriesXMsxcPath))
+ {
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.Filename] = string.Join("\n",
+ Directory.GetFiles(xboxSeriesXMsxcPath, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName));
+ }
}
break;
@@ -389,6 +424,7 @@ namespace MPF.Core
case RedumpSystem.SonyPlayStation:
// Only check the disc if the dumping program couldn't detect
+ if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
if (drive != null && info.CopyProtection.AntiModchip == YesNo.NULL)
{
resultProgress?.Report(Result.Success("Checking for anti-modchip strings... this might take a while!"));
@@ -397,7 +433,7 @@ namespace MPF.Core
}
// Special case for DIC only
- if (parameters.InternalProgram == InternalProgram.DiscImageCreator)
+ if (parameters?.InternalProgram == InternalProgram.DiscImageCreator)
{
resultProgress?.Report(Result.Success("Checking for LibCrypt status... this might take a while!"));
GetLibCryptDetected(info, combinedBase);
@@ -411,6 +447,7 @@ namespace MPF.Core
break;
case RedumpSystem.SonyPlayStation3:
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.DiscKey = options.AddPlaceholders ? Template.RequiredValue : string.Empty;
info.Extras.DiscID = options.AddPlaceholders ? Template.RequiredValue : string.Empty;
break;
@@ -420,6 +457,7 @@ namespace MPF.Core
break;
case RedumpSystem.ZAPiTGamesGameWaveFamilyEntertainmentSystem:
+ if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
info.CopyProtection.Protection = options.AddPlaceholders ? Template.RequiredIfExistsValue : string.Empty;
break;
}
@@ -447,13 +485,25 @@ namespace MPF.Core
/// Parameters object representing what to send to the internal program
/// True if this is a check done before a dump, false if done after
/// Tuple of true if all required files exist, false otherwise and a list representing missing files
+#if NET48
public static (bool, List) FoundAllFiles(string outputDirectory, string outputFilename, BaseParameters parameters, bool preCheck)
+#else
+ public static (bool, List) FoundAllFiles(string? outputDirectory, string outputFilename, BaseParameters? parameters, bool preCheck)
+#endif
{
+ // If there are no parameters set
+ if (parameters == null)
+ return (false, new List());
+
// First, sanitized the output filename to strip off any potential extension
outputFilename = Path.GetFileNameWithoutExtension(outputFilename);
// Then get the base path for all checking
- string basePath = Path.Combine(outputDirectory, outputFilename);
+ string basePath;
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ basePath = outputFilename;
+ else
+ basePath = Path.Combine(outputDirectory, outputFilename);
// Finally, let the parameters say if all files exist
return parameters.CheckAllOutputFilesExist(basePath, preCheck);
@@ -474,11 +524,15 @@ namespace MPF.Core
/// Options object that determines what to scan
/// Optional progress callback
/// Detected copy protection(s) if possible, null on error
- private static async Task<(string, Dictionary>)> GetCopyProtection(Drive drive, Core.Data.Options options, IProgress progress = null)
+#if NET48
+ private static async Task<(string, Dictionary>)> GetCopyProtection(Drive drive, Data.Options options, IProgress progress = null)
+#else
+ private static async Task<(string?, Dictionary>?)> GetCopyProtection(Drive? drive, Data.Options options, IProgress? progress = null)
+#endif
{
if (options.ScanForProtection && drive != null)
{
- (var protection, string _) = await Protection.RunProtectionScanOnPath($"{drive.Letter}:\\", options, progress);
+ (var protection, _) = await Protection.RunProtectionScanOnPath($"{drive.Letter}:\\", options, progress);
return (Protection.FormatProtections(protection), protection);
}
@@ -491,7 +545,11 @@ namespace MPF.Core
/// file location
/// True if should read as binary, false otherwise (default)
/// Full text of the file, null on error
+#if NET48
private static string GetFullFile(string filename, bool binary = false)
+#else
+ private 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))
@@ -512,7 +570,11 @@ namespace MPF.Core
///
/// String representing the combined hash data
/// True if extraction was successful, false otherwise
+#if NET48
private static bool GetISOHashValues(string hashData, out long size, out string crc32, out string md5, out string sha1)
+#else
+ private 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;
@@ -544,6 +606,7 @@ namespace MPF.Core
private static void GetLibCryptDetected(SubmissionInfo info, string basePath)
{
bool? psLibCryptStatus = Protection.GetLibCryptDetected(basePath + ".sub");
+ if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
if (psLibCryptStatus == true)
{
// Guard against false positives
@@ -587,11 +650,24 @@ namespace MPF.Core
/// Output filename to use as the base path
/// Parameters object to use to derive log file paths
/// True if the process succeeded, false otherwise
+#if NET48
public static (bool, string) CompressLogFiles(string outputDirectory, string outputFilename, BaseParameters parameters)
+#else
+ public static (bool, string) CompressLogFiles(string? outputDirectory, string outputFilename, BaseParameters? parameters)
+#endif
{
+ // If there are no parameters
+ if (parameters == null)
+ return (false, "No parameters provided!");
+
// Prepare the necessary paths
outputFilename = Path.GetFileNameWithoutExtension(outputFilename);
- string combinedBase = Path.Combine(outputDirectory, outputFilename);
+ string combinedBase;
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ combinedBase = outputFilename;
+ else
+ combinedBase = Path.Combine(outputDirectory, outputFilename);
+
string archiveName = combinedBase + "_logs.zip";
// Get the list of log files from the parameters object
@@ -616,19 +692,30 @@ namespace MPF.Core
}
// Add the log files to the archive and delete the uncompressed file after
+#if NET48
ZipArchive zf = null;
+#else
+ ZipArchive? zf = null;
+#endif
try
{
zf = ZipFile.Open(archiveName, ZipArchiveMode.Create);
foreach (string file in files)
{
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ {
+ zf.CreateEntryFromFile(file, file, CompressionLevel.Optimal);
+ }
+ else
+ {
#if NET48
- string entryName = file.Substring(outputDirectory.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
- zf.CreateEntryFromFile(file, entryName, CompressionLevel.Optimal);
+ string entryName = file.Substring(outputDirectory.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
+ zf.CreateEntryFromFile(file, entryName, CompressionLevel.Optimal);
#else
- string entryName = file[outputDirectory.Length..].TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
- zf.CreateEntryFromFile(file, entryName, CompressionLevel.SmallestSize);
+ string entryName = file[outputDirectory.Length..].TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
+ zf.CreateEntryFromFile(file, entryName, CompressionLevel.SmallestSize);
#endif
+ }
// If the file is MPF-specific, don't delete
if (mpfFiles.Contains(file))
@@ -659,7 +746,11 @@ namespace MPF.Core
/// Information object that should contain normalized values
/// Options object representing user-defined options
/// List of strings representing each line of an output file, null on error
- public static (List, string) FormatOutputData(SubmissionInfo info, Core.Data.Options options)
+#if NET48
+ public static (List, string) FormatOutputData(SubmissionInfo info, Data.Options options)
+#else
+ public static (List?, string?) FormatOutputData(SubmissionInfo? info, Data.Options options)
+#endif
{
// Check to see if the inputs are valid
if (info == null)
@@ -668,7 +759,7 @@ namespace MPF.Core
try
{
// Sony-printed discs have layers in the opposite order
- var system = info.CommonDiscInfo.System;
+ var system = info.CommonDiscInfo?.System;
bool reverseOrder = system.HasReversedRingcodes();
// Preamble for submission
@@ -682,120 +773,120 @@ namespace MPF.Core
// Common Disc Info section
output.Add("Common Disc Info:");
- AddIfExists(output, Template.TitleField, info.CommonDiscInfo.Title, 1);
- AddIfExists(output, Template.ForeignTitleField, info.CommonDiscInfo.ForeignTitleNonLatin, 1);
- AddIfExists(output, Template.DiscNumberField, info.CommonDiscInfo.DiscNumberLetter, 1);
- AddIfExists(output, Template.DiscTitleField, info.CommonDiscInfo.DiscTitle, 1);
- AddIfExists(output, Template.SystemField, info.CommonDiscInfo.System.LongName(), 1);
+ AddIfExists(output, Template.TitleField, info.CommonDiscInfo?.Title, 1);
+ AddIfExists(output, Template.ForeignTitleField, info.CommonDiscInfo?.ForeignTitleNonLatin, 1);
+ AddIfExists(output, Template.DiscNumberField, info.CommonDiscInfo?.DiscNumberLetter, 1);
+ AddIfExists(output, Template.DiscTitleField, info.CommonDiscInfo?.DiscTitle, 1);
+ AddIfExists(output, Template.SystemField, info.CommonDiscInfo?.System.LongName(), 1);
AddIfExists(output, Template.MediaTypeField, GetFixedMediaType(
- info.CommonDiscInfo.Media.ToMediaType(),
- info.SizeAndChecksums.PICIdentifier,
- info.SizeAndChecksums.Size,
- info.SizeAndChecksums.Layerbreak,
- info.SizeAndChecksums.Layerbreak2,
- info.SizeAndChecksums.Layerbreak3),
+ info.CommonDiscInfo?.Media.ToMediaType(),
+ info.SizeAndChecksums?.PICIdentifier,
+ info.SizeAndChecksums?.Size,
+ info.SizeAndChecksums?.Layerbreak,
+ info.SizeAndChecksums?.Layerbreak2,
+ info.SizeAndChecksums?.Layerbreak3),
1);
- AddIfExists(output, Template.CategoryField, info.CommonDiscInfo.Category.LongName(), 1);
+ AddIfExists(output, Template.CategoryField, info.CommonDiscInfo?.Category.LongName(), 1);
AddIfExists(output, Template.FullyMatchingIDField, info.FullyMatchedID?.ToString(), 1);
AddIfExists(output, Template.PartiallyMatchingIDsField, info.PartiallyMatchedIDs, 1);
- AddIfExists(output, Template.RegionField, info.CommonDiscInfo.Region.LongName() ?? "SPACE! (CHANGE THIS)", 1);
- AddIfExists(output, Template.LanguagesField, (info.CommonDiscInfo.Languages ?? new Language?[] { null }).Select(l => l.LongName() ?? "SILENCE! (CHANGE THIS)").ToArray(), 1);
- AddIfExists(output, Template.PlaystationLanguageSelectionViaField, (info.CommonDiscInfo.LanguageSelection ?? Array.Empty()).Select(l => l.LongName()).ToArray(), 1);
- AddIfExists(output, Template.DiscSerialField, info.CommonDiscInfo.Serial, 1);
+ AddIfExists(output, Template.RegionField, info.CommonDiscInfo?.Region.LongName() ?? "SPACE! (CHANGE THIS)", 1);
+ AddIfExists(output, Template.LanguagesField, (info.CommonDiscInfo?.Languages ?? new Language?[] { null }).Select(l => l.LongName() ?? "SILENCE! (CHANGE THIS)").ToArray(), 1);
+ AddIfExists(output, Template.PlaystationLanguageSelectionViaField, (info.CommonDiscInfo?.LanguageSelection ?? Array.Empty()).Select(l => l.LongName()).ToArray(), 1);
+ AddIfExists(output, Template.DiscSerialField, info.CommonDiscInfo?.Serial, 1);
// All ringcode information goes in an indented area
output.Add(""); output.Add("\tRingcode Information:"); output.Add("");
// If we have a triple-layer disc
- if (info.SizeAndChecksums.Layerbreak3 != default)
+ if (info.SizeAndChecksums?.Layerbreak3 != default && info.SizeAndChecksums?.Layerbreak3 != default(long))
{
- AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringRingField, info.CommonDiscInfo.Layer0MasteringRing, 0);
- AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringSIDField, info.CommonDiscInfo.Layer0MasteringSID, 0);
- AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.ToolstampField, info.CommonDiscInfo.Layer0ToolstampMasteringCode, 0);
- AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo.Layer0MouldSID, 0);
- AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo.Layer0AdditionalMould, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer0MasteringRing, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer0MasteringSID, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer0ToolstampMasteringCode, 0);
+ AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer0MouldSID, 0);
+ AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer0AdditionalMould, 0);
- AddIfExists(output, "Layer 1 " + Template.MasteringRingField, info.CommonDiscInfo.Layer1MasteringRing, 0);
- AddIfExists(output, "Layer 1 " + Template.MasteringSIDField, info.CommonDiscInfo.Layer1MasteringSID, 0);
- AddIfExists(output, "Layer 1 " + Template.ToolstampField, info.CommonDiscInfo.Layer1ToolstampMasteringCode, 0);
- AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo.Layer1MouldSID, 0);
- AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo.Layer1AdditionalMould, 0);
+ AddIfExists(output, "Layer 1 " + Template.MasteringRingField, info.CommonDiscInfo?.Layer1MasteringRing, 0);
+ AddIfExists(output, "Layer 1 " + Template.MasteringSIDField, info.CommonDiscInfo?.Layer1MasteringSID, 0);
+ AddIfExists(output, "Layer 1 " + Template.ToolstampField, info.CommonDiscInfo?.Layer1ToolstampMasteringCode, 0);
+ AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer1MouldSID, 0);
+ AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer1AdditionalMould, 0);
- AddIfExists(output, "Layer 2 " + Template.MasteringRingField, info.CommonDiscInfo.Layer2MasteringRing, 0);
- AddIfExists(output, "Layer 2 " + Template.MasteringSIDField, info.CommonDiscInfo.Layer2MasteringSID, 0);
- AddIfExists(output, "Layer 2 " + Template.ToolstampField, info.CommonDiscInfo.Layer2ToolstampMasteringCode, 0);
+ AddIfExists(output, "Layer 2 " + Template.MasteringRingField, info.CommonDiscInfo?.Layer2MasteringRing, 0);
+ AddIfExists(output, "Layer 2 " + Template.MasteringSIDField, info.CommonDiscInfo?.Layer2MasteringSID, 0);
+ AddIfExists(output, "Layer 2 " + Template.ToolstampField, info.CommonDiscInfo?.Layer2ToolstampMasteringCode, 0);
- AddIfExists(output, (reverseOrder ? "Layer 3 (Inner) " : "Layer 3 (Outer) ") + Template.MasteringRingField, info.CommonDiscInfo.Layer3MasteringRing, 0);
- AddIfExists(output, (reverseOrder ? "Layer 3 (Inner) " : "Layer 3 (Outer) ") + Template.MasteringSIDField, info.CommonDiscInfo.Layer3MasteringSID, 0);
- AddIfExists(output, (reverseOrder ? "Layer 3 (Inner) " : "Layer 3 (Outer) ") + Template.ToolstampField, info.CommonDiscInfo.Layer3ToolstampMasteringCode, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 3 (Inner) " : "Layer 3 (Outer) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer3MasteringRing, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 3 (Inner) " : "Layer 3 (Outer) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer3MasteringSID, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 3 (Inner) " : "Layer 3 (Outer) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer3ToolstampMasteringCode, 0);
}
// If we have a triple-layer disc
- else if (info.SizeAndChecksums.Layerbreak2 != default)
+ else if (info.SizeAndChecksums?.Layerbreak2 != default && info.SizeAndChecksums?.Layerbreak2 != default(long))
{
- AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringRingField, info.CommonDiscInfo.Layer0MasteringRing, 0);
- AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringSIDField, info.CommonDiscInfo.Layer0MasteringSID, 0);
- AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.ToolstampField, info.CommonDiscInfo.Layer0ToolstampMasteringCode, 0);
- AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo.Layer0MouldSID, 0);
- AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo.Layer0AdditionalMould, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer0MasteringRing, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer0MasteringSID, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer0ToolstampMasteringCode, 0);
+ AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer0MouldSID, 0);
+ AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer0AdditionalMould, 0);
- AddIfExists(output, "Layer 1 " + Template.MasteringRingField, info.CommonDiscInfo.Layer1MasteringRing, 0);
- AddIfExists(output, "Layer 1 " + Template.MasteringSIDField, info.CommonDiscInfo.Layer1MasteringSID, 0);
- AddIfExists(output, "Layer 1 " + Template.ToolstampField, info.CommonDiscInfo.Layer1ToolstampMasteringCode, 0);
- AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo.Layer1MouldSID, 0);
- AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo.Layer1AdditionalMould, 0);
+ AddIfExists(output, "Layer 1 " + Template.MasteringRingField, info.CommonDiscInfo?.Layer1MasteringRing, 0);
+ AddIfExists(output, "Layer 1 " + Template.MasteringSIDField, info.CommonDiscInfo?.Layer1MasteringSID, 0);
+ AddIfExists(output, "Layer 1 " + Template.ToolstampField, info.CommonDiscInfo?.Layer1ToolstampMasteringCode, 0);
+ AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer1MouldSID, 0);
+ AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer1AdditionalMould, 0);
- AddIfExists(output, (reverseOrder ? "Layer 2 (Inner) " : "Layer 2 (Outer) ") + Template.MasteringRingField, info.CommonDiscInfo.Layer2MasteringRing, 0);
- AddIfExists(output, (reverseOrder ? "Layer 2 (Inner) " : "Layer 2 (Outer) ") + Template.MasteringSIDField, info.CommonDiscInfo.Layer2MasteringSID, 0);
- AddIfExists(output, (reverseOrder ? "Layer 2 (Inner) " : "Layer 2 (Outer) ") + Template.ToolstampField, info.CommonDiscInfo.Layer2ToolstampMasteringCode, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 2 (Inner) " : "Layer 2 (Outer) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer2MasteringRing, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 2 (Inner) " : "Layer 2 (Outer) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer2MasteringSID, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 2 (Inner) " : "Layer 2 (Outer) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer2ToolstampMasteringCode, 0);
}
// If we have a dual-layer disc
- else if (info.SizeAndChecksums.Layerbreak != default)
+ else if (info.SizeAndChecksums?.Layerbreak != default && info.SizeAndChecksums?.Layerbreak != default(long))
{
- AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringRingField, info.CommonDiscInfo.Layer0MasteringRing, 0);
- AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringSIDField, info.CommonDiscInfo.Layer0MasteringSID, 0);
- AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.ToolstampField, info.CommonDiscInfo.Layer0ToolstampMasteringCode, 0);
- AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo.Layer0MouldSID, 0);
- AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo.Layer0AdditionalMould, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer0MasteringRing, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer0MasteringSID, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer0ToolstampMasteringCode, 0);
+ AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer0MouldSID, 0);
+ AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer0AdditionalMould, 0);
- AddIfExists(output, (reverseOrder ? "Layer 1 (Inner) " : "Layer 1 (Outer) ") + Template.MasteringRingField, info.CommonDiscInfo.Layer1MasteringRing, 0);
- AddIfExists(output, (reverseOrder ? "Layer 1 (Inner) " : "Layer 1 (Outer) ") + Template.MasteringSIDField, info.CommonDiscInfo.Layer1MasteringSID, 0);
- AddIfExists(output, (reverseOrder ? "Layer 1 (Inner) " : "Layer 1 (Outer) ") + Template.ToolstampField, info.CommonDiscInfo.Layer1ToolstampMasteringCode, 0);
- AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo.Layer1MouldSID, 0);
- AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo.Layer1AdditionalMould, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 1 (Inner) " : "Layer 1 (Outer) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer1MasteringRing, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 1 (Inner) " : "Layer 1 (Outer) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer1MasteringSID, 0);
+ AddIfExists(output, (reverseOrder ? "Layer 1 (Inner) " : "Layer 1 (Outer) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer1ToolstampMasteringCode, 0);
+ AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer1MouldSID, 0);
+ AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer1AdditionalMould, 0);
}
// If we have a single-layer disc
else
{
- AddIfExists(output, "Data Side " + Template.MasteringRingField, info.CommonDiscInfo.Layer0MasteringRing, 0);
- AddIfExists(output, "Data Side " + Template.MasteringSIDField, info.CommonDiscInfo.Layer0MasteringSID, 0);
- AddIfExists(output, "Data Side " + Template.ToolstampField, info.CommonDiscInfo.Layer0ToolstampMasteringCode, 0);
- AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo.Layer0MouldSID, 0);
- AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo.Layer0AdditionalMould, 0);
+ AddIfExists(output, "Data Side " + Template.MasteringRingField, info.CommonDiscInfo?.Layer0MasteringRing, 0);
+ AddIfExists(output, "Data Side " + Template.MasteringSIDField, info.CommonDiscInfo?.Layer0MasteringSID, 0);
+ AddIfExists(output, "Data Side " + Template.ToolstampField, info.CommonDiscInfo?.Layer0ToolstampMasteringCode, 0);
+ AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer0MouldSID, 0);
+ AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer0AdditionalMould, 0);
- AddIfExists(output, "Label Side " + Template.MasteringRingField, info.CommonDiscInfo.Layer1MasteringRing, 0);
- AddIfExists(output, "Label Side " + Template.MasteringSIDField, info.CommonDiscInfo.Layer1MasteringSID, 0);
- AddIfExists(output, "Label Side " + Template.ToolstampField, info.CommonDiscInfo.Layer1ToolstampMasteringCode, 0);
- AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo.Layer1MouldSID, 0);
- AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo.Layer1AdditionalMould, 0);
+ AddIfExists(output, "Label Side " + Template.MasteringRingField, info.CommonDiscInfo?.Layer1MasteringRing, 0);
+ AddIfExists(output, "Label Side " + Template.MasteringSIDField, info.CommonDiscInfo?.Layer1MasteringSID, 0);
+ AddIfExists(output, "Label Side " + Template.ToolstampField, info.CommonDiscInfo?.Layer1ToolstampMasteringCode, 0);
+ AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer1MouldSID, 0);
+ AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer1AdditionalMould, 0);
}
output.Add("");
- AddIfExists(output, Template.BarcodeField, info.CommonDiscInfo.Barcode, 1);
- AddIfExists(output, Template.EXEDateBuildDate, info.CommonDiscInfo.EXEDateBuildDate, 1);
- AddIfExists(output, Template.ErrorCountField, info.CommonDiscInfo.ErrorsCount, 1);
- AddIfExists(output, Template.CommentsField, info.CommonDiscInfo.Comments.Trim(), 1);
- AddIfExists(output, Template.ContentsField, info.CommonDiscInfo.Contents.Trim(), 1);
+ AddIfExists(output, Template.BarcodeField, info.CommonDiscInfo?.Barcode, 1);
+ AddIfExists(output, Template.EXEDateBuildDate, info.CommonDiscInfo?.EXEDateBuildDate, 1);
+ AddIfExists(output, Template.ErrorCountField, info.CommonDiscInfo?.ErrorsCount, 1);
+ AddIfExists(output, Template.CommentsField, info.CommonDiscInfo?.Comments?.Trim(), 1);
+ AddIfExists(output, Template.ContentsField, info.CommonDiscInfo?.Contents?.Trim(), 1);
// Version and Editions section
output.Add(""); output.Add("Version and Editions:");
- AddIfExists(output, Template.VersionField, info.VersionAndEditions.Version, 1);
- AddIfExists(output, Template.EditionField, info.VersionAndEditions.OtherEditions, 1);
+ AddIfExists(output, Template.VersionField, info.VersionAndEditions?.Version, 1);
+ AddIfExists(output, Template.EditionField, info.VersionAndEditions?.OtherEditions, 1);
// EDC section
- if (info.CommonDiscInfo.System == RedumpSystem.SonyPlayStation)
+ if (info.CommonDiscInfo?.System == RedumpSystem.SonyPlayStation)
{
output.Add(""); output.Add("EDC:");
- AddIfExists(output, Template.PlayStationEDCField, info.EDC.EDC.LongName(), 1);
+ AddIfExists(output, Template.PlayStationEDCField, info.EDC?.EDC.LongName(), 1);
}
// Parent/Clone Relationship section
@@ -804,7 +895,7 @@ namespace MPF.Core
// AddIfExists(output, Template.RegionalParentField, info.RegionalParent.ToString());
// Extras section
- if (info.Extras.PVD != null || info.Extras.PIC != null || info.Extras.BCA != null || info.Extras.SecuritySectorRanges != null)
+ if (info.Extras?.PVD != null || info.Extras?.PIC != null || info.Extras?.BCA != null || info.Extras?.SecuritySectorRanges != null)
{
output.Add(""); output.Add("Extras:");
AddIfExists(output, Template.PVDField, info.Extras.PVD?.Trim(), 1);
@@ -817,14 +908,14 @@ namespace MPF.Core
}
// Copy Protection section
- if (!string.IsNullOrWhiteSpace(info.CopyProtection.Protection)
- || (info.CopyProtection.AntiModchip != null && info.CopyProtection.AntiModchip != YesNo.NULL)
- || (info.CopyProtection.LibCrypt != null && info.CopyProtection.LibCrypt != YesNo.NULL)
- || !string.IsNullOrWhiteSpace(info.CopyProtection.LibCryptData)
- || !string.IsNullOrWhiteSpace(info.CopyProtection.SecuROMData))
+ if (!string.IsNullOrWhiteSpace(info.CopyProtection?.Protection)
+ || (info.CopyProtection?.AntiModchip != null && info.CopyProtection.AntiModchip != YesNo.NULL)
+ || (info.CopyProtection?.LibCrypt != null && info.CopyProtection.LibCrypt != YesNo.NULL)
+ || !string.IsNullOrWhiteSpace(info.CopyProtection?.LibCryptData)
+ || !string.IsNullOrWhiteSpace(info.CopyProtection?.SecuROMData))
{
output.Add(""); output.Add("Copy Protection:");
- if (info.CommonDiscInfo.System == RedumpSystem.SonyPlayStation)
+ if (info.CommonDiscInfo?.System == RedumpSystem.SonyPlayStation)
{
AddIfExists(output, Template.PlayStationAntiModchipField, info.CopyProtection.AntiModchip.LongName(), 1);
AddIfExists(output, Template.PlayStationLibCryptField, info.CopyProtection.LibCrypt.LongName(), 1);
@@ -841,12 +932,12 @@ namespace MPF.Core
// AddIfExists(output, Template.OtherDumpersField, info.OtherDumpers);
// Tracks and Write Offsets section
- if (!string.IsNullOrWhiteSpace(info.TracksAndWriteOffsets.ClrMameProData))
+ if (!string.IsNullOrWhiteSpace(info.TracksAndWriteOffsets?.ClrMameProData))
{
output.Add(""); output.Add("Tracks and Write Offsets:");
AddIfExists(output, Template.DATField, info.TracksAndWriteOffsets.ClrMameProData + "\n", 1);
AddIfExists(output, Template.CuesheetField, info.TracksAndWriteOffsets.Cuesheet, 1);
- string offset = info.TracksAndWriteOffsets.OtherWriteOffsets;
+ var offset = info.TracksAndWriteOffsets.OtherWriteOffsets;
if (Int32.TryParse(offset, out int i))
offset = i.ToString("+#;-#;0");
@@ -859,29 +950,33 @@ namespace MPF.Core
// Gross hack because of automatic layerbreaks in Redump
if (!options.EnableRedumpCompatibility
- || (info.CommonDiscInfo.Media.ToMediaType() != MediaType.BluRay
- && !info.CommonDiscInfo.System.IsXGD()))
+ || (info.CommonDiscInfo?.Media.ToMediaType() != MediaType.BluRay
+ && info.CommonDiscInfo?.System.IsXGD() == false))
{
- AddIfExists(output, Template.LayerbreakField, (info.SizeAndChecksums.Layerbreak == default ? null : info.SizeAndChecksums.Layerbreak.ToString()), 1);
+ AddIfExists(output, Template.LayerbreakField, (info.SizeAndChecksums?.Layerbreak == default && info.SizeAndChecksums?.Layerbreak != default(long) ? null : info.SizeAndChecksums?.Layerbreak.ToString()), 1);
}
- AddIfExists(output, Template.SizeField, info.SizeAndChecksums.Size.ToString(), 1);
- AddIfExists(output, Template.CRC32Field, info.SizeAndChecksums.CRC32, 1);
- AddIfExists(output, Template.MD5Field, info.SizeAndChecksums.MD5, 1);
- AddIfExists(output, Template.SHA1Field, info.SizeAndChecksums.SHA1, 1);
+ AddIfExists(output, Template.SizeField, info.SizeAndChecksums?.Size.ToString(), 1);
+ AddIfExists(output, Template.CRC32Field, info.SizeAndChecksums?.CRC32, 1);
+ AddIfExists(output, Template.MD5Field, info.SizeAndChecksums?.MD5, 1);
+ AddIfExists(output, Template.SHA1Field, info.SizeAndChecksums?.SHA1, 1);
}
// Dumping Info section
output.Add(""); output.Add("Dumping Info:");
- AddIfExists(output, Template.DumpingProgramField, info.DumpingInfo.DumpingProgram, 1);
- AddIfExists(output, Template.DumpingDateField, info.DumpingInfo.DumpingDate, 1);
- AddIfExists(output, Template.DumpingDriveManufacturer, info.DumpingInfo.Manufacturer, 1);
- AddIfExists(output, Template.DumpingDriveModel, info.DumpingInfo.Model, 1);
- AddIfExists(output, Template.DumpingDriveFirmware, info.DumpingInfo.Firmware, 1);
- AddIfExists(output, Template.ReportedDiscType, info.DumpingInfo.ReportedDiscType, 1);
+ AddIfExists(output, Template.DumpingProgramField, info.DumpingInfo?.DumpingProgram, 1);
+ AddIfExists(output, Template.DumpingDateField, info.DumpingInfo?.DumpingDate, 1);
+ AddIfExists(output, Template.DumpingDriveManufacturer, info.DumpingInfo?.Manufacturer, 1);
+ AddIfExists(output, Template.DumpingDriveModel, info.DumpingInfo?.Model, 1);
+ AddIfExists(output, Template.DumpingDriveFirmware, info.DumpingInfo?.Firmware, 1);
+ AddIfExists(output, Template.ReportedDiscType, info.DumpingInfo?.ReportedDiscType, 1);
// Make sure there aren't any instances of two blank lines in a row
+#if NET48
string last = null;
+#else
+ string? last = null;
+#endif
for (int i = 0; i < output.Count;)
{
if (output[i] == last && string.IsNullOrWhiteSpace(last))
@@ -914,7 +1009,11 @@ namespace MPF.Core
/// Third layerbreak value, as applicable
/// String representation of the media, including layer specification
/// TODO: Figure out why we have this and NormalizeDiscType as well
- public static string GetFixedMediaType(MediaType? mediaType, string picIdentifier, long size, long layerbreak, long layerbreak2, long layerbreak3)
+#if NET48
+ public static string GetFixedMediaType(MediaType? mediaType, string picIdentifier, long? size, long? layerbreak, long? layerbreak2, long? layerbreak3)
+#else
+ public static string? GetFixedMediaType(MediaType? mediaType, string? picIdentifier, long? size, long? layerbreak, long? layerbreak2, long? layerbreak3)
+#endif
{
switch (mediaType)
{
@@ -925,15 +1024,15 @@ namespace MPF.Core
return $"{mediaType.LongName()}-5";
case MediaType.BluRay:
- if (layerbreak3 != default)
+ if (layerbreak3 != default && layerbreak3 != default(long))
return $"{mediaType.LongName()}-128";
- else if (layerbreak2 != default)
+ else if (layerbreak2 != default && layerbreak2 != default(long))
return $"{mediaType.LongName()}-100";
- else if (layerbreak != default && picIdentifier == SabreTools.Models.PIC.Constants.DiscTypeIdentifierROMUltra)
+ else if (layerbreak != default && layerbreak != default(long) && picIdentifier == SabreTools.Models.PIC.Constants.DiscTypeIdentifierROMUltra)
return $"{mediaType.LongName()}-66";
- else if (layerbreak != default && size > 53_687_063_712)
+ else if (layerbreak != default && layerbreak != default(long) && size > 53_687_063_712)
return $"{mediaType.LongName()}-66";
- else if (layerbreak != default)
+ else if (layerbreak != default && layerbreak != default(long))
return $"{mediaType.LongName()}-50";
else if (picIdentifier == SabreTools.Models.PIC.Constants.DiscTypeIdentifierROMUltra)
return $"{mediaType.LongName()}-33";
@@ -943,7 +1042,7 @@ namespace MPF.Core
return $"{mediaType.LongName()}-25";
case MediaType.UMD:
- if (layerbreak != default)
+ if (layerbreak != default && layerbreak != default(long))
return $"{mediaType.LongName()}-DL";
else
return $"{mediaType.LongName()}-SL";
@@ -957,8 +1056,16 @@ namespace MPF.Core
/// Process any fields that have to be combined
///
/// Information object to normalize
+#if NET48
public static void ProcessSpecialFields(SubmissionInfo info)
+#else
+ public static void ProcessSpecialFields(SubmissionInfo? info)
+#endif
{
+ // If there is no submission info
+ if (info == null)
+ return;
+
// Process the comments field
if (info.CommonDiscInfo?.CommentsSpecialFields != null && info.CommonDiscInfo.CommentsSpecialFields?.Any() == true)
{
@@ -1016,7 +1123,11 @@ namespace MPF.Core
/// Output folder to write to
/// Preformatted list of lines to write out to the file
/// True on success, false on error
+#if NET48
public static (bool, string) WriteOutputData(string outputDirectory, List lines)
+#else
+ public static (bool, string) WriteOutputData(string? outputDirectory, List? lines)
+#endif
{
// Check to see if the inputs are valid
if (lines == null)
@@ -1025,7 +1136,14 @@ namespace MPF.Core
// Now write out to a generic file
try
{
- using (var sw = new StreamWriter(File.Open(Path.Combine(outputDirectory, "!submissionInfo.txt"), FileMode.Create, FileAccess.Write)))
+ // Get the file path
+ string path;
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ path = "!submissionInfo.txt";
+ else
+ path = Path.Combine(outputDirectory, "!submissionInfo.txt");
+
+ using (var sw = new StreamWriter(File.Open(path, FileMode.Create, FileAccess.Write)))
{
foreach (string line in lines)
{
@@ -1048,7 +1166,11 @@ namespace MPF.Core
/// SubmissionInfo object representing the JSON to write out to the file
/// True if artifacts were included, false otherwise
/// True on success, false on error
+#if NET48
public static bool WriteOutputData(string outputDirectory, SubmissionInfo info, bool includedArtifacts)
+#else
+ public static bool WriteOutputData(string? outputDirectory, SubmissionInfo? info, bool includedArtifacts)
+#endif
{
// Check to see if the input is valid
if (info == null)
@@ -1063,7 +1185,13 @@ namespace MPF.Core
// If we included artifacts, write to a GZip-compressed file
if (includedArtifacts)
{
- using (var fs = File.Create(Path.Combine(outputDirectory, "!submissionInfo.json.gz")))
+ string file;
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ file = "!submissionInfo.json.gz";
+ else
+ file = Path.Combine(outputDirectory, "!submissionInfo.json.gz");
+
+ using (var fs = File.Create(file))
using (var gs = new GZipStream(fs, CompressionMode.Compress))
{
gs.Write(jsonBytes, 0, jsonBytes.Length);
@@ -1073,7 +1201,13 @@ namespace MPF.Core
// Otherwise, write out to a normal JSON
else
{
- using (var fs = File.Create(Path.Combine(outputDirectory, "!submissionInfo.json")))
+ string file;
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ file = "!submissionInfo.json";
+ else
+ file = Path.Combine(outputDirectory, "!submissionInfo.json");
+
+ using (var fs = File.Create(file))
{
fs.Write(jsonBytes, 0, jsonBytes.Length);
}
@@ -1094,7 +1228,11 @@ namespace MPF.Core
/// Output folder to write to
/// SubmissionInfo object containing the protection information
/// True on success, false on error
+#if NET48
public static bool WriteProtectionData(string outputDirectory, SubmissionInfo info)
+#else
+ public static bool WriteProtectionData(string? outputDirectory, SubmissionInfo? info)
+#endif
{
// Check to see if the inputs are valid
if (info?.CopyProtection?.FullProtections == null || !info.CopyProtection.FullProtections.Any())
@@ -1103,11 +1241,20 @@ namespace MPF.Core
// Now write out to a generic file
try
{
- using (var sw = new StreamWriter(File.Open(Path.Combine(outputDirectory, "!protectionInfo.txt"), FileMode.Create, FileAccess.Write)))
+ string file;
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ file = "!protectionInfo.txt";
+ else
+ file = Path.Combine(outputDirectory, "!protectionInfo.txt");
+
+ using (var sw = new StreamWriter(File.Open(file, FileMode.Create, FileAccess.Write)))
{
foreach (var kvp in info.CopyProtection.FullProtections)
{
- sw.WriteLine($"{kvp.Key}: {string.Join(", ", kvp.Value)}");
+ if (kvp.Value == null)
+ sw.WriteLine($"{kvp.Key}: None");
+ else
+ sw.WriteLine($"{kvp.Key}: {string.Join(", ", kvp.Value)}");
}
}
}
@@ -1127,7 +1274,11 @@ namespace MPF.Core
/// Name of the output key to write
/// Name of the output value to write
/// Number of tabs to indent the line
+#if NET48
private static void AddIfExists(List output, string key, string value, int indent)
+#else
+ private static void AddIfExists(List output, string key, string? value, int indent)
+#endif
{
// If there's no valid value to write
if (value == null)
@@ -1181,7 +1332,11 @@ namespace MPF.Core
/// Name of the output key to write
/// Name of the output value to write
/// Number of tabs to indent the line
+#if NET48
private static void AddIfExists(List output, string key, string[] value, int indent)
+#else
+ private static void AddIfExists(List output, string key, string?[]? value, int indent)
+#endif
{
// If there's no valid value to write
if (value == null || value.Length == 0)
@@ -1197,7 +1352,11 @@ namespace MPF.Core
/// Name of the output key to write
/// Name of the output value to write
/// Number of tabs to indent the line
+#if NET48
private static void AddIfExists(List output, string key, List value, int indent)
+#else
+ private static void AddIfExists(List output, string key, List? value, int indent)
+#endif
{
// If there's no valid value to write
if (value == null || value.Count == 0)
@@ -1211,18 +1370,36 @@ namespace MPF.Core
///
/// Output folder to write to
/// List of all log file paths, empty otherwise
+#if NET48
private static List GetGeneratedFilePaths(string outputDirectory)
+#else
+ private static List GetGeneratedFilePaths(string? outputDirectory)
+#endif
{
var files = new List();
- if (File.Exists(Path.Combine(outputDirectory, "!submissionInfo.txt")))
- files.Add(Path.Combine(outputDirectory, "!submissionInfo.txt"));
- if (File.Exists(Path.Combine(outputDirectory, "!submissionInfo.json")))
- files.Add(Path.Combine(outputDirectory, "!submissionInfo.json"));
- if (File.Exists(Path.Combine(outputDirectory, "!submissionInfo.json.gz")))
- files.Add(Path.Combine(outputDirectory, "!submissionInfo.json.gz"));
- if (File.Exists(Path.Combine(outputDirectory, "!protectionInfo.txt")))
- files.Add(Path.Combine(outputDirectory, "!protectionInfo.txt"));
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ {
+ if (File.Exists("!submissionInfo.txt"))
+ files.Add("!submissionInfo.txt");
+ if (File.Exists("!submissionInfo.json"))
+ files.Add("!submissionInfo.json");
+ if (File.Exists("!submissionInfo.json.gz"))
+ files.Add("!submissionInfo.json.gz");
+ if (File.Exists("!protectionInfo.txt"))
+ files.Add("!protectionInfo.txt");
+ }
+ else
+ {
+ if (File.Exists(Path.Combine(outputDirectory, "!submissionInfo.txt")))
+ files.Add(Path.Combine(outputDirectory, "!submissionInfo.txt"));
+ if (File.Exists(Path.Combine(outputDirectory, "!submissionInfo.json")))
+ files.Add(Path.Combine(outputDirectory, "!submissionInfo.json"));
+ if (File.Exists(Path.Combine(outputDirectory, "!submissionInfo.json.gz")))
+ files.Add(Path.Combine(outputDirectory, "!submissionInfo.json.gz"));
+ if (File.Exists(Path.Combine(outputDirectory, "!protectionInfo.txt")))
+ files.Add(Path.Combine(outputDirectory, "!protectionInfo.txt"));
+ }
return files;
}
@@ -1632,7 +1809,7 @@ namespace MPF.Core
public static void NormalizeDiscType(SubmissionInfo info)
{
// If we have nothing valid, do nothing
- if (info?.CommonDiscInfo?.Media == null)
+ if (info?.CommonDiscInfo?.Media == null || info?.SizeAndChecksums == null)
return;
switch (info.CommonDiscInfo.Media)
@@ -1709,18 +1886,24 @@ namespace MPF.Core
// Try getting the combined path and returning that directly
string fullPath = getFullPath ? Path.GetFullPath(path) : path;
- string fullDirectory = Path.GetDirectoryName(fullPath);
+ var fullDirectory = Path.GetDirectoryName(fullPath);
string fullFile = Path.GetFileName(fullPath);
// Remove invalid path characters
- foreach (char c in Path.GetInvalidPathChars())
- fullDirectory = fullDirectory.Replace(c, '_');
+ if (fullDirectory != null)
+ {
+ foreach (char c in Path.GetInvalidPathChars())
+ fullDirectory = fullDirectory.Replace(c, '_');
+ }
// Remove invalid filename characters
foreach (char c in Path.GetInvalidFileNameChars())
fullFile = fullFile.Replace(c, '_');
- return Path.Combine(fullDirectory, fullFile);
+ if (string.IsNullOrWhiteSpace(fullDirectory))
+ return fullFile;
+ else
+ return Path.Combine(fullDirectory, fullFile);
}
catch { }
@@ -1737,7 +1920,11 @@ namespace MPF.Core
/// String containing the HTML disc data
/// Filled SubmissionInfo object on success, null on error
/// Not currently working
+#if NET48
private static SubmissionInfo CreateFromID(string discData)
+#else
+ private static SubmissionInfo? CreateFromID(string discData)
+#endif
{
var info = new SubmissionInfo()
{
@@ -1760,12 +1947,16 @@ namespace MPF.Core
return null;
// Get the body node, if possible
- XmlNode bodyNode = redumpPage["html"]?["body"];
+ var bodyNode = redumpPage["html"]?["body"];
if (bodyNode == null || !bodyNode.HasChildNodes)
return null;
// Loop through and get the main node, if possible
+#if NET48
XmlNode mainNode = null;
+#else
+ XmlNode? mainNode = null;
+#endif
foreach (XmlNode tempNode in bodyNode.ChildNodes)
{
// We only care about div elements
@@ -1836,12 +2027,16 @@ namespace MPF.Core
if (gameInfoNode["th"] == null || gameInfoNode["td"] == null)
continue;
- XmlNode gameInfoNodeHeader = gameInfoNode["th"];
- XmlNode gameInfoNodeData = gameInfoNode["td"];
+ var gameInfoNodeHeader = gameInfoNode["th"];
+ var gameInfoNodeData = gameInfoNode["td"];
- if (string.Equals(gameInfoNodeHeader.InnerText, "System", StringComparison.OrdinalIgnoreCase))
+ if (gameInfoNodeHeader == null || gameInfoNodeData == null)
{
- info.CommonDiscInfo.System = Extensions.ToRedumpSystem(gameInfoNodeData["a"]?.InnerText);
+ // No-op for invalid data
+ }
+ else if (string.Equals(gameInfoNodeHeader.InnerText, "System", StringComparison.OrdinalIgnoreCase))
+ {
+ info.CommonDiscInfo.System = Extensions.ToRedumpSystem(gameInfoNodeData["a"]?.InnerText ?? string.Empty);
}
else if (string.Equals(gameInfoNodeHeader.InnerText, "Media", StringComparison.OrdinalIgnoreCase))
{
@@ -1924,7 +2119,14 @@ namespace MPF.Core
#else
private async static Task FillFromId(RedumpHttpClient wc, SubmissionInfo info, int id, bool includeAllData)
{
- string discData = await wc.DownloadSingleSiteID(id);
+ // Ensure that required sections exist
+ if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+ if (info.CommonDiscInfo.ContentsSpecialFields == null) info.CommonDiscInfo.ContentsSpecialFields = new Dictionary();
+ if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
+ if (info.DumpersAndStatus == null) info.DumpersAndStatus = new DumpersAndStatusSection();
+
+ var discData = await wc.DownloadSingleSiteID(id);
if (string.IsNullOrEmpty(discData))
return false;
#endif
@@ -2031,7 +2233,7 @@ namespace MPF.Core
{
// Start with any currently listed dumpers
var tempDumpers = new List();
- if (info.DumpersAndStatus.Dumpers.Length > 0)
+ if (info.DumpersAndStatus.Dumpers != null && info.DumpersAndStatus.Dumpers.Length > 0)
{
foreach (string dumper in info.DumpersAndStatus.Dumpers)
tempDumpers.Add(dumper);
@@ -2094,7 +2296,8 @@ namespace MPF.Core
continue;
// If the line doesn't contain this tag, just skip
- if (!commentLine.Contains(siteCode.ShortName()))
+ var shortName = siteCode.ShortName();
+ if (shortName == null || !commentLine.Contains(shortName))
continue;
// Mark as having found a tag
@@ -2140,11 +2343,11 @@ namespace MPF.Core
// If we don't already have this site code, add it to the dictionary
if (!info.CommonDiscInfo.CommentsSpecialFields.ContainsKey(siteCode.Value))
- info.CommonDiscInfo.CommentsSpecialFields[siteCode.Value] = $"(VERIFY THIS) {commentLine.Replace(siteCode.ShortName(), string.Empty).Trim()}";
+ info.CommonDiscInfo.CommentsSpecialFields[siteCode.Value] = $"(VERIFY THIS) {commentLine.Replace(shortName, string.Empty).Trim()}";
// Otherwise, append the value to the existing key
else
- info.CommonDiscInfo.CommentsSpecialFields[siteCode.Value] += $", {commentLine.Replace(siteCode.ShortName(), string.Empty).Trim()}";
+ info.CommonDiscInfo.CommentsSpecialFields[siteCode.Value] += $", {commentLine.Replace(shortName, string.Empty).Trim()}";
break;
}
@@ -2218,7 +2421,8 @@ namespace MPF.Core
continue;
// If the line doesn't contain this tag, just skip
- if (!contentLine.Contains(siteCode.ShortName()))
+ var shortName = siteCode.ShortName();
+ if (shortName == null || !contentLine.Contains(shortName))
continue;
// Cache the current site code
@@ -2226,7 +2430,7 @@ namespace MPF.Core
// If we don't already have this site code, add it to the dictionary
if (!info.CommonDiscInfo.ContentsSpecialFields.ContainsKey(siteCode.Value))
- info.CommonDiscInfo.ContentsSpecialFields[siteCode.Value] = $"(VERIFY THIS) {contentLine.Replace(siteCode.ShortName(), string.Empty).Trim()}";
+ info.CommonDiscInfo.ContentsSpecialFields[siteCode.Value] = $"(VERIFY THIS) {contentLine.Replace(shortName, string.Empty).Trim()}";
// A subset of tags can be multiline
addToLast = IsMultiLine(siteCode);
@@ -2288,12 +2492,17 @@ namespace MPF.Core
/// Existing SubmissionInfo object to fill
/// Optional result progress callback
#if NET48
- private static bool FillFromRedump(Core.Data.Options options, SubmissionInfo info, IProgress resultProgress = null)
+ private static bool FillFromRedump(Data.Options options, SubmissionInfo info, IProgress resultProgress = null)
#else
- private async static Task FillFromRedump(Core.Data.Options options, SubmissionInfo info, IProgress resultProgress = null)
+ private async static Task FillFromRedump(Data.Options options, SubmissionInfo info, IProgress? resultProgress = null)
#endif
{
+ // If no username is provided
+ if (string.IsNullOrWhiteSpace(options.RedumpUsername) || string.IsNullOrWhiteSpace(options.RedumpPassword))
+ return false;
+
// Set the current dumper based on username
+ if (info.DumpersAndStatus == null) info.DumpersAndStatus = new DumpersAndStatusSection();
info.DumpersAndStatus.Dumpers = new string[] { options.RedumpUsername };
info.PartiallyMatchedIDs = new List();
@@ -2322,13 +2531,17 @@ namespace MPF.Core
// Setup the full-track checks
bool allFound = true;
+#if NET48
List fullyMatchedIDs = null;
+#else
+ List? fullyMatchedIDs = null;
+#endif
// Loop through all of the hashdata to find matching IDs
resultProgress?.Report(Result.Success("Finding disc matches on Redump..."));
- string[] splitData = info.TracksAndWriteOffsets.ClrMameProData.TrimEnd('\n').Split('\n');
- int trackCount = splitData.Length;
- foreach (string hashData in splitData)
+ var splitData = info.TracksAndWriteOffsets?.ClrMameProData?.TrimEnd('\n')?.Split('\n');
+ int trackCount = splitData?.Length ?? 0;
+ foreach (string hashData in splitData ?? Array.Empty())
{
// Catch any errant blank lines
if (string.IsNullOrWhiteSpace(hashData))
@@ -2354,7 +2567,7 @@ namespace MPF.Core
#if NET48
(bool singleFound, List foundIds) = ValidateSingleTrack(wc, info, hashData, resultProgress);
#else
- (bool singleFound, List foundIds) = await ValidateSingleTrack(wc, info, hashData, resultProgress);
+ (bool singleFound, var foundIds) = await ValidateSingleTrack(wc, info, hashData, resultProgress);
#endif
// Ensure that all tracks are found
@@ -2376,12 +2589,12 @@ namespace MPF.Core
}
// If we don't have any matches but we have a universal hash
- if (!info.PartiallyMatchedIDs.Any() && info.CommonDiscInfo.CommentsSpecialFields.ContainsKey(SiteCode.UniversalHash))
+ if (!info.PartiallyMatchedIDs.Any() && info.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.UniversalHash) == true)
{
#if NET48
(bool singleFound, List foundIds) = ValidateUniversalHash(wc, info, resultProgress);
#else
- (bool singleFound, List foundIds) = await ValidateUniversalHash(wc, info, resultProgress);
+ (bool singleFound, var foundIds) = await ValidateUniversalHash(wc, info, resultProgress);
#endif
// Ensure that the hash is found
@@ -2405,12 +2618,12 @@ namespace MPF.Core
.OrderBy(id => id)
.ToList();
- resultProgress?.Report(Result.Success("Match finding complete! " + (fullyMatchedIDs.Count > 0
+ resultProgress?.Report(Result.Success("Match finding complete! " + (fullyMatchedIDs != null && fullyMatchedIDs.Count > 0
? "Fully Matched IDs: " + string.Join(",", fullyMatchedIDs)
: "No matches found")));
// Exit early if one failed or there are no matched IDs
- if (!allFound || fullyMatchedIDs.Count == 0)
+ if (!allFound || fullyMatchedIDs == null || fullyMatchedIDs.Count == 0)
return false;
// Find the first matched ID where the track count matches, we can grab a bunch of info from it
@@ -2465,7 +2678,9 @@ namespace MPF.Core
foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode)))
{
- text = text.Replace(siteCode.LongName(), siteCode.ShortName());
+ var longname = siteCode.LongName();
+ if (!string.IsNullOrEmpty(longname))
+ text = text.Replace(longname, siteCode.ShortName());
}
// For some outdated tags, we need to use alternate names
@@ -2496,9 +2711,13 @@ namespace MPF.Core
#if NET48
private static List ListSearchResults(RedumpWebClient wc, string query, bool filterForwardSlashes = true)
#else
- private async static Task> ListSearchResults(RedumpHttpClient wc, string query, bool filterForwardSlashes = true)
+ private async static Task?> ListSearchResults(RedumpHttpClient wc, string? query, bool filterForwardSlashes = true)
#endif
{
+ // If there is an invalid query
+ if (string.IsNullOrWhiteSpace(query))
+ return null;
+
var ids = new List();
// Strip quotes
@@ -2549,11 +2768,11 @@ namespace MPF.Core
#if NET48
private static (bool, List) ValidateSingleTrack(RedumpWebClient wc, SubmissionInfo info, string hashData, IProgress resultProgress = null)
#else
- private async static Task<(bool, List)> ValidateSingleTrack(RedumpHttpClient wc, SubmissionInfo info, string hashData, IProgress resultProgress = null)
+ private async static Task<(bool, List?)> ValidateSingleTrack(RedumpHttpClient wc, SubmissionInfo info, string hashData, IProgress? resultProgress = null)
#endif
{
// If the line isn't parseable, we can't validate
- if (!GetISOHashValues(hashData, out long _, out string _, out string _, out string sha1))
+ if (!GetISOHashValues(hashData, out long _, out var _, out var _, out var sha1))
{
resultProgress?.Report(Result.Failure("Line could not be parsed for hash data"));
return (false, null);
@@ -2563,7 +2782,7 @@ namespace MPF.Core
#if NET48
List newIds = ListSearchResults(wc, sha1);
#else
- List newIds = await ListSearchResults(wc, sha1);
+ var newIds = await ListSearchResults(wc, sha1);
#endif
// If we got null back, there was an error
@@ -2578,7 +2797,7 @@ namespace MPF.Core
return (false, null);
// Join the list of found IDs to the existing list, if possible
- if (info.PartiallyMatchedIDs.Any())
+ if (info.PartiallyMatchedIDs != null && info.PartiallyMatchedIDs.Any())
info.PartiallyMatchedIDs.AddRange(newIds);
else
info.PartiallyMatchedIDs = newIds;
@@ -2596,11 +2815,18 @@ namespace MPF.Core
#if NET48
private static (bool, List) ValidateUniversalHash(RedumpWebClient wc, SubmissionInfo info, IProgress resultProgress = null)
#else
- private async static Task<(bool, List)> ValidateUniversalHash(RedumpHttpClient wc, SubmissionInfo info, IProgress resultProgress = null)
+ private async static Task<(bool, List?)> ValidateUniversalHash(RedumpHttpClient wc, SubmissionInfo info, IProgress? resultProgress = null)
#endif
{
+ // If we don't have special fields
+ if (info.CommonDiscInfo?.CommentsSpecialFields == null)
+ {
+ resultProgress?.Report(Result.Failure("Universal hash was missing"));
+ return (false, null);
+ }
+
// If we don't have a universal hash
- string universalHash = info.CommonDiscInfo.CommentsSpecialFields[SiteCode.UniversalHash];
+ var universalHash = info.CommonDiscInfo.CommentsSpecialFields[SiteCode.UniversalHash];
if (string.IsNullOrEmpty(universalHash))
{
resultProgress?.Report(Result.Failure("Universal hash was missing"));
@@ -2618,7 +2844,7 @@ namespace MPF.Core
#if NET48
List newIds = ListSearchResults(wc, universalHash, filterForwardSlashes: false);
#else
- List newIds = await ListSearchResults(wc, universalHash, filterForwardSlashes: false);
+ var newIds = await ListSearchResults(wc, universalHash, filterForwardSlashes: false);
#endif
// If we got null back, there was an error
@@ -2633,7 +2859,7 @@ namespace MPF.Core
return (false, null);
// Join the list of found IDs to the existing list, if possible
- if (info.PartiallyMatchedIDs.Any())
+ if (info.PartiallyMatchedIDs != null && info.PartiallyMatchedIDs.Any())
info.PartiallyMatchedIDs.AddRange(newIds);
else
info.PartiallyMatchedIDs = newIds;
@@ -2658,7 +2884,7 @@ namespace MPF.Core
#if NET48
string discData = wc.DownloadSingleSiteID(id);
#else
- string discData = await wc.DownloadSingleSiteID(id);
+ string? discData = await wc.DownloadSingleSiteID(id);
#endif
if (string.IsNullOrEmpty(discData))
return false;
diff --git a/MPF.Core/MPF.Core.csproj b/MPF.Core/MPF.Core.csproj
index 885c66d7..0a1b9734 100644
--- a/MPF.Core/MPF.Core.csproj
+++ b/MPF.Core/MPF.Core.csproj
@@ -9,6 +9,10 @@
true
+
+ enable
+
+
diff --git a/MPF.Core/Modules/Aaru/Parameters.cs b/MPF.Core/Modules/Aaru/Parameters.cs
index 8ff145b4..14f77292 100644
--- a/MPF.Core/Modules/Aaru/Parameters.cs
+++ b/MPF.Core/Modules/Aaru/Parameters.cs
@@ -26,10 +26,18 @@ namespace MPF.Core.Modules.Aaru
#region Generic Dumping Information
///
+#if NET48
public override string InputPath => InputValue;
+#else
+ public override string? InputPath => InputValue;
+#endif
///
+#if NET48
public override string OutputPath => OutputValue;
+#else
+ public override string? OutputPath => OutputValue;
+#endif
///
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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
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;
}
}
///
+#if NET48
public override string GenerateParameters()
+#else
+ public override string? GenerateParameters()
+#endif
{
List parameters = new List();
@@ -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
///
/// Command string to normalize
/// Normalized command
+#if NET48
private string NormalizeCommand(List parts, ref int start)
+#else
+ private string? NormalizeCommand(List 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
///
/// Command string to normalize
/// Normalized command
+#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
/// CICM Sidecar data generated by Aaru
/// Base path for determining file names
/// String containing the cuesheet, null on error
+#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
/// CICM Sidecar data generated by Aaru
/// Base path for determining file names
/// String containing the datfile, null on error
+#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
/// CICM Sidecar data generated by Aaru
/// Base path for determining file names
/// Datafile containing the hash information, null on error
+#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
///
/// CICM Sidecar data generated by Aaru
/// String containing the PVD, null on error
+#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
///
/// OpticalDisc type from CICM Sidecar data
/// Byte array representing the PVD, null on error
+#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
/// Row ID for outputting
/// Byte span representing the data to write
/// Formatted string representing the sector line
+#if NET48
private static string GenerateSectorOutputLine(string row, ReadOnlySpan bytes)
+#else
+ private static string? GenerateSectorOutputLine(string row, ReadOnlySpan 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
///
/// CICM Sidecar data generated by Aaru
/// Object containing the data, null on error
+#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;
}
///
@@ -3049,7 +3292,11 @@ namespace MPF.Core.Modules.Aaru
///
/// CICM Sidecar data generated by Aaru
/// True if disc type info was set, false otherwise
+#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
///
/// CICM Sidecar data generated by Aaru
/// Formatted string representing the DVD protection, null on error
+#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(""))
+ if (string.IsNullOrWhiteSpace(line))
+ continue;
+ else if (line.StartsWith(""))
totalErrors = 0;
else if (line.StartsWith(""))
return totalErrors ?? -1;
@@ -3173,7 +3426,11 @@ namespace MPF.Core.Modules.Aaru
///
/// CICM Sidecar data generated by Aaru
/// True if hardware info was set, false otherwise
+#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
///
/// CICM Sidecar data generated by Aaru
/// Layerbreak if possible, null on error
+#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
///
/// CICM Sidecar data generated by Aaru
/// Sample write offset if possible, null on error
+#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
///
/// CICM Sidecar data generated by Aaru
/// True on successful extraction of info, false otherwise
+#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
///
/// CICM Sidecar data generated by Aaru
/// True on successful extraction of info, false otherwise
+#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
///
/// CICM Sidecar data generated by Aaru
/// True on successful extraction of info, false otherwise
+#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;
diff --git a/MPF.Core/Modules/BaseParameters.cs b/MPF.Core/Modules/BaseParameters.cs
index 389ccb61..757bd883 100644
--- a/MPF.Core/Modules/BaseParameters.cs
+++ b/MPF.Core/Modules/BaseParameters.cs
@@ -25,7 +25,11 @@ namespace MPF.Core.Modules
/// Geneeic way of reporting a message
///
/// String value to report
+#if NET48
public EventHandler ReportStatus;
+#else
+ public EventHandler? ReportStatus;
+#endif
#endregion
@@ -34,7 +38,11 @@ namespace MPF.Core.Modules
///
/// Base command to run
///
+#if NET48
public string BaseCommand { get; set; }
+#else
+ public string? BaseCommand { get; set; }
+#endif
///
/// Set of flags to pass to the executable
@@ -63,7 +71,11 @@ namespace MPF.Core.Modules
///
/// Process to track external program
///
+#if NET48
private Process process;
+#else
+ private Process? process;
+#endif
#endregion
@@ -72,18 +84,30 @@ namespace MPF.Core.Modules
///
/// Command to flag support mappings
///
+#if NET48
public Dictionary> CommandSupport => GetCommandSupport();
+#else
+ public Dictionary>? CommandSupport => GetCommandSupport();
+#endif
///
/// Input path for operations
///
+#if NET48
public virtual string InputPath => null;
+#else
+ public virtual string? InputPath => null;
+#endif
///
/// Output path for operations
///
/// String representing the path, null on error
+#if NET48
public virtual string OutputPath => null;
+#else
+ public virtual string? OutputPath => null;
+#endif
///
/// Get the processing speed from the implementation
@@ -97,7 +121,11 @@ namespace MPF.Core.Modules
///
/// Path to the executable
///
+#if NET48
public string ExecutablePath { get; set; }
+#else
+ public string? ExecutablePath { get; set; }
+#endif
///
/// Program that this set of parameters represents
@@ -171,20 +199,32 @@ namespace MPF.Core.Modules
/// Get all commands mapped to the supported flags
///
/// Mappings from command to supported flags
+#if NET48
public virtual Dictionary> GetCommandSupport() => null;
+#else
+ public virtual Dictionary>? GetCommandSupport() => null;
+#endif
///
/// Blindly generate a parameter string based on the inputs
///
/// Parameter string for invocation, null on error
+#if NET48
public virtual string GenerateParameters() => null;
+#else
+ public virtual string? GenerateParameters() => null;
+#endif
///
/// Get the default extension for a given media type
///
/// MediaType value to check
/// String representing the media type, null on error
+#if NET48
public virtual string GetDefaultExtension(MediaType? mediaType) => null;
+#else
+ public virtual string? GetDefaultExtension(MediaType? mediaType) => null;
+#endif
///
/// Generate a list of all log files generated
@@ -320,7 +360,11 @@ namespace MPF.Core.Modules
///
/// String content to encode
/// Base64-encoded contents, if possible
+#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
/// file location
/// True if should read as binary, false otherwise (default)
/// Full text of the file, null on error
+#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
/// Long flag string, if available
/// Reference to the position in the parts
/// True if the parameter was processed successfully or skipped, false otherwise
+#if NET48
protected bool ProcessFlagParameter(List parts, string shortFlagString, string longFlagString, ref int i)
+#else
+ protected bool ProcessFlagParameter(List parts, string? shortFlagString, string longFlagString, ref int i)
+#endif
{
if (parts == null)
return false;
@@ -501,7 +553,11 @@ namespace MPF.Core.Modules
/// Reference to the position in the parts
/// True if missing values are allowed, false otherwise
/// True if the parameter was processed successfully or skipped, false otherwise
+#if NET48
protected bool ProcessBooleanParameter(List parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
+#else
+ protected bool ProcessBooleanParameter(List 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
/// Reference to the position in the parts
/// True if missing values are allowed, false otherwise
/// SByte value if success, SByte.MinValue if skipped, null on error/returns>
+#if NET48
protected sbyte? ProcessInt8Parameter(List parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
+#else
+ protected sbyte? ProcessInt8Parameter(List 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
/// Reference to the position in the parts
/// True if missing values are allowed, false otherwise
/// Int16 value if success, Int16.MinValue if skipped, null on error/returns>
+#if NET48
protected short? ProcessInt16Parameter(List parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
+#else
+ protected short? ProcessInt16Parameter(List 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
/// Reference to the position in the parts
/// True if missing values are allowed, false otherwise
/// Int32 value if success, Int32.MinValue if skipped, null on error/returns>
+#if NET48
protected int? ProcessInt32Parameter(List parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
+#else
+ protected int? ProcessInt32Parameter(List 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
/// Reference to the position in the parts
/// True if missing values are allowed, false otherwise
/// Int64 value if success, Int64.MinValue if skipped, null on error/returns>
+#if NET48
protected long? ProcessInt64Parameter(List parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
+#else
+ protected long? ProcessInt64Parameter(List 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
/// Reference to the position in the parts
/// True if missing values are allowed, false otherwise
/// String value if possible, string.Empty on missing, null on error
+#if NET48
protected string ProcessStringParameter(List parts, string flagString, ref int i, bool missingAllowed = false)
- => ProcessStringParameter(parts, null, flagString, ref i, missingAllowed);
+#else
+ protected string? ProcessStringParameter(List parts, string flagString, ref int i, bool missingAllowed = false)
+#endif
+ => ProcessStringParameter(parts, null, flagString, ref i, missingAllowed);
///
/// Process a string parameter
@@ -885,7 +961,11 @@ namespace MPF.Core.Modules
/// Reference to the position in the parts
/// True if missing values are allowed, false otherwise
/// String value if possible, string.Empty on missing, null on error
+#if NET48
protected string ProcessStringParameter(List parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
+#else
+ protected string? ProcessStringParameter(List 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
/// Reference to the position in the parts
/// True if missing values are allowed, false otherwise
/// Byte value if success, Byte.MinValue if skipped, null on error/returns>
+#if NET48
protected byte? ProcessUInt8Parameter(List parts, string shortFlagString, string longFlagString, ref int i, bool missingAllowed = false)
+#else
+ protected byte? ProcessUInt8Parameter(List 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
///
/// .dat file location
/// Relevant pieces of the datfile, null on error
+#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
///
/// Path to the DAT file to parse
/// Filled Datafile on success, null on error
+#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
/// Path to a PIC.bin file
/// Filled DiscInformation on success, null on error
/// This omits the emergency brake information, if it exists
+#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
///
/// Path to the input file
/// True if hashing was successful, false otherwise
+#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
///
/// Path to the input file
/// Filled DateTime on success, null on failure
+#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
///
/// String representing the combined hash data
/// True if extraction was successful, false otherwise
+#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
///
/// Datafile represenging the hash data
/// True if extraction was successful, false otherwise
+#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
///
/// Disc information containing unformatted data
/// True if layerbreak info was set, false otherwise
+#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(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
///
/// Disc information containing the data
/// String representing the PIC identifier, null on error
+#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;
}
///
@@ -1428,7 +1555,11 @@ namespace MPF.Core.Modules
/// Output region, if possible
/// Output EXE date in "yyyy-mm-dd" format if possible, null on error
///
+#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
///
/// Drive letter to use to check
/// Game version if possible, null on error
+#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
///
/// Drive letter to use to check
/// Internal disc serial if possible, null on error
+#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
///
/// Drive letter to use to check
/// Game version if possible, null on error
+#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
///
/// Drive letter to use to check
/// Internal disc serial if possible, null on error
+#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;
}
}
-
+
///
/// Get the version from a PlayStation 4 disc, if possible
///
/// Drive letter to use to check
/// Game version if possible, null on error
+#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
///
/// Drive letter to use to check
/// Internal disc serial if possible, null on error
+#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
///
/// Drive letter to use to check
/// Game version if possible, null on error
+#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])
{
diff --git a/MPF.Core/Modules/CleanRIp/Parameters.cs b/MPF.Core/Modules/CleanRIp/Parameters.cs
index e9e8f7ab..dc0ea013 100644
--- a/MPF.Core/Modules/CleanRIp/Parameters.cs
+++ b/MPF.Core/Modules/CleanRIp/Parameters.cs
@@ -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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
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
/// Path to ISO file
/// Path to discinfo file
///
+#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
/// Path to the BCA file associated with the dump
/// BCA data as a hex string if possible, null on error
/// https://stackoverflow.com/questions/9932096/add-separator-to-string-at-every-n-characters
+#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
/// Path to ISO file
/// Path to discinfo file
///
+#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
/// Output internal version of the game
/// Output internal name of the game
///
+#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);
}
diff --git a/MPF.Core/Modules/Datafile.cs b/MPF.Core/Modules/Datafile.cs
index c42679c2..02836741 100644
--- a/MPF.Core/Modules/Datafile.cs
+++ b/MPF.Core/Modules/Datafile.cs
@@ -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
}
diff --git a/MPF.Core/Modules/DiscImageCreator/Converters.cs b/MPF.Core/Modules/DiscImageCreator/Converters.cs
index a544b38e..577de4a0 100644
--- a/MPF.Core/Modules/DiscImageCreator/Converters.cs
+++ b/MPF.Core/Modules/DiscImageCreator/Converters.cs
@@ -48,7 +48,11 @@ namespace MPF.Core.Modules.DiscImageCreator
/// Command value to check
/// MediaType if possible, null on error
/// This takes the "safe" route by assuming the larger of any given format
+#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
///
/// MediaType value to check
/// Valid extension (with leading '.'), null on error
+#if NET48
public static string Extension(MediaType? type)
+#else
+ public static string? Extension(MediaType? type)
+#endif
{
switch (type)
{
diff --git a/MPF.Core/Modules/DiscImageCreator/Parameters.cs b/MPF.Core/Modules/DiscImageCreator/Parameters.cs
index e9781094..09331996 100644
--- a/MPF.Core/Modules/DiscImageCreator/Parameters.cs
+++ b/MPF.Core/Modules/DiscImageCreator/Parameters.cs
@@ -19,10 +19,18 @@ namespace MPF.Core.Modules.DiscImageCreator
#region Generic Dumping Information
///
+#if NET48
public override string InputPath => DriveLetter;
+#else
+ public override string? InputPath => DriveLetter;
+#endif
///
+#if NET48
public override string OutputPath => Filename;
+#else
+ public override string? OutputPath => Filename;
+#endif
///
///
@@ -46,7 +54,11 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// Drive letter or path to pass to DiscImageCreator
///
+#if NET48
public string DriveLetter { get; set; }
+#else
+ public string? DriveLetter { get; set; }
+#endif
///
/// Drive speed to set, if applicable
@@ -56,12 +68,20 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// Destination filename for DiscImageCreator output
///
+#if NET48
public string Filename { get; set; }
+#else
+ public string? Filename { get; set; }
+#endif
///
/// Optiarc drive output filename for merging
///
+#if NET48
public string OptiarcFilename { get; set; }
+#else
+ public string? OptiarcFilename { get; set; }
+#endif
///
/// Start LBA value for dumping specific sectors
@@ -87,7 +107,11 @@ namespace MPF.Core.Modules.DiscImageCreator
/// Possible values: raw (default), pack
///
/// TODO: Make this an enum
+#if NET48
public string BEOpcodeValue { get; set; }
+#else
+ public string? BEOpcodeValue { get; set; }
+#endif
///
/// C2 reread options for dumping [CD only]
@@ -248,7 +272,7 @@ namespace MPF.Core.Modules.DiscImageCreator
if (!File.Exists($"{basePath}.ccd"))
missingFiles.Add($"{basePath}.ccd");
}
-
+
if (!File.Exists($"{basePath}.dat"))
missingFiles.Add($"{basePath}.dat");
if (!File.Exists($"{basePath}.sub") && !File.Exists($"{basePath}.subtmp"))
@@ -328,7 +352,7 @@ namespace MPF.Core.Modules.DiscImageCreator
missingFiles.Add($"{basePath}_mainInfo.txt");
if (!File.Exists($"{basePath}_volDesc.txt"))
missingFiles.Add($"{basePath}_volDesc.txt");
- }
+ }
// Removed or inconsistent files
//{
@@ -382,15 +406,16 @@ namespace MPF.Core.Modules.DiscImageCreator
///
public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive drive, bool includeArtifacts)
{
- string outputDirectory = Path.GetDirectoryName(basePath);
+ var outputDirectory = Path.GetDirectoryName(basePath);
// Get the dumping program and version
- (string dicCmd, string dicVersion) = GetCommandFilePathAndVersion(basePath);
+ var (dicCmd, dicVersion) = GetCommandFilePathAndVersion(basePath);
+ if (info.DumpingInfo == null) info.DumpingInfo = new DumpingInfoSection();
info.DumpingInfo.DumpingProgram = $"{EnumConverter.LongName(this.InternalProgram)} {dicVersion ?? "Unknown Version"}";
info.DumpingInfo.DumpingDate = GetFileModifiedDate(dicCmd)?.ToString("yyyy-MM-dd HH:mm:ss");
// Fill in the hardware data
- if (GetHardwareInfo($"{basePath}_drive.txt", out string manufacturer, out string model, out string firmware))
+ if (GetHardwareInfo($"{basePath}_drive.txt", out var manufacturer, out var model, out var firmware))
{
info.DumpingInfo.Manufacturer = manufacturer;
info.DumpingInfo.Model = model;
@@ -398,13 +423,14 @@ namespace MPF.Core.Modules.DiscImageCreator
}
// Fill in the disc type data
- if (GetDiscType($"{basePath}_disc.txt", out string discTypeOrBookType))
+ if (GetDiscType($"{basePath}_disc.txt", out var discTypeOrBookType))
info.DumpingInfo.ReportedDiscType = discTypeOrBookType;
// Get the Datafile information
- Datafile datafile = GetDatafile($"{basePath}.dat");
+ var datafile = GetDatafile($"{basePath}.dat");
// Fill in the hash data
+ if (info.TracksAndWriteOffsets == null) info.TracksAndWriteOffsets = new TracksAndWriteOffsetsSection();
info.TracksAndWriteOffsets.ClrMameProData = GenerateDatfile(datafile);
// Extract info based generically on MediaType
@@ -412,7 +438,15 @@ namespace MPF.Core.Modules.DiscImageCreator
{
case MediaType.CDROM:
case MediaType.GDROM: // TODO: Verify GD-ROM outputs this
- info.Extras.PVD = GetPVD($"{basePath}_mainInfo.txt") ?? "Disc has no PVD"; ;
+ if (info.Extras == null) info.Extras = new ExtrasSection();
+ info.Extras.PVD = GetPVD($"{basePath}_mainInfo.txt") ?? "Disc has no PVD";
+
+ if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
+#if NET48
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
// Audio-only discs will fail if there are any C2 errors, so they would never get here
if (this.System.IsAudio())
@@ -456,7 +490,8 @@ namespace MPF.Core.Modules.DiscImageCreator
case MediaType.HDDVD:
case MediaType.BluRay:
// Get the individual hash data, as per internal
- if (GetISOHashValues(datafile, out long size, out string crc32, out string md5, out string sha1))
+ if (info.SizeAndChecksums == null) info.SizeAndChecksums = new SizeAndChecksumsSection();
+ if (GetISOHashValues(datafile, out long size, out var crc32, out var md5, out var sha1))
{
info.SizeAndChecksums.Size = size;
info.SizeAndChecksums.CRC32 = crc32;
@@ -488,6 +523,7 @@ namespace MPF.Core.Modules.DiscImageCreator
}
// Read the PVD
+ if (info.Extras == null) info.Extras = new ExtrasSection();
if (!options.EnableRedumpCompatibility || System != RedumpSystem.MicrosoftXbox)
info.Extras.PVD = GetPVD($"{basePath}_mainInfo.txt") ?? string.Empty;
@@ -522,65 +558,99 @@ namespace MPF.Core.Modules.DiscImageCreator
{
FileInfo fi = new FileInfo($"{basePath}_subIntention.txt");
if (fi.Length > 0)
+ {
+ if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
info.CopyProtection.SecuROMData = GetFullFile($"{basePath}_subIntention.txt") ?? string.Empty;
+ }
}
break;
case RedumpSystem.DVDAudio:
case RedumpSystem.DVDVideo:
+ if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
info.CopyProtection.Protection = GetDVDProtection($"{basePath}_CSSKey.txt", $"{basePath}_disc.txt") ?? 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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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:
- string xgd1XMID = GetXGD1XMID(Path.Combine(outputDirectory, $"{basePath}_DMI.bin"));
+ if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
+#if NET48
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
+
+ string xgd1XMID;
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ xgd1XMID = GetXGD1XMID($"{basePath}_DMI.bin");
+ else
+ xgd1XMID = GetXGD1XMID(Path.Combine(outputDirectory, $"{basePath}_DMI.bin"));
+
XgdInfo xgd1Info = new XgdInfo(xgd1XMID);
if (xgd1Info?.Initialized == true)
{
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.XMID] = xgd1Info.RawXMID;
+#if NET48
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.XMID] = xgd1Info.RawXMID ?? string.Empty;
info.CommonDiscInfo.Serial = xgd1Info.GetSerial() ?? string.Empty;
if (!options.EnableRedumpCompatibility)
+ {
+ if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
info.VersionAndEditions.Version = xgd1Info.GetVersion() ?? string.Empty;
- info.CommonDiscInfo.Region = XgdInfo.GetRegion(xgd1Info.XMID.RegionIdentifier);
+ }
+ info.CommonDiscInfo.Region = XgdInfo.GetRegion(xgd1Info.XMID?.RegionIdentifier);
}
// If we have the new, external DAT
if (File.Exists($"{basePath}_suppl.dat"))
{
- Datafile suppl = GetDatafile($"{basePath}_suppl.dat");
- if (GetXGDAuxHashInfo(suppl, out string xgd1DMIHash, out string xgd1PFIHash, out string xgd1SSHash))
+ var suppl = GetDatafile($"{basePath}_suppl.dat");
+ if (GetXGDAuxHashInfo(suppl, out var xgd1DMIHash, out var xgd1PFIHash, out var xgd1SSHash))
{
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd1DMIHash;
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd1PFIHash;
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd1SSHash;
+
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd1DMIHash ?? string.Empty;
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd1PFIHash ?? string.Empty;
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd1SSHash ?? string.Empty;
}
- if (GetXGDAuxSSInfo($"{basePath}_disc.txt", out string xgd1SS, out string xgd1SSVer))
+ if (GetXGDAuxSSInfo($"{basePath}_disc.txt", out var xgd1SS, out var xgd1SSVer))
{
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd1SSVer;
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd1SSVer ?? string.Empty;
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.SecuritySectorRanges = xgd1SS ?? string.Empty;
}
}
else
{
- if (GetXGDAuxInfo($"{basePath}_disc.txt", out string xgd1DMIHash, out string xgd1PFIHash, out string xgd1SSHash, out string xgd1SS, out string xgd1SSVer))
+ if (GetXGDAuxInfo($"{basePath}_disc.txt", out var xgd1DMIHash, out var xgd1PFIHash, out var xgd1SSHash, out var xgd1SS, 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;
+ 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 = xgd1SS ?? string.Empty;
}
}
@@ -588,42 +658,59 @@ namespace MPF.Core.Modules.DiscImageCreator
break;
case RedumpSystem.MicrosoftXbox360:
- string xgd23XeMID = GetXGD23XeMID(Path.Combine(outputDirectory, $"{basePath}_DMI.bin"));
+ if (info.CommonDiscInfo == null) info.CommonDiscInfo = new CommonDiscInfoSection();
+#if NET48
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
+
+ string xgd23XeMID;
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ xgd23XeMID = GetXGD23XeMID($"{basePath}_DMI.bin");
+ else
+ xgd23XeMID = GetXGD23XeMID(Path.Combine(outputDirectory, $"{basePath}_DMI.bin"));
+
XgdInfo xgd23Info = new XgdInfo(xgd23XeMID);
if (xgd23Info?.Initialized == true)
{
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.XeMID] = xgd23Info.RawXMID;
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.XeMID] = xgd23Info.RawXMID ?? string.Empty;
info.CommonDiscInfo.Serial = xgd23Info.GetSerial() ?? string.Empty;
if (!options.EnableRedumpCompatibility)
+ {
+ if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
info.VersionAndEditions.Version = xgd23Info.GetVersion() ?? string.Empty;
- info.CommonDiscInfo.Region = XgdInfo.GetRegion(xgd23Info.XeMID.RegionIdentifier);
+ }
+ info.CommonDiscInfo.Region = XgdInfo.GetRegion(xgd23Info.XeMID?.RegionIdentifier);
}
// If we have the new, external DAT
if (File.Exists($"{basePath}_suppl.dat"))
{
- Datafile suppl = GetDatafile($"{basePath}_suppl.dat");
- if (GetXGDAuxHashInfo(suppl, out string xgd23DMIHash, out string xgd23PFIHash, out string xgd23SSHash))
+ var suppl = GetDatafile($"{basePath}_suppl.dat");
+ if (GetXGDAuxHashInfo(suppl, out var xgd23DMIHash, out var xgd23PFIHash, out var xgd23SSHash))
{
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd23DMIHash;
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd23PFIHash;
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd23SSHash;
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.DMIHash] = xgd23DMIHash ?? string.Empty;
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.PFIHash] = xgd23PFIHash ?? string.Empty;
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSHash] = xgd23SSHash ?? string.Empty;
}
- if (GetXGDAuxSSInfo($"{basePath}_disc.txt", out string xgd23SS, out string xgd23SSVer))
+ if (GetXGDAuxSSInfo($"{basePath}_disc.txt", out var xgd23SS, out var xgd23SSVer))
{
- info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd23SSVer;
+ info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SSVersion] = xgd23SSVer ?? string.Empty;
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.SecuritySectorRanges = xgd23SS ?? string.Empty;
}
}
else
{
- if (GetXGDAuxInfo($"{basePath}_disc.txt", out string xgd23DMIHash, out string xgd23PFIHash, out string xgd23SSHash, out string xgd23SS, out string xgd23SSVer))
+ if (GetXGDAuxInfo($"{basePath}_disc.txt", out var xgd23DMIHash, out var xgd23PFIHash, out var xgd23SSHash, out var xgd23SS, 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;
+ 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 = xgd23SS ?? string.Empty;
}
}
@@ -633,16 +720,24 @@ namespace MPF.Core.Modules.DiscImageCreator
case RedumpSystem.NamcoSegaNintendoTriforce:
if (this.Type == MediaType.CDROM)
{
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
// Take only the first 16 lines for GD-ROM
if (!string.IsNullOrEmpty(info.Extras.Header))
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
- if (GetGDROMBuildInfo(info.Extras.Header, out string gdSerial, out string gdVersion, out string gdDate))
+ if (GetGDROMBuildInfo(info.Extras.Header, out var gdSerial, out var gdVersion, out var gdDate))
{
// 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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = gdSerial ?? string.Empty;
+ if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
info.VersionAndEditions.Version = gdVersion ?? string.Empty;
info.CommonDiscInfo.EXEDateBuildDate = gdDate ?? string.Empty;
}
@@ -651,15 +746,22 @@ namespace MPF.Core.Modules.DiscImageCreator
break;
case RedumpSystem.SegaMegaCDSegaCD:
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
// Take only the last 16 lines for Sega CD
if (!string.IsNullOrEmpty(info.Extras.Header))
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Skip(16));
- if (GetSegaCDBuildInfo(info.Extras.Header, out string scdSerial, out string fixedDate))
+ if (GetSegaCDBuildInfo(info.Extras.Header, out var scdSerial, out var fixedDate))
{
// 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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = scdSerial ?? string.Empty;
info.CommonDiscInfo.EXEDateBuildDate = fixedDate ?? string.Empty;
}
@@ -669,16 +771,24 @@ namespace MPF.Core.Modules.DiscImageCreator
case RedumpSystem.SegaChihiro:
if (this.Type == MediaType.CDROM)
{
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
// Take only the first 16 lines for GD-ROM
if (!string.IsNullOrEmpty(info.Extras.Header))
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
- if (GetGDROMBuildInfo(info.Extras.Header, out string gdSerial, out string gdVersion, out string gdDate))
+ if (GetGDROMBuildInfo(info.Extras.Header, out var gdSerial, out var gdVersion, out var gdDate))
{
// 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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = gdSerial ?? string.Empty;
+ if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
info.VersionAndEditions.Version = gdVersion ?? string.Empty;
info.CommonDiscInfo.EXEDateBuildDate = gdDate ?? string.Empty;
}
@@ -689,16 +799,24 @@ namespace MPF.Core.Modules.DiscImageCreator
case RedumpSystem.SegaDreamcast:
if (this.Type == MediaType.CDROM)
{
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
// Take only the first 16 lines for GD-ROM
if (!string.IsNullOrEmpty(info.Extras.Header))
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
- if (GetGDROMBuildInfo(info.Extras.Header, out string gdSerial, out string gdVersion, out string gdDate))
+ if (GetGDROMBuildInfo(info.Extras.Header, out var gdSerial, out var gdVersion, out var gdDate))
{
// 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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = gdSerial ?? string.Empty;
+ if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
info.VersionAndEditions.Version = gdVersion ?? string.Empty;
info.CommonDiscInfo.EXEDateBuildDate = gdDate ?? string.Empty;
}
@@ -709,16 +827,24 @@ namespace MPF.Core.Modules.DiscImageCreator
case RedumpSystem.SegaNaomi:
if (this.Type == MediaType.CDROM)
{
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
// Take only the first 16 lines for GD-ROM
if (!string.IsNullOrEmpty(info.Extras.Header))
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
- if (GetGDROMBuildInfo(info.Extras.Header, out string gdSerial, out string gdVersion, out string gdDate))
+ if (GetGDROMBuildInfo(info.Extras.Header, out var gdSerial, out var gdVersion, out var gdDate))
{
// 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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = gdSerial ?? string.Empty;
+ if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
info.VersionAndEditions.Version = gdVersion ?? string.Empty;
info.CommonDiscInfo.EXEDateBuildDate = gdDate ?? string.Empty;
}
@@ -729,16 +855,24 @@ namespace MPF.Core.Modules.DiscImageCreator
case RedumpSystem.SegaNaomi2:
if (this.Type == MediaType.CDROM)
{
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? string.Empty;
// Take only the first 16 lines for GD-ROM
if (!string.IsNullOrEmpty(info.Extras.Header))
info.Extras.Header = string.Join("\n", info.Extras.Header.Split('\n').Take(16));
- if (GetGDROMBuildInfo(info.Extras.Header, out string gdSerial, out string gdVersion, out string gdDate))
+ if (GetGDROMBuildInfo(info.Extras.Header, out var gdSerial, out var gdVersion, out var gdDate))
{
// 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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = gdSerial ?? string.Empty;
+ if (info.VersionAndEditions == null) info.VersionAndEditions = new VersionAndEditionsSection();
info.VersionAndEditions.Version = gdVersion ?? string.Empty;
info.CommonDiscInfo.EXEDateBuildDate = gdDate ?? string.Empty;
}
@@ -747,16 +881,24 @@ namespace MPF.Core.Modules.DiscImageCreator
break;
case RedumpSystem.SegaSaturn:
+ if (info.Extras == null) info.Extras = new ExtrasSection();
info.Extras.Header = GetSegaHeader($"{basePath}_mainInfo.txt") ?? 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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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;
}
@@ -764,9 +906,15 @@ namespace MPF.Core.Modules.DiscImageCreator
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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = playstationSerial ?? string.Empty;
info.CommonDiscInfo.Region = info.CommonDiscInfo.Region ?? playstationRegion;
info.CommonDiscInfo.EXEDateBuildDate = playstationDate;
@@ -778,34 +926,64 @@ namespace MPF.Core.Modules.DiscImageCreator
else if (File.Exists($"{basePath}.img_EccEdc.txt"))
psEdcStatus = GetPlayStationEDCStatus($"{basePath}.img_EccEdc.txt");
+ if (info.EDC == null) info.EDC = new EDCSection();
info.EDC.EDC = psEdcStatus.ToYesNo();
+ if (info.CopyProtection == null) info.CopyProtection = new CopyProtectionSection();
info.CopyProtection.AntiModchip = GetPlayStationAntiModchipDetected($"{basePath}_disc.txt").ToYesNo();
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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#endif
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.InternalSerialName] = GetPlayStation5Serial(drive?.Letter) ?? string.Empty;
break;
}
@@ -813,61 +991,67 @@ namespace MPF.Core.Modules.DiscImageCreator
// Fill in any artifacts that exist, Base64-encoded, if we need to
if (includeArtifacts)
{
+ if (info.Artifacts == null) info.Artifacts = new Dictionary();
+
//if (File.Exists($"{basePath}.c2"))
- // info.Artifacts["c2"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}.c2"));
+ // info.Artifacts["c2"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}.c2")) ?? string.Empty;
if (File.Exists($"{basePath}_c2Error.txt"))
- info.Artifacts["c2Error"] = GetBase64(GetFullFile($"{basePath}_c2Error.txt"));
+ info.Artifacts["c2Error"] = GetBase64(GetFullFile($"{basePath}_c2Error.txt")) ?? string.Empty;
if (File.Exists($"{basePath}.ccd"))
- info.Artifacts["ccd"] = GetBase64(GetFullFile($"{basePath}.ccd"));
+ info.Artifacts["ccd"] = GetBase64(GetFullFile($"{basePath}.ccd")) ?? string.Empty;
if (File.Exists($"{basePath}_cmd.txt")) // TODO: Figure out how to read in the timestamp-named file
- info.Artifacts["cmd"] = GetBase64(GetFullFile($"{basePath}_cmd.txt"));
+ info.Artifacts["cmd"] = GetBase64(GetFullFile($"{basePath}_cmd.txt")) ?? string.Empty;
if (File.Exists($"{basePath}_CSSKey.txt"))
- info.Artifacts["csskey"] = GetBase64(GetFullFile($"{basePath}_CSSKey.txt"));
+ info.Artifacts["csskey"] = GetBase64(GetFullFile($"{basePath}_CSSKey.txt")) ?? 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}.dat"))
- info.Artifacts["dat"] = GetBase64(GetFullFile($"{basePath}.dat"));
+ info.Artifacts["dat"] = GetBase64(GetFullFile($"{basePath}.dat")) ?? string.Empty;
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(Path.Combine(outputDirectory, $"{basePath}_DMI.bin")))
- // info.Artifacts["dmi"] = Convert.ToBase64String(File.ReadAllBytes(Path.Combine(outputDirectory, $"{basePath}_DMI.bin")));
+ // info.Artifacts["dmi"] = Convert.ToBase64String(File.ReadAllBytes(Path.Combine(outputDirectory, $"{basePath}_DMI.bin"))) ?? 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}_img.cue"))
- info.Artifacts["img_cue"] = GetBase64(GetFullFile($"{basePath}_img.cue"));
+ info.Artifacts["img_cue"] = GetBase64(GetFullFile($"{basePath}_img.cue")) ?? string.Empty;
if (File.Exists($"{basePath}.img_EdcEcc.txt"))
- info.Artifacts["img_EdcEcc"] = GetBase64(GetFullFile($"{basePath}.img_EdcEcc.txt"));
+ info.Artifacts["img_EdcEcc"] = GetBase64(GetFullFile($"{basePath}.img_EdcEcc.txt")) ?? string.Empty;
if (File.Exists($"{basePath}.img_EccEdc.txt"))
- info.Artifacts["img_EdcEcc"] = GetBase64(GetFullFile($"{basePath}.img_EccEdc.txt"));
+ info.Artifacts["img_EdcEcc"] = GetBase64(GetFullFile($"{basePath}.img_EccEdc.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}_PFI.bin"))
- // info.Artifacts["pfi"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}_PFI.bin"));
+ // info.Artifacts["pfi"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}_PFI.bin")) ?? string.Empty;
//if (File.Exists($"{basePath}_PIC.bin"))
- // info.Artifacts["pfi"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}_PFI.bin"));
+ // info.Artifacts["pfi"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}_PFI.bin")) ?? string.Empty;
//if (File.Exists($"{basePath}_SS.bin"))
- // info.Artifacts["ss"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}_SS.bin"));
+ // info.Artifacts["ss"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}_SS.bin")) ?? string.Empty;
if (File.Exists($"{basePath}.sub"))
- info.Artifacts["sub"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}.sub"));
+ info.Artifacts["sub"] = Convert.ToBase64String(File.ReadAllBytes($"{basePath}.sub")) ?? string.Empty;
if (File.Exists($"{basePath}_subError.txt"))
- info.Artifacts["subError"] = GetBase64(GetFullFile($"{basePath}_subError.txt"));
+ info.Artifacts["subError"] = GetBase64(GetFullFile($"{basePath}_subError.txt")) ?? string.Empty;
if (File.Exists($"{basePath}_subInfo.txt"))
- info.Artifacts["subInfo"] = GetBase64(GetFullFile($"{basePath}_subInfo.txt"));
+ info.Artifacts["subInfo"] = GetBase64(GetFullFile($"{basePath}_subInfo.txt")) ?? string.Empty;
if (File.Exists($"{basePath}_subIntention.txt"))
- info.Artifacts["subIntention"] = GetBase64(GetFullFile($"{basePath}_subIntention.txt"));
+ info.Artifacts["subIntention"] = GetBase64(GetFullFile($"{basePath}_subIntention.txt")) ?? string.Empty;
//if (File.Exists($"{basePath}_sub.txt"))
- // info.Artifacts["subReadable"] = GetBase64(GetFullFile($"{basePath}_sub.txt"));
+ // info.Artifacts["subReadable"] = GetBase64(GetFullFile($"{basePath}_sub.txt")) ?? string.Empty;
//if (File.Exists($"{basePath}_subReadable.txt"))
- // info.Artifacts["subReadable"] = GetBase64(GetFullFile($"{basePath}_subReadable.txt"));
+ // info.Artifacts["subReadable"] = GetBase64(GetFullFile($"{basePath}_subReadable.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;
}
}
///
+#if NET48
public override string GenerateParameters()
+#else
+ public override string? GenerateParameters()
+#endif
{
List parameters = new List();
@@ -957,7 +1141,7 @@ namespace MPF.Core.Modules.DiscImageCreator
|| BaseCommand == CommandStrings.XGD3Swap)
{
if (DriveSpeed != null)
- parameters.Add(DriveSpeed.ToString());
+ parameters.Add(DriveSpeed.ToString() ?? string.Empty);
else
return null;
}
@@ -968,8 +1152,8 @@ namespace MPF.Core.Modules.DiscImageCreator
{
if (StartLBAValue != null && EndLBAValue != null)
{
- parameters.Add(StartLBAValue.ToString());
- parameters.Add(EndLBAValue.ToString());
+ parameters.Add(StartLBAValue.ToString() ?? string.Empty);
+ parameters.Add(EndLBAValue.ToString() ?? string.Empty);
}
else
return null;
@@ -982,7 +1166,7 @@ namespace MPF.Core.Modules.DiscImageCreator
{
parameters.Add(FlagStrings.AddOffset);
if (AddOffsetValue != null)
- parameters.Add(AddOffsetValue.ToString());
+ parameters.Add(AddOffsetValue.ToString() ?? string.Empty);
}
}
@@ -1003,7 +1187,7 @@ namespace MPF.Core.Modules.DiscImageCreator
// BE Opcode
if (IsFlagSupported(FlagStrings.BEOpcode))
{
- if (this[FlagStrings.BEOpcode] == true && this[FlagStrings.D8Opcode] != true)
+ if (this[FlagStrings.BEOpcode] == true && this[FlagStrings.D8Opcode]== false)
{
parameters.Add(FlagStrings.BEOpcode);
if (BEOpcodeValue != null
@@ -1021,29 +1205,29 @@ namespace MPF.Core.Modules.DiscImageCreator
if (C2OpcodeValue[0] != null)
{
if (C2OpcodeValue[0] > 0)
- parameters.Add(C2OpcodeValue[0].ToString());
+ parameters.Add(C2OpcodeValue[0].ToString() ?? string.Empty);
else
return null;
}
if (C2OpcodeValue[1] != null)
{
- parameters.Add(C2OpcodeValue[1].ToString());
+ parameters.Add(C2OpcodeValue[1].ToString() ?? string.Empty);
}
if (C2OpcodeValue[2] != null)
{
if (C2OpcodeValue[2] == 0)
{
- parameters.Add(C2OpcodeValue[2].ToString());
+ parameters.Add(C2OpcodeValue[2].ToString() ?? string.Empty);
}
else if (C2OpcodeValue[2] == 1)
{
- parameters.Add(C2OpcodeValue[2].ToString());
+ parameters.Add(C2OpcodeValue[2].ToString() ?? string.Empty);
if (C2OpcodeValue[3] != null && C2OpcodeValue[4] != null)
{
if (C2OpcodeValue[3] > 0 && C2OpcodeValue[4] > 0)
{
- parameters.Add(C2OpcodeValue[3].ToString());
- parameters.Add(C2OpcodeValue[4].ToString());
+ parameters.Add(C2OpcodeValue[3].ToString() ?? string.Empty);
+ parameters.Add(C2OpcodeValue[4].ToString() ?? string.Empty);
}
else
{
@@ -1094,7 +1278,7 @@ namespace MPF.Core.Modules.DiscImageCreator
{
parameters.Add(FlagStrings.DVDReread);
if (DVDRereadValue != null)
- parameters.Add(DVDRereadValue.ToString());
+ parameters.Add(DVDRereadValue.ToString() ?? string.Empty);
}
}
@@ -1112,7 +1296,7 @@ namespace MPF.Core.Modules.DiscImageCreator
{
parameters.Add(FlagStrings.Fix);
if (FixValue != null)
- parameters.Add(FixValue.ToString());
+ parameters.Add(FixValue.ToString() ?? string.Empty);
else
return null;
}
@@ -1125,7 +1309,7 @@ namespace MPF.Core.Modules.DiscImageCreator
{
parameters.Add(FlagStrings.ForceUnitAccess);
if (ForceUnitAccessValue != null)
- parameters.Add(ForceUnitAccessValue.ToString());
+ parameters.Add(ForceUnitAccessValue.ToString() ?? string.Empty);
}
}
@@ -1136,7 +1320,7 @@ namespace MPF.Core.Modules.DiscImageCreator
{
parameters.Add(FlagStrings.MultiSectorRead);
if (MultiSectorReadValue != null)
- parameters.Add(MultiSectorReadValue.ToString());
+ parameters.Add(MultiSectorReadValue.ToString() ?? string.Empty);
}
}
@@ -1182,7 +1366,7 @@ namespace MPF.Core.Modules.DiscImageCreator
{
parameters.Add(FlagStrings.NoSkipSS);
if (NoSkipSecuritySectorValue != null)
- parameters.Add(NoSkipSecuritySectorValue.ToString());
+ parameters.Add(NoSkipSecuritySectorValue.ToString() ?? string.Empty);
}
}
@@ -1193,7 +1377,7 @@ namespace MPF.Core.Modules.DiscImageCreator
{
parameters.Add(FlagStrings.PadSector);
if (PadSectorValue != null)
- parameters.Add(PadSectorValue.ToString());
+ parameters.Add(PadSectorValue.ToString() ?? string.Empty);
}
}
@@ -1230,8 +1414,8 @@ namespace MPF.Core.Modules.DiscImageCreator
if (ReverseStartLBAValue == null || ReverseEndLBAValue == null)
return null;
- parameters.Add(ReverseStartLBAValue.ToString());
- parameters.Add(ReverseEndLBAValue.ToString());
+ parameters.Add(ReverseStartLBAValue.ToString() ?? string.Empty);
+ parameters.Add(ReverseEndLBAValue.ToString() ?? string.Empty);
}
}
}
@@ -1252,7 +1436,7 @@ namespace MPF.Core.Modules.DiscImageCreator
if (ScanFileProtectValue != null)
{
if (ScanFileProtectValue > 0)
- parameters.Add(ScanFileProtectValue.ToString());
+ parameters.Add(ScanFileProtectValue.ToString() ?? string.Empty);
else
return null;
}
@@ -1282,14 +1466,14 @@ namespace MPF.Core.Modules.DiscImageCreator
if (SkipSectorValue[0] != null)
{
if (SkipSectorValue[0] > 0)
- parameters.Add(SkipSectorValue[0].ToString());
+ parameters.Add(SkipSectorValue[0].ToString() ?? string.Empty);
else
return null;
}
if (SkipSectorValue[1] != null)
{
if (SkipSectorValue[1] == 0)
- parameters.Add(SkipSectorValue[1].ToString());
+ parameters.Add(SkipSectorValue[1].ToString() ?? string.Empty);
}
}
}
@@ -1303,7 +1487,7 @@ namespace MPF.Core.Modules.DiscImageCreator
if (SubchannelReadLevelValue != null)
{
if (SubchannelReadLevelValue >= 0 && SubchannelReadLevelValue <= 2)
- parameters.Add(SubchannelReadLevelValue.ToString());
+ parameters.Add(SubchannelReadLevelValue.ToString() ?? string.Empty);
else
return null;
}
@@ -1326,7 +1510,7 @@ namespace MPF.Core.Modules.DiscImageCreator
if (VideoNowValue != null)
{
if (VideoNowValue >= 0)
- parameters.Add(VideoNowValue.ToString());
+ parameters.Add(VideoNowValue.ToString() ?? string.Empty);
else
return null;
}
@@ -1582,12 +1766,16 @@ namespace MPF.Core.Modules.DiscImageCreator
}
///
+#if NET48
public override string GetDefaultExtension(MediaType? mediaType) => Converters.Extension(mediaType);
+#else
+ public override string? GetDefaultExtension(MediaType? mediaType) => Converters.Extension(mediaType);
+#endif
///
public override List GetLogFilePaths(string basePath)
{
- (string cmdPath, _) = GetCommandFilePathAndVersion(basePath);
+ (var cmdPath, _) = GetCommandFilePathAndVersion(basePath);
List logFiles = new List();
switch (this.Type)
@@ -2316,7 +2504,11 @@ namespace MPF.Core.Modules.DiscImageCreator
// Flag read-out values
byte? byteValue = null;
int? intValue = null;
+#if NET48
string stringValue = null;
+#else
+ string? stringValue = null;
+#endif
// Add Offset
intValue = ProcessInt32Parameter(parts, FlagStrings.AddOffset, ref i, missingAllowed: true);
@@ -2527,7 +2719,11 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// Base filename and path to use for checking
/// Tuple of file path and version as strings, both null on error
+#if NET48
private static (string, string) GetCommandFilePathAndVersion(string basePath)
+#else
+ private static (string?, string?) GetCommandFilePathAndVersion(string basePath)
+#endif
{
// If we have an invalid base path, we can do nothing
if (string.IsNullOrWhiteSpace(basePath))
@@ -2538,9 +2734,12 @@ namespace MPF.Core.Modules.DiscImageCreator
Regex cmdFilenameRegex = new Regex(Regex.Escape(basePathFileName) + @"_(\d{8})T\d{6}\.txt");
// Find the first match for the command file
- string parentDirectory = Path.GetDirectoryName(basePath);
+ var parentDirectory = Path.GetDirectoryName(basePath);
+ if (string.IsNullOrWhiteSpace(parentDirectory))
+ return (null, null);
+
var currentFiles = Directory.GetFiles(parentDirectory);
- string commandPath = currentFiles.FirstOrDefault(f => cmdFilenameRegex.IsMatch(f));
+ var commandPath = currentFiles.FirstOrDefault(f => cmdFilenameRegex.IsMatch(f));
if (string.IsNullOrWhiteSpace(commandPath))
return (null, null);
@@ -2621,7 +2820,11 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// _disc.txt file location
/// True if disc type info was set, false otherwise
+#if NET48
private static bool GetDiscType(string drive, out string discTypeOrBookType)
+#else
+ private static bool GetDiscType(string drive, out string? discTypeOrBookType)
+#endif
{
// Set the default values
discTypeOrBookType = null;
@@ -2637,7 +2840,7 @@ namespace MPF.Core.Modules.DiscImageCreator
// Create a hashset to contain all of the found values
var discTypeOrBookTypeSet = new HashSet();
- string line = sr.ReadLine();
+ var line = sr.ReadLine();
while (line != null)
{
// Trim the line for later use
@@ -2693,14 +2896,22 @@ namespace MPF.Core.Modules.DiscImageCreator
/// _CSSKey.txt file location
/// _disc.txt file location
/// Formatted string representing the DVD protection, null on error
+#if NET48
private static string GetDVDProtection(string cssKey, string disc)
+#else
+ private static string? GetDVDProtection(string cssKey, string disc)
+#endif
{
// If one of the files doesn't exist, we can't get info from them
if (!File.Exists(disc))
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
// Get everything from _disc.txt first
using (StreamReader sr = File.OpenText(disc))
@@ -2708,18 +2919,21 @@ namespace MPF.Core.Modules.DiscImageCreator
try
{
// Fast forward to the copyright information
- while (!sr.ReadLine().Trim().StartsWith("========== CopyrightInformation ==========")) ;
+ while (sr.ReadLine()?.Trim()?.StartsWith("========== CopyrightInformation ==========")== false) ;
// Now read until we hit the manufacturing information
- string line = sr.ReadLine().Trim();
- while (!line.StartsWith("========== ManufacturingInformation =========="))
+ var line = sr.ReadLine()?.Trim();
+ while (line?.StartsWith("========== ManufacturingInformation ==========")== false)
{
+ if (line == null)
+ break;
+
if (line.StartsWith("CopyrightProtectionType"))
copyrightProtectionSystemType = line.Substring("CopyrightProtectionType: ".Length);
else if (line.StartsWith("RegionManagementInformation"))
region = line.Substring("RegionManagementInformation: ".Length);
- line = sr.ReadLine().Trim();
+ line = sr.ReadLine()?.Trim();
}
}
catch { }
@@ -2735,7 +2949,9 @@ namespace MPF.Core.Modules.DiscImageCreator
// Read until the end
while (!sr.EndOfStream)
{
- string line = sr.ReadLine().Trim();
+ var line = sr.ReadLine()?.Trim();
+ if (line == null)
+ break;
if (line.StartsWith("DecryptedDiscKey"))
{
@@ -2813,7 +3029,9 @@ namespace MPF.Core.Modules.DiscImageCreator
// Read in the error count whenever we find it
while (!sr.EndOfStream)
{
- string line = sr.ReadLine().Trim();
+ var line = sr.ReadLine()?.Trim();
+ if (line == null)
+ break;
if (line.StartsWith("[NO ERROR]"))
{
@@ -2854,7 +3072,11 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// <String representing a formatter variant of the GD-ROM header
/// True on successful extraction of info, false otherwise
+#if NET48
private static bool GetGDROMBuildInfo(string segaHeader, out string serial, out string version, out string date)
+#else
+ private static bool GetGDROMBuildInfo(string? segaHeader, out string? serial, out string? version, out string? date)
+#endif
{
serial = null; version = null; date = null;
@@ -2885,7 +3107,11 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// _drive.txt file location
/// True if hardware info was set, false otherwise
+#if NET48
private static bool GetHardwareInfo(string drive, out string manufacturer, out string model, out string firmware)
+#else
+ private static bool GetHardwareInfo(string drive, out string? manufacturer, out string? model, out string? firmware)
+#endif
{
// Set the default values
manufacturer = null; model = null; firmware = null;
@@ -2898,7 +3124,7 @@ namespace MPF.Core.Modules.DiscImageCreator
{
try
{
- string line = sr.ReadLine();
+ var line = sr.ReadLine();
while (line != null)
{
// Trim the line for later use
@@ -2940,7 +3166,11 @@ namespace MPF.Core.Modules.DiscImageCreator
/// _disc.txt file location
/// True if XGD layerbreak info should be used, false otherwise
/// Layerbreak if possible, null on error
+#if NET48
private static string GetLayerbreak(string disc, bool xgd)
+#else
+ private static string? GetLayerbreak(string disc, bool xgd)
+#endif
{
// If the file doesn't exist, we can't get info from it
if (!File.Exists(disc))
@@ -2950,7 +3180,7 @@ namespace MPF.Core.Modules.DiscImageCreator
{
try
{
- string line = sr.ReadLine();
+ var line = sr.ReadLine();
while (line != null)
{
// Trim the line for later use
@@ -2997,7 +3227,11 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// _disc.txt file location
/// Formatted multisession information, null on error
+#if NET48
private static string GetMultisessionInformation(string disc)
+#else
+ private static string? GetMultisessionInformation(string disc)
+#endif
{
// If the file doesn't exist, we can't get info from it
if (!File.Exists(disc))
@@ -3008,33 +3242,49 @@ namespace MPF.Core.Modules.DiscImageCreator
try
{
// Seek to the TOC data
- string line = sr.ReadLine();
+ var line = sr.ReadLine();
+ if (line == null)
+ return null;
+
if (!line.StartsWith("========== TOC"))
- while (!(line = sr.ReadLine()).StartsWith("========== TOC")) ;
+ while ((line = sr.ReadLine())?.StartsWith("========== TOC")== false) ;
+ if (line == null)
+ return null;
// Create the required regex
Regex trackLengthRegex = new Regex(@"^\s*.*?Track\s*([0-9]{1,2}), LBA\s*[0-9]{1,8} - \s*[0-9]{1,8}, Length\s*([0-9]{1,8})$");
// Read in the track length data
var trackLengthMapping = new Dictionary();
- while ((line = sr.ReadLine()).Contains("Track"))
+ while ((line = sr.ReadLine())?.Contains("Track") == true)
{
var match = trackLengthRegex.Match(line);
trackLengthMapping[match.Groups[1].Value] = match.Groups[2].Value;
}
+ if (line == null)
+ return null;
+
// Seek to the FULL TOC data
line = sr.ReadLine();
+ if (line == null)
+ return null;
+
if (!line.StartsWith("========== FULL TOC"))
- while (!(line = sr.ReadLine()).StartsWith("========== FULL TOC")) ;
+ while ((line = sr.ReadLine())?.StartsWith("========== FULL TOC")== false) ;
+ if (line == null)
+ return null;
// Create the required regex
Regex trackSessionRegex = new Regex(@"^\s*Session\s*([0-9]{1,2}),.*?,\s*Track\s*([0-9]{1,2}).*?$");
// Read in the track session data
var trackSessionMapping = new Dictionary();
- while (!(line = sr.ReadLine()).StartsWith("========== OpCode"))
+ while ((line = sr.ReadLine())?.StartsWith("========== OpCode")== false)
{
+ if (line == null)
+ return null;
+
var match = trackSessionRegex.Match(line);
if (!match.Success)
continue;
@@ -3047,26 +3297,35 @@ namespace MPF.Core.Modules.DiscImageCreator
return null;
// Seek to the multisession data
- line = sr.ReadLine().Trim();
+ line = sr.ReadLine()?.Trim();
+ if (line == null)
+ return null;
+
if (!line.StartsWith("Lead-out length"))
- while (!(line = sr.ReadLine().Trim()).StartsWith("Lead-out length")) ;
+ while ((line = sr.ReadLine()?.Trim())?.StartsWith("Lead-out length")== false) ;
// TODO: Are there any examples of 3+ session discs?
// Read the first session lead-out
- string firstSessionLeadOutLengthString = line.Substring("Lead-out length of 1st session: ".Length);
- line = sr.ReadLine().Trim();
-
+ var firstSessionLeadOutLengthString = line?.Substring("Lead-out length of 1st session: ".Length);
+ line = sr.ReadLine()?.Trim();
+ if (line == null)
+ return null;
+
// Read the second session lead-in, if it exists
+#if NET48
string secondSessionLeadInLengthString = null;
- while (line.StartsWith("Lead-in length"))
+#else
+ string? secondSessionLeadInLengthString = null;
+#endif
+ while (line?.StartsWith("Lead-in length")== false)
{
- secondSessionLeadInLengthString = line.Substring("Lead-in length of 2nd session: ".Length);
- line = sr.ReadLine().Trim();
+ secondSessionLeadInLengthString = line?.Substring("Lead-in length of 2nd session: ".Length);
+ line = sr.ReadLine()?.Trim();
}
-
+
// Read the second session pregap
- string secondSessionPregapLengthString = line.Substring("Pregap length of 1st track of 2nd session: ".Length);
+ var secondSessionPregapLengthString = line?.Substring("Pregap length of 1st track of 2nd session: ".Length);
// Calculate the session gap total
if (!int.TryParse(firstSessionLeadOutLengthString, out int firstSessionLeadOutLength))
@@ -3084,7 +3343,7 @@ namespace MPF.Core.Modules.DiscImageCreator
if (!int.TryParse(lengthMapping.Value, out int trackLength))
trackLength = 0;
- if (trackSessionMapping.TryGetValue(lengthMapping.Key, out string session))
+ if (trackSessionMapping.TryGetValue(lengthMapping.Key, out var session))
firstSessionLength += session == "1" ? trackLength : 0;
totalLength += trackLength;
@@ -3116,7 +3375,11 @@ namespace MPF.Core.Modules.DiscImageCreator
/// Number of characters to trim the PIC to, if -1, ignored
/// PIC data as a hex string if possible, null on error
/// https://stackoverflow.com/questions/9932096/add-separator-to-string-at-every-n-characters
+#if NET48
private static string GetPIC(string picPath, int trimLength = -1)
+#else
+ private static string? GetPIC(string picPath, int trimLength = -1)
+#endif
{
// If the file doesn't exist, we can't get the info
if (!File.Exists(picPath))
@@ -3124,7 +3387,10 @@ namespace MPF.Core.Modules.DiscImageCreator
try
{
- string hex = GetFullFile(picPath, true);
+ var hex = GetFullFile(picPath, true);
+ if (hex == null)
+ return null;
+
if (trimLength > -1)
hex = hex.Substring(0, trimLength);
@@ -3153,15 +3419,21 @@ namespace MPF.Core.Modules.DiscImageCreator
try
{
// Check for either antimod string
- string line = sr.ReadLine().Trim();
+ var line = sr.ReadLine()?.Trim();
+ if (line == null)
+ return null;
+
while (!sr.EndOfStream)
{
+ if (line == null)
+ return false;
+
if (line.StartsWith("Detected anti-mod string"))
return true;
else if (line.StartsWith("No anti-mod string"))
return false;
- line = sr.ReadLine().Trim();
+ line = sr.ReadLine()?.Trim();
}
return false;
@@ -3194,7 +3466,10 @@ namespace MPF.Core.Modules.DiscImageCreator
{
while (!sr.EndOfStream)
{
- string line = sr.ReadLine();
+ var line = sr.ReadLine();
+ if (line == null)
+ break;
+
if (line.Contains("mode 2 form 2"))
modeTwoFormTwo++;
else if (line.Contains("mode 2 no edc"))
@@ -3233,7 +3508,11 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// _mainInfo.txt file location
/// Newline-delimited PVD if possible, null on error
+#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))
@@ -3244,33 +3523,45 @@ namespace MPF.Core.Modules.DiscImageCreator
try
{
// If we're in a new mainInfo, the location of the header changed
- string line = sr.ReadLine();
+ var line = sr.ReadLine();
+ if (line == null)
+ return null;
+
if (line.StartsWith("========== OpCode")
|| line.StartsWith("========== TOC (Binary)")
|| line.StartsWith("========== FULL TOC (Binary)"))
{
// Seek to unscrambled data
- while (!(line = sr.ReadLine()).StartsWith("========== Check Volume Descriptor ==========")) ;
+ while ((line = sr.ReadLine())?.StartsWith("========== Check Volume Descriptor ==========")== false) ;
// Read the next line so the search goes properly
line = sr.ReadLine();
}
+ if (line == null)
+ return null;
+
// Make sure we're in the area
- if (!line.StartsWith("========== LBA"))
- while (!(line = sr.ReadLine()).StartsWith("========== LBA")) ;
+ if (line.StartsWith("========== LBA") == true)
+ while ((line = sr.ReadLine())?.StartsWith("========== LBA")== false) ;
+ if (line == null)
+ return null;
// If we have a Sega disc, skip sector 0
if (line.StartsWith("========== LBA[000000, 0000000]: Main Channel =========="))
- while (!(line = sr.ReadLine()).StartsWith("========== LBA")) ;
+ while ((line = sr.ReadLine())?.StartsWith("========== LBA")== false) ;
+ if (line == null)
+ return null;
// If we have a PlayStation disc, skip sector 4
if (line.StartsWith("========== LBA[000004, 0x00004]: Main Channel =========="))
- while (!(line = sr.ReadLine()).StartsWith("========== LBA")) ;
+ while ((line = sr.ReadLine())?.StartsWith("========== LBA")== false) ;
+ if (line == null)
+ return null;
// We assume the first non-LBA0/4 sector listed is the proper one
// Fast forward to the PVD
- while (!(line = sr.ReadLine()).StartsWith("0310")) ;
+ while ((line = sr.ReadLine())?.StartsWith("0310")== false) ;
// Now that we're at the PVD, read each line in and concatenate
string pvd = "";
@@ -3292,7 +3583,11 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// <String representing a formatter variant of the Saturn header
/// True on successful extraction of info, false otherwise
+#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;
@@ -3325,7 +3620,11 @@ namespace MPF.Core.Modules.DiscImageCreator
/// <String representing a formatter variant of the Sega CD header
/// True on successful extraction of info, false otherwise
/// Note that this works for MOST headers, except ones where the copyright stretches > 1 line
+#if NET48
private static bool GetSegaCDBuildInfo(string segaHeader, out string serial, out string date)
+#else
+ private static bool GetSegaCDBuildInfo(string? segaHeader, out string? serial, out string? date)
+#endif
{
serial = null; date = null;
@@ -3408,7 +3707,11 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// _mainInfo.txt file location
/// Header as a byte array if possible, null on error
+#if NET48
private static string GetSegaHeader(string mainInfo)
+#else
+ private static string? GetSegaHeader(string mainInfo)
+#endif
{
// If the file doesn't exist, we can't get info from it
if (!File.Exists(mainInfo))
@@ -3419,28 +3722,42 @@ namespace MPF.Core.Modules.DiscImageCreator
try
{
// If we're in a new mainInfo, the location of the header changed
- string line = sr.ReadLine();
+ var line = sr.ReadLine();
+ if (line == null)
+ return null;
+
if (line.StartsWith("========== OpCode")
|| line.StartsWith("========== TOC (Binary)")
|| line.StartsWith("========== FULL TOC (Binary)"))
{
// Seek to unscrambled data
- while (!(line = sr.ReadLine()).Contains("Check MCN and/or ISRC")) ;
+ while ((line = sr.ReadLine())?.Contains("Check MCN and/or ISRC")== false) ;
+ if (line == null)
+ return null;
// Read the next line so the search goes properly
line = sr.ReadLine();
}
+ if (line == null)
+ return null;
+
// Make sure we're in the area
if (!line.StartsWith("========== LBA"))
- while (!(line = sr.ReadLine()).StartsWith("========== LBA")) ;
+ while ((line = sr.ReadLine())?.StartsWith("========== LBA")== false) ;
+ if (line == null)
+ return null;
// Make sure we're in the right sector
if (!line.StartsWith("========== LBA[000000, 0000000]: Main Channel =========="))
- while (!(line = sr.ReadLine()).StartsWith("========== LBA[000000, 0000000]: Main Channel ==========")) ;
+ while ((line = sr.ReadLine())?.StartsWith("========== LBA[000000, 0000000]: Main Channel ==========")== false) ;
+ if (line == null)
+ return null;
// Fast forward to the header
- while (!(line = sr.ReadLine()).Trim().StartsWith("+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F")) ;
+ while ((line = sr.ReadLine())?.Trim()?.StartsWith("+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F")== false) ;
+ if (line == null)
+ return null;
// Now that we're at the Header, read each line in and concatenate
string header = "";
@@ -3462,7 +3779,11 @@ namespace MPF.Core.Modules.DiscImageCreator
///
/// _disc.txt file location
/// Universal hash if possible, null on error
+#if NET48
private static string GetUniversalHash(string disc)
+#else
+ private static string? GetUniversalHash(string disc)
+#endif
{
// If the file doesn't exist, we can't get info from it
if (!File.Exists(disc))
@@ -3473,16 +3794,23 @@ namespace MPF.Core.Modules.DiscImageCreator
try
{
// Fast forward to the universal hash information
- while (!sr.ReadLine().Trim().StartsWith("========== Hash(Universal Whole image) ==========")) ;
+ while (sr.ReadLine()?.Trim().StartsWith("========== Hash(Universal Whole image) ==========")== false) ;
// If we find the universal hash line, return the SHA-1 hash only
+#if NET48
string line;
+#else
+ string? line;
+#endif
while (!sr.EndOfStream)
{
- line = sr.ReadLine().TrimStart();
+ line = sr.ReadLine()?.TrimStart();
+ if (line == null)
+ return null;
+
if (line.StartsWith("
/// _disc.txt file location
/// Sample write offset if possible, null on error
+#if NET48
private static string GetWriteOffset(string disc)
+#else
+ private static string? GetWriteOffset(string disc)
+#endif
{
// If the file doesn't exist, we can't get info from it
if (!File.Exists(disc))
@@ -3514,13 +3846,13 @@ namespace MPF.Core.Modules.DiscImageCreator
try
{
// Fast forward to the offsets
- while (!sr.ReadLine().Trim().StartsWith("========== Offset")) ;
+ while (sr.ReadLine()?.Trim()?.StartsWith("========== Offset")== false) ;
sr.ReadLine(); // Combined Offset
sr.ReadLine(); // Drive Offset
sr.ReadLine(); // Separator line
// Now that we're at the offsets, attempt to get the sample offset
- return sr.ReadLine().Split(' ').LastOrDefault();
+ return sr.ReadLine()?.Split(' ')?.LastOrDefault();
}
catch
{
@@ -3539,20 +3871,27 @@ namespace MPF.Core.Modules.DiscImageCreator
/// Extracted SS.bin CRC32 hash (upper-cased)
/// True on successful extraction of info, false otherwise
/// Currently only the CRC32 values are returned for each, this may change in the future
+#if NET48
private static bool GetXGDAuxHashInfo(Datafile suppl, out string dmihash, out string pfihash, out string sshash)
+#else
+ private static bool GetXGDAuxHashInfo(Datafile? suppl, out string? dmihash, out string? pfihash, out string? sshash)
+#endif
{
// Assign values to all outputs first
dmihash = null; pfihash = null; sshash = null;
// If we don't have a valid datafile, we can't do anything
- if (suppl == null || suppl.Games.Length == 0 || suppl.Games[0].Roms.Length == 0)
+ if (suppl?.Games == null)
return false;
// Try to extract the hash information
var roms = suppl.Games[0].Roms;
- dmihash = roms.FirstOrDefault(r => r.Name.EndsWith("DMI.bin"))?.Crc?.ToUpperInvariant();
- pfihash = roms.FirstOrDefault(r => r.Name.EndsWith("PFI.bin"))?.Crc?.ToUpperInvariant();
- sshash = roms.FirstOrDefault(r => r.Name.EndsWith("SS.bin"))?.Crc?.ToUpperInvariant();
+ if (roms == null || roms.Length == 0)
+ return false;
+
+ dmihash = roms.FirstOrDefault(r => r.Name?.EndsWith("DMI.bin") == true)?.Crc?.ToUpperInvariant();
+ pfihash = roms.FirstOrDefault(r => r.Name?.EndsWith("PFI.bin") == true)?.Crc?.ToUpperInvariant();
+ sshash = roms.FirstOrDefault(r => r.Name?.EndsWith("SS.bin") == true)?.Crc?.ToUpperInvariant();
return true;
}
@@ -3567,7 +3906,11 @@ namespace MPF.Core.Modules.DiscImageCreator
/// Extracted security sector data
/// Extracted security sector version
/// True on successful extraction of info, false otherwise
+#if NET48
private static bool GetXGDAuxInfo(string disc, out string dmihash, out string pfihash, out string sshash, out string ss, out string ssver)
+#else
+ private static bool GetXGDAuxInfo(string disc, 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;
@@ -3582,9 +3925,11 @@ namespace MPF.Core.Modules.DiscImageCreator
{
try
{
- while(!sr.EndOfStream)
+ while (!sr.EndOfStream)
{
- string line = sr.ReadLine().Trim();
+ var line = sr.ReadLine()?.Trim();
+ if (line == null)
+ break;
// Security Sector version
if (line.StartsWith("Version of challenge table"))
@@ -3600,7 +3945,10 @@ namespace MPF.Core.Modules.DiscImageCreator
Regex layerRegex = new Regex(@"Layer [01].*, startLBA-endLBA:\s*(\d+)-\s*(\d+)");
- line = sr.ReadLine().Trim();
+ line = sr.ReadLine()?.Trim();
+ if (line == null)
+ break;
+
while (!line.StartsWith("========== TotalLength ==========")
&& !line.StartsWith("========== Unlock 2 state(wxripper) =========="))
{
@@ -3611,21 +3959,26 @@ namespace MPF.Core.Modules.DiscImageCreator
ss += $"{match.Groups[1]}-{match.Groups[2]}\n";
}
- line = sr.ReadLine().Trim();
+ line = sr.ReadLine()?.Trim();
+ if (line == null)
+ break;
}
+
+ if (line == null)
+ break;
}
// Special File Hashes
else if (line.StartsWith("Extracted security sector data
/// Extracted security sector version
/// True on successful extraction of info, false otherwise
+#if NET48
private static bool GetXGDAuxSSInfo(string disc, out string ss, out string ssver)
+#else
+ private static bool GetXGDAuxSSInfo(string disc, out string? ss, out string? ssver)
+#endif
{
ss = null; ssver = null;
@@ -3664,7 +4021,9 @@ namespace MPF.Core.Modules.DiscImageCreator
{
while (!sr.EndOfStream)
{
- string line = sr.ReadLine().Trim();
+ var line = sr.ReadLine()?.Trim();
+ if (line == null)
+ break;
// Security Sector version
if (line.StartsWith("Version of challenge table"))
@@ -3680,7 +4039,10 @@ namespace MPF.Core.Modules.DiscImageCreator
Regex layerRegex = new Regex(@"Layer [01].*, startLBA-endLBA:\s*(\d+)-\s*(\d+)");
- line = sr.ReadLine().Trim();
+ line = sr.ReadLine()?.Trim();
+ if (line == null)
+ break;
+
while (!line.StartsWith("========== TotalLength ==========")
&& !line.StartsWith("========== Unlock 2 state(wxripper) =========="))
{
@@ -3691,8 +4053,13 @@ namespace MPF.Core.Modules.DiscImageCreator
ss += $"{match.Groups[1]}-{match.Groups[2]}\n";
}
- line = sr.ReadLine().Trim();
+ line = sr.ReadLine()?.Trim();
+ if (line == null)
+ break;
}
+
+ if (line == null)
+ break;
}
}
diff --git a/MPF.Core/Modules/Redumper/Converters.cs b/MPF.Core/Modules/Redumper/Converters.cs
index 83fd3319..7f8ac9d8 100644
--- a/MPF.Core/Modules/Redumper/Converters.cs
+++ b/MPF.Core/Modules/Redumper/Converters.cs
@@ -11,7 +11,11 @@ namespace MPF.Core.Modules.Redumper
///
/// MediaType value to check
/// Valid extension (with leading '.'), null on error
+#if NET48
public static string Extension(MediaType? type)
+#else
+ public static string? Extension(MediaType? type)
+#endif
{
switch (type)
{
diff --git a/MPF.Core/Modules/Redumper/Parameters.cs b/MPF.Core/Modules/Redumper/Parameters.cs
index 631bc694..01eb45e6 100644
--- a/MPF.Core/Modules/Redumper/Parameters.cs
+++ b/MPF.Core/Modules/Redumper/Parameters.cs
@@ -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
///
+#if NET48
public override string InputPath => DriveValue;
+#else
+ public override string? InputPath => DriveValue;
+#endif
///
+#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
///
public override int? Speed => SpeedValue;
@@ -48,14 +57,22 @@ namespace MPF.Core.Modules.Redumper
///
/// List of all modes being run
///
+#if NET48
public List ModeValues { get; set; }
+#else
+ public List? ModeValues { get; set; }
+#endif
#region General
///
/// Drive to use, first available drive with disc, if not provided
///
+#if NET48
public string DriveValue { get; set; }
+#else
+ public string? DriveValue { get; set; }
+#endif
///
/// Drive read speed, optimal drive speed will be used if not provided
@@ -70,12 +87,20 @@ namespace MPF.Core.Modules.Redumper
///
/// Dump files base directory
///
+#if NET48
public string ImagePathValue { get; set; }
+#else
+ public string? ImagePathValue { get; set; }
+#endif
///
/// Dump files prefix, autogenerated in dump mode, if not provided
///
+#if NET48
public string ImageNameValue { get; set; }
+#else
+ public string? ImageNameValue { get; set; }
+#endif
#endregion
@@ -84,7 +109,11 @@ namespace MPF.Core.Modules.Redumper
///
/// Override drive type, possible values: GENERIC, PLEXTOR, LG_ASUS
///
+#if NET48
public string DriveTypeValue { get; set; }
+#else
+ public string? DriveTypeValue { get; set; }
+#endif
///
/// Override drive read offset
@@ -104,12 +133,20 @@ namespace MPF.Core.Modules.Redumper
///
/// Override drive read method, possible values: BE, D8, BE_CDDA
///
+#if NET48
public string DriveReadMethodValue { get; set; }
+#else
+ public string? DriveReadMethodValue { get; set; }
+#endif
///
/// Override drive sector order, possible values: DATA_C2_SUB, DATA_SUB_C2
///
+#if NET48
public string DriveSectorOrderValue { get; set; }
+#else
+ public string? DriveSectorOrderValue { get; set; }
+#endif
#endregion
@@ -151,7 +188,11 @@ namespace MPF.Core.Modules.Redumper
///
/// LBA ranges of sectors to skip
///
+#if NET48
public string SkipValue { get; set; }
+#else
+ public string? SkipValue { get; set; }
+#endif
///
/// 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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
+#else
+ if (info.CommonDiscInfo.CommentsSpecialFields == null) info.CommonDiscInfo.CommentsSpecialFields = new Dictionary();
+#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();
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
}
///
+#if NET48
public override string GetDefaultExtension(MediaType? mediaType) => Converters.Extension(mediaType);
+#else
+ public override string? GetDefaultExtension(MediaType? mediaType) => Converters.Extension(mediaType);
+#endif
///
public override List 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;
}
///
@@ -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
///
/// Log file location
/// Newline-delimited cuesheet if possible, null on error
+#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
///
/// Log file location
/// Newline-delimited datfile if possible, null on error
+#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("
/// Log file location
/// Formatted string representing the DVD protection, null on error
+#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:
@@ -1405,7 +1548,11 @@ namespace MPF.Core.Modules.Redumper
///
/// Log file location
/// Layerbreak if possible, null on error
+#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
///
/// Log file location
/// Formatted multisession information, null on error
+#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
///
/// Log file location
/// PS1 LibCrypt data, if possible
+#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
///
/// Log file location
/// Newline-delimited PVD if possible, null on error
+#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
///
/// Log file location
/// Non-zero dta start if possible, null on error
+#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
///
/// <String representing a formatter variant of the Saturn header
/// True on successful extraction of info, false otherwise
- /// 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
///
/// Log file location
/// Header as a byte array if possible, null on error
+#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
///
/// Log file location
/// Header as a byte array if possible, null on error
+#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
///
/// Log file location
/// Universal hash if possible, null on error
+#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
///
/// Log file location
/// Sample write offset if possible, null on error
+#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
///
/// Log file location
/// Version if possible, null on error
+#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
///
/// Log file location
/// True if hardware info was set, false otherwise
+#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: - (revision level: , 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());
diff --git a/MPF.Core/Modules/UmdImageCreator/Parameters.cs b/MPF.Core/Modules/UmdImageCreator/Parameters.cs
index 9a729c05..8d839c37 100644
--- a/MPF.Core/Modules/UmdImageCreator/Parameters.cs
+++ b/MPF.Core/Modules/UmdImageCreator/Parameters.cs
@@ -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();
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
///
/// _mainInfo.txt file location
/// Newline-deliminated PVD if possible, null on error
+#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
///
/// _disc.txt file location
/// True on successful extraction of info, false otherwise
+#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;
diff --git a/MPF.Core/Protection.cs b/MPF.Core/Protection.cs
index 5b34f20c..86ef1a01 100644
--- a/MPF.Core/Protection.cs
+++ b/MPF.Core/Protection.cs
@@ -19,7 +19,11 @@ namespace MPF.Core
/// Options object that determines what to scan
/// Optional progress callback
/// Set of all detected copy protections with an optional error string
- public static async Task<(Dictionary>, string)> RunProtectionScanOnPath(string path, Core.Data.Options options, IProgress progress = null)
+#if NET48
+ public static async Task<(Dictionary>, string)> RunProtectionScanOnPath(string path, Data.Options options, IProgress progress = null)
+#else
+ public static async Task<(Dictionary>?, string?)> RunProtectionScanOnPath(string path, Data.Options options, IProgress? progress = null)
+#endif
{
try
{
@@ -62,7 +66,11 @@ namespace MPF.Core
///
/// Dictionary of file to list of protection mappings
/// Detected protections, if any
+#if NET48
public static string FormatProtections(Dictionary> protections)
+#else
+ public static string? FormatProtections(Dictionary>? protections)
+#endif
{
// If the filtered list is empty in some way, return
if (protections == null || !protections.Any())
diff --git a/MPF.Core/Utilities/Logging.cs b/MPF.Core/Utilities/Logging.cs
index b897b6b7..d2e93d51 100644
--- a/MPF.Core/Utilities/Logging.cs
+++ b/MPF.Core/Utilities/Logging.cs
@@ -14,7 +14,11 @@ namespace MPF.Core.Utilities
/// TextReader representing the input
/// Invoking class, passed on to the event handler
/// Event handler to be invoked to write to log
+#if NET48
public static async Task OutputToLog(TextReader reader, object baseClass, EventHandler handler)
+#else
+ public static async Task OutputToLog(TextReader reader, object baseClass, EventHandler? handler)
+#endif
{
// Initialize the required variables
char[] buffer = new char[256];
@@ -63,7 +67,11 @@ namespace MPF.Core.Utilities
/// Current line to process
/// Invoking class, passed on to the event handler
/// Event handler to be invoked to write to log
+#if NET48
private static void ProcessNewLines(StringBuilder sb, string line, object baseClass, EventHandler handler)
+#else
+ private static void ProcessNewLines(StringBuilder sb, string line, object baseClass, EventHandler? handler)
+#endif
{
line = line.Replace("\r\n", "\n");
var split = line.Split('\n');
@@ -105,7 +113,11 @@ namespace MPF.Core.Utilities
/// Current line to process
/// Invoking class, passed on to the event handler
/// Event handler to be invoked to write to log
+#if NET48
private static void ProcessCarriageReturns(StringBuilder sb, string line, object baseClass, EventHandler handler)
+#else
+ private static void ProcessCarriageReturns(StringBuilder sb, string line, object baseClass, EventHandler? handler)
+#endif
{
var split = line.Split('\r');
diff --git a/MPF.Core/Utilities/OptionsLoader.cs b/MPF.Core/Utilities/OptionsLoader.cs
index 48e00352..1fb6b13c 100644
--- a/MPF.Core/Utilities/OptionsLoader.cs
+++ b/MPF.Core/Utilities/OptionsLoader.cs
@@ -15,7 +15,11 @@ namespace MPF.Core.Utilities
///
/// Load the current set of options from application arguments
///
+#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)) as Dictionary;
+#else
+ var settings = serializer.Deserialize(reader, typeof(Dictionary)) as Dictionary;
+#endif
return new Options(settings);
}
diff --git a/MPF.Core/Utilities/Tools.cs b/MPF.Core/Utilities/Tools.cs
index 1bc6978f..a2999576 100644
--- a/MPF.Core/Utilities/Tools.cs
+++ b/MPF.Core/Utilities/Tools.cs
@@ -130,16 +130,23 @@ namespace MPF.Core.Utilities
/// String representing the message to display the the user.
/// String representing the new release URL.
///
+#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
///
/// Get the current informational version formatted as a string
///
+#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
///
/// Get the latest version of MPF from GitHub and the release URL
///
+#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);
}