melonDS Nightly - RetroBIOS¶
Technical notes
Android port of melonDS. The emulation code is the melonDS-android-lib submodule, a fork of melonDS-emu/melonDS pinned at 431ab4bd and declaring version 1.1 (CMakeLists.txt:20); the app around it is Kotlin plus a JNI layer under app/src/main/cpp.
Nightly is a product flavor, not a separate tree: the build dimension "build" has prod and nightly, and nightly sets applicationIdSuffix ".nightly" and the version suffix " (NIGHTLY)" (app/build.gradle.kts:59-61,76-79), giving the package id me.magnum.melonds.nightly. Its source set holds an app name and a launcher icon (app/src/nightly/res), and the gitHubNightly set points the update check at the nightly release instead of the tagged one (app/src/gitHubNightly/java/me/magnum/melonds/github/repositories/GitHubNightlyUpdatesRepository.kt:31). No load path differs from the prod flavor.
Files live in two directories the user picks through the storage access framework, stored in the preferences bios_dir and dsi_bios_dir (app/src/main/res/xml/pref_custom_firmware.xml:29-39). Both are read by basename, so bios7.bin, bios9.bin and firmware.bin each name a DS image in one directory and a DSi image in the other; the accepted lengths are what tell them apart. The app lists the expected names on screen when a directory is unset or rejected (app/src/main/res/values/strings.xml:116,118). Entries below carry the basename the app opens in the path, under the console identifier the picker binds to each directory, ds and dsi (app/src/main/res/xml/pref_custom_firmware.xml:33,39).
use_custom_bios defaults off (app/src/main/res/xml/pref_custom_firmware.xml:11, SharedPreferencesSettingsRepository.kt:258-260). With it off, launching a ROM skips the directory check entirely and the core substitutes FreeBIOS and a firmware built in memory, so DS games run with nothing supplied. Booting into the firmware menu instead of a ROM always turns it on (AndroidEmulatorManager.kt:247-253), as does any per-ROM console override (AndroidEmulatorManager.kt:239). DSi needs both directories: the DSi check runs the DS check after its own (ConfigurationDirectoryVerifier.kt:13-21).
The generated firmware keeps its Wi-Fi access point block in wfcsettings.bin, read at boot and written back by the emulator (EmulatorArgsBuilder.cpp:189,200-226, MelonInstance.cpp:58-62). It resolves against context.filesDir (PlatformAndroid.cpp:158-163, SharedPreferencesSettingsRepository.kt:155), app-private internal storage the user cannot write to, and holds settings this build produced. Not listed below: there is nothing to obtain.
Neither SD card is reachable in this build. getSDCardArgs returns nothing when a card is disabled (SDCardArgsBuilder.cpp:19-20) and the JNI layer hardcodes both the DSi card and the homebrew DLDI card to disabled (MelonDSAndroidConfiguration.cpp:93-94), with no preference anywhere in the app to turn either on; the README lists DSi SD card support under missing features. The Action Replay database the core can parse is likewise never built: ARDatabaseDAT is reached only from src/frontend/qt_sdl, and the Android build sets BUILD_QT_SDL OFF and links the core alone (app/CMakeLists.txt:8,73). Cheats are entered in the app's own database.
7 files | 4 required, 3 optional | 7 in repo, 0 missing | 3 with HLE fallback
bios9.bin optional in repo HLE fallback
Nintendo DS ARM9 BIOS
- Path:
ds/bios9.bin - System: nintendo-ds
- Size: 4.0 KB
- CRC32:
2ab23573 - Aliases:
NDS_Bios9.bin,nds9.bin - Validation: size, crc32
- Source:
app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:51-53,app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:100-113,app/src/main/java/me/magnum/melonds/impl/SharedPreferencesSettingsRepository.kt:149,app/src/main/cpp/EmulatorArgsBuilder.cpp:19-40,src/MemConstants.h:30-36,src/NDS.cpp:807-811,src/NDS.cpp:277-296,src/NDS.cpp:303-310 - Platforms: batocera, emudeck, lakka, recalbox, retroarch, retrobat, retrodeck, retropie, rocknix, romm
- Config key:
bios_dir - The picker rejects any length other than 4096. The core hashes what it loads and keeps the result as a flag rather than refusing the image: a CRC32 other than 2ab23573 marks the BIOS non-native, which forces direct boot and makes SetupDirectBoot copy the Nintendo logo out of the ROM header into the BIOS at 0x20 so DS-to-GBA communication still works. FreeBIOS is substituted when custom BIOS is off.
bios7.bin optional in repo HLE fallback
Nintendo DS ARM7 BIOS
- Path:
ds/bios7.bin - System: nintendo-ds
- Size: 16.0 KB
- CRC32:
1280f0d5 - Aliases:
NDS_Bios7.bin,nds7.bin - Validation: size, crc32
- Source:
app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:47-49,app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:100-113,app/src/main/java/me/magnum/melonds/impl/SharedPreferencesSettingsRepository.kt:148,app/src/main/cpp/EmulatorArgsBuilder.cpp:42-62,src/MemConstants.h:30-36,src/NDS.cpp:801-805,src/NDSCart.cpp:138-151 - Platforms: batocera, emudeck, lakka, recalbox, retroarch, retrobat, retrodeck, retropie, rocknix, romm
- Config key:
bios_dir - The picker rejects any length other than 16384. A CRC32 other than 1280f0d5 marks the BIOS non-native, which forces direct boot and leaves Key1_KeyBuf zeroed instead of seeding it from offset 0x0030, so cartridge Key1 encryption is unavailable. FreeBIOS is substituted when custom BIOS is off.
firmware.bin optional in repo HLE fallback
Nintendo DS firmware image
- Path:
ds/firmware.bin - System: nintendo-ds
- Aliases:
dsfirmware.bin - Validation: size
- Source:
app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:55-70,app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:120,app/src/main/java/me/magnum/melonds/impl/SharedPreferencesSettingsRepository.kt:150,app/src/main/cpp/EmulatorArgsBuilder.cpp:93-185,app/src/main/cpp/EmulatorArgsBuilder.cpp:289-337,src/NDS.cpp:286-288 - Platforms: batocera, emudeck, lakka, recalbox, retroarch, retrobat, retrodeck, retropie, rocknix, romm
- Config key:
bios_dir - Size options: 128.0 KB, 256.0 KB, 512.0 KB
- Three lengths are accepted and everything else is rejected. Loaded only in DS mode; DSi mode reads the firmware from the DSi directory but still needs this file present, because the DSi check re-runs the DS directory check. Nickname, message, language, colour, birthday and MAC are written into the image before it reaches the core. A firmware the core reports as non-bootable forces direct boot. When custom BIOS is off the core builds a firmware in memory instead.
dsi_bios9.bin required in repo
Nintendo DSi ARM9i BIOS
- Path:
dsi/bios9.bin - System: nintendo-dsi
- Size: 64.0 KB
- Aliases:
biosdsi9.bin - Validation: size
- Source:
app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:76-78,app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:100-113,app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:124,app/src/main/java/me/magnum/melonds/impl/SharedPreferencesSettingsRepository.kt:152,app/src/main/cpp/EmulatorArgsBuilder.cpp:235-260,app/src/main/cpp/EmulatorArgsBuilder.cpp:475-477,src/DSi.cpp:950-955,src/NDSCart.cpp:127-134 - Platforms: batocera, lakka, retroarch, retrobat, retropie, rocknix
- Config key:
dsi_bios_dir - Opened as bios9.bin inside the DSi directory. The picker rejects any length other than 65536, and no hash is computed on it. A load failure aborts the launch. DSi boot copies four blocks out of it into ITCM from 0x87F4, 0x9920, 0x99A0 and 0xA9E8, and cartridge Key1 in DSi mode is seeded from 0x99A0. With the boot screen off, the reset vector is overwritten in memory with 0xEAFFFFFE.
dsi_bios7.bin required in repo
Nintendo DSi ARM7i BIOS
- Path:
dsi/bios7.bin - System: nintendo-dsi
- Size: 64.0 KB
- Aliases:
biosdsi7.bin - Validation: size
- Source:
app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:72-74,app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:100-113,app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:123,app/src/main/java/me/magnum/melonds/impl/SharedPreferencesSettingsRepository.kt:151,app/src/main/cpp/EmulatorArgsBuilder.cpp:262-287,app/src/main/cpp/EmulatorArgsBuilder.cpp:347,app/src/main/cpp/EmulatorArgsBuilder.cpp:471-473,src/DSi.cpp:959-962 - Platforms: batocera, lakka, retroarch, retrobat, retropie, rocknix
- Config key:
dsi_bios_dir - Opened as bios7.bin inside the DSi directory. The picker rejects any length other than 65536, and no hash is computed on it. A load failure aborts the launch. Offset 0x8308 holds the ES key used to derive the NAND AES keys, so the NAND cannot be opened without this exact image. DSi boot copies four blocks out of it from 0x8188, 0xB5D8, 0xC6D0 and 0xD718. With the boot screen off, the reset vector is overwritten in memory with 0xEAFFFFFE.
dsi_firmware.bin required in repo
Nintendo DSi firmware image
- Path:
dsi/firmware.bin - System: nintendo-dsi
- Size: 128.0 KB
- Aliases:
dsifirmware.bin - Validation: size
- Source:
app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:80-93,app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:125,app/src/main/java/me/magnum/melonds/impl/SharedPreferencesSettingsRepository.kt:153,app/src/main/cpp/EmulatorArgsBuilder.cpp:289-337 - Platforms: batocera, lakka, retroarch, retrobat, retropie, rocknix
- Config key:
dsi_bios_dir - Opened as firmware.bin inside the DSi directory, where only 131072 is accepted against three accepted lengths in the DS directory. Read in DSi mode in place of the DS firmware, and customised the same way. The core has no generator for DSi firmware, so nothing stands in for it.
dsi_nand.bin required in repo large_file
Nintendo DSi NAND dump
- Path:
dsi/nand.bin - System: nintendo-dsi
- Validation: existence
- Source:
app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:95-98,app/src/main/java/me/magnum/melonds/impl/FileSystemConfigurationDirectoryVerifier.kt:126,app/src/main/java/me/magnum/melonds/impl/SharedPreferencesSettingsRepository.kt:154,app/src/main/cpp/EmulatorArgsBuilder.cpp:339-420,app/src/main/cpp/EmulatorArgsBuilder.cpp:479-481,app/src/main/java/me/magnum/melonds/domain/services/EmulatorLaunchPreconditionChecker.kt:47-70,src/DSi_NAND.cpp:43-70 - Platforms: batocera, lakka, retroarch, retropie, rocknix
- Config key:
dsi_bios_dir - Opened as nand.bin inside the DSi directory. The only test the app makes is that the entry is a file: no length, no hash. It is opened for read and write and must already exist. The core wants the nocash footer "DSi eMMC CID/CPU" at 0x40 before the end, falling back to 0x000FF800 for images cut short by external tools, and reads the eMMC CID and console ID from there to derive the FAT and ES keys with the key at 0x8308 of the ARM7i BIOS. Touchscreen calibration is rewritten in the mounted user data on every launch. Any regional dump works. A DSiWare title is refused unless it is already installed in this image.
Generated on 2026-08-23T16:12:06Z