- Format Type : Archive
- Endian Order : Little Endian
RLB files are resource archives used in various games from Tsunami. There are several variations in the format reflecting the evolution of the format since it was used in a progression of games from the same publisher. Much of this information was gleaned from studying the source code of the ScummVM project.
There are tools for unpacking, modifying, and repacking some of the resources types (mostly with a goal of language translation) as part of the Improved Spoon game hacking project.
RLB files are comprised of a series of resource blocks starting with a signature of 'TMI-'. Each resource block starts with the following 6-byte data structure:
bytes 0-3 'TMI-' signature byte 4 resource type byte 5 number of entries in this resource block
Each entry in the resource begins with the following 12-byte structure:
bytes 0-1 entry ID bytes 2-3 compressed size bytes 4-5 uncompressed size byte 6 high nibbles of the compressed and uncompressed sizes byte 7 type (bits 7-5) bytes 8-11 payload offset
Byte 6 contains the high 4 bits of the uncompressed size in bits 7-4 and the high 4 bits of the compressed size in bits 3-0. Thus, the largest size which can be specified is 220 = 1,048,576 bytes.
The high 3 bits of byte 7 are interpreted by ScummVM as 'type' and the field is expected to be either 0 (uncompressed) or 1 (compressed).
The payload offset specifies the offset relative to the beginning of the resource block (beginning of the 'TMI-' signature).
The first resource block in the file conforms to the same general format described above, but encapsulates all of the other blocks in the file as well as the block index. The compressed and uncompressed sizes match and they specify the size of the index. The offset points to the index. Further, the block type is 32. It's possible that bit 5 of the type field means something else and bits 4-0 are the actual resource type; type 0 corresponds to 'library'.
The index consists of a series of 6-byte records. Each record is formatted as:
bytes 0-1 resource number bytes 2-3 block type bytes 4-5 block offset
The final entry in the index contains 0xFFFF for all 3 16-bit entries.
The block type should match the type specified in the block's TMI header.
The block offset is absolute for most games. However, in Return to Ringworld, it specifies the absolute paragraph offset (where a paragraph is defined as 16 bytes). Thus, in R2RW, all 'TMI-' signatures should be aligned to 16-byte boundaries. One curious implication of this is that there appears to be random garbage between the logical end of one resource block and the paragraph boundary of the next.
These are the RLB resource types known to ScummVM:
- 0: library
- 1: strip
- 2: image
- 3: palette
- 4: visage
- 5: sound
- 6: message
- 7: font
- 8: pointer
- 9: bank
- 10: sound driver
- 11: priority
- 12: control
- 13: walk regions
- 14: bitmap
- 15: save
- 16: sequence
Further, Return to Ringworld uses types 17 through 31, but ScummVM does not name them.
(implemented in ScummVM; to be documented)
The payload of a message resource block contains a simple concatenation of NULL-terminated strings in which each string is comprised of 8-bit bytes. These strings are rendered by using each byte as an index into a font specified by a font resource.
Many strings are prefixed with a '!' character and a 4-digit number. For example:
!0001You see nothing peculiar. !0002Utterly commonplace. !0003There's nothing unique about this. !0004Completely typical in appearance. !0005Looks quite normal.
The payload of a font resource has the following layout:
bytes 0-1 number of font elements (commonly 128/0x80) bytes 2-3 unknown (0x0000) bytes 4-5 number of font elements bytes 6-7 character height bytes 8-9 character width bytes 10-11 bits per pixel
Following this header is a 32-bit offset for each letter. The offset is in reference to the start of the font resource. Each font entry starts with a 16-bit little-endian integer, followed by the character bitmap data. The meaning of the 16 bits is:
bits 15-11 Y offset bits 10-5 character height bits 4-0 character width
Empirically, fonts are either 1 or 2 bits per pixel. The bits are packed with no padding. Thus, if a character's width is 9 pixels and is encoded with 1 bit per pixel, the first byte encodes the first 8 pixels of the first line and the second byte encodes the last pixel of the first line and the first 7 pixels of the second line.
Strip resources appear to be used for conversation text. A strip resource block will have 2 entries. The first entry has a series of data structures describing dialog exchanges. The second entry contains a sequence of NULL-terminated character strings, similar to a message resource block.
The data structures in the first entry are all 68 bytes long, except in the case of Return To Ringworld (R2RW) which uses 126-byte records. This is a description of the layout which attempts to merge the 2 types:
if R2RW 2 bytes mode 2 bytes lookup value 2 bytes lookup index 2 bytes exit mode 2 bytes speaker mode 2 bytes id 10 bytes list of 5 16-bit callback indexes if R2RW 22 bytes 11 16-bit numbers of unknown meaning else 4 bytes unknown read 8 (if R2RW) or 5 (every other game) of the following records: 2 bytes id 2 bytes text offset 6 bytes unknown 2 bytes speaker offset
The speaker offset references the speaker's name in the message entry.