[Complete ReEdit3] 进一步改进并缩短文本以适应 30KB 的限制
首先输入一些我是如何到达这里的(对于将来尝试对不同格式执行相同操作的读者)。
图像数据大小
将提供的背景图像与其原始图像大小进行比较xs*ys
揭示了直接依赖性,这意味着没有压缩或具有始终相同的像素与数据比的压缩。我假设没有压缩。
图像数据对齐。
第一个数字DWORD
与零填充对齐。通过仔细观察,它总是DWORD[ys]
暗示每个ScanLine 的一些信息。数字在不断增加。对于800x600
带有 step 的图像,826
它是包含相对偏移量的ScanLine目录。测试证实了这一点:
小图像太小,看不到任何细节,所以我完全忽略了它们。
垂直线是从包含某种信息的ScanLine 的第一个开始的26 BYTES
不一致。经过更多的教学和像素测量后,这些线出现,每条线可能包含一些标志信息(如:平铺高光、透明度或效果蒙版)。如果跳过结果更接近:xs
BYTE
33 BYTES
颜色
我只是拿了你的ScreenShot并将第一个解码的像素与其进行了比较。在调色板中找到匹配每个图像颜色的颜色索引,发现差异是简单的增量。所以我首先在解码时增加颜色索引并且结果很好。经过一些研究,我发现调色板数据具有257
颜色而不是一开始假设的颜色,256
因此我更改调色板偏移以进行补偿(不再需要更改颜色索引)暗示第一个颜色条目(通过偏移更改跳过)是某种特殊颜色(见项目符号#1)。后来我推断它根本不是颜色,也不属于调色板数据,而是属于标题数据。现在的结果是:
如果我不会发现颜色依赖性,那么我会为解码和屏幕截图图像做直方图,然后分析对大多数出现的颜色索引的依赖性,希望能发现某种模式。
比较
我将解码后的图像与您的ScreenShot像素匹配,但图像不匹配。可能对它应用了一些后期处理或照明,或者解码中有一些错误。很难决定,因为我无法访问原始应用程序或了解其内部工作原理。您应该检查更多图像以查看是否存在一些伪影。小图像无法使用,因为您不知道内容,而且尺寸很小,无法显示任何重要细节......
透明图片
那么Iter项目ATOR发现,一些文件没有正确地解码,并推断它是与透明度(如图像是图标和后来也精灵)。因此进行了一些更深入的分析以取得一些进展。
经过一些思考和循环之后,我创建了特殊的调试视图,以便我可以以某种方便的方式查看编码图像数据、参考屏幕截图和相应的调色板颜色,以发现模式或依赖项。结果是这样的:
我只是将数据的每个像素/字节渲染为正方形,颜色与调色板条目相对应,并在其中渲染十六进制代码。我在下面渲染了编码的ScanLine和屏幕截图ScanLine(里面印有来自图像调色板的交叉匹配颜色代码。然后我痛苦地交叉引用Paint 中的两个ScanLine,在比较了所有图标后,我开始推断编码格式。间隙意味着某种标志或前缀,序列或特殊命令。将这些规则实施到解码器中后,图像突然变得更好看。
我处于一种状态,我得到的所有图标都是像素完美的,但在更多图像(精灵)进入后,很明显某些代码可能是可变的,需要对文件中的块进行更深入的分析来搜索一些代码表或字典。
为了帮助进行分析,我将解码器调试视图重写为具有识别完美颜色匹配(正方形)和接近颜色匹配(圆形)的能力的单独类,以便首先更好地评估非透明像素上的代码。
我从这样的规则开始:
我从中推断出这一点(不完全正确,请参阅实际状态的代码):
前 2 个字节是标志 03 unknonw 标志/命令跳过标志可以跟随!
也结束序列 23(标志和像素跟随为 01) 02 扫描线结束标志和像素跟随,序列结束(如果不是前 5 个像素)序列开始:13,17,23,27,2B 像素跟随:0D ,0F,12,15,16,18,1A,1C,1D,1E 标志或像素如下:06,07,0C,0E?,10
序列不能作为第一个像素开始,否则它是像素
- 序列可以在 5 个像素已经完成后停止,否则 01/03 只是像素
我后来直接在解码器中对其进行了更多改进
扫描线偏移
当我发现ScanLine的第一个字节是否用作透明图像的偏移时,一些图像看起来好多了。Ite Ator发现它是偏移量和 LSB 位是这个能力的开关。我发现如果第一个ScanLine的第一个 BYTE是0xFC
那么它不是透明图像并且解码在第一个项目符号中描述。我mode 0/1
在解码器中引入了变量来识别这一点。并且偏移量仅在模式 1(透明)下有效。我还发现,offset=(flag>>1)+1
因为它从编码效率方面更有意义(测试确认这是正确的假设)。
文件块
为了寻找丢失的代码表或字典,我开始剖析文件格式(尚未使用的每个字节)。经过一些编码和分析后,我向解码器添加了另一个调试输出,该输出以对齐的形式为每个文件/帧创建文本,因此我可以轻松地比较我得到的所有图像,因为在两个 ro 更多十六进制视图中进行比较不是很方便。
这里的标题数据:
file K E R D file_size frames image_ofs palette_ofs used_colors
dragon 00000000: 4B 45 52 44 C8 00 00 00 A1 BF 01 00 01 00 0B 00 60 03 00 00 01 00 00 00 54 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 2E 00 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 00 01 00 00 18 CD CD CD
mountain 00000000: 4B 45 52 44 C8 00 00 00 58 8C 01 00 01 00 02 00 60 03 00 00 01 00 00 00 54 00 00 00 00 00 00 00 56 8A 01 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 00 01 00 00 18 CD CD CD
icon0 00000000: 4B 45 52 44 C8 00 00 00 4F 05 00 00 01 00 01 00 60 03 00 00 01 00 00 00 54 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 5A 00 00 00 18 CD CD CD
icon1 00000000: 4B 45 52 44 C8 00 00 00 4F 05 00 00 01 00 01 00 60 03 00 00 01 00 00 00 54 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 59 00 00 00 18 CD CD CD
icon2 00000000: 4B 45 52 44 C8 00 00 00 4D 05 00 00 01 00 01 00 60 03 00 00 01 00 00 00 54 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 50 00 00 00 18 CD CD CD
icon3 00000000: 4B 45 52 44 C8 00 00 00 46 0B 00 00 01 00 01 00 60 03 00 00 01 00 00 00 54 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 00 01 00 00 18 CD CD CD
back 00000000: 4B 45 52 44 C8 00 00 00 78 9D 07 00 01 00 01 00 60 03 00 00 01 00 00 00 54 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 00 01 00 00 18 CD CD CD
这里是 ImageData:
file frame sz xs ys xs ys
dragon 00000360: 00 00 00 00 00 00 00 00 00 00 00 00 08 CD 01 00 04 25 00 00 B2 00 00 00 5B 00 00 00 E5 FF FF FF B3 FF FF FF 00 00 00 00 C0 03 00 00 C4 28 00 00 00 00 00 00 00 CD CD CD 00 00 00 00 04 CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD B2 00 5B 00 00 00 00 00
000028C4: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 02 00 A1 26 00 00 B6 00 00 00 5B 00 00 00 DD FF FF FF B4 FF FF FF 00 00 00 00 24 29 00 00 C5 4F 00 00 60 03 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B6 00 5B 00 00 00 00 00
00004FC5: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 03 00 57 27 00 00 C4 00 00 00 5E 00 00 00 D6 FF FF FF B1 FF FF FF 00 00 00 00 25 50 00 00 7C 77 00 00 C4 28 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C4 00 5E 00 00 00 00 00
0000777C: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 04 00 26 28 00 00 BF 00 00 00 64 00 00 00 D3 FF FF FF AA FF FF FF 00 00 00 00 DC 77 00 00 02 A0 00 00 C5 4F 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BF 00 64 00 00 00 00 00
0000A002: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 05 00 70 29 00 00 C3 00 00 00 67 00 00 00 D0 FF FF FF A6 FF FF FF 00 00 00 00 62 A0 00 00 D2 C9 00 00 7C 77 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C3 00 67 00 00 00 00 00
0000C9D2: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 06 00 DA 29 00 00 C6 00 00 00 6C 00 00 00 CF FF FF FF A2 FF FF FF 00 00 00 00 32 CA 00 00 0C F4 00 00 02 A0 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C6 00 6C 00 00 00 00 00
0000F40C: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 07 00 33 2A 00 00 C5 00 00 00 6F 00 00 00 D1 FF FF FF 9F FF FF FF 00 00 00 00 6C F4 00 00 9F 1E 01 00 D2 C9 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C5 00 6F 00 00 00 00 00
00011E9F: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 08 00 1A 2B 00 00 C0 00 00 00 6C 00 00 00 D4 FF FF FF A2 FF FF FF 00 00 00 00 FF 1E 01 00 19 4A 01 00 0C F4 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 00 6C 00 00 00 00 00
00014A19: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 09 00 59 29 00 00 BE 00 00 00 68 00 00 00 DA FF FF FF A7 FF FF FF 00 00 00 00 79 4A 01 00 D2 73 01 00 9F 1E 01 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BE 00 68 00 00 00 00 00
000173D2: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 0A 00 E5 26 00 00 B5 00 00 00 62 00 00 00 E1 FF FF FF AB FF FF FF 00 00 00 00 32 74 01 00 17 9B 01 00 19 4A 01 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B5 00 62 00 00 00 00 00
00019B17: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 0B 00 CA 23 00 00 AB 00 00 00 5A 00 00 00 EA FF FF FF B3 FF FF FF 00 00 00 00 77 9B 01 00 41 BF 01 00 D2 73 01 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 AB 00 5A 00 00 00 00 00
mountain 00000360: 00 00 00 00 00 00 00 00 00 00 00 00 08 CD 01 00 A7 BA 00 00 37 01 00 00 D3 00 00 00 00 00 00 00 C9 FF FF FF 00 00 00 00 C0 03 00 00 67 BE 00 00 00 00 00 00 00 CD CD CD 00 00 00 00 04 CD CD CD 00 00 00 00 CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 37 01 D3 00 00 00 00 00
0000BE67: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 02 00 2B C7 00 00 3C 01 00 00 DD 00 00 00 FC FF FF FF C4 FF FF FF 00 00 00 00 C7 BE 00 00 F2 85 01 00 60 03 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3C 01 DD 00 00 00 00 00
icon0 00000360: 00 00 00 00 00 00 00 00 00 00 00 00 08 CD 01 00 2F 01 00 00 0D 00 00 00 0D 00 00 00 11 00 00 00 F9 FF FF FF 00 00 00 00 C0 03 00 00 EF 04 00 00 00 00 00 00 00 CD CD CD 00 00 00 00 04 CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 0D 00 0D 00 00 00 00 00
icon1 00000360: 00 00 00 00 00 00 00 00 00 00 00 00 08 CD 01 00 2F 01 00 00 0D 00 00 00 0D 00 00 00 11 00 00 00 F9 FF FF FF 00 00 00 00 C0 03 00 00 EF 04 00 00 00 00 00 00 00 CD CD CD 00 00 00 00 04 CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 0D 00 0D 00 00 00 00 00
icon2 00000360: 00 00 00 00 00 00 00 00 00 00 00 00 08 CD 01 00 2D 01 00 00 0D 00 00 00 0D 00 00 00 11 00 00 00 F9 FF FF FF 00 00 00 00 C0 03 00 00 ED 04 00 00 00 00 00 00 00 CD CD CD 00 00 00 00 04 CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 0D 00 0D 00 00 00 00 00
icon3 00000360: 00 00 00 00 00 00 00 00 00 00 00 00 08 CD 01 00 26 07 00 00 26 00 00 00 26 00 00 00 05 00 00 00 ED FF FF FF 00 00 00 00 C0 03 00 00 E6 0A 00 00 00 00 00 00 00 CD CD CD 00 00 00 00 04 CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 26 00 26 00 00 00 00 00
back 00000360: 00 00 00 00 00 00 00 00 00 00 00 00 08 CD 01 00 58 99 07 00 20 03 00 00 58 02 00 00 08 00 00 00 B4 FD FF FF 00 00 00 00 C0 03 00 00 18 9D 07 00 00 00 00 00 00 CD CD CD 00 00 00 00 04 CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 20 03 58 02 00 00 00 00
更好地揭示结构。我从中发现了一些东西,比如帧索引和 ImageData 对齐,0x0360
而不是0x0370
我之前假设的。此外,0xCD
模式仅存在于第一帧而不是所有位置。文件格式是这样的:
Offset DataType Meaning
--------------------------------------------------------
Header (0x0000):
0x0000 char[4] `DREK` Signature
0x0008 DWORD whole file size
0x000E WORD number of frames
0x0010 DWORD ImageData offset from start of file 0x0360
0x0054 DWORD Palette offset from start of file 0x0060
0x0058 DWORD used_colors from Palette (rest are set to (CD,CD,CD))
--------------------------------------------------------
Palette: (0x060)
+0x0000 BYTE[768] RGB palette
--------------------------------------------------------
ImageData (0x0360)
+0x000E WORD frame 1,2,3,4,...
+0x0010 DWORD sz (ImageData size - 0x60)
+0x0014 DWORD xs
+0x0018 DWORD ys
+0x0060 WORD xs
+0x0064 WORD ys
+0x0068 DWORD[ys] ScanLine offsets relative to end of this table (0x0068 + ys*4)
+0x0068+(ys*4) BYTE[sz-68-(ys*4)] ScanLineData
+0x0060+sz Next frame ImageData if frame<frames
现在终于解码器了
该代码写在Borlands BDS2006 C ++使用VCL TBitmap
和AnsiString
因此,你需要把它改写为你这样的GFX访问和串编程环境的支持。如果您需要有关 gfx 代码含义的帮助,请参阅:
此外,文件访问函数的名称可能略有不同。我对代码做了一些注释,但无论如何它应该是显而易见的。至少对于那些已经做过这样的事情的人来说。
定义只是在调试和正常解码之间切换。如果不存在,则您根本不需要调试图像类img
。为了保持这个简单并且在 30KB 限制内,我删除了调试绘制类的代码(那些想要/需要它的人在编辑历史记录中查看)。这意味着忽略所有_debug_draw
定义......
现在图标定义的像素被正确解码。但我做了很多假设,可能不适用于所有图像。我需要更多关于 ScreenShots 的例子来使它更健壮。代码本身应该编码 alpha 通道,也可能是位置/偏移量。
我更改了一些代码,现在我暂时忽略了当存在未正确解码的代码时会造成混乱的0x02
结尾ScanLine
。我还添加了一些我发现的特殊情况。模式 1 的 x 偏移也存在。
在代码查找行中:
// image data (decoded)
这就是主要解码的地方。解码变量是:
_pixel
- 接下来BYTE
是像素
_sequence
- 像素序列如下(以渲染0x01
或0x03
渲染超过 5 个像素结束)
_stop
- 标记为扫描线的结束 0x02
seq
- 只计算序列中处理了多少像素
在注释中,一些代码被标记// OK
为不冲突且简单明了。其余注释表示以下代码:
pXX
表示像素 0xXX
cXX
手段代码 0xXX
?XX
意味着不确定是像素还是代码
?pXX
表示最有可能的像素 0xXX
Transparent ScanLine 数据在第一个 BYTE 之后开始,所以不要只跳过 2 个字节!!!
这里有一些预览:
和龙帧:
解码器的 C++ 源代码:
#ifdef _debug_save
AnsiString dbg_hdr="file K E R D file_size frames image_ofs palette_ofs used_colors\r\n";
AnsiString dbg_img=" frame sz xs ys xs ys \r\n";
#endif
void load_drk(Graphics::TBitmap *bmp,AnsiString name)
{
AnsiString s,fnam;
fnam=name.SubString(1,name.Length()-4);
// variables
BYTE *dat;
int hnd,adr,adr0,siz;
int i,x,y,xs,ys,sz,mode,frame,frames;
DWORD *p,*dir,pal[256],r,g,b,a;
// allow direct pixel access
bmp->HandleType=bmDIB;
bmp->PixelFormat=pf32bit;
// read file into memory
hnd=FileOpen(name,fmOpenRead);
if (hnd<0) return;
siz=FileSeek(hnd,0,2);
FileSeek(hnd,0,0);
dat=new BYTE[siz];
if (dat==NULL) { FileClose(hnd); return; }
FileRead(hnd,dat,siz);
FileClose(hnd);
// decode
for (;;)
{
#ifdef _debug_save
// save frames to bmp
s=fnam+" ";
s=s.SubString(1,20);
dbg_hdr+=s;
dbg_img+=s;
dbg_hdr+="00000000: "; for (i=0;i<0x60;i++) { s=s.sprintf("%X ",dat[i]); while (s.Length()<3) s="0"+s; dbg_hdr+=s; }
dbg_hdr+="\r\n";
#endif
// signature
if (siz<0x3C8) break;
if (((DWORD*)(dat))[ 0]!='DREK') break;
if (((DWORD*)(dat))[ 2]!= siz) break;
// palette
for (adr=0x060,i=0;i<256;i++)
{
b=dat[adr]; adr++;
g=dat[adr]; adr++;
r=dat[adr]; adr++;
pal[i]=(r<<16)|(g<<8)|(b);
}
// frames
frames=((WORD*)(dat+0x0E))[0];
adr0 =((DWORD*)(dat))[4];
for (frame=0;frame<frames;adr0+=sz+0x60,frame++)
{
adr=adr0;
// resolution
if (adr0+0x60>siz) break;
sz=((DWORD*)(dat+adr))[4];
xs=((DWORD*)(dat+adr))[5];
ys=((DWORD*)(dat+adr))[6];
if (adr0+0x60+sz>siz) break;
bmp->SetSize(xs,ys);
#ifdef _debug_save
// save frames to bmp
if (frame) dbg_img+=" ";
s=s.sprintf("%X: ",adr0); while (s.Length()<10) s="0"+s; dbg_img+=s;
for (i=adr0;i<adr0+0x68;i++) { s=s.sprintf("%X ",dat[i]); while (s.Length()<3) s="0"+s; dbg_img+=s; }
dbg_img+="\r\n";
#endif
// scanline table
dir=new DWORD[ys+1];
if (dir==NULL) break;
adr+=0x68;
for (y=0;y<ys;y++)
dir[y]=adr+(ys<<2)+((DWORD*)(dat+adr))[y];
dir[ys]=adr0+sz+0x68;
#ifdef _debug_draw
// set size and palette of debug image
img.resize(xs,ys);
for (i=0;i<256;i++) img.rgb_pal[i]=pal[i];
// copy reference data to debug image
for (y=0;y<ys;y++) img.p[y].ref="";
if ((png->Height)&&(png->Width))
{
Graphics::TBitmap *qqq=new Graphics::TBitmap;
qqq->Assign(png);
qqq->HandleType=bmDIB;
qqq->PixelFormat=pf32bit;
for (y=0;(y<qqq->Height)&&(y<ys);y++)
{
img.p[y].ref="";
img.p[y].cmp="";
p=(DWORD*)qqq->ScanLine[y];
for (x=0;(x<qqq->Width)&&(x<xs);x++)
{
for (a=0,b=256,g=768;a<256;a++)
{
r=rgb_absdistance(p[x],pal[a]);
if (g>r) { g=r; b=a; }
} a=b;
if (g) g='1'; else g='0';
img.p[y].ref+=char(BYTE(a));
img.p[y].cmp+=char(BYTE(g));
}
}
delete qqq;
}
// copy encoded data to debug image
for (y=0;y<ys;y++)
{
adr=dir[y];
img.p[y].adr=adr;
img.p[y].enc="";
img.p[y].dec="";
img.p[y].spc="";
for (;adr<dir[y+1];adr++)
img.p[y].enc+=char(BYTE(dat[adr]));
}
#endif
// image data (decoded)
a=dat[dir[0]];
mode=0; if (a!=0xFC) mode=1;
for (y=0;y<ys;y++)
{
adr=dir[y]; // get actual ScanLine offset in file
p=(DWORD*)bmp->ScanLine[y]; // get actual ScanLine pointer in bmp
int _sequence=0;
int _pixel=0;
int _stop=0;
int seq=0;
for (x=0;x<xs;x++) p[x]=0; x=0;
if (mode==1)
{
// 1st ScanLine BYTE (x-offset)
a=dat[adr]; adr++;
if (BYTE(a&1)==1)
{
x=(a>>1)+1;
#ifdef _debug_draw
for (i=0;i<x;i++) img.p[y].spc+='\0';
#endif
}
// 2nd ScanLine BYTE special cases
a=dat[adr];
if (a==0x0D) adr++;
}
for (a=0;adr<dir[y+1];)
{
if (mode==0)
{
a=dat[adr]; adr++; // color index
if (int(x&31)==0)
{
r=a; // flag
a=dat[adr]; adr++; // color index
}
}
if (mode==1) for (;;)
{
a=dat[adr]; adr++; // color index
if (_pixel) { _pixel=false; break; }
if (_sequence) { seq++; if (seq<6) break; }
// commands
if (a==0x01)
{
a=dat[adr]; adr++;
_pixel=true; _sequence=false;
//if (a==0x07) { adr++; _pixel=false; }
continue;
}
if (a==0x03)
{
if (!_sequence)
{
if (dat[adr]==0x18) _pixel=1;
continue;
}
if (_sequence==0x2B) break;
a=dat[adr]; adr++;
_pixel=true; _sequence=false;
//if (a==0x07) { adr++; _pixel=false; }
continue;
}
if (_sequence) break;
// unused: 0A,14,1F,20,21,22,24,25,26,28,29,2A,2C+
// flag/color prefix
// if((a==0x02)&&(adr>dir[y]+3)) { _stop=true; break; } // end of ScanLine
if (a==0x04) { _pixel=1; continue; } // ?? ?p18 p47 ?p47
if (a==0x05) { _pixel=1; continue; } // ?? ?18 ?09
if (a==0x06) { _pixel=1; continue; } // ?? ?p18 ?p47
if (a==0x07) { _pixel=1; continue; } // ?? ?18 ?46 ?47
if (a==0x08) { _pixel=1; continue; } // ?? ?09
if (a==0x09) { _pixel=0; continue; } // ?? ?p02 !!!!!!!!!!!
if (a==0x0B) { _pixel=1; continue; } // ?? ?p02
if (a==0x0C) { _pixel=1; continue; } // OK p1D
if (a==0x0D) // ?? c04 p23 ?c06 p05 p12
{
_pixel=0;
if (dat[adr]==0x02) _pixel=1;
if (dat[adr]==0x05) _pixel=1; // p47 c0D p05 | c0D c05 p09
if (dat[adr]==0x12) _pixel=1;
if (dat[adr]==0x23) _pixel=1;
continue;
}
if (a==0x0E) { _pixel=1; continue; } // OK p24 p26 p16
if (a==0x0F) { _pixel=1; continue; } // OK p0F
if (a==0x10) { _pixel=1; continue; } // OK p04
if (a==0x11) { _pixel=1; continue; } // ?? ?p02
if (a==0x12) { _pixel=1; continue; } // OK p27
if (a==0x15) { _pixel=1; continue; } // OK p16
if (a==0x16) { _pixel=1; continue; } // OK p16
if (a==0x18) { _pixel=1; continue; } // OK p00 p02
if (a==0x19) // ?? p1B
{
_pixel=1;
if (dat[adr]==0x01) _pixel=0;
continue;
}
if (a==0x1A) { _pixel=1; continue; } // OK p05 p04
if (a==0x1B) { _pixel=1; continue; } // OK p1F
if (a==0x1C) { _pixel=1; continue; } // OK p10
if (a==0x1D) { _pixel=1; continue; } // OK p33 p1E p14
if (a==0x1E) { _pixel=1; continue; } // OK p34 p50 p13
// test from dragon and mountain
if (a==0x49) { _pixel=1; continue; } // ?? ?p02
if (a==0xE3) { _pixel=1; continue; } // ?? p18
if (a==0xD7) { _pixel=1; continue; } // ?? pBC
if (a==0xDA) { _pixel=1; continue; } // ?? ?p02
// sequence start
if (a==0x13) { seq=0; _sequence=a; } // 03
if (a==0x17) { seq=0; _sequence=a; } // 01
if (a==0x23) { seq=0; _sequence=a; } // 01 03
if (a==0x27) { seq=0; _sequence=a; } // 01
if (a==0x2B) { seq=0; _sequence=a; } // 01 !03 03
if (_sequence)
{
if (adr==dir[y]+3) { _sequence=false; break; }
continue;
}
break;
}
if (_stop) break;
if (x>xs) break;
if ((mode==1)&&((a==0xFE)||(a==0xFF))) { a=dat[adr]; adr++; } // shadows?
if ((x>=0)&&(x<xs)) p[x]=pal[a]; x++;
#ifdef _debug_draw
// copy decoded data to debug image
img.p[y].dec+=char(BYTE(a));
#endif
}
}
delete[] dir; dir=NULL;
#ifdef _debug_save
// save frames to bmp
s=frame;
while (s.Length()<3) s="0"+s;
png->Assign(bmp);
png->SaveToFile("decoded_"+fnam+"_"+s+".png");
#endif
}
img.compute();
break;
}
delete[] dat;
}