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.
Fix de Instrumentación y Desbloqueo Visual
Resumen
Corrección crítica de la instrumentación del emulador para asegurar que los monitores de diagnóstico se ejecuten correctamente, incluso cuando hay interrupciones que causan early returns. Movimiento del bloque de Sniper del Handler ([HANDLER-EXEC]) al inicio de CPU::step() y implementación de un monitor liberal de escrituras en VRAM ([VRAM-VIBE]) para detectar cargas de gráficos reales. Verificación de que las escrituras en el rango 0x8000-0x9FFF se realicen correctamente en la memoria para que el PPU pueda leerlas.
Concepto de Hardware
En el hardware real de la Game Boy, la VRAM (Video RAM) es una región de memoria especial ubicada en el rango 0x8000-0x9FFF que contiene los datos de los tiles (gráficos) y los mapas de tiles que la PPU (Picture Processing Unit) lee para renderizar la pantalla. La VRAM es accesible tanto por la CPU (para escribir datos de gráficos) como por la PPU (para leer datos durante el renderizado).
Restricciones de Acceso a VRAM: En el hardware real, la VRAM solo es accesible por la CPU durante ciertos modos de la PPU (específicamente, durante V-Blank y H-Blank). Sin embargo, muchos emuladores modernos relajan esta restricción para simplificar la implementación, permitiendo escrituras en VRAM en cualquier momento. Este emulador sigue este enfoque más permisivo.
Detección de Datos Reales: Cuando un juego carga gráficos en VRAM, típicamente escribe valores distintos de 0x00 (blanco) y 0x7F (un valor común de inicialización). Un monitor "liberal" filtra estos valores comunes y solo reporta escrituras que probablemente contengan datos de gráficos reales.
Fuente: Pan Docs - "VRAM (Video RAM)": 0x8000-0x9FFF contiene Tile Data (0x8000-0x97FF) y Tile Maps (0x9800-0x9FFF).
Implementación
Se realizaron tres cambios principales para mejorar la instrumentación y asegurar la correcta escritura en VRAM:
1. Movimiento del Bloque de Sniper del Handler
El bloque de instrumentación [HANDLER-EXEC] que rastrea la ejecución del handler de V-Blank fue movido desde el final de CPU::step() (después del switch de opcodes) al inicio del método, justo después de capturar el PC original. Esto asegura que el monitor se ejecute incluso cuando hay interrupciones que causan early returns antes de llegar al switch.
Motivación: El código original estaba ubicado después del switch de opcodes, lo que significaba que si una interrupción causaba un early return (línea 518-520), el monitor nunca se ejecutaba. Al moverlo al inicio, garantizamos que se ejecute en cada llamada a step(), independientemente de si hay interrupciones.
2. Monitor Liberal de Escrituras en VRAM ([VRAM-VIBE])
Se implementó un nuevo monitor en MMU::write() que detecta escrituras en VRAM (0x8000-0x9FFF) filtrando valores comunes de inicialización (0x00 y 0x7F). El monitor reporta hasta 200 escrituras que probablemente contengan datos de gráficos reales.
Características:
- Filtra valores 0x00 (blanco) y 0x7F (inicialización común)
- Reporta valores distintos que probablemente sean datos de gráficos reales
- Límite de 200 reportes para evitar saturación de logs
- Incluye información de PC, banco ROM y dirección/valor escrito
3. Verificación de Escrituras en VRAM
Se añadió una verificación explícita en el código para asegurar que las escrituras en el rango 0x8000-0x9FFF se realicen correctamente en la memoria. Aunque la escritura directa en memory_[addr] se hace al final de la función, se añadió un comentario y verificación explícita para garantizar que el PPU pueda leer los datos escritos.
Componentes modificados
- CPU.cpp: Movido el bloque [HANDLER-EXEC] al inicio de step(), después de capturar original_pc y antes de handle_interrupts(). Eliminado el bloque duplicado del final del método.
- MMU.cpp: Implementado el monitor [VRAM-VIBE] en MMU::write() que detecta escrituras en VRAM con valores distintos de 0x00 y 0x7F. Añadida verificación explícita de que las escrituras en VRAM se realizan correctamente.
Decisiones de diseño
Monitor Liberal: Se eligió un enfoque "liberal" para el monitor de VRAM porque los valores 0x00 y 0x7F son muy comunes en inicialización y borrado de memoria, pero no representan datos de gráficos reales. Filtrar estos valores reduce el ruido en los logs y permite enfocarse en escrituras que probablemente contengan datos de gráficos reales.
Ubicación del Monitor del Handler: Se movió al inicio de step() para garantizar su ejecución en cada ciclo, incluso cuando hay interrupciones. Esto es crítico para el diagnóstico porque el handler de V-Blank es una parte esencial del flujo de renderizado.
Archivos Afectados
src/core/cpp/CPU.cpp- Movimiento del bloque [HANDLER-EXEC] al inicio de step()src/core/cpp/MMU.cpp- Implementación del monitor [VRAM-VIBE] y verificación de escrituras en VRAM
Tests y Verificación
La implementación fue verificada mediante:
- Compilación exitosa: El código C++ se compiló sin errores usando
python setup.py build_ext --inplace - Validación de sintaxis: No se encontraron errores de linter en los archivos modificados
- Validación de módulo compilado C++: La extensión Cython se compiló correctamente y está lista para uso
Nota: Los tests funcionales se realizarán en ejecuciones posteriores del emulador para verificar que los monitores capturan correctamente la actividad del handler y las escrituras en VRAM.
Fuentes Consultadas
- Pan Docs: VRAM (Video RAM) - Rango 0x8000-0x9FFF contiene Tile Data y Tile Maps
- Pan Docs: Interrupt Vectors - Vector 0x0040 es el handler de V-Blank
Integridad Educativa
Lo que Entiendo Ahora
- Early Returns en Instrumentación: Los early returns (como los causados por interrupciones) pueden hacer que el código de instrumentación ubicado después del return nunca se ejecute. Es crítico colocar los monitores de diagnóstico antes de cualquier posible early return.
- Filtrado de Valores Comunes: En instrumentación, es útil filtrar valores comunes de inicialización (como 0x00 y 0x7F) para reducir el ruido en los logs y enfocarse en datos que probablemente sean significativos.
- Acceso a VRAM: Aunque el hardware real tiene restricciones de acceso a VRAM basadas en el modo de la PPU, muchos emuladores permiten escrituras en cualquier momento para simplificar la implementación.
Lo que Falta Confirmar
- Efectividad del Monitor [VRAM-VIBE]: Necesitamos verificar en ejecuciones reales si el monitor captura correctamente las cargas de gráficos y si el filtrado de valores comunes es efectivo.
- Impacto en Rendimiento: Aunque el monitor tiene un límite de 200 reportes, necesitamos verificar que no afecte significativamente el rendimiento del emulador.
Hipótesis y Suposiciones
Suposición sobre Valores de Inicialización: Asumimos que los valores 0x00 y 0x7F son comunes en inicialización y borrado de memoria, pero esto se basa en observaciones empíricas. Si encontramos que otros valores son más comunes, podemos ajustar el filtro.
Próximos Pasos
- [ ] Ejecutar el emulador con una ROM de test para verificar que los monitores [HANDLER-EXEC] y [VRAM-VIBE] capturan correctamente la actividad
- [ ] Analizar los logs generados para identificar patrones en las escrituras de VRAM
- [ ] Verificar que las escrituras en VRAM se reflejan correctamente en el renderizado de la PPU
- [ ] Ajustar el filtro del monitor [VRAM-VIBE] si es necesario basándose en los datos observados