home *** CD-ROM | disk | FTP | other *** search
/ hobbes.nmsu.edu 2008 / 2008-06-02_hobbes.nmsu.edu.zip / new / scummc-0.2.0-os2.zip / ScummC / src / decode.c < prev    next >
Encoding:
C/C++ Source or Header  |  2007-12-18  |  10.7 KB  |  514 lines

  1. /* ScummC
  2.  * Copyright (C) 2004-2006  Alban Bedel
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17.  *
  18.  */
  19.  
  20. /**
  21.  * @file decode.c
  22.  * @ingroup scumm
  23.  * @brief SCUMM image decoders
  24.  */
  25.  
  26. #include "config.h"
  27.  
  28. #include <inttypes.h>
  29. #include <stdlib.h>
  30. #include <unistd.h>
  31. #include <stdio.h>
  32. #include <errno.h>
  33. #include <string.h>
  34.  
  35. #include "scc_fd.h"
  36. #include "scc_util.h"
  37.  
  38. #define READ_BIT (cl--, bit = bits&1, bits>>=1, bit)
  39. #define FILL_BITS if(cl < 8) { \
  40.   bits |= (*src++) << cl; \
  41.   cl += 8; \
  42.  
  43.  
  44. static void unkDecodeA(uint8_t *dst, int dst_stride,
  45.                uint8_t *src, int height,
  46.                uint32_t palette_mod,
  47.                uint32_t decomp_mask,uint32_t decomp_shr) {
  48.   uint8_t color = *src++;
  49.   uint32_t bits = *src++;
  50.   uint8_t cl = 8;
  51.   uint8_t bit;
  52.   int16_t incm, reps;
  53.  
  54.   //  printf("Start data: %x %x %x %x\n",color,bits,src[0],src[1]);
  55.   
  56.   do {
  57.     int x = 8;
  58.     do {
  59.       FILL_BITS;
  60.       *dst++ = color + palette_mod;
  61.       
  62.     againPos:
  63.       if (!READ_BIT) {
  64.       } else if (!READ_BIT) {
  65.     FILL_BITS;
  66.     color = bits & decomp_mask;
  67.     bits >>= decomp_shr;
  68.     cl -= decomp_shr;
  69.       } else {
  70.     incm = (bits & 7) - 4;
  71.     cl -= 3;
  72.     bits >>= 3;
  73.     if (incm) {
  74.       color += incm;
  75.     } else {
  76.       FILL_BITS;
  77.       reps = bits & 0xFF;
  78.       do {
  79.         if (!--x) {
  80.           x = 8;
  81.           dst += dst_stride - 8;
  82.           if (!--height)
  83.         return;
  84.         }
  85.         *dst++ = color + palette_mod;
  86.       } while (--reps);
  87.       bits >>= 8;
  88.       bits |= (*src++) << (cl - 8);
  89.       goto againPos;
  90.     }
  91.       }
  92.       x--;
  93.     } while (x);
  94.     dst += dst_stride - 8;
  95.     height--;
  96.   } while (height);
  97. }
  98.  
  99.  
  100. static void unkDecodeA_trans(uint8_t *dst, int dst_stride,
  101.                  uint8_t *src, int height,
  102.                  uint32_t palette_mod,uint8_t transparentColor,
  103.                  uint32_t decomp_mask,uint32_t decomp_shr) {
  104.   uint8_t color = *src++;
  105.   uint32_t bits = *src++;
  106.   uint8_t cl = 8;
  107.   uint8_t bit;
  108.   uint8_t incm, reps;
  109.  
  110.   do {
  111.     int x = 8;
  112.     do {
  113.       FILL_BITS;
  114.       if (color != transparentColor)
  115.     *dst = color + palette_mod;
  116.       dst++;
  117.       
  118.     againPos:
  119.       if (!READ_BIT) {
  120.       } else if (!READ_BIT) {
  121.     FILL_BITS;
  122.     color = bits & decomp_mask;
  123.     bits >>= decomp_shr;
  124.     cl -= decomp_shr;
  125.       } else {
  126.     incm = (bits & 7) - 4;
  127.     cl -= 3;
  128.     bits >>= 3;
  129.     if (incm) {
  130.       color += incm;
  131.     } else {
  132.       FILL_BITS;
  133.       reps = bits & 0xFF;
  134.       do {
  135.         if (!--x) {
  136.           x = 8;
  137.           dst += dst_stride - 8;
  138.           if (!--height)
  139.         return;
  140.         }
  141.         if (color != transparentColor)
  142.           *dst = color + palette_mod;
  143.         dst++;
  144.       } while (--reps);
  145.       bits >>= 8;
  146.       bits |= (*src++) << (cl - 8);
  147.       goto againPos;
  148.     }
  149.       }
  150.     } while (--x);
  151.     dst += dst_stride - 8;
  152.   } while (--height);
  153. }
  154.  
  155. void unkDecodeB(uint8_t *dst, int dst_stride,
  156.         uint8_t *src, int height,
  157.         uint32_t palette_mod,
  158.         uint32_t decomp_mask,uint32_t decomp_shr) {
  159.   uint8_t color = *src++;
  160.   uint32_t bits = *src++;
  161.   uint8_t cl = 8;
  162.   uint8_t bit;
  163.   int8_t inc = -1;
  164.   
  165.   do {
  166.     int x = 8;
  167.     do {
  168.       FILL_BITS;
  169.       *dst++ = color + palette_mod;
  170.       if (!READ_BIT) {
  171.       } else if (!READ_BIT) {
  172.     FILL_BITS;
  173.     color = bits & decomp_mask;
  174.     bits >>= decomp_shr;
  175.     cl -= decomp_shr;
  176.     inc = -1;
  177.       } else if (!READ_BIT) {
  178.     color += inc;
  179.       } else {
  180.     inc = -inc;
  181.     color += inc;
  182.       }
  183.     } while (--x);
  184.     dst += dst_stride - 8;
  185.   } while (--height);
  186. }
  187.  
  188. void unkDecodeB_trans(uint8_t *dst, int dst_stride,
  189.               uint8_t *src, int height,
  190.               uint32_t palette_mod,uint8_t transparentColor,
  191.               uint32_t decomp_mask,uint32_t decomp_shr) {
  192.   uint8_t color = *src++;
  193.   uint32_t bits = *src++;
  194.   uint8_t cl = 8;
  195.   uint8_t bit;
  196.   int8_t inc = -1;
  197.  
  198.   do {
  199.     int x = 8;
  200.     do {
  201.       FILL_BITS;
  202.       if (color != transparentColor)
  203.     *dst = color + palette_mod;
  204.       dst++;
  205.       if (!READ_BIT) {
  206.       } else if (!READ_BIT) {
  207.     FILL_BITS;
  208.     color = bits & decomp_mask;
  209.     bits >>= decomp_shr;
  210.     cl -= decomp_shr;
  211.     inc = -1;
  212.       } else if (!READ_BIT) {
  213.     color += inc;
  214.       } else {
  215.     inc = -inc;
  216.     color += inc;
  217.       }
  218.     } while (--x);
  219.     dst += dst_stride - 8;
  220.   } while (--height);
  221. }
  222.  
  223. void unkDecodeC(uint8_t *dst, int dst_stride,
  224.         uint8_t *src, int height,
  225.         uint32_t palette_mod,
  226.         uint32_t decomp_mask,uint32_t decomp_shr) {
  227.   uint8_t color = *src++;
  228.   uint32_t bits = *src++;
  229.   uint8_t cl = 8;
  230.   uint8_t bit;
  231.   int8_t inc = -1;
  232.   
  233.   int x = 8;
  234.   do {
  235.     int h = height;
  236.     do {
  237.       FILL_BITS;
  238.       *dst = color + palette_mod;
  239.       dst += dst_stride;
  240.       if (!READ_BIT) {
  241.       } else if (!READ_BIT) {
  242.     FILL_BITS;
  243.     color = bits & decomp_mask;
  244.     bits >>= decomp_shr;
  245.     cl -= decomp_shr;
  246.     inc = -1;
  247.       } else if (!READ_BIT) {
  248.     color += inc;
  249.       } else {
  250.     inc = -inc;
  251.     color += inc;
  252.       }
  253.     } while (--h);
  254.     dst -= height*dst_stride - 1;
  255.   } while (--x);
  256. }
  257.  
  258. void unkDecodeC_trans(uint8_t *dst, int dst_stride,
  259.                  uint8_t *src, int height,
  260.                  uint32_t palette_mod,uint8_t transparentColor,
  261.                  uint32_t decomp_mask,uint32_t decomp_shr) {
  262.   uint8_t color = *src++;
  263.   uint32_t bits = *src++;
  264.   uint8_t cl = 8;
  265.   uint8_t bit;
  266.   int8_t inc = -1;
  267.  
  268.   int x = 8;
  269.   do {
  270.     int h = height;
  271.     do {
  272.       FILL_BITS;
  273.       if (color != transparentColor)
  274.     *dst = color + palette_mod;
  275.       dst += dst_stride;
  276.       if (!READ_BIT) {
  277.       } else if (!READ_BIT) {
  278.     FILL_BITS;
  279.     color = bits & decomp_mask;
  280.     bits >>= decomp_shr;
  281.     cl -= decomp_shr;
  282.     inc = -1;
  283.       } else if (!READ_BIT) {
  284.     color += inc;
  285.       } else {
  286.     inc = -inc;
  287.     color += inc;
  288.       }
  289.     } while (--h);
  290.     dst -= height*dst_stride - 1;
  291.   } while (--x);
  292. }
  293.  
  294.  
  295. int scc_decode_image(uint8_t* dst, int dst_stride,
  296.              int width,int height,
  297.              uint8_t* smap,uint32_t smap_size,
  298.              int transparentColor) {
  299.   int i,offs = (width/8);
  300.   uint8_t type;
  301.   uint32_t decomp_shr,decomp_mask;
  302.   int stripe_size;
  303.   int have_trans = 0;
  304.  
  305.   scc_log(LOG_V,"\nDecode image: %dx%d smap: %d\n",width,height,smap_size);
  306.  
  307.   for(i = 0 ; i < offs ; i++) {
  308.     int o = ((uint32_t*)smap)[i]-8;
  309.     if(i+1 < offs)
  310.       stripe_size = ((uint32_t*)smap)[i+1] - ((uint32_t*)smap)[i];
  311.     else
  312.       stripe_size = smap_size-o;
  313.     stripe_size -= 1;
  314.     //scc_log(LOG_V,"Stripe %d: 0x%x\n",i,o);
  315.     type = smap[o];
  316.     scc_log(LOG_V,"SMAP type: %d (0x%x)\n",type,type);
  317.     decomp_shr = type % 10;
  318.     decomp_mask = 0xFF >> (8 - decomp_shr);
  319.  
  320.     scc_log(LOG_V,"Decomp_shr: %d (0x%x)\n",decomp_shr,decomp_mask);
  321.  
  322.     switch(type) {
  323.     case 14:
  324.     case 15:
  325.     case 16:
  326.     case 17:
  327.     case 18:
  328.       unkDecodeC(dst + i*8,dst_stride,&smap[o+1],
  329.          height,0,
  330.          decomp_mask,decomp_shr);
  331.       //check_coder(dst + i*8,dst_stride,&smap[o+1],stripe_size,height,unkCodeC,unkDecodeC);
  332.       break;
  333.  
  334.     case 24:
  335.     case 25:
  336.     case 26:
  337.     case 27:
  338.     case 28:
  339.       unkDecodeB(dst + i*8,dst_stride,&smap[o+1],
  340.          height,0,
  341.          decomp_mask,decomp_shr);
  342.       //check_coder(dst + i*8,dst_stride,&smap[o+1],stripe_size,height,unkCodeB,unkDecodeB);
  343.       break;
  344.  
  345.     case 34:
  346.     case 35:
  347.     case 36:
  348.     case 37:
  349.     case 38:
  350.       have_trans = 1;
  351.       if(transparentColor < 0)
  352.     unkDecodeC(dst + i*8,dst_stride,&smap[o+1],
  353.            height,0,
  354.            decomp_mask,decomp_shr);
  355.       else
  356.     unkDecodeC_trans(dst + i*8,dst_stride,&smap[o+1],
  357.              height,0,transparentColor,
  358.              decomp_mask,decomp_shr);
  359.       //check_coder(dst + i*8,dst_stride,&smap[o+1],stripe_size,height,unkCodeC,unkDecodeC);
  360.       break;
  361.  
  362.     case 44:
  363.     case 45:
  364.     case 46:
  365.     case 47:
  366.     case 48:
  367.       have_trans = 1;
  368.       if(transparentColor < 0)
  369.     unkDecodeB(dst + i*8,dst_stride,&smap[o+1],
  370.            height,0,
  371.            decomp_mask,decomp_shr);
  372.       else
  373.     unkDecodeB_trans(dst + i*8,dst_stride,&smap[o+1],
  374.              height,0,transparentColor,
  375.              decomp_mask,decomp_shr);
  376.       //check_coder(dst + i*8,dst_stride,&smap[o+1],stripe_size,height,unkCodeB,unkDecodeB);
  377.       break;
  378.     case 64:
  379.     case 65:
  380.     case 66:
  381.     case 67:
  382.     case 68:
  383.       unkDecodeA(dst + i*8,dst_stride,&smap[o+1],
  384.          height,0,
  385.          decomp_mask,decomp_shr);
  386.       //check_coder(dst + i*8,dst_stride,&smap[o+1],stripe_size,height,unkCodeA6,unkDecodeA);
  387.       break;
  388.     case 104:
  389.     case 105:
  390.     case 106:
  391.     case 107:
  392.     case 108:
  393.       unkDecodeA(dst + i*8,dst_stride,&smap[o+1],
  394.          height,0,
  395.          decomp_mask,decomp_shr);
  396.       //check_coder(dst + i*8,dst_stride,&smap[o+1],stripe_size,height,unkCodeA,unkDecodeA);
  397.       break;
  398.     case 84:
  399.     case 85:
  400.     case 86:
  401.     case 87:
  402.     case 88:
  403.     case 124:
  404.     case 125:
  405.     case 126:
  406.     case 127:
  407.     case 128:
  408.       have_trans = 1;
  409.       if(transparentColor < 0)
  410.     unkDecodeA(dst + i*8,dst_stride,&smap[o+1],
  411.            height,0,
  412.            decomp_mask,decomp_shr);
  413.       else
  414.     unkDecodeA_trans(dst + i*8,dst_stride,&smap[o+1],
  415.              height,0,transparentColor,
  416.              decomp_mask,decomp_shr);
  417.  
  418.       //check_coder(dst + i*8,dst_stride,&smap[o+1],stripe_size,height,unkCodeA,unkDecodeA);
  419.       break;
  420.     default:
  421.       scc_log(LOG_ERR,"Unknown image coding: %d\n",type);
  422.       break;
  423.     }
  424.   }
  425.  
  426.   return 1+have_trans;
  427. }
  428.  
  429. static void decompMask(uint8_t *dst, int dst_stride,
  430.                uint8_t *src, int height) {
  431.  
  432.   uint8_t b, c;
  433.  
  434.   while (height) {
  435.     b = *src++;
  436.     
  437.     if (b & 0x80) {
  438.       b &= 0x7F;
  439.       c = *src++;
  440.  
  441.       do {
  442.     *dst = c;
  443.     dst += dst_stride;
  444.     --height;
  445.       } while (--b && height);
  446.     } else {
  447.       do {
  448.     *dst = *src++;
  449.     dst += dst_stride;
  450.     --height;
  451.       } while (--b && height);
  452.     }
  453.   }
  454. }
  455.  
  456. static void decompMaskOr(uint8_t *dst, int dst_stride,
  457.              uint8_t *src, int height) {
  458.  
  459.   uint8_t b, c;
  460.  
  461.   while (height) {
  462.     b = *src++;
  463.     
  464.     if (b & 0x80) {
  465.       b &= 0x7F;
  466.       c = *src++;
  467.  
  468.       do {
  469.     *dst |= c;
  470.     dst += dst_stride;
  471.     --height;
  472.       } while (--b && height);
  473.     } else {
  474.       do {
  475.     *dst |= *src++;
  476.     dst += dst_stride;
  477.     --height;
  478.       } while (--b && height);
  479.     }
  480.   }
  481. }
  482.  
  483. int scc_decode_zbuf(uint8_t* dst, int dst_stride,
  484.             int width,int height,
  485.             uint8_t* zmap,uint32_t zmap_size,int or) {
  486.   int stripes = width/8;
  487.   int i;
  488.  
  489.   if(width != stripes*8) {
  490.     scc_log(LOG_V,"Can't decode zbuf if width %% 8 != 0 !!\n");
  491.     return 0;
  492.   }
  493.  
  494.   for(i = 0 ; i < stripes ; i++) {
  495.     int o = ((uint16_t*)zmap)[i];
  496.     
  497.     if(o) {
  498.       o -= 8;
  499.       if(or)
  500.     decompMaskOr(&dst[i],dst_stride,
  501.              &zmap[o],height);
  502.       else
  503.     decompMask(&dst[i],dst_stride,
  504.            &zmap[o],height);
  505.     } else {
  506.       int j;
  507.       for(j = 0 ; j < height ; j++)
  508.     dst[i+j*dst_stride] = 0;
  509.     }
  510.   }
  511.   return 1;
  512. }
  513.