🌐 Sprache / Language: English · Deutsch
Commodore 64 SID chiptune player as a single-file HTML5 version and a native SwiftUI macOS app.
A self-contained Commodore 64 SID music player in two variants:
- HTML5 (
vicious-sid-player.html) — a single HTML file (~50 KB) that runs straight from the file system via double click, no web server required. - Native macOS app (
Vicious SID Player.app) — SwiftUI desktop application withAVAudioEngineand a real-time oscilloscope.
Neither variant ships any SID files. Tunes are loaded via drag & drop, file dialog, or (macOS app) by double-clicking a .sid file in Finder.
Ready-made builds of the macOS app are available as notarized DMGs on the Releases page. Download the DMG, open it, and drag the app into your Applications folder.
The HTML5 player needs no download beyond that: the file vicious-sid-player.html opens directly in the browser.
- Drag & drop: Drop single
.sidfiles or entire folders onto the player. Playback starts immediately. - Real-time oscilloscope: Shows the waveforms of the three SID voices (triangle, sawtooth, pulse, noise) along with frequencies, gate status, and ADSR envelopes.
- SID model selection (macOS app): Picker with
Auto,6581, and8580.Autofollows the preference stored in the SID file; a fixed choice forces the respective chip model and applies live to the running song (many tunes only sound right on the chip they were originally written for). - Quick Look preview (macOS app): Select a
.sidfile in Finder and press Space — the tune plays instantly, with title, composer, and copyright plus subtune switching for multi-song files. Setup: see Quick Look preview. - Dark / light mode: Follows the system setting automatically or toggles manually.
- Playlist with duplicate detection: Already loaded tunes are not added twice. The playlist can be cleared at any time.
- Shuffle: Random playback that persists across restarts; a random song starts on launch when enabled.
- Media keys: Play/pause, stop, and track skipping via F7/F8/F9, the Touch Bar, and AirPods — the app registers as the system's Now Playing app.
- No external assets: The entire interface (including macOS window decorations and icons) is drawn procedurally in CSS and SwiftUI Canvas.
Every control in the app has a tooltip: rest the pointer on it for a moment and a short explanation appears. macOS only shows tooltips after a delay, so they are easy to miss — here is the full reference.
Control bar
| Control | Function |
|---|---|
| Tune menu | Pick a track from the playlist. |
| Öffnen… | Open one or more .sid files. |
| Auto Next | When a tune ends, continue automatically — first through the remaining subtunes of the file, then to the next track. |
| SID: Auto / 6581 / 8580 | Chip model. Auto follows the file's preference; a fixed choice forces that model and applies live to the running song. |
| ‹ n / m › | Subtune navigation. A .sid file can hold several songs ("subtunes"); 2 / 5 means subtune 2 of 5. |
| Shuffle | Random playback. The setting persists across restarts; while on, a random song starts each time the app launches. |
| ↺ 15 | Skip 15 seconds back. |
| Play / Pause | Start playback, or pause (pausing keeps the current position and freezes the oscilloscope). |
| 30 ↻ | Skip 30 seconds forward. |
| Stop | Stop and return to the beginning. |
| Position slider | Seek — works even while paused or stopped; pressing Play then starts from that point. |
| Volume slider | Playback volume. |
| Trash (playlist header) | Clear the playlist. |
Title, composer, and info in the sidebar, as well as long track names, also show their full text as a tooltip when truncated.
Keyboard shortcuts
| Key | Action |
|---|---|
| Space | Play / pause |
| ⌘P | Play / pause |
| ⌘→ | Next track |
| ⌘← | Previous track |
| ⌘T | Toggle dark / light theme |
Media keys
The app registers as the system's Now Playing app, so the media keys (F7 / F8 / F9), the Touch Bar, and AirPods controls work: play/pause, stop, and previous/next track. Title and playback position also appear in Control Center.
The app bundle includes a Quick Look extension that plays .sid files directly in the Finder preview. There is nothing to install separately:
- Drag
Vicious SID Player.appinto the Applications folder (the DMG contains a shortcut). - Launch the app once — this registers the extension and the
.sidfile type with macOS. - Select a
.sidfile in Finder and press the space bar: the tune starts playing and shows title, composer, and copyright, with buttons to switch between subtunes.
If no preview appears:
- Make sure the extension is enabled: open System Settings, search for “Extensions”, and enable Vicious SID Quick Look under Quick Look.
- Reset the Quick Look cache in Terminal:
qlmanage -r, then press Space on the file again. - Test the preview directly from Terminal:
qlmanage -p /path/to/tune.sid.
Requires macOS 13 or later.
The emulator for the MOS 6581/8580 SID chip and the 6502 CPU core is based on jsSID 0.9.1 by Hermit (Mihály Horváth, 2016, WTFPL license).
The following fixes were applied on top of the original:
- 6502 opcode mask:
IR & 0xF0instead ofIR & 0xC0for implied opcodes. The faulty mask kept instructions such asINX,TAY,PHP, andPLPfrom executing — many songs stayed silent or froze. - AudioWorklet architecture: The engine is implemented as a standalone class instead of a subclass of
AudioWorkletProcessor, which removes the constructor error in the browser. - Noise waveform and ENV3 readback: Aligned with the correct jsSID reference.
- Swift port: Correct 24-bit XOR shifts for combined waveforms and array guards against out-of-bounds access.
| Layer | HTML5 | macOS (Swift) |
|---|---|---|
| Parser | sidplayer.js |
SidParser.swift |
| DSP / emulator | sid-player-worklet.js (AudioWorklet) |
ViciousProcessor.swift (AVAudioSourceNode) |
| UI | Vanilla JS + CSS custom properties | SwiftUI + Canvas |
python3 build.py # → vicious-sid-player.html (~50 KB)
python3 build.py --no-min # without minificationbash build_app.sh # → "Vicious SID Player.app"On startup the app builds its playlist from an autoplay folder, searched recursively (subfolders included). Pick any folder in the app settings (app menu → "Settings…", Cmd+,); without a custom choice the default is ~/Music/Vicious SID Player/. Drop your .sid files there; they load automatically on launch. Changing the folder in the settings reloads the playlist immediately. The folder lives outside the repository and is never published.
For release builds, build_app.sh automatically signs with the Developer ID
Developer ID Application: Daniel Mueller (9QSWKSR4NQ) if it is available in
the keychain. Local unsigned builds are possible with
SIGN_APP=0 bash build_app.sh.
The Quick Look extension is built as part of the app bundle
(Contents/PlugIns/ViciousSIDQuickLook.appex) and is therefore included in
every app build and DMG automatically.
bash build_dmg.sh # → build/Vicious SID Player.dmg
NOTARY_PROFILE=<profile> bash build_dmg.sh --notarize # sign, notarize, and staple the DMGThe DMG contains a Retina-compatible background image (1x/2x TIFF via tiffutil).
Notarization requires a notarytool keychain profile, passed via the
NOTARY_PROFILE environment variable. It can be created once interactively:
xcrun notarytool store-credentials <profile>swift testbash publish_github.sh --dry-run --release
bash publish_github.sh --releaseThe publishing script sets origin to
https://github.com/DanielMuellerIR/vicious-sidplayer.git, blocks accidentally
tracked audio and release artifacts, and with --release creates the matching
GitHub release entry with the DMG asset.
The SID and CPU emulation was ported from the JavaScript project jsSID by Hermit and extended with the bugfixes listed above. The native macOS app is a complete reimplementation in Swift.
WTFPL — see LICENSE.
