From a4616d139da77104bbfbf8ee6fb5c5afaef5b4fa Mon Sep 17 00:00:00 2001
From: Deterous <138427222+Deterous@users.noreply.github.com>
Date: Tue, 24 Jun 2025 10:03:42 +0900
Subject: [PATCH] Better handling of Xbox/360, redumper build 613 (#865)
* Better handling of bad SS, redumper build 613
* Add missing helper function
* Fix new func signature
* Fix var name
* Nulls
* Don't get vollabel for xbox/360
* formatting
* formatting v2
---
CHANGELIST.md | 1 +
.../Redumper/ExecutionContext.cs | 2 +
MPF.ExecutionContexts/Redumper/FlagStrings.cs | 1 +
MPF.Processors/ProcessingTool.cs | 61 ++++++++++
MPF.Processors/Redumper.cs | 105 +++++++-----------
publish-nix.sh | 10 +-
publish-win.ps1 | 10 +-
7 files changed, 116 insertions(+), 74 deletions(-)
diff --git a/CHANGELIST.md b/CHANGELIST.md
index 5ace8a81..7175e2a7 100644
--- a/CHANGELIST.md
+++ b/CHANGELIST.md
@@ -19,6 +19,7 @@
- Remove dead code in DIC processor
- Set some default values for CLI
- Address nullable default value
+- Better handling of Xbox/360, redumper build 613
### 3.3.2 (2025-06-12)
diff --git a/MPF.ExecutionContexts/Redumper/ExecutionContext.cs b/MPF.ExecutionContexts/Redumper/ExecutionContext.cs
index 06a990ec..a7de0c26 100644
--- a/MPF.ExecutionContexts/Redumper/ExecutionContext.cs
+++ b/MPF.ExecutionContexts/Redumper/ExecutionContext.cs
@@ -87,6 +87,7 @@ namespace MPF.ExecutionContexts.Redumper
[FlagStrings.PlextorSkipLeadin] = new FlagInput(FlagStrings.PlextorSkipLeadin),
[FlagStrings.PlextorLeadinRetries] = new Int32Input(FlagStrings.PlextorLeadinRetries),
[FlagStrings.PlextorLeadinForceStore] = new FlagInput(FlagStrings.PlextorLeadinForceStore),
+ [FlagStrings.KreonPartialSS] = new FlagInput(FlagStrings.KreonPartialSS),
[FlagStrings.AsusSkipLeadout] = new FlagInput(FlagStrings.AsusSkipLeadout),
[FlagStrings.AsusLeadoutRetries] = new Int32Input(FlagStrings.AsusLeadoutRetries),
[FlagStrings.DisableCDText] = new FlagInput(FlagStrings.DisableCDText),
@@ -183,6 +184,7 @@ namespace MPF.ExecutionContexts.Redumper
FlagStrings.PlextorSkipLeadin,
FlagStrings.PlextorLeadinRetries,
FlagStrings.PlextorLeadinForceStore,
+ FlagStrings.KreonPartialSS,
FlagStrings.AsusSkipLeadout,
FlagStrings.AsusLeadoutRetries,
FlagStrings.DisableCDText,
diff --git a/MPF.ExecutionContexts/Redumper/FlagStrings.cs b/MPF.ExecutionContexts/Redumper/FlagStrings.cs
index 32d78038..8aa65d4d 100644
--- a/MPF.ExecutionContexts/Redumper/FlagStrings.cs
+++ b/MPF.ExecutionContexts/Redumper/FlagStrings.cs
@@ -41,6 +41,7 @@ namespace MPF.ExecutionContexts.Redumper
public const string PlextorSkipLeadin = "--plextor-skip-leadin";
public const string PlextorLeadinRetries = "--plextor-leadin-retries";
public const string PlextorLeadinForceStore = "--plextor-leadin-force-store";
+ public const string KreonPartialSS = "--kreon-partial-ss";
public const string AsusSkipLeadout = "--asus-skip-leadout";
public const string AsusLeadoutRetries = "--asus-leadout-retries";
public const string DisableCDText = "--disable-cdtext";
diff --git a/MPF.Processors/ProcessingTool.cs b/MPF.Processors/ProcessingTool.cs
index 383995cb..c5f6bc9f 100644
--- a/MPF.Processors/ProcessingTool.cs
+++ b/MPF.Processors/ProcessingTool.cs
@@ -1085,6 +1085,67 @@ namespace MPF.Processors
#endif
}
+ ///
+ /// Determine if a given SS.bin is valid but contains zeroed challenge responses
+ ///
+ /// Path to the SS file to check
+ /// True if valid but partial SS.bin, false otherwise
+ public static bool IsValidPartialSS(string ssPath)
+ {
+ if (!File.Exists(ssPath))
+ return false;
+
+ byte[] ss = File.ReadAllBytes(ssPath);
+ if (ss.Length != 2048)
+ return false;
+
+ return IsValidPartialSS(ss);
+ }
+
+ ///
+ /// Determine if a given SS is valid but contains zeroed challenge responses
+ ///
+ /// Byte array of SS sector
+ /// True if SS is a valid but partial SS, false otherwise
+ public static bool IsValidPartialSS(byte[] ss)
+ {
+ // Check 1 sector long
+ if (ss.Length != 2048)
+ return false;
+
+ // Must be a valid XGD type
+ if (!GetXGDType(ss, out int xgdType))
+ return false;
+
+ // Determine challenge table offset, XGD1 is never partial
+ int ccrt_offset = 0;
+ if (xgdType == 1)
+ return false;
+ else if (xgdType == 2)
+ ccrt_offset = 0x200;
+ else if (xgdType == 3)
+ ccrt_offset = 0x20;
+
+ int[] entry_offsets = {0, 9, 18, 27, 36, 45, 54, 63};
+ int[] entry_lengths = {8, 8, 8, 8, 4, 4, 4, 4};
+ for (int i = 0; i < entry_offsets.Length; i++)
+ {
+ bool emptyResponse = true;
+ for (int b = 0; b < entry_lengths[i]; b++)
+ {
+ if (ss[ccrt_offset + entry_offsets[i] + b] != 0x00)
+ {
+ emptyResponse = false;
+ break;
+ }
+ }
+ if (emptyResponse)
+ return true;
+ }
+
+ return false;
+ }
+
///
/// Determine if a given SS has already been cleaned
///
diff --git a/MPF.Processors/Redumper.cs b/MPF.Processors/Redumper.cs
index 0537563c..b93f24b9 100644
--- a/MPF.Processors/Redumper.cs
+++ b/MPF.Processors/Redumper.cs
@@ -86,9 +86,12 @@ namespace MPF.Processors
if (!string.IsNullOrEmpty(multiSessionInfo))
info.CommonDiscInfo.CommentsSpecialFields![SiteCode.Multisession] = multiSessionInfo!;
- // Fill in the volume labels
- if (GetVolumeLabels($"{basePath}.log", out var volLabels))
- VolumeLabels = volLabels;
+ // Fill in the volume labels (ignore for Xbox/Xbox360)
+ if (System != RedumpSystem.MicrosoftXbox && System != RedumpSystem.MicrosoftXbox360)
+ {
+ if (GetVolumeLabels($"{basePath}.log", out var volLabels))
+ VolumeLabels = volLabels;
+ }
// Extract info based generically on MediaType
switch (mediaType)
@@ -211,46 +214,6 @@ namespace MPF.Processors
break;
case RedumpSystem.MicrosoftXbox:
- // If .dmi / .pfi / .ss don't already exist, create them
- if (!File.Exists($"{basePath}.dmi"))
- RemoveHeaderAndTrim($"{basePath}.manufacturer", $"{basePath}.dmi");
- if (!File.Exists($"{basePath}.pfi"))
- RemoveHeaderAndTrim($"{basePath}.physical", $"{basePath}.pfi");
- if (!File.Exists($"{basePath}.ss"))
- ProcessingTool.CleanSS($"{basePath}.security", $"{basePath}.ss");
-
- string xmidString = ProcessingTool.GetXMID($"{basePath}.dmi");
- var xmid = SabreTools.Serialization.Wrappers.XMID.Create(xmidString);
- if (xmid != null)
- {
- info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.XMID] = xmidString?.TrimEnd('\0') ?? string.Empty;
- info.CommonDiscInfo.Serial = xmid.Serial ?? string.Empty;
- if (!redumpCompat)
- {
- info.VersionAndEditions!.Version = xmid.Version ?? string.Empty;
- info.CommonDiscInfo.Region = ProcessingTool.GetXGDRegion(xmid.Model.RegionIdentifier);
- }
- }
-
- string? dmi1Crc = HashTool.GetFileHash($"{basePath}.dmi", HashType.CRC32);
- if (dmi1Crc != null)
- info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = dmi1Crc.ToUpperInvariant();
- string? pfi1Crc = HashTool.GetFileHash($"{basePath}.pfi", HashType.CRC32);
- if (pfi1Crc != null)
- info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.PFIHash] = pfi1Crc.ToUpperInvariant();
- if (ProcessingTool.IsValidSS($"{basePath}.ss"))
- {
- string? ss1Crc = HashTool.GetFileHash($"{basePath}.ss", HashType.CRC32);
- if (ss1Crc != null)
- info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.SSHash] = ss1Crc.ToUpperInvariant();
- }
-
- string? ranges1 = ProcessingTool.GetSSRanges($"{basePath}.ss");
- if (!string.IsNullOrEmpty(ranges1))
- info.Extras!.SecuritySectorRanges = ranges1;
-
- break;
-
case RedumpSystem.MicrosoftXbox360:
// If .dmi / .pfi / .ss don't already exist, create them
if (!File.Exists($"{basePath}.dmi"))
@@ -260,34 +223,48 @@ namespace MPF.Processors
if (!File.Exists($"{basePath}.ss"))
ProcessingTool.CleanSS($"{basePath}.security", $"{basePath}.ss");
- string xemidString = ProcessingTool.GetXeMID($"{basePath}.dmi");
- var xemid = SabreTools.Serialization.Wrappers.XeMID.Create(xemidString);
- if (xemid != null)
+ string xmidString = ProcessingTool.GetXMID($"{basePath}.dmi").Trim('\0');
+ if (!string.IsNullOrEmpty(xmidString))
{
- info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.XeMID] = xemidString?.TrimEnd('\0') ?? string.Empty;
- info.CommonDiscInfo.Serial = xemid.Serial ?? string.Empty;
+ info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.XMID] = xmidString;
+ var xmid = SabreTools.Serialization.Wrappers.XMID.Create(xmidString);
+ info.CommonDiscInfo.Serial = xmid?.Serial ?? string.Empty;
if (!redumpCompat)
- info.VersionAndEditions!.Version = xemid.Version ?? string.Empty;
-
- info.CommonDiscInfo.Region = ProcessingTool.GetXGDRegion(xemid.Model.RegionIdentifier);
+ {
+ info.VersionAndEditions!.Version = xmid?.Version ?? string.Empty;
+ info.CommonDiscInfo.Region = ProcessingTool.GetXGDRegion(xmid?.Model.RegionIdentifier);
+ }
}
- string? dmi23Crc = HashTool.GetFileHash($"{basePath}.dmi", HashType.CRC32);
- if (dmi23Crc != null)
- info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = dmi23Crc.ToUpperInvariant();
- string? pfi23Crc = HashTool.GetFileHash($"{basePath}.pfi", HashType.CRC32);
- if (pfi23Crc != null)
- info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.PFIHash] = pfi23Crc.ToUpperInvariant();
- if (ProcessingTool.IsValidSS($"{basePath}.ss"))
+ string xemidString = ProcessingTool.GetXeMID($"{basePath}.dmi").Trim('\0');
+ if (!string.IsNullOrEmpty(xemidString))
{
- string? ss23Crc = HashTool.GetFileHash($"{basePath}.ss", HashType.CRC32);
- if (ss23Crc != null)
- info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.SSHash] = ss23Crc.ToUpperInvariant();
+ info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.XeMID] = xemidString;
+ var xemid = SabreTools.Serialization.Wrappers.XeMID.Create(xemidString);
+ info.CommonDiscInfo.Serial = xemid?.Serial ?? string.Empty;
+ if (!redumpCompat)
+ {
+ info.VersionAndEditions!.Version = xemid?.Version ?? string.Empty;
+ info.CommonDiscInfo.Region = ProcessingTool.GetXGDRegion(xemid?.Model.RegionIdentifier);
+ }
}
- string? ranges23 = ProcessingTool.GetSSRanges($"{basePath}.ss");
- if (!string.IsNullOrEmpty(ranges23))
- info.Extras!.SecuritySectorRanges = ranges23;
+ string? dmiCrc = HashTool.GetFileHash($"{basePath}.dmi", HashType.CRC32);
+ if (dmiCrc != null)
+ info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.DMIHash] = dmiCrc.ToUpperInvariant();
+ string? pfiCrc = HashTool.GetFileHash($"{basePath}.pfi", HashType.CRC32);
+ if (pfiCrc != null)
+ info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.PFIHash] = pfiCrc.ToUpperInvariant();
+ if (ProcessingTool.IsValidSS($"{basePath}.ss") && !ProcessingTool.IsValidPartialSS($"{basePath}.ss"))
+ {
+ string? ssCrc = HashTool.GetFileHash($"{basePath}.ss", HashType.CRC32);
+ if (ssCrc != null)
+ info.CommonDiscInfo!.CommentsSpecialFields![SiteCode.SSHash] = ssCrc.ToUpperInvariant();
+ }
+
+ string? ssRanges = ProcessingTool.GetSSRanges($"{basePath}.ss");
+ if (!string.IsNullOrEmpty(ssRanges))
+ info.Extras!.SecuritySectorRanges = ssRanges;
break;
diff --git a/publish-nix.sh b/publish-nix.sh
index 785c557a..4fe8a4dd 100755
--- a/publish-nix.sh
+++ b/publish-nix.sh
@@ -100,12 +100,12 @@ function download_programs() {
# Redumper
DL_MAP["Redumper_linux-arm64"]=""
- DL_MAP["Redumper_linux-x64"]="https://github.com/superg/redumper/releases/download/build_611/redumper-2025.06.15_build611-Linux64.zip"
- DL_MAP["Redumper_osx-arm64"]="https://github.com/superg/redumper/releases/download/build_611/redumper-2025.06.15_build611-Darwin64.zip"
- DL_MAP["Redumper_osx-x64"]="https://github.com/superg/redumper/releases/download/build_611/redumper-2025.06.15_build611-Darwin64.zip"
+ DL_MAP["Redumper_linux-x64"]="https://github.com/superg/redumper/releases/download/build_613/redumper-2025.06.22_build613-Linux64.zip"
+ DL_MAP["Redumper_osx-arm64"]="https://github.com/superg/redumper/releases/download/build_613/redumper-2025.06.22_build613-Darwin64.zip"
+ DL_MAP["Redumper_osx-x64"]="https://github.com/superg/redumper/releases/download/build_613/redumper-2025.06.22_build613-Darwin64.zip"
DL_MAP["Redumper_win-arm64"]=""
- DL_MAP["Redumper_win-x86"]="https://github.com/superg/redumper/releases/download/build_611/redumper-2025.06.15_build611-Windows32.zip"
- DL_MAP["Redumper_win-x64"]="https://github.com/superg/redumper/releases/download/build_611/redumper-2025.06.15_build611-Windows64.zip"
+ DL_MAP["Redumper_win-x86"]="https://github.com/superg/redumper/releases/download/build_613/redumper-2025.06.22_build613-Windows32.zip"
+ DL_MAP["Redumper_win-x64"]="https://github.com/superg/redumper/releases/download/build_613/redumper-2025.06.22_build613-Windows64.zip"
# Download and extract files
echo "===== Downloading Required Programs ====="
diff --git a/publish-win.ps1 b/publish-win.ps1
index feef5361..0f55453e 100644
--- a/publish-win.ps1
+++ b/publish-win.ps1
@@ -89,12 +89,12 @@ function Download-Programs {
# Redumper
"Redumper_linux-arm64" = ""
- "Redumper_linux-x64" = "https://github.com/superg/redumper/releases/download/build_611/redumper-2025.06.15_build611-Linux64.zip"
- "Redumper_osx-arm64" = "https://github.com/superg/redumper/releases/download/build_611/redumper-2025.06.15_build611-Darwin64.zip"
- "Redumper_osx-x64" = "https://github.com/superg/redumper/releases/download/build_611/redumper-2025.06.15_build611-Darwin64.zip"
+ "Redumper_linux-x64" = "https://github.com/superg/redumper/releases/download/build_613/redumper-2025.06.22_build613-Linux64.zip"
+ "Redumper_osx-arm64" = "https://github.com/superg/redumper/releases/download/build_613/redumper-2025.06.22_build613-Darwin64.zip"
+ "Redumper_osx-x64" = "https://github.com/superg/redumper/releases/download/build_613/redumper-2025.06.22_build613-Darwin64.zip"
"Redumper_win-arm64" = ""
- "Redumper_win-x86" = "https://github.com/superg/redumper/releases/download/build_611/redumper-2025.06.15_build611-Windows32.zip"
- "Redumper_win-x64" = "https://github.com/superg/redumper/releases/download/build_611/redumper-2025.06.15_build611-Windows64.zip"
+ "Redumper_win-x86" = "https://github.com/superg/redumper/releases/download/build_613/redumper-2025.06.22_build613-Windows32.zip"
+ "Redumper_win-x64" = "https://github.com/superg/redumper/releases/download/build_6113/redumper-2025.06.22_build613-Windows64.zip"
}
# Download and extract files