more DUMPLOG lint
[aNetHack.git] / sys / amiga / txt2iff.c
blob8e1916b9e7223a3228496460c03c395385b3aaf2
1 /* NetHack 3.6 txt2iff.c $NHDT-Date: 1432512795 2015/05/25 00:13:15 $ $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */
2 /* Copyright (c) 1995 by Gregg Wonderly, Naperville, Illinois */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include <stdlib.h>
7 #include "config.h"
8 #include "tile.h"
10 #include <dos/dos.h>
11 #include <dos/dos.h>
12 #include <dos/dosextens.h>
13 #include <graphics/gfx.h>
14 #include <graphics/gfxbase.h>
15 #include <graphics/view.h>
16 #include <libraries/iffparse.h>
17 #include <libraries/dos.h>
18 #include <clib/dos_protos.h>
19 #include <clib/iffparse_protos.h>
20 #ifndef _DCC
21 #include <proto/exec.h>
22 #include <proto/iffparse.h>
23 #include <proto/dos.h>
24 #endif
26 void panic(const char *);
27 void map_colors(void);
28 int BestMatch(int, int, int);
30 extern pixval ColorMap[3][MAXCOLORMAPSIZE];
31 extern int colorsinmap;
34 * WARNING:
35 * This program carries forth the assumption that the colormaps in all
36 * of the .txt files are the same. This is a bug.
39 struct {
40 int Height;
41 int Width;
42 } IFFScreen;
45 * We are using a hybrid form of our own design which we call a BMAP (for
46 * bitmap) form. It is an ILBM with the bitmaps already deinterleaved,
47 * completely uncompressed.
48 * This speeds the loading of the images from the games point of view because
49 * it
50 * does not have to deinterleave and uncompress them.
52 #define ID_BMAP MAKE_ID('B', 'M', 'A', 'P') /* instead of ILBM */
53 #define ID_BMHD MAKE_ID('B', 'M', 'H', 'D') /* Same as ILBM */
54 #define ID_CAMG MAKE_ID('C', 'A', 'M', 'G') /* Same as ILBM */
55 #define ID_CMAP MAKE_ID('C', 'M', 'A', 'P') /* Same as ILBM */
56 #define ID_PDAT \
57 MAKE_ID('P', 'D', 'A', 'T') /* Extra data describing plane \
58 * size due to graphics.library \
59 * rounding requirements. \
61 #define ID_PLNE MAKE_ID('P', 'L', 'N', 'E') /* The planes of the image */
63 #ifndef _DCC
64 extern
65 #endif
66 struct Library *IFFParseBase;
68 int nplanes;
70 /* BMHD from IFF documentation */
71 typedef struct {
72 UWORD w, h;
73 WORD x, y;
74 UBYTE nPlanes;
75 UBYTE masking;
76 UBYTE compression;
77 UBYTE reserved1;
78 UWORD transparentColor;
79 UBYTE xAspect, yAspect;
80 WORD pageWidth, pageHeight;
81 } BitMapHeader;
83 typedef struct {
84 UBYTE r, g, b;
85 } AmiColorMap;
87 pixel pixels[TILE_Y][TILE_X];
88 AmiColorMap *cmap;
90 int findcolor(register pixel *pix);
91 void packwritebody(pixel (*tile)[TILE_X], char **planes, int tileno);
93 void
94 error(char *str)
96 fprintf(stderr, "ERROR: %s\n", str);
100 * This array maps the image colors to the amiga's first 16 colors. The
101 * colors
102 * are reordered to help with maintaining dripen settings.
104 int colrmap[] = { 0, 6, 9, 15, 4, 10, 2, 3, 5, 11, 7, 13, 8, 1, 14, 12 };
106 /* How many tiles fit across and down. */
108 #define COLS 20
109 #define ROWS ((tiles + COLS - 1) / COLS)
111 main(int argc, char **argv)
113 int colors;
114 struct {
115 long nplanes;
116 long pbytes;
117 long across;
118 long down;
119 long npics;
120 long xsize;
121 long ysize;
122 } pdat;
123 long pbytes; /* Bytes of data in a plane */
124 int i, cnt;
125 BitMapHeader bmhd;
126 struct IFFHandle *iff;
127 long camg = HIRES | LACE;
128 int tiles = 0;
129 char **planes;
131 if (argc != 3) {
132 fprintf(stderr, "Usage: %s source destination\n", argv[0]);
133 exit(1);
136 #if defined(_DCC) || defined(__GNUC__)
137 IFFParseBase = OpenLibrary("iffparse.library", 0);
138 if (!IFFParseBase) {
139 error("unable to open iffparse.library");
140 exit(1);
142 #endif
144 /* First, count the files in the file */
145 if (fopen_text_file(argv[1], "r") != TRUE) {
146 perror(argv[1]);
147 return (1);
150 nplanes = 0;
151 i = colorsinmap - 1; /*IFFScreen.Colors - 1; */
152 while (i != 0) {
153 nplanes++;
154 i >>= 1;
157 planes = malloc(nplanes * sizeof(char *));
158 if (planes == 0) {
159 error("can not allocate planes pointer");
160 exit(1);
163 while (read_text_tile(pixels) == TRUE)
164 ++tiles;
165 fclose_text_file();
167 IFFScreen.Width = COLS * TILE_X;
168 IFFScreen.Height = ROWS * TILE_Y;
170 pbytes = (COLS * ROWS * TILE_X + 15) / 16 * 2 * TILE_Y;
172 for (i = 0; i < nplanes; ++i) {
173 planes[i] = calloc(1, pbytes);
174 if (planes[i] == 0) {
175 error("can not allocate planes pointer");
176 exit(1);
180 /* Now, process it */
181 if (fopen_text_file(argv[1], "r") != TRUE) {
182 perror(argv[1]);
183 return (1);
186 iff = AllocIFF();
187 if (!iff) {
188 error("Can not allocate IFFHandle");
189 return (1);
192 iff->iff_Stream = Open(argv[2], MODE_NEWFILE);
193 if (!iff->iff_Stream) {
194 error("Can not open output file");
195 return (1);
198 InitIFFasDOS(iff);
199 OpenIFF(iff, IFFF_WRITE);
201 PushChunk(iff, ID_BMAP, ID_FORM, IFFSIZE_UNKNOWN);
203 bmhd.w = IFFScreen.Width;
204 bmhd.h = IFFScreen.Height;
205 bmhd.x = 0;
206 bmhd.y = 0;
207 bmhd.nPlanes = nplanes;
208 bmhd.masking = 0;
209 bmhd.compression = 0;
210 bmhd.reserved1 = 0;
211 bmhd.transparentColor = 0;
212 bmhd.xAspect = 100;
213 bmhd.yAspect = 100;
214 bmhd.pageWidth = TILE_X;
215 bmhd.pageHeight = TILE_Y;
217 PushChunk(iff, ID_BMAP, ID_BMHD, sizeof(bmhd));
218 WriteChunkBytes(iff, &bmhd, sizeof(bmhd));
219 PopChunk(iff);
221 PushChunk(iff, ID_BMAP, ID_CAMG, sizeof(camg));
222 WriteChunkBytes(iff, &camg, sizeof(camg));
223 PopChunk(iff);
225 /* We need to reorder the colors to get reasonable default pens but
226 * we also need to know where some of the colors are - so go find out.
228 map_colors();
230 cmap = malloc((colors = (1L << nplanes)) * sizeof(AmiColorMap));
231 for (i = 0; i < colors; ++i) {
232 cmap[colrmap[i]].r = ColorMap[CM_RED][i];
233 cmap[colrmap[i]].g = ColorMap[CM_GREEN][i];
234 cmap[colrmap[i]].b = ColorMap[CM_BLUE][i];
237 PushChunk(iff, ID_BMAP, ID_CMAP, IFFSIZE_UNKNOWN);
238 for (i = 0; i < colors; ++i)
239 WriteChunkBytes(iff, &cmap[i], 3);
240 PopChunk(iff);
242 cnt = 0;
243 while (read_text_tile(pixels) == TRUE) {
244 packwritebody(pixels, planes, cnt);
245 if (cnt % 20 == 0)
246 printf("%d..", cnt);
247 ++cnt;
248 fflush(stdout);
251 pdat.nplanes = nplanes;
252 pdat.pbytes = pbytes;
253 pdat.xsize = TILE_X;
254 pdat.ysize = TILE_Y;
255 pdat.across = COLS;
256 pdat.down = ROWS;
257 pdat.npics = cnt;
259 PushChunk(iff, ID_BMAP, ID_PDAT, IFFSIZE_UNKNOWN);
260 WriteChunkBytes(iff, &pdat, sizeof(pdat));
261 PopChunk(iff);
263 PushChunk(iff, ID_BMAP, ID_PLNE, IFFSIZE_UNKNOWN);
264 for (i = 0; i < nplanes; ++i)
265 WriteChunkBytes(iff, planes[i], pbytes);
266 PopChunk(iff);
268 CloseIFF(iff);
269 Close(iff->iff_Stream);
270 FreeIFF(iff);
272 printf("\n%d tiles converted\n", cnt);
274 #if defined(_DCC) || defined(__GNUC__)
275 CloseLibrary(IFFParseBase);
276 #endif
277 exit(0);
280 findcolor(register pixel *pix)
282 register int i;
284 for (i = 0; i < MAXCOLORMAPSIZE; ++i) {
285 if ((pix->r == ColorMap[CM_RED][i])
286 && (pix->g == ColorMap[CM_GREEN][i])
287 && (pix->b == ColorMap[CM_BLUE][i])) {
288 return (i);
291 return (-1);
294 void
295 packwritebody(pixel (*tile)[TILE_X], char **planes, int tileno)
297 register int i, j, k, col;
298 register char *buf;
299 register int across, rowbytes, xoff, yoff;
301 /* how many tiles fit across? */
302 across = COLS;
304 /* How many bytes per pixel row */
305 rowbytes = ((IFFScreen.Width + 15) / 16) * 2;
307 /* How many bytes to account for y distance in planes */
308 yoff = ((tileno / across) * TILE_Y) * rowbytes;
310 /* How many bytes to account for x distance in planes */
311 xoff = (tileno % across) * (TILE_X / 8);
313 /* For each row... */
314 for (i = 0; i < TILE_Y; ++i) {
315 /* For each bitplane... */
316 for (k = 0; k < nplanes; ++k) {
317 const int mask = 1l << k;
319 /* Go across the row */
320 for (j = 0; j < TILE_X; j++) {
321 col = findcolor(&tile[i][j]);
322 if (col == -1) {
323 error("can not convert pixel color to colormap index");
324 return;
326 /* Shift the colors around to have good complements and to
327 * know the dripen values.
329 col = colrmap[col];
331 /* To top left corner of tile */
332 buf = planes[k] + yoff + xoff;
334 /*To i'th row of tile and the correct byte for the j'th
335 * pixel*/
336 buf += (i * rowbytes) + (j / 8);
338 /* Or in the bit for this color */
339 *buf |= (((col & mask) != 0) << (7 - (j % 8)));
345 /* #define DBG */
347 /* map_colors
348 * The incoming colormap is in arbitrary order and has arbitrary colors in
349 * it, but we need (some) specific colors in specific places. Find the
350 * colors we need and fix the mapping table to match.
352 /* What we are aiming for: */
353 /* XXX was 0-7 */
354 #define CX_BLACK 0
355 #define CX_WHITE 1
356 #define CX_BROWN 11
357 #define CX_CYAN 2
358 #define CX_GREEN 5
359 #define CX_MAGENTA 10
360 #define CX_BLUE 4
361 #define CX_RED 7
362 /* we don't care about the rest, at least now */
363 /* should get: black white blue red grey greyblue ltgrey */
364 void
365 map_colors()
367 int x;
368 #if 1
369 int tmpmap[] = { 0, 2, 3, 7, 4, 5, 8, 9, 10, 11, 13, 15, 12, 1, 14, 6 };
370 /* still not right: gray green yellow lost somewhere? */
371 #else
372 int tmpmap[16];
373 int x, y;
374 for (x = 0; x < 16; x++)
375 tmpmap[x] = -1; /* set not assigned yet */
377 tmpmap[BestMatch(0, 0, 0)] = CX_BLACK;
378 tmpmap[BestMatch(255, 255, 255)] = CX_WHITE;
379 tmpmap[BestMatch(255, 0, 0)] = CX_RED;
380 tmpmap[BestMatch(0, 255, 0)] = CX_GREEN;
381 tmpmap[BestMatch(0, 0, 255)] = CX_BLUE;
383 /* clean up the rest */
384 for (x = 0; x < 16; x++) {
385 for (y = 0; y < 16; y++)
386 if (tmpmap[y] == x)
387 goto outer_cont;
388 for (y = 0; y < 16; y++)
389 if (tmpmap[y] == -1) {
390 tmpmap[y] = x;
391 break;
393 if (y == 16)
394 panic("too many colors?");
395 outer_cont:
398 for (x = 0; x < 16; x++)
399 if (tmpmap[y] == -1)
400 panic("lost color?");
401 #endif
402 for (x = 0; x < 16; x++) {
403 #ifdef DBG
404 printf("final: c[%d]=%d (target: %d)\n", x, tmpmap[x], colrmap[x]);
405 #endif
406 colrmap[x] = tmpmap[x];
409 BestMatch(r, g, b) int r, g, b;
411 int x;
412 int bestslot;
413 int bestrate = 99999999L;
414 for (x = 0; x < 16; x++) {
415 int rr = r - ColorMap[CM_RED][x];
416 int gg = g - ColorMap[CM_GREEN][x];
417 int bb = b - ColorMap[CM_BLUE][x];
418 int rate = rr * rr + gg * gg + bb * bb;
419 if (bestrate > rate) {
420 bestrate = rate;
421 bestslot = x;
424 #ifdef DBG
425 printf("map (%d,%d,%d) -> %d (error=%d)\n", r, g, b, bestslot, bestrate);
426 #endif
427 return bestslot;
430 long *
431 alloc(unsigned int n)
433 long *ret = malloc(n);
434 if (!ret) {
435 error("Can't allocate memory");
436 exit(1);
438 return (ret);
441 void
442 panic(const char *msg)
444 fprintf(stderr, "PANIC: %s\n", msg);
445 exit(1);