333. Преобразование логической таблицы имён Ppu в маску непрозрачности

Построить маску непрозрачности из одной выбранной логической таблицы имён PPU.

Урок 333 из 356 · tests/chapter_13_scrolling/test_333_ppu_logical_nametable_to_opaque_mask.py

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

emulator/rendering/ppu_background_renderer.py

Справочные материалы

https://www.nesdev.org/wiki/PPU_nametables

Зачем нужен этот шаг

Существующая вспомогательная функция строит маску, используемую приоритетом спрайтов и обнаружением попадания нулевого спрайта, но изначально читает только логическую таблицу имён $2000. Для горизонтальной прокрутки нужна также маска, относящаяся к соседней логической таблице имён.

Совместимость

Если параметр base_nametable_addr опущен, по-прежнему выбирается $2000, поэтому существующие вызывающие стороны из Console и логики попадания нулевого спрайта остаются корректными до тех пор, пока интеграция области просмотра не будет выполнена намеренно.

Входные данные для непрозрачности

  • 960 идентификаторов тайлов из выбранной логической таблицы имён
  • таблица паттернов фона, выбираемая битом 4 PPUCTRL

Для непрозрачности не используются байты атрибутов, RAM палитры и итоговые цвета RGB.

Вне объёма работ

  • составление левой и правой масок
  • отрисовка фреймбуфера
  • интеграция Console
  • интеграция области просмотра в логику попадания нулевого спрайта
  • вертикальная прокрутка

Полный пример реализации

# emulator/rendering/ppu_background_renderer.py

def ppu_background_to_opaque_mask(
    ppu: PPU,
    # --- NEW LINE: OPTIONAL LOGICAL NAMETABLE SELECTION ---
    base_nametable_addr: int = BASE_NAMETABLE_ADDR,
) -> BackgroundOpaqueMask:
    # --- NEW BLOCK: REJECT NON-NAMETABLE BASE ADDRESSES ---
    if base_nametable_addr not in LOGICAL_NAMETABLE_BASE_ADDRS:
        raise ValueError(
            "Logical nametable base address must be $2000, $2400, $2800, $2C00"
        )

    nametable_bytes = bytes(
        # --- UPDATED LINE: READ FROM THE SELECTED NAMETABLE ---
        ppu.ppu_bus.read(base_nametable_addr + offset)
        for offset in range(NAMETABLE_SIZE)
    )

    ...
    # Everything remains the same below this point.

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

uv run pytest tests/chapter_13_scrolling/test_333_ppu_logical_nametable_to_opaque_mask.py -v