323. Console programa el sprite zero hit por frame
Programar el sprite 0 hit automáticamente cuando Console avanza un frame.
Lección 323 de 356 · tests/chapter_11_sprite_zero_hit/test_323_console_schedules_sprite_zero_hit_per_frame.py
Archivo a actualizar
emulator/console.pyPor qué existe este paso
Los pasos anteriores proporcionan todos los mecanismos necesarios
ppu_sprite_zero_hit_position(ppu)
-> extracts current PPU state and finds the overlap position
ppu.set_sprite_zero_hit_position(position)
-> stores the future timing event
ppu.step(...)
-> sets PPUSTATUS bit 6 when timing reaches that positionEste paso los conecta al bucle de frames.
Decisión de arquitectura
Ponemos la preparación del sprite zero hit dentro de Console.step_until_next_frame() de forma intencionada. Un código llamante como main.py debe pedir a Console que avance un frame emulado completo sin saber qué eventos de timing internos del PPU deben prepararse primero.
Esto mantiene main.py centrado en las responsabilidades del frontend:
input
display
FPS reporting
frame pacingConsole es el propietario de la coordinación del emulador a nivel de frame.
Cambio de implementación sugerido
# --- NEW LINE ---
from emulator.rendering.sprite_zero_hit import ppu_sprite_zero_hit_position
# --- END NEW LINE ---
def step_until_next_frame(
self,
max_cpu_instructions: int | None = None,
) -> int:
# --- NEW BLOCK ---
position = ppu_sprite_zero_hit_position(self.ppu)
self.ppu.set_sprite_zero_hit_position(position)
# --- END NEW BLOCK ---
start_frame = self.ppu.frame
executed = 0
while self.ppu.frame == start_frame:
...¿Por qué antes del bucle de pasos? La CPU puede consultar PPUSTATUS mientras se emula el frame. El hit futuro debe programarse antes de que la ejecución CPU/PPU alcance el píxel solapado.
Punto de comprobación manual de compatibilidad
Después de este paso, los estudiantes pueden cambiar temporalmente la ruta local de la ROM manual en main.py por su propia copia legal:
Cambio de implementación sugerido en main.py:
ROM_PATH = Path("Super Mario Bros.nes")Después, ejecuta con PyPy
Linux/macOS
sh launcher.shSímbolo del sistema de Windows
launcher.cmdMejora manual esperada
Super Mario Bros. usa el sprite 0 hit como señal de timing del PPU. Con el hit ahora detectado, programado y expuesto a través de PPUSTATUS, la pantalla de título/menú debería avanzar más, Mario debería aparecer y la entrada del mando debería volverse utilizable.
Limitación conocida restante
Cuando Mario avanza horizontalmente, la escena aún puede verse incorrecta porque el renderizador de fondo actual todavía no aplica el estado de scrolling del PPU para seleccionar y desplazar la región visible del nametable. El sprite 0 hit habilita la ruta de timing del juego; no implementa el scrolling horizontal del fondo.
Regla legal y de testeo
Super Mario Bros.nes es solo un experimento manual de compatibilidad proporcionado por el usuario. No hagas commit de la ROM y no la exijas en los tests automatizados. Estos tests usan objetos CPU/PPU falsos y solo comprueban el comportamiento de coordinación.
Fuera del alcance
- scrolling horizontal/vertical
- scrolling X fino
- composición de nametables adyacentes
- comportamiento exacto de Y+1 de OAM
- reglas del borde izquierdo de PPUMASK
- excepción del sprite 0 hit en x=255
- fixtures de ROM comerciales
Ejecutar esta lección
uv run pytest tests/chapter_11_sprite_zero_hit/test_323_console_schedules_sprite_zero_hit_per_frame.py -v