Skip to content

feat(frontend): wire the View -> Hide Overscan toggle#115

Merged
doublegate merged 3 commits into
mainfrom
feat/v1.20.0-overscan-toggle
Jul 15, 2026
Merged

feat(frontend): wire the View -> Hide Overscan toggle#115
doublegate merged 3 commits into
mainfrom
feat/v1.20.0-overscan-toggle

Conversation

@doublegate

Copy link
Copy Markdown
Owner

Summary

Phase A.3 of the new UI/UX-parity plan (RustySNES ↔ RustyNES).

  • View → Hide Overscan crops the trailing "overscan" scanlines a real 4:3 CRT wouldn't reliably
    show. The SNES's own SETINI register (rustysnes_ppu) already distinguishes the standard
    224-line display from a game-opted-in 239-line extension; app.rs's new crop_overscan crops
    exactly that extra 15-line extension back off.
  • Applied once per frame at the point where both the synchronous and emu-thread render paths
    converge on the bytes actually being presented — after HD-pack compositing, run-ahead, and the
    PresentBuffer handoff have all already run, so it covers both build variants correctly.
  • Crops a fraction (15/239) of the current height rather than a fixed pixel count, so it
    stays exact under an HD-pack integer upscale too (239 * scale * 15 / 239 reduces to exactly
    15 * scale, no rounding).
  • Presentation-only (never touches the deterministic core), additive, false by default —
    byte-identical to every prior release when unchanged.

Test plan

  • cargo test --workspace --exclude rustysnes-android — all green, including 3 new real unit
    tests (native resolution, HD-pack-scaled resolution, kept-bytes-untouched)
  • cargo clippy --workspace --exclude rustysnes-android --all-targets -- -D warnings — clean
  • cargo clippy -p rustysnes-frontend --features full -- -D warnings — clean
  • cargo clippy -p rustysnes-frontend --no-default-features --features wasm-winit,emu-thread — clean
  • cargo clippy -p rustysnes-frontend --target wasm32-unknown-unknown --features wasm-winit -- -D warnings — clean (only a known, pre-existing, unrelated save_states.rs finding remains, confirmed present on a clean origin/main checkout too)
  • cargo fmt --check — clean
  • RUSTDOCFLAGS="-D warnings" cargo doc --workspace --exclude rustysnes-android --no-deps — clean

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings July 15, 2026 04:49

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request implements the 'Hide Overscan' feature to crop the trailing 15 scanlines of the SNES's extended 239-line display back to 224 lines on the presentation side, including configuration options, UI integration, documentation, and unit tests. The reviewer identified a state desynchronization bug where capturing overscan_active before emulation runs can cause visual glitches during resolution transitions. To resolve this, the reviewer suggested checking dims.1 % 239 == 0 directly at the presentation site and provided code suggestions to update the check and its documentation.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/rustysnes-frontend/src/app.rs Outdated
Comment thread crates/rustysnes-frontend/src/app.rs Outdated
Comment thread crates/rustysnes-frontend/src/app.rs Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR implements the frontend wiring for View → Hide Overscan, a presentation-only option that crops the SNES 239-line “overscan” mode down to 224 lines at the point where framebuffer bytes are finalized for display (covering both synchronous and emu-thread render paths).

Changes:

  • Add video.hide_overscan to the frontend config (default false) and expose it in the View menu UI.
  • Apply overscan cropping during the final present-path framebuffer handling via a new crop_overscan helper and add unit tests for native + HD-pack-scaled cases.
  • Document the feature in docs/frontend.md and add an Unreleased changelog entry.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
docs/frontend.md Documents the new View → Hide Overscan behavior and its determinism boundary.
crates/rustysnes-frontend/src/ui_shell.rs Adds the View menu checkbox that toggles cfg.video.hide_overscan.
crates/rustysnes-frontend/src/config.rs Introduces VideoConfig::hide_overscan with docs and default false.
crates/rustysnes-frontend/src/app.rs Implements the crop and wires it into the present path; adds unit tests.
CHANGELOG.md Adds an Unreleased entry describing the new overscan-crop toggle.

Comment thread crates/rustysnes-frontend/src/app.rs Outdated
doublegate and others added 3 commits July 15, 2026 02:23
Crops the trailing "overscan" scanlines a real 4:3 CRT wouldn't
reliably show. SETINI (rustysnes_ppu) already distinguishes the
standard 224-line display from a game-opted-in 239-line extension;
crop_overscan crops exactly that extra 15-line extension back off,
once per frame, at the point where both the synchronous and
emu-thread render paths converge on the bytes actually being
presented - after HD-pack compositing, run-ahead, and the
PresentBuffer handoff have all already run.

Crops a fraction (15/239) of the current height rather than a fixed
pixel count, so it stays exact under an HD-pack integer upscale too.
Presentation-only, additive, false by default. 3 real unit tests.

Phase A.3 of the new UI/UX-parity ladder.
emu.fb_dims() was read before run-ahead/HD-pack/the emu-thread
PresentBuffer handoff settle on the actual presented (fb, dims), so a
resolution switch mid-frame could desync the two, cropping a 224-line
frame or skipping the crop on a 239-line one. Check dims.1 % 239 == 0
against the finalized dims at the crop site instead (found in review:
gemini-code-assist and Copilot both independently flagged this).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CI's --features emu-thread lint job (a combination not covered by
--features full, which excludes emu-thread) flagged
clippy::manual_is_multiple_of on the dims.1 % 239 == 0 overscan check.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@doublegate
doublegate force-pushed the feat/v1.20.0-overscan-toggle branch from db56724 to 3a58070 Compare July 15, 2026 06:25
@doublegate
doublegate merged commit 498c15d into main Jul 15, 2026
26 checks passed
@doublegate
doublegate deleted the feat/v1.20.0-overscan-toggle branch July 15, 2026 06:38
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