From 572e2c0dcc4e124136f9ad4bc493184e917e8f63 Mon Sep 17 00:00:00 2001 From: ultramage Date: Fri, 2 Mar 2007 00:11:54 +0000 Subject: EOL-styled some more files git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@9947 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/script.c | 1 + src/tool/grfio.c | 1964 +++++++++++++++++++++++++-------------------------- src/tool/grfio.h | 46 +- src/tool/mapcache.c | 404 +++++------ src/zlib/zlib-1.2.3 | Bin 58 -> 0 bytes 5 files changed, 1208 insertions(+), 1207 deletions(-) (limited to 'src') diff --git a/src/map/script.c b/src/map/script.c index 09f84afbd..3b51a18b6 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -9058,6 +9058,7 @@ static int buildin_maprespawnguildid_sub_mob(struct block_list *bl,va_list ap) if(!md->guardian_data && md->class_ != MOBID_EMPERIUM) status_kill(bl); + return 0; } diff --git a/src/tool/grfio.c b/src/tool/grfio.c index ad6a466ba..2fa48a2a1 100644 --- a/src/tool/grfio.c +++ b/src/tool/grfio.c @@ -1,982 +1,982 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -/********************************************************************* - * - * Ragnarok Online Emulator : grfio.c -- grf file I/O Module - *-------------------------------------------------------------------- - * special need library : zlib - ********************************************************************* - * $Id: grfio.c,v 1.2 2004/09/29 17:31:49 kalaspuff Exp $ - * - * 2002/12/18... the original edition - * 2003/01/23 ... Code correction - * 2003/02/01 ... An addition and decryption processing are improved for LocalFile and two or more GRF(s) check processing. - * 2003/02/02 ... Even if there is no grf it does not stop -- as -- correction - * 2003/02/02... grf reading specification can be added later -- as -- correction (grfio_add function addition) - * 2003/02 / 03... at the time of grfio_resourcecheck processing the entry addition processing method -- correction - * 2003/02/05... change of the processing in grfio_init - * 2003/02/23... a local file check -- GRFIO_LOCAL -- switch (Defoe -- Function Off) - * 2003/10/21 ... The data of alpha client was read. - * 2003/11/10 ... Ready new grf format. - * 2003/11/11 ... version check fix & bug fix - * 2006/04/16 ... fixed crash grfio_find_file when file is not found. - */ - -#include -#include -#include -#include -#include -#include - -#include "grfio.h" -#include "../common/mmo.h" -#include "../zlib/unzip.h" - -#define CHUNK 16384 - -#ifdef __WIN32 - #include "../zlib/zlib.h" - #include "../zlib/iowin32.h" -#else - #ifndef __FREEBSD__ - #include - #endif -#endif - -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef unsigned long DWORD; - -static char data_dir[1024] = ""; // "../"; - -//---------------------------- -// file entry table struct -//---------------------------- -typedef struct { - int srclen; // compressed size - int srclen_aligned; // - int declen; // original size - int srcpos; - short next; - int cycle; - char type; - char fn[128-4*5]; // file name - char *fnd; - signed char gentry; // read grf file select -} FILELIST; -//gentry ... 0 : It acquires from a local file. -// It acquires from the resource file of 1>=:gentry_table[gentry-1]. -// 1<=: Check a local file. -// If it is, after re-setting to 0, it acquires from a local file. -// If there is nothing, mark reversal will be carried out, and it will re-set, and will acquire from a resource file as well as 1>=. - -//Since char defines *FILELIST.gentry, the maximum which can be added by grfio_add becomes by 127 pieces. - -#define GENTRY_LIMIT 512 -#define FILELIST_LIMIT 1048576 // temporary maximum, and a theory top maximum are 2G. - -static FILELIST *filelist = NULL; -static int filelist_entrys = 0; -static int filelist_maxentry = 0; - -static char **gentry_table = NULL; -static int gentry_entrys = 0; -static int gentry_maxentry = 0; - -//---------------------------- -// 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[0] - | p[1] << 0x08 - | p[2] << 0x10 - | p[3] << 0x18; // Shinomori -} - -/*========================================== - * 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]; - memset(tmp,0,8); - 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]; - } - } - memcpy(Src,tmp,8); -} - -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]; - } - } - Src[0] ^= tmp[4]; - Src[1] ^= tmp[5]; - Src[2] ^= tmp[6]; - Src[3] ^= tmp[7]; -} - -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 = (Bytef*) 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; -} - -int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen) { - z_stream stream; - int err; - memset(&stream, 0, sizeof(stream)); - 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 = (Bytef*) 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 = deflateInit(&stream,Z_DEFAULT_COMPRESSION); - if (err != Z_OK) return err; - - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; - - err = deflateEnd(&stream); - return err; -} - -/* =================================== -* Unzips a file. 1: success, 0: error -* Adapted from miniunz.c [Celest] -* Version 1.01b, May 30th, 2004 -* Copyright (C) 1998-2004 Gilles Vollant -* ------------------------------------- -*/ -int deflate_file (const char *source, const char *filename) -{ -#ifdef _WIN32 - zlib_filefunc_def ffunc; -#endif - unzFile uf = NULL; - int err = UNZ_OK; - uInt size_buf = 8192; - FILE *fout = NULL; - void *buf; - -#ifdef _WIN32 - fill_win32_filefunc(&ffunc); - uf = unzOpen2(source, &ffunc); -#else - uf = unzOpen(source); -#endif - - if (uf == NULL) - return 0; - - if (unzLocateFile(uf, filename, 0) != UNZ_OK) - return 0; - - err = unzOpenCurrentFilePassword(uf, NULL); - - fout = fopen(filename,"wb"); - if (fout == NULL) - return 0; - - buf = (void *)malloc(size_buf); - do { - err = unzReadCurrentFile(uf, buf, size_buf); - if (err < 0) - break; - if (err > 0 && - fwrite(buf, err, 1, fout)!=1) - { - err = UNZ_ERRNO; - break; - } - } while (err > 0); - - if (fout) fclose(fout); - - if (err == UNZ_OK) { - err = unzCloseCurrentFile (uf); - free(buf); - return (err == UNZ_OK); - } - - unzCloseCurrentFile(uf); /* don't lose the error */ - - return 0; -} - -unsigned long grfio_crc32 (const unsigned char *buf, unsigned int len) -{ - return crc32(crc32(0L, Z_NULL, 0), buf, len); -} - -/*********************************************************** - *** File List Subroutines *** - ***********************************************************/ - -/*========================================== - * 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 - *------------------------------------------ - */ -static FILELIST *filelist_find(char *fname) -{ - int hash; - - if (!filelist) - return NULL; - - for (hash = filelist_hash[filehash((unsigned char *) fname)]; hash >= 0; hash = filelist[hash].next) { - if(strcmpi(filelist[hash].fn, fname) == 0) - break; - } - - return (hash >= 0) ? &filelist[hash] : NULL; -} - -char *grfio_find_file(char *fname){ - FILELIST *filelist = filelist_find(fname); - if (!filelist) return NULL; - return (!filelist->fnd?filelist->fn:filelist->fnd); -} - -/*========================================== - * File List : Filelist add - *------------------------------------------ - */ -#define FILELIST_ADDS 1024 // number increment of file lists ` - -static FILELIST* filelist_add(FILELIST *entry) -{ - int hash; - - if (filelist_entrys >= FILELIST_LIMIT) { - printf("GRF filelist limit reached!\n"); - exit(1); - } - - if (filelist_entrys >= filelist_maxentry) { - filelist = (FILELIST *)realloc(filelist, (filelist_maxentry + FILELIST_ADDS) * sizeof(FILELIST)); - memset(filelist + filelist_maxentry, '\0', FILELIST_ADDS * sizeof(FILELIST)); - filelist_maxentry += FILELIST_ADDS; - } - - memcpy (&filelist[filelist_entrys], entry, sizeof(FILELIST)); - - hash = filehash((unsigned char *) 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 = (FILELIST *)realloc( - filelist, filelist_entrys * sizeof(FILELIST)); - filelist_maxentry = filelist_entrys; - } - } -} - -/*********************************************************** - *** 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; - - sprintf(lfname, "%s%s", data_dir, fname); - - for (p = &lfname[0]; *p != 0; p++) - if (*p=='\\') *p = '/'; // * At the time of Unix - - if (stat(lfname, &st) == 0) { - strncpy(lentry.fn, fname, sizeof(lentry.fn) - 1); - lentry.fnd = NULL; - lentry.declen = st.st_size; - lentry.gentry = 0; // 0:LocalFile - entry = filelist_modify(&lentry); - } else if (entry == NULL) { - printf("%s not found (grfio_size)\n", fname); - //exit(1); - return -1; - } - } - return entry->declen; -} - -/*========================================== - * Grfio : Resource file read & size get - *------------------------------------------ - */ -void* grfio_reads(char *fname, int *size) -{ - FILE *in; - FILELIST *entry; - unsigned char *buf2 = NULL; - - entry = filelist_find(fname); - - if (entry == NULL || entry->gentry <= 0) { // LocalFileCheck - char lfname[256], *p; - FILELIST lentry; - - sprintf(lfname, "%s%s", data_dir, fname); - - for (p = &lfname[0]; *p != 0; p++) - if (*p == '\\') *p = '/'; // * At the time of 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 = (unsigned char *)malloc(lentry.declen + 1024); - fread(buf2, 1, lentry.declen, in); - fclose(in); - strncpy(lentry.fn, fname, sizeof(lentry.fn) - 1); - lentry.fnd = NULL; - 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 (grfio_reads - local file %s)\n", fname, lfname); - return NULL; - } - } - } - if (entry != NULL && entry->gentry > 0) { // Archive[GRF] File Read - char *gfname = gentry_table[entry->gentry - 1]; - in = fopen(gfname, "rb"); - if(in != NULL) { - unsigned char *buf = (unsigned char *)malloc(entry->srclen_aligned + 1024); - fseek(in, entry->srcpos, 0); - fread(buf, 1, entry->srclen_aligned, in); - fclose(in); - buf2 = (unsigned char *)malloc(entry->declen + 1024); - 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 mismatch err: %d != %d\n", (int)len, entry->declen); - free(buf); - free(buf2); - return NULL; - } - } else { - memcpy(buf2, buf, entry->declen); - } - free(buf); - } else { - printf("%s not found (grfio_reads - GRF file %s)\n", fname, gfname); - return NULL; - } - } - if (size != NULL && entry != NULL) - *size = entry->declen; - - return buf2; -} - -/*========================================== - * Resource filename decode - *------------------------------------------ - */ -static 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 = (unsigned char *) malloc(list_size); - 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; entry < entrys; entry++) { - int ofs2, srclen, srccount, type; - char *period_ptr; - FILELIST aentry; - - ofs2 = ofs+getlong(grf_filelist+ofs)+4; - type = grf_filelist[ofs2+12]; - if (type != 0) { // Directory Index ... skip - fname = decode_filename(grf_filelist+ofs+6, grf_filelist[ofs]-6); - if (strlen(fname) > sizeof(aentry.fn) - 1) { - printf("GRF file name %s is too long\n", fname); - free(grf_filelist); - exit(1); - } - srclen = 0; - if ((period_ptr = strrchr(fname, '.')) != NULL) { - for(lop = 0; lop < 4; lop++) { - if (strcmpi(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); - aentry.fnd = NULL; -#ifdef GRFIO_LOCAL - aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck -#else - aentry.gentry = gentry+1; // With no first time 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 ((long)rSize > grf_size-ftell(fp)) { // Warning fix [Lance] - fclose(fp); - printf("Illegal data format: GRF compress entry size\n"); - return 4; - } - - rBuf = (unsigned char *)malloc(rSize); // Get a Read Size - grf_filelist = (unsigned char *)malloc(eSize); // Get a Extend Size - 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; entry < entrys; entry++){ - int ofs2, srclen, srccount, type; - FILELIST aentry; - - fname = (char*)(grf_filelist+ofs); - if (strlen(fname) > sizeof(aentry.fn)-1) { - printf("GRF file name %s is too long\n", fname); - free(grf_filelist); - exit(1); - } - //ofs2 = ofs+strlen((char*)(grf_filelist+ofs))+1; - ofs2 = ofs + strlen(fname)+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); - aentry.fnd = NULL; -#ifdef GRFIO_LOCAL - aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck -#else - aentry.gentry = gentry+1; // With no first time LocalFileCheck -#endif - filelist_modify(&aentry); - } - ofs = ofs2 + 17; - } - free(grf_filelist); - - } else { //****** Grf Other version ****** - fclose(fp); - printf("GRF version %04x not supported\n",getlong(grf_header+0x2a)); - return 4; - } - - filelist_adjust(); // Unnecessary area release of filelist - - return 0; // 0:no error -} - -/*========================================== - * Grfio : Resource file check - *------------------------------------------ - */ -static void grfio_resourcecheck(void) -{ - char w1[256], w2[256], src[256], dst[256], restable[256], line[256]; - char *ptr, *buf; - FILELIST *entry; - int size, i = 0; - FILE *fp; - - // read resnametable from data directory and return if successful - sprintf(restable, "%sdata\\resnametable.txt", data_dir); - for (ptr = &restable[0]; *ptr != 0; ptr++) - if (*ptr == '\\') *ptr = '/'; - - fp = fopen(restable,"rb"); - if (fp) { - while (fgets(line, sizeof(line) - 1, fp)) { - if (sscanf(line, "%[^#]#%[^#]#", w1, w2) == 2 && - // we only need the maps' GAT and RSW files - (strstr(w2, ".gat") || strstr(w2, ".rsw"))) - { - sprintf(src, "data\\%s", w1); - sprintf(dst, "data\\%s", w2); - entry = filelist_find(dst); - // create new entries reusing the original's info - if (entry != NULL) { - FILELIST fentry; - memcpy(&fentry, entry, sizeof(FILELIST)); - strncpy(fentry.fn, src, sizeof(fentry.fn) - 1); - fentry.fnd = grfio_alloc_ptr(dst); - filelist_modify(&fentry); - i++; - } - } - } - fclose(fp); - return; // we're done here! - } - - // read resnametable from loaded GRF's, only if it cannot be - // loaded from the data directory - buf = (char *)grfio_reads("data\\resnametable.txt", &size); - if (buf) { - buf[size] = 0; - ptr = buf; - - while (ptr - buf < size) { - if (sscanf(ptr, "%[^#]#%[^#]#", w1, w2) == 2 && - (strstr(w2, ".gat") || strstr(w2, ".rsw"))) - { - sprintf(src, "data\\%s", w1); - sprintf(dst, "data\\%s", w2); - entry = filelist_find(dst); - if (entry != NULL) { - FILELIST fentry; - memcpy(&fentry, entry, sizeof(FILELIST)); - strncpy(fentry.fn, src, sizeof(fentry.fn) - 1); - fentry.fnd = grfio_alloc_ptr(dst); - filelist_modify(&fentry); - i++; - } - } - ptr = strchr(ptr,'\n'); // Next line - if (!ptr) break; - ptr++; - } - free(buf); - return; - } - -} - -/*========================================== - * Grfio : Resource add - *------------------------------------------ - */ -#define GENTRY_ADDS 4 // The number increment of gentry_table entries - -static int grfio_add(char *fname) -{ - grfio_alloc_ptr(fname); - - return grfio_entryread(fname, gentry_entrys - 1); -} - -char *grfio_alloc_ptr(char *fname) -{ - int len; - char *buf; - - if (gentry_entrys >= GENTRY_LIMIT) { - printf("GRF file entry limit reached!\n"); - exit(1); - } - - if (gentry_entrys >= gentry_maxentry) { - gentry_maxentry += GENTRY_ADDS; - gentry_table = (char**)realloc(gentry_table, gentry_maxentry * sizeof(char*)); - memset(gentry_table + (gentry_maxentry - GENTRY_ADDS), 0, sizeof(char*) * GENTRY_ADDS); - } - len = strlen( fname ); - buf = (char*)malloc(len + 1); - strcpy(buf, fname); - gentry_table[gentry_entrys++] = buf; - - return buf; -} - -/*========================================== - * Grfio : Finalize - *------------------------------------------ - */ -void grfio_final(void) -{ - if (filelist != NULL) - free(filelist); - - filelist_entrys = filelist_maxentry = 0; - - if (gentry_table != NULL) { - int lop; - 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(char *fname) -{ - FILE *data_conf; - char line[1024], w1[1024], w2[1024]; - int grf_num = 0; - - hashinit(); // hash table initialization - - data_conf = fopen(fname, "r"); - // It will read, if there is grf-files.txt. - if (data_conf) { - while(fgets(line, sizeof(line) - 1, data_conf)) { - if (line[0] == '/' && line[1] == '/') - continue; - if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2) - continue; - // Entry table reading - if(strcmp(w1, "grf") == 0) // GRF file - grf_num += (grfio_add(w2) == 0); - else if(strcmp(w1,"data_dir") == 0) // Data directory - strcpy(data_dir, w2); - } - fclose(data_conf); - } // end of reading grf-files.txt - - if (grf_num == 0) { - printf("No GRF loaded, using default data directory\n"); - } - - // Unnecessary area release of filelist - filelist_adjust(); - // Resource check - grfio_resourcecheck(); - - return; -} +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +/********************************************************************* + * + * Ragnarok Online Emulator : grfio.c -- grf file I/O Module + *-------------------------------------------------------------------- + * special need library : zlib + ********************************************************************* + * $Id: grfio.c,v 1.2 2004/09/29 17:31:49 kalaspuff Exp $ + * + * 2002/12/18... the original edition + * 2003/01/23 ... Code correction + * 2003/02/01 ... An addition and decryption processing are improved for LocalFile and two or more GRF(s) check processing. + * 2003/02/02 ... Even if there is no grf it does not stop -- as -- correction + * 2003/02/02... grf reading specification can be added later -- as -- correction (grfio_add function addition) + * 2003/02 / 03... at the time of grfio_resourcecheck processing the entry addition processing method -- correction + * 2003/02/05... change of the processing in grfio_init + * 2003/02/23... a local file check -- GRFIO_LOCAL -- switch (Defoe -- Function Off) + * 2003/10/21 ... The data of alpha client was read. + * 2003/11/10 ... Ready new grf format. + * 2003/11/11 ... version check fix & bug fix + * 2006/04/16 ... fixed crash grfio_find_file when file is not found. + */ + +#include +#include +#include +#include +#include +#include + +#include "grfio.h" +#include "../common/mmo.h" +#include "../zlib/unzip.h" + +#define CHUNK 16384 + +#ifdef __WIN32 + #include "../zlib/zlib.h" + #include "../zlib/iowin32.h" +#else + #ifndef __FREEBSD__ + #include + #endif +#endif + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +static char data_dir[1024] = ""; // "../"; + +//---------------------------- +// file entry table struct +//---------------------------- +typedef struct { + int srclen; // compressed size + int srclen_aligned; // + int declen; // original size + int srcpos; + short next; + int cycle; + char type; + char fn[128-4*5]; // file name + char *fnd; + signed char gentry; // read grf file select +} FILELIST; +//gentry ... 0 : It acquires from a local file. +// It acquires from the resource file of 1>=:gentry_table[gentry-1]. +// 1<=: Check a local file. +// If it is, after re-setting to 0, it acquires from a local file. +// If there is nothing, mark reversal will be carried out, and it will re-set, and will acquire from a resource file as well as 1>=. + +//Since char defines *FILELIST.gentry, the maximum which can be added by grfio_add becomes by 127 pieces. + +#define GENTRY_LIMIT 512 +#define FILELIST_LIMIT 1048576 // temporary maximum, and a theory top maximum are 2G. + +static FILELIST *filelist = NULL; +static int filelist_entrys = 0; +static int filelist_maxentry = 0; + +static char **gentry_table = NULL; +static int gentry_entrys = 0; +static int gentry_maxentry = 0; + +//---------------------------- +// 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[0] + | p[1] << 0x08 + | p[2] << 0x10 + | p[3] << 0x18; // Shinomori +} + +/*========================================== + * 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]; + memset(tmp,0,8); + 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]; + } + } + memcpy(Src,tmp,8); +} + +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]; + } + } + Src[0] ^= tmp[4]; + Src[1] ^= tmp[5]; + Src[2] ^= tmp[6]; + Src[3] ^= tmp[7]; +} + +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 = (Bytef*) 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; +} + +int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen) { + z_stream stream; + int err; + memset(&stream, 0, sizeof(stream)); + 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 = (Bytef*) 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 = deflateInit(&stream,Z_DEFAULT_COMPRESSION); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =================================== +* Unzips a file. 1: success, 0: error +* Adapted from miniunz.c [Celest] +* Version 1.01b, May 30th, 2004 +* Copyright (C) 1998-2004 Gilles Vollant +* ------------------------------------- +*/ +int deflate_file (const char *source, const char *filename) +{ +#ifdef _WIN32 + zlib_filefunc_def ffunc; +#endif + unzFile uf = NULL; + int err = UNZ_OK; + uInt size_buf = 8192; + FILE *fout = NULL; + void *buf; + +#ifdef _WIN32 + fill_win32_filefunc(&ffunc); + uf = unzOpen2(source, &ffunc); +#else + uf = unzOpen(source); +#endif + + if (uf == NULL) + return 0; + + if (unzLocateFile(uf, filename, 0) != UNZ_OK) + return 0; + + err = unzOpenCurrentFilePassword(uf, NULL); + + fout = fopen(filename,"wb"); + if (fout == NULL) + return 0; + + buf = (void *)malloc(size_buf); + do { + err = unzReadCurrentFile(uf, buf, size_buf); + if (err < 0) + break; + if (err > 0 && + fwrite(buf, err, 1, fout)!=1) + { + err = UNZ_ERRNO; + break; + } + } while (err > 0); + + if (fout) fclose(fout); + + if (err == UNZ_OK) { + err = unzCloseCurrentFile (uf); + free(buf); + return (err == UNZ_OK); + } + + unzCloseCurrentFile(uf); /* don't lose the error */ + + return 0; +} + +unsigned long grfio_crc32 (const unsigned char *buf, unsigned int len) +{ + return crc32(crc32(0L, Z_NULL, 0), buf, len); +} + +/*********************************************************** + *** File List Subroutines *** + ***********************************************************/ + +/*========================================== + * 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 + *------------------------------------------ + */ +static FILELIST *filelist_find(char *fname) +{ + int hash; + + if (!filelist) + return NULL; + + for (hash = filelist_hash[filehash((unsigned char *) fname)]; hash >= 0; hash = filelist[hash].next) { + if(strcmpi(filelist[hash].fn, fname) == 0) + break; + } + + return (hash >= 0) ? &filelist[hash] : NULL; +} + +char *grfio_find_file(char *fname){ + FILELIST *filelist = filelist_find(fname); + if (!filelist) return NULL; + return (!filelist->fnd?filelist->fn:filelist->fnd); +} + +/*========================================== + * File List : Filelist add + *------------------------------------------ + */ +#define FILELIST_ADDS 1024 // number increment of file lists ` + +static FILELIST* filelist_add(FILELIST *entry) +{ + int hash; + + if (filelist_entrys >= FILELIST_LIMIT) { + printf("GRF filelist limit reached!\n"); + exit(1); + } + + if (filelist_entrys >= filelist_maxentry) { + filelist = (FILELIST *)realloc(filelist, (filelist_maxentry + FILELIST_ADDS) * sizeof(FILELIST)); + memset(filelist + filelist_maxentry, '\0', FILELIST_ADDS * sizeof(FILELIST)); + filelist_maxentry += FILELIST_ADDS; + } + + memcpy (&filelist[filelist_entrys], entry, sizeof(FILELIST)); + + hash = filehash((unsigned char *) 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 = (FILELIST *)realloc( + filelist, filelist_entrys * sizeof(FILELIST)); + filelist_maxentry = filelist_entrys; + } + } +} + +/*********************************************************** + *** 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; + + sprintf(lfname, "%s%s", data_dir, fname); + + for (p = &lfname[0]; *p != 0; p++) + if (*p=='\\') *p = '/'; // * At the time of Unix + + if (stat(lfname, &st) == 0) { + strncpy(lentry.fn, fname, sizeof(lentry.fn) - 1); + lentry.fnd = NULL; + lentry.declen = st.st_size; + lentry.gentry = 0; // 0:LocalFile + entry = filelist_modify(&lentry); + } else if (entry == NULL) { + printf("%s not found (grfio_size)\n", fname); + //exit(1); + return -1; + } + } + return entry->declen; +} + +/*========================================== + * Grfio : Resource file read & size get + *------------------------------------------ + */ +void* grfio_reads(char *fname, int *size) +{ + FILE *in; + FILELIST *entry; + unsigned char *buf2 = NULL; + + entry = filelist_find(fname); + + if (entry == NULL || entry->gentry <= 0) { // LocalFileCheck + char lfname[256], *p; + FILELIST lentry; + + sprintf(lfname, "%s%s", data_dir, fname); + + for (p = &lfname[0]; *p != 0; p++) + if (*p == '\\') *p = '/'; // * At the time of 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 = (unsigned char *)malloc(lentry.declen + 1024); + fread(buf2, 1, lentry.declen, in); + fclose(in); + strncpy(lentry.fn, fname, sizeof(lentry.fn) - 1); + lentry.fnd = NULL; + 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 (grfio_reads - local file %s)\n", fname, lfname); + return NULL; + } + } + } + if (entry != NULL && entry->gentry > 0) { // Archive[GRF] File Read + char *gfname = gentry_table[entry->gentry - 1]; + in = fopen(gfname, "rb"); + if(in != NULL) { + unsigned char *buf = (unsigned char *)malloc(entry->srclen_aligned + 1024); + fseek(in, entry->srcpos, 0); + fread(buf, 1, entry->srclen_aligned, in); + fclose(in); + buf2 = (unsigned char *)malloc(entry->declen + 1024); + 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 mismatch err: %d != %d\n", (int)len, entry->declen); + free(buf); + free(buf2); + return NULL; + } + } else { + memcpy(buf2, buf, entry->declen); + } + free(buf); + } else { + printf("%s not found (grfio_reads - GRF file %s)\n", fname, gfname); + return NULL; + } + } + if (size != NULL && entry != NULL) + *size = entry->declen; + + return buf2; +} + +/*========================================== + * Resource filename decode + *------------------------------------------ + */ +static 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 = (unsigned char *) malloc(list_size); + 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; entry < entrys; entry++) { + int ofs2, srclen, srccount, type; + char *period_ptr; + FILELIST aentry; + + ofs2 = ofs+getlong(grf_filelist+ofs)+4; + type = grf_filelist[ofs2+12]; + if (type != 0) { // Directory Index ... skip + fname = decode_filename(grf_filelist+ofs+6, grf_filelist[ofs]-6); + if (strlen(fname) > sizeof(aentry.fn) - 1) { + printf("GRF file name %s is too long\n", fname); + free(grf_filelist); + exit(1); + } + srclen = 0; + if ((period_ptr = strrchr(fname, '.')) != NULL) { + for(lop = 0; lop < 4; lop++) { + if (strcmpi(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); + aentry.fnd = NULL; +#ifdef GRFIO_LOCAL + aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck +#else + aentry.gentry = gentry+1; // With no first time 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 ((long)rSize > grf_size-ftell(fp)) { // Warning fix [Lance] + fclose(fp); + printf("Illegal data format: GRF compress entry size\n"); + return 4; + } + + rBuf = (unsigned char *)malloc(rSize); // Get a Read Size + grf_filelist = (unsigned char *)malloc(eSize); // Get a Extend Size + 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; entry < entrys; entry++){ + int ofs2, srclen, srccount, type; + FILELIST aentry; + + fname = (char*)(grf_filelist+ofs); + if (strlen(fname) > sizeof(aentry.fn)-1) { + printf("GRF file name %s is too long\n", fname); + free(grf_filelist); + exit(1); + } + //ofs2 = ofs+strlen((char*)(grf_filelist+ofs))+1; + ofs2 = ofs + strlen(fname)+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); + aentry.fnd = NULL; +#ifdef GRFIO_LOCAL + aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck +#else + aentry.gentry = gentry+1; // With no first time LocalFileCheck +#endif + filelist_modify(&aentry); + } + ofs = ofs2 + 17; + } + free(grf_filelist); + + } else { //****** Grf Other version ****** + fclose(fp); + printf("GRF version %04x not supported\n",getlong(grf_header+0x2a)); + return 4; + } + + filelist_adjust(); // Unnecessary area release of filelist + + return 0; // 0:no error +} + +/*========================================== + * Grfio : Resource file check + *------------------------------------------ + */ +static void grfio_resourcecheck(void) +{ + char w1[256], w2[256], src[256], dst[256], restable[256], line[256]; + char *ptr, *buf; + FILELIST *entry; + int size, i = 0; + FILE *fp; + + // read resnametable from data directory and return if successful + sprintf(restable, "%sdata\\resnametable.txt", data_dir); + for (ptr = &restable[0]; *ptr != 0; ptr++) + if (*ptr == '\\') *ptr = '/'; + + fp = fopen(restable,"rb"); + if (fp) { + while (fgets(line, sizeof(line) - 1, fp)) { + if (sscanf(line, "%[^#]#%[^#]#", w1, w2) == 2 && + // we only need the maps' GAT and RSW files + (strstr(w2, ".gat") || strstr(w2, ".rsw"))) + { + sprintf(src, "data\\%s", w1); + sprintf(dst, "data\\%s", w2); + entry = filelist_find(dst); + // create new entries reusing the original's info + if (entry != NULL) { + FILELIST fentry; + memcpy(&fentry, entry, sizeof(FILELIST)); + strncpy(fentry.fn, src, sizeof(fentry.fn) - 1); + fentry.fnd = grfio_alloc_ptr(dst); + filelist_modify(&fentry); + i++; + } + } + } + fclose(fp); + return; // we're done here! + } + + // read resnametable from loaded GRF's, only if it cannot be + // loaded from the data directory + buf = (char *)grfio_reads("data\\resnametable.txt", &size); + if (buf) { + buf[size] = 0; + ptr = buf; + + while (ptr - buf < size) { + if (sscanf(ptr, "%[^#]#%[^#]#", w1, w2) == 2 && + (strstr(w2, ".gat") || strstr(w2, ".rsw"))) + { + sprintf(src, "data\\%s", w1); + sprintf(dst, "data\\%s", w2); + entry = filelist_find(dst); + if (entry != NULL) { + FILELIST fentry; + memcpy(&fentry, entry, sizeof(FILELIST)); + strncpy(fentry.fn, src, sizeof(fentry.fn) - 1); + fentry.fnd = grfio_alloc_ptr(dst); + filelist_modify(&fentry); + i++; + } + } + ptr = strchr(ptr,'\n'); // Next line + if (!ptr) break; + ptr++; + } + free(buf); + return; + } + +} + +/*========================================== + * Grfio : Resource add + *------------------------------------------ + */ +#define GENTRY_ADDS 4 // The number increment of gentry_table entries + +static int grfio_add(char *fname) +{ + grfio_alloc_ptr(fname); + + return grfio_entryread(fname, gentry_entrys - 1); +} + +char *grfio_alloc_ptr(char *fname) +{ + int len; + char *buf; + + if (gentry_entrys >= GENTRY_LIMIT) { + printf("GRF file entry limit reached!\n"); + exit(1); + } + + if (gentry_entrys >= gentry_maxentry) { + gentry_maxentry += GENTRY_ADDS; + gentry_table = (char**)realloc(gentry_table, gentry_maxentry * sizeof(char*)); + memset(gentry_table + (gentry_maxentry - GENTRY_ADDS), 0, sizeof(char*) * GENTRY_ADDS); + } + len = strlen( fname ); + buf = (char*)malloc(len + 1); + strcpy(buf, fname); + gentry_table[gentry_entrys++] = buf; + + return buf; +} + +/*========================================== + * Grfio : Finalize + *------------------------------------------ + */ +void grfio_final(void) +{ + if (filelist != NULL) + free(filelist); + + filelist_entrys = filelist_maxentry = 0; + + if (gentry_table != NULL) { + int lop; + 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(char *fname) +{ + FILE *data_conf; + char line[1024], w1[1024], w2[1024]; + int grf_num = 0; + + hashinit(); // hash table initialization + + data_conf = fopen(fname, "r"); + // It will read, if there is grf-files.txt. + if (data_conf) { + while(fgets(line, sizeof(line) - 1, data_conf)) { + if (line[0] == '/' && line[1] == '/') + continue; + if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2) + continue; + // Entry table reading + if(strcmp(w1, "grf") == 0) // GRF file + grf_num += (grfio_add(w2) == 0); + else if(strcmp(w1,"data_dir") == 0) // Data directory + strcpy(data_dir, w2); + } + fclose(data_conf); + } // end of reading grf-files.txt + + if (grf_num == 0) { + printf("No GRF loaded, using default data directory\n"); + } + + // Unnecessary area release of filelist + filelist_adjust(); + // Resource check + grfio_resourcecheck(); + + return; +} diff --git a/src/tool/grfio.h b/src/tool/grfio.h index 72aceeda9..0d6268b0d 100644 --- a/src/tool/grfio.h +++ b/src/tool/grfio.h @@ -1,23 +1,23 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#ifndef _GRFIO_H_ -#define _GRFIO_H_ - -void grfio_init(char*); // GRFIO Initialize -void grfio_final(void); // GRFIO Finalize -void* grfio_reads(char*,int*); // GRFIO data file read & size get -char *grfio_find_file(char *fname); -char *grfio_alloc_ptr(char *fname); - -#define grfio_read(fn) grfio_reads(fn, NULL) - -int grfio_size(char*); // GRFIO data file size get -unsigned long grfio_crc32(const unsigned char *buf, unsigned int len); - -int decode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); -int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); -int deflate_file (const char *source, const char *filename); - -#endif /* _GRFIO_H_ */ - +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#ifndef _GRFIO_H_ +#define _GRFIO_H_ + +void grfio_init(char*); // GRFIO Initialize +void grfio_final(void); // GRFIO Finalize +void* grfio_reads(char*,int*); // GRFIO data file read & size get +char *grfio_find_file(char *fname); +char *grfio_alloc_ptr(char *fname); + +#define grfio_read(fn) grfio_reads(fn, NULL) + +int grfio_size(char*); // GRFIO data file size get +unsigned long grfio_crc32(const unsigned char *buf, unsigned int len); + +int decode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); +int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); +int deflate_file (const char *source, const char *filename); + +#endif /* _GRFIO_H_ */ + diff --git a/src/tool/mapcache.c b/src/tool/mapcache.c index c7e6aaa60..f2d638d34 100644 --- a/src/tool/mapcache.c +++ b/src/tool/mapcache.c @@ -1,202 +1,202 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#include -#include -#include -#include - -#ifndef _WIN32 -#include -#endif - -#include "grfio.h" - -char grf_list_file[256] = "tools/mapcache/grf_files.txt"; -char map_list_file[256] = "tools/mapcache/map_list.txt"; -char map_cache_file[256] = "map_cache.dat"; - -#define MAP_NAME_LENGTH 16 -#define NO_WATER 1000000 - -// Used internally, this structure contains the physical map cells -struct map_data { - short xs; - short ys; - unsigned char *cells; -}; - -// This is the header appended before every compressed map cells info -struct map_cache_info { - char name[MAP_NAME_LENGTH]; - unsigned short index; - short xs; - short ys; - long len; -}; - -// This is the main header found at the very beginning of the file -struct map_cache_head { - short sizeof_header; - short sizeof_mapinfo; - long filesize; - unsigned short map_count; -} header; - -FILE *map_cache_fp; - - -// Read map from GRF's GAT and RSW files -int read_map(char *name, struct map_data *m) -{ - char filename[256]; - char *gat, *rsw; - int water_height; - int x, y, xs, ys; - struct gat_cell { - float height[4]; - int type; - } *p = NULL; - - // Open map GAT - sprintf(filename,"data\\%s.gat", name); - gat = (char *)grfio_read(filename); - if (gat == NULL) - return 0; - - // Open map RSW - sprintf(filename,"data\\%s.rsw", name); - rsw = (char *)grfio_read(filename); - - // Read water height - if (rsw) { - float temp = *(float*)(rsw+166); - water_height = (int)temp; - free(rsw); - } else - water_height = NO_WATER; - - // Read map size and allocate needed memory - xs = m->xs = *(int*)(gat+6); - ys = m->ys = *(int*)(gat+10); - m->cells = (unsigned char *)malloc(xs*ys); - - // Set cell properties - for (y = 0; y < ys; y++) { - p = (struct gat_cell*)(gat+14+y*xs*20); - for (x = 0; x < xs; x++) { - if (water_height != NO_WATER && p->type == 0 && (p->height[0] > water_height || p->height[1] > water_height || p->height[2] > water_height || p->height[3] > water_height)) - m->cells[x+y*xs] = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water) - else - m->cells[x+y*xs] = p->type; - p++; - } - } - - free(gat); - - return 1; -} - -void cache_map(char *name, unsigned short index, struct map_data *m) -{ - struct map_cache_info info; - unsigned long len; - char *write_buf; - - // Create an output buffer twice as big as the uncompressed map... this way we're sure it fits - len = m->xs*m->ys*2; - write_buf = (char *)malloc(len); - // Compress the cells and get the compressed length - encode_zip((unsigned char *)write_buf, &len, m->cells, m->xs*m->ys); - - // Fill the map header - strncpy(info.name, name, MAP_NAME_LENGTH); - info.index = index; - info.xs = m->xs; - info.ys = m->ys; - info.len = len; - - // Append map header then compressed cells at the end of the file - fseek(map_cache_fp, header.filesize, SEEK_SET); - fwrite(&info, sizeof(struct map_cache_info), 1, map_cache_fp); - fwrite(write_buf, 1, len, map_cache_fp); - header.map_count++; - header.filesize += header.sizeof_mapinfo + len; - - free(write_buf); - free(m->cells); - - return; -} - -int main(int argc, char *argv[]) -{ - FILE *list; - char line[1024]; - struct map_data map; - char name[MAP_NAME_LENGTH]; - unsigned short index = 1; - - if(argc > 1) - strcpy(grf_list_file, argv[1]); - if(argc > 2) - strcpy(map_list_file, argv[2]); - if(argc > 3) - strcpy(map_cache_file, argv[3]); - - printf("Initializing grfio with %s\n", grf_list_file); - grfio_init(grf_list_file); - - printf("Opening map cache: %s\n", map_cache_file); - if(!(map_cache_fp = fopen(map_cache_file, "wb"))) { - printf("Failure when opening map cache file %s\n", map_cache_file); - exit(1); - } - - printf("Opening map list: %s\n", map_list_file); - if(!(list = fopen(map_list_file, "r"))) { - printf("Failure when opening maps list file %s\n", map_list_file); - exit(1); - } - - // Initialize the main header - header.sizeof_header = sizeof(struct map_cache_head); - header.sizeof_mapinfo = sizeof(struct map_cache_info); - header.map_count = 0; - header.filesize = sizeof(struct map_cache_head); - - // Read and process the map list - while(fgets(line, 1020, list)){ - - if(line[0] == '/' && line[1] == '/') - continue; - - if(sscanf(line, "%16s %hu", name, &index) > 0) { // No defines in strings, 16 is hardcoded here - printf("Index %d : %s\n", index, name); - if(read_map(name, &map)) - cache_map(name, index, &map); - else - printf("Map file not found in GRF\n"); - // If the 2nd argument is omitted at next line, we'll keep last used index + 1 - index++; - } else - printf("Skipping incorrect line\n"); - } - - printf("Closing map list: %s\n", map_list_file); - fclose(list); - - printf("Closing map cache: %s\n", map_cache_file); - // Write the main header and close the map cache - fseek(map_cache_fp, 0, SEEK_SET); - fwrite(&header, sizeof(struct map_cache_head), 1, map_cache_fp); - fclose(map_cache_fp); - - printf("Finalizing grfio\n"); - grfio_final(); - - printf("%d maps cached\n", header.map_count); - - return 0; -} +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include "grfio.h" + +char grf_list_file[256] = "tools/mapcache/grf_files.txt"; +char map_list_file[256] = "tools/mapcache/map_list.txt"; +char map_cache_file[256] = "map_cache.dat"; + +#define MAP_NAME_LENGTH 16 +#define NO_WATER 1000000 + +// Used internally, this structure contains the physical map cells +struct map_data { + short xs; + short ys; + unsigned char *cells; +}; + +// This is the header appended before every compressed map cells info +struct map_cache_info { + char name[MAP_NAME_LENGTH]; + unsigned short index; + short xs; + short ys; + long len; +}; + +// This is the main header found at the very beginning of the file +struct map_cache_head { + short sizeof_header; + short sizeof_mapinfo; + long filesize; + unsigned short map_count; +} header; + +FILE *map_cache_fp; + + +// Read map from GRF's GAT and RSW files +int read_map(char *name, struct map_data *m) +{ + char filename[256]; + char *gat, *rsw; + int water_height; + int x, y, xs, ys; + struct gat_cell { + float height[4]; + int type; + } *p = NULL; + + // Open map GAT + sprintf(filename,"data\\%s.gat", name); + gat = (char *)grfio_read(filename); + if (gat == NULL) + return 0; + + // Open map RSW + sprintf(filename,"data\\%s.rsw", name); + rsw = (char *)grfio_read(filename); + + // Read water height + if (rsw) { + float temp = *(float*)(rsw+166); + water_height = (int)temp; + free(rsw); + } else + water_height = NO_WATER; + + // Read map size and allocate needed memory + xs = m->xs = *(int*)(gat+6); + ys = m->ys = *(int*)(gat+10); + m->cells = (unsigned char *)malloc(xs*ys); + + // Set cell properties + for (y = 0; y < ys; y++) { + p = (struct gat_cell*)(gat+14+y*xs*20); + for (x = 0; x < xs; x++) { + if (water_height != NO_WATER && p->type == 0 && (p->height[0] > water_height || p->height[1] > water_height || p->height[2] > water_height || p->height[3] > water_height)) + m->cells[x+y*xs] = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water) + else + m->cells[x+y*xs] = p->type; + p++; + } + } + + free(gat); + + return 1; +} + +void cache_map(char *name, unsigned short index, struct map_data *m) +{ + struct map_cache_info info; + unsigned long len; + char *write_buf; + + // Create an output buffer twice as big as the uncompressed map... this way we're sure it fits + len = m->xs*m->ys*2; + write_buf = (char *)malloc(len); + // Compress the cells and get the compressed length + encode_zip((unsigned char *)write_buf, &len, m->cells, m->xs*m->ys); + + // Fill the map header + strncpy(info.name, name, MAP_NAME_LENGTH); + info.index = index; + info.xs = m->xs; + info.ys = m->ys; + info.len = len; + + // Append map header then compressed cells at the end of the file + fseek(map_cache_fp, header.filesize, SEEK_SET); + fwrite(&info, sizeof(struct map_cache_info), 1, map_cache_fp); + fwrite(write_buf, 1, len, map_cache_fp); + header.map_count++; + header.filesize += header.sizeof_mapinfo + len; + + free(write_buf); + free(m->cells); + + return; +} + +int main(int argc, char *argv[]) +{ + FILE *list; + char line[1024]; + struct map_data map; + char name[MAP_NAME_LENGTH]; + unsigned short index = 1; + + if(argc > 1) + strcpy(grf_list_file, argv[1]); + if(argc > 2) + strcpy(map_list_file, argv[2]); + if(argc > 3) + strcpy(map_cache_file, argv[3]); + + printf("Initializing grfio with %s\n", grf_list_file); + grfio_init(grf_list_file); + + printf("Opening map cache: %s\n", map_cache_file); + if(!(map_cache_fp = fopen(map_cache_file, "wb"))) { + printf("Failure when opening map cache file %s\n", map_cache_file); + exit(1); + } + + printf("Opening map list: %s\n", map_list_file); + if(!(list = fopen(map_list_file, "r"))) { + printf("Failure when opening maps list file %s\n", map_list_file); + exit(1); + } + + // Initialize the main header + header.sizeof_header = sizeof(struct map_cache_head); + header.sizeof_mapinfo = sizeof(struct map_cache_info); + header.map_count = 0; + header.filesize = sizeof(struct map_cache_head); + + // Read and process the map list + while(fgets(line, 1020, list)){ + + if(line[0] == '/' && line[1] == '/') + continue; + + if(sscanf(line, "%16s %hu", name, &index) > 0) { // No defines in strings, 16 is hardcoded here + printf("Index %d : %s\n", index, name); + if(read_map(name, &map)) + cache_map(name, index, &map); + else + printf("Map file not found in GRF\n"); + // If the 2nd argument is omitted at next line, we'll keep last used index + 1 + index++; + } else + printf("Skipping incorrect line\n"); + } + + printf("Closing map list: %s\n", map_list_file); + fclose(list); + + printf("Closing map cache: %s\n", map_cache_file); + // Write the main header and close the map cache + fseek(map_cache_fp, 0, SEEK_SET); + fwrite(&header, sizeof(struct map_cache_head), 1, map_cache_fp); + fclose(map_cache_fp); + + printf("Finalizing grfio\n"); + grfio_final(); + + printf("%d maps cached\n", header.map_count); + + return 0; +} diff --git a/src/zlib/zlib-1.2.3 b/src/zlib/zlib-1.2.3 index a6a9cc84d..e69de29bb 100644 Binary files a/src/zlib/zlib-1.2.3 and b/src/zlib/zlib-1.2.3 differ -- cgit v1.2.3-60-g2f50