mirror of
https://github.com/SabreTools/MPF.git
synced 2026-07-02 17:24:48 +00:00
Support more Redumper log outputs (fixes #951)
This commit is contained in:
@@ -52,6 +52,7 @@
|
||||
- Include BCA in zipped files for Redumper
|
||||
- Add retry override for MPF.CLI
|
||||
- Limit BCA read to 64 bytes for Redumper
|
||||
- Support more Redumper log outputs
|
||||
|
||||
### 3.6.0 (2025-11-28)
|
||||
|
||||
|
||||
@@ -306,6 +306,61 @@ namespace MPF.Processors.Test
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetBCA
|
||||
|
||||
[Fact]
|
||||
public void GetBCA_InvalidPath_Null()
|
||||
{
|
||||
string bcaPath = "INVALID";
|
||||
string? actual = Redumper.GetBCA(bcaPath);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBCA_ValidPath_Formatted()
|
||||
{
|
||||
string expected = "0001 0203 0405 0607 0809 0A0B 0C0D 0E0F\n0001 0203 0405 0607 0809 0A0B 0C0D 0E0F\n";
|
||||
string bcaPath = Path.Combine(Environment.CurrentDirectory, "TestData", "Redumper", "DVD", "test.bca");
|
||||
|
||||
string? actual = Redumper.GetBCA(bcaPath);
|
||||
Assert.NotNull(actual);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetBookType
|
||||
|
||||
[Fact]
|
||||
public void GetBookType_Empty_Null()
|
||||
{
|
||||
string log = string.Empty;
|
||||
bool actual = Redumper.GetBookType(log, out MediaType? bookType);
|
||||
Assert.False(actual);
|
||||
Assert.Null(bookType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBookType_Invalid_Null()
|
||||
{
|
||||
string log = "INVALID";
|
||||
bool actual = Redumper.GetBookType(log, out MediaType? bookType);
|
||||
Assert.False(actual);
|
||||
Assert.Null(bookType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBookType_Valid_Filled()
|
||||
{
|
||||
MediaType? expected = MediaType.DVD;
|
||||
string log = Path.Combine(Environment.CurrentDirectory, "TestData", "Redumper", "DVD", "test.log");
|
||||
bool actual = Redumper.GetBookType(log, out MediaType? bookType);
|
||||
Assert.True(actual);
|
||||
Assert.Equal(expected, bookType);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetCuesheet
|
||||
|
||||
[Fact]
|
||||
@@ -507,6 +562,8 @@ namespace MPF.Processors.Test
|
||||
[InlineData("HD DVD-RW", MediaType.HDDVD)]
|
||||
[InlineData("HD DVD-R DL", MediaType.HDDVD)]
|
||||
[InlineData("HD DVD-RW DL", MediaType.HDDVD)]
|
||||
[InlineData("NINTENDO", MediaType.NintendoWiiOpticalDisc)]
|
||||
[InlineData("RESERVED5", MediaType.NintendoWiiOpticalDisc)]
|
||||
[InlineData("NON STANDARD", null)]
|
||||
public void GetDiscTypeFromProfileTest(string? profile, MediaType? expected)
|
||||
{
|
||||
@@ -755,7 +812,7 @@ namespace MPF.Processors.Test
|
||||
{
|
||||
string? expectedManufacturer = "manufacturer";
|
||||
string? expectedModel = "model";
|
||||
string? expectedFirmware = "revision (vendor)";
|
||||
string? expectedFirmware = "revision (vendor), firmware";
|
||||
|
||||
string log = Path.Combine(Environment.CurrentDirectory, "TestData", "Redumper", "CDROM", "test.log");
|
||||
bool actual = Redumper.GetHardwareInfo(log,
|
||||
|
||||
@@ -13,9 +13,6 @@ CUE [
|
||||
dat:
|
||||
<rom name="INVALID" size="12345" crc="00000000" md5="d41d8cd98f00b204e9800998ecf8427e" sha1="da39a3ee5e6b4b0d3255bfef95601890afd80709" />
|
||||
|
||||
<< GetDiscProfile >>
|
||||
current profile: CD-ROM
|
||||
|
||||
<< GetDiscType >>
|
||||
disc type: INVALID
|
||||
disc type: CD
|
||||
@@ -63,9 +60,12 @@ DC [
|
||||
0090 TEST DATA
|
||||
00A0 TEST DATA
|
||||
|
||||
<< GetDiscProfile >>
|
||||
<< GetHardwareInfo >>
|
||||
drive path:
|
||||
drive: manufacturer - model (revision level: revision, vendor specific: vendor)
|
||||
drive information
|
||||
inquiry: manufacturer - model (revision level: revision, vendor specific: vendor)
|
||||
profile: CD-ROM
|
||||
firmware: firmware
|
||||
|
||||
<< GetLayerbreaks >>
|
||||
layer break (layer: 0): 12345
|
||||
|
||||
BIN
MPF.Processors.Test/TestData/Redumper/DVD/test.bca
Normal file
BIN
MPF.Processors.Test/TestData/Redumper/DVD/test.bca
Normal file
Binary file not shown.
@@ -1,3 +1,6 @@
|
||||
<< GetBookType >>
|
||||
book type: DVD-ROM
|
||||
|
||||
<< GetDiscType >>
|
||||
disc type: INVALID
|
||||
disc type: DVD
|
||||
@@ -58,11 +58,15 @@ namespace MPF.Processors
|
||||
}
|
||||
#endif
|
||||
|
||||
// Use the log first, if it exists
|
||||
if (GetDiscType($"{basePath}.log", out MediaType? mediaType))
|
||||
return mediaType;
|
||||
// Use the disc type, if possible
|
||||
if (GetDiscType($"{basePath}.log", out MediaType? discType))
|
||||
return discType;
|
||||
|
||||
// Use the profile for older Redumper versions
|
||||
// Use the book type, if possible
|
||||
if (GetBookType($"{basePath}.log", out MediaType? bookType))
|
||||
return bookType;
|
||||
|
||||
// Use the profile, if possible
|
||||
if (GetDiscProfile($"{basePath}.log", out string? discProfile))
|
||||
return GetDiscTypeFromProfile(discProfile);
|
||||
|
||||
@@ -921,6 +925,80 @@ namespace MPF.Processors
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get reported book type, if possible
|
||||
/// </summary>
|
||||
/// <param name="log">Log file location</param>
|
||||
/// <returns>True if book type was set, false otherwise</returns>
|
||||
internal static bool GetBookType(string log, out MediaType? bookType)
|
||||
{
|
||||
// Set the default values
|
||||
bookType = null;
|
||||
|
||||
// If the file doesn't exist, we can't get the info
|
||||
if (string.IsNullOrEmpty(log))
|
||||
return false;
|
||||
if (!File.Exists(log))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
using var sr = File.OpenText(log);
|
||||
var line = sr.ReadLine()?.Trim();
|
||||
while (line is not null)
|
||||
{
|
||||
// If the line isn't the book type, skip
|
||||
if (!line.StartsWith("book type:"))
|
||||
{
|
||||
line = sr.ReadLine()?.Trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
// book type: <bookType>
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string bookTypeStr = line["book type: ".Length..];
|
||||
#else
|
||||
string bookTypeStr = line.Substring("book type: ".Length);
|
||||
#endif
|
||||
|
||||
// Set the media type based on the string
|
||||
bookType = bookTypeStr switch
|
||||
{
|
||||
"DVD-ROM" => MediaType.DVD,
|
||||
"DVD-RAM" => MediaType.DVD,
|
||||
"DVD-R" => MediaType.DVD,
|
||||
"DVD-RW" => MediaType.DVD,
|
||||
"DVD+RW" => MediaType.DVD,
|
||||
"DVD+R" => MediaType.DVD,
|
||||
"DVD+RW DL" => MediaType.DVD,
|
||||
"DVD+R DL" => MediaType.DVD,
|
||||
|
||||
"HD DVD-ROM" => MediaType.HDDVD,
|
||||
"HD DVD-RAM" => MediaType.HDDVD,
|
||||
"HD DVD-R" => MediaType.HDDVD,
|
||||
|
||||
"NINTENDO" => MediaType.NintendoWiiOpticalDisc, // Maybe also GC?
|
||||
"RESERVED5" => MediaType.NintendoWiiOpticalDisc, // Maybe also GC?
|
||||
|
||||
"RESERVED1" => null,
|
||||
"RESERVED2" => null,
|
||||
"RESERVED3" => null,
|
||||
"RESERVED4" => null,
|
||||
_ => null,
|
||||
};
|
||||
return bookType is not null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Absorb the exception
|
||||
bookType = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the cuesheet from the input file, if possible
|
||||
/// </summary>
|
||||
@@ -1193,6 +1271,9 @@ namespace MPF.Processors
|
||||
"HD DVD-R DL" => MediaType.HDDVD,
|
||||
"HD DVD-RW DL" => MediaType.HDDVD,
|
||||
|
||||
"NINTENDO" => MediaType.NintendoWiiOpticalDisc, // Maybe also GC?
|
||||
"RESERVED5" => MediaType.NintendoWiiOpticalDisc, // Maybe also GC?
|
||||
|
||||
"NON STANDARD" => null,
|
||||
|
||||
_ => null,
|
||||
@@ -1614,32 +1695,85 @@ namespace MPF.Processors
|
||||
if (!File.Exists(log))
|
||||
return false;
|
||||
|
||||
// Firmware can be split into different lines
|
||||
List<string> firmwarePieces = [];
|
||||
|
||||
try
|
||||
{
|
||||
// Fast forward to the drive information line
|
||||
// Fast forward to the drive information section
|
||||
using var sr = File.OpenText(log);
|
||||
while (!(sr.ReadLine()?.Trim().StartsWith("drive path:") ?? true)) ;
|
||||
do
|
||||
{
|
||||
// Read the next line until EOF
|
||||
string? tempLine = sr.ReadLine()?.Trim();
|
||||
if (tempLine is null)
|
||||
break;
|
||||
|
||||
// Check old and new drive information sections
|
||||
if (tempLine.StartsWith("drive path:"))
|
||||
break;
|
||||
else if (tempLine.StartsWith("drive information"))
|
||||
break;
|
||||
|
||||
} while (true);
|
||||
|
||||
// If we find the hardware info line, return each value
|
||||
// drive: <vendor_id> - <product_id> (revision level: <product_revision_level>, vendor specific: <vendor_specific>)
|
||||
var regex = new Regex(@"drive: (.+) - (.+) \(revision level: (.+), vendor specific: (.+)\)", RegexOptions.Compiled);
|
||||
var oldRegex = new Regex(@"drive: (.+) - (.+) \(revision level: (.+), vendor specific: (.+)\)", RegexOptions.Compiled);
|
||||
|
||||
// inquiry: <vendor_id> - <product_id> (revision level: <product_revision_level>, vendor specific: <vendor_specific>)
|
||||
var newRegex = new Regex(@"inquiry: (.+) - (.+) \(revision level: (.+), vendor specific: (.+)\)", RegexOptions.Compiled);
|
||||
|
||||
string? line;
|
||||
while ((line = sr.ReadLine()) is not null)
|
||||
while ((line = sr.ReadLine()?.Trim()) is not null)
|
||||
{
|
||||
var match = regex.Match(line.Trim());
|
||||
// Check old version of line
|
||||
var match = oldRegex.Match(line);
|
||||
if (match.Success)
|
||||
{
|
||||
manufacturer = match.Groups[1].Value;
|
||||
model = match.Groups[2].Value;
|
||||
firmware = match.Groups[3].Value;
|
||||
firmware += match.Groups[4].Value == "<empty>" ? "" : $" ({match.Groups[4].Value})";
|
||||
return true;
|
||||
|
||||
string revisionLevel = match.Groups[3].Value;
|
||||
revisionLevel += match.Groups[4].Value == "<empty>" ? "" : $" ({match.Groups[4].Value})";
|
||||
firmwarePieces.Add(revisionLevel);
|
||||
}
|
||||
|
||||
// Check new version of line
|
||||
match = newRegex.Match(line);
|
||||
if (match.Success)
|
||||
{
|
||||
manufacturer = match.Groups[1].Value;
|
||||
model = match.Groups[2].Value;
|
||||
|
||||
string revisionLevel = match.Groups[3].Value;
|
||||
revisionLevel += match.Groups[4].Value == "<empty>" ? "" : $" ({match.Groups[4].Value})";
|
||||
firmwarePieces.Add(revisionLevel);
|
||||
}
|
||||
|
||||
// Distinct additional firmware
|
||||
if (line.StartsWith("firmware:"))
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string exactFirmware = line["firmware: ".Length..].Trim();
|
||||
#else
|
||||
string exactFirmware = line.Substring("firmware: ".Length).Trim();
|
||||
#endif
|
||||
firmwarePieces.Add(exactFirmware);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(line))
|
||||
{
|
||||
// An empty line indicates the end of the section
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Required lines were not found
|
||||
return false;
|
||||
// Assemble the firmware string, if needed
|
||||
firmware = string.Join(", ", [.. firmwarePieces]);
|
||||
|
||||
// Return if the fields are filled
|
||||
return manufacturer is not null && model is not null && firmware is not null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user