Homeentitytool

Matt Gray's player (Driller / Dominator engine)

The 6502 music driver matt-gray wrote for himself from late 1986 after codemasters told him he needed one, and used for every C64 game from driller (1987) to Deliverance (1990). It is documented twice: Stefano Tognon reverse-engineered the Driller version in sidin #2 (2002), and Gray released his own source of "PLAYER V4.2 (C)1987" with a dominator subtune in 2014 (sources: s-sidin02-matt-gray-driller, s-matt-gray-dominator-source, s-c64com-matt-gray-interview).

Structure#

  • "A sequencer approach" — "Rather than program every note played in sequence, it used a series of smaller sequences" (source: s-c64com-matt-gray-interview). In the code: a song = three tracks (one per voice), a track = a list of pattern/bar numbers ended by $FF (restart) or $FE (stop), a pattern = a byte stream of commands and notes (orderlist; sources: s-sidin02-matt-gray-driller, s-matt-gray-dominator-source).
  • Called once per frame; DRIVER runs the voice routine for X = 0, 7, 14; a tune number variable (songsNumber / TN) is set by the game and becomes $AB while playing; song 0 = silence. Rastertime in Driller: 10 lines minimum, up to 34 when a new note or pattern is fetched (sid-player-routine; source: s-sidin02-matt-gray-driller).

Cheat sheet#

Pattern bytes (Driller, 1987; the same in V4.2 with additions):

