grfio.c
来自「仙镜游戏源码,仅供学习!请勿用于非法应用!」· C语言 代码 · 共 415 行
C
415 行
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <zlib.h>#include "grfio.h"static unsigned char IP[64]={ 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7};static unsigned char RIP[64]={ 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25};static unsigned char S[8][64];static unsigned char S_[8][64]={ { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 }, { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 }, { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 }, { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 }, { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 }, { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 }, { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 }, { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } };static unsigned char P[32] = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 };static unsigned char shift[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};static unsigned int getlong(unsigned char *p){ return *p+p[1]*256+(p[2]+p[3]*256)*65536;}static void do_ip(unsigned char *buf,int len){ int i,j,k; unsigned char tmp[8]; for(i=0;i<len;i+=8){ *((long*)tmp)=0; *((long*)(tmp+4))=0; for(j=0;j<64;j++){ k=IP[j]-1; if(buf[i+(k>>3)] & shift[k&7]) tmp[j>>3] |= shift[j&7]; } *((long*)(buf+i))=*((long*)tmp); *((long*)(buf+i+4))=*((long*)(tmp+4)); }}static void do_rip(unsigned char *buf,int len){ int i,j,k; unsigned char tmp[8]; for(i=0;i<len;i+=8){ *((long*)tmp)=0; *((long*)(tmp+4))=0; for(j=0;j<64;j++){ k=RIP[j]-1; if(buf[i+(k>>3)] & shift[k&7]) tmp[j>>3] |= shift[j&7]; } *((long*)(buf+i))=*((long*)tmp); *((long*)(buf+i+4))=*((long*)(tmp+4)); }}static void do_f(unsigned char *buf,int len){ unsigned char tmp[8]; unsigned long a; int i,j,k; for(i=0;i<len;i+=8){// E a=(buf[i+4]<<24)+(buf[i+5]<<16)+(buf[i+6]<<8)+buf[i+7]; tmp[0]=((a&1)<<5)+(a>>27); tmp[1]=(a>>23)&0x3f; tmp[2]=(a>>19)&0x3f; tmp[3]=(a>>15)&0x3f; tmp[4]=(a>>11)&0x3f; tmp[5]=(a>>7)&0x3f; tmp[6]=(a>>3)&0x3f; tmp[7]=((a<<1)+(a>>31))&0x3f;// S for(j=0;j<4;j++) tmp[j]=(S[j*2][tmp[j*2]]<<4)+S[j*2+1][tmp[j*2+1]];// P *((long*)(tmp+4))=0; for(j=0;j<32;j++){ k=P[j]-1; if(tmp[k>>3] & shift[k&7]) tmp[(j>>3)+4] |= shift[j&7]; } *((long*)(buf+i))^=*((long*)(tmp+4)); }}static void decode_des_etc(unsigned char *p,int s,int type,int cycle){ int i,j=0; if(cycle<3) cycle=3; else if(cycle<5) cycle++; else if(cycle<7) cycle+=9; else cycle+=15; for(i=0;i*8<s;i++){ if(i<20 || (type==0 && i%cycle==0)){ // des do_ip(p+i*8,8); do_f(p+i*8,8); do_rip(p+i*8,8); } else { if(j==7 && type==0){ int a; unsigned char tmp[8]; memcpy(tmp,p+i*8,8); j=0; p[i*8+0]=tmp[3]; p[i*8+1]=tmp[4]; p[i*8+2]=tmp[6]; p[i*8+3]=tmp[0]; p[i*8+4]=tmp[1]; p[i*8+5]=tmp[2]; p[i*8+6]=tmp[5]; a=tmp[7]; if(a==0x00) a=0x2b; else if(a==0x2b) a=0x00; else if(a==0x01) a=0x68; else if(a==0x68) a=0x01; else if(a==0x48) a=0x77; else if(a==0x77) a=0x48; else if(a==0x60) a=0xff; else if(a==0xff) a=0x60; else if(a==0x6c) a=0x80; else if(a==0x80) a=0x6c; else if(a==0xb9) a=0xc0; else if(a==0xc0) a=0xb9; else if(a==0xeb) a=0xfe; else if(a==0xfe) a=0xeb; p[i*8+7]=a; } j++; } }}static int decode_zip(Bytef* dest, uLongf* destLen, const Bytef* source, uLong sourceLen){ z_stream stream; int err; stream.next_in = (Bytef*)source; stream.avail_in = (uInt)sourceLen; /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; stream.next_out = dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; err = inflateInit(&stream); if (err != Z_OK) return err; err = inflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { inflateEnd(&stream); return err == Z_OK ? Z_BUF_ERROR : err; } *destLen = stream.total_out; err = inflateEnd(&stream); return err;}static struct { int srclen,srclen_aligned,declen,srcpos; short next; char cycle,type; char fn[128-4*5];} *filelist;static int filelist_hash[256];static int filehash(unsigned char *fn){ unsigned int a=0; while(*fn){ a=((a<<1)+(a>>7)*9+tolower(*fn)); fn++; } return a&255;}int grfio_size(char *fn){ int f; for(f=filelist_hash[filehash(fn)];f>=0;f=filelist[f].next) if(strcasecmp(filelist[f].fn,fn)==0) break; if(f<0){ printf("file not found in data.grf : %s\n",fn); exit(1); } return filelist[f].declen;}void* grfio_read(char *fn){ FILE *in; unsigned char *buf,*buf2; int f; in=fopen("data.grf","rb"); if(in==NULL){ printf("data.grf not found\n"); exit(1); } for(f=filelist_hash[filehash(fn)];f>=0;f=filelist[f].next) if(strcasecmp(filelist[f].fn,fn)==0) break; if(f<0){ printf("file not found in data.grf : %s\n",fn); exit(1); } fseek(in,filelist[f].srcpos,0); buf=malloc(filelist[f].srclen_aligned+1024); fread(buf,1,filelist[f].srclen_aligned,in); fclose(in); buf2=malloc(filelist[f].declen+1024); if(filelist[f].type==1){ uLongf len; decode_des_etc(buf,filelist[f].srclen_aligned,filelist[f].cycle==0,filelist[f].cycle); len=filelist[f].declen; decode_zip(buf2,&len,buf,filelist[f].srclen); if(len!=filelist[f].declen){ printf("%d != %d\n",(int)len,filelist[f].declen); exit(1); } } else { memcpy(buf2,buf,filelist[f].declen); } free(buf); return buf2;}static unsigned char * decode_filename(unsigned char *buf,int len){ int i; for(i=0;i<len;i++) buf[i]=(buf[i]<<4)+((buf[i]>>4)&0xff); do_ip(buf,len); do_f(buf,len); do_rip(buf,len); return buf;}void grfio_init(void){ FILE *fp; int s,i; unsigned char tmp[0x2e]; int j,num; unsigned char *fn; unsigned char *buf,*p; for(i=0;i<8;i++){ for(j=0;j<64;j++){ S[i][j]=S_[i][(j&0x20)+((j&1)<<4)+((j&0x1e)>>1)]; } } fp=fopen("data.grf","rb"); if(fp==NULL){ printf("data.grf not found\n"); exit(2); } fseek(fp,0,2); s=ftell(fp); fseek(fp,0,0); fread(tmp,1,0x2e,fp); if(strcmp(tmp,"Master of Magic") || fseek(fp,getlong(tmp+0x1e),1)){ printf("data.grf read error\n"); exit(2); } s-=ftell(fp); buf=malloc(s); if(buf==NULL){ printf("out of memory : grf_filelist\n"); exit(1); } fread(buf,1,s,fp); fclose(fp); for(j=0;j<256;j++) filelist_hash[j]=-1; for(j=0,num=0;j<s;j+=21+getlong(buf+j)) if(buf[j+getlong(buf+j)+16]) num++; //printf("file num %d\n",num); filelist=malloc((num+1024)*sizeof(filelist[0])); if(filelist==NULL){ printf("out of memory : filelist\n"); exit(1); } for(i=0,j=0;i<num;i++,j+=21+getlong(buf+j)){ int k,h,srclen,srccount; char *period_ptr; k=j+getlong(buf+j)+4; if(buf[k+12]==0){ i--; continue; } fn=decode_filename(buf+j+6,buf[j]-6); if(strlen(fn)>=sizeof(filelist[i].fn)-1){ printf("file name too long : %s\n",fn); exit(1); } srclen=0; if((period_ptr=rindex(fn,'.'))!=NULL){ int l; for(l=0;l<4;l++) if(strcasecmp(period_ptr,".gnd\0.gat\0.act\0.str"+l*5)==0) break; srclen=getlong(buf+k)-getlong(buf+k+8)-715; if(l==4){ for(l=10,srccount=1;srclen>=l;l=l*10,srccount++); } else srccount=0; } else srccount=0; filelist[i].srclen=srclen; filelist[i].srclen_aligned=getlong(buf+k+4)-37579; filelist[i].declen=getlong(buf+k+8); filelist[i].srcpos=getlong(buf+k+13)+0x2e; filelist[i].cycle=srccount; filelist[i].type=buf[k+12]; strcpy(filelist[i].fn,fn); filelist[i].next=filelist_hash[h=filehash(fn)]; filelist_hash[h]=i; } free(buf); buf=grfio_read("data\\resnametable.txt"); s=grfio_size("data\\resnametable.txt"); buf[s]=0; for(i=num,p=buf;i<num+1024 && p-buf<s;i++){ char w1[256],w2[256],src[256],dst[256]; if(sscanf(p,"%[^#]#%[^#]#",w1,w2)==2){ int f; if(strstr(w2,"bmp")){ sprintf(src,"data\\texture\\%s",w1); sprintf(dst,"data\\texture\\%s",w2); } else { sprintf(src,"data\\%s",w1); sprintf(dst,"data\\%s",w2); } for(f=filelist_hash[filehash(dst)];f>=0;f=filelist[f].next) if(strcasecmp(filelist[f].fn,dst)==0) break; if(f>=0){ memcpy(&filelist[i],&filelist[f],sizeof(filelist[0])); strcpy(filelist[i].fn,src); filelist[i].next=filelist_hash[j=filehash(src)]; filelist_hash[j]=i; } else { //printf("file not found in data.grf : %s < %s\n",dst,src); i--; } } p=strchr(p,'\n'); if(!p) break; p++; } free(buf);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?