---
title: "viper"
url: https://manvsmidi.com/projects/viper/
category: music
status: wip
date: 2026-09-26
tags: [nes, chiptune, sequencer, terminal, rust]
related: [bdm-covers, picrossh, shellscape, rommage, society, pxl]
---

# viper

> A vim-keyed NES chiptune tracker for the terminal that compiles songs to real NSF files, plays them through an emulated 2A03, and can rip music back out of NSFs and cartridges.

Music · In progress · 2026-09-26

- [Source](https://github.com/sadovsky/viper)

A step sequencer for the five NES sound channels (two pulse, triangle, noise, DPCM) in a single Rust binary. You edit a tracker grid with vim motions, operators and text objects: `dd` deletes a row, `dip` deletes a phrase, `.` repeats, `q`/`@` record and replay macros. Insert mode turns the bottom keyboard row into a chromatic piano.

Songs save as plain-text `.vip` files that round-trip losslessly, so they can be diffed, grepped, or written by hand.

## Beyond the grid

- **Real NES output.** `viper compile` links a song against a 6502 sound driver and produces an NSF or NSFe. `:engine apu` plays the song through an emulated 2A03 instead of the built-in ADSR synth.
- **Verification.** `viper render` writes a deterministic mix, per-channel stems, trigger MIDI and a register-write log. `viper verify` diffs that log against another emulator; the bundled stress song matches FCEUX frame for frame.
- **Ripping.** `viper rip` reads music back out of an NSF, a register dump, or a cartridge it boots itself. It recovers the row grid by simulating the driver's row clock at candidate tempos, infers instruments from the envelopes, and reports which numbers were read and which were guessed.
- **Generators.** `:gen` covers Euclidean rhythms, chord progressions, basslines, arpeggios, L-systems and cellular automata, all deterministic per seed. `viper gen` composes a whole song from a style directory.
- **Visualizer.** Bars, scope, grid, orbit and sprite renderers in half-blocks. Sprite sheets can be loaded straight from a ROM's CHR data, and sprite properties bind to audio sources through a small expression language.
- **Live mode.** Play notes in real time, overdub, launch scenes on bar boundaries, mute channels.

## Running it

Needs Rust 1.80+ (and ALSA headers on Linux). It boots with a demo song loaded.

```sh
git clone https://github.com/sadovsky/viper.git
cd viper
cargo run --release
```

A working sound driver ships in `tests/fixtures/`, so the compile, render and verify commands work out of the box.

## Connected projects

- [What a Horrible Night to Have a Curse](https://manvsmidi.com/projects/bdm-covers/index.md): linked
- [picrossh](https://manvsmidi.com/projects/picrossh/index.md): linked
- [shellscape](https://manvsmidi.com/projects/shellscape/index.md): linked
- [rommage](https://manvsmidi.com/projects/rommage/index.md): linked
- [Society](https://manvsmidi.com/projects/society/index.md): shared tags: terminal
- [pxl](https://manvsmidi.com/projects/pxl/index.md): shared tags: terminal
