⚠️ Clean-Room / Educational

This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.

Brute Force Diagnostics: VRAM Flood

Date:2025-12-21 StepID:0208 State: ✅ VERIFIED

Summary

After Step 0207, with the tilemap coordinates corrected (centered on Row 8, Column 4), the screen continues to display blank and the logs indicate that the PPU reads zeros. This suggests that either we are not writing to the correct location, or the PPU is not reading what we write. To resolve this definitively, we apply an aggressive diagnostic technique:fill entire Tile Data region (0x8000-0x97FF) with `0xFF` (black pixels). This destructive but enlightening test will give us the absolute truth about whether the PPU is reading the VRAM.

Binary Hypothesis:If the screen turns black, we confirm that the PPU DOES read the VRAM and that the previous problem was with coordinates or logo data format. If the screen remains white, there is a fundamental error in how the MMU or PPU accesses video memory.

Hardware Concept: Flooded Tile Data

The VRAM (Video RAM) in the Game Boy occupies the range0x8000-0x9FFF(8KB). This region is divided into two main areas:

  • Tile Data (0x8000-0x97FF):1536 tiles × 16 bytes = 6KB of graphics data in 2bpp format
  • Tile Maps (0x9800-0x9FFF):Maps that indicate which tile to draw at each position on the screen

In the Tile 2bpp format, each byte represents 4 pixels (2 bits per pixel). The value0xFFrepresents two consecutive bytes of a tile row:

  • First byte (low bits):0xFF= all bits set to 1
  • Second byte (high bits):0xFF= all bits set to 1
  • Result: All pixels in that row inColor 3 (Black)

If we fill the entire Tile Data area with0xFF, each possible tile (from 0 to 383) will become a solid block of "black" color (Color 3). As the default Tilemap (0x9800) is usually initialized to zeros (Tile ID 0) by our own memory initialization, if we turn Tile 0 into a black block,the entire screen should turn black.

Fountain:Pan Docs - "Tile Data", "Tile Map", "Memory Map"

Implementation

We modified the MMU constructor to temporarily comment out the fine loading of the logo (tiles and tilemap) and add a "flood" loop that fills the entire range of Tile Data with0xFF.

Modification in MMU::MMU()

Insrc/core/cpp/MMU.cpp, inside the constructor, we comment on the loading of the Viboy logo and add the flooding code:

// --- Step 0208: VRAM FLOOD DIAGNOSIS ---
// BRUTE FORCE TECHNIQUE: Fill the entire Tile Data area (0x8000 - 0x97FF) with 0xFF.
// If the screen turns black, we will know that the PPU DOES read the VRAM.
// If the screen remains white, there is a fundamental error in the video memory access.
//
// Concept: 0xFF in Tile format (2bpp) = all pixels in Color 3 (Black).
// Since the default Tilemap (0x9800) is initialized to zeros (Tile ID 0),
// if we turn Tile 0 into a black block, the entire screen should turn black.
//
// Source: Pan Docs - "Tile Data", "Tile Map"
printf("[MMU] FLOODING VRAM WITH 0xFF (BLACK) FOR DIAGNOSTICS...\n");
for (int i = 0x8000; i< 0x9800; ++i) {
    memory_[i] = 0xFF;
}
// -----------------------------------------

Modified Components

  • src/core/cpp/MMU.cpp- Modified builder to flood VRAM with 0xFF instead of loading logo

Design Decisions

We choose to flood only the Tile Data area (0x8000-0x97FF) and not the Tile Maps area (0x9800-0x9FFF) because:

  • The default Tilemap already contains zeros (Tile ID 0), which point to the first tile
  • If we turn Tile 0 into a black block, the entire screen will turn black without needing to modify the tilemap
  • This approach is simpler and more direct for diagnosis

Affected Files

  • src/core/cpp/MMU.cpp- Modified builder to flood VRAM with 0xFF (commented logo code)
  • docs/bitacora/entries/2025-12-21__0208__diagnosis-brute-force-flood-vram.html- New log entry
  • docs/bitacora/index.html- Updated with new entry
  • REPORT_PHASE_2.md- Updated with Step 0208

