例如伏魔记
(数据是可以用c直接读取的)
0x0 :lib
0x3 伏魔记 00 0
0x0E 全局色彩字节数: 2或4,建议选择4
0x0F 非零有压缩,0无压缩,建议选择有压缩1
0x10开始 三字节索引(与lib一致索引)(unsigned char resType ,unsigned char type ,unsigned char index) ...;
(数据是可以用c直接读取的)
0x0 :lib
0x3 伏魔记 00 0
0x0E 全局色彩字节数: 2或4,建议选择4
0x0F 非零有压缩,0无压缩,建议选择有压缩1
0x10开始 三字节索引(与lib一致索引)(unsigned char resType ,unsigned char type ,unsigned char index) ...;
0x2000 开始 四字节地址(相对文件头偏移) (unsigned int mDataOffset)...
typedef struct GMCheadstru{char ckHeadstr[3];//校验GMC
char gamename[9];//游戏名
unsigned short sizeofIndexArea;//索引区域大小
unsigned char sizeofPixcel;// 像素字节数
unsigned char isComressed;//非零为有deflate压缩,0为无压缩
} GMChead; //16字节信息头
GMChead myGMChead;
typedef struct GMCIndexStru{unsigned char resType ;unsigned char objType;unsigned char index;}GMCIndex;
GMCIndex AllGMCIndex[2726]; //与lib一致的索引,0x10开始, (0x2000-16)的索引空间最多2725个资源
unsigned int AllGMCAddr[2725];//地址是真实地址,0x2000开始
初始化读取如下:
FILE* file;
/* 装载源文件数据到缓冲区 */
if((file = fopen("dat.gmc", "rb")) == NULL)
{
printf("Can\'t open %s!\n", "dat.gmc");
return -1;
}
// 测试文件头
fread(&myGMChead,16,1,file);
char testStr[4];
memset (testStr,0,4);
memcpy(testStr,myGMChead.ckHeadstr,3);
if(stricmp(testStr,"GMC")){
printf("不是有效GMC文件\n", argv[1]);
return -1;
}
//判断像素字节大小
if(myGMChead.sizeofPixcel!=4){
printf("不支持的像素字节数 status:%d","");
return -1;
}
//读取索引和地址
fseek(file,16,SEEK_SET);
fread(&AllGMCIndex,0x2000-16,1,file);
fseek(file,0X2000,SEEK_SET);
fread(&AllGMCAddr,2725<<2,1,file);
索引查找方法
unsigned int getGMCAddr(int rType, int otype, int oindex){
int i=0;
int j=0;
while(i<2725&&(j=AllGMCIndex[i].resType)<15){
if(AllGMCIndex[i].resType==rType&&AllGMCIndex[i].objType==otype
&&AllGMCIndex[i].index==oindex) return AllGMCAddr[i];
i++;
}
return 0;
}
读取案例:
int resaddress=getGMCAddr(5,2,1);
printf("mySrs resaddress=%d\n",(int)resaddress);
fseek(file,resaddress,SEEK_SET);
Srs *mySrs=readSrs(file);
resaddress=getGMCAddr(7,1,1);
printf("mPic resaddress=%d\n",(int)resaddress);
fseek(file,resaddress,SEEK_SET);
Pic*mPic=readpic(file);
#include "zlib\zlib.h"
#pragma comment(lib,"zlib\\Release\\zlib.lib")
使用了zlib读取需导入zlib库
资源数据只有动画 和图片数据不一样,其他例如脚本、NPC、地图等数据与lib一致。
地图图片分割为32*32,npc大多数也是32的倍数,最常见RPG素材是32分割,源码中已经收集齐几乎所有符合这种RPG彩色的NPC素材和地图素材。
战斗背景320*200(来源于仙剑98图片资源),也就是主窗口至少320*200(因为仙剑98也是这么大窗口)
地图资源多数是来源于轩辕剑之枫之舞地图。
pic数据 mDataOffset +0
头6字节,依次是
mWidth,mHeight,mNumber,mTransparent
typedef struct Picheadstru{unsigned short mWidth ;
unsigned short mHeight;
unsigned char mNumber;
unsigned char mTransparent;} Pichead;
typedef struct pixcelstru{unsigned char blue;
unsigned char green;
unsigned char red;
unsigned char alpha;} Pixcel;
typedef struct picstr{Pichead myPHead;
Pixcel * pixs;
} Pic;
mDataOffset +6 是像素数据,可以压缩
例如读取案例
Pic* readpic(FILE* file){ //测试 当sizeofPixcel==4时图片
uLong flen;
unsigned char* fbuf = NULL;
uLong ulen;
unsigned char* ubuf = NULL;
Pic* myPic;
if((myPic= (Pic*)malloc(sizeof(Pic) )) == NULL)
{
printf("No enough memory! myPic\n");
return 0;
}
fread(&myPic->myPHead,6,1,file); //读取图片头
printf("pic w=%d,h=%d,n=%d,t=%d\n",(int)myPic->myPHead.mWidth,(int)myPic->myPHead.mHeight,
(int) myPic->myPHead.mNumber,(int)myPic->myPHead.mTransparent);
if(!myGMChead.isComressed){//未压缩
int picpixsize=myPic->myPHead.mWidth*myPic->myPHead.mHeight
* myPic->myPHead.mNumber<<2;
if((myPic->pixs= (Pixcel*)malloc(picpixsize) )== NULL)
{
printf("No enough memory! 未压缩 myPic.pixs\n");
free(myPic);
return 0;
}
fread(myPic->pixs,picpixsize,1,file); //直接读取
}else {//已压缩
fread(&ulen,4, 1, file); /* 获取解压后数据大小*/
fread(&flen,4, 1, file); /* 获取已压缩数据流大小 */
printf("l=%d\n",flen);
if((fbuf = (unsigned char*)malloc(sizeof(unsigned char) * flen)) == NULL)
{
fseek(file,ftell(file)-14,SEEK_SET);
printf("No enough memory! 已压缩fbuf\n");
free(myPic);
return 0;
}
fread(fbuf, 1, flen, file);//读取已压缩数据
// memcpy(&ulen,fbuf+ flen-4, 4); /* 获取缓冲区大小 */
//printf("解压像素字节数=%d\n",ulen);
/* 解压缩数据 */
int failed_number=0;
while(failed_number < 4)
{
if((ubuf = (unsigned char*)malloc(sizeof(unsigned char) * ulen)) == NULL)
{
printf("No dest enough memory 已解压像素内存 ubuf!\n");
free(myPic);
return 0;
}
if(uncompress(ubuf, &ulen, fbuf, flen) != Z_OK)
{
printf("Uncompress %s failed,try allocate more space!\n", "dat.gmc");
free(ubuf);
ubuf = NULL;
/*失败后分配两倍空间*/
ulen <<=1;
failed_number++;
}
else
{
break;
}
}
if(failed_number==4){
printf("解压数据失败!数据已损坏\n");
fseek(file,ftell(file)-flen-14,SEEK_SET);
free(fbuf);
free(myPic);
return 0;
}
free(fbuf);//释放已压缩数据的缓存
myPic->pixs=(Pixcel *)ubuf;/* 保存解压缩后的数据到目标文件 */
}
//测试像素(0,1)红值
//printf( "(0,1)像素 r=%d\n",(myPic->pixs+(1*myPic->myPHead.mWidth+0))->red);
return myPic;
}
用完后释放
void freePic(Pic* desPic){
free( desPic->pixs); //测试结束释放像素内存
free( desPic);//测试结束释放Pic内存
}
srs数据mDataOffset +0是数据头,依次
mType,mIndex ,mFrameNum,mImageNum ,mStartFrame ,mEndFrame
mDataOffset +6是帧数据,大小7*mFrameNum
typedef struct srsHeadstru {
unsigned char mType;
unsigned char mIndex ;
unsigned char mFrameNum;
unsigned char mImageNum ;
unsigned char mStartFrame ;
unsigned char mEndFrame; } SrsHead;
typedef struct frameStru{unsigned short x;
unsigned short y;
unsigned char Show;
unsigned char nShow;
unsigned char PICid;} SrsFrame;
typedef struct SrsStru{SrsHead srshead;SrsFrame * mframes;Pic** pics;} Srs;
mDataOffset +6+7*mFrameNum是图片数据
读取srs方法
Srs * readSrs(FILE* file) {
Srs* mySrs;
if((mySrs= (Srs*)malloc(sizeof(Srs) )) == NULL)
{
printf("No enough memory! mySrs\n");
return 0;
}
fread(&mySrs->srshead,6,1,file);
if((mySrs->mframes= (SrsFrame*)malloc(7*mySrs->srshead.mFrameNum )) == NULL)
{free(mySrs);
printf("No enough memory! mySrs->mframes\n");
return 0;
}
int i;//必须循环读取,因为编译器结构体大小判断不准,每帧读取7字节
for (i=0;i<mySrs->srshead.mFrameNum;i++)fread(mySrs->mframes,7/*必须数字7*/ ,1,file);
if((mySrs->pics= (Pic**)malloc( mySrs->srshead.mImageNum<<2)) == NULL)
{
free(mySrs->mframes);
free(mySrs);
printf("No enough memory! mySrs->pics\n");
return 0;
}
Pic * Frampic;
for (i=0;i<mySrs->srshead.mImageNum;i++){
if(( Frampic=readpic(file))==NULL){
int j; for (j=0;j<i;j++)freePic(mySrs->pics[j]);
free(mySrs->pics);
free(mySrs->mframes);
free(mySrs);
printf("fail to load Srs Pic ! no.%d\n,ftell=%d",i+1,(int)ftell(file));
return 0;
}
mySrs->pics[i]=Frampic;
}
return mySrs;
}
用完后释放
void freeSrs(Srs * desSrs){
int i;
for (i=0;i<desSrs->srshead.mImageNum;i++){
freePic(desSrs->pics[i]);
}
free(desSrs->mframes);
free(desSrs);
}
例子源码vc6(亲测,已编译通过)
链接:https://pan.baidu.com/s/1hM_rrrcYRy0fndG5PWSNgA 密码:j0g9