bytemeaning
$01–$60note number (V4.2 source uses names C0 … B7 = 1 … 96)
$00gate off for the previous note → release (hard-restart)
$FA nninstrument nn
$FB mm / $FC ppslide down / up by that amount per frame (pitch-slide-and-portamento)
$FD kkDriller: note duration kk. V4.2: $FD ci is the chord-plex command (count nibble c, table nibble i; AGAIN3 CMP #$FD → PLEXSETUP in Gray's source) — a Driller-style duration byte would be read as an arpeggio (sources: s-sidin02-matt-gray-driller, s-sidin14-dominator-player)
$FFend of pattern
V4.2 only: $F9 nnvibrato delay (label VIBDELAY)
V4.2 only: $70–$F8note duration = byte − $70 (NOTEDUR CMP #$70 / SBC #$70): $70 = 0, $71 = 1 … $EF = 127, $F8 = 136 frames — e.g. $71,D2,D2,$70,F2; the bytes $AF/$DF/$EF/$EE/$97/$E7 seen in the Dominator bars are durations 63/111/127/126/39/119 (source: s-sidin14-dominator-player)

Example (Driller): $FA,$0C / $FD,$01 / $31,$3D,$49,$3D … = instrument $0C, very short notes a 12-semitone stack apart (source: s-sidin02-matt-gray-driller). Example (Dominator): T1: $FA,$04, $71,D2,D2, $70,F2,D2,F2, $71,G2,G2, $70,G2, $FF (source: s-matt-gray-dominator-source).

Instruments — two 8-byte rows per instrument (Driller instr1/instr2, Dominator VDATA/VDATA2; source: s-sidin02-matt-gray-driller):

table 1table 2
0 pulse width as nibbles xxyy → lo xx00, hi 00yy0 vibrato step
1 control register (waveform + gate)1 vibrato length
2 attack/decay2 control register for the first two frames (drum switch)
3 sustain/release3 portamento value
4 pulse inc/dec step; hi byte bounces between $08 and $0E4 portamento flag: 00 none, 01 −lo, 02 +lo, 03 −hi, else +hi
5 arpeggio xxyy: xx notes, table yy5 length of the effect-1 cycle
6 control register written at the end of the note, same frame as the next6–7 unused
7 effect bits: 1 freq/noise effect, 2 re-set pulse each note, 4 waveform switch (drums)
  • Arpeggio tables are short semitone lists ($00,$08,$12; $00,$08; $00,$04,$08) and the instrument says how many entries to use, so $30 = table 0 with 3 notes, $22 = table 2 with 2 (source: s-sidin02-matt-gray-driller). V4.2 adds the PLEX chord tables P0–P6 = $07,$03,$00, $09,$05,$00, $08,$03,$00, $18,$0C,$00, $07,$05,$00, $07,$04,$00, $08,$05,$00 — the "note or chord plex" (chord-arpeggio; source: s-matt-gray-dominator-source).
  • Vibrato: subtract the step for L frames, add it for 2L, subtract for 2L … — a triangle on the frequency value, which is why Gray says "the higher the notes you played, the less vibrato you got, and the lower you went, the deeper it got" (vibrato; sources: s-sidin02-matt-gray-driller, s-c64com-matt-gray-interview).
  • Drums: effect bit 4 plays table-2's control register for two frames, then the instrument's own; V4.2 adds a drum table of (control, pitch) frame pairs — DT: $81,$30, $11,$02, $41,$04, $80,$30, $80,$15 … $FF — and a hi-hat routine that writes $50 to the frequency high byte and $81 (noise+gate) to the control register (wavetable-programming; sources: s-sidin02-matt-gray-driller, s-matt-gray-dominator-source).
  • Pulse: a per-instrument step and a bounce between $08xx and $0Exx, i.e. pulse width 2048–3584 — Gray's "pulse width mod" (pulse-width-modulation; source: s-sidin02-matt-gray-driller).
  • Gray: "I was always adding-in modifiers and routines to produce better-sounding drums, but I always kept a bank of sounds that could be modified from project to project" (source: s-c64com-matt-gray-interview).

In Gray's words, again#

  • Tools and size: "I used Ocean's Laser Genius to edit and assemble my code. It was just that, a c64, me and a small keyboard. The only tools I had were the routines I designed to handle everything from sequences to modulation … Most of my games tracks were under 4k, often less" (source: s-rvg-matt-gray-interview).
  • Origin: learnt 6502 "by reading books and disassembling others code", planned the code "with pen and paper … before I even had an assembler", added filters only later; "A SID composer's player is like a brand of guitar" (source: s-vandalism63-matt-gray-interview).
  • Everything is a routine: the chord plex, PWM sweeps on it, drums by waveform switching ("originally Rob Hubbard's idea"), vibrato — "There was no button to push" (source: s-rvg-matt-gray-interview). A one-channel bass with "a small hat on each note" after Sanxion (source: s-vandalism63-matt-gray-interview).
  • Ported to the NES for Treasure Island Dizzy — "the NES had a very different sound" (source: s-arcadeattack-matt-gray-interview). SIDId knows a 1990 modification by Andrew Rodger (source: s-sidid-player-list). When LN2 was re-released, the new composer "couldn't work in Matt's driver", so the game was rescored in the MoN driver instead (source: s-remix64-ninja-remix).

History#

  • Written in 6502 from late 1986; refined with each game; Mean Streak's programmers rewrote it without the modulation and pitch routines; Martin Walker discussed music routines with Gray while writing his own; a "licensable SID player" offered to Gray at a show "turned out to be just a disassembled Rob Hubbard routine" (source: s-c64com-matt-gray-interview).
  • Tognon: "the Matt's engine was used in the past even by Tomas Danko and Jon Wells for a total of 11 tunes" (source: s-sidin02-matt-gray-driller).
  • 2014: the Dominator subtune 6 source (CC BY-NC 4.0, 64tass) and the Reformation competition to compose in it; six new SIDs by Gray in the same driver (source: s-matt-gray-dominator-source). ACME conversions of both the Driller listing and the Dominator source are on GitHub (source: s-realdmx-sid-players).

Its fingerprint#

  • Tognon's 2003 signature for finding the player in any .sid: the code that reads the next pattern byte and tests the portamento commands — INC $xxxx,X / BNE / CMP #$FB / BCC / CMP #$FB / BNE / LDA #$01 / STA $xxxx,X / INY / INC $xxxx,X / LDA ($xx),Y, in Perl '\xFE..'.'\xD0.'.'\xC9\xFB'.'\x90\x20'.'\xC9\xFB'.'\xD0\x18'.'\xA9\x01'.'\x9D..'.'\xC8'.'\xFE..'.'\xB1' with every relocatable address wildcarded (.) — chosen "as the code is very characteristic" (source: s-sidin03-pattern-searching-1; see player-identification).

V4.2 as Tognon reads it (SIDin #14, 2015)#

Tognon's line-by-line commented edition of Gray's dom6-public.asm settles the V4.2 command set and instrument layout; where it differs from the Driller-based cheat sheet above, this section wins (source: s-sidin14-dominator-player).

  • Pattern bytes: $00 rest (gate off), $01–$6F note, $70–$F8 duration kk − $70 (one byte instead of Driller's $FD kk; the bars' $AF, $DF, $EF are durations 63, 111, 127), $F9 nn vibrato delay, $FA nn instrument, $FB mm / $FC kk slide down / up, $FD ci plexc notes from table i ($FD,$36 = table 6 × 3 notes) — and $FF end. $FD is no longer the duration command. A slide lasts one note and cancels plex and vibrato; a plex holds until the next instrument or slide (source: s-sidin14-dominator-player).
  • Instrument rows (VDATA / VDATA2, 16 bytes; up to 32 instruments): 0 pulse start as swapped nibbles · 1 control register · 2 AD · 3 SR · 4 pulse step · 5 unused (the Driller arpeggio byte) · 6 control register 2, written gate-off on instrument change and before the main control register at each note · 7 effect bits 1 drum table, 2 pulse modulation, 4 implex, 16 hat — then 8 vibrato step · 9 vibrato length · 10 implex control register · 11 slide value · 12 slide flag (1 down, 2 up, 3 / 4 on the high byte) · 13 drum-table index · 14 pulse limits as nibbles $LH = bounce between $0Lxx and $0Hxx (fixed at $08/$0E in Driller) · 15 unused (source: s-sidin14-dominator-player).
  • Drum tables: DTL/DTH point to up to 32 tables of (control, value) pairs ending in $FF, one pair per frame; 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 note's high byte — so DT is noise at $30xx, triangle at note − $0200, pulse at note − $0400, then gate-off noise frames at $30, $15, $20, $10(source: s-sidin14-dominator-player).
  • Hat (bit 16): one frame of noise ($81) with frequency high byte $50 at every tempo tick, then the instrument's own waveform and pitch return — the Sanxion-style "small hat on each note" as an instrument flag. Fade-out: $FE in a track now loads FADE = $5F, and the volume steps down one level every $5F frames until the tune stops — absent in Driller (source: s-sidin14-dominator-player).
  • Housekeeping: the player sits at STARTADD = $C000 (movable, minimum $1000), raster IRQ at 1×; speed per tune in TDATA .BYTE 0,5,3,4, and the released file holds three songs (TUNE, OVER, FIN; TN starts at 3); an unused transpose variable TP; the note table NTL/NTH starts at C0 = 268 (15.73 Hz) and puts A4 at 424 Hz on PAL — Gray: "I was sure I got the frequencies from the back of the C64 Reference manual", an accident he noticed only when remaking the tunes (sources: s-sidin14-dominator-player, s-sidin15-matt-gray-interview).
  • Tognon's empty template empty_public.asm (one tune, 32 instruments, 166 patterns, 32 drum tables, 16 plex tables) and his seven steps to a tune are on dominator (source: s-sidin14-dominator-player).

The Serpent Demo build: a fourth, sample voice (SIDin #15)#

Between Driller and Dominator sits the engine of the Serpent Demo, reverse-engineered by Tognon in 2015: the Driller command set and instruments (duration $FD kk, arpeggio in instrument byte 5, fixed pulse limits, the EOR #$23 noise effect) plus a sample track (source: s-sidin15-serpent-demo-player).

  • Every song has a fourth pointer pair VOICE4LO/HI; its patterns share BARLO/BARHI with the SID voices but use three commands of their own: NN = sample speed (the CIA 2 Timer A low byte, high byte 1 — smaller is faster and higher), $FD vv = length in tempo ticks, $FA bi = bank nibble + sample index; $FF ends the pattern, $FF/$FE restart/end the track as usual (chip-samples; source: s-sidin15-serpent-demo-player).
  • The IRQ still runs MAIN for the three voices and then MAINEXTRA for the sample track; the timer's NMI calls SAMPLEROUTINE, which writes one 4-bit value — the high nibble, then the low nibble of the same byte — to $D418 per interrupt; when the pointer's high byte reaches BANKEND the sample stops or restarts from the BANKHI1 page. Music volume is $09 while no sample plays ($0E at init), so a drum peak of 15 sits well above the music — Gray: "the levels on the drums are too loud" (sources: s-sidin15-serpent-demo-player, s-sidin15-matt-gray-interview).
  • Seven samples SM10 … SM1F occupy 4 KB from $1000 ahead of the code; T29, the first sample pattern, plays sample 3 at speeds $01 … $40 in a row — a hand-written pitch sweep; a second song, EMPTY, plays only sample pattern T16 (a test); three unused tracks and two undeclared patterns in the file are from the Hunter's Moon tune (hunters-moon). The eight PLEX tables are four-note chords ($00,$03,$07,$0C, $00,$04,$07,$0C, $13,$0C,$07,$00 …) (chord-arpeggio; source: s-sidin15-serpent-demo-player).
  • Gray in 2015: the player took "about 4-6 months" and was refined "over the next 18 months"; "created from scratch", with Hubbard's drum-table idea borrowed but "always coded from scratch, not cut and pasted"; a vibrato "very different to his and Martin Galway's"; "my routine didn't take much memory or raster time, no more than any of my rivals"; filters only "post Dominator on Vendetta" — the fourth build, which Tognon left unanalysed (sources: s-sidin15-matt-gray-interview, s-sidin15-serpent-demo-player).

Around the player#

  • The composing loop it sat in: "On the C64 it was basically working out melody & chord ideas on a small 3 octave casio keyboard and then inputting the data manually via a 6502 assembler. I designed all the sounds within my SID player from scratch usually. If you wanted any mod routines on the sound you had to code them. It was real low level coding. Nothing much existed unless you coded it" — the player is the instrument design, which is why each game refined it (tracking-workflow, instrument-design; source: s-retrogamesmaster-matt-gray-interview).
  • Beside another engine, in one game: Hunter's Moon (Thalamus, 1987) runs Gray's engine for the music and Martin Walker's separate table-driven engine for the sound effects — which uses up to all three voices per effect, and whose pulse step bounces between $08xx and $0Exx exactly as Gray's does (hunters-moon, sound-effects; source: s-sidin14-hunters-moon).

matt-gray · driller · dominator · last-ninja-2 · sidin · sid-player-routine · instrument-tables · musicfile · soundmonitor · goattracker · sid-wizard

Sources#

s-sidin02-matt-gray-driller · s-matt-gray-dominator-source · s-c64com-matt-gray-interview · s-vgmpf-matt-gray · s-realdmx-sid-players · s-rvg-matt-gray-interview · s-vandalism63-matt-gray-interview · s-arcadeattack-matt-gray-interview · s-remix64-ninja-remix · s-sidid-player-list · s-sidin03-pattern-searching-1 · s-sidin14-dominator-player · s-sidin15-matt-gray-interview · s-sidin15-serpent-demo-player · s-retrogamesmaster-matt-gray-interview · s-sidin14-hunters-moon

source file wiki/entities/matt-gray-player.md · graph