Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * Portions of this file are copyright Rebirth contributors and licensed as
3
 * described in COPYING.txt.
4
 * Portions of this file are copyright Parallax Software and licensed
5
 * according to the Parallax license below.
6
 * See COPYING.txt for license details.
7
 
8
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9
SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12
IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14
FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17
COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18
*/
19
 
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <alloc.h>
23
 
24
#include "iff.h"
25
 
26
#define MIN(a,b) ((a<b)?a:b)
27
 
28
#define MAKE_SIG(a,b,c,d) (((long)(a)<<24)+((long)(b)<<16)+((c)<<8)+(d))
29
 
30
#define form_sig MAKE_SIG('F','O','R','M')
31
#define ilbm_sig MAKE_SIG('I','L','B','M')
32
#define body_sig MAKE_SIG('B','O','D','Y')
33
#define pbm_sig MAKE_SIG('P','B','M',' ')
34
#define bmhd_sig MAKE_SIG('B','M','H','D')
35
#define cmap_sig MAKE_SIG('C','M','A','P')
36
 
37
void printsig(long s)
38
{
39
        char *t=(char *) &s;
40
 
41
/*      printf("%c%c%c%c",*(&s+3),*(&s+2),*(&s+1),s);*/
42
        printf("%c%c%c%c",t[3],t[2],t[1],t[0]);
43
}
44
 
45
long get_sig(FILE *f)
46
{
47
        char s[4];
48
 
49
        if ((s[3]=getc(f))==EOF) return(EOF);
50
        if ((s[2]=getc(f))==EOF) return(EOF);
51
        if ((s[1]=getc(f))==EOF) return(EOF);
52
        if ((s[0]=getc(f))==EOF) return(EOF);
53
 
54
        return(*((long *) s));
55
}
56
 
57
int put_sig(long sig,FILE *f)
58
{
59
        char *s = (char *) &sig;
60
 
61
        putc(s[3],f);
62
        putc(s[2],f);
63
        putc(s[1],f);
64
        return putc(s[0],f);
65
 
66
}
67
 
68
int get_word(FILE *f)
69
{
70
        unsigned char c0,c1;
71
 
72
        c1=getc(f);
73
        c0=getc(f);
74
 
75
        if (c0==0xff) return(EOF);
76
 
77
        return(((int)c1<<8) + c0);
78
 
79
}
80
 
81
char get_byte(FILE *f)
82
{
83
        return getc(f);
84
}
85
 
86
char put_byte(unsigned char c,FILE *f)
87
{
88
        return putc(c,f);
89
}
90
 
91
int put_word(int n,FILE *f)
92
{
93
        unsigned char c0,c1;
94
 
95
        c0 = (n & 0xff00) >> 8;
96
        c1 = n & 0xff;
97
 
98
        put_byte(c0,f);
99
        return put_byte(c1,f);
100
}
101
 
102
int put_long(long n,FILE *f)
103
{
104
        int n0,n1;
105
 
106
        n0 = (int) ((n & 0xffff0000l) >> 16);
107
        n1 = (int) (n & 0xffff);
108
 
109
        put_word(n0,f);
110
        return put_word(n1,f);
111
 
112
}
113
 
114
long get_long(FILE *f)
115
{
116
        unsigned char c0,c1,c2,c3;
117
 
118
        c3=getc(f);
119
        c2=getc(f);
120
        c1=getc(f);
121
        c0=getc(f);
122
 
123
//printf("get_long %x %x %x %x\n",c3,c2,c1,c0);
124
 
125
//      if (c0==0xff) return(EOF);
126
 
127
        return(((long)c3<<24) + ((long)c2<<16) + ((long)c1<<8) + c0);
128
 
129
}
130
 
