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.
Configuración del Pipeline de Compilación Híbrido
Resumen
Se ha configurado la infraestructura completa de compilación híbrida (Python + C++/Cython) para la Fase 2.
Se creó la estructura de directorios del núcleo, se implementó una prueba de concepto "Hello World" en C++,
se configuró el sistema de build con setup.py y se verificó que el pipeline de compilación
funciona correctamente en Windows. Este es el primer paso crítico antes de migrar cualquier componente
de emulación al código compilado.
Concepto de Hardware
Nota: Esta entrada no trata directamente sobre hardware del Game Boy, sino sobre la infraestructura de compilación necesaria para emularlo eficientemente.
La emulación ciclo a ciclo de un sistema como el Game Boy requiere precisión de timing en el orden de microsegundos. Python, siendo un lenguaje interpretado, introduce overhead significativo en cada operación, lo que impide alcanzar la sincronización necesaria para jugabilidad fluida.
La solución adoptada es una arquitectura híbrida:
- Python (Frontend): Maneja la interfaz de usuario, carga de archivos, eventos de input y orquestación de alto nivel. Mantiene la flexibilidad y facilidad de desarrollo.
- C++ (Núcleo): Implementa la lógica crítica de emulación ciclo a ciclo (CPU, MMU, PPU, APU). Proporciona el rendimiento necesario para sincronización precisa.
- Cython (Puente): Permite que Python llame a código C++ compilado sin overhead significativo. Cython genera código C que se compila a extensiones Python (.pyd en Windows, .so en Linux/macOS).
Esta arquitectura permite mantener los beneficios de Python (tests, documentación, desarrollo rápido) mientras se obtiene el rendimiento de código compilado en las rutas críticas.
Implementación
Se configuró completamente el sistema de compilación híbrido siguiendo las mejores prácticas de Cython y setuptools. La implementación incluye:
1. Gestión de Dependencias
Se actualizó requirements.txt con las dependencias necesarias:
cython>=3.0.0: Compilador Cython para generar código C/C++setuptools>=68.0.0: Sistema de build para extensiones Pythonnumpy>=1.24.0: Para futuros usos de buffers de video/audio (MemoryViews)
2. Estructura de Directorios
Se creó la siguiente estructura para organizar el código del núcleo:
src/core/
├── __init__.py # Módulo Python del núcleo
├── cpp/ # Código C++ puro (.cpp, .hpp)
│ ├── NativeCore.hpp
│ └── NativeCore.cpp
└── cython/ # Wrappers Cython (.pyx, .pxd)
└── native_core.pyx
3. Prueba de Concepto: NativeCore
Se implementó una clase C++ simple NativeCore con un método add(int a, int b)
para verificar que el pipeline funciona. Esta clase será expandida en el futuro para contener la lógica
de emulación.
Archivo C++ (NativeCore.hpp/cpp):
- Clase simple con constructor, destructor y método
add() - Estándar C++17 para compatibilidad moderna
- Preparado para expansión futura
4. Wrapper Cython
Se creó el wrapper Cython native_core.pyx que:
- Declara la clase C++ usando
cdef extern - Expone una clase Python
PyNativeCoreque envuelve la clase C++ - Gestiona memoria correctamente (constructor
__cinit__y destructor__dealloc__) - Permite llamar métodos C++ desde Python sin overhead
5. Sistema de Build (setup.py)
Se configuró setup.py con:
- Extensiones Cython usando
Cython.Build.cythonize - Configuración de compilador C++17 (compatible con Windows/Linux/macOS)
- Directivas de optimización:
boundscheck=False,wraparound=False - Include directories para headers C++ y numpy
6. Script de Verificación
Se creó test_build.py que:
- Importa el módulo compilado
viboy_core - Crea una instancia de
PyNativeCore - Ejecuta la prueba:
core.add(2, 2) == 4 - Proporciona mensajes de error claros si la compilación falla
Decisiones de Diseño
- Separación C++/Cython: El código C++ puro está en
cpp/y los wrappers encython/. Esto permite reutilizar el código C++ en otros contextos si es necesario. - Naming: El módulo compilado se llama
viboy_corepara evitar conflictos con el módulo Pythonsrc/core. - Windows Compatibility: Se usa
/std:c++17para MSVC y-std=c++17para GCC/Clang, detectando automáticamente la plataforma.
Archivos Afectados
requirements.txt- Añadidas dependencias Cython, setuptools, numpysrc/core/__init__.py- Módulo Python del núcleo (nuevo)src/core/cpp/NativeCore.hpp- Header C++ de prueba (nuevo)src/core/cpp/NativeCore.cpp- Implementación C++ de prueba (nuevo)src/core/cython/native_core.pyx- Wrapper Cython (nuevo)setup.py- Sistema de build para extensiones (nuevo)test_build.py- Script de verificación (nuevo)
Tests y Verificación
La verificación se realizó mediante el script test_build.py:
- Compilación: Ejecutar
python setup.py build_ext --inplacegenera el archivoviboy_core.pyd(oviboy_core.soen Linux/macOS) en el directorio raíz. - Importación: El módulo se importa correctamente desde Python.
- Instanciación: Se puede crear una instancia de
PyNativeCoresin errores. - Funcionalidad: El método
add(2, 2)retorna correctamente4.
Comando de compilación:
python setup.py build_ext --inplace
Comando de verificación:
python test_build.py
Nota: Si la compilación falla, puede ser necesario instalar Visual Studio Build Tools en Windows o las herramientas de desarrollo en Linux/macOS.
Resultados de Verificación Realizados
La compilación y verificación se ejecutaron exitosamente en Windows 10 con Python 3.13:
- Dependencias instaladas: Cython 3.2.3, setuptools 75.1.0, numpy 2.2.6
- Compilador detectado: Visual Studio 2022 Community (MSVC 14.44.35207)
- Archivo generado:
viboy_core.cp313-win_amd64.pyd(44 KB) - Estándar C++: C++17 habilitado correctamente
- Warnings: Algunos warnings menores de Cython (normales, no afectan funcionalidad)
- Importación: Módulo importado correctamente desde Python
- Instanciación:
PyNativeCore()creada sin errores - Funcionalidad:
core.add(2, 2)retorna4correctamente
Conclusión: El pipeline de compilación híbrido está completamente funcional y listo para comenzar la migración de componentes reales de emulación.
Fuentes Consultadas
Nota: Esta implementación es estándar y no requiere documentación específica de hardware del Game Boy. Se basa en conocimiento general de interoperabilidad Python/C++ mediante Cython.
Integridad Educativa
Lo que Entiendo Ahora
- Cython como puente: Cython permite escribir código "casi Python" que se compila a C, generando extensiones Python que pueden llamar código C++ directamente. El overhead de llamadas es mínimo comparado con ctypes o cffi.
- Gestión de memoria: Las clases Cython que envuelven objetos C++ deben gestionar
memoria manualmente en
__cinit__y__dealloc__. Esto es crítico para evitar memory leaks. - Tipos estáticos: Cython permite usar tipos estáticos de C (
cdef int,cdef unsigned char) que evitan el overhead de objetos Python en rutas críticas. - MemoryViews: Para buffers grandes (video/audio), Cython puede usar MemoryViews de numpy que permiten acceso directo a memoria sin copias.
Lo que Falta Confirmar
- Rendimiento real: Aunque el pipeline funciona, falta medir el rendimiento real comparado con Python puro. Esto se validará al migrar componentes reales de emulación.
- Compatibilidad cross-platform: La compilación se probó en Windows. Falta verificar que funciona correctamente en Linux y macOS.
- Debugging: Falta explorar herramientas de debugging para código C++ compilado desde Python (gdb, Visual Studio Debugger, etc.).
Hipótesis y Suposiciones
Se asume que el compilador C++ está disponible en el sistema. En Windows, esto requiere Visual Studio Build Tools o Visual Studio con componentes de C++. Si no está disponible, el usuario deberá instalarlo.
Se asume que la arquitectura híbrida será suficiente para alcanzar 60 FPS estables. Si no es así, puede ser necesario optimizar más agresivamente o considerar otras estrategias (JIT compilation, etc.).
Próximos Pasos
- [ ] Migrar CPU (LR35902) a C++/Cython
- [ ] Migrar MMU a código compilado
- [ ] Migrar PPU a código compilado
- [ ] Implementar APU (Audio Processing Unit) en C++
- [ ] Optimizar sincronización ciclo a ciclo
- [ ] Validar rendimiento con juegos sensibles al timing