SIDin #14 — Inside Matt Gray's Dominator player (Tognon's commented PLAYER V4.2 and the musician's guide to composing in it, 2015)

author Stefano Tognon (ice00), SIDin magazine
date 2015-01-25
article SIDin issue 14 (version 1.00, 2015-01-25), pp. 25–60: 'Inside Matt Gray Dominator player' — sections Starting (building with 64tass), Background (assembler syntax for musicians), Player, Tracks, Patterns, Instruments, Source (the re-commented listing, pp. 41–56), Use it (the empty template, steps 1–7), Conclusion. The listing was skimmed only to verify values
created 2026-08-30 · updated 2026-08-31

Written for the Reformation driver competition (s-matt-gray-dominator-source): Tognon takes matt-gray's released dom6-public.asm, comments every line, explains 64tass syntax to non-programmers, walks through the matt-gray-player as "PLAYER V4.2" and ships an empty template so that "a musician with no programming knowledge" can type a tune into it. It is the authoritative reading of the V4.2 tables — it settles several bytes the wiki had marked unverified — and it lists what changed since Driller (s-sidin02-matt-gray-driller).

Key claims#

Starting — build: download the zip from Remix64, 64tass.exe dom6-public.asm (Windows, 64tass is in the zip) or c64tass dom6-public.asm (Linux, yum/apt-get install 64tass), load the resulting a.out in vice. The addendum to the issue holds the original source, Tognon's re-commented version (only comments and blank lines added) and an empty empty_public.asm. Entries must stay in 64tass format to be accepted by Gray; help thread: CSDb forum topic 107150.

Background — a primer: ; comments, mnemonics, .BYTE / .WORD / .TEXT, *= $0801, labels vs constants (BB = 55), and the two operators the tables rely on: CC&255 = low byte, CC/256 = high byte of an address (other assemblers write < and >). "Use hexadecimal numbers … all is more simple."

Player — starts at $0801 with a BASIC stub, installs a raster IRQ (SETIRQ, PAL 50 Hz, "all tunes are played at speed 1X" — multispeed or CIA timing would need code changes; multispeed); the player itself sits at STARTADD = $C000, movable down to "the (safe) minimum of $1000". Note frequencies are hard-coded in NTL/NTH from C0: NTL .BYTE 12,28,45,62,81,102,…, NTH .BYTE 1,1,1,… — C0 = 1*256+12 = 268 → 268 × 0.0587235 = 15.73 Hz; A4 comes out at 424 Hz on PAL (441 Hz on NTSC). Constants C0 = 1 … B7 = 96 let notes be typed by name. TN holds the tune number (initial value 3; the player sets it to $AB while playing and to 0 at the end, "or you can use it for stopping the tune playback at any time"). TDATA .BYTE 0,5,3,4 = speed per tune (tune 0 is silence; the shortest note of tune 3 "will take 4 frames"; "the higher is that value and more slowly is the tune"); VOICE1L/H … VOICE3L/H hold the three track addresses per tune (TUNE1–3, OVER1–3, FIN1–3), so the released file plays three songs, not one.

TracksXX = pattern number $00–$FD, $FF repeat the track, $FE end of music — and "in this version of the player (but was not present into Driller) there is an automatically fade out volume effects at the end of the tune". (In the listing: $FE stores $5F in FADE, then every $5F frames VOLUME is decremented and written to $D418 until it runs out and TN is cleared.) BARLO/BARHI map pattern numbers to labels T0 … T56; Tognon shows how to rename them (PIPPO, PLUTO) and define index constants (orderlist).

Patterns — the V4.2 command set as Tognon tabulates it:

bytemeaning
$00rest — implemented as gate off, "so starting the release phase" (hard-restart)
$01–$6Fnote (1 = C0)
$70–$F9duration kk − $70 — "more efficient" than Driller's two-byte $FD kk
$FA NNinstrument NN (0 = first)
$FB MM / $FC KKslide down / up by that amount per cycle — "you can ever see this as a portamento" (pitch-slide-and-portamento)
$FD CIplex (arpeggio): C = number of notes, I = table index — $FD,$30 = table 0 × 3, $FD,$4A = table 10 × 4 (chord-arpeggio)
$FFend of pattern

