NES TDD

272. Сетка индексов цвета во фреймбуфер

Преобразование сеток индексов цвета в RGB-данные фреймбуфера.

Урок 272 из 356 · tests/chapter_05_rendering_pipeline/test_272_color_index_grid_to_framebuffer.py

Файл для создания

emulator/rendering/color_index_renderer.py

Почему этот шаг важен

Ранее написанные вспомогательные функции PPU/CHR выдают индексы цвета, а не RGB-пиксели. Например, decode_chr_tile() выдаёт значения вида:

0, 1, 2, 3

Эти значения — индексы палитры. Пока это ещё не отображаемые напрямую цвета.

Этот шаг создаёт чистую вспомогательную функцию рендеринга, которая отображает

color-index grid + RGB palette -> Framebuffer

Что такое сетка индексов цвета? Сетка индексов цвета — это 2D-сетка, где каждое число указывает на элемент палитры.

Минимальный пример

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

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

Ожидаемые пиксели фреймбуфера

(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)

Пример возможной реализации

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

Важное упрощение

Пока считаем входные данные корректными

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

Дополнительные проверки можно добавить позже, если это станет проблемой при отладке.

Архитектурное правило

Эта вспомогательная функция выполняет чистое преобразование данных. Она не должна импортировать pygame, CPU, тайминг PPU, загрузку ROM или код фронтенда.

Вне рамок этого шага

  • поиск в памяти палитры NES
  • прямой рендеринг тайлов CHR
  • прямой рендеринг таблиц шаблонов
  • рендеринг таблиц имён/фонов
  • отображение через pygame

Запустить этот урок

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