A cycle-accurate Game Boy (DMG) emulator written in C++ with modern architecture and comprehensive feature set.
Running The Legend of Zela: Link's Awakening
This emulator implements a complete Game Boy (DMG) system with cycle-accurate timing for a Z80-like processor, proper interrupt handling, and accurate graphics rendering. The project is built with modern C++17 standards and uses SDL2 for cross-platform graphics and input handling.
The emulator delivers cycle-accurate Game Boy emulation through a carefully designed modular architecture:
- Complete Z80-like instruction set with all 8-bit and 16-bit operations including arithmetic, logical, bit manipulation, and control flow instructions (e.g.,
ADD,LD,JP,CALL,RST) - Precise timing: Every instruction executes in the exact number of cycles as the original hardware (4.19 MHz clock)
- Advanced interrupt system: V-Blank, LCD Status, Timer, Serial, and Joypad interrupts with proper priority handling and interrupt enable/disable flags
- Register architecture: Full 8-bit registers (A, F, B, C, D, E, H, L) and 16-bit registers (PC, SP) with proper flag handling (Zero, Subtract, Half-carry, Carry)
- Memory addressing modes: Direct addressing, register indirect, immediate, and indexed addressing with accurate bus timing
- Stack operations: Push/pop operations with proper stack pointer management and interrupt handling
- 160x144 resolution with pixel-perfect rendering at 456 ticks per line, 154 lines per frame
- Advanced sprite system: Up to 40 sprites with OAM (Object Attribute Memory) and proper priority handling
- Pixel FIFO: Hardware-accurate pixel pipeline that mimics the original Game Boy's rendering process
- VRAM management: 8KB video RAM with proper banking
- LCD timing: Accurate LCD controller timing and synchronization
- Comprehensive memory mapping: ROM (0x0000-0x7FFF), VRAM (0x8000-0x9FFF), WRAM (0xC000-0xDFFF)
- MBC1 cartridge support: ROM banking with variable sizes and battery-backed save RAM
- DMA system: High-speed sprite data transfer with accurate timing and bus arbitration
- Dual-threaded architecture: Dedicated CPU thread with cycle-accurate timing + UI thread for rendering
- Thread-safe communication: Atomic variables and mutexes for optimal performance
- Optimized memory allocation: Efficient memory management for smooth 60 FPS performance
Performance: Runs at 60 FPS with <5% CPU usage on modern systems while maintaining cycle-accurate timing at 4.19 MHz CPU clock.
Accuracy: Passes comprehensive test suites including CPU instruction tests, interrupt handling, and memory timing validation.
Modularity: Clean separation of concerns with each component (CPU, PPU, Memory, etc.) as independent modules for easy maintenance and extension.
Cross-Platform: Full support for macOS, Linux, and Windows with SDL2 for graphics and input handling.
The emulator includes a comprehensive test suite with various ROMs:
01-special.gb- Special instruction tests02-interrupts.gb- Interrupt handling tests03-op sp,hl.gb- Stack pointer operations04-op r,imm.gb- Register-immediate operations05-op rp.gb- Register pair operations06-ld r,r.gb- Register-to-register loads07-jr,jp,call,ret,rst.gb- Jump and call instructions08-misc instrs.gb- Miscellaneous instructions09-op r,r.gb- Register operations10-bit ops.gb- Bit manipulation instructions11-op a,(hl).g- Accumulator operations
Additionally, the emulator can run any MBC1-type game. Support for other MBC types may be added later.
- CMake 3.16 or higher
- C++17 compatible compiler
- SDL2 and SDL2_ttf libraries
- Check library (for unit tests)
# Clone the repository
git clone <repository-url>
cd gbemu
# Create build directory
mkdir build && cd build
# Configure with CMake
cmake ..
# Build the project
make
# Run the emulator
cd gbemu && ./gbemu <path-to-rom-file>- macOS: Full support with Homebrew SDL2
- Linux: Full support with system SDL2
- Windows: Full support with bundled SDL2 libraries
gbemu/
├── include/ # Header files
│ ├── cpu.hpp # CPU emulation
│ ├── ppu.hpp # Graphics processing
│ ├── bus.hpp # Memory bus
│ ├── cart.hpp # Cartridge system
│ ├── timer.hpp # Timer system
│ ├── dma.hpp # Direct memory access
│ ├── joypad.hpp # Input handling
│ ├── ui.hpp # User interface
│ └── emu.hpp # Main emulator
├── lib/ # Implementation files
├── tests/ # Unit tests
├── roms/ # Test ROMs
├── cmake/ # CMake configuration
└── CMakeLists.txt # Build configuration
Enable debug features by setting DEBUG_MODE in common.hpp:
#define DEBUG_MODE 1 // Enable debug features- Frame rate: Configurable target FPS (default: 60)
- Threading: CPU and UI thread synchronization
- Memory allocation: Optimized memory management
- A: Z key
- B: X key
- Start: Enter key
- Select: Shift key
- Up: Up arrow
- Down: Down arrow
- Left: Left arrow
- Right: Right arrow
- Debug Window: F1 key
- Pause: Space bar
- Step: F2 key (when paused)
- Target: 60 FPS at 4.19 MHz CPU clock
- Memory usage: ~2MB for typical games
- CPU usage: <5% on modern systems
- Accuracy: Cycle-accurate timing
This project welcomes contributions! Areas for improvement:
- Audio emulation: Complete sound system implementation
- Networking: Link cable emulation
- Performance: Further optimization opportunities
- Testing: Additional test ROMs and validation
This project is licensed under the MIT License - see the LICENSE file for details.
- Game Boy documentation: Pan Docs and other technical references
- SDL2: Cross-platform multimedia library
- Test ROMs: Various Game Boy test suites and commercial games
- Open source community: For inspiration and technical guidance
This emulator aims for accuracy and performance while maintaining clean, maintainable code. The modular architecture makes it easy to extend and improve individual components.