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