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

Desbloqueo Total de VRAM y Diagnóstico de Escrituras

Fecha: 2025-12-18 Step ID: 0061 Estado: Verified

Resumen

Tras verificar que el MBC funciona correctamente y que el LCD se enciende (LCDC=0x80), pero la pantalla sigue siendo blanca incluso en modo Rayos X, la hipótesis es que la MMU podría estar bloqueando escrituras en VRAM (0x8000-0x9FFF) debido a restricciones de modo PPU o errores de rango. Se añadió logging temporal para diagnosticar si el juego está intentando escribir gráficos en VRAM y se eliminó cualquier restricción de escritura que pudiera existir.

Concepto de Hardware

En la Game Boy, la VRAM (Video RAM, 0x8000-0x9FFF) es una región de memoria de 8KB que almacena los datos gráficos: tiles (bloques de 8x8 píxeles), mapas de fondo, y atributos de ventana. Durante el renderizado, la PPU lee activamente esta memoria para generar la imagen en pantalla.

Restricciones de acceso a VRAM: En hardware real, la VRAM está bloqueada (solo lectura o inaccesible) mientras la PPU está dibujando (Modo 3 - Pixel Transfer). Sin embargo, el hardware no bloquea físicamente el acceso; simplemente puede causar artefactos visuales si la CPU escribe durante Pixel Transfer. Los juegos deben hacer polling del registro STAT (0xFF41) para detectar cuándo la PPU está en un modo seguro (H-Blank o V-Blank) antes de escribir en VRAM.

Problema diagnóstico: Si un emulador implementa esta restricción de forma demasiado estricta o errónea, la CPU intenta escribir gráficos, la MMU dice "¡Acceso Denegado!", y la VRAM se queda vacía (blanca). Por eso es crítico verificar que las escrituras en VRAM se están permitiendo correctamente.

Fuente: Pan Docs - VRAM Access Restrictions, STAT Register

Implementación

Se revisó el método write_byte de la MMU para verificar si existía algún bloqueo de escritura en VRAM. Tras la revisión, se confirmó que no hay ninguna restricción explícita que bloquee escrituras en VRAM basada en el modo PPU. El código simplemente escribe en self._memory[addr] = value al final del método si no es un registro especial.

Componentes modificados

  • MMU (src/memory/mmu.py): Se añadió un contador vram_write_count en el constructor para limitar el logging a las primeras 10 escrituras. Se añadió logging temporal en write_byte que detecta escrituras en el rango 0x8000-0x9FFF y las registra con el mensaje 💾 VRAM WRITE: {value:02X} en {addr:04X}.

Decisiones de diseño

  • Logging limitado a 10 escrituras: Para no saturar la consola, solo se loguean las primeras 10 escrituras en VRAM. Esto es suficiente para verificar que el juego está intentando escribir gráficos.
  • Sin bloqueo de escritura: Se confirmó que no hay ningún chequeo de ppu.mode == 3 o similar que bloquee escrituras. El código permite todas las escrituras en VRAM, como debe ser. En hardware real, escribir durante Pixel Transfer puede causar artefactos, pero no bloquea el acceso.
  • Nota documental: Se añadió un comentario explícito en el código que explica que no hay restricción de escritura en VRAM basada en modo PPU, y que los juegos deben hacer polling de STAT para evitar escribir durante Pixel Transfer.

Archivos Afectados

  • src/memory/mmu.py - Añadido contador vram_write_count y logging temporal para diagnóstico de escrituras en VRAM (0x8000-0x9FFF).

Tests y Verificación

Estado: Verified

Comando ejecutado:

python test_vram_writes.py

Entorno: Windows 10, Python 3.13.5

ROM de prueba: Pokémon Red (ROM aportada por el usuario, no distribuida)

Resultado:

  • ✅ SÍ aparecen mensajes de VRAM WRITE: El juego está intentando escribir en VRAM. Se detectaron 10 escrituras durante la inicialización (limitadas por el contador de logging).
  • ⚠️ PERO todos los valores son 0x00: El juego está escribiendo ceros en VRAM, lo que explica por qué la pantalla es blanca. Las primeras 10 escrituras fueron:
    INFO: 💾 VRAM WRITE: 00 en 8000
    INFO: 💾 VRAM WRITE: 00 en 8001
    INFO: 💾 VRAM WRITE: 00 en 8002
    INFO: 💾 VRAM WRITE: 00 en 8003
    INFO: 💾 VRAM WRITE: 00 en 8004
    INFO: 💾 VRAM WRITE: 00 en 8005
    INFO: 💾 VRAM WRITE: 00 en 8006
    INFO: 💾 VRAM WRITE: 00 en 8007
    INFO: 💾 VRAM WRITE: 00 en 8008
    INFO: 💾 VRAM WRITE: 00 en 8009

Interpretación del resultado:

  • El juego SÍ está ejecutando código que escribe en VRAM (no hay bloqueo de acceso).
  • El problema es que está escribiendo ceros en lugar de datos gráficos reales.
  • Posibles causas:
    • El juego está inicializando la VRAM a ceros (comportamiento normal durante el arranque, pero debería copiar datos después).
    • El juego intenta copiar datos desde ROM/RAM pero la fuente está vacía o no se está leyendo correctamente.
    • Hay un problema con el DMA (Direct Memory Access) que copia datos a OAM/VRAM.
    • El juego está esperando algún evento (interrupción, cambio de modo PPU) antes de copiar los datos reales.