131
void parse_bmhd(FILE *ifile,long len,struct bitmap_header *bitmap_header)
132
{
133
        len++;  /* so no "parm not used" warning */
134
 
135
//      debug("parsing bmhd len=%ld\n",len);
136
 
137
        bitmap_header->w = get_word(ifile);
138
        bitmap_header->h = get_word(ifile);
139
        bitmap_header->x = get_word(ifile);
140
        bitmap_header->y = get_word(ifile);
141
 
142
        bitmap_header->nplanes = get_byte(ifile);
143
        bitmap_header->masking = get_byte(ifile);
144
        bitmap_header->compression = get_byte(ifile);
145
        get_byte(ifile);                /* skip pad */
146
 
147
        bitmap_header->transparentcolor = get_word(ifile);
148
        bitmap_header->xaspect = get_byte(ifile);
149
        bitmap_header->yaspect = get_byte(ifile);
150
 
151
        bitmap_header->pagewidth = get_word(ifile);
152
        bitmap_header->pageheight = get_word(ifile);
153
 
154
//      debug("w,h=%d,%d x,y=%d,%d\n",w,h,x,y);
155
//      debug("nplanes=%d, masking=%d ,compression=%d, transcolor=%d\n",nplanes,masking,compression,transparentcolor);
156
 
157
}
158
 
159
 
160
//      the buffer pointed to by raw_data is stuffed with a pointer to decompressed pixel data
161
int parse_body_pbm(FILE *ifile,long len,struct bitmap_header *bitmap_header)
162
{
163
        unsigned char huge *p=bitmap_header->raw_data;
164
        int width=bitmap_header->w;
165
        long cnt,old_cnt;
166
        char n;
167
        int nn,wid_cnt;
168
        char ignore;
169
 
170
        if (bitmap_header->compression == cmpNone) {            /* no compression */
171
                int x,y;
172
 
173
                for (y=bitmap_header->h;y;y--) {
174
                        for (x=bitmap_header->w;x;x--) *p++=getc(ifile);
175
                        if (bitmap_header->w & 1) ignore = getc(ifile);
176
                }
177
 
178
        }
179
        else if (bitmap_header->compression == cmpByteRun1)
180
                for (old_cnt=cnt=len,wid_cnt=width;cnt>0;) {
181
                        unsigned char c;
182
 
183
                        if (old_cnt-cnt > 2048) {
184
//                              printf(".");
185
                                old_cnt=cnt;
186
                        }
187
 
188
                        if (wid_cnt <= 0) wid_cnt = width;
189
 
190
                        n=getc(ifile);
191
                        if (n >= 0) {                                           // copy next n+1 bytes from source, they are not compressed
192
                                nn = (int) n+1;
193
                                cnt -= nn+1;
194
                                wid_cnt -= nn;
195
                                if (wid_cnt==-1) --nn;
196
                                while (nn--) *p++=getc(ifile);
197
                                if (wid_cnt==-1) ignore = getc(ifile);          /* extra char */
198
                        }
199
                        else if (n>=-127) {                             // next -n + 1 bytes are following byte
200
                                cnt -= 2;
201
                                c=getc(ifile);
202
                                nn = (int) -n+1;
203
                                wid_cnt -= nn;
204
                                if (wid_cnt==-1) --nn;
205
                                while (nn--) *p++=c;
206
                        }
207
 
208
                }
209
 
210
        if (len & 1) ignore = getc(ifile);
211
 
212
        if (ignore) ignore++;   // haha, suppress the evil warning message
213
 
214
        return IFF_NO_ERROR;
215
}
216
 
217
//      the buffer pointed to by raw_data is stuffed with a pointer to bitplane pixel data
218
int parse_body_ilbm(FILE *ifile,long len,struct bitmap_header *bitmap_header)
219
{
220
        unsigned char huge *p=bitmap_header->raw_data;
221
        int width=bitmap_header->w;
222
        long cnt,old_cnt;
223
        char n;
224
        int nn,wid_cnt;
225
        char    ignore;
226
 
227
        if (bitmap_header->compression == cmpNone) {            /* no compression */
228
                int x,y;
229
 
230
                for (y=bitmap_header->h;y;y--) {
231
                        for (x=bitmap_header->w;x;x--) *p++=getc(ifile);
232
                        if (bitmap_header->w & 1) ignore = getc(ifile);
233
                }
234
 
235
        }
236
        else if (bitmap_header->compression == cmpByteRun1)
237
                for (old_cnt=cnt=len,wid_cnt=width;cnt>0;) {
238
                        unsigned char c;
239
 
240
                        if (old_cnt-cnt > 2048) {
241
//                              printf(".");
242
                                old_cnt=cnt;
243
                        }
244
 
245
                        if (wid_cnt <= 0) wid_cnt = width;
246
 
247
                        n=getc(ifile);
248
                        if (n >= 0) {                                           // copy next n+1 bytes from source, they are not compressed
249
                                nn = (int) n+1;
250
                                cnt -= nn+1;
251
                                wid_cnt -= nn;
252
                                if (wid_cnt==-1) --nn;
253
                                while (nn--) *p++=getc(ifile);
254
                                if (wid_cnt==-1) ignore = getc(ifile);          /* extra char */
255
                        }
256
                        else if (n>=-127) {                             // next -n + 1 bytes are following byte
257
                                cnt -= 2;
258
                                c=getc(ifile);
259
                                nn = (int) -n+1;
260
                                wid_cnt -= nn;
261
                                if (wid_cnt==-1) --nn;
262
                                while (nn--) *p++=c;
263
                        }
264
 
265
                }
266
 
267
        if (len & 1) ignore = getc(ifile);
268
 
269
        if (ignore) ignore++;   // haha, suppress the evil warning message
270
 
271
        return IFF_NO_ERROR;
272
}
273
 
