This is an old revision of the document!
Table of Contents
Appendix 5 Sound System
This is Appendix 5 of the SD-8516 Programmer's Reference Guide.
Introduction
The SD-8516 is paired with the SD-450 sound subsystem; named for featuring 4 independent voices with 5 waveforms available, each with a programmable ADSR envelope. Let's dive in with an overview of the architecture and a quick look at INT 11h, the sound services library. If you are just interested in how to play sounds and music in your own games, you can skip ahead to Sounds and Music.
Voice Architecture
Each voice occupies 16 bytes of memory in Bank 1:
| Offset | Register | Description |
|---|---|---|
| +$00 | FREQ_LO | Frequency low byte |
| +$01 | FREQ_MID | Frequency mid byte |
| +$02 | FREQ_HI | Frequency high byte |
| +$03 | GATE | Waveform/gate control |
| +$04 | VOLUME | Volume (0-255) |
| +$05 | ATTACK | Attack time |
| +$06 | DECAY | Decay time |
| +$07 | SUSTAIN | Sustain level |
| +$08 | RELEASE | Release time |
| +$09 | DATA1 | Pulse width / noise type |
| +$09-$0F | DATA2-7 | Reserved - Future expansion |
Voice base addresses:
- Voice 0:
$1EF80 - Voice 1:
$1EF90 - Voice 2:
$1EFA0 - Voice 3:
$1EFB0
Waveforms
Gate register values:
- 0: Silent (gate off)
- 1: Square wave
- 2: Triangle wave
- 3: Sawtooth wave
- 4: Sine wave
- 5: Pulse wave (variable width via DATA1)
- 6: White/pink/brown noise (type via DATA1)
ADSR Envelope
The Attack-Decay-Sustain-Release envelope shapes each note:
- Attack: Time to reach peak volume (0-255 × 10ms)
- Decay: Time to decay to sustain level (0-255 × 10ms)
- Sustain: Held volume level (0.0-1.0 of peak)
- Release: Time to fade to silence after gate off (0-255 × 10ms)
Example:
; Play middle C on voice 0
LDA $112B ; C4 frequency (262 Hz / 0.0596)
STA [$1ED00] ; $01ED00 = FREQ_LO/MID
LDA #0
STA [$1ED02] ; $01ED02 = FREQ_HI
LDAL $4D ; Initialize volume to ~30%
STAL [$1ED03] ; $1ED03 = VOLUME
LDAL $01 ; Square wave
STAL [$1ED02] ; set GATE to square wave (i.e. turn on)
You can also use the sound services library (I
Sound System Memory Map
Also see Appendix 3 Memory Map.
Sound System Memory Map
The sound system memory map occupies ($01EF80–$01EFBF) – 64 bytes total
| Address Range | Size | Symbol / Register | Description |
|---|---|---|---|
| $01EF80–$01EF8F | 16 bytes | SOUND0_BASE | Voice 0 |
| $01EF80 | 1 byte | SOUND0_FREQ_LO | Frequency low byte (bits 7–0) |
| $01EF81 | 1 byte | SOUND0_FREQ_HI | Frequency high byte (bits 15–8) |
| $01EF82 | 1 byte | SOUND0_GATE | Gate / Waveform select (gate bit + waveform type: noise, pulse, saw, triangle, etc.) |
| $01EF83 | 1 byte | SOUND0_VOLUME | Master volume for voice 0 (usually 0–15, may include global volume in some implementations) |
| $01EF84 | 1 byte | SOUND0_ATTACK | Attack rate (0–15) |
| $01EF85 | 1 byte | SOUND0_DECAY | Decay rate (0–15) |
| $01EF86 | 1 byte | SOUND0_SUSTAIN | Sustain level (0–15) |
| $01EF87 | 1 byte | SOUND0_RELEASE | Release rate (0–15) |
| $01EF88 | 1 byte | SOUND0_DATA1 | Voice-specific control / extra parameter 1 (e.g. pulse width low, filter routing, etc.) |
| $01EF89 | 1 byte | SOUND0_DATA2 | Voice-specific control / extra parameter 2 (e.g. pulse width high, ring/mod flags, etc.) |
| $01EF8A–$01EF8F | 6 bytes | — | Reserved / unused / future expansion for Voice 0 |
| Address Range | Size | Symbol / Register | Description |
|---|---|---|---|
| $01EF90–$01EF9F | 16 bytes | SOUND1_BASE | Voice 1 |
| $01EF90 | 1 byte | SOUND1_FREQ_LO | Frequency low byte |
| $01EF91 | 1 byte | SOUND1_FREQ_HI | Frequency high byte |
| $01EF92 | 1 byte | SOUND1_GATE | Gate / Waveform select |
| $01EF93 | 1 byte | SOUND1_VOLUME | Volume for voice 1 |
| $01EF94 | 1 byte | SOUND1_ATTACK | Attack rate |
| $01EF95 | 1 byte | SOUND1_DECAY | Decay rate |
| $01EF96 | 1 byte | SOUND1_SUSTAIN | Sustain level |
| $01EF97 | 1 byte | SOUND1_RELEASE | Release rate |
| $01EF98 | 1 byte | SOUND1_DATA1 | Extra control 1 |
| $01EF99 | 1 byte | SOUND1_DATA2 | Extra control 2 |
| $01EF9A–$01EF9F | 6 bytes | — | Reserved / unused / future expansion for Voice 1 |
| Address Range | Size | Symbol / Register | Description |
|---|---|---|---|
| $01EFA0–$01EFAF | 16 bytes | SOUND2_BASE | Voice 2 |
| $01EFA0 | 1 byte | SOUND2_FREQ_LO | Frequency low byte |
| $01EFA1 | 1 byte | SOUND2_FREQ_HI | Frequency high byte |
| $01EFA2 | 1 byte | SOUND2_GATE | Gate / Waveform select |
| $01EFA3 | 1 byte | SOUND2_VOLUME | Volume for voice 2 |
| $01EFA4 | 1 byte | SOUND2_ATTACK | Attack rate |
| $01EFA5 | 1 byte | SOUND2_DECAY | Decay rate |
| $01EFA6 | 1 byte | SOUND2_SUSTAIN | Sustain level |
| $01EFA7 | 1 byte | SOUND2_RELEASE | Release rate |
| $01EFA8 | 1 byte | SOUND2_DATA1 | Extra control 1 |
| $01EFA9 | 1 byte | SOUND2_DATA2 | Extra control 2 |
| $01EFAA–$01EFAF | 6 bytes | — | Reserved / unused / future expansion for Voice 2 |
| Address Range | Size | Symbol / Register | Description |
|---|---|---|---|
| $01EFB0–$01EFBF | 16 bytes | SOUND3_BASE | Voice 3 |
| $01EFB0 | 1 byte | SOUND3_FREQ_LO | Frequency low byte |
| $01EFB1 | 1 byte | SOUND3_FREQ_HI | Frequency high byte |
| $01EFB2 | 1 byte | SOUND3_GATE | Gate / Waveform select |
| $01EFB3 | 1 byte | SOUND3_VOLUME | Volume for voice 3 |
| $01EFB4 | 1 byte | SOUND3_ATTACK | Attack rate |
| $01EFB5 | 1 byte | SOUND3_DECAY | Decay rate |
| $01EFB6 | 1 byte | SOUND3_SUSTAIN | Sustain level |
| $01EFB7 | 1 byte | SOUND3_RELEASE | Release rate |
| $01EFB8 | 1 byte | SOUND3_DATA1 | Extra control 1 |
| $01EFB9 | 1 byte | SOUND3_DATA2 | Extra control 2 |
| $01EFBA–$01EFBF | 6 bytes | — | Reserved / unused / future expansion for Voice 3 |
INT 11h Sound Services
; ============================================================================
; INT 11h - SOUND & MUSIC SERVICES
; SD-450 Sound Interface Device + Music Player
; ============================================================================
;
; REGISTER CONVENTION:
; AH = command
; AL = voice (1-4 for music commands, 0-3 for hardware channel)
; B = data (BL=low, BH=high; or BL=single byte)
; C = additional data
; D, E, F = extended data (for AH=30h "new instrument")
;
; FUNCTION MAP:
; --- Music Player Control ---
; AH=00h: Poll music player (check tick timer, advance if ready)
; AH=01h: Execute next note group from song data
; AH=02h: Set clock for next note group
; AH=03h: Execute a single music command
; AH=04h: Reset music player (stop + rewind to start)
; AH=05h: Start / continue music player
; AH=06h: Pause / unpause (AL=00 pause, AL=01+ unpause)
; AH=07h: Load new song (pointer, tempo, calc tick length)
; AH=08h: Insert note data by index
; AH=09h: Delete note data by index
; AH=0Ah: Ask JavaScript to LOAD a music file
; AH=0Bh: Ask JavaScript to SAVE a music file
;
; --- Direct Sound Commands (also used by music file data) ---
; AH=10h: Turn off voice
; AH=11h: Turn on as square (+3 bytes freq: BL, BH, CL)
; AH=12h: Turn on as triangle (+3 bytes freq)
; AH=13h: Turn on as sawtooth (+3 bytes freq)
; AH=14h: Turn on as sine (+3 bytes freq)
; AH=15h: Turn on as PWM (+3 bytes freq)
; AH=16h: Turn on as noise (+3 bytes freq)
; AH=17h: Turn on as waveform byte + note index
; (BL=note index 1-88, BH=waveform 01-06)
; AH=21h: Set GATE (BL = gate byte)
; AH=22h: Set FREQ (BL=lo, BH=mid, CL=hi)
; AH=23h: Set ATTACK (BL = attack byte)
; AH=24h: Set SUSTAIN (BL = sustain byte)
; AH=25h: Set RELEASE (BL = release byte)
; AH=26h: Set DATA1 (BL = data1 byte)
; AH=27h: Set DATA2 (BL = data2 byte)
; AH=28h: Set VOLUME (BL = volume byte)
; AH=29h: Set DECAY (BL = decay byte)
; AH=30h: Set new voice data at-once (10 bytes: BCDEF)
;
; --- Legacy / Utility ---
; AH=40h: Initialize sound system
; AH=41h: Play note (blocking, with duration)
; AH=42h: Stop channel
; AH=43h: Stop all channels
; AH=44h: Set master volume
; AH=45h: Get channel status
; AH=46h: Sound effect (bell, beep, buzz, etc.)
; AH=47h: Play startup sound (GECF)
; AH=48h: Wait milliseconds (C = ms)
; AH=49h: Note index to frequency lookup (BH=index, returns B:CL)
;
; ============================================================================
