⚠️ 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.

VRAM Cleanup Analysis and Verification Sync

Date:2025-12-29 StepID:0327 State: VERIFIED

Summary

This step implements tile verification synchronization with the time they are loaded, using [TILE-LOADED] events to capture the state of VRAM when there are tiles before they are cleaned. We investigate why the game clears VRAM after loading tiles (PC:0x36E3 writes zeros), and checks if the tilemap points correctly to the tiles when they are loaded.

Real-time checking is implemented that captures the state of VRAM when there are tiles, more frequent checking (every 10 frames instead of every 60), VRAM cleanup analysis that detects when 0x00 is written after loading tiles, and immediate verification of the tilemap when tiles are detected to confirm if it points to tiles with data.

Hardware Concept

Timing and Synchronization

Hardware events occur at specific times. If the verification is too slow, you may miss transient events. Tiles can be loaded and cleaned quickly. Verification must be frequent enough to capture these events.

Issue identified in Step 0326:The tiles are loaded in PC:0x618D (20 tiles = 320 bytes), but the verification is done every 60 frames (1 second). By the time it is verified (Frame 61+), the tiles have already been cleaned (0 bytes). Result: It is never detected that there are real tools.

Fountain: Empirical analysis based on logs from Step 0326.

VRAM Cleaning

Games may clear VRAM during initialization. This can occur before or after loading tiles. If cleared after loading tiles, the tilemap may point to tiles that no longer exist. Some games load tiles, update tilemap, and then clear unused tiles.

Identified problem:PC:0x36E3 writes 100+ zeros to VRAM (cleans tiles). This happens AFTER loading the tiles. The game loads tiles but then clears them.

Fountain: Pan Docs - "VRAM (Video RAM)", empirical observation of logs.

Tilemap-Tiles correspondence

The tilemap must point to tiles that exist in VRAM. If the tiles are cleared but the tilemap is not updated, it is rendered white. The correspondence should be verified when the tiles are loaded, not after.

Identified problem:The tilemap has 32/32 non-zero tile IDs, but VRAM is empty (0 non-zero bytes). The tilemap points to tiles that do not exist (they were cleaned).

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

Sequence of Events

Sequence identified in the analysis of Step 0326:

  1. Frame 1: 40 non-zero bytes (test or initialization tools)
  2. PC:0x618D: Load 20 tiles (320 bytes)
  3. PC:0x36E3: Clean VRAM (0 bytes)
  4. Frame 61+: Verification finds 0 bytes (tiles already cleaned)

Fountain: Log analysis of Step 0326.

Implementation

Task 1: Synchronize Verification with Tiles Loading

Added immediate check when [TILE-LOADED] is detected inMMU::write(). When it is detected that a tile has been loaded, the VRAM state is immediately checked, capturing the moment when there are tiles before they are cleaned.

Added more frequent verification inPPU::render_scanline()(every 10 frames instead of every 60) to capture tiles before they are cleaned up.

Task 2: Investigate Why the Game Clears VRAM

Added analysis of the cleanup routine (PC:0x36E3) inMMU::write(). It is detected when the game writes zeros to VRAM after loading tiles, logging the context (PC, ROM bank, frame) and checking if there is a pattern (clears all VRAM or just parts).

A global static variable is usedtiles_were_loaded_recently_globalto track if tiles were recently loaded, allowing you to detect when VRAM is cleared after loading tiles.

Task 3: Check Tilemap When Tiles Are Loaded

Added immediate tilemap verification when tiles are detected inPPU::render_scanline(). When it is detected that there are tiles in VRAM, it is immediately verified if the tilemap points to those tiles, logging the correspondence.

It checks whether the first 32 tile IDs of the tilemap point to tiles with data or empty tiles, identifying if there is a correspondence between the tilemap and loaded tiles.

Task 4: Real-Time Correspondence Analysis

Added analysis of which tile IDs correspond to the tiles loaded inPPU::render_scanline(). When tiles are detected in VRAM, it calculates which tile IDs should point to them and compares them with the tile IDs of the tilemap, logging if there is a match.

The known addresses where tiles are loaded are checked (0x8820+) and it is calculated which tile IDs should point to those addresses according to the addressing (signed/unsigned), verifying if the tilemap has those tile IDs.

