www.pudn.com > 传奇3源代码.rar > grfio.c


/********************************************************************* 
 * 
 *		Ragnarok Online Emulator : grfio.c -- grf file I/O Module 
 *-------------------------------------------------------------------- 
 *		special need library : zlib 
 ********************************************************************* 
 *	$Id: grfio.c,v 1.4 2003/11/10 23:32:44 jmb Exp $ 
 * 
 *	2002/12/18 ... 尨斉 
 *	2003/01/23 ... 僐乕僪廋惓 
 *	2003/02/01 ... LocalFile媦傃暋悢GRF僠僃僢僋張棟傪捛壛,埫崋夝撉張棟傪夵椙 
 *	2003/02/02 ... grf偑柍偔偰傕巭傑傜側偄傛偆偵廋惓 
 *	2003/02/02 ... grf撉傒崬傒巜掕傪屻偐傜捛壛偱偒傞傛偆偵廋惓(grfio_add娭悢捛壛) 
 *	2003/02/03 ... grfio_resourcecheck張棟帪丄僄儞僩儕捛壛張棟曽朄傪廋惓 
 *	2003/02/05 ... grfio_init撪張棟偺曄峏 
 *	2003/02/23 ... 儘乕僇儖僼傽僀儖僠僃僢僋傪GRFIO_LOCAL偱僗僀僢僠(僨僼僅傪婡擻Off偵) 
 *      2003/10/21 ゥ 兛僋儔僀傾儞僩偺僨乕僞傪撉傓傛偆偵偟偨丅 
 *	2003/11/10 ... Ready new grf format. 
 *	2003/11/11 ... version check fix & bug fix 
 */ 
 
#include  
#include  
#include  
#include  
#include  
 
#include  
 
#include "grfio.h" 
 
#ifdef MEMWATCH 
#include "memwatch.h" 
#endif 
 
typedef	unsigned char	BYTE; 
typedef	unsigned short	WORD; 
typedef	unsigned long	DWORD; 
 
static char data_file[1024] = "data.grf"; 
static char adata_file[1024] = "adata.grf"; 
static char sdata_file[1024] = "sdata.grf"; 
 
// accessor to data_file,adata_file,sdata_file 
char *grfio_setdatafile(const char *str){ strcpy(data_file,str); return data_file; } 
char *grfio_setadatafile(const char *str){ strcpy(adata_file,str); return adata_file; } 
char *grfio_setsdatafile(const char *str){ strcpy(sdata_file,str); return sdata_file; } 
 
//---------------------------- 
//	file entry table struct 
//---------------------------- 
typedef struct { 
	int 	srclen;				// compressed size 
	int		srclen_aligned;		//  
	int		declen;				// original size 
	int		srcpos; 
	short	next; 
	char	cycle; 
	char	type; 
	char	fn[128-4*5];		// file name 
	char	gentry;				// read grf file select 
} FILELIST; 
// gentry ... 0  :儘乕僇儖僼傽僀儖傛傝庢摼 
//            1>=:gentry_table[gentry-1]偺儕僜乕僗僼傽僀儖傛傝庢摼 
//            1<=:儘乕僇儖僼傽僀儖傪僠僃僢僋 
//                   桳傟偽0偵嵞僙僢僩偟偰埲崀儘乕僇儖僼傽僀儖傛傝庢摼 
//                   柍偗傟偽晞崋斀揮偟偰嵞僙僢僩偟丄1>=偲摨偠偔儕僜乕僗僼傽僀儖傛傝庢摼 
 
// 仸FILELIST.gentry傪char偱掕媊偟偰偄傞偺偱grfio_add偱捛壛偱偒傞忋尷偼127僐傑偱偵側傝傑偡 
#define	GENTRY_LIMIT	127 
#define	FILELIST_LIMIT	32768	// 壖忋尷,棟榑忋忋尷偼2G 
 
static FILELIST *filelist; 
static int	filelist_entrys; 
static int	filelist_maxentry; 
 
static char **gentry_table; 
static int gentry_entrys; 
static int gentry_maxentry; 
 
//---------------------------- 
//	file list hash table 
//---------------------------- 
static int filelist_hash[256]; 
 
//---------------------------- 
//	grf decode data table 
//---------------------------- 
static unsigned char BitMaskTable[8] = { 
	0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 
}; 
 
