Skip to content

Commit

Permalink
Retrieve volume label from logs (SabreTools#627)
Browse files Browse the repository at this point in the history
* Retrieve volume label from DIC and redumper logs

* Fix logic

* Remove unnecessary using

* Update changelog

* Sanitise label somewhat

* Refactor
  • Loading branch information
Deterous authored Jan 16, 2024
1 parent a167652 commit 0732e9d
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- Use PSX/PS2 serial as filename when Volume Label not present (Deterous)
- Allow variables in output path (Deterous)
- Check for presence of complete dump from other programs (Deterous)
- Retrieve volume label from logs (Deterous)

### 3.0.3 (2023-12-04)

Expand Down
28 changes: 14 additions & 14 deletions MPF.Core/Data/Drive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ public static List<Drive> CreateListOfDrives(bool ignoreFixedDrives)
return RedumpSystem.IBMPCcompatible;

// Check volume labels first
RedumpSystem? systemFromLabel = GetRedumpSystemFromVolumeLabel();
RedumpSystem? systemFromLabel = GetRedumpSystemFromVolumeLabel(this.VolumeLabel);
if (systemFromLabel != null)
return systemFromLabel;

Expand Down Expand Up @@ -512,48 +512,48 @@ public static List<Drive> CreateListOfDrives(bool ignoreFixedDrives)
/// Get the current system from the drive volume label
/// </summary>
/// <returns>The system based on volume label, null if none detected</returns>
public RedumpSystem? GetRedumpSystemFromVolumeLabel()
public static RedumpSystem? GetRedumpSystemFromVolumeLabel(string? volumeLabel)
{
// If the volume label is empty, we can't do anything
if (string.IsNullOrEmpty(this.VolumeLabel))
if (string.IsNullOrEmpty(volumeLabel))
return null;

// Audio CD
if (this.VolumeLabel!.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
if (volumeLabel!.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.AudioCD;

// Microsoft Xbox
if (this.VolumeLabel.Equals("SEP13011042", StringComparison.OrdinalIgnoreCase))
if (volumeLabel.Equals("SEP13011042", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.MicrosoftXbox;
else if (this.VolumeLabel.Equals("SEP13011042072", StringComparison.OrdinalIgnoreCase))
else if (volumeLabel.Equals("SEP13011042072", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.MicrosoftXbox;

// Microsoft Xbox 360
if (this.VolumeLabel.Equals("XBOX360", StringComparison.OrdinalIgnoreCase))
if (volumeLabel.Equals("XBOX360", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.MicrosoftXbox360;
else if (this.VolumeLabel.Equals("XGD2DVD_NTSC", StringComparison.OrdinalIgnoreCase))
else if (volumeLabel.Equals("XGD2DVD_NTSC", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.MicrosoftXbox360;

// Microsoft Xbox 360 - Too overly broad even if a lot of discs use this
//if (this.VolumeLabel.Equals("CD_ROM", StringComparison.OrdinalIgnoreCase))
//if (volumeLabel.Equals("CD_ROM", StringComparison.OrdinalIgnoreCase))
// return RedumpSystem.MicrosoftXbox360; // Also for Xbox One?
//if (this.VolumeLabel.Equals("DVD_ROM", StringComparison.OrdinalIgnoreCase))
//if (volumeLabel.Equals("DVD_ROM", StringComparison.OrdinalIgnoreCase))
// return RedumpSystem.MicrosoftXbox360;

// Sega Mega-CD / Sega-CD
if (this.VolumeLabel.Equals("Sega_CD", StringComparison.OrdinalIgnoreCase))
if (volumeLabel.Equals("Sega_CD", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.SegaMegaCDSegaCD;

// Sony PlayStation 3
if (this.VolumeLabel.Equals("PS3VOLUME", StringComparison.OrdinalIgnoreCase))
if (volumeLabel.Equals("PS3VOLUME", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.SonyPlayStation3;

// Sony PlayStation 4
if (this.VolumeLabel.Equals("PS4VOLUME", StringComparison.OrdinalIgnoreCase))
if (volumeLabel.Equals("PS4VOLUME", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.SonyPlayStation4;

// Sony PlayStation 5
if (this.VolumeLabel.Equals("PS5VOLUME", StringComparison.OrdinalIgnoreCase))
if (volumeLabel.Equals("PS5VOLUME", StringComparison.OrdinalIgnoreCase))
return RedumpSystem.SonyPlayStation5;

return null;
Expand Down
5 changes: 5 additions & 0 deletions MPF.Core/Modules/BaseParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ public bool? this[string key]
/// </summary>
private Process? process;

/// <summary>
/// All found volume labels and their corresponding file systems
/// </summary>
public Dictionary<string, List<string>>? VolumeLabels;

#endregion

#region Virtual Dumping Information
Expand Down
87 changes: 87 additions & 0 deletions MPF.Core/Modules/DiscImageCreator/Parameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,10 @@ public override void GenerateSubmissionInfo(SubmissionInfo info, Options options
// Fill in the hash data
info.TracksAndWriteOffsets!.ClrMameProData = InfoTool.GenerateDatfile(datafile);

// Fill in the volume labels
if (GetVolumeLabels($"{basePath}_volDesc.txt", out var volLabels))
VolumeLabels = volLabels;

// Extract info based generically on MediaType
switch (this.Type)
{
Expand Down Expand Up @@ -2722,6 +2726,89 @@ private static bool GetDiscType(string drive, out string? discTypeOrBookType)
}
}

/// <summary>
/// Get all Volume Identifiers
/// </summary>
/// <param name="volDesc">_volDesc.txt file location</param>
/// <returns>Volume labels (by type), or null if none present</returns>
private static bool GetVolumeLabels(string volDesc, out Dictionary<string, List<string>> volLabels)
{
// If the file doesn't exist, can't get the volume labels
volLabels = [];
if (!File.Exists(volDesc))
return false;

try
{
using var sr = File.OpenText(volDesc);
var line = sr.ReadLine();

string volType = "UNKNOWN";
string label;
while (line != null)
{
// Trim the line for later use
line = line.Trim();

// ISO9660 and extensions section
if (line.StartsWith("Volume Descriptor Type: "))
{
Int32.TryParse(line.Substring("Volume Descriptor Type: ".Length), out int volTypeInt);
volType = volTypeInt switch
{
// 0 => "Boot Record" // Should not not contain a Volume Identifier
1 => "ISO", // ISO9660
2 => "Joliet",
// 3 => "Volume Partition Descriptor" // Should not not contain a Volume Identifier
// 255 => "???" // Should not not contain a Volume Identifier
_ => "UNKNOWN" // Should not contain a Volume Identifier
};
}
// UDF section
else if (line.StartsWith("Primary Volume Descriptor Number:"))
{
volType = "UDF";
}
// Identifier
else if (line.StartsWith("Volume Identifier: "))
{
label = line.Substring("Volume Identifier: ".Length);

// Remove leading non-printable character (unsure why DIC outputs this)
if (Convert.ToUInt32(label[0]) == 0x7F || Convert.ToUInt32(label[0]) < 0x20)
label = label.Substring(1);

// Skip if label is blank
if (label == null || label.Length <= 0)
{
volType = "UNKNOWN";
line = sr.ReadLine();
continue;
}

if (volLabels.ContainsKey(label))
volLabels[label].Add(volType);
else
volLabels.Add(label, [volType]);

// Reset volume type
volType = "UNKNOWN";
}

line = sr.ReadLine();
}

// Return true if a volume label was found
return volLabels.Count > 0;
}
catch
{
// We don't care what the exception is right now
volLabels = [];
return false;
}
}

/// <summary>
/// Get the DVD protection information, if possible
/// </summary>
Expand Down
66 changes: 62 additions & 4 deletions MPF.Core/Modules/Redumper/Parameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ public override void GenerateSubmissionInfo(SubmissionInfo info, Options options
if (GetDiscType($"{basePath}.log", out var discTypeOrBookType))
info.DumpingInfo.ReportedDiscType = discTypeOrBookType;

// Fill in the volume labels
if (GetVolumeLabels($"{basePath}.log", out var volLabels))
VolumeLabels = volLabels;

switch (this.Type)
{
case MediaType.CDROM:
Expand Down Expand Up @@ -1452,20 +1456,20 @@ protected override bool ValidateAndSetParameters(string? parameters)
/// <summary>
/// Get reported disc type information, if possible
/// </summary>
/// <param name="drive">_disc.txt file location</param>
/// <param name="log">Log file location</param>
/// <returns>True if disc type info was set, false otherwise</returns>
private static bool GetDiscType(string drive, out string? discTypeOrBookType)
private static bool GetDiscType(string log, out string? discTypeOrBookType)
{
// Set the default values
discTypeOrBookType = null;

// If the file doesn't exist, we can't get the info
if (!File.Exists(drive))
if (!File.Exists(log))
return false;

try
{
using var sr = File.OpenText(drive);
using var sr = File.OpenText(log);
var line = sr.ReadLine();
while (line != null)
{
Expand All @@ -1492,6 +1496,60 @@ private static bool GetDiscType(string drive, out string? discTypeOrBookType)
}
}

/// <summary>
/// Get all Volume Identifiers
/// </summary>
/// <param name="log">Log file location</param>
/// <returns>Volume labels (by type), or null if none present</returns>
private static bool GetVolumeLabels(string log, out Dictionary<string, List<string>> volLabels)
{
// If the file doesn't exist, can't get the volume labels
volLabels = [];
if (!File.Exists(log))
return false;

try
{
using var sr = File.OpenText(log);
var line = sr.ReadLine();

while (line != null)
{
// Trim the line for later use
line = line.Trim();

// ISO9660 Volume Identifier
if (line.StartsWith("volume identifier: "))
{
string label = line.Substring("volume identifier: ".Length);

// Skip if label is blank
if (label == null || label.Length <= 0)
break;

if (volLabels.ContainsKey(label))
volLabels[label].Add("ISO");
else
volLabels[label] = ["ISO"];

// Redumper log currently only outputs ISO9660 label, end here
break;
}

line = sr.ReadLine();
}

// Return true if a volume label was found
return volLabels.Count > 0;
}
catch
{
// We don't care what the exception is right now
volLabels = [];
return false;
}
}

/// <summary>
/// Get the DVD protection information, if possible
/// </summary>
Expand Down
65 changes: 62 additions & 3 deletions MPF.Core/SubmissionInfoTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,9 @@ internal static class SubmissionInfoTool
info.TracksAndWriteOffsets.ClrMameProData = null;

// Add the volume label to comments, if possible or necessary
if (drive?.VolumeLabel != null && drive.GetRedumpSystemFromVolumeLabel() == null)
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.VolumeLabel] = drive.VolumeLabel;
string? volLabels = FormatVolumeLabels(drive?.VolumeLabel, parameters?.VolumeLabels);
if (volLabels != null)
info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.VolumeLabel] = volLabels;

// Extract info based generically on MediaType
switch (mediaType)
Expand Down Expand Up @@ -670,6 +671,64 @@ public async static Task<bool> FillFromRedump(Options options, SubmissionInfo in
return true;
}

#endregion
#endregion

#region Helper Functions

/// <summary>
/// Formats a list of volume labels and their corresponding filesystems
/// </summary>
/// <param name="labels">Dictionary of volume labels and their filesystems</param>
/// <returns>Formatted string of volume labels and their filesystems</returns>
private static string? FormatVolumeLabels(string? driveLabel, Dictionary<string, List<string>>? labels)
{
// Must have at least one label to format
if (driveLabel == null && (labels == null || labels.Count == 0))
return null;

// If no labels given, use drive label
if (labels == null || labels.Count == 0)
{
// Ignore common volume labels
if (Drive.GetRedumpSystemFromVolumeLabel(driveLabel) != null)
return null;

return driveLabel;
}

// If only one label, don't mention fs
string firstLabel = labels.First().Key;
if (labels.Count == 1 && (firstLabel == driveLabel || driveLabel == null))
{
// Ignore common volume labels
if (Drive.GetRedumpSystemFromVolumeLabel(firstLabel) != null)
return null;

return firstLabel;
}

// Otherwise, state filesystem for each label
List<string> volLabels = [];

// Begin formatted output with the label from Windows, if it is unique and not a common volume label
if (driveLabel != null && !labels.TryGetValue(driveLabel, out List<string>? value) && Drive.GetRedumpSystemFromVolumeLabel(driveLabel) == null)
volLabels.Add(driveLabel);

// Add remaining labels with their corresponding filesystems
foreach (KeyValuePair<string, List<string>> label in labels)
{
// Ignore common volume labels
if (Drive.GetRedumpSystemFromVolumeLabel(label.Key) == null)
volLabels.Add($"{label.Key} ({string.Join(", ", [.. label.Value])})");
}

// Print each label separated by a comma and a space
if (volLabels.Count == 0)
return null;

return string.Join(", ", [.. volLabels]);
}

#endregion
}
}

0 comments on commit 0732e9d

Please sign in to comment.