This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.
Checkerboard Disappearance Investigation
Summary
This step investigates why the temporary checkerboard disappears after a few frames. Diagnostic logs were implemented to verify the status of the framebuffer, when it is cleaned, changes to vram_is_empty_, and the state of the renderer. The logs revealed that the problem was that the periodic framebuffer check was done when ly_ == 0, right after to clean it, always showing an empty framebuffer. Fixed by moving the check to VBLANK_START (144), after rendering the entire frame.
Hardware Concept
Framebuffer persistence
The framebuffer must hold its data until the next frame is rendered. If the framebuffer is cleared prematurely, the screen turns white. The framebuffer should only be cleared at the start of the next frame, after Python has read it.
Temporary Checkerboard
The temporary checkerboard is activated when VRAM is empty (vram_is_empty_ == true). It should stay active as long as VRAM is empty. If vram_is_empty_ changes incorrectly, the checkerboard may disappear.
Render Cycle
The PPU rendering cycle works like this:
- Lines 0-143:Rendering scanlines (render_scanline())
- Line 144 (VBLANK_START):V-Blank, frame ready to read
- Lines 145-153:V-Blank continued
- Line > 153:Reset to ly_ = 0, clear framebuffer for next frame
Therefore, the framebuffer must be checked at VBLANK_START(144), after render the entire frame, but before it is cleared for the next frame.
Implementation
Aggregated Diagnostic Logs
The following diagnostic logs were added to investigate the disappearance of the checkerboard:
- [PPU-FRAMEBUFFER-PERIODIC]:Periodic check of framebuffer status every 100 frames
- [PPU-CLEAR-FRAMEBUFFER]:Log every time the framebuffer is cleared
- [PPU-VRAM-EMPTY-CHANGE]:Log when vram_is_empty_ changes state
- [Renderer-Periodic]:Periodic renderer check every 100 frames
Critical Correction
It was identified that the periodic checking of the framebuffer was done when ly_ == 0, right after cleaning it. This caused an empty framebuffer to always be displayed, even though the checkerboard was drawing correctly.
Solution:Move the periodic check to VBLANK_START (144), then to render the entire frame, but before it is cleared for the next frame.
Modified Components
src/core/cpp/PPU.cpp: Added diagnostic logs and periodic verification correctionsrc/gpu/renderer.py: Added periodic renderer logs
Affected Files
src/core/cpp/PPU.cpp- Added diagnostic logs and periodic verification correctionsrc/gpu/renderer.py- Added periodic renderer logs
Tests and Verification
Tests were run with the 5 ROMs (Pokémon Red, TETRIS, Mario, Pokémon Yellow, Pokémon Gold) for 2.5 minutes each to collect diagnostic logs.
Log Results
Before correction:The logs showed that the framebuffer was completely empty (0 non-white pixels) although VRAM was empty and should have checkerboard.
After correction:The logs show that the framebuffer has data correct (11520 pixels with index 0 and 11520 with index 3), indicating that the checkerboard it is being drawn correctly.
Corrected Log Example
[PPU-FRAMEBUFFER-PERIODIC] Frame 1 | Non-zero pixels: 11520/23040 |
Distribution: 0=11520 1=0 2=0 3=11520 | VRAM empty: YES
[PPU-FRAMEBUFFER-PERIODIC] Frame 101 | Non-zero pixels: 11520/23040 |
Distribution: 0=11520 1=0 2=0 3=11520 | VRAM empty: YES
Checking Other Calls to clear_framebuffer()
Verified that there are only 3 calls to clear_framebuffer():
- In the constructor (line 25) - Correct
- When ly_ > 153 (line 292) - Correct
- The definition of the function (line 500) - Correct
Sources consulted
- Pan Docs: LCD Display, V-Blank, Framebuffer
- Implementation based on general knowledge of architecture LR35902
Educational Integrity
What I Understand Now
- Render Cycle:The framebuffer is cleared at the start of the frame (ly_ == 0), rendered during lines 0-143, and marked ready at VBLANK_START (144).
- Framebuffer verification:Checking the framebuffer should be done after rendering the entire frame (VBLANK_START), not at startup when clearing it.
- Temporary Checkerboard:The checkerboard draws correctly when VRAM is empty, but premature checking showed an empty framebuffer.
What remains to be confirmed
- Disappearance of the Checkerboard:Although the logs show that the checkerboard is drawn correctly, we still need to visually verify if the checkerboard disappears after a few frames on the screen.
- Changes to vram_is_empty_:The logs show that vram_is_empty_ changes after some frames (ex: frame 4723, 4732), which is normal when the game loads tiles. We need to check if this causes the checkerboard to disappear.
Hypotheses and Assumptions
Main Hypothesis:The problem of the disappearance of the checkerboard may be related to changes in vram_is_empty_ after some frames. When VRAM fills with tiles, vram_is_empty_ changes to false, which disables the checkerboard. This is expected behavior, but may cause visual confusion if the game loads tiles. and then deletes them.
Next Steps
- [ ] Visually check if the checkerboard disappears after some frames
- [ ] Analyze if changes in vram_is_empty_ cause the checkerboard to disappear
- [ ] If the problem persists, implement correction based on the findings of the logs
- [ ] Final rendering verification with all ROMs