Chapter 28: nix, the Mesen launcher
flake.nix at the top of the repository is the devshell: every tool at an
exact version. This folder holds the Nix expressions it calls, and today
there is one: the wrapper that launches Mesen.
Mesen 2 is a well-regarded emulator the devshell carries as a second opinion. When our core and the game seem to disagree about a RAM address or a picture, Mesen running the same ROM settles it. Jev never plays in it.
Mesen keeps all its settings in one settings.json of about 220 KB, and
rewrites the whole file on startup and exit. So the file cannot be a
read-only file Nix puts in place. What can be declared is the handful of
keys this project depends on, merged into the file before every launch,
leaving the rest of it Mesen's:
Video.UseSoftwareRenderer = true. Mesen reads it before it parses the command line, so no switch can set it. The GPU renderer shows a black game surface (with working sound) whenever Mesa falls back to software rendering, which an ordinary WSLg session does; the software renderer works either way.Debug.ScriptWindow.AllowIoOsAccessandAllowNetworkAccess = true, which gate LuaSocket and have no switch at all.
If there is no settings file yet, it writes a seed instead: those keys plus
ConfigUpgrade = 1, the one value for which Mesen fills in controller
mappings (a bare {} leaves every port unmapped), and whose existence
suppresses the first-run wizard, which would otherwise hang --testRunner.
Aside: the invisible byte. Mesen writes
settings.jsonwith a UTF-8 byte-order mark, whichjqrejects. The wrapper strips it withsedbefore merging. A test against a hand-made seed would never notice, which is why changes here are tested against a copy of a file Mesen really wrote.
Try it.
nix develop -c sh -c 'cat "$(command -v Mesen)"'prints the wrapper script itself. Inside the devshell,Mesenis the only Mesen onPATH: the wrapper takes the upstream binary's name so that there is no unwrapped one to start by mistake.
For the people who maintain it
In this folder
| File | What |
|---|---|
| mesen.nix | The Mesen launcher: merges the enforce attrset (set in ../flake.nix) into Mesen's settings.json, seeds a missing one, then execs the real emulator. Its header comment is the full rationale, with file and line citations into the Mesen source. |
| README.md | This chapter. |
| CLAUDE.md | How to test a wrapper change, for agents. |
← Previous: Chapter 27, hotpatch/ · Up: jevsnes · Next: Chapter 29, toolchains/ →