KLM Format

From ModdingWiki
Jump to navigation Jump to search
KLM Format
Format typeMusic
Notation typeCustom
InstrumentsOPL
Max channel count9
Max track count1
Max pattern countUnknown
Max order countUnknown
Tags?Unknown
Games

The KLM Format is used by Wacky Wheels to store Adlib music tracks. It is probably named after Mark Klem, the Wacky Wheels composer.

File format

The file is structured as follows.

Data type Description
UINT16LE tempo Playback speed in ticks per second
UINT8 unknown Unknown
UINT16LE offNotes Offset of song data
BYTE[] inst Instrument data
BYTE[] notes Song data

Instrument block

The instrument block contains all the instruments used in the song. Each instrument is 11 bytes long, and is stored one after the other, in the following structure.

Data type OPL base register Description
UINT8 iModScale 0x40 Modulator key scaling/output level
UINT8 iCarScale 0x43 Carrier key scaling/output level
UINT8 iModAttack 0x60 Modulator attack/decay level
UINT8 iCarAttack 0x63 Carrier attack/decay level
UINT8 iModSustain 0x80 Modulator sustain/release level
UINT8 iCarSustain 0x83 Carrier sustain/release level
UINT8 iModChar 0x20 Modulator characteristic (Mult, KSR, EG, VIB and AM flags)
UINT8 iCarChar 0x23 Carrier characteristic (Mult, KSR, EG, VIB and AM flags)
UINT8 iModWaveSel 0xE0 Modulator wave select
UINT8 iCarWaveSel 0xE3 Carrier wave select
UINT8 iFeedback 0xC0 Feedback/connection

Song data follows the instrument data.

Song data

The song data appears to be a custom event-style structure, superficially similar to MIDI. Each command byte is followed by a variable number of data bytes whose purpose depends on the command. The lower four bits are used for the channel (so command bytes of 0x30 and 0x31 perform the same command on the first and second channels, respectively.)

Many songs are stored with 128 ticks per quarter note, however some do differ. The correct value for this does not appear to be stored in the file, however this is not required for playback, only to neatly arrange notes on a graphical musical staff.

Command byte # of data bytes Description
0x00 0 Note off
0x10 0/2 Note on with frequency
0x20 1 Volume
0x30 1 Set instrument
0x40 0 Note on
0xFD 1 Delay
0xFE 2 Long delay
0xFF 0 End of song

0x00: Note off

Turn the note on the current channel off (this sets the keyon bit to 0, on OPL base reg 0xB0).

0x10: Note on with frequency

Plays a note at the given frequency.

For channels 0-5 inclusive (i.e. command bytes 0x10 to 0x15), the first data byte is written to OPL base register 0xA0, and the second data byte is written to OPL base register 0xB0. As an example, if the command byte was 0x12 (set frequency on channel 2) then the two data bytes are written to register 0xA2 and 0xB2.

For channels 6-10 inclusive, there are no data bytes. Instead, these activate the OPL rhythm-mode percussion channels without setting a frequency:

Command byte OPL 0xBD bit Instrument
0x16 5 Bass drum
0x17 4 Snare drum
0x18 3 Tom tom
0x19 2 Top cymbal
0x1A 1 Hi-hat

0x20: Volume

This command sets the velocity of subsequent notes on the channel. As with MIDI, the single data value ranges between 0 (silence) and 127 (full volume). Wacky Wheels uses this value to write the appropriate output level to the OPL chip, using the following formula:

value = (127 - databyte) / 2

Thus a data byte of 0x58 results in the value 0x13 being written to the OPL chip. The value is written to the carrier operator on OPL base reg 0x40 (so channel 0 will actually write to reg 0x43.)

0x30: Set instrument

This command causes the instrument settings to be copied into the corresponding OPL registers for the channel. A data byte of 0x00 selects the first instrument in the instrument block.

0x40: Note on

Turn the note on the current channel on, at the last set frequency (this sets the keyon bit to 1, on OPL base reg 0xB0).

0xFD: Delay

This command causes a delay. The single data byte indicates how many ticks to wait for. Combined with the ticks-per-second tempo field in the header, the actual delay time can be calculated. With a data byte of 0x10 (delay for 16 ticks) and a tempo of 0x138 (312 ticks per second) the delay should be 16 ÷ 312 = 0.0512 seconds (51.2ms).

0xFE: Long delay

This command is the same as 0xFD except it is followed by a UINT16LE delay value rather than UINT8.

0xFF: End of song

This command has no delay bytes and signifies the end of the song data.

Tools

  • Camoto can just about load KLM files (some instruments are a bit off)

Credits

This file format was reverse engineered by Malvineous. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)