⚠️ Clean-Room / Educativo

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.

Triage Real "No Veo Gráficos" (MBC Requerido + VRAM Raw + Headless Funcional)

Fecha: 2026-01-02 Step ID: 0450 Estado: VERIFIED

Resumen

Implementación de herramientas de diagnóstico robustas para triage real del problema "no veo gráficos". Añadido preflight check en headless para detectar módulo C++ no compilado, API de lectura RAW en MMU para diagnóstico sin restricciones, herramienta de análisis de headers ROM para detectar soporte MBC, y contadores de writes MBC para evidencia de banking. Modificado headless para usar read_raw() en VRAMnz y generar resumen de MBC writes. Objetivo: determinar causa raíz (MBC/banking vs PPU/paletas vs CPU/IRQ) con evidencia confiable.

Concepto de Hardware

Memory Bank Controllers (MBC): Los cartuchos de Game Boy usan controladores de banco de memoria para mapear ROMs grandes (>32KB) y RAM externa en el espacio de direcciones de 16 bits. Los writes a rangos 0x0000-0x7FFF se interpretan como comandos MBC (no como escrituras a ROM). Tipos comunes: MBC1 (0x01-0x03), MBC3 (0x0F-0x13), MBC5 (0x19-0x1E). Si el emulador no soporta el MBC requerido por la ROM, los writes de banking no tienen efecto y el juego no puede acceder a bancos ROM/RAM necesarios, resultando en ejecución incorrecta o bloqueo.

Restricciones de Acceso a VRAM: En modo PPU Mode 3 (transferencia de datos a OAM), la CPU no puede acceder a VRAM (0x8000-0x9FFF). Si se intenta leer, el hardware devuelve 0xFF. Esto puede falsear diagnósticos que usan mmu.read() para medir VRAMnz. Para diagnóstico confiable, se necesita acceso RAW que bypass estas restricciones.

Header ROM (0x0100-0x014F): Contiene metadatos del cartucho: título (0x0134-0x0143), tipo de cartucho (0x0147), tamaño ROM (0x0148), tamaño RAM (0x0149), flag CGB (0x0143). El tipo de cartucho determina qué MBC se requiere.

Implementación

Implementación en 5 fases: preflight check, API RAW, ROM info, contadores MBC, y modificación headless.

Fase A: Headless "A Prueba de Mentiras"

Añadido preflight check en tools/rom_smoke_0442.py que verifica:

  • Import de viboy_core exitoso
  • Creación de instancia PyMMU exitosa (detecta errores de linking)

Si falla, imprime error claro con instrucciones de compilación y exit code != 0. Esto evita que headless genere tablas falsas cuando el módulo no está compilado.

Fase B: API de Lectura RAW en MMU

Añadidos métodos en MMU C++ y wrapper Cython:

  • read_raw(uint16_t addr): Lee memory_[] directo sin restricciones
  • dump_raw_range(uint16_t start, uint16_t length, uint8_t* buffer): Dump rápido de rango de memoria

WARNING: Solo para diagnóstico/tools, NO para emulación normal. Bypassa restricciones de modo PPU, banking, etc.

Fase C: ROM Info Tool

Creado tools/rom_info_0450.py que:

  • Lee header ROM (0x0100-0x014F)
  • Extrae: título, tipo cartucho, MBC name, CGB flag, tamaños ROM/RAM
  • Detecta si el emulador soporta el MBC requerido (según SUPPORTED_MBCS)
  • Imprime tabla: ROM | cart_type(hex) | MBC name | CGB flag | soportado

Fase D: Contadores de MBC Writes

Añadidos contadores en MMU para writes a rangos MBC (0x0000-0x7FFF):

  • mbc_write_count_: Total de writes MBC
  • Ring buffer de últimos 8 writes: addr, val, PC
  • Log limitado (primeras 20) con rango identificado (RAM_EN, ROM_BANK, RAM_BANK, MODE)
  • Método log_mbc_writes_summary() para resumen al final de ejecución

Fase E: Modificación Headless

