你起步很好;将未知数据绘制为像素立即向您显示这确实是图形数据,未压缩(至少按钮不是),并且按可用的 RGB 顺序排列。我猜是缺少 RGB 格式阻碍了你;现在您知道了,您可以编写一个简单的程序来绘制彩色图并显示图像的偏移量和宽度。有了这些信息,您就可以检查图像之前(也可能是之后)的未知字节,并得出它们的含义。
总体概述
该文件001_buttons.tsp
由一系列图像组成,没有通用文件头,但每个图像都有一个头。
这个头的第一个长字(4个字节,小端格式)是后面数据的字节大小,不包括头本身(这个长度可能是0
)。然后按照宽度和高度作为单词。接下来的 12 个字节是 3 个字大小的 x,y 对;第一对是图像的中心。坐标是带符号的字,它们环绕在0xFFFF/2
. 其他对仍然用于未知目的。
之后,您有 (height) 乘以words 中下一个图像扫描行的偏移量,从起点偏移 4(因此 4+2*offset = 下一行)。
这些偏移指向的每条扫描线都经过行程编码 (RLE) 压缩。透明运行仅由要跳过的水平像素数表示;不透明的运行可以直接复制到屏幕上。这些图像中没有 alpha 透明度。解压缩后,每条扫描线正好填充宽度像素。
像素格式打包为 16 位 RGB: RRRR.RGGG.GGGB.BBBB
,可以通过以下(未优化)方式转换为 24 位 RGB:
putpixel (x,y, (((val >> 8) & 0xf8)<<16) | (((val >> 3) & 0xfc)<<8) | ((val & 0x1f)<<3) );
whereval
只是下一个词:data[c]+(data[c+1]<<8)
。
行程编码格式
下文提到的所有值都是字大小(2 个字节,小端)。
每个扫描行都以该行的命令数和一个标志开始,该标志指示是以“跳过”还是“复制”开始。如果命令数后的标志字是0000
,则该行以“跳过”开始,如果是0001
,则该行以“复制”开始。
之后,“跳过”和“复制”命令交替进行,直到填满整个扫描线。每个命令是要跳过或复制的像素数;对于“复制”,实际像素值紧随其后。
所有行都应该完全填充——如有必要,命令列表以一些要跳过的“空”像素结束。
并非所有对象sprites.data
都是这种格式的精灵。至少有两种不同的类型:
单色遮罩对象,使用相同的 RLE 压缩方案但没有像素数据——它只包含每次运行的长度。这可能是绘制蒙版、覆盖颜色或帮助选择像素完美的对象。
未知用途的带符号单词对列表。
这些对象和实际精灵一开始都没有可识别的标识符,因此您只能通过反复试验找出哪个是哪个(例如:如果报告的图像“大小”是负数或大于整个数据文件,您知道它毕竟不能是 RLE 压缩的图像)。
精灵索引文件
索引文件sprite.info
被混淆了,但不是很多。它具有以下格式:
4 x some byte flag (all `01` in this file)
long total number of objects (377, in this file)
377 x
0-terminated "filename" (obfuscated)
long offset in 'sprite.data'
long length in 'sprite.data'
通过向10
每个字符添加常量来混淆文件名。解码这个,你会得到一个包含 377 个项目的列表:
__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
这是某种通用索引,因为显然并非所有图像都被列出。它必须只列出动画集的第一个;“长度”是该特定集合中所有文件的总长度。文件扩展名是对其内容的一种提示:以.ps6
all结尾的文件至少包含一个图像(并且可能包含更多),以 结尾的文件.msk
可能是单色蒙版和.sha
阴影。这些文件包含坐标对。.podigit