Difference between revisions of "Sonic the Hedgehog 2 (Master System)/Music Hacking"
From Sonic Retro
m (Text replacement - "{| class=prettytable " to "{| class="prettytable" style="width:auto;" ") |
m (Text replacement - "{{SCHGuides}}" to "==References== <references /> {{SCHGuides}}") |
||
Line 463: | Line 463: | ||
| Nothing (empty slot) | | Nothing (empty slot) | ||
|} | |} | ||
+ | |||
+ | ==References== | ||
+ | <references /> | ||
{{SCHGuides}} | {{SCHGuides}} |
Revision as of 15:53, 24 March 2020
SCHG: Sonic 2 (Master System) |
---|
Main Article |
Art Editing |
Editing Art |
Level Editing |
Editing Levels |
Object Editing |
Editing Objects |
Music Editing |
Editing Music |
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 | Sound ID Main Trigger |
$DD04 | Byte | Sound ID Queue, Slot 1 |
$DD05 | Byte | Sound ID Queue, Slot 2 |
$DD06 | Byte | Sound ID Queue, Slot 3 |
$DD07 | Byte | Unused |
$DD08 | Byte | Pause Mode (00 - off, 01-7F - paused, 80-FF - do unpause) |
$DD09 | Byte | Fade-out countdown - major value |
$DD0A | Byte | Fade-out countdown - minor value |
$DD0B | Byte | Fade-out countdown - minor reset value |
$DD0C | Byte | Unused |
$DD0D | Byte | Current sound effect number |
$DD0E | Byte | Unused |
$DD0F | Byte | Current Sound priority |
$DD10 | Byte | Unused (Game Gear Stereo bits in later drivers) |
$DD11 | Byte | Current PSG noise mode |
$DD12-14 | 3 Bytes | Unused |
$DD15 | Byte | Unknown (modifies noise mode, never written and should always be 0) |
$DD16 | Byte | Noise channel attenuation |
$DD17 | 41 Bytes | Unused |
$DD40 | 48 Bytes | Music Channel 1 RAM (PSG 1) |
$DD70 | 48 Bytes | Music Channel 2 RAM (PSG 2) |
$DDA0 | 48 Bytes | Music Channel 3 RAM (PSG 3) |
$DDD0 | 48 Bytes | Music Channel 4 RAM (PSG Noise) |
$DE00 | 48 Bytes | SFX Channel 1 RAM (PSG 2) |
$DE30 | 48 Bytes | SFX Channel 2 RAM (PSG 3) |
$DE60 | 48 Bytes | SFX Channel 3 RAM (PSG Noise) |
Channel Structures
Each channel occupies 48 bytes of RAM:
Offset | Type | Description |
---|---|---|
$00 | Byte | Control flags |
$01 | Byte | PSG channel number |
$02 | Unsigned Byte | Note length multiplier |
$03 | Word | Data pointer |
$05 | Signed Byte | Transposition (added to note value) |
$06 | Signed Byte | Volume |
$07 | Byte | Pitch Envelope |
$08 | Byte | Volume Envelope |
$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 | Note Stop counter (number of frames after the note gets turned off) |
$0F | Byte | Note Stop reset value |
$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 | Volume effect mode (00 - normal, 08 - repeat Attack/Decay phase) |
$1F | Unsigned Byte | Volume effect value / Volume envelope index |
$20 | Signed Byte | Volume Effects - Adjustment value |
$21 | 4 Bytes. | Volume effect memory |
$25 | Signed Byte | Detune value (added to raw PSG frequency) |
$26 | Byte | Unused (Channel Stereo Bits in later drivers) |
$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 (i.e. music channel that is overridden by SFX) |
3 | Triggers literal read mode |
4 | Suppress writes to the PSG volume register (channel plays a rest) |
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
Module Header
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 | Note length multiplier. 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. (transposition) |
$03 | Byte | Volume adjustment. |
Commands
Command | Description |
---|---|
$00 - $7F | Duration values |
$80 - $DF | Notes ($80 = rest) |
$E0vvwwxxyyzz | Volume effect / ADSR envelope (Attack, Decay, Sustain, Release)
|
$E1xx | Detune - xx = amount (signed) |
$E2xx | Adjust volume - same as $E6 |
$E3xx | Nothing (empty slot) |
$E4xx | Adjust noise volume - xx = amount (signed) |
$E5xx | Change ADSR Mode. 00 - normal, 01-FF - repeat Attack/Decay phases |
$E6xx | Adjust volume - xx = amount (signed) |
$E7 | Maintain effect state (sets bit 1 of channel control) |
$E8xx | set Note Stop timeout (number of frames after that the note is turned off forcibly, 0 - off) |
$E9xx | Nothing (empty slot) |
$EAxx | Nothing (empty slot) |
$EBxx | Nothing (empty slot) |
$ECxx | Nothing (empty slot) |
$EDxx | Set global speed - xx = new speed |
$EExx | Nothing (empty slot) |
$EF | Invalid command (points into data) |
$F0wwxxyyzz | Pitch Bend
|
$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
|
$F8xxxx | Subroutine branch - xxxx = absolute address |
$F9 | Return from subroutine |
$FAxx | Set channel speed - xx = new speed |
$FBxx | Transpose channel by xx (added to current transpose value, which is added to all notes before looking up the PSG frequency) |
$FCxx | Nothing (empty slot) |
$FDxx | Set read literal mode. Turned on if xx == $01, otherwise off. |
$FExx | Nothing (empty slot) |
$FFxx | Nothing (empty slot) |
References