c64cast turns a real Commodore 64 — driven over the network through an
Ultimate 64 or
TeensyROM+ — into a programmable
display and audio device. It runs a playlist of scenes on the real
hardware: play videos and images, stream a live webcam, visualize SID music
on a 3-voice oscilloscope, synthesize a MIDI keyboard or an ASID stream
through the real SID chip, render reactive generative visuals, or hand the
machine over to a native game or demo. Frames from any source are quantized
in real time to a VIC-II display mode (PETSCII, MCM, hi-res bitmap, multicolor
hi-res); audio plays through the SID's $D418 DAC or the hi-fi Ultimate Audio
PCM sampler. Stackable overlays decorate any scene with scrolling text,
spectrum analyzers, clocks, weather, RSS, logos, and more; a performance
layer puts the whole show on a MIDI controller or a phone; and ensemble
mode drives a wall of C64s at once.
The full documentation lives at https://kfox.github.io/c64cast/ — three books (User's Guide, Programmer's Reference Guide, Performance Card) plus the caveats and troubleshooting notes, rebuilt from this repository on every push.
uv tool install 'c64cast[all]' # or: pipx install 'c64cast[all]'
c64cast --config example:hello -u u64://192.168.2.64That puts a c64cast command on your PATH. To try it without installing
anything permanently:
uvx --from 'c64cast[all]' c64cast clip.mp4 -u u64://192.168.2.64[all] pulls in every optional feature — video files and YouTube URLs, mic
capture, MIDI, webcam gestures, the WLED bridge, the HTTP control plane, the
browser console (the web extra), the config wizard. Plain
uv tool install c64cast gets a much smaller core install (no mediapipe, no
yt-dlp) that still covers every generative scene, PETSCII/bitmap rendering, SID
playback, and overlays; add extras à la carte later
(uv tool install 'c64cast[video,midi,web]'). Extras don't accumulate, so name
every one you want in a single command.
Later, c64cast --upgrade is the upgrade — it works out whether you're on
uv tool, pipx, or plain pip and runs that installer's own command, so you
never have to remember which. c64cast --check-for-updates just asks. See
Upgrading.
You need a reachable Ultimate 64 or TeensyROM+ — there is no emulator path for the streaming side. An Ultimate ships with the three firmware services c64cast needs switched off; Hardware needed lists the switches, and it is worth following Quick Start through the menus the first time — miss one and c64cast connects and then hangs rather than printing anything useful.
Every row below is a runnable demo that ships inside the package — pass it to
--config and it loops forever until you Ctrl+C. Point it at your hardware
with -u (see Quick start). The
Programmer's Reference Guide
documents every option for these scenes and overlays.
| I want to… | Try | Reference |
|---|---|---|
| Play a video (or YouTube URL) | c64cast clip.mp4 · example:scene-video |
Quick playback |
| Play an audio track with visuals that react to it | c64cast tune.mp3 |
Quick playback |
| Show a live webcam as C64 art | example:scene-webcam-petscii |
webcam |
| Visualize a SID tune (oscilloscope) | example:scene-waveform |
waveform |
| Play a SID from a MIDI keyboard | example:scene-midi |
midi |
| Stream from DeepSID / SIDFactory II | example:scene-asid |
asid |
| Slideshow of images | example:scene-slideshow |
slideshow |
| Generative / music-reactive visuals | example:scene-generative-plasma |
generative |
| Stack pixel effects on any scene | example:effect-chain |
Generators + effects |
| Play the show live from a controller or a phone | example:performance-clips |
Performing |
Run a native .prg/.crt game or demo |
example:scene-launcher |
launcher |
| An info board (clock/weather/RSS) | example:overlay-clock |
Overlays |
| Drive multiple C64s as one video wall | example:ensemble/master |
Ensemble mode |
| Make the C64 a WLED LED matrix | example:scene-wled |
wled |
| Control c64cast from the WLED app | example:wled-control |
WLED bridge |
Run any of them with c64cast --config example:<name>, or list the whole set
with c64cast --list-examples (one demo per scene type and per overlay).
- Scenes — video files and YouTube/other URLs (soundtrack and all, A/V
locked to the audio clock), live webcam, slideshows, a
.sidplaying natively on the real chip under a per-voice oscilloscope (multi-SID too), live MIDI → SID and ASID streams, 20 procedural generative sources (optionally music-reactive), native.prg/.crthand-off, a virtual WLED matrix fed live pixels by LedFx/xLights, and a blank canvas for title cards. - Display + audio — six VIC-II display modes, each with its own vectorized
quantizer (≈30 fps bitmap, 50/60 fps char over a LAN); audio through the
SID's lo-fi
$D418DAC (4-bit, or ≈6-7-bit via the Mahoney companding technique) or, on the U64, the high-fidelity Ultimate Audio PCM sampler. - Overlays — scrolling text, marquee, RSS ticker, spectrum analyzers, clock, weather, callsign, countdown, network info, logos, demo-scene big text, OBS Studio status — stackable on any compatible scene.
- Pixel effects — eight of them (trails, pulse, RGB shift, blur, strobe, invert, mirror, posterize), layerable into an ordered chain, each tunable and bypass-toggleable live, and lockable to the music or the beat grid.
- Live performance — a MIDI controller, a phone or a browser drives the whole show; see Live control.
- Browser console —
c64cast --serveturns the program into a host that holds the Commodore and starts, stops and switches shows on request. Author a configuration in a generated form, watch the C64's own screen live in the browser (the U64's FPGA taps the VIC), tune the color pipeline from a phone and keep what you tuned, and hand out a read-only link. Ships inside the package — nothing to install, no separate service. - Ensemble mode — one process drives N systems at once as a video wall, with cross-system orchestration.
- WLED bridge — interoperate with the WLED LED ecosystem in three directions: drive real LED matrices from the C64's SID, present c64cast as a WLED device the WLED app / Home Assistant can control, or turn the C64 into a virtual LED matrix. See WLED bridge.
- Preview + recording — an optional desktop window and an MP4 writer, both host-side reconstructions of the bytes c64cast sent rather than captures of the Commodore's own output. Know what they cannot show you before you rely on them.
# "Hello world": scrolls big text across a solid canvas. Needs nothing but a
# reachable U64/TR+ — no webcam, mic, SID, or video files. Ctrl-C to exit.
c64cast --config example:hello -u u64://192.168.2.64
# Save the connection target so you never type -u again:
c64cast -u u64://192.168.2.64 --save-settings
c64cast --config example:hello-u/--url is a scheme-aware target that picks the backend + endpoint:
u64://HOST or http(s)://HOST (Ultimate 64 / II+), tr:// (TeensyROM+ over
auto-detected USB serial), tr:///dev/cu.usbmodem* / tr://COM3 (a specific
serial device), or tr://HOST (TeensyROM+ over TCP). $C64CAST_URL is the env
fallback, and --save-settings persists it — along with the capture device and
SID model — to ~/.config/c64cast/settings.toml, where it applies to every
later run including quick playback.
The first run against a machine spends about a second reading that machine's
character ROM over the wire and caching it under ~/.local/share/c64cast/,
so every glyph c64cast draws is your Commodore's own font rather than a
built-in approximation.
From example:hello, the next steps:
# Try a single feature in isolation — one demo per scene type / overlay:
c64cast --config example:scene-webcam-petscii
c64cast --config example:overlay-clock
# Build your own: the wizard walks you through a single scene or a whole
# playlist and writes a ./c64cast.toml, which later runs pick up on their own
# (needs the 'wizard' extra, included in [all]):
c64cast --init
# ...or by hand, starting from the fully-annotated reference config:
c64cast --print-example c64cast.example > c64cast.toml && $EDITOR c64cast.toml
c64cast
# Check a config and your installed extras without touching the C64:
c64cast --doctor --config c64cast.toml --skip-probeThe demos ship inside the package, so example:NAME works the same from an
installed wheel, from uvx, or from a git checkout —
c64cast/examples/README.md
is the narrative tour of them. c64cast -h lists every CLI flag, grouped by
section.
Pass media files/directories/globs/URLs as positional arguments to play them
once, in order, without writing a TOML (mutually exclusive with --config).
Audio is on by default; --no-audio mutes.
# A video, a SID tune, then a folder of pictures, on an Ultimate 64:
c64cast -u u64://192.168.1.64 clip.mp4 tune.sid ~/Pictures/
# A YouTube URL, on a TeensyROM+ over auto-detected USB serial (the 'yt'
# extra, included in [all]); an audio file works too — the track plays
# through the C64 while a generative visual reacts to it.
c64cast -u tr:// 'https://youtu.be/dQw4w9WgXcQ'A config is a single TOML file (--config PATH, else ./c64cast.toml, else
built-in defaults) that defines the playlist and every overridable option.
c64cast --init builds one interactively, --print-example c64cast.example
prints a fully-annotated one to edit, and --doctor --skip-probe validates the
result without touching the C64. The whole config surface is discoverable from
the command line (--describe, --list-scenes, --list-overlays,
--list-modes, --compat, --print-schema), and every one of those reads the
same field metadata the loader runs on, so the answers can't drift from the
code. See
The Configuration Language
for the complete walkthrough and
Appendix A
for every section and field.
While the show is running you can drive it from the C64's own keyboard (pause,
skip, cycle styles, an on-C64 menu of live knobs), a MIDI controller (a
clip-launch grid quantized to a beat grid, CC knobs mapped to live parameters,
pad LEDs driven from actual state, saved looks that recall a scene and its
whole effect chain in one press), a browser, webcam gestures, or plain HTTP +
signals with [control] enabled = true.
The browser gets two pages, both served by c64cast itself. GET /perf is
the zero-dependency phone console — clips, the effect rack, the current scene's
tune knobs, tempo, transport, looks and a jump to any scene — and needs only
[control] enabled = true. c64cast --serve (the web extra) is the full
console: the same performance surface plus the C64's live screen, a form that
edits and validates a configuration, save-back of anything you tuned, and a
read-only link to hand out.
Inputs and Outputs documents every surface in full, and the Performance Card is the printable version for the desk beside the controller.
Everything below is also a website: https://kfox.github.io/c64cast/ reads
all three books and the notes beneath them in one place, built from these same
files on every push to main.
- docs/guide/ — the User's Guide: a friendly, read-in-order introduction that starts from nothing and builds up. Start at Quick Start, or download the typeset PDF.
- docs/reference/ — the Programmer's Reference Guide: the volume you open at the page you need. The rules of the configuration language, every scene and overlay, the display and sound paths in full, what lands in the Commodore's memory, and ten appendices, nine of them generated from the code. PDF.
- docs/card/ — the Performance Card: two printable pages of controls, live targets and clip-grid syntax for the desk beside the controller. PDF.
- docs/caveats.md — known quirks (6502 emulator scope, char ROM substitution, U64 endpoint variance, licensing of SIDs / videos)
- docs/troubleshooting.md — symptom-first index for "I saw X, what now?"
- docs/extending.md — how to add a new Scene, Overlay, DisplayMode, or interstitial Background
- docs/architecture.md — per-module internals: design rationale, hardware constraints, and edge-case history. Split by topic area under docs/architecture/; the index routes each module to its notes
- CHANGELOG.md — what changed in each release
Each PDF link above always serves the newest release; every past release keeps its own version-stamped copy on its release page.
One of the following:
-
An Ultimate 64 — confirmed with Elite I, Elite II, Ultimate II+ cartridge, or Commodore 64 Ultimate. Best results will be obtained from using the Elite II or the Commodore 64 Ultimate. Three firmware switches, in two menus under F2, then save and reboot:
- Ultimate DMA Service (Network Settings) — the socket on TCP port 64 that carries every memory write. Without it nothing works at all.
- Command Interface (Memory Configuration — a different menu, and the one people miss) — gates command dispatch even when the socket is open. Without it c64cast connects and then hangs forever.
- Web Remote Control Service (Network Settings) — the REST service carrying the operations that have no DMA equivalent: reset, launching a program or a SID, and every memory read, including the keyboard poll and the character-ROM dump. Without it pixels still paint, but nothing starts. On older Ultimate 64 and Ultimate II+ firmware it has no switch of its own and is already on.
Nothing else needs enabling by hand: c64cast turns on the REU and maps the Ultimate Audio sampler itself when a run needs them, and puts both back at teardown.
-
A TeensyROM+ Multi-Capable Cartridge for C64/128 plugged into an original Commodore 64 or one of the above modern "ultimate" equivalents.
Depending on how you use it, you'll also want some of these things:
- Any C64 video output path supported by a U64/C64.
- A webcam (any cv2-compatible USB device) for live capture scenes.
- A microphone for live audio; otherwise the audio path can sit idle or play a video's soundtrack via PyAV.
- A MIDI controller if you want to use MIDI scenes, or to perform with the clip grid and live parameter knobs.
- An HDMI capture device if you want to capture output directly from a U64 or C64 equipped with a Kawari Large. Example capture devices include the Elgato Cam Link 4K or the Genki ShadowCast.
- A WLED device (or a WLED-ecosystem sender like LedFx/xLights) on the same LAN if you want to use the WLED bridge in any direction — none of this is required for the core streaming experience.
There is no software emulator path for the streaming side: c64cast writes directly to C64 memory and VIC-II registers over the wire, and SID playback runs a small player PRG in the machine's own RAM so the real 6510 calls PLAY at IRQ time. See docs/caveats.md for why, and for the PSID-only limitation that follows from it.
Bug reports, feature ideas, and pull requests are all welcome. See
CONTRIBUTING.md
for the development setup (a git checkout and uv sync --all-extras), the
make check gate, and the conventions this repo follows. Security reports go
through SECURITY.md
rather than a public issue.
- Gideon Zweijtzer for the Ultimate 64 hardware and firmware.
- Travis Smith for the TeensyROM+ - including cartridge, firmware, hands-on testing, and suggestions.
- Bo Zimmerman for his excellent online and physical collections of all things Commodore.
- The HVSC team for the SID archive and the Songlengths database.
- Pex 'Mahoney' Tufvesson for the 8-bit
$D418DAC technique (his "Musings in the Key of C64" white paper) behind the optionaldac_curve = "mahoney_ultisid"audio path. - Jürgen Wothke (webSID / Tiny'R'Sid) for
documenting the
$D418filter-bit "almost 8-bit" playback approach behind Mahoney's technique. - Antonio Savona for the
48 kHz
$D418write-up. - CodeBase64 for the extensive reference material.
- Many open source contributors for all of the many Python packages that make this app possible. <3
MIT — see LICENSE.
Third-party assets. The books are typeset in two fonts that are
redistributed in this repository under the SIL Open Font
License 1.1, not under MIT: Jost*
(Copyright 2020 The Jost Project Authors) and Inconsolata (Copyright 2006
The Inconsolata Project Authors). They live in
docs/shared/fonts/
alongside their license texts — see
that directory's README
for provenance and for what has to travel with them.
