realdmx: Rob Hubbard's driver — McSweeney's Monty on the Run disassembly and the Commando title
Two files from the realdmx collection (s-realdmx-sid-players) hold the 6502 driver rob-hubbard used, per the header, "(with small modifications) for his first approx. 30 tunes": Anthony McSweeney's commented disassembly of monty-on-the-run (1985, Gremlin Graphics), and a separately labelled disassembly of the commando title (1985, Elite). Together they show what a "Hubbard routine" is: about 1 KB of code, a 3-byte note format, 8-byte instruments, and three flag-bit effects — drum, "skydive" and octave arpeggio — that Newman's article only names (s-newman-driving-the-sid-chip). The page hubbard-player carries the cheat sheet.
Key claims#
Provenance and shape
- Monty header: "Rob Hubbard Music Driver / Original disassembly and commenting by Anthony McSweeney / Port to ACME by dmx87 / This player was used (with small modifications) for his first approx. 30 tunes". PSID: one song, load
$8000,initandplayarejmp initmusic/jmp playmusic. Commando: load$1000,init/playlikewise, one song; the file names note constants (C0 = $00 … H7 = $5f, GermanHfor B), anINSTRmacro and flag names — the reverse-engineer's conveniences, not Hubbard's. - Commando's variable labels carry their original addresses (
posoff … ; 14a2), so the player code plus its 192-byte note table occupies$1000–$14a1= 1186 bytes — about 1 KB of code, matching Newman's "900–1000 bytes" for McSweeney's disassembly (s-newman-driving-the-sid-chip). - The play routine runs once per frame and loops over the three voices (
ldx #2 … dex, register offsets$00,$07,$0e). A tempo counter (resetspd=$01in Monty; Commando reads it from a per-song table,songtempos !by 2) decides on which frames new note data is fetched; the effects (vibrato, pulse, portamento, drum, skydive, arpeggio) run every frame. So a "tick" in Monty is 2 frames and in Commando 3 frames, and note lengths are counted in ticks.
Song → tracks → patterns (orderlist)
inittakes the song number, multiplies by 6 and copies three track pointers (lo/hi) fromsongs; a track is a list of pattern numbers;$ffrestarts the track from its first entry,$festops the music. Pattern pointers sit in two tables (patptl/patpth). Monty: 60 patterns (ptn00–ptn3b,$2eempty), tracks of 65, 77 and 129 entries; Commando: 32 patterns.- A pattern is a byte stream of notes, each 1–3 bytes (McSweeney's header comment): Byte 1 — bits 0–4 the length in ticks (0–31), bit 5 "no release", bit 6 "retrig off", bit 7 "new instr/porta coming"; Byte 2 (only when bit 7 is set) — the instrument number, or a portamento speed if negative; Byte 3 — the note number (
$00= C-0 …$5f= B-7, a 96-entry frequency table$0116 … $fd2e).$ffends the pattern. - Read from the code: bit 6 makes a one-byte entry that extends the current note by its length without fetching a new note; the instrument registers are re-written with the gate bit masked off (
and appendfl— "clever eh?"), so the tail plays in the release phase, and with bit 5 also set the ADSR bytes are left alone. This is how notes longer than 32 ticks are written:ptn12: $bf,$0c,$56, $7f,$7f,$7f,$7f,$7f,$7f,$7f= instrument$0c, note$56, 32 ticks, then seven 32-tick extensions. Without bit 5 the end of a note clears the gate and writes$00to AD and SR — the note is cut with the fastest release (hard-restart). - Portamento is a pattern-level, per-note command: a second byte with bit 7 set, bits 1–6 the amount added to the 16-bit frequency every frame, bit 0 the direction (clear = up, set = down — the Commando file's constants
PBU = $81/PBD = $80name them the other way round; the code adds when bit 0 is clear). Monty's middle section (ptn30–ptn33) is full of them:$af,$90,$35(32 ticks, bend up 16/frame, note$35),$a7,$99,$37(down 24/frame),$a3,$e8,$35(up 104/frame) — Hubbard's "new pitch bend code" for this game (pitch-slide-and-portamento; the quote is in s-newman-driving-the-sid-chip).
Instruments — 8 bytes (instrument-tables): 0 pulse width lo, 1 pulse width hi, 2 control register (waveform + gate), 3 attack/decay, 4 sustain/release, 5 vibrato depth, 6 pulse-modulation byte, 7 effect flags. Monty has 20, Commando 13. Rows (Monty): $80,$09,$41,$48,$60,$03,$81,$00 (pulse lead with vibrato and PWM); $00,$08,$81,$02,$08,$00,$00,$01 (noise drum); $00,$09,$41,$3f,$ff,$01,$e7,$02 ; first skydive; $00,$08,$41,$08,$50,$02,$00,$04 (pulse with octave arpeggio); $00,$02,$81,$09,$09,$00,$00,$05 (drum + arpeggio); $00,$00,$11,$0a,$fa,$00,$00,$05 (triangle drum + arpeggio). Commando names two: $52,$01,$41,$09,$9f,$00,$16,$08 ; bass and $00,$02,$81,$0a,$09,$00,$00,$05 ; snare IARP | IDRUM.
The effects, as coded
- Vibrato (byte 5 ≠ 0; only for notes of 8+ ticks in Monty, 6+ in Commando): the frame counter
and #7, mirrored above 3, gives the sequence0,1,2,3,3,2,1,0("this is clever!!"); the step is the frequency difference to the next semitone shifted right depth+1 times; the frequency written is the note plus step × sequence value — an 8-frame triangle that only bends upwards from the note. Depth$02= steps of ⅛ semitone, peak ⅜ (vibrato). - Pulse (byte 6): bits 0–4 a delay in frames between steps, bits 5–7 the step (
$20, $40, $60 …) added to the pulse width; the direction flips when the high byte reaches$0egoing up or$08going down — every Hubbard pulse sweep lives between$0800and$0eff, and the routine modifies the instrument's own bytes 0–1 in place (pulse-width-modulation). Commando adds flag$08(IPWL, "pulse width lo modulation instead of pulse"): byte 6 is added to the low byte every frame, wrapping — used by its bass ($16per frame). - Drum (flag
$01): McSweeney's comment — "Drum timbre depends on ctrl register value for instrument. If ctrl is 0, it's all noise, otherwise ctrl waveform and noise after 1st vblank. Fast attack/decay and a rapid downwards frequency slide creates this sound". The code writes noise ($80) on the first tick and then, every frame, the instrument's waveform with the gate cleared while decrementing the frequency high byte. This is the "tell-tale" Hubbard drum (wavetable-programming). - Skydive (flag
$02): "The famous Hubbard signature effect — a long slide down from note to zero": every second frame the frequency high byte is decremented until it is 0. In the Commando file the same flag increments the high byte by 2 every second frame (for notes of 3+ ticks) — an upward sweep until the byte wraps; the file still calls it skydive. - Octave arpeggio (flag
$04): "Simple octave arpeggio, also a signature sound" — odd frames play note + 12, even frames the note, i.e. a 25 Hz octave trill (chord-arpeggio, octave-bass). Flags combine:$05= drum + arpeggio (Commando's snare), and the Commando file's comment onIARP: "octave arp, combine with ISKY for classic effect". - Order of processing each frame: note fetch (or gate-off check) → vibrato → pulse → portamento → drum → skydive → arpeggio; later effects overwrite the frequency written by earlier ones.
Practical takeaways#
- To make a "Hubbard drum" in a tracker: one frame of noise, then the instrument's waveform with the gate off, pitch falling by one frequency-high-byte unit per frame — an absolute-pitch wave table, as on wavetable-programming and monty-on-the-run.
- To make a Hubbard lead: pulse
$41, pulse width between$0800and$0e00, vibrato of an eighth-semitone step over an 8-frame triangle, delayed until the note is long enough. - Long skydive notes are "note + release": gate on for 32 ticks, then extensions with the gate off and a long release (
SR = $ff), while the skydive keeps decrementing. - The whole feature set fits in 1 KB because the effects are per-instrument bits, not per-note tables — the reason later trackers' "player types" exist (sid-player-routine).
Notable quotes#
- "Rob Hubbard Music Driver … This player was used (with small modifications) for his first approx. 30 tunes" (Monty header).
- "A clever little trick to create an oscillating value" (vibrato); "The famous Hubbard signature effect — A long slide down from note to zero" (skydive); "Simple octave arpeggio, also a signature sound" (McSweeney's comments).
Relevance to the wiki#
Primary source for hubbard-player; verifies from code the claims Newman and SIDwave make about the driver on rob-hubbard (McSweeney's disassembly, the drum, the "Monty player used in almost 30 games"); gives monty-on-the-run and commando their actual data; adds a fourth column to the driver comparison on sid-player-routine.
Pages touched#
hubbard-player · rob-hubbard · monty-on-the-run · commando · sid-player-routine · sidid · instrument-tables · wavetable-programming · vibrato · pulse-width-modulation · pitch-slide-and-portamento · chord-arpeggio · octave-bass · hard-restart · orderlist