Paul Hughes's Ocean music driver (Jonathan Dunn's player) cheat sheet

From Paul Hughes's Ocean music driver (Jonathan Dunn's player) · print · built 2026-08-31

Reference

Cheat sheet#

All from the two sources (source: s-realdmx-ocean-dunn-hughes-driver).

Voice program — bytes $00–$5d notes (C0 = 0 … A7 = 93, sharps CS4), 94 = REST; in manual mode every note/rest is followed by its duration in frames, after LENGTH n (auto mode) each note lasts n. Commands:

bytenameargumentseffect
$80JUMPaddrgo to
$81CALLaddrcall a phrase (5-deep stack shared with LOOP)
$82RETreturn, and reset the transpose
$83$84LOOP n … NEXTrepeat
$85BENDdir, step, length, offset16bend into the next note: the frequency is pre-offset by step × length and climbs to the written pitch
$86PATCHnselect a 5-byte patch
$87LENGTHframesauto-duration mode
$88 / $89VIBON / VIBOFFdelay, rate, depthtriangle vibrato on the 16-bit frequency (cancels an arpeggio)
$8a / $8bARPON / ARPOFFaddrarpeggio table (suppresses vibrato and bend while active)
$8cMANUALback to note,duration pairs
$8dPWMnselect a 5-byte pulse-sweep entry
$8e / $92FILTER / FILTOFFempty handlers
$8fENDstop the voice
$90TRANSPOSEnsigned semitones
$91CTn, addrtransposed CALL — the harmony device
$93MODEmaskbit 7 of the mask = set, else clear: gate writes, pulse retrigger per note, "pluck" mode
$94DRUMn, transpose[, duration]voice C only
$95PORTvalue, sid-offsetwrite any SID register (volume $18)
$96CODEaddrJSR into the music data (fades, ramps)
$97EFFECTnoteevery note starts at that (absolute or relative) pitch until its release point — a pluck

Durations: TEMPO = 5SQ 5, QV 10, CR 20, MN 40, SB 80; TEMPO2 = 6SQ2 6, QV2 12, DQV2 18, CR2 24, DCR2 36, MN2 48, SB2 96 (a 4/4 bar). Example: DITTY2: PATCH,1,PWM,1 / ARPON ARP2 / LENGTH,SQ / CALL MEL1 / CT,-5 MEL1 / CT,-12 MEL1 / CT,-17 MEL1 / D4 / END with MEL1: LOOP,2 / F4,G4,F4,D5 / NEXT / RET. The loader: MANUAL / PATCH,1,PWM,1 / VIBON,0,9,6 / EFFECT,12 / BEND,UP,$10,48 / !wo $10*48 / C2,192 ….

Patch = 5 bytes: gate-on control byte, AD, SR, hold (frames; bit 7 GAP = "N frames before the next note" instead of "N frames after note-on"), gate-off control byte — two waveforms per instrument:

patchbytessound
DT88 00$51,$00,$C8,3,$40triangle + pulse, 3 frames, released as pulse
DT88 01$01,$00,$88,2,$42gate with no waveform for 2 frames, then pulse + sync — heard only in release
DT88 02$55,$00,$99,3,$40triangle + pulse + ring
DT88 05$81,$00,$A8,3,$103 frames of noise, then triangle — a click transient
DT88 09$11,$AA,$79,QV2+SQ2+GAP,$10the only patch with an attack — the title pad
DT88 13$41,$00,$88,4+GAP,$14pulse, released as triangle + ring
Loader 0$43,$00,$7B,96+GAP,$22pulse + sync, gate off 96 frames before the end, released as sawtooth + sync — the lead
Loader 1$41,$00,$AD,3,$40the bend bass

PWM entry (5 bytes): rate, frames up, frames down, initial width (word)$80,$00,$02 / $0F50; $F0,$04,$04 / $0800; loader $40,48,42 / $0000. Arpeggio table: frames per step, steps, offsets…ARP1 !by 3,4,0,4,7,9, ARP2 !by 1,3,24,12,0, TARP1 !by 2,3,0,3,7. Drum (7-byte entry: wave ptr, freq ptr, length, SR, pulse-hi; AD forced $00): BASS DRUM $41,$41,$10,$80 / $0E,$06,$0F,$10; SNARE $41,$41,$40,$80,$80,$80,$10,$80,$10,$80,$80,$10,$80 / $11,$0C,$08,$70,$70,$2F,$0C,$2E,$0C,$2D,$BC,$0C,$2B; HI-HAT $11,$11,$80,$80,$80 / $10,$10,$70,$20,$30. Fades are self-modifying data: FADEPOS !by PORT,$0F,$18 with TFADEAWAY DEC FADEPOS+1 in a loop.