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

Verificación Conexión MMU-PPU y Limpieza de Debug

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

Resumen

Se verificó y confirmó que la conexión entre MMU y PPU para la lectura del registro LY (0xFF44) está correctamente implementada. El código existente ya manejaba correctamente la lectura de LY desde la PPU cuando el juego accede a la dirección 0xFF44. Se eliminaron los prints de debug temporales que se habían añadido en el paso anterior (sonda de diagnóstico) para limpiar el código y mejorar el rendimiento. El test test_ly_read_from_mmu confirma que la funcionalidad está operativa.

Concepto de Hardware

El registro LY (Línea actual) en la dirección 0xFF44 es un registro de solo lectura que indica qué línea de escaneo se está dibujando actualmente (rango 0-153). Los juegos leen constantemente este registro para sincronizarse y saber cuándo pueden actualizar la VRAM de forma segura (durante V-Blank, cuando LY >= 144).

En hardware real, el registro LY está conectado directamente a la PPU (Pixel Processing Unit), no a la memoria RAM. Cuando el software lee 0xFF44, el hardware devuelve el valor actual de LY desde la PPU, no desde una celda de memoria. Si el juego lee un valor incorrecto (por ejemplo, 0 constante), puede quedarse en un bucle infinito esperando que LY cambie.

Fuente: Pan Docs - LCD Timing, LY Register (0xFF44)

Implementación

Se verificó que la implementación existente en src/memory/mmu.py ya maneja correctamente la lectura de LY:

# En read_byte(), líneas 232-237
if addr == IO_LY:
    if self._ppu is not None:
        return self._ppu.get_ly() & 0xFF
    else:
        return 0

La conexión PPU-MMU se establece correctamente en src/viboy.py mediante el método set_ppu() después de crear ambas instancias (evitando dependencias circulares).

Limpieza de código de debug

Se eliminaron los prints de debug temporales que se habían añadido en el paso anterior:

  • Eliminado: Print de "DEBUG PROBE" cada 1000 iteraciones (líneas 313-325)
  • Eliminado: Límite de seguridad con prints de emergencia (líneas 327-332)
  • Eliminado: Print de "V-BLANK DETECTADO" (líneas 348-354)
  • Mantenido: Heartbeat con logger.info() cada 60 frames (línea 364)

Estos prints estaban ralentizando la ejecución y ya no son necesarios ahora que se confirmó que la conexión MMU-PPU funciona correctamente.

Archivos Afectados

  • src/viboy.py - Eliminados prints de debug temporales del bucle principal

Tests y Verificación

Se ejecutó el test existente que verifica la lectura de LY desde la MMU:

  • Comando ejecutado: pytest tests/test_ppu_timing.py::TestPPUTiming::test_ly_read_from_mmu -v
  • Entorno: Windows, Python 3.13.5
  • Resultado: PASSED (1 passed in 0.25s)
  • Qué valida:
    • La MMU puede leer LY desde la PPU a través del registro 0xFF44
    • El valor devuelto por MMU coincide con el valor interno de la PPU
    • El valor cambia correctamente cuando la PPU avanza líneas

Código del test:

def test_ly_read_from_mmu(self) -> None:
    """Test: La MMU puede leer LY desde la PPU a través del registro 0xFF44."""
    mmu = MMU(None)
    ppu = PPU(mmu)
    mmu.set_ppu(ppu)
    
    # Inicialmente LY debe ser 0
    assert mmu.read_byte(0xFF44) == 0
    
    # Avanzar algunas líneas
    ppu.step(456 * 5)  # 5 líneas
    
    # LY debe ser 5
    assert ppu.get_ly() == 5
    
    # La MMU debe devolver el mismo valor
    assert mmu.read_byte(0xFF44) == 5

Por qué este test demuestra algo del hardware: Este test verifica que cuando el software (juego) lee la dirección 0xFF44, obtiene el valor actual de LY desde la PPU, no desde la memoria RAM. Esto es crítico porque los juegos dependen de este valor para sincronizarse y saber cuándo pueden actualizar la VRAM de forma segura. Si la MMU devolviera un valor incorrecto (por ejemplo, siempre 0), el juego se quedaría en un bucle infinito esperando que LY cambie.

Fuentes Consultadas

Integridad Educativa

Lo que Entiendo Ahora

  • Registro LY (0xFF44): Es un registro de solo lectura conectado directamente a la PPU. Cuando el software lee esta dirección, el hardware devuelve el valor actual de LY desde la PPU, no desde la memoria RAM.
  • Conexión MMU-PPU: La MMU necesita una referencia a la PPU para poder devolver el valor correcto de LY cuando se lee 0xFF44. Esta conexión se establece después de crear ambas instancias para evitar dependencias circulares.
  • Importancia crítica: Si el juego lee un valor incorrecto de LY (por ejemplo, siempre 0), puede quedarse en un bucle infinito esperando que LY cambie, lo que causa el síntoma de "pantalla blanca eterna" o "emulador congelado".

Lo que Falta Confirmar

  • Comportamiento en hardware real: Según la documentación, LY es de solo lectura y escribir en él no tiene efecto. Esto ya está implementado correctamente en el código (se ignora silenciosamente).
  • Timing exacto: La PPU avanza LY cada 456 T-Cycles. Esto está implementado y verificado por los tests, pero podría necesitar ajustes finos si se detectan problemas de sincronización en juegos reales.

Hipótesis y Suposiciones

Hipótesis principal: El problema de "pantalla blanca eterna" que se observó en el paso anterior (0040) NO se debe a un problema de conexión MMU-PPU, ya que el código está correctamente implementado y los tests pasan. El problema probablemente se debe a otro factor, como:

  • El juego está esperando una interrupción V-Blank que no se está procesando correctamente
  • El juego está esperando que pase un tiempo específico (contando ciclos) antes de continuar
  • Hay algún otro registro de I/O que no está implementado correctamente

Esta hipótesis se validará en pasos posteriores cuando se pruebe el emulador con ROMs reales y se observe el comportamiento detallado.

Próximos Pasos

  • [ ] Si el problema de "pantalla blanca" persiste, investigar el manejo de interrupciones V-Blank
  • [ ] Verificar que las interrupciones se procesan correctamente cuando IME está habilitado
  • [ ] Probar el emulador con ROMs de test para validar el comportamiento completo
  • [ ] Continuar con la implementación de características faltantes según sea necesario