282. Fondo de la ppu al framebuffer

Renderizar la memoria de fondo actual de la PPU en un framebuffer.

Lección 282 de 356 · tests/chapter_05_rendering_pipeline/test_282_ppu_background_to_framebuffer.py

Archivo a crear

emulator/rendering/ppu_background_renderer.py

Por qué existe este paso

El renderizador ahora puede producir un framebuffer de fondo a partir de arreglos de bytes explícitos:

nametable bytes
attribute table bytes
pattern table bytes
palette RAM bytes

Pero el estado actual del emulador guarda esos bytes detrás de la interfaz de memoria PPU/PpuBus. Este paso crea un pequeño ayudante de extracción:

ppu_background_to_framebuffer(ppu)

Lee las regiones de memoria de la PPU relevantes y luego delega en el renderizador puro.

Regiones de memoria usadas en este renderizador simplificado

$2000-$23BF -> visible nametable tile IDs, 960 bytes
$23C0-$23FF -> attribute table, 64 bytes
$0000-$0FFF -> pattern table 0, if PPUCTRL bit 4 is clear
$1000-$1FFF -> pattern table 1, if PPUCTRL bit 4 is set
$3F00-$3F0F -> background palette RAM, 16 bytes

Ejemplo de implementación sugerida

def ppu_background_to_framebuffer(ppu: PPU) -> Framebuffer:
    nametable_bytes = bytes(
        ppu.ppu_bus.read(BASE_NAMETABLE_ADDR + offset)
        for offset in range(NAMETABLE_SIZE)
    )

    attribute_table = bytes(
        ppu.ppu_bus.read(BASE_ATTR_TABLE_ADDR + offset)
        for offset in range(ATTR_TABLE_SIZE)
    )

    pattern_table_base = (
        PATTERN_TABLE_1_ADDR
        if ppu.ctrl & CTRL_BACKGROUND_PATTERN_TABLE
        else PATTERN_TABLE_0_ADDR
    )

    pattern_table_bytes = bytes(
        ppu.ppu_bus.read(pattern_table_base + offset)
        for offset in range(PATTERN_TABLE_SIZE)
    )

    palette_ram = bytes(
        ppu.ppu_bus.read(PALETTE_RAM_ADDR + offset)
        for offset in range(PALETTE_RAM_SIZE)
    )

    return nametable_with_palette_ram_to_framebuffer(
        nametable_bytes,
        attribute_table,
        pattern_table_bytes,
        palette_ram,
    )

Regla de arquitectura

Este ayudante extrae datos de la memoria de la PPU. No debe duplicar la lógica de renderizado de la tabla de nombres, los atributos, el CHR ni la paleta.

Simplificación importante

Esto renderiza solo la tabla de nombres base en $2000. Todavía no aplica el scroll ni los bits de selección de tabla de nombres de PPUCTRL.

Fuera de alcance

  • scroll
  • selección de tabla de nombres base de PPUCTRL
  • sprites
  • OAMDMA
  • visualización con pygame
  • bucle de fotogramas completo

Ejecutar esta lección

uv run pytest tests/chapter_05_rendering_pipeline/test_282_ppu_background_to_framebuffer.py -v