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