285. Manual framebuffer display helpers
Add manual framebuffer display helpers using pygame Surface drawing.
Lesson 285 of 356 · tests/chapter_05_rendering_pipeline/test_285_manual_framebuffer_display_helpers.py
File to create
tools/show_framebuffer.pyWhy this step exists
The emulator core now produces pure Framebuffer data. Before building a full frontend, we want a small manual tool that can draw a Framebuffer with pygame for visual smoke checks.
Important boundary
This file lives under tools/ because pygame is a frontend/manual-display concern.
Core emulator modules must not import pygame
emulator/rendering/framebuffer.py
emulator/rendering/nametable_renderer.py
emulator/rendering/ppu_background_renderer.py
emulator/console.pyWhat is a pygame Surface? A Surface is a drawable pixel buffer managed by pygame. A window created by pygame.display.set_mode(...) is also a Surface.
Minimal example
surface.fill((255, 0, 0), pygame.Rect(0, 0, 10, 10))This fills a 10x10 rectangle with red.
How draw_framebuffer works:
Framebuffer pixel (x, y)
-> RGB color
-> pygame Rect(x * scale, y * scale, scale, scale)
-> surface.fill(color, rect)Suggested implementation example
import pygame
from emulator.rendering.framebuffer import Framebuffer
def make_checkerboard_framebuffer(width: int = 64, height: int = 64) -> Framebuffer:
framebuffer = Framebuffer(width=width, height=height)
for y in range(height):
for x in range(width):
block_x = x // 8
block_y = y // 8
if (block_x + block_y) % 2 == 0:
framebuffer.set_pixel(x, y, (255, 255, 255))
else:
framebuffer.set_pixel(x, y, (40, 40, 40))
return framebuffer
def draw_framebuffer(
surface: pygame.Surface,
framebuffer: Framebuffer,
scale: int,
) -> None:
for y in range(framebuffer.height):
for x in range(framebuffer.width):
color = framebuffer.get_pixel(x, y)
rect = pygame.Rect(
x * scale,
y * scale,
scale,
scale,
)
surface.fill(color, rect)Testing policy
This test does not open a real pygame window. It uses an off-screen pygame Surface to verify the drawing helper. The window/main-loop step is separate.
Out of scope
- pygame main loop
- pygame.display.set_mode
- event handling
- displaying ROM output
- controller input
- sprites
Run this lesson
uv run pytest tests/chapter_05_rendering_pipeline/test_285_manual_framebuffer_display_helpers.py -v