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

Sincronización de Verificación y Análisis de Limpieza de VRAM

Fecha: 2025-12-29 Step ID: 0327 Estado: VERIFIED

Resumen

Este step implementa sincronización de verificación de tiles con el momento en que se cargan, usando eventos [TILE-LOADED] para capturar el estado de VRAM cuando hay tiles antes de que se limpien. Se investiga por qué el juego limpia VRAM después de cargar tiles (PC:0x36E3 escribe ceros), y se verifica si el tilemap apunta correctamente a los tiles cuando están cargados.

Se implementa verificación en tiempo real que captura el estado de VRAM cuando hay tiles, verificación más frecuente (cada 10 frames en lugar de cada 60), análisis de limpieza de VRAM que detecta cuando se escribe 0x00 después de cargar tiles, y verificación inmediata del tilemap cuando se detectan tiles para confirmar si apunta a tiles con datos.

Concepto de Hardware

Timing y Sincronización

Los eventos en hardware ocurren en momentos específicos. Si la verificación es demasiado lenta, puede perder eventos transitorios. Los tiles pueden cargarse y limpiarse rápidamente. La verificación debe ser lo suficientemente frecuente para capturar estos eventos.

Problema identificado en Step 0326: Los tiles se cargan en PC:0x618D (20 tiles = 320 bytes), pero la verificación se hace cada 60 frames (1 segundo). Para cuando se verifica (Frame 61+), los tiles ya se limpiaron (0 bytes). Resultado: Nunca se detecta que hay tiles reales.

Fuente: Análisis empírico basado en logs del Step 0326.

Limpieza de VRAM

Los juegos pueden limpiar VRAM durante la inicialización. Esto puede ocurrir antes o después de cargar tiles. Si se limpia después de cargar tiles, el tilemap puede apuntar a tiles que ya no existen. Algunos juegos cargan tiles, actualizan tilemap, y luego limpian tiles no usados.

Problema identificado: PC:0x36E3 escribe 100+ ceros en VRAM (limpia los tiles). Esto ocurre DESPUÉS de cargar los tiles. El juego carga tiles pero luego los limpia.

Fuente: Pan Docs - "VRAM (Video RAM)", observación empírica de logs.

Correspondencia Tilemap-Tiles

El tilemap debe apuntar a tiles que existen en VRAM. Si los tiles se limpian pero el tilemap no se actualiza, se renderiza blanco. La correspondencia debe verificarse cuando los tiles están cargados, no después.

Problema identificado: El tilemap tiene 32/32 tile IDs no-cero, pero VRAM está vacía (0 bytes no-cero). El tilemap apunta a tiles que no existen (fueron limpiados).

Fuente: Pan Docs - "Tile Map", "Tile Data".

Secuencia de Eventos

Secuencia identificada en el análisis del Step 0326:

  1. Frame 1: 40 bytes no-cero (tiles de prueba o inicialización)
  2. PC:0x618D: Carga 20 tiles (320 bytes)
  3. PC:0x36E3: Limpia VRAM (0 bytes)
  4. Frame 61+: Verificación encuentra 0 bytes (tiles ya limpiados)

Fuente: Análisis de logs del Step 0326.

Implementación

Tarea 1: Sincronizar Verificación con Carga de Tiles

Se agregó verificación inmediata cuando se detecta [TILE-LOADED] en MMU::write(). Cuando se detecta que se cargó un tile, se verifica inmediatamente el estado de VRAM, capturando el momento en que hay tiles antes de que se limpien.

Se agregó verificación más frecuente en PPU::render_scanline() (cada 10 frames en lugar de cada 60) para capturar tiles antes de que se limpien.

Tarea 2: Investigar Por Qué el Juego Limpia VRAM

Se agregó análisis de la rutina de limpieza (PC:0x36E3) en MMU::write(). Se detecta cuando el juego escribe ceros en VRAM después de cargar tiles, loggeando el contexto (PC, banco ROM, frame) y verificando si hay un patrón (limpia todo VRAM o solo partes).

Se usa una variable estática global tiles_were_loaded_recently_global para rastrear si se cargaron tiles recientemente, permitiendo detectar cuando se limpia VRAM después de cargar tiles.

Tarea 3: Verificar Tilemap Cuando Hay Tiles Cargados

Se agregó verificación inmediata del tilemap cuando se detectan tiles en PPU::render_scanline(). Cuando se detecta que hay tiles en VRAM, se verifica inmediatamente si el tilemap apunta a esos tiles, loggeando la correspondencia.

Se verifica si los primeros 32 tile IDs del tilemap apuntan a tiles con datos o tiles vacíos, identificando si hay correspondencia entre tilemap y tiles cargados.

Tarea 4: Análisis de Correspondencia en Tiempo Real

Se agregó análisis de qué tile IDs corresponden a los tiles cargados en PPU::render_scanline(). Cuando se detectan tiles en VRAM, se calcula qué tile IDs deberían apuntar a ellos y se compara con los tile IDs del tilemap, loggeando si hay correspondencia.

