phantasia

Phantasia - 2D SDL3 RPG prototype.
git clone git://git.beep.wimdupont.com/phantasia.git
Log | Files | Refs | README | LICENSE

mapc.c (2853B)


      1 #include <stdint.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 
      6 enum {
      7 	PH_MAP_MAGIC = 0x50484d50,
      8 	PH_MAP_VERSION = 1,
      9 	PH_AREA_NAME_MAX = 64,
     10 	PH_MAP_LINE_MAX = 512,
     11 };
     12 
     13 typedef struct {
     14 	uint32_t magic;
     15 	uint32_t version;
     16 	uint32_t width;
     17 	uint32_t height;
     18 	char name[PH_AREA_NAME_MAX];
     19 } PhMapHeader;
     20 
     21 static void
     22 ph_strip_newline(char *line)
     23 {
     24 	size_t len = strlen(line);
     25 
     26 	while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
     27 		line[--len] = '\0';
     28 	}
     29 }
     30 
     31 static int
     32 ph_compile_map(const char *src_path, const char *dst_path)
     33 {
     34 	FILE *src;
     35 	FILE *dst;
     36 	PhMapHeader header = {
     37 		.magic = PH_MAP_MAGIC,
     38 		.version = PH_MAP_VERSION,
     39 	};
     40 	char line[PH_MAP_LINE_MAX];
     41 	unsigned char *tiles = NULL;
     42 	size_t tile_cap = 0;
     43 	size_t tile_count = 0;
     44 	int in_tiles = 0;
     45 
     46 	src = fopen(src_path, "r");
     47 	if (!src) {
     48 		perror(src_path);
     49 		return 1;
     50 	}
     51 
     52 	while (fgets(line, sizeof(line), src)) {
     53 		size_t len;
     54 
     55 		ph_strip_newline(line);
     56 		if (!in_tiles && strncmp(line, "name:", 5) == 0) {
     57 			const char *name = line + 5;
     58 			size_t name_len;
     59 
     60 			while (*name == ' ' || *name == '\t') {
     61 				++name;
     62 			}
     63 			name_len = strlen(name);
     64 			if (name_len >= sizeof(header.name)) {
     65 				fprintf(stderr, "%s: map name too long\n", src_path);
     66 				free(tiles);
     67 				fclose(src);
     68 				return 1;
     69 			}
     70 			memcpy(header.name, name, name_len + 1);
     71 			continue;
     72 		}
     73 		if (!in_tiles && line[0] == '\0') {
     74 			in_tiles = 1;
     75 			continue;
     76 		}
     77 		if (line[0] == '\0') {
     78 			continue;
     79 		}
     80 
     81 		len = strlen(line);
     82 		if (header.width == 0) {
     83 			header.width = (uint32_t)len;
     84 		} else if (len != header.width) {
     85 			fprintf(stderr, "%s: inconsistent row width: got %zu, expected %u\n",
     86 				src_path, len, header.width);
     87 			free(tiles);
     88 			fclose(src);
     89 			return 1;
     90 		}
     91 
     92 		if (tile_count + len > tile_cap) {
     93 			size_t new_cap = tile_cap ? tile_cap * 2 : 256;
     94 			unsigned char *new_tiles;
     95 
     96 			while (new_cap < tile_count + len) {
     97 				new_cap *= 2;
     98 			}
     99 			new_tiles = realloc(tiles, new_cap);
    100 			if (!new_tiles) {
    101 				free(tiles);
    102 				fclose(src);
    103 				return 1;
    104 			}
    105 			tiles = new_tiles;
    106 			tile_cap = new_cap;
    107 		}
    108 
    109 		memcpy(tiles + tile_count, line, len);
    110 		tile_count += len;
    111 		++header.height;
    112 	}
    113 	fclose(src);
    114 
    115 	if (header.width == 0 || header.height == 0 || header.name[0] == '\0') {
    116 		fprintf(stderr, "%s: missing name or tile data\n", src_path);
    117 		free(tiles);
    118 		return 1;
    119 	}
    120 
    121 	dst = fopen(dst_path, "wb");
    122 	if (!dst) {
    123 		perror(dst_path);
    124 		free(tiles);
    125 		return 1;
    126 	}
    127 
    128 	if (fwrite(&header, sizeof(header), 1, dst) != 1 ||
    129 			fwrite(tiles, 1, tile_count, dst) != tile_count) {
    130 		perror(dst_path);
    131 		free(tiles);
    132 		fclose(dst);
    133 		return 1;
    134 	}
    135 
    136 	free(tiles);
    137 	fclose(dst);
    138 	return 0;
    139 }
    140 
    141 int
    142 main(int argc, char **argv)
    143 {
    144 	if (argc != 3) {
    145 		fprintf(stderr, "usage: %s <map.txt> <map.phmap>\n", argv[0]);
    146 		return 1;
    147 	}
    148 	return ph_compile_map(argv[1], argv[2]);
    149 }