You got started well; plotting unknown data as pixels immediately showed you this is indeed graphic data, not compressed (at least the buttons aren't), and in a usable RGB order. I guess the missing RGB format was what held you back; now you know it, you can write a simple program to plot in color and show offsets and widths of the images. Armed with that information, you can inspect the unknown bytes before (and possibly after) the images, and derive their meaning.
001_buttons.tsp consists of a series of images, without a general file header but with a header per image.
The first long word of this header (4 bytes, little endian format) is the size of the following data in bytes, excluding the header itself (this length may be
0). Then follow width and height as words. The next 12 bytes are 3 word-sized x,y pairs; the first pair is the center of the image. The coordinates are signed words, they wrap around at
0xFFFF/2. The other pairs still serve an unknown purpose.
After that, you have (height) times the offset of the next image scan line in words, offset from the start by 4 (so 4+2*offset = next line).
Each scan line pointed to by these offsets is Run-Length Encoded (RLE) compressed. Transparent runs are indicated only by the number of horizontal pixels to skip; opaque runs can be copied directly to the screen. There is no alpha transparency in these images. Each scan line fills exactly width pixels after decompressing.
The pixel format is packed 16-bit RGB:
RRRR.RGGG.GGGB.BBBB, which can be converted to 24-bit RGB in the following (not optimized) way:
putpixel (x,y, (((val >> 8) & 0xf8)<<16) | (((val >> 3) & 0xfc)<<8) | ((val & 0x1f)<<3) );
val is simply the next word:
Run-Length Encoding format
All values mentioned hereafter are word sized (2 bytes, little endian).
Each scan line starts with the number of commands for that line and a flag indicating whether to start with a "skip" or "copy". If the flag word after the number of commands is
0000, the line starts with a "skip", and if it is
0001, the line starts with a "copy".
After that, "skip" and "copy" commands alternate until the entire scan line is filled. Each command is the number of pixels to skip or copy; for "copy", the actual pixel values follow directly after it.
All lines should be filled entirely -- if necessary, the command list ends with a number of 'empty' pixels to skip.
Not all objects in
sprites.data are sprites in this format. There are at least two different types:
A monochrome mask object, using the same RLE compression scheme but without pixel data -- it contains only the length of each run. This could be to draw a mask, overlay a color, or aid in pixel-perfect object selection.
A list of signed word pairs of unknown use.
Neither these objects nor the actual sprites have a recognizable identifier at the start, so you can only find out which is which by trial and error (for example: if the reported 'size' of an image is negative or larger than the entire data file, you know it cannot be an RLE-compressed image after all).
Sprite index file
The index file
sprite.info is obfuscated, but not by much. It has the following format:
4 x some byte flag (all `01` in this file)
long total number of objects (377, in this file)
0-terminated "filename" (obfuscated)
long offset in 'sprite.data'
long length in 'sprite.data'
The filename is obfuscated by adding the constant
10 to each character. Decoding this, you get a list of 377 items:
__extras\compplay.ps6 | 00000000 000000C0
__extras\dim1.ps6 | 000000C0 00000BC4
__extras\dim2.ps6 | 00000C84 00000EB4
units\tur_05_blue.ps6 | 01FAC346 00013E12
units\tur_05_gren.ps6 | 01FC0158 00013E12
units\turrets_shadow.ps6 | 01FD3F6A 00013C9C
This is some sort of general index, as clearly not all images are listed. It must list only the first of an animated set; the 'length' is then the total length of all files in that particular set. The file extensions are a hint to their contents: files ending with
.ps6 all contain at least one image (and may contain more), files ending with
.msk are probably a monochrome mask and
.sha possibly shadows. The
.podigit files contain coordinate pairs.