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
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
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:
- Recompilar la extensión C++:
.\rebuild_cpp.ps1opython setup.py build_ext --inplace - Ejecutar el emulador:
python main.py roms/tetris.gb - 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.
- Si aparece
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