Kris' Music System Format
Kris' Music System stores its music in *.kms files. Used by a number of games, the format is mostly unknown.
The format does not store any instruments, instead using four-character patch names which reference the instrument settings in a corresponding .vce file.
The file begins with a header.
|UINT32LE||lenFile||Length of the whole file, in bytes|
|UINT16LE||unknown1||Always 0x0001 (possibly number of songs in the file?)|
|UINT32LE||lenTracks||Length of track data, in bytes (typically number of bytes from this field until EOF, including this field). May be relevant if more than one song is in the file.|
|UINT16LE||numTracks||Number of tracks|
|char[numTracks]||trackIDs||List of four-character strings to identify each track, one per track, e.g. HDR1, t0s0, t1s0, t2s0, etc.|
|UINT32LE[numTracks]||offTrack||Offset of the track's first data byte, relative to the start of the track data|
After this header, the tracks begin. The offTrack values are relative to this point, so one track should always have an offset of zero, which refers to the byte directly following the above header.
Each track appears to be in the following structure:
|UINT32LE||lenTrack||Length of the track, in bytes (including this field)|
|BYTE[lenTrack - 4]||trackData||Notation data for this track|
Notation data is a variable-length array of events. Each event is preceded by a delay as shown below. Events occur back to back until the end of the track.
The data bytes following depend on certain bits in the event type.
Finish reverse engineering this
|Event byte||Event||Data bytes||First data byte||Second data byte||Notes|
|0x00||Song data||Variable||-||-||See below|
|0x01..0xCF||Play note||2||Unknown purpose||Note duration In ticks?||How to convert note numbers into pitch?|
|0xD9||Set tempo||2?||?||?||Same as 0xDD? Except can't seem to control speed|
|0xDC||Set instrument||1||Instrument index||-||Instrument #0 loads patch from instName|
|0xDD||Set tempo||1||New tempo||-||Tempo is in (lower numbers are slower.) Affects whole song, not just the current track. what? ticks per second?|
|0xDE||Set velocity||1||New velocity||-||0x00 is silent, 0x7F is full volume, high bit is ignored|
|0xE2||Set loop point||1||?||-||Data byte is always 0xFF and occurs at start of track|
|0xE3||Jump to loop point||1 or 2?||?||-||Jumps to location where last 0xE2 event was. Always occurs at end of each track so that the song loops.|
|0xE7||Track title||Variable||-||-||See below|
|0xEA..0xF0||Unknown||1||?||-||Plays next few notes faster than normal then transposes the rest way down|
0x00: Song data event
There will always be one track with the codename "HDR1", typically the first track in trackCodenames (but not necessarily at track offset zero) and this track has only one event, of type 0x00. This 0x00 event is in the following format.
|UINT8||numInst||Number of instruments|
|char[numInst]||instName||Instrument patch names (e.g. "DRUM" or "BASS"), not null-terminated. The instrument patch names are loaded from a corresponding voice (.vce) file, and when song event 0xDC selects an instrument, the instrument number is a zero-based index into this list.|
|UINT8||numActiveTracks||Number of five-char strings|
|char[numActiveTracks]||activeTracks||List of four-character + terminating null strings ("t0s0 ", "t1s0 ", etc.). This is a list of tracks that will be played in the song. Omitting a track from this list will cause it not to be played. The text here corresponds to the track ID from the header field trackIDs. The order of the tracks in this list does not seem to matter.|
0xE7: Track title
This event's data is in the following structure.
|UINT8||lenTitle||Length of track title, including terminating null|
|char[lenTitle]||title||Track title, null terminated|
There are no known tools that work with files in this format.
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!)