jevsnes.git / apps / headless / README.md
1# Chapter 10: headless, does it even boot?
2
3Before anything clever, one question: does the core, built by buck2, run
4this game? `headless` answers it with no window, no bot and no Jev:
5
6```bash
7nix develop -c buck2 run //apps/headless:headless -- \
8  "roms/Legend of Zelda, The - A Link to the Past (USA).sfc" 1500 run/out.ppm
9```
10
11It boots the cartridge and runs the number of frames you ask for, tapping
12Start for 4 frames out of every 60 (enough to get through the title screens
13without holding the button down). Then it writes the last frame as a binary
14PPM and checks the one property everything else in the repository leans on:
15it takes a snapshot, runs 300 frames, goes back to the snapshot, runs the
16same 300 frames again, and asserts the two futures are the same picture and
17the same work RAM. Finally it prints the frame size, the audio sample count,
18and the handful of work-RAM bytes the rest of the code keys on (game mode,
19submode, Link's position, health).
20
21> **Aside: four times faster than a SNES.** Measured 2026-09-20: 1,500
22> frames in 5.6 s and 3,600 in 14.5 s, about four times real time, reaching
23> the title screen by frame 900 and the name-registration screen by frame
24> 1,500. That margin is what lets the headless bot (chapter 11) play 30,000
25> frames, eight minutes of game, in about two and a half.
26
27> **Try it.** Run the command above, then
28> `ffmpeg -i run/out.ppm run/out.png` and open the picture. You should see
29> the name-registration screen, and a line saying the snapshot was
30> identical after 300 frames.
31
32## For the people who maintain it
33
34### In this folder
35
36| Path | What |
37| --- | --- |
38| [src/main.rs](src/main.rs) | The whole program: boot, run, write the PPM, the snapshot round trip, print the bytes. |
39| [BUCK](BUCK) | The `rust_binary`, over `//packages/console:console` alone. |
40
41Usage: `headless <rom.sfc> <frames> <out.ppm>`. Link's position reads 0 until
42a save is loaded and the game is in play, so zeros at the title or the
43name-registration screen are correct.
44
45← Previous: [Chapter 9, apps/](../) · Up: [apps](../) · Next: [Chapter 11, zbanks/](../zbanks/) →