heartbeat-demo is a demo for the Ultimate 64, built around a song composed in the Heartbeat Soundtracker. The core of the project is not the demo itself but what sits underneath it: a full C port of Heartbeat Soundtracker's standalone player, taken from licensed 6502 assembly source down to a single raw interrupt trampoline. The port went through one release, then a second after the tracker's own author reviewed the code and found a genuine bug in it.
Heartbeat Soundtracker and the Ultimate 64
The Ultimate 64 (U64) is an FPGA-based reimplementation of the C64 mainboard by Gideon Zweijtzer, extending the original machine with a 16 MB REU, CPU turbo modes up to 64 MHz, and Ultimate Audio -- 7 channels of DMA-driven sample playback that sit alongside the machine's own SID chip (or chips; the U64 can address up to 8).
Heartbeat Soundtracker, by Aleksi Eeben / Eight Bit Shed, is a music tracker written specifically for that combination. Where a conventional SID tune uses one to three SID voices, a Heartbeat song can drive every SID channel the hardware exposes plus all 7 Ultimate Audio channels at once, with its own modulation set (portamento, vibrato, PWM, filter sweeps) and pattern-command language. A Gold license for the tracker includes the standalone player's assembly source -- the code responsible for actually running a finished song outside the editor -- with the author's explicit permission to redistribute it and to publish a derived library.
Porting the Player to C
The player source is close to 3100 lines of 6502 assembly: pattern fetch from REU, SID and Ultimate Audio register writes, the modulation engine, track-command handling. The port kept every routine in C, including the per-tick hot paths -- register updates, SID writes, frequency table lookups. Profiling never showed a case where hand-written assembly was needed; running at turbo speed leaves enough cycle budget per tick that a fairly literal C translation keeps up.
Only two things stayed as raw assembly. One is a pair of short inline reads used to detect PAL versus NTSC timing from raster behaviour. The other is hb_irq itself -- the actual interrupt entry point, which by nature has to be assembly, since it is where the CPU's own interrupt hardware hands off, before there is a C calling convention to speak of.
That IRQ trampoline turned out to be the one place where getting the C port "close enough" was not actually close enough.
A Bug Report From the Author
The reference player uses two different interrupt sources: a CIA timer that fires at the song's tempo (the tick, driving playback), and a fixed raster interrupt (driving keyboard scanning independently of tempo). Each needs to hand off to the C64's own KERNAL interrupt tail afterwards, but the reference player only does that in full for the raster branch -- the tick branch exits directly, skipping keyboard scanning and the jiffy clock update entirely, since nothing about song playback needs either.
The first working version of heartbeat-demo did not preserve that distinction. An earlier, unrelated crash had been worked around by sending both branches through the same full KERNAL exit. It solved that crash, and the song played back correctly on hardware, so the release shipped.
After the release, Aleksi Eeben -- the tracker's own author -- read through the ported player and raised a specific concern: sending the tick branch through the full KERNAL interrupt tail would run keyboard scanning and jiffy-clock housekeeping at the tick rate rather than never, and asked whether that couldn't cause the keyboard to feel wrong.
It was a correct read of the code, and comparing directly against the reference player confirmed why: at a typical tick rate, the tick branch was running that housekeeping roughly four times as often as the raster branch alone should have. The only externally visible symptom was key repeat firing noticeably faster than normal -- easy to miss during hardware testing, since nothing about audio playback was affected. The fix restores the CPU registers in the exact order the hardware's own interrupt entry pushed them and returns directly, bypassing the KERNAL tail on the tick branch entirely, while leaving the raster branch's full KERNAL exit untouched. Confirmed on hardware afterwards: key repeat behaves normally again.
The episode is a reminder that a working demo on real hardware is not the same thing as a correct one -- audio played, patterns advanced, nothing crashed, and a genuine timing bug still sat underneath all of it, waiting for someone who knew the reference implementation to notice what "extra KERNAL work at the wrong rate" actually looks like from the outside.
A Note Visualiser
Beyond the player port, the demo itself adds a two-column VU-meter visualiser reacting live to the player's own note-event stream: one bar per active channel, up to 31 in total across 8 possible SID chips and the 7 Ultimate Audio channels, each jumping to peak brightness on a note-on and decaying afterwards. A plasma background animates behind the bars, a small pitch-histogram band reacts to whatever notes are currently sounding, and an 8-sprite scrolltext sweeps across the screen -- all driven from the same event queue the VU meters use, with no separate audio analysis involved.
A buttons.s-equivalent test harness runs alongside the visualiser: restart the song, switch between the two bundled tracks, silence playback, or trigger sample effects by hand -- useful both for demonstration and for exercising the player library directly.
Firmware Configuration
Getting Ultimate Audio, SID addressing, filter curves and turbo mode all set correctly by hand is easy to get subtly wrong, and Heartbeat Soundtracker's own bundled settings file does not load cleanly on every U64 firmware revision -- one setting name it expects is not accepted on a U64 Elite II. The project ships two ready-made configuration presets, one matching the tracker's own original file and one adjusted for the Elite II (confirmed against a live device), so getting a machine into the right state is a single "Load Settings from File" step rather than a manual checklist.
Credits
- Code: Xander Mol
- Demo framework: scaffolded from UltimateDemo2026
- Heartbeat Soundtracker player: (c) Aleksi Eeben / Eight Bit Shed, used and redistributed with permission
- UCI/DOS library: Scott Hutter and Francesco Sblendorio
- Compiler: Oscar64 by drmortalwombat
- Sprite scroller font: "Sprite Font" by hedning, from the demo World in Progress (1st place, Mixed category, Syntax Society Summerparty 2012)
- Ultimate 64 hardware: designed by Gideon Zweijtzer / Gideon's Logic
Licensed under the GNU General Public License v3.0 (player and demo code; song files and third-party assets carry their own terms).
Sources and More Information
heartbeat-demo repository -- source code, both firmware config presets, and all documentation manuals: github.com/xahmol/heartbeat-demo
Heartbeat Soundtracker -- the tracker this player was ported from, including the evaluation download: sites.google.com/view/heartbeatsoundtracker
Oscar64 compiler -- C99/C++ cross-compiler for 6502, by drmortalwombat: github.com/drmortalwombat/oscar64
UltimateDemo2026 -- the sibling project this demo's framework was scaffolded from: github.com/xahmol/UltimateDemo2026
"Sprite Font" by hedning -- the sprite font used for the visualiser's scrolltext, from the demo World in Progress (Summerparty 2012): c64gfx.com/image/9998103
Ultimate 64 hardware -- product page for the FPGA-based C64 mainboard this project targets: ultimate64.com