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 Signos Vitales en Tiempo Real
Resumen
Se implementó un monitor de signos vitales basado en tiempo real que funciona independientemente de los frames de la PPU. Este monitor imprime el estado del sistema (PC, LCDC, LY, ciclos totales) cada 1 segundo de tiempo real, incluso cuando el LCD está apagado y no se generan frames. Además, cuando el LCD está apagado, muestra el checksum de VRAM para diagnosticar si el juego está cargando gráficos. Se eliminó el monitor de arranque anterior (20 prints) para limpiar la salida.
Concepto de Hardware
El monitor de arranque anterior confirmó que la CPU ejecuta instrucciones correctamente (el PC avanza de 0x0100 a 0x1F68 y más allá). Sin embargo, cuando el LCD está apagado (`LCDC=00`), la PPU no avanza `LY` (se mantiene en 0), no se generan frames completos, y por tanto el "Heartbeat" basado en frames nunca aparece. El emulador está funcionando "en la oscuridad": el juego puede estar copiando datos a VRAM con la pantalla apagada (comportamiento correcto), pero no tenemos visibilidad de qué está ocurriendo.
Para diagnosticar el estado del emulador mientras la pantalla está apagada, necesitamos un monitor que funcione basado en tiempo real (segundos del reloj del sistema), no en frames. Este monitor debe mostrar:
- PC (Program Counter): Dónde está ejecutándose el código actualmente
- 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)
- Total de ciclos: Cuántos ciclos se han ejecutado desde el inicio
- VRAM Checksum: Suma de todos los bytes en VRAM (0x8000-0x9FFF) - si aumenta, el juego está cargando gráficos
Fuente: Pan Docs - LCD Control Register, VRAM Access
Implementación
Se modificó el método run() de la clase Viboy para añadir un monitor de signos vitales basado en tiempo real que funciona independientemente de los frames de la PPU.
Componentes modificados
- Viboy (`src/viboy.py`):
- Se eliminó el monitor de arranque anterior (contador
debug_step_countery los 20 prints de "BOOT STEP") - Se añadió una variable
last_realtime_log = time.time()antes del bucle principal - Dentro del bucle, después de ejecutar cada instrucción, se comprueba si han pasado 1.0 segundos desde el último reporte
- Si han pasado 1.0 segundos, se imprime un mensaje con el estado actual: PC, LCDC, LY, y total de ciclos
- Si el LCD está apagado (`LCDC & 0x80 == 0`), se muestra adicionalmente el checksum de VRAM para diagnosticar si el juego está cargando gráficos
- Se eliminó el monitor de arranque anterior (contador
Decisiones de diseño
Intervalo de 1.0 segundos: Se eligió un intervalo de 1 segundo para balancear entre información útil y no saturar la consola. Este intervalo es suficiente para ver si el PC está avanzando o estático, y si el VRAM checksum está aumentando (indicando carga de gráficos).
Uso de logging.info() en lugar de print(): Aunque el monitor de arranque usaba print() para garantizar visibilidad, este monitor usa logging.info() porque es menos intrusivo y permite controlar el nivel de logging. Si el usuario necesita visibilidad garantizada, puede configurar el nivel de logging a INFO.
Diagnóstico de VRAM cuando LCD está apagado: Cuando el LCD está apagado, el juego suele estar cargando datos gráficos en VRAM. Mostrar el checksum de VRAM permite verificar si el juego está realmente copiando datos o si está en un bucle infinito sin hacer nada. Si el checksum aumenta entre reportes, el juego está cargando gráficos. Si el checksum es 0 y no cambia, el juego está en un bucle infinito.
Eliminación del monitor de arranque: El monitor de arranque anterior (20 prints) era útil para diagnosticar deadlocks inmediatos, pero saturaba la consola. Ahora que sabemos que la CPU funciona correctamente, el monitor de tiempo real es más útil para diagnosticar problemas a largo plazo.
Archivos Afectados
src/viboy.py- Se eliminó el monitor de arranque y se añadió el monitor de signos vitales basado en tiempo real
Tests y Verificación
Este monitor es una herramienta de diagnóstico que se validará ejecutando el emulador con ROMs que muestran problemas de bloqueo (pantalla negra indefinida).
- ROM de prueba: Pokémon Red (ROM aportada por el usuario, no distribuida) - muestra pantalla negra cuando el LCD está apagado
- Modo de ejecución: UI con monitor activado, ejecutar durante 10-20 segundos
- Criterio de éxito: El monitor debe mostrar información cada 1 segundo con el estado actual del sistema, permitiendo identificar:
- Si el PC está avanzando o estático (indicando si hay un bucle infinito)
- Si el LCDC cambia de 0x00 a 0x80 o 0x91 (indicando que el juego intenta arrancar el video)
- Si el VRAM checksum aumenta (indicando que el juego está cargando gráficos)
- Si el VRAM checksum es 0 y no cambia (indicando que el juego está en un bucle infinito sin copiar datos)
- Observación esperada:
- Si el VRAM checksum aumenta: El juego está cargando gráficos, solo hay que esperar a que termine y encienda el LCD
- Si el VRAM checksum es 0 y no cambia: El juego está en un bucle infinito y NO está copiando datos (posible fallo de DMA o lógica)
- Si el LCDC cambia a 0x80 o 0x91: El juego intenta arrancar el video
- 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: VRAM (Video RAM)
Integridad Educativa
Lo que Entiendo Ahora
- Monitor basado en tiempo real vs. frames: Cuando el LCD está apagado, la PPU no genera frames, por lo que un monitor basado en frames nunca mostrará información. Un monitor basado en tiempo real (segundos del reloj del sistema) funciona independientemente del estado de la PPU y permite diagnosticar el estado del emulador incluso cuando la pantalla está apagada.
- VRAM checksum como diagnóstico: El checksum de VRAM (suma de todos los bytes en 0x8000-0x9FFF) es una herramienta útil para diagnosticar si el juego está cargando gráficos. Si el checksum aumenta entre reportes, el juego está copiando datos. Si el checksum es 0 y no cambia, el juego está en un bucle infinito sin hacer nada.
- Herramienta de diagnóstico 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
- Patrones de carga de gráficos: Aún no he ejecutado el emulador con el monitor activado para ver qué patrones de carga de gráficos aparecen. Los reportes del monitor revelarán si el juego está cargando gráficos correctamente o si hay un problema de DMA o lógica.
- Intervalo óptimo: El intervalo de 1 segundo puede ser demasiado largo o demasiado corto dependiendo del comportamiento del juego. Si el juego carga gráficos muy rápido, podríamos perder información. Si carga muy lento, 1 segundo es suficiente.
Hipótesis y Suposiciones
Hipótesis principal: El juego está cargando gráficos en VRAM con el LCD apagado (comportamiento correcto). El monitor de tiempo real mostrará si el VRAM checksum aumenta, confirmando que el juego está copiando datos. Una vez que termine de cargar, el juego debería encender el LCD y mostrar la pantalla.
Suposición del monitor: Asumimos que mostrar el estado cada 1 segundo 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 negra
- [ ] Esperar 10-20 segundos para ver al menos 10-20 reportes del monitor
- [ ] Analizar los reportes para identificar:
- Si el PC está avanzando o estático
- Si el VRAM checksum aumenta (indicando carga de gráficos)
- Si el LCDC cambia de 0x00 a 0x80 o 0x91 (indicando arranque del video)
- [ ] Si el VRAM checksum aumenta: Esperar a que termine de cargar y verificar si el LCD se enciende
- [ ] Si el VRAM checksum es 0 y no cambia: Investigar por qué el juego no está copiando datos (posible fallo de DMA o lógica)
- [ ] Una vez resuelto el problema, remover o desactivar el monitor temporal