268. Console.step avanza la PPU
Hacer que Console.step() avance el tiempo de la PPU a partir de los ciclos de la CPU.
Lección 268 de 356 · tests/chapter_04_ppu_timing_and_vblank/test_268_console_step_advances_ppu.py
Referencias
https://www.nesdev.org/wiki/CPU
https://www.nesdev.org/wiki/PPU_rendering#Line-by-line_timingArchivo a actualizar
emulator/console.pyPor qué existe este paso
El emulador ahora tiene las piezas necesarias para conectar el tiempo de la CPU con el tiempo de la PPU
CPU.step() returns base CPU cycles
PPU.step(cycles) advances PPU timing counters
Console.consume_nmi_if_requested() connects PPU NMI requests to CPU NMIConsole.step() es donde esas piezas se convierten en un paso a nivel de máquina.
¿Qué es el stepping a nivel de máquina? El stepping a nivel de máquina significa avanzar múltiples chips emulados juntos según su relación de reloj.
Regla de temporización mínima de la NES
1 CPU cycle = 3 PPU cyclesEjemplo mínimo
CPU executes NOP
NOP takes 2 CPU cycles
PPU advances 2 * 3 = 6 PPU cyclesConcepto erróneo común
No hagas que CPU.step() llame a PPU.step(). La CPU no debería poseer la temporización de vídeo. Console es quien coordina los chips.
Ejemplo de implementación sugerido
@dataclass
class Console:
cpu: CPU
ppu: PPU
def consume_nmi_if_requested(self) -> None:
if not self.ppu.nmi_requested:
return
self.ppu.nmi_requested = False
self.cpu.interrupt_nmi()
def step(self) -> int:
# This is base timing only. Later steps can add branch penalties,
# NMI latency, DMA stalls, and other timing details.
cpu_cycles = self.cpu.step()
self.ppu.step(cpu_cycles * 3)
self.consume_nmi_if_requested()
return cpu_cyclesLimitación importante
Esta es todavía una temporización simplificada. CPU.step() actualmente devuelve solo ciclos base.
Las mejoras posteriores pueden tener en cuenta
branch taken extra cycles
branch page-cross extra cycles
indexed addressing page-cross extra cycles
NMI latency
OAM DMA stallsFuera de alcance
- penalizaciones dinámicas de ciclo de la CPU
- latencia NMI precisa a nivel de punto
- OAM DMA
- renderizado de píxeles
- bucle de pygame/frontend
- entrada de controlador
Ejecutar esta lección
uv run pytest tests/chapter_04_ppu_timing_and_vblank/test_268_console_step_advances_ppu.py -v