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

Debug: Verificación de Puntero Nulo en la PPU

Fecha: 2025-12-19 Step ID: 0141 Estado: 🔍 DRAFT

Resumen

Se añadió una verificación de diagnóstico temporal en el método render_scanline() de la PPU para confirmar si el puntero a la MMU es nulo cuando se llama al método. Esta verificación utiliza printf para emitir un mensaje crítico que confirme si el problema está en la capa de Cython, específicamente en cómo se pasa el puntero desde el wrapper de Cython al constructor de la PPU en C++.

Concepto de Hardware

En un emulador híbrido Python/C++, la comunicación entre las capas requiere un manejo cuidadoso de los punteros. El flujo de datos desde Python hasta C++ pasa por varias capas:

  1. Python: Se crea una instancia de PyMMU, que contiene un puntero C++ válido (MMU*).
  2. Python: Se crea una instancia de PyPPU pasando el objeto PyMMU.
  3. Cython: El constructor de PyPPU debe "desenvolver" el objeto PyMMU para extraer el puntero MMU* crudo que contiene y pasárselo al constructor de la PPU en C++.
  4. C++: El constructor de la PPU recibe el puntero MMU* y lo almacena en un miembro de la clase.

Si en cualquier punto de esta cadena el puntero se corrompe o no se pasa correctamente, la PPU intentará acceder a memoria inválida, causando un Segmentation Fault. La verificación de puntero nulo con printf nos permite identificar exactamente en qué punto falla la cadena.

Implementación

Se añadió una verificación temporal de puntero nulo al inicio del método render_scanline() que imprime un mensaje crítico si el puntero mmu_ es nulo. Esta verificación es binaria y definitiva:

Componentes modificados

  • PPU.cpp: Se añadió #include <cstdio> para usar printf.
  • PPU.cpp: Se añadió una verificación if (this->mmu_ == nullptr) al inicio de render_scanline() que imprime un mensaje y retorna temprano para evitar el crash.

Código añadido

#include <cstdio>

// ...

void PPU::render_scanline() {
    // CRÍTICO: Verificar que mmu_ no sea nullptr antes de acceder
    // AÑADE ESTA VERIFICACIÓN CRÍTICA AL INICIO DEL MÉTODO
    if (this->mmu_ == nullptr) {
        printf("[PPU CRITICAL] ¡El puntero a la MMU es NULO! El problema está en la capa de Cython.\n");
        return; // Salimos pronto para evitar el crash y ver el mensaje.
    }
    
    // ... resto del método render_scanline ...
}

Decisiones de diseño

Se utiliza printf en lugar de std::cout porque es más seguro para depuración de crashes (no depende de los objetos estáticos de la librería estándar de C++ que pueden no estar inicializados durante un crash). El mensaje es explícito y directo para identificar rápidamente el problema si ocurre.

Nota: Esta verificación es temporal y será eliminada una vez confirmado o descartado el problema del puntero nulo. Si el mensaje aparece, confirmaremos que el problema está en el wrapper de Cython. Si no aparece y el crash persiste, sabremos que el problema es más profundo.

Archivos Afectados

  • src/core/cpp/PPU.cpp - Añadido #include <cstdio> y verificación de puntero nulo con printf en render_scanline()

Tests y Verificación

Esta verificación se valida mediante ejecución real del emulador:

  1. Recompilación: Se debe recompilar el módulo C++ con .\rebuild_cpp.ps1.
  2. Ejecución: Se ejecuta el emulador con python main.py roms/tetris.gb.
  3. Análisis del resultado:
    • Si aparece el mensaje: Confirma al 100% que el problema está en el wrapper de Cython (ppu.pyx) y sabremos exactamente dónde corregirlo.
    • Si NO aparece el mensaje y sigue habiendo crash: Nuestra hipótesis es incorrecta y el problema es más profundo (aunque esto es muy poco probable).

Validación de módulo compilado C++: Esta verificación se ejecuta directamente en el código compilado de C++, por lo que cualquier mensaje impreso confirmará que el código C++ se está ejecutando correctamente y que el puntero es efectivamente nulo en ese momento.

Fuentes Consultadas

  • Documentación de Cython: https://cython.readthedocs.io/ - Gestión de punteros C++ desde Python
  • Principios de depuración de punteros: Basado en conocimiento general de depuración de sistemas híbridos Python/C++

Integridad Educativa

Lo que Entiendo Ahora

  • Flujo de punteros en arquitectura híbrida: El flujo Python → Cython → C++ requiere un manejo cuidadoso de los punteros en cada capa. Si el puntero se corrompe en cualquier punto, el resultado será un crash en tiempo de ejecución.
  • Diagnóstico binario: Las verificaciones de puntero nulo con mensajes de diagnóstico son herramientas efectivas para aislar problemas en sistemas híbridos, ya que proporcionan una respuesta binaria: el puntero es nulo o no lo es.

Lo que Falta Confirmar

  • Hipótesis del wrapper de Cython: Necesitamos confirmar si el problema está en cómo Cython extrae el puntero de PyMMU y lo pasa al constructor de la PPU. Si el mensaje aparece, confirmaremos esta hipótesis.
  • Corrección del wrapper: Si se confirma que el problema está en Cython, necesitaremos revisar el código de ppu.pyx para corregir cómo se pasa el puntero.

Hipótesis y Suposiciones

Hipótesis principal (99% de certeza): El puntero MMU* que se pasa al constructor de la PPU desde el wrapper de Cython ya es un puntero nulo (nullptr). El problema no está en la asignación dentro del constructor de la PPU, sino en el valor que se está pasando.

Esta hipótesis se basa en el hecho de que:

  1. Ya hemos descartado que el problema esté en los valores calculados (Step 0139).
  2. Ya hemos confirmado que el constructor asigna correctamente el puntero (Step 0140).
  3. El único punto restante en la cadena es el paso del puntero desde Cython a C++.

Próximos Pasos

  • [ ] Recompilar el módulo C++: .\rebuild_cpp.ps1
  • [ ] Ejecutar el emulador: python main.py roms/tetris.gb
  • [ ] Analizar el resultado:
    • Si aparece el mensaje: Revisar y corregir el wrapper de Cython (ppu.pyx)
    • Si NO aparece: Investigar causas más profundas del Segmentation Fault
  • [ ] Eliminar la verificación temporal una vez confirmado el problema