336. Console uses background viewport
Integrate the horizontal framebuffer and opacity-mask viewports into Console.
Lesson 336 of 356 · tests/chapter_13_scrolling/test_336_console_uses_background_viewport.py
File to update
emulator/console.pyWhy this step exists
Steps 334 and 335 produce viewport-aware background data from current PPU scroll state. This step assembles those new functions inside Console so the full-frame path uses both the scrolled framebuffer and its matching opacity mask.
What changes
Console.render_background_framebuffer()
-> keeps the older fixed-background behavior
Console.render_framebuffer()
-> uses ppu_background_viewport_to_framebuffer(self.ppu)
-> uses the new viewport opacity mask through a compatibility alias
-> passes both new results to the existing sprite compositorWhy use an alias for the mask? Earlier lessons already use the name ppu_background_to_opaque_mask inside Console. Importing the new viewport-mask function under that name lets the full-frame path use the new behavior without breaking compatibility with those earlier lessons.
Temporary Super Mario Bros. limitation: Do not worry if it is not scrolling as expected yet. This step uses only one scroll position for the whole frame. Super Mario Bros. uses one position for the fixed status bar and another for the moving gameplay area during the same frame. The game can therefore still show a stationary background, a moving status bar, or other incorrect scrolling after this test passes. That is expected. Future steps will record the scroll changes and render the status bar and gameplay as separate horizontal bands.
Out of scope
- changing sprite-zero-hit scheduling
- tracing $2005 writes
- split-screen band rendering
- vertical pixel scrolling
- pygame
Complete example implementation
# emulator/console.py
from emulator.rendering.ppu_background_renderer import (
ppu_background_to_framebuffer,
# --- NEW LINE: FULL-FRAME RENDERING USES THE VIEWPORT ADAPTER ---
ppu_background_viewport_to_framebuffer,
# --- UPDATED LINE: USE THE NEW MASK WITH THE EXISTING CONSOLE NAME ---
ppu_background_viewport_to_opaque_mask as ppu_background_to_opaque_mask,
PATTERN_TABLE_0_ADDR,
PATTERN_TABLE_1_ADDR,
)
...
def render_background_framebuffer(self) -> Framebuffer:
# Keep the older background-only behavior for compatibility.
return ppu_background_to_framebuffer(self.ppu)
def render_framebuffer(self) -> Framebuffer:
# --- UPDATED LINE: FULL-FRAME OUTPUT USES THE VIEWPORT FRAMEBUFFER ---
background = ppu_background_viewport_to_framebuffer(self.ppu)
# The existing name now refers to the new viewport-mask function.
background_opaque_mask = ppu_background_to_opaque_mask(self.ppu)
...
# Everything remains the same below this point.Run this lesson
uv run pytest tests/chapter_13_scrolling/test_336_console_uses_background_viewport.py -v