mml2m64: Music Macro Language importer for Mario 64

                         _ ____             __   _  _  
     _ __ ___  _ __ ___ | |___ \ _ __ ___  / /_ | || | 
    | '_ ` _ \| '_ ` _ \| | __) | '_ ` _ \| '_ \| || |_
    | | | | | | | | | | | |/ __/| | | | | | (_) |__   _|
    |_| |_| |_|_| |_| |_|_|_____|_| |_| |_|\___/   |_| 
         by messiaen (aka frauber)            [v0.1b]




What is it?
What is the .mml format?
What are .m64 and .zseq files?
Custom Commands Guide
Putting everything together (Sample of a valid .mml file)
Mario 64 Sequence Inserter v0.2
Tutorial: From MIDI to .m64

Extra tools:

Tinymm's octave raisers/lowerers fixer
Mario 64 Sequence Cleaner
Mario 64 Sequenced Music Parser
Sequence Bank Ripper
Zelda 64  Sequence Ripper

Download mml2m64 v0.1b

   mml2m64 is an experimental .mml importer that produces custom music in the Mario 64
and Zelda 64 sequence format. The main importer module is built from Addmusic's (revX)
MML parser, so big thanks to whoever wrote that program. You can download Addmusic
binaries, source code and documentation at

    The importer is to be used along a MIDI -> MML conversion tool, such as tinymm or
mid2mml, both of which can be download at SMW Central. Afterwards, you can insert the
custom music using the sequence inserter tool included in this package, which replaces
the original  Mario 64 sequences files with your custom music.

    This package also includes a few more music-related tools, such as sequence rippers
for Mario and Zelda 64 as well as parsing utilities that can display all the sequence
content. A description of all the tools included and their usage can be found below in
this document. All sources are in the src folder except mml2m64, because it will be
cleared and partly rewritten for a next release.

   Here is a sample of mml2m64's output (first release):

mml2m64 sample

What is the .mml format?

   Music Macro Language (MML) is a text-based format suitable for simple sequenced music.
The basic format is very simple and consist of the following fundamental syntax:

cdefgabc = pitches followed by lenght (1 = whole note, 2 = half, 4 = quarter and so on)
+/#      = sharp note (c+ = C#)
-        = flat note (b- = Bb)
r        = rest, followed by time
o        = octave setting
<        = lower octave
>        = raise octave
l        = default note value (l8 c d e f g is the same as c8 d8 e8 f8 g8)

   This is the syntax adopted by Addmusic and followed by mml2m64. There are also some
