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

EI Watchdog

Fecha: 2025-12-23 Step ID: 0248 Estado: Draft

Resumen

El análisis del Timeline Logger (Step 0247) reveló que el juego está intentando usar DMA y escribiendo el centinela `FD` en HRAM, pero el GPS muestra constantemente `IME:0` (interrupciones deshabilitadas). La hipótesis es que el juego depende de una rutina de interrupción (V-Blank) para copiar datos de HRAM/ROM a WRAM, pero como IME está deshabilitado, la interrupción nunca se dispara y el bucle principal espera eternamente.

Este Step instrumenta la instrucción `EI` (Enable Interrupts, opcode 0xFB) para detectar si el juego intenta habilitar las interrupciones en algún momento. Si nunca aparece el log `[EI]`, significa que el juego ha decidido no usar interrupciones todavía, lo que explicaría el deadlock.

Concepto de Hardware

EI (Enable Interrupts, Opcode 0xFB): Instrucción que habilita el Interrupt Master Enable (IME) con un retraso de 1 instrucción. En hardware real, cuando se ejecuta `EI`, el IME no se activa inmediatamente, sino después de ejecutar la siguiente instrucción. Esto permite que la instrucción siguiente a `EI` se ejecute sin interrupciones, lo cual es crítico para patrones como:

EI
RETI  ; Esta instrucción se ejecuta sin interrupciones
      ; Después de RETI, IME se activa y se comprueban interrupciones pendientes

IME (Interrupt Master Enable): Flag global que controla si la CPU puede procesar interrupciones. Si IME está deshabilitado (`IME:0`), la CPU ignora todas las interrupciones, incluso si están habilitadas en el registro IE (Interrupt Enable, 0xFFFF) y hay señales pendientes en IF (Interrupt Flag, 0xFF0F).

El Problema del Deadlock por IME: Muchos juegos de Game Boy usan interrupciones V-Blank para sincronizar operaciones críticas como copias de datos a VRAM o WRAM. Si el juego espera una interrupción que nunca ocurre (porque IME está deshabilitado), puede quedar atascado en un bucle infinito esperando un evento que nunca llegará.

Fuente: Pan Docs - CPU Instruction Set (EI), Interrupt Master Enable (IME)

Implementación

Se añadió instrumentación temporal en el caso `0xFB` (EI) de `CPU.cpp` para registrar cada vez que el juego intenta habilitar las interrupciones. El log muestra el Program Counter (PC) donde se ejecutó la instrucción `EI`, lo que permite determinar si el juego intenta habilitar interrupciones y en qué punto del código.

Componentes modificados

  • src/core/cpp/CPU.cpp: Añadido log `[EI]` en el caso 0xFB con el PC actual. Re-añadido `#include ` temporalmente para el diagnóstico.

Decisiones de diseño

Se re-añadió `#include ` temporalmente (aunque se eliminó en Step 0243 para rendimiento) porque este diagnóstico específico requiere visibilidad inmediata en la consola. Una vez identificado el problema, esta instrumentación se eliminará para restaurar el rendimiento.

El log se imprime directamente con `printf` en lugar de usar un sistema de logging más complejo porque:

  • Es instrumentación temporal de diagnóstico
  • Necesita ser visible inmediatamente en la consola
  • No debe interferir con el flujo normal de ejecución

Archivos Afectados

  • src/core/cpp/CPU.cpp - Añadido log en caso 0xFB (EI) y re-añadido #include <cstdio> temporalmente (Step 0248)

Tests y Verificación

Para verificar esta instrumentación:

  1. Recompilar la extensión C++: .\rebuild_cpp.ps1 o python setup.py build_ext --inplace
  2. Ejecutar el emulador: python main.py roms/tetris.gb
  3. Observar la consola:
    • Si aparece [EI] ¡Interrupciones Habilitadas en PC:XXXX!: El juego intenta habilitar interrupciones. Anotar el PC y verificar si ocurre antes o después del bucle de espera.
    • Si NO aparece [EI]: El juego nunca ejecuta `EI`, lo que confirma que las interrupciones permanecen deshabilitadas y explica el deadlock.

Validación de módulo compilado C++: La instrumentación está en el código C++ nativo, por lo que requiere recompilación para que surta efecto.

Fuentes Consultadas

Integridad Educativa

Lo que Entiendo Ahora

  • EI tiene retraso de 1 instrucción: El IME no se activa inmediatamente después de `EI`, sino después de ejecutar la siguiente instrucción. Esto es un comportamiento del hardware real.
  • IME es el control global: Aunque IE (Interrupt Enable) esté configurado correctamente, si IME está deshabilitado, la CPU ignora todas las interrupciones.
  • Deadlock por IME: Si un juego espera una interrupción que nunca ocurre (porque IME está deshabilitado), puede quedar atascado en un bucle infinito.

Lo que Falta Confirmar

  • ¿El juego ejecuta EI?: Necesitamos verificar si el juego intenta habilitar interrupciones en algún momento. Si nunca ejecuta `EI`, el IME permanecerá deshabilitado y las interrupciones nunca se procesarán.
  • ¿Cuándo debería ejecutarse EI?: Si el juego ejecuta `EI`, necesitamos determinar si ocurre antes o después del bucle de espera. Si ocurre después, el bucle nunca se romperá.
  • ¿El registro IE está configurado?: Aunque el GPS ya reporta IE, necesitamos verificar si el juego escribe en IE para habilitar las interrupciones V-Blank o Timer.

Hipótesis y Suposiciones

Hipótesis Principal: El juego depende de una rutina de interrupción (probablemente V-Blank) para copiar datos de HRAM/ROM a WRAM. Como IME está deshabilitado, la interrupción nunca se dispara, la copia nunca ocurre, y el bucle principal espera eternamente.

Suposición: Si el juego nunca ejecuta `EI`, significa que está diseñado para funcionar sin interrupciones en esta fase de inicialización, o que hay un bug en el flujo del código que impide que se ejecute `EI`.

Próximos Pasos

  • [ ] Ejecutar el emulador y observar si aparece el log [EI]
  • [ ] Si aparece [EI]: Analizar en qué PC ocurre y si es antes o después del bucle de espera
  • [ ] Si NO aparece [EI]: Confirmar que el juego nunca habilita interrupciones y buscar alternativas (¿copia manual? ¿otro mecanismo?)
  • [ ] Verificar el valor del registro IE en el GPS para confirmar si las interrupciones están habilitadas a nivel de hardware
  • [ ] Una vez identificado el problema, eliminar la instrumentación temporal para restaurar el rendimiento