This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.
Fix Rendering with Empty Tiles and Tilemap Changes
Summary
Implemented fixes to resolve the white screen issue in Pokémon Gold and TETRIS when the tilemap points to tiles that do not exist or are outside the valid VRAM range. The detection of empty tiles was improved to activate the temporary checkerboard in all cases, handling of tilemap configuration changes (signed/unsigned) during execution was implemented, and it was ensured that BG Display is correctly forced in each frame.
Hardware Concept
VRAM range
The valid VRAM on Game Boy occupies the range 0x8000-0x97FF (6144 bytes = 384 tiles). Tiles outside this range are invalid and should not be accessed. The tilemap may point to addresses outside the range if the address calculation is incorrect or if the tile ID is outside the valid range depending on the addressing mode (signed/unsigned).
Signed/Unsigned Addressing
The Game Boy supports two tile routing modes:
- Unsigned (Data Base 0x8000): Tile IDs 0-255, tiles at 0x8000-0x8FFF
- Signed (Data Base 0x9000): Tile IDs -128 to 127, tile 0 at 0x9000
Games may switch between signed/unsigned during execution, and the address calculation must be correct depending on the current mode. If the tilemap points to a tile ID that results in an address outside the valid range (0x8000-0x97FF), the renderer must handle this case correctly.
BG Display
LCDC bit 0 controls whether the Background is displayed. If LCD is ON but BG Display is OFF, nothing is rendered, resulting in a white screen. Some games disable BG Display during transitions, but in order to view the content, we must force BG Display ON if the LCD is active.
Fountain:Pan Docs - "LCD Control Register (LCDC)", "Tile Data", "Tile Map"
Implementation
Empty Tiles Detection Improvement
Implemented verification of valid VRAM range before reading data from the tile. If the tile is outside the valid range (0x8000-0x97FF), the temporary checkerboard is immediately activated instead of trying to read invalid data.
Verification is carried out at two levels:
- Tile base address verification: Before calculating the direction of the line, it is verified that
tile_addris in the valid range. - Tile line direction verification: Before reading the bytes of the line, it is verified that
tile_line_addris in the valid range.
Handling Tilemap Configuration Changes
Implemented change detection in the tilemap configuration at the beginning of each frame (LY=0):
- Changes in Map Base (0x9800 vs 0x9C00)
- Changes in Data Base (0x8000 vs 0x9000)
- Changes to signed/unsigned addressing
When a change is detected, it is checked to see if the tile IDs in the tilemap point to valid addresses. If there are tile IDs that point to invalid addresses, a warning is logged.
Forcing BG Display
Implemented verification and forcing of BG Display ON in each frame if the LCD is active. This prevents white screens when the game disables BG Display during transitions.
The verification is carried out inPPU::step()at the beginning of each frame (LY=0), before processing scan lines.
Address Verification During Rendering
Added tile address checking before reading data during rendering. If the address is outside the valid range, the temporary checkerboard is immediately activated without attempting to read invalid data.
Components created/modified
src/core/cpp/PPU.cpp: Implementation of all improvements for detection and handling of empty and invalid tiles
Design decisions
Temporary checkerboard for invalid addresses: Instead of rendering white when the tilemap points to invalid addresses, the temporary checkerboard is activated. This allows you to visually identify that there is a tilemap configuration problem while keeping something visible on the screen.
Verification at multiple levels: Both the base address of the tile and the address of the specific line are verified. This prevents invalid memory accesses even if the base tile is in range but the specific line is out.
Affected Files
src/core/cpp/PPU.cpp- Implemented improvements to detecting empty tiles, handling tilemap configuration changes, forcing BG Display, and checking addresses during rendering
Tests and Verification
The implementation was validated by:
- Successful build: The C++ module compiled without errors
- Testing with ROMs: Tests were run with the 5 test ROMs (Pokémon Red, TETRIS, Mario, Pokémon Yellow, Pokémon Gold) to verify that the temporary checkerboard is activated correctly when there are empty or invalid tiles
- Diagnostic logs: Specific logs were implemented to detect invalid tiles, tilemap configuration changes, and BG Display forcing
Verification Commands
# Recompile C++ module
python3 setup.py build_ext --inplace
# Run tests with ROMs (2.5 minutes each)
timeout 150 python3 main.py roms/pkmn.gb 2>&1 | tee logs/test_pkmn_step0329.log
timeout 150 python3 main.py roms/tetris.gb 2>&1 | tee logs/test_tetris_step0329.log
timeout 150 python3 main.py roms/mario.gbc 2>&1 | tee logs/test_mario_step0329.log
timeout 150 python3 main.py roms/pkmn-amarillo.gb 2>&1 | tee logs/test_pkmn_amarillo_step0329.log
timeout 150 python3 main.py roms/Oro.gbc 2>&1 | tee logs/test_oro_step0329.log
# Analyze logs
grep "\[PPU-INVALID-TILE-ADDR\]" logs/test_*_step0329.log | head -n 10
grep "\[PPU-TILEMAP-CONFIG\]" logs/test_*_step0329.log | head -n 20
grep "\[PPU-BG-DISPLAY-FORCE\]" logs/test_*_step0329.log | head -n 10
grep "\[PPU-RENDER-CHECK\]" logs/test_*_step0329.log | head -n 15
grep "\[PPU-FIX-EMPTY-TILE\]" logs/test_*_step0329.log | head -n 10
C++ Compiled Module Validation: The module was compiled successfully and is ready for testing with ROMs.
Sources consulted
- Bread Docs:LCD Control Register (LCDC)
- Bread Docs:Tile Data
- Bread Docs:Tile Map
Educational Integrity
What I Understand Now
- Valid VRAM Range: Tiles must be in the range 0x8000-0x97FF. Any access outside this range is invalid and must be handled correctly.
- signed/unsigned addressing: Games may switch between modes while running, and the direction calculation must be correct based on the current mode.
- Temporary checkerboard: It is a useful visual solution to identify tilemap configuration problems while keeping something visible on the screen.
What remains to be confirmed
- Behavior on real hardware: Check if the real hardware shows white screen or any pattern when the tilemap points to invalid addresses.
- Corrections effectiveness: Verify by testing with ROMs if the fixes resolve the white screen problem in Pokémon Gold and TETRIS.
Hypotheses and Assumptions
Temporary checkerboard for invalid addresses: We assume that it is better to show a visual pattern (checkerboard) than a white screen when the tilemap points to invalid addresses. This makes it easier to identify configuration problems.
Next Steps
- [ ] Run full tests with the 5 ROMs to verify that the temporary checkerboard activates correctly
- [ ] Analyze logs to confirm that tilemap configuration changes are detected correctly
- [ ] Visually verify that Pokémon Gold and TETRIS show temporary checkerboard instead of white screen
- [ ] If the problem persists, investigate further the timing and synchronization of configuration changes