241. Чтение PPUSTATUS сбрасывает переключатель второй записи
Чтение PPUSTATUS ($2002) сбрасывает переключатель второй записи PPU.
Урок 241 из 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_241_ppustatus_read_resets_second_write_toggle.py
Файл для обновления
emulator/ppu/ppu.pyМетод для обновления
PPU.read_register(addr)Почему этот шаг важен
PPU NES имеет регистры с двойной записью, особенно
$2005 PPUSCROLL
$2006 PPUADDRЭти регистры используют внутренний переключатель первой/второй записи. В этом курсе это состояние называется:
second_write_toggleЗначение
False -> the next two-write register access is the first write
True -> the next two-write register access is the second writeВажное поведение PPUSTATUS
Чтение $2002 сбрасывает этот переключатель обратно в False.
Почему
Игры обычно читают PPUSTATUS перед записью в PPUSCROLL или PPUADDR, чтобы гарантировать, что PPU снова ожидает первую запись.
Пример
write $23 to $2006
second_write_toggle = True
read $2002
second_write_toggle = False
write $20 to $2006
treated as first write / high byte, not as low byteПредлагаемый псевдокод реализации
def read_register(self, addr: int) -> int:
match addr:
case 0x2002:
value = self.status
self.status &= ~VBLANK_STARTED
self.second_write_toggle = False
return value
case 0x2004:
return self.oam_data
case 0x2007:
return self.data
case _:
raise ValueError(...)Важный инвариант
Чтение $2002 должно возвращать старое значение статуса, а затем применять побочные эффекты.
Побочные эффекты, смоделированные на данный момент
- сброс VBLANK_STARTED
- сброс second_write_toggle
Побочные эффекты, которые пока не смоделированы
- полное поведение защёлки прокрутки
- тайминг/генерация VBlank
- поведение NMI
Запустить этот урок
uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_241_ppustatus_read_resets_second_write_toggle.py -v