fm1-sidj, image 1 from its README
1/2
Firmware

fm1-sidj

Loud94/100

SiDJ: SID player and live remixer firmware for the M-VAVE FM-1

fm1-sidj is custom firmware for the M-VAVE FM-1, by @thomasj. Open source under GPL-3.0, latest release v1.3.0 (November 2026), 3 stars on GitHub.

forM-VAVE FM-1·by@thomasj

Unclaimed. Is this yours? Sign in with GitHub as @thomasj to claim it.

Downloads
0
Stars
3
Forks
0
Commits
8
Last commit
Download v1.3.0

sidj-1.3.0.fwsc· 596 KB

GPL-3.0· thomasj/fm1-sidj·thomasj.github.io/fm1-sidj/·downloads come from the creator’s GitHub releases

8
Commits
8
Releases
8 commits and 8 releases in the last year
Activity · last 12 months

SiDJ

A C64 music deck for the M-VAVE FM-1.

SiDJ playing Commando, voice 1 an octave up

SiDJ is free firmware that turns the FM-1 into a player and live remixer for Commodore 64 music. It plays the tunes of the High Voltage SID Collection on a cycle-exact emulated C64, and every voice is yours to remix from the panel or a MIDI keyboard: transpose, mute and solo, swap waveforms, bend envelopes and the filter, add LFOs, ride the tempo and a vinyl fader. The remix builds on the one I made for the TherapSID.

The sound comes out three ways, alone or together:

  • The FM-1's audio jack, from an emulated 6581 or 8580 SID chip.
  • USB audio: the FM-1 is a driverless audio interface for your computer, with the mix or each voice on its own channel, ready to record.
  • Real SID hardware over ASID: a SidStation, TherapSID, TeensyROM, USBSID-Pico or any other ASID receiver, with the remix included.

And a MIDI clock in time with the tune, found from the tune itself, to sync a drum machine or sequencer.

▶ Watch SiDJ in action, a demo video on YouTube.

Get started

  1. Open https://thomasj.github.io/fm1-sidj/ in Chrome or Edge, connect the FM-1 by USB and press Install.
  2. On the same page, add songs: two of mine in one click, or search your copy of HVSC.
  3. Play. The browser emulator runs the same firmware if you want to try it first.

Installing custom firmware is at your own risk. The same page puts M-VAVE's official firmware back whenever you like.

User manual

SiDJ has two screens: SONGS, the list of tunes on the FM-1, and the PLAYER. SEQ switches between them. At power-on a short intro plays; any button skips it.

Below, A & B means: hold A, then press B. A voice button is HOME, SAVE or ARP, for voice 1, 2 or 3.

Songs

ControlFunction
SELECTmove through the list
OCT-eight songs up the list
OCT+eight songs down the list
PLAYplay the song and go to the player
PRESETSthe subsong
KNOB 1the chip: AUTO (the one the tune was written for), 6581 or 8580
KNOB 2the output: the emulated SID, ASID, both, or the emulated SID with a MIDI clock
KNOB 3USB audio: the mix, or the mix and the three voices
SAVEkeep these settings, and this song as the one selected at power-on

The list is grouped by composer, with each song's length from HVSC. The FM-1 holds a few dozen tunes at a time (240 KB). Add and remove them from the web page, or with tools/fm1_sid.py (below).

SiDJ plays PSID and RSID tunes for one SID, multi-speed tunes up to at least 38x included. Tunes for two or three SIDs, and BASIC tunes, are not played.

Player

The screen shows the song, its time and length, and the three voices, each with a scope, its note, waveform, envelope and pulse width; the filter is beneath them.

ControlFunction
PLAYplay / pause
REC & PLAYplay from the start
SELECTthe next / previous song
PRESETSthe subsong
ALGORITHMthe output: the emulated SID, ASID, both, or the emulated SID with a MIDI clock
MASTERthe level at the audio jack
SEQback to the song list

