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.
El Testigo de LY: ¿La CPU es ciega?
Resumen
La autopsia del Step 0225 confirmó que la CPU está atascada en el bucle de espera de V-Blank (`LY=144`) con la VRAM completamente vacía. Para entender por qué el bucle nunca termina, instrumentamos `MMU::read` para trazar todas las lecturas del registro `LY` (0xFF44). Esto nos permitirá verificar si la CPU está leyendo correctamente el registro y si el valor se incrementa hasta 144, o si hay una desincronización entre la CPU y la PPU.
Concepto de Hardware
El registro LY (LCD Y-Coordinate) en la dirección 0xFF44 contiene la línea de escaneo actual que la PPU está renderizando. Este registro es de solo lectura y es actualizado automáticamente por la PPU cada 456 ciclos de CPU (duración de una línea de escaneo).
El registro LY tiene un rango de valores de 0 a 153:
- 0-143: Líneas visibles del frame (modo 3: Pixel Transfer)
- 144: Primera línea de V-Blank (modo 0: H-Blank/V-Blank)
- 145-153: Resto de V-Blank
Los juegos de Game Boy típicamente esperan a que LY llegue a 144 antes de copiar datos gráficos a la VRAM, ya que durante V-Blank la PPU no está accediendo a la VRAM y es seguro escribir. El bucle de espera típico es:
.wait_vblank:
LDH A, (LY) ; Lee LY (0xFF44)
CP 144 ; Compara con 144
JR NZ, .wait_vblank ; Si no es 144, repite
Si la CPU nunca ve `LY=144`, el bucle se ejecuta indefinidamente y el juego no progresa. Esto puede ocurrir si:
- La PPU no está actualizando LY correctamente
- La CPU lee un valor incorrecto de LY (problema de mapeo de memoria)
- Hay una desincronización entre la CPU y la PPU (timing incorrecto)
Fuente: Pan Docs - "LCD Y-Coordinate (LY)"
Implementación
Añadimos instrumentación en `MMU::read` para trazar todas las lecturas del registro LY. El código está comentado inicialmente para evitar saturar la consola, pero puede activarse fácilmente descomentando una línea.
Componentes modificados
- MMU.cpp: Añadido bloque de debug para LY (0xFF44) que imprime el valor leído cada vez que la CPU accede al registro.
Decisiones de diseño
El código de debug está comentado por defecto para evitar saturar la consola durante la ejecución normal. Cuando se necesita activar el debug, el usuario debe:
- Descomentar la línea del
printf - Redirigir la salida a un archivo:
python main.py roms/tetris.gb > ly_log.txt 2>&1 - Ejecutar durante unos segundos y luego interrumpir con Ctrl+C
- Buscar en el log si aparece el valor 144
Esta estrategia permite obtener evidencia forense sin afectar el rendimiento del emulador durante el desarrollo normal.
Archivos Afectados
src/core/cpp/MMU.cpp- Añadido bloque de debug para LY (0xFF44) en el métodoread()
Tests y Verificación
Para verificar la instrumentación:
- Recompilar: Ejecutar
.\rebuild_cpp.ps1opython setup.py build_ext --inplace - Activar debug: Descomentar la línea del
printfenMMU.cpp - Ejecutar con redirección:
python main.py roms/tetris.gb > ly_log.txt 2>&1 - Interrumpir: Esperar 2-3 segundos y presionar Ctrl+C
- Analizar log: Buscar en
ly_log.txtsi aparece el valor 144
Interpretación de resultados:
- Si aparece "Read LY: 144": La CPU SÍ está leyendo el valor correcto. El problema está en otro lugar (quizás el bucle de espera tiene un bug lógico).
- Si nunca aparece 144: La PPU no está actualizando LY correctamente, o hay un problema de sincronización.
- Si los valores se repiten mucho: La CPU está leyendo LY muchas veces dentro de la misma línea (comportamiento esperado en un bucle de espera).
Validación de módulo compilado C++: El código se ejecuta directamente en C++, sin overhead de Python, garantizando que las lecturas se trazan en tiempo real.
Fuentes Consultadas
- Pan Docs: LCD Y-Coordinate (LY) - 0xFF44
Integridad Educativa
Lo que Entiendo Ahora
- LY es un registro de solo lectura: La CPU no puede escribir en 0xFF44, solo la PPU lo actualiza automáticamente.
- El bucle de espera de V-Blank es crítico: Si la CPU nunca ve LY=144, el juego no puede copiar datos gráficos y la pantalla permanece en blanco.
- La instrumentación debe ser no intrusiva: Los logs masivos pueden afectar el rendimiento y distorsionar el comportamiento del emulador.
Lo que Falta Confirmar
- ¿La CPU realmente lee LY=144? Necesitamos ejecutar el debug y verificar si el valor 144 aparece en el log.
- ¿Hay una desincronización de timing? Si LY sí llega a 144 pero la CPU no lo ve, puede haber un problema de sincronización entre CPU y PPU.
- ¿El bucle de espera tiene un bug lógico? Si la CPU ve LY=144 pero el bucle no termina, el problema está en la lógica del bucle (quizás la comparación está mal implementada).
Hipótesis y Suposiciones
Hipótesis principal: La CPU está leyendo LY correctamente, pero el valor nunca llega a 144 porque la PPU no está actualizando LY correctamente, o hay una desincronización de timing que hace que la CPU "se pierda" el momento exacto en que LY vale 144.
Suposición: El mapeo de memoria de 0xFF44 en MMU es correcto. Si no lo fuera, la CPU leería un valor incorrecto o 0x00 constantemente.
Próximos Pasos
- [ ] Activar el debug de LY y ejecutar el emulador durante 2-3 segundos
- [ ] Analizar el log para verificar si aparece el valor 144
- [ ] Si aparece 144: Investigar por qué el bucle de espera no termina (bug lógico)
- [ ] Si no aparece 144: Investigar por qué la PPU no actualiza LY correctamente (bug de timing)
- [ ] Comparar el patrón de valores de LY con el comportamiento esperado (0→143→144→153→0)