Skip to content

amyanger/ds-emulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

219 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŽฎ ds-emulator

A from-scratch Nintendo DS emulator written in C++20

C++20 CMake SDL2 Apple Silicon License


โœจ What is this?

A solo project to build a Nintendo DS emulator from scratch in modern C++. The primary target is Pokรฉmon HeartGold / SoulSilver, with full compatibility goals for the rest of the Gen 4 and Gen 5 Pokรฉmon DS lineup:

  • ๐Ÿ’Ž Pokรฉmon Diamond / Pearl
  • ๐ŸŒŸ Pokรฉmon Platinum
  • โค๏ธ Pokรฉmon HeartGold / SoulSilver (primary target)
  • โšซ Pokรฉmon Black / White
  • โšซ Pokรฉmon Black 2 / White 2

๐Ÿ—๏ธ Architecture at a Glance

The DS isn't "GBA + more" โ€” it's a fundamentally different machine, so the architecture starts from scratch:

  • ๐Ÿง  Two CPUs on two bus domains โ€” ARM9 (ARMv5TE @ 67 MHz, with caches + TCM) and ARM7 (ARMv4T @ 33 MHz). Each CPU has its own Bus object modeling its view of memory.
  • โฑ๏ธ Single central event scheduler (min-heap of timed events) drives everything. Nothing advances time except scheduler.run_until(t) โ€” no scanline-chunk loop, no per-subsystem clocks.
  • ๐ŸŽจ Two 2D PPU engines (main + sub) sharing one class via an is_main flag โ€” four BG modes, sprite engine, windowing, blending, master brightness.
  • ๐Ÿ“ Two-stage 3D pipeline โ€” geometry engine โ†’ Frame3D hand-off struct โ†’ software rasterizer, with post-processing passes for edge marking, fog, and toon/highlight. The door is deliberately left open for a hardware backend later.
  • ๐Ÿงฉ Runtime-reconfigurable VRAM modeled as 9 independently-mapped banks (Aโ€“I) plus per-consumer page tables that are rebuilt on VRAMCNT writes.
  • ๐Ÿ”Š SPU on the ARM7 side โ€” 16 channels (PCM8 / PCM16 / IMA-ADPCM / PSG / noise) plus sound capture units.
  • ๐Ÿ”Œ Direct boot only โ€” no BIOS, no firmware dumps required. The cart's KEY1 decryption is handled by a hardcoded seed table, and BIOS SWIs are provided by a minimal HLE layer.
  • ๐ŸชŸ Three CMake targets: ds_core (platform-free), ds_frontend (the only SDL-aware code), and ds_emulator (the binary). Unit tests link ds_core only โ€” no SDL, no window.
  • ๐Ÿฉป In-emulator X-Ray debug overlay โ€” page-cycled real-time view of CPU state, bus page tables, VRAM bank map, OAM, palette, geometry FIFO, polygon list, scheduler events, IPC state, and SPU channels.

๐Ÿš€ Build & Run

๐Ÿ“ฆ Dependencies

  • SDL2 โ€” brew install sdl2 (macOS) / apt install libsdl2-dev (Linux)
  • CMake 3.20+ โ€” brew install cmake / apt install cmake
  • C++20 compiler โ€” clang 15+ or gcc 11+

That's it. SDL2 is the only runtime dependency.

๐Ÿ”จ Build

git clone https://github.com/amyanger/ds-emulator.git
cd ds-emulator
mkdir -p build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug
make

โ–ถ๏ธ Run

./ds_emulator <rom.nds>             # boot a ROM
./ds_emulator <rom.nds> --scale 3   # 3x window scale

ROMs go in roms/. Saves are written to saves/<game_code>.sav automatically. No BIOS or firmware required.

๐Ÿงช Tests

cd build
ctest --output-on-failure

Unit tests link against ds_core only โ€” no SDL, no window, runs in milliseconds.


๐ŸŽ Apple Silicon

First-class build target. Optional optimized build flag enables arm64-specific tuning:

mkdir -p build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DDS_TARGET_APPLE_SILICON=ON
make

When enabled, this turns on:

  • ๐Ÿ› ๏ธ -mcpu=apple-m1 clang tuning
  • ๐ŸŽฏ NEON SIMD rasterizer paths
  • ๐Ÿงต QOS_CLASS_USER_INTERACTIVE thread attribute (keeps the emulator off efficiency cores)
  • ๐Ÿ” Codesign / JIT entitlement scaffolding

The default build stays portable across macOS arm64, macOS x86_64, Linux, and Windows. Apple-specific code is confined to src/frontend/platform/macos.cpp and src/gpu3d/simd_neon.cpp โ€” nothing else uses #ifdef __APPLE__.


๐ŸŽฎ Controls

