This is a tool for the Pokémon Red/Blue disassembly project, which allows editing the music tracks by exporting them to MIDI files and then importing them back into assembly.
Features:
-
Given a monophonic sequence of MIDI notes, takes care of generating
octave
commands and using the right combination ofnote_type
speeds andnote
lengths to encode MIDI durations. -
Can create one-shot or looping tracks.
-
Changes tempo with MIDI tempo events.
-
Supports all note modifiers used by the game's music engine.
-
Finds repeated sections of assembly events and breaks them out into subroutines, referenced via
sound_call
, to save ROM space.
Future work:
- Extend to the pokegold or pokecrystal projects?
- Possibly use
sound_loop
to further shorten the assembly code.
Windows/Mac/Linux executables are posted on the releases page.
To build yourself, install a Haskell development kit and build the package as
appropriate. I use Stack where stack build
is the only step, but Cabal
should work as well as long as you also have GHC, Alex, and Happy.
make
uses Stack to produce a release .zip
file. Ruby is also required to get
the package version. make docker
uses Docker to build in an older Linux
distribution for higher compatibility.
pokemid in.asm out.mid # assembly to MIDI
pokemid in.mid out.asm # MIDI to assembly
# Second argument can be elided to go to stdout
For MIDI to assembly, the MIDI file should be in the following format:
-
Up to 4 tracks, each for one Game Boy channel, where the track for channel
N
(1 to 4) has a track name event containingChN
. -
MIDI tempos are used to create tempo change events, inserted into the first track in the assembly file.
-
In addition to monophonic notes, you can insert engine commands which affect the sound using MIDI text events. Supported events are:
note_type <volume>, <fade>
vibrato <delay>, <rate>, <depth>
duty_cycle <int>
duty_cycle_pattern <int>, <int>, <int>, <int>
volume <left>, <right>
stereo_panning <int>
pitch_slide <int>, <int>
toggle_perfect_pitch
For documentation on these see the pokered project. All of these events affect all notes that come after them, except the
pitch_slide
event which affects only the next (or coinciding) note.Note that
note_type
does not require you to supply a note encoding speed, though you can if you wish (before the volume and fade parameters). It is ignored because speeds are chosen by the program automatically.Events cannot be placed in the middle of a note, only at its beginning/end or in the middle of a rest.
-
To make a loop, use text events
begin
andend
around the looping portion. Without these the song will simply play once. You can also have just anend
event for a one-shot song.begin
andend
, like other events, cannot be in the middle of a note. -
Only tempos that fit into the following equation are precisely encodable:
x = 19200 / bpm
where
x
is a 2-byte integer, andbpm
is the tempo in beats per minute.x
will be rounded to the nearest integer if needed. -
Only note durations that fit into the following equation are precisely encodable:
duration = (ticks / 4) * (speed / 12) duration = (ticks * speed) / 48
where
duration
is the length of the note in beats or quarter notes,ticks
is a number from 1 to 16, andspeed
is a number from 1 to 15. Furthermore,ticks
andspeed
cannot both be 1. If a length cannot be exactly represented, the closest one less than it will be used. Rests between notes/events can be any length which is a sum of encodable lengths. -
Channel 4 notes (percussion/noise) use the following pitches:
- 0:
snare1
- 1:
snare2
- 2:
snare3
- 3:
snare4
- 4:
snare5
- 5:
triangle1
- 6:
triangle2
- 7:
snare6
- 8:
snare7
- 9:
snare8
- 10:
snare9
- 11:
cymbal1
- 12:
cymbal2
- 13:
cymbal3
- 14:
mutedsnare1
- 15:
triangle3
- 16:
mutedsnare2
- 17:
mutedsnare3
- 18:
mutedsnare4
- 0:
-
Assembly
notetype
volumes are encoded as MIDI note velocities as follows:- Assembly 0: MIDI 1 to 7
- Assembly 1: MIDI 8 to 15
- Assembly 2: MIDI 16 to 23
- Assembly 3: MIDI 24 to 31
- Assembly 4: MIDI 32 to 39
- Assembly 5: MIDI 40 to 47
- Assembly 6: MIDI 48 to 55
- Assembly 7: MIDI 56 to 63
- Assembly 8: MIDI 64 to 71
- Assembly 9: MIDI 72 to 79
- Assembly 10: MIDI 80 to 87
- Assembly 11: MIDI 88 to 95
- Assembly 12: MIDI 96 to 103
- Assembly 13: MIDI 104 to 111
- Assembly 14: MIDI 112 to 119
- Assembly 15: MIDI 120 to 127
That is, each assembly volume gets 8 MIDI velocities, except assembly 0 which gets 7.