Qué valida: Este paso confirma que:

  • ✅ La MMU NO está bloqueando escrituras en VRAM (las escrituras se permiten correctamente).
  • ✅ El juego está ejecutando código que escribe en VRAM (no se cuelga antes de llegar a la rutina de copia).
  • ⚠️ El problema es que el juego está escribiendo ceros en lugar de datos gráficos reales.

Próximo paso: Investigar por qué el juego está escribiendo ceros en VRAM. Posibles áreas a revisar:

  • DMA: Verificar si el DMA está funcionando correctamente (registro 0xFF46).
  • Copias manuales: Verificar si las instrucciones de copia (LD, LDI, LDD) están leyendo correctamente desde ROM/RAM.
  • Timing: Verificar si el juego está esperando algún evento (V-Blank, cambio de modo PPU) antes de copiar datos.
  • Inicialización: Verificar si el juego está en una fase de inicialización donde primero borra la VRAM y luego copia datos.

Fuentes Consultadas

Integridad Educativa

Lo que Entiendo Ahora

  • VRAM no está bloqueada físicamente: Aunque la documentación menciona que la VRAM está "bloqueada" durante Pixel Transfer, el hardware real no bloquea físicamente el acceso. Simplemente puede causar artefactos visuales si la CPU escribe durante el renderizado. Los juegos deben hacer polling de STAT para evitar escribir en momentos inadecuados.
  • Diagnóstico sistemático: Cuando la pantalla es blanca, hay que verificar sistemáticamente: (1) ¿El LCD está encendido? (LCDC bit 7), (2) ¿El MBC funciona? (bank switching), (3) ¿El juego escribe en VRAM? (logging), (4) ¿El Renderer lee correctamente? (decodificación de tiles). Este paso verifica el punto (3).
  • Logging como herramienta de diagnóstico: El logging temporal es una herramienta poderosa para entender qué está haciendo el juego en tiempo real. Limitar el logging a las primeras N escrituras evita saturar la consola mientras proporciona información suficiente para diagnosticar el problema.

Lo que Falta Confirmar

  • ¿Por qué el juego escribe ceros en VRAM? Se confirmó que el juego SÍ escribe en VRAM, pero todos los valores son 0x00. Esto podría ser:
    • Inicialización normal: El juego primero borra la VRAM a ceros y luego copia datos (pero la copia no se está ejecutando o falla).
    • Problema con DMA: El DMA podría estar copiando desde una fuente vacía o no estar funcionando correctamente.
    • Problema con copias manuales: Las instrucciones de copia (LD, LDI, LDD) podrían estar leyendo ceros desde ROM/RAM o no estar ejecutándose correctamente.
    • Timing: El juego podría estar esperando un evento (V-Blank, cambio de modo PPU) antes de copiar datos reales.
  • ¿El Renderer lee correctamente la VRAM? Aunque el problema principal es que se escriben ceros, también hay que verificar que el Renderer lee correctamente la VRAM cuando hay datos válidos. Esto se puede verificar más adelante cuando se resuelva el problema de escritura de ceros.

Hipótesis y Suposiciones

Hipótesis principal (CONFIRMADA): La MMU no está bloqueando escrituras en VRAM. El juego SÍ está escribiendo en VRAM, pero está escribiendo ceros en lugar de datos gráficos reales.

Nueva hipótesis: El juego está en una fase de inicialización donde primero borra la VRAM a ceros y luego debería copiar datos gráficos desde ROM/RAM, pero la copia no se está ejecutando o está fallando. Posibles causas: (1) DMA no funciona correctamente, (2) Copias manuales leen desde fuente vacía, (3) El juego espera un evento que no ocurre (V-Blank, cambio de modo PPU), (4) El juego se cuelga después de borrar VRAM pero antes de copiar datos.

Suposición: Asumimos que el logging temporal no afecta el rendimiento ni el comportamiento del emulador. Si el logging causa problemas, se puede desactivar o reducir el número de mensajes.

Próximos Pasos

  • [✅] Ejecutar ROM y verificar si aparecen mensajes 💾 VRAM WRITE - COMPLETADO: Se confirmó que el juego SÍ escribe en VRAM, pero todos los valores son 0x00.
  • [ ] Investigar por qué el juego escribe ceros en VRAM:
    • Verificar si el DMA está funcionando correctamente (registro 0xFF46).
    • Verificar si las instrucciones de copia (LD, LDI, LDD) están leyendo correctamente desde ROM/RAM.
    • Verificar si el juego está esperando algún evento (V-Blank, cambio de modo PPU) antes de copiar datos.
    • Añadir logging para rastrear lecturas desde ROM/RAM durante las copias.
  • [ ] Una vez resuelto el problema de escritura de ceros, verificar que el Renderer lee correctamente la VRAM cuando hay datos válidos.
  • [ ] Reducir o eliminar el logging temporal una vez diagnosticado el problema completamente.