Luma3DS: Custom Firmware for the Nintendo 3DS, Explained
Nintendo 3DS "Custom Firmware"
At a glance
- What is it?
- Luma3DS patches and reimplements large parts of the 3DS system software. Here is what it does, how it installs on top of boot9strap, and where it stops being the right tool.
- Who is it for?
- Adopt Luma3DS if you already run boot9strap on a 3DS and want homebrew, per-game patches, Rosalina screenshots and a GDB stub on real hardware. Do not adopt it for an emulator: the project targets console system software, and the documentation says nothing about Citra or any other emulator, so a question about running Luma3DS there has no answer in the repository.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 26 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Luma3DS replaces on a stock 3DS
The README describes Luma3DS as patching and reimplementing significant parts of the system software running on all models of the Nintendo 3DS family. That sentence is the whole scope: it is not an application you launch, it is a replacement layer that runs before and underneath the console's own operating system. The stated goal is to improve the user experience and support the 3DS beyond its end-of-life.
The audience follows from that. Homebrew developers get first-class support for their applications and a fully-fledged GDB stub, which the README calls out as a way for developers and reverse-engineers to work more efficiently. Players get game modding features: plugins in 3GX format, per-game language overrides the project calls locale emulation, and asset redirection through LayeredFS. A third group, people maintaining Nintendo Network replacements and similar services, depend on the support for user-provided patches and full system module replacements. If you only want to play retail cartridges untouched, none of this is aimed at you.
How the components fit together, from boot9strap to Rosalina
The repository is split into five build inputs listed in the Makefile: sysmodules, arm11, arm9 and k11_extension, plus the top-level Makefile that links them into boot.firm. Understanding that split explains most of the project's behaviour.
The arm9 and arm11 directories hold the baremetal main settings menu, the chainloader and the firmware loader. The README says this component patches the official firmware to modify Process9 code and injects all other custom components, and notes it was the first component written, in 2015. k11_extension is injected into the Arm11 NATIVE_FIRM kernel by hooking its startup code, then hooks itself into the rest of the kernel. According to the README it hooks system calls, introduces new SVCs and hooks interprocess communication to bypass limitations in Nintendo's design; that is what lets Rosalina pause other processes when the overlay opens.
The sysmodules directory contains reimplemented system processes. loader loads non-KIP processes from storage and is where process patches happen, which is why game modding lives there; it also handles 3DSX homebrew loading. rosalina is described as the most important component and custom KIP: overlay menu, GDB server and a reimplementation of the err:f fatal error screen. pxi reimplements Arm11 to Arm9 communication, sm removes service access control restrictions, and pm handles starting and terminating processes and instructing loader to load them, which is what enables the break-on-start GDB feature. The README is candid that these components were written over many years and may not reflect how maintainers would write new code today. That is worth knowing before you read the source expecting a single style.
Installing Luma3DS on a 3DS with boot9strap already in place
Luma3DS requires boot9strap to run, and the README points to the boot9strap repository for that prerequisite. It does not walk through installing boot9strap itself, so treat that as a separate task you must complete first.
Once boot9strap is installed, installation and upgrade are the same operation. Download the latest release archive and extract it onto the root of your SD card. The README says to replace existing files and merge existing folders if necessary. The archive also ships the homebrew menu and certs bundle from devkitPro's 3ds-hbmenu.
The Makefile shows how the project itself assembles the firmware file that ends up on the card. The final link step combines the sysmodule binary with the arm11, arm9 and k11_extension ELF files:
boot.firm: $(SUBFOLDERS)
@firmtool build $@ -D sysmodules/sysmodules.bin arm11/arm11.elf arm9/arm9.elf k11_extension/k11_extension.elf \
-A 0x18180000 -C XDMA XDMA NDMA XDMA
@echo built... $(notdir $@)You do not run that yourself unless you build from source. The result on the card is a boot.firm at the root. There is no installer, no menu entry and no companion application on the console side. If you are upgrading rather than installing fresh, the same extraction overwrites boot.firm and merges the folders.
After rebooting, hold Select at boot to open the main configuration menu. The README states the configuration file lives at /luma/config.ini on the SD card, or at /rw/luma/config.ini on the CTRNAND partition when Luma3DS was launched from CTRNAND, which happens when the SD card is missing.
A first real use is the overlay. Press L+Down+Select by default and Rosalina appears over whatever is running. The README lists screenshots in game, blue light and other screen filters, input redirection to external controllers, cheat codes and NTP time setting among its options. Most Rosalina settings are not saved automatically, so use the Save settings option before you leave the menu.
The chainloader, payload hotkeys and GDB ports
Pressing Start at boot opens the chainloader menu, which is also reachable from the configuration menu. Payloads live in /luma/payloads and must carry the .firm extension. If exactly one payload is present, the README says the selection menu is skipped and that payload runs. Hotkeys are encoded in the filename: a payload named x_test.firm is chainloaded when X is held at boot. This is a small design decision with a real consequence, since renaming a file changes its trigger, and a stray .firm in that folder changes what happens at startup.
For debugging, Luma3DS exposes a GDB stub. When enabled, the normal ports are 4000-4002, and the README recommends attach in extended-remote mode together with info os processes. The break-on-start port is 4003 and is used without extended-remote. Both devkitARM-patched GDB and IDA Pro are described as actively supported, with the caveat that IDA Pro support excludes stepping. The README also points at monitor getmemregions for reverse-engineering work. This is the part of the project with the clearest developer-facing value and the least coverage elsewhere: the README says the wiki exists but is currently very outdated, so port numbers and modes in the README are the better reference.
Where Luma3DS is the wrong choice, and what it is not
The most common mismatch is treating Luma3DS as an emulator feature. It patches and reimplements the system software of real console hardware, and the README describes nothing about running under an emulator. There is no documented path for using it on a PC, and no Android or APK distribution appears anywhere in the repository description or the README. Searches for an Android build or an APK have no corresponding artifact here.
A second limit is the configuration surface. Most Rosalina settings are not persisted automatically, so an upgrade or a forgotten Save settings leaves you where you started. The configuration file is written by the menu rather than documented as a hand-editing format.
A third is the documentation itself. The README states plainly that the wiki is currently very outdated. Component-level behaviour, particularly the reimplemented sysmodules, is documented in a few sentences each, so anyone modifying them is reading C. The README also warns that the code was written over many years and may not match current maintainer style.
Finally, removing it is not a documented operation. The README covers installation and upgrade by extraction and says nothing about uninstalling or rolling back, so plan for that before you start. The Makefile contains a build flag, BUILD_FOR_EXPLOIT_DEV, with the comment that it disables kext and firmlaunch patches and all custom sysmodules except Loader, and is marked as dangerous. That flag is for exploit development, not for ordinary use.
How Luma3DS differs from GodMode9 and other 3DS tools
Luma3DS is often mentioned in the same breath as boot9strap and GodMode9, but they occupy different layers. boot9strap is the prerequisite: it is the exploit chain that lets Luma3DS run at all, and Luma3DS does not replace it. GodMode9 is a file and system management tool that runs as a payload, and the chainloader in Luma3DS is the mechanism that launches payloads like it from /luma/payloads.
The difference in approach matters when you choose what to install. Luma3DS is resident: it patches the firmware at boot and stays underneath everything, which is why it can offer per-game locale overrides, LayeredFS redirection and an overlay that pauses other processes. A payload-based tool runs when you invoke it and then exits back to whatever you were doing. If your goal is to copy files, dump a cartridge or edit NAND contents, a payload tool is the right shape. If your goal is to change how games and system processes behave while they run, that requires something resident, and that is Luma3DS's position.
Within the project's own history, the README notes that AuroraWright created it in 2015 and is currently inactive, while TuxSH is the lead developer and has maintained most features since joining in 2016. PabloMK7 joined in 2023 and maintains the plugin loader merged for v13.0. The last push to the repository was on 2026-09-04.
Licence, build requirements and upgrade cost
Luma3DS is GPL-3.0. If you redistribute a modified build, the licence's source-availability terms apply to what you ship; that is a statement about the licence text, not legal advice, and anyone embedding it in a product should read the terms rather than rely on a summary.
Building from source has prerequisites the Makefile enforces. It checks for firmtool and fails with the message asking you to install firmtool v1.1 or greater. The release target produces a zip named after the project and the git revision, built from boot.firm plus hbmenu.zip, and hbmenu.zip is downloaded at build time from devkitPro's 3ds-hbmenu releases. The final link step assembles sysmodules/sysmodules.bin together with the arm11, arm9 and k11_extension ELF files into boot.firm. Two build flags change the output: BUILD_FOR_GDB compiles with O0 and frame pointer information for GDB, and BUILD_FOR_EXPLOIT_DEV strips most custom sysmodules as described above.
Upgrade cost for an ordinary user is close to zero. Because the release archive is extracted over the SD card, moving from one release to the next is the same operation as installing, and the README instructs you to replace existing files and merge folders. The releases listed for this project are v13.4 from 2026-04-02, v13.3.3 from 2025-07-15 and v13.3.2 from 2025-03-10, so the cadence is measured in months rather than weeks. The real cost is attention: an upgrade overwrites boot.firm, and any Rosalina settings you did not save are not carried across.
Editorial conclusion
Adopt Luma3DS if you already run boot9strap on a 3DS and want homebrew, per-game patches, Rosalina screenshots and a GDB stub on real hardware. Do not adopt it for an emulator: the project targets console system software, and the documentation says nothing about Citra or any other emulator, so a question about running Luma3DS there has no answer in the repository. Before installing, verify that boot9strap is present and confirm which Luma3DS version your current setup already reports, because the project ships a single archive that you extract over the SD card rather than an installer with an uninstall path.
Frequently asked questions
What does Luma3DS do?
It patches and reimplements significant parts of the system software on all models of the Nintendo 3DS family. Its features include homebrew support, the Rosalina overlay menu, game modding through plugins, locale emulation and LayeredFS, and a GDB stub for debugging.
How do I get Luma3DS?
Download the latest release archive from the project's releases page and extract it onto the root of your SD card. Luma3DS requires boot9strap to run, so that has to be installed first.
How do I install Luma3DS on a 3DS?
Once boot9strap is installed, extract the latest release archive onto the root of the SD card, replacing existing files and merging existing folders. The archive also ships the homebrew menu and certs bundle.
How do I access the Luma3DS configuration menu?
Press Select at boot. The configuration file is stored at /luma/config.ini on the SD card, or at /rw/luma/config.ini on the CTRNAND partition when Luma3DS was launched from CTRNAND.
How do I use Luma3DS cheats?
Cheat codes are one of the options in the Rosalina overlay menu, which is opened with L+Down+Select by default. Most Rosalina settings are not saved automatically, so use Save settings if you want the change to persist.
How do you tell if you have Luma3DS installed?
The README does not describe a version-check procedure. The observable signs it documents are boot.firm at the root of the SD card and the ability to open the configuration menu with Select at boot or the Rosalina overlay with L+Down+Select.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/lumateam-luma3ds)