From 0477c7a88f8b0338c5331bcf0dfcce9fc4f9f201 Mon Sep 17 00:00:00 2001 From: DracoRPG Date: Wed, 28 Feb 2007 00:57:29 +0000 Subject: [PATCH] Added experimental new mapcache generator git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@9928 54d463be-8e91-2dee-dedb-b68131a5f0ec --- eAthena-8.sln | 16 +- src/tool/grfio.c | 982 +++++++++++++++++++++++++++++++++++ src/tool/grfio.h | 23 + src/tool/mapcache.c | 202 +++++++ tools/mapcache/grf_files.txt | 14 + tools/mapcache/map_list.txt | 646 +++++++++++++++++++++++ vcproj-8/mapcache.vcproj | 261 ++++++++++ 7 files changed, 2143 insertions(+), 1 deletion(-) create mode 100644 src/tool/grfio.c create mode 100644 src/tool/grfio.h create mode 100644 src/tool/mapcache.c create mode 100644 tools/mapcache/grf_files.txt create mode 100644 tools/mapcache/map_list.txt create mode 100644 vcproj-8/mapcache.vcproj diff --git a/eAthena-8.sln b/eAthena-8.sln index 88a55a5a3c..355912d6af 100644 --- a/eAthena-8.sln +++ b/eAthena-8.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 +# Visual C++ Express 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "map-server_txt", "vcproj-8\map-server_txt.vcproj", "{D356871D-58E1-450B-967A-E1E9646175AF}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "login-server_txt", "vcproj-8\login-server_txt.vcproj", "{D356871D-58E1-450B-967A-E2E9646175AF}" @@ -12,6 +12,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "login-server_sql", "vcproj- EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "map-server_sql", "vcproj-8\map-server_sql.vcproj", "{D356871D-58E1-450B-967A-E6E9646175AF}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mapcache", "vcproj-8\mapcache.vcproj", "{82A4EF25-7047-4DF1-A89C-94A6C73E0712}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -82,6 +84,18 @@ Global {D356871D-58E1-450B-967A-E6E9646175AF}.Release-sql|Win32.ActiveCfg = Release|Win32 {D356871D-58E1-450B-967A-E6E9646175AF}.Release-sql|Win32.Build.0 = Release|Win32 {D356871D-58E1-450B-967A-E6E9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Debug|Win32.ActiveCfg = Debug|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Debug|Win32.Build.0 = Debug|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Debug-sql|Win32.ActiveCfg = Debug|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Debug-sql|Win32.Build.0 = Debug|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Debug-txt|Win32.ActiveCfg = Debug|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Debug-txt|Win32.Build.0 = Debug|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Release|Win32.ActiveCfg = Release|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Release|Win32.Build.0 = Release|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Release-sql|Win32.ActiveCfg = Release|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Release-sql|Win32.Build.0 = Release|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Release-txt|Win32.ActiveCfg = Release|Win32 + {82A4EF25-7047-4DF1-A89C-94A6C73E0712}.Release-txt|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/tool/grfio.c b/src/tool/grfio.c new file mode 100644 index 0000000000..ad6a466ba0 --- /dev/null +++ b/src/tool/grfio.c @@ -0,0 +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; +} diff --git a/src/tool/grfio.h b/src/tool/grfio.h new file mode 100644 index 0000000000..72aceeda99 --- /dev/null +++ b/src/tool/grfio.h @@ -0,0 +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_ */ + diff --git a/src/tool/mapcache.c b/src/tool/mapcache.c new file mode 100644 index 0000000000..c7e6aaa608 --- /dev/null +++ b/src/tool/mapcache.c @@ -0,0 +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; +} diff --git a/tools/mapcache/grf_files.txt b/tools/mapcache/grf_files.txt new file mode 100644 index 0000000000..38e4bca905 --- /dev/null +++ b/tools/mapcache/grf_files.txt @@ -0,0 +1,14 @@ +//----------------------------------------- +// GRF List +//----------------------------------------- + +grf: C:\Jeux\RO\sdata.grf + +// You may add more in this format +// grf: + +//------ Others --------------------------- + +//Path to directory that contains the data dir +//NOTE: Path must include trailing backslash, only one data_dir entry is supported. +//data_dir: C:\Program Files\Gravity\RO\ diff --git a/tools/mapcache/map_list.txt b/tools/mapcache/map_list.txt new file mode 100644 index 0000000000..5bb039d6f0 --- /dev/null +++ b/tools/mapcache/map_list.txt @@ -0,0 +1,646 @@ +//====================================================================================== +// Map Index +//====================================================================================== +//Contains the list of maps with their respective IDs for inter-server use. +//IDs must never change, therefore any new maps need to be added at the end, +//and old ones must not be removed, but may be replaced. +//Format: +//mapnameindex <- specifies index for this map +//mapname <- map will use index of previous map +1 +//Note that map index 0 is special and reserved for "error" status. +alb_ship 1 +alb2trea +alberta +alberta_in +alde_dun01 +alde_dun02 +alde_dun03 +alde_dun04 +aldeba_in +aldebaran +anthell01 +anthell02 +arena_room +c_tower1 +c_tower2 +c_tower3 +c_tower4 +force_1-1 +force_1-2 +force_1-3 +force_2-1 +force_2-2 +force_2-3 +force_3-1 +force_3-2 +force_3-3 +gef_dun00 +gef_dun01 +gef_dun02 +gef_dun03 +gef_fild00 +gef_fild01 +gef_fild02 +gef_fild03 +gef_fild04 +gef_fild05 +gef_fild06 +gef_fild07 +gef_fild08 +gef_fild09 +gef_fild10 +gef_fild11 +gef_fild12 +gef_fild13 +gef_fild14 +gef_tower +geffen +geffen_in +gl_cas01 +gl_cas02 +gl_church +gl_chyard +gl_dun01 +gl_dun02 +gl_in01 +gl_knt01 +gl_knt02 +gl_prison +gl_prison1 +gl_sew01 +gl_sew02 +gl_sew03 +gl_sew04 +gl_step +glast_01 +hunter_1-1 +hunter_2-1 +hunter_3-1 +in_hunter +in_moc_16 +in_orcs01 +in_sphinx1 +in_sphinx2 +in_sphinx3 +in_sphinx4 +in_sphinx5 +iz_dun00 +iz_dun01 +iz_dun02 +iz_dun03 +iz_dun04 +job_sword1 +izlu2dun +izlude +izlude_in +job_thief1 +knight_1-1 +knight_2-1 +knight_3-1 +mjo_dun01 +mjo_dun02 +mjo_dun03 +mjolnir_01 +mjolnir_02 +mjolnir_03 +mjolnir_04 +mjolnir_05 +mjolnir_06 +mjolnir_07 +mjolnir_08 +mjolnir_09 +mjolnir_10 +mjolnir_11 +mjolnir_12 +moc_castle +moc_fild01 +moc_fild02 +moc_fild03 +moc_fild04 +moc_fild05 +moc_fild06 +moc_fild07 +moc_fild08 +moc_fild09 +moc_fild10 +moc_fild11 +moc_fild12 +moc_fild13 +moc_fild14 +moc_fild15 +moc_fild16 +moc_fild17 +moc_fild18 +moc_fild19 +moc_pryd01 +moc_pryd02 +moc_pryd03 +moc_pryd04 +moc_pryd05 +moc_pryd06 +moc_prydb1 +moc_ruins +monk_in +morocc +morocc_in +new_1-1 +new_1-2 +new_1-3 +new_1-4 +new_2-1 +new_2-2 +new_2-3 +new_2-4 +new_3-1 +new_3-2 +new_3-3 +new_3-4 +new_4-1 +new_4-2 +new_4-3 +new_4-4 +new_5-1 +new_5-2 +new_5-3 +new_5-4 +orcsdun01 +orcsdun02 +ordeal_1-1 +ordeal_1-2 +ordeal_1-3 +ordeal_1-4 +ordeal_2-1 +ordeal_2-2 +ordeal_2-3 +ordeal_2-4 +ordeal_3-1 +ordeal_3-2 +ordeal_3-3 +ordeal_3-4 +pay_arche +pay_dun00 +pay_dun01 +pay_dun02 +pay_dun03 +pay_dun04 +pay_fild01 +pay_fild02 +pay_fild03 +pay_fild04 +pay_fild05 +pay_fild06 +pay_fild07 +pay_fild08 +pay_fild09 +pay_fild10 +pay_fild11 +payon +payon_in01 +payon_in02 +priest_1-1 +priest_2-1 +priest_3-1 +prontera +prt_are_in +prt_are01 +pvp_room +prt_castle +prt_church +prt_fild00 +prt_fild01 +prt_fild02 +prt_fild03 +prt_fild04 +prt_fild05 +prt_fild06 +prt_fild07 +prt_fild08 +prt_fild09 +prt_fild10 +prt_fild11 +prt_in +prt_maze01 +prt_maze02 +prt_maze03 +prt_monk +prt_sewb1 +prt_sewb2 +prt_sewb3 +prt_sewb4 +pvp_2vs2 +pvp_c_room +pvp_n_1-1 +pvp_n_1-2 +pvp_n_1-3 +pvp_n_1-4 +pvp_n_1-5 +pvp_n_2-1 +pvp_n_2-2 +pvp_n_2-3 +pvp_n_2-4 +pvp_n_2-5 +pvp_n_3-1 +pvp_n_3-2 +pvp_n_3-3 +pvp_n_3-4 +pvp_n_3-5 +pvp_n_4-1 +pvp_n_4-2 +pvp_n_4-3 +pvp_n_4-4 +pvp_n_4-5 +pvp_n_5-1 +pvp_n_5-2 +pvp_n_5-3 +pvp_n_5-4 +pvp_n_5-5 +pvp_n_6-1 +pvp_n_6-2 +pvp_n_6-3 +pvp_n_6-4 +pvp_n_6-5 +pvp_n_7-1 +pvp_n_7-2 +pvp_n_7-3 +pvp_n_7-4 +pvp_n_7-5 +pvp_n_8-1 +pvp_n_8-2 +pvp_n_8-3 +pvp_n_8-4 +pvp_n_8-5 +pvp_n_room +pvp_y_1-1 +pvp_y_1-2 +pvp_y_1-3 +pvp_y_1-4 +pvp_y_1-5 +pvp_y_2-1 +pvp_y_2-2 +pvp_y_2-3 +pvp_y_2-4 +pvp_y_2-5 +pvp_y_3-1 +pvp_y_3-2 +pvp_y_3-3 +pvp_y_3-4 +pvp_y_3-5 +pvp_y_4-1 +pvp_y_4-2 +pvp_y_4-3 +pvp_y_4-4 +pvp_y_4-5 +pvp_y_5-1 +pvp_y_5-2 +pvp_y_5-3 +pvp_y_5-4 +pvp_y_5-5 +pvp_y_6-1 +pvp_y_6-2 +pvp_y_6-3 +pvp_y_6-4 +pvp_y_6-5 +pvp_y_7-1 +pvp_y_7-2 +pvp_y_7-3 +pvp_y_7-4 +pvp_y_7-5 +pvp_y_8-1 +pvp_y_8-2 +pvp_y_8-3 +pvp_y_8-4 +pvp_y_8-5 +pvp_y_room +sword_1-1 +sword_2-1 +sword_3-1 +treasure01 +treasure02 +wizard_1-1 +wizard_2-1 +wizard_3-1 +xmas +xmas_dun01 +xmas_dun02 +xmas_fild01 +xmas_in +beach_dun +beach_dun2 +beach_dun3 +cmd_fild01 +cmd_fild02 +cmd_fild03 +cmd_fild04 +cmd_fild05 +cmd_fild06 +cmd_fild07 +cmd_fild08 +cmd_fild09 +cmd_in01 +cmd_in02 +comodo +quiz_00 +quiz_01 +g_room1-1 +g_room1-2 +g_room1-3 +g_room2 +tur_dun01 +tur_dun02 +tur_dun03 +tur_dun04 +tur_dun05 +tur_dun06 +alde_gld +aldeg_cas01 +aldeg_cas02 +aldeg_cas03 +aldeg_cas04 +aldeg_cas05 +gefg_cas01 +gefg_cas02 +gefg_cas03 +gefg_cas04 +gefg_cas05 +gld_dun01 +gld_dun02 +gld_dun03 +gld_dun04 +guild_room +guild_vs1 +guild_vs2 +guild_vs3 +guild_vs4 +guild_vs5 +guild_vs1-1 +guild_vs1-2 +guild_vs1-3 +guild_vs1-4 +guild_vs2-1 +guild_vs2-2 +job_hunte +job_knt +job_prist +job_wiz +pay_gld +payg_cas01 +payg_cas02 +payg_cas03 +payg_cas04 +payg_cas05 +prt_gld +prtg_cas01 +prtg_cas02 +prtg_cas03 +prtg_cas04 +prtg_cas05 +alde_alche +in_rogue +job_cru +job_duncer +job_monk +job_sage +mag_dun01 +mag_dun02 +monk_test +quiz_test +yuno +yuno_fild01 +yuno_fild02 +yuno_fild03 +yuno_fild04 +yuno_in01 +yuno_in02 +yuno_in03 +yuno_in04 +yuno_in05 +ama_dun01 +ama_dun02 +ama_dun03 +ama_fild01 +ama_in01 +ama_in02 +ama_test +amatsu +gon_dun01 +gon_dun02 +gon_dun03 +gon_fild01 +gon_in +gon_test +gonryun +sec_in01 +sec_in02 +sec_pri +umbala +um_dun01 +um_dun02 +um_fild01 +um_fild02 +um_fild03 +um_fild04 +um_in +niflheim +nif_fild01 +nif_fild02 +nif_in +yggdrasil01 +valkyrie +himinn +lou_in01 +lou_in02 +lou_dun03 +lou_dun02 +lou_dun01 +lou_fild01 +louyang +siege_test +n_castle +nguild_gef +nguild_prt +nguild_pay +nguild_alde +jawaii +jawaii_in +gefenia01 +gefenia02 +gefenia03 +gefenia04 +new_zone01 +new_zone02 +new_zone03 +new_zone04 +payon_in03 +ayothaya +ayo_in01 +ayo_in02 +ayo_fild01 +ayo_fild02 +ayo_dun01 +ayo_dun02 +que_god01 +que_god02 +yuno_fild05 +yuno_fild07 +yuno_fild08 +yuno_fild09 +yuno_fild11 +yuno_fild12 +alde_tt02 +turbo_n_1 +turbo_n_4 +turbo_n_8 +turbo_n_16 +turbo_e_4 +turbo_e_8 +turbo_e_16 +turbo_room +airplane +airport +einbech +einbroch +ein_dun01 +ein_dun02 +ein_fild06 +ein_fild07 +ein_fild08 +ein_fild09 +ein_fild10 +ein_in01 +que_sign01 +que_sign02 +ein_fild03 +ein_fild04 +lhz_fild02 +lhz_fild03 +yuno_pre +lhz_fild01 +lighthalzen +lhz_in01 +lhz_in02 +lhz_in03 +lhz_que01 +lhz_dun01 +lhz_dun02 +lhz_dun03 +lhz_cube +juperos_01 +juperos_02 +jupe_area1 +jupe_area2 +jupe_core +jupe_ele +jupe_ele_r +jupe_gate +y_airport +lhz_airport +airplane_01 +jupe_cave +quiz_02 +hu_fild07 +hu_fild05 +hu_fild04 +hu_fild01 +yuno_fild06 +job_soul +job_star +que_job01 +que_job02 +que_job03 +abyss_01 +abyss_02 +abyss_03 +thana_step +thana_boss +tha_scene01 +tha_t01 +tha_t02 +tha_t03 +tha_t04 +tha_t07 +tha_t05 +tha_t06 +tha_t08 +tha_t09 +tha_t10 +tha_t11 +tha_t12 +auction_01 +auction_02 +hugel +hu_in01 +que_bingo +que_hugel +p_track01 +p_track02 +odin_tem01 +odin_tem02 +odin_tem03 +hu_fild02 +hu_fild03 +hu_fild06 +ein_fild01 +ein_fild02 +ein_fild05 +yuno_fild10 +kh_kiehl02 +kh_kiehl01 +kh_dun02 +kh_dun01 +kh_mansion +kh_rossi +kh_school +kh_vila +force_map1 +force_map2 +force_map3 +job_hunter +job_knight +job_priest +job_wizard +g_room2 +rachel +ra_in01 +ra_fild01 +ra_fild02 +ra_fild03 +ra_fild04 +ra_fild05 +ra_fild06 +ra_fild07 +ra_fild08 +ra_fild09 +ra_fild10 +ra_fild11 +ra_fild12 +ra_fild13 +ra_san01 +ra_san02 +ra_san03 +ra_san04 +ra_san05 +ra_temin +ra_temple +ra_temsky +que_rachel +ice_dun01 +ice_dun02 +ice_dun03 +ice_dun04 +que_thor +thor_camp +thor_v01 +thor_v02 +thor_v03 +veins +ve_in +ve_fild01 +ve_fild02 +ve_fild03 +ve_fild04 +ve_fild05 +ve_fild06 +ve_fild07 +poring_c01 +poring_c02 +que_ng diff --git a/vcproj-8/mapcache.vcproj b/vcproj-8/mapcache.vcproj new file mode 100644 index 0000000000..f2db1a2da5 --- /dev/null +++ b/vcproj-8/mapcache.vcproj @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +