realdmx: two scene players with their own sources — Francois Prijt's Audial Arts 'zong player' v1/v2 (1991) and Adam Bulka's FAME 'Sound Routine f 4.1.0' (1988)
Three original Turbo Assembler sources in the realdmx collection (s-realdmx-sid-players) from the demoscene rather than the games industry: Francois Prijt's "zong player" for the Dutch group Audial Arts (two versions, 1991, Dutch comments) and Adam Bulka's "Sound Routine f 4.1.0" for FAME (dated to the hour: 27.07.1988, 2.29 pm; German comments). Both are ~3 KB players with 16-byte and 8-byte instruments, both put the gate length in the instrument, and the FAME routine does a hard restart in 1988.
Key claims#
Audial Arts "zong player" v1.0 / v2.0 (Francois Prijt, 1991)
- v1 header: "(c) copyright FRANCOIS PRIJT / -AA- / Audial Arts / Flash Inc. 1991 / >> zong player v1.0 <<", text
"player by fp/-aa-(c) "; entriesreset(A = song),play,stop, and ademoraster-IRQ entry; its variables live outside the player at$4a08(varia = $4a08 ;geheugen adres variab.) and leftover keyboard-controller variables (;keyboard on(1)off(0),;sound nr.#$,;wich voice (0-2)) show it was cut out of an editor build. v2 ("zong player v2.0 (c) Francois Prijt!") is self-contained, drops the demo entry, and its instrument comment says ";sound instelling (pak handleiding!)" — "sound settings (grab the manual!)" — so a manual existed. - Data model: song = three track pointers; track bytes
$00–$3fblock,$40+nplay the next block n times,$80–$bftranspose up& 31,$c0+n/$e0+ninstrument offset ±n,$ff,posloop to a track position (t11 !by $e0,$98,$43,$05 / $98,$43,$06 / $98,$43,$05 / $80,$42,$07 / $ff,$00); block bytes = note + duration in frames (2 bytes per note, on a 6-frame grid in v1),$c0+ninstrument,$e0/$e1 target,dur,speedglide up/down,$ffend. No tempo variable at all (orderlist). - Instrument = 16 bytes (instrument-tables): 0 = two preset indexes into
wavepr !by 0,$10,$20,$40,$80,$50,$12,$14,$44,$14,$20,$14,$10,$14,$20,$24— the waveform while gated and the waveform after gate-off ($23= sawtooth gated, pulse released;$44= noise/noise;$66= triangle + sync both); 1–2 AD/SR; 3 = gate length − 3 frames (the gate is an instrument property, the note duration only says when the next note starts); 4 = frame at which the pulse sweep starts; 5 = pulse width ($30→$0300); 6 = sweep turnaround in frames; 7 = sweep add; 8 = acceleration added to the sweep add every frame; 9 = arpeggio table (high nibble) + waveform pattern (low nibble), sharing one counter — a drum is one arp table (pitch per frame) plus one wave pattern; 10–14 filter (on/off + direction, mode + resonance, cutoff, min/max nibbles, add per frame); 15 flags: bit 0 "tock" (two frames of noise at note$5f— a click), bit 1 "haper" (two frames of$01, gate only), bit 2 fixed pitch (drums). Rows: bass drums2 !by $00,$0f,$e7,$00 / $00,$08,$04,$40 / $00,$22,$00,$00 / $00,$00,$00,$04; a filtered pulse leads0f !by $33,$00,$ec,$01 / $00,$03,$04,$70 / $00,$60,$01,$3f / $30,$2c,$0c,$02; v2's bass!by $33,$01,$ec,$00 / $00,$03,$04,$60 / $00,$00,$03,$1f / $c0,$4c,$18,$00(LP, resonance$f, cutoff$c0falling$18per frame between$40and$c0) (pulse-width-modulation, filter-programming). - Tables: arpeggios with
$ffrestart (ap5 !by 0,12,7,3,$ff; v2ap3 !by 14,14,19,19,22,22,$ff,ap4 !by 12,15,19,$ff— three-note chords cycling one entry per frame for the lead instruments 4–7) and drum pitch lists (ap2 !by $5f,$1e,$1c,$18,$14,$10,$0e,$0c, a kick falling from note 95); waveform patterns (;golfvorm pattern tabel(for drums ect))wv1 !by $41,$41,$80,$80,$80,$10,$80,$c4($c0|n= jump to index n,$ff= freeze),wv2 !by $81,$41,$40,$40,$40,$40,$40,$40,$ff(chord-arpeggio, wavetable-programming). - Engineering notes (read from the code): a staggered look-ahead — voice n pre-reads its next event on frame n + 1 of the current note into shadow variables, spreading the sequencer over frames; v1's glide path pops the stack without a push (a latent crash; no track uses the glide block), fixed in v2 by staging AD/SR in self-modified operands; v2 zeroes
$d404/$d405/$d406at note-on and rewrites them in the same frame — a retrigger, not a hard restart; v2 has a$fe"stop voice" track command that can never fire. Sizes (estimated): v1 ≈ 2.6 KB, v2 ≈ 3.0 KB.
FAME "Sound Routine f 4.1.0" (Adam Bulka, 1988)
- Header box: "SOUND ROUTINE f 4.1.0 / WRITTEN BY ADAM BULKA / WORKING VERSION I / DATE: 27.07.1988 2.29 pm". Entries
musicset0(A = song) andmusic. Comments in German:NOTEN DEFINITION,werte direkt in sid,Betriebsart,GEFILTERT,floete,lange halten. Drum "notes" are constants:bd = $21,sd = $29,cd = $1a. - Timing: a tick every
speedtab + 1= 3 frames; voices processed 2 → 0; a note length$80+nlasts n + 1 ticks. Track bytes: step number,$80–$9ftranspose up,$a0–$bfinstrument offset,$c0+nrepeat the next step n + 1 times,$ff lo hiabsolute jump (track1 !by $bf+2,2 / 3,3,3,3,3,3,3,11 / 17,17 / 0 / $ff / !wo track1). Step bytes:< $60note,$60–$7fextended arpeggio 1–4 (switchable mid-step),$80–$9flength (sticky),$a0–$bfinstrument,$c0–$dfwait without retrigger,$e0–$feportamentolen,time,from,to,$ffend. Drums and melody share a voice by switching instruments per note:s3 !by $81,$a1,bd / $af,e5,d5,h4,e4,g4 / $a1,bd,$af,d5(channel-interleaving). - Instrument = 8 bytes: AD, SR,
puls(one 8-bit value written to both$d402and$d403),wave(a raw$d404value, or the wave-table length),wibbyte— ";Vibrato Pointer / ;Betriebsart / ;$80=tab/$c0=arp" (0 none, 1–31 vibrato table,$80|ndirect-frequency table,$c0|nnote-offset table),fpbyte— ";Lownibble=Puls Po. / ;Highnibble=Fil Po.",wavetab(table number, bit 6 = gate-off time counted from the note end, bit 7 = never),release(bit 7 = hard restart, bits 0–6 = gate-off time in ticks). Rows:;1 bd $00,$d8,$08,$0c, $c1,$00,$81,$80;;2 sd ;GEFILTERT $00,$f8,$08,$0f, $c2,$00,$82,$80;;4 main I $01,$98,$e7,$41, $04,$01,$40,$03;;5 bass I $01,$ef,$05,$02, $05,$12,$43,$81;;7 floete I $00,$f8,$00,$11, $04,$00,$40,$03;;$10 main II lange halten $01,$9d,$a0,$04, $04,$01,$44,$01. - Hard restart, 1988: on the trigger tick an instrument with
releasebit 7 gets$d405/$d406 = $00and no other SID write that frame; frequency, waveform and ADSR follow on the next frame — every drum and both basses use it (hard-restart). Gate-off is automatic per instrument, in ticks from the start or from the end. - One table engine for vibrato, arpeggio and drum pitch:
tab1 !by $26,$0b,$08,$05,$03,$01,$00,$ff,$fe,$fd,$fc(the kick: +38 semitones on the noise frame, then falling to −4),tab6 !by $00,$07,$04,tab7 !by $00,$18,$0c(chords/octaves), vibrato tables as 2-byte segments; extended arpeggiosarp1 !by $00,$03,$07…arp4 !by $00,$04,$08on a 3-frame cycle; wave tableswtab1 !by $81,$41,$40 ×9,$08(the kick ends on the test bit$08as a mute),wtab3 !by $81,$41(one noise frame then pulse — the bass); pulse programs as (frames, add) pairsptab1 !by $3a,$20 / $0f,$df / $07,$20,$07,$df; filter programsftab1 !by $01,$00,$00,$a0 / $01,$f0,$05,$f8 / $00,$f0,$7f,$00withfiltermode !by $1f,$1f; the filter belongs to the voice that last selected a filtered instrument (wavetable-programming, chord-arpeggio, vibrato, pulse-width-modulation, filter-programming). Size ≈ 2.9 KB (estimated). - Data quirks:
high[5] = 254in the frequency table (a data error), two byte-identical snares labelled "GEFILTERT" and "Nicht Gefiltert", atab2one byte shorter than its pointer says.
Practical takeaways#
- Both scene players make the gate time an instrument parameter with a second "release" waveform or an automatic gate-off — the same idea as Ocean's patches (s-realdmx-ocean-dunn-hughes-driver) and a precursor of tracker gate-off tables.
- Audial Arts' drum recipe: an arpeggio table as an absolute-pitch list plus a waveform pattern, sharing a counter — exactly a two-column wave table.
- FAME's hard restart — zero ADSR on the trigger tick, write the note a frame later — is the minimal form of what goattracker and sid-wizard do with their HR timers.
- An accelerating pulse sweep (Audial Arts byte 8) is a cheap way to get the "opening" PWM that a linear sweep lacks.
Notable quotes#
- "
;sound instelling (pak handleiding!)" (Audial Arts v2); "varia = $4a08 ;geheugen adres variab." (v1). - "
SOUND ROUTINE f 4.1.0 / WRITTEN BY ADAM BULKA / WORKING VERSION I / DATE: 27.07.1988 2.29 pm" (FAME); ";$10 main II lange halten".
Relevance to the wiki#
Two more driver designs for the comparison on sid-player-routine and rows for sidid (Audial_Arts, FAME); a dated 1988 hard restart for hard-restart; instrument-as-gate-length examples for instrument-tables and adsr-envelope; drum and chord tables for the technique pages; the first Audial Arts / FAME material in the wiki (tracker-scene-history).
To verify#
- (unverified) Who Francois Prijt and Adam Bulka are beyond these files (groups Audial Arts / Flash Inc. and FAME); the files give no more than the credits quoted.
Pages touched#
sid-player-routine · sidid · hard-restart · instrument-tables · adsr-envelope · wavetable-programming · chord-arpeggio · pulse-width-modulation · filter-programming · vibrato · orderlist · channel-interleaving · tracker-scene-history