The SDK ships inside the UVMC2 Starter Kit: the SDK itself, a minimal example game to copy, a full worked example (an arcade game emulated in C) and the host-side tools. Nothing in the kit looks outside its own directory, so it builds from wherever you unpack it.
- Starter kit: github.com/tullulah/uvmc2-starter-kit (latest release: v1.3)
- SDK (a git submodule of the kit, at
sdk/): github.com/tullulah/uvmc2-sdk
Prerequisites
All five are required, Rust included.
| Tool | Minimum | Verified with | Why |
|---|---|---|---|
| Arm GNU Toolchain | any with nosys.specs | 15.2.rel1 (gcc 15.2.1) | The cross compiler. Use the official Arm installer (bare-metal AArch32, arm-none-eabi). Homebrew's arm-none-eabi-gcc does not ship nosys.specs, and the pico-sdk link needs it. |
| CMake | 3.13 | 4.2.0 | pico-sdk 2.2.0 builds through CMake; 4.x is fine. |
| Python 3 | 3.6 | 3.14 | Writes the 20-byte .um2 header (stdlib only). |
| Rust / cargo | 1.78 | 1.91.1 | The beam model and the bus stream are two no_std crates, and every build links them. |
| git | any | — | setup.sh clones the pico-sdk. |
You also need a network connection for the first build: cargo fetches the crates' dependencies from crates.io once. After that the build is offline.
Why Rust is not optional
The beam model, the code that turns a line into hardware timings, exists in exactly one implementation, written in Rust and shared with the Debug Cart's firmware. The build stops with a fatal error if cargo is not on the PATH. Add the bare-metal target once:
rustup target add thumbv8m.main-none-eabi # softfp bare-metal Cortex-M33Optional tools
| Tool | Needed for |
|---|---|
| ffmpeg | Regenerating sampled sound bundles (make snd in game/tacscan). The bundle ships pre-built. |
| emscripten | make sim: a WASM build for a browser harness. |
| A host C compiler | make host: the desktop test harness. Any cc. |
| probe-rs + a Pico running Debugprobe | Reading counters and the command list over SWD on real hardware. See Debugging. |
Set up the kit
git clone --recursive https://github.com/tullulah/uvmc2-starter-kit.git
cd uvmc2-starter-kit
./setup.shsetup.sh checks the tools, adds the Rust target, fetches the sdk/ submodule if you cloned without --recursive, and shallow-clones pico-sdk 2.2.0 into third_party/pico-sdk. If you already have a pico-sdk 2.2.0 checkout, point PICO_SDK_PATH at it instead.
Build
cd examples/hello_uvmc2 && make uvm2 # -> build_uvm2/hello_uvmc2.um2 (~47 KB)
cd game/tacscan && make uvm2 # -> build_uvm2/aae_tacscan.um2 (~143 KB)The .um2 lands in the example's build_uvm2/ directory, next to the .elf you will need later for debugging.
Run it
The SD card
Format the card FAT32 or exFAT, any size. The multicart's menu and SDK games both read either.
/ the .um2 images, and any sound bundle a game ships (tacscan.vsm)
roms/<game>.zip romsets, read by the game itself at start-up
config/uvm2.cfg this console's beam calibration (written by the calibration screen)
config/<GAME>.CFG per-game settings, for games that declare anyCopy the .um2 to the root of the card and pick it from the multicart menu. For tacscan, also copy:
game/tacscan/roms/tacscan.ziptoroms/tacscan.zip: the game reads its ROM off the card at start-up;game/tacscan/build/tacscan.vsmnext to the.um2, for the sampled sound. Keep the name 8.3: this SDK reads long names, but not every cartridge's reader does.
config/ is created the first time a calibration is saved. Do not copy config/uvm2.cfg from another console: it describes that console's analog parts, not yours.
Debug Cart: games are launched from the Debug Cart's BIOS menu instead of the multicart's menu. The SD layout is the same.
Calibrate once
If text leans into diagonals, columns cascade to one side or glyphs fall apart while native cartridges look fine on the same console, the console needs calibrating. The image is not broken. Hold buttons 2 and 3 and launch any game with button 4: the calibration screen opens first. See Calibrating a console.
Troubleshooting
| Symptom | First thing to check |
|---|---|
Link fails mentioning nosys.specs | You are using Homebrew's toolchain. Install the official Arm GNU Toolchain. |
CMake stops with a fatal error about cargo | Rust is not installed, or not on the PATH. |
region RAM overflowed by N bytes | The image is over the ~496 KB SRAM ceiling. See Hardware. |
| Game starts, then says its romset is missing | The zip is not at roms/<game>.zip, or the game predates exFAT support. It prints the path it tried. |
| Solid red LED on the cartridge | A hardfault: bad pointer, stack overflow, unaligned access. See Your first game. |
| Black screen, nothing else | Console off or cartridge not seated, or the list is overflowing. See Debugging. |
Next: Your first game.