This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.
Total VRAM Unlock and Write Diagnostics
Summary
After verifying that the MBC works correctly and that the LCD turns on (LCDC=0x80), but the screen remains white even in X-Ray mode, the hypothesis is that the MMU could be blocking writes in VRAM (0x8000-0x9FFF) due to PPU mode restrictions or range errors. Added temporary logging to diagnose if the game is trying to write graphics to VRAM and any restrictions have been removed of writing that could exist.
Hardware Concept
On the Game Boy, VRAM (Video RAM, 0x8000-0x9FFF) is an 8KB region of memory that stores data graphics: tiles (8x8 pixel blocks), background maps, and window attributes. During rendering, The PPU actively reads this memory to generate the screen image.
VRAM access restrictions:On real hardware, VRAM is locked (read only or inaccessible) while the PPU is drawing (Mode 3 - Pixel Transfer). However, the hardware does not block physically access; it may simply cause visual artifacts if the CPU writes during Pixel Transfer. Games should poll the STAT register (0xFF41) to detect when the PPU is in a safe mode (H-Blank or V-Blank) before writing to VRAM.
Diagnostic problem:If an emulator implements this restriction too strictly or erroneous, the CPU tries to write graphics, the MMU says "Access Denied!", and the VRAM goes empty (white). This is why it is critical to verify that writes to VRAM are being allowed correctly.
Source: Pan Docs - VRAM Access Restrictions, STAT Register
Implementation
The method was reviewedwrite_byteof the MMU to check if there was a write lock
in VRAM. Upon review, it was confirmed thatthere are no explicit restrictionsthat block
writes to VRAM based on PPU mode. The code simply writes inself._memory[addr] = valueat the end of the method if it is not a special record.
Modified components
- MMU (src/memory/mmu.py): A counter was added
vram_write_countin the constructor to limit logging to the first 10 writes. Added temporary logging inwrite_bytewhich detects writes in the range 0x8000-0x9FFF and logs them with the message💾 VRAM WRITE: {value:02X} into {addr:04X}.
Design decisions
- Logging limited to 10 writes:In order not to saturate the console, only the first 10 writes to VRAM. This is enough to verify that the game is trying to write graphics.
- No write lock:It was confirmed that there is no check of
ppu.mode == 3or similar that blocks writes. The code allows all writes to VRAM, as it should. In hardware In reality, typing during Pixel Transfer may cause artifacts, but does not block access. - Documentary note:Added an explicit comment to the code explaining that there is no VRAM write restriction based on PPU mode, and that games must poll STAT to avoid writing during Pixel Transfer.
Affected Files
src/memory/mmu.py- Added countervram_write_countand temporary logging for diagnosis of writes in VRAM (0x8000-0x9FFF).
Tests and Verification
State: Verified
Command executed:
python test_vram_writes.py
Around:Windows 10, Python 3.13.5
Test ROM:Pokémon Red (user-contributed ROM, not distributed)
Result:
- ✅ VRAM WRITE messages DO appear:The game is trying to write to VRAM. 10 writes were detected during initialization (limited by the log counter).
- ⚠️ BUT all values are 0x00:The game is writing zeros to VRAM, which
explains why the screen is white. The first 10 scriptures were:
INFO: 💾 VRAM WRITE: 00 in 8000 INFO: 💾 VRAM WRITE: 00 in 8001 INFO: 💾 VRAM WRITE: 00 in 8002 INFO: 💾 VRAM WRITE: 00 in 8003 INFO: 💾 VRAM WRITE: 00 in 8004 INFO: 💾 VRAM WRITE: 00 in 8005 INFO: 💾 VRAM WRITE: 00 in 8006 INFO: 💾 VRAM WRITE: 00 in 8007 INFO: 💾 VRAM WRITE: 00 in 8008 INFO: 💾 VRAM WRITE: 00 in 8009
Interpretation of the result:
- The gameYES you are running codewhich writes to VRAM (there is no access lock).
- The problem is that he is writingzeros instead of actual graph data.
- Possible causes:
- The game is initializing the VRAM to zeros (normal behavior during boot, but it should copy data later).
- The game tries to copy data from ROM/RAM but the source is empty or not being read correctly.
- There is a problem with DMA (Direct Memory Access) copying data to OAM/VRAM.
- The game is waiting for some event (interrupt, PPU mode change) before copying the actual data.
What is valid:This step confirms that:
- ✅ The MMU is NOT blocking writes to VRAM (writes are allowed correctly).
- ✅ The game is running code that writes to VRAM (it doesn't crash before reaching the copy routine).
- ⚠️ The problem is that the game is writing zeros instead of actual graphical data.
Next step:Investigate why the game is writing zeros to VRAM. Possible areas to review:
- DMA: Check if the DMA is working correctly (register 0xFF46).
- Manual copies: Check if the copy instructions (LD, LDI, LDD) are reading correctly from ROM/RAM.
- Timing: Check if the game is waiting for any events (V-Blank, PPU mode change) before copying data.
- Initialization: Check if the game is in an initialization phase where it first clears the VRAM and then copies data.
Sources consulted
- Bread Docs:VRAM Access Restrictions
- Bread Docs:LCD Status Register (STAT)
- Bread Docs:Memory Map
Educational Integrity
What I Understand Now
- VRAM is not physically locked:Although the documentation mentions that the VRAM is "locked" during Pixel Transfer, the actual hardware does not physically block access. Simply can cause visual artifacts if the CPU writes during rendering. Games must do STAT polling to avoid writing at inappropriate times.
- Systematic diagnosis:When the screen is white, you must systematically check: (1) Is the LCD on? (LCDC bit 7), (2) Is the MBC working? (bank switching), (3) Does the game write in VRAM? (logging), (4) Does the Renderer read correctly? (tile decoding). This step verifies point (3).
- Logging as a diagnostic tool:Temporal logging is a powerful tool to understand what the game is doing in real time. Limit logging to first N writes avoids cluttering the console while providing enough information to diagnose the problem.
What remains to be confirmed
- Why does the game write zeros to VRAM?It was confirmed that the game DOES write to VRAM,
but all the values are 0x00. This could be:
- Normal initialization: The game first clears the VRAM to zeros and then copies data (but the copy is not running or crashes).
- DMA problem: The DMA could be copying from an empty source or not working properly.
- Problem with manual copies: Copy instructions (LD, LDI, LDD) could be reading zeros from ROM/RAM or not running correctly.
- Timing: The game could be waiting for an event (V-Blank, PPU mode change) before copying real data.
- Does the Renderer read the VRAM correctly?Although the main problem is that zeros are written, You must also verify that the Renderer correctly reads the VRAM when there is valid data. This can be Check later when the zero writing issue is resolved.
Hypotheses and Assumptions
Main hypothesis (CONFIRMED):The MMU is not blocking writes to VRAM. The game YES it is writing to VRAM, but it is writing zeros instead of actual graphics data.
New hypothesis:The game is in an initialization phase where it first clears the VRAM to zeros and then it should copy graphics data from ROM/RAM, but the copy is not running or is failing. Possible causes: (1) DMA not working properly, (2) Manual copies read from empty source, (3) The game waits for an event that does not occur (V-Blank, PPU mode change), (4) Game crashes after clearing VRAM but before copying data.
Assumption:We assume that temporary logging does not affect performance or behavior of the emulator. If logging causes problems, you can disable it or reduce the number of messages.
Next Steps
- [✅] Run ROM and check if messages appear
💾 VRAM WRITE- FILLED: It was confirmed that the game DOES write to VRAM, but all values are 0x00. - [ ] Investigate why the game writes zeros to VRAM:
- Check if the DMA is working correctly (register 0xFF46).
- Check if the copy instructions (LD, LDI, LDD) are reading correctly from ROM/RAM.
- Check if the game is waiting for any events (V-Blank, PPU mode change) before copying data.
- Add logging to track reads from ROM/RAM during copies.
- [ ] Once the zero writing problem has been resolved, verify that the Renderer reads the VRAM correctly when there is valid data.
- [ ] Reduce or delete temporary logging once the problem is fully diagnosed.