A song or subsong picked with SELECT or PRESETS stops the one playing and waits for PLAY. A song stops at its end and waits: SELECT for the next, PLAY to hear it again.

Remix

The remix changes what reaches the chip, never the tune itself. Whatever you change turns gold on screen, with REMIX in the top bar. OCT- and OCT+ pressed together put everything back. Loading a song starts clean.

Voices and keys

ControlFunction
HOMEselect voice 1
SAVEselect voice 2
ARPselect voice 3
The keysplay the selected voice: in set mode (the default) it holds the key's note while the key is down; in transpose mode the tune's melody moves by the key's distance from F#4
OCT-the keys an octave down, three at most; the screen shows their range
OCT+the keys an octave up, three at most
FX & OCT-the keys transpose
FX & OCT+the keys set the pitch
A MIDI keyboardplays like the keys, over USB or the MIDI IN jack: channels 1 to 3 play voices 1 to 3, any other channel the selected voice
RECmute / unmute the selected voice
voice button & RECsolo that voice; again for all three

Waveforms (the same button again gives the tune's waveform back)

ControlFunction
voice button & FXpulse
voice button & SELtriangle
voice button & ENVsawtooth
voice button & LFOnoise
voice button & EDITsync on / off
voice button & GLOring modulation on / off

Drums keep sounding like drums: a voice playing pure noise keeps its waveform and its pitch.

Filter

ControlFunction
SEL & HOMEvoice 1 through the filter or around it
SEL & SAVEvoice 2 through the filter or around it
SEL & ARPvoice 3 through the filter or around it
SEL & LFOlow-pass on / off
SEL & EDITband-pass on / off
SEL & GLOhigh-pass on / off
SEL & OCT+the cutoff knob scales the tune's cutoff (the default)
SEL & OCT-the cutoff knob adds to the tune's cutoff

Knob pages (press the page button, then turn KNOB 1 to KNOB 4)

PageKNOB 1KNOB 2KNOB 3KNOB 4
FX (OSC)pulse widthoctavefine tune
ENVattackdecaysustainrelease
SEL (FLT)cutoffresonance
LFOratedepthtarget: pulse width, pitch or cutoffshape
GLOtempo, 25 to 150 %vinyl fader, ±8 %SID+CLK: the clock's offsetSID+CLK: the clock's tempo put right, or set by hand

Each voice has its own LFO. The tempo speeds the tune up without changing its pitch; the vinyl fader moves both, like a turntable. A new song or subsong starts at 100 % with the fader at 0, as the rest of the remix starts clean. RSID tunes, which drive the whole C64 themselves, play as written: no tempo, fader or LFOs.

MIDI. A MIDI controller can play the whole remix too, with a CC for every control above. The map is in the addendum SiDJ over MIDI.

Outputs

The audio jack plays the emulated SID; MASTER sets its level.

USB audio. Connected to a computer, the FM-1 shows up as an audio input, SiDJ FM-1: 44.1 kHz, no driver needed on macOS, Windows, Linux or iOS. KNOB 3 in SONGS picks what it carries:

  • USB:MIX (the default): the mix, in stereo.
  • USB:5CH: the mix plus each voice on its own channel (3 to 5). The voices are stems, with the filter and volume in them, and add up to the mix. The tempo stops at 100 % in this mode.

USB audio comes at the chip's own level, whatever MASTER is set to.

ASID sends the tune to real SID hardware: a SidStation, TherapSID, TeensyROM, USBSID-Pico or any other ASID receiver. The remix plays on the real chip too, and with BOTH the FM-1 plays along. The FM-1 is a USB device, so the receiver connects through a USB-MIDI host box or a computer. ASID sends one update per frame, so sampled sounds (drums, speech) only sound right on the emulation, and RSID tunes are never sent: they play on the emulated SID.

SID+CLK plays the emulated SID and sends a MIDI clock over USB, its beat found in the tune itself. On the GLO page, KNOB 4 puts a wrong tempo right (or sets one when none is found) and KNOB 3 moves the clock; GLO & PLAY clicks on the beats. A clock coming in over USB or the MIDI IN jack starts, stops and continues the song, and with SID+CLK the tune follows it. More in SiDJ over MIDI.

Installing

The web page, https://thomasj.github.io/fm1-sidj/, installs SiDJ and puts the official firmware back (with the FM-1.fwsc you download from M-VAVE). From the command line:

.venv/bin/python3 tools/fm1_install.py --info            # what the FM-1 runs
.venv/bin/python3 tools/fm1_install.py build/sidj.fwsc   # install a package

Both work from M-VAVE's firmware (V15 or V16), Felucca, X0X and SiDJ itself. SiDJ runs at full speed whichever official firmware the FM-1 had before: M-VAVE's V16 leaves the chip at 320 MHz instead of V15's 360, and SiDJ sets 360 back up as it starts. If something goes wrong: two failed starts give a safe mode (PLAY tries again), four give the chip's own update mode, and holding OCT- and OCT+ together for 5 seconds gets there too. From the chip's update mode, tools/fm1_rescue.sh puts the official firmware back, and Leo Kuroshita's FM-1 Transporter is the last resort.

Other firmwares' data. SiDJ keeps its songs in the flash area where Felucca and the firmwares built on it keep their user samples (0xA0000 to 0xDBFFF). Adding songs erases what another firmware saved there, and other firmwares cannot read SiDJ's songs. SiDJ ignores anything in the area that is not a SiDJ song. Back up your samples and projects before you install SiDJ. Going the other way, save a setlist on the web page (step 2) before you install another firmware: it keeps every song, its order and song lengths in one .zip, and Load setlist puts them back. The page also keeps a copy in the browser and offers it back when it finds the FM-1 empty.

Songs from the command line

tools/fm1_sid.py manages the songs over USB, with song lengths from your HVSC copy (~/Music/C64Music, or --hvsc DIR):

.venv/bin/python3 tools/fm1_sid.py list
.venv/bin/python3 tools/fm1_sid.py put ~/Music/C64Music/MUSICIANS/H/Hubbard_Rob/Commando.sid
.venv/bin/python3 tools/fm1_sid.py put ~/Music/C64Music/MUSICIANS/G/Galway_Martin/    # a whole folder
.venv/bin/python3 tools/fm1_sid.py play 3 2                                            # song 3, subsong 2
.venv/bin/python3 tools/fm1_sid.py delete 3
.venv/bin/python3 tools/fm1_sid.py compact      # reclaim the space deleted songs leave
.venv/bin/python3 tools/fm1_sid.py stats 10     # the audio load, once a second

For developers

Building

Everything builds on a Mac. The host side (tests, simulator, players) needs only Xcode's command-line tools (xcode-select --install) and Python 3. Optional, from Homebrew: brew install emscripten node to build and test the browser emulator and the web page, and brew install gh for releases. Docker Desktop can come from there too (brew install --cask docker). The firmware needs:

  • Docker Desktop, running (the JieLi toolchain is Linux x86-64 only)
  • the toolchain: tools/get_toolchain.sh installs it to ~/.jieli/toolchain
  • the JieLi AC79 SDK (Apache-2.0; three of its files go into every package): git clone --depth 1 --branch AC79NN_SDK_V1.2.1_2023-12-13 https://gitee.com/Jieli-Tech/fw-AC79_AIoT_SDK.git ~/fw-AC79_AIoT_SDK
  • Python packages: python3 -m venv .venv && .venv/bin/pip install -r requirements.txt (Pillow 11 to 13 tested; its raqm, for the screen's tabular digits, needs brew install fribidi, without which the build warns and draws proportional digits)
./build.sh                  # build/sidj.fwsc, a development build
./build.sh --release 1.0.0  # build/sidj-1.0.0.fwsc, a release
tests/run_tests.sh          # all tests: SID, 6510, the C64, the remix, storage, the app in the simulator
make test                   # the SID engine against the original reSID 0.16, sample by sample
make sidplay                # build/host/sidplay FILE.sid: a tune through the same C64 and SID, to WAV
web/emu/build.sh            # the browser emulator (needs Emscripten)

JIELI_TOOLCHAIN and AC79_SDK override the default locations; SIDJ_TRS=0 turns the MIDI IN jack off, SIDJ_CDC=1 adds a USB serial console.

tools/make_site.py build/sidj-1.0.0.fwsc builds the web site around a package, in build/site. The browser emulator also takes a song from another page: opened as emu/#import, it tells the page that opened it that it is ready, takes one .sid from it, adds it to its songs and plays it when switched on. SID Factory II Pocket's page uses it to open a song composed on the FM-1 in SiDJ, ready to play and remix. tools/release.sh X.Y.Z makes a public release: the package, the tests, one commit on the public repository, the GitHub release and the site.

How it works

The design and its reasoning are in docs/design.md. In short:

  • The C64 (firmware/src/c64/) runs the tune cycle by cycle: a 6510 with IRQ and NMI, both CIAs, the VIC's raster and bad lines, and a small KERNAL replacement. Every SID write is logged with its cycle.
  • The SID (sid/) is a fixed-point port of reSID 0.16, bit-exact with the original. On the FM-1 the pulse, sawtooth and combined waveforms are averaged over each sample against aliasing, and the 8580's floating waveform DAC plays the samples some tunes make with the test bit.
  • The engine (firmware/src/app/engine.c) runs in the audio interrupt: each write goes through the remix and reaches the chip at its exact cycle.
  • The remix (firmware/src/app/remix.c) keeps the tune's register image and the chip's, and derives one from the other.
  • ASID (firmware/src/app/asid.c) sends each frame's changes as one message, cut exactly at the raster wrap.
  • The MIDI clock (firmware/src/app/beat.c, engine.c) finds the tune's beat from when its voices start to sound, schedules the pulses at their cycles, and follows a clock coming in by steering the tune's speed; clkstore.c keeps each song's clock.

Verification

The C64 was checked against libsidplayfp's own C64 on random HVSC tunes: the SID register writes match at a median of 99.99 % for PSID tunes and 99.92 % for RSID tunes. The audio load was measured on the FM-1 with the heaviest tunes found, and SiDJ's limits keep the worst case inside the budget: one SID, the tempo up to 150 %, and no tempo, fader or LFOs for RSID tunes. Why reSID 0.16: docs/engine-choice.md.

Layout

PathWhat
sid/the SID engine
firmware/src/c64/the 6510, the SID file format, the C64 and its driver
firmware/src/app/the engine, the remix, the UI, the song store, ASID, the beat and kept clocks, settings, the boot and main loop
firmware/src/, firmware/hal/, firmware/loader/the platform, the hardware layer and the update loader, from Felucca by way of X0X
host/the simulator and the WAV player
web/site/, web/emu/the web page (installer, song manager) and the browser emulator
tests/the host tests and the simulator's scenarios
tools/build, package, install, songs, site, release
docs/MIDI control (docs/midi.md), the design, the FM-1 platform (docs/platform.md), the engine choice
third_party/reSID 0.16 unmodified, the 6502 functional test, licence texts

Licence

SiDJ is free software: GPL-3.0-only for the firmware, GPL-2.0-or-later for the SID engine. It is built on Felucca by Leo Kuroshita (the platform, the update loader and the installer), by way of X0X by charlesvestal, and the SID engine is a port of reSID 0.16 by Dag Lem. File-by-file origins and the licence reasoning are in LICENSING.md. It contains no vendor material, no Commodore ROMs and nothing from my employer. M-VAVE and FM-1 are trademarks of their owners; SiDJ is independent of them.

Author

I'm Thomas Jansson (github.com/thomasj), and I make chiptune and synth music as tubesockor: YouTube, TikTok, Instagram, Facebook, X and tubesockor.com. Bug reports and ideas are welcome as GitHub issues.

SiDJ is developed with the help of AI coding tools: I direct the work, review it and test it on the FM-1.