1{ 2 description = "jev plays Zelda — a Rust app that hosts a SNES core and lets Jev (TypeSafe AI) play A Link to the Past, natively and as WASM"; 3 4 inputs = { 5 # Same branch as ~/config, and locked to the same rev, so Mesen and 6 # ffmpeg-full are the store paths the system already has rather than a 7 # second 600 MB copy. 8 nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
The Rust toolchain comes from fenix, not nixpkgs: the emulator core
(jgenesis' snes-core) uses float_algebraic, stabilised after the
rustc 1.95 nixos-26.05 carried — measured 2026-09-20, 16 E0658
errors on 1.95, clean on 1.98.1. fenix's stable is the release
channel, i.e. the newest released compiler; nix flake update fenix
moves it forward.
The estate package set, for buck2 (see the devshell).
One toolchain for both outputs of the app: the native window and the browser build. wasm32-unknown-unknown needs only its rust-std — the linker for it (rust-lld) ships inside rustc.
51 mesen = pkgs.callPackage ./nix/mesen.nix { 52 enforce = { 53 Video.UseSoftwareRenderer = true; 54 Debug.ScriptWindow = { 55 AllowIoOsAccess = true; 56 AllowNetworkAccess = true; 57 }; 58 }; 59 }; 60 in 61 { 62 packages.${system}.mesen = mesen; 63 64 devShells.${system}.default = pkgs.mkShell { 65 packages = [ 66 rustToolchain
The build: buck2 drives it, reindeer turns Cargo.lock into the third-party BUCK targets. nix-pkgs' buck2, not nixpkgs': the 2026-08-22 binary drops its forkserver under test load (fixed in facebook/buck2 1cc3e05f85, released 2026-09-15); the nix-pkgs package header has the account.
buck2's system cxx toolchain looks up plain clang/clang++ by
name and links with -fuse-ld=lld; without both, every Rust binary
and build script fails at the link step. Same wall ~/dashboard and
~/mobo hit.
cpal compiles its ALSA host on every Linux build, and alsa-sys's build script finds libasound through pkg-config or panics.
Mesen 2: the reference emulator, for checking our core's RAM and picture against a known-good one.
90 mesen
Capture. -full, not plain ffmpeg: only -full is built with XCB,
so only it has the x11grab input device that grabs a WSLg
window by id. xwininfo is what finds that id.
102 pkgs.jq
The zbanks C bot (third-party/c) was written to run under gdb: its assert_bp is an int3 breakpoint. gdb is how its static state (targets, goal scores) is read mid-run.
107 pkgs.gdb
Poking the Jev HTTP API by hand.
110 pkgs.curl
Linting tools/*.sh - code-bash.md requires shellcheck-clean.
113 pkgs.shellcheck
"Which GPU did I actually get": glxinfo/eglinfo and vulkaninfo.
Reaching the GPU under WSL. wsl.useWindowsDriver links the D3D12
libraries into /run/opengl-driver/lib and stops there: Mesa dlopens
libd3d12.so / libdxcore.so by bare name with no runpath to that
directory, and with no DRM node it never picks d3d12 unprompted.
Without these two, GL, EGL and Vulkan all report llvmpipe; with
them, all three report the RTX 3080 (measured 2026-09-20). Vulkan
(Dozen) needs only the library path, GL needs both — and
GALLIUM_DRIVER without the path is worse than neither: GL programs
fail to start.
The rest of the path is for our own window. winit, wgpu and xkbcommon-dl link none of their system libraries: they dlopen them by bare name at startup, so a Nix-built binary finds nothing unless the directories are on the search path.
alsa-lib is the one that IS linked (cpal's ALSA host, a DT_NEEDED on libasound.so.2), but buck2's link writes no runpath to the store, so the loader still has to be told where it is: without it the binary dies before main with "libasound.so.2: cannot open shared object file" (measured 2026-09-20).