home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 22 / PCPP #22.iso / Quake2 / q2source_12_11 / utils3 / qdata / video.c < prev   
Encoding:
C/C++ Source or Header  |  1997-11-11  |  22.7 KB  |  1,238 lines

  1. #include "qdata.h"
  2.  
  3. byte    *soundtrack;
  4. char    base[32];
  5.  
  6. /*
  7. ===============================================================================
  8.  
  9. WAV loading
  10.  
  11. ===============================================================================
  12. */
  13.  
  14. typedef struct
  15. {
  16.     int            rate;
  17.     int            width;
  18.     int            channels;
  19.     int            loopstart;
  20.     int            samples;
  21.     int            dataofs;        // chunk starts this many bytes from file start
  22. } wavinfo_t;
  23.  
  24.  
  25. byte    *data_p;
  26. byte     *iff_end;
  27. byte     *last_chunk;
  28. byte     *iff_data;
  29. int     iff_chunk_len;
  30.  
  31.  
  32. int        samplecounts[0x10000];
  33.  
  34. wavinfo_t    wavinfo;
  35.  
  36. short GetLittleShort(void)
  37. {
  38.     short val = 0;
  39.     val = *data_p;
  40.     val = val + (*(data_p+1)<<8);
  41.     data_p += 2;
  42.     return val;
  43. }
  44.  
  45. int GetLittleLong(void)
  46. {
  47.     int val = 0;
  48.     val = *data_p;
  49.     val = val + (*(data_p+1)<<8);
  50.     val = val + (*(data_p+2)<<16);
  51.     val = val + (*(data_p+3)<<24);
  52.     data_p += 4;
  53.     return val;
  54. }
  55.  
  56. void FindNextChunk(char *name)
  57. {
  58.     while (1)
  59.     {
  60.         data_p=last_chunk;
  61.  
  62.         if (data_p >= iff_end)
  63.         {    // didn't find the chunk
  64.             data_p = NULL;
  65.             return;
  66.         }
  67.         
  68.         data_p += 4;
  69.         iff_chunk_len = GetLittleLong();
  70.         if (iff_chunk_len < 0)
  71.         {
  72.             data_p = NULL;
  73.             return;
  74.         }
  75. //        if (iff_chunk_len > 1024*1024)
  76. //            Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
  77.         data_p -= 8;
  78.         last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
  79.         if (!strncmp(data_p, name, 4))
  80.             return;
  81.     }
  82. }
  83.  
  84. void FindChunk(char *name)
  85. {
  86.     last_chunk = iff_data;
  87.     FindNextChunk (name);
  88. }
  89.  
  90.  
  91. void DumpChunks(void)
  92. {
  93.     char    str[5];
  94.     
  95.     str[4] = 0;
  96.     data_p=iff_data;
  97.     do
  98.     {
  99.         memcpy (str, data_p, 4);
  100.         data_p += 4;
  101.         iff_chunk_len = GetLittleLong();
  102.         printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
  103.         data_p += (iff_chunk_len + 1) & ~1;
  104.     } while (data_p < iff_end);
  105. }
  106.  
  107. /*
  108. ============
  109. GetWavinfo
  110. ============
  111. */
  112. wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
  113. {
  114.     wavinfo_t    info;
  115.     int     i;
  116.     int     format;
  117.     int        samples;
  118.  
  119.     memset (&info, 0, sizeof(info));
  120.  
  121.     if (!wav)
  122.         return info;
  123.         
  124.     iff_data = wav;
  125.     iff_end = wav + wavlength;
  126.  
  127. // find "RIFF" chunk
  128.     FindChunk("RIFF");
  129.     if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
  130.     {
  131.         printf("Missing RIFF/WAVE chunks\n");
  132.         return info;
  133.     }
  134.  
  135. // get "fmt " chunk
  136.     iff_data = data_p + 12;
  137. // DumpChunks ();
  138.  
  139.     FindChunk("fmt ");
  140.     if (!data_p)
  141.     {
  142.         printf("Missing fmt chunk\n");
  143.         return info;
  144.     }
  145.     data_p += 8;
  146.     format = GetLittleShort();
  147.     if (format != 1)
  148.     {
  149.         printf("Microsoft PCM format only\n");
  150.         return info;
  151.     }
  152.  
  153.     info.channels = GetLittleShort();
  154.     info.rate = GetLittleLong();
  155.     data_p += 4+2;
  156.     info.width = GetLittleShort() / 8;
  157.  
  158. // get cue chunk
  159.     FindChunk("cue ");
  160.     if (data_p)
  161.     {
  162.         data_p += 32;
  163.         info.loopstart = GetLittleLong();
  164. //        Com_Printf("loopstart=%d\n", sfx->loopstart);
  165.  
  166.     // if the next chunk is a LIST chunk, look for a cue length marker
  167.         FindNextChunk ("LIST");
  168.         if (data_p)
  169.         {
  170.             if (!strncmp (data_p + 28, "mark", 4))
  171.             {    // this is not a proper parse, but it works with cooledit...
  172.                 data_p += 24;
  173.                 i = GetLittleLong ();    // samples in loop
  174.                 info.samples = info.loopstart + i;
  175.             }
  176.         }
  177.     }
  178.     else
  179.         info.loopstart = -1;
  180.  
  181. // find data chunk
  182.     FindChunk("data");
  183.     if (!data_p)
  184.     {
  185.         printf("Missing data chunk\n");
  186.         return info;
  187.     }
  188.  
  189.     data_p += 4;
  190.     samples = GetLittleLong ();
  191.  
  192.     if (info.samples)
  193.     {
  194.         if (samples < info.samples)
  195.             Error ("Sound %s has a bad loop length", name);
  196.     }
  197.     else
  198.         info.samples = samples;
  199.  
  200.     info.dataofs = data_p - wav;
  201.  
  202.     return info;
  203. }
  204.  
  205. //=====================================================================
  206.  
  207. /*
  208. ==============
  209. LoadSoundtrack
  210. ==============
  211. */
  212. void LoadSoundtrack (void)
  213. {
  214.     char    name[1024];
  215.     FILE    *f;
  216.     int        len;
  217.     int     i, val, j;
  218.  
  219.     soundtrack = NULL;
  220.     sprintf (name, "%svideo/%s/%s.wav", gamedir, base, base);
  221.     printf ("%s\n", name);
  222.     f = fopen (name, "rb");
  223.     if (!f)
  224.     {
  225.         printf ("no soundtrack for %s\n", base);
  226.         return;
  227.     }
  228.     len = Q_filelength(f);
  229.     soundtrack = malloc(len);
  230.     fread (soundtrack, 1, len, f);
  231.     fclose (f);
  232.  
  233.     wavinfo = GetWavinfo (name, soundtrack, len);
  234.  
  235.     // count samples for compression
  236.     memset (samplecounts, 0, sizeof(samplecounts));
  237.  
  238.     j = wavinfo.samples/2;
  239.     for (i=0 ; i<j ; i++)
  240.     {
  241.         val = ((unsigned short *)( soundtrack + wavinfo.dataofs))[i];
  242.         samplecounts[val]++;
  243.     }
  244.     val = 0;
  245.     for (i=0 ; i<0x10000 ; i++)
  246.         if (samplecounts[i])
  247.             val++;
  248.  
  249.     printf ("%i unique sample values\n", val);
  250. }
  251.  
  252. /*
  253. ==================
  254. WriteSound
  255. ==================
  256. */
  257. void WriteSound (FILE *output, int frame)
  258. {
  259.     int        start, end;
  260.     int        count;
  261.     int        empty = 0;
  262.     int        i;
  263.     int        sample;
  264.     int        width;
  265.  
  266.     width = wavinfo.width * wavinfo.channels;
  267.  
  268.     start = frame*wavinfo.rate/14;
  269.     end = (frame+1)*wavinfo.rate/14;
  270.     count = end - start;
  271.  
  272.     for (i=0 ; i<count ; i++)
  273.     {
  274.         sample = start+i;
  275.         if (sample > wavinfo.samples || !soundtrack)
  276.             fwrite (&empty, 1, width, output);
  277.         else
  278.             fwrite (soundtrack + wavinfo.dataofs + sample*width, 1, width,output);
  279.     }
  280. }
  281.  
  282. //==========================================================================
  283.  
  284. /*
  285. ==================
  286. MTF
  287. ==================
  288. */
  289. cblock_t MTF (cblock_t in)
  290. {
  291.     int            i, j, b, code;
  292.     byte        *out_p;
  293.     int            index[256];
  294.     cblock_t    out;
  295.  
  296.     out_p = out.data = malloc(in.count + 4);
  297.  
  298.     // write count
  299.     *out_p++ = in.count&255;
  300.     *out_p++ = (in.count>>8)&255;
  301.     *out_p++ = (in.count>>16)&255;
  302.     *out_p++ = (in.count>>24)&255;
  303.  
  304.     for (i=0 ; i<256 ; i++)
  305.         index[i] = i;
  306.  
  307.     for (i=0 ; i<in.count ; i++)
  308.     {
  309.         b = in.data[i];
  310.         code = index[b];
  311.         *out_p++ = code;
  312.         
  313.         // shuffle b indexes to 0
  314.         for (j=0 ; j<256 ; j++)
  315.             if (index[j] < code)
  316.                 index[j]++;
  317.         index[b] = 0;
  318.     }
  319.  
  320.     out.count = out_p - out.data;
  321.  
  322.     return out;
  323. }
  324.  
  325.  
  326. //==========================================================================
  327.  
  328. int        bwt_size;
  329. byte    *bwt_data;
  330.  
  331. int bwtCompare (const void *elem1, const void *elem2)
  332. {
  333.     int        i;
  334.     int        i1, i2;
  335.     int        b1, b2;
  336.  
  337.     i1 = *(int *)elem1;
  338.     i2 = *(int *)elem2;
  339.  
  340.     for (i=0 ; i<bwt_size ; i++)
  341.     {
  342.         b1 = bwt_data[i1];
  343.         b2 = bwt_data[i2];
  344.         if (b1 < b2)
  345.             return -1;
  346.         if (b1 > b2)
  347.             return 1;
  348.         if (++i1 == bwt_size)
  349.             i1 = 0;
  350.         if (++i2 == bwt_size)
  351.             i2 = 0;
  352.     }
  353.  
  354.     return 0;
  355. }
  356.  
  357. /*
  358. ==================
  359. BWT
  360. ==================
  361. */
  362. cblock_t BWT (cblock_t in)
  363. {
  364.     int        *sorted;
  365.     int        i;
  366.     byte    *out_p;
  367.     cblock_t    out;
  368.  
  369.     bwt_size = in.count;
  370.     bwt_data = in.data;
  371.  
  372.     sorted = malloc(in.count*sizeof(*sorted));
  373.     for (i=0 ; i<in.count ; i++)
  374.         sorted[i] = i;
  375.     qsort (sorted, in.count, sizeof(*sorted), bwtCompare);
  376.  
  377.     out_p = out.data = malloc(in.count + 8);
  378.  
  379.     // write count
  380.     *out_p++ = in.count&255;
  381.     *out_p++ = (in.count>>8)&255;
  382.     *out_p++ = (in.count>>16)&255;
  383.     *out_p++ = (in.count>>24)&255;
  384.  
  385.     // write head index
  386.     for (i=0 ; i<in.count ; i++)
  387.         if (sorted[i] == 0)
  388.             break;
  389.     *out_p++ = i&255;
  390.     *out_p++ = (i>>8)&255;
  391.     *out_p++ = (i>>16)&255;
  392.     *out_p++ = (i>>24)&255;
  393.  
  394.     // write the L column
  395.     for (i=0 ; i<in.count ; i++)
  396.         *out_p++ = in.data[(sorted[i]+in.count-1)%in.count];
  397.  
  398.     free (sorted);
  399.  
  400.     out.count = out_p - out.data;
  401.  
  402.     return out;
  403. }
  404.  
  405. //==========================================================================
  406.  
  407. typedef struct hnode_s
  408. {
  409.     int            count;
  410.     qboolean    used;
  411.     int            children[2];
  412. } hnode_t;
  413.  
  414. int            numhnodes;
  415. hnode_t        hnodes[512];
  416. unsigned    charbits[256];
  417. int            charbitscount[256];
  418.  
  419. int    SmallestNode (void)
  420. {
  421.     int        i;
  422.     int        best, bestnode;
  423.  
  424.     best = 99999999;
  425.     bestnode = -1;
  426.     for (i=0 ; i<numhnodes ; i++)
  427.     {
  428.         if (hnodes[i].used)
  429.             continue;
  430.         if (!hnodes[i].count)
  431.             continue;
  432.         if (hnodes[i].count < best)
  433.         {
  434.             best = hnodes[i].count;
  435.             bestnode = i;
  436.         }
  437.     }
  438.  
  439.     if (bestnode == -1)
  440.         return -1;
  441.  
  442.     hnodes[bestnode].used = true;
  443.     return bestnode;
  444. }
  445.  
  446. void BuildChars (int nodenum, unsigned bits, int bitcount)
  447. {
  448.     hnode_t    *node;
  449.  
  450.     if (nodenum < 256)
  451.     {
  452.         if (bitcount > 32)
  453.             Error ("bitcount > 32");
  454.         charbits[nodenum] = bits;
  455.         charbitscount[nodenum] = bitcount;
  456.         return;
  457.     }
  458.  
  459.     node = &hnodes[nodenum];
  460.     bits <<= 1;
  461.     BuildChars (node->children[0], bits, bitcount+1);
  462.     bits |= 1;
  463.     BuildChars (node->children[1], bits, bitcount+1);
  464. }
  465.  
  466.  
  467. /*
  468. ==================
  469. Huffman
  470. ==================
  471. */
  472. cblock_t Huffman (cblock_t in)
  473. {
  474.     int            i;
  475.     hnode_t        *node;
  476.     int            outbits, c;
  477.     unsigned    bits;
  478.     byte        *out_p;
  479.     cblock_t    out;
  480.     int            max, maxchar;
  481.  
  482.     // count
  483.     memset (hnodes, 0, sizeof(hnodes));
  484.     for (i=0 ; i<in.count ; i++)
  485.         hnodes[in.data[i]].count++;
  486.  
  487.     // normalize counts
  488.     max = 0;
  489.     maxchar = 0;
  490.     for (i=0 ; i<256 ; i++)
  491.     {
  492.         if (hnodes[i].count > max)
  493.         {
  494.             max = hnodes[i].count;
  495.             maxchar = i;
  496.         }
  497.     }
  498.     if (max == 0)
  499.         Error ("Huffman: max == 0");
  500.  
  501.     for (i=0 ; i<256 ; i++)
  502.     {
  503.         hnodes[i].count = (hnodes[i].count*255+max-1) / max;
  504.     }
  505.  
  506.     // build the nodes
  507.     numhnodes = 256;
  508.     while (numhnodes != 511)
  509.     {
  510.         node = &hnodes[numhnodes];
  511.  
  512.         // pick two lowest counts
  513.         node->children[0] = SmallestNode ();
  514.         if (node->children[0] == -1)
  515.             break;    // no more
  516.  
  517.         node->children[1] = SmallestNode ();
  518.         if (node->children[1] == -1)
  519.         {
  520.             if (node->children[0] != numhnodes-1)
  521.                 Error ("Bad smallestnode");
  522.             break;
  523.         }
  524.         node->count = hnodes[node->children[0]].count + 
  525.             hnodes[node->children[1]].count;
  526.         numhnodes++;
  527.     }
  528.  
  529.     BuildChars (numhnodes-1, 0, 0);
  530.  
  531.     out_p = out.data = malloc(in.count*2 + 1024);
  532.     memset (out_p, 0, in.count*2+1024);
  533.  
  534.     // write count
  535.     *out_p++ = in.count&255;
  536.     *out_p++ = (in.count>>8)&255;
  537.     *out_p++ = (in.count>>16)&255;
  538.     *out_p++ = (in.count>>24)&255;
  539.  
  540.     // save out the 256 normalized counts so the tree can be recreated
  541.     for (i=0 ; i<256 ; i++)
  542.         *out_p++ = hnodes[i].count;
  543.  
  544.     // write bits
  545.     outbits = 0;
  546.     for (i=0 ; i<in.count ; i++)
  547.     {
  548.         c = charbitscount[in.data[i]];
  549.         bits = charbits[in.data[i]];
  550.         while (c)
  551.         {
  552.             c--;
  553.             if (bits & (1<<c))
  554.                 out_p[outbits>>3] |= 1<<(outbits&7);
  555.             outbits++;
  556.         }
  557.     }
  558.  
  559.     out_p += (outbits+7)>>3;
  560.  
  561.     out.count = out_p - out.data;
  562.  
  563.     return out;
  564. }
  565.  
  566. //==========================================================================
  567.  
  568. /*
  569. ==================
  570. RLE
  571. ==================
  572. */
  573. #define    RLE_CODE    0xe8
  574. #define    RLE_TRIPPLE    0xe9
  575.  
  576. int    rle_counts[256];
  577. int    rle_bytes[256];
  578.  
  579. cblock_t RLE (cblock_t in)
  580. {
  581.     int        i;
  582.     byte    *out_p;
  583.     int        val;
  584.     int        repeat;
  585.     cblock_t    out;
  586.  
  587.     out_p = out.data = malloc (in.count*2);
  588.  
  589.     // write count
  590.     *out_p++ = in.count&255;
  591.     *out_p++ = (in.count>>8)&255;
  592.     *out_p++ = (in.count>>16)&255;
  593.     *out_p++ = (in.count>>24)&255;
  594.  
  595.     for (i=0 ; i<in.count ; )
  596.     {
  597.         val = in.data[i];
  598.         rle_bytes[val]++;
  599.         repeat = 1;
  600.         i++;
  601.         while (i<in.count && repeat < 255 && in.data[i] == val)
  602.         {
  603.             repeat++;
  604.             i++;
  605.         }
  606. if (repeat < 256)
  607. rle_counts[repeat]++;
  608.         if (repeat > 3 || val == RLE_CODE)
  609.         {
  610.             *out_p++ = RLE_CODE;
  611.             *out_p++ = val;
  612.             *out_p++ = repeat;
  613.         }
  614.         else
  615.         {
  616.             while (repeat--)
  617.                 *out_p++ = val;
  618.         }
  619.     }
  620.  
  621.     out.count = out_p - out.data;
  622.     return out;
  623. }
  624.  
  625. //==========================================================================
  626.  
  627. unsigned    lzss_head[256];
  628. unsigned    lzss_next[0x20000];
  629.  
  630. /*
  631. ==================
  632. LZSS
  633. ==================
  634. */
  635. #define    BACK_WINDOW        0x10000
  636. #define    BACK_BITS        16
  637. #define    FRONT_WINDOW    16
  638. #define    FRONT_BITS        4
  639. cblock_t LZSS (cblock_t in)
  640. {
  641.     int        i;
  642.     byte    *out_p;
  643.     cblock_t    out;
  644.     int        val;
  645.     int        j, start, max;
  646.     int        bestlength, beststart;
  647.     int        outbits;
  648.  
  649. if (in.count >= sizeof(lzss_next)/4)
  650. Error ("LZSS: too big");
  651.  
  652.     memset (lzss_head, -1, sizeof(lzss_head));
  653.  
  654.     out_p = out.data = malloc (in.count*2);
  655.     memset (out.data, 0, in.count*2);
  656.  
  657.     // write count
  658.     *out_p++ = in.count&255;
  659.     *out_p++ = (in.count>>8)&255;
  660.     *out_p++ = (in.count>>16)&255;
  661.     *out_p++ = (in.count>>24)&255;
  662.  
  663.     outbits = 0;
  664.     for (i=0 ; i<in.count ; )
  665.     {
  666.         val = in.data[i];
  667. #if 1
  668. // chained search
  669.         bestlength = 0;
  670.         beststart = 0;
  671.  
  672.         max = FRONT_WINDOW;
  673.         if (i + max > in.count)
  674.             max = in.count - i;
  675.  
  676.         start = lzss_head[val];
  677.         while (start != -1 && start >= i-BACK_WINDOW)
  678.         {            
  679.             // count match length
  680.             for (j=0 ; j<max ; j++)
  681.                 if (in.data[start+j] != in.data[i+j])
  682.                     break;
  683.             if (j > bestlength)
  684.             {
  685.                 bestlength = j;
  686.                 beststart = start;
  687.             }
  688.             start = lzss_next[start];
  689.         }
  690.  
  691. #else
  692. // slow simple search
  693.         // search for a match
  694.         max = FRONT_WINDOW;
  695.         if (i + max > in.count)
  696.             max = in.count - i;
  697.  
  698.         start = i - BACK_WINDOW;
  699.         if (start < 0)
  700.             start = 0;
  701.         bestlength = 0;
  702.         beststart = 0;
  703.         for ( ; start < i ; start++)
  704.         {
  705.             if (in.data[start] != val)
  706.                 continue;
  707.             // count match length
  708.             for (j=0 ; j<max ; j++)
  709.                 if (in.data[start+j] != in.data[i+j])
  710.                     break;
  711.             if (j > bestlength)
  712.             {
  713.                 bestlength = j;
  714.                 beststart = start;
  715.             }
  716.         }
  717. #endif
  718.         beststart = BACK_WINDOW - (i-beststart);
  719.  
  720.         if (bestlength < 3)
  721.         {    // output a single char
  722.             bestlength = 1;
  723.  
  724.             out_p[outbits>>3] |= 1<<(outbits&7);    // set bit to mark char
  725.             outbits++;
  726.             for (j=0 ; j<8 ; j++, outbits++)
  727.                 if (val & (1<<j) )
  728.                     out_p[outbits>>3] |= 1<<(outbits&7);
  729.         }
  730.         else
  731.         {    // output a phrase
  732.             outbits++;    // leave a 0 bit to mark phrase
  733.             for (j=0 ; j<BACK_BITS ; j++, outbits++)
  734.                 if (beststart & (1<<j) )
  735.                     out_p[outbits>>3] |= 1<<(outbits&7);
  736.             for (j=0 ; j<FRONT_BITS ; j++, outbits++)
  737.                 if (bestlength & (1<<j) )
  738.                     out_p[outbits>>3] |= 1<<(outbits&7);
  739.         }
  740.  
  741.         while (bestlength--)
  742.         {
  743.             val = in.data[i];
  744.             lzss_next[i] = lzss_head[val];
  745.             lzss_head[val] = i;
  746.             i++;
  747.         }
  748.     }
  749.  
  750.     out_p += (outbits+7)>>3;
  751.     out.count = out_p - out.data;
  752.     return out;
  753. }
  754.  
  755. //==========================================================================
  756.  
  757. #define    MIN_REPT    15
  758. #define    MAX_REPT    0
  759. #define    HUF_TOKENS    (256+MAX_REPT)
  760.  
  761. unsigned    charbits1[256][HUF_TOKENS];
  762. int            charbitscount1[256][HUF_TOKENS];
  763.  
  764. hnode_t        hnodes1[256][HUF_TOKENS*2];
  765. int            numhnodes1[256];
  766.  
  767. int            order0counts[256];
  768.  
  769. /*
  770. ==================
  771. SmallestNode1
  772. ==================
  773. */
  774. int    SmallestNode1 (hnode_t *hnodes, int numhnodes)
  775. {
  776.     int        i;
  777.     int        best, bestnode;
  778.  
  779.     best = 99999999;
  780.     bestnode = -1;
  781.     for (i=0 ; i<numhnodes ; i++)
  782.     {
  783.         if (hnodes[i].used)
  784.             continue;
  785.         if (!hnodes[i].count)
  786.             continue;
  787.         if (hnodes[i].count < best)
  788.         {
  789.             best = hnodes[i].count;
  790.             bestnode = i;
  791.         }
  792.     }
  793.  
  794.     if (bestnode == -1)
  795.         return -1;
  796.  
  797.     hnodes[bestnode].used = true;
  798.     return bestnode;
  799. }
  800.  
  801.  
  802. /*
  803. ==================
  804. BuildChars1
  805. ==================
  806. */
  807. void BuildChars1 (int prev, int nodenum, unsigned bits, int bitcount)
  808. {
  809.     hnode_t    *node;
  810.  
  811.     if (nodenum < HUF_TOKENS)
  812.     {
  813.         if (bitcount > 32)
  814.             Error ("bitcount > 32");
  815.         charbits1[prev][nodenum] = bits;
  816.         charbitscount1[prev][nodenum] = bitcount;
  817.         return;
  818.     }
  819.  
  820.     node = &hnodes1[prev][nodenum];
  821.     bits <<= 1;
  822.     BuildChars1 (prev, node->children[0], bits, bitcount+1);
  823.     bits |= 1;
  824.     BuildChars1 (prev, node->children[1], bits, bitcount+1);
  825. }
  826.  
  827.  
  828. /*
  829. ==================
  830. BuildTree1
  831. ==================
  832. */
  833. void BuildTree1 (int prev)
  834. {
  835.     hnode_t        *node, *nodebase;
  836.     int            numhnodes;
  837.  
  838.     // build the nodes
  839.     numhnodes = HUF_TOKENS;
  840.     nodebase = hnodes1[prev];
  841.     while (1)
  842.     {
  843.         node = &nodebase[numhnodes];
  844.  
  845.         // pick two lowest counts
  846.         node->children[0] = SmallestNode1 (nodebase, numhnodes);
  847.         if (node->children[0] == -1)
  848.             break;    // no more
  849.  
  850.         node->children[1] = SmallestNode1 (nodebase, numhnodes);
  851.         if (node->children[1] == -1)
  852.             break;
  853.  
  854.         node->count = nodebase[node->children[0]].count + 
  855.             nodebase[node->children[1]].count;
  856.         numhnodes++;
  857.     }
  858.     numhnodes1[prev] = numhnodes-1;
  859.     BuildChars1 (prev, numhnodes-1, 0, 0);
  860. }
  861.  
  862.  
  863. /*
  864. ==================
  865. Huffman1_Count
  866. ==================
  867. */
  868. void Huffman1_Count (cblock_t in)
  869. {
  870.     int        i;
  871.     int        prev;
  872.     int        v;
  873.     int        rept;
  874.  
  875.     prev = 0;
  876.     for (i=0 ; i<in.count ; i++)
  877.     {
  878.         v = in.data[i];
  879.         order0counts[v]++;
  880.         hnodes1[prev][v].count++;
  881.         prev = v;
  882. #if 1
  883.         for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
  884.             if (in.data[i+rept] != v)
  885.                 break;
  886.         if (rept > MIN_REPT)
  887.         {
  888.             hnodes1[prev][255+rept].count++;
  889.             i += rept-1;
  890.         }
  891. #endif
  892.     }
  893. }
  894.  
  895.  
  896. /*
  897. ==================
  898. Huffman1_Build
  899. ==================
  900. */
  901. byte    scaled[256][HUF_TOKENS];
  902. void Huffman1_Build (FILE *f)
  903. {
  904.     int        i, j, v;
  905.     int        max;
  906.     int        total;
  907.  
  908.     for (i=0 ; i<256 ; i++)
  909.     {
  910.         // normalize and save the counts
  911.         max = 0;
  912.         for (j=0 ; j<HUF_TOKENS ; j++)
  913.         {
  914.             if (hnodes1[i][j].count > max)
  915.                 max = hnodes1[i][j].count;
  916.         }
  917.         if (max == 0)
  918.             max = 1;
  919.         total = 0;
  920.         for (j=0 ; j<HUF_TOKENS ; j++)
  921.         {    // easy to overflow 32 bits here!
  922.             v = (hnodes1[i][j].count*(double)255+max-1)/max;
  923.             if (v > 255)
  924.                 Error ("v > 255");
  925.             scaled[i][j] = hnodes1[i][j].count = v;
  926.             if (v)
  927.                 total++;
  928.         }
  929.         if (total == 1)
  930.         {    // must have two tokens
  931.             if (!scaled[i][0])
  932.                 scaled[i][0] = hnodes1[i][0].count = 1;
  933.             else
  934.                 scaled[i][1] = hnodes1[i][1].count = 1;
  935.         }
  936.  
  937.         BuildTree1 (i);
  938.     }
  939.  
  940. #if 0
  941.     // count up the total bits
  942.     total = 0;
  943.     for (i=0 ; i<256 ; i++)
  944.         for (j=0 ; j<256 ; j++)
  945.             total += charbitscount1[i][j] * hnodes1[i][j].count;
  946.  
  947.     total = (total+7)/8;
  948.     printf ("%i bytes huffman1 compressed\n", total);
  949. #endif
  950.  
  951.     fwrite (scaled, 1, sizeof(scaled), f);
  952. }
  953.  
  954. /*
  955. ==================
  956. Huffman1
  957.  
  958. Order 1 compression with pre-built table
  959. ==================
  960. */
  961. cblock_t Huffman1 (cblock_t in)
  962. {
  963.     int            i;
  964.     int            outbits, c;
  965.     unsigned    bits;
  966.     byte        *out_p;
  967.     cblock_t    out;
  968.     int            prev;
  969.     int            v;
  970.     int            rept;
  971.  
  972.     out_p = out.data = malloc(in.count*2 + 1024);
  973.     memset (out_p, 0, in.count*2+1024);
  974.  
  975.     // write count
  976.     *out_p++ = in.count&255;
  977.     *out_p++ = (in.count>>8)&255;
  978.     *out_p++ = (in.count>>16)&255;
  979.     *out_p++ = (in.count>>24)&255;
  980.  
  981.     // write bits
  982.     outbits = 0;
  983.     prev = 0;
  984.     for (i=0 ; i<in.count ; i++)
  985.     {
  986.         v = in.data[i];
  987.  
  988.         c = charbitscount1[prev][v];
  989.         bits = charbits1[prev][v];
  990.         if (!c)
  991.             Error ("!bits");
  992.         while (c)
  993.         {
  994.             c--;
  995.             if (bits & (1<<c))
  996.                 out_p[outbits>>3] |= 1<<(outbits&7);
  997.             outbits++;
  998.         }
  999.  
  1000.         prev = v;
  1001. #if 1
  1002.         // check for repeat encodes
  1003.         for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
  1004.             if (in.data[i+rept] != v)
  1005.                 break;
  1006.         if (rept > MIN_REPT)
  1007.         {
  1008.             c = charbitscount1[prev][255+rept];
  1009.             bits = charbits1[prev][255+rept];
  1010.             if (!c)
  1011.                 Error ("!bits");
  1012.             while (c)
  1013.             {
  1014.                 c--;
  1015.                 if (bits & (1<<c))
  1016.                     out_p[outbits>>3] |= 1<<(outbits&7);
  1017.                 outbits++;
  1018.             }
  1019.             i += rept-1;
  1020.         }
  1021. #endif
  1022.     }
  1023.  
  1024.     out_p += (outbits+7)>>3;
  1025.  
  1026.     out.count = out_p - out.data;
  1027.  
  1028.     return out;
  1029. }
  1030.  
  1031. //==========================================================================
  1032.  
  1033.  
  1034. /*
  1035. ===================
  1036. LoadFrame
  1037. ===================
  1038. */
  1039. cblock_t LoadFrame (char *base, int frame, int digits, byte **palette)
  1040. {
  1041.     int            ten3, ten2, ten1, ten0;
  1042.     cblock_t    in;
  1043.     int            width, height;
  1044.     char        name[1024];
  1045.     FILE        *f;
  1046.  
  1047.     in.data = NULL;
  1048.     in.count = -1;
  1049.  
  1050.     ten3 = frame/1000;
  1051.     ten2 = (frame-ten3*1000)/100;
  1052.     ten1 = (frame-ten3*1000-ten2*100)/10;
  1053.     ten0 = frame%10;
  1054.  
  1055.     if (digits == 4)
  1056.         sprintf (name, "%svideo/%s/%s%i%i%i%i.pcx", gamedir, base, base, ten3, ten2, ten1, ten0);
  1057.     else
  1058.         sprintf (name, "%svideo/%s/%s%i%i%i.pcx", gamedir, base, base, ten2, ten1, ten0);
  1059.  
  1060.     f = fopen(name, "rb");
  1061.     if (!f)
  1062.     {
  1063.         in.data = NULL;
  1064.         return in;
  1065.     }
  1066.     fclose (f);
  1067.  
  1068.     printf ("%s\n", name);
  1069.     Load256Image (name, &in.data, palette, &width, &height);
  1070.     in.count = width*height;
  1071. // FIXME: map 0 and 255!
  1072.  
  1073. #if 0
  1074.     // rle compress
  1075.     rle = RLE(in);
  1076.     free (in.data);
  1077.  
  1078.     return rle;
  1079. #endif
  1080.  
  1081.     return in;
  1082. }
  1083.  
  1084. /*
  1085. ===============
  1086. Cmd_Video
  1087.  
  1088. video <directory> <framedigits>
  1089. ===============
  1090. */
  1091. void Cmd_Video (void)
  1092. {
  1093.     char    savename[1024];
  1094.     char    name[1024];
  1095.     FILE    *output;
  1096.     int        startframe, frame;
  1097.     byte    *palette;
  1098.     int        width, height;
  1099.     byte    current_palette[768];
  1100.     int        command;
  1101.     int        i;
  1102.     int        digits;
  1103.     cblock_t    in, huffman;
  1104.     int        swap;
  1105.  
  1106.  
  1107.     GetToken (false);
  1108.     strcpy (base, token);
  1109.     if (g_release)
  1110.     {
  1111. //        sprintf (savename, "video/%s.cin", token);
  1112. //        ReleaseFile (savename);
  1113.         return;
  1114.     }
  1115.  
  1116.     GetToken (false);
  1117.     digits = atoi(token);
  1118.  
  1119.     // optionally skip frames
  1120.     if (TokenAvailable ())
  1121.     {
  1122.         GetToken (false);
  1123.         startframe = atoi(token);
  1124.     }
  1125.     else
  1126.         startframe=0;
  1127.  
  1128.     sprintf (savename, "%svideo/%s.cin", gamedir, base);
  1129.  
  1130.  
  1131.     // clear stuff
  1132.     memset (charbits1, 0, sizeof(charbits1));
  1133.     memset (charbitscount1, 0, sizeof(charbitscount1));
  1134.     memset (hnodes1, 0, sizeof(hnodes1));
  1135.     memset (numhnodes1, 0, sizeof(numhnodes1));
  1136.     memset (order0counts, 0, sizeof(order0counts));
  1137.  
  1138.  
  1139.     // load the entire sound wav file if present
  1140.     LoadSoundtrack ();
  1141.  
  1142.     if (digits == 4)
  1143.         sprintf (name, "%svideo/%s/%s0000.pcx", gamedir, base, base);
  1144.     else
  1145.         sprintf (name, "%svideo/%s/%s000.pcx", gamedir, base, base);
  1146.  
  1147.     printf ("%s\n", name);
  1148.     Load256Image (name, NULL, &palette, &width, &height);
  1149.  
  1150.     output = fopen (savename, "wb");
  1151.     if (!output)
  1152.         Error ("Can't open %s", savename);
  1153.  
  1154.     // write header info
  1155.     i = LittleLong (width);
  1156.     fwrite (&i, 4, 1, output);
  1157.     i = LittleLong (height);
  1158.     fwrite (&i, 4, 1, output);
  1159.     i = LittleLong (wavinfo.rate);
  1160.     fwrite (&i, 4, 1, output);
  1161.     i = LittleLong (wavinfo.width);
  1162.     fwrite (&i, 4, 1, output);
  1163.     i = LittleLong (wavinfo.channels);
  1164.     fwrite (&i, 4, 1, output);
  1165.  
  1166.     // build the dictionary
  1167.     for ( frame=startframe ;  ; frame++)
  1168.     {
  1169.         printf ("counting ", frame);
  1170.         in = LoadFrame (base, frame, digits, &palette);
  1171.         if (!in.data)
  1172.             break;
  1173.         Huffman1_Count (in);
  1174.         free (in.data);
  1175.     }
  1176.     printf ("\n");
  1177.  
  1178.     // build nodes and write counts
  1179.     Huffman1_Build (output);
  1180.  
  1181.  
  1182.     memset (current_palette, 0, sizeof(current_palette));
  1183.  
  1184.     // compress it with the dictionary
  1185.     for (frame=startframe ;  ; frame++)
  1186.     {
  1187.         printf ("packing ", frame);
  1188.         in = LoadFrame (base, frame, digits, &palette);
  1189.         if (!in.data)
  1190.             break;
  1191.  
  1192.         // see if the palette has changed
  1193.         for (i=0 ; i<768 ; i++)
  1194.             if (palette[i] != current_palette[i])
  1195.             {
  1196.                 // write a palette change
  1197.                 memcpy (current_palette, palette, sizeof(current_palette));
  1198.                 command = LittleLong(1);
  1199.                 fwrite (&command, 1, 4, output);
  1200.                 fwrite (current_palette, 1, sizeof(current_palette), output);
  1201.                 break;
  1202.             }
  1203.         if (i == 768)
  1204.         {
  1205.             command = 0;    // no palette change
  1206.             fwrite (&command, 1, 4, output);
  1207.         }
  1208.  
  1209.         // save the image
  1210.         huffman = Huffman1 (in);
  1211.         printf ("%5i bytes after huffman1\n", huffman.count);
  1212.  
  1213.         swap = LittleLong (huffman.count);
  1214.         fwrite (&swap, 1, sizeof(swap), output);
  1215.  
  1216.         fwrite (huffman.data, 1, huffman.count, output);
  1217.  
  1218.         // save some sound samples
  1219.         WriteSound (output, frame);
  1220.  
  1221.         free (palette);
  1222.         free (in.data);
  1223.         free (huffman.data);
  1224.     }
  1225.     printf ("\n");
  1226.  
  1227.     // write end-of-file command
  1228.     command = 2;
  1229.     fwrite (&command, 1, 4, output);
  1230.  
  1231.     printf ("Total size: %i\n", ftell (output));
  1232.  
  1233.     fclose (output);
  1234.  
  1235.     if (soundtrack)
  1236.         free (soundtrack);
  1237. }
  1238.