Driver Technical Information
Note: Since this is Z80 code, all words are little-endian unless otherwise stated.
Memory Layout
Address |
Size |
Description
|
$DD00
|
Byte
|
Unused
|
$DD01
|
Byte
|
Global speed counter.
|
$DD02
|
Byte
|
Global speed counter reset.
|
$DD03
|
Byte
|
Main Trigger.
|
$DD04
|
Byte
|
Trigger 1.
|
$DD05
|
Byte
|
Trigger 2.
|
$DD06
|
Byte
|
Trigger 3.
|
$DD07
|
Byte
|
Unknown.
|
$DD08
|
Byte
|
Reset/Disable Trigger
|
$DD09
|
Byte
|
Fade-out countdown - major value.
|
$DD0A
|
Byte
|
Fade-out countdown - minor value.
|
$DD0B
|
Byte
|
Fade-out countdown - minor reset value.
|
$DD0C
|
Byte
|
Unknown.
|
$DD0D
|
Byte
|
Current sound effect number.
|
$DD0E
|
Byte
|
Unknown
|
$DD0F
|
Byte
|
Sound priority.
|
$DD10
|
Byte
|
Unknown.
|
$DD11
|
Byte
|
Unknown (noise channel related).
|
$DD12
|
Byte
|
Unknown.
|
$DD13
|
Byte
|
Unknown.
|
$DD14
|
Byte
|
Unknown.
|
$DD15
|
Byte
|
Unknown (noise channel related).
|
$DD16
|
Byte
|
Noise channel attenuation.
|
$DD17
|
40 Bytes
|
Unused.
|
$DD40
|
48 Bytes
|
Primary channel 0 structure.
|
$DD70
|
48 Bytes
|
Primary channel 1 structure.
|
$DDA0
|
48 Bytes
|
Primary channel 2 structure.
|
$DDD0
|
48 Bytes
|
Primary channel 3 (noise) structure.
|
$DE00
|
48 Bytes
|
Secondary channel 0 structure.
|
$DE30
|
48 Bytes
|
Secondary channel 1 structure.
|
$DE60
|
48 Bytes
|
Secondary channel 2 structure.
|
Channel Structures
Each channel occupies 48 bytes of RAM:
Offset |
Type |
Description
|
$00
|
Byte
|
Control flags.
|
$01
|
Byte
|
PSG channel number.
|
$02
|
Unsigned Byte
|
Channel tempo.
|
$03
|
Word
|
Data pointer.
|
$05
|
Signed Byte
|
Pitch adjustment.
|
$06
|
Signed Byte
|
Volume adjustment.
|
$07
|
Byte
|
Pitch effect flags.
|
$08
|
Byte
|
Volume effect flags.
|
$09
|
Unsigned Byte
|
Channel branch "stack" pointer.
|
$0A
|
Unsigned Byte
|
Note duration counter.
|
$0B
|
Unsigned Word
|
PSG tone register value (i.e. the value written to the PSG to generate the note).
|
$0D
|
Unsigned Byte
|
Note duration reset value.
|
$0E
|
Byte
|
Unknown.
|
$0F
|
Byte
|
Unknown.
|
$10
|
Word
|
Data pointer for pitch bend effect.
|
$12
|
Signed Word
|
Pitch bend effect adjustment value. Added to word at $0B before writing to the PSG.
|
$14
|
Unsigned Byte
|
Number of ticks to wait before starting pitch bend.
|
$15
|
Unsigned Byte
|
Number of ticks to wait before increasing the pitch bend. Also used as the pitch envelope index.
|
$16
|
Signed Byte
|
Pitch bend step size.
|
$17
|
Unsigned Byte
|
Number of pitch bend steps before negating step value.
|
$18
|
5 Bytes
|
Unused.
|
$1D
|
Byte
|
Volume effect flags?
|
$1E
|
Byte
|
Unknown (volume effect related).
|
$1F
|
Unsigned Byte
|
Channel volume / Volume envelope index.
|
$20
|
Signed Byte
|
Volume Effects - Adjustment value.
|
$21
|
4 Bytes.
|
Volume effect memory.
|
$25
|
Signed Byte
|
Detune value.
|
$26
|
Byte
|
Unused.
|
$27
|
3 Bytes
|
Loop counters.
|
$2A
|
3 Words
|
Branch return address stack.
|
Channel Control Flags
Bit |
Description
|
0
|
Unknown.
|
1
|
Maintain effect state across notes.
|
2
|
Suppress PSG writes.
|
3
|
Triggers literal read mode.
|
4
|
Suppress writes to the PSG volume register.
|
5
|
Unknown.
|
6
|
Allow PSG volume updates only.
|
7
|
Channel active flag.
|
Pitch Effect Flags
Bit |
Description
|
0-6
|
If bit 7 = 0: pitch envelope number otherwise unused.
|
7
|
Set = pitch bend; Reset = pitch envelope.
|
Literal Read Mode
If bit 3 of the channel's control byte is set the driver enters literal read mode. This changes the way that data is read from the channel's stream: instead of reading bytes, the driver starts reading big-endian words (command bytes are still processed). These words are interpreted as PSG tone register values and are copied into offset $0B. The pitch adjustment at $05 is sign-extended to 16-bits and treated as a detune value which is added to the word before copying to the offset. Each word must be followed by a duration byte.
Module Editing
Offset |
Size |
Description
|
$00
|
Word
|
Unused. Was probably intended as a pointer to volume envelope data but the driver ignores it.
|
$02
|
Byte
|
Number of channels.
|
$03
|
Byte
|
Unused. Skipped by the driver.
|
$04
|
Byte
|
Channel tempo. Copied into offset $02 of each channel structure.
|
$05
|
Byte
|
Global speed. Copied into $DD01 and $DD02
|
Following the module header are the channel headers. The number of channel headers must match the value at offset $02 in the module header.
Offset |
Size |
Description
|
$00
|
Word
|
Channel data pointer (absolute).
|
$02
|
Byte
|
Pitch adjustment.
|
$03
|
Byte
|
Volume adjustment.
|
Commands
Command |
Description
|
$00 - $7F
|
Duration values.
|
$80 - $DF
|
Notes ($80 = rest).
|
$E0vvwwxxyyzz
|
Volume effects (parameters currently unknown).
|
$E1xx
|
Detune - xx = amount (signed).
|
$E2xx
|
Adjust volume - xx = amount (signed).
|
$E3
|
Nothing (empty slot).
|
$E4xx
|
Adjust noise volume - xx = amount (signed).
|
$E5xx
|
Unknown.
|
$E6xx
|
Adjust volume - same as $E2.
|
$E7
|
Maintain effect state (sets bit 1 of channel control).
|
$E8xx
|
Unknown.
|
$E9
|
Nothing (empty slot).
|
$EA
|
Nothing (empty slot).
|
$EB
|
Nothing (empty slot).
|
$EC
|
Nothing (empty slot).
|
$EDxx
|
Set global speed - xx = new speed.
|
$EE
|
Nothing (empty slot).
|
$EF
|
Invalid command (points into data).
|
$F0wwxxyyzz
|
Pitch Bend -
- ww - Number of ticks to wait.
- xx - Number of ticks before increasing pitch bend.
- yy - Pitch bend step size.
- zz - Number of ticks before negating step size.
|
$F1
|
Invalid command (points into data).
|
$F2
|
Stop channel playback.
|
$F3??
|
Unknown.
|
$F4xx
|
Pitch envelope - xx = envelope number.
|
$F5xx
|
Volume envelope - xx = envelope number.
|
$F6xxxx
|
Jump - xxxx = absolute address.
|
$F7xxyyzzzz
|
Loop
- xx - Slot number.
- yy - Loop count.
- zzzz - Absolute address.
|
$F8xxxx
|
Branch - xxxx = absolute address.
|
$F9
|
Return from branch.
|
$FAxx
|
Set channel speed - xx = new speed.
|
$FBxx
|
Pitch adjustment - xx = adjustment (added to current value).
|
$FC
|
Nothing (empty slot).
|
$FDxx
|
Set read literal mode. Turned on if xx == $01, otherwise off.
|
$FE
|
Nothing (empty slot).
|
$FF
|
Nothing (empty slot).
|