Tests and Verification

This is a functional diagnostic test, not a unit test. The verification process is:

  1. Recompiling C++ module:
.\rebuild_cpp.ps1
  1. Running the emulator:
python main.py roms/tetris.gb

Expected Result (Binary)

There are two possible outcomes, each with a different diagnosis:

Scenario 1: BLACK (or very dark) screen ✅

Meaning:Success! The PPU correctly reads the VRAM.

Diagnosis:The previous problem with the logo was that we were using the wrong Tile IDs, writing to the wrong VRAM bank (if CGB emulation is interfering), or Tile 0 was dominating the screen. The PPU is working correctly and accessing memory as it should.

Next step:Restore the logo loading and adjust the coordinates or data format as necessary.

Scenario 2: WHITE Screen ❌

Meaning:Critical memory access failure.

Diagnosis:Although we write inmemory_, the PPU is reading from somewhere else, or the read is intercepted incorrectly. Possible causes:

  • The PPU is reading from a different VRAM bank (if CGB emulation is active and not configured correctly)
  • There is CGB VRAM Banking logic that returns zeros if not configured
  • The methodMMU::read()is not correctly returning values ​​written to VRAM
  • The PPU is reading directly from another memory source instead of using theMMU::read()

Next step:Investigate the VRAM read flow on the PPU and verify that the MMU-PPU connection is working correctly.

Compiled C++ module validation:The test uses the compiled C++ module (viboy_core), which contains the native implementation of the MMU and the PPU.

Sources consulted

  • Bread Docs:Memory Map- VRAM layout description
  • Bread Docs:Tile Data- 2bpp tile format
  • Bread Docs:Tile Map- Mapping of tiles to screen positions
  • Implementation based on general knowledge of LR35902 architecture and behavior of Game Boy hardware

Educational Integrity

What I Understand Now

  • Brute Force Diagnosis:Sometimes the best way to diagnose a complex problem is to apply a destructive but definitive technique. Filling the entire VRAM with a known value (0xFF) eliminates all possible variables and gives us a clear binary answer: is the PPU reading VRAM or not?
  • Tile 2bpp format:In the 2bpp format, each byte represents 4 pixels (2 bits per pixel). The value 0xFF in both bytes (low and high) of a row results in all pixels in Color 3 (Black).
  • Default Tilemap:If the tilemap is initialized to zeros (Tile ID 0), and we turn Tile 0 into a black block, the entire screen should turn black. This allows us to test VRAM access without needing to modify the tilemap.

What remains to be confirmed

  • Test Result:Run the emulator and see if the screen turns black or remains white. This result will determine if the problem is one of coordinates/format (if black) or fundamental memory access (if white).
  • Root Cause (if white):If the screen is still white, we will need to investigate why the PPU is not reading the VRAM. Possible areas to review: CGB VRAM Banking, MMU::read() method, MMU-PPU connection.

Hypotheses and Assumptions

Main Assumption:We assume that the default tilemap (0x9800-0x9FFF) is initialized to zeros (Tile ID 0). If this is not true, the test may not show a completely black screen, but should still show some visual change confirming that the PPU is reading the VRAM.

Palette Assumption:We assume that the BGP palette is configured so that Color 3 displays as black. If the palette is set differently, the resulting color might vary, but it should still be visible and different from white.

Next Steps

  • [ ] Run the test and observe the result:Black screen (PPU reads VRAM) or white screen (memory access error)
  • [ ] If black screen:Restore logo loading and adjust coordinates or data format as necessary
  • [ ] If white screen:Investigate the VRAM read flow on the PPU, verify VRAM Banking of CGB, and ensure that the MMU-PPU connection is working correctly
  • [ ] Validate the diagnosis:Once the problem is identified, implement the solution and verify that the logo appears correctly