271. Framebuffer pixel access

Add simple framebuffer pixel access helpers.

Lesson 271 of 356 · tests/chapter_05_rendering_pipeline/test_271_framebuffer_pixel_access.py

File to update

emulator/rendering/framebuffer.py

Why this step exists

The framebuffer now stores a flat list of RGB pixels. Rendering code should not need to repeat the flat-index formula everywhere, so Framebuffer exposes two tiny helpers:

get_pixel(x, y) -> RGBColor
set_pixel(x, y, color) -> None

What is flat pixel indexing? Flat indexing stores 2D image coordinates in a 1D list.

Formula

index = y * width + x

Minimal example with width = 4:

(x=0, y=0) -> index 0
(x=1, y=0) -> index 1
(x=0, y=1) -> index 4
(x=2, y=1) -> index 6

Suggested implementation example

class Framebuffer:
    ...

    def get_pixel(self, x: int, y: int) -> RGBColor:
        return self.pixels[y * self.width + x]

    def set_pixel(self, x: int, y: int, color: RGBColor) -> None:
        self.pixels[y * self.width + x] = color

Important simplification

This tutorial step intentionally keeps the helpers small. In the future, we can add validation for:

x/y out of bounds
negative coordinates
RGB tuple length
RGB component byte range 0-255

For now, tests use valid coordinates and valid RGB colors only.

Out of scope

  • coordinate validation
  • RGB validation
  • palette lookup
  • rendering pattern tables
  • rendering nametables
  • pygame display

Run this lesson

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