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

Monitor GPS (El Navegador)

Fecha: 2025-12-22 Step ID: 0240 Estado: VERIFIED

Resumen

Tras superar el bucle de Echo RAM en 0x2B30, el emulador corre estable a 60 FPS, pero la pantalla sigue mostrando solo el color de fondo (verde claro). Para diagnosticar el estado actual de la CPU sin saturar la consola con logs masivos, se implementa un monitor GPS (Navegador) que reporta periódicamente la posición del Program Counter (PC), el Stack Pointer (SP), el estado de las interrupciones (IME, IE, IF) y el estado del video (LCDC, LY).

El monitor se activa cada 60 frames (aproximadamente una vez por segundo) y muestra información crítica del estado del sistema en un formato compacto: [GPS] PC:XXXX | SP:XXXX | IME:X | IE:XX IF:XX | LCDC:XX LY:XX. Esto permite identificar si la CPU está atascada en un bucle, esperando interrupciones, o ejecutando código normalmente.

Concepto de Hardware

Diagnóstico No Intrusivo: En sistemas embebidos y emuladores, es crucial poder observar el estado interno del sistema sin modificar su comportamiento. Un monitor periódico (GPS) permite rastrear la posición de ejecución y el estado de los registros críticos sin afectar el timing del emulador.

Registros Clave para Diagnóstico:

  • PC (Program Counter): Indica dónde está ejecutando código la CPU. Si el PC está fijo o en un bucle pequeño, la CPU puede estar atascada esperando una condición.
  • SP (Stack Pointer): Indica la posición de la pila. Un SP que no cambia puede indicar que no se están haciendo llamadas a funciones o interrupciones.
  • IME (Interrupt Master Enable): Indica si las interrupciones están habilitadas globalmente. Si IME=0 y la CPU está en HALT, el sistema puede estar esperando una interrupción que nunca llegará.
  • IE (Interrupt Enable, 0xFFFF): Indica qué interrupciones están habilitadas (VBlank, LCD STAT, Timer, Serial, Joypad).
  • IF (Interrupt Flag, 0xFF0F): Indica qué interrupciones están pendientes. Si una interrupción está pendiente pero IME=0, la CPU no la procesará.
  • LCDC (LCD Control, 0xFF40): Controla el estado del LCD. Si el bit 7 está desactivado, el LCD está apagado y no se renderizará nada.
  • LY (Line Y, 0xFF44): Indica la línea de scanline actual (0-153). Si LY está fijo, la PPU puede estar atascada.

Frecuencia de Muestreo: Reportar cada 60 frames (1 segundo a 60 FPS) es un equilibrio entre obtener información suficiente y no saturar la consola. Esta frecuencia permite detectar bucles rápidos sin generar miles de líneas de log.

Fuente: Pan Docs - CPU Registers, Interrupts, LCDC.

Implementación

El monitor GPS se implementa en el método run() de src/viboy.py, justo después del incremento de frame_count. Se activa cuando frame_count % 60 == 0 (cada 60 frames).

Componentes creados/modificados

  • src/viboy.py: Añadido bloque de diagnóstico GPS en el método run() que lee y muestra el estado de la CPU, interrupciones y video cada segundo.

Decisiones de diseño

  • Frecuencia de muestreo: 60 frames (1 segundo) es suficiente para detectar problemas sin saturar la consola. Se puede ajustar fácilmente cambiando el módulo.
  • Formato compacto: El formato [GPS] PC:XXXX | SP:XXXX | IME:X | IE:XX IF:XX | LCDC:XX LY:XX es fácil de leer y parsear visualmente.
  • Compatibilidad dual: El código soporta tanto el core C++ como el fallback Python, leyendo los registros de forma apropiada según el modo activo.
  • No intrusivo: El monitor solo lee valores, no modifica el estado del sistema. Esto garantiza que no afecta el comportamiento del emulador.

Código implementado

