grfio.c

来自「CS反恐精英1.6的部分C源代码。」· C语言 代码 · 共 765 行 · 第 1/2 页

C
765
字号

/*==========================================
 *	File List Sub : File Read
 *------------------------------------------
 */
static void filelist_adjust(void)
{
	if (filelist!=NULL) {
		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);
		}
	}
}

/*==========================================
 *	File List Sub : File Read
 *------------------------------------------
 */
void* grfio_read(char *fname)
{
	FILE *in;
	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 = '/';	// only for 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 = malloc(lentry.declen+1024);
			if (buf2==NULL) {
				fclose(in);
				printf("file read memory allocate error\n");
				exit(1);
			}
			fread(buf2,1,lentry.declen,in);
			fclose(in);
			strcpy(lentry.fn, fname);
			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);
				exit(1);
			}
		}
	}
	if (entry!=NULL && entry->gentry>0) {	// Archive[GRF] File Read
		buf = malloc(entry->srclen_aligned+1024);
		if (buf==NULL) {
			printf("file read memory allocate error\n");
			exit(1);
		}
		gfname = gentry_table[entry->gentry-1];
		in = fopen(gfname,"rb");
		if(in==NULL) {
			printf("%s not found\n",gfname);
			exit(1);
		}
		fseek(in,entry->srcpos,0);
		fread(buf,1,entry->srclen_aligned,in);
		fclose(in);
		buf2=malloc(entry->declen+1024);
		if (buf2==NULL) {
			free(buf);
			printf("file decode memory allocate error\n");
			exit(1);
		}
		if(entry->type==1) {
			uLongf len;
			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);
				exit(1);
			}
		} else {
			memcpy(buf2,buf,entry->declen);
		}
		free(buf);
	}
	return buf2;
}

/*==========================================
 *	File List Sub : Filename Decode
 *------------------------------------------
 */
static unsigned char * decode_filename(unsigned char *buf,int len)
{
	int lop;
	for(lop=0;lop<len;lop+=8) {
		NibbleSwap(&buf[lop],8);
		BitConvert(&buf[lop],BitSwapTable1);
		BitConvert4(&buf[lop]);
		BitConvert(&buf[lop],BitSwapTable2);
	}
	return buf;
}

/*==========================================
 * Grfio Entry Read
 *------------------------------------------
 */
static int grfio_entryread(char *gfname,int gentry)
{
	FILE *fp;
	int grf_size,list_size;
	unsigned char grf_header[0x2e];
	int lop,entry,ofs,num;
	unsigned char *fname;
	unsigned char *grf_filelist;

	fp = fopen(gfname,"rb");
	if(fp==NULL) {
		printf("%s not found\n",gfname);
		return 1;	// 1:not found err
	}

	fseek(fp,0,2);	// SEEK_END
	grf_size = ftell(fp);
	fseek(fp,0,0);	// SEEK_SET
	fread(grf_header,1,0x2e,fp);
	if(strcmp(grf_header,"Master of Magic") || fseek(fp,getlong(grf_header+0x1e),1)){	// SEEK_CUR
		printf("%s read error\n",gfname);
		exit(2);
	}

	list_size = grf_size-ftell(fp);
	grf_filelist = malloc(list_size);
	if(grf_filelist==NULL){
		printf("out of memory : grf_filelist\n");
		exit(1);
	}
	fread(grf_filelist,1,list_size,fp);
	fclose(fp);

	// 僄儞僩儕乕悢専嶕
	for(lop=0,num=0;lop<list_size;lop+=21+getlong(grf_filelist+lop))
		if(grf_filelist[lop+getlong(grf_filelist+lop)+16]) num++;

	for(entry=0,ofs=0;entry<num;entry++,ofs+=21+getlong(grf_filelist+ofs)){
		int ofs2,srclen,srccount;
		char *period_ptr;
		FILELIST aentry;
		ofs2 = ofs+getlong(grf_filelist+ofs)+4;
		if(grf_filelist[ofs2+12]==0){	// Directory Index ... skip
			entry--;
			continue;
		}
		fname = decode_filename(grf_filelist+ofs+6,grf_filelist[ofs]-6);
		if(strlen(fname)>=sizeof(filelist[entry].fn)-1){
			printf("file name too long : %s\n",fname);
			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           = grf_filelist[ofs2+12];
		strcpy(aentry.fn,fname);
		aentry.gentry         = -(gentry+1);
		//As for making negative number as a Flag because it can point to the first LocalFileCheck (raw babblefish translation)

		filelist_modify(&aentry);
	}
	free(grf_filelist);
	filelist_adjust();	//release unused area from filelist

	return 0;	// 0:noerr
}

/*==========================================
 * Grfio Resource Check
 *------------------------------------------
 */
static void grfio_resourcecheck()
{
	int lop,lopext,size;
	unsigned char *buf,*ptr;
	char w1[256],w2[256],src[256],dst[256];
	FILELIST *entry;

	size=grfio_size("data\\resnametable.txt");
	buf=grfio_read("data\\resnametable.txt");
	buf[size] = 0;

	lopext = filelist_entrys+1024;

	for(lop=filelist_entrys,ptr=buf;lop<lopext && ptr-buf<size;lop++){
		if(sscanf(ptr,"%[^#]#%[^#]#",w1,w2)==2){
			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);
			}

			entry = filelist_find(dst);
			if (entry!=NULL) {
				FILELIST fentry;
				memcpy( &fentry, entry, sizeof(FILELIST) );
				strcpy( fentry.fn ,src );
				filelist_add(&fentry);
			} else {
				//printf("file not found in data.grf : %s < %s\n",dst,src);
				lop--;
			}
		}
		ptr = strchr(ptr,'\n');
		if (!ptr) break;
		ptr++;
	}
	free(buf);
	filelist_adjust();	//release unused area from filelist
}

