我们接着上一次,解决遗留的问题,然后遗留新的问题
本系列基本完结,以下是目录供快速翻阅:
上一期我们的读取程序在四个平面读取完毕后就终止了,然后只画出了一点点图像, 所以一定是没有读完,从 dosbox-x 的日志我们也可以确认这一点:
一万多行就已经读到四个 0xff
了,但是进度条显然文件还有很多内容没读,
但是四个平面都已经读到了终止符,这应该也就是我们只画出一点点内容的原因。
但是 FUN_1427_38af
应该没有值得我们注意的内容了,所以我们要再往上看一层。
找上层代码的位置,最快的方法是看日志中回到了哪里:
1427:0000018F inc word cs:[00DC] cs:[00DC]=00B4 2E FF 06 DC 00 EAX:00003AFF EBX:00003E6D ECX:000000FF EDX:0000434E ESI:0000001E EDI:00006874 EBP:00000F78 ESP:00000F6E DS:434E ES:3A28 FS:0000 GS:0000 SS:218C CF:0 ZF:0 SF:0 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007212 CR0:00000010
然后在 ghidra 中定位代码:
这里面有两个细节需要我们注意:
所以需要引入一个偏移量,一个控制循环次数的变量,前面读取时,我默认每平面开始的偏移量都是 0, 那么改成每次读取完成后都加 1,就好了,然后对于循环的次数,这个数字其实是从文件中读取的:
读取出 0x09
位置的 0x28
,然后除以 2 得到,事实上用 0x08
位置的 0x14
应该也可以。
因为看上去这三位保持 [0x08] * [0x0a] = [0x09]
的关系。
解决了这两个问题,我们得到了这样一个图:
我们跟实际的画面做一个对比:
首先我们的大方向肯定是对了,因为图形基本上已经出来了,只是问题也很明显:
所以我们接下来要找到调色板,以及我们之前绘图函数中的问题。
我们之前的系列,调色板基本无一例外都是猜出来的,这次也不例外,其实前面我们看到的黄色图像, 已经是我们猜测的第一版的结果了,重新看这里:
我们之前提到了 gdt 文件读取完第一行数据后会跳过 24 个字节,这 24 个字节一眼望上去没看出什么规律,
但是写完绘图函数后,再看这组数据可能就有感觉了,因为我们可以发现,这组数据以 000
开头,FFF
结尾。
这就很像是调色板了,为什么说写完绘图函数会理解这个,
是因为绘图函数中就有把 0xAE
展开为 0xAA 0xEE
的操作,这样看来的话,24 个字节,
展开后正好是 16 个颜色。所以如果这是调色板的数据,那么留给我们的问题变成了两个:
RGB 的排列有 6 种,四平面的排列虽然有 24 种,但是估计只会有 [0123] 和 [3210] 两种排法, 我想一般不会有人会设计出类似 [2301] 这种的排列方式,为自己徒增烦恼。对于上面的黄色图案, 我印象是按 RGB + [3210] 的排列方式画出来的,看来运气不是很好,不过很快也就发现,实际的排列方式是 BRG:
这个配色是不是就和实际的配色对上了,不要问我为什么会这样排,另外,四平面的排列方式是 [3210], 也就是第一个平面在最小位,可能也算是 little endian?
总结我们已知的内容:
0x10..0x28
的位置,以 BRG 的顺序排列,同屏 16 色,最多 4096 色(16x16x16)目前我们还剩下绘图函数错误的问题,下次再分析吧,如果你的观察仔细,其实还有一个小问题, 我们也放在下次一起说吧。