static char	BitSwapTable1[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 char	BitSwapTable2[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 char	BitSwapTable3[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 NibbleData[4][64]={ 
	{ 
		0xef, 0x03, 0x41, 0xfd, 0xd8, 0x74, 0x1e, 0x47,  0x26, 0xef, 0xfb, 0x22, 0xb3, 0xd8, 0x84, 0x1e, 
		0x39, 0xac, 0xa7, 0x60, 0x62, 0xc1, 0xcd, 0xba,  0x5c, 0x96, 0x90, 0x59, 0x05, 0x3b, 0x7a, 0x85, 
		0x40, 0xfd, 0x1e, 0xc8, 0xe7, 0x8a, 0x8b, 0x21,  0xda, 0x43, 0x64, 0x9f, 0x2d, 0x14, 0xb1, 0x72, 
		0xf5, 0x5b, 0xc8, 0xb6, 0x9c, 0x37, 0x76, 0xec,  0x39, 0xa0, 0xa3, 0x05, 0x52, 0x6e, 0x0f, 0xd9, 
	}, { 
		0xa7, 0xdd, 0x0d, 0x78, 0x9e, 0x0b, 0xe3, 0x95,  0x60, 0x36, 0x36, 0x4f, 0xf9, 0x60, 0x5a, 0xa3, 
		0x11, 0x24, 0xd2, 0x87, 0xc8, 0x52, 0x75, 0xec,  0xbb, 0xc1, 0x4c, 0xba, 0x24, 0xfe, 0x8f, 0x19, 
		0xda, 0x13, 0x66, 0xaf, 0x49, 0xd0, 0x90, 0x06,  0x8c, 0x6a, 0xfb, 0x91, 0x37, 0x8d, 0x0d, 0x78, 
		0xbf, 0x49, 0x11, 0xf4, 0x23, 0xe5, 0xce, 0x3b,  0x55, 0xbc, 0xa2, 0x57, 0xe8, 0x22, 0x74, 0xce, 
	}, { 
		0x2c, 0xea, 0xc1, 0xbf, 0x4a, 0x24, 0x1f, 0xc2,  0x79, 0x47, 0xa2, 0x7c, 0xb6, 0xd9, 0x68, 0x15, 
		0x80, 0x56, 0x5d, 0x01, 0x33, 0xfd, 0xf4, 0xae,  0xde, 0x30, 0x07, 0x9b, 0xe5, 0x83, 0x9b, 0x68, 
		0x49, 0xb4, 0x2e, 0x83, 0x1f, 0xc2, 0xb5, 0x7c,  0xa2, 0x19, 0xd8, 0xe5, 0x7c, 0x2f, 0x83, 0xda, 
		0xf7, 0x6b, 0x90, 0xfe, 0xc4, 0x01, 0x5a, 0x97,  0x61, 0xa6, 0x3d, 0x40, 0x0b, 0x58, 0xe6, 0x3d, 
	}, { 
		0x4d, 0xd1, 0xb2, 0x0f, 0x28, 0xbd, 0xe4, 0x78,  0xf6, 0x4a, 0x0f, 0x93, 0x8b, 0x17, 0xd1, 0xa4, 
		0x3a, 0xec, 0xc9, 0x35, 0x93, 0x56, 0x7e, 0xcb,  0x55, 0x20, 0xa0, 0xfe, 0x6c, 0x89, 0x17, 0x62, 
		0x17, 0x62, 0x4b, 0xb1, 0xb4, 0xde, 0xd1, 0x87,  0xc9, 0x14, 0x3c, 0x4a, 0x7e, 0xa8, 0xe2, 0x7d, 
		0xa0, 0x9f, 0xf6, 0x5c, 0x6a, 0x09, 0x8d, 0xf0,  0x0f, 0xe3, 0x53, 0x25, 0x95, 0x36, 0x28, 0xcb, 
	} 
}; 
/*----------------- 
 *	long data get 
 */ 
static unsigned int getlong(unsigned char *p) 
{ 
  return *p+p[1]*256+(p[2]+p[3]*256)*65536; 
} 
 
/*========================================== 
 *	Grf data decode : Subs 
 *------------------------------------------ 
 */ 
static void NibbleSwap(BYTE *Src, int len) 
{ 
	for(;0>4) | (*Src<<4); 
	} 
} 
 
static void BitConvert(BYTE *Src,char *BitSwapTable) 
{ 
	int lop,prm; 
	BYTE tmp[8]; 
	*(DWORD*)tmp=*(DWORD*)(tmp+4)=0; 
	for(lop=0;lop!=64;lop++) { 
		prm = BitSwapTable[lop]-1; 
		if (Src[(prm >> 3) & 7] & BitMaskTable[prm & 7]) { 
			tmp[(lop >> 3) & 7] |= BitMaskTable[lop & 7]; 
		} 
	} 
	*(DWORD*)Src     = *(DWORD*)tmp; 
	*(DWORD*)(Src+4) = *(DWORD*)(tmp+4); 
} 
 
static void BitConvert4(BYTE *Src) 
{ 
	int lop,prm; 
	BYTE tmp[8]; 
	tmp[0] = ((Src[7]<<5) | (Src[4]>>3)) & 0x3f;	// ..0 vutsr 
	tmp[1] = ((Src[4]<<1) | (Src[5]>>7)) & 0x3f;	// ..srqpo n 
	tmp[2] = ((Src[4]<<5) | (Src[5]>>3)) & 0x3f;	// ..o nmlkj 
	tmp[3] = ((Src[5]<<1) | (Src[6]>>7)) & 0x3f;	// ..kjihg f 
	tmp[4] = ((Src[5]<<5) | (Src[6]>>3)) & 0x3f;	// ..g fedcb 
	tmp[5] = ((Src[6]<<1) | (Src[7]>>7)) & 0x3f;	// ..cba98 7 
	tmp[6] = ((Src[6]<<5) | (Src[7]>>3)) & 0x3f;	// ..8 76543 
	tmp[7] = ((Src[7]<<1) | (Src[4]>>7)) & 0x3f;	// ..43210 v 
 
	for(lop=0;lop!=4;lop++) { 
		tmp[lop] = (NibbleData[lop][tmp[lop*2]] & 0xf0) 
		         | (NibbleData[lop][tmp[lop*2+1]] & 0x0f); 
	} 
 
	*(DWORD*)(tmp+4)=0; 
	for(lop=0;lop!=32;lop++) { 
		prm = BitSwapTable3[lop]-1; 
		if (tmp[prm >> 3] & BitMaskTable[prm & 7]) { 
			tmp[(lop >> 3) + 4] |= BitMaskTable[lop & 7]; 
		} 
	} 
	*(DWORD*)Src ^= *(DWORD*)(tmp+4); 
} 
 
static void decode_des_etc(BYTE *buf,int len,int type,int cycle) 
{ 
	int lop,cnt=0; 
	if(cycle<3) cycle=3; 
	else if(cycle<5) cycle++; 
	else if(cycle<7) cycle+=9; 
	else cycle+=15; 
 
	for(lop=0;lop*8 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; 
} 
/*********************************************************** 
 ***                File List Sobroutines                *** 
 ***********************************************************/ 
 
/*========================================== 
 *	File List : Hash make 
 *------------------------------------------ 
 */ 
static int filehash(unsigned char *fname) 
{ 
	unsigned int hash=0; 
	while(*fname) { 
		hash = ((hash<<1)+(hash>>7)*9+tolower(*fname)); 
		fname++; 
	} 
	return hash & 255; 
} 
 
/*========================================== 
 *	File List : Hash initalize 
 *------------------------------------------ 
 */ 
static void hashinit(void) 
{ 
	int lop; 
	for(lop=0;lop<256;lop++) 
		filelist_hash[lop]=-1; 
} 
 
/*========================================== 
 *	File List : File find 
 *------------------------------------------ 
 */ 
FILELIST *filelist_find(char *fname) 
{ 
	int hash; 
 
	for(hash=filelist_hash[filehash(fname)];hash>=0;hash=filelist[hash].next) { 
		if(strcasecmp(filelist[hash].fn,fname)==0) 
			break; 
	} 
 
	return (hash>=0)? &filelist[hash] : NULL; 
} 
 
/*========================================== 
 *	File List : Filelist add 
 *------------------------------------------ 
 */ 
#define	FILELIST_ADDS	1024	// 僼傽僀儖儕僗僩悢憹暘 
 
static FILELIST* filelist_add(FILELIST *entry) 
{ 
	int hash; 
 
	if (filelist_entrys>=FILELIST_LIMIT) { 
		printf("filelist limit : filelist_add\n"); 
		exit(1); 
	} 
 
	if (filelist_entrys>=filelist_maxentry) { 
		FILELIST *new_filelist = (FILELIST*)realloc( 
			(void*)filelist, (filelist_maxentry+FILELIST_ADDS)*sizeof(FILELIST) ); 
		if (new_filelist != NULL) { 
			filelist = new_filelist; 
			memset(filelist + filelist_maxentry, '\0', 
				FILELIST_ADDS * sizeof(FILELIST)); 
			filelist_maxentry += FILELIST_ADDS; 
		} else { 
			printf("out of memory : filelist_add\n"); 
			exit(1); 
		} 
	} 
 
	memcpy( &filelist[filelist_entrys], entry, sizeof(FILELIST) ); 
 
	hash = filehash(entry->fn); 
	filelist[filelist_entrys].next = filelist_hash[hash]; 
	filelist_hash[hash] = filelist_entrys; 
 
	filelist_entrys++; 
 
	return &filelist[filelist_entrys-1]; 
} 
 
static FILELIST* filelist_modify(FILELIST *entry) 
{ 
	FILELIST *fentry; 
	if ((fentry=filelist_find(entry->fn))!=NULL) { 
		int tmp = fentry->next; 
		memcpy( fentry, entry, sizeof(FILELIST) ); 
		fentry->next = tmp; 
	} else { 
		fentry = filelist_add(entry); 
	} 
	return fentry; 
} 
 
/*========================================== 
 *	File List : filelist size adjust 
 *------------------------------------------ 
 */ 
static void filelist_adjust(void) 
{ 
	if (filelist!=NULL) { 
		if (filelist_maxentry>filelist_entrys) { 
			FILELIST *new_filelist = (FILELIST*)realloc( 
				(void*)filelist,filelist_entrys*sizeof(FILELIST) ); 
			if (new_filelist != NULL) { 
				filelist = new_filelist; 
				filelist_maxentry = filelist_entrys; 
			} else { 
				printf("out of memory : filelist\n"); 
				exit(1); 
			} 
		} 
	} 
} 
 
/*********************************************************** 
 ***                  Grfio Sobroutines                  *** 
 ***********************************************************/ 
 
/*========================================== 
 *	Grfio : Resource file size get 
 *------------------------------------------ 
 */ 
int grfio_size(char *fname) 
{ 
	FILELIST *entry; 
 
	entry = filelist_find(fname); 
 
	if (entry==NULL || entry->gentry<0) {	// LocalFileCheck 
		char lfname[256],*p; 
		FILELIST lentry; 
		struct stat st; 
 
		strncpy(lfname,fname,255); 
		for(p=&lfname[0];*p!=0;p++) if (*p=='\\') *p = '/';	// 仸Unix帪偺傒 
 
		if (stat(lfname,&st)==0) { 
			strncpy(lentry.fn, fname, sizeof(lentry.fn)-1 ); 
			lentry.declen = st.st_size; 
			lentry.gentry = 0;	// 0:LocalFile 
			entry = filelist_modify(&lentry); 
		} else if (entry==NULL) { 
			printf("%s not found\n", fname); 
			exit(1);	//return 0; 
		} 
	} 
	return entry->declen; 
} 
 
/*========================================== 
 *	Grfio : Resource file read & size get 
 *------------------------------------------ 
 */ 
void* grfio_reads(char *fname, int *size) 
{ 
	FILE *in = NULL; 
	unsigned char *buf=NULL,*buf2=NULL; 
	char *gfname; 
	FILELIST *entry; 
 
	entry = filelist_find(fname); 
 
	if (entry==NULL || entry->gentry<=0) {	// LocalFileCheck 
		char lfname[256],*p; 
		FILELIST lentry; 
 
		strncpy(lfname,fname,255); 
		for(p=&lfname[0];*p!=0;p++) if (*p=='\\') *p = '/';	// 仸Unix帪偺傒 
 
		in = fopen(lfname,"rb"); 
		if(in!=NULL) { 
			if (entry!=NULL && entry->gentry==0) { 
				lentry.declen=entry->declen; 
			} else { 
				fseek(in,0,2);	// SEEK_END 
				lentry.declen = ftell(in); 
			} 
			fseek(in,0,0);	// SEEK_SET 
			buf2 = calloc(lentry.declen+1024, 1); 
			if (buf2==NULL) { 
				printf("file read memory allocate error : declen\n"); 
				goto errret; 
			} 
			fread(buf2,1,lentry.declen,in); 
			fclose(in); in = NULL; 
			strncpy( lentry.fn, fname, sizeof(lentry.fn)-1 ); 
			lentry.gentry = 0;	// 0:LocalFile 
			entry = filelist_modify(&lentry); 
		} else { 
			if (entry!=NULL && entry->gentry<0) { 
				entry->gentry = -entry->gentry;	// local file checked 
			} else { 
				printf("%s not found\n", fname); 
				goto errret; 
			} 
		} 
	} 
	if (entry!=NULL && entry->gentry>0) {	// Archive[GRF] File Read 
		buf = calloc(entry->srclen_aligned+1024, 1); 
		if (buf==NULL) { 
			printf("file read memory allocate error : srclen_aligned\n"); 
			goto errret; 
		} 
		gfname = gentry_table[entry->gentry-1]; 
		in = fopen(gfname,"rb"); 
		if(in==NULL) { 
			printf("%s not found\n",gfname); 
			goto errret; 
		} 
		fseek(in,entry->srcpos,0); 
		fread(buf,1,entry->srclen_aligned,in); 
		fclose(in); 
		buf2=calloc(entry->declen+1024, 1); 
		if (buf2==NULL) { 
			printf("file decode memory allocate error\n"); 
			goto errret; 
		} 
		if(entry->type==1 || entry->type==3 || entry->type==5) { 
			uLongf len; 
			if (entry->cycle>=0) { 
				decode_des_etc(buf,entry->srclen_aligned,entry->cycle==0,entry->cycle); 
			} 
			len=entry->declen; 
			decode_zip(buf2,&len,buf,entry->srclen); 
			if(len!=entry->declen) { 
				printf("decode_zip size miss match err: %d != %d\n",(int)len,entry->declen); 
				goto errret; 
			} 
		} else { 
			memcpy(buf2,buf,entry->declen); 
		} 
		free(buf); 
	} 
	if (size!=NULL && entry!=NULL) 
		*size = entry->declen; 
	return buf2; 
errret: 
	if (buf!=NULL) free(buf); 
	if (buf2!=NULL) free(buf2); 
	if (in!=NULL) fclose(in); 
	exit(1);	//return NULL; 
} 
 
/*========================================== 
 *	Grfio : Resource file read 
 *------------------------------------------ 
 */ 
void* grfio_read(char *fname) 
{ 
	return grfio_reads(fname,NULL); 
} 
 
/*========================================== 
 *	Resource filename decode 
 *------------------------------------------ 
 */ 
static unsigned char * decode_filename(unsigned char *buf,int len) 
{ 
	int lop; 
	for(lop=0;lop> 8; 
 
	if (grf_version==0x01) {	//****** Grf version 01xx ****** 
		list_size = grf_size-ftell(fp); 
		grf_filelist = calloc(list_size, 1); 
		if(grf_filelist==NULL){ 
			fclose(fp); 
			printf("out of memory : grf_filelist\n"); 
			return 3;	// 3:memory alloc error 
		} 
		fread(grf_filelist,1,list_size,fp); 
		fclose(fp); 
		 
		entrys = getlong(grf_header+0x26) - getlong(grf_header+0x22) - 7; 
		 
		// Get an entry 
		for(entry=0,ofs=0;entrysizeof(aentry.fn)-1){ 
					printf("file name too long : %s\n",fname); 
					free(grf_filelist); 
					exit(1); 
				} 
				srclen=0; 
				if((period_ptr=rindex(fname,'.'))!=NULL){ 
					for(lop=0;lop<4;lop++) { 
						if(strcasecmp(period_ptr,".gnd\0.gat\0.act\0.str"+lop*5)==0) 
							break; 
					} 
					srclen=getlong(grf_filelist+ofs2)-getlong(grf_filelist+ofs2+8)-715; 
					if(lop==4) { 
						for(lop=10,srccount=1;srclen>=lop;lop=lop*10,srccount++); 
					} else { 
						srccount=0; 
					} 
				} else { 
					srccount=0; 
				} 
			 
				aentry.srclen         = srclen; 
				aentry.srclen_aligned = getlong(grf_filelist+ofs2+4)-37579; 
				aentry.declen         = getlong(grf_filelist+ofs2+8); 
				aentry.srcpos         = getlong(grf_filelist+ofs2+13)+0x2e; 
				aentry.cycle          = srccount; 
				aentry.type           = type; 
				strncpy(aentry.fn,fname,sizeof(aentry.fn)-1); 
#ifdef	GRFIO_LOCAL 
				aentry.gentry         = -(gentry+1);	// 晧悢偵偡傞偺偼弶夞LocalFileCheck傪偝偣傞偨傔偺Flag偲偟偰 
#else 
				aentry.gentry         = gentry+1;		// 弶夞LocalFileCheck柍偟 
#endif 
				filelist_modify(&aentry); 
			} 
			ofs = ofs2 + 17; 
		} 
		free(grf_filelist); 
	 
	} else if (grf_version==0x02) {	//****** Grf version 02xx ****** 
		unsigned char eheader[8]; 
		unsigned char *rBuf; 
		uLongf rSize,eSize; 
 
		fread(eheader,1,8,fp); 
		rSize = getlong(eheader);	// Read Size 
		eSize = getlong(eheader+4);	// Extend Size 
		 
		if (rSize > grf_size-ftell(fp)) { 
			fclose(fp); 
			printf("Illegal data format : grf compress entry size\n"); 
			return 4; 
		} 
		 
		rBuf = calloc( rSize , 1);	// Get a Read Size 
		if (rBuf==NULL) { 
			fclose(fp); 
			printf("out of memory : grf compress entry table buffer\n"); 
			return 3; 
		} 
		grf_filelist = calloc( eSize , 1);	// Get a Extend Size 
		if (grf_filelist==NULL) { 
			free(rBuf); 
			fclose(fp); 
			printf("out of memory : grf extract entry table buffer\n"); 
			return 3; 
		} 
		fread(rBuf,1,rSize,fp); 
		fclose(fp); 
		decode_zip(grf_filelist,&eSize,rBuf,rSize);	// Decode function 
		list_size = eSize; 
		free(rBuf); 
		 
		entrys = getlong(grf_header+0x26) - 7; 
		 
		// Get an entry 
		for(entry=0,ofs=0;entrysizeof(aentry.fn)-1) { 
				printf("grf : file name too long : %s\n",fname); 
				free(grf_filelist); 
				exit(1); 
			} 
			ofs2 = ofs+strlen(grf_filelist+ofs)+1; 
			type = grf_filelist[ofs2+12]; 
			if(type==1 || type==3 || type==5) { 
				srclen=getlong(grf_filelist+ofs2); 
				if (grf_filelist[ofs2+12]==3) { 
					for(lop=10,srccount=1;srclen>=lop;lop=lop*10,srccount++); 
				} else if (grf_filelist[ofs2+12]==5) { 
					srccount = 0; 
				} else {	// if (grf_filelist[ofs2+12]==1) { 
					srccount = -1; 
				} 
			 
				aentry.srclen         = srclen; 
				aentry.srclen_aligned = getlong(grf_filelist+ofs2+4); 
				aentry.declen         = getlong(grf_filelist+ofs2+8); 
				aentry.srcpos         = getlong(grf_filelist+ofs2+13)+0x2e; 
				aentry.cycle          = srccount; 
				aentry.type           = type; 
				strncpy(aentry.fn,fname,sizeof(aentry.fn)-1); 
#ifdef	GRFIO_LOCAL 
				aentry.gentry         = -(gentry+1);	// 晧悢偵偡傞偺偼弶夞LocalFileCheck傪偝偣傞偨傔偺Flag偲偟偰 
#else 
				aentry.gentry         = gentry+1;		// 弶夞LocalFileCheck柍偟 
#endif 
				filelist_modify(&aentry); 
			} 
			ofs = ofs2 + 17; 
		} 
		free(grf_filelist); 
	 
	} else {	//****** Grf Other version ****** 
		fclose(fp); 
		printf("not support grf versions : %04x\n",getlong(grf_header+0x2a)); 
		return 4; 
	} 
 
	filelist_adjust();	// filelist偺晄梫僄儕傾夝曻 
 
	return 0;	// 0:no error 
} 
 
/*========================================== 
 * Grfio : Resource file check 
 *------------------------------------------ 
 */ 
static void grfio_resourcecheck() 
{ 
	int size; 
	unsigned char *buf,*ptr; 
	char w1[256],w2[256],src[256],dst[256]; 
	FILELIST *entry; 
 
	buf=grfio_reads("data\\resnametable.txt",&size); 
	buf[size] = 0; 
 
	for(ptr=buf;ptr-buf=GENTRY_LIMIT) { 
		printf("gentrys limit : grfio_add\n"); 
		exit(1); 
	} 
 
	printf("%s file reading...\n",fname); 
 
	if (gentry_entrys>=gentry_maxentry) { 
		char **new_gentry = (char**)realloc( 
			(void*)gentry_table,(gentry_maxentry+GENTRY_ADDS)*sizeof(char*) ); 
		if (new_gentry!=NULL) { 
			int lop; 
			gentry_table = new_gentry; 
			gentry_maxentry += GENTRY_ADDS; 
			for(lop=gentry_entrys;lop