This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.
Hybrid Build Pipeline Configuration
Summary
Complete hybrid build infrastructure (Python + C++/Cython) has been configured for Phase 2.
Created kernel directory structure, implemented a "Hello World" proof of concept in C++,
the build system was configured withsetup.pyand it was verified that the compilation pipeline
It works correctly on Windows. This is the first critical step before migrating any component
emulation to compiled code.
Hardware Concept
Note:This entry is not directly about Game Boy hardware, but about the compilation infrastructure needed to emulate it efficiently.
Cycle-by-cycle emulation of a system like the Game Boy requires timing precision in the order of microseconds. Python, being an interpreted language, introduces significant overhead in each operation, which prevents achieving the synchronization necessary for fluid gameplay.
The solution adopted is ahybrid architecture:
- Python (Frontend): Handles UI, file uploads, input events and high-level orchestration. Maintains flexibility and ease of development.
- C++ (Core): Implements critical cycle-by-cycle emulation logic (CPU, MMU, PPU, APU). Provides the performance needed for precise synchronization.
- Cython (Bridge): Allows Python to call compiled C++ code without significant overhead. Cython generates C code that compiles to Python extensions (.pyd on Windows, .so on Linux/macOS).
This architecture allows you to maintain the benefits of Python (tests, documentation, rapid development) while performance of compiled code on critical paths is obtained.
Implementation
Fully configured hybrid build system following Cython best practices and setuptools. The implementation includes:
1. Dependency Management
It was updatedrequirements.txtwith the necessary dependencies:
cython>=3.0.0: Cython compiler to generate C/C++ codesetuptools>=68.0.0: Build system for Python extensionsnumpy>=1.24.0: For future uses of video/audio buffers (MemoryViews)
2. Directory Structure
The following structure was created to organize the core code:
src/core/
├── __init__.py # Core Python module
├── cpp/ # Pure C++ code (.cpp, .hpp)
│ ├── NativeCore.hpp
│ └── NativeCore.cpp
└── cython/ # Wrappers Cython (.pyx, .pxd)
└── native_core.pyx
3. Proof of Concept: NativeCore
Implemented a simple C++ classNativeCorewith a methodadd(int a, int b)to verify that the pipeline works. This class will be expanded in the future to contain the logic
emulation.
C++ file (NativeCore.hpp/cpp):
- Simple class with constructor, destructor and method
add() - C++17 standard for modern compatibility
- Prepared for future expansion
4. Wrapper Cython
The Cython wrapper was creatednative_core.pyxthat:
- Declare the C++ class using
external cdef - Expose a Python class
PyNativeCorewhich wraps the C++ class - Manage memory correctly (constructor
__cinit__and destroyer__dealloc__) - Allows calling C++ methods from Python without overhead
5. Build System (setup.py)
It was configuredsetup.pywith:
- Cython extensions using
Cython.Build.cythonize - C++17 compiler configuration (Windows/Linux/macOS supported)
- Optimization Directives:
boundscheck=False,wraparound=False - Include directories for C++ and numpy headers
6. Verification Script
was createdtest_build.pythat:
- Import the compiled module
viboy_core - Create an instance of
PyNativeCore - Run the test:
core.add(2, 2) == 4 - Provides clear error messages if the build fails
Design Decisions
- C++/Cython separation:The pure C++ code is in
cpp/and the wrappers incython/. This allows C++ code to be reused in other contexts if necessary. - Naming:The compiled module is called
viboy_coreto avoid conflicts with Python modulesrc/core. - Windows Compatibility:It is used
/std:c++17for MSVC and-std=c++17for GCC/Clang, automatically detecting the platform.
Affected Files
requirements.txt- Added Cython, setuptools, numpy dependenciessrc/core/__init__.py- Core Python module (new)src/core/cpp/NativeCore.hpp- Test C++ header (new)src/core/cpp/NativeCore.cpp- Test C++ implementation (new)src/core/cython/native_core.pyx- Cython wrapper (new)setup.py- Build system for extensions (new)test_build.py- Verification script (new)
Tests and Verification
Verification was done using the scripttest_build.py:
- Compilation:Execute
python setup.py build_ext --inplacegenerate the fileviboy_core.pyd(eitherviboy_core.soon Linux/macOS) in the root directory. - Import:The module imports successfully from Python.
- Instantiation:You can create an instance of
PyNativeCoreno errors. - Functionality:The method
add(2, 2)returns correctly4.
Compile command:
python setup.py build_ext --inplace
Verification command:
python test_build.py
Note:If the build fails, you may need to install Visual Studio Build Tools on Windows or the development tools on Linux/macOS.
Verification Results Completed
The build and verification ran successfully on Windows 10 with Python 3.13:
- Installed dependencies:Cython 3.2.3, setuptools 75.1.0, numpy 2.2.6
- Compiler detected:Visual Studio 2022 Community (MSVC 14.44.35207)
- Generated file:
viboy_core.cp313-win_amd64.pyd(44KB) - C++ standard:C++17 enabled correctly
- Warnings:Some minor Cython warnings (normal, do not affect functionality)
- Import:Module imported successfully from Python
- Instantiation:
PyNativeCore()created without errors - Functionality:
core.add(2, 2)returns4correctly
Conclusion:Hybrid build pipeline is fully functional and ready to begin the migration of real emulation components.
Sources consulted
Note: This implementation is standard and does not require specific Game Boy hardware documentation. It is based on general knowledge of Python/C++ interoperability using Cython.
Educational Integrity
What I Understand Now
- Cython as a bridge:Cython allows you to write "almost Python" code that compiles to C, generating Python extensions that can call C++ code directly. The call overhead is minimal compared to ctypes or cffi.
- Memory management:Cython classes that wrap C++ objects must handle
memory manually in
__cinit__and__dealloc__. This is critical to avoid memory leaks. - Static types:Cython allows you to use C static types (
cdef int,cdef unsigned char) that avoid the overhead of Python objects on critical paths. - MemoryViews:For large buffers (video/audio), Cython can use MemoryViews from numpy that allow direct access to memory without copies.
What remains to be confirmed
- Actual performance:Although the pipeline works, the real performance needs to be measured compared to pure Python. This will be validated when migrating actual emulation components.
- Cross-platform compatibility:The build was tested on Windows. Need to verify which works correctly on Linux and macOS.
- Debugging:Debugging tools for C++ code compiled from Python (gdb, Visual Studio Debugger, etc.).
Hypotheses and Assumptions
It is assumed that the C++ compiler is available on the system. On Windows, this requires Visual Studio Build Tools or Visual Studio with C++ components. If it is not available, the user must install it.
It is assumed that the hybrid architecture will be enough to achieve a stable 60 FPS. If not, it may be necessary to optimize more aggressively or consider other strategies (JIT compilation, etc.).
Next Steps
- [ ] Migrate CPU (LR35902) to C++/Cython
- [ ] Migrate MMU to compiled code
- [ ] Migrate PPU to compiled code
- [ ] Implement APU (Audio Processing Unit) in C++
- [ ] Optimize cycle-by-cycle synchronization
- [ ] Validate performance with timing-sensitive games