Este proyecto es educativo y Open Source. No se copia código de otros emuladores. Implementación basada únicamente en documentación técnica y tests permitidas.
Validar Diagnóstico VRAM RAW + Headless + Mapping Bancos
Resumen
Validación del diagnóstico de VRAM RAW, headless trust test y herramientas de prueba de mapping MBC.
Se confirmó que VRAM está almacenada en bancos separados (vram_bank0_, vram_bank1_) en MMU,
se corrigió read_raw() para leer correctamente de los bancos VRAM, se creó test de validación write→read_raw,
se creó herramienta de headless trust test y se creó herramienta de MBC bank probe para validar mapping determinista.
Hallazgo clave: VRAM storage confirmado en MMU (no en PPU), read_raw() funciona correctamente,
y las herramientas de diagnóstico están listas para validar mapping MBC y confiabilidad de headless.
Concepto de Hardware
En Game Boy Color (CGB), la VRAM (Video RAM) está dividida en dos bancos de 8KB cada uno (total 16KB):
- VRAM Bank 0 (0x8000-0x9FFF): Tile Data y Tile Map base
- VRAM Bank 1 (0x8000-0x9FFF): Tile Data alternativo y atributos de Tile Map (CGB)
El registro VBK (0xFF4F) bit 0 selecciona qué banco ve la CPU. El PPU puede acceder a ambos bancos simultáneamente durante el renderizado. En modo DMG (Game Boy clásico), solo se usa Bank 0.
Diagnóstico RAW: Para diagnóstico confiable, necesitamos leer VRAM directamente sin restricciones de modo PPU.
read_raw() debe leer de los bancos VRAM correctos (vram_bank0_, vram_bank1_) cuando la dirección
está en el rango 0x8000-0x9FFF, no de memory_[] que no contiene el contenido de VRAM.
Fuente: Pan Docs - "CGB Registers", "VRAM Banks", "FF4F - VBK - VRAM Bank"
Implementación
Se implementaron tres fases del plan:
Fase A: Verificar Dónde Está VRAM Realmente
Se localizó el storage de VRAM usando grep sobre el código C++:
- Hallazgo: VRAM está en
MMUcomovram_bank0_yvram_bank1_(vectores de 0x2000 bytes cada uno) - NO está en PPU: PPU no tiene arrays propios de VRAM, solo lee desde MMU usando
read_vram_bank() - Problema identificado:
read_raw()leía dememory_[]que no contiene VRAM
Fase B: Corregir read_raw() para Leer de Bancos VRAM
Se modificó MMU::read_raw() en src/core/cpp/MMU.cpp para leer de los bancos VRAM cuando la dirección
está en el rango 0x8000-0x9FFF:
uint8_t MMU::read_raw(uint16_t addr) const {
// Step 0452: VRAM está en bancos separados (vram_bank0_, vram_bank1_)
// Para diagnóstico confiable, read_raw() debe leer de los bancos VRAM
if (addr >= 0x8000 && addr <= 0x9FFF) {
uint16_t offset = addr - 0x8000;
if (vram_bank_ == 0 && offset < vram_bank0_.size()) {
return vram_bank0_[offset];
} else if (vram_bank_ == 1 && offset < vram_bank1_.size()) {
return vram_bank1_[offset];
}
return 0xFF;
}
if (addr >= MEMORY_SIZE) {
return 0xFF;
}
return memory_[addr];
}
Fase C: Crear Test de Validación write→read_raw
Se creó tests/test_vram_raw_write_read_0452.py con tres tests:
- test_vram_write_read_raw_mmu: Valida que escribir a VRAM y leer con
read_raw()funciona - test_vram_write_read_raw_range: Valida que
dump_raw_range()funciona correctamente - test_vram_nonzero_sampling: Valida que podemos detectar bytes non-zero en VRAM usando
read_raw()
Resultado: Todos los tests pasan correctamente ✅
Fase D: Crear Herramientas de Diagnóstico
Se crearon dos herramientas:
- tools/test_headless_trust_0452.py: Headless trust test que valida que headless reporta correctamente con ROM clean-room
- tools/mbc_bank_probe_0452.py: MBC bank probe que prueba mapping MBC determinista comparando bytes leídos con ROM real
Corrección de dump_raw_range() en Cython
Se corrigió dump_raw_range() en src/core/cython/mmu.pyx para manejar correctamente la conversión de bytes:
def dump_raw_range(self, uint16_t start, uint16_t length):
# ... código de asignación de buffer ...
try:
self._mmu.dump_raw_range(start, length, buffer)
# Convert to Python bytes by creating a list and converting to bytes
result_list = []
for i in range(length):
result_list.append(buffer[i])
return bytes(result_list)
finally:
free(buffer)
Archivos Afectados
src/core/cpp/MMU.cpp- Modificadoread_raw()para leer de bancos VRAMsrc/core/cython/mmu.pyx- Corregidodump_raw_range()para conversión de bytestests/test_vram_raw_write_read_0452.py- Creado test de validación write→read_rawtools/test_headless_trust_0452.py- Creado headless trust testtools/mbc_bank_probe_0452.py- Creado MBC bank probe
Tests y Verificación
Tests unitarios:
$ python3 -m pytest tests/test_vram_raw_write_read_0452.py -v
tests/test_vram_raw_write_read_0452.py::test_vram_write_read_raw_mmu PASSED
tests/test_vram_raw_write_read_0452.py::test_vram_write_read_raw_range PASSED
tests/test_vram_raw_write_read_0452.py::test_vram_nonzero_sampling PASSED
✅ 3 passed in 0.30s
Validación de módulo compilado C++: Todos los tests pasan, confirmando que read_raw()
lee correctamente de los bancos VRAM y que dump_raw_range() funciona correctamente.
Código del Test:
def test_vram_write_read_raw_mmu():
"""Valida que escribir a VRAM y leer con read_raw funciona."""
mmu = PyMMU()
ppu = PyPPU(mmu)
mmu.set_ppu(ppu)
# Escribir patrón no-cero en 0x8000-0x8010
pattern = [0xAA, 0xBB, 0xCC, 0xDD]
for i, byte_val in enumerate(pattern):
mmu.write(0x8000 + i, byte_val)
# Leer con read_raw (VRAM está en MMU)
for i, expected in enumerate(pattern):
actual = mmu.read_raw(0x8000 + i)
assert actual == expected, (
f"VRAM write→read_raw falló en 0x{0x8000+i:04X}: "
f"esperado 0x{expected:02X}, obtenido 0x{actual:02X}"
)
print("✅ MMU.write→read_raw funciona correctamente")
Fuentes Consultadas
- Pan Docs: "CGB Registers", "VRAM Banks", "FF4F - VBK - VRAM Bank"
- Implementación basada en análisis del código C++ existente (MMU.cpp, PPU.hpp)
Integridad Educativa
Lo que Entiendo Ahora
- VRAM Storage: VRAM está en MMU como bancos separados (
vram_bank0_,vram_bank1_), no enmemory_[]ni en PPU. Esto es crítico para diagnóstico confiable. - read_raw() vs read():
read_raw()debe leer directamente de los bancos VRAM cuando la dirección está en 0x8000-0x9FFF, no dememory_[].read()hace mapping dinámico de ROM pero no es útil para diagnóstico RAW de VRAM. - Diagnóstico Confiable: Para validar que VRAM tiene datos, necesitamos
read_raw()que lea directamente de los bancos VRAM sin restricciones de modo PPU.
Lo que Falta Confirmar
- Headless Trust Test: Validar que headless reporta correctamente con ROM clean-room (ejecutado en Step 0453)
- MBC Bank Probe: Validar que el mapping MBC funciona correctamente comparando bytes leídos con ROM real (ejecutado en Step 0453)
Hipótesis y Suposiciones
Se asume que los bancos VRAM (vram_bank0_, vram_bank1_) son la fuente de verdad para VRAM.
Esto se confirmó mediante análisis del código C++ y tests de validación write→read_raw.
Próximos Pasos
- [x] Validar VRAM storage (MMU vs PPU)
- [x] Corregir read_raw() para leer de bancos VRAM
- [x] Crear test write→read_raw
- [x] Crear headless trust test
- [x] Crear MBC bank probe
- [ ] Ejecutar headless trust test y MBC bank probe (Step 0453)
- [ ] Analizar resultados y decidir causa raíz (mapping vs CPU/IRQ vs PPU/paletas)