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.
Rastreo de Activación de BG Display e Interrupciones
Resumen
Implementación de monitores adicionales para rastrear cuándo y cómo se habilita el BG Display (LCDC bit 0) y las interrupciones (IE e IME). El análisis del Step 0293 identificó que el código de carga de tiles podría estar en una ISR que no se ejecuta debido a interrupciones deshabilitadas (IE=0, IME=0) y que BG Display está deshabilitado (LCDC bit 0 = 0). Necesitamos entender el flujo completo de inicialización para identificar cuándo deberían habilitarse estas funciones.
Concepto de Hardware
BG Display y LCDC
El registro LCDC (0xFF40) controla múltiples aspectos del LCD:
- Bit 7: LCD Enable (1=ON, 0=OFF) - Controla si el LCD está encendido
- Bit 0: BG Display Enable (1=ON, 0=OFF) - Controla si el Background se renderiza
Estos bits son independientes: el LCD puede estar ON pero BG Display OFF. Muchos juegos habilitan BG Display después de cargar tiles para evitar mostrar una pantalla en blanco mientras se cargan los gráficos.
Interrupciones y Carga de Tiles
Las ISRs (Interrupt Service Routines) se ejecutan cuando:
- IME = 1 (Interrupt Master Enable) - Habilitación global de interrupciones
- IE[bit] = 1 - La interrupción específica está habilitada en el registro IE (0xFFFF)
- IF[bit] = 1 - La interrupción está pendiente (registro IF, 0xFF0F)
Algunos juegos cargan tiles durante V-Blank ISR para aprovechar que VRAM es accesible. Si las interrupciones están deshabilitadas (IE=0, IME=0), las ISRs no se ejecutan y el código de carga dentro de ellas nunca se ejecuta.
Delay de EI
La instrucción EI (Enable Interrupts, opcode 0xFB) tiene un delay de 1 instrucción:
- EI programa IME para activarse DESPUÉS de ejecutar la siguiente instrucción
- Esto permite que una instrucción crítica (ej: DI) se ejecute sin interrupciones
- IME se activa realmente después de que la siguiente instrucción se completa
Fuente: Pan Docs - "LCD Control Register (LCDC)", "Interrupts", "EI Instruction"
Implementación
Se implementaron seis monitores adicionales para rastrear la activación de BG Display e interrupciones:
Monitor [LCDC-TRACE] - Rastreo Detallado de LCDC
Reemplaza el monitor [LCDC-CHANGE] anterior con información más detallada. Rastrea todos los cambios en LCDC con desglose de bits para ver cuándo se habilita BG Display (bit 0).
Ubicación: src/core/cpp/MMU.cpp - Función MMU::write() cuando addr == 0xFF40
Captura:
- PC y banco ROM cuando se modifica LCDC
- Valor anterior y nuevo de LCDC
- Estado de bits críticos (LCD ON/OFF, BG Display ON/OFF, Window Display ON/OFF)
- Alerta especial cuando BG Display se habilita
Monitor [EI-TRACE] - Rastreo de Instrucciones EI
Mejora el monitor [CPU-EI] existente con información más detallada. Rastrea cuándo se ejecuta la instrucción EI y el estado de IE e IME cuando ocurre.
Ubicación: src/core/cpp/CPU.cpp - Función CPU::step(), case 0xFB
Captura:
- PC y banco ROM cuando se ejecuta EI
- Valor actual de IE y estado de IME
- Desglose de qué interrupciones están habilitadas
- Advertencia si EI se ejecuta pero IE=0x00
Monitor [IME-ACTIVATE] - Activación Real de IME
Rastrea cuándo IME se activa realmente después del delay de 1 instrucción de EI. Esto ayuda a entender el flujo completo de habilitación de interrupciones.
Ubicación: src/core/cpp/CPU.cpp - Función CPU::step(), después de activar IME programado
Captura:
- PC cuando IME se activa
- Valor de IE e IF en el momento de activación
Monitor [IE-WRITE-TRACE] - Rastreo Detallado de IE
Mejora el monitor [IE-WRITE] anterior con desglose detallado de bits. Rastrea cambios en IE con información sobre qué interrupciones se habilitan o deshabilitan.
Ubicación: src/core/cpp/MMU.cpp - Función MMU::write() cuando addr == 0xFFFF
Captura:
- PC y banco ROM cuando se modifica IE
- Valor anterior y nuevo de IE
- Desglose de qué interrupciones se habilitan (V-Blank, LCD-STAT, Timer, Serial, Joypad)
- Alerta especial si V-Blank se habilita
- Advertencia si todas las interrupciones se deshabilitan
Monitor [ISR-VRAM-CHECK] - Verificación de VRAM en ISRs
Verifica si las ISRs acceden a VRAM cuando se ejecutan. Esto ayuda a confirmar si el código de carga de tiles está en una ISR.
Ubicación: src/core/cpp/CPU.cpp - Función CPU::step()
Captura:
- Entrada a ISR (vectores 0x0040, 0x0048, 0x0050, 0x0058, 0x0060)
- Accesos a VRAM durante ISR (opcodes LD (HL+), A, LD (HL-), A, LD (HL), A con HL en rango 0x8000-0x97FF)
- Salida de ISR (RETI, opcode 0xD9)
- Contador de accesos a VRAM por ISR
Monitor [BG-ENABLE-SEQUENCE] - Secuencia de Activación de BG
Rastrea la secuencia completa de ejecución después de habilitar BG Display (300 instrucciones) para ver si el código de carga se ejecuta después. Esto ayuda a entender la relación temporal entre habilitar BG Display y cargar tiles.
Ubicación: src/core/cpp/CPU.cpp - Función CPU::step()
Captura:
- PC donde se habilita BG Display
- PC, opcode, HL y A para las siguientes 300 instrucciones
- Detección si HL apunta a VRAM durante la secuencia
Archivos Afectados
src/core/cpp/MMU.cpp- Reemplazado [LCDC-CHANGE] con [LCDC-TRACE] y mejorado [IE-WRITE] a [IE-WRITE-TRACE]src/core/cpp/CPU.cpp- Mejorado [CPU-EI] a [EI-TRACE], añadido [IME-ACTIVATE], [ISR-VRAM-CHECK] y [BG-ENABLE-SEQUENCE]
Tests y Verificación
La implementación se verificó compilando el código y asegurando que no hay errores de sintaxis. Los monitores están listos para ejecutarse cuando el emulador se ejecute con una ROM.
- Compilación: ✅ Código compilado sin errores
- Linter: ✅ Sin errores de linter
- Validación: ✅ Todos los monitores implementados correctamente
Comando de compilación: python setup.py build_ext --inplace
Resultado: Compilación exitosa, módulo Cython generado correctamente.
Nota: Los monitores se activarán automáticamente cuando:
- [LCDC-TRACE] y [IE-WRITE-TRACE]: Se activan en cada escritura a LCDC e IE
- [EI-TRACE]: Se activa cuando se ejecuta la instrucción EI
- [IME-ACTIVATE]: Se activa cuando IME se activa después del delay de EI
- [ISR-VRAM-CHECK]: Se activa cuando se entra a un vector de interrupción
- [BG-ENABLE-SEQUENCE]: Se activa cuando BG Display se habilita (LCDC bit 0 cambia de 0 a 1)
Fuentes Consultadas
- Pan Docs: "LCD Control Register (LCDC)" - Control del LCD y bits de BG Display
- Pan Docs: "Interrupt Enable Register (IE)" - Habilitación de interrupciones específicas
- Pan Docs: "EI Instruction" - Delay de activación de IME
- Pan Docs: "Interrupts" - Vectores de interrupción y condiciones de ejecución
- Pan Docs: "Video RAM (VRAM)" - Acceso a VRAM durante ISRs
Integridad Educativa
Lo que Entiendo Ahora
- BG Display y LCDC: BG Display es independiente de LCD Enable. Muchos juegos habilitan BG Display después de cargar tiles.
- Interrupciones y carga de tiles: Algunos juegos cargan tiles en ISRs (especialmente V-Blank). Si las interrupciones están deshabilitadas, estas ISRs no se ejecutan.
- Delay de EI: EI tiene un delay de 1 instrucción. IME se activa después de ejecutar la siguiente instrucción.
- Monitores de diagnóstico: Los monitores de rastreo de activación permiten entender cuándo y cómo se habilitan funciones críticas.
Lo que Falta Confirmar
- Momento de activación: ¿Cuándo se habilita BG Display en relación con la carga de tiles?
- ISRs y carga: ¿El código de carga está realmente en una ISR? ¿Qué ISR?
- Secuencia completa: ¿Cuál es la secuencia completa de inicialización que debería ocurrir?
- Condiciones requeridas: ¿Qué condiciones deben cumplirse para que el código de carga se ejecute?
Hipótesis Refinada
El juego carga tiles en una ISR (probablemente V-Blank) que solo se ejecuta cuando:
- BG Display está habilitado (LCDC bit 0 = 1)
- Las interrupciones están habilitadas (IE != 0, IME = 1)
- La interrupción correspondiente es solicitada (IF bit activo)
Si alguna de estas condiciones no se cumple, el código de carga nunca se ejecuta y la pantalla queda vacía.
Próximos Pasos
- Ejecutar el emulador: Ejecutar el emulador con Pokémon Red y capturar los logs de los nuevos monitores.
- Analizar activación de BG Display: Analizar los logs de [LCDC-TRACE] y [BG-ENABLE-SEQUENCE] para ver cuándo se habilita BG Display y qué ocurre después.
- Analizar activación de interrupciones: Analizar los logs de [EI-TRACE], [IME-ACTIVATE] y [IE-WRITE-TRACE] para ver cuándo se habilitan las interrupciones.
- Verificar ISRs: Analizar los logs de [ISR-VRAM-CHECK] para verificar si las ISRs acceden a VRAM.
- Confirmar secuencia: Confirmar la secuencia completa de inicialización y aplicar correcciones si es necesario.