The data chunk is a list of events, one after another with nothing between them. Each event is one ID byte and a value. The ID says what the value means and also how big it is, so a reader can step over any event it does not recognise. Image-Line’s 1999 document describes this scheme, and every later version keeps it.
Size classes
The ID byte falls into one of four ranges, which set the size of the value.
| IDs | Class | Value |
|---|---|---|
| 0x00 (0) to 0x3F (63) | Byte | 1 byte |
| 0x40 (64) to 0x7F (127) | Word | 2 bytes, little-endian |
| 0x80 (128) to 0xBF (191) | Dword | 4 bytes, little-endian |
| 0xC0 (192) to 0xFF (255) | Variable | a variable-length size, then that many bytes |
The document gives the dword range as “128..192” and the variable range as “192..255”; the overlap at 192 is a slip, and 192 is a variable-length event. Later readers split the variable range into text (192 to 207) and data (208 to 255), but the storage is the same.
Variable-length size
Variable-length events give their size between the ID and the bytes. Each byte of the size carries seven bits of the number, lowest bits first, and its top bit is set when another byte follows. The document remarks that this is “not stupidly inverted” as in MIDI files, where the highest bits come first.
300 in binary = 10 0101100
low seven bits = 0101100 = 0x2C, more follows → 0x2C + 0x80 = 0xAC
next seven bits = 10 = 0x02, last byte → 0x02
stored as = AC 02
Text
Text events hold a zero-terminated string of single-byte characters. Every string in these versions is stored this way, the version included. The code page used for characters outside ASCII is not documented.
C2 05 53 6F 6E 67 00 Song
How events are grouped
The stream has no nesting, and order matters. In the document’s words, “when storing a channel, an FLP_NewChan event is added. Then any next ‘channel’ event will affect this newly created channel.” Patterns work the same way.
| Event | ID | Opens |
|---|---|---|
| NewChan | 0x40 (64) | a channel; the events after it describe that channel |
| NewPat | 0x41 (65) | a pattern; the value is its number |
The document also warns that some events are “stored only if they differ from their default value”, so a reader has to start each channel and pattern from defaults and apply only the events that appear. Those defaults are not documented.