-
Notifications
You must be signed in to change notification settings - Fork 27
Dvd iso volume size #302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dvd iso volume size #302
Conversation
WalkthroughRange insertion now throws on invalid input and merges overlaps; string_to_ranges was templatized. Xbox utilities moved into a new dvd.xbox module exposing a Context-based security-layer API. DVD dump/split flows were refactored to use protection ranges, FORM1_DATA_SIZE, and expanded Kreon handling; tests and endian utilities were extended. Changes
Sequence Diagram(s)sequenceDiagram
participant CLI as Options/Client
participant Dump as redumper_dump_dvd
participant Ranges as range module
participant Xbox as dvd::xbox::initialize
participant Drive as SPTD / Drive
CLI->>Dump: start dump (options, skip string)
Dump->>Ranges: string_to_ranges<T>(options.skip)
Ranges-->>Dump: protection ranges (std::vector<Range<uint32_t>>)
Dump->>Xbox: initialize(protection, sptd, layer0, capacity, ...)
Xbox->>Drive: read_security_layer_descriptor / read sectors
Drive-->>Xbox: security descriptor / sector data
Xbox-->>Dump: Context (security_sector, lock_sector_start, layer1_video_start)
loop per-sector
Dump->>Ranges: is sector in protection ranges?
alt protected
Dump->>Drive: read sector (skip storing)
else unprotected
Dump->>Drive: read sector (store/write)
end
end
Dump->>Xbox: finalize (unlock/cleanup)
Dump-->>CLI: finish (result/logs)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45–60 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (5)
drive.ixx (1)
404-414: LGTM! Minor suggestion: consider documenting the distinction between these predicates.The implementation is correct. Both functions serve different purposes:
is_kreon_firmware: Detects drives with Kreon firmware via vendor-specific stringis_custom_kreon_firmware: Detects specific patched revision levels ("DC02", "ZZ01")Note that "DC02" doesn't appear in the current
DRIVE_DATABASEentries—verify this is intentional for drives expected in the wild but not yet catalogued.Consider extracting magic strings as constants for maintainability:
+static constexpr std::string_view KREON_FIRMWARE_PREFIX = "KREON V1.00"; +static constexpr std::string_view KREON_REVISION_DC02 = "DC02"; +static constexpr std::string_view KREON_REVISION_ZZ01 = "ZZ01"; + export bool is_kreon_firmware(const DriveConfig &drive_config) { - return drive_config.vendor_specific.starts_with("KREON V1.00"); + return drive_config.vendor_specific.starts_with(KREON_FIRMWARE_PREFIX); } export bool is_custom_kreon_firmware(const DriveConfig &drive_config) { - return drive_config.product_revision_level == "DC02" || drive_config.product_revision_level == "ZZ01"; + return drive_config.product_revision_level == KREON_REVISION_DC02 || drive_config.product_revision_level == KREON_REVISION_ZZ01; }debug.ixx (1)
24-145: Xbox debug block is inert but grows debug.ixx surfaceThe new
import dvd.xbox;andif(0)block are debug-only and currently have no runtime effect, which is fine. If this code becomes something you rely on regularly, consider promoting it to a named helper or toggling it via a flag instead of hardcodedif(0)to keepredumper_debugmaintainable.range.ixx (1)
1-6: Verify throw_line header pathThis file includes
"utils/throw_line.hh", while other modules include"throw_line.hh". Please confirm that this path is valid in your include layout; otherwise, align it with the existing includes to avoid build issues.dvd/dvd_dump.ixx (1)
681-690: Minor optimization opportunity: cachefind_rangeresult.
find_range(protection, s)is called twice - once in the loop condition and once for comparison. Consider caching the result:auto base_range = find_range(protection, s); for(uint32_t i = 0; i < sectors_to_read; ++i) { if(base_range != find_range(protection, s + i)) { sectors_to_read = i; break; } }utils/xbox.ixx (1)
207-216: Clarify complex condition with parentheses.The condition on line 209 relies on operator precedence (
&&before||). Adding explicit parentheses would improve readability:- if(xgd_version(layer0_last) == 1 && i >= 16 || xgd_version(layer0_last) != 1 && i != 0 && i != 3) + if((xgd_version(layer0_last) == 1 && i >= 16) || (xgd_version(layer0_last) != 1 && i != 0 && i != 3))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
cd/cd_common.ixx(1 hunks)cd/cd_dump.ixx(1 hunks)cd/cd_split.ixx(1 hunks)debug.ixx(2 hunks)drive.ixx(2 hunks)dvd/dvd_dump.ixx(11 hunks)dvd/dvd_split.ixx(4 hunks)range.ixx(2 hunks)scsi/cmd.ixx(1 hunks)tests/CMakeLists.txt(1 hunks)tests/tests.cc(3 hunks)utils/endian.ixx(2 hunks)utils/strings.ixx(2 hunks)utils/xbox.ixx(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-07T19:05:32.220Z
Learnt from: superg
Repo: superg/redumper PR: 283
File: scsi/cmd.ixx:558-571
Timestamp: 2025-09-07T19:05:32.220Z
Learning: In the scsi/cmd.ixx file, there are multiple functions that use pointer-byte indexing for endianness conversion that could be prone to endianness issues. The maintainer prefers to address these systematically in a centralized manner rather than piecemeal fixes.
Applied to files:
scsi/cmd.ixx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: build-windows (x86, Win32)
- GitHub Check: build-windows (arm64, ARM64)
- GitHub Check: build-macos (x64)
- GitHub Check: build-windows (x64, x64)
- GitHub Check: build-macos (arm64)
- GitHub Check: build-linux (x64, ubuntu-24.04)
- GitHub Check: build-linux (x86, ubuntu-24.04)
- GitHub Check: build-linux (arm64, ubuntu-24.04-arm)
🔇 Additional comments (27)
drive.ixx (2)
130-176: LGTM on DRIVE_DATABASE updates.The database entries are well-structured with consistent offset, revision, and type classifications. The addition of the "PATCHED KREON" comment on line 175 improves clarity for distinguishing Kreon-specific firmware entries.
183-211: LGTM on remaining database entries.The legacy PLEXTOR drives and OTHER section entries are consistently formatted with appropriate type classifications and sector order configurations.
utils/endian.ixx (1)
4-4: LGTM!The
<climits>include is necessary forCHAR_BITused in the new template functions.scsi/cmd.ixx (1)
513-531: Lock-state branch simplification is safeUsing
if(lock_state == KREON_LockState::LEGACY)instead of an intermediate boolean preserves the original behavior and improves readability; no issues found.cd/cd_common.ixx (1)
694-705: Protection range insertion correctly delegates validation to insert_rangeSwitching to unconditional
insert_rangecalls and dropping explicit failure handling is consistent with the new API whereinsert_rangethrows on invalid ranges and merges overlaps itself; no further changes needed here.range.ixx (1)
56-82: insert_range merge/validation semantics look correctThe new
insert_range:
- Rejects invalid ranges via
throw_line, centralizing validation.- Correctly finds and merges all overlapping or adjacent intervals, maintaining sorted, non-overlapping ranges.
This matches the behavior exercised intest_range()and aligns with callers now ignoring a return value.tests/CMakeLists.txt (1)
13-13: Including range.ixx in the tests target is correctAdding
range.ixxto thetestsmodule set matches the newimport range;intests.ccand is required for the range tests to compile.cd/cd_dump.ixx (1)
281-286: Session gap handling via insert_range is consistent with new APIUsing
insert_range(session_gaps, r);without checking a return value is appropriate now thatinsert_rangevalidates and merges ranges internally; this keeps the gap logic simpler and leverages the shared range semantics.tests/tests.cc (1)
14-457: Range tests give good coverage of the new insert_range semantics
import range;plustest_range()exercise:
- Non-overlapping insertion and ordering,
find_rangelookup correctness,- Overlapping and adjacent range merges,
- Insertions inside existing ranges,
- Exception behavior on invalid ranges,
- Edge insertions at start/end of the set.
This should catch most regressions in the range module; no issues spotted.
dvd/dvd_split.ixx (3)
12-21: LGTM! Import updates align with module refactoring.The imports correctly reflect the module rename (
dvd.xbox) and the addition of therangemodule forRange<uint32_t>support.
48-54: LGTM! Consistent use ofFORM1_DATA_SIZE.The manufacturer file size check (
FORM1_DATA_SIZE + 4) and ROM entry update correctly account for the 4-byte header that gets trimmed.
103-117: LGTM! Clean refactoring to usexboxnamespace andRangetype.The security sector processing correctly uses the new
xbox::clean_security_sectorandxbox::get_security_layer_descriptor_rangesAPIs. The range logging withr.end - 1properly converts the exclusive end to an inclusive display format.utils/strings.ixx (1)
304-335: Approve templatedstring_to_rangeswith a note on potential edge case.The template generalization is well-implemented with proper unsigned validation. The range storage semantics (exclusive end via
end + 1) are consistent.However, if
endequalsstd::numeric_limits<T>::max(), the(T)end + 1expression on line 331 will overflow/wrap to zero. This is unlikely in practice for sector ranges but worth noting.Consider whether the input validation should guard against
end == std::numeric_limits<T>::max()to prevent wraparound, or document this as a precondition.dvd/dvd_dump.ixx (8)
379-381: LGTM! Protection range initialization.Correct use of the templated
string_to_ranges<uint32_t>andinsert_rangeto build the protection ranges vector.
383-392: LGTM! Early Kreon unlock for accurate capacity reading.The early unlock ensures
READ_CAPACITYreturns the correct value for Xbox disc detection. The non-fatal error handling allows graceful fallback.
394-404: LGTM! Capacity querying with block size validation.The capacity read and block size validation are correct. Using a scoped block keeps variables contained.
424-467: LGTM! Xbox context initialization and security sector handling.The Xbox detection logic, security sector storage/comparison for disc verification during refine, and fallback for malformed XGD are well-structured.
469-480: LGTM! Physical sector count calculation.Correctly accumulates layer lengths across all physical structures using optional semantics.
734-772: LGTM! Protection range handling.Sectors within protection ranges are correctly marked for storage without reading, resulting in zeroed sectors in the output. The SCSI error handling with retry logic for refine mode is properly implemented.
845-851: LGTM! Kreon drive cleanup.Properly re-unlocks the drive at the end of the dump if it was locked, ensuring the drive is left in a usable state.
642-649: LGTM! Sectors count determination logic.Correctly prioritizes physical structure sector count over capacity, with appropriate warning for mismatches outside Xbox context.
utils/xbox.ixx (6)
26-31: LGTM!Contextstruct design.Clean encapsulation of Xbox-related state for passing between dump functions.
34-136: LGTM! Well-documentedSecurityLayerDescriptorunion.The packed union with documented byte offsets provides clean access to XGD security sector data. The structure handles XGD1/2/3 variants appropriately.
139-162: LGTM! PSN/LBA conversion and version detection.The PSN-to-LBA conversion correctly handles the 0x30000 offset and layer wrap-around for opposite track path. Version detection via
layer0_lastvalues is clean.
220-244: LGTM! Security sector cleaning for consistent comparison.Correctly normalizes challenge-response data for XGD2/XGD3 to enable consistent security sector comparison across dumps.
247-306: LGTM! Xbox initialization with XGD3 repair support.The
initializefunction correctly handles XGD detection, optional XGD3 security sector repair via leadout, and computes the necessary offsets for Kreon lock/unlock. The modification oflayer0_ldis documented.One note:
read_security_layer_descriptorcan throw, which will propagate up. This is appropriate for initialization failure.
187-198: LGTM! XGD3 security sector merge/repair logic.Correctly transfers the necessary fields from Kreon-read SS to leadout SS to produce a valid XGD3 security sector.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
dvd/dvd_dump.ixx (3)
434-468: Consider extracting Xbox initialization logic to a helper function.The Xbox/Kreon detection and security sector handling is deeply nested (6+ levels) and spans 30+ lines. Extracting this to a helper function like
try_initialize_xbox_context(...)would improve readability and testability.
470-481: Consider simplifying sectors_count_physical accumulation.The current pattern of checking
!sectors_count_physical, initializing to 0, then dereferencing works but is verbose. Consider usingvalue_or():- for(uint32_t i = 0; i < physical_structures.size(); ++i) - { - auto const &structure = physical_structures[i]; - - auto &layer_descriptor = (READ_DVD_STRUCTURE_LayerDescriptor &)structure[sizeof(CMD_ParameterListHeader)]; - - if(!sectors_count_physical) - sectors_count_physical = 0; - - *sectors_count_physical = *sectors_count_physical + get_layer_length(layer_descriptor); - } + for(uint32_t i = 0; i < physical_structures.size(); ++i) + { + auto const &structure = physical_structures[i]; + + auto &layer_descriptor = (READ_DVD_STRUCTURE_LayerDescriptor &)structure[sizeof(CMD_ParameterListHeader)]; + + sectors_count_physical = sectors_count_physical.value_or(0) + get_layer_length(layer_descriptor); + }
693-711: Consider extracting Xbox/Kreon locking logic to a helper function.The Xbox-specific sector adjustment and Kreon locking logic adds complexity to the main read loop. Extracting this to a helper function like
handle_xbox_sector_adjustment(...)would improve readability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
dvd/dvd_dump.ixx(11 hunks)rom_entry.ixx(1 hunks)utils/endian.ixx(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- utils/endian.ixx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: build-windows (x86, Win32)
- GitHub Check: build-macos (arm64)
- GitHub Check: build-windows (arm64, ARM64)
- GitHub Check: build-macos (x64)
- GitHub Check: build-windows (x64, x64)
- GitHub Check: build-linux (x64, ubuntu-24.04)
- GitHub Check: build-linux (x86, ubuntu-24.04)
- GitHub Check: build-linux (arm64, ubuntu-24.04-arm)
🔇 Additional comments (14)
rom_entry.ixx (1)
30-31: Defaulted destructor is safe but likely optional.The defaulted destructor is appropriate for this class, as all members are value types or standard library types that manage their own cleanup. This addition is fine, though it may be unnecessary unless required by a coding standard or style guide.
dvd/dvd_dump.ixx (13)
5-6: LGTM!The new includes and imports appropriately support the Xbox context management, optional physical sector counts, and protection range functionality introduced in this PR.
Also applies to: 9-9, 18-18, 21-21
384-393: LGTM!The early Kreon unlock logic is well-motivated by the comment and appropriately handles errors with logging rather than throwing, allowing the operation to continue if the unlock fails.
395-405: LGTM!The capacity reading refactor clearly separates this logic and correctly validates the block size against
FORM1_DATA_SIZE. The calculationsector_last + 1is correct for converting the 0-indexed last sector address to a total count.
411-413: LGTM!The use of
std::shared_ptrfor the Xbox context andstd::optionalfor the physical sector count appropriately models the conditional nature of these values.
428-431: LGTM!Good defensive validation of physical structure sizes before accessing layer descriptors. The error message includes the layer index for debugging.
486-502: LGTM!The indexed suffix logic cleanly handles both single and multi-layer disc structures, creating filenames like
.manufacturer.0,.manufacturer.1for multi-layer discs and.manufacturerfor single-layer discs.
565-567: LGTM!The reference cast style is consistent with the new approach used earlier in the function and is safe due to the size validation performed at lines 428-431.
643-650: LGTM!The sector count determination logic correctly prioritizes physical structure counts and appropriately warns on mismatches only for non-Xbox discs, where such discrepancies are unexpected.
683-691: LGTM!The protection range boundary checking ensures that read operations don't span across different ranges (skip vs. non-skip), which is essential for correct handling. The pointer comparison in
find_range(protection, s) != find_range(protection, s + i)correctly identifies range transitions.
735-773: LGTM!The protection-based read path correctly skips sectors in protected ranges and handles errors with detailed logging. The conditional retry information in verbose mode (lines 747-752) is particularly helpful for debugging.
832-834: LGTM!Correctly conditions ROM entry updates on dump mode and absence of errors, ensuring hash calculations only include successfully read data.
846-852: LGTM!The Kreon re-unlock logic appropriately restores the drive state at the end of the operation. Error logging without throwing is correct for cleanup code, ensuring the function completes even if the unlock fails.
380-383: Error handling for invalid skip ranges is already appropriately implemented.The code provides user-friendly error messages through two validation layers:
string_to_ranges(utils/strings.ixx): Validates input format and throws"negative value not allowed for unsigned range type ({value})"with the actual problematic value.
insert_range(range.ixx): Validates range structure and throws"insertion failed, invalid range configuration: [{start}, {end}]"with actual values whenstart >= end.Both use
throw_line, which wrapsstd::runtime_errorwith formatted messages that reach users. This error-handling pattern is consistent with other validation in theredumper_dump_dvdfunction and appropriately catches user configuration errors early.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/tests.cc (2)
402-416: Test 9 is identical to Test 1.Both tests insert ranges
{10,20},{30,40},{50,60}and verify 3 non-overlapping ranges with the same assertions. Consider either removing this duplicate or modifying it to specifically test appending to the end by inserting ranges in a different order (e.g., insert{50,60}last after{10,20}and{30,40}are already present).// Test 9: Insert at end without overlap ranges.clear(); std::cout << "Test 9: Insert at end without overlap... " << std::flush; insert_range(ranges, Range<int32_t>{ 10, 20 }); insert_range(ranges, Range<int32_t>{ 30, 40 }); - insert_range(ranges, Range<int32_t>{ 50, 60 }); + insert_range(ranges, Range<int32_t>{ 70, 80 }); // Append beyond existing ranges - if(ranges.size() == 3 && ranges[0].start == 10 && ranges[0].end == 20 && ranges[1].start == 30 && ranges[1].end == 40 && ranges[2].start == 50 && ranges[2].end == 60) + if(ranges.size() == 3 && ranges[0].start == 10 && ranges[0].end == 20 && ranges[1].start == 30 && ranges[1].end == 40 && ranges[2].start == 70 && ranges[2].end == 80)
277-280: Consider adding edge case tests for invalid ranges.The test suite covers happy-path scenarios well. Based on the range module changes, consider adding tests for:
- Invalid ranges where
start > end(should throw per the new behavior)- Empty ranges where
start == end(boundary behavior)Example test for exception on invalid range:
// Test: Invalid range should throw std::cout << "Test: Invalid range (start > end) should throw... " << std::flush; try { std::vector<Range<int32_t>> temp; insert_range(temp, Range<int32_t>{ 30, 10 }); std::cout << "failure (no exception thrown)" << std::endl; success = false; } catch (...) { std::cout << "success" << std::endl; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
tests/tests.cc(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: build-linux (x86, ubuntu-24.04)
- GitHub Check: build-linux (arm64, ubuntu-24.04-arm)
- GitHub Check: build-macos (arm64)
- GitHub Check: build-macos (x64)
- GitHub Check: build-windows (arm64, ARM64)
- GitHub Check: build-windows (x64, x64)
- GitHub Check: build-windows (x86, Win32)
- GitHub Check: build-linux (x64, ubuntu-24.04)
🔇 Additional comments (3)
tests/tests.cc (3)
14-14: LGTM!Import correctly added to enable testing of the range module.
283-432: Well-structured test cases with good coverage.The test logic correctly validates:
- Non-overlapping range insertion and ordering
- Range lookup with
find_range- Merge behavior for overlapping, adjacent, and contained ranges
- Boundary cases at start and end of the range collection
Good use of defensive access patterns and diagnostic output in failure messages.
452-453: LGTM!Correctly integrates
test_range()into the test suite following the established pattern.
|
This PR adds support for --skip when dumping DVDs, thus fixing #69 ? |
Will come in another PR, this one already has too much. Please review my changes though, meanwhile I'm testing here by dumping my xbox discs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
utils/endian.ixx (1)
77-84: Mirror unsigned-intermediate pattern and optionally constrainUto bytes.The size
static_assertis a solid guard here as well. For symmetry withendian_swap_from_arrayand to avoid implementation-defined behavior whenTis signed (right-shifting negatives), consider shifting an unsigned copy ofv:export template<typename T, typename U, std::size_t N> void endian_swap_to_array(U (&a)[N], T v) { - static_assert(sizeof(T) >= N * sizeof(U), "source type T must be large enough to contain all array data"); - - for(size_t i = 0; i < N; ++i) - a[i] = (U)(v >> CHAR_BIT * sizeof(U) * (N - 1 - i)); + static_assert(sizeof(T) >= N * sizeof(U), + "source type T must be large enough to contain all array data"); + + using UT = std::make_unsigned_t<T>; + + UT uv = static_cast<UT>(v); + + for (std::size_t i = 0; i < N; ++i) + a[i] = static_cast<U>(uv >> (CHAR_BIT * sizeof(U) * (N - 1 - i))); }If the intent is strictly “array of raw bytes”, you might also add an optional constraint:
static_assert(std::is_unsigned_v<U>, "endian_swap_to_array expects unsigned element type U");(This echoes an earlier review suggestion for this function.)
#!/bin/bash # Optional: confirm that current uses of endian_swap_to_array pass unsigned U/T as expected. rg -n "endian_swap_to_array" -C3
🧹 Nitpick comments (2)
range.ixx (1)
56-59: insert_range merge logic looks correct; consider documenting adjacency and a tiny micro‑optThe new implementation correctly:
- Rejects invalid ranges via
throw_lineinstead of a boolean return.- Finds all existing ranges whose
end >= range.startandstart <= range.end(including touching ones) and merges them into a single[start, end)segment while preserving sorted order.Because of the
>=/<=checks, adjacent intervals like[a, b)and[b, c)will now be coalesced into[a, c). That’s a reasonable design, but it’s a behaviour change vs strictly non-overlapping, non‑coalescing semantics; worth calling out in a brief comment or doc so callers know that “touching” ranges are merged.Minor nit: after
ranges.erase(first_overlap, last_overlap);you know the insertion position is wherefirst_overlapused to be. You could cache the index and useranges.begin() + indexinstead of re‑runninglower_boundto shave a tiny amount of work.Also applies to: 63-79, 81-81
dvd/dvd_dump.ixx (1)
384-386: Kreon lock/unlock flow is clearer; RAII guard would make it exception‑safeThe Kreon handling is much improved:
- You detect Kreon firmware and proactively switch to
WXRIPPERbefore capacity/Xbox detection (Lines 384–393).- During the main loop, you delay locking until
s >= xbox->lock_sector_start, then setkreon_locked = trueand computesector_shiftwhile in the locked state (Lines 690–707).- At normal function exit you conditionally restore
WXRIPPERif the drive was locked (Lines 843–849), and you also log an interrupt‑driven early stop (Line 835).One remaining robustness gap is exception safety: any
throw_lineafter the drive has been locked (e.g., from SCSI calls or structure validation) will bypass the final unlock block and potentially leave the drive in the locked state until the user intervenes.Non‑blocking suggestion: consider wrapping the lock state in a small RAII helper that calls
cmd_kreon_set_lock_state(*ctx.sptd, KREON_LockState::WXRIPPER)in its destructor when it knows the drive is currently locked. That would guarantee unlock on all exit paths (normal return and exceptions) without changing the high‑level control flow here.Also applies to: 387-393, 690-708, 835-835, 843-849
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
dvd/dvd_dump.ixx(11 hunks)range.ixx(2 hunks)tests/CMakeLists.txt(2 hunks)tests/tests.cc(3 hunks)utils/endian.ixx(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- tests/tests.cc
- tests/CMakeLists.txt
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-07T19:05:32.220Z
Learnt from: superg
Repo: superg/redumper PR: 283
File: scsi/cmd.ixx:558-571
Timestamp: 2025-09-07T19:05:32.220Z
Learning: In the scsi/cmd.ixx file, there are multiple functions that use pointer-byte indexing for endianness conversion that could be prone to endianness issues. The maintainer prefers to address these systematically in a centralized manner rather than piecemeal fixes.
Applied to files:
utils/endian.ixx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: build-macos (x64)
- GitHub Check: build-macos (arm64)
- GitHub Check: build-linux (arm64, ubuntu-24.04-arm)
- GitHub Check: build-windows (x86, Win32)
- GitHub Check: build-linux (x86, ubuntu-24.04)
- GitHub Check: build-linux (x64, ubuntu-24.04)
- GitHub Check: build-windows (x64, x64)
- GitHub Check: build-windows (arm64, ARM64)
🔇 Additional comments (5)
utils/endian.ixx (2)
4-4: Include of<climits>is appropriate and necessary forCHAR_BIT.This correctly satisfies the dependency introduced by the new templates using
CHAR_BIT. No issues here.
30-38: Explicit specializations remain valid optimized fast paths.The
endian_swapspecializations foruint16_t/32/64still funnel to platform intrinsics while keeping the generic template in place. This looks fine and keeps the optimized paths centralized.Also applies to: 41-49, 52-60
dvd/dvd_dump.ixx (3)
5-9: New headers and imports match the added functionalityThe additions of
<memory>,<optional>, and<vector>, plus theimport dvd.xbox;andimport range;, are consistent with the new use ofstd::shared_ptr,std::optional,std::vector, and the Xbox context/protection range utilities. No issues here.Also applies to: 18-18, 21-21
380-383: Skip/protection ranges: semantics look coherent; confirm zero‑fill & success state are desiredThe new protection handling around
options.skipand Xbox security looks internally consistent:
protectionis built fromstring_to_ranges<uint32_t>(options.skip)usinginsert_range, so user‑supplied and Xbox‑supplied ranges end up merged and sorted (Lines 380–383).- At the start of each loop iteration you limit
sectors_to_readso that a batch never straddles a protection boundary (Lines 679–689), which keeps the “skip” and “read” paths cleanly separated.- In the main read path, if
find_range(protection, s)hits,storeis settrueand no SCSI read is issued for that batch;drive_datastays as zero‑initialized memory (Lines 732–737).- When
storeis true in DUMP mode you:
- Swap
file_datawithdrive_data(so the ISO gets zero‑filled sectors),- Mark all
file_stateentries in the chunk asState::SUCCESS,- And later call
rom_entry.update(...)as long aserrors.scsi == 0(Lines 772–772, 779–781, 829–831).- In REFINE/VERIFY, protected sectors also avoid SCSI reads; they are effectively treated as always‑good data.
This matches a “deliberately skipped / logically known content” interpretation: skipped or protected regions become zero‑filled, are not counted as SCSI errors, and participate in DAT/rom computation as long as the rest of the dump is error‑free.
If that’s the intended contract for
--skip(i.e., intentional gaps that should not be distinguishable from error‑free sectors in the state file or DAT), then the implementation looks good. If instead you want skipped sectors to remain distinguishable (e.g., marked asERROR_SKIP, excluded fromrom_entry.update, or always re‑skipped in REFINE/VERIFY), you may want to adjust the state handling in these branches accordingly.Also applies to: 676-676, 679-689, 732-737, 739-770, 772-772, 789-789, 829-831
482-482: Physical/manufacturer/CSS structure handling and logging look solidA few notes on the structural metadata handling:
- Manufacturer structures are now read per physical layer and written to
*.manufacturerfiles usingstd::formatfor consistent file naming (Lines 482, 488, 492, 496–499); this aligns well with the existing*.physicalnaming and multi‑layer handling.- For non‑Blu‑ray DVDs, you reuse
print_physical_structureafter extracting theREAD_DVD_STRUCTURE_LayerDescriptorfrom each physical structure buffer (Lines 561–564), which nicely centralizes the logging.- In REFINE mode, the disc’s current physical structures are compared byte‑for‑byte against the stored
*.physicalfiles, and a clearthrow_lineis raised on mismatch (Lines 603–607); that’s a good integrity check to ensure refinement is done on the same disc.- CSS/COPYRIGHT reading via
cmd_read_disc_structurewithstrip_response_headerand interpretation ofREAD_DVD_STRUCTURE_CopyrightInformation(Line 615 and subsequent code) is consistent with standard CSS authentication flows.I don’t see correctness issues in these pieces; the behaviour and diagnostics look appropriate.
Also applies to: 488-488, 492-492, 496-501, 561-564, 606-607, 615-615
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
dvd/xbox.ixx (1)
209-210: Add explicit parentheses for clarity.The conditional mixes
&&and||operators. While operator precedence makes this work, explicit grouping improves readability and prevents future maintenance errors.- if(xgd_version(layer0_last) == 1 && i >= 16 || xgd_version(layer0_last) != 1 && i != 0 && i != 3) + if((xgd_version(layer0_last) == 1 && i >= 16) || (xgd_version(layer0_last) != 1 && i != 0 && i != 3))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
CMakeLists.txt(1 hunks)dvd/xbox.ixx(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: superg
Repo: superg/redumper PR: 302
File: dvd/dvd_dump.ixx:395-405
Timestamp: 2025-11-28T01:02:39.514Z
Learning: In dvd/dvd_dump.ixx, the sector count determination logic (around lines 641-647) is intentionally centralized to support multiple sources: READ_CAPACITY, physical structures, and future options like ISO/UDF filesystem size. For Xbox/Kreon XGD discs, the physical structure sector count is correct to use because xbox::initialize() updates the layer0_ld.layer0_end_sector with the true value from the security sector before sectors_count_physical is calculated.
📚 Learning: 2025-10-21T21:23:42.149Z
Learnt from: superg
Repo: superg/redumper PR: 288
File: .github/workflows/cmake.yml:0-0
Timestamp: 2025-10-21T21:23:42.149Z
Learning: In the redumper project, REDUMPER_OS and REDUMPER_ARCH CMake variables are deprecated. Package naming now derives the suffix from the CMAKE_TOOLCHAIN_FILE basename (e.g., the toolchain file cmake/toolchains/macos-x64.cmake produces a package suffix of macos-x64).
Applied to files:
CMakeLists.txt
📚 Learning: 2025-10-21T21:22:45.817Z
Learnt from: superg
Repo: superg/redumper PR: 288
File: cmake/toolchains/macos-arm64.cmake:0-0
Timestamp: 2025-10-21T21:22:45.817Z
Learning: The redumper codebase uses only C++, not C, so CMAKE_C_COMPILER configuration is not needed in toolchain files.
Applied to files:
CMakeLists.txt
📚 Learning: 2025-11-28T01:02:39.514Z
Learnt from: superg
Repo: superg/redumper PR: 302
File: dvd/dvd_dump.ixx:395-405
Timestamp: 2025-11-28T01:02:39.514Z
Learning: In dvd/dvd_dump.ixx, the sector count determination logic (around lines 641-647) is intentionally centralized to support multiple sources: READ_CAPACITY, physical structures, and future options like ISO/UDF filesystem size. For Xbox/Kreon XGD discs, the physical structure sector count is correct to use because xbox::initialize() updates the layer0_ld.layer0_end_sector with the true value from the security sector before sectors_count_physical is calculated.
Applied to files:
dvd/xbox.ixx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: build-macos (x64)
- GitHub Check: build-macos (arm64)
- GitHub Check: build-linux (arm64, ubuntu-24.04-arm)
- GitHub Check: build-linux (x86, ubuntu-24.04)
- GitHub Check: build-linux (x64, ubuntu-24.04)
- GitHub Check: build-windows (x64, x64)
- GitHub Check: build-windows (x86, Win32)
- GitHub Check: build-windows (arm64, ARM64)
🔇 Additional comments (7)
CMakeLists.txt (1)
118-118: LGTM!The module relocation from
utils/xbox.ixxtodvd/xbox.ixxappropriately groups Xbox-related functionality with other DVD modules.dvd/xbox.ixx (6)
1-20: LGTM!Module declaration and imports are well-organized and appropriate for the Xbox security sector handling functionality.
26-31: LGTM!The
Contextstruct provides a clean interface for Xbox security context data.
288-291: Verify no integer underflow on l1_padding_length calculation.If
ss_lba_first <= layer0_last, the subtraction produces a negative value which wraps when stored inuint32_t. This would result in an extremely large padding value.If this invariant is guaranteed by the XGD specification, consider adding an assertion or comment documenting the assumption:
// XGD spec guarantees ss_lba_first > layer0_last assert(ss_lba_first > layer0_last && "Invalid layer addressing"); uint32_t l1_padding_length = ss_lba_first - layer0_last - 1;
165-198: LGTM!The security layer descriptor reading and merging logic handles partial responses appropriately, with proper error handling for SCSI failures.
155-162: LGTM!The PSN to LBA conversion logic correctly handles dual-layer disc addressing with the layer0_last adjustment.
139-145: LGTM!Version mapping and lead-out sector constants are well-defined for the three XGD versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
dvd/xbox.ixx (2)
34-136: Complex packed union structure for security layer data.The
SecurityLayerDescriptorunion maps the on-disc security sector format with byte-level precision. The nested unions for xgd1/xgd2/xgd3 variants handle the different Xbox disc generations appropriately.Note: The decimal offset comments on lines 98-100 appear incorrect (already flagged in a previous review).
220-244: Strict aliasing concern already flagged.The
uint16_t&casts on lines 232-233 and 240-241 were noted in a previous review for potential strict aliasing violations. The same bounds-check recommendation from the previous function applies here as well.
🧹 Nitpick comments (1)
dvd/xbox.ixx (1)
201-217: Add bounds check before casting security_sector to SecurityLayerDescriptor.The function casts
security_sector[0]toSecurityLayerDescriptor&without verifying that the vector has sufficient size. If an undersized vector is passed, this could lead to undefined behavior.Consider adding a size check:
export void get_security_layer_descriptor_ranges(std::vector<Range<uint32_t>> &protection, const std::vector<uint8_t> &security_sector) { + if(security_sector.size() < sizeof(SecurityLayerDescriptor)) + throw_line("security sector too small"); + auto const &sld = (SecurityLayerDescriptor &)security_sector[0];
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
dvd/dvd_dump.ixx(12 hunks)dvd/xbox.ixx(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: superg
Repo: superg/redumper PR: 302
File: dvd/dvd_dump.ixx:395-405
Timestamp: 2025-11-28T01:02:39.514Z
Learning: In dvd/dvd_dump.ixx, the sector count determination logic (around lines 641-647) is intentionally centralized to support multiple sources: READ_CAPACITY, physical structures, and future options like ISO/UDF filesystem size. For Xbox/Kreon XGD discs, the physical structure sector count is correct to use because xbox::initialize() updates the layer0_ld.layer0_end_sector with the true value from the security sector before sectors_count_physical is calculated.
📚 Learning: 2025-11-28T01:02:39.514Z
Learnt from: superg
Repo: superg/redumper PR: 302
File: dvd/dvd_dump.ixx:395-405
Timestamp: 2025-11-28T01:02:39.514Z
Learning: In dvd/dvd_dump.ixx, the sector count determination logic (around lines 641-647) is intentionally centralized to support multiple sources: READ_CAPACITY, physical structures, and future options like ISO/UDF filesystem size. For Xbox/Kreon XGD discs, the physical structure sector count is correct to use because xbox::initialize() updates the layer0_ld.layer0_end_sector with the true value from the security sector before sectors_count_physical is calculated.
Applied to files:
dvd/dvd_dump.ixxdvd/xbox.ixx
📚 Learning: 2025-09-07T19:05:32.220Z
Learnt from: superg
Repo: superg/redumper PR: 283
File: scsi/cmd.ixx:558-571
Timestamp: 2025-09-07T19:05:32.220Z
Learning: In the scsi/cmd.ixx file, there are multiple functions that use pointer-byte indexing for endianness conversion that could be prone to endianness issues. The maintainer prefers to address these systematically in a centralized manner rather than piecemeal fixes.
Applied to files:
dvd/dvd_dump.ixxdvd/xbox.ixx
📚 Learning: 2025-09-07T20:29:35.084Z
Learnt from: superg
Repo: superg/redumper PR: 283
File: scsi/mmc.ixx:853-862
Timestamp: 2025-09-07T20:29:35.084Z
Learning: In scsi/mmc.ixx, the maintainer only adds pragma pack directives to structures when needed, not preemptively. They verify struct layouts work correctly through actual hardware testing rather than relying solely on static assertions.
Applied to files:
dvd/xbox.ixx
🔇 Additional comments (12)
dvd/xbox.ixx (4)
26-31: LGTM - Context struct is well-defined.The
Contextstruct provides a clean encapsulation for Xbox-specific state including the security sector data and key offsets needed for dump operations.
148-162: PSN to LBA conversion logic is correct.The
PSN_to_LBAfunction properly handles the standard DVD PSN offset (0x30000) and layer wrap-around for opposite track path discs.
165-184: LGTM - Security layer descriptor read with proper error handling.The function correctly handles partial security sector reads for Kreon firmware, throws on initial failure, and returns a completeness indicator for caller logging.
258-314: Well-structured Xbox initialization with proper resource management.The function correctly:
- Returns
nullptrfor unrecognized XGD versions, allowing graceful fallback- Repairs XGD3 security sectors when custom Kreon firmware is available
- Uses
std::shared_ptrfor proper ownership semantics- Efficiently transfers the security sector via
swap()The protection range insertion for L1 padding at line 307 correctly extends the skip regions beyond capacity for Xbox-specific layer handling.
dvd/dvd_dump.ixx (8)
380-382: LGTM - Protection ranges from skip option.The code properly converts user-specified skip ranges using the templatized
string_to_rangesand inserts them into the protection vector.
384-405: Proper early Kreon unlock and capacity validation.Unlocking the Kreon drive early ensures READ_CAPACITY returns the correct value for Xbox disc detection. The block length validation guards against unsupported disc formats.
443-479: Robust Xbox/Kreon detection and security sector handling.The detection logic correctly identifies Xbox discs when physical layer length differs from READ_CAPACITY. The security sector comparison during refine mode uses cleaned versions to avoid false mismatches from drive-specific variations.
643-657: Sector count determination logic is correct.Based on learnings, this centralized sector count logic is intentionally designed to support multiple sources (READ_CAPACITY, physical structures, and future options like ISO/UDF filesystem size). For Xbox/Kreon XGD discs,
sectors_count_xboxcorrectly takes priority sincexbox::initialize()updates the layer descriptor with the true value from the security sector.
717-718: Verify sector_shift calculation cannot underflow.The calculation
xbox->layer1_video_start - xbox->lock_sector_startassigns the result of subtracting twouint32_tvalues to anint32_t. Iflayer1_video_start < lock_sector_start, this would underflow before the signed conversion.Could you confirm that by design
layer1_video_start >= lock_sector_startis always true for valid Xbox contexts? If not, consider adding a check or using signed arithmetic:- if(kreon_locked) - sector_shift = xbox->layer1_video_start - xbox->lock_sector_start; + if(kreon_locked) + sector_shift = static_cast<int32_t>(xbox->layer1_video_start) - static_cast<int32_t>(xbox->lock_sector_start);
743-781: Protection range skip logic correctly writes zero-filled sectors.When a sector falls within a protection range,
store=trueis set without reading from the drive. Thedrive_datavector remains zero-initialized, which is the correct behavior for skip ranges (e.g., Xbox security sectors that cannot be read normally).
854-860: LGTM - Graceful Kreon drive re-unlock at operation end.The non-throwing error handling for unlock failure is appropriate since the dump data is already complete. Logging the failure allows users to diagnose drive state issues.
840-842: Correct ROM entry update condition.The ROM entry hash is only updated during dump mode when there are no SCSI errors, ensuring hash integrity for clean dumps only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
dvd/xbox.ixx (2)
209-210: Add parentheses for clarity in complex conditional.The operator precedence is technically correct (
&&binds tighter than||), but explicit parentheses would improve readability:- if(xgd_version(layer0_last) == 1 && i >= 16 || xgd_version(layer0_last) != 1 && i != 0 && i != 3) + if((xgd_version(layer0_last) == 1 && i >= 16) || (xgd_version(layer0_last) != 1 && i != 0 && i != 3))
201-217: Consider adding size validation before casting.The cast on line 203 assumes
security_sectorhas at leastsizeof(SecurityLayerDescriptor)bytes. While callers likely ensure this, a defensive check would prevent undefined behavior if called with insufficient data.export void get_security_layer_descriptor_ranges(std::vector<Range<uint32_t>> &protection, const std::vector<uint8_t> &security_sector) { + if(security_sector.size() < sizeof(SecurityLayerDescriptor)) + throw_line("security sector too small: {} < {}", security_sector.size(), sizeof(SecurityLayerDescriptor)); + auto const &sld = (SecurityLayerDescriptor &)security_sector[0];
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
dvd/xbox.ixx(1 hunks)range.ixx(2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: superg
Repo: superg/redumper PR: 302
File: dvd/dvd_dump.ixx:395-405
Timestamp: 2025-11-28T01:02:39.514Z
Learning: In dvd/dvd_dump.ixx, the sector count determination logic (around lines 641-647) is intentionally centralized to support multiple sources: READ_CAPACITY, physical structures, and future options like ISO/UDF filesystem size. For Xbox/Kreon XGD discs, the physical structure sector count is correct to use because xbox::initialize() updates the layer0_ld.layer0_end_sector with the true value from the security sector before sectors_count_physical is calculated.
📚 Learning: 2025-11-28T01:02:39.514Z
Learnt from: superg
Repo: superg/redumper PR: 302
File: dvd/dvd_dump.ixx:395-405
Timestamp: 2025-11-28T01:02:39.514Z
Learning: In dvd/dvd_dump.ixx, the sector count determination logic (around lines 641-647) is intentionally centralized to support multiple sources: READ_CAPACITY, physical structures, and future options like ISO/UDF filesystem size. For Xbox/Kreon XGD discs, the physical structure sector count is correct to use because xbox::initialize() updates the layer0_ld.layer0_end_sector with the true value from the security sector before sectors_count_physical is calculated.
Applied to files:
dvd/xbox.ixx
📚 Learning: 2025-09-07T19:05:32.220Z
Learnt from: superg
Repo: superg/redumper PR: 283
File: scsi/cmd.ixx:558-571
Timestamp: 2025-09-07T19:05:32.220Z
Learning: In the scsi/cmd.ixx file, there are multiple functions that use pointer-byte indexing for endianness conversion that could be prone to endianness issues. The maintainer prefers to address these systematically in a centralized manner rather than piecemeal fixes.
Applied to files:
dvd/xbox.ixx
📚 Learning: 2025-09-07T20:29:35.084Z
Learnt from: superg
Repo: superg/redumper PR: 283
File: scsi/mmc.ixx:853-862
Timestamp: 2025-09-07T20:29:35.084Z
Learning: In scsi/mmc.ixx, the maintainer only adds pragma pack directives to structures when needed, not preemptively. They verify struct layouts work correctly through actual hardware testing rather than relying solely on static assertions.
Applied to files:
dvd/xbox.ixx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: build-macos (arm64)
- GitHub Check: build-macos (x64)
- GitHub Check: build-windows (x86, Win32)
- GitHub Check: build-windows (arm64, ARM64)
- GitHub Check: build-windows (x64, x64)
- GitHub Check: build-linux (x64, ubuntu-24.04)
- GitHub Check: build-linux (x86, ubuntu-24.04)
- GitHub Check: build-linux (arm64, ubuntu-24.04-arm)
🔇 Additional comments (5)
range.ixx (1)
55-84: LGTM!The overlap detection and merging logic is correct. The use of
>=and<=in overlap detection (lines 65, 69) means adjacent ranges are also merged, which is appropriate behavior for protection/skip ranges. The iterator invalidation aftereraseis handled correctly by recalculating frominsertion_index.dvd/xbox.ixx (4)
34-136: Packed union structure looks correct for binary parsing.The struct layout with
#pragma pack(push, 1)is appropriate for interpreting raw security sector data. The hex offset comments align with field names.
230-244: Good use of memcpy for safe unaligned writes.The memcpy approach correctly avoids the strict aliasing and alignment issues that were flagged in a previous review. This is the portable way to write to potentially unaligned offsets within packed structures.
296-314: Verify assumptions about sector ordering for signed arithmetic.The calculations on lines 300 and 313 perform signed subtraction before assigning to unsigned:
l1_padding_length = ss_lba_first - layer0_last - 1layer1_video_start = layer0_last + 1 - lba_firstFor valid XGD data these should always be positive, but if the security sector contains unexpected values (corrupted data, non-Xbox disc misidentified), the signed-to-unsigned conversion could silently produce incorrect large values.
Consider whether defensive checks are warranted:
int32_t l1_padding = ss_lba_first - layer0_last - 1; if(l1_padding < 0) throw_line("invalid security sector: unexpected layer ordering"); uint32_t l1_padding_length = static_cast<uint32_t>(l1_padding);
165-184: LGTM!The error handling strategy is reasonable: fail hard on initial read failure, but tolerate partial reads for subsequent sectors. The return value correctly indicates whether a complete security sector was obtained.
WIP
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.