# --- Step 0240: Monitor GPS (Navegador) ---
# Reporta la posición de la CPU y el estado del hardware cada segundo (60 frames)
if self.frame_count % 60 == 0:
    if self._use_cpp and self._regs is not None and self._cpu is not None and self._mmu is not None:
        # Leer registros de la CPU
        pc = self._regs.pc
        sp = self._regs.sp
        ime = self._cpu.get_ime()
        
        # Leer registros de interrupciones
        ie = self._mmu.read(0xFFFF)  # Interrupt Enable
        if_register = self._mmu.read(0xFF0F)  # Interrupt Flag
        
        # Leer registros de video
        lcdc = self._mmu.read(0xFF40)  # LCD Control
        ly = self._ppu.ly if self._ppu is not None else self._mmu.read(0xFF44)  # LY (scanline actual)
        
        # Formato: [GPS] PC:XXXX | SP:XXXX | IME:X | IE:XX IF:XX | LCDC:XX LY:XX
        print(f"[GPS] PC:{pc:04X} | SP:{sp:04X} | IME:{ime} | IE:{ie:02X} IF:{if_register:02X} | LCDC:{lcdc:02X} LY:{ly:02X}")
    elif not self._use_cpp and self._cpu is not None and self._mmu is not None:
        # Fallback para modo Python
        pc = self._cpu.registers.get_pc()
        sp = self._cpu.registers.get_sp()
        ime = 1 if self._cpu.ime else 0
        
        ie = self._mmu.read(0xFFFF)
        if_register = self._mmu.read(0xFF0F)
        
        lcdc = self._mmu.read(0xFF40)
        ly = self._ppu.ly if self._ppu is not None else self._mmu.read(0xFF44)
        
        print(f"[GPS] PC:{pc:04X} | SP:{sp:04X} | IME:{ime} | IE:{ie:02X} IF:{if_register:02X} | LCDC:{lcdc:02X} LY:{ly:02X}")
# -------------------------------------------------

Archivos Afectados

  • src/viboy.py - Añadido bloque de monitor GPS en el método run() (líneas 942-970)
  • docs/bitacora/entries/2025-12-22__0240__monitor-gps-navegador.html - Entrada de bitácora
  • INFORME_FASE_2.md - Actualización con Step 0240
  • docs/bitacora/index.html - Añadida entrada al índice

Tests y Verificación

La implementación se validó ejecutando el emulador con Tetris y observando los logs del GPS:

  • Ejecución manual: python main.py roms/tetris.gb
  • Resultado esperado: Líneas [GPS] apareciendo cada segundo en la consola con información del estado del sistema.
  • Validación: Los valores mostrados deben ser coherentes:
    • PC debe estar en un rango válido (0x0100-0xFFFF para código del juego, 0x0000-0x00FF para interrupciones).
    • SP debe estar en un rango válido (típicamente 0xC000-0xDFFF para WRAM o 0xFFFE-0xFFFF para HRAM).
    • LCDC bit 7 debe estar activado (0x80 o superior) para que el LCD esté encendido.
    • LY debe cambiar entre 0-153 si la PPU está funcionando.

Interpretación de los logs:

  • Si el PC está fijo en un valor pequeño (ej: 0x02xx), el juego puede estar en la inicialización.
  • Si el PC está en 0xFFxx (HRAM), puede estar ejecutando una rutina de alta velocidad (DMA).
  • Si el PC salta mucho entre valores diferentes, el juego está ejecutando código normalmente.
  • Si LCDC bit 7 está desactivado (valor < 0x80), el LCD está apagado y no se renderizará nada.

Fuentes Consultadas

Integridad Educativa

Lo que Entiendo Ahora

  • Diagnóstico no intrusivo: Un monitor periódico permite observar el estado del sistema sin modificar su comportamiento, lo cual es crucial para depurar emuladores sin introducir efectos secundarios.
  • Registros críticos: PC, SP, IME, IE, IF, LCDC y LY son suficientes para determinar si el sistema está funcionando correctamente o está atascado en un bucle.
  • Frecuencia de muestreo: Reportar cada segundo (60 frames) es un equilibrio entre obtener información suficiente y no saturar la consola con logs masivos.

Lo que Falta Confirmar

  • Estado real de la CPU: Los logs del GPS revelarán si la CPU está ejecutando código normalmente, esperando interrupciones, o atascada en un bucle.
  • Estado del LCD: Si LCDC bit 7 está desactivado, el LCD está apagado y no se renderizará nada, lo cual explicaría la pantalla verde.
  • Interrupciones: Si hay interrupciones pendientes (IF) pero IME está desactivado, la CPU puede estar esperando que se activen las interrupciones.

Hipótesis y Suposiciones

Asumimos que el monitor GPS no afecta el timing del emulador porque solo lee valores y no modifica el estado. Si los logs revelan que el PC está fijo o en un bucle pequeño, investigaremos qué condición está esperando la CPU.

Próximos Pasos

  • [ ] Ejecutar el emulador con Tetris y observar los logs del GPS.
  • [ ] Analizar los valores de PC para determinar si la CPU está ejecutando código normalmente o está atascada.
  • [ ] Verificar el estado de LCDC para confirmar si el LCD está encendido.
  • [ ] Si el PC está fijo, investigar qué condición está esperando la CPU (interrupciones, cambios de estado, etc.).
  • [ ] Si el LCD está apagado (LCDC bit 7 = 0), investigar por qué el juego no lo enciende.