summaryrefslogtreecommitdiff
path: root/src/tool/mapcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tool/mapcache.c')
-rw-r--r--src/tool/mapcache.c214
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;
}