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. */
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>
21 #include <proto/exec.h>
22 #include <proto/iffparse.h>
23 #include <proto/dos.h>
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
;
35 * This program carries forth the assumption that the colormaps in all
36 * of the .txt files are the same. This is a bug.
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
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 */
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 */
66 struct Library
*IFFParseBase
;
70 /* BMHD from IFF documentation */
78 UWORD transparentColor
;
79 UBYTE xAspect
, yAspect
;
80 WORD pageWidth
, pageHeight
;
87 pixel pixels
[TILE_Y
][TILE_X
];
90 int findcolor(register pixel
*pix
);
91 void packwritebody(pixel (*tile
)[TILE_X
], char **planes
, int tileno
);
96 fprintf(stderr
, "ERROR: %s\n", str
);
100 * This array maps the image colors to the amiga's first 16 colors. The
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. */
109 #define ROWS ((tiles + COLS - 1) / COLS)
111 main(int argc
, char **argv
)
123 long pbytes
; /* Bytes of data in a plane */
126 struct IFFHandle
*iff
;
127 long camg
= HIRES
| LACE
;
132 fprintf(stderr
, "Usage: %s source destination\n", argv
[0]);
136 #if defined(_DCC) || defined(__GNUC__)
137 IFFParseBase
= OpenLibrary("iffparse.library", 0);
139 error("unable to open iffparse.library");
144 /* First, count the files in the file */
145 if (fopen_text_file(argv
[1], "r") != TRUE
) {
151 i
= colorsinmap
- 1; /*IFFScreen.Colors - 1; */
157 planes
= malloc(nplanes
* sizeof(char *));
159 error("can not allocate planes pointer");
163 while (read_text_tile(pixels
) == TRUE
)
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");
180 /* Now, process it */
181 if (fopen_text_file(argv
[1], "r") != TRUE
) {
188 error("Can not allocate IFFHandle");
192 iff
->iff_Stream
= Open(argv
[2], MODE_NEWFILE
);
193 if (!iff
->iff_Stream
) {
194 error("Can not open output file");
199 OpenIFF(iff
, IFFF_WRITE
);
201 PushChunk(iff
, ID_BMAP
, ID_FORM
, IFFSIZE_UNKNOWN
);
203 bmhd
.w
= IFFScreen
.Width
;
204 bmhd
.h
= IFFScreen
.Height
;
207 bmhd
.nPlanes
= nplanes
;
209 bmhd
.compression
= 0;
211 bmhd
.transparentColor
= 0;
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
));
221 PushChunk(iff
, ID_BMAP
, ID_CAMG
, sizeof(camg
));
222 WriteChunkBytes(iff
, &camg
, sizeof(camg
));
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.
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);
243 while (read_text_tile(pixels
) == TRUE
) {
244 packwritebody(pixels
, planes
, cnt
);
251 pdat
.nplanes
= nplanes
;
252 pdat
.pbytes
= pbytes
;
259 PushChunk(iff
, ID_BMAP
, ID_PDAT
, IFFSIZE_UNKNOWN
);
260 WriteChunkBytes(iff
, &pdat
, sizeof(pdat
));
263 PushChunk(iff
, ID_BMAP
, ID_PLNE
, IFFSIZE_UNKNOWN
);
264 for (i
= 0; i
< nplanes
; ++i
)
265 WriteChunkBytes(iff
, planes
[i
], pbytes
);
269 Close(iff
->iff_Stream
);
272 printf("\n%d tiles converted\n", cnt
);
274 #if defined(_DCC) || defined(__GNUC__)
275 CloseLibrary(IFFParseBase
);
280 findcolor(register pixel
*pix
)
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
])) {
295 packwritebody(pixel (*tile
)[TILE_X
], char **planes
, int tileno
)
297 register int i
, j
, k
, col
;
299 register int across
, rowbytes
, xoff
, yoff
;
301 /* how many tiles fit across? */
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
]);
323 error("can not convert pixel color to colormap index");
326 /* Shift the colors around to have good complements and to
327 * know the dripen values.
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
336 buf
+= (i
* rowbytes
) + (j
/ 8);
338 /* Or in the bit for this color */
339 *buf
|= (((col
& mask
) != 0) << (7 - (j
% 8)));
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: */
359 #define CX_MAGENTA 10
362 /* we don't care about the rest, at least now */
363 /* should get: black white blue red grey greyblue ltgrey */
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? */
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
++)
388 for (y
= 0; y
< 16; y
++)
389 if (tmpmap
[y
] == -1) {
394 panic("too many colors?");
398 for (x
= 0; x
< 16; x
++)
400 panic("lost color?");
402 for (x
= 0; x
< 16; x
++) {
404 printf("final: c[%d]=%d (target: %d)\n", x
, tmpmap
[x
], colrmap
[x
]);
406 colrmap
[x
] = tmpmap
[x
];
409 BestMatch(r
, g
, b
) int r
, g
, b
;
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
) {
425 printf("map (%d,%d,%d) -> %d (error=%d)\n", r
, g
, b
, bestslot
, bestrate
);
431 alloc(unsigned int n
)
433 long *ret
= malloc(n
);
435 error("Can't allocate memory");
442 panic(const char *msg
)
444 fprintf(stderr
, "PANIC: %s\n", msg
);