This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.
Step 0255 - OAM Inspector and Palettes
Summary
This Step extends the GPS monitor (Step 0240) insrc/viboy.pyto include
real-time inspection of pallet records (BGP, OBP0, OBP1) and first
OAM (Object Attribute Memory) sprites. The objective is to diagnose why the
screen appears green/white when it should be showing sprites, checking if the problem
it's either in the data (empty OAM or DMA not working) or in the rendering (bad palettes).
Hardware Concept
On the Game Boy, sprites (objects) are stored in the OAM (Object Attribute Memory),
located in the range0xFE00-0xFE9F(160 bytes = 40 sprites × 4 bytes).
Each sprite occupies 4 consecutive bytes:
- Byte 0 (Y): Vertical position (0-255, but Y=0 or Y≥160 hides the sprite)
- Byte 1 (X): Horizontal position (0-255, but X=0 or X≥168 hides the sprite)
- Byte 2 (Tile): Tile index in VRAM (0-255)
- Byte 3 (Attributes): Attributes (palette, X/Y flip, priority, etc.)
Palette registers control how tile colors are translated:
- BGP (0xFF47): Background palette (4 colors: 00, 01, 10, 11)
- OBP0 (0xFF48): Sprite Palette (channel 0, colors 1-3; color 0 is transparent)
- OBP1 (0xFF49): Sprite Palette (channel 1, colors 1-3; color 0 is transparent)
Critical problem:YeahOBP0eitherOBP1are in0x00either0xFF(all white or all transparent), the sprites will be invisible even
if they are correctly rendered. If the OAM is empty (all zeros), the DMA is not working
or the game hasn't initialized the sprites yet.
Fountain:Pan Docs - OAM (Object Attribute Memory), Sprite Attributes, Palette Registers
Implementation
Changed GPS monitor block insrc/viboy.py(lines 944-976) to add
reading palette registers and the first 2 sprites from the OAM. The inspection is carried out every
second (60 frames) along with the standard GPS report.
Modified components
src/viboy.py: Extended GPS block (Step 0240) with OAM and paddle inspection
Inspection logic
The code reads:
- Pallets:
0xFF47(BGP),0xFF48(OBP0),0xFF49(OBP1) - Sprite 0:
0xFE00-0xFE03(Y, X, Tile, Attributes) - Sprite 1:
0xFE04-0xFE07(Y, X, Tile, Attributes)
Values are recorded usinglogger.info()with hexadecimal format to facilitate
the diagnosis. The format is:
[VIDEO] BGP:XX OBP0:XX OBP1:XX | LCDC:XX
[SPRITE 0] Y:XX X:XX T:XX A:XX
[SPRITE 1] Y:XX X:XX T:XX A:XX
Diagnostic scenarios:
- Empty OAM (Y:00 X:00 T:00):DMA is not copying data or memory is cleared
- OAM with valid data (Y:10 X:08 T:5A):The sprites are present. If you don't see them, the problem is with C++ rendering or the palettes
- Palettes at 0x00 or 0xFF:The sprites will be invisible (white or transparent)
Affected Files
src/viboy.py- Extended GPS monitor with OAM and pallet inspection (Step 0255)
Tests and Verification
This Step does not require unit tests, since it is a real-time diagnostic tool. Validation is carried out by running the emulator and observing the logs:
- Command:
python main.py roms/pkmn.gb(or any ROM with sprites) - Observation:The logs
[VIDEO]and[SPRITE]appear every second on the console - Validation:Verify that OAM and palette values are consistent with the game state
Note:This Step does not modify the C++ core, it only adds Python instrumentation for diagnosis. No C++ recompilation required.
Sources consulted
- Bread Docs:OAM (Object Attribute Memory)
- Bread Docs:LCDC (LCD Control Register)
- Bread Docs:Palette Registers (BGP, OBP0, OBP1)
Educational Integrity
What I Understand Now
- OAM Structure:Each sprite occupies 4 consecutive bytes (Y, X, Tile, Attributes) in the range 0xFE00-0xFE9F
- Palette Registers:BGP controls the background, OBP0/OBP1 controls the sprites. If they are at 0x00 or 0xFF, the sprites will be invisible
- Diagnosis:OAM and palette inspection distinguishes between data issues (empty OAM) and rendering issues (bad palettes)
What remains to be confirmed
- DMA Timing:Verify that the DMA is executed frequently and the OAM is not deleted between frames
- Sprite Visibility:Confirm that sprites with Y=0 or X=0 are hidden correctly in the render
- Palette Mapping:Verify that C++ rendering correctly respects OBP0/OBP1 values
Hypotheses and Assumptions
Main hypothesis:If the screen appears green/white with sprites implemented, the most likely problem is that the OBP0/OBP1 palettes are at 0x00 (all transparent) or that the OAM is empty (DMA not working or game still initializing).
This diagnostic tool will allow us to confirm or refute this hypothesis by observing the values real at runtime.
Next Steps
- [ ] Run the emulator with a ROM (Pokémon Red, Mario) and observe the OAM and palette logs
- [ ] Analyze the reported values to determine if the problem is data (empty OAM) or rendering (bad palettes)
- [ ] If OAM is empty: Investigate the DMA and verify that it runs frequently
- [ ] If OAM has data but invisible sprites: Check C++ rendering and palette mapping
- [ ] Correct the identified issue and validate that the sprites are displayed correctly