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.
Debug Crítico: El "Test del Checkerboard" para Validar la Tubería de Datos
Resumen
Hemos llegado a un punto crítico. A pesar de tener un núcleo de emulación completamente sincronizado y funcional, la pantalla permanece en blanco. La hipótesis principal es que, aunque la PPU en C++ podría estar renderizando correctamente en su framebuffer interno, estos datos no están llegando a la capa de Python a través del puente de Cython (`memoryview`).
Este Step implementa un "Test del Checkerboard": modifica temporalmente `PPU::render_scanline()` para que ignore toda la lógica de emulación y dibuje un patrón de tablero de ajedrez directamente en el framebuffer. Esto nos permitirá validar de forma inequívoca si la tubería de datos C++ → Cython → Python está funcionando.
Concepto de Ingeniería: Aislamiento y Prueba de la Tubería de Datos
Cuando un sistema complejo falla, la mejor estrategia de depuración es el aislamiento. Vamos a aislar la "tubería" de renderizado del resto del emulador. Si podemos escribir datos en un `std::vector` en C++ y leerlos en un `PixelArray` en Python, entonces la tubería funciona. Si no, la tubería está rota.
El patrón de checkerboard es ideal porque es:
- Visualmente inconfundible: Un tablero de ajedrez es imposible de confundir con cualquier otro patrón.
- Fácil de generar matemáticamente: No requiere acceso a VRAM, tiles, o cualquier otro componente del emulador.
- Determinista: Si la tubería funciona, veremos el patrón. Si no funciona, veremos pantalla blanca.
Este test nos dará una respuesta binaria y definitiva sobre dónde está el problema:
- Si vemos el checkerboard: La tubería funciona. El problema está en la VRAM (la CPU no está copiando los datos del logo).
- Si la pantalla sigue en blanco: La tubería está rota. El problema está en el wrapper de Cython o en cómo se expone el framebuffer.
Implementación
Modificamos temporalmente `PPU::render_scanline()` para reemplazar toda la lógica de renderizado con un generador de patrón checkerboard simple.
Componentes modificados
src/core/cpp/PPU.cpp: Métodorender_scanline()reemplazado con lógica de checkerboard
Lógica del Checkerboard
El patrón se genera línea por línea:
// Para cada píxel (x, y) en la línea actual:
bool is_dark = ((ly_ / 8) % 2) == ((x / 8) % 2);
uint8_t color_index = is_dark ? 3 : 0;
framebuffer_[line_start_index + x] = color_index;
Esta lógica divide la pantalla en bloques de 8x8 píxeles. Si tanto la fila como la columna del bloque son pares o impares, el bloque es oscuro (color 3). Si uno es par y el otro impar, el bloque es claro (color 0).
Decisiones de diseño
- Ignorar toda la lógica de la PPU: No leemos LCDC, VRAM, tiles, o cualquier otro registro. Esto elimina todas las variables posibles excepto la tubería de datos.
- Usar colores 0 y 3: Color 0 (blanco) y color 3 (negro) son los extremos de la paleta, lo que hace el patrón más visible.
- Patrón de 8x8: Coincide con el tamaño de los tiles del Game Boy, lo que hace el patrón más reconocible para desarrolladores familiarizados con el hardware.
Archivos Afectados
src/core/cpp/PPU.cpp- Métodorender_scanline()reemplazado con test del checkerboarddocs/bitacora/entries/2025-12-20__0192__debug-critico-test-checkerboard-validar-tuberia-datos.html- Nueva entrada de bitácoradocs/bitacora/index.html- Actualizado con la nueva entradaINFORME_FASE_2.md- Actualizado con el Step 0192
Tests y Verificación
Este test es puramente visual. No requiere tests unitarios, ya que estamos validando la integración completa del sistema.
Proceso de Verificación
- Recompilar el módulo C++:
.\rebuild_cpp.ps1 - Ejecutar el emulador:
python main.py roms/tetris.gb - Observar la ventana de Pygame: La ventana debería mostrar uno de dos resultados posibles.
Resultados Posibles
Resultado 1: Vemos un Tablero de Ajedrez
Significado: ¡La tubería de datos funciona! C++ está escribiendo, Cython está exponiendo, y Python está leyendo y dibujando.
Diagnóstico: El problema, entonces, es 100% que la VRAM está realmente vacía. La CPU, por alguna razón que aún no entendemos, no está copiando los datos del logo.
Siguiente Paso: Volveríamos a instrumentar la CPU para entender por qué su camino de ejecución no llega a la rutina de copia de DMA/VRAM.
Resultado 2: La Pantalla Sigue en Blanco
Significado: ¡La tubería de datos está rota! La PPU C++ está generando el patrón, pero este nunca llega a la pantalla.
Diagnóstico: El problema está en nuestro wrapper de Cython (ppu.pyx), específicamente en cómo exponemos el puntero del framebuffer y lo convertimos en un memoryview.
Siguiente Paso: Depuraríamos la interfaz de Cython, verificando:
- Los punteros del framebuffer
- Los tipos de datos del memoryview
- El ciclo de vida del memoryview (si se está invalidando entre frames)
- La sincronización entre la escritura en C++ y la lectura en Python
Validación de módulo compilado C++
El emulador utiliza el módulo C++ compilado (viboy_core), que contiene la implementación modificada de PPU::render_scanline() con el test del checkerboard.
Fuentes Consultadas
- Documentación de Cython: Memoryviews y Zero-Copy
- Principios de depuración de sistemas complejos: Aislamiento y pruebas de integración
Integridad Educativa
Lo que Entiendo Ahora
- Aislamiento de componentes: Cuando un sistema complejo falla, la mejor estrategia es aislar cada componente y probarlo individualmente.
- Validación de la tubería de datos: En un sistema híbrido Python/C++, es crítico validar que los datos fluyen correctamente a través de las capas (C++ → Cython → Python).
- Patrones de depuración: Un patrón visual simple y determinista (como un checkerboard) es más valioso para depuración que un patrón complejo que podría fallar por múltiples razones.
Lo que Falta Confirmar
- Estado de la tubería de datos: ¿El framebuffer de C++ está llegando correctamente a Python a través del memoryview de Cython?
- Si la tubería funciona: ¿Por qué la CPU no está copiando los datos del logo a la VRAM?
- Si la tubería está rota: ¿Dónde exactamente se rompe la conexión? ¿En el puntero, en el memoryview, o en la sincronización?
Hipótesis y Suposiciones
Hipótesis principal: El problema está en la tubería de datos entre C++ y Python. Aunque la PPU podría estar renderizando correctamente en su framebuffer interno, estos datos no están llegando a la capa de Python.
Suposición: Si el test del checkerboard funciona, entonces sabemos que la tubería está bien y el problema está en la emulación de la CPU/VRAM. Si no funciona, entonces sabemos que el problema está en el wrapper de Cython.
Próximos Pasos
- [ ] Ejecutar el emulador con el test del checkerboard
- [ ] Observar el resultado visual (checkerboard o pantalla blanca)
- [ ] Si vemos checkerboard: Instrumentar la CPU para entender por qué no copia datos a VRAM
- [ ] Si vemos pantalla blanca: Depurar el wrapper de Cython y el memoryview del framebuffer
- [ ] Restaurar la lógica original de
render_scanline()una vez identificado el problema