273. Pattern table to framebuffer

Render a pattern table debug grid into a framebuffer.

Lesson 273 of 356 · tests/chapter_05_rendering_pipeline/test_273_pattern_table_to_framebuffer.py

File to create

emulator/rendering/pattern_table_renderer.py

Why this step exists

The emulator already has pure CHR helpers

decode_pattern_table(pattern_table_bytes)
    -> 256 decoded 8x8 tiles of color indexes

build_pattern_table_debug_grid(decoded_tiles)
    -> 128x128 color-index debug grid

And the rendering pipeline now has

color_index_grid_to_framebuffer(grid, palette)
    -> RGB Framebuffer

This step composes those pieces into one pure helper

pattern_table bytes + RGB palette -> 128x128 Framebuffer

What is a pattern table debug framebuffer? A pattern table contains 256 tiles. Each tile is 8x8 pixels. For debugging, we arrange those tiles as:

16 tiles across * 8 pixels = 128 pixels wide
16 tiles down   * 8 pixels = 128 pixels high

Suggested implementation example

from emulator.ppu.chr_decoder import (
    build_pattern_table_debug_grid,
    decode_pattern_table,
)
from emulator.rendering.color_index_renderer import color_index_grid_to_framebuffer
from emulator.rendering.framebuffer import Framebuffer, RGBColor


def pattern_table_to_framebuffer(
    pattern_table_bytes: bytes,
    palette: list[RGBColor],
) -> Framebuffer:
    decoded_tiles = decode_pattern_table(pattern_table_bytes)
    grid = build_pattern_table_debug_grid(decoded_tiles)
    return color_index_grid_to_framebuffer(grid, palette)

Architecture rule

This renderer should compose existing pure functions. Do not duplicate CHR decode logic here.

Important fixture rule

Use synthetic CHR bytes only. Do not use commercial ROM CHR data in this test.

Out of scope

  • pygame display
  • writing image files
  • nametable rendering
  • palette RAM lookup
  • sprite rendering

Run this lesson

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