This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.
Real Triage "I Don't See Graphics" (MBC Required + Raw VRAM + Functional Headless)
Summary
Implementation of robust diagnostic tools for real triage of the "I don't see graphs" problem. Added preflight check in headless to detect uncompiled C++ module, RAW reading API in MMU for unrestricted diagnosis, ROM header analysis tool to detect MBC support, and MBC writes counters for evidence of banking. Modified headless to use read_raw() in VRAMnz and generate summary of MBC writes. Objective: determine root cause (MBC/banking vs PPU/pallets vs CPU/IRQ) with reliable evidence.
Hardware Concept
Memory Bank Controllers (MBC): Game Boy cartridges use bench controllers memory to map large ROMs (>32KB) and external RAM into the 16-bit address space. Writes to ranges 0x0000-0x7FFF are interpreted as MBC commands (not ROM writes). Common types: MBC1 (0x01-0x03), MBC3 (0x0F-0x13), MBC5 (0x19-0x1E). If the emulator does not support the MBC required by the ROM, banking writes have no effect and the game cannot access ROM/RAM banks needed, resulting in incorrect execution or crash.
VRAM Access Restrictions: In PPU Mode 3 (data transfer to OAM), CPU cannot access VRAM (0x8000-0x9FFF). If a read is attempted, the hardware returns 0xFF. This can falsify diagnostics that use mmu.read() to measure VRAMnz. For reliable diagnosis, RAW access is needed that bypasses these restrictions.
ROM Header (0x0100-0x014F): Contains cartridge metadata: title (0x0134-0x0143), cartridge type (0x0147), ROM size (0x0148), RAM size (0x0149), CGB flag (0x0143). The type of cartridge determines which MBC is required.
Implementation
Implementation in 5 phases: preflight check, RAW API, ROM info, MBC counters, and headless modification.
Phase A: Headless "Lie Proof"
Added preflight check intools/rom_smoke_0442.pywhich verifies:
- Import of
viboy_coresuccessful - Instance creation
PyMMUsuccessful (detects linking errors)
If it fails, print clear error with compile instructions and exit code != 0. This prevents headless from generating false tables when the module is not compiled.
Phase B: RAW Reading API in MMU
Added methods in MMU C++ and Cython wrapper:
read_raw(uint16_t addr): Leememory_[]direct without restrictionsdump_raw_range(uint16_t start, uint16_t length, uint8_t* buffer): Fast memory range dump
WARNING: For diagnostics/tools only, NOT for normal emulation. Bypass restrictions in PPU mode, banking, etc.
Phase C: ROM Info Tool
Createdtools/rom_info_0450.pythat:
- Read ROM header (0x0100-0x014F)
- Extracts: title, cartridge type, MBC name, CGB flag, ROM/RAM sizes
- Detects if the emulator supports the required MBC (according to
SUPPORTED_MBCS) - Print table: ROM | cart_type(hex) | MBC name | CGB flag | supported
Phase D: MBC Writes Counters
Added counters in MMU for writes to MBC ranges (0x0000-0x7FFF):
mbc_write_count_: Total MBC writes- Ring buffer of last 8 writes: addr, val, PC
- Limited log (first 20) with identified range (RAM_EN, ROM_BANK, RAM_BANK, MODE)
- Method
log_mbc_writes_summary()for summary at the end of execution
Phase E: Headless Modification
Modifiedtools/rom_smoke_0442.py:
- Added method
_sample_vram_nonzero_raw()what does he useread_raw() - Metrics include both
vram_nonzero(normal) likevram_nonzero_raw(RAW) - Summary shows both metrics for comparison
- In the end, call
log_mbc_writes_summary()if available - Preliminary diagnostic compares normal VRAM vs RAW to detect access restrictions
Affected Files
tools/rom_smoke_0442.py- Preflight check, _sample_vram_nonzero_raw() method, RAW metrics, log MBC writessrc/core/cpp/MMU.hpp- read_raw(), dump_raw_range(), log_mbc_writes_summary() statements, MBC counterssrc/core/cpp/MMU.cpp- Implementation read_raw(), dump_raw_range(), log_mbc_writes_summary(), MBC counters logic in write()src/core/cython/mmu.pxd- Cython declarations of new methodssrc/core/cython/mmu.pyx- Python wrappers of read_raw(), dump_raw_range(), log_mbc_writes_summary()tools/rom_info_0450.py- New tool for ROM header analysis
Tests and Verification
Compilation:BUILD_EXIT=0, TEST_BUILD_EXIT=0
Preflight Check:Verified that headless fails correctly if module not compiled:
# Test: Try to run without compiling
python3 tools/rom_smoke_0442.py roms/mario.gbc
# Result: Clear error with instructions, exit code != 0
ROM Info Tool:Verified that it correctly detects MBC types:
# Test: Analyze ROMs
python3 tools/rom_info_0450.py roms/mario.gbc roms/pkmn.gb
# Result: Table with cart_type, MBC name, support
Native Validation:C++ module compiled successfully, RAW methods available in Python.
Sources consulted
- Bread Docs:Memory Bank Controllers (MBC1/MBC3/MBC5)
- Bread Docs:Cartridge Header (0x0100-0x014F)
- Bread Docs:VRAM Access Restrictions (Mode 3)
Educational Integrity
What I Understand Now
- MBC Writes: Writes to 0x0000-0x7FFF are MBC commands, not ROM writes. If the emulator does not support MBC, these writes have no effect and the game cannot access necessary banks.
- VRAM Access Restrictions: In PPU Mode 3, the CPU cannot read VRAM. For reliable diagnosis, RAW access is needed that bypasses these restrictions.
- ROM Header: The cartridge type (0x0147) determines which MBC is required. It is critical to verify support before executing.
What remains to be confirmed
- MBC Implementation: Verify which MBCs are actually implemented in the emulator (MBC1, MBC3, MBC5 according to code).
- VRAM RAW vs Normal: Run actual comparison to check if there is difference between read() and read_raw() in VRAMnz.
- MBC Write Patterns: Analyze patterns of MBC writes in real ROMs to determine if banking is working.
Hypotheses and Assumptions
Main Hypothesis: If a ROM requires unsupported MBC, banking writes have no effect, the game cannot access necessary ROM/RAM banks, and the framebuffer remains blank because the initialization code graph is on a non-accessible bench.
Assumption: read_raw()will be more reliable thanread()for diagnostic VRAMnz
because it bypasses PPU mode restrictions. This will be validated in real execution.
Next Steps
- [ ] Execute
tools/rom_info_0450.pyabout all ROMs to sort by MBC - [ ] Run headless with RAW VRAM and MBC writes for 4 ROMs (Mario, Pokémon, Tetris, Tetris DX)
- [ ] Analyze results: PC progresses + MBC writes exist + VRAM raw nonzero
- [ ] Determine root cause: MBC/banking vs PPU/pallets vs CPU/IRQ
- [ ] Step 0451: Implement missing MBC or fix identified bug