Skip to content

Emulator Explainer

Citra, melonDS, And Desmume: How Android Emulator Core Updates Work

A plain explanation of how Android emulator core updates work, using Citra, melonDS, and desmume changes in FullRoid as concrete examples.

Citra, melonDS, And Desmume: How Android Emulator Core Updates Work preview

Written by the Fulldive product engineering team, based on direct inspection of the repositories listed below.

Android emulator core updates are the most important maintenance work an emulator app does, and the least visible to users. When you see that an app added “new 3DS core support” or “Citra hardware shader cache,” what actually happened under the hood? This post uses real commits from Fulldive’s One Emulator for Game Consoles — specifically around Citra, melonDS, and desmume — to explain how cores are bumped, deprecated, and migrated, without overclaiming universal game compatibility.

Cores, briefly

An emulator core is a library that pretends to be a specific console. The host app (our emulator) loads cores through a common interface (RetroArch’s Libretro API is the reference model for many Android emulators). Each system usually has one or more cores; different cores trade off accuracy, performance, and compatibility.

Practical implications:

  • Different systems need different cores.
  • The same system can have competing cores — like desmume and melonDS for Nintendo DS.
  • Cores update independently. The app has to pick versions and wire them in.

The RetroArch / Libretro documentation is the canonical reference for how this works in practice.

Bumping cores: not just a version string

Commit be65800d bumped emulator cores. In a blog post that is one line. In a repository it is careful work:

  • Re-check that existing save files still load with the new core version.
  • Re-run a compatibility sweep on representative game files.
  • Update any core-specific options that were renamed or reworked upstream.
  • Ship with a rollback plan if the new version regresses a system.

A core bump can fix a long-standing bug for one game and introduce a new bug for another. That is why core bumps are not always announced as headline features. They are maintenance.

Desmume to melonDS: a deprecation with lazy migration

Commit f71aade4 deprecated desmume and lazily migrated users to melonDS. Here is what “lazy migration” means in practice:

  • Existing desmume users keep their saves in place.
  • The next time a DS title is loaded, the emulator detects the old save and migrates it to the melonDS format on the fly.
  • If anything goes wrong, the old save is preserved as a fallback.

Before that, the melonDS save import work in commit 28a1f115 handled users who had already been on melonDS but were upgrading across a format change. The two commits together define what a respectful core change should look like: no forced migration prompt, no data loss, a transparent path forward.

Why move off desmume? Over time, the melonDS project has improved accuracy and Android performance for many DS titles. Moving to it is a net upgrade for the subset of titles where melonDS has better results, even though some edge-case games may behave slightly differently. We are deliberate in not claiming every DS game now “just works” on the new core — core changes do not deliver that.

Citra: shader cache and experimental save states

Citra is the reference 3DS emulator core. Two commits show how it is evolving inside Fulldive’s emulator:

  • Commit 640cdc59: Citra hardware shader cache. 3DS games lean heavily on shader compilation; caching compiled shaders dramatically improves the “first time entering an area” stutter that users notice most.
  • Commit 1030d028: experimental Citra save-state support. The “experimental” label is honest — save states on a newer, more complex core need tuning, and we don’t want users to assume state files will survive every future core bump.

Then commit e9ca6f9b added new 3DS core support — which is not the same thing as “every 3DS game works.” It is “we ship a core that handles a subset of 3DS software on a range of Android devices.” For the why, see Why emulator compatibility varies on Android.

Save states and core changes don’t always mix

Save states are serialized snapshots of the core’s internal state. That means:

  • Save states are tightly bound to the core and often the core version.
  • A core bump can invalidate save states made on the prior version.
  • In-game saves, which the game itself writes to its save memory, survive much better across core bumps because they depend on the game’s save format, not the core’s internal data model.

We cover this difference in depth in Save states vs in-game saves on Android emulators.

How to read core-update release notes

When an emulator’s changelog says something like “bumped X core” or “added Y core”:

  • Treat it as potential compatibility movement, not universal support.
  • Expect some existing games to run better; expect a small subset to regress.
  • Back up your save folder before updating. The migration paths work hard to preserve saves (e.g., f71aade4, 28a1f115), but a backup is still cheap.
  • If a specific game mattered to you, test it on the new version before deleting the old state file.

Why the work never stops

The story told in The FullRoid evolution makes this concrete: in late 2025 and into 2026, the Citra shader cache, experimental save states, the new 3DS core, and the melonDS migration landed in a rolling sequence, interleaved with Android target SDK bumps and the Jetpack Compose UI migration. All of that is ongoing maintenance on someone else’s upstream emulator projects plus Fulldive-specific integration and shipping. There is no “finished” state for an Android multi-core emulator.

Fulldive’s emulator apps do not include or distribute copyrighted games, BIOS files, or ROM downloads. Users are expected to provide legally obtained game files that are compatible with the app. Compatibility varies by core, core version, game file, device, Android version, and controller. Specifically: we do not claim all Nintendo DS, 3DS, Game Boy, GBA, or other system titles work — each core supports a subset, and that subset changes over time.

Sources

Last updated: 2026-04-16. Commit hashes and version numbers are drawn from Fulldive repositories inspected on 2026-04-13.