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

Diagnóstico de Bloqueo de Interrupciones

Fecha: 2025-12-18 Step ID: 0051 Estado: Draft

Resumen

Se implementó un sistema de diagnóstico crítico para identificar por qué la CPU ignora las peticiones de interrupción V-Blank. El diagnóstico añade logs específicos con el símbolo ⚠️ cuando se detecta una petición V-Blank en IF pero no se atiende, indicando si el problema es que IE no tiene el bit activado o si IME está desactivado. Adicionalmente, se añadió un log informativo cada vez que se escribe en el registro IE (0xFFFF) para monitorizar cuándo y cómo el juego configura las interrupciones.

Concepto de Hardware

En la Game Boy, para que una interrupción se procese correctamente, deben cumplirse tres condiciones simultáneas:

  1. IF tiene el bit activado: El hardware (PPU, Timer, etc.) ha generado una petición de interrupción y ha activado el bit correspondiente en el registro IF (0xFF0F).
  2. IE tiene el bit activado: El software ha habilitado esa interrupción escribiendo el bit correspondiente en el registro IE (0xFFFF). Esto permite que el juego seleccione qué interrupciones quiere recibir.
  3. IME está activado: La CPU tiene las interrupciones habilitadas globalmente. IME se activa con la instrucción EI (Enable Interrupts) y se desactiva con DI (Disable Interrupts).

Si alguna de estas condiciones no se cumple, la interrupción no se procesa, aunque el hardware siga generando la petición en IF. Esto es especialmente crítico para V-Blank, ya que muchos juegos dependen de esta interrupción para avanzar en su inicialización.

El diagnóstico implementado verifica específicamente la interrupción V-Blank (bit 0 de IF/IE) porque es la primera que debería ocurrir después de encender el LCD. Si V-Blank no se procesa, el juego se queda esperando indefinidamente.

Fuente: Pan Docs - Interrupts, Interrupt Enable Register (IE), Interrupt Flag Register (IF), IME

Implementación

Se añadieron dos puntos de diagnóstico estratégicos:

1. Diagnóstico de V-Blank en handle_interrupts() (CPU)

En src/cpu/core.py, método handle_interrupts(), se añadió un bloque de diagnóstico antes de verificar si hay interrupciones pendientes. El diagnóstico verifica específicamente si hay una petición V-Blank en IF (bit 0) y por qué no se está atendiendo:

  • Si IE no tiene el bit 0 activado: Se logea ⚠️ V-Blank IGNORADO: No habilitado en IE (IE=XX)
  • Si IME está desactivado: Se logea ⚠️ V-Blank IGNORADO: IME desactivado (DI ejecutado)

Este diagnóstico se ejecuta cada vez que handle_interrupts() se llama, incluso si no hay interrupciones pendientes, lo que permite detectar el problema en tiempo real.

2. Log de Escritura en IE (MMU)

En src/memory/mmu.py, método write_byte(), se añadió un log informativo que se activa cada vez que se escribe en el registro IE (0xFFFF). El log muestra:

  • El valor escrito en IE (formato hexadecimal)
  • Qué interrupciones se están habilitando (V-Blank, STAT, Timer) en formato legible

Este log permite identificar si el juego nunca escribe en IE (lo cual sería un bug del juego o un problema de emulación anterior) o si escribe un valor incorrecto.

Decisiones de diseño

  • Nivel de log DEBUG para diagnóstico V-Blank: Se usa logging.debug() para que el log sea visible cuando se active el modo debug, pero no sature la consola en modo normal.
  • Nivel de log INFO para escritura en IE: Se usa logging.info() porque es un evento menos frecuente y crítico para entender el flujo de inicialización del juego.
  • Símbolo ⚠️ para alertas: Se añadió un símbolo visual distintivo para facilitar la búsqueda en los logs y distinguir estos mensajes de diagnóstico de otros logs.
  • Verificación antes de calcular pending: El diagnóstico se ejecuta antes de calcular pending para poder distinguir entre "IE no tiene el bit" y "IME desactivado", ya que ambos casos resultan en pending == 0.

