Skip to content

Implement raw DVD split and descramble#346

Merged
superg merged 8 commits intosuperg:mainfrom
Deterous:dvd-descramble
Feb 15, 2026
Merged

Implement raw DVD split and descramble#346
superg merged 8 commits intosuperg:mainfrom
Deterous:dvd-descramble

Conversation

@Deterous
Copy link
Contributor

@Deterous Deterous commented Feb 9, 2026

Summary by CodeRabbit

  • New Features

    • Integrated descrambling and ISO extraction into the DVD split workflow.
  • Improvements

    • Improved type safety for zone identification in DVD structures.
    • Refined Xbox metadata extraction with stricter size validation, overwrite handling, and clearer warnings.
    • Enhanced logging and error reporting during split and extraction, including detailed reporting for descrambling and I/O issues.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Added exported ZoneType and changed DataFrame.id.zone_type to it; extended DVD split workflow with extract_iso (per-frame descrambling), refined handling for .manufacturer.dmi, .physical.pfi, and .security.ss including size/overwrite checks and logging.

Changes

Cohort / File(s) Summary
Type System Change
dvd/dvd.ixx
Added export enum class ZoneType : uint8_t (DATA_ZONE, LEADIN_ZONE, LEADOUT_ZONE, MIDDLE_ZONE). Updated DataFrame.id.zone_type from uint8_t to ZoneType.
Split Workflow & Descrambling
dvd/dvd_split.ixx
Added imports (dvd.scrambler, scsi.cmd); reworked generate_extra_xbox control flow and file handling for .manufacturer.dmi, .physical.pfi, .security.ss with size validation, header stripping, overwrite warnings; added void extract_iso(Context &ctx, Options &options) to read .sdram/.state, descramble per-frame data using DVD_Scrambler, write .iso, and integrated it into redumper_split_dvd.

Sequence Diagram

sequenceDiagram
    participant Tool as Tool
    participant FS as FileSystem
    participant Scrambler as DVD_Scrambler
    participant Logger as Logger

    Tool->>FS: open `.sdram` / `.state` (read)
    FS-->>Tool: file handle + size
    Tool->>FS: check `.iso` existence & overwrite policy
    alt `.iso` exists and no overwrite
        Tool->>Logger: warn and abort
    else
        Tool->>Scrambler: init (start LBA)
        loop per-frame
            Tool->>FS: read frame bytes
            FS-->>Tool: frame bytes
            Tool->>Scrambler: descramble frame
            Scrambler-->>Tool: main data portion / status
            Tool->>FS: write main data to `.iso`
            Tool->>Logger: log progress / errors
        end
        Tool->>FS: close `.iso`
        Tool->>Logger: log completion
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I found new zones and hopped through bits,
I pulled out headers, unrolled scrambled skits.
Frames untangle, ISO grows bright —
Tiny paws, big bytes, into the night.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly matches the main changes: implementing raw DVD split and descramble functionality by adding ZoneType enum, updating DataFrame structure, implementing extract_iso function for descrambling, and integrating descrambling into the split workflow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Deterous
Copy link
Contributor Author

