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

ROM Read Probe

Date:2025-12-23 StepID:0262 State: draft

Summary

This Step implements the methodMMU::read()to monitor readings in the switched ROM area (0x4000-0x7FFF). Step 0261 confirmed that MBC1 works (we see bank changes), but VRAM writes are still zero. The hypothesis is thatMMU::read()It could be returning zeros when reading from the switched bank, even though the bank switch is recorded correctly. This instrumentation will allow us to verify what values ​​the MMU is actually returning when the game reads from the selected ROM banks.

Hardware Concept

Reading Switched ROM:When a game needs to access data stored in ROM banks other than bank 0, it first selects the bank by writing to0x2000-0x3FFF, and then read from0x4000-0x7FFF. The MBC1 maps the selected bank to this memory space, allowing the game to access up to 16KB of data from the chosen bank.

The problem of zeros in VRAM:If the game switches banks correctly (we see switch logs in Step 0261), but the writes to VRAM are still zero, there are two possibilities:

  1. The game is intentionally clearing VRAM:Some games write zeros to VRAM before copying the actual graphics to ensure the area is clean.
  2. Switched bank reading returns zeros:YeahMMU::read()is returning zeros when reading from0x4000-0x7FFF, the game will copy those zeros to VRAM, resulting in a blank screen.

ROM reading probe:To distinguish between these cases, we need to check what value it is actually returningMMU::read()when the game reads from the switched area. If it returns zeros (or0xFF), our reading logicrom_data_is failing. If it returns varied values ​​(0x3E, 0xCD, etc.), then the reading is correct and the problem is somewhere else (possibly in the data copy logic to VRAM or in the timing).

Fountain:Pan Docs - "MBC1", "Memory Bank Controllers", "Memory Map"

Implementation

The method was modifiedread()ofMMU.cppto record the first 50 readings of the switched ROM area (0x4000-0x7FFF). The log includes the current Program Counter (PC), the address read, the current bank, the offset calculated inrom_data_, and the returned value.

Modified components

  • MMU::read(): Added static counterrom_read_counterto limit the logs to the first 50 readings (avoiding saturating the output). The log is printed before the value is returned, showing exactly what the game is reading and what value is being returned.

Design decisions

Limit of 50 readings:To avoid flooding the logs with thousands of reads, we limit logging to the first 50. This is enough to verify if the read is working correctly during game initialization, when the main graphics load.

Complete information in the log:The log includes the current PC (to correlate with the game instructions), the address read, the current bank, the offset calculated inrom_data_, and the returned value. This allows us to verify if the offset calculation is correct and if the returned value corresponds to the real data in the ROM.

Log after offset calculation:The log is printed after calculating the offset but before returning the value, ensuring that we see exactly what value is being returned to the game.

Affected Files

  • src/core/cpp/MMU.cpp- Modified methodread()to log the first 50 reads of the switched ROM area (Step 0262).

Tests and Verification

To validate this instrumentation:

  1. Recompile: .\rebuild_cpp.ps1
  2. Execute: python main.py roms/pkmn.gb(Pokémon Red is ideal because it has 1024KB of ROM and requires multiple banks).
  3. Observe the logs:
    • Look for[ROM-READ] PC:XXXX -> Read ROM[YYYY] (Bank N, Offset ZZZZ) = VV- Shows what the game is reading and what value is being returned.
    • If Val = 00:The readout is returning zeros, indicating a failure in ROM loading or offset calculation. The vectorrom_data_could be empty or the calculated offset could be out of range.
    • If Val varied (3E, CD, etc.):The read is correct and is returning real data from the ROM. In this case, if the VRAM is still empty, the problem is somewhere else (possibly in the data copy logic to VRAM or in the timing).

Expected validation:If MBC1 is working correctly and the ROM is loaded, you should see varying values ​​(not just zeros) in the switched area readings. If all values ​​are zeros, there is a problem in ROM loading or offset calculation.

Correlation with VRAM:If the ROM reads return varying values ​​but the VRAM writes are still zero, the problem is with the data copy logic to VRAM or the timing (the game could be clearing the VRAM before copying the actual graphics).

Sources consulted

Educational Integrity

What I Understand Now

  • Reading Switched ROM:When the game reads from0x4000-0x7FFF, MBC1 maps the selected bank to this space. The offset calculation is(bank * 0x4000) + (addr - 0x4000).
  • Reading diagnosis:If the game changes banks but the writes to VRAM are still zeros, we need to check if the read is returning the correct data or if it is returning zeros.
  • Data validation:If the ROM reads return varying values, the read is correct and the problem lies elsewhere. If they return zeros, there is a problem with the ROM loading or offset calculation.

What remains to be confirmed

  • Return values:What values ​​are you actually returningMMU::read()when the game reads from the switched area? The logs will tell us if it returns zeros or varied values.
  • Correlation with VRAM:If the ROM reads return varied values ​​but the VRAM is still empty, is the problem in the data copy logic to VRAM or in the timing?
  • Intentional Cleaning:Is the game intentionally writing zeros to VRAM before copying the actual graphics? If so, we need to wait more time to see the real data.

Hypotheses and Assumptions

Main hypothesis:If MBC1 works (we see bank changes in Step 0261) but the writes to VRAM are still zero, it is possible that:

  1. Switched bank reading returns zeros:YeahMMU::read()is returning zeros when reading from0x4000-0x7FFF, the game will copy those zeros to VRAM. This would indicate a failure in the ROM loading or offset calculation.
  2. The game is intentionally clearing VRAM:Some games write zeros to VRAM before copying the actual graphics. If this is the case, we need to wait longer to see the actual data.
  3. The reading is correct but the problem is elsewhere:If the ROM readings return varied values ​​but the VRAM is still empty, the problem is in the data copy logic to VRAM or in the timing.

This instrumentation will allow us to distinguish between these cases and determine where the real problem is.

Next Steps

  • [ ] Executepython main.py roms/pkmn.gband observe the ROM reading logs.
  • [ ] If the readings return zeros, check the ROM loading and offset calculation.
  • [ ] If the readings return varied values, check the data copy logic to VRAM or the timing.
  • [ ] Correlate ROM reads with VRAM writes to determine if the correct data is reaching VRAM.
  • [ ] If the game is clearing the VRAM intentionally, wait longer to see the actual data.