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.
MBC Unificado & Instrumentación VRAM/WRAM
Resumen
Se unificó el soporte de controladores de banco (MBC) en la MMU C++ para ROM_ONLY, MBC1, MBC2, MBC3 y MBC5, dimensionando la RAM externa según el header y normalizando bancos de ROM/RAM. Se añadieron trazas ligeras para detectar escrituras/lecturas a 0xD732, VRAM y solicitudes/servicio de interrupciones.
El monitor GPS ahora separa VRAM_TILE_SUM (0x8000-0x97FF) de VRAM_MAP_SUM (0x9800-0x9FFF) y reporta 0xD732 en caliente. Resultado actual (Pokémon Red): VBlank se solicita y atiende, D732 solo se escribe con 00, se detecta un barrido de escrituras de VRAM llenando de ceros la tile data desde PC=0x36E3, y el tilemap sigue lleno de 0x7F (pantalla verde).
Concepto de Hardware
Los MBC (Memory Bank Controllers) permiten a cartuchos de >32KB exponer bancos de ROM/RAM conmutables. MBC1 combina bits bajos/altos y modo ROM/RAM; MBC2 trae RAM interna de 512x4 bits; MBC3 añade RTC y bancos de RAM seleccionables; MBC5 extiende a 9 bits de banco de ROM y hasta 16 bancos de RAM.
Instrumentar VRAM y flags de estado (ej. 0xD732) es clave para verificar si la CPU está copiando gráficos (tile data) o solo modificando el tilemap. Separar tile data vs tilemap ayuda a localizar la causa de pantalla verde cuando el mapa cambia pero los tiles no.
Implementación
En MMU.cpp/MMU.hpp se añadieron campos de estado para cada MBC, cálculo de bancos desde el header, asignación de RAM por tamaño declarado y mapeo de bancos bank0_rom/bankN_rom. Se implementaron rutas de escritura para enable de RAM, selección de banco de ROM/RAM (MBC1/2/3/5) y stub de RTC en MBC3. Se normalizan bancos contra el total cargado para evitar lecturas fuera de rango.
Se instrumentaron las primeras escrituras/lecturas a 0xD732 y VRAM (0x8000-0x9FFF) para detectar actividad real. En viboy.py el GPS ahora reporta sumas separadas de tile data y tilemap, más la lectura de D732 cada segundo.
Componentes creados/modificados
src/core/cpp/MMU.hpp / MMU.cpp– Soporte MBC1/2/3/5 unificado, asignación dinámica de RAM, logs de VRAM/WRAM.src/viboy.py– GPS ampliado conVRAM_TILE_SUM,VRAM_MAP_SUMy lectura de0xD732.
Decisiones de diseño
Se mantuvo el estado por-MBC para no romper compatibilidad con cartuchos pequeños (ROM_ONLY) y se limitaron los logs a los primeros accesos para no inundar la salida en modo --verbose. Se priorizó visibilidad sobre corrección visual mientras se diagnostica la falta de escrituras de tile data.
Archivos Afectados
src/core/cpp/MMU.hpp– Nuevos campos de estado y helpers de MBC/RAM.src/core/cpp/MMU.cpp– Lógica de banking unificada, asignación de RAM, logs VRAM/WRAM.src/viboy.py– Métricas de VRAM separadas y lectura deD732en GPS.
Tests y Verificación
- ROM:
python main.py roms/pkmn.gb --verbose(10-15s). Observado:VRAM_TILE_SUM=0,VRAM_MAP_SUM=16256,D732=00, PC en 0x615x; VBlank IRQs solicitadas/atendidas; escritura masiva de 0x00 en VRAM tile data desde PC=0x36E3; tilemap permanece en 0x7F. - Rebuild:
rebuild_cpp.ps1tras cada cambio en C++. - VRAM inicial: PyMMU + cartucho: 0x8000/0x9800 arrancan en 0x00 (confirmado que el llenado de 0x7F ocurre en runtime, no en la carga).
Fuentes Consultadas
- Pan Docs – Secciones: MBC1, MBC2, MBC3, MBC5, Memory Map.
- Pan Docs – LCD Control, VRAM layout (tile data 0x8000-0x97FF, tilemaps 0x9800/0x9C00).
Integridad Educativa
Lo que Entiendo Ahora
- Pokémon Red (tipo 0x13) usa MBC3: necesita bancos de ROM altos y RAM con enable.
- El tilemap se está llenando (0x7F); la tile data se sobrescribe con ceros desde PC=0x36E3, lo que explica la pantalla verde.
0xD732permanece en 0, solo escrito con 0x00 en PC=0x1F80.- VBlank se solicita y se atiende (logs en IRQ/VBlank), por lo que las interrupciones básicas están vivas.
Lo que Falta Confirmar
- Quién y por qué limpia la tile data a 0x00 en PC=0x36E3 (desensamblar esa rutina y su banco).
- Quién debería setear
D732y en qué rutina (posible ISR o bucle de init).
Hipótesis y Suposiciones
El juego inicializa tilemap y luego limpia tile data (0x36E3) porque aún no ha ejecutado la rutina que copia los tiles reales; podría estar bloqueado esperando D732 antes de cargar gráficos o en otra rama de init.
Próximos Pasos
- [ ] Loguear escrituras a 0x9800-0x9FFF y 0x8000-0x97FF con un límite mayor para captar el primer copy.
- [ ] Desensamblar el bloque en 0x6150 (banco activo) y la rutina en 0x36E3 que limpia VRAM para ver condiciones de carga de tiles.
- [ ] Identificar cuándo debería escribirse
D732(ISR o bucle de init) y forzar un log allí.