Deterous commented Feb 9, 2026

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@dvd/dvd_split.ixx`:
- Around line 139-143: The existing check around iso_path unconditionally logs
and returns when the .iso exists, ignoring options.overwrite; update the logic
in dvd_split.ixx to mirror generate_extra_xbox behavior by respecting
options.overwrite: when std::filesystem::exists(iso_path) evaluate
options.overwrite and either remove/replace the file (or allow continuing) if
options.overwrite is true, otherwise log the warning referencing
options.image_name and return; ensure you reference iso_path, options.overwrite
and options.image_name so the overwrite behavior is consistent with
generate_extra_xbox.
- Around line 157-171: The loop variable psn is being incremented twice (once by
the for loop ++psn and again by the psn += 1 at the end), causing every other
sector to be skipped; remove the redundant psn += 1 statement so the
for(uint32_t psn = -DVD_LBA_START;; ++psn) loop alone controls iteration,
leaving the body (including sdram_fs.read, RecordingFrame_to_DataFrame,
scrambler.descramble and iso_fs.write) unchanged.
- Line 163: The call uses a C-style cast of the std::vector object (rf) to
RecordingFrame&, which reads garbage; instead take a reference to the struct
stored inside the vector's data (e.g., reinterpret_cast a reference or pointer
to the first byte of rf) and pass that to RecordingFrame_to_DataFrame, and
ensure rf.size() >= sizeof(RecordingFrame) before casting. Update the call site
(RecordingFrame_to_DataFrame and rf) to use a memory-based cast (e.g.,
reinterpret_cast to RecordingFrame& from &rf[0] or from rf.data()) and add a
size check to avoid out-of-bounds access.
🧹 Nitpick comments (1)
dvd/dvd_split.ixx (1)

146-151: Nit: key is always std::nullopt — consider a TODO or comment clarifying future intent.

key is declared but never assigned a value. If this is a placeholder for future CSS/CPRM key support, a brief comment would help readers understand the intent.

Copy link
Owner

@superg superg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fundamentally it's good, but one thing is missing: .state handling. If we encounter .state errors, we shouldn't split.
I suggest with each sector that you read from sdram (in the loop), also read state byte and check if it's good (you cannot pre-read everything before as you don't know where it ends). If state byte is bad, throw.

@Deterous
Copy link
Contributor Author

Deterous commented Feb 11, 2026

If state byte is bad, throw.

How do I tell the difference between a SCSI error and an intentionally skipped sector when splitting DVD? I don't want to throw on skipped sectors. Unless you think that skipped sectors should require --force-split ?

@superg
Copy link
Owner

superg commented Feb 11, 2026

If state byte is bad, throw.

How do I tell the difference between a SCSI error and an intentionally skipped sector when splitting DVD? I don't want to throw on skipped sectors. Unless you think that skipped sectors should require --force-split ?

In CD this is done by passing a protection range from a previous command. Based on a state you can't tell if that's intentionally skipped error or not, Let's focus on a generic DVD raw split, we will add protection later.

@Deterous Deterous marked this pull request as ready for review February 12, 2026 01:43
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@dvd/dvd_split.ixx`:
- Line 6: Remove the unused `#include` <numeric> from dvd_split.ixx; locate the
include directive (the line containing "<numeric>") and delete it so the file no
longer pulls in the numeric header since no std::accumulate/std::iota/etc. are
used in the compilation unit.
🧹 Nitpick comments (2)
dvd/dvd_split.ixx (2)

46-49: Minor: Inconsistent log message format compared to other overwrite warnings.

Line 48 uses dmi_path.filename().string() while the equivalent warnings for .pfi (line 77), .ss (line 103), and .iso (line 137) use options.image_name with a hardcoded extension. Consider aligning for consistency.

Suggested fix
-            LOG("warning: file already exists ({})", dmi_path.filename().string());
+            LOG("warning: file already exists ({}.dmi)", options.image_name);

168-180: No progress feedback for a potentially long-running operation.

For a full DVD (~2.2M sectors), this loop runs silently with no progress indication. Other dump/split functions in the codebase typically log progress periodically. Consider adding a progress counter or percentage log at an appropriate interval to avoid appearing hung.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@dvd/dvd_split.ixx`:
- Line 156: Remove the unused local variable bytes_read declared in extract_iso
(it's never assigned or read); either delete the bytes_read declaration from the
extract_iso function or, if the intention was to track read bytes, replace
usages where read counts are ignored with assignments to bytes_read and then use
it for validating reads or loop termination—locate the declaration of bytes_read
in extract_iso and remove or repurpose it accordingly.
🧹 Nitpick comments (1)
dvd/dvd_split.ixx (1)

136-136: Inconsistent log message format.

Other "file already exists" warnings use path.filename().string() (lines 47, 76, 102), but this one manually constructs the filename with a format string. For consistency:

Suggested fix
-        LOG("warning: file already exists ({}.iso)", options.image_name);
+        LOG("warning: file already exists ({})", iso_path.filename().string());

@Deterous
Copy link
Contributor Author

I've made the requested changes you wanted, PR is now complete and ready for review and merging.

Comment on lines +143 to +145
uint64_t sdram_size = std::filesystem::file_size(sdram_path);
if(sdram_size % sizeof(RecordingFrame) != 0)
throw_line("unexpected file size ({})", sdram_path.filename().string());
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: let's move this block above std::fstream sdram_fs (we can check size before opening the file as it's faster check).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

if(sdram_fs.fail())
throw_line("seek failed");

for(uint32_t sector_count = sdram_size / sizeof(RecordingFrame); psn < sector_count; ++psn)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given removal of previous code block it can now be:
for(uint32_t lba = -DVD_LBA_START; lba < sdram_size / sizeof(RecordingFrame); ++lba)

@superg superg merged commit 771bb6b into superg:main Feb 15, 2026
11 checks passed
@Deterous Deterous deleted the dvd-descramble branch February 16, 2026 01:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants