Specification for K1n9_Duk3'S Music Format (KMF) ================================================ ############################################################################### # If you want to suggest extensions to this format specification, feel free # # to contact me (K1n9_Duk3). If you want to modify this format without # # contacting me first, please use a different value in your file header. # ############################################################################### KMF is a slight modification of IMF (Id software Music Format). IMF files are usually headerless files (unless improperly ripped from an AudioT file) that consist entirely of a series of 4-byte instructions in the following format: Type | Name | Description ---------+-------+------------------------------------------------------------ UINT8 | reg | OPL register to write to UINT8 | val | value to write to that OPL register UINT16LE | delay | number of ticks to wait before the next instruction The vast majority of instructions in an IMF file either have a delay value of 0 or at least have a very short delay. The delay value almost never exceeds 255. Based on these observations, I designed the KMF specification as follows: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - All KMF files start with an 8-byte header: Type | Name | Description ---------+-------+------------------------------------------------------------ UINT32LE | id | always 0x1A464D4B (the ASCII characters "KMF" + 0x1A) UINT16LE | rate | playback rate in Hz (usually 560) UINT16LE | size | size of the instruction data The rest of the file contains a series of instruction blocks. Each block of instructions is preceeded by the following header: Type | Name | Description ---------+-------+------------------------------------------------------------ UINT8 | count | number of instructions that follow UINT8 | delay | number of ticks to wait before processing the next block Each instruction in that block is stored in the same format as used by IMF, but without the delay value: Type | Name | Description ---------+-------+------------------------------------------------------------ UINT8 | reg | OPL register to write to UINT8 | val | value to write to that OPL register - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Basic Playback Algorithm: ------------------------- 1 read file header 2 check if is correct, otherwise abort or use IMF playback code 3 if is not 0 then set that playback rate 4 allocate a buffer of bytes (abort if allocation failed) 5 read bytes into that buffer (abort if read failed) 6 set to 0 7 execute the following times per second: 7.1 WHILE == 0 AND > 0 7.1.1 read block header 7.1.2 = 7.1.3 WHILE > 0 7.1.3.1 read instruction 7.1.3.2 decrease by 2 7.1.3.3 write to OPL register 7.1.3.4 decrease by 1 and go to 7.1.3 7.1.4 decrease by 2 and go to 7.1 7.2 decrease by 1 For actual implementation details, please refer to "K1n9_Duk3's IMF Player" or "K1n9_Duk3's IMF to WAV converter". Notes: ------ The value in the KMF header is supposed to be used to detect whether a file is using KMF or IMF. The value was chosen to make false positives in KMF detection highly unlikely: Ripped AudioT chunks always start with a UINT16LE value storing the length of the IMF data. Since each IMF instruction has a length of 4 bytes, the length of the IMF data must always be evenly divisable by 4. 0x4D4B is not divisable by 4 and therefore no ripped AudioT chunk should ever be falsely identified as a KMF file. In theory, the KMF value could appear at the beginning of a regular IMF file. In that case, 0x4B would be the OPL register, 0x4D would be the value to write to that register and 0x1A46 would be the delay value. Writing the value 0x4D to OPL register 0x4B is a perfectly valid instruction, but waiting 6726 ticks right at the beginning of the file would be rather pointless, since that would mean a pause of 12 seconds (when the IMF rate is 560). It is highly unlikely that any actual IMF song would ever have such a large delay after the very first instruction. The value in the KMF header is purely for convenience. Games may ignore this value and stick to the hard-coded playback rate. Standalone IMF/KMF players should use the value to set the correct playback rate for the song unless the user explicitly selects a different playback rate. If the value is 0, the player should use a default value (like 560) instead, since 0 Hz would lead to divide by 0 errors. My tools will not allow you to create KMF files with a value of 0, but I think it's important to specify how such a value should be handled. The value is limited to 16 bits, and since each instruction and each block header has a length of 2 bytes, the size value should always be an even number. The whole point of KMF was to make the IMF files small enough to be used by games based on the ID Engine (Keen 4-6, Wolf3D etc.) without rewriting major parts of the code. The engine can't load more than 64k from the resource files and even if it could, it would need to use huge pointers to actually use that data, which would just slow things down. Besides, if the engine could handle files larger than 64k, you could just use IMF instead of KMF. KMF is not designed to support files larger than 64k, since the ID Engine would not be able to play such large files anyway (and any game using this engine probably could not afford to "waste" such large amounts of memory on music). Since the file has to be smaller than 64k in order to be loaded correctly by the ID Engine, the largest valid size value for KMF files is 65526 bytes (0xFFF6 in hex). My tools will not allow you to create larger KMF files. The behavior for values of not divisable by 2 as well as values greater than 65526 bytes is currently undefined. Such files are not to be considered "valid" KMF files and my tools will never create such files. A value of 0 is pointless, but still valid. It means that the file contains no instructions and ends right after the header file header (i.e. the file is exactly 8 bytes long). Thrid-party tools should not put any additional information after the end of the instruction blocks i.e. at file offset + 8 (size of the header). That space is reserved for future revisions of this format. Each block can contain anything from 0 to 255 instructions. If the block has 0 instructions, the next block header follows immediately after the current block header. If you need to use delays of more than 255 ticks between instructions, you need to use 255 as the delay value for the current block and subtract 255 from your desired delay value. Then keep inserting block headers with a value of 0 and a of either 255 or what's left of your desired delay value and subtracting that delay from your desired delay until the desired delay is 0. This is a rather ineffecient method and could drastically increase the size of the file, but situations where you actually need to use delays greater than 255 ticks are extremely rare. The value is allowed to be 0. In this case, the playback routines must process all the instructions in that block and immediately continue with the next block. Since the OPL chip has less than 255 valid registers, you should never need to have more than 255 instructions in one block. But just in case you do, you can split your instructions into multiple blocks where only the last block has a delay that is not 0. Third-party tools should not create block headers that have the and the values both set to 0. Such block headers are reserved for future revisions of this format. [END OF FILE]