Archivos Afectados

  • src/cpu/core.py - Añadido diagnóstico de V-Blank en handle_interrupts() antes de verificar IME
  • src/memory/mmu.py - Añadido log informativo cuando se escribe en IE (0xFFFF)

Tests y Verificación

Modo de ejecución: Manual con ROM comercial (Pokémon Red, aportada por el usuario, no distribuida)

Comando ejecutado: python main.py pkmn.gb

Entorno: Windows 10, Python 3.13.5

Criterio de éxito:

  • Ver mensajes de diagnóstico ⚠️ V-Blank IGNORADO en la consola cuando se ejecuta el emulador
  • Ver mensajes SET IE REGISTER si el juego intenta configurar IE
  • Identificar la causa raíz del bloqueo de interrupciones (IE no configurado o IME desactivado)

Observación esperada:

Al ejecutar el emulador, deberían aparecer en la consola mensajes de diagnóstico que indiquen por qué la interrupción V-Blank no se está procesando. Si el mensaje es ⚠️ V-Blank IGNORADO: No habilitado en IE, significa que el juego nunca escribió en IE para habilitar V-Blank. Si el mensaje es ⚠️ V-Blank IGNORADO: IME desactivado, significa que el juego ejecutó DI y nunca ejecutó EI o RETI.

Resultado: Pendiente de ejecución

Notas legales: La ROM de Pokémon Red es aportada por el usuario para pruebas locales. No se distribuye ni se incluye en el repositorio. No se enlazan descargas de ROMs comerciales.

Fuentes Consultadas

Integridad Educativa

Lo que Entiendo Ahora

  • Condiciones para procesar interrupciones: Una interrupción requiere tres condiciones simultáneas: IF activado, IE activado, e IME activado. Si cualquiera de estas falla, la interrupción no se procesa.
  • Diagnóstico proactivo: Para identificar problemas de interrupciones, es necesario verificar cada condición por separado, no solo el resultado final (pending == 0).
  • Flujo de inicialización: Muchos juegos encienden el LCD (LCDC=0x80) y luego esperan V-Blank para configurar el resto de los gráficos. Si V-Blank no se procesa, el juego se congela.

Lo que Falta Confirmar

  • Causa raíz del bloqueo: Necesito ejecutar el emulador y ver qué mensaje de diagnóstico aparece para identificar si el problema es IE no configurado o IME desactivado.
  • Timing de escritura en IE: No estoy seguro de cuándo exactamente los juegos escriben en IE. Algunos juegos pueden hacerlo muy temprano en la inicialización, otros pueden hacerlo después de encender el LCD.
  • Comportamiento de IME en inicialización: No estoy seguro si la CPU inicia con IME activado o desactivado por defecto. Esto podría afectar el diagnóstico.

Hipótesis y Suposiciones

Hipótesis principal: El juego nunca escribe en IE para habilitar V-Blank, o lo hace después de encender el LCD pero la interrupción ya se perdió. Alternativamente, el juego ejecutó DI en algún momento y nunca ejecutó EI o RETI.

Suposición sobre IME inicial: Asumo que la CPU inicia con IME desactivado (como en muchos sistemas embebidos), pero esto necesita confirmación con documentación o tests.

Próximos Pasos

  • [ ] Ejecutar el emulador con python main.py pkmn.gb y buscar mensajes ⚠️ V-Blank IGNORADO
  • [ ] Si aparece No habilitado en IE: Verificar si hay mensajes SET IE REGISTER en los logs
  • [ ] Si aparece IME desactivado: Buscar en los logs dónde se ejecutó DI y por qué no se ejecutó EI
  • [ ] Implementar fix según la causa identificada (forzar IE, forzar IME, o corregir lógica de EI/DI)
  • [ ] Verificar que el juego avance después del fix ejecutando nuevamente la ROM