335. Преобразование области просмотра фона Ppu в маску непрозрачности

Составить горизонтальную область просмотра маски непрозрачности из текущего состояния прокрутки PPU.

Урок 335 из 356 · tests/chapter_13_scrolling/test_335_ppu_background_viewport_to_opaque_mask.py

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

emulator/rendering/ppu_background_renderer.py

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

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

Почему это похоже на шаг 334

Адаптер маски непрозрачности намеренно копирует структуру адресации адаптера фреймбуфера:

decode the same viewport X
select the same horizontal logical pair
process the same left and right bases
compose using the same viewport X

Важное отличие состоит в том, что каждая операция, производящая данные, должна использовать путь маски непрозрачности:

ppu_background_to_opaque_mask()
compose_horizontal_opaque_mask_viewport()

Этот адаптер не должен случайно вызывать

ppu_background_to_framebuffer()
compose_horizontal_framebuffer_viewport()

Такое намеренное копирование сохраняет лёгкую читаемость обоих путей. Их тесты на согласованность защищают небольшой продублированный механизм адресации от дрейфа.

Итоговая маска позже будет совместно использоваться приоритетом спрайтов и обнаружением попадания нулевого спрайта. Этот шаг только строит её; он не интегрирует ни одного из потребителей.

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

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

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

# emulator/rendering/ppu_background_renderer.py

# --- NEW BLOCK: COPY FRAMEBUFFER ADDRESSING FOR THE OPACITY-MASK PATH ---
def ppu_background_viewport_to_opaque_mask(
    ppu: PPU,
) -> BackgroundOpaqueMask:
    viewport_x, _ = decode_background_viewport_position(
        temp_vram_addr=ppu.temp_vram_addr,
        fine_x=ppu.fine_x,
    )

    nametable_y = (ppu.temp_vram_addr >> 11) & 1
    left_base = BASE_NAMETABLE_ADDR + nametable_y * 0x0800
    right_base = left_base + 0x0400

    # Same addresses, but call the opacity-mask producer.
    left = ppu_background_to_opaque_mask(
        ppu,
        base_nametable_addr=left_base,
    )
    right = ppu_background_to_opaque_mask(
        ppu,
        base_nametable_addr=right_base,
    )

    # Use the opacity-mask compositor, not the framebuffer compositor.
    return compose_horizontal_opaque_mask_viewport(
        left=left,
        right=right,
        viewport_x=viewport_x,
    )

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

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