Azahar organizes all emulation work through a centralDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/azahar-emu/azahar/llms.txt
Use this file to discover all available pages before exploring further.
Core::System singleton (defined in src/core/core.h). When you load a game, System::Load() initializes every subsystem in dependency order — memory, kernel, CPU cores, DSP, GPU — then hands control to System::RunLoop(), which drives the ARM11 CPU and schedules hardware events until the game exits or you request a reset.
Top-level subsystems
ARM CPU backends
One or more
Core::ARM_Interface instances execute ARM11 machine code. Azahar selects either the Dynarmic JIT or the Dyncom interpreter at startup based on your platform and settings.HLE kernel
Kernel::KernelSystem (in src/core/hle/kernel/kernel.h) manages processes, threads, IPC sessions, shared memory, timers, and resource limits — all without running real 3DS kernel code.Memory subsystem
Memory::MemorySystem (in src/core/memory.h) owns the page tables and physical memory regions that back every address space in the emulated system.Audio DSP
AudioCore::DspInterface (in src/audio_core/dsp_interface.h) is the abstract base for HLE and LLE audio emulation. The concrete backend is chosen at runtime and exposed on System via System::DSP().Video / GPU
VideoCore::GPU (in src/video_core/gpu.h) is the high-level GPU interface. It owns the PICA200 emulation core (Pica::PicaCore) and the active renderer backend.Service manager
Service::SM::ServiceManager (accessed via System::ServiceManager()) bootstraps all HLE service modules and routes IPC requests from emulated processes.ARM CPU emulation
The abstract base classCore::ARM_Interface (in src/core/arm/arm_interface.h) defines the contract every CPU backend must satisfy:
System holds a std::vector<std::shared_ptr<ARM_Interface>> for multi-core support (the 3DS has two ARM11 cores) and exposes System::GetCore(u32 core_id) and System::GetRunningCore().
Two backends are available:
| Backend | Location | Description |
|---|---|---|
| Dynarmic | src/core/arm/dynarmic/ | JIT recompiler. Translates ARM11 blocks to native x86-64 or AArch64 code at runtime. Available on x86-64 and arm64 builds (#if CITRA_ARCH(x86_64) || CITRA_ARCH(arm64)). Recommended for performance. |
| Dyncom | src/core/arm/dyncom/ | Interpreter. Executes one ARM11 instruction at a time via a dispatch loop. Slower but portable to any host architecture. |
HLE kernel
Kernel::KernelSystem (in src/core/hle/kernel/kernel.h) re-implements the 3DS operating system kernel in host C++ rather than running 3DS firmware. It creates and manages:
- Processes (
Process,src/core/hle/kernel/process.h) — loaded from NCCH executables by the app loader - Threads (
Thread,src/core/hle/kernel/thread.h) — scheduled cooperatively byThreadManageracross both ARM11 cores - Synchronization —
Mutex,Semaphore,Event,Timer,AddressArbiter(one source file per primitive insrc/core/hle/kernel/) - IPC sessions —
ClientPort,ServerPort,ClientSession,ServerSessionhandle the 3DS inter-process communication protocol - Virtual memory —
VMManager(insrc/core/hle/kernel/vm_manager.h) manages per-process address spaces - Shared memory —
SharedMemoryallows GPU and DSP shared pages to be mapped into process address spaces
std::recursive_mutex hle_lock that serializes all HLE state access from the CPU thread. IPC traffic can be recorded for debugging through IPCDebugger::Recorder (in src/core/hle/kernel/ipc_debugger/).
HLE services
src/core/hle/service/ contains high-level implementations of every 3DS system service, organized by module:
- APT (
service/apt/) — Application Manager, applet lifecycle,AppletManager - FS (
service/fs/) — File system access; bridges to archive backends viaService::FS::ArchiveManager - GSP (
service/gsp/) — Graphics service; relays GPU commands and interrupt signals toVideoCore::GPU - DSP (
service/dsp/) — Audio DSP interface; forwards pipe reads/writes toAudioCore::DspInterface - HID (
service/hid/) — Input (buttons, touch screen, accelerometer, gyroscope) - CAM (
service/cam/) — Camera interface - MIC (
service/mic/) — Microphone; checks host OS permission viaSystem::HasMicPermission() - IR (
service/ir/) — Infrared remote and extra buttons - PLGLDR (
service/plgldr/) — Plugin loader (Luma3DS-compatible) - SM (
service/sm/) — Service Manager; the root registry used by all other services
Memory subsystem
Memory::MemorySystem (declared in src/core/memory.h) manages the full 32-bit ARM11 physical address space. It provides the page tables consumed by both CPU backends (ARM_Interface::SetPageTable()). The kernel’s VMManager builds per-process virtual-to-physical mappings on top of this system.
On real hardware the 3DS has either 128 MB (Old 3DS) or 256 MB (New 3DS) of FCRAM. Azahar selects the active memory mode through
Kernel::MemoryMode (values Prod, Dev1–Dev4, NewProd, NewDev1) when initializing KernelSystem.File system
The file system layer lives insrc/core/file_sys/. An abstract ArchiveBackend interface covers every storage medium the 3DS exposes, and Service::FS::ArchiveManager routes fs:USER/fs:LDR IPC requests to the correct backend:
| Archive backend | Header | Description |
|---|---|---|
ArchiveSdmc | archive_sdmc.h | SD card — maps to the host sdmc/ directory |
ArchiveNand | archive_nand.h | NAND storage — maps to nand/ on the host |
ArchiveNcch | archive_ncch.h | Read-only ROM filesystem inside an NCCH partition |
ArchiveSaveData | archive_savedata.h | Per-title save data |
ArchiveExtSaveData | archive_extsavedata.h | Extended save data (shared between titles) |
ArchiveSelfNcch | archive_selfncch.h | Self-referencing archive for the running title’s own RomFS |
ArchiveSystemSaveData | archive_systemsavedata.h | System-wide save data (e.g., Mii data) |
ArchiveArtic | archive_artic.h | Remote cartridge access over the Artic Base network protocol |
LayeredFS (layered_fs.h), which intercepts RomFS reads and substitutes files from the host.
App loader
src/core/loader/ provides format-specific loaders that all derive from Loader::AppLoader (in loader/loader.h). Azahar selects the right loader based on the file extension and magic bytes:
| Loader | File | Supported formats |
|---|---|---|
AppLoader_NCCH | ncch.h | .3ds, .cci, .cxi, .app (NCCH/CCI cartridge images) |
AppLoader_ELF | elf.h | .elf (raw ARM ELF binaries) |
AppLoader_3DSX | 3dsx.h | .3dsx (homebrew portables) |
AppLoader_Artic | artic.h | Remote cartridge streaming over Artic Base |
Additional core systems
Movie recording
Core::Movie (src/core/movie.h) records and plays back input sequences for TAS and bug reproduction. System::Movie() exposes the instance.Save states
System::SaveState(u32 slot) and System::LoadState(u32 slot) serialize the full emulator state using Boost.Serialization. Buffer-based variants (SaveStateBuffer / LoadStateBuffer) support in-memory snapshots.GDB stub
src/core/gdbstub/ implements the GDB Remote Serial Protocol. When enabled at compile time (ENABLE_GDBSTUB), GDBStub::HandlePacket() is called each run-loop iteration so a debugger can step, inspect registers, and set breakpoints.RPC server
src/core/rpc/ (Core::RPC::Server) provides a scripting interface when built with ENABLE_SCRIPTING. It lets external tools read and write emulated memory and trigger events.Network / multiplayer
src/network/ implements the multiplayer room system. Peers exchange packets over the network and System relays them through the HLE NWM (network module) service.Cheat engine
Cheats::CheatEngine (src/core/cheats/cheats.h) applies GameShark-style memory patches each frame. System::CheatEngine() exposes the instance.Frontend integration
Azahar’s core is frontend-agnostic. The two official frontends are:- citra_qt — the desktop Qt6 frontend. It creates a
Frontend::EmuWindowsubclass backed by an OpenGL or Vulkan surface, registers applet implementations (Frontend::MiiSelector,Frontend::SoftwareKeyboard), and drivesSystem::RunLoop()from a dedicated emulation thread. - Android — the Android frontend wraps the same
Core::SystemAPI and renders into aSurfaceViewusing the same renderer backends.
System before calling System::Load():
Frontend::EmuWindow (in src/core/frontend/) is the abstract window interface that the renderer uses to swap buffers, query the framebuffer layout, and receive surface-change notifications.