Persistence rules: an instrument holds until the next $FA; a duration until the next duration byte; a slide "lies only for the next note to play" and cancels plex and vibrato; a plex cancels slide and vibrato and "stays up until a new instrument is activated (or there is a slide)". The plex moved from the Driller instrument byte to a pattern command; tables PLEXLH .WORD P0,P1,P2 … with P0 .BYTE $07,$03,$00 (note+7, +3, +0, repeated); a longer table can be used with different counts ($FD,$30 then $FD,$40 on P0 .BYTE $07,$03,$00,$09). Worked examples: T56 .BYTE $FA,$06,$7F,$FD,$36,G4,$FD,$31,F4,$FD,$32,G4,$FD,$35,F4,$FF (instrument 6, duration 15, four chords); T6 .BYTE $FA,$02,$EF,$FC,$0A,AS3,$FB,$0A,AS4,$FF (duration $EF−$70 = 127, slide up +10 into AS3, down −10 into AS4). The listing adds one command Tognon's table folds into the duration range: $F9 nn = vibrato delay (VIBDELAY; durations therefore end at $F8), and a transpose variable TP that "seems to not be used".

Instruments$FA NN × 8 indexes two 8-byte tables directly (VDATA, VDATA2; "maximum of 256/8 = 32 instruments"):

indexmeaning
0pulse width as nibbles: $12 → high $02, low $10 ($0210 = 528)
1control register
2 / 3AD / SR (adsr-envelope)
4pulse step, added/subtracted per frame
5not used ("were used in old player for plex/arpeggio")
6control register 2: written with the gate bit forced off when the instrument is selected, and just before the normal control register at each new note — "a 'basic' restart of note"
7effect bits: 1 drum table, 2 pulse modulation, 4 implex (waveform switch on the first frames of a note, using byte 10), 16 hat
8 / 9vibrato step / vibrato length (vibrato)
10control register for implex
11 / 12instrument slide value / flag: 0 none, 1 down, 2 up, 3 down on the high byte, 4 up on the high byte — "instrument slide is more capable in comparison with pattern slide"
13drum table index
14pulse-width limits as nibbles $LH → bounce between $0Lxx and $0Hxx ("in Driller it was fixed into the source")
15not used

Pulse example: start $23 (= $0320 = 800), step $A0 (160), limits $18 → rises 800, 960, 1120 … 2080 ($0820), then falls to $01xx and back (pulse-width-modulation). Vibrato direction sequence 0 (down, first time), 1, 2 (up), 3, 4 (down), then 1, 2, 3, 4 … — the Driller triangle. Hat = "a brief noise waveform at frequency $50xx played after every note duration decrements" — "not present into Driller player". Drum tables: DTL/DTH point to DT, BT; pairs of (control, value) ended by $FF, up to 127 pairs; a control byte with bit 7 set ($8x noise) sets the frequency high byte to the value, one without ($1x, $4x) subtracts the value from the current high byte — "a 'negative value' of control register is when you choose a noise waveform … while a 'positive' value is for the other waveform (like $4x) that you can use for a bass". DT decoded: $81,$30 noise on at $30xx (≥ 721 Hz, "AS4/B4"), $11,$02 triangle at note − $02xx, $41,$04 pulse at note − $04xx, then gate-off noise frames at $30, $15, $20, $10, $20, $20, $10, $20; BT: $81,$30, $41,$03, $40,$03, then noise $20/$10 alternating (wavetable-programming, instrument-design). Decoded instruments: 0 = drum table BT then plain triangle ($87,$11,$00,$E6,$00,$00,$10,$01 / $00,$00,$81,$00,$00,$01,$8E,$00); 1 = pulse from $0130 up to $0E00 and down to $08xx in $15 steps; 4 = pulse $01F0, step $20, limits $33 ("stay around" $03xx) plus hat; 9 = pulse $0440 between $0300 and $0500 in $C0 steps plus vibrato step $90, length 2; 13 = triangle with an instrument slide $B3, flag 3 ("a 'big' negative slide effect").

