overdub
op1-overdub: new synth engines, FX with animated screens, and keyboard modes for the original OP-1 (firmware 246). They are patched into TE's own firmware: every stock engine, FX and feature keeps working. Like an overdub on tape, it adds new layers over TE's firmware without erasing anything underneath.
Not affiliated with or supported by teenage engineering. You flash this at your own risk (see Safety).
va | wavetable |
grain | ensemble |
pingpong | distortion |
Every knob drives part of the picture, in its own colour.
FX screens in motion
![]() | ![]() |
![]() | ![]() |
What's in it
Synth engines (in the engine list with their own presets and screens)
| engine | blue | green | white | orange |
|---|---|---|---|---|
| va: two-oscillator virtual analog with sub and noise (no filter: use the filter FX) | wave (sine → saw → square → pulse) | osc 2 detune | noise | sub (square, octave down) |
| wavetable: 8 banks of morphing wavetables, plus SAMPLE: a bank built from any sampler slot (green fully clockwise) | position | bank | warp | unison |
| grain: granular; plays a built-in bank, or the sample in any sampler slot | position | grain size | density | spray |
FX (on synth, drum and master; stereo as master FX)
| FX | blue | green | white | orange | screen |
|---|---|---|---|---|---|
| ensemble: BBD chorus, CE-2 style by default | rate | depth | character (CE solo → Juno-style dual → three-tap string ensemble) | mix | a choir |
| pingpong: ping-pong delay | time: free 20 ms … 1.28 s, then tempo-synced 1/32 … 1/2 (dotted, triplets) | feedback | tone | mix | table tennis |
| distortion: TUBE, MUFF, FUZZ, CLIP, FOLD, CRUSH | drive | voice (low-pass ↓, wah ↑) | character | mix | two pedals |
Keyboard
- HOLD: SHIFT + T2 on the synth screen latches released notes; again to release.
- CHORD: hold SHIFT and play a chord (up to 4 notes); then every key plays that shape. SHIFT + one key turns it off.
Install
- Download stock firmware 246 from TE: https://teenage.engineering/_software/op-1/op1_246.op1.
- Download
overdub-*.zipfrom Releases and unzip it. python3 apply.py op1_246.op1(Python 3.10+, no other dependencies) asks which features to install and writesOVERDUB.OP1. It checks that your file is stock 246 and that the result is exactly the expected image for your choice.- On the OP-1: hold COM while switching on, press 1 (upload firmware), connect USB, copy
OVERDUB.OP1to the OP-1 disk, eject. Same procedure as an official update.
Choosing features
Every engine, FX, HOLD and CHORD can be left out. In a terminal apply.py shows a checklist with everything on;
type numbers to toggle, Enter to install. Or choose with flags:
python3 apply.py --list # the features in this release
python3 apply.py op1_246.op1 --all # everything, no questions (also the default when not in a terminal)
python3 apply.py op1_246.op1 --without amp,crush # everything except these
python3 apply.py op1_246.op1 --only va,grain,hold # only these
A left-out engine or FX stays in the firmware with the same name and id but is not listed in the browsers (its engine/FX list entry, presets and kits are not installed), so a sound saved with it still loads. A left-out HOLD or CHORD is switched off: SHIFT+T2 and SHIFT+keys behave as on stock firmware.
The release contains only our code, our database rows (engine/FX names and presets) and our SVG screens. TE's firmware never leaves your computer.
Safety
- The bootloader is never touched.
te-boot.ldrstays byte-identical to stock (the tools refuse otherwise), so you can always go back: hold COM at power-on, upload stockop1_246.op1. - Before going back to stock, delete sounds saved with these engines or FX. Stock firmware doesn't know their names and stops at boot on such a sound. If that happens: COM at power-on, then factory reset.
- Never name a firmware file with
FRC,RBTorKEYin it: the OP-1's updater treats those as commands.apply.pyandbuild.pyrefuse such names.
Build from source
Needs Docker and Python 3.10+.
docker build -t op1-bfin tools/docker # ADI's bfin-elf GCC 4.3 toolchain (x86_64; runs under emulation on Apple silicon)
python3 build.py # everything; downloads stock 246 into firmware/stock/
python3 build.py --engines grain --fx distortion --no-hold --name MINE
python3 build.py --without crush --name MINE # the image with a feature left out (the zip keeps them all)
Outputs firmware/images/<NAME>.OP1 and the shareable dist/overdub-<version>.zip.
firmware/ holds TE's firmware and anything built from it: it is gitignored, never commit or share it.
DSP is checked in the Blackfin simulator first (src/engine/test/, src/slot/test/).
Screens render on the computer too: python3 src/slot/test/preview.py OUTDIR 15 k0 k1 k2 k3 ... (engine ids 15 va,
16 wavetable, 18 grain; 108–110 the FX as master). CLEAN=1 gives the README screenshots in docs/screens/.
How it works
Short version: the update file has a checksum but no signature, almost all of the app is unencrypted, and the boot ROM loads the app as a list of "copy these bytes here" blocks. We append blocks that put our code in RAM that TE's firmware doesn't use and repoint a few of TE's tables at it. Details, with what is confirmed and what is a hypothesis:
- notes/firmware-format.md, notes/memory-map.md: image format, boot chain, update rules
- notes/engine-interface.md, notes/engine-slot.md: adding synth engines
- notes/fx-slot.md: adding FX
- notes/screen.md, notes/svg-route.md: drawing screens, animated SVGs
- notes/hold.md, notes/seq-chord.md: keyboard hooks
- notes/LOG.md: every test image and its result
Everything is tied to firmware 246 (addresses change with any TE update).
Credits
- op1repacker (op1hacks): the hidden iter engine and filter FX, and the iter presets our presets start from.
- op1-decryptor (TabascoEye) and op1dumps (Tolsi): reading the encrypted part of the firmware for research. Nothing from them is needed to build or apply.
- ghidra-blackfin: Blackfin support for Ghidra.
MIT License (see LICENSE).









