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 Checks and White Screen Diagnostics
Summary
Fixed checks for Tasks 3 and 4 of Step 0374 not running because they were in the wrong place in the flow (afterpygame.display.flip()). The checks were moved to their correct locations in the render pipeline, and new checks were added to diagnose why screens are completely white even though the framebuffer has data (checkerboard pattern). Checks are now executed at the correct points in the flow: after drawing to the surface, after scaling, and after blit to screen (before flip).
Hardware Concept
Rendering Pipeline in the Emulator
The rendering pipeline in the emulator follows this flow:
- C++ Framebuffer: The C++ PPU generates a framebuffer with palette indices (0-3) for each pixel (160x144 = 23040 pixels).
- Conversion to RGB: Palette indices are converted to RGB values using the BGP (Background Palette) palette.
- Surface Drawing: RGB pixels are drawn on a 160x144 Pygame surface using NumPy (surfarray.blit_array) or PixelArray.
- Scaling: The surface is scaled to the window size using
pygame.transform.scale(). - Blit to Screen: The scaled surface is flashed to the screen using
screen.blit(). - flip: The screen is updated using
pygame.display.flip().
Identified Problem
Incorrect location of checks:The verifications for Tasks 3 and 4 of Step 0374 were afterpygame.display.flip(), outside the main flow. This means that:
- Checks were not running at the correct time (after the screen had already been updated).
- They couldn't detect problems in the pipeline before the flip.
- The logs did not show these checks because they were in a place that was not executed in the normal flow.
Symptoms observed:
[Renderer-Pixel-Draw]and[Renderer-Scale-Blit]They did NOT appear in the logs.[Renderer-CPP-PPU-Entry]and[Renderer-Screen-Update]They DID appear (other checks worked).- Completely white screens with some scattered dark pixels.
- The application crashed (
main.pydid not respond).
Implementation
Task 1: Move Check Task 3 (Pixel Draw) to the Correct Point
Previous location:Lines 1971-2000 (afterpygame.display.flip()).
New location:Aftersurfarray.blit_array()(line 1570) for NumPy, and after assigningself.surface = self._px_array_surface(line 1619) for PixelArray.
The verification now runs immediately after drawing pixels on the surface, allowing problems in converting indices to RGB or in drawing pixels to be detected.
Task 2: Move Check Task 4 (Scale Blit) to the Correct Point
Previous location:Lines 2046-2076 (afterpygame.display.flip()).
New location:Afterself.screen.blit()(line 2002), beforepygame.display.flip().
The verification is now executed after the blit to the screen but before the flip, allowing problems in scaling or blit to be detected.
Task 3: Add Framebuffer Verification Received
Location:At the beginning of the C++ PPU block (after line 593).
Function:Verify that the framebuffer received from C++ has valid data:
- Verify that
frame_indicesis not None and has 23040 elements. - Displays the first 20 indices of the framebuffer.
- Counts non-zero pixels and shows the percentage.
- Logs if the framebuffer is completely blank (all indices are 0).
Task 4: Add RGB Conversion Check
Location:After creatingrgb_array(after line 1529).
Function:Verify that the first 20 pixels of thergb_arraythey have the correct RGB values depending on the palette:
- Compares the expected RGB values (based on the framebuffer and palette indices) with the current RGB values in the array.
- Log discrepancies if values do not match.
Task 5: Add Surface Check After NumPy Blit
Location:Aftersurfarray.blit_array()(after line 1570).
Function:Verify thatself.surfacehas the correct pixels aftersurfarray.blit_array():
- Reads the first 20 pixels of
self.surface. - Compare with the expected values of the
rgb_array. - Log discrepancies if there are differences.
Task 6: Add Scaled Surface Verification
Location:Afterpygame.transform.scale()(after line 1816).
Function:Verify thatself._scaled_surface_cachehas the correct pixels after scaling:
- It reads some pixels from the scaled surface and compares them with the original surface.
- Verify that scaling is not corrupting the data (allows for small differences due to interpolation).
Implemented Code
All verifications were implemented with specific tags to facilitate log analysis:
[Renderer-Framebuffer-Received]: Check received framebuffer[Renderer-RGB-Conversion]: RGB conversion check[Renderer-Surface-After-NumPy]: Surface check after NumPy blit[Renderer-Pixel-Draw]: Checking drawn pixels (Task 3)[Renderer-Surface-Scaled]: Climbing surface verification[Renderer-Scale-Blit]: Scaling and blit verification (Task 4)
Findings
Verification Location Correction
✅ Checks moved successfully:The checks for Tasks 3 and 4 are now in their correct locations in the render pipeline.
✅ New checks added:Added 4 new checks to diagnose the white screens issue:
- Verification of received framebuffer (at start of C++ PPU block)
- RGB conversion check (after creating rgb_array)
- Surface verification after NumPy blit
- Climbing surface verification
Testing Status
The tests were run with a timeout of 30 seconds. The renderer initializes correctly, but no full frames were generated at the time of testing. The checks are in the right places and will run when the render runs.
Tests and Verification
Executed Tests
A short test (30 seconds) was run with the pkmn.gb ROM:
timeout 30 python3 main.py roms/pkmn.gb 2>&1 | tee logs/test_pkmn_step0375.log
Compile Command
python3 setup.py build_ext --inplace
Result:Successful build without errors.
Log Analysis
The logs show that the renderer initializes correctly, but no full frames were generated in the test time (30 seconds). The checks are in the right places and will run when the render runs.
C++ Compiled Module Validation
✅ C++ module compiled successfully:No compilation errors found. The module is ready to run.
Affected Files
src/gpu/renderer.py- Corrected location of checks and added new diagnostic checks (Step 0375)build_log_step0375.txt- Successful compilation loglogs/test_pkmn_step0375.log- Test log with pkmn.gb ROM
Next Steps
After completing this step:
- Run longer tests to generate complete frames and verify that the verifications appear in the logs.
- Analyze the logs to identify at what point in the pipeline the framebuffer information is lost.
- If the screens are still white, further investigate the index to RGB conversion issue or the palette issue.