Cosmo Tileinfo Format
The Cosmo Tileinfo Format is the data format used by Cosmo's Cosmic Adventures (and later it was extended for Duke Nukem II) to store the layout of the actor tiles - where each 8x8 tile should be drawn to produce a creature on-screen, how many frames the creature has, etc.
The format consists of a list of offsets for each actor, with a number of frames at each offset.
|UINT16LE iOffset||Offset in words (2-bytes) from the start of the file to the actor structure (see below)|
Since the count is not stored in the file, the only way to read in all the actor offsets is to keep reading until the offset of the first structure is reached (alternatively since the offsets are in words and the offsets are each a word long, the first offset is also the number of offsets/actor structures.)
At each offset, the actor structure is:
|UINT16LE iHeight||Height of frame (in tiles)|
|UINT16LE iWidth||Width of frame (in tiles)|
|UINT32LE iOffset||Offset into tileset file for frame image. One byte too many every 64k (see below.)|
This structure is repeated until the offset of the next actor is reached. The only way to calculate how many frames a specific actor occupies would be to find the difference between its offset and the following offset (or the file size, if it's the last offset) and divide the result by four (the size of the actor structure.)
Graphics data is stored in blocks in memory with a maximum size of 65535 bytes ($FFFF), and no actor frame can span two blocks. This has important consequences, namely that the there is padding data in the tileset. If there is not enough space in one block for an actor frame then the block will be filled with padding and the actor frame will be placed at the start of the next block.
Since blocks are one byte less than 64K, but the addresses of blocks are multiples of 64K there is a one byte discrepancy per block. That is, the iOffset figure contains one too many bytes in every 64k block - i.e. if the offset is 65536, you only seek to 65535. If the offset is 131072 you only seek to 131070. A simple formula for this is iFinalOffset = iOffset - (iOffset / 65536).
This file format was reverse engineered by Malvineous. Szevvy figured out how the 65535 offset works and Levellass figured out why. 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!)