⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grf.c

📁 一个曾经热门的网络游戏RO查看GRF工具的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		grf->files = (GrfFile *) calloc (sizeof (GrfFile), grf->nfiles);		for (entry = 0, index = 0, offset = 0; entry < filelist_entries; entry++) {			unsigned long ofs2;			int type;			ofs2 = offset + getlong (filelist_data + offset) + 4;			type = filelist_data[ofs2 + 12];			/* Type 0 is a directory index; skip that */			if (type != 0) {				unsigned char *name;			/* Filename */				unsigned long compressed_len;		/* Compressed file size */				unsigned long compressed_len_aligned;	/* Not sure what this is but it's used for decoding the data */				unsigned long real_len;			/* Real (uncompressed) file size */				unsigned long pos;			/* Position of the real file data */				long cycle;				char *ext;				name = decode_filename (filelist_data + offset + 6, filelist_data[offset] - 6);				compressed_len_aligned = getlong (filelist_data + ofs2 + 4) - 37579;				real_len = getlong (filelist_data + ofs2 + 8);				pos = getlong (filelist_data + ofs2 + 13) + 46;				/* Detect the file's "cycle". This contains information about how the file entry's encoded */				compressed_len = 0;				cycle = 0;				/* Only files with an extension are encoded */				if ((ext = strrchr ((const char *) name, '.')) != NULL) {					compressed_len = getlong (filelist_data + ofs2) - getlong (filelist_data + ofs2 + 8) - 715;					if (strcasecmp (ext, ".gnd") != 0 && strcasecmp (ext, ".gat") != 0					 && strcasecmp (ext, ".act") != 0 && strcasecmp (ext, ".str") != 0) {						unsigned long i;						for (i = 10, cycle = 1; compressed_len >= i; i *= 10, cycle++);					}				}				grf->files[index].name = strdup ((const char *) name);				grf->files[index].compressed_len = compressed_len;				grf->files[index].compressed_len_aligned = compressed_len_aligned;				grf->files[index].real_len = real_len;				grf->files[index].pos = pos;				grf->files[index].cycle = cycle;				grf->files[index].type = type;				index++;			}			offset = ofs2 + 17;		}		free (filelist_data);	} else if (grf->version == 2) {		/* The file list header contains two sections:		   1. Information about the number of files and how big the file list data is.		   2. The actual file list itself (compressed).		 */		unsigned char size_header[8];	/* The header that contains information about sizes */		uLongf compressed_size;		/* Size of the compressed file list data */		uLongf decompressed_size;	/* Size of the decompressed file list data */		unsigned char *rBuf;		/* Temporarily store the compress file list data */		unsigned char *filelist_data;	/* The decompressed file list data */		unsigned long entry;		int offset;		/* Get size information */		fread (size_header, 1, 8, f);		compressed_size = getlong (size_header);		decompressed_size = getlong (size_header + 4);		debug ("File header compressed:\t\t%ld bytes\n"			"File header decompressed:\t%ld bytes\n",			compressed_size, decompressed_size);		if (compressed_size > (uLongf) (grf_size - ftell (f))) {			fclose (f);			if (error) *error = GE_CORRUPTED;			free (grf);			return NULL;		}		/* Allocate a buffer to store the raw (compressed) file list data */		rBuf = (unsigned char *) malloc (compressed_size);		if (!rBuf) {			fclose (f);			if (error) *error = GE_NOMEM;			free (grf);			return NULL;		}		fread (rBuf, 1, compressed_size, f);		/* Allocate a buffer to store the decompressed file list data */		filelist_data = (unsigned char *) malloc (decompressed_size);		if (!filelist_data) {			free (rBuf);			free (filelist_data);			fclose (f);			if (error) *error = GE_NOMEM;			free (grf);			return NULL;		}		/* Decompress the file list data */		decode_zip (filelist_data, &decompressed_size, rBuf, compressed_size);		free (rBuf);		/* Store the entire file list into an array */		grf->nfiles = getlong (grf_header + 0x26) - 7;		debug ("nfiles: %ld\n"			"Allocating %d bytes of memory for file list structure.\n",			grf->nfiles,			sizeof (GrfFile) * grf->nfiles);		grf->files = (GrfFile *) calloc (sizeof (GrfFile), grf->nfiles);		if (!grf->files) {			free (filelist_data);			fclose (f);			free (grf);			if (error) *error = GE_NOMEM;			return NULL;		}		debug ("Reading file list...\n");		for (entry = 0, offset = 0; entry < grf->nfiles; entry++){			char *name;	/* This entry's filename */			int type;			int ofs2;			name = strdup ((char *) (filelist_data + offset));			ofs2 = offset + strlen (name) + 1;			type = filelist_data[ofs2 + 12];			if (type == 1 || type == 3 || type == 5) {				unsigned long compressed_len;		/* Compressed file size */				unsigned long compressed_len_aligned;	/* Not sure what this is but it's used for decoding the data */				unsigned long real_len;			/* Real (uncompressed) file size */				unsigned long pos;			/* Position of the real file data */				long cycle;				compressed_len = getlong (filelist_data + ofs2);				compressed_len_aligned = getlong (filelist_data + ofs2 + 4);				real_len = getlong (filelist_data + ofs2 + 8);				pos = getlong (filelist_data + ofs2 + 13) + 0x2e;				/* Detect the file's "cycle". This contains information about how the file entry's encoded */				if (type == 3) {					unsigned long i;					for (i = 10, cycle = 1; compressed_len >= i; i *= 10, cycle++);				} else if (type == 5) {					cycle = 0;				} else {	/* if (type == 1) */					cycle = -1;				}				grf->files[entry].compressed_len = compressed_len;				grf->files[entry].compressed_len_aligned = compressed_len_aligned;				grf->files[entry].real_len = real_len;				grf->files[entry].pos = pos;				grf->files[entry].cycle = cycle;			}			grf->files[entry].name = name;			grf->files[entry].type = type;			/* Calculate next entry's offset */			offset += strlen ((char *) (filelist_data + offset)) + 18;		}		free (filelist_data);		debug ("Done!\n");	} else {		if (error) *error = GE_NSUP;		free (grf);		fclose (f);		return NULL;	}	grf->filename = strdup (fname);	return grf;}GRFEXPORT GrfFile *grf_find (Grf *grf, char *fname, unsigned long *index){	unsigned long i;	if (!grf || !fname) return NULL;	for (i = 0; i < grf->nfiles; i++) {		if (strcmp (grf->files[i].name, fname) == 0) {			if (index) *index = i;			return &(grf->files[i]);		}	}	return NULL;}GRFEXPORT void *grf_get (Grf *grf, char *fname, unsigned long *size, GrfError *error){	unsigned long index;	if (!grf || !fname) {		if (error) *error = GE_BADARGS;		return NULL;	}	if (!grf_find (grf, fname, &index)) {		if (error) *error = GE_NOTFOUND;		return NULL;	}	return grf_index_get (grf, index, size, error);}GRFEXPORT void *grf_index_get (Grf *grf, unsigned long index, unsigned long *size, GrfError *error){	GrfFile *file;	unsigned char *buf, *decbuf;	if (!grf) {		if (error) *error = GE_BADARGS;		return NULL;	}	if (index < 0 || index >= grf->nfiles) {		if (error) *error = GE_INDEX;		return NULL;	}	file = &(grf->files[index]);	buf = (unsigned char *) calloc (file->compressed_len_aligned + 1024, 1);	if (!buf) {		if (error) *error = GE_NOMEM;		return NULL;	}	fseek (grf->f, file->pos, SEEK_SET);	fread (buf, 1, file->compressed_len_aligned, grf->f);	if (file->type == 1 || file->type == 3 || file->type == 5) {		uLongf len;		decbuf = (unsigned char *) calloc (file->real_len + 1024, 1);		/* Some data are encoded. They must be decoded first before they can be decompressed. */		if (file->cycle >= 0) {			decode_des_etc (buf, file->compressed_len_aligned,				file->cycle == 0, file->cycle);		}		/* Now, decompress the data and return it */		len = file->real_len;		decode_zip (decbuf, &len, buf, file->compressed_len);		if (size) *size = len;		if (len != file->real_len) {			fprintf (stderr, "decode_zip size miss match err: %ld != %ld\n", len, file->real_len);		}		free (buf);	} else		decbuf = buf;	return decbuf;}GRFEXPORT intgrf_extract (Grf *grf, char *fname, const char *writeToFile, GrfError *error){	unsigned long index;	if (!grf || !fname) {		if (error) *error = GE_BADARGS;		return 0;	}	if (!grf_find (grf, fname, &index)) {		if (error) *error = GE_NOTFOUND;		return 0;	}	return grf_index_extract (grf, index, writeToFile, error);}GRFEXPORT intgrf_index_extract (Grf *grf, unsigned long index, const char *writeToFile, GrfError *error){	void *buf;	unsigned long size;	FILE *f;	if (!writeToFile) {		if (error) *error = GE_BADARGS;		return 0;	}	buf = grf_index_get (grf, index, &size, error);	if (!buf) return 0;	f = fopen (writeToFile, "wb");	if (!f) {		free (buf);		if (error) *error = GE_WRITE;		return 0;	}	fwrite (buf, size, 1, f);	fclose (f);	free (buf);	return 1;}GRFEXPORT voidgrf_free (Grf *grf){	unsigned long i;	if (!grf) return;	if (grf->f) fclose (grf->f);	if (grf->filename) free (grf->filename);	if (grf->files) {		for (i = 0; i < grf->nfiles; i++) {			if (grf->files[i].name)				free (grf->files[i].name);		}		free (grf->files);	}	free (grf);}GRFEXPORT const char *grf_strerror (GrfError error){	switch (error) {	case GE_BADARGS:		return "Bad arguments passed to function.";	case GE_CANTOPEN:		return "Cannot open file.";	case GE_INVALID:		return "Not a valid GRF archive.";	case GE_CORRUPTED:		return "The GRF archive appears to be corrupted.";	case GE_NOMEM:		return "Not enough free memory.";	case GE_NSUP:		return "GRF archives of this version is not supported.";	case GE_NOTFOUND:		return "File not found inside GRF file.";	case GE_INDEX:		return "Invalid index.";	case GE_WRITE:		return "Cannot write to destination file.";	default:		return "Unknown error.";	};}#ifdef __cplusplus	}#endif /* __cplusplus */

⌨️ 快捷键说明

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