-
Notifications
You must be signed in to change notification settings - Fork 0
Nintendo 3DS
Azahar is the successor to Citra, formed by merging PabloMK7's Citra fork with Lime3DS after the original Citra project was taken down. It requires OpenGL Core >= 3.3 and uses hardware-accelerated rendering via the libretro HW render interface. On Linux it renders through a GL context (GLX or EGL) into an FBO, read back with a never-blocking 4-slot PBO ring, then presented through the native Wayland toplevel (X11/SDL fallback).
| Extension | Format |
|---|---|
.3ds / .cci
|
Cartridge dump (most common) |
.cia |
Install package |
.cxi |
Executable content |
.3dsx |
Homebrew |
.app |
Raw application data |
ROMs must be decrypted — encrypted dumps will not load. No BIOS files are required.
Azahar's GPU thread continues cleanup after retro_unload_game returns. Calling context_destroy during this window causes a null-pointer AV (READ 0x8) inside the core — the same pattern seen with PPSSPP.
Fix: Skip context_destroy and call retro_deinit on the emu thread while the GL context is still active. The quarantine delay before releasing the GL context gives the core's internal threads time to drain safely.
NATIVE AV in [azahar_libretro.so] RVA=0x2E5B4D: READ addr=0x0000000000000008
Azahar uses libretro_saves = true — it manages its own save files internally using the save directory path provided by the frontend (BatterySaves/3DS/ under ~/.local/share/Emutastic). The standard retro_get_memory_data SRAM interface returns zero size (no-op).
The full RetroPad mapping exposed by the core (driven by SDL3 gamepad on Linux):
| 3DS Input | RetroPad |
|---|---|
| D-pad | D-pad |
| Circle Pad | Left Analog |
| C-Stick (New 3DS) | Right Analog |
| A, B, X, Y | Face buttons |
| L, R | L, R |
| ZL (New 3DS) | L2 |
| ZR (New 3DS) | R2 |
| Start, Select | Start, Select |
| Home / Swap screens | L3 |
| Touch screen touch | R3 |
Touch input on 3DS is driven through the right analog stick (cursor) and the Touch button (tap), not direct mouse-click. This matches the binding scheme defined by the Azahar core itself:
- Move the cursor on the bottom screen by tilting the right analog stick.
-
Tap by pressing the Touch button (libretro
R3, defaulting to right-stick-click on gamepads).
Bind a key or button to Touch in Preferences → Controls for 3DS just like any other button. On a controller, right-stick-click is the natural fit and matches the libretro convention.
The mouse-as-touchscreen path that other libretro cores use is not currently reliable in Azahar (see RetroArch#18911) — the right-stick + Touch button combo is the working path.
Azahar renders at native 400x240 (top screen). The HW renderer supports significant upscaling:
| Option | Native | Upscaled (suggested) |
|---|---|---|
citra_resolution_factor |
1 |
4 or 5
|
citra_texture_filter |
none |
ScaleForce or xBRZ
|
citra_texture_sampling |
GameControlled |
Linear (smoother, slight softening) |
citra_use_hw_shader |
enabled |
enabled |
citra_use_shader_jit |
enabled |
enabled |
citra_resolution_factor and citra_texture_filter are surfaced in the cog menu; the rest are in the full Core Options panel. All options take effect immediately without restarting the game.
High internal resolutions are cheap on the frame-transfer side: the rendered image is GPU-downscaled to the window size before readback, so the per-frame transfer cost is constant regardless of factor (a 3080 Ti holds a locked 60 at 10x). The practical ceiling is the core's own render cost — at very high factors a mid-range GPU can still drop frames rendering the upscaled scene, and the small 400x240 source means returns diminish past ~5x. The setting is also applied a frame after game load (a core init quirk otherwise mis-sizes the framebuffer at high factors), so a saved high resolution boots correctly.
The rcheevos library (v11.1+) includes 3DS hash support — Emutastic generates hashes correctly for .3ds, .cci, .cia, and .3dsx ROMs. However, 3DS is not yet a supported RetroAchievements system. No achievement sets have been authored and the RA server returns "Unknown game" for all 3DS hashes.
The rcheevos console ID for 3DS is 62 (RC_CONSOLE_NINTENDO_3DS). Note: this differs from the RA web API's console numbering.
3DS cartridge dumps can be encrypted (NCCH encryption). The rcheevos hash function requires AES key derivation callbacks (get_3ds_ncch_normal_keys, get_3ds_cia_normal_key) to decrypt partition headers during hashing. Emutastic implements the 3DS key scrambler algorithm: NormalKey = ROL128((ROL128(KeyX, 2) XOR KeyY) + C, 87) where C = 0x1FF9E9AAC5FE0408024591DC5D52768A. Decrypted dumps hash without needing these callbacks.
Console Notes
- Nintendo 64
- Nintendo 3DS
- GameCube
- Sega Saturn
- Dreamcast
- PlayStation
- PlayStation Portable
- TurboGrafx-CD
- Neo Geo
- Arcade
- Vectrex
- Philips CD-i
- Atari Jaguar
Features
- Artwork & Metadata
- Cheats
- Cloud Sync
- Controllers
- Disc-Based Systems
- Disk Swapping
- Portable Mode
- RetroAchievements
- ROM Hacks
- Hardcore Compliance
Technical
Platforms
Legal