2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
5 This file is part of Quake 2 Tools source code.
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
29 ===============================================================================
33 ===============================================================================
43 int dataofs; // chunk starts this many bytes from file start
54 int samplecounts[0x10000];
58 short GetLittleShort(void)
62 val = val + (*(data_p+1)<<8);
67 int GetLittleLong(void)
71 val = val + (*(data_p+1)<<8);
72 val = val + (*(data_p+2)<<16);
73 val = val + (*(data_p+3)<<24);
78 void FindNextChunk(char *name)
84 if (data_p >= iff_end)
85 { // didn't find the chunk
91 iff_chunk_len = GetLittleLong();
92 if (iff_chunk_len < 0)
97 // if (iff_chunk_len > 1024*1024)
98 // Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
100 last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
101 if (!strncmp(data_p, name, 4))
106 void FindChunk(char *name)
108 last_chunk = iff_data;
109 FindNextChunk (name);
113 void DumpChunks(void)
121 memcpy (str, data_p, 4);
123 iff_chunk_len = GetLittleLong();
124 printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
125 data_p += (iff_chunk_len + 1) & ~1;
126 } while (data_p < iff_end);
134 wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
141 memset (&info, 0, sizeof(info));
147 iff_end = wav + wavlength;
151 if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
153 printf("Missing RIFF/WAVE chunks\n");
158 iff_data = data_p + 12;
164 printf("Missing fmt chunk\n");
168 format = GetLittleShort();
171 printf("Microsoft PCM format only\n");
175 info.channels = GetLittleShort();
176 info.rate = GetLittleLong();
178 info.width = GetLittleShort() / 8;
185 info.loopstart = GetLittleLong();
186 // Com_Printf("loopstart=%d\n", sfx->loopstart);
188 // if the next chunk is a LIST chunk, look for a cue length marker
189 FindNextChunk ("LIST");
192 if (!strncmp (data_p + 28, "mark", 4))
193 { // this is not a proper parse, but it works with cooledit...
195 i = GetLittleLong (); // samples in loop
196 info.samples = info.loopstart + i;
207 printf("Missing data chunk\n");
212 samples = GetLittleLong ();
216 if (samples < info.samples)
217 Error ("Sound %s has a bad loop length", name);
220 info.samples = samples;
222 info.dataofs = data_p - wav;
227 //=====================================================================
234 void LoadSoundtrack (void)
242 sprintf (name, "%svideo/%s/%s.wav", gamedir, base, base);
243 printf ("%s\n", name);
244 f = fopen (name, "rb");
247 printf ("no soundtrack for %s\n", base);
250 len = Q_filelength(f);
251 soundtrack = malloc(len);
252 fread (soundtrack, 1, len, f);
255 wavinfo = GetWavinfo (name, soundtrack, len);
257 // count samples for compression
258 memset (samplecounts, 0, sizeof(samplecounts));
260 j = wavinfo.samples/2;
261 for (i=0 ; i<j ; i++)
263 val = ((unsigned short *)( soundtrack + wavinfo.dataofs))[i];
267 for (i=0 ; i<0x10000 ; i++)
271 printf ("%i unique sample values\n", val);
279 void WriteSound (FILE *output, int frame)
288 width = wavinfo.width * wavinfo.channels;
290 start = frame*wavinfo.rate/14;
291 end = (frame+1)*wavinfo.rate/14;
294 for (i=0 ; i<count ; i++)
297 if (sample > wavinfo.samples || !soundtrack)
298 fwrite (&empty, 1, width, output);
300 fwrite (soundtrack + wavinfo.dataofs + sample*width, 1, width,output);
304 //==========================================================================
311 cblock_t MTF (cblock_t in)
318 out_p = out.data = malloc(in.count + 4);
321 *out_p++ = in.count&255;
322 *out_p++ = (in.count>>8)&255;
323 *out_p++ = (in.count>>16)&255;
324 *out_p++ = (in.count>>24)&255;
326 for (i=0 ; i<256 ; i++)
329 for (i=0 ; i<in.count ; i++)
335 // shuffle b indexes to 0
336 for (j=0 ; j<256 ; j++)
342 out.count = out_p - out.data;
348 //==========================================================================
353 int bwtCompare (const void *elem1, const void *elem2)
362 for (i=0 ; i<bwt_size ; i++)
370 if (++i1 == bwt_size)
372 if (++i2 == bwt_size)
384 cblock_t BWT (cblock_t in)
394 sorted = malloc(in.count*sizeof(*sorted));
395 for (i=0 ; i<in.count ; i++)
397 qsort (sorted, in.count, sizeof(*sorted), bwtCompare);
399 out_p = out.data = malloc(in.count + 8);
402 *out_p++ = in.count&255;
403 *out_p++ = (in.count>>8)&255;
404 *out_p++ = (in.count>>16)&255;
405 *out_p++ = (in.count>>24)&255;
408 for (i=0 ; i<in.count ; i++)
412 *out_p++ = (i>>8)&255;
413 *out_p++ = (i>>16)&255;
414 *out_p++ = (i>>24)&255;
416 // write the L column
417 for (i=0 ; i<in.count ; i++)
418 *out_p++ = in.data[(sorted[i]+in.count-1)%in.count];
422 out.count = out_p - out.data;
427 //==========================================================================
429 typedef struct hnode_s
438 unsigned charbits[256];
439 int charbitscount[256];
441 int SmallestNode (void)
448 for (i=0 ; i<numhnodes ; i++)
452 if (!hnodes[i].count)
454 if (hnodes[i].count < best)
456 best = hnodes[i].count;
464 hnodes[bestnode].used = true;
468 void BuildChars (int nodenum, unsigned bits, int bitcount)
475 Error ("bitcount > 32");
476 charbits[nodenum] = bits;
477 charbitscount[nodenum] = bitcount;
481 node = &hnodes[nodenum];
483 BuildChars (node->children[0], bits, bitcount+1);
485 BuildChars (node->children[1], bits, bitcount+1);
494 cblock_t Huffman (cblock_t in)
505 memset (hnodes, 0, sizeof(hnodes));
506 for (i=0 ; i<in.count ; i++)
507 hnodes[in.data[i]].count++;
512 for (i=0 ; i<256 ; i++)
514 if (hnodes[i].count > max)
516 max = hnodes[i].count;
521 Error ("Huffman: max == 0");
523 for (i=0 ; i<256 ; i++)
525 hnodes[i].count = (hnodes[i].count*255+max-1) / max;
530 while (numhnodes != 511)
532 node = &hnodes[numhnodes];
534 // pick two lowest counts
535 node->children[0] = SmallestNode ();
536 if (node->children[0] == -1)
539 node->children[1] = SmallestNode ();
540 if (node->children[1] == -1)
542 if (node->children[0] != numhnodes-1)
543 Error ("Bad smallestnode");
546 node->count = hnodes[node->children[0]].count +
547 hnodes[node->children[1]].count;
551 BuildChars (numhnodes-1, 0, 0);
553 out_p = out.data = malloc(in.count*2 + 1024);
554 memset (out_p, 0, in.count*2+1024);
557 *out_p++ = in.count&255;
558 *out_p++ = (in.count>>8)&255;
559 *out_p++ = (in.count>>16)&255;
560 *out_p++ = (in.count>>24)&255;
562 // save out the 256 normalized counts so the tree can be recreated
563 for (i=0 ; i<256 ; i++)
564 *out_p++ = hnodes[i].count;
568 for (i=0 ; i<in.count ; i++)
570 c = charbitscount[in.data[i]];
571 bits = charbits[in.data[i]];
576 out_p[outbits>>3] |= 1<<(outbits&7);
581 out_p += (outbits+7)>>3;
583 out.count = out_p - out.data;
588 //==========================================================================
595 #define RLE_CODE 0xe8
596 #define RLE_TRIPPLE 0xe9
601 cblock_t RLE (cblock_t in)
609 out_p = out.data = malloc (in.count*2);
612 *out_p++ = in.count&255;
613 *out_p++ = (in.count>>8)&255;
614 *out_p++ = (in.count>>16)&255;
615 *out_p++ = (in.count>>24)&255;
617 for (i=0 ; i<in.count ; )
623 while (i<in.count && repeat < 255 && in.data[i] == val)
629 rle_counts[repeat]++;
630 if (repeat > 3 || val == RLE_CODE)
643 out.count = out_p - out.data;
647 //==========================================================================
649 unsigned lzss_head[256];
650 unsigned lzss_next[0x20000];
657 #define BACK_WINDOW 0x10000
659 #define FRONT_WINDOW 16
661 cblock_t LZSS (cblock_t in)
668 int bestlength, beststart;
671 if (in.count >= sizeof(lzss_next)/4)
672 Error ("LZSS: too big");
674 memset (lzss_head, -1, sizeof(lzss_head));
676 out_p = out.data = malloc (in.count*2);
677 memset (out.data, 0, in.count*2);
680 *out_p++ = in.count&255;
681 *out_p++ = (in.count>>8)&255;
682 *out_p++ = (in.count>>16)&255;
683 *out_p++ = (in.count>>24)&255;
686 for (i=0 ; i<in.count ; )
695 if (i + max > in.count)
698 start = lzss_head[val];
699 while (start != -1 && start >= i-BACK_WINDOW)
701 // count match length
702 for (j=0 ; j<max ; j++)
703 if (in.data[start+j] != in.data[i+j])
710 start = lzss_next[start];
714 // slow simple search
715 // search for a match
717 if (i + max > in.count)
720 start = i - BACK_WINDOW;
725 for ( ; start < i ; start++)
727 if (in.data[start] != val)
729 // count match length
730 for (j=0 ; j<max ; j++)
731 if (in.data[start+j] != in.data[i+j])
740 beststart = BACK_WINDOW - (i-beststart);
743 { // output a single char
746 out_p[outbits>>3] |= 1<<(outbits&7); // set bit to mark char
748 for (j=0 ; j<8 ; j++, outbits++)
750 out_p[outbits>>3] |= 1<<(outbits&7);
754 outbits++; // leave a 0 bit to mark phrase
755 for (j=0 ; j<BACK_BITS ; j++, outbits++)
756 if (beststart & (1<<j) )
757 out_p[outbits>>3] |= 1<<(outbits&7);
758 for (j=0 ; j<FRONT_BITS ; j++, outbits++)
759 if (bestlength & (1<<j) )
760 out_p[outbits>>3] |= 1<<(outbits&7);
766 lzss_next[i] = lzss_head[val];
772 out_p += (outbits+7)>>3;
773 out.count = out_p - out.data;
777 //==========================================================================
781 #define HUF_TOKENS (256+MAX_REPT)
783 unsigned charbits1[256][HUF_TOKENS];
784 int charbitscount1[256][HUF_TOKENS];
786 hnode_t hnodes1[256][HUF_TOKENS*2];
789 int order0counts[256];
796 int SmallestNode1 (hnode_t *hnodes, int numhnodes)
803 for (i=0 ; i<numhnodes ; i++)
807 if (!hnodes[i].count)
809 if (hnodes[i].count < best)
811 best = hnodes[i].count;
819 hnodes[bestnode].used = true;
829 void BuildChars1 (int prev, int nodenum, unsigned bits, int bitcount)
833 if (nodenum < HUF_TOKENS)
836 Error ("bitcount > 32");
837 charbits1[prev][nodenum] = bits;
838 charbitscount1[prev][nodenum] = bitcount;
842 node = &hnodes1[prev][nodenum];
844 BuildChars1 (prev, node->children[0], bits, bitcount+1);
846 BuildChars1 (prev, node->children[1], bits, bitcount+1);
855 void BuildTree1 (int prev)
857 hnode_t *node, *nodebase;
861 numhnodes = HUF_TOKENS;
862 nodebase = hnodes1[prev];
865 node = &nodebase[numhnodes];
867 // pick two lowest counts
868 node->children[0] = SmallestNode1 (nodebase, numhnodes);
869 if (node->children[0] == -1)
872 node->children[1] = SmallestNode1 (nodebase, numhnodes);
873 if (node->children[1] == -1)
876 node->count = nodebase[node->children[0]].count +
877 nodebase[node->children[1]].count;
880 numhnodes1[prev] = numhnodes-1;
881 BuildChars1 (prev, numhnodes-1, 0, 0);
890 void Huffman1_Count (cblock_t in)
898 for (i=0 ; i<in.count ; i++)
902 hnodes1[prev][v].count++;
905 for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
906 if (in.data[i+rept] != v)
910 hnodes1[prev][255+rept].count++;
923 byte scaled[256][HUF_TOKENS];
924 void Huffman1_Build (FILE *f)
930 for (i=0 ; i<256 ; i++)
932 // normalize and save the counts
934 for (j=0 ; j<HUF_TOKENS ; j++)
936 if (hnodes1[i][j].count > max)
937 max = hnodes1[i][j].count;
942 for (j=0 ; j<HUF_TOKENS ; j++)
943 { // easy to overflow 32 bits here!
944 v = (hnodes1[i][j].count*(double)255+max-1)/max;
947 scaled[i][j] = hnodes1[i][j].count = v;
952 { // must have two tokens
954 scaled[i][0] = hnodes1[i][0].count = 1;
956 scaled[i][1] = hnodes1[i][1].count = 1;
963 // count up the total bits
965 for (i=0 ; i<256 ; i++)
966 for (j=0 ; j<256 ; j++)
967 total += charbitscount1[i][j] * hnodes1[i][j].count;
970 printf ("%i bytes huffman1 compressed\n", total);
973 fwrite (scaled, 1, sizeof(scaled), f);
980 Order 1 compression with pre-built table
983 cblock_t Huffman1 (cblock_t in)
994 out_p = out.data = malloc(in.count*2 + 1024);
995 memset (out_p, 0, in.count*2+1024);
998 *out_p++ = in.count&255;
999 *out_p++ = (in.count>>8)&255;
1000 *out_p++ = (in.count>>16)&255;
1001 *out_p++ = (in.count>>24)&255;
1006 for (i=0 ; i<in.count ; i++)
1010 c = charbitscount1[prev][v];
1011 bits = charbits1[prev][v];
1018 out_p[outbits>>3] |= 1<<(outbits&7);
1024 // check for repeat encodes
1025 for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
1026 if (in.data[i+rept] != v)
1028 if (rept > MIN_REPT)
1030 c = charbitscount1[prev][255+rept];
1031 bits = charbits1[prev][255+rept];
1038 out_p[outbits>>3] |= 1<<(outbits&7);
1046 out_p += (outbits+7)>>3;
1048 out.count = out_p - out.data;
1053 //==========================================================================
1061 cblock_t LoadFrame (char *base, int frame, int digits, byte **palette)
1063 int ten3, ten2, ten1, ten0;
1073 ten2 = (frame-ten3*1000)/100;
1074 ten1 = (frame-ten3*1000-ten2*100)/10;
1078 sprintf (name, "%svideo/%s/%s%i%i%i%i.pcx", gamedir, base, base, ten3, ten2, ten1, ten0);
1080 sprintf (name, "%svideo/%s/%s%i%i%i.pcx", gamedir, base, base, ten2, ten1, ten0);
1082 f = fopen(name, "rb");
1090 printf ("%s\n", name);
1091 Load256Image (name, &in.data, palette, &width, &height);
1092 in.count = width*height;
1093 // FIXME: map 0 and 255!
1110 video <directory> <framedigits>
1113 void Cmd_Video (void)
1115 char savename[1024];
1118 int startframe, frame;
1121 byte current_palette[768];
1125 cblock_t in, huffman;
1130 strcpy (base, token);
1133 // sprintf (savename, "video/%s.cin", token);
1134 // ReleaseFile (savename);
1139 digits = atoi(token);
1141 // optionally skip frames
1142 if (TokenAvailable ())
1145 startframe = atoi(token);
1150 sprintf (savename, "%svideo/%s.cin", gamedir, base);
1154 memset (charbits1, 0, sizeof(charbits1));
1155 memset (charbitscount1, 0, sizeof(charbitscount1));
1156 memset (hnodes1, 0, sizeof(hnodes1));
1157 memset (numhnodes1, 0, sizeof(numhnodes1));
1158 memset (order0counts, 0, sizeof(order0counts));
1161 // load the entire sound wav file if present
1165 sprintf (name, "%svideo/%s/%s0000.pcx", gamedir, base, base);
1167 sprintf (name, "%svideo/%s/%s000.pcx", gamedir, base, base);
1169 printf ("%s\n", name);
1170 Load256Image (name, NULL, &palette, &width, &height);
1172 output = fopen (savename, "wb");
1174 Error ("Can't open %s", savename);
1176 // write header info
1177 i = LittleLong (width);
1178 fwrite (&i, 4, 1, output);
1179 i = LittleLong (height);
1180 fwrite (&i, 4, 1, output);
1181 i = LittleLong (wavinfo.rate);
1182 fwrite (&i, 4, 1, output);
1183 i = LittleLong (wavinfo.width);
1184 fwrite (&i, 4, 1, output);
1185 i = LittleLong (wavinfo.channels);
1186 fwrite (&i, 4, 1, output);
1188 // build the dictionary
1189 for ( frame=startframe ; ; frame++)
1191 printf ("counting ", frame);
1192 in = LoadFrame (base, frame, digits, &palette);
1195 Huffman1_Count (in);
1200 // build nodes and write counts
1201 Huffman1_Build (output);
1204 memset (current_palette, 0, sizeof(current_palette));
1206 // compress it with the dictionary
1207 for (frame=startframe ; ; frame++)
1209 printf ("packing ", frame);
1210 in = LoadFrame (base, frame, digits, &palette);
1214 // see if the palette has changed
1215 for (i=0 ; i<768 ; i++)
1216 if (palette[i] != current_palette[i])
1218 // write a palette change
1219 memcpy (current_palette, palette, sizeof(current_palette));
1220 command = LittleLong(1);
1221 fwrite (&command, 1, 4, output);
1222 fwrite (current_palette, 1, sizeof(current_palette), output);
1227 command = 0; // no palette change
1228 fwrite (&command, 1, 4, output);
1232 huffman = Huffman1 (in);
1233 printf ("%5i bytes after huffman1\n", huffman.count);
1235 swap = LittleLong (huffman.count);
1236 fwrite (&swap, 1, sizeof(swap), output);
1238 fwrite (huffman.data, 1, huffman.count, output);
1240 // save some sound samples
1241 WriteSound (output, frame);
1245 free (huffman.data);
1249 // write end-of-file command
1251 fwrite (&command, 1, 4, output);
1253 printf ("Total size: %i\n", ftell (output));