274
void skip_chunk(FILE *ifile,long len)
275
{
276
        len = len+1 & ~1;
277
        fseek(ifile,len,SEEK_CUR);
278
}
279
 
280
// Pass pointer to opened file, and to empty bitmap header.
281
int parse_iff(FILE *ifile,struct bitmap_header *bitmap_header)
282
{
283
        long sig,form_len,len,form_type;
284
        char    ignore;
285
 
286
        sig=get_sig(ifile);
287
 
288
//      printsig(sig);
289
 
290
        if (sig==form_sig) {
291
 
292
                form_len = get_long(ifile);
293
                form_len++;             /* get rid of never used message */
294
 
295
                form_type = get_sig(ifile);
296
 
297
//              printf(" %ld ",form_len);
298
//              printsig(form_type);
299
//              printf("\n");
300
 
301
                if ((form_type == pbm_sig) || (form_type == ilbm_sig)) {
302
 
303
                        if (form_type == pbm_sig)
304
                                bitmap_header->type = PBM_TYPE;
305
                        else
306
                                bitmap_header->type = ILBM_TYPE;
307
 
308
                        while ((sig=get_sig(ifile)) != EOF) {
309
 
310
                                len=get_long(ifile);
311
 
312
//                              printf(" ");
313
//                              printsig(sig);
314
//                              printf(" %ld\n",len);
315
 
316
                                switch (sig) {
317
 
318
                                        case bmhd_sig:
319
 
320
                                                parse_bmhd(ifile,len,bitmap_header);
321
 
322
                                                if (! (bitmap_header->raw_data = farmalloc((long) bitmap_header->w * bitmap_header->h))) return IFF_NO_MEM;
323
 
324
                                                break;
325
 
326
                                        case cmap_sig:
327
                                        {
328
                                                int ncolors=(int) (len/3),cnum;
329
                                                unsigned char r,g,b;
330
 
331
                                                for (cnum=0;cnum<ncolors;cnum++) {
332
                                                        r=getc(ifile);
333
                                                        g=getc(ifile);
334
                                                        b=getc(ifile);
335
                                                        r >>= 2; bitmap_header->palette[cnum].r = r;
336
                                                        g >>= 2; bitmap_header->palette[cnum].g = g;
337
                                                        b >>= 2; bitmap_header->palette[cnum].b = b;
338
                                                }
339
                                                if (len & 1) ignore = getc(ifile);
340
 
341
                                                break;
342
                                        }
343
 
344
                                        case body_sig:
345
                                        {
346
                                                int r;
347
                                                switch (form_type) {
348
                                                        case pbm_sig:
349
                                                                if (!(r=parse_body_pbm(ifile,len,bitmap_header))) return r;
350
                                                                break;
351
                                                        case ilbm_sig:
352
                                                                if (!(r=parse_body_ilbm(ifile,len,bitmap_header))) return r;
353
                                                                break;
354
                                                }
355
                                                break;
356
                                        }
357
                                        default:
358
                                                skip_chunk(ifile,len);
359
                                                break;
360
                                }
361
                        }
362
                }
363
                else return IFF_UNKNOWN_FORM;
364
        }
365
        else
366
                {printf("Not an IFF file\n"); return IFF_NOT_IFF;}
367
 
368
        if (ignore) ignore++;
369
 
370
        return IFF_NO_ERROR;    /* ok! */
371
}
372
 
373
#define BMHD_SIZE 20
374
 
