1 /*	SCCS Id: @(#)tile2bmp.c	3.4	2002/03/14	*/
2 /*   Copyright (c) NetHack PC Development Team 1995                 */
3 /*   NetHack may be freely redistributed.  See license for details. */
4 
5 /*
6  * Edit History:
7  *
8  *	Initial Creation			M.Allison   1994/01/11
9  *
10  */
11 
12 /* #pragma warning(4103:disable) */
13 
14 #include "hack.h"
15 #include "tile.h"
16 #ifndef __GNUC__
17 #include "win32api.h"
18 #endif
19 
20 /* #define COLORS_IN_USE MAXCOLORMAPSIZE       /* 256 colors */
21 #if (TILE_X==32)
22 #define COLORS_IN_USE 256
23 #else
24 #define COLORS_IN_USE 16                       /* 16 colors */
25 #endif
26 
27 #define BITCOUNT 8
28 
29 extern char *FDECL(tilename, (int, int));
30 
31 #if BITCOUNT==4
32 #define MAX_X 320		/* 2 per byte, 4 bits per pixel */
33 #define MAX_Y 480
34 #else
35 # if (TILE_X==32)
36 #define MAX_X (32 * 40)
37 #define MAX_Y 960
38 # else
39 #define MAX_X 640		/* 1 per byte, 8 bits per pixel */
40 #define MAX_Y 480
41 # endif
42 #endif
43 
44 /* GCC fix by Paolo Bonzini 1999/03/28 */
45 #ifdef __GNUC__
46 #define PACK		__attribute__((packed))
47 #else
48 #define PACK
49 #endif
50 
leshort(short x)51 static short leshort(short x)
52 {
53 #ifdef __BIG_ENDIAN__
54     return ((x&0xff)<<8)|((x>>8)&0xff);
55 #else
56     return x;
57 #endif
58 }
59 
60 
lelong(long x)61 static long lelong(long x)
62 {
63 #ifdef __BIG_ENDIAN__
64     return ((x&0xff)<<24)|((x&0xff00)<<8)|((x>>8)&0xff00)|((x>>24)&0xff);
65 #else
66     return x;
67 #endif
68 }
69 
70 #ifdef __GNUC__
71 typedef struct tagBMIH {
72         unsigned long   biSize;
73         long       	biWidth;
74         long       	biHeight;
75         unsigned short  biPlanes;
76         unsigned short  biBitCount;
77         unsigned long   biCompression;
78         unsigned long   biSizeImage;
79         long       	biXPelsPerMeter;
80         long       	biYPelsPerMeter;
81         unsigned long   biClrUsed;
82         unsigned long   biClrImportant;
83 } PACK BITMAPINFOHEADER;
84 
85 typedef struct tagBMFH {
86         unsigned short bfType;
87         unsigned long  bfSize;
88         unsigned short bfReserved1;
89         unsigned short bfReserved2;
90         unsigned long  bfOffBits;
91 } PACK BITMAPFILEHEADER;
92 
93 typedef struct tagRGBQ {
94         unsigned char    rgbBlue;
95         unsigned char    rgbGreen;
96         unsigned char    rgbRed;
97         unsigned char    rgbReserved;
98 } PACK RGBQUAD;
99 #define UINT unsigned int
100 #define DWORD unsigned long
101 #define LONG long
102 #define WORD unsigned short
103 #define BI_RGB        0L
104 #define BI_RLE8       1L
105 #define BI_RLE4       2L
106 #define BI_BITFIELDS  3L
107 #endif /* __GNUC__ */
108 
109 #pragma pack(1)
110 struct tagBMP{
111     BITMAPFILEHEADER bmfh;
112     BITMAPINFOHEADER bmih;
113 #if BITCOUNT==4
114 #define RGBQUAD_COUNT 16
115     RGBQUAD          bmaColors[RGBQUAD_COUNT];
116 #else
117 #if (TILE_X==32)
118 #define RGBQUAD_COUNT 256
119 #else
120 #define RGBQUAD_COUNT 16
121 #endif
122     RGBQUAD          bmaColors[RGBQUAD_COUNT];
123 #endif
124 #if (COLORS_IN_USE==16)
125     uchar            packtile[MAX_Y][MAX_X];
126 #else
127     uchar            packtile[MAX_Y][MAX_X];
128 /*    uchar            packtile[TILE_Y][TILE_X]; */
129 #endif
130 } PACK bmp;
131 #pragma pack()
132 
133 #define BMPFILESIZE (sizeof(struct tagBMP))
134 
135 FILE *tibfile2;
136 
137 pixel tilepixels[TILE_Y][TILE_X];
138 
139 static void FDECL(build_bmfh,(BITMAPFILEHEADER *));
140 static void FDECL(build_bmih,(BITMAPINFOHEADER *));
141 static void FDECL(build_bmptile,(pixel (*)[TILE_X]));
142 
143 char *tilefiles[] = {
144 #if (TILE_X == 32)
145 		"../win/share/mon32.txt",
146 		"../win/share/obj32.txt",
147 		"../win/share/oth32.txt"
148 #else
149 		"../win/share/monsters.txt",
150 		"../win/share/objects.txt",
151 		"../win/share/other.txt"
152 #endif
153 };
154 
155 int num_colors = 0;
156 int tilecount;
157 int max_tiles_in_row = 40;
158 int tiles_in_row;
159 int filenum;
160 int initflag;
161 int yoffset,xoffset;
162 char bmpname[128];
163 FILE *fp;
164 
165 int
main(argc,argv)166 main(argc, argv)
167 int argc;
168 char *argv[];
169 {
170 	int i, j;
171 
172 	if (argc != 2) {
173 		Fprintf(stderr, "usage: %s outfile.bmp\n", argv[0]);
174 		exit(EXIT_FAILURE);
175 	} else
176 		strcpy(bmpname, argv[1]);
177 
178 #ifdef OBSOLETE
179 	bmpfile2 = fopen(NETHACK_PACKED_TILEFILE, WRBMODE);
180 	if (bmpfile2 == (FILE *)0) {
181 		Fprintf(stderr, "Unable to open output file %s\n",
182 				NETHACK_PACKED_TILEFILE);
183 		exit(EXIT_FAILURE);
184 	}
185 #endif
186 
187 	tilecount = 0;
188 	xoffset = yoffset = 0;
189 	initflag = 0;
190 	filenum = 0;
191 	fp = fopen(bmpname,"wb");
192 	if (!fp) {
193 	    printf("Error creating tile file %s, aborting.\n",bmpname);
194 	    exit(1);
195 	}
196 	while (filenum < (sizeof(tilefiles) / sizeof(char *))) {
197 		if (!fopen_text_file(tilefiles[filenum], RDTMODE)) {
198 			Fprintf(stderr,
199 				"usage: tile2bmp (from the util directory)\n");
200 			exit(EXIT_FAILURE);
201 		}
202 		num_colors = colorsinmap;
203 		if (num_colors > 62) {
204 			Fprintf(stderr, "too many colors (%d)\n", num_colors);
205 			exit(EXIT_FAILURE);
206 		}
207 		if (!initflag) {
208 		    build_bmfh(&bmp.bmfh);
209 		    build_bmih(&bmp.bmih);
210 		    for (i = 0; i < MAX_Y; ++i)
211 		    	for (j = 0; j < MAX_X; ++j)
212 		    		bmp.packtile[i][j] = (uchar)0;
213 		    for (i = 0; i < num_colors; i++) {
214 			    bmp.bmaColors[i].rgbRed = ColorMap[CM_RED][i];
215 			    bmp.bmaColors[i].rgbGreen = ColorMap[CM_GREEN][i];
216 			    bmp.bmaColors[i].rgbBlue = ColorMap[CM_BLUE][i];
217 			    bmp.bmaColors[i].rgbReserved = 0;
218 		    }
219 		    initflag = 1;
220 		}
221 /*		printf("Colormap initialized\n"); */
222 		while (read_text_tile(tilepixels)) {
223 			build_bmptile(tilepixels);
224 			tilecount++;
225 #if BITCOUNT==4
226 			xoffset += (TILE_X / 2);
227 #else
228 			xoffset += TILE_X;
229 #endif
230 			if (xoffset >= MAX_X) {
231 				yoffset += TILE_Y;
232 				xoffset = 0;
233 			}
234 		}
235 		(void) fclose_text_file();
236 		++filenum;
237 	}
238 	fwrite(&bmp, sizeof(bmp), 1, fp);
239 	fclose(fp);
240 	Fprintf(stderr, "Total of %d tiles written to %s.\n",
241 		tilecount, bmpname);
242 
243 	exit(EXIT_SUCCESS);
244 	/*NOTREACHED*/
245 	return 0;
246 }
247 
248 
249 static void
build_bmfh(pbmfh)250 build_bmfh(pbmfh)
251 BITMAPFILEHEADER *pbmfh;
252 {
253 	pbmfh->bfType = leshort(0x4D42);
254 	pbmfh->bfSize = lelong(BMPFILESIZE);
255 	pbmfh->bfReserved1 = (UINT)0;
256 	pbmfh->bfReserved2 = (UINT)0;
257 	pbmfh->bfOffBits = lelong(sizeof(bmp.bmfh) + sizeof(bmp.bmih) +
258 			   (RGBQUAD_COUNT * sizeof(RGBQUAD)));
259 }
260 
261 static void
build_bmih(pbmih)262 build_bmih(pbmih)
263 BITMAPINFOHEADER *pbmih;
264 {
265 	WORD cClrBits;
266 	int w,h;
267 	pbmih->biSize = lelong(sizeof(bmp.bmih));
268 #if BITCOUNT==4
269 	pbmih->biWidth = lelong(w = MAX_X * 2);
270 #else
271 	pbmih->biWidth = lelong(w = MAX_X);
272 #endif
273 	pbmih->biHeight = lelong(h = MAX_Y);
274 	pbmih->biPlanes = leshort(1);
275 #if BITCOUNT==4
276 	pbmih->biBitCount = leshort(4);
277 	cClrBits = 4;
278 #else
279 	pbmih->biBitCount = leshort(8);
280 	cClrBits = 8;
281 #endif
282 	if (cClrBits == 1)
283 	        cClrBits = 1;
284 	else if (cClrBits <= 4)
285 		cClrBits = 4;
286 	else if (cClrBits <= 8)
287 		cClrBits = 8;
288 	else if (cClrBits <= 16)
289 		cClrBits = 16;
290 	else if (cClrBits <= 24)
291 		cClrBits = 24;
292 	else cClrBits = 32;
293 	pbmih->biCompression = lelong(BI_RGB);
294 	pbmih->biXPelsPerMeter = lelong(0);
295 	pbmih->biYPelsPerMeter = lelong(0);
296 #if (TILE_X==32)
297 	if (cClrBits < 24)
298         	pbmih->biClrUsed = lelong(1<<cClrBits);
299 #else
300 	pbmih->biClrUsed = lelong(RGBQUAD_COUNT);
301 #endif
302 
303 #if (TILE_X==16)
304 	pbmih->biSizeImage = lelong(0);
305 #else
306 	pbmih->biSizeImage = lelong(((w * cClrBits +31) & ~31) /8 * h);
307 #endif
308  	pbmih->biClrImportant = (DWORD)0;
309 }
310 
311 static void
312 build_bmptile(pixels)
313 pixel (*pixels)[TILE_X];
314 {
315 	int cur_x, cur_y, cur_color;
316 	int x,y;
317 
318 	for (cur_y = 0; cur_y < TILE_Y; cur_y++) {
319 	 for (cur_x = 0; cur_x < TILE_X; cur_x++) {
320 	  for (cur_color = 0; cur_color < num_colors; cur_color++) {
321 	   if (ColorMap[CM_RED][cur_color] == pixels[cur_y][cur_x].r &&
322 	      ColorMap[CM_GREEN][cur_color]== pixels[cur_y][cur_x].g &&
323 	      ColorMap[CM_BLUE][cur_color] == pixels[cur_y][cur_x].b)
324 		break;
325 	  }
326 	  if (cur_color >= num_colors)
327 		Fprintf(stderr, "color not in colormap!\n");
328 	  y = (MAX_Y - 1) - (cur_y + yoffset);
329 #if BITCOUNT==4
330 	  x = (cur_x / 2) + xoffset;
331 	  bmp.packtile[y][x] = cur_x%2 ?
332 		(uchar)(bmp.packtile[y][x] | cur_color) :
333 		(uchar)(cur_color<<4);
334 #else
335 	  x = cur_x + xoffset;
336 	  bmp.packtile[y][x] = (uchar)cur_color;
337 #endif
338 	 }
339 	}
340 }
341