Rob Hubbard's driver (the Monty on the Run player) cheat sheet
From Rob Hubbard's driver (the Monty on the Run player) · print · built 2026-08-31
Reference
Cheat sheet#
All values from the two disassemblies (source: s-realdmx-hubbard-player).
Song structure: init (A = song) copies three track pointers; a track is a list of pattern numbers, $ff = restart the track, $fe = stop. A pattern is a stream of notes ended by $ff.
Note entry (1–3 bytes):
| byte | bits | meaning |
|---|---|---|
| 1 | 0–4 | length in ticks, 0–31 |
| 1 | 5 | "no release": do not clear the gate (and do not zero AD/SR) when the length runs out |
| 1 | 6 | extension: a one-byte entry that adds its length to the current note; the registers are re-written with the gate off, so the tail is the release ($7f = +32 ticks, keep ADSR; $5f = +32 ticks, then cut) |
| 1 | 7 | a second byte follows |
| 2 | 7 = 0 | instrument number |
| 2 | 7 = 1 | portamento: bits 1–6 the frequency step per frame, bit 0 the direction (0 = up, 1 = down) — e.g. $90 = +16/frame, $99 = −24/frame, $e8 = +104/frame |
| 3 | note, $00 = C-0 … $5f = B-7 (frequency table $0116 … $fd2e) |
Examples: $83,$00,$37 = 4 ticks, instrument 0, G-4; $bf,$0c,$56,$7f,$7f = a 32-tick note held for 64 more ticks in release; $af,$90,$35 = 16 ticks of pitch bend up. Note-off is the end of the length, and without bit 5 it writes $00 to AD and SR — an instant cut (hard-restart).
Instrument (8 bytes):
| # | byte | values |
|---|---|---|
| 0 | pulse width lo | |
| 1 | pulse width hi | $08–$0e if the pulse sweep is used |
| 2 | control register with gate | $41 pulse, $81 noise, $11 triangle |
| 3 | attack/decay | |
| 4 | sustain/release | $ff for skydive notes that must keep sounding through their extensions |
| 5 | vibrato depth | 0 = off; n = step of a semitone ÷ 2^(n+1); needs a note of 8+ ticks (Commando: 6+) |
| 6 | pulse modulation | bits 0–4 delay in frames between steps, bits 5–7 step ($20, $40 …); the width bounces between $0800 and $0eff; with flag $08 (Commando only) the whole byte is added to the low byte every frame instead |
| 7 | effect flags | $01 drum, $02 skydive, $04 octave arpeggio, $08 pulse-lo modulation (Commando); they combine ($05 = drum + arpeggio) |
Rows from Monty on the Run: $80,$09,$41,$48,$60,$03,$81,$00 (lead: pulse, vibrato 3, slow 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 + octave arpeggio) · $00,$00,$11,$0a,$fa,$00,$00,$05 (triangle drum + arpeggio). From Commando: $52,$01,$41,$09,$9f,$00,$16,$08 (bass, pulse-lo modulation) · $00,$02,$81,$0a,$09,$00,$00,$05 (snare).
The effects
| effect | what the code does |
|---|---|
| vibrato | 8-frame sequence 0,1,2,3,3,2,1,0 × step, added to the note frequency (bends upward only) |
| pulse sweep | add the step every delay frames; reverse at hi byte $0e / $08; modifies the instrument bytes in place |
| portamento | add/subtract the step to the 16-bit frequency every frame for the length of the note |
drum $01 | first tick noise ($80), then each frame the instrument waveform with the gate off while the frequency high byte decrements by 1 — "fast attack/decay and a rapid downwards frequency slide" (wavetable-programming) |
skydive $02 | every 2nd frame decrement the frequency high byte until 0 (Commando's variant increments by 2) |
octave arpeggio $04 | odd frames note + 12, even frames the note — a 25 Hz octave trill (octave-bass) |
Processing order per frame: note fetch → vibrato → pulse → portamento → drum → skydive → arpeggio.