NDS Button Default Key
A Z
B X
X S
Y A
Start Enter
Select Right Shift
L Q
R W
D-Pad Arrow Keys
๐Ÿ‘† Touch Left mouse drag
๐Ÿ’ผ Lid open/close L
๐ŸŽค Mic (blow) M (hold)

Rebindable via keybinds.cfg. MFi / Xbox / DualSense controllers auto-detected via SDL2.

๐Ÿ› Debug keys (DEBUG builds)

Key Action
F1 Dump both CPUs' state to stderr
F2 Toggle ๐Ÿฉป X-Ray debug overlay
F3 Step one instruction
F4 Step one scanline
F5 Step one frame
F6 Toggle ARM9 instruction trace
F7 Toggle ARM7 instruction trace
F8 Dump main RAM
F9 Dump VRAM (all banks)
F10 Save state
F11 Load state
Tab Cycle X-Ray overlay pages
Esc Quit

๐Ÿ“ Project Layout

ds-emulator/
โ”œโ”€โ”€ ๐Ÿ“ docs/specs/        โ† Design spec (source of truth)
โ”œโ”€โ”€ ๐Ÿ› ๏ธ cmake/                         โ† Build helpers
โ”‚   โ”œโ”€โ”€ CompilerWarnings.cmake
โ”‚   โ”œโ”€โ”€ AppleSilicon.cmake
โ”‚   โ””โ”€โ”€ Sanitizers.cmake
โ”œโ”€โ”€ ๐Ÿ“ฆ include/ds/                    โ† Cross-cutting types
โ”‚   โ”œโ”€โ”€ common.hpp
โ”‚   โ”œโ”€โ”€ fixed.hpp                     โ† templated Fixed<I, F>
โ”‚   โ””โ”€โ”€ ring_buffer.hpp               โ† CircularBuffer<T, N>
โ”œโ”€โ”€ โš™๏ธ src/
โ”‚   โ”œโ”€โ”€ main.cpp                      โ† Entry point
โ”‚   โ”œโ”€โ”€ nds.hpp / nds.cpp             โ† Top-level system
โ”‚   โ”œโ”€โ”€ scheduler/                    โ† Min-heap event scheduler
โ”‚   โ”œโ”€โ”€ cpu/
โ”‚   โ”‚   โ”œโ”€โ”€ arm9/                     โ† ARMv5TE core
โ”‚   โ”‚   โ”œโ”€โ”€ arm7/                     โ† ARMv4T core
โ”‚   โ”‚   โ””โ”€โ”€ bios/                     โ† HLE SWI handlers
โ”‚   โ”œโ”€โ”€ bus/                          โ† ARM9 + ARM7 bus page tables
โ”‚   โ”œโ”€โ”€ memory/vram/                  โ† 9-bank VRAM controller
โ”‚   โ”œโ”€โ”€ ppu/                          โ† 2D engines (main + sub)
โ”‚   โ”œโ”€โ”€ gpu3d/                        โ† 3D geometry + rasterizer
โ”‚   โ”œโ”€โ”€ spu/                          โ† 16-channel sound processor
โ”‚   โ”œโ”€โ”€ dma/ timer/ ipc/ interrupt/   โ† Supporting hardware
โ”‚   โ”œโ”€โ”€ cartridge/                    โ† Slot-1 bus + KEY1 + saves
โ”‚   โ””โ”€โ”€ frontend/                     โ† SDL2 โ€” only place SDL is allowed
โ”‚       โ””โ”€โ”€ xray/                     โ† In-emulator debug overlay
โ””โ”€โ”€ ๐Ÿงช tests/                         โ† Unit tests (link ds_core only)

๐Ÿ“– Documentation

The full architecture spec lives at docs/specs/2026-04-12-nds-emulator-design.md โ€” 16 sections covering every subsystem.


๐Ÿ“š References

The references that made this project possible:


โš–๏ธ Legal

This project does not distribute any Nintendo intellectual property:

  • โŒ No ROMs
  • โŒ No BIOS files
  • โŒ No firmware dumps
  • โŒ No proprietary game data

Direct boot is implemented from publicly documented hardware behavior. Users supply their own legally obtained ROMs of games they own. Pokรฉmon, Nintendo DS, and all related trademarks belong to Nintendo / The Pokรฉmon Company / Game Freak.


๐Ÿ™ Acknowledgments

Built standing on the shoulders of giants: the GBATEK authors who reverse-engineered the DS hardware, the melonDS and DeSmuME teams for showing what's possible, and the gbadev / nds-dev homebrew communities for keeping the knowledge alive.


About

๐ŸŽฎ A from-scratch Nintendo DS emulator in C++20 โ€” targeting Pokรฉmon HG/SS, DPPt, BW/BW2 โ€” with first-class Apple Silicon support

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages