1 | /* SCCS Id: @(#)tiletext.c 3.3 1999/10/24 */
2 | /* NetHack may be freely redistributed. See license for details. */
3 |
4 | #include "config.h"
5 | #include "tile.h"
6 |
7 | pixval ColorMap[3][MAXCOLORMAPSIZE];
8 | int colorsinmap;
9 | pixval MainColorMap[3][MAXCOLORMAPSIZE];
10 | int colorsinmainmap;
11 |
12 | static short color_index[MAXCOLORMAPSIZE];
13 | static int num_colors;
14 | static char charcolors[MAXCOLORMAPSIZE];
15 |
16 | static int placeholder_init = 0;
17 | static pixel placeholder[TILE_Y][TILE_X];
18 | static FILE *tile_file;
19 | static int tile_set, tile_set_indx;
20 | #if (TILE_X==8)
21 | static const char *text_sets[] = { "monthin.txt", "objthin.txt", "oththin.txt" };
22 | #else
23 | static const char *text_sets[] = { "monsters.txt", "objects.txt", "other.txt" };
24 | #endif
25 |
26 | extern const char *FDECL(tilename, (int, int));
27 | static void FDECL(read_text_colormap, (FILE *));
28 | static boolean FDECL(write_text_colormap, (FILE *));
29 | static boolean FDECL(read_txttile, (FILE *, pixel(*)[TILE_X]));
30 | static void FDECL(write_txttile, (FILE *, pixel(*)[TILE_X]));
31 |
32 | /* Ugh. DICE doesn't like %[A-Z], so we have to spell it out... */
33 | #define FORMAT_STRING \
34 | "%[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789] = (%d, %d, %d) "
35 |
36 | static void
37 | read_text_colormap(txtfile)
38 | FILE *txtfile;
39 | {
40 | int i, r, g, b;
41 | char c[2];
42 |
43 | for (i = 0; i < MAXCOLORMAPSIZE; i++)
44 | color_index[i] = -1;
45 |
46 | num_colors = 0;
47 | while (fscanf(txtfile, FORMAT_STRING, c, &r, &g, &b) == 4) {
48 | color_index[(int) c[0]] = num_colors;
49 | ColorMap[CM_RED][num_colors] = r;
50 | ColorMap[CM_GREEN][num_colors] = g;
51 | ColorMap[CM_BLUE][num_colors] = b;
52 | num_colors++;
53 | }
54 | colorsinmap = num_colors;
55 | }
56 |
57 | #undef FORMAT_STRING
58 |
59 | static boolean
60 | write_text_colormap(txtfile)
61 | FILE *txtfile;
62 | {
63 | int i;
64 | char c;
65 |
66 | num_colors = colorsinmainmap;
67 | if (num_colors > 62) {
68 | Fprintf(stderr, "too many colors (%d)\n", num_colors);
69 | return FALSE;
70 | }
71 | for (i = 0; i < num_colors; i++) {
72 | if (i < 26) c = 'A' + i;
73 | else if (i < 52) c = 'a' + i - 26;
74 | else c = '0' + i - 52;
75 |
76 | charcolors[i] = c;
77 | Fprintf(txtfile, "%c = (%d, %d, %d)\n", c,
78 | (int)MainColorMap[CM_RED][i],
79 | (int)MainColorMap[CM_GREEN][i],
80 | (int)MainColorMap[CM_BLUE][i]);
81 | }
82 | return TRUE;
83 | }
84 |
85 | static boolean
86 | read_txttile(txtfile, pixels)
87 | FILE *txtfile;
88 | pixel (*pixels)[TILE_X];
89 | {
90 | int ph, i, j, k;
91 | char buf[BUFSZ], ttype[BUFSZ];
92 | const char *p;
93 | char c[2];
94 |
95 | if (fscanf(txtfile, "# %s %d (%[^)])", ttype, &i, buf) <= 0)
96 | return FALSE;
97 |
98 | ph = strcmp(ttype, "placeholder") == 0;
99 |
100 | if (!ph && strcmp(ttype,"tile") != 0)
101 | Fprintf(stderr,
102 | "Keyword \"%s\" unexpected for entry %d\n",
103 | ttype, i);
104 |
105 | if (tile_set != 0) {
106 | /* check tile name, but not relative number, which will
107 | * change when tiles are added
108 | */
109 | p = tilename(tile_set, tile_set_indx);
110 | if (p && strcmp(p, buf)) {
111 | Fprintf(stderr, "warning: for tile %d (numbered %d) of %s,\n",
112 | tile_set_indx, i, text_sets[tile_set-1]);
113 | Fprintf(stderr, "\tfound '%s' while expecting '%s'\n",
114 | buf, p);
115 | }
116 | }
117 | tile_set_indx++;
118 |
119 | /* look for non-whitespace at each stage */
120 | if (fscanf(txtfile, "%1s", c) < 0) {
121 | Fprintf(stderr, "unexpected EOF\n");
122 | return FALSE;
123 | }
124 | if (c[0] != '{') {
125 | Fprintf(stderr, "didn't find expected '{'\n");
126 | return FALSE;
127 | }
128 | for (j = 0; j < TILE_Y; j++) {
129 | for (i = 0; i < TILE_X; i++) {
130 | if (fscanf(txtfile, "%1s", c) < 0) {
131 | Fprintf(stderr, "unexpected EOF\n");
132 | return FALSE;
133 | }
134 | k = color_index[(int) c[0]];
135 | if (k == -1)
136 | Fprintf(stderr,
137 | "color %c not in colormap!\n", c[0]);
138 | else {
139 | pixels[j][i].r = ColorMap[CM_RED][k];
140 | pixels[j][i].g = ColorMap[CM_GREEN][k];
141 | pixels[j][i].b = ColorMap[CM_BLUE][k];
142 | }
143 | }
144 | }
145 | if ( ph ) {
146 | /* remember it for later */
147 | memcpy( placeholder, pixels, sizeof(placeholder) );
148 | }
149 | if (fscanf(txtfile, "%1s ", c) < 0) {
150 | Fprintf(stderr, "unexpected EOF\n");
151 | return FALSE;
152 | }
153 | if (c[0] != '}') {
154 | Fprintf(stderr, "didn't find expected '}'\n");
155 | return FALSE;
156 | }
157 | #ifdef _DCC
158 | /* DICE again... it doesn't seem to eat whitespace after the } like
159 | * it should, so we have to do so manually.
160 | */
161 | while ((*c = fgetc(txtfile)) != EOF && isspace(*c))
162 | ;
163 | ungetc(*c, txtfile);
164 | #endif
165 | return TRUE;
166 | }
167 |
168 | static void
169 | write_txttile(txtfile, pixels)
170 | FILE *txtfile;
171 | pixel (*pixels)[TILE_X];
172 | {
173 | const char *p;
174 | const char *type;
175 | int i, j, k;
176 |
177 | if ( memcmp(placeholder, pixels, sizeof(placeholder)) == 0 )
178 | type = "placeholder";
179 | else
180 | type = "tile";
181 |
182 | if (tile_set == 0)
183 | Fprintf(txtfile, "# %s %d (unknown)\n", type, tile_set_indx);
184 | else {
185 | p = tilename(tile_set, tile_set_indx);
186 | if (p)
187 | Fprintf(txtfile, "# %s %d (%s)\n", type, tile_set_indx, p);
188 | else
189 | Fprintf(txtfile, "# %s %d (null)\n", type, tile_set_indx);
190 | }
191 | tile_set_indx++;
192 |
193 | Fprintf(txtfile, "{\n");
194 | for (j = 0; j < TILE_Y; j++) {
195 | Fprintf(txtfile, " ");
196 | for (i = 0; i < TILE_X; i++) {
197 | for (k = 0; k < num_colors; k++) {
198 | if (ColorMap[CM_RED][k] == pixels[j][i].r &&
199 | ColorMap[CM_GREEN][k] == pixels[j][i].g &&
200 | ColorMap[CM_BLUE][k] == pixels[j][i].b)
201 | break;
202 | }
203 | if (k >= num_colors)
204 | Fprintf(stderr, "color not in colormap!\n");
205 | (void) fputc(charcolors[k], txtfile);
206 | }
207 | Fprintf(txtfile, "\n");
208 | }
209 | Fprintf(txtfile, "}\n");
210 | }
211 |
212 | /* initialize main colormap from globally accessed ColorMap */
213 | void
214 | init_colormap()
215 | {
216 | int i;
217 |
218 | colorsinmainmap = colorsinmap;
219 | for (i = 0; i < colorsinmap; i++) {
220 | MainColorMap[CM_RED][i] = ColorMap[CM_RED][i];
221 | MainColorMap[CM_GREEN][i] = ColorMap[CM_GREEN][i];
222 | MainColorMap[CM_BLUE][i] = ColorMap[CM_BLUE][i];
223 | }
224 | }
225 |
226 | /* merge new colors from ColorMap into MainColorMap */
227 | void
228 | merge_colormap()
229 | {
230 | int i, j;
231 |
232 | for (i = 0; i < colorsinmap; i++) {
233 | for (j = 0; j < colorsinmainmap; j++) {
234 | if (MainColorMap[CM_RED][j] == ColorMap[CM_RED][i] &&
235 | MainColorMap[CM_GREEN][j] == ColorMap[CM_GREEN][i] &&
236 | MainColorMap[CM_BLUE][j] == ColorMap[CM_BLUE][i])
237 | break;
238 | }
239 | if (j >= colorsinmainmap) { /* new color */
240 | if (colorsinmainmap >= MAXCOLORMAPSIZE) {
241 | Fprintf(stderr,
242 | "Too many colors to merge -- excess ignored.\n");
243 | }
244 | j = colorsinmainmap;
245 | MainColorMap[CM_RED][j] = ColorMap[CM_RED][i];
246 | MainColorMap[CM_GREEN][j] = ColorMap[CM_GREEN][i];
247 | MainColorMap[CM_BLUE][j] = ColorMap[CM_BLUE][i];
248 | colorsinmainmap++;
249 | }
250 | }
251 | }
252 |
253 | boolean
254 | fopen_text_file(filename, type)
255 | const char *filename;
256 | const char *type;
257 | {
258 | const char *p;
259 | int i;
260 |
261 | if (tile_file != (FILE *)0) {
262 | Fprintf(stderr, "can only open one text file at at time\n");
263 | return FALSE;
264 | }
265 |
266 | tile_file = fopen(filename, type);
267 | if (tile_file == (FILE *)0) {
268 | Fprintf(stderr, "cannot open text file %s\n", filename);
269 | return FALSE;
270 | }
271 |
272 | p = rindex(filename, '/');
273 | if (p) p++;
274 | else p = filename;
275 |
276 | tile_set = 0;
277 | for (i = 0; i < SIZE(text_sets); i++) {
278 | if (!strcmp(p, text_sets[i]))
279 | tile_set = i+1;
280 | }
281 | tile_set_indx = 0;
282 |
283 | if (!strcmp(type, RDTMODE)) {
284 | /* Fill placeholder with noise */
285 | if ( !placeholder_init ) {
286 | placeholder_init++;
287 | for ( i=0; i<sizeof(placeholder); i++ )
288 | ((char*)placeholder)[i]=i%256;
289 | }
290 |
291 | read_text_colormap(tile_file);
292 | if (!colorsinmainmap)
293 | init_colormap();
294 | else
295 | merge_colormap();
296 | return TRUE;
297 | } else if (!strcmp(type, WRTMODE)) {
298 | if (!colorsinmainmap) {
299 | Fprintf(stderr, "no colormap set yet\n");
300 | return FALSE;
301 | }
302 | return(write_text_colormap(tile_file));
303 | } else {
304 | Fprintf(stderr, "bad mode (%s) for fopen_text_file\n", type);
305 | return FALSE;
306 | }
307 | }
308 |
309 | boolean
310 | read_text_tile(pixels)
311 | pixel (*pixels)[TILE_X];
312 | {
313 | return(read_txttile(tile_file, pixels));
314 | }
315 |
316 | boolean
317 | write_text_tile(pixels)
318 | pixel (*pixels)[TILE_X];
319 | {
320 | write_txttile(tile_file, pixels);
321 | return TRUE;
322 | }
323 |
324 | int
325 | fclose_text_file()
326 | {
327 | int ret;
328 |
329 | ret = fclose(tile_file);
330 | tile_file = (FILE *)0;
331 | return ret;
332 | }