1 /*
2 * Convert the given input files into an output file that is expected
3 * by nethack.
4 *
5 * Assumptions:
6 * + Two dimensional byte arrays are in row order and are not padded
7 * between rows (x11_colormap[][]).
8 */
9 #include "hack.h" /* for MAX_GLYPH */
10 #include "tile.h"
11 #include "tile2x11.h" /* x11 output file header structure */
12
13 #define OUTNAME "x11tiles" /* Default output file name */
14 /* #define PRINT_COLORMAP */ /* define to print the colormap */
15
16
17 x11_header header;
18 unsigned char *tile_bytes = NULL;
19 unsigned char *curr_tb = NULL;
20 unsigned char x11_colormap[MAXCOLORMAPSIZE][3];
21
22
23 /* Look up the given pixel and return its colormap index. */
24 static unsigned char
pix_to_colormap(pix)25 pix_to_colormap(pix)
26 pixel pix;
27 {
28 int i;
29
30 for (i = 0; i < header.ncolors; i++) {
31 if (pix.r == x11_colormap[i][CM_RED] &&
32 pix.g == x11_colormap[i][CM_GREEN] &&
33 pix.b == x11_colormap[i][CM_BLUE])
34 break;
35 }
36
37 if (i == header.ncolors) {
38 Fprintf(stderr, "can't find color: [%u,%u,%u]\n", pix.r, pix.g, pix.b);
39 exit(1);
40 }
41 return (unsigned char) (i & 0xFF);
42 }
43
44
45 /* Convert the tiles in the file to our format of bytes. */
46 static unsigned long
convert_tiles(tb_ptr)47 convert_tiles(tb_ptr)
48 unsigned char **tb_ptr; /* pointer to a tile byte pointer */
49 {
50 unsigned char *tb = *tb_ptr;
51 unsigned long count = 0;
52 pixel tile[MAX_TILE_Y][MAX_TILE_X];
53 int x, y;
54
55 while (read_text_tile(tile)) {
56 count++;
57 for (y = 0; y < tile_y; y++)
58 for (x = 0; x < tile_x; x++)
59 *tb++ = pix_to_colormap(tile[y][x]);
60 }
61
62 *tb_ptr = tb; /* update return val */
63 return count;
64 }
65
66
67 /* Merge the current text colormap (ColorMap) with ours (x11_colormap). */
68 static void
merge_text_colormap()69 merge_text_colormap()
70 {
71 int i, j;
72
73 for (i = 0; i < colorsinmap; i++) {
74 for (j = 0; j < header.ncolors; j++)
75 if (x11_colormap[j][CM_RED] == ColorMap[CM_RED][i] &&
76 x11_colormap[j][CM_GREEN] == ColorMap[CM_GREEN][i] &&
77 x11_colormap[j][CM_BLUE] == ColorMap[CM_BLUE][i])
78 break;
79
80 if (j >= MAXCOLORMAPSIZE) {
81 Fprintf(stderr, "colormap overflow\n");
82 exit(1);
83 }
84
85 if (j == header.ncolors) { /* couldn't find it */
86 #ifdef PRINT_COLORMAP
87 printf("color %2d: %3d %3d %3d\n", header.ncolors,
88 ColorMap[CM_RED][i], ColorMap[CM_GREEN][i],
89 ColorMap[CM_BLUE][i]);
90 #endif
91
92 x11_colormap[j][CM_RED] = ColorMap[CM_RED][i];
93 x11_colormap[j][CM_GREEN] = ColorMap[CM_GREEN][i];
94 x11_colormap[j][CM_BLUE] = ColorMap[CM_BLUE][i];
95 header.ncolors++;
96 }
97 }
98 }
99
100
101 /* Open the given file, read & merge the colormap, convert the tiles. */
102 static void
process_file(fname)103 process_file(fname)
104 char *fname;
105 {
106 unsigned long count;
107
108 if (!fopen_text_file(fname, RDTMODE)) {
109 Fprintf(stderr, "can't open file \"%s\"\n", fname);
110 exit(1);
111 }
112
113 if (!tile_bytes) {
114 /*
115 * Delayed until we open the first input file so that
116 * we know the size of the tiles we are processing.
117 */
118 tile_bytes = malloc(tile_x*tile_y*MAX_GLYPH);
119 if (!tile_bytes) {
120 Fprintf(stderr, "Not enough memory.\n");
121 exit(1);
122 }
123 curr_tb = tile_bytes;
124 }
125 merge_text_colormap();
126 count = convert_tiles(&curr_tb);
127 Fprintf(stderr, "%s: %lu tiles\n", fname, count);
128 header.ntiles += count;
129 fclose_text_file();
130 }
131
132
133 #ifdef USE_XPM
134 static int
xpm_write(fp)135 xpm_write(fp)
136 FILE *fp;
137 {
138 int i,j,x,y;
139 char c[3]="?";
140 unsigned char *bytes;
141
142 if (header.ncolors > 4096) {
143 Fprintf(stderr, "Sorry, only configured for up to 4096 colors\n");
144 exit(1);
145 /* All you need to do is add more char per color - below */
146 }
147
148 /* Fill unused entries with "checkerboard" pattern */
149 for(i = TILES_PER_COL * TILES_PER_ROW - header.ntiles; i > 0; i--)
150 for (y = 0; y < tile_y; y++)
151 for (x = 0; x < tile_x; x+=2)
152 {
153 *curr_tb++ = 0;
154 *curr_tb++ = 1;
155 }
156
157 Fprintf(fp, "/* XPM */\n");
158 Fprintf(fp, "static char* nhtiles[] = {\n");
159 Fprintf(fp, "\"%lu %lu %lu %d\",\n",
160 header.tile_width*TILES_PER_ROW,
161 header.tile_height*TILES_PER_COL,
162 header.ncolors,
163 header.ncolors > 64 ? 2 : 1 /* char per color */);
164 for (i = 0; i < header.ncolors; i++) {
165 if (header.ncolors > 64) {
166 /* two chars per color */
167 c[0] = i / 64 + '0';
168 c[1] = i % 64 + '0';
169 }
170 else
171 c[0] = i + '0'; /* just one char per color */
172 Fprintf(fp, "\"%s c #%02x%02x%02x\",\n", c,
173 x11_colormap[i][0],
174 x11_colormap[i][1],
175 x11_colormap[i][2]);
176 }
177
178 for (j = 0; j < TILES_PER_COL; j++)
179 for (y = 0; y < header.tile_height; y++) {
180 bytes=tile_bytes+(j*TILES_PER_ROW*header.tile_height+y)*
181 header.tile_width;
182 Fprintf(fp, "\"");
183 for (i = 0; i < TILES_PER_ROW; i++) {
184 for (x = 0; x < header.tile_width; x++) {
185 if (header.ncolors > 64) {
186 /* two chars per color */
187 c[0] = bytes[x] / 64 + '0';
188 c[1] = bytes[x] % 64 + '0';
189 }
190 else
191 c[0] = bytes[x] + '0'; /* just one char per color */
192 fputs(c, fp);
193 }
194 bytes+=header.tile_height*header.tile_width;
195 }
196 Fprintf(fp, "\",\n");
197 }
198
199 return fprintf(fp, "};\n")>=0;
200 }
201 #endif /* USE_XPM */
202
203 /*
204 * ALI
205 *
206 * Architecture independent tile file so that x11tiles can always be
207 * stored in FILE_AREA_SHARE, thus simplifying the configuration.
208 */
209
210 static boolean
fwrite_tile_header_item(item,fp)211 fwrite_tile_header_item(item, fp)
212 long item;
213 FILE *fp;
214 {
215 putc((item>>24)&0xff,fp);
216 putc((item>>16)&0xff,fp);
217 putc((item>>8)&0xff,fp);
218 putc(item&0xff,fp);
219 return !ferror(fp);
220 }
221
222 static boolean
fwrite_tile_header(header,fp)223 fwrite_tile_header(header, fp)
224 x11_header *header;
225 FILE *fp;
226 {
227 return fwrite_tile_header_item(header->version,fp) &&
228 fwrite_tile_header_item(header->ncolors,fp) &&
229 fwrite_tile_header_item(header->tile_width,fp) &&
230 fwrite_tile_header_item(header->tile_height,fp) &&
231 fwrite_tile_header_item(header->ntiles,fp) &&
232 fwrite_tile_header_item(header->per_row,fp);
233 }
234
235 int
main(argc,argv)236 main(argc, argv)
237 int argc;
238 char **argv;
239 {
240 FILE *fp;
241 int i, argn = 1;
242 char *outname = OUTNAME;
243
244 header.version = 2; /* version 1 had no per_row field */
245 header.ncolors = 0;
246 header.ntiles = 0; /* updated as we read in files */
247 header.per_row = 1;
248
249 while (argn < argc) {
250 if (argn + 1 < argc && !strcmp(argv[argn], "-o")) {
251 outname = argv[argn + 1];
252 argn += 2;
253 }
254 else
255 break;
256 }
257
258 if (argn == argc) {
259 Fprintf(stderr, "usage: %s [-o out_file] txt_file1 [txt_file2 ...]\n",
260 argv[0]);
261 exit(1);
262 }
263
264 fp = fopen(outname, "w");
265 if (!fp) {
266 perror(outname);
267 exit(1);
268 }
269
270 for (i = argn; i < argc; i++)
271 process_file(argv[i]);
272 Fprintf(stderr, "Total tiles: %ld\n", header.ntiles);
273
274 header.tile_width = tile_x;
275 header.tile_height = tile_y;
276
277 #ifdef USE_XPM
278 if (xpm_write(fp) == 0) {
279 Fprintf(stderr, "can't write XPM file\n");
280 exit(1);
281 }
282 #else
283 if (fwrite_tile_header(&header, fp) == 0) {
284 Fprintf(stderr, "can't write output header\n");
285 exit(1);
286 }
287
288 if (fwrite((char *)x11_colormap, 1, header.ncolors*3, fp) == 0) {
289 Fprintf(stderr, "can't write output colormap\n");
290 exit(1);
291 }
292
293 if (fwrite((char *)tile_bytes, 1,
294 (int) header.ntiles*header.tile_width*header.tile_height, fp) == 0) {
295
296 Fprintf(stderr, "can't write tile bytes\n");
297 exit(1);
298 }
299 #endif
300
301 fclose(fp);
302 free(tile_bytes);
303 return 0;
304 }
305