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

Rastreo de Activación de BG Display e Interrupciones

Fecha: 2025-12-25 Step ID: 0294 Estado: VERIFIED

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:

  1. IME = 1 (Interrupt Master Enable) - Habilitación global de interrupciones
  2. IE[bit] = 1 - La interrupción específica está habilitada en el registro IE (0xFFFF)
  3. 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:

  1. BG Display está habilitado (LCDC bit 0 = 1)
  2. Las interrupciones están habilitadas (IE != 0, IME = 1)
  3. 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

  1. Ejecutar el emulador: Ejecutar el emulador con Pokémon Red y capturar los logs de los nuevos monitores.
  2. 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.
  3. 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.
  4. Verificar ISRs: Analizar los logs de [ISR-VRAM-CHECK] para verificar si las ISRs acceden a VRAM.
  5. Confirmar secuencia: Confirmar la secuencia completa de inicialización y aplicar correcciones si es necesario.