NES TDD

300. Декодирование записи спрайта

Декодирование одной записи спрайта из байтов OAM.

Урок 300 из 356 · tests/chapter_09_sprite_rendering/test_300_decode_sprite_entry.py

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

emulator/rendering/sprite_renderer.py

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

На предыдущем шаге был определён SpriteEntry. Теперь мы добавляем небольшой декодер, преобразующий сырые байты OAM PPU в один SpriteEntry.

Сырая раскладка OAM

sprite 0 -> bytes 0, 1, 2, 3
sprite 1 -> bytes 4, 5, 6, 7
...
sprite 63 -> bytes 252, 253, 254, 255

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

def decode_sprite_entry(oam: bytes | bytearray, sprite_index: int) -> SpriteEntry:
    if len(oam) < OAM_SIZE:
        raise ValueError("OAM must contain 256 bytes")

    if not 0 <= sprite_index < OAM_SPRITE_COUNT:
        raise ValueError("sprite_index must be in range 0..63")

    base = sprite_index * BYTES_PER_SPRITE

    return SpriteEntry(
        y=oam[base],
        tile_index=oam[base + 1],
        attributes=oam[base + 2],
        x=oam[base + 3],
    )

Важная деталь NES

Сырой байт Y имеет особую семантику рендеринга на реальном железе. Спрайты отображаются на одну строку развёртки ниже сохранённого значения Y. Не корректируйте его в этом декодере. Эта функция возвращает только сырые данные OAM.

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

  • декодирование битов атрибутов спрайта
  • палитры спрайтов
  • рендеринг пикселей
  • sprite 0 hit
  • переполнение спрайтов
  • pygame

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

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