334. Viewport de fondo de la PPU a framebuffer

Compone el framebuffer de fondo horizontal a partir del estado de desplazamiento actual de la PPU.

Lección 334 de 356 · tests/chapter_13_scrolling/test_334_ppu_background_viewport_to_framebuffer.py

Archivo a actualizar

emulator/rendering/ppu_background_renderer.py

Referencias

https://www.nesdev.org/wiki/PPU_scrolling
https://www.nesdev.org/wiki/PPU_nametables

Por qué existe este paso

Los pasos anteriores pueden renderizar un nametable lógico seleccionado y componer dos framebuffers existentes. Este adaptador conecta esos mecanismos con el estado de desplazamiento actual de la PPU.

Flujo horizontal

temp_vram_addr + fine_x
          |
          v
    decode viewport X
          |
          v
select horizontal logical pair
          |
          v
render left and right nametables
          |
          v
compose one 256x240 framebuffer

Selección del par lógico

nametable Y = 0 -> left $2000, right $2400
nametable Y = 1 -> left $2800, right $2C00

Nametable X sigue formando parte del viewport X decodificado. Por ejemplo, nametable X=1, coarse X=5 y fine X=3 producen el viewport X 299.

Compatibilidad

La función existente ppu_background_to_framebuffer() sigue renderizando un nametable seleccionado. Este nuevo adaptador la llama dos veces y después compone los resultados.

Fuera del alcance

  • composición de la máscara de opacidad
  • integración en Console
  • integración del sprite-zero-hit
  • desplazamiento vertical por píxeles
  • pygame

Implementación de ejemplo completa

# emulator/rendering/ppu_background_renderer.py

# --- NEW LINES: HORIZONTAL VIEWPORT OPERATIONS ---
from emulator.rendering.background_viewport import (
    compose_horizontal_framebuffer_viewport,
    compose_horizontal_opaque_mask_viewport,
    decode_background_viewport_position,
)

...

# --- NEW BLOCK: COMPOSE THE HORIZONTAL FRAMEBUFFER VIEWPORT ---
def ppu_background_viewport_to_framebuffer(ppu: PPU) -> Framebuffer:
    viewport_x, _ = decode_background_viewport_position(
        temp_vram_addr=ppu.temp_vram_addr,
        fine_x=ppu.fine_x,
    )

    nametable_y = (ppu.temp_vram_addr >> 11) & 1
    left_base = BASE_NAMETABLE_ADDR + nametable_y * 0x0800
    right_base = left_base + 0x0400

    left = ppu_background_to_framebuffer(
        ppu,
        base_nametable_addr=left_base,
    )
    right = ppu_background_to_framebuffer(
        ppu,
        base_nametable_addr=right_base,
    )

    return compose_horizontal_framebuffer_viewport(
        left=left,
        right=right,
        viewport_x=viewport_x,
    )

Ejecutar esta lección

uv run pytest tests/chapter_13_scrolling/test_334_ppu_background_viewport_to_framebuffer.py -v