Sound Engine Documentation

Nintendo MusicPlayer2000 ("Sappy" / "m4a")

Klonoa: Empire of Dreams uses the standard GBA sound engine known as Nintendo MusicPlayer2000, commonly referred to as "Sappy" or "m4a" in the decomp community. This is the same engine found in Pokemon, Kirby, Fire Emblem, and most first-party and many third-party GBA titles.

ROM Layout

Region Address Range Size Content
Sound tables 0x08117xxx ~3 KB Pitch, frequency, command dispatch LUTs
Voice tables 0x08117CBC – 0x081189xx ~3 KB 3 instrument/voice group tables
PCM samples 0x0811BB00 – 0x08163044 ~300 KB Signed 8-bit PCM waveform data
Song/track data 0x0816CB04 – 0x08184604 ~100 KB Song headers + bytecode track data
Song pointer table 0x08118AE4 ~1.3 KB 165 entries (39 songs + 126 SFX)

Structure

Song Table

Located at ROM_MUSIC_META_TABLE = 0x08118AE4. Contains 165 entries of the form:

struct SongTableEntry {
    u32 songHeaderPtr;
    u32 flags;  // songs: 0, SFX: encodes priority
};

Song Header

struct SongHeader {
    u8  numTracks;
    u8  blockCount;
    u16 priority;
    u32 voiceGroupPtr;
    u32 trackPtrs[numTracks];
};

Track Data

Proprietary MIDI-like bytecode. Encodes notes (0x81–0xB0), waits (0x00–0x7F), and control commands (tempo, instrument select, volume, pan, pitch bend, loops, subroutines).

Voice / Instrument Entry (12 bytes)

struct VoiceEntry {
    u8  type;       // see Voice/Instrument Types table
    u8  baseKey;
    u16 flags;
    u32 samplePtr;
    u32 adsr;
};

PCM Sample Header (16 bytes)

struct SampleHeader {
    u32 flags;
    u32 pitch;
    u32 loopOffset;
    u32 length;
    // followed by signed 8-bit PCM data
};

Content: 39 Songs, 126 Sound Effects

Songs range from 3–8 tracks. Most use the main voice table at 0x08117FD4.

Song Table (39 songs)

ID ROM Addr Tracks Priority Voice Table Est. Size
00x0816CB0470x9E0x08117FD4200
10x0816CBCC40xA80x08117FD4588
20x0816CE1830x940x081185C8572
30x0816D05440x9E0x08117FD42440
40x0816D9DC60x800x08117FD41556
50x0816DFF060x800x08117FD42116
60x0816E83460x800x08117FD42004
70x0816F00870x800x08117FD41904
80x0816F77860x800x08117FD41624
90x0816FDD070x800x08117FD42040
100x081705C860x800x08117FD42060
110x08170DD470x800x081185C81808
120x081714E470xA80x081185C8536
130x081716FC40x990x08117FD4756
140x081719F050x990x08117FD4508
150x08171BEC30xB20x08117FD41156
160x0817207060x990x08117FD4440
170x0817222840x990x08117FD4660
180x081724BC60x990x08117FD4988
190x0817289850x990x08117FD41180
200x08172D3470x990x08117FD41020
210x0817313060x990x08117FD41176
220x081735C860x990x08117FD41756
230x08173CA450x990x08117FD41324
240x081741D060x990x08117FD4488
250x081743B850x990x08117FD4564
260x081745EC60x990x08117FD41644
270x08174C5860x990x08117FD4804
280x08174F7C60x940x08117FD4920
290x0817531450x990x081185C82284
300x08175C0060x800x08117FD4180
310x08175CB430x800x081185C8712
320x08175F7C70x990x081185C8~57K
330x08183F7C30x9E0x08117CBC1672
340x0818460480x9E0x081185C8—

m4a Bytecode Reference

Byte Range Meaning
0x00 – 0x7FWait / duration values
0x80Rest
0x81 – 0xB0Note on (MIDI note number)
0xB1End of track (FINE)
0xB2Goto (loop)
0xB3Pattern call (subroutine)
0xB4Pattern return
0xBBSet tempo (BPM)
0xBCSet key shift (transpose)
0xBDSelect voice / instrument
0xBESet volume
0xBFSet panning
0xC0Pitch bend
0xC1 – 0xCFVarious controllers
0xCEExtended command

Voice / Instrument Types

Type Value Description
DirectSound0x00PCM sample playback
Square10x01CGB Square wave with sweep
Square20x02CGB Square wave
Wave0x03CGB Programmable wave
Noise0x04CGB Noise
KeySplit0x08Split by key range
Drumset0x40Percussion kit

First 16 Instruments (Main Voice Table)

Idx Type Key Sample Ptr ADSR
0DirectSound600x08143F1C0x0000E7FF
1DirectSound600x081446BC0x6BCBEC80
2Square260—duty=2, len=512
3DirectSound600x081463A80x7FE500FF
4Noise60—period=15
5DirectSound600x08130D1C0x9500F9FF
6DirectSound600x081229B00xA5E5E340
7DirectSound600x081280640x0000EBFF
8DirectSound600x08148CCC0x3C33FD80
9Square160—sweep=3, duty=5
10Square260—duty=2, len=512
11Square260—duty=3, len=1280
12Noise60—duty=2
13Square160—sweep=2, len=0xB02
14Square260—duty=1, len=0xD02
15Drumset00x081188B0(sub-table)

Tools

The m4a format is compatible with standard GBA music tools:

Decompilation Status

51 of 113 m4a/sound functions matched (byte-exact C reimplementations). Recent progress includes major breakthroughs in the core MP2000 engine functions using register pinning via asm barriers and the -ftst compiler flag.

Core Engine (matched)

Playback & Sequencer (matched)

Stream Commands & Dispatch (matched)

Utility (matched)

pokeemerald Alignment

The m4a engine is shared across virtually all GBA games. The pret/pokeemerald project has the most complete decompilation with established naming conventions. We align our function names with theirs for cross-project consistency:

22 functions have been renamed to match pokeemerald (m4aSongNumStart, MPlayStart, m4aMPlayAllStop, SoundClear, m4aSoundVSyncOff/On, m4aSoundMode, SampleFreqSet, TrackStop, MidiKeyToFreq, CgbOscOff, ply_voice/vol/pan/bend/bendr/lfos/lfodl/mod/keysh). Game-specific wrappers (StreamCmd_*, SoundEffect*) keep Klonoa-specific names.