diff options
Diffstat (limited to 'src/tool/mapcache.c')
-rw-r--r-- | src/tool/mapcache.c | 214 |
1 files changed, 154 insertions, 60 deletions
diff --git a/src/tool/mapcache.c b/src/tool/mapcache.c index d088a9d52..c576a6b6c 100644 --- a/src/tool/mapcache.c +++ b/src/tool/mapcache.c @@ -4,6 +4,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <malloc.h> #ifndef _WIN32 #include <unistd.h> @@ -11,12 +12,18 @@ #include "grfio.h" -char grf_list_file[256] = "db/grf_files.txt"; -char map_list_file[256] = "db/map_list.txt"; +#define MAP_NAME_LENGTH 12 +#define MAP_NAME_LENGTH_EXT 16 +#define NO_WATER 1000000 + +char grf_list_file[256] = "tools/mapcache/grf_files.txt"; +char map_list_file[256] = "db/map_index.txt"; char map_cache_file[256] = "db/map_cache.dat"; +int rebuild = 0; -#define MAP_NAME_LENGTH 16 -#define NO_WATER 1000000 +FILE *map_cache_fp; + +unsigned long file_size; // Used internally, this structure contains the physical map cells struct map_data { @@ -26,31 +33,25 @@ struct map_data { }; // This is the main header found at the very beginning of the file -unsigned short map_count; +struct main_header { + unsigned long file_size; + unsigned short map_count; +} header; // This is the header appended before every compressed map cells info -struct map_cache_info { +struct map_info { char name[MAP_NAME_LENGTH]; - unsigned short index; short xs; short ys; long len; }; -FILE *map_cache_fp; - -int filesize; -/// Converts an unsigned short (16 bits) from current machine order to little-endian -unsigned short MakeUShortLE(unsigned short val) -{ - unsigned char buf[2]; - buf[0] = (unsigned char)( (val & 0x00FF) ); - buf[1] = (unsigned char)( (val & 0xFF00) >> 0x08 ); - return *((unsigned short*)buf); -} +/************************************* +* Big-endian compatibility functions * +*************************************/ -/// Converts a short (16 bits) from current machine order to little-endian +// Converts a short (16 bits) from current machine order to little-endian short MakeShortLE(short val) { unsigned char buf[2]; @@ -59,7 +60,7 @@ short MakeShortLE(short val) return *((short*)buf); } -/// Converts a long (32 bits) from current machine order to little-endian +// Converts a long (32 bits) from current machine order to little-endian long MakeLongLE(long val) { unsigned char buf[4]; @@ -70,7 +71,23 @@ long MakeLongLE(long val) return *((long*)buf); } -/// Reads an unsigned long (32 bits) in little-endian from the buffer +// Reads an unsigned short (16 bits) in little-endian from the buffer +unsigned short GetUShort(const unsigned char *buf) +{ + return ( ((unsigned short)(buf[0])) ) + |( ((unsigned short)(buf[1])) << 0x08 ); +} + +// Reads a long (32 bits) in little-endian from the buffer +long GetLong(const unsigned char *buf) +{ + return ( ((long)(buf[0])) ) + |( ((long)(buf[1])) << 0x08 ) + |( ((long)(buf[2])) << 0x10 ) + |( ((long)(buf[3])) << 0x18 ); +} + +// Reads an unsigned long (32 bits) in little-endian from the buffer unsigned long GetULong(const unsigned char *buf) { return ( ((unsigned long)(buf[0])) ) @@ -87,7 +104,7 @@ float GetFloat(const unsigned char *buf) } -// Read map from GRF's GAT and RSW files +// Reads a map from GRF's GAT and RSW files int read_map(char *name, struct map_data *m) { char filename[256]; @@ -143,31 +160,31 @@ int read_map(char *name, struct map_data *m) return 1; } -void cache_map(char *name, unsigned short index, struct map_data *m) +// Adds a map to the cache +void cache_map(char *name, struct map_data *m) { - struct map_cache_info info; - unsigned long len; - char *write_buf; + struct map_info info; + long len; + unsigned 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); + write_buf = (unsigned char *)malloc(len); // Compress the cells and get the compressed length - encode_zip((unsigned char *)write_buf, &len, m->cells, m->xs*m->ys); + encode_zip(write_buf, &len, m->cells, m->xs*m->ys); // Fill the map header strncpy(info.name, name, MAP_NAME_LENGTH); - info.index = MakeUShortLE(index); info.xs = MakeShortLE(m->xs); info.ys = MakeShortLE(m->ys); - info.len = MakeLongLE((long)len); + info.len = MakeLongLE(len); // Append map header then compressed cells at the end of the file - fseek(map_cache_fp, filesize, SEEK_SET); - fwrite(&info, sizeof(struct map_cache_info), 1, map_cache_fp); + fseek(map_cache_fp, header.file_size, SEEK_SET); + fwrite(&info, sizeof(struct map_info), 1, map_cache_fp); fwrite(write_buf, 1, len, map_cache_fp); - map_count++; - filesize += sizeof(struct map_cache_info) + len; + header.file_size += sizeof(struct map_info) + len; + header.map_count++; free(write_buf); free(m->cells); @@ -175,41 +192,111 @@ void cache_map(char *name, unsigned short index, struct map_data *m) return; } +// Checks whether a map is already is the cache +int find_map(char *name) +{ + int i; + struct map_info info; + + fseek(map_cache_fp, sizeof(struct main_header), SEEK_SET); + + for(i = 0; i < header.map_count; i++) { + fread(&info, sizeof(info), 1, map_cache_fp); + if(strcmp(name, info.name) == 0) // Map found + return 1; + else // Map not found, jump to the beginning of the next map info header + fseek(map_cache_fp, GetLong((unsigned char *)&(info.len)), SEEK_CUR); + } + + return 0; +} + +// Cuts the extension from a map name +char *remove_extension(char *mapname) +{ + char *ptr, *ptr2; + ptr = strchr(mapname, '.'); + if (ptr) { //Check and remove extension. + while (ptr[1] && (ptr2 = strchr(ptr+1, '.'))) + ptr = ptr2; //Skip to the last dot. + if(stricmp(ptr,".gat") == 0 || + stricmp(ptr,".afm") == 0 || + stricmp(ptr,".af2") == 0) + *ptr = '\0'; //Remove extension. + } + return mapname; +} + +// Processes command-line arguments +void process_args(int argc, char *argv[]) +{ + int i; + + for(i = 0; i < argc; i++) { + if(strcmp(argv[i], "-grf") == 0) { + if(++i < argc) + strcpy(grf_list_file, argv[i]); + } else if(strcmp(argv[i], "-list") == 0) { + if(++i < argc) + strcpy(map_list_file, argv[i]); + } else if(strcmp(argv[i], "-cache") == 0) { + if(++i < argc) + strcpy(map_cache_file, argv[i]); + } else if(strcmp(argv[i], "-rebuild") == 0) + rebuild = 1; + } + +} + int main(int argc, char *argv[]) { FILE *list; char line[1024]; struct map_data map; - char name[MAP_NAME_LENGTH]; - unsigned short index = 1; + char name[MAP_NAME_LENGTH_EXT]; - 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]); + // Process the command-line arguments + process_args(argc, argv); printf("Initializing grfio with %s\n", grf_list_file); grfio_init(grf_list_file); + // Attempt to open the map cache file and force rebuild if not found printf("Opening map cache: %s\n", map_cache_file); - map_cache_fp = fopen(map_cache_file, "wb"); - if( map_cache_fp == NULL ) { + if(!rebuild) { + map_cache_fp = fopen(map_cache_file, "rb"); + if(map_cache_fp == NULL) { + printf("Existing map cache not found, forcing rebuild mode\n"); + rebuild = 1; + } else + fclose(map_cache_fp); + } + if(rebuild) + map_cache_fp = fopen(map_cache_file, "w+b"); + else + map_cache_fp = fopen(map_cache_file, "r+b"); + if(map_cache_fp == NULL) { printf("Failure when opening map cache file %s\n", map_cache_file); exit(1); } + // Open the map list printf("Opening map list: %s\n", map_list_file); list = fopen(map_list_file, "r"); - if( list == NULL ) { + if(list == NULL) { printf("Failure when opening maps list file %s\n", map_list_file); - exit(1); + exit(2); } // Initialize the main header - map_count = 0; - filesize = sizeof(map_count); + if(rebuild) { + header.file_size = sizeof(struct main_header); + header.map_count = 0; + } else { + fread(&header, sizeof(struct main_header), 1, map_cache_fp); + header.file_size = GetULong((unsigned char *)&(header.file_size)); + header.map_count = GetUShort((unsigned char *)&(header.map_count)); + } // Read and process the map list while(fgets(line, 1020, list)){ @@ -217,30 +304,37 @@ int main(int argc, char *argv[]) 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++; - } + if(sscanf(line, "%15s", name) < 1) + continue; + + if(strcmp("map:", name) == 0 && sscanf(line, "%*s %15s", name) < 1) + continue; + + remove_extension(name); + printf("%s", name); + if(find_map(name)) + printf(" already in cache!\n"); + else if(read_map(name, &map)) { + cache_map(name, &map); + printf(" successfully cached\n"); + } else + printf(" not found in GRF!\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 + printf("Closing map cache: %s\n", map_cache_file); fseek(map_cache_fp, 0, SEEK_SET); - fwrite(&map_count, sizeof(map_count), 1, map_cache_fp); + fwrite(&header, sizeof(struct main_header), 1, map_cache_fp); fclose(map_cache_fp); printf("Finalizing grfio\n"); grfio_final(); - printf("%d maps cached\n", map_count); + printf("%d maps now in cache\n", header.map_count); return 0; } |