NES TDD

303. Палитры спрайтов из палитровой RAM

Построить палитры спрайтов из байтов палитровой RAM PPU.

Урок 303 из 356 · tests/chapter_09_sprite_rendering/test_303_sprite_palettes_from_palette_ram.py

Изменяемый файл

emulator/rendering/palette_ram.py

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

Прежде чем отрисовывать пиксели спрайтов, нам нужно преобразовать байты палитровой RAM спрайтов в RGB-палитры. Палитровая RAM спрайтов находится в диапазоне адресов палитр PPU:

$3F10-$3F1F

Эта вспомогательная функция получает эти 16 байт и возвращает четыре RGB-палитры спрайтов.

Ссылки

https://www.nesdev.org/wiki/PPU_palettes#Palette_RAM

Важная терминология

CHR color index
    The 2-bit pixel value decoded from CHR tile data: 0, 1, 2, or 3.

PPU palette RAM byte
    A runtime NES color index, usually $00-$3F.

RGB color
    The emulator's display color tuple from NES_PALETTE_RGB.

Структура палитры спрайтов

palette 0 uses bytes 0, 1, 2, 3
palette 1 uses bytes 4, 5, 6, 7
palette 2 uses bytes 8, 9, 10, 11
palette 3 uses bytes 12, 13, 14, 15

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

SpritePalettes = list[list[RGBColor]]


def build_sprite_palettes_from_palette_ram(palette_ram: bytes) -> SpritePalettes:
    if len(palette_ram) != PALETTE_RAM_SIZE:
        raise ValueError(f"Sprite palette RAM must be {PALETTE_RAM_SIZE} bytes")

    sprite_palettes = []

    for palette_id in range(TOTAL_PALETTES):
        base = palette_id * COLORS_PER_PALETTE

        palette = [
            get_nes_rgb_color(palette_ram[base]),
            get_nes_rgb_color(palette_ram[base + 1]),
            get_nes_rgb_color(palette_ram[base + 2]),
            get_nes_rgb_color(palette_ram[base + 3]),
        ]

        sprite_palettes.append(palette)

    return sprite_palettes

Важное правило прозрачности спрайтов

У спрайтов индекс CHR-цвета 0 прозрачен при отрисовке. Эта вспомогательная функция не применяет прозрачность. Она лишь преобразует байты палитровой RAM в цвета RGB. Отрисовщик спрайтов, который появится позже, будет решать:

if sprite_color_index == 0:
    skip drawing this pixel

Распространённое заблуждение

"Sprite palette entry 0 should be removed from the palette helper."

Нет. Сохраните четыре элемента. Отрисовщику нужна стабильная индексация 0..3, хотя индекс 0 означает прозрачность при отрисовке пикселей спрайтов.

Вне рамок этого шага

  • отрисовка пикселей спрайтов
  • применение прозрачности
  • приоритет спрайтов
  • отражение спрайтов
  • попадание спрайта 0
  • переполнение спрайтов
  • pygame

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

uv run pytest tests/chapter_09_sprite_rendering/test_303_sprite_palettes_from_palette_ram.py -v