mapcache.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #ifndef _WIN32
  7. #include <unistd.h>
  8. #endif
  9. #include "../common/cbasetypes.h"
  10. #include "grfio.h"
  11. #define MAP_NAME_LENGTH 12
  12. #define MAP_NAME_LENGTH_EXT 16
  13. #define NO_WATER 1000000
  14. char grf_list_file[256] = "tools/mapcache/grf_files.txt";
  15. char map_list_file[256] = "db/map_index.txt";
  16. char map_cache_file[256] = "db/map_cache.dat";
  17. int rebuild = 0;
  18. FILE *map_cache_fp;
  19. unsigned long file_size;
  20. // Used internally, this structure contains the physical map cells
  21. struct map_data {
  22. short xs;
  23. short ys;
  24. unsigned char *cells;
  25. };
  26. // This is the main header found at the very beginning of the file
  27. struct main_header {
  28. unsigned long file_size;
  29. unsigned short map_count;
  30. } header;
  31. // This is the header appended before every compressed map cells info
  32. struct map_info {
  33. char name[MAP_NAME_LENGTH];
  34. short xs;
  35. short ys;
  36. long len;
  37. };
  38. /*************************************
  39. * Big-endian compatibility functions *
  40. *************************************/
  41. // Converts a short (16 bits) from current machine order to little-endian
  42. short MakeShortLE(short val)
  43. {
  44. unsigned char buf[2];
  45. buf[0] = (unsigned char)( (val & 0x00FF) );
  46. buf[1] = (unsigned char)( (val & 0xFF00) >> 0x08 );
  47. return *((short*)buf);
  48. }
  49. // Converts a long (32 bits) from current machine order to little-endian
  50. long MakeLongLE(long val)
  51. {
  52. unsigned char buf[4];
  53. buf[0] = (unsigned char)( (val & 0x000000FF) );
  54. buf[1] = (unsigned char)( (val & 0x0000FF00) >> 0x08 );
  55. buf[2] = (unsigned char)( (val & 0x00FF0000) >> 0x10 );
  56. buf[3] = (unsigned char)( (val & 0xFF000000) >> 0x18 );
  57. return *((long*)buf);
  58. }
  59. // Reads an unsigned short (16 bits) in little-endian from the buffer
  60. unsigned short GetUShort(const unsigned char *buf)
  61. {
  62. return ( ((unsigned short)(buf[0])) )
  63. |( ((unsigned short)(buf[1])) << 0x08 );
  64. }
  65. // Reads a long (32 bits) in little-endian from the buffer
  66. long GetLong(const unsigned char *buf)
  67. {
  68. return ( ((long)(buf[0])) )
  69. |( ((long)(buf[1])) << 0x08 )
  70. |( ((long)(buf[2])) << 0x10 )
  71. |( ((long)(buf[3])) << 0x18 );
  72. }
  73. // Reads an unsigned long (32 bits) in little-endian from the buffer
  74. unsigned long GetULong(const unsigned char *buf)
  75. {
  76. return ( ((unsigned long)(buf[0])) )
  77. |( ((unsigned long)(buf[1])) << 0x08 )
  78. |( ((unsigned long)(buf[2])) << 0x10 )
  79. |( ((unsigned long)(buf[3])) << 0x18 );
  80. }
  81. // Reads a float (32 bits) from the buffer
  82. float GetFloat(const unsigned char *buf)
  83. {
  84. unsigned long val = GetULong(buf);
  85. return *((float*)&val);
  86. }
  87. // Reads a map from GRF's GAT and RSW files
  88. int read_map(char *name, struct map_data *m)
  89. {
  90. char filename[256];
  91. unsigned char *gat, *rsw;
  92. int water_height;
  93. size_t xy, off, num_cells;
  94. float height[4];
  95. unsigned long type;
  96. // Open map GAT
  97. sprintf(filename,"data\\%s.gat", name);
  98. gat = (unsigned char *)grfio_read(filename);
  99. if (gat == NULL)
  100. return 0;
  101. // Open map RSW
  102. sprintf(filename,"data\\%s.rsw", name);
  103. rsw = (unsigned char *)grfio_read(filename);
  104. // Read water height
  105. if (rsw) {
  106. water_height = (int)GetFloat(rsw+166);
  107. free(rsw);
  108. } else
  109. water_height = NO_WATER;
  110. // Read map size and allocate needed memory
  111. m->xs = (short)GetULong(gat+6);
  112. m->ys = (short)GetULong(gat+10);
  113. num_cells = (size_t)m->xs*m->ys;
  114. m->cells = (unsigned char *)malloc(num_cells);
  115. // Set cell properties
  116. off = 14;
  117. for (xy = 0; xy < num_cells; xy++)
  118. {
  119. // Height of the corners
  120. height[0] = GetFloat( gat + off );
  121. height[1] = GetFloat( gat + off + 4 );
  122. height[2] = GetFloat( gat + off + 8 );
  123. height[3] = GetFloat( gat + off + 12 );
  124. // Type of cell
  125. type = GetULong( gat + off + 16 );
  126. off += 20;
  127. if (water_height != NO_WATER && type == 0 && (height[0] > water_height || height[1] > water_height || height[2] > water_height || height[3] > water_height))
  128. m->cells[xy] = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water)
  129. else
  130. m->cells[xy] = (unsigned char)type;
  131. }
  132. free(gat);
  133. return 1;
  134. }
  135. // Adds a map to the cache
  136. void cache_map(char *name, struct map_data *m)
  137. {
  138. struct map_info info;
  139. unsigned long len;
  140. unsigned char *write_buf;
  141. // Create an output buffer twice as big as the uncompressed map... this way we're sure it fits
  142. len = m->xs*m->ys*2;
  143. write_buf = (unsigned char *)malloc(len);
  144. // Compress the cells and get the compressed length
  145. encode_zip(write_buf, &len, m->cells, m->xs*m->ys);
  146. // Fill the map header
  147. strncpy(info.name, name, MAP_NAME_LENGTH);
  148. info.xs = MakeShortLE(m->xs);
  149. info.ys = MakeShortLE(m->ys);
  150. info.len = MakeLongLE(len);
  151. // Append map header then compressed cells at the end of the file
  152. fseek(map_cache_fp, header.file_size, SEEK_SET);
  153. fwrite(&info, sizeof(struct map_info), 1, map_cache_fp);
  154. fwrite(write_buf, 1, len, map_cache_fp);
  155. header.file_size += sizeof(struct map_info) + len;
  156. header.map_count++;
  157. free(write_buf);
  158. free(m->cells);
  159. return;
  160. }
  161. // Checks whether a map is already is the cache
  162. int find_map(char *name)
  163. {
  164. int i;
  165. struct map_info info;
  166. fseek(map_cache_fp, sizeof(struct main_header), SEEK_SET);
  167. for(i = 0; i < header.map_count; i++) {
  168. fread(&info, sizeof(info), 1, map_cache_fp);
  169. if(strcmp(name, info.name) == 0) // Map found
  170. return 1;
  171. else // Map not found, jump to the beginning of the next map info header
  172. fseek(map_cache_fp, GetLong((unsigned char *)&(info.len)), SEEK_CUR);
  173. }
  174. return 0;
  175. }
  176. // Cuts the extension from a map name
  177. char *remove_extension(char *mapname)
  178. {
  179. char *ptr, *ptr2;
  180. ptr = strchr(mapname, '.');
  181. if (ptr) { //Check and remove extension.
  182. while (ptr[1] && (ptr2 = strchr(ptr+1, '.')))
  183. ptr = ptr2; //Skip to the last dot.
  184. if(stricmp(ptr,".gat") == 0 ||
  185. stricmp(ptr,".afm") == 0 ||
  186. stricmp(ptr,".af2") == 0)
  187. *ptr = '\0'; //Remove extension.
  188. }
  189. return mapname;
  190. }
  191. // Processes command-line arguments
  192. void process_args(int argc, char *argv[])
  193. {
  194. int i;
  195. for(i = 0; i < argc; i++) {
  196. if(strcmp(argv[i], "-grf") == 0) {
  197. if(++i < argc)
  198. strcpy(grf_list_file, argv[i]);
  199. } else if(strcmp(argv[i], "-list") == 0) {
  200. if(++i < argc)
  201. strcpy(map_list_file, argv[i]);
  202. } else if(strcmp(argv[i], "-cache") == 0) {
  203. if(++i < argc)
  204. strcpy(map_cache_file, argv[i]);
  205. } else if(strcmp(argv[i], "-rebuild") == 0)
  206. rebuild = 1;
  207. }
  208. }
  209. int main(int argc, char *argv[])
  210. {
  211. FILE *list;
  212. char line[1024];
  213. struct map_data map;
  214. char name[MAP_NAME_LENGTH_EXT];
  215. // Process the command-line arguments
  216. process_args(argc, argv);
  217. printf("Initializing grfio with %s\n", grf_list_file);
  218. grfio_init(grf_list_file);
  219. // Attempt to open the map cache file and force rebuild if not found
  220. printf("Opening map cache: %s\n", map_cache_file);
  221. if(!rebuild) {
  222. map_cache_fp = fopen(map_cache_file, "rb");
  223. if(map_cache_fp == NULL) {
  224. printf("Existing map cache not found, forcing rebuild mode\n");
  225. rebuild = 1;
  226. } else
  227. fclose(map_cache_fp);
  228. }
  229. if(rebuild)
  230. map_cache_fp = fopen(map_cache_file, "w+b");
  231. else
  232. map_cache_fp = fopen(map_cache_file, "r+b");
  233. if(map_cache_fp == NULL) {
  234. printf("Failure when opening map cache file %s\n", map_cache_file);
  235. exit(1);
  236. }
  237. // Open the map list
  238. printf("Opening map list: %s\n", map_list_file);
  239. list = fopen(map_list_file, "r");
  240. if(list == NULL) {
  241. printf("Failure when opening maps list file %s\n", map_list_file);
  242. exit(2);
  243. }
  244. // Initialize the main header
  245. if(rebuild) {
  246. header.file_size = sizeof(struct main_header);
  247. header.map_count = 0;
  248. } else {
  249. fread(&header, sizeof(struct main_header), 1, map_cache_fp);
  250. header.file_size = GetULong((unsigned char *)&(header.file_size));
  251. header.map_count = GetUShort((unsigned char *)&(header.map_count));
  252. }
  253. // Read and process the map list
  254. while(fgets(line, 1020, list)){
  255. if(line[0] == '/' && line[1] == '/')
  256. continue;
  257. if(sscanf(line, "%15s", name) < 1)
  258. continue;
  259. if(strcmp("map:", name) == 0 && sscanf(line, "%*s %15s", name) < 1)
  260. continue;
  261. name[MAP_NAME_LENGTH_EXT-1] = '\0';
  262. remove_extension(name);
  263. printf("%s", name);
  264. if(find_map(name))
  265. printf(" already in cache!\n");
  266. else if(read_map(name, &map)) {
  267. cache_map(name, &map);
  268. printf(" successfully cached\n");
  269. } else
  270. printf(" not found in GRF!\n");
  271. }
  272. printf("Closing map list: %s\n", map_list_file);
  273. fclose(list);
  274. // Write the main header and close the map cache
  275. printf("Closing map cache: %s\n", map_cache_file);
  276. fseek(map_cache_fp, 0, SEEK_SET);
  277. fwrite(&header, sizeof(struct main_header), 1, map_cache_fp);
  278. fclose(map_cache_fp);
  279. printf("Finalizing grfio\n");
  280. grfio_final();
  281. printf("%d maps now in cache\n", header.map_count);
  282. return 0;
  283. }