Skip to content

Latest commit

 

History

68 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Commodore 64 Ultimate Viewer

c64uv icon

Use your Commodore 64 Ultimate (or Ultimate 64) from a Linux desktop over the network: live video and audio streamed into an SDL window, your keystrokes typed straight into BASIC, and the Ultimate's menu one keypress away - no second monitor, no capture card, just the Ethernet cable.

./c64uv --host <ultimate-ip>

What you get

  • Video - the raw VIC stream (PAL 384×272 @ 50 Hz or NTSC 384×240 @ 60 Hz), decoded losslessly and pixel-scaled; latency is roughly one frame on a wired LAN. If the stream stops (machine switched off, cable out) the window says so and picks the picture up again by itself when it returns.
  • Audio - the SID output as 48 kHz stereo PCM, with an adaptive latency servo that holds the pipeline at ~60 ms.
  • Keyboard - what you type lands in the C64's keyboard buffer: full PETSCII mapping, cursor keys, F1–F8, and Esc acting as RUN/STOP.
  • Ultimate menu - press F9 to flip to the Ultimate's own menu (file browser, disk mounting, configuration) rendered via its telnet remote screen; F9 again returns to the C64.
  • Discovery - run it with no address and it finds the Ultimate on your LAN (preferring its wired interface, the one that can stream).
  • Run files - drop a .prg, .crt, or .sid onto the window (or --run file) and the machine runs it, cartridge-safe.
  • Machine control - reset, reboot, pause/resume, and menu button as hotkeys or one-shot --do commands; F10 shows the in-window key reference.
  • Shareable streams - --multicast lets any number of viewers watch the same machine.

Requirements

  • Linux with SDL3 and libcurl (pacman -S sdl3 curl / apt install libsdl3-dev libcurl4-openssl-dev), C compiler, make.
  • A C64 Ultimate / Ultimate 64 on your network. The viewer talks to its REST API (HTTP), streaming ports (UDP 11000/11001), DMA socket (TCP 64), and telnet menu (TCP 23).

On the Ultimate, enable (F5 → Settings → Network Settings)

Service Needed for
Web Remote Control Service (REST API, port 80) discovery, starting/stopping the streams, the Ctrl+R/P/M machine controls and --do, running dropped .prg/.crt/.sid files, mounting .g64/.d71/.g71/.d81 images, cartridge parking, and matrix-level typing on firmware that has machine:input
Ultimate DMA Service (port 64) typing into the C64 (KERNAL buffer), RUN/STOP, and mount-and-run of a dropped .d64
Telnet Remote Menu Service (port 23) the F9 menu view

Everything else the viewer does needs no service: the video/audio streams arrive on UDP 11000/11001 once started. The REST API alone gets you a picture and sound; add the DMA service to type, and telnet to browse the Ultimate's menu from the viewer.

Wired Ethernet is required for the streams

The video/audio streams are generated by the FPGA and only leave through the Ultimate's Ethernet port. With the machine on WiFi alone, stream start fails with "No Operational Network Interface". Keyboard, menu, and REST work over either; plug in a cable for the full experience. (Your PC may be on WiFi, though wired is smoother - the streams total ~22 Mbit/s.)

Building and running

make
./c64uv --host 192.168.1.64        # or: export C64U_HOST=192.168.1.64
./c64uv                            # no address? it scans your LAN for one

With no --host (and no C64U_HOST) the viewer sweeps your local /24 subnets with one /v1/info request per address and uses the Ultimate it finds; --discover runs the same scan, lists every Ultimate on the network, and exits.

The viewer asks the Ultimate to send its streams to your PC's address on the Ultimate's subnet (auto-detected, wired interfaces preferred; override with --dest). It re-issues the start request every 5 s, so streams survive machine resets - and it pings the Ultimate first, because the firmware refuses to start a stream toward an address missing from its ARP table.

Key Action
any typing typed into the C64 (lowercase = letters, Shift = PETSCII graphics)
Esc RUN/STOP
F1–F8, cursors, Home, Del/Ins the corresponding C64 keys
F9 toggle the Ultimate menu view
F10 in-window key reference (same table as --help)
Ctrl+R / Ctrl+Shift+R reset / reboot the machine
Ctrl+P pause / resume the machine
Ctrl+M press the Ultimate's menu button (the on-screen menu then answers the physical keyboard only; use F9 to drive a menu from the viewer)
Ctrl+Q quit

