home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / pal / iff.c next >
C/C++ Source or Header  |  1998-06-08  |  8KB  |  336 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13.  
  14. /*
  15.         routines to load an IFF picture into memory
  16.  
  17. */
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <malloc.h>
  22. #include <conio.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.  
  58. int get_word(FILE *f)
  59. {
  60.     unsigned char c0,c1;
  61.  
  62.     c1=getc(f);
  63.     c0=getc(f);
  64.  
  65.     if (c0==0xff) return(EOF);
  66.  
  67.     return(((int)c1<<8) + c0);
  68.  
  69. }
  70.  
  71. char get_byte(FILE *f)
  72. {
  73.     return getc(f);
  74. }
  75.  
  76. long get_long(FILE *f)
  77. {
  78.     unsigned char c0,c1,c2,c3;
  79.  
  80.     c3=getc(f);
  81.     c2=getc(f);
  82.     c1=getc(f);
  83.     c0=getc(f);
  84.  
  85. //printf("get_long %x %x %x %x\n",c3,c2,c1,c0);
  86.  
  87. //  if (c0==0xff) return(EOF);
  88.  
  89.     return(((long)c3<<24) + ((long)c2<<16) + ((long)c1<<8) + c0);
  90.  
  91. }
  92.  
  93. void parse_bmhd(FILE *ifile,long len,struct bitmap_header *bitmap_header)
  94. {
  95.     len++;  /* so no "parm not used" warning */
  96.  
  97. //  debug("parsing bmhd len=%ld\n",len);
  98.  
  99.     bitmap_header->w = get_word(ifile);
  100.     bitmap_header->h = get_word(ifile);
  101.     bitmap_header->x = get_word(ifile);
  102.     bitmap_header->y = get_word(ifile);
  103.  
  104.     bitmap_header->nplanes = get_byte(ifile);
  105.     bitmap_header->masking = get_byte(ifile);
  106.     bitmap_header->compression = get_byte(ifile);
  107.     get_byte(ifile);        /* skip pad */
  108.  
  109.     bitmap_header->transparentcolor = get_word(ifile);
  110.     bitmap_header->xaspect = get_byte(ifile);
  111.     bitmap_header->yaspect = get_byte(ifile);
  112.  
  113.     bitmap_header->pagewidth = get_word(ifile);
  114.     bitmap_header->pageheight = get_word(ifile);
  115.  
  116. //  debug("w,h=%d,%d x,y=%d,%d\n",w,h,x,y);
  117. //  debug("nplanes=%d, masking=%d ,compression=%d, transcolor=%d\n",nplanes,masking,compression,transparentcolor);
  118.  
  119. }
  120.  
  121.  
  122. //  the buffer pointed to by raw_data is stuffed with a pointer to decompressed pixel data
  123. int parse_body_pbm(FILE *ifile,long len,struct bitmap_header *bitmap_header)
  124. {
  125.     unsigned char  *p=bitmap_header->raw_data;
  126.     int width=bitmap_header->w;
  127.     long cnt,old_cnt;
  128.     signed char n;
  129.     int nn,wid_cnt;
  130.     char ignore;
  131.  
  132.     if (bitmap_header->compression == cmpNone) {        /* no compression */
  133.         int x,y;
  134.  
  135.         for (y=bitmap_header->h;y;y--) {
  136.             for (x=bitmap_header->w;x;x--) *p++=getc(ifile);
  137.             if (bitmap_header->w & 1) ignore = getc(ifile);
  138.         }
  139.  
  140.     }
  141.     else if (bitmap_header->compression == cmpByteRun1)
  142.         for (old_cnt=cnt=len,wid_cnt=width;cnt>0;) {
  143.             unsigned char c;
  144.  
  145.             if (old_cnt-cnt > 2048) {
  146. //              printf(".");
  147.                 old_cnt=cnt;
  148.             }
  149.  
  150.             if (wid_cnt <= 0) wid_cnt = width;
  151.  
  152.             n=getc(ifile);
  153.             if (n >= 0) {                       // copy next n+1 bytes from source, they are not compressed
  154.                 nn = (int) n+1;
  155.                 cnt -= nn+1;
  156.                 wid_cnt -= nn;
  157.                 if (wid_cnt==-1) --nn;
  158.                 while (nn--) *p++=getc(ifile);
  159.                 if (wid_cnt==-1) ignore = getc(ifile);      /* extra char */
  160.             }
  161.             else if (n>=-127) {             // next -n + 1 bytes are following byte
  162.                 cnt -= 2;
  163.                 c=getc(ifile);
  164.                 nn = (int) -n+1;
  165.                 wid_cnt -= nn;
  166.                 if (wid_cnt==-1) --nn;
  167.                 while (nn--) *p++=c;
  168.             }
  169.  
  170.         }
  171.  
  172.     if (len & 1) ignore = getc(ifile);
  173.  
  174.     if (ignore) ignore++;   // haha, suppress the evil warning message
  175.  
  176.     return IFF_NO_ERROR;
  177. }
  178.  
  179. //  the buffer pointed to by raw_data is stuffed with a pointer to bitplane pixel data
  180. int parse_body_ilbm(FILE *ifile,long len,struct bitmap_header *bitmap_header)
  181. {
  182.     unsigned char  *p=bitmap_header->raw_data;
  183.     int width=bitmap_header->w;
  184.     long cnt,old_cnt;
  185.     signed char n;
  186.     int nn,wid_cnt;
  187.     char    ignore;
  188.  
  189.     if (bitmap_header->compression == cmpNone) {        /* no compression */
  190.         int x,y;
  191.  
  192.         for (y=bitmap_header->h;y;y--) {
  193.             for (x=bitmap_header->w;x;x--) *p++=getc(ifile);
  194.             if (bitmap_header->w & 1) ignore = getc(ifile);
  195.         }
  196.  
  197.     }
  198.     else if (bitmap_header->compression == cmpByteRun1)
  199.         for (old_cnt=cnt=len,wid_cnt=width;cnt>0;) {
  200.             unsigned char c;
  201.  
  202.             if (old_cnt-cnt > 2048) {
  203. //              printf(".");
  204.                 old_cnt=cnt;
  205.             }
  206.  
  207.             if (wid_cnt <= 0) wid_cnt = width;
  208.  
  209.             n=getc(ifile);
  210.  
  211.             if (n >= 0) {                       // copy next n+1 bytes from source, they are not compressed
  212.                 nn = (int) n+1;
  213.                 cnt -= nn+1;
  214.                 wid_cnt -= nn;
  215.                 if (wid_cnt==-1) --nn;
  216.                 while (nn--) *p++=getc(ifile);
  217.                 if (wid_cnt==-1) ignore = getc(ifile);      /* extra char */
  218.             }
  219.             else if (n>=-127) {             // next -n + 1 bytes are following byte
  220.                 cnt -= 2;
  221.                 c=getc(ifile);
  222.                 nn = (int) -n+1;
  223.                 wid_cnt -= nn;
  224.                 if (wid_cnt==-1) --nn;
  225.                 while (nn--) *p++=c;
  226.             }
  227.  
  228.         }
  229.  
  230.     if (len & 1) ignore = getc(ifile);
  231.  
  232.     if (ignore) ignore++;   // haha, suppress the evil warning message
  233.  
  234.     return IFF_NO_ERROR;
  235. }
  236.  
  237. void skip_chunk(FILE *ifile,long len)
  238. {
  239.     len = len+1 & ~1;
  240.     fseek(ifile,len,SEEK_CUR);
  241. }
  242.  
  243. // Pass pointer to opened file, and to empty bitmap header.
  244. int parse_iff(FILE *ifile,struct bitmap_header *bitmap_header)
  245. {
  246.     long sig,form_len,len,form_type;
  247.     char    ignore;
  248.  
  249.     sig=get_sig(ifile);
  250.  
  251. //  printsig(sig);
  252.  
  253.     if (sig==form_sig) {
  254.  
  255.         form_len = get_long(ifile);
  256.         form_len++;     /* get rid of never used message */
  257.  
  258.         form_type = get_sig(ifile);
  259.  
  260. //      printf(" %ld ",form_len);
  261. //      printsig(form_type);
  262. //      printf("\n");
  263.  
  264.         if ((form_type == pbm_sig) || (form_type == ilbm_sig)) {
  265.  
  266.             if (form_type == pbm_sig)
  267.                 bitmap_header->type = PBM_TYPE;
  268.             else
  269.                 bitmap_header->type = ILBM_TYPE;
  270.  
  271.             while ((sig=get_sig(ifile)) != EOF) {
  272.  
  273.                 len=get_long(ifile);
  274.  
  275. //              printf(" ");
  276. //              printsig(sig);
  277. //              printf(" %ld\n",len);
  278.  
  279.                 switch (sig) {
  280.  
  281.                     case bmhd_sig:
  282.  
  283.                         parse_bmhd(ifile,len,bitmap_header);
  284.  
  285.                         if (! (bitmap_header->raw_data = malloc((long) bitmap_header->w * bitmap_header->h*3))) exit(1);
  286.  
  287.                         break;
  288.  
  289.                     case cmap_sig:
  290.                     {
  291.                         int ncolors=(int) (len/3),cnum;
  292.                         unsigned char r,g,b;
  293.  
  294.                         for (cnum=0;cnum<ncolors;cnum++) {
  295.                             r=getc(ifile);
  296.                             g=getc(ifile);
  297.                             b=getc(ifile);
  298.                             r >>= 2; bitmap_header->palette[cnum].r = r;
  299.                             g >>= 2; bitmap_header->palette[cnum].g = g;
  300.                             b >>= 2; bitmap_header->palette[cnum].b = b;
  301.                         }
  302.                         if (len & 1) ignore = getc(ifile);
  303.  
  304.                         break;
  305.                     }
  306.  
  307.                     case body_sig:
  308.                     {
  309.                         int r;
  310.                         switch (form_type) {
  311.                             case pbm_sig:
  312.                                 if (!(r=parse_body_pbm(ifile,len,bitmap_header))) return r;
  313.                                 break;
  314.                             case ilbm_sig:
  315.                                 if (!(r=parse_body_ilbm(ifile,len,bitmap_header))) return r;
  316.                                 break;
  317.                         }
  318.                         break;
  319.                     }
  320.                     default:
  321.                         skip_chunk(ifile,len);
  322.                         break;
  323.                 }
  324.             }
  325.         }
  326.         else return IFF_UNKNOWN_FORM;
  327.     }
  328.     else
  329.         {printf("Not an IFF file\n"); return IFF_NOT_IFF;}
  330.  
  331.     if (ignore) ignore++;
  332.  
  333.     return IFF_NO_ERROR;    /* ok! */
  334. }
  335.  
  336.