Video summary
Gameboy Emulator Development - Part 14
Main summary
Key takeaways
Summary of the video (Game Boy Emulator Dev – Part 14)
This installment continues the low-level Game Boy PPU/GPU pipeline work. After building the pixel FIFO background rendering in the previous part, the author now adds sprite support by:
- implementing OAM (sprite attribute memory) scanning per scanline
- building a small linked-list of sprites visible on the current line
- extending the pixel FIFO to fetch sprite pixels (with priority, palettes, transparency, and x/y flipping)
- loading sprite tile indices and pattern data for up to a limited number of sprites per FIFO window
1) OAM scan changes: build “sprites on this line”
The PPU switches into an OAM scan mode (described as mode 2) that reads sprite data for the current scanline. Key constraints noted:
- Up to 10 sprites can be on a given line (hardware behavior).
- OAM has 40 entries, but only visible ones are stored for the current line.
A new structure is created:
oam line entry: a linked-list node containing the sprite entry and anextpointer- stored inside the PPU context
- includes:
line_sprite_count(0–10)line_sprites(head pointer for linked list)- an
line entry array[10]used as preallocated storage (avoids repeatedmalloc/free) fetched_entry_countto manage how many sprites are currently being fetched into the FIFO for the next pixel chunk
2) load_line_sprites: scan OAM for sprites on current Y
The author adds a function like load_line_sprites that:
- reads each OAM entry (looping through 40)
- ignores non-visible sprites (checks an x-value condition; subtitles imply x==0 used as not visible)
- checks Y overlap using sprite height and the current scanline:
- if sprite lies within the current 8-bit scanline region, it is considered “on this line”
- inserts the sprite entry into the linked list sorted by X order
- ordering matters for correct game behavior
This scan happens when line_ticks == 1 (a simplified timing approximation rather than exact cycle-accurate emulation).
3) FIFO integration: fetching sprite pixels per 8-pixel chunk
The pixel FIFO is extended to blend sprites over the background.
New helper: fetch_sprite_pixels
A function is added conceptually to:
- return a sprite-derived color for a given pixel bit position and sprite data
- output includes:
color(U32)- uses
bg_coloras the fallback when sprite pixel is transparent
It handles:
- x-offset + scroll x adjustment
- bounds checking (only affects the current 8-pixel FIFO window)
- x flipping:
- chooses bit index reversed if flipped
- extracts sprite pattern bytes:
- high/low bits from two consecutive bytes (
data0/data1behavior)
- high/low bits from two consecutive bytes (
- transparency:
- sprite pixel value 0 means “transparent”, so background shows through
- priority vs background:
- checks the “background priority” bit
- if priority rules allow, sprite overwrites; otherwise may keep background
- palette selection:
- chooses between sprite palettes (subtitles mention correcting palette1 vs palette2)
Where it plugs in
In the FIFO “pixel rendering” stage:
- color selection becomes conditional:
- if background disabled → use
background_color[0] - if sprites enabled → call
fetch_sprite_pixels(...)to possibly override color
- if background disabled → use
4) FIFO sprite data loading: pipeline_load_sprite_tile + pipeline_load_sprite_data
Before sprite pixel bits can be fetched, the FIFO needs to load the relevant sprite patterns.
pipeline_load_sprite_tile
- iterates over the
line_spriteslinked list -
computes sprite X for the current FIFO window:
spx = sprite_x - 8 + (scrollx % 8)
-
checks whether the sprite intersects the FIFO’s current 8-pixel section:
- ensures
spxandspx+8overlap with[fetch_x, fetch_x+8)
- ensures
- adds matching sprites into a
fetched_entries[]array-like region - enforces a maximum of 3 sprites per FIFO window:
- stops when
fetched_entry_count >= 3
- stops when
pipeline_load_sprite_data
- loads pattern bytes for each fetched sprite:
- uses current
LYand sprite height from LCDC - computes the correct
tYfor the scanline within the sprite - applies y-flip via reversing logic (subtitles describe reversing within sprite height)
- computes tile index adjustments:
- mentions a “trick” for 8x16/16px cases by masking bits
- uses current
- reads sprite tile pattern bytes from VRAM:
index * 16 + tY + offsetfor the two bitplanes (data0/data1)
5) Build fixes and correctness notes
The author notes build/setup fixes (e.g., includes string.h, forward declarations). Then small correctness fixes are made:
- a missing
continuein sprite loading logic (referred to as causing problems) - palette correction:
- “palette one” vs “palette two” swap
6) Visual results and remaining work
After these changes:
- sprites start appearing, including examples like:
- Mario preview
- hearts
- jumping/pills
- a spaceship/asteroids
- however, some sprite sections are missing, attributed to the Game Boy Window feature:
- the “window” rendering region isn’t implemented yet
- expectation: once window handling is added, sprite rendering should fully match
Future steps mentioned
- implement window
- possibly implement gamepad/controller input
- then support larger ROMs / different ROM types beyond ROM-only/simple cases
Main sources / speakers
- Primary speaker/source: the channel host from “Low Level Devil” (narrating and writing the emulator code / implementing PPU + FIFO sprite support).