Design Decisions

  • Check every 10 frames:Balance between frequency and performance. 10 frames (approx. 6 times per second) is enough to capture transient events without significantly affecting performance.
  • Global static variable:A global static variable is used to track whether tiles were recently loaded, allowing the cleanup analysis to access this information from different sections of the code.
  • Log limits:Logs are limited to 5-20 events to avoid context saturation, following the project rules.

Affected Files

  • src/core/cpp/MMU.cpp- Added immediate VRAM check when loading tiles, VRAM cleanup analysis, and global static variable to track tile loading
  • src/core/cpp/PPU.cpp- Added more frequent VRAM checking (every 10 frames), immediate tilemap checking when there are tiles, and real-time correspondence analysis

Tests and Verification

Tests were run with the 3 ROMs (pkmn.gb, tetris.gb, mario.gbc) for 2.5 minutes each to capture immediate verification logs, cleanup analysis, and correspondence.

Commands executed:

timeout 150 python3 main.py roms/pkmn.gb > logs/test_pkmn_step0327.log 2>&1
timeout 150 python3 main.py roms/tetris.gb > logs/test_tetris_step0327.log 2>&1
timeout 150 python3 main.py roms/mario.gbc > logs/test_mario_step0327.log 2>&1

Log analysis:The logs are analyzed using commands that do not saturate the context:

grep "\[VRAM-IMMEDIATE\]" logs/test_*_step0327.log
grep "\[PPU-VRAM-FREQ\]" logs/test_*_step0327.log | head -n 20
grep "\[VRAM-CLEAN\]" logs/test_*_step0327.log
grep "\[PPU-CORRESPONDENCE\]" logs/test_*_step0327.log
grep "\[PPU-TILEMAP-IMMEDIATE\]" logs/test_*_step0327.log

Compiled C++ module validation:The module was successfully recompiled without errors. Only minor warnings were generated about printf formats and unused variables, which do not affect the functionality.

Sources consulted

  • Bread Docs:"VRAM (Video RAM)"- Range 0x8000-0x9FFF contains Tile Data and Tile Maps
  • Bread Docs:"Tile Map"- 32x32 tiles at 0x9800-0x9BFF or 0x9C00-0x9FFF
  • Bread Docs:"Tile Data"- 0x8000-0x97FF contains 384 tiles of 16 bytes each
  • Empirical analysis: Logs from Step 0326 that identified the VRAM timing and cleaning problem

Educational Integrity

What I Understand Now

  • Verification timing:Verification should be frequent enough to capture transient events. If you check too late, you miss important events like tile loading before they are cleaned up.
  • VRAM Cleaning:Games can clear VRAM after loading tiles, which can cause the tilemap to point to tiles that no longer exist. This requires immediate verification when tiles are loaded.
  • tilemap-tiles correspondence:The tilemap must point to tiles that exist in VRAM. If the tiles are cleared but the tilemap is not updated, it is rendered white. The correspondence must be verified when the tiles are loaded.

What remains to be confirmed

  • Why VRAM is cleaned:We need to analyze the logs to understand why the game cleans VRAM after loading tiles. Is this part of normal initialization or is there a problem?
  • Exact timing:We need to confirm the exact timing between tile loading and cleanup to determine if there is a window of opportunity to capture tiles.
  • tilemap-tiles correspondence:We need to check if the tilemap is updated after loading tiles or if it always points to tiles that do not exist.

Hypotheses and Assumptions

Hypothesis:The game clears VRAM as part of normal initialization, but the tilemap is not updated immediately after loading tiles. This causes the tilemap to point to tiles that no longer exist.

Assumption:Checking every 10 frames is sufficient to capture transient events. If it is not sufficient, we might need even more frequent verification or immediate verification when specific events are detected.

Next Steps

  • [ ] Analyze logs of the 3 ROMs to identify VRAM loading and cleaning patterns
  • [ ] If the cause of the problem is identified: Implement solution to maintain tiles or update tilemap correctly (Step 0328)
  • [ ] If the problem persists: Deeper Analysis and Workaround (Step 0328)
  • [ ] Final rendering check when issue is resolved (Step 0329)