Audioseq
Audioseq contains data for playing the game's sequenced music. The sequenced music in the Zelda 64 games follows a MIDI type format which is a slightly updated version of that used in earlier games like Super Mario 64.
Contents
Moving Audioseq
To move the Audioseq file to another location in ROM, you will need to correct its entry in the file table, update the assembly code used to load sequences from the file, and update the CRC. This can be found at 0xB5A4AC (Debug ROM) and looks like:
3C05 xxxx 24A5 yyyy
In MIPS assembly:
LUI $A1,xxxx ADDIU $A1,$A1,yyyy
- x = upper half of address
- y = lower half of address
Sequence Pointer Table
Version | Offset | VRom | VRam | ||
---|---|---|---|---|---|
Debug | 1386A0 | 00BCC6A0 | 00BCCD90 | 80155500 | 80155BF0 |
NTSC 1.0 | 102AD0 | 00B89AD0 | 00B8A1C0 | 80113B70 | 80114260 |
NTSC 1.1 | 102C90 | 00B89C90 | 00B8A380 | 80113D30 | 80114420 |
NTSC 1.2 | 102B40 | 00B89B40 | 00B8A230 | 80114220 | 80114910 |
PAL 1.0 | 100290 | 00B89290 | 00B89980 | 80111970 | 80112060 |
PAL 1.1 | 1002D0 | 00B892D0 | 00B899C0 | 801119B0 | 801120A0 |
JP GC | 1021F0 | 00B881F0 | 00B888E0 | 801130D0 | 801137C0 |
JP MQ | 1021D0 | 00B881D0 | 00B888C0 | 801130B0 | 801137A0 |
USA GC | 1021D0 | 00B881D0 | 00B888C0 | 801130B0 | 801137A0 |
USA MQ | 1021B0 | 00B881B0 | 00B888A0 | 80113090 | 80113780 |
PAL GC | 0FF9C0 | 00B879C0 | 00B880B0 | 801108C0 | 80110FB0 |
PAL MQ | 0FF9A0 | 00B879A0 | 00B88090 | 801108A0 | 80110F90 |
JP Collection | 1021D0 | 00B881D0 | 00B888C0 | 801130B0 | 801137A0 |
The sequence pointer table begins with an 0x10 byte header:
/* 0x00 */ short NumberOfSequences = 0x6E;
/* 0x04 */ int AudioSeq_StartAddress; //ram only
/* 0x08-0x0F is padded to 0 */
Following that is a record for each sequence in the table:
xxxxxxxx yyyyyyyy uuaa 0000 00000000
- x = Pointer to the start of the sequence in the sequenced music file. In rom, this value is an offset relative to the start of the file, while in ram, this value will be converted into the VRom address that the sequence is located at
- y = Length of the sequence, in bytes.
- u = Unknown. Value set to 0x02
- a = Sequence Type, affects memory allocation. 0x00 is Hyrule Field, 0x01 is fanfares, 0x02 is BGM
Format
There are generally three different parts to the sequences:
Sequence Header
This is the part of the sequence that controls things such as master volume, tempo and loop settings.
Channel Header
Controls volume, pan, etc. and points to music data to be played back on each channel.
Music Data
Contains the data for which notes should be played, their velocity, length, etc.
From here, all numbers will be given in hexadecimal unless stated otherwise.
Sequence Header Commands
Command | Description |
---|---|
D3 xx | Seems to be something to do with the sequence type or format; for Super Mario 64, xx is usually 80, for Zelda 64, xx is usually 20. |
D5 xx | Unknown. xx usually takes the value of 32. For sequences that don't play any music xx is 46. |
D7 xxxx | Enables channels given by xxxx (boolean, each channel is one bit). |
9x yyyy | Points to a channel header offset. x is the channel number (0 - F) and yyyy is the offset of that channel's header relative to the start of the sequence file. |
DB xx | Master volume control, xx is the volume. |
DD xx | Tempo control, xx is the tempo value in beats per minute. |
CC yyxx | Unknown. yy starts at zero and increases each time the command appears, xx is (always?) 73. |
FD xx / FD yyyy | Timestamp (number of 'ticks' to wait before the next command is read, relative to tempo), variable length. If xx goes above 7F, add 8000 to it to get yyyy. |
FB xxxx | Offset to loop from, xxxx is the offset relative to the start of the sequence file. |
D6 xxxx | Disables channels given by xxxx. |
FF | Marks the end of the sequence header. |
Some sequences have the following data after the first four bytes of their sequence header. Its purpose is currently unknown but it may be to do with continuing playback mid-sequence after returning to the area from a house/shop:
D7FFFF 8776CCFF7786F3 vv F2 ww C801F3 xx [C801FA yyyy] FB zzzz
v, w and x are unknowns, y and z seem to be pointers to 9x commands for different parts of the sequence within the sequence header. The part in square brackets is repeated in some sequences.
Channel Header Commands
Command | Purpose | Variables |
---|---|---|
C4 | Initialises the channel for music playback | |
8x yyyy | Points to music data to be played on the current channel | x is 'note layer' to be used (8 - B). A maximum of four note layers can be loaded per channel. y is the offset of the music data to be played, relative to the start of the sequence file. |
DF xx (yy) | Channel volume | x is the volume value y is a timestamp used between control changes (when the volume is changing constantly) |
DD xx | Channel pan | x is the pan amount, 00 = hard left, 3F = centre, 7F = hard right |
E9 xx | Priority. Unknown how it is used | x = ? |
D4 xx | Effects level (echo) | x is the effect amount |
D8 xx (yy) | Vibrato | x Vibrato amount. Higher values can produce odd sounds. y is a timestamp used between control changes |
D3 xx (yy) | Pitch bend | x Pitch bend amount, signed. y is a timestamp used between control changes |
C2 xx | Transposition | x is the number of semitones to transpose by. Signed value |
C1 xx | Sets the instrument number | x instrument number to be used for the current channel |
FD xx / FD yyyy | Timestamp (see sequence header commands). | |
FF | Marks the end of the channel header. |
Music Data
Things get a little more complicated here.
Command | Format | Description | Values | Notes |
---|---|---|---|---|
nn (0x00 to 0x3F) |
tt(tt)vvgg | Play note | n = Note value t = Variable length timestamp v = Note velocity g = Gate time |
|
nn (0x40 to 0x7F) |
tt(tt) vv | n = Note value + 40 t = Variable length timestamp v = Note velocity |
Gate time is the same as was used for the previous play note command. | |
nn (0x80 to 0xBF) |
vv gg | n = Note value + 80 v = Note velocity g = Gate time |
Timestamp is the same as was used for the previous play note command. | |
C0 | xx, or yyyy |
Timestamp / rest | x or y is the variable length timestamp value | Used when no music needs to be played for a set amount of time |
FC | xxxx | Jump to offset | x is offset relative to the start of the sequence file to jump to | Plays the data from there until it reaches the next FF command |
FF | Terminator | Marks the end of the current music data. |
Note: It seems that some of the channel header commands are valid for use in the music data but the only one that's really useful is the C2 command (transposition).
Differences with the Super Mario 64 format
In Super Mario 64, the 8x yyyy command appears as:
9x yyyy
Where x is the 'note layer' to use (0 - 3) and yyyy is the offset to load music data from relative to the start of the sequence file.
Super Mario 64 does not use the E9 (priority) command and does not seem to be compatible with the way Zelda 64 does control changes. There may be other differences but this has not been looked into fully as of yet.
Tips for converting from MIDI
Zelda note value = MIDI note value - 0x15
Zelda timestamp = (MIDI timestamp/0x80)*0x18
Instrument Sets
There is no master instrument index in Zelda 64 as there is for MIDI sequences, instead there are different instrument sets that contain the instruments needed to play each sequence. The instrument set a sequence uses is not defined in the sequence itself but is defined externally. The lookup table for this data is retrieved in a rather unusual way:
In the Debug Rom for example, address BCC4E0 acts as the start address to the table. In order to reach the instrument set record, the game reads the halfword at BCC4E0 + (SequenceId * 2), then adds that to BCC4E0 to reach the appropriate record. Fortunately, this calculation can be simplified as being Table Start (BCC4E0 for debug) + DD + (SequenceId * 2) for all but sequence 0, where you'll have to subtract the result by 1.
nnii*
- n is number of Instrument Sets within the record
- i is the Instrument Set number for the Sequence
Version | Offset | VRom | VRam | ||
---|---|---|---|---|---|
Debug | 1384E0 | 00BCC4E0 | ? | 80155340 | ? |
NTSC 1.0 | 102910 | 00B89910 | ? | 801139B0 | ? |
Here's a list of which sequences use which instrument sets:
OoT instrument sets list
Instrument Set Number |
Purpose | Dependent Sequences |
---|---|---|
0x00 | Ocarina songs |
0x44 |
0x01 | Actor Sounds | none |
0x02 | Nature Sounds | 0x01 |
0x03 | Hyrule Field |
0x02 |
0x04 | Deku Tree | 0x1C |
0x05 | Market |
0x1D |
0x06 | Title Screen | 0x1E |
0x07 | Jabu Jabu's Belly | 0x26 |
0x08 | Kakariko Village (guitar) |
0x27 |
0x09 | Fairy Fountain |
0x28 |
0x0A | Fire Temple | 0x2A |
0x0B | Dodongo's Cavern | 0x18 |
0x0C | Forest Temple | 0x2C |
0x0D | Lon Lon Ranch | 0x2F |
0x0E | Goron City | 0x30 |
0x0F | Kokiri Forest | 0x3C |
0x10 | Spirit Temple | 0x3F |
0x11 | Horse Race |
0x40 |
0x12 | Warp songs (ocarina songs 2) |
0x25 |
0x13 | Goddess Cutscene |
0x4D |
0x14 | Shooting Gallery | 0x4E |
0x15 | Zora's Domain | 0x50 |
0x16 | Shop | 0x55 |
0x17 | Ice Cavern | 0x58 |
0x18 | Shadow Temple | 0x5B |
0x19 | Water Temple | 0x5C |
0x1A | Blank? | none |
0x1B | Gerudo Valley | 0x5F |
0x1C | Lakeside Laboratory | 0x60 |
0x1D | Kotake and Koume's Theme | 0x61 |
0x1E | Ganon's Castle (organ) | 0x2E |
0x1F | Inside Ganon's Castle | 0x63 |
0x20 | Ganondorf Battle/Boss Battle 2 |
0x5E |
0x21 | Ending sequence 1 |
0x67 |
0x22 | Ending sequence 2 | 0x68 |
0x23 | Game Over/Fanfares |
0x20 |
0x24 | Owl | 0x5A |
Legacy Credits
messiaen, DeathBasket - Sequence format
messiaen - pointer table format
DeathBasket - Instrument set lists for OoT and MM
DeathBasket - Writing this