⚠️ 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.

El Regreso del Estetoscopio: ¿Dónde está la CPU?

Fecha: 2025-12-22 Step ID: 0230 Estado: DRAFT

Resumen

A pesar de que el emulador corre a velocidad real tras eliminar los logs (Step 0229), la pantalla sigue mostrando el color de fondo (verde/blanco) y no hay gráficos. Esto indica que la PPU está apagada (LCDC bit 7 = 0) o no está renderizando. Reactivamos el monitor de estado periódico ("Estetoscopio", Step 0222) para observar el Program Counter (PC) y el registro LCDC en tiempo real y determinar si el juego está atascado en un bucle de carga o si ha fallado silenciosamente.

Concepto de Hardware

Cuando un juego de Game Boy arranca, típicamente sigue esta secuencia:

  1. Inicialización: La CPU ejecuta código de inicialización desde la ROM del cartucho.
  2. Carga de gráficos: El juego copia los tiles desde la ROM a la VRAM (0x8000-0x9FFF).
  3. Configuración del TileMap: El juego escribe en el TileMap (0x9800-0x9BFF) para indicar qué tile dibujar en cada posición.
  4. Encendido del LCD: El juego activa el bit 7 del registro LCDC (0xFF40) para encender la pantalla.
  5. Bucle principal: El juego entra en su bucle principal, renderizando frames continuamente.

Si la pantalla sigue verde después de eliminar los logs, puede ser porque:

  • El juego apagó la pantalla: El registro LCDC tiene el bit 7 apagado (0x00-0x7F). Esto es normal durante la inicialización, pero el juego debería encenderla después.
  • El juego está copiando gráficos: El bucle de copia de tiles puede ser largo (cientos de frames). El juego puede tener la pantalla apagada mientras copia.
  • El juego está atascado: La CPU puede estar en un bucle infinito esperando algo (Timer, Joypad, interrupción).
  • El juego terminó y está esperando: El juego puede haber terminado su inicialización y estar esperando una interrupción para arrancar.

El "Estetoscopio" es un monitor de bajo impacto que imprime una línea de estado cada 60 frames (1 segundo). Esto nos permite observar los signos vitales del emulador sin afectar el rendimiento:

  • PC (Program Counter): Si cambia rápidamente, la CPU está corriendo. Si está fijo, hay un deadlock.
  • LCDC: Si el bit 7 está encendido (0x80-0xFF), el juego cree que la pantalla está encendida. Si está apagado (0x00-0x7F), el juego la tiene apagada.
  • TileMap[0x9904]: Si es 0x00, el TileMap está vacío. Si tiene valores, el juego ha configurado tiles.
  • TileData[0x8010]: Si es 0x00, la VRAM está vacía. Si tiene valores, el juego ha copiado gráficos.

Implementación

Se reactivó el bloque de diagnóstico del "Estetoscopio" (Step 0222) en el método run() de viboy.py. El código se ejecuta cada 60 frames (aproximadamente 1 segundo) y lee directamente del hardware los signos vitales.

Componentes modificados

  • src/viboy.py: Reactivado bloque de diagnóstico "El Estetoscopio" en el método run() (líneas ~819-834). El código estaba comentado desde el Step 0224.

Código implementado

# --- Step 0230: EL REGRESO DEL ESTETOSCOPIO ---
# Diagnóstico periódico (cada 60 frames = 1 segundo aprox)
# Reactivado para diagnosticar por qué la pantalla sigue verde tras eliminar los logs.
# Esto nos dirá si la CPU sigue corriendo, dónde está y el estado del LCD.
if self.frame_count % 60 == 0:
    if self._use_cpp:
        # Leer estado vital directamente del hardware
        pc = self._regs.pc
        lcdc = self._mmu.read(0xFF40)
        
        # Ver si hay datos en VRAM (Tile Map y Tile Data)
        tile_map_val = self._mmu.read(0x9904)
        tile_data_val = self._mmu.read(0x8010)
        
        print(f"[VITAL] PC: {pc:04X} | LCDC: {lcdc:02X} | Map[9904]: {tile_map_val:02X} | Data[8010]: {tile_data_val:02X}")
# ---------------------------------------------

Decisiones de diseño

Se eligió reactivar el Estetoscopio en lugar de instrumentar el código C++ porque:

  • Bajo impacto: Imprimir una línea cada segundo no afecta el rendimiento significativamente.
  • Información suficiente: El PC y el LCDC nos dirán si la CPU está corriendo y si el juego intenta encender la pantalla.
  • No requiere recompilación: El código está en Python, así que no necesitamos recompilar C++.

