287. Console avanza hasta el siguiente fotograma
Añadir Console.step_until_next_frame() para el avance a nivel de fotograma.
Lección 287 de 356 · tests/chapter_05_rendering_pipeline/test_287_console_step_until_next_frame.py
Archivo a actualizar
emulator/console.pyPor qué existe este paso
Console ya tiene un método de avance de una instrucción
console.step()Esa es la operación de tiempo de máquina más pequeña de este emulador. Ejecuta una instrucción de CPU, avanza la PPU en ciclos de CPU * 3 y luego consume cualquier NMI pendiente.
Los ejecutores manuales y los futuros frontends normalmente necesitan una operación más grande
run emulation until one full PPU frame completes
then ask for a framebuffer explicitlyEste paso añade
console.step_until_next_frame(max_cpu_instructions: int | None = None) -> intEjemplo de implementación
def step_until_next_frame(
self,
max_cpu_instructions: int | None = None,
) -> int:
start_frame = self.ppu.frame
executed = 0
while self.ppu.frame == start_frame:
if max_cpu_instructions is not None:
if executed >= max_cpu_instructions:
raise RuntimeError("Frame did not complete before instruction limit")
self.step()
executed += 1
return executedDiferencia entre step() y step_until_next_frame():
step()
executes exactly one CPU instruction
advances PPU by that instruction's cycles * 3
returns CPU cycles for that instruction
step_until_next_frame()
calls step() repeatedly until ppu.frame changes
returns how many CPU instructions were executedEjemplo de uso
console.step_until_next_frame()
framebuffer = console.render_background_framebuffer()Por qué max_cpu_instructions es opcional: este parámetro no es comportamiento de hardware del NES. Es una salvaguarda de depuración/testing del emulador.
Con None, no hay límite artificial de instrucciones. Esto es útil para la ejecución real o manual:
console.step_until_next_frame()Con un entero, el ayudante lanza una excepción si se ejecutan esa cantidad de instrucciones de CPU sin que se complete un nuevo fotograma. Esto es útil para tests y depuración porque evita bucles infinitos si la CPU se atasca, falta un opcode o un fotograma nunca se completa:
console.step_until_next_frame(max_cpu_instructions=10)Separación importante
step_until_next_frame()
advances emulation time
render_background_framebuffer()
observes current PPU memory and returns Framebuffer dataNo renderices automáticamente dentro de step_until_next_frame().
Fuera de alcance
- visualización con pygame
- sprites
- OAMDMA
- latencia exacta de NMI
- penalizaciones dinámicas de ciclos de CPU
- entrada del mando
Ejecutar esta lección
uv run pytest tests/chapter_05_rendering_pipeline/test_287_console_step_until_next_frame.py -v