375
int write_bmhd(FILE *ofile,struct bitmap_header *bitmap_header)
376
{
377
 
378
        put_sig(bmhd_sig,ofile);
379
        put_long((long) BMHD_SIZE,ofile);
380
 
381
        put_word(bitmap_header->w,ofile);
382
        put_word(bitmap_header->h,ofile);
383
        put_word(bitmap_header->x,ofile);
384
        put_word(bitmap_header->y,ofile);
385
 
386
        put_byte(bitmap_header->nplanes,ofile);
387
        put_byte(bitmap_header->masking,ofile);
388
        put_byte(bitmap_header->compression,ofile);
389
        put_byte(0,ofile);      /* pad */
390
 
391
        put_word(bitmap_header->transparentcolor,ofile);
392
        put_byte(bitmap_header->xaspect,ofile);
393
        put_byte(bitmap_header->yaspect,ofile);
394
 
395
        put_word(bitmap_header->pagewidth,ofile);
396
        put_word(bitmap_header->pageheight,ofile);
397
 
398
        return 1;
399
 
400
}
401
 
402
int write_huge(unsigned char huge *huge_ptr,long len,FILE *f)
403
{
404
        unsigned char temp_buffer[256],*t;
405
 
406
//printf("write_huge %ld\n",len);
407
 
408
        while (len) {
409
                int n,wsize = (int) MIN(len,256);
410
 
411
//printf("len,wsize=%ld,%d\n",len,wsize);
412
                for (t=temp_buffer,n=wsize;n--;) *t++ = *huge_ptr++;
413
 
414
                fwrite(temp_buffer,wsize,1,f);
415
 
416
                len -= wsize;
417
 
418
        }
419
 
420
        return 1;
421
}
422
 
423
int write_pal(FILE *ofile,struct bitmap_header *bitmap_header)
424
{
425
        int     i;
426
 
427
        int n_colors = 1<<bitmap_header->nplanes;
428
 
429
        put_sig(cmap_sig,ofile);
430
//      put_long(sizeof(struct pal_entry) * n_colors,ofile);
431
        put_long(3 * n_colors,ofile);
432
 
433
//printf("new write pal %d %d\n",3,n_colors);
434
 
435
        for (i=0; i<256; i++) {
436
                unsigned char r,g,b;
437
                r = bitmap_header->palette[i].r * 4;
438
                g = bitmap_header->palette[i].g * 4;
439
                b = bitmap_header->palette[i].b * 4;
440
                fputc(r,ofile);
441
                fputc(g,ofile);
442
                fputc(b,ofile);
443
        }
444
 
445
//printf("write pal %d %d\n",sizeof(struct pal_entry),n_colors);
446
//      fwrite(bitmap_header->palette,sizeof(struct pal_entry),n_colors,ofile);
447
 
448
        return 1;
449
}
450
 
451
#define EVEN(a) ((a+1)&0xfffffffel)
452
 
453
int write_body(FILE *ofile,struct bitmap_header *bitmap_header)
454
{
455
        int w=bitmap_header->w,h=bitmap_header->h;
456
        int y,odd=w&1;
457
        long len = EVEN(w) * h;
458
        unsigned char huge *p=bitmap_header->raw_data;
459
 
460
        put_sig(body_sig,ofile);
461
        put_long(len,ofile);
462
 
463
        for (y=bitmap_header->h;y--;) {
464
 
465
                write_huge(p,bitmap_header->w,ofile);
466
                if (odd) putc(0,ofile);
467
                p+=bitmap_header->w;
468
 
469
        }
470
 
471
        return 1;
472
}
473
 
474
int write_pbm(FILE *ofile,struct bitmap_header *bitmap_header)                  /* writes a pbm iff file */
475
{
476
        long raw_size = EVEN(bitmap_header->w) * bitmap_header->h;
477
        long pbm_size = 4 + BMHD_SIZE + 8 + EVEN(raw_size) + sizeof(struct pal_entry)*(1<<bitmap_header->nplanes)+8;
478
 
479
//printf("write_pbm\n");
480
 
481
        put_sig(form_sig,ofile);
482
        put_long(pbm_size+8,ofile);
483
        put_sig(pbm_sig,ofile);
484
 
485
        write_bmhd(ofile,bitmap_header);
486
 
487
        write_pal(ofile,bitmap_header);
488
 
489
        write_body(ofile,bitmap_header);
490
 
491
        return 1;
492
 
493
}
494