Modificado tools/rom_smoke_0442.py:

  • Añadido método _sample_vram_nonzero_raw() que usa read_raw()
  • Métricas incluyen tanto vram_nonzero (normal) como vram_nonzero_raw (RAW)
  • Resumen muestra ambas métricas para comparación
  • Al final, llama a log_mbc_writes_summary() si está disponible
  • Diagnóstico preliminar compara VRAM normal vs RAW para detectar restricciones de acceso

Archivos Afectados

  • tools/rom_smoke_0442.py - Preflight check, método _sample_vram_nonzero_raw(), métricas RAW, log MBC writes
  • src/core/cpp/MMU.hpp - Declaraciones read_raw(), dump_raw_range(), log_mbc_writes_summary(), contadores MBC
  • src/core/cpp/MMU.cpp - Implementación read_raw(), dump_raw_range(), log_mbc_writes_summary(), lógica contadores MBC en write()
  • src/core/cython/mmu.pxd - Declaraciones Cython de nuevos métodos
  • src/core/cython/mmu.pyx - Wrappers Python de read_raw(), dump_raw_range(), log_mbc_writes_summary()
  • tools/rom_info_0450.py - Herramienta nueva para análisis de headers ROM

Tests y Verificación

Compilación: BUILD_EXIT=0, TEST_BUILD_EXIT=0

Preflight Check: Verificado que headless falla correctamente si módulo no compilado:

# Test: Intentar ejecutar sin compilar
python3 tools/rom_smoke_0442.py roms/mario.gbc
# Resultado: Error claro con instrucciones, exit code != 0

ROM Info Tool: Verificado que detecta correctamente tipos MBC:

# Test: Analizar ROMs
python3 tools/rom_info_0450.py roms/mario.gbc roms/pkmn.gb
# Resultado: Tabla con cart_type, MBC name, soporte

Validación Nativa: Módulo C++ compilado correctamente, métodos RAW disponibles en Python.

Fuentes Consultadas

Integridad Educativa

Lo que Entiendo Ahora

  • MBC Writes: Los writes a 0x0000-0x7FFF son comandos MBC, no escrituras a ROM. Si el emulador no soporta el MBC, estos writes no tienen efecto y el juego no puede acceder a bancos necesarios.
  • VRAM Access Restrictions: En modo PPU Mode 3, la CPU no puede leer VRAM. Para diagnóstico confiable, se necesita acceso RAW que bypass estas restricciones.
  • ROM Header: El tipo de cartucho (0x0147) determina qué MBC se requiere. Es crítico verificar soporte antes de ejecutar.

Lo que Falta Confirmar

  • MBC Implementation: Verificar qué MBCs están realmente implementados en el emulador (MBC1, MBC3, MBC5 según código).
  • VRAM RAW vs Normal: Ejecutar comparación real para verificar si hay diferencia entre read() y read_raw() en VRAMnz.
  • MBC Write Patterns: Analizar patrones de writes MBC en ROMs reales para determinar si banking está funcionando.

Hipótesis y Suposiciones

Hipótesis Principal: Si una ROM requiere MBC no soportado, los writes de banking no tienen efecto, el juego no puede acceder a bancos ROM/RAM necesarios, y el framebuffer queda blanco porque el código de inicialización gráfica está en un banco no accesible.

Suposición: read_raw() será más confiable que read() para diagnóstico VRAMnz porque bypassa restricciones de modo PPU. Esto se validará en ejecución real.

Próximos Pasos

  • [ ] Ejecutar tools/rom_info_0450.py sobre todas las ROMs para clasificar por MBC
  • [ ] Ejecutar headless con VRAM RAW y MBC writes para 4 ROMs (Mario, Pokémon, Tetris, Tetris DX)
  • [ ] Analizar resultados: PC progresa + MBC writes existen + VRAM raw nonzero
  • [ ] Determinar causa raíz: MBC/banking vs PPU/paletas vs CPU/IRQ
  • [ ] Step 0451: Implementar MBC faltante o corregir bug identificado