This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.
MBC1 Bank Audit and VRAM Loading
Technical Context
After implementing the V-Blank handler audit (Step 0281), we see that the game correctly jumps to interrupt vectors, but the screen still shows a solid color (DMG green). Analysis of the logs indicates that although the CPU is "alive", the actual game graphics are not being loaded into VRAM after the initial cleanup.
This Step focuses on auditing the Memory Bank Controller (MBC1), specifically ROM bank mapping and loading data into VRAM, to identify if the problem lies with incorrect mapping that is preventing the CPU from reading graphics data from the ROM.
Diagnostics Implementation
1. Monitor Readings in Upper Banks (0x4000-0x7FFF)
A monitor has been added[BANK-READ]inMMU::readwhich captures the first 20 readings in the switchable bank range. This allows us to verify that the CPU is trying to read from ROM and which bank is actually mapped.
// MMU.cpp
if (addr< 0x8000) {
size_t rom_addr = static_cast(bankN_rom_) * 0x4000 + (addr - 0x4000);
//...instrumentation...
printf("[BANK-READ] Read %04X (Bank:%d Offset:%04X) -> %02X on PC:0x%04X\n", ...);
}
2. Sniper Write to VRAM (Values != 0x00)
To avoid noise from VRAM cleaning routines (which write thousands of zeros), it has been implemented[VRAM-SNIPER]. This monitor only captures writes of non-zero values, which will tell us the exact moment when the game tries to load real tiles or background maps.
// MMU.cpp
if (addr >= 0x8000 && addr<= 0x9FFF && value != 0x00) {
printf("[VRAM-SNIPER] Write %04X=%02X PC:%04X (Bank:%d)\n", ...);
}
3. update_bank_mapping audit
The function has been implementedupdate_bank_mapping()to record each time the bank mapping (Bank 0 or Bank N) changes. This is vital to confirm that the MBC1 is operating in the correct mode and that the bench calculations (including normalization) are accurate.
// MMU.cpp
if (old_bank0 != bank0_rom_ || old_bankN != bankN_rom_) {
printf("[BANK-AUDIT] Mapping change: Bank0:%d->%d | BankN:%d->%d (MBC1 Mode:%d) on PC:0x%04X\n", ...);
}
Academic Concepts
MBC1 ROM Banking:The MBC1 allows up to 2MB of ROM to be addressed by dividing it into 16KB banks. The 0x0000-0x3FFF area is usually fixed to Bank 0, while 0x4000-0x7FFF can switch between the remaining banks. A common error in emulators is not correctly handling the "mode" of the MBC1, which can cause Bank 0 to be replaced, breaking access to the interrupt vectors.
VRAM Timing:Games often load data into VRAM during the V-Blank period or when the LCD is off. If the CPU is stuck in a loop waiting for an interrupt that never happens (or happens but isn't communicated), VRAM loading will never happen.
Testing and Verification
Command: python main.py roms/pkmn.gb > report2.md 2>&1
Results in report2.md:
[BANK-AUDIT]: Will confirm if the game changes banks after initialization.[BANK-READ]: Will check if ROM reads return valid data (other than 0xFF/0x00).[VRAM-SNIPER]: If this log does not appear, we confirm that the game NEVER attempts to load real graphics, suggesting a previous logical crash.