Your game is written in C, but the SNES does not eat PNGs, Tiled maps, or WAV files — it eats tiles, tilemaps, BGR555 palettes, BRR samples, and SPC700 soundbanks. The OpenSNES tools are the converters that bridge the two: each takes an artist- or musician-friendly source format and emits the exact binary the hardware (and this SDK's runtime) expects.
You rarely run most of them by hand — the build system wires the common ones in, so dropping a .png or .wav in an example's res/ is usually enough. But knowing what each tool does, and which knobs it exposes, is what takes you from "the example builds" to "I shaped my own assets on purpose." That confidence is what this section is here to give.
Most assets flow through a short, one-way pipeline from source art to ROM data:
Each tool does exactly one conversion; the Makefile chains them. It is the Unix-pipe idea applied to asset building — small, composable, individually testable steps rather than one opaque converter.
| Tool | Turns… | …into | In your build |
|---|---|---|---|
| gfx4snes — images to tiles, palettes & maps | an indexed PNG/BMP | tiles + palette + tilemap | auto (drop a PNG in GFXSRC) |
| tmx2snes — Tiled levels to SNES map data | a Tiled JSON map | tilemap + collision + objects | one line per example |
| img2snes — RGB artwork to indexed palettes | RGB/RGBA artwork | a palette-indexed PNG (feeds gfx4snes) | manual pre-step |
| font2snes — font images to text tiles | a 96-glyph font PNG | 2bpp/4bpp text tiles | manual, optional |
| wav2brr — WAV to BRR sound samples | a PCM .wav | a .brr sound sample | auto (drop a WAV in res/) |
| smconv — tracker modules to SNESMOD soundbanks | an Impulse Tracker .it | a SNESMOD soundbank | auto (USE_SNESMOD) |
| palplan — project shared-palette planner | a manifest of .pal files | a CGRAM layout + C header | manual, project-level |
| aseprite2snes — Aseprite animations → AnimClip tables | an Aseprite animation export | AnimClip tables (one per tag) | one line per sprite |
The tools sit at three levels of automation — worth knowing so you reach for the right one:
All binaries live in bin/ and are built by make tools. Every tool prints --help; the pages here are the guided version.
The opensnes-* family replaces these converters — one tool per function, the same conventions everywhere, settings beside each asset. The opensnes-* tools: conventions is the contract; the earlier tools stay one more release. The first two are opensnes-sample — WAV to BRR samples (WAV → BRR) and opensnes-music — Impulse Tracker to soundbank (Impulse Tracker → soundbank); opensnes-rom — is the ROM good? runs the post-link checks of every build; opensnes-sprite — sheets, metasprites and Aseprite clips is the sprite artist's tool (sheets, metasprites, Aseprite clips); opensnes-level — Tiled levels to SNES map data turns a Tiled level into map, tile tables and entities; opensnes-tileset — pictures to tilesets and tilemaps the background artist's (tilesets, tilemaps, palette banks); opensnes-text — bitmap fonts for the text module converts a typeface; opensnes-palette — a project's palettes plans a project's palettes into CGRAM and quantizes RGB art; opensnes-image — full-screen pictures and their tables makes HiColor screens and the Mode 7 perspective tables; opensnes-save — battery save files creates, reads and patches battery save files; and opensnes — the project tool is the project's own command (init, build, run, test, doctor).
The build itself has knobs — cartridge mapping, save RAM, coprocessor, ROM size, the link-time checks. Your project's Makefile lists every one with its default.
Testing is not a converter, but it is the other tool you will run every day. luna is the cycle-accurate emulator behind make tests, luna mcp is the debugger, and luna — command reference (pinned v1.38.0) is the pinned release's own --help, one section per subcommand — generated from the binary, so it cannot drift from testing/luna.version.
The one rule. Keep the source (the PNG, the Tiled project, the WAV, the .it) as your single source of truth and let the tools regenerate the binary on every build. The moment you hand-edit a .pic or a .brr, it drifts from its source and you have lost the pipeline's whole benefit.