Help build it
Contribute to elekloader!
elekloader is a passion project, and it grows from what people bring to it. Pull requests
are welcome and encouraged, and you don't need to ask first. Help the community grow and earn a spot on the
leaderboard: claim an entry from the to-do list, and your name goes on the board, the pull request and the
release notes of the version that takes it.
- Take an entry from the to-do list below. Each is stock code a mod still hooks for
itself. As a core event, any number of mods can use it, and none of them needs its own port for the next
OS. What is a core mod? Your first pull request
- Write a mod on the core and offer it to the shop.
Get started developing
- Add a device or an OS version, fix a step that didn't work, or make a page clearer.
Contributing
Leaderboard
Claim an entry from the list below: put a line Claims: <entry id> in your pull
request's description (several ids are fine). When it is merged, each entry it names is a point on this board.
The first merged claim on an entry takes it.
How claiming works
The to-do list
One entry per stock routine that mods hook themselves. A core event:
the core has nothing there yet. Move onto the core: the core or a companion already hooks
the same bytes, so those mods can use it (that pull request goes to the mod's author, and its shop update
here is where you claim it). Open your pull request as a draft early, with its Claims: line, so
others see the entry is taken.
More in the docs
Contribute
Get started developing
From nothing to your first mod built, linked and checked: about half an hour, most of it
installing a compiler.
What you need
- Python 3.9 or newer and git. elekloader itself has no other dependencies.
- The stock OS file for your device, from Elektron's support pages: the same file this page
asks for. elekloader recognises each release by its hash.
- The cross compiler, for a mod with code. On the Digitakt mk1 and the Digitone mk1 that is m68k
binutils and gcc: on Debian or Ubuntu
apt install binutils-m68k-linux-gnu gcc-m68k-linux-gnu; on
Windows, the same inside WSL; on a Mac, with Homebrew, brew install m68k-elf-binutils m68k-elf-gcc,
then export ELEKLOADER_CROSS=m68k-elf- (Homebrew's tools have that prefix). A mod that only
changes a byte or two needs none.
- Optional: digiemu,
to run and check your build without a unit (Test before you flash).
Your first mod
- Get the code and check it runs:
git clone https://github.com/irpina/elekloader
cd elekloader
python tests/test_units.py
- Copy the template, a complete mod that draws a small square in the corner of every screen. For the
Digitakt II start from
examples/hello-marker-dt2, for the Digitone II hello-marker-dn2,
for the Octatrack hello-marker-ot,
for the Models hello-marker-model:
cp -r examples/hello-marker my-mod
- Give it your own
id in my-mod/mod.json (lowercase; it also prefixes your global
symbols), then build it and the core for your device:
python -m elekloader.sdk.build my-mod --stock Digitakt_OS1.53.syx
python -m elekloader.sdk.build mods/core --stock Digitakt_OS1.53.syx
Each prints BUILT and the .elemod it wrote (in the folder's out/).
- Check it the way every build is checked, then make a firmware file from it:
python -m elekloader.lint my-mod/out/my-mod-1.0.elemod --stock Digitakt_OS1.53.syx --with mods/core/out/core-4.0.elemod
python -m elekloader.patch --stock Digitakt_OS1.53.syx --mod mods/core/out/core-4.0.elemod --mod my-mod/out/my-mod-1.0.elemod --out test.syx --version TEST
The file names are the ones the build printed. Or skip the command line: drop your .elemod on
this page's Build view with your stock file.
The rules in short
- Subscribe, don't patch. If the core has an event for what you need, use it. If it
doesn't and another mod could want the same thing, that's a core event to add: What is a core mod?
- Ship no firmware. Call firmware routines by address; never copy Elektron's code into your sources.
- One namespace. Prefix your global symbols with your mod's id, and keep the rest
static.
- Only the main OS changes, so the stock OS file always gets a unit back.
The whole guide, with every command's expected output and every refusal message with its fix:
Adapting your mod.
Working with a coding agent? Point it at
AGENTS.md:
it has the rules, the commands and what "done" means.
Next: What is a core mod?
Contribute
What is a core mod?
The one mod every build has, and the reason mods from different people combine.
Without it
A mod changes the stock firmware at the places it needs: it replaces an instruction with a jump to its own
code. Two mods that need the same place can't both have it, so they can't be in one build, and every mod has
to find all its places again for each new OS version.
With it
The core owns the shared places once, for every mod, and offers them as:
- Events a mod subscribes to: the UI tick, the screen, keys and encoders, SETTINGS, the
audio render, MIDI, and more on each device. A handler can also take what it sees (a key, a CC) so
the stock firmware doesn't.
- Tables other mods add entries to: the Digitakt's SRC machines, the Digitone's Mod Menu.
- Firmware exports: named firmware routines and variables (
fw_…), so a mod that uses
only those builds for every OS version the core supports without a port of its own.
It also copies every mod's code into RAM when the unit boots, and gives the mods their share of it. Every
linkable mod needs exactly one core for its device, and builds pick it for you.
Companions
A group of places only one kind of mod uses has a companion beside the core: machine-pages
draws the Digitakt's SRC and LFO pages for machine mods, machines plays a machine mod's voice
on the Digitone, seq-events turns the sequencer's steps into events, and on the Octatrack
intercepts gives places a mod intercepts (MIDI notes, the CHROMATIC keyboard, locks, the
project file) to the one mod that claims each. The to-do list counts them as core.
Versions
Each core keeps everything the one before it had, so a mod built for an older core links with the newest,
and a build takes the newest: core 4.x on the Digitakt mk1, core-dn1 4.x on the Digitone mk1, core-ot 0.3.x on
the Octatrack. The Digitakt II, the Digitone II (experimental), the Analog Rytm MKII, the Analog Four MKII and the Models have early cores (the tick, the screen,
keys and encoders) with a lot left to add.
Growing it
Every event the core has came from a mod that needed it. When yours needs something the core lacks, build
that part in the core's shape, in a file of its own, and open a pull request that moves it into the core:
Growing the core
says how. The to-do list is every place a mod still patches itself: each one a core
event waiting to be written.
Next: Your first pull request
Contribute
Your first pull request
Taking an entry from the to-do list to the leaderboard. You don't need to ask first, and a
draft that says what it couldn't finish is a fine start.
- Pick an entry from the to-do list. A core event means the
core has nothing there yet; move onto the core means a mod can use what the core already has (that
change goes to the mod's own repository, and its shop update here is where you claim it).
- Open a draft pull request early, on irpina/elekloader,
with a plain line in its description naming the entry:
Claims: digitakt-mk1@1.53:0x400d553e
Others then see it's taken. Several ids on one line are fine.
- Build it in the core's shape: a file of its own in the core's folder, the core's names
(
ev_…, core_…, fw_…), the handler written down over the code, the unit
behaving exactly as stock when no mod subscribes, and the address on every OS version the core supports.
Growing the core
has the checklist.
- Show it works: say in the pull request which tests ran (
python tests/test_units.py
always; the others need stock files), what you checked in digiemu or on a
unit, and, best of all, a mod rebuilt on your event without its own patch.
- Mark it ready. A maintainer reviews and merges it, and the next build of this page puts
you on the leaderboard, one point for each entry you claimed. The first merged
claim on an entry takes it.
A Claims: line inside a code block, a comment or a quote is an example and claims nothing. More in
Claiming an entry.
Next: Test before you flash
Contribute
Test before you flash
You can build, run and check most of it without a unit, and a unit always comes back.
Every build is checked
Before it writes a file, elekloader refuses any build that would change the bootloader, put two mods on the
same bytes, or run out of the mods' RAM. python -m elekloader.lint runs the same checks on your
mod alone, with the reason for each refusal.
In an emulator
digiemu runs the real firmware
of the Digitakt mk1, the Digitone mk1, the Model:Cycles and the Model:Samples on Windows and on Apple silicon
Macs, with a clickable front panel and live audio. You bring Elektron's file, as here.
- Check firmware… takes your build's
.syx and compares it with stock: it boots it,
drives it through the screens and the sequencer, and ends with PASS or FAIL and the reasons.
- Add your build as a firmware of its own to play it from the panel, or from a script with
digiemu-console.exe --add FILE.syx.
digiemu does not support the Octatrack, the Digitakt II, the Digitone II, the Analog Rytm MKII or the Analog Four MKII: there, test on a unit.
On a unit
Send your .syx with Elektron Transfer like any OS update
(how to flash).
The bootloader is never changed, so the stock OS file always gets the unit back: on a Digitakt mk1, Digitakt II,
Digitone mk1 or Digitone II, hold FUNC while powering on and press TRIG 4 for OS UPGRADE,
then send the stock file (on the Digitakt II and Digitone II, over MIDI DIN, not USB);
on an Octatrack, hold FUNC and press TRIG 3, and send
it over 5-pin MIDI (recovery).
Back to the to-do list and the leaderboard