232. Чтение статуса PPU очищает vblank
Чтение PPUSTATUS очищает флаг VBlank.
Урок 232 из 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_232_ppu_status_read_clears_vblank.py
Файл для обновления
emulator/ppu/ppu.pyМетод для обновления
PPU.read_register(addr)Зачем нужен этот шаг
PPUSTATUS по адресу $2002 — не пассивное значение. На реальном оборудовании NES чтение PPUSTATUS возвращает текущий байт состояния и сбрасывает флаг начала VBlank внутри PPU.
Важное поведение
read_register($2002):
1. save the old status value
2. clear only VBLANK_STARTED, bit 7
3. return the old status valueПорядок имеет значение.
Правильно
value = self.status
self.status &= ~VBLANK_STARTED
return valueНеправильно
self.status &= ~VBLANK_STARTED
return self.statusПочему это неправильно
CPU должен иметь возможность наблюдать, что VBlank установлен. Если эмулятор очищает бит 7 перед возвратом, циклы опроса CPU пропустят VBlank.
Побитовый пример
status before read: 0b1110_0000
~VBLANK_STARTED: 0b0111_1111
status after AND: 0b0110_0000Очищается только бит 7. Попадание спрайта 0 и переполнение спрайтов остаются установленными.
Предлагаемый псевдокод реализации
def read_register(self, addr: int) -> int:
match addr:
case 0x2002:
value = self.status
self.status &= ~VBLANK_STARTED
return value
case 0x2004:
return self.oam_data
case 0x2007:
return self.data
case _:
raise ValueError(...)Вне области действия
- автоматическая установка VBlank из тайминга PPU
- генерация NMI
- сканлайны/циклы
- поведение попадания спрайта 0
- поведение переполнения спрайтов
Запустить этот урок
uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_232_ppu_status_read_clears_vblank.py -v