Modern, open-source SDK for Super Nintendo development
Write SNES games in C. Build on Linux, macOS, and Windows.
OpenSNES lets you write Super Nintendo games in standard C11 — no proprietary toolchain, no assembly required to get started. One make command builds the compiler, tools, library, and all 83 example ROMs.
This project builds on PVSnesLib by Alekmaul and its community. OpenSNES is a fork focused on a modern C11 compiler, comprehensive testing, and developer experience.
SNES development is hard. Not "takes a weekend to figure out" hard — fundamentally, structurally hard.
The SNES was designed in 1989 by hardware engineers, for assembly programmers, with no concessions to convenience. There is no operating system. There is no standard library. There is no debugger that pauses the world while you inspect variables. The CPU runs at 3.58 MHz, has 128 KB of RAM, and doesn't know what a float is.
You will need to understand how a PPU renders tiles scanline by scanline. You will need to know why writing to VRAM outside of VBlank silently fails. You will need to care about individual clock cycles, because on this hardware, every single one matters.
OpenSNES lets you write game logic in C. That's a real advantage — you get if/else, functions, structs, and all the abstraction C provides. The SDK handles initialization, DMA transfers, joypad reading, sprite management, and audio playback through a clean API. For many things, you'll never touch a register directly.
But C alone won't get you to a finished game.
The PPU has quirks that no C abstraction can fully hide. Performance-critical inner loops, custom HDMA effects, and advanced hardware tricks eventually require reading — and writing — 65816 assembly. The SDK handles audio through SNESMOD (music and sound effects from C, no assembly needed), and it handles sprites, backgrounds, and DMA through its library. But the moment you push past what the library provides, you're on the hardware's terms.
This is not a flaw in the SDK. It's the nature of the machine. OpenSNES will keep improving — better optimizations, more library functions, smoother workflows — but the gap between "my sprites move" and "my game ships" will always require understanding what happens beneath the C.
If that sounds exciting rather than terrifying, you're in the right place.
OpenSNES meets you at your level. The SDK does the hardware bookkeeping so you can start in C, and gets out of the way when you're ready to go deeper. There's a lane here whether you're curious, comfortable, or hardcore:
- New to the SNES but fluent in C? Start with
examples/text/print_stringand follow the learning path. You'll have a ROM running in minutes and meet the hardware one example at a time — no assembly required to get moving. Once you have a project of your own,docs/API_INDEX.mdindexes the SDK by what you are trying to do — scan it before writing a helper, several already exist. - Comfortable with retro hardware? The library covers sprites, backgrounds, DMA, HDMA, input, audio and Mode 7 through a clean C API, so your time goes into the game, not the boilerplate.
- Porting from PVSnesLib, or chasing cycles? Drop to 65816 assembly
whenever you want —
compiler/ABI.mddocuments the calling convention with worked examples, and the SDK never hides the hardware from you.
Two honest expectations before you start:
- The SNES doesn't hide its hardware, and neither do we. The language is the easy part; the machine is the hard part. You'll meet VRAM-only-in-VBlank, DMA budgets, and hex addresses — that's the nature of the target, not a flaw in the SDK. The difference here is that you can learn it incrementally, in C, with a worked example for each step.
- The SDK is late beta. The test suite is green and CI is enforced on three platforms, but several optimisations and chip APIs are still planned (see the roadmap). It's a great place to learn and build; pin a commit if you need a frozen toolchain for a hard deadline.
Read KNOWN_LIMITATIONS.md before you start. It
catalogs every silent failure we know about, with severity tags and
mitigations. Skim it once; refer back when something mysterious happens.
For ASM-writing contributors, compiler/ABI.md documents
the calling convention with worked examples (push order, frame layout, return
values) — required reading before porting any function from PVSnesLib.
| Mode / Chip | Status | Notes |
|---|---|---|
| LoROM | Stable | Default. Production-ready. |
| HiROM | Stable | Set USE_HIROM := 1 in your Makefile. |
| FastROM | Stable | Set USE_FASTROM := 1. Adds ~33 % CPU bandwidth. |
| SA-1 | Experimental | C wrapper is minimal; coprocessor code lives in a per-example sa1_boot.asm. SIWP register init is an assumption, not a published spec. |
| SuperFX | Experimental | GSU is assembly-only (no C compiler exists for the RISC ISA). Validated by luna, which detects and executes the GSU natively in the headless test harness. |
| C11 compiler for the 65816 | cproc + QBE with a custom backend (benchmark) |
| 30 hardware modules | PPU, sprites, backgrounds, DMA, HDMA, input, audio, Mode 7, collision, SRAM... |
| Asset pipeline | PNG to tiles, fonts, Impulse Tracker to SPC700 |
| 83 examples | From "Hello World" to Tetris with music — each with README and screenshot |
| Framework opt-ins | Game loop, scene stack, asset bundles — drop them in if they fit, ignore them otherwise |
| Debug emulator | luna (cycle-accurate native emulator) — corpus liveness + visual regression + functional probes; SA-1 / Super FX / DSP-1 run natively |
| Cross-platform | Linux, macOS, Windows — CI-enforced on all three |
OpenSNES is a 2D game engine for SNES, not a thin C-over-asm wrapper. Five principles guide every design decision:
- Sane defaults, escape hatches — the 90% case is a one-liner; the 10% case stays possible.
- Hide quirks, document the escape — hardware traps don't reach the user, but the explanation is one click away.
- Modules are opt-in, never all-or-nothing —
LIB_MODULESselects what links into your ROM. - Type-safe at the boundary — structs and enums beat positional
u16arguments. - Predictable performance — no hidden allocations, no lazy patterns, every frame-time cost is documented.
See PHILOSOPHY.md for the full statement and the explicit positioning vs. PVSnesLib (the two projects sit at different altitudes of the same stack and are complementary).
git clone --recursive https://github.com/k0b3n4irb/opensnes.git
cd opensnes
makeOpen examples/text/print_string/print_string.sfc in your favourite emulator (luna, Mesen2, bsnes…) and you're running on a Super Nintendo.
To start your own game, the build installs an opensnes CLI in bin/:
bin/opensnes init my-game --template game # scaffolds a working project
cd my-game && ../bin/opensnes run # builds and launches your emulatoropensnes doctor checks your toolchain, library, and emulator. For prerequisites
and platform-specific setup, see the Getting Started guide.
Prefer a ready-made git repo with CI? starter/ is a complete
movable-sprite game you can copy out or Use as a GitHub template — it wires
up the PNG→tiles asset pipeline and a build workflow out of the box.
83 examples organized as a progressive learning path — backgrounds, sprites, scrolling, HDMA effects, audio, input, save games, and complete games.
Browse all examples · Learning path
| Platform | Architecture | Status |
|---|---|---|
| Linux | x86_64, arm64 | |
| macOS | arm64 (Apple Silicon), x86_64 | |
| Windows | x86_64 (MSYS2) |
We stand on the shoulders of:
- PVSnesLib by Alekmaul — the foundation
- QBE by Quentin Carbonneaux — compiler backend
- cproc by Michael Forney — C frontend
- WLA-DX by Ville Helin — assembler
- SNESMOD by Mukunda Johnson — audio driver
See ATTRIBUTION.md for the full list of dependencies, licenses, and contributors.
Contributions welcome! See the Contributing Guide.
- Documentation
- Open issues
- Roadmap
- Changelog
- Known limitations — silent failures and trade-offs to read before starting
MIT License — See LICENSE