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.
Step 0333: Corrección de Renderizado Basada en Diagnóstico
Resumen
Este step implementa correcciones críticas en la configuración del logger y el código de diagnóstico
para identificar dónde se pierde la información de color en el pipeline de renderizado. Se agregó
configuración explícita del logger para asegurar que los logs de nivel INFO aparezcan correctamente,
se implementaron logs con print() como fallback para garantizar visibilidad, y se
mejoró el código de diagnóstico para ejecutarse tanto cuando el framebuffer se recibe como parámetro
como cuando se obtiene directamente desde la PPU.
Concepto de Hardware
Pipeline de Renderizado Python
El pipeline de renderizado en Viboy Color sigue esta secuencia:
- C++ (PPU): Escribe índices de color (0-3) en el framebuffer
- Cython: Expone el framebuffer como memoryview
- Python (viboy.py): Copia el framebuffer a bytearray (snapshot inmutable)
- Python (renderer.py): Convierte índices a RGB usando la paleta
- Pygame: Dibuja los píxeles RGB en la pantalla
El problema identificado en el Step 0332 es que el framebuffer en C++ contiene datos correctos (80/160 píxeles no-blancos según logs de C++), pero la pantalla se muestra completamente blanca. Esto sugiere que la información de color se pierde en algún punto del pipeline Python.
Configuración del Logger
El logger de Python debe estar configurado correctamente para mostrar logs de nivel INFO. Si el logger no está configurado o está configurado con un nivel más alto (WARNING, ERROR), los logs de diagnóstico no aparecerán, impidiendo identificar dónde se pierde la información.
Implementación
1. Configuración Explícita del Logger
Se agregó configuración explícita del logger en src/viboy.py para asegurar que
los logs de nivel INFO aparezcan correctamente:
# --- Step 0333: Configuración Explícita del Logger ---
# Asegurar que el logger muestra logs de nivel INFO
logging.basicConfig(
level=logging.INFO,
format='%(levelname)s: %(message)s',
force=True # Forzar reconfiguración si ya estaba configurado
)
# -------------------------------------------
El parámetro force=True asegura que la configuración se aplique incluso si el logger
ya estaba configurado previamente.
2. Logs con print() como Fallback
Se agregaron logs con print() además de logger.info() para asegurar
que los logs aparezcan incluso si hay problemas con la configuración del logger:
# --- Step 0333: Logs con print() como fallback ---
log_msg = f"[Renderer-Framebuffer-Diagnostic] Frame {self._framebuffer_diagnostic_count} | ..."
print(log_msg) # Fallback a print()
logger.info(log_msg) # Logger normal
# -------------------------------------------
3. Verificación de Ejecución del Código de Diagnóstico
Se agregaron logs de entrada al código de diagnóstico para verificar que se ejecuta correctamente. El código ahora verifica tanto cuando el framebuffer se recibe como parámetro como cuando se obtiene directamente desde la PPU:
# --- STEP 0333: Verificación de Ejecución del Código de Diagnóstico ---
if framebuffer_data is not None:
print(f"[Renderer-Diagnostic-Entry] Framebuffer recibido como parámetro, longitud: {len(framebuffer_data)}")
logger.info(f"[Renderer-Diagnostic-Entry] Framebuffer recibido como parámetro, longitud: {len(framebuffer_data)}")
diagnostic_data = framebuffer_data
else:
# Obtener desde PPU y verificar
if frame_indices is not None:
print(f"[Renderer-Diagnostic-Entry] Framebuffer obtenido desde PPU, longitud: {len(frame_indices)}")
logger.info(f"[Renderer-Diagnostic-Entry] Framebuffer obtenido desde PPU, longitud: {len(frame_indices)}")
diagnostic_data = frame_indices
# -------------------------------------------
4. Verificación de Dibujo de Píxeles
Se agregaron logs en el punto de dibujo de píxeles para verificar que los colores RGB son correctos antes de dibujarlos:
# --- STEP 0333: Verificación de Dibujo de Píxeles ---
if self._pixel_draw_check_count < 5:
self._pixel_draw_check_count += 1
test_pixels = [(0, 0), (80, 72), (159, 143)]
for x, y in test_pixels:
idx = y * 160 + x
if idx < len(frame_indices):
color_index = frame_indices[idx] & 0x03
rgb_color = palette[color_index]
print(f"[Renderer-Pixel-Draw] Pixel ({x}, {y}): index={color_index} -> RGB={rgb_color}")
logger.info(f"[Renderer-Pixel-Draw] Pixel ({x}, {y}): index={color_index} -> RGB={rgb_color}")
# -------------------------------------------
Decisiones de Diseño
- Doble logging (print + logger): Se usa tanto
print()comologger.info()para asegurar que los logs aparezcan incluso si hay problemas con la configuración del logger. - Variable diagnostic_data: Se usa una variable
diagnostic_dataque puede serframebuffer_dataoframe_indicespara unificar el código de diagnóstico. - Límite de logs: Los logs de diagnóstico se limitan a los primeros 5 frames para evitar saturar el contexto.
Archivos Afectados
src/viboy.py- Configuración explícita del logger y logs con print() como fallbacksrc/gpu/renderer.py- Mejoras en el código de diagnóstico y verificación de dibujo de píxeles
Tests y Verificación
Se recompiló el módulo C++ y se ejecutaron pruebas con las 5 ROMs según el plan:
- Compilación: Módulo C++ recompilado exitosamente sin errores
- Pruebas: Se ejecutaron pruebas con las 5 ROMs (pkmn.gb, tetris.gb, mario.gbc, pkmn-amarillo.gb, Oro.gbc)
- Logs: Los logs de diagnóstico ahora aparecen correctamente con la configuración explícita del logger
Comando de compilación:
python3 setup.py build_ext --inplace
Comando de prueba (ejemplo):
timeout 150 python3 main.py roms/pkmn.gb 2>&1 | tee logs/test_pkmn_step0333.log
Fuentes Consultadas
- Python Logging Documentation: https://docs.python.org/3/library/logging.html
- Step 0332: Investigación y Corrección del Renderizado de Framebuffer (anterior)
Integridad Educativa
Lo que Entiendo Ahora
- Configuración del Logger: El logger de Python debe configurarse explícitamente
para mostrar logs de nivel INFO. El parámetro
force=Trueasegura que la configuración se aplique incluso si el logger ya estaba configurado. - Pipeline de Renderizado: El pipeline de renderizado tiene múltiples puntos donde la información de color puede perderse. Los logs de diagnóstico ayudan a identificar exactamente dónde ocurre el problema.
- Doble Logging: Usar tanto
print()comologger.info()proporciona redundancia y asegura que los logs aparezcan incluso si hay problemas con la configuración del logger.
Lo que Falta Confirmar
- Análisis de Logs: Se necesita analizar los logs de diagnóstico de las 5 ROMs para identificar dónde se pierde la información de color en el pipeline.
- Corrección Específica: Una vez identificado el problema mediante los logs, se implementará la corrección específica en el Step 0334.
Hipótesis y Suposiciones
Se asume que el problema está en el pipeline Python (viboy.py → renderer.py) basándose en la evidencia de que el framebuffer en C++ contiene datos correctos pero la pantalla se muestra completamente blanca. Los logs de diagnóstico confirmarán o refutarán esta hipótesis.
Próximos Pasos
- [ ] Analizar logs de diagnóstico de las 5 ROMs para identificar dónde se pierde la información de color
- [ ] Implementar corrección específica basada en los hallazgos de los logs
- [ ] Verificar que el checkerboard temporal se muestra correctamente en todas las ROMs
- [ ] Step 0334: Verificación final de renderizado o análisis más profundo según los resultados