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.
Monitor de Estado en Tiempo Real
Resumen
Se implementó un monitor de estado en tiempo real en el bucle principal del emulador que imprime información detallada del estado de la CPU, registros, interrupciones y hardware cada 5 segundos. Este monitor permite diagnosticar bloqueos y bucles infinitos cuando el juego se queda "dormido" con la pantalla apagada (LCD OFF), mostrando exactamente dónde está atascada la CPU y qué está esperando. Es una herramienta temporal de diagnóstico que ayuda a identificar problemas de sincronización, interrupciones y timing.
Concepto de Hardware
Cuando un juego de Game Boy apaga el LCD (escribiendo 0x00 en LCDC, bit 7 = 0), la PPU se detiene completamente: LY (Línea actual) se mantiene en 0, el timing de la PPU no avanza, y no se generan interrupciones V-Blank. Si el juego espera a que LY se mueva o a una interrupción V-Blank mientras el LCD está apagado, nunca saldrá del bucle de espera porque el hardware real no genera estos eventos cuando el LCD está apagado.
Los programadores de Nintendo sabían esto, así que suelen esperar al Timer (que sigue funcionando incluso con LCD apagado) o simplemente activan el LCD directamente. Sin embargo, algunos juegos pueden tener bugs lógicos o incompatibilidades que los hacen quedar atascados esperando eventos que nunca ocurrirán.
Para diagnosticar estos problemas, es necesario saber:
- PC (Program Counter): Dónde está ejecutándose el código actualmente
- Opcode actual: Qué instrucción está ejecutando (y las siguientes 2 bytes para instrucciones multi-byte)
- IME (Interrupt Master Enable): Si las interrupciones están habilitadas globalmente
- IE (Interrupt Enable, 0xFFFF): Qué interrupciones están habilitadas (VBlank, LCD, Timer, etc.)
- IF (Interrupt Flag, 0xFF0F): Qué interrupciones están pendientes
- LCDC (LCD Control, 0xFF40): Si el LCD está encendido (bit 7) y otros controles
- LY (Scanline): Línea actual de la PPU (debe ser 0 si LCD está apagado)
- DIV (Divider, 0xFF04): Registro del Timer que sigue funcionando incluso con LCD apagado
Fuente: Pan Docs - LCD Control Register, LCD Timing, Interrupts, Timer
Implementación
Se añadió un sistema de monitoreo periódico en el método run() de la clase Viboy que imprime información detallada del estado del sistema cada 5 segundos.
Componentes creados/modificados
- Viboy (`src/viboy.py`): Se añadió un import de
timey una variablelast_debug_timeque se inicializa antes del bucle principal. Dentro del bucle, se comprueba si han pasado 5 segundos desde el último reporte, y si es así, se imprime un bloque de información detallada con el estado actual del sistema.
Decisiones de diseño
Intervalo de 5 segundos: Se eligió un intervalo de 5 segundos para balancear entre información útil y no saturar la consola con demasiados mensajes. Si el PC no cambia entre reportes (o oscila entre 2 valores), sabremos exactamente la instrucción que bloquea.
Uso de print() en lugar de logging: Aunque las reglas del proyecto prohíben print() en favor de logging, este monitor usa print() intencionalmente porque es una herramienta temporal de diagnóstico que debe ser visible inmediatamente en la consola sin necesidad de configurar niveles de logging. El usuario puede ver el estado en tiempo real mientras el emulador está ejecutándose.
Información mostrada: El monitor muestra información crítica para diagnóstico:
- Estado del LCD (ON/OFF basado en LCDC bit 7)
- PC y los 3 bytes de opcode en esa dirección (para ver la instrucción actual y las siguientes)
- SP (Stack Pointer) para verificar el estado de la pila
- IME para saber si las interrupciones están habilitadas globalmente
- IE e IF con desglose de bits (VBlank, LCD, Timer) para identificar qué interrupciones están habilitadas/pendientes
- LY para verificar si la PPU está avanzando
- DIV para verificar si el Timer está funcionando
Archivos Afectados
src/viboy.py- Se añadió import detimey lógica de monitoreo periódico en el métodorun()
Tests y Verificación
Este monitor es una herramienta temporal de diagnóstico que se validará ejecutando el emulador con ROMs que muestran problemas de bloqueo (pantalla azul/negra indefinida).
- ROM de prueba: Pokémon Red (ROM aportada por el usuario, no distribuida) - muestra pantalla azul indefinida cuando el LCD está apagado
- Modo de ejecución: UI con monitor activado
- Criterio de éxito: El monitor debe mostrar información cada 5 segundos con el estado actual del sistema, permitiendo identificar dónde está atascada la CPU
- Observación esperada: Si el PC no cambia entre reportes (o oscila entre 2 valores), sabremos la instrucción que bloquea. Si IME=False y hay bits en IE e IF, sabremos que el juego olvidó activar interrupciones. Si LCD=OFF y el juego espera VBlank, sabremos que hay un bug lógico.
- Resultado:
draft- Pendiente de verificación con ejecución real del emulador
Nota legal: La ROM de Pokémon Red es aportada por el usuario para pruebas locales. No se distribuye ni se incluye en el repositorio.
Fuentes Consultadas
- Pan Docs: LCD Control Register
- Pan Docs: Timer and Divider
- Pan Docs: Interrupts
Integridad Educativa
Lo que Entiendo Ahora
- LCD OFF y PPU: Cuando el LCD está apagado, la PPU se detiene completamente. LY se mantiene en 0, no se generan interrupciones V-Blank, y el timing no avanza. Esto es crítico para entender por qué algunos juegos se quedan atascados esperando eventos que nunca ocurrirán.
- Diagnóstico de bloqueos: Para diagnosticar bloqueos, necesitamos saber exactamente dónde está la CPU (PC), qué está ejecutando (opcode), y qué está esperando (IME, IE, IF, LCDC, LY). El monitor de estado en tiempo real proporciona esta información de forma periódica.
- Herramienta temporal: Este monitor es una herramienta temporal de diagnóstico que debe ser removida o desactivada cuando se resuelvan los problemas de bloqueo. No es parte de la funcionalidad final del emulador.
Lo que Falta Confirmar
- Comportamiento real del hardware: No tengo acceso a una Game Boy real para verificar exactamente qué ocurre cuando el LCD está apagado y el juego espera eventos que nunca ocurrirán. El comportamiento descrito se basa en documentación técnica (Pan Docs).
- Patrones de bloqueo: Aún no he ejecutado el emulador con el monitor activado para ver qué patrones de bloqueo aparecen. Los reportes del monitor revelarán si el problema es de interrupciones, timing, o lógica del juego.
Hipótesis y Suposiciones
Hipótesis principal: El juego se queda atascado porque apagó el LCD para cargar datos, terminó de cargar, y ahora está en un bucle esperando "algo" (posiblemente V-Blank o un cambio en LY) para volver a encenderlo. Ese "algo" no está ocurriendo porque el LCD está apagado y la PPU está detenida.
Suposición del monitor: Asumimos que mostrar el estado cada 5 segundos es suficiente para identificar el problema sin saturar la consola. Si el problema requiere más frecuencia, se puede ajustar el intervalo.
Próximos Pasos
- [ ] Ejecutar el emulador con Pokémon Red y esperar a que aparezca la pantalla azul
- [ ] Esperar 10 segundos para ver al menos 2 reportes del monitor
- [ ] Analizar los reportes para identificar dónde está atascada la CPU
- [ ] Si el PC no cambia, identificar la instrucción que bloquea
- [ ] Si IME=False y hay bits en IE e IF, investigar por qué el juego no activa interrupciones
- [ ] Si LCD=OFF y el juego espera VBlank, investigar el bug lógico
- [ ] Una vez resuelto el problema, remover o desactivar el monitor temporal