Every example and every project scaffolded by opensnes init has a short Makefile that sets a few variables and includes make/common.mk. This page lists every variable common.mk reads, its default, and what it changes. devtools/check_doc_drift.py fails when common.mk gains a ?= variable this page does not name.
Every variable can also be set on the command line for one build: make USE_FASTROM=1.
| Variable | Default | What it does |
|---|---|---|
| CSRC | main.c | C sources, compiled by cc65816 and linked in order |
| ASMSRC | (none) | Extra 65816 assembly sources (data sections, hand-written routines) |
| GFXSRC | (none) | PNG files converted by gfx4snes into .pic / .pal (+ a C header) at build time |
| SPRITE_SIZE | 8 | Tile size passed to gfx4snes -s for the GFXSRC files |
| LUNA | $(OPENSNES)/testing/bin/luna | The luna binary make test / make test-update run the project's test/*.toml with (scripts/install-luna.sh puts it there); a LUNA_BIN in the environment, the installer's own override, takes precedence |
| SPCSRC | (none) | SPC700 assembly (*.spc700.asm), assembled with wla-spc700 into a .spc700.bin your 65816 code .incbins |
| GSUSRC | (none) | Super FX assembly (*.sfx), assembled with wla-superfx into a .sfx.bin (needs USE_SUPERFX := 1) |
A .wav that an assembly file .incbins as its .brr is converted by wav2brr automatically (one-shot samples; run wav2brr --loop by hand for looping ones).
| Variable | Default | What it does |
|---|---|---|
| USE_LIB | 0 | 1 links the OpenSNES library |
| LIB_MODULES | console | The library modules to link. Each module's own dependencies are added for you; a name that matches no module is an error that lists the available ones. USE_SRAM, USE_SNESMOD, USE_SUPERFX and USE_DSP1 add their module |
| Variable | Default | What it does |
|---|---|---|
| USE_HIROM | 0 | 1 builds a HiROM cartridge (64 KB banks instead of 32 KB) |
| USE_FASTROM | 0 | 1 marks the ROM as FastROM and runs the code from the fast mirror (~33 % more ROM bandwidth) |
| ROM_BANKS | 8 | Number of linker banks: 256 KB LoROM, 512 KB HiROM by default. The header's ROM size byte and the asset bank range follow it |
| ASSET_TOML | *.toml and res/*.toml that name an opensnes-* tool | The assets' settings files the build converts before compiling (one opensnes-<tool> <subcommand> run per file, then assets_gen.asm gathers their .incbin fragments); see The opensnes-* tools: conventions |
| ROMSIZE | from ROM_BANKS | The header's ROM size byte ($FFD7, 1 KB << n, rounded up to a power of two). Leave it computed |
| ASSET_BANKS_RANGE | ROM_BANKS - 1 down to 1 | Banks the linker may use for ASSET_SECTION data and C const data, highest first. Leave it computed |
| ROM_REGION | ntsc | The region the header declares ($FFD9): ntsc = $01 USA, pal = $02 Europe, jp = $00 Japan. A console runs at its own standard whatever the byte says (isPAL() reads the console); emulators, luna included, choose 50 or 60 Hz from it |
| USE_SRAM | 0 | 1 declares battery-backed save RAM and links the sram module |
| SRAM_SIZE | 3 | Save RAM size as the header byte $FFD8: 1 KB << n, n = 1..7 (3 = 8 KB) |
| RAM_CODE_SIZE | 0 | Bytes (1 to 16384) of a code window at the top of WRAM bank $7E, for code that runs from RAM (RAM_CODE_SECTION): stored in the top of ROM bank 1, copied by crt0 at boot. 0 = no window. A Super FX build adds 768 bytes for the SDK's own interrupt entries, gsuLaunch wait loop and presentation step. The window shares ROM bank 1 with SNESMOD's default soundbank bank: a soundbank that fills bank 1 fails the link with "No room for section .ram_code" — move it with SOUNDBANK_BANK := 2. See the Super FX tutorial |
A cartridge carries one coprocessor: setting two of these is refused.
| Variable | Default | What it does |
|---|---|---|
| USE_SA1 | 0 | 1 builds an SA-1 cartridge (its own memory map; not with USE_HIROM). The header declares SA-1 + RAM ($34), or + battery ($35) with USE_SRAM := 1; the BW-RAM size comes from SA1_BWRAM_SIZE |
| SA1_BWRAM_SIZE | 5 | BW-RAM of an SA-1 cartridge as the header byte $FFD8: 1 KB << n (5 = 32 KB). It is the cartridge's work RAM whether or not the game saves; SRAM_SIZE does not apply to SA-1 |
| USE_SUPERFX | 0 | 1 builds a Super FX cartridge (LoROM-mapped; not with USE_HIROM). With USE_SRAM := 1 the header declares a battery ($15) and the save is the Game Pak RAM itself |
| GSU_BANK | (none) | ROM bank (1 to ROM_BANKS − 1) the Super FX program is linked in, at $8000: its labels become real addresses, so absolute jumps and tables in ROM work (GSU_SECTION in the loader, one .sfx in GSUSRC). Unset = assembled at 0, placed where it fits, position-independent code only |
| GSU_RAM_KB | 64 | Super FX Game Pak RAM declared in the extended header ($FFBD) |
| USE_DSP1 | 0 | 1 declares a DSP-1 cartridge and links the dsp1 module (LoROM board; not with USE_HIROM) |
| Variable | Default | What it does |
|---|---|---|
| USE_SNESMOD | 0 | 1 links the SNESMOD driver and converts SOUNDBANK_SRC with smconv |
| SOUNDBANK_SRC | (none) | Impulse Tracker .it files that make up the soundbank |
| SOUNDBANK_OUT | soundbank | Base name of the generated soundbank files |
| SOUNDBANK_BANK | 1 | ROM bank passed to smconv -b for the soundbank data |
A C object depends on every header of the library (lib/include/snes.h, lib/include/snes/*.h), on every header of the project (*.h, *.inc, res/*.h, res/*.inc, next to each C source), on the generated graphics headers, on the memory map and on .opensnes_config; and, through a stamp that holds a checksum of bin/cc65816, cproc-qbe and qbe, on the compiler itself. So a header edited anywhere rebuilds every C file of the project, and an SDK update rebuilds them too — coarse, and never stale. An assembled object depends on the files its .incbin lines name. The link runs again whenever an object did.
Every link runs checks that catch silent failures (a const table read through the wrong bank, RAM past $2000, the stack reaching the C variables). Their thresholds are variables; lowering one is a decision to write down, raising it is almost always wrong (.claude/rules/bank0_budget.md).
| Variable | Default | What it does |
|---|---|---|
| BANK0_FAIL_THRESHOLD | 0 | 0: never. Bank $00 holds code only, and code that does not fit goes to the next banks by itself (the link report says how much). A value fails the link when bank $00 has fewer free bytes: for a project that wants its code bank watched |
| RAM_FAIL_THRESHOLD | 512 | Fail the link when the plain C RAM band ($0000-$1FFF) has fewer free bytes than this |
| RAM_WARN_THRESHOLD | 1024 | Warn below this many free bytes in that band |
| LD_DISCARD | 1 | Link only the sections something refers to (wlalink -d): the library functions and RAM your program does not use are left out of the ROM. 0 links every section of every listed module, as before 2026-10-08 |
Each check has a bypass for debugging, never for a commit: SKIP_LINT=1 (the clang syntax pass over your C), SKIP_BANK0_CHECK=1, SKIP_RAM_CHECK=1, SKIP_BANKREAD_CHECK=1 (bank-blind reads of const data), SKIP_NMI_RACE_CHECK=1 (WRAM data port use in NMI code), SKIP_ASSET_BUDGET=1.