This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
|
music [2015/12/09 14:14] queueram created |
— (current) | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== SM64 Music ====== | ||
| - | |||
| - | ===== Specification ===== | ||
| - | These are the specifications for the data formats to store music in the SM64 ROM. They are common across many first-party Nintendo 64 titles, such as Mario Kart 64, Wave Race 64, Starfox 64, Zelda 64. | ||
| - | |||
| - | ==== Sequence Bank ==== | ||
| - | The sequence bank starts at 0x7B0860. The format of the sequence bank header is shown in the following table. | ||
| - | |||
| - | ^ Offset ^ Length ^ Description ^ | ||
| - | | 0x00 | 2 | Revision number? | | ||
| - | | 0x02 | 2 | Sequence count | | ||
| - | | 0x04 + <color darkred>N</color>*8 | 4 | Start offset of sequence <color darkred>N</color> | | ||
| - | | 0x08 + <color darkred>N</color>*8 | 4 | Length of sequence <color darkred>N/color> | | ||
| - | |||
| - | ==== Header Format and Commands Table ==== | ||
| - | The sequence header consist of pointers for all tracks, tempo, volume and loop settings. Each sequence is usually divided in chunks (i.e., eight 4/4 bars) separated by variable-length timestamp commands (0xFD). The first command is always 0xD3, followed by parameter 80, 60 or 20. | ||
| - | |||
| - | ^ Byte ^ Parameters ^ Description ^ | ||
| - | | 0x90 - 0x9F | Offset (2 bytes) | Points to track data for a specific channel, indicated by the second nibble of status byte | | ||
| - | | 0xD3 | 1 byte | Sequente type? Usually 80 (Mario64) or 20 (all other games). 60 is used for the 'Mario sounds' sequence | | ||
| - | | 0xD6 | Channels (16 bits) | Disable channels flag. Each bit = one channel | | ||
| - | | 0xDB | Master Volume (1 byte) | Master Volume (unsigned integer) | | ||
| - | | 0xDD | Tempo in BMP (1 byte) | Tempo setting (BPM) | | ||
| - | | 0xD5 | 16 bits | Unsure. Used in the very beggining of sequences (before channel enable flag) | | ||
| - | | 0xD7 | Channels (16 bits) | Enable channels flag. Each bit = one channel | | ||
| - | | 0xFD | Variable-length (1 or 2 bytes) | Timestamp (used between track chunks and to ensure right looping) | | ||
| - | | 0xFB | Offset (2 bytes) | Loop from the specified offset | | ||
| - | | 0xFF |No param | End of header | | ||
| - | |||
| - | ==== Track Format and Commands Table ==== | ||
| - | The track data commands are very similar to the header ones. | ||
| - | |||
| - | ^ Byte ^ Parameters ^ Description ^ | ||
| - | | 0x90 - 0x9F | Offset (2 bytes) | Loads music data (divided in "layers"). Since simultaneous notes (using a "0" timestamp) aren't possible, many layers are loaded and played simultaneously. The second nibble of the status byte indicates the layer number | | ||
| - | | 0xC1 | Program (1 byte) | "Set program" related. There isn't a master index for instruments, this seems to refer to the current set of instruments, which is not specified in the sequence data but loaded by something external to it. Drums tracks usually use program 0x7f (127). | | ||
| - | | 0xC2 | Transposition (1 signed byte) | Transposition in semitones | | ||
| - | | 0xC4 | No Param | Mark the beggining of track data | | ||
| - | | 0xD3 | Pitch bend (1 byte) | Pitch Bend (signed integer) | | ||
| - | | 0xD4 | unknown (1 byte) | ?? | | ||
| - | | 0xD8 | Vibrato (1 byte) | Vibrato range | | ||
| - | | 0xDC | unknown (1 byte) | Drum-related? | | ||
| - | | 0xDD | Pan (1 byte) | Set pan for this track (01 = left, 64 = center, 127 = right) | | ||
| - | | 0xDF | Track Volume (1 byte) | Volume for this track (unsigned integer) | | ||
| - | | 0xFD | Variable-length (1 or 2 bytes) | Timestamp (used between track chunks and to ensure right looping) | | ||
| - | | 0xFF | No Param |End of Track Data | | ||
| - | |||
| - | ==== Music Events Table ==== | ||
| - | This is the format for the data pointed by the Track Data 0x90 - 0x9F commands. | ||
| - | ^ Byte ^ Parameters ^ Description ^ | ||
| - | | 0x00-0x3F | Timestamp (1 or 2 bytes). Velocity (1 byte). Duration (1 byte) | "Play Note" commands ('Type 0'). Unlike MIDI, 0 = A0. Timestamp is variable lenght (see below). Duration byte seems to be timestamp before "NoteOff" (I'm not sure about this) | | ||
| - | | 0x40-0x7F | Timestamp (1 or 2 bytes). Velocity (1 byte). | "Play Note" commands ('Type 1') Duration = previous specified (producing more compact data) | | ||
| - | | 0x80-0xBF | Velocity (1 byte). Duration (1 byte) | "Play Note" commands ('Type 2'). Timestamp = previous specified (producing more compact data) | | ||
| - | | 0xC0 | Timestamp (1 or 2 bytes) | Timestamp used for rests | | ||
| - | | 0xC2 | Transposition (1 byte) | Transposition in semitones. Since the 'PlayNote' commands just cover a range of 0x40 notes (as opposed to 0x7F possible MIDI notes), this is used to shift the range when needed | | ||
| - | | 0xE0 - E8 | ? | ? | | ||
| - | | 0xFC | 2 bytes | Jump (used for loops). There isn't a loop counter, so the command is repeated. Offset is relative to individual sequence start | | ||
| - | | 0xFF | No Param | End of music track / Return from jump | | ||
| - | |||
| - | === Timestamp Parameter === | ||
| - | The variable length timestamp parameter comes in two forms: | ||
| - | - Fixed values: | ||
| - | * 0x10 = Triplet | ||
| - | * 0x18 = Eight-note | ||
| - | * 0x30 = Quarter note | ||
| - | * 0x60 = Half-note | ||
| - | - Variable lenght timestamp. If most significant bit (0x80) is set, an additional byte is read, e.g.: | ||
| - | * 0x8C00 = 0xC00 timestamp | ||
| - | * 0x9C00 = 0x1C00 timestamp | ||
| - | |||
| - | ==== Instrument Sets ==== | ||
| - | The table that determines which instrument set is used in each sequence is located at 0x7CC620. | ||
| - | |||
| - | ===== References ===== | ||
| - | * https://sites.google.com/site/messiaen64/mario-64-sequenced-music-specification | ||
| - | * https://sites.google.com/site/messiaen64/parsed-music-files | ||