- C 91.6%
- C++ 6%
- Makefile 1.4%
- Python 1%
|
All checks were successful
build-bundle / bundle (push) Successful in 20m24s
Ports the HOME-menu news feature from upstream 3.5.12, which the previous
commit had deliberately left out. Re-examined and that exclusion was wrong:
nextendo_news.c performs NO network access at all (no gethostbyname, no
socket, no ssl, no hardcoded host). It only manipulates local bcat system
save data. The news themselves arrive over the bcat-*-lp1.cdn.nintendo.net
hosts, which nextendo_hosts_build() already redirects to our own server --
so this is not a phone-home to nextendo.network.
Added:
- source/nextendo_news.{c,h}
news:a -> CreateNewsService(0) -> ClearStorage(40200) to flush the two
bcat system saves (0x...90 data, 0x...91 index/history), then
RequestAutoSubscription(40101) to re-subscribe the HOME menu. Falls back
to mounting the saves directly if the service call fails. passphrase.bin
is never touched -- the news decryption key derives from it.
- romfs/.../exefs_patches/nextendo_bcat_signature/
bcat signature patch (build-id 6D9772A7..., sysNAND 22.5.0)
- nextendo_apply.c: purge on both mode switches (Nextendo mode only when the
signature patch covers this console's bcat build-id, otherwise our news
would not render and we would be left with an empty list)
- main.c: SCREEN_NEWS_REBOOT -- on first launch after updating while staying
in Nextendo mode the patch lands on the SD for the first time, so purge and
ask for a reboot (the bcat patch only loads at boot). Needed sys/stat.h;
access() in devkitPro newlib returns 0 even for absent paths.
- lang.{c,h}: STR_NEWS_TITLE / STR_NEWS_CLEANED in all SIX languages
(upstream has five -- German is ours and stays)
STILL NOT PORTED:
- Account-link fallback (network_mitm v2, title 4200000000000666) -- excluded
on request. Not shipped, and NEXTENDO_STALE_FILES keeps deleting it.
- Upstream deletion of nextendo_prodinfo.c -- our synthetic PRODINFO stays.
Verified on the built NRO (18,042,304 bytes, NRO0 magic): all three news
symbols linked (nm shows T), the "news:a" service name present twice as a
movk immediate at both call sites (it is loaded into x1 as a u64, NOT stored
as a string -- a string grep for it always fails, confirmed by objdump), the
bcat signature .ips embedded, both news strings 6-language. All 8 game patch
directories and the new host strings from v3.4.18 still present; account_link
tree, mitm.lst and nextendo_account_link_install all absent.
|
||
|---|---|---|
| .forgejo/workflows | ||
| atmosphere-patches | ||
| contrib/npshop-ssl-mitm | ||
| romfs | ||
| scripts | ||
| source | ||
| .gitattributes | ||
| .gitignore | ||
| icon.jpg | ||
| LICENSE.md | ||
| LISEZ-MOI.txt | ||
| Makefile | ||
| README.md | ||
| Switch nnAccount Private Server Setup.txt | ||
Prelude (Generated Serial)
Prelude switches a Nintendo Switch between the Nextendo Network and Nintendo's official servers.
This build consists of two halves that belong together:
nextendo.nro— the homebrew you launch from the HBMenu. It writes the configuration (hosts, CA trust, game patches) and reboots.- Custom Atmosphère 1.11.2 — a patched
ams_mitmthat builds and injects a synthetic console identity at boot (the "generated serial").
The second half is what sets this build apart: without the patched Atmosphère the identity feature does nothing at all. Both halves are built together by CI and shipped as one ready-to-install SD bundle.
Which network do you want to load?
[ NEXTENDO ] [ NINTENDO ]
- Nextendo mode — redirects Nintendo traffic to the Nextendo servers and provisions everything the console needs to trust them.
- Nintendo mode — removes every component Prelude installed and hands the console back to Nintendo, with Atmosphère's own telemetry blocking restored.
Quick start
What you need: a Switch that can boot CFW (RCM/modchip), an SD card, and the latest
prelude-bundle-<tag>.zip from the releases page.
⚠ System firmware 22.5.0 is required
This bundle ships custom Atmosphère 1.11.2, whose minimum supported firmware is 22.5.0. On an older system version, CFW will not boot cleanly — you need to be on 22.5.0 (or newer) before installing. Update the console through Nintendo's normal system update first if you are below it. Prelude itself does not change your firmware; it just cannot run below that version.
Prelude detects on its own whether it is running on emuMMC or sysNAND, so you never pick that yourself. But what it can protect differs, so follow the section that matches your setup:
- You have an emuMMC — the recommended setup.
- You only use sysNAND — works too, with one caveat worth understanding.
Installation (same for both)
- Back up your SD card. At minimum copy your existing
/atmosphere/folder somewhere safe — this bundle replaces it. - Power off the console and put the SD card in your PC.
- Extract the bundle onto the root of the SD card, overwriting when asked. You should end
up with
/atmosphere/,/switch/andfusee.binon the card. - Put the SD card back and boot into CFW using the
fusee.binfrom this bundle. - Open the homebrew menu (hold R while launching a game, or use the Album).
- Launch nextendo.
⚠ You must use the new
fusee.binPrelude is not just the
.nro— the identity handling lives in the payload. Theexosphere.inikeys that drive it (blank_prodinfo_*,nextendo_synth_prodinfo) are parsed by fusee, before Horizon even starts. An older payload does not know the synthesis key and silently ignores it.If you keep booting your previous payload, the app will look like it worked — it writes the configuration and reboots — but the console comes up with the wrong identity: no synthetic serial in Nextendo mode, and on emuMMC no blanking in Nintendo mode either.
So make sure that:
- your injector (TegraRcmGUI, NXLoader, Rekado…) points at this bundle's
fusee.bin;- your modchip (Picofly/HWFLY/SX Core) has this
fusee.binas its payload on the SD;/atmosphere/reboot_payload.bincomes from this bundle too — it is a copy of the same payload and is what "reboot to payload" uses. Extracting the bundle handles this for you;- if you boot through hekate, put
fusee.bininbootloader/payloads/on the SD card (e.g.bootloader/payloads/fusee.bin) — it then shows up in hekate's Payloads menu. For autoboot, add a boot entry withpayload=bootloader/payloads/fusee.bintobootloader/hekate_ipl.ini.Same goes for updates: a new Prelude release ships a new
fusee.bin. Replacing only the.nrois not enough whenever the payload changed.
First launch takes a moment — the app provisions the whole certificate and patch tree onto the SD card the first time you apply a mode.
Quick start — emuMMC (recommended)
Boot into your emuMMC and run Prelude there.
- Pick NEXTENDO and confirm. The app writes the configuration and reboots.
- After the reboot, go online as usual — your console now talks to the Nextendo servers.
That is all. Your emuMMC boots with a synthetic console identity: a randomized serial number and device id, rebuilt from your real calibration data at boot. Nothing has to be enabled for this, it is the default on emuMMC.
To go back: launch Prelude again and pick NINTENDO. Your emuMMC then boots with a blank identity — not the synthetic one, and not your real one. That is the safe state for touching Nintendo's own servers, and it is what upstream Atmosphère does too.
Your sysNAND is never touched by any of this. It keeps its real identity, its eShop account and its online membership, exactly as before.
| Serial the console reports | |
|---|---|
| emuMMC, Nextendo mode | synthetic (randomized) |
| emuMMC, Nintendo mode | blank |
| sysNAND | real — untouched |
Quick start — sysNAND only
If your console has no emuMMC, CFW runs on the internal memory — the same NAND that carries your real eShop account and online membership. Prelude works fine here, but it deliberately does not alter that NAND's identity by default.
- Pick NEXTENDO and confirm. The app writes the configuration and reboots.
- After the reboot, go online as usual — your console now talks to the Nextendo servers.
You will see a warning card on the confirmation screen telling you this console has no emuMMC. That is expected, and it is not an error: it means no identity protection is active.
Is that a problem? For playing on Nextendo, no. Prelude redirects Nintendo's domains to the Nextendo servers, so Nintendo never receives the connection in the first place — your identity stays confined to your own server regardless of what the console would report.
To go back: pick NINTENDO. Your console is then a completely normal CFW console talking to Nintendo with its real identity, exactly as it was before you installed Prelude.
Optional: synthetic identity on sysNAND
If you want the randomized serial on sysNAND too, press X on the confirmation screen to toggle it. The warning card then shows the option as ON.
Understand what this does and does not buy you before enabling it:
- It randomizes the serial number and device id only. All cryptographic material — most importantly the SSL client certificate — stays byte-identical, because changing it would break TLS entirely.
- That certificate, not the serial, is what actually identifies your console to Nintendo. So the protection gained is largely cosmetic.
- Meanwhile the risk is real: this manipulates calibration handling on the NAND holding your actual account.
The option applies to Nextendo mode only. Nintendo mode always hands your real identity back before any contact with Nintendo, whether the option is on or off.
Recommendation: leave it off on a console you care about. Use it on a test console, or set up an emuMMC instead — that is what emuMMC is for.
| Serial the console reports | |
|---|---|
| sysNAND, Nextendo mode, option off (default) | real |
| sysNAND, Nextendo mode, option on | synthetic (randomized) |
| sysNAND, Nintendo mode | real — always, option ignored |
If something goes wrong
| Symptom | What to do |
|---|---|
| Console does not boot / black screen after installing | You overwrote a working /atmosphere/ with a different version (or your system firmware is below 22.5.0, which Atmosphère 1.11.2 requires). Restore your backup, and make sure the console is on 22.5.0 or newer before reinstalling. |
| Applied Nextendo mode, but the serial did not change | You are almost certainly still booting an old payload. Point your injector or modchip at this bundle's fusee.bin — it is what parses the identity keys. |
| Nintendo mode still shows a made-up serial | Same cause: an old fusee.bin does not know nextendo_synth_prodinfo and cannot turn the synthesis off. |
Online games show 2618-201 |
NAT traversal failed. See the nncs1/nncs2 note under Servers. |
| "This console has no emuMMC" warning | Expected on a sysNAND-only console. See Quick start — sysNAND only. |
| Want the stock console back entirely | Pick NINTENDO mode, then restore your original /atmosphere/ folder from the backup. |
Components — what does what
1. nextendo.nro (homebrew, source/)
Writes only files that Atmosphère already reads at boot. It does not patch games at runtime and does not touch the network stack.
| What | Where |
|---|---|
| Host redirections | /atmosphere/hosts/{sysmmc,emummc}.txt (Atmosphère DNS.mitm) |
| DNS.mitm on/off | /atmosphere/config/system_settings.ini |
| PRODINFO per mode | /exosphere.ini (blank_prodinfo_emummc, emuMMC only) |
| Certificate trust | exefs_patches/, nro_patches/, browser CA bundle, rootCA.pem |
| Game content (BCAT, mods, flags) | /atmosphere/contents/ and exefs_patches/ |
The complete SD layout is embedded in the NRO (romfs/sd/) and provisioned to the card on
first apply via copyTreeRomfs("romfs:/sd", "sdmc:"). That is why the .nro alone is a
sufficient deliverable — a separate SD zip is not required.
Key source files:
source/nextendo_config.h— the server addresses (see the table below). Overridable at build time via-DNEXTENDO_SERVER_HOST=....source/nextendo_apply.c— the apply flow for both modes andnextendo_hosts_build(), which generates the actual DNS.mitm hosts table written to the SD card. (source/nextendo_hosts.honly declares that function; it is not a host list.)source/nextendo_prodinfo.c— stash/restore of the synthetic identity across mode switches.source/nextendo_update.c— self-updater (Forgejo releases API, see Updating below).source/nextendo_net.c— HTTPS client plusresolve_host(), which statically overrides hosts the Switch cannot resolve through Nintendo's own DNS.
Servers
Prelude does not point everything at a single machine:
| Constant | IP | What goes there |
|---|---|---|
NEXTENDO_SERVER_IP_DEFAULT |
51.178.29.194 |
Account/BAAS/dauth/aauth, *.nintendo.com, *.srv.nintendo.net, the g2* NEX wildcard and most per-game hosts |
NEXTENDO_SERVER_IP_ALT |
3.135.232.168 |
Alternate server, selectable at runtime (see below) |
NEXTENDO_SERVER_IP_NNCSD2 |
164.132.111.120 |
Mario Kart 8 Deluxe (g2b309e01-lp1.s.n.srv.nintendo.net) and the nncs2 NAT probe (nncs2-*.n.n.srv.nintendo.net) |
The nncs2 split is not cosmetic: Pia requires two distinct IPs for nncs1/nncs2. If they are
identical it deduplicates them, never sends the second probe, NAT traversal never completes and
MK8 / Splatoon 2 fail with 2618-201.
Atmosphère's rule is last matching line wins, which is why the explicit MK8 line must come
after the g2* wildcard.
A hidden D-Pad server switch on the picker screen (Up, Down, Left, Right) toggles between the default and alternate IP at runtime; the UI shows which one is active.
Some hosts are deliberately not redirected and resolve to the real Nintendo: d4c (system
updates), ctest (browser connection test) and *.nintendowifi.net — otherwise the console
shows error popups.
2. Custom Atmosphère — atmosphere-patches/ (6 patches on upstream 1.11.2)
Applied to the verified upstream tag 1.11.2
(commit 5388824be146a89619e8d641acd64599cf1c5f62). CI fetches the tag fresh from GitHub and
checks the commit hash — nothing is built from a local tree.
| Patch | What it does |
|---|---|
0001 |
Base: PRODINFO overlay in amsmitm_prodinfo_utils.cpp + SetOverrideRegisterInternalPki in libstratosphere (the hooks ssl_mitm links against) |
0002 |
Loads nextendo_prodinfo.bin lazily — the SD is not mounted yet that early in boot |
0003 |
Moves the overlay off the CAL0 read path; fixes the re-entrancy deadlock / black screen |
0004 |
Synthesizes nextendo_prodinfo.bin from the real CAL0 |
0005 |
Runs the synthesis in InitializeProdInfoManagement(), not on the init thread |
0006 |
Separates blanking from synthesis via a dedicated exosphere flag |
Why blanking and synthesis had to be separated (patch 0006): up to 0005 the synthesis was
gated on should_blank alone, which conflates two different things. Upstream, blanking is
the protection in Nintendo mode — a blank identity cannot be tied back to the real console.
Synthesizing there would instead show real Nintendo an invented serial whose device-certificate
signature no longer matches: strictly worse than blank, and a state no legitimate console can
be in. Parking nextendo_prodinfo.bin does not prevent it either, because the image is rebuilt
from RAM on every boot and InitializeProdInfoManagement() runs before the SD card is
mounted, so no file on the card can act as the gate.
Patch 0006 therefore adds a dedicated exosphere config item (65013, secmon flag bit 9), wired
through the same path as ExosphereAllowCalWrites, and an exosphere.ini key
nextendo_synth_prodinfo. The two settings are now independent:
blank_prodinfo_* |
nextendo_synth_prodinfo |
Result |
|---|---|---|
1 |
0 |
blank identity (Nintendo mode — upstream behaviour) |
1 |
1 |
synthetic serial (Nextendo mode) |
Unlike the blank_prodinfo_sysmmc / blank_prodinfo_emummc pair, the synthesis key is
deliberately not gated on the boot type: the blank keys already decide which boot type
blanks at all, so one key covers both and Prelude never has to detect whether it is running on
emuMMC before writing exosphere.ini.
Why the synthesis lives in Atmosphère and not in the homebrew: once blank_prodinfo is
active, every CAL0 read from outside goes through this very MITM. Prelude as homebrew only
ever sees the blanked image, and anything built from it fails IsValid(). ams_mitm does not
mitm itself: g_calibration_info holds the genuine calibration data. That makes it the only
place in the system where the real CAL0 is reliably available while blanking is on.
What the synthesis actually changes:
- Randomizes the serial number (
XKW+ 11 alphanumeric characters) - Randomizes the device id embedded at offset
0xC6of the ECC device certificate - Leaves all crypto material untouched — SSL key, SSL certificate, extended SSL key, amiibo roots. Otherwise TLS breaks.
- Recomputes the two block CRC16s, the body SHA256 (over
header.body_size) and the header CRC, then validates withIsValid()before writing.
The result is written to sdmc:/atmosphere/nextendo_prodinfo.bin so the identity stays
stable across reboots, and is applied to the live blank buffer so no extra reboot is needed.
Timing (patch 0005): fs_mitm starts serving the CAL0 partition as soon as
LaunchAllModules() runs, and HorizonOS reads the serial number very early. Swapping it on the
init thread was too late — HorizonOS had already cached the blanked value. So the work is split:
BuildNextendoProdInfo() touches no filesystem (source is RAM, randomness from
os::GenerateRandomBytes, CRC/SHA are pure computation) and runs early; only
PersistNextendoProdInfo() needs the SD and stays on the init thread.
3. ssl_mitm — contrib/npshop-ssl-mitm/
Sysmodule (title ID 4200000000000053), embedded as a prebuilt exefs.nsp. It links against
its own copy of Atmosphere-libs (contrib/npshop-ssl-mitm/src/Atmosphere-libs) — patching
the main Atmosphère does not patch that copy. It is not built in CI because its Makefile
references a local symlink; the prebuilt NSP is committed.
Honest assessment: what the generated serial does and does not achieve
Rewriting the device id inside the ECC/RSA certificates only updates the CRC16, an integrity checksum — not a signature. The certificates are signed by Nintendo's CA, so a modified id yields an invalid signature.
- Against your own server: perfectly fine, it does not verify them.
- Against real Nintendo servers: not a plausible identity. A fully synthetic identity would require re-signing the certificates — out of scope.
Equally important: the serial number is not the identifier. The SSL client certificate is Nintendo-signed, unique per console, stays byte-identical in the synthetic file (it must, or TLS breaks), and goes out on every client-authenticated handshake. The real protection in Nextendo mode comes from the host redirection — Nintendo never receives the handshake at all.
Scope: by default blank_prodinfo_emummc affects emuMMC boots only, so the synthetic
identity exists only there and sysNAND always keeps its real PRODINFO. On a console without an
emuMMC this can be enabled explicitly — see below.
Optional: synthetic identity on sysNAND
fusee accepts both blank_prodinfo_sysmmc and blank_prodinfo_emummc, each gated on the boot
type, so a console only ever reads the key that matches it. Prelude writes only the emuMMC key
by default; the sysNAND key is an opt-in.
On the confirmation screen of a console without an emuMMC, press X to toggle it. The
setting is stored in sdmc:/switch/prelude_sysnand.cfg and is off unless you turn it on.
Turning it back off rewrites the key to 0, so a previously enabled console is not left
blanking silently.
The option only ever applies in Nextendo mode. Nintendo mode always writes
blank_prodinfo_sysmmc=0 and nextendo_synth_prodinfo=0, so the console is handed back
untouched before you talk to Nintendo. See patch 0006 above for why the synthesis needs its
own flag: parking the identity file is not enough to stop it.
Read this before enabling it. sysNAND is the NAND that carries your real eShop account and online membership. The synthesis does not blank anything — it serves a copy of the real CAL0 with a randomized serial and device id, leaving every byte of crypto material intact. But that is exactly the limit: the unchanged SSL client certificate is what actually identifies the console, so the gain is largely cosmetic while the risk (manipulating CAL0 handling on the NAND holding your real account) is not. Use it on a test console.
What if you only use sysNAND?
That is the normal case for a console without an emuMMC, and it works — the option above is not required for anything.
With the option off (the default), Prelude never touches blank_prodinfo_sysmmc, so the
console keeps its real PRODINFO in both modes. In Nextendo mode that is not a leak: the DNS
redirection means Nintendo never receives the handshake in the first place, so the identity
stays confined to your own server. In Nintendo mode you are simply a normal CFW console talking
to Nintendo with its real identity — which is what the warning card on the confirmation screen
tells you plainly.
Reference
What is in the bundle
prelude-bundle-<tag>.zip (install steps are in Quick start above):
atmosphere/ Custom Atmosphère 1.11.2 with the Nextendo patches (requires system firmware 22.5.0+)
atmosphere/package3 contains the patched ams_mitm as a KIP
atmosphere/reboot_payload.bin copy of fusee.bin — used by "reboot to payload"
switch/nextendo.nro Prelude
switch/daybreak.nro (Atmosphère standard)
switch/haze.nro
switch/reboot_to_payload.nro
fusee.bin the payload you must boot — parses the identity keys
README.txt install instructions + content manifest
Three parts have to match. fusee.bin parses exosphere.ini (including
nextendo_synth_prodinfo) and sets the secure-monitor flags; package3 carries the patched
ams_mitm that acts on them; nextendo.nro writes the configuration. Mixing a new .nro with
an old payload leaves the identity handling inert — see the warning in Quick start.
Mode switching and the synthetic identity
When switching to NINTENDO, nextendo_prodinfo.bin is parked in sdmc:/switch/prelude/
rather than deleted. Reason: generation draws a fresh serial and device id on every call, so
each mode switch would mint a different synthetic console. A serial that changes on every
toggle is itself a signal, and any server-side pairing keyed to the device id would break each
time.
Updating
The NRO checks for a new release at launch and can download and replace the .nro it is
running from (any SD path, not just /switch/). The update source is the Forgejo releases
API at git.it-geek.at, not GitHub:
/api/v1/repos/KutaroKazuki/Prelude-Generated-Serial/releases/latest
The self-updater only replaces the
.nro. It cannot touchfusee.bin,package3or your injector, because those are not running when it updates — and on a modchip the payload may not even live on the SD card. When a release changes the payload or the Atmosphère patches (asv3.4.15did), update by extracting the fullprelude-bundle-<tag>.zipand re-pointing your injector at the newfusee.bin. Otherwise you get a new app on top of an old payload, which is the one combination where the identity handling silently does nothing.
Because the Switch resolves names through Nintendo's DNS and cannot look up that host,
resolve_host() in source/nextendo_net.c hardcodes the connect target. SNI still uses the
real hostname, so the TLS certificate validates normally.
Version numbers are kept in lockstep: APP_VERSION in the Makefile is X.Y.Z, the update
checker compares full semver, and the release tag is vX.Y.Z. CI enforces this.
Manual rollback
- Delete
/atmosphere/nextendo_prodinfo.bin→ams_mitmfalls back to a blanked PRODINFO. - Restore stock
package3→ removes the overlay entirely.
Running your own server
The server IPs are defined in source/nextendo_config.h (NEXTENDO_SERVER_IP_DEFAULT,
NEXTENDO_SERVER_IP_ALT, NEXTENDO_SERVER_IP_NNCSD2), or override at build time with
-DNEXTENDO_SERVER_HOST="your.ip". The host-to-server mapping itself is generated by
nextendo_hosts_build() in source/nextendo_apply.c — that is where you change which domain
goes to which machine.
Keep in mind that nncs1 and nncs2 must resolve to two different IPs, otherwise Pia
deduplicates the NAT probes and MK8 / Splatoon 2 fail with 2618-201.
Features
A complete settings app
- Follows the console's system theme (HOME menu / Settings look, including light/dark mode).
- In-app language selection: English, Español, Português, Français, 中文.
- Background music, decoded with mpg123 — no SDL2, the
.nrois ~35% smaller than before. - Self-updating (see Updating above). Stale bundled mods are detected and offered as an update too.
Online games, out of the box
One switch to Nextendo mode and these are configured with the proper hosts and patches:
- Mario Kart 8 Deluxe — NEX secure-server routed to the production machine, plus a country flag installer (110 flags) that builds the ExeFS patch locally, no download needed.
- Super Smash Bros. Ultimate — optional SSBU Online Deluxe quickplay mod (L button),
bundled in the
.nrowith its full dependency stack (ARCropolis, smashline, Skyline plugins) and a toggle for the mod's own overclock if you already run sys-clk / Horizon OC. - Splatoon 2 — BCAT online schedule installer via LayeredFS (no save-data tricks, no network needed at install time).
- Splatoon 3 — NPLN (gRPC/HTTP2) hosts plus the certificate ExeFS patches required by the game's bundled BoringSSL, with a status screen showing whether the installed patches match the ones this build ships and what to do after a game update.
- Super Mario Bros. 35 — official BCAT event installer plus an optional Special Battle (27 merged events, 119 queues), installed on demand because its ExeFS patch replaces the normal 35-player battle instead of adding to it.
- Super Mario Bros. Wonder — ExeFS patches (certificate + peer name) shipped for everyone; harmless if you don't own the game (Atmosphère matches by build ID).
- Super Mario Party Jamboree — certificate ExeFS patch for the game's own bundled TLS stack. Jamboree speaks NPLN (gRPC over HTTP/2) rather than NEX, and our wildcard certificate already covers its tenant, so no peer-name patch is needed. Taken from upstream; shipped for everyone and likewise harmless without the game.
- Metal Gear Solid: Peace Walker (Master Collection) — certificate ExeFS patch, same
one-instruction pattern. Recovered from an upstream release that shipped only a built
.nrowith no matching commit, so it was extracted from that binary's RomFS and verified byte for byte rather than cherry-picked. - Explicit per-game NEX entries for Mario Tennis Aces, ARMS, Luigi's Mansion 3, Animal Crossing
and Strikers, on top of the
g2*wildcard.
Privacy & reversibility
- Telemetry blocked in both modes (Atmosphère's native defaults are merged, not replaced).
- Nintendo mode removes the whole certificate-trust stack (CA bundle,
disable_ca_verification,rootCA.pem) and purges the logs that could leak the server IP — no.bak, no debug logs. - Your own
hostsfiles are offered a one-time backup before Prelude writes over them.
Building
NRO locally
docker run --rm -v "$PWD:/work" -w /work devkitpro/devkita64 \
bash -c 'dkp-pacman -Syu --noconfirm switch-freetype switch-mpg123 && make -j$(nproc)'
Produces nextendo.nro. The package names are switch-freetype and switch-mpg123 —
no 2 suffix.
Never pass
CFLAGS=on the make command line — CLI variables clobber the Makefile's own CFLAGS (the FreeType include path is lost). Editsource/nextendo_config.hinstead.
Both halves via CI
.forgejo/workflows/build-bundle.yml builds both halves and assembles the bundle. It runs
on pushing a v* tag or via workflow_dispatch. Steps:
- Version guard —
APP_VERSIONin the Makefile must match the tag. - Build the NRO.
- Fetch the Atmosphère tag — clone tag
1.11.2, then verify both the commit hash and the version header (ams_api_version.h). A moved tag would otherwise silently build a different base. - Apply the patches —
git am atmosphere-patches/*.patch, then verify thatnextendo_prodinfo.binandSetOverrideRegisterInternalPkiactually landed in the source. - Build Atmosphère — Haze shaders serially first (
-j1), otherwise thedkshtarget races; thenmake -f atmosphere.mk dist -j$(nproc)(distlives inatmosphere.mk, not the root Makefile). - Verify the binary — release NSOs are LZ4-compressed, so the debug ELF is grepped for
nextendo_prodinfo.bin,BuildNextendoProdInfo,ApplyPendingNextendoProdInfoOverlay. It additionally verifies that the patchedams_mitmKIP is embedded byte-exact inpackage3. - Verify the NRO — NRO0 magic,
ssl_mitmembedded byte-exact, no foreign deployment data, and the expected server IPs present. - Assemble the bundle (
scripts/make_bundle.py) and release.
The AMS build takes a while (libstratosphere alone ~5 min, full build ~15 min) — hence a separate workflow, so the NRO goes green quickly on every push.
Not bit-reproducible: two builds of the same commit differ in ~60 of 17.9 M bytes, all inside GNU build-id notes. Never verify a CI artifact by SHA-comparing it against a local build.
PRODINFO and BIS key backups
automatic_backups/<SERIAL>_PRODINFO.bin and <SERIAL>_BISKEYS.bin are stock upstream
Atmosphère, not a Nextendo feature — they are created on every CFW Switch on every boot. The
code is byte-identical to upstream and there is no exfiltration (no socketInitialize /
connect() / sendto anywhere in ams_mitm).
The risk is in handling, not in the code: these files identify the console, and the BIS keys
decrypt its NAND. Never ship them in an SD image, backup folder, or zip. Note the irony after a
Prelude apply: <REAL_SN>_PRODINFO.bin sits right next to the synthetic file — so the real
serial is in a filename next to the anonymized one.
Special thanks
Special thanks to ESC and El Tඞnke for testing and for finding bugs.
In the early versions, sysNAND support simply was not working at all — it had been assumed to, but real hardware testing showed it never actually took effect. ESC and El Tඞnke were the ones who proved that out and kept the pressure on until it was fixed. They also caught the later case where Nintendo mode was synthesizing an invented serial with broken certificate signatures instead of handing back a clean blank identity — that one needed a new exosphere flag (patch 0006) and would have been a quiet, hard-to-spot failure on sysNAND. Their testing is the reason the identities in this release actually behave the way the docs say.
Licence
Copyright (C) 2026 Nextendo Network.
Prelude is licensed under the PolyForm Shield License 1.0.0. You may use, study, share and modify it for any purpose, and distribute your changes — with one exception: you may not use it to provide a product that competes with Nextendo Network, or with any product Nextendo Network provides using it.
See LICENSE.md for the full text, or https://polyformproject.org/licenses/shield/1.0.0.
Required Notice: Copyright 2026 Nextendo Network
This project is not affiliated with, endorsed by, or connected to Nintendo. "Nintendo" and "Nintendo Switch" are trademarks of Nintendo. Use it on hardware you own.