285. Ayudantes manuales de visualización de framebuffer

Añadir ayudantes manuales de visualización de framebuffer usando el dibujo de Surface de pygame.

Lección 285 de 356 · tests/chapter_05_rendering_pipeline/test_285_manual_framebuffer_display_helpers.py

Archivo a crear

tools/show_framebuffer.py

Por qué existe este paso

El núcleo del emulador ahora produce datos de Framebuffer puros. Antes de construir un frontend completo, queremos una pequeña herramienta manual que pueda dibujar un Framebuffer con pygame para comprobaciones visuales rápidas (smoke checks).

Límite importante

Este archivo vive bajo tools/ porque pygame es una preocupación de frontend/visualización manual.

Los módulos del núcleo del emulador no deben importar pygame

emulator/rendering/framebuffer.py
emulator/rendering/nametable_renderer.py
emulator/rendering/ppu_background_renderer.py
emulator/console.py

¿Qué es una Surface de pygame? Una Surface es un búfer de píxeles dibujable gestionado por pygame. Una ventana creada con pygame.display.set_mode(...) también es una Surface.

Ejemplo mínimo

surface.fill((255, 0, 0), pygame.Rect(0, 0, 10, 10))

Esto rellena un rectángulo de 10x10 con rojo.

Cómo funciona draw_framebuffer:

Framebuffer pixel (x, y)
    -> RGB color
    -> pygame Rect(x * scale, y * scale, scale, scale)
    -> surface.fill(color, rect)

Ejemplo de implementación sugerida

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)

Política de testing

Este test no abre una ventana real de pygame. Usa una Surface de pygame fuera de pantalla para verificar el ayudante de dibujo. El paso de ventana/bucle principal es independiente.

Fuera de alcance

  • bucle principal de pygame
  • pygame.display.set_mode
  • gestión de eventos
  • mostrar la salida de la ROM
  • entrada del mando
  • sprites

Ejecutar esta lección

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