/*==========================================
 * Grfio Resource Add
 *------------------------------------------
 */
int grfio_add(char *fname)
{
	int len,result;
	char *buf;

	printf("%s file reading...\n",fname);

	if (gentry_entrys>=gentry_maxentry) {
		char **new_gentry = (char**)realloc((void*)gentry_table,(gentry_maxentry+16)*sizeof(char*));
		if (new_gentry!=NULL) {
			int lop;
			gentry_table = new_gentry;
			gentry_maxentry += 16;
			for(lop=gentry_entrys;lop<gentry_maxentry;lop++)
				gentry_table[lop] = NULL;
		} else {
			printf("out of memory : gentry\n");
			exit(1);
		}
	}
	len = strlen( fname );
	buf = malloc(len+1);
	if (buf==NULL) {
		printf("out of memory : gentry\n");
		exit(1);
	}
	strcpy( buf, fname );
	gentry_table[gentry_entrys++] = buf;

	result = grfio_entryread(fname,gentry_entrys-1);

	if (result==0) {
		//Resource check
		grfio_resourcecheck();
	}

	return result;
}

/*==========================================
 * Grfio Finalize
 *------------------------------------------
 */
void grfio_final(void)
{
	int lop;

	if (filelist!=NULL)	free(filelist);
	filelist = NULL;
	filelist_entrys = filelist_maxentry = 0;

	if (gentry_table!=NULL) {
		for(lop=0;lop<gentry_entrys;lop++) {
			if (gentry_table[lop]!=NULL) {
				free(gentry_table[lop]);
			}
		}
		free(gentry_table);
	}
	gentry_table = NULL;
	gentry_entrys = gentry_maxentry = 0; 
}

/*==========================================
 * Grfio Initialize
 *------------------------------------------
 */
void grfio_init(void)
{
	// ADDED ON 03/31/2003 -----------------
	FILE *data_cnf;
	char data_file[500] = "data.grf";
	char sdata_file[500] = "sdata.grf";
	char line[500], w1[500], w2[500];
	// END ---------------------------------



	hashinit();	// hash table initialization

	filelist = NULL;     filelist_entrys = filelist_maxentry = 0;
	gentry_table = NULL; gentry_entrys = gentry_maxentry = 0; 
	atexit(grfio_final);	//end processing



	// ADDED AND CHANGED ON 03/31/2003 -----------------------
	// NEW STUFF - GIVE grfio_add FUNCTION WHERE data.grf AND
	//             sdata.grf ARE, ACCORDING TO data_athena.cnf
 data_cnf = fopen("grf-files.txt", "r");
 if(data_cnf != NULL)
 {
   printf("grf-files.txt found.\n");
   while(fgets(line, 499, data_cnf))
   {
     if(sscanf(line, "%[^:]:%s", w1, w2) == 2)
     {
       if(strcmp(w1, "data") == 0)
       {
         strcpy(data_file, w2);
       }
       else if(strcmp(w1, "sdata") == 0)
       {
         strcpy(sdata_file, w2);
       }
     }
   }
   fclose(data_cnf);
 }
 else
 {
   printf( "grf-files.txt not found.\n" );
   exit(1);
 }	

	//reading entry table
	grfio_add(data_file);	// Standard data file
	grfio_add(sdata_file);	// Sakray addon data file
	// END -----------------------------------------------------
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?