Archivos Afectados

  • src/viboy.py - Reactivado bloque de diagnóstico "El Estetoscopio" en el método run() (líneas ~819-834)

Tests y Verificación

Para validar el diagnóstico, ejecutar el emulador y observar la salida de la consola:

python main.py roms/tetris.gb

Cada segundo aparecerá una línea con el formato:

[VITAL] PC: 02B4 | LCDC: 91 | Map[9904]: 00 | Data[8010]: 00

Análisis de resultados:

  • Caso A (PC estático): Si el PC no cambia entre líneas (ej: siempre 02B4), la CPU está en un bucle infinito (deadlock). El juego está atascado esperando algo que nunca llega.
  • Caso B (PC cambiando, LCDC apagado): Si el PC cambia rápidamente (ej: 2B15, 0340, 2000...) pero el LCDC es 0x08 o 0x00 (bit 7 apagado), el juego está corriendo pero tiene la pantalla apagada voluntariamente. Puede estar copiando gráficos o esperando algo.
  • Caso C (PC cambiando, LCDC encendido, VRAM vacía): Si el PC cambia, el LCDC tiene el bit 7 encendido (0x91, 0x80...), pero Map[9904] y Data[8010] son 0x00, el juego cree que la pantalla está encendida pero no ha copiado los gráficos aún. Esto es normal durante la inicialización.
  • Caso D (PC cambiando, LCDC encendido, VRAM con datos): Si el PC cambia, el LCDC está encendido, y la VRAM tiene datos, el juego debería estar renderizando. Si no vemos gráficos, el problema está en el renderizado, no en la CPU.

Evidencia de Tests:

# Comando ejecutado:
python main.py roms/tetris.gb

# Resultado esperado:
# Cada segundo aparece una línea:
# [VITAL] PC: XXXX | LCDC: XX | Map[9904]: XX | Data[8010]: XX

# Validación:
# - Si PC cambia: CPU está corriendo ✅
# - Si PC está fijo: Deadlock ❌
# - Si LCDC bit 7 encendido: Juego intenta encender pantalla ✅
# - Si LCDC bit 7 apagado: Juego tiene pantalla apagada ⚠️

Fuentes Consultadas

Integridad Educativa

Lo que Entiendo Ahora

  • Diagnóstico no intrusivo: Un monitor de estado periódico puede proporcionar información valiosa sin afectar el rendimiento. Imprimir una línea cada segundo es insignificante comparado con imprimir en cada ciclo de CPU.
  • Signos vitales del emulador: El PC, LCDC y VRAM son indicadores clave del estado del sistema. Si el PC no cambia, la CPU está atascada. Si el LCDC tiene el bit 7 apagado, el juego tiene la pantalla apagada. Si la VRAM está vacía, los gráficos no se han copiado.
  • Balance entre diagnóstico y rendimiento: El Estetoscopio proporciona suficiente información para diagnosticar el problema sin saturar la consola ni afectar el rendimiento.

Lo que Falta Confirmar

  • Valores observados: Necesitamos ejecutar el emulador y observar qué valores muestra el diagnóstico para determinar si la CPU está corriendo, si el LCDC está configurado, y si la VRAM contiene datos.
  • Comportamiento del juego: Una vez que tengamos los valores del diagnóstico, podremos determinar si el problema es un deadlock, una configuración incorrecta del hardware, o simplemente que el juego aún no ha copiado los gráficos.

Hipótesis y Suposiciones

Hipótesis principal: El juego está corriendo correctamente pero tiene la pantalla apagada durante la inicialización. El Estetoscopio nos confirmará si el PC avanza (CPU corriendo) y si el LCDC cambia (juego intenta encender la pantalla). Si el PC está fijo, hay un deadlock que necesitamos investigar.

Próximos Pasos

  • [ ] Ejecutar el emulador y observar los valores del diagnóstico
  • [ ] Analizar los valores para determinar si la CPU está corriendo, si el LCDC está configurado, y si la VRAM contiene datos
  • [ ] Basado en el análisis, implementar la corrección correspondiente:
    • Si PC está fijo: Investigar deadlock (Timer, Interrupciones, Joypad)
    • Si PC cambia pero LCDC apagado: Esperar a que el juego encienda la pantalla o investigar por qué no lo hace
    • Si PC cambia, LCDC encendido, pero VRAM vacía: Investigar por qué el juego no copia gráficos
    • Si todo está bien pero no hay gráficos: Investigar el renderizado