1 /* NetHack 3.6 xpm2iff.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>
19 #include <proto/iffparse.h>
20 #include <proto/dos.h>
21 #include <proto/exec.h>
35 /* translation table from xpm characters to RGB and colormap slots */
39 int slot
; /* output colortable index */
42 pixval ColorMap
[3][MAXCOLORMAPSIZE
];
46 * We are using a hybrid form of our own design which we call a BMAP (for
47 * bitmap) form. It is an ILBM with the bitmaps already deinterleaved,
48 * completely uncompressed.
49 * This speeds the loading of the images from the games point of view because
51 * does not have to deinterleave and uncompress them.
53 #define ID_BMAP MAKE_ID('B', 'M', 'A', 'P') /* instead of ILBM */
54 #define ID_BMHD MAKE_ID('B', 'M', 'H', 'D') /* Same as ILBM */
55 #define ID_CAMG MAKE_ID('C', 'A', 'M', 'G') /* Same as ILBM */
56 #define ID_CMAP MAKE_ID('C', 'M', 'A', 'P') /* Same as ILBM */
58 MAKE_ID('P', 'D', 'A', 'T') /* Extra data describing plane \
59 * size due to graphics.library \
60 * rounding requirements. \
62 #define ID_PLNE MAKE_ID('P', 'L', 'N', 'E') /* The planes of the image */
66 /* BMHD from IFF documentation */
74 UWORD transparentColor
;
75 UBYTE xAspect
, yAspect
;
76 WORD pageWidth
, pageHeight
;
83 pixel pixels
[TILE_Y
][TILE_X
];
89 fprintf(stderr
, "ERROR: %s\n", str
);
94 main(int argc
, char **argv
)
106 long pbytes
; /* Bytes of data in a plane */
109 struct IFFHandle
*iff
;
110 long camg
= HIRES
| LACE
;
114 #if defined(_DCC) || defined(__GNUC__)
115 IFFParseBase
= OpenLibrary("iffparse.library", 0);
117 error("unable to open iffparse.library");
122 if (fopen_xpm_file(argv
[1], "r") != TRUE
) {
128 i
= XpmScreen
.Colors
- 1;
134 planes
= malloc(nplanes
* sizeof(char *));
136 error("can not allocate planes pointer");
140 XpmScreen
.BytesPerRow
= ((XpmScreen
.Width
+ 15) / 16) * 2;
141 pbytes
= XpmScreen
.BytesPerRow
* XpmScreen
.Height
;
142 for (i
= 0; i
< nplanes
; ++i
) {
143 planes
[i
] = malloc(pbytes
);
144 if (planes
[i
] == 0) {
145 error("can not allocate planes pointer");
148 memset(planes
[i
], 0, pbytes
);
153 error("Can not allocate IFFHandle");
157 iff
->iff_Stream
= Open(argv
[2], MODE_NEWFILE
);
158 if (!iff
->iff_Stream
) {
159 error("Can not open output file");
164 OpenIFF(iff
, IFFF_WRITE
);
166 PushChunk(iff
, ID_BMAP
, ID_FORM
, IFFSIZE_UNKNOWN
);
168 bmhd
.w
= XpmScreen
.Width
;
169 bmhd
.h
= XpmScreen
.Height
;
172 bmhd
.nPlanes
= nplanes
;
174 bmhd
.compression
= 0;
176 bmhd
.transparentColor
= 0;
179 bmhd
.pageWidth
= 0; /* not needed for this program */
180 bmhd
.pageHeight
= 0; /* not needed for this program */
182 PushChunk(iff
, ID_BMAP
, ID_BMHD
, sizeof(bmhd
));
183 WriteChunkBytes(iff
, &bmhd
, sizeof(bmhd
));
186 PushChunk(iff
, ID_BMAP
, ID_CAMG
, sizeof(camg
));
187 WriteChunkBytes(iff
, &camg
, sizeof(camg
));
191 cmap
= malloc((colors
= (1L << nplanes
)) * sizeof(AmiColorMap
));
193 error("Can't allocate color map");
196 for (index
= 0; index
< 256; index
++) {
197 if (ttable
[index
].flag
) {
198 cmap
[ttable
[index
].slot
].r
= SCALE(ttable
[index
].r
);
199 cmap
[ttable
[index
].slot
].g
= SCALE(ttable
[index
].g
);
200 cmap
[ttable
[index
].slot
].b
= SCALE(ttable
[index
].b
);
205 PushChunk(iff
, ID_BMAP
, ID_CMAP
, IFFSIZE_UNKNOWN
);
206 WriteChunkBytes(iff
, cmap
, colors
* sizeof(*cmap
));
211 pdat
.nplanes
= nplanes
;
212 pdat
.pbytes
= pbytes
;
213 pdat
.xsize
= XpmScreen
.Width
;
214 pdat
.ysize
= XpmScreen
.Height
;
219 PushChunk(iff
, ID_BMAP
, ID_PDAT
, IFFSIZE_UNKNOWN
);
220 WriteChunkBytes(iff
, &pdat
, sizeof(pdat
));
223 PushChunk(iff
, ID_BMAP
, ID_PLNE
, IFFSIZE_UNKNOWN
);
224 for (i
= 0; i
< nplanes
; ++i
)
225 WriteChunkBytes(iff
, planes
[i
], pbytes
);
229 Close(iff
->iff_Stream
);
232 #if defined(_DCC) || defined(__GNUC__)
233 CloseLibrary(IFFParseBase
);
238 #define SETBIT(Plane, Plane_offset, Col, Value) \
240 planes[Plane][Plane_offset + (Col / 8)] |= 1 << (7 - (Col & 7)); \
245 int row
, col
, planeno
;
247 for (row
= 0; row
< XpmScreen
.Height
; row
++) {
248 char *xb
= xpmgetline();
252 plane_offset
= row
* XpmScreen
.BytesPerRow
;
253 for (col
= 0; col
< XpmScreen
.Width
; col
++) {
256 if (!ttable
[color
].flag
) {
257 fprintf(stderr
, "Bad image data\n");
259 slot
= ttable
[color
].slot
;
260 for (planeno
= 0; planeno
< nplanes
; planeno
++) {
261 SETBIT(planeno
, plane_offset
, col
, slot
& (1 << planeno
));
268 alloc(unsigned int n
)
270 long *ret
= malloc(n
);
272 error("Can't allocate memory");
280 char *xpmbuf
= initbuf
;
282 /* version 1. Reads the raw xpm file, NOT the compiled version. This is
283 * not a particularly good idea but I don't have time to do the right thing
284 * at this point, even if I was absolutely sure what that was. */
285 fopen_xpm_file(const char *fn
, const char *mode
)
289 if (strcmp(mode
, "r"))
290 return FALSE
; /* no choice now */
292 return FALSE
; /* one file at a time */
293 xpmfh
= fopen(fn
, mode
);
295 return FALSE
; /* I'm hard to please */
297 /* read the header */
301 if (4 != sscanf(xb
, "%d %d %d %d", &XpmScreen
.Width
, &XpmScreen
.Height
,
302 &XpmScreen
.Colors
, &temp
))
303 return FALSE
; /* bad header */
304 /* replace the original buffer with one big enough for
308 xpmbuf
= malloc(XpmScreen
.Width
* 2);
310 error("Can't allocate line buffer");
314 return FALSE
; /* limitation of this code */
317 /* read the colormap and translation table */
319 while (ccount
++ < (XpmScreen
.Colors
- 1)) {
325 if (4 != sscanf(xb
, "%c c #%2x%2x%2x", &index
, &r
, &g
, &b
)) {
326 fprintf(stderr
, "Bad color entry: %s\n", xb
);
329 ttable
[index
].flag
= 1; /* this color is valid */
333 ttable
[index
].slot
= ccount
;
339 /* This deserves better. Don't read it too closely - you'll get ill. */
346 if (fgets(buf
, bufsz
, xpmfh
) == 0)
348 } while (buf
[0] != '"');
349 /* strip off the trailing <",> if any */
350 for (bp
= buf
; *bp
; bp
++)