Пошаговое руководство · Разработка через тестирование

Эмулятор NES через TDD

Соберите эмулятор Nintendo Entertainment System с нуля на Python, пройдя 356 уроков, управляемых тестами.

Автор: linkfy · 14 глав · 356 уроков

Что это за руководство

Это стартовый проект, содержащий только тесты. Готовый эмулятор в него намеренно не входит: каталог tests/ и есть учебная программа. Каждый пронумерованный тест объясняет, почему важно следующее поведение, какой файл рабочего кода создать или обновить и какая минимальная реализация ожидается на этом шаге.

Это руководство идёт осознанным путём, а не быстрым.

Первые главы строят и проверяют CPU, память, картридж и основы PPU. Графика игры и интерактивный фронтенд появятся позже, когда поддерживающие их компоненты заслужат своё место через тесты. Не ждите картинки на экране в первых уроках; ждите понимания того, почему всё работает, когда она наконец появится.

Как начать

  1. 1. Клонируйте репозиторий

    git clone https://github.com/linkfy/nes-emulator-tutorial-tdd
    cd nes-emulator-tutorial-tdd
  2. 2. Установите uv и создайте зафиксированное окружение

    Не запускайте uv init внутри репозитория: проект уже инициализирован. Из корня проекта установите зависимости, зафиксированные в uv.lock.

    uv --version
    uv sync

    docs.astral.sh/uv

  3. 3. Откройте урок 001 и запустите только этот тест

    Прочитайте документацию модуля от начала до конца, прежде чем писать рабочий код. Затем запустите только этот урок:

    uv run pytest tests/chapter_01_cpu/test_001_initial_files.py -v
  4. 4. Повторяйте цикл Красный → Зелёный → Рефакторинг

    Продвигайтесь по одному пронумерованному тесту за раз. Каждый пройденный урок должен оставаться зелёным, прежде чем двигаться дальше. Запускайте только завершённые тесты; пока не запускайте будущие главы.

    После урока 356 запустите полный набор тестов:

    uv run pytest

Цикл TDD

Красный

Запустите тест урока и убедитесь, что он падает.

Зелёный

Напишите минимальную реализацию, которая заставит его пройти.

Рефакторинг

Наведите порядок в коде, сохраняя все предыдущие тесты зелёными.

Маркеры в коде

В примерах уроков могут встречаться NEW LINE / NEW BLOCK для нового кода, UPDATED LINE / UPDATED BLOCK для изменений, DELETED LINE / DELETED BLOCK для устаревшего кода и ... там, где существующий код остаётся без изменений.

Карта курса

Четырнадцать глав и 356 упорядоченных уроков. По диапазонам номеров видно, где вы сейчас и что будет дальше.

01CPUCPU, RAM, шина, режимы адресации, инструкции, флаги и проверкаТесты 001211 · 211 уроков
02Загрузка ROMРазбор iNES, картриджи, Mapper 000 и выполнение ROMТесты 212223 · 12 уроков
03Память PPU и графикаРегистры PPU, шина PPU, VRAM, данные CHR и декодирование графикиТесты 224258 · 35 уроков
04Тайминги PPU и VBlankТайминги PPU, VBlank, NMI и согласование CPU/PPUТесты 259269 · 11 уроков
05Конвейер рендерингаЧистый конвейер рендеринга, данные фреймбуфера и помощники pygameТесты 270287 · 18 уроков
06Запуск ROMПодготовка запуска ROM, заглушки APU и OAM DMAТесты 288289 · 2 уроков
07Ввод с контроллераПротокол контроллера NES и интеграция $4016Тесты 290293 · 4 уроков
08Ручной mainРучной цикл ROM, фронтенд pygame, ввод с клавиатуры и ошибкиТесты 294298 · 5 уроков
09Рендеринг спрайтовДекодирование спрайтов, рендеринг, приоритет и композицияТесты 299314 · 16 уроков
10ПроизводительностьОтчёт о FPS, быстрая загрузка фреймбуфера, PyPy и начальная синхронизацияТесты 315318 · 4 уроков
11Sprite Zero HitОбнаружение sprite-zero-hit и интеграция тайминговТесты 319323 · 5 уроков
12ЗеркалированиеЗеркалирование nametable картриджаТесты 324327 · 4 уроков
13СкроллингГоризонтальная композиция вьюпорта и таймированный скроллингТесты 328353 · 26 уроков
14ОптимизацииНеизменяемые кеши рендеринга и покадровая синхронизация по абсолютному дедлайнуТесты 354356 · 3 уроков

ROM-файлы для ручной проверки

Некоторые поздние уроки включают ручные проверки на легально полученных реальных ROM (например, Super Mario Bros. или Mario Bros.). Они нужны только тогда, когда урок доходит до ручной контрольной точки.