By Kylinx E-mail:game-diy@163.com
现在的游戏资源资源在网上都不少了,可是发现有些不合适自己的游戏 (哈哈,不是专业的制作嘛,学习研究:)),在网上找了大半天也没有~ 没办法了,自己动手,丰衣足食:)经过整整3天的不懈努力,终于成功 提取出了图片数据!下面谈谈整个分析过程和结果
拿阿玛迪斯战记(The Lord of Beast)以下简称Lob("萝卜"哈哈)这个SLG游戏来开刀:) 先废话几句话~ 本来已开始也不是打算分析这个游戏的,因为打算要写SLG类的,正好手上有一个 "梦幻模拟战3"的游戏,图片还不错,就立马用UltraEdit来分析了~~,累了一上午和 一个下午,收获到不少,不过只是把里面的打包格式给解了出来,图片的压缩方法 仍然搞不定(看起来不太像简单的RLE压缩),算了,反正抽屉里还有一个,就是 "萝卜",咋一看,这个游戏的资源没有打包~就少了第一层障碍~ 本来以为是很简单的格式,后来才发觉错也!!
开始分析.... 准备工作: 打开UltraEdit(以下简称UE),计算器.... 用UE随便打开几个"萝卜"的后缀为sf2的文件(map文件夹的一些例外,不过格式和 下面要分析的差不多) 发现前面12个byte都是固定的(以下称ID),就不管那个了 晕~接下来的这么多乱七八糟的东西是什么啊! 还有一大堆的00~ 最多也就判断除了ID外,剩下的8个byte估计是width,height... 没办法了,太多,重新想其他办法
打开data文件夹,发现里面有个mouse.sf2文件,嘿嘿,不用说就知道这个肯定是 鼠标的图片文件,嘿嘿,随便找个其它的文件替换之!再运行游戏... (当时我选的是face\face000.sf2) 能正常进入了,怪,怎么鼠标的活动范围减少了? 并且指示到菜单的位置有偏移了,于是猜想有个offsite的位 还有,图片有2帧,用UE找找看是在哪里...
发现了2个位置0x14处和0x1e处,究竟是哪一个呢?先改前面一个看看 于是把0x14处的02 00改为01 00,再进入游戏,嗬嗬,这下好了,只有1帧了! 于是判断0x14处的2个byte为动画帧数.
后面一个呢?猜想为总的帧数(结果证明猜想正确) 0x16处的BC 42是什么东西?怎么每一个文件都一样?初看之下,以为是一些垃圾数据 就不去管了,后面的从0x20处开始,究竟哪个是数据的offsite呢? 先找到0x20处的4个byte的位置....
又发现了一大堆的4个byte的东西(#1),后面有很多00,如果用RLE压缩后,应该不可能出现 这些东西,如果不压缩呢?帧数*宽度*高度*2个byte都大于了文件长度,再说combak文件夹的 2个高宽都相同的文件大小也不一样,所以肯定是压缩过了,很容易就想到最简单的 RLE压缩.继续分析上面的,如果不是数据,猜想是某些东西的offsite,又找到下一个地址 又是一大堆很稀疏的00,不管他,继续往下看,又发现了一堆很有规律增加的数, 同理分析也是某些数据的偏移(#2),跳到第一个有规律的数指向的位置,好了 发现,下面开始有很多4,8和c开头的东西~,心里狂喜~这不就是一种RLE压缩的模型 么?
随便修改几个Cx 后面的2byte数据(我修改成ff ff),进入游戏,发现图片最上方 的颜色变了,呵呵,用放大镜放大数了一下,发现正是XX-C0的值加1个 好了,大于等于C0的就是重复的数据
继续分析8X,修改后得出的结论是不重复数据,数量为XX-80+1 4X是什么?修改了一下,发现是偏移(其实不是),后来经过多次试验后 发现是透明色的个数!并且发现了图片的存放格式不是整块,而是分块的 经过多次实践,发现是0x30*0x30的大小,也就是48*48
既然知道了这些,那么解压缩就很简单了:如下 bool decode(unsigned char*pbuf,int size,unsigned short**ppbuf,unsigned long*psize) { unsigned char*pbufend=pbuf+size; unsigned short*temp=new unsigned short[1<<20]; unsigned short*ptr=temp; int resize=0; while(pbuf<pbufend) { if(*pbuf>=0xc0) { int all=((unsigned char)*pbuf)-0xc0; pbuf++; WORD value=*(WORD*)pbuf; pbuf+=2; for(int i=0;i<=all;i++) { *ptr=value; ptr++; } resize+=all+1; } else if(*pbuf>=0x80) { int all=((unsigned char)*pbuf)-0x80; pbuf++; unsigned short*pvalue=(WORD*)pbuf; for(int i=0;i<=all;i++) { *ptr=*pvalue; ptr++; pvalue++; } pbuf=(unsigned char*)pvalue;//all*2; resize+=all+1; } else if(*pbuf>=0x40) { int all=((unsigned char)*pbuf)-0x40; for(int i=0;i<=all;i++) { *ptr=0x7c3f; ptr++; } resize+=all+1; pbuf++; } else { *ppbuf=temp; *psize=resize; return true; } } *ppbuf=temp; *psize=resize; return true; } 再看看是555还是565格式,很简单的,填充一些555的点和565的点到数据里面 再进入游戏看看就知道了!结果发现是555格式
剩下的问题,数据大小是多少? 再返回上面的一大堆offsite的位置#2,把后面一个减去前面一个后,读出这么多数据来 解压看看,解压后,再转换为bmp格式,发现正确!
#1处的偏移是什么呢? 既然图片是通过Tile的方式拼接成的,那么就肯定有TIle的信息,所以找找看~~ 经过多次失败,终于找到了有用的几个位:每一行Tile数,每一列Tile数 Tile的索引....
大概就是这些,上面虽然说了很少,但是其实在真正的分析中,弄得我是焦头烂额, 还打算放弃分析过~好在有时候突然发现了"玄机",动力大增... 总之,"萝卜"的图片格式还是比较复杂的,(真想说是bt) 现在虽然还不明白一些数据的作用,但是也不妨碍分析出它的图片数据 文件头信息基本上如下 0x00----ID,12byte 0xC-----宽度4byte 0x10----高度4byte 0x14----帧数2byte 0x16----帧属性偏移4byte 0x1a----未知4byte 0x1e----图片数2byte 0x20----图片信息的偏移4byte 0x24----未知4byte 0x28----TILE数量2byte 0x2a----Tile信息偏移4byte 0x2e----未知2byte 0x30----未知4byte 0x34----文件大小4byte 0x38后面的一直到0x42bc处都不知道 0x42bc---每一帧的信息偏移,比如有4个帧(0x14处),就有4个dword的偏移值 得到的偏移地址,假设为0x42c0,则0x42c0处 起始84个byte都基本上用不到 不过也说一下吧,相对0x42c0处偏移8个字节为帧宽,相对偏移12个字节为高 其他的不知道了 相对偏移86处,是这个帧有几张图片,2byte 接下来的就是每个帧中的图片信息 相对偏移为0处,为图片的索引2byte 相对偏移为2处,为该图片相对于屏幕的x偏移2byte 相对偏移为4处,为该图片相对于屏幕的y偏移2byte 相对偏移为6处,未知4byte 相对偏移10处,为该图片的显示模式,比如是否Addtive,alpha等等 接下来的15个byte都不清楚
图片信息偏移处(0x20处的偏移地址的东西) 相对偏移0处,为该图片每行有多少个tile---2byte 相对偏移2处,为该图片每列有多少个tile---2byte 接下来的20个byte不清楚 相对偏移24处,是图片中的tile索引
Tile信息偏移处(0x2a处的偏移地址的东西) 对应的n个dword都是每一个tile的数据偏移(数据终于出来了) 其中n是0x28处的值 再下来就是数据内容了,按照上面的方法就可以解压缩~
阿!终于写完了,分析了几天,头都大了,写的这些东西也乱七八糟 不知道对大家有没有什么帮助,如果觉得没有的话,就当着垃圾丢到一边去 不用管了~ 在这里再提供一个我自己写的"萝卜"图片资源抓取的软件(很抱歉,我懒得去 用mfc来写了,就用console的形式吧,如果您自己感兴趣,可以根据上面我分析 出的一些东西自己写一个吧~) 需要的朋友们请到我的小组(Game++Studio)主业上下载 http://www.gamepp.org/tools/lobpiccracker.exe另外注意一下,由于map文件夹中的mapXX.sf2的文件存放方式和其他的不一样(其实格式相对于其他格式来说更加简单了!), 所以这个软件不能分析出mapXX.sf2的文件,有兴趣的朋友就自己去研究吧:)这里就不耽搁大家时间了:)
最后,由于本人水平有限,分析的东西可能会有很多不当之处,还望大家多多指教! 如果有任何问题,欢迎与我联系 E-mail:game-diy@163.com OICQ:30784290(难得糊涂) http://www.gamepp.org/ |