1 /* $NHDT-Date: 1546081295 2018/12/29 11:01:35 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.12 $ */
2 /*      Copyright (c) 2017 by Pasi Kallinen                       */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 /*
6  * Convert the given input files into an output file that is expected
7  * by nethack.
8  *
9  * Assumptions:
10  * 	+ Two dimensional byte arrays are in row order and are not padded
11  *	  between rows (x11_colormap[][]).
12  */
13 #include "hack.h" /* for MAX_GLYPH */
14 #include "tile.h"
15 #include "tile2x11.h" /* x11 output file header structure */
16 
17 #define OUTNAME "x11tiles"   /* output file name */
18 /* #define PRINT_COLORMAP */ /* define to print the colormap */
19 
20 x11_header header;
21 unsigned char tile_bytes[TILE_X * TILE_Y * (MAX_GLYPH + TILES_PER_ROW)];
22 unsigned char *curr_tb = tile_bytes;
23 unsigned char x11_colormap[MAXCOLORMAPSIZE][3];
24 
25 /* Look up the given pixel and return its colormap index. */
26 static unsigned char
pix_to_colormap(pix)27 pix_to_colormap(pix)
28 pixel pix;
29 {
30     unsigned long i;
31 
32     for (i = 0; i < header.ncolors; i++) {
33         if (pix.r == ColorMap[CM_RED][i]
34             && pix.g == ColorMap[CM_GREEN][i]
35             && pix.b == ColorMap[CM_BLUE][i])
36             break;
37     }
38 
39     if (i == header.ncolors) {
40         Fprintf(stderr, "can't find color: [%u,%u,%u]\n", pix.r, pix.g,
41                 pix.b);
42         exit(1);
43     }
44     return (unsigned char) (i & 0xFF);
45 }
46 
47 /* Convert the tiles in the file to our format of bytes. */
48 static unsigned long
convert_tiles(tb_ptr,total)49 convert_tiles(tb_ptr, total)
50 unsigned char **tb_ptr; /* pointer to a tile byte pointer */
51 unsigned long total;    /* total tiles so far */
52 {
53     unsigned char *tb = *tb_ptr;
54     unsigned long count = 0;
55     pixel tile[TILE_Y][TILE_X];
56     int x, y;
57 
58     while (read_text_tile(tile)) {
59         count++;
60         total++;
61         for (y = 0; y < TILE_Y; y++) {
62             for (x = 0; x < TILE_X; x++)
63                 tb[x] = pix_to_colormap(tile[y][x]);
64             tb += TILE_X * header.per_row;
65         }
66 
67         /* repoint at the upper-left corner of the next tile */
68         *tb_ptr += TILE_X;
69         if (header.per_row == 1 || (total % header.per_row) == 0)
70             *tb_ptr += TILE_X * (TILE_Y - 1) * header.per_row;
71         tb = *tb_ptr;
72     }
73 
74     return count;
75 }
76 
77 /* Merge the current text colormap (ColorMap) with ours (x11_colormap). */
78 static void
merge_text_colormap()79 merge_text_colormap()
80 {
81     unsigned i, j;
82 
83     for (i = 0; i < (unsigned) colorsinmap; i++) {
84         for (j = 0; j < header.ncolors; j++)
85             if (x11_colormap[j][CM_RED] == ColorMap[CM_RED][i]
86                 && x11_colormap[j][CM_GREEN] == ColorMap[CM_GREEN][i]
87                 && x11_colormap[j][CM_BLUE] == ColorMap[CM_BLUE][i])
88                 break;
89 
90         if (j >= MAXCOLORMAPSIZE) {
91             Fprintf(stderr, "colormap overflow\n");
92             exit(1);
93         }
94 
95         if (j == header.ncolors) { /* couldn't find it */
96 #ifdef PRINT_COLORMAP
97             Fprintf(stdout, "color %2d: %3d %3d %3d\n", header.ncolors,
98                    ColorMap[CM_RED][i], ColorMap[CM_GREEN][i],
99                    ColorMap[CM_BLUE][i]);
100 #endif
101 
102             x11_colormap[j][CM_RED] = ColorMap[CM_RED][i];
103             x11_colormap[j][CM_GREEN] = ColorMap[CM_GREEN][i];
104             x11_colormap[j][CM_BLUE] = ColorMap[CM_BLUE][i];
105             header.ncolors++;
106         }
107     }
108 }
109 
110 /* Open the given file, read & merge the colormap, convert the tiles. */
111 static void
process_file(fname)112 process_file(fname)
113 char *fname;
114 {
115     unsigned long count;
116 
117     if (!fopen_text_file(fname, RDTMODE)) {
118         Fprintf(stderr, "can't open file \"%s\"\n", fname);
119         exit(1);
120     }
121     merge_text_colormap();
122     count = convert_tiles(&curr_tb, header.ntiles);
123     Fprintf(stdout, "%s: %lu tiles\n", fname, count);
124     header.ntiles += count;
125     fclose_text_file();
126 }
127 
128 #ifdef USE_XPM
129 static int
xpm_write(fp)130 xpm_write(fp)
131 FILE *fp;
132 {
133     unsigned long i, j;
134     unsigned n;
135 
136     if (header.ncolors > 64) {
137         Fprintf(stderr, "Sorry, only configured for up to 64 colors\n");
138         exit(1);
139         /* All you need to do is add more char per color - below */
140     }
141 
142     Fprintf(fp, "/* XPM */\n");
143     Fprintf(fp, "static char* nhtiles[] = {\n");
144     Fprintf(fp, "\"%lu %lu %lu %d\",\n", header.tile_width * header.per_row,
145             (header.tile_height * header.ntiles) / header.per_row,
146             header.ncolors, 1 /* char per color */);
147     for (i = 0; i < header.ncolors; i++)
148         Fprintf(fp, "\"%c  c #%02x%02x%02x\",\n",
149                 (char) (i + '0'), /* just one char per color */
150                 x11_colormap[i][0], x11_colormap[i][1], x11_colormap[i][2]);
151 
152     n = 0;
153     for (i = 0; i < (header.tile_height * header.ntiles) / header.per_row;
154          i++) {
155         Fprintf(fp, "\"");
156         for (j = 0; j < header.tile_width * header.per_row; j++) {
157             /* just one char per color */
158             fputc(tile_bytes[n++] + '0', fp);
159         }
160 
161         Fprintf(fp, "\",\n");
162     }
163 
164     return fprintf(fp, "};\n") >= 0;
165 }
166 #endif /* USE_XPM */
167 
168 int
main(argc,argv)169 main(argc, argv)
170 int argc;
171 char **argv;
172 {
173     FILE *fp;
174     int i;
175 
176     header.version = 2; /* version 1 had no per_row field */
177     header.ncolors = 0;
178     header.tile_width = TILE_X;
179     header.tile_height = TILE_Y;
180     header.ntiles = 0; /* updated as we read in files */
181     header.per_row = TILES_PER_ROW;
182 
183     if (argc == 1) {
184         Fprintf(stderr,
185                 "usage: %s txt_file1 [txt_file2 ...] [-grayscale txt_fileN]\n",
186                 argv[0]);
187         exit(1);
188     }
189 
190     fp = fopen(OUTNAME, "w");
191     if (!fp) {
192         Fprintf(stderr, "can't open output file\n");
193         exit(1);
194     }
195 
196     /* don't leave garbage at end of partial row */
197     (void) memset((genericptr_t) tile_bytes, 0, sizeof(tile_bytes));
198 
199     for (i = 1; i < argc; i++) {
200         if (!strncmp(argv[i], "-grayscale", 10)) {
201             set_grayscale(TRUE);
202             if (i < (argc - 1)) i++;
203         } else {
204             set_grayscale(FALSE);
205         }
206         process_file(argv[i]);
207     }
208     Fprintf(stdout, "Total tiles: %ld\n", header.ntiles);
209 
210     /* round size up to the end of the row */
211     if ((header.ntiles % header.per_row) != 0) {
212         header.ntiles += header.per_row - (header.ntiles % header.per_row);
213     }
214 
215 #ifdef USE_XPM
216     if (xpm_write(fp) == 0) {
217         Fprintf(stderr, "can't write XPM file\n");
218         exit(1);
219     }
220 #else
221     if (fwrite((char *) &header, sizeof(x11_header), 1, fp) == 0) {
222         Fprintf(stderr, "can't open output header\n");
223         exit(1);
224     }
225 
226     if (fwrite((char *) x11_colormap, 1, header.ncolors * 3, fp) == 0) {
227         Fprintf(stderr, "can't write output colormap\n");
228         exit(1);
229     }
230 
231     if (fwrite((char *) tile_bytes, 1,
232                (int) header.ntiles * header.tile_width * header.tile_height,
233                fp) == 0) {
234         Fprintf(stderr, "can't write tile bytes\n");
235         exit(1);
236     }
237 #endif
238 
239     fclose(fp);
240     return 0;
241 }
242