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:
| byte | name | arguments | effect |
|---|---|---|---|
$80 | JUMP | addr | go to |
$81 | CALL | addr | call a phrase (5-deep stack shared with LOOP) |
$82 | RET | return, and reset the transpose | |
$83 … $84 | LOOP n … NEXT | repeat | |
$85 | BEND | dir, step, length, offset16 | bend into the next note: the frequency is pre-offset by step × length and climbs to the written pitch |
$86 | PATCH | n | select a 5-byte patch |
$87 | LENGTH | frames | auto-duration mode |
$88 / $89 | VIBON / VIBOFF | delay, rate, depth | triangle vibrato on the 16-bit frequency (cancels an arpeggio) |
$8a / $8b | ARPON / ARPOFF | addr | arpeggio table (suppresses vibrato and bend while active) |
$8c | MANUAL | back to note,duration pairs | |
$8d | PWM | n | select a 5-byte pulse-sweep entry |
$8e / $92 | FILTER / FILTOFF | empty handlers | |
$8f | END | stop the voice | |
$90 | TRANSPOSE | n | signed semitones |
$91 | CT | n, addr | transposed CALL — the harmony device |
$93 | MODE | mask | bit 7 of the mask = set, else clear: gate writes, pulse retrigger per note, "pluck" mode |
$94 | DRUM | n, transpose[, duration] | voice C only |
$95 | PORT | value, sid-offset | write any SID register (volume $18) |
$96 | CODE | addr | JSR into the music data (fades, ramps) |
$97 | EFFECT | note | every note starts at that (absolute or relative) pitch until its release point — a pluck |
Durations: TEMPO = 5 → SQ 5, QV 10, CR 20, MN 40, SB 80; TEMPO2 = 6 → SQ2 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:
| patch | bytes | sound |
|---|---|---|
| DT88 00 | $51,$00,$C8,3,$40 | triangle + pulse, 3 frames, released as pulse |
| DT88 01 | $01,$00,$88,2,$42 | gate with no waveform for 2 frames, then pulse + sync — heard only in release |
| DT88 02 | $55,$00,$99,3,$40 | triangle + pulse + ring |
| DT88 05 | $81,$00,$A8,3,$10 | 3 frames of noise, then triangle — a click transient |
| DT88 09 | $11,$AA,$79,QV2+SQ2+GAP,$10 | the only patch with an attack — the title pad |
| DT88 13 | $41,$00,$88,4+GAP,$14 | pulse, released as triangle + ring |
| Loader 0 | $43,$00,$7B,96+GAP,$22 | pulse + sync, gate off 96 frames before the end, released as sawtooth + sync — the lead |
| Loader 1 | $41,$00,$AD,3,$40 | the 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.