306. Render all oam sprites

Render all 64 OAM sprites into framebuffer data.

Lesson 306 of 356 · tests/chapter_09_sprite_rendering/test_306_render_all_oam_sprites.py

File to update

emulator/rendering/sprite_renderer.py

Why this step exists

We can now render one SpriteEntry. Since OAMDMA fills PPU.oam with 64 sprite entries, the next step is to loop over all OAM entries and render each sprite into the target framebuffer.

Important sprite priority rule

When sprites overlap, lower OAM index has higher priority

sprite 0 is in front of sprite 1
sprite 1 is in front of sprite 2
...

Because this renderer mutates a framebuffer, draw in reverse OAM order

sprite 63 first
...
sprite 0 last

That way lower-index sprites overwrite higher-index sprites at overlapping pixels.

Suggested implementation example

def render_oam_sprites_to_framebuffer(
    framebuffer: Framebuffer,
    oam: bytes | bytearray,
    pattern_table: bytes,
    sprite_palettes: SpritePalettes,
) -> None:
    if len(oam) < OAM_SIZE:
        raise ValueError("OAM must contain 256 bytes")

    for sprite_index in reversed(range(OAM_SPRITE_COUNT)):
        sprite = decode_sprite_entry(oam, sprite_index)
        render_sprite_8x8_to_framebuffer(
            framebuffer,
            sprite,
            pattern_table,
            sprite_palettes,
        )

Out of scope

  • sprite 0 hit
  • sprite overflow
  • background priority/compositing policy
  • 8x16 sprites
  • scanline sprite evaluation
  • pygame

Run this lesson

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