272. Cuadrícula de índices de color a framebuffer

Convertir cuadrículas de índices de color en datos RGB de framebuffer.

Lección 272 de 356 · tests/chapter_05_rendering_pipeline/test_272_color_index_grid_to_framebuffer.py

Archivo a crear

emulator/rendering/color_index_renderer.py

Por qué existe este paso

Los ayudantes anteriores de PPU/CHR producen índices de color, no píxeles RGB. Por ejemplo, decode_chr_tile() produce valores como:

0, 1, 2, 3

Esos valores son índices de paleta. Todavía no son colores directamente visualizables.

Este paso crea un ayudante de renderizado puro que asigna

color-index grid + RGB palette -> Framebuffer

¿Qué es una cuadrícula de índices de color? Una cuadrícula de índices de color es una cuadrícula 2D donde cada número apunta a una paleta.

Ejemplo mínimo

grid = [
    [0, 1, 1, 0, ...],
    [2, 3, 3, 0, ...],
    ...
]

palette = [
    (0, 0, 0),
    (85, 85, 85),
    (170, 170, 170),
    (255, 255, 255),
]

Píxeles de framebuffer esperados

(x=0, y=0) -> palette[0] -> (0, 0, 0)
(x=1, y=0) -> palette[1] -> (85, 85, 85)
(x=0, y=1) -> palette[2] -> (170, 170, 170)
(x=1, y=1) -> palette[3] -> (255, 255, 255)

Ejemplo de implementación sugerida

from emulator.rendering.framebuffer import Framebuffer, RGBColor

Grid = list[list[int]]


def color_index_grid_to_framebuffer(
    grid: Grid,
    palette: list[RGBColor],
) -> Framebuffer:
    height = len(grid)
    width = len(grid[0])

    framebuffer = Framebuffer(width=width, height=height)

    for y, row in enumerate(grid):
        for x, color_index in enumerate(row):
            framebuffer.set_pixel(x, y, palette[color_index])

    return framebuffer

Simplificación importante

Por ahora, asume una entrada válida

grid is not empty
grid is rectangular
palette contains every used index
color indexes are valid

Se pueden añadir validaciones futuras más adelante si esto se convierte en un problema de depuración.

Regla de arquitectura

Este ayudante es una transformación de datos pura. No debería importar pygame, CPU, temporización de PPU, carga de ROM ni código de frontend.

Fuera de alcance

  • búsqueda en memoria de paleta de la NES
  • renderizado directo de tiles CHR
  • renderizado directo de tablas de patrones
  • renderizado de nametables/fondos
  • pantalla de pygame

Ejecutar esta lección

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