【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2527|回复: 2

[转帖]关于金山公司的剑侠情缘系列游戏的图片格式

[复制链接]
发表于 2005-2-28 19:40:03 | 显示全部楼层 |阅读模式
我对金山公司的剑侠情愿系列的图片是仰慕已久啊!最近实在憋不住,我就开始的艰难的图片格式探索.但是在发表这篇文章的中心内容之前,我郑重声明,我对这篇文章所造成的后果不承担任何责任,我是一个游戏的探索者,没有对这种方法和使用这种方法获得的任何数据作任何的商业化.请读者只是将获得的数据用于自己的研究. 通过这种技术,剑侠情缘系列的所有图片就将是垂手可的!但是不要侵犯版权,一切图片都是金山公司所有,自己用吧,不用找美工了!好爽啊!! 好了,言归正传.我们研究的游戏是,剑侠情愿的 demo2 ,研究之后的技术是通用的. 我们来看,在demo2 中有 "Data" 这样一个文件夹,在这里,所有的文件都是 *.dat. 我们知道这里是游戏数据的仓库,那么,他的图片肯定放在这里,看见哪个 graphic.dat 了么?图片肯定就在里面向你傻笑!还有一个叫 gamedata.dat 猜想他里面肯定是 游戏的脚本之类的东东,我们使用一个叫 "WinHex" 的工具软件(好象是黑客 :> ),打开gamedata.dat ,里面是什么?请看下文(别急吗!) 在gamedata.dat 中是游戏的脚本还有一些对话信息,至于是以什么格式存储的,我不多说了.我们的重点是得到图片格式.现在干什么?找啊.我第一个想到的就是 "南宫飞云", 找吧!!找到了好多,注意有一些叫什么 "z02-南宫飞云-sp.mpc",有好多叫什么 *.mpc ,你明白了么?"mpc"肯定就是图片的扩展名。那么接下来呢,我到 graphic.dat 中找 "z02 -南宫飞云-sp.mpc",结果,什么都没有,怎么,完蛋了?我猜想肯定文件名被转换成数字,变成编号了,于是呼,我开始疯狂的查找有关与文件名转换成数字的方法,结果,你都猜到了,我被搞的差点仙去!!我想我一辈子也别想知道 西山居是怎么转的,因为随便就能找到一种方法。就这样结束了么? 实在难受,我就随便的看 gamedata.dat 中的内容,突然发现 "MPC File Ver2.0",哦,我知道了,这是mpc的第二版.会不会是一个标记呢?我也写过游戏数据的封装,我的图片标记就是 "清风引擎图片 Ver1.0",每张图片都有,那么!!!哈哈!!! 你知道我要做什么?我到graphic.dat 中查找 "MPC File Ver2.0",谢天谢地,西山居竟然是这样...哈哈...我统计了一下,在graphic.dat 中有 1300多个 "MPC File Ver2.0",啊,我们找了!!!开始破解文件头格式吧!!!也!!! 我们来想想,文件头中有什么,应该是,图片的宽.高.长度.是否压缩.有几张小图片.图片的点是什么格式(8,16,24...),是不是有调色板(游戏引擎自定义的调色板),那么只要找到一个数据来测试,就可以一步一步的揭开,最容易想的就是图片的宽和高.多数是固定的.现在,我们在 gamedata.dat 中找一些关于宽和高的信息,很简单,我们知道了"\mpc\ui\dialog\panel.mpc"的宽是"440",高是"90",都是写英文和中文,你查看gamedata.dat 时就会发现的.我将宽和高转化成16进制的数,凭经验,宽在前,高在后, 查找 " B8 01 00 00 45 00 00 00 "找到了么?你可以发现就一个,说明什么??还有,你看到在 这个数字的前边不远就是 "MPC File ver2.0",哈哈!!!再多查几个,是不是相对位置永远都是那样!   今天接着写.上次说在gamedata.dat 还有 graphic.dat 中查找 mpc...的内容,其实. graphic.dat 中的内容是压缩的(图片头只是压缩了一部分),所以从这两个文件中我们不可能简单的提取出图片信息.但是游戏在运行时肯定要解压,那么图片的信息就应该能够以原型出现在内存中,那么我们就来察看运行时的游戏内存. 使用winhex 的 ram 编辑工具,察看jxqydemo2 的主内存(进程名称为sword). 找到某个 MPC File Ver2.0... 没时间了,以后再写. 想写好一部文章真的挺难。 好了,努力一点。 上回说到使用WinHex查看jxqyDemo2的内存,不知道诸位有否去做了?结果么便是非常的少了,不过总会有点收获吧。前文提到“\mpc\ui\ dialog\panel.mpc"的宽是"440",高是"90",都是写英文和中文,你查看gamedata.dat 时就会发现的.我将宽和高转化成16进制的数,凭经验,宽在前,高在后,查找 " B8 01 00 00 45 00 00 00 ”那么,我们就再来找" B8 01 00 00 45 00 00 00 ",结果?!他的上面是不是也有“MPC File Ver2.0”,先不管他。多找几个"MPC File Ver2.0",比如,我知道“剑侠情缘”的最下面的控制面板(就是放物品小图标和武功小图标的大长条),他的宽是"640",高是"69",二进制就是 “80 02 00 00 45 00 00 00”,找他!好了这一下就能够确定图片结构中是: 标志 : MPC File Ver2.0 [16字节之后 : xx [这个 Int(4字节)是之后的图片数据的长度] 之后 : yy [这个Int 是图片的“最大”宽度] 之后 : zz [这个Int 是图片的"最大"高度] ..... 那么?就这样结束了么??远远没有,好戏还在后头! 今天,我把他的图片格式公布如下。 感兴趣的朋友可以试试。 调色板的结构: struct MPCPALETE { unsigned blue:8; unsigned green:8; unsigned red:8; unsigned alpha:8; //不知道什么作用 } 图片数据的头结构: struct MPCPICDATAHEADER { int picDataSize; int picWidth; int picHeight; int NULL1; // 0 //不知道是什么 int NULL2; // 0 } MPC 图片文件的头结构: struct MPCFILEHEADER { char mpcFlag[16]; // 标志 "MPC File Ver2.0" int mpcNULL1[12]; // 0 int mpcPicDataSize; // 图片数据长度 int mpcMaxWidth; // 所有图片中最大的宽度 int mpcMaxHeight; int mpcPicCount; int mpcPicBitCount; // 8 int mpcPalleteSize; // 调色板数据的长度 int mpcNull3; // 0 } MPC 文件的结构如下: 先是一个头结构:mpcFileheader 接下来是调色板信息:每个颜色32位(MPCPALETE),长度是mpcFileHeader.mpcPalleteSize . 接下来是偏移表,每个偏移量用一个整数(4字节)表示,有多少张图片,就有多少个偏移量。 最后就是图片数据了。 图片数据有一个头结构 ( MPCPICDATAHEADER ),这里的图片的长度不包括这个头结构(重点注意),头结构之后就是压缩后的图片数据了 还有,图片的压缩其实很简单。 比如:(16进制) 84 04 23 45 23 35 .... 那么,他是什么意思呢? 84 ? 先来看 “80”,在二进制中,一个字节最大 “FF” (1111 1111),“80”(1000 0000),其实,“80”,相当与 “-0”,就是负号,那么‘81’,就是“-1”,那么,这个有什么用呢? 你可以看到很多的 “7F”,你问我“为什么你能发现压缩的规律”,其实就是这些分布规则的“7F”告诉我的,你看,"7F"(也就是127),之后恰好有 127 字节,接着又是一个“7F”....,所以我猜测"7F"就是这一块颜色索引的长度,那么,所有的都是么?"84“又是什么呢?你知道,就是 ”-4“ 了,其实啊,就是透明色的个数,当然是连续的透明色的个数。那么”04“? 他啊,就是不透明的连续颜色索引的个数!那么如下的一段压缩码: 84 03 23 23 23 89 06 89 89 89 89 89 89 89 ... ... 是什么意思呢? 有兴趣的朋友可以发贴来猜猜!!!
 楼主| 发表于 2005-2-28 19:40:19 | 显示全部楼层
代码:
                                                我可是从家里电脑抄到纸上,再从纸上抄到这里,大家要珍惜啊。



void                savebmp(const char *bmpfileName,unsigned char *
                                                                                                                                                                                                bmpData,int nDataLen,int nWidth,int nHeight);

void                mpc2bmp(const char *mpcFileName)
{
                 FILE                                                                                                                                *mpcfile=NULL;
                 int                                                                                                                                                 nbmpFileNameLen=strlen(mpcFileName);
                 char                                                                                                                                *bmpfileName=new                 char[nbmpFileNameLen+3];
                 char                                                                                                                                *bmpFileName=new                char[nbmpFileNameLen+3];
                 memset(bmpFileName,0,nbmpFileNameLen+3);
                 memset(bmpfileName,0,nbmpFileNameLen+3);
                 strcpy(bmpFileName,mpcFileName);
                 strcat(bmpFileName,"%d.bmp");
                 nbmpFileNameLen-=4;
                 
                 MPCFILEHEADER                                                                 mpcFileHeader;
                 MPCPICDATAHEADER                mpcPicDataHeader;
                 unsigned                char                                                                                 *picData=NULL;
                 unsigned                char                                                                                 *bmpData=NULL;
                 int                                                                                                                                                                                                                                                                row=0;
                 int                                                                                                                                                                                                                                                                col=0;
                 int                                                                                                                                                                                                                                                                maxrow=0;
                 int                                                                                                                                                                                                                                                                maxcol=0;
                 int                                                                                                                                                                                                                                                                nextColorOffset=0;
                 int                                                                                                                                                                                                                                                                nextColorOffsetInBmp=0;
                 int                                                                                                                                                                                                                                                                npicCount=0;
                 int                                                                                                                                                                                                                                                                bmpBufLen=0;
                 int                                                                                                                                                                                                                                                                mpcBufLen=0;
                 int                                                                                                                                                                                                                                                                i=0;
                 
                 mpcfile=fopen(mpcFileName,"rb");
                 if(mpcfile==NULL)
                 return;
                 fread(&mpcFileHeader,1,sizeof(mpbFileHeader),mpcfile);
                 MPCPALETE                                                                                                                                                *mpcPalete=new                 MPCPALETE                mpcFileHeader.mpcPalleteSize];
                 fread(mpcPalete,4,mpcFileHeader.mpcPalleteSize,mpcfile);
                 int                                                                                                                                                                                                                                                                 *mpcPicOffset=new                int[mpcFileHeader.mpcPicCount];
                 fread(mpcPicOffset=n,1,mpcFileHeader.mpcPicCount*4,mpcfile);
                 fread(&mpcPicDataHeader,1,sizeof(mpcPicDataHeader),mpcfile);
                 mpcBufLen=mpcPicDataHeader.picSize-sizeof(mpcPicDataHeader);
                 picData=new                unsigned                char[mpcBufLen];
                 fread(picData,1,mpcBufLen,mpcfile);
                 bmpBufLen=mpcPicDataHeader.picHeight*(mpcPicDataHeader.picWidth*3+mpcPicDataHeader.picWidth%4);
                 bmpData=new unsigned char[bmpBufLen];
                 maxcol=mpcPicDataHeader.picWidth;
                 maxrow=mpcPicDataHeader.picHeight;
                 
                 while(1)
                 {
                                                 col                 =0;
                                                 row =0;
                                                 nextColorOffset=0;
                                                 nextColorOffsetInBmp=0;
                                               
                                                 while(nextColorOffset<mpcBufLen)
                                                 {
                                                                                 if(picData[nextColorOffset]>0x80)
                                                                                 {
                                                                                                                 i=picData[nextColorOffset]&0x7F;
                                                                                                                 while(i>0)
                                                                                                                 {
                                                                                                                                                                bmpData[nextColorOffsetInBmp++]=0xFF;
                                                                                                                                                                bmpData[nextColorOffsetInBmp++]=0x00;
                                                                                                                                                                bmpData[nextColorOffsetInBmp++]=0xFF;
                                                                                                                                                                --i;
                                                                                                                 }
                                                                                                                 col=0;
                                                                                                                 ++row;
                                                                                 }
                                                                                 ++nextColorOffset;
                                                 }
                                                 i=picData[nextColorOffset];
                                                 ++nextColorOffset;
                                                 while(i>0)
                                                 {
                                                                                                bmpData[nextColorOffsetInBmp]=
                                                                                                mpcPalete[picData[nextColorOffset]].blue;
                                                                                                ++nextColorOffsetInBmp;
                                                                                                bmpData[nextColorOffsetInBmp]=
                                                                                                mpcPalete[picData[nextColorOffset]].green;
                                                                                                ++nextColorOffsetInBmp;
                                                                                                bmpData[nextColorOffsetInBmp]=
                                                                                                mpcPalete[picData[nextColorOffset]].red;
                                                                                                ++nextColorOffsetInBmp;
                                                                                                ++nextColorOffset;
                                                                                                ++col;
                                                                                                ++i;
                                                                }
                                                                if(col==maxcol)
                                                                {
                                                                                                 for(i=0;i<mpcPicDataHeader.picWidth%4;i++)
                                                                                                {
                                                                                                                                 bmpData[nextColorOffsetInBmp]=0;
                                                                                                                                 ++nextColorOffsetInBmp;
                                                                                                }
                                                                                                col=0;
                                                                                                ++row;
                                                                 }
                                 }
                                 
                                 wsprintf(bmpfileName,bmpFileName,npicCount);
                                 savebmp(bmpfileName,bmpData,bmpBufLen,
                                                                                                                                                                 mpcPicDataHeader.picWidth,
                                                                                                                                                                 mpcPicDataHeader.picHeight);
                                 delete                                 bmpData;
                                 delete                                 picData;
                                 ++npicCount;
                                 if(npicCount<mpcFileHeader.mpcPicCount)
                                 {
                                                                                fread(&mpcPicDataHeader,1,sizeof(mpcPicDataHeader),mpcfile);
                                                                                mpcBufLen=mpcPicDataHeader.picSize-
                                                                                                                                                                                                                                 sizeof(mpcPicDataHeader);
                                                                                picData=new                                                 unsigned char[mpcBufLen];
                                                                                bmpBufLen=mpcPicDataHeader.picHeight*
                                                                                                                                                                                                                                                mpcPicDataHeader.picWidth*3+
                                                                                                                                                                                                                                                mpcPicDataHeader.picWidth%4);
                                                                                bmpData=new unsigned char[bmpBufLen];
                                                                               
                                                                                fread(picData,1,mpcbufLen,mpcFile);
                                                 }
                                                 else
                                                                                                break;
                                               
}