Use itempty_public.asm: one tune, 32 empty instruments, 166 empty patterns (T0 … T165), 32 empty drum tables (DBT0 … DBT31), 16 plex tables (P0–P8 three notes, P9–P12 four, P13–P15 two — "95% of arpeggio are based into 3 values"). Steps: 1 TDATA .BYTE 0,5; 2 fill VDATA/VDATA2 rows; 3 drum tables, e.g. DBT2 .BYTE $81,$30,$11,$02,$FF; 4 plex rows, e.g. P1 .BYTE $08,$03,$00, a seven-note P2 .BYTE $10,$0E,$08,$05,$03,$01,$00 used with $FD $72; 5 patterns, e.g. T0 .BYTE $FA,$01,$75,G1,$FF; 6 tracks TUNE1 .BYTE T0,T1,T1,T2,T12,$FF ($FE for no repeat); 7 readability constants — INSTR = $FA, FLUTE = $00, ARPEG = $FD, P850 = $32, DUR5 = $75 — so $FA,$00,$75,F2,$FD,$32,E2,$FA,$01,F1,$76,G1,$FF becomes INSTR,FLUTE,DUR5,F2,ARPEG,P850,E2,INSTR,GUITAR,F1,DUR6,G1,$FF.

Practical takeaways#

  • The whole V4.2 workflow in six tables: speed, instrument rows, drum tables, plex tables, patterns, tracks — a checklist for composing in any assembler-era driver (sid-player-routine, tracking-workflow).
  • Byte 6 + the implex control byte are a pre-tracker hard restart: gate off on instrument change, a different waveform for the first frames of the note.
  • Drum tables are (waveform, pitch) frame lists where noise frames set an absolute pitch and tonal frames step down from the note — the same shape as a GoatTracker/SID-Wizard wave table with pitch column.
  • Gray's note table is tuned to A4 ≈ 424 Hz on PAL; retune NTL/NTH if 440 Hz matters (Gray's own comment in s-sidin15-matt-gray-interview).

Notable quotes#

"I will try to describe the player not in the standard SIDin way (that means you are a coder …), but I will go in trivial description of some tasks that for a musician with no programming knowledge will let him to use the source."

"The previous work is substantially correct if compared with the actual knowledge we can get from this player. However the player is changed from the previous one in a non compatible way and it has lot of more features."

Relevance to the wiki#

Completes matt-gray-player's V4.2 cheat sheet (pattern bytes, 16-byte instrument layout, drum-table semantics, fade-out, per-instrument pulse limits); corrects two readings on s-matt-gray-dominator-source ($FD is plex, not duration; $AF/$DF/$EF/$EE/$97/$E7 are durations); adds the A4 = 424 Hz tuning; gives dominator the build-and-compose story; examples for chord-arpeggio, pulse-width-modulation, vibrato, wavetable-programming, instrument-tables.

To verify#

  • The fade-out length: $5F frames per volume step × 16 steps ≈ 30 s at 50 Hz — computed from the listing, not stated by Tognon (unverified).
  • Tognon writes "65tass syntax" once and "64tass" elsewhere; the assembler is 64tass.

Pages touched#

matt-gray-player · dominator · matt-gray · driller · instrument-tables · chord-arpeggio · pulse-width-modulation · vibrato · wavetable-programming · pitch-slide-and-portamento · orderlist · hard-restart · sid-player-routine · tracking-workflow · vice · sidin · song-init-and-looping

source file wiki/summaries/s-sidin14-dominator-player.md · 1 unverified · graph