259. Счётчики синхронизации PPU

Реализуйте базовые счётчики синхронизации PPU.

Урок 259 из 356 · tests/chapter_04_ppu_timing_and_vblank/test_259_ppu_timing_counters.py

Справка

https://www.nesdev.org/wiki/PPU_rendering#Line-by-line_timing

Файл для обновления

emulator/ppu/ppu.py

Константы для добавления

PPU_CYCLES_PER_SCANLINE = 341
PPU_SCANLINES_PER_FRAME = 262

Состояние для добавления

cycle: int = 0
scanline: int = 0
frame: int = 0

Метод для добавления

PPU.step(cycles: int = 1) -> None

Почему этот шаг существует

PPU — это устройство, основанное на времени. Позже VBlank, NMI, рендеринг и синхронизация кадров будут зависеть от знания того, где находится PPU внутри текущего кадра.

Для этого шага добавьте только счётчики

cycle    -> position inside the current scanline
scanline -> current scanline inside the frame
frame    -> completed frame count

Начальная модель синхронизации

341 PPU cycles per scanline
262 scanlines per frame

Предлагаемый пример реализации

def step(self, cycles: int = 1) -> None:
    for _ in range(cycles):
        self.cycle += 1

        if self.cycle >= PPU_CYCLES_PER_SCANLINE:
            self.cycle = 0
            self.scanline += 1

            if self.scanline >= PPU_SCANLINES_PER_FRAME:
                self.scanline = 0
                self.frame += 1

Совместимость в будущем

Эти тесты намеренно проверяют только поведение счётчиков. Они ещё не требуют точных побочных эффектов VBlank/NMI. Более поздние шаги могут добавить побочные эффекты внутри PPU.step(), но эти инварианты счётчиков должны остаться верными.

Вне области действия

  • генерация VBlank
  • запрос NMI
  • рендеринг
  • попадание спрайта 0
  • переполнение спрайтов
  • пропуск цикла нечётного кадра

Запустить этот урок

uv run pytest tests/chapter_04_ppu_timing_and_vblank/test_259_ppu_timing_counters.py -v