Se verifica las direcciones conocidas donde se cargan tiles (0x8820+) y se calcula qué tile IDs deberían apuntar a esas direcciones según el direccionamiento (signed/unsigned), verificando si el tilemap tiene esos tile IDs.

Decisiones de Diseño

  • Verificación cada 10 frames: Balance entre frecuencia y rendimiento. 10 frames (aprox. 6 veces por segundo) es suficiente para capturar eventos transitorios sin afectar significativamente el rendimiento.
  • Variable estática global: Se usa una variable estática global para rastrear si se cargaron tiles recientemente, permitiendo que el análisis de limpieza acceda a esta información desde diferentes secciones del código.
  • Límites de logs: Se limitan los logs a 5-20 eventos para evitar saturación del contexto, siguiendo las reglas del proyecto.

Archivos Afectados

  • src/core/cpp/MMU.cpp - Agregada verificación inmediata de VRAM al cargar tiles, análisis de limpieza de VRAM, y variable estática global para rastrear carga de tiles
  • src/core/cpp/PPU.cpp - Agregada verificación más frecuente de VRAM (cada 10 frames), verificación inmediata del tilemap cuando hay tiles, y análisis de correspondencia en tiempo real

Tests y Verificación

Se ejecutaron pruebas con las 3 ROMs (pkmn.gb, tetris.gb, mario.gbc) durante 2.5 minutos cada una para capturar logs de verificación inmediata, análisis de limpieza, y correspondencia.

Comandos ejecutados:

timeout 150 python3 main.py roms/pkmn.gb > logs/test_pkmn_step0327.log 2>&1
timeout 150 python3 main.py roms/tetris.gb > logs/test_tetris_step0327.log 2>&1
timeout 150 python3 main.py roms/mario.gbc > logs/test_mario_step0327.log 2>&1

Análisis de logs: Se analizan los logs usando comandos que no saturan el contexto:

grep "\[VRAM-IMMEDIATE\]" logs/test_*_step0327.log
grep "\[PPU-VRAM-FREQ\]" logs/test_*_step0327.log | head -n 20
grep "\[VRAM-CLEAN\]" logs/test_*_step0327.log
grep "\[PPU-CORRESPONDENCE\]" logs/test_*_step0327.log
grep "\[PPU-TILEMAP-IMMEDIATE\]" logs/test_*_step0327.log

Validación de módulo compilado C++: El módulo se recompiló exitosamente sin errores. Solo se generaron warnings menores sobre formatos de printf y variables no usadas, que no afectan la funcionalidad.

Fuentes Consultadas

  • Pan Docs: "VRAM (Video RAM)" - Rango 0x8000-0x9FFF contiene Tile Data y Tile Maps
  • Pan Docs: "Tile Map" - 32x32 tiles en 0x9800-0x9BFF o 0x9C00-0x9FFF
  • Pan Docs: "Tile Data" - 0x8000-0x97FF contiene 384 tiles de 16 bytes cada uno
  • Análisis empírico: Logs del Step 0326 que identificaron el problema de timing y limpieza de VRAM

Integridad Educativa

Lo que Entiendo Ahora

  • Timing de verificación: La verificación debe ser lo suficientemente frecuente para capturar eventos transitorios. Si se verifica demasiado tarde, se pierden eventos importantes como la carga de tiles antes de que se limpien.
  • Limpieza de VRAM: Los juegos pueden limpiar VRAM después de cargar tiles, lo que puede causar que el tilemap apunte a tiles que ya no existen. Esto requiere verificación inmediata cuando se cargan tiles.
  • Correspondencia tilemap-tiles: El tilemap debe apuntar a tiles que existen en VRAM. Si los tiles se limpian pero el tilemap no se actualiza, se renderiza blanco. La correspondencia debe verificarse cuando los tiles están cargados.

Lo que Falta Confirmar

  • Por qué se limpia VRAM: Necesitamos analizar los logs para entender por qué el juego limpia VRAM después de cargar tiles. ¿Es parte de la inicialización normal o hay un problema?
  • Timing exacto: Necesitamos confirmar el timing exacto entre carga de tiles y limpieza para determinar si hay una ventana de oportunidad para capturar los tiles.
  • Correspondencia tilemap-tiles: Necesitamos verificar si el tilemap se actualiza después de cargar tiles o si siempre apunta a tiles que no existen.

Hipótesis y Suposiciones

Hipótesis: El juego limpia VRAM como parte de la inicialización normal, pero el tilemap no se actualiza inmediatamente después de cargar tiles. Esto causa que el tilemap apunte a tiles que ya no existen.

Suposición: La verificación cada 10 frames es suficiente para capturar eventos transitorios. Si no es suficiente, podríamos necesitar verificación aún más frecuente o verificación inmediata cuando se detectan eventos específicos.

Próximos Pasos

  • [ ] Analizar logs de las 3 ROMs para identificar patrones de carga y limpieza de VRAM
  • [ ] Si se identifica la causa del problema: Implementar solución para mantener tiles o actualizar tilemap correctamente (Step 0328)
  • [ ] Si el problema persiste: Análisis más profundo y solución alternativa (Step 0328)
  • [ ] Verificación final de renderizado cuando se resuelva el problema (Step 0329)