261. VBlank 时 PPU 发起 NMI 请求
实现 VBlank 时 PPU 端的 NMI 请求。
第 261 / 356 · tests/chapter_04_ppu_timing_and_vblank/test_261_ppu_nmi_request_on_vblank.py
参考资料
https://www.nesdev.org/wiki/PPU_registers#PPUCTRL
https://www.nesdev.org/wiki/PPU_registers#Vblank_NMI需要更新的文件
emulator/ppu/ppu.py需要添加的状态
nmi_requested: bool = False此步骤存在的原因
许多 NES 游戏并不会在主循环中轮询 PPUSTATUS。相反,它们通过 PPUCTRL 的第 7 位启用 NMI,并期望 PPU 在 VBlank 开始时请求一次中断。
在这一步中,只实现 PPU 端的信号
if VBlank starts and PPUCTRL bit 7 is set:
ppu.nmi_requested = TrueCPU 目前还不会消费这个 NMI。那是之后的集成步骤要做的事情。
建议的实现示例
nmi_requested: bool = False
...
...
if self.scanline == PPU_VBLANK_START_SCANLINE:
self.status |= VBLANK_STARTED
if self.ctrl & CTRL_NMI_ENABLE:
self.nmi_requested = True重要概念
NMI 请求是在 VBlank 开始时产生的事件,不应该在 VBlank 期间的每个周期都持续产生。
不在本步骤范围内
- CPU 的中断处理
- 读取 NMI 向量
- 把 PC/状态寄存器压入 CPU 栈
- 由 CPU/系统集成来清除 nmi_requested
- 在 VBlank 已经处于激活状态时再次启用 NMI
- 逐点/逐周期精确的 NMI 时序
运行本课
uv run pytest tests/chapter_04_ppu_timing_and_vblank/test_261_ppu_nmi_request_on_vblank.py -v