--- name: teensyrom-build description: How to build and flash TeensyROM firmware from this repo. Covers the C64 menu programs (npm run build:c64), the combined dual-boot firmware .hex for a TeensyROM or a TeensyROM+ (npm run build:tr / build:tr-plus), writing it to one or several boards over USB (npm run flash, tools/flash-firmware.mjs), and the tests and CI around them. Use whenever the user wants to build, compile, rebuild, flash, program or update firmware, make a .hex, find out what needs rebuilding after a change, check which build a board runs, or fix a failing build, for either cartridge type. --- # Building TeensyROM Two toolchains and a flasher, run in this order. Node is the only prerequisite for most of it (`.nvmrc` pins the version), and the repo takes no npm dependencies. | Step | Command | Produces | How-to | |---|---|---|---| | 1. C64 programs | `npm run build:c64` | C headers in `Source/Teensy/TRMenuFiles/ROMs/` | [c64-build.md](references/c64-build.md) | | 2. Firmware | `npm run build:tr` or `npm run build:tr-plus` | `build/firmware/TeensyROM[+]__full.hex` | [firmware-build.md](references/firmware-build.md) | | 3. Flash | `npm run flash` | that image running on a board, checked | [flash.md](references/flash.md) | | Tests and CI | `npm test` | | [tests-and-ci.md](references/tests-and-ci.md) | Why the build works this way (the two toolchains, the dual-boot image, the pinned tool versions) is in [docs/Architecture/Build-System.md](/docs/Architecture/Build-System.md). Read it before changing the build itself. ## What needs rebuilding | You changed | Run | |---|---| | Anything under `Source/C64/`: source, a shared include (several projects include `c64defs.i`, `CommonDefs.i` and `Menu_Regs.i`), or a `.prg`/`.bin` some project converts | step 1 (all projects unless you know only one uses the file), then step 2 | | `Source/Teensy/MinimalBoot/Common/Menu_Regs.h` (shared with the C64 side) | step 1 (all projects), then step 2 | | Anything else under `Source/Teensy/` | step 2 | | Nothing: you want a board on this commit's firmware | step 2 with `--force`, unless `build/firmware` already holds this commit's image (its build date is the commit's time, see [flash.md](references/flash.md)); then step 3 | | The build tools under `tools/` | `npm test` | Step 2 builds one cartridge type per run. Build both when both kinds of board need it. ## Easy to get wrong - **TR and TR+ images are not interchangeable.** `--target tr` is the TeensyROM (Fab 0.2/0.3), `--target tr-plus` the TeensyROM+ (Fab 0.4). Both build cleanly. The flasher refuses the wrong one before writing; the SD-card updater refuses it only after the file has been carried over. - **The build date names a commit, not a build.** It is the HEAD commit's time, so a build with uncommitted edits carries the previous commit's date, and rebuilding a commit gives the same hex. Commit first if the date on the board has to prove what it runs. - **Skipping step 1 is silent.** The firmware embeds whatever headers are in the working tree, so a C64 change that was not rebuilt ships the old program. - **Old images keep their name.** An image is named after the firmware version, not the commit, so `build/firmware` can hold an older build under the current name, and the flasher takes the newest file of either type. Check the build date it prints. ## After a build (for agents) - The person does not see the build's output, only your reply. Show them its memory report verbatim, in a code block: for each image built (`[minimal]`, `[main]`, and `[extension]` when there is one), the `[name] Building` line, the `Memory Usage on Teensy 4.1` block under it and the `Hex:` line. Do this after every build, a successful one included, and do not summarize or reformat the numbers. - Put it in your final reply for the task, even when you already showed it partway through (before flashing, say): messages between tool calls can be collapsed out of sight, and the final reply is the one the person reads. - A build that failed before linking has no report for that image; say so, and show the error instead. ## On real hardware (for agents) - Flashing changes a physical board. Say which board gets which image, and wait for the person's go-ahead; if they want to watch, wait for them. - Start with `npm run flash -- --check`. It identifies every attached board and writes nothing. - With more than one Teensy attached, never call `teensy_post_compile -port=...` yourself: with `-port` alone it falls back to auto-search and can write the other board. The flasher passes the board's whole address. - Stop anything that holds a board's serial port (a TeensyROM app or API, a serial monitor) before flashing; a board it holds cannot answer and cannot be identified. - TeensyROM settings survive a USB flash. ## Options `npm run flash -- --help` and `npm run build:c64 -- --help` list their options. `tools/build-firmware.mjs` has no `--help`; [firmware-build.md](references/firmware-build.md) lists its options, and the top of the file explains them.