custom commands which will be covered briefly. You can good overviews of the MML format
in Wikipedia ( and in the "Documents"
section of SMW Central (look for custom music tutorials).

   I strongly recommend associating the .mml extension with Notepad/Worpad so you can
edit the .mml files just by double clicking them.

What are .m64 and .zseq files?

    Both .m64 and .zseq are arbritarly file extensions I came up with to designate
sequence files which follow the specifications used by Mario 64 and Zelda 64. The idea
is to have a portable format which can be easily shared and inserted in any suitable
ROM. This package only includes a Sequence Inserter for Mario 64, but eventually I
may also release one for the Zelda Debug ROM.

     You can find the most recent specification of the Mario 64 format at my site:

Custom commands guide

    Besides the basic mml syntax, mml2m64 support a few custom commands, most of them
based on Addmusic's implementation.

Global commands (used before channel specific data):

w = Global volume -> Sets the global volume of your song (min: 1, max 255)

t = Tempo (in BMP) -> Tempo of your song in BPM (min: 1, max: 255)

? = Loop setting -> Use with parameter 0 if you don't want to loop the song.

These global commands can be used as a sort of sequence header. For instance:

?0       ; don't loop song
w200     ; sets global volume to 200
t120     ; sets tempo (BPM) to 120

You can use ';' for comments. Everything after the ; until the newline will be ignored.
If no tempo and volume are specified, default settings will be used. By default, songs
will loop.

Channel commands:

# = Begin channel data -> Only use once for each channel. In theory, you can use
up to 16 channels, but some channels are reserved for Mario sounds, so it's better
to leave some of them free. After the '#', follows the channel number. Channels
are numbered starting from 0 up to 15. Channel #9 (10) is usually used for drums,
like MIDI.

v = Track volume -> Volume for this channel (min: 1, max: 255)

@ = Instrument number -> Instrument index for this channel. There isn't a master
index of instruments, but a index specific to the sequence you are replacing. For now,
the only way to know what instrument will be used is to experiment. You can try
values between 01 and 20. If you want it to be a drums/percussion channel, use
instrument number 127. If none is specified, a random value is used (from 1 to 8).

k = Gate Time -> This is a custom command specific to mml2m64. In MIDI, gate time is
the distance between NoteOn and NoteOff events. Use higher values for non-legato and
staccato and lower values for legato. If none is specified, a default value of 80
will be used, which usually produces a 'non-legato', but that depends on the instrument
you're using.

Here is an example of channel commands used between blocks of track data (musical
events) in a .mml file that follows mml2m64 commands:

#0  v120  k20 @1       ; channel 0, volume 120, game time 20 (legato) , instrument 1
d+16d+16r8f16f16r8f+16f+16r8g+16f+16g+16a+1^16      ; track data
#9  v150  @127         ; channel 9, volume 150, instrument 127 (drums)

Putting everything together

    Here is a sample valid .mml file ready to be processed by mml2m64:

--- victory.mml start ---

?0          ; don't loop
w160        ; global volume = 200
t158        ; tempo = 158 BMP

#0  v120  @1
#1  v150  @2
#2  v120  @3
#9   v130  @127           ; volume 150, instrument 127 (drums)

--- victory.mml end ---

    Now to turn this into a .m64 file, just run "mml2m64 victory.mml" (or drag
and drop a .mml file into mml2m64 if you are using Windows) and a file called
"victory.mml.m64" will be created. To insert it in the ROM, you'll need to use
the Mario 64 Sequence Inserter. To produce a .zseq file, include the -zelda
argument: "C:\my_mml2m64_dir\mml2m64 victory.mml -zelda".

    You can find a guide showing the usual steps from MIDI to a proper .mml
file in the tutorial.txt file.

Mario 64 Sequence Inserter (insert_seq.exe)

    After the .m64 is ready, the custom sequence must be inserted in the ROM.
The Sequence Inserter replaces any of the original sequences in an extended
Super Mario 64 ROM with custom music (.m64 files). The new sequence files are
copied after the original ones, which are keep intact in case you want to revert
(using the m64seq_clean tool).
    The Sequence Inserter is a console program, so you must run it from the
command prompt.


insert_seq <sequence_file> <rom_file> <sequence_number> or <-all>


insert_seq smb3.m64 mario64.z64 4    (Replaces Inside Castle music with smb3.m64)
insert_seq smb3.m64 mario64.z64 -all (Replaces all sequences with smb3.m64)

Sequence numbers for Mario 64

00 - Reserved
01 - End level
02 - SMB music title
03 - Bob-omb's Battlefield
04 - Inside Castle
05 - Dire Dire Docks
06 - Lethal Laval land
07 - Bowser Battle
08 - Snow
09 - Slide
10 - Boo's Haunt
11 - Piranha Plant lullaby
12 - Hazy Maze
13 - Star select
14 - Wing cap
15 - Metal cap
16 - Bowser Message
17 - Bowser course
18 - Collect Star
19 - Ghost Merry-go-round
20 - Start and End Race with Koopa the Quick
21 - Star appears
22 - Boss fight
23 - Take a Key
24 - Looping stairs
25 - Bowser Final Battle
26 - Credits song
27 - ?
28 - Toad
29 - Peach message
30 - Intro Castle sequence
31 - End fanfare
32 - End music
33 - Menu
34 - Lakitu

    Replacing all sequences at once is very useful so you can test how the same
sequence sounds in different instrument sets.
    The custom sequences are saved from 0x7cc6c0 to 0x800000 in the ROM, after
the original sequence bank end and before the first uncompressed MIO0 segment
(in an extended ROM). If you have run out of space, rom m64_seq_clean to clear
all the area between 0x7cc6c0 to 0x800000 and revert the pointers to the original

Tutorial: from MIDI to .m64

    This simple tutorial will guide you through the steps required to make an .m64 file
from a MIDI file. First, you'll need an external program that converts from MIDI to MML.
For this tutorial, I will use tinymm, which can be downloaded at SMW Central Tools
    The MIDI file victory.mid will be used in this example. Just run victory.mid through
tinymm (either using the console or dragging and drop a file there) and you shall get this
output in a file called victory.mid.mml:

    { Ch 01 ===================================== }
    { Ch 02 ===================================== }
    { Ch 03 ===================================== }
    { Ch 10 ===================================== }

   Tinymm has a bug with octave raisers/lowerers, so now just drag and drop the .mml file
to the mml_fix program. All the '<' and '>' will be inverted and the output will be saved
as victory.mml.mml:

    { Ch 01 ===================================== }
    { Ch 02 ===================================== }
    { Ch 03 ===================================== }
    { Ch 10 ===================================== }

    Now you have to fix the channel headers by replacing { ch ... } with the command #
followed by the channel number. Remember channels are numbered starting from 0, so this
is how it must goes:


    At this point, the .mml file is already compatible with mml2m64, so if you drag and
drop the text file above a valid .m64 will be produced. However, there are still some things
you'll have to do to make it sound better. First, let me remind you that channel 10 in MIDI
is used for drums/percussion, so remember to assign instrument @127 (drums) to channel #9.
In the following step, I also assigned random instruments and volume settings:

    #0  v150  @1
    #1  v150  @2
    #2  v150  @3
    #9  @127                  ; drums (originally channel 10)

    After inserting the sequence in the ROM with the Sequence Inserter, you can hear that
this sequence is not to be looped, and that the first channel is on the wrong octave. After
correcting this, here is the final version of it:

    -- final victory.mml file --

    ?0          ; don't loop
    w200        ; global volume = 200
    t158        ; tempo = 158 BMP

    #0  v150  @1
    d+16d+16r8f16f16r8f+16f+16r8g+16f+16g+16a+1^16      ; the '>' was removed to lower one octave
    #1  v150  @2
    #2  v150  @3
    #9   v150  @127           ; volume 150, instrument 127 (drums)

    There might be another adjustments you want to do for even better results, but these are
the basic steps to use a MIDI file.


    So you did everything right but found out there are missing channels,
instruments out of range and other problems? This section will guide you through
a few possible workarounds. Let me remind you that this is the very first (working)
release of this program, so not everything will work greatly.

1 - One/some of the channels doesn't work.

    Try changing the channel number (# command) or the instrument (@ command). Some
channels are reserved for Mario sounds, so there might be conflicts. If you replace
one sequence which is played at the same time as another (ie, Toad's music from
Inside Castle or the Piranha Plant lullaby) you'll have to make sure they don't use
the same channels. Also, when you first convert your .mml file, try using the first
5 instruments (@1 to @5), as sometimes higher values can result in invalid instrument
settings depeding on the sequence you are replacing.
    I recommend also using the "-all" option of the sequence inserter to find out if
the problem isn't specific to the sequence you are replacing. Alternatively, you can
run m64parser on the original Mario 64 sequences to know which channels each original
sequence is using.

2 - The notes of a specific channel are too low/too high.

    There are two workarounds for this. If you are importing from a MIDI file, you can
use some notation program (such as Finale Notepad) to lower the octaves until you find
an ideal range. Alternatively, you may also work directly with the .mml file. A good way
is to avoid this is to change the initial octave setting. For instance:

    o7 a8 b8 >c4 g4    --> this octave is too high, try changing o7 to o5 or o4.

    <<c16^8 d16 e1     --> to avoid this getting too low, just remove one of the
                           octave lowerews ("<") from the beggining and everything
                           will sound one octave higher.

    Some instruments have more limited ranges than others, so even if mml2m64 doesn't
wary you that the note is too high, it might not work with that specific instrument. Be
sure to experiment many different instruments to get optimum results.

3 - My Super Mario World .mml file doesn't work very well in mml2m64.

    Although this program is based on Addmusic, there are some differences in the .mml
implementation. Commands such as loops ('[' and ']') aren't supported yet and channels
are handled a bit differently. Most unsupported commands will be ignored, so there is a
good chance that with some work you can port your SMW .mml to mml2m64. During the initial
development stages of this program, I used .mml files from the Custom Music section of SMW
entral with varying degrees of success, so you might want to experiment with that also if
you are already familiar with the .mml format

4 - The sequence Inserter will open a window and then close it right away.

    Seq_insert is a console program, meaning it should run from the command prompt. In
Windows XP, you can reach the command prompt by doing Start Menu -> Run - "cmd". Afterwards,
just go the mml2m64 directory you unpacked mml2m64 and run insert_seq from there.

5 - The Sequence Inserter won't save the music in the ROM.

    Most likely, you have run out of space. Try running m64seq_clean.exe (just drag and drop
your ROM there) to erase all the custom sequences. Remember the inserter only works with an
extended Super Mario 64 ROM. Make sure you typed the arguments (sequence file, ROM file and
sequence to replace) in the right order.

6 - I produced a .zseq file. How do I insert it in the Zelda 64 Master Quest Debug ROM?

There isn't any program to insert it for you, so you'll have to replace an existing
sequence manually. The sequence files (all enclosed within the 'audioseq' file) start at
0x44DF0, and the pointer table is located at 0xBCC6A0
. The first 0x10 bytes is just the
sequence count (a halfworld), which should be 0x6E, followed by seq_count * 0x10 bytes of
entries (see struct below).


006E 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 6A90 0200 0000 0000 0000
0000 6A90 0000 1040 0202 0000 0000 0000
0000 7AD0 0000 2500 0202 0000 0000 0000
0000 9FD0 0000 0AB0 0202 0000 0000 0000

    If you want to make a program to insert it, you can use this struct:

struct PointerTableEntry
u32 relative_offset;     /* offset relative to start of audioseq file */
u32 lenght;
u32 seq_type;            /* 0x02000000,
0x02010000, 0x02020000 */
u32 padding;             /* NULL */
} SequencePointers[SeqCount];

    Here you can find a list of all sequences in the Debug ROM:


Extra tools:

Tinymm's octave raisers/lowerers fixer (mml_fix.exe)

    This program corrects tinymm's (MIDI->MML converter) octave raisers/lowerers
output. It's not required if you are using another program to generate the MML.
A later version shall fix also the channel headers.

Usage: fix_mml [mml_file]  (or just drag and drop a .mml file into mml_fix)

You can download tinymm from SMW Central.

Mario 64 Sequence Cleaner (m64seq_clean.exe)

    This program cleans all the new sequences you inserted in the ROM and restores
the original sequence pointer table.

Usage: m64seq_clean [rom_file]  (or drag and drop an Extended Mario 64 ROM into it)

Mario 64 Sequenced Music Parser (m64parser.exe)

    This tools parses and display all the content of a Mario 64 sequence file.

Usage: m64parser.exe [file.m64]

    You can save the output by using "m64parser file.m64 > log.txt". The z64parser
is a branch of the parser for .zseq files.

Sequence Bank Ripper (seq_rip.exe)

    This tool can extract sequence files from Super Mario 64, Mario Kart 64
and Wave Race 64, if you provide the sequence bank start offset.

Usage: seq_rip.exe [rom] [hex offset]
ie: seq_rip.exe mario_us.z64 0x7B0860

    If the extraction is sucessful, the sequences will be extracted as seq_xx in
the same directory. You can use a USF rip ( as a
reference for sequence numbering.

Offsets for sequence banks:

Super Mario 64 (US) - 0x7B0860
Mario Kart 64 (US) - 0xBC5F60

Zelda 64 Sequence Ripper (z64seqrip.exe)

    This tool extracts sequences from Zelda 64 Debug ROM (and probably Ocarina
of Time/Majora's Mask if you decompress the sequence pointer table).

    It is similar to seq_rip, except that in Zelda the pointer table is separated
from the sequence bank, so you'll have to provide these two offsets.

Usage: z64seqrip.exe [debugrom] [seq_bank_offset] [seq_pointers_offset]
ie: z64seqrip.exe zelootma.z64 0x44DF0 0xBCC6A0

0x44DF0 and 0xBCC6A0 are the offsets in the Debug ROM for the Sequence Bank
and sequence pointer table.