Drop a .prg, .crt, .sid, or .d64 file onto the window and the Ultimate runs it (DMA program run, cartridge run, SID player, or for a .d64: mount on drive A, reset, LOAD"*",8,1 and RUN, all done by the firmware over the DMA socket). If a cartridge is configured on the machine, it is parked for the run and restored afterwards, so a freezer cart won't hijack the program's reset; the cart is back on your next manual reset. The same works headless: c64uv --run game.prg.

The window title shows the transfer progress ("sending game.d64 42%"). The Ultimate serves one DMA-socket client at a time, so the viewer drops its keyboard connection for the duration and reconnects it on your next keypress; a second drop while one is in flight is refused.

Other disk images (.g64, .d71, .g71, .d81) are mounted on drive A without touching the machine; type LOAD"*",8,1 yourself. Every image is copied to the Ultimate's temp area first, so writes never reach the file you dropped.

The same machine controls work headless: c64uv --do reset (also reboot, pause, resume, menu, poweroff) issues one REST call and exits. If your Ultimate has a network password set (firmware 3.12+), pass it with --password or the C64U_PASSWORD environment variable; it is sent as the X-Password header on every request, discovery included.

Several viewers, one Ultimate

The Ultimate streams to a single destination, so normally the first viewer wins. --multicast asks it to stream to multicast groups instead (239.0.1.64 video, 239.0.1.65 audio): every viewer started with --multicast joins the groups and shows the same machine, and c64uv can share the stream with other multicast-aware tools watching the same groups. A custom group works too: --dest 239.x.y.z joins that group for video and group + 1 for audio. When one multicast viewer quits it stops the stream, and the remaining viewers' keepalive restarts it within 5 s (a short blip).

The menu view is its own remote session on the firmware side: after you launch something from it (Run Disk, Run Program), the menu stays where it was and the viewer does not switch on its own - press F9 to flip back to the C64 screen and watch it boot.

Useful flags: --no-audio, --no-keyb, --scale N (window size), --discover (list Ultimates on the network and exit), --verbose (fps/packet/latency stats), --dump f.ppm (grab one frame headless), --term-test (print the menu screen as text and exit), --no-start (listen only; pair with tools/mockstream.py to develop with no hardware).

Installing

make install (respects DESTDIR and PREFIX, default /usr) installs the binary, a desktop entry, and the icon. Arch users can build a package from packaging/aur/PKGBUILD; prebuilt static binaries are on the releases page. Set C64U_HOST in your environment if you launch it from the desktop menu rather than a terminal.

Limitations

  • On current official firmware, typed input goes through the KERNAL keyboard buffer: it works for BASIC, the READY prompt, and anything reading input normally - not for games that scan the keyboard matrix directly. The viewer probes for the hardware-level machine:input API (in upstream firmware betas) on every start and switches to true matrix-level press/release automatically once your firmware has it; games, chords, and held keys then work, with Tab acting as the C64 CTRL key, PageUp as RESTORE, Insert as £ and End as + (both also on the numeric keypad; a PC has no unshifted key for either).
  • The Ultimate's menu overlay is not part of the VIC stream - that's what the F9 telnet view is for. The on-screen menu (Ctrl+M) cannot be driven from the viewer on current firmware: every remote keystroke is a DMA write into C64 memory, and the firmware closes its menu before any DMA write, so the first key you press kicks the menu out. Newer firmware with the machine:input API routes keys into the menu; the viewer switches to it automatically once your machine has it.
  • IPv4 only. The device streams to one destination, so it's one viewer per Ultimate unless everyone uses --multicast.

How it talks to the machine

REST (/v1/streams/*, /v1/machine:*) for control; UDP 11000 carries 4-bit VIC color indices (384 px × 4 lines per 780-byte packet), UDP 11001 carries 192 stereo s16le frames per packet; TCP 64 speaks the firmware's socket-DMA protocol (KEYB 0xFF03, DMAWRITE 0xFF06); TCP 23 is a VT100 session emulated in src/term.c. Protocol docs: REST API, data streams.

License

MIT for this project's code. src/font8x8.h is public domain (Daniel Hepper / Marcel Sondaar).

About

Commodore 64 Ultimate Viewer - stream video/audio from a C64 Ultimate into an SDL window, type into BASIC, browse the Ultimate menu. Linux, C, SDL3.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages