Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  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.  
  495.