NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / amiga / xpm2iff.c
blobc3a6295f5d337c62f923d7fa5b2107d3a70a3410
1 /* aNetHack 0.0.1 xpm2iff.c $ANH-Date: 1432512795 2015/05/25 00:13:15 $ $ANH-Branch: master $:$ANH-Revision: 1.7 $ */
2 /* Copyright (c) 1995 by Gregg Wonderly, Naperville, Illinois */
3 /* aNetHack 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 #ifndef _DCC
19 #include <proto/iffparse.h>
20 #include <proto/dos.h>
21 #include <proto/exec.h>
22 #endif
24 struct xpmscreen {
25 int Width;
26 int Height;
27 int Colors;
28 int ColorResolution;
29 int Background;
30 int AspectRatio;
31 int Interlace;
32 int BytesPerRow;
33 } XpmScreen;
35 /* translation table from xpm characters to RGB and colormap slots */
36 struct Ttable {
37 char flag;
38 char r, g, b;
39 int slot; /* output colortable index */
40 } ttable[256];
42 pixval ColorMap[3][MAXCOLORMAPSIZE];
43 int colorsinmap;
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
50 * it
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 */
57 #define ID_PDAT \
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 */
64 int nplanes;
66 /* BMHD from IFF documentation */
67 typedef struct {
68 UWORD w, h;
69 WORD x, y;
70 UBYTE nPlanes;
71 UBYTE masking;
72 UBYTE compression;
73 UBYTE reserved1;
74 UWORD transparentColor;
75 UBYTE xAspect, yAspect;
76 WORD pageWidth, pageHeight;
77 } BitMapHeader;
79 typedef struct {
80 UBYTE r, g, b;
81 } AmiColorMap;
83 pixel pixels[TILE_Y][TILE_X];
84 AmiColorMap *cmap;
86 void
87 error(char *str)
89 fprintf(stderr, "ERROR: %s\n", str);
92 char **planes;
94 main(int argc, char **argv)
96 int colors;
97 struct {
98 long nplanes;
99 long pbytes;
100 long across;
101 long down;
102 long npics;
103 long xsize;
104 long ysize;
105 } pdat;
106 long pbytes; /* Bytes of data in a plane */
107 int i, cnt;
108 BitMapHeader bmhd;
109 struct IFFHandle *iff;
110 long camg = HIRES | LACE;
111 int tiles = 0;
112 int index;
114 #if defined(_DCC) || defined(__GNUC__)
115 IFFParseBase = OpenLibrary("iffparse.library", 0);
116 if (!IFFParseBase) {
117 error("unable to open iffparse.library");
118 exit(1);
120 #endif
122 if (fopen_xpm_file(argv[1], "r") != TRUE) {
123 perror(argv[1]);
124 return (1);
127 nplanes = 0;
128 i = XpmScreen.Colors - 1;
129 while (i != 0) {
130 nplanes++;
131 i >>= 1;
134 planes = malloc(nplanes * sizeof(char *));
135 if (planes == 0) {
136 error("can not allocate planes pointer");
137 exit(1);
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");
146 exit(1);
148 memset(planes[i], 0, pbytes);
151 iff = AllocIFF();
152 if (!iff) {
153 error("Can not allocate IFFHandle");
154 return (1);
157 iff->iff_Stream = Open(argv[2], MODE_NEWFILE);
158 if (!iff->iff_Stream) {
159 error("Can not open output file");
160 return (1);
163 InitIFFasDOS(iff);
164 OpenIFF(iff, IFFF_WRITE);
166 PushChunk(iff, ID_BMAP, ID_FORM, IFFSIZE_UNKNOWN);
168 bmhd.w = XpmScreen.Width;
169 bmhd.h = XpmScreen.Height;
170 bmhd.x = 0;
171 bmhd.y = 0;
172 bmhd.nPlanes = nplanes;
173 bmhd.masking = 0;
174 bmhd.compression = 0;
175 bmhd.reserved1 = 0;
176 bmhd.transparentColor = 0;
177 bmhd.xAspect = 100;
178 bmhd.yAspect = 100;
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));
184 PopChunk(iff);
186 PushChunk(iff, ID_BMAP, ID_CAMG, sizeof(camg));
187 WriteChunkBytes(iff, &camg, sizeof(camg));
188 PopChunk(iff);
190 #define SCALE(x) (x)
191 cmap = malloc((colors = (1L << nplanes)) * sizeof(AmiColorMap));
192 if (cmap == 0) {
193 error("Can't allocate color map");
194 exit(1);
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);
203 #undef SCALE
205 PushChunk(iff, ID_BMAP, ID_CMAP, IFFSIZE_UNKNOWN);
206 WriteChunkBytes(iff, cmap, colors * sizeof(*cmap));
207 PopChunk(iff);
209 conv_image();
211 pdat.nplanes = nplanes;
212 pdat.pbytes = pbytes;
213 pdat.xsize = XpmScreen.Width;
214 pdat.ysize = XpmScreen.Height;
215 pdat.across = 0;
216 pdat.down = 0;
217 pdat.npics = 1;
219 PushChunk(iff, ID_BMAP, ID_PDAT, IFFSIZE_UNKNOWN);
220 WriteChunkBytes(iff, &pdat, sizeof(pdat));
221 PopChunk(iff);
223 PushChunk(iff, ID_BMAP, ID_PLNE, IFFSIZE_UNKNOWN);
224 for (i = 0; i < nplanes; ++i)
225 WriteChunkBytes(iff, planes[i], pbytes);
226 PopChunk(iff);
228 CloseIFF(iff);
229 Close(iff->iff_Stream);
230 FreeIFF(iff);
232 #if defined(_DCC) || defined(__GNUC__)
233 CloseLibrary(IFFParseBase);
234 #endif
235 exit(0);
238 #define SETBIT(Plane, Plane_offset, Col, Value) \
239 if (Value) { \
240 planes[Plane][Plane_offset + (Col / 8)] |= 1 << (7 - (Col & 7)); \
243 conv_image()
245 int row, col, planeno;
247 for (row = 0; row < XpmScreen.Height; row++) {
248 char *xb = xpmgetline();
249 int plane_offset;
250 if (xb == 0)
251 return;
252 plane_offset = row * XpmScreen.BytesPerRow;
253 for (col = 0; col < XpmScreen.Width; col++) {
254 int slot;
255 int color = xb[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));
267 long *
268 alloc(unsigned int n)
270 long *ret = malloc(n);
271 if (!ret) {
272 error("Can't allocate memory");
273 exit(1);
275 return (ret);
278 FILE *xpmfh = 0;
279 char initbuf[200];
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)
287 int temp;
288 char *xb;
289 if (strcmp(mode, "r"))
290 return FALSE; /* no choice now */
291 if (xpmfh)
292 return FALSE; /* one file at a time */
293 xpmfh = fopen(fn, mode);
294 if (!xpmfh)
295 return FALSE; /* I'm hard to please */
297 /* read the header */
298 xb = xpmgetline();
299 if (xb == 0)
300 return FALSE;
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
305 * the real data
307 /* XXX */
308 xpmbuf = malloc(XpmScreen.Width * 2);
309 if (!xpmbuf) {
310 error("Can't allocate line buffer");
311 exit(1);
313 if (temp != 1)
314 return FALSE; /* limitation of this code */
317 /* read the colormap and translation table */
318 int ccount = -1;
319 while (ccount++ < (XpmScreen.Colors - 1)) {
320 char index;
321 int r, g, b;
322 xb = xpmgetline();
323 if (xb == 0)
324 return FALSE;
325 if (4 != sscanf(xb, "%c c #%2x%2x%2x", &index, &r, &g, &b)) {
326 fprintf(stderr, "Bad color entry: %s\n", xb);
327 return FALSE;
329 ttable[index].flag = 1; /* this color is valid */
330 ttable[index].r = r;
331 ttable[index].g = g;
332 ttable[index].b = b;
333 ttable[index].slot = ccount;
336 return TRUE;
339 /* This deserves better. Don't read it too closely - you'll get ill. */
340 #define bufsz 2048
341 char buf[bufsz];
342 xpmgetline()
344 char *bp;
345 do {
346 if (fgets(buf, bufsz, xpmfh) == 0)
347 return 0;
348 } while (buf[0] != '"');
349 /* strip off the trailing <",> if any */
350 for (bp = buf; *bp; bp++)
352 bp--;
353 while (isspace(*bp))
354 bp--;
355 if (*bp == ',')
356 bp--;
357 if (*bp == '"')
358 bp--;
359 bp++;
360 *bp = '\0';
362 return &buf[1];