void                savebmp(const char *bmpfileName,unsigned char *
                                                                                                                                                                                                bmpData,int nDataLen,int nWidth,int nHeight)
{
                                                FILE                                                                                                                                                                                                                                                                                *bmpFile=NULL;
                                                BITMAPFILEHEADER                                                                                bmpHeader;
                                                BITMAPINFO                                                                                                                                                                                bmpInfo;
                                                unsigned char                                                                                                                                                 *tempData;
                                                int                                                                                                                                                                                                                                                                                                 nPitch=nWidth*3+nWidth%4;
                                                tempData=bmpData+nDataLen-nPitch;
                                                bmpFile=fopen(bmpfileName,"w+b");
                                                if(bmpFile==NULL)
                                                                                                 return ;

                                                bmpHeader.bfOffBits=54;
                                                bmpHeader.bfSize=nDataLen+54;
                                                bmpHeader.bfType=19778;                                                                 //"BM"
                                                bmpHeader.bfReserved1=0;
                                                bmpHeader.bfReserved2=0;
                                               
                                                bmpInfo.bmiHeader.biSize=40;
                                                bmpInfo.bmiHeader.biWidth=nWidth;
                                                bmpInfo.bmiHeader.biHeight=nHeight;
                                                bmpInfo.bmiHeader.biPlanes=1;
                                                bmpInfo.bmiHeader.biBitCount=24;
                                                bmpInfo.bmiHeader.biCompression=0;
                                                bmpInfo.bmiHeader.biSizeImage=nDataLen;
                                                bmpInfo.bmiHeader.biXPelsPerMeter=3780;
                                                bmpInfo.bmiHeader.biYPelsPerMeter=3780;
                                                bmpInfo.bmiHeader.biClrUsed=0;
                                                bmpInfo.bmiHeader.biClrImportant=0;

                                                fwrite(&bmpHeader,1,sizeof(bmpHeader),bmpFile);
                                                fwrite(&bmpInfo,1,sizeof(bmpInfo),bmpFile);
                                               
                                                fseek(bmpFile,(-1)*sizeof(bmpInfo.bmiColors),SEEK_CUR);
                                               
                                                for(;nHeight>0;--nHeight)
                                                {
                                                                                 fwrite(tempData,1,nPicth,bmpFile);
                                                                                 tempData-=nPitch;
                                                }
                                                fclose(bmpFile);
}





来自:Gameres.com 与 game173.com
发表于 2005-4-3 15:05:46 | 显示全部楼层

大哥辛苦了

我会努力学习的

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-6-23 06:16

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表