313. De fondo de la PPU a máscara de opacidad

Construye una máscara de opacidad de fondo a partir de la memoria de fondo actual de la PPU.

Lección 313 de 356 · tests/chapter_09_sprite_rendering/test_313_ppu_background_to_opaque_mask.py

Archivo a actualizar

emulator/rendering/ppu_background_renderer.py

Por qué existe este paso

El paso 310 añadió el ayudante puro

build_background_opaque_mask(pattern_table, nametable)

Ese ayudante trabaja a partir de bytes en bruto. Este paso añade el equivalente a nivel de PPU de:

ppu_background_to_framebuffer(ppu)

El nuevo ayudante debería ser

ppu_background_to_opaque_mask(ppu)

Es muy similar a ppu_background_to_framebuffer(), pero necesita menos información.

ppu_background_to_framebuffer() necesita:

  • bytes visibles de la tabla de nombres
  • bytes de la tabla de atributos
  • bytes de la tabla de patrones de fondo seleccionada
  • bytes de la RAM de paletas

porque produce píxeles RGB.

ppu_background_to_opaque_mask() solo necesita:

  • bytes visibles de la tabla de nombres
  • bytes de la tabla de patrones de fondo seleccionada

porque la opacidad depende únicamente de:

CHR color index != 0

La tabla de atributos y la RAM de paletas no afectan a la opacidad.

Implementación de ejemplo

def ppu_background_to_opaque_mask(ppu: PPU) -> BackgroundOpaqueMask:
    nametable_bytes = bytes(
        ppu.ppu_bus.read(BASE_NAMETABLE_ADDR + offset)
        for offset in range(NAMETABLE_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)
    )

    return build_background_opaque_mask(
        pattern_table=pattern_table_bytes,
        nametable=nametable_bytes,
    )

Importante

Este paso todavía no modifica Console.render_framebuffer(). El siguiente paso conectará Console para que llame a este ayudante y pase la máscara al compositor.

Fuera de alcance

  • cambiar emulator/console.py
  • pasar la máscara a composite_background_and_sprites()
  • sprite 0 hit
  • desbordamiento de sprites
  • pygame

Ejecutar esta lección

uv run pytest tests/chapter_09_sprite_rendering/test_313_ppu_background_to_opaque_mask.py -v