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.
Diagnóstico de STAT/LYC en Vivo
Resumen
Se añadió instrumentación de diagnóstico en tiempo real para detectar configuraciones de LYC y STAT, y para identificar cuándo la PPU detecta señales de interrupción STAT activas. El objetivo es diagnosticar por qué juegos como Pokémon y Tetris se quedan congelados en el logo: los logs muestran muchas interrupciones V-Blank (0x0040) pero ninguna interrupción STAT (0x0048), lo que sugiere que el juego espera una interrupción STAT (LY=LYC) para animar el logo pero no se está disparando.
Concepto de Hardware
La Game Boy puede generar interrupciones STAT (LCD Status) cuando se cumplen ciertas condiciones relacionadas con el estado de la PPU. Una de estas condiciones es la coincidencia LYC=LY: cuando el registro LY (Línea actual) coincide con el registro LYC (LY Compare), se puede generar una interrupción si el bit 6 del registro STAT está activo.
Muchos juegos usan esta característica para animar el logo durante la intro: configuran LYC a un valor específico (por ejemplo, línea 144 para V-Blank o una línea visible para efectos especiales), habilitan la interrupción STAT en IE (bit 1) y en STAT (bit 6), y esperan a que se dispare la interrupción para actualizar los gráficos.
Si la interrupción STAT no se dispara, el juego se queda esperando indefinidamente en un bucle, causando que la pantalla se congele en el logo.
Fuente: Pan Docs - LCD Status Register (STAT), LYC Register, STAT Interrupt
Implementación
Se añadió instrumentación de diagnóstico en tres puntos clave del sistema:
1. Instrumentación en MMU (escrituras a LYC y STAT)
En src/memory/mmu.py, se añadieron logs informativos cuando el juego escribe en:
- LYC (0xFF45): Se registra el valor escrito con el log
👁️ LYC SET: {value} - STAT (0xFF41): Se registra el valor escrito y qué bits de interrupción están habilitados:
- Bit 3: H-Blank Interrupt Enable
- Bit 4: V-Blank Interrupt Enable
- Bit 5: OAM Search Interrupt Enable
- Bit 6: LYC=LY Coincidence Interrupt Enable
2. Instrumentación en PPU (detección de señal STAT activa)
En src/gpu/ppu.py, en el método _check_stat_interrupt(), se añadieron logs cuando
se detecta una señal STAT activa por cualquiera de las condiciones:
- LYC Match: Cuando LY == LYC y el bit 6 de STAT está activo
- H-Blank: Cuando el modo es Mode 0 y el bit 3 de STAT está activo
- V-Blank: Cuando el modo es Mode 1 y el bit 4 de STAT está activo
- OAM Search: Cuando el modo es Mode 2 y el bit 5 de STAT está activo
El log incluye información completa: modo PPU, LY actual, LYC configurado, valor de STAT, y qué condición activó la señal.
3. Verificación del Dispatcher de Interrupciones
Se verificó que el dispatcher de interrupciones en src/cpu/core.py chequea correctamente el bit 1
de IF para la interrupción STAT y salta al vector 0x0048. La implementación es correcta y sigue la prioridad
de interrupciones del hardware (V-Blank tiene prioridad más alta que STAT).
Decisiones de diseño
Los logs se añadieron con nivel INFO para que sean visibles durante la ejecución normal del emulador.
Esto permite diagnosticar problemas en tiempo real sin necesidad de activar logging DEBUG, que puede ser muy verboso.
Archivos Afectados
src/memory/mmu.py- Añadida instrumentación para escrituras a LYC (0xFF45) y STAT (0xFF41)src/gpu/ppu.py- Añadida instrumentación para detección de señal STAT activa en_check_stat_interrupt()
Tests y Verificación
Esta es una implementación de diagnóstico, no una funcionalidad nueva. La instrumentación se añadió para ayudar a identificar por qué los juegos se quedan congelados.
Próximos pasos para verificación:
- Ejecutar
python main.py pkmn.gbopython main.py tetris_dx.gbc - Buscar en los logs:
- Si aparece
👁️ LYC SET: El juego está configurando LYC - Si aparece
👁️ STAT WRITE: El juego está configurando STAT - Si aparece
🚨 STAT SIGNAL ACTIVE: La PPU detecta el evento - Si aparece lo anterior pero NO aparece
⚡ INTERRUPT DISPATCHED! Vector: 0048: El fallo está en el dispatcher de interrupciones (CPU)
- Si aparece
Estado: Draft - Pendiente de ejecutar y analizar los logs para identificar el problema exacto.
Fuentes Consultadas
- Pan Docs: LCD Status Register (STAT)
- Pan Docs: LYC Register (LY Compare)
- Pan Docs: Interrupts
Integridad Educativa
Lo que Entiendo Ahora
- Interrupciones STAT: La Game Boy puede generar interrupciones cuando se cumplen condiciones específicas relacionadas con el estado de la PPU (modo, LYC=LY, etc.).
- LYC=LY Coincidence: Cuando LY coincide con LYC, se puede generar una interrupción si el bit 6 de STAT está activo. Esto es útil para sincronizar actualizaciones gráficas con líneas específicas.
- Rising Edge Detection: Las interrupciones STAT se disparan en "rising edge", es decir, solo cuando la condición pasa de False a True, no mientras permanece True.
- Prioridad de Interrupciones: V-Blank tiene prioridad más alta que STAT. Si ambas están pendientes, V-Blank se procesa primero.
Lo que Falta Confirmar
- Configuración del juego: ¿El juego está configurando LYC y STAT correctamente? Los logs nos dirán si el juego escribe en estos registros.
- Detección de señal: ¿La PPU está detectando la coincidencia LY==LYC? Los logs nos dirán si se activa la señal STAT.
- Dispatcher de interrupciones: ¿El dispatcher está chequeando correctamente el bit 1 de IF? Ya verificamos el código y parece correcto, pero los logs confirmarán si se dispara la interrupción.
- Habilitación en IE: ¿El juego está habilitando la interrupción STAT en IE (bit 1)? Si no está habilitada en IE, la interrupción no se procesará aunque IF tenga el bit activo.
Hipótesis y Suposiciones
Hipótesis principal: El juego está configurando LYC y STAT correctamente, pero la interrupción STAT no se está disparando porque:
- La PPU no está detectando la coincidencia LY==LYC (problema en
_check_stat_interrupt()) - El juego no está habilitando la interrupción STAT en IE (bit 1)
- Hay un problema con el rising edge detection que impide que se dispare múltiples veces
Los logs nos dirán exactamente dónde está el problema.
Próximos Pasos
- [ ] Ejecutar el emulador con una ROM (pkmn.gb o tetris_dx.gbc) y analizar los logs
- [ ] Identificar si el juego configura LYC y STAT (buscar
👁️ LYC SETy👁️ STAT WRITE) - [ ] Identificar si la PPU detecta la señal STAT (buscar
🚨 STAT SIGNAL ACTIVE) - [ ] Identificar si se dispara la interrupción STAT (buscar
⚡ INTERRUPT DISPATCHED! Vector: 0048) - [ ] Corregir el problema identificado en los logs
- [ ] Verificar que el juego ya no se congela y avanza correctamente