home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 December / PCWKCD1296.iso / sharewar / quake106 / utils / common / lbmlib.c < prev    next >
C/C++ Source or Header  |  1996-09-12  |  10KB  |  509 lines

  1. // lbmlib.c
  2.  
  3. #include "cmdlib.h"
  4. #include "lbmlib.h"
  5.  
  6.  
  7.  
  8. /*
  9. ============================================================================
  10.  
  11.                         LBM STUFF
  12.  
  13. ============================================================================
  14. */
  15.  
  16.  
  17. #define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
  18. #define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
  19. #define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
  20. #define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
  21. #define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
  22. #define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
  23.  
  24.  
  25. bmhd_t  bmhd;
  26.  
  27. int    Align (int l)
  28. {
  29.     if (l&1)
  30.         return l+1;
  31.     return l;
  32. }
  33.  
  34.  
  35.  
  36. /*
  37. ================
  38. =
  39. = LBMRLEdecompress
  40. =
  41. = Source must be evenly aligned!
  42. =
  43. ================
  44. */
  45.  
  46. byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
  47. {
  48.     int     count;
  49.     byte    b,rept;
  50.  
  51.     count = 0;
  52.  
  53.     do
  54.     {
  55.         rept = *source++;
  56.  
  57.         if (rept > 0x80)
  58.         {
  59.             rept = (rept^0xff)+2;
  60.             b = *source++;
  61.             memset(unpacked,b,rept);
  62.             unpacked += rept;
  63.         }
  64.         else if (rept < 0x80)
  65.         {
  66.             rept++;
  67.             memcpy(unpacked,source,rept);
  68.             unpacked += rept;
  69.             source += rept;
  70.         }
  71.         else
  72.             rept = 0;               // rept of 0x80 is NOP
  73.  
  74.         count += rept;
  75.  
  76.     } while (count<bpwidth);
  77.  
  78.     if (count>bpwidth)
  79.         Error ("Decompression exceeded width!\n");
  80.  
  81.  
  82.     return source;
  83. }
  84.  
  85.  
  86. #define BPLANESIZE      128
  87. byte    bitplanes[9][BPLANESIZE];       // max size 1024 by 9 bit planes
  88.  
  89.  
  90. /*
  91. =================
  92. =
  93. = MungeBitPlanes8
  94. =
  95. = This destroys the bit plane data!
  96. =
  97. =================
  98. */
  99.  
  100. void MungeBitPlanes8 (int width, byte *dest)
  101. {
  102.     *dest=width;    // shut up the compiler warning
  103.     Error ("MungeBitPlanes8 not rewritten!");
  104. #if 0
  105. asm     les     di,[dest]
  106. asm     mov     si,-1
  107. asm     mov     cx,[width]
  108. mungebyte:
  109. asm     inc     si
  110. asm     mov     dx,8
  111. mungebit:
  112. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*7 +si],1
  113. asm     rcl     al,1
  114. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*6 +si],1
  115. asm     rcl     al,1
  116. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*5 +si],1
  117. asm     rcl     al,1
  118. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*4 +si],1
  119. asm     rcl     al,1
  120. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*3 +si],1
  121. asm     rcl     al,1
  122. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*2 +si],1
  123. asm     rcl     al,1
  124. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*1 +si],1
  125. asm     rcl     al,1
  126. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*0 +si],1
  127. asm     rcl     al,1
  128. asm     stosb
  129. asm     dec     cx
  130. asm     jz      done
  131. asm     dec     dx
  132. asm     jnz     mungebit
  133. asm     jmp     mungebyte
  134.  
  135. done:
  136. #endif
  137. }
  138.  
  139.  
  140. void MungeBitPlanes4 (int width, byte *dest)
  141. {
  142.     *dest=width;    // shut up the compiler warning
  143.     Error ("MungeBitPlanes4 not rewritten!");
  144. #if 0
  145.  
  146. asm     les     di,[dest]
  147. asm     mov     si,-1
  148. asm     mov     cx,[width]
  149. mungebyte:
  150. asm     inc     si
  151. asm     mov     dx,8
  152. mungebit:
  153. asm     xor     al,al
  154. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*3 +si],1
  155. asm     rcl     al,1
  156. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*2 +si],1
  157. asm     rcl     al,1
  158. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*1 +si],1
  159. asm     rcl     al,1
  160. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*0 +si],1
  161. asm     rcl     al,1
  162. asm     stosb
  163. asm     dec     cx
  164. asm     jz      done
  165. asm     dec     dx
  166. asm     jnz     mungebit
  167. asm     jmp     mungebyte
  168.  
  169. done:
  170. #endif
  171. }
  172.  
  173.  
  174. void MungeBitPlanes2 (int width, byte *dest)
  175. {
  176.     *dest=width;    // shut up the compiler warning
  177.     Error ("MungeBitPlanes2 not rewritten!");
  178. #if 0
  179. asm     les     di,[dest]
  180. asm     mov     si,-1
  181. asm     mov     cx,[width]
  182. mungebyte:
  183. asm     inc     si
  184. asm     mov     dx,8
  185. mungebit:
  186. asm     xor     al,al
  187. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*1 +si],1
  188. asm     rcl     al,1
  189. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*0 +si],1
  190. asm     rcl     al,1
  191. asm     stosb
  192. asm     dec     cx
  193. asm     jz      done
  194. asm     dec     dx
  195. asm     jnz     mungebit
  196. asm     jmp     mungebyte
  197.  
  198. done:
  199. #endif
  200. }
  201.  
  202.  
  203. void MungeBitPlanes1 (int width, byte *dest)
  204. {
  205.     *dest=width;    // shut up the compiler warning
  206.     Error ("MungeBitPlanes1 not rewritten!");
  207. #if 0
  208. asm     les     di,[dest]
  209. asm     mov     si,-1
  210. asm     mov     cx,[width]
  211. mungebyte:
  212. asm     inc     si
  213. asm     mov     dx,8
  214. mungebit:
  215. asm     xor     al,al
  216. asm     shl     [BYTE PTR bitplanes + BPLANESIZE*0 +si],1
  217. asm     rcl     al,1
  218. asm     stosb
  219. asm     dec     cx
  220. asm     jz      done
  221. asm     dec     dx
  222. asm     jnz     mungebit
  223. asm     jmp     mungebyte
  224.  
  225. done:
  226. #endif
  227. }
  228.  
  229.  
  230. /*
  231. =================
  232. =
  233. = LoadLBM
  234. =
  235. =================
  236. */
  237.  
  238. void LoadLBM (char *filename, byte **picture, byte **palette)
  239. {
  240.     byte    *LBMbuffer, *picbuffer, *cmapbuffer;
  241.     int             y,p,planes;
  242.     byte    *LBM_P, *LBMEND_P;
  243.     byte    *pic_p;
  244.     byte    *body_p;
  245.     unsigned        rowsize;
  246.  
  247.     int    formtype,formlength;
  248.     int    chunktype,chunklength;
  249.     void    (*mungecall) (int, byte *);
  250.  
  251. // qiet compiler warnings
  252.     picbuffer = NULL;
  253.     cmapbuffer = NULL;
  254.     mungecall = NULL;
  255.  
  256. //
  257. // load the LBM
  258. //
  259.     LoadFile (filename, (void **)&LBMbuffer);
  260.  
  261. //
  262. // parse the LBM header
  263. //
  264.     LBM_P = LBMbuffer;
  265.     if ( *(int *)LBMbuffer != LittleLong(FORMID) )
  266.        Error ("No FORM ID at start of file!\n");
  267.  
  268.     LBM_P += 4;
  269.     formlength = BigLong( *(int *)LBM_P );
  270.     LBM_P += 4;
  271.     LBMEND_P = LBM_P + Align(formlength);
  272.  
  273.     formtype = LittleLong(*(int *)LBM_P);
  274.  
  275.     if (formtype != ILBMID && formtype != PBMID)
  276.         Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
  277.         ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
  278.  
  279.     LBM_P += 4;
  280.  
  281. //
  282. // parse chunks
  283. //
  284.  
  285.     while (LBM_P < LBMEND_P)
  286.     {
  287.         chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
  288.         LBM_P += 4;
  289.         chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
  290.         LBM_P += 4;
  291.  
  292.         switch ( chunktype )
  293.         {
  294.         case BMHDID:
  295.             memcpy (&bmhd,LBM_P,sizeof(bmhd));
  296.             bmhd.w = BigShort(bmhd.w);
  297.             bmhd.h = BigShort(bmhd.h);
  298.             bmhd.x = BigShort(bmhd.x);
  299.             bmhd.y = BigShort(bmhd.y);
  300.             bmhd.pageWidth = BigShort(bmhd.pageWidth);
  301.             bmhd.pageHeight = BigShort(bmhd.pageHeight);
  302.             break;
  303.  
  304.         case CMAPID:
  305.             cmapbuffer = malloc (768);
  306.             memset (cmapbuffer, 0, 768);
  307.             memcpy (cmapbuffer, LBM_P, chunklength);
  308.             break;
  309.  
  310.         case BODYID:
  311.             body_p = LBM_P;
  312.  
  313.             pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
  314.             if (formtype == PBMID)
  315.             {
  316.             //
  317.             // unpack PBM
  318.             //
  319.                 for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
  320.                 {
  321.                     if (bmhd.compression == cm_rle1)
  322.                         body_p = LBMRLEDecompress ((byte *)body_p
  323.                         , pic_p , bmhd.w);
  324.                     else if (bmhd.compression == cm_none)
  325.                     {
  326.                         memcpy (pic_p,body_p,bmhd.w);
  327.                         body_p += Align(bmhd.w);
  328.                     }
  329.                 }
  330.  
  331.             }
  332.             else
  333.             {
  334.             //
  335.             // unpack ILBM
  336.             //
  337.                 planes = bmhd.nPlanes;
  338.                 if (bmhd.masking == ms_mask)
  339.                     planes++;
  340.                 rowsize = (bmhd.w+15)/16 * 2;
  341.                 switch (bmhd.nPlanes)
  342.                 {
  343.                 case 1:
  344.                     mungecall = MungeBitPlanes1;
  345.                     break;
  346.                 case 2:
  347.                     mungecall = MungeBitPlanes2;
  348.                     break;
  349.                 case 4:
  350.                     mungecall = MungeBitPlanes4;
  351.                     break;
  352.                 case 8:
  353.                     mungecall = MungeBitPlanes8;
  354.                     break;
  355.                 default:
  356.                     Error ("Can't munge %i bit planes!\n",bmhd.nPlanes);
  357.                 }
  358.  
  359.                 for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
  360.                 {
  361.                     for (p=0 ; p<planes ; p++)
  362.                         if (bmhd.compression == cm_rle1)
  363.                             body_p = LBMRLEDecompress ((byte *)body_p
  364.                             , bitplanes[p] , rowsize);
  365.                         else if (bmhd.compression == cm_none)
  366.                         {
  367.                             memcpy (bitplanes[p],body_p,rowsize);
  368.                             body_p += rowsize;
  369.                         }
  370.  
  371.                     mungecall (bmhd.w , pic_p);
  372.                 }
  373.             }
  374.             break;
  375.         }
  376.  
  377.         LBM_P += Align(chunklength);
  378.     }
  379.  
  380.     free (LBMbuffer);
  381.  
  382.     *picture = picbuffer;
  383.     *palette = cmapbuffer;
  384. }
  385.  
  386.  
  387. /*
  388. ============================================================================
  389.  
  390.                             WRITE LBM
  391.  
  392. ============================================================================
  393. */
  394.  
  395. /*
  396. ==============
  397. =
  398. = WriteLBMfile
  399. =
  400. ==============
  401. */
  402.  
  403. void WriteLBMfile (char *filename, byte *data, int width, int height, byte *palette)
  404. {
  405.     byte    *lbm, *lbmptr;
  406.     int    *formlength, *bmhdlength, *cmaplength, *bodylength;
  407.     int    length;
  408.     bmhd_t  basebmhd;
  409.  
  410.     lbm = lbmptr = malloc (width*height+1000);
  411.  
  412. //
  413. // start FORM
  414. //
  415.     *lbmptr++ = 'F';
  416.     *lbmptr++ = 'O';
  417.     *lbmptr++ = 'R';
  418.     *lbmptr++ = 'M';
  419.  
  420.     formlength = (int*)lbmptr;
  421.     lbmptr+=4;                      // leave space for length
  422.  
  423.     *lbmptr++ = 'P';
  424.     *lbmptr++ = 'B';
  425.     *lbmptr++ = 'M';
  426.     *lbmptr++ = ' ';
  427.  
  428. //
  429. // write BMHD
  430. //
  431.     *lbmptr++ = 'B';
  432.     *lbmptr++ = 'M';
  433.     *lbmptr++ = 'H';
  434.     *lbmptr++ = 'D';
  435.  
  436.     bmhdlength = (int *)lbmptr;
  437.     lbmptr+=4;                      // leave space for length
  438.  
  439.     memset (&basebmhd,0,sizeof(basebmhd));
  440.     basebmhd.w = BigShort((short)width);
  441.     basebmhd.h = BigShort((short)height);
  442.     basebmhd.nPlanes = BigShort(8);
  443.     basebmhd.xAspect = BigShort(5);
  444.     basebmhd.yAspect = BigShort(6);
  445.     basebmhd.pageWidth = BigShort((short)width);
  446.     basebmhd.pageHeight = BigShort((short)height);
  447.  
  448.     memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
  449.     lbmptr += sizeof(basebmhd);
  450.  
  451.     length = lbmptr-(byte *)bmhdlength-4;
  452.     *bmhdlength = BigLong(length);
  453.     if (length&1)
  454.         *lbmptr++ = 0;          // pad chunk to even offset
  455.  
  456. //
  457. // write CMAP
  458. //
  459.     *lbmptr++ = 'C';
  460.     *lbmptr++ = 'M';
  461.     *lbmptr++ = 'A';
  462.     *lbmptr++ = 'P';
  463.  
  464.     cmaplength = (int *)lbmptr;
  465.     lbmptr+=4;                      // leave space for length
  466.  
  467.     memcpy (lbmptr,palette,768);
  468.     lbmptr += 768;
  469.  
  470.     length = lbmptr-(byte *)cmaplength-4;
  471.     *cmaplength = BigLong(length);
  472.     if (length&1)
  473.         *lbmptr++ = 0;          // pad chunk to even offset
  474.  
  475. //
  476. // write BODY
  477. //
  478.     *lbmptr++ = 'B';
  479.     *lbmptr++ = 'O';
  480.     *lbmptr++ = 'D';
  481.     *lbmptr++ = 'Y';
  482.  
  483.     bodylength = (int *)lbmptr;
  484.     lbmptr+=4;                      // leave space for length
  485.  
  486.     memcpy (lbmptr,data,width*height);
  487.     lbmptr += width*height;
  488.  
  489.     length = lbmptr-(byte *)bodylength-4;
  490.     *bodylength = BigLong(length);
  491.     if (length&1)
  492.         *lbmptr++ = 0;          // pad chunk to even offset
  493.  
  494. //
  495. // done
  496. //
  497.     length = lbmptr-(byte *)formlength-4;
  498.     *formlength = BigLong(length);
  499.     if (length&1)
  500.         *lbmptr++ = 0;          // pad chunk to even offset
  501.  
  502. //
  503. // write output file
  504. //
  505.     SaveFile (filename, lbm, lbmptr-lbm);
  506.     free (lbm);
  507. }
  508.  
  509.