8 ===============================================================================
12 ===============================================================================
22 int dataofs; // chunk starts this many bytes from file start
33 int samplecounts[0x10000];
37 short GetLittleShort(void)
41 val = val + (*(data_p+1)<<8);
46 int GetLittleLong(void)
50 val = val + (*(data_p+1)<<8);
51 val = val + (*(data_p+2)<<16);
52 val = val + (*(data_p+3)<<24);
57 void FindNextChunk(char *name)
63 if (data_p >= iff_end)
64 { // didn't find the chunk
70 iff_chunk_len = GetLittleLong();
71 if (iff_chunk_len < 0)
76 // if (iff_chunk_len > 1024*1024)
77 // Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
79 last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
80 if (!strncmp(data_p, name, 4))
85 void FindChunk(char *name)
87 last_chunk = iff_data;
100 memcpy (str, data_p, 4);
102 iff_chunk_len = GetLittleLong();
103 printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
104 data_p += (iff_chunk_len + 1) & ~1;
105 } while (data_p < iff_end);
113 wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
120 memset (&info, 0, sizeof(info));
126 iff_end = wav + wavlength;
130 if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
132 printf("Missing RIFF/WAVE chunks\n");
137 iff_data = data_p + 12;
143 printf("Missing fmt chunk\n");
147 format = GetLittleShort();
150 printf("Microsoft PCM format only\n");
154 info.channels = GetLittleShort();
155 info.rate = GetLittleLong();
157 info.width = GetLittleShort() / 8;
164 info.loopstart = GetLittleLong();
165 // Com_Printf("loopstart=%d\n", sfx->loopstart);
167 // if the next chunk is a LIST chunk, look for a cue length marker
168 FindNextChunk ("LIST");
171 if (!strncmp (data_p + 28, "mark", 4))
172 { // this is not a proper parse, but it works with cooledit...
174 i = GetLittleLong (); // samples in loop
175 info.samples = info.loopstart + i;
186 printf("Missing data chunk\n");
191 samples = GetLittleLong ();
195 if (samples < info.samples)
196 Error ("Sound %s has a bad loop length", name);
199 info.samples = samples;
201 info.dataofs = data_p - wav;
206 //=====================================================================
213 void LoadSoundtrack (void)
221 sprintf (name, "%svideo/%s/%s.wav", gamedir, base, base);
222 printf ("%s\n", name);
223 f = fopen (name, "rb");
226 printf ("no soundtrack for %s\n", base);
229 len = Q_filelength(f);
230 soundtrack = malloc(len);
231 fread (soundtrack, 1, len, f);
234 wavinfo = GetWavinfo (name, soundtrack, len);
236 // count samples for compression
237 memset (samplecounts, 0, sizeof(samplecounts));
239 j = wavinfo.samples/2;
240 for (i=0 ; i<j ; i++)
242 val = ((unsigned short *)( soundtrack + wavinfo.dataofs))[i];
246 for (i=0 ; i<0x10000 ; i++)
250 printf ("%i unique sample values\n", val);
258 void WriteSound (FILE *output, int frame)
267 width = wavinfo.width * wavinfo.channels;
269 start = frame*wavinfo.rate/14;
270 end = (frame+1)*wavinfo.rate/14;
273 for (i=0 ; i<count ; i++)
276 if (sample > wavinfo.samples || !soundtrack)
277 fwrite (&empty, 1, width, output);
279 fwrite (soundtrack + wavinfo.dataofs + sample*width, 1, width,output);
283 //==========================================================================
290 cblock_t MTF (cblock_t in)
297 out_p = out.data = malloc(in.count + 4);
300 *out_p++ = in.count&255;
301 *out_p++ = (in.count>>8)&255;
302 *out_p++ = (in.count>>16)&255;
303 *out_p++ = (in.count>>24)&255;
305 for (i=0 ; i<256 ; i++)
308 for (i=0 ; i<in.count ; i++)
314 // shuffle b indexes to 0
315 for (j=0 ; j<256 ; j++)
321 out.count = out_p - out.data;
327 //==========================================================================
332 int bwtCompare (const void *elem1, const void *elem2)
341 for (i=0 ; i<bwt_size ; i++)
349 if (++i1 == bwt_size)
351 if (++i2 == bwt_size)
363 cblock_t BWT (cblock_t in)
373 sorted = malloc(in.count*sizeof(*sorted));
374 for (i=0 ; i<in.count ; i++)
376 qsort (sorted, in.count, sizeof(*sorted), bwtCompare);
378 out_p = out.data = malloc(in.count + 8);
381 *out_p++ = in.count&255;
382 *out_p++ = (in.count>>8)&255;
383 *out_p++ = (in.count>>16)&255;
384 *out_p++ = (in.count>>24)&255;
387 for (i=0 ; i<in.count ; i++)
391 *out_p++ = (i>>8)&255;
392 *out_p++ = (i>>16)&255;
393 *out_p++ = (i>>24)&255;
395 // write the L column
396 for (i=0 ; i<in.count ; i++)
397 *out_p++ = in.data[(sorted[i]+in.count-1)%in.count];
401 out.count = out_p - out.data;
406 //==========================================================================
408 typedef struct hnode_s
417 unsigned charbits[256];
418 int charbitscount[256];
420 int SmallestNode (void)
427 for (i=0 ; i<numhnodes ; i++)
431 if (!hnodes[i].count)
433 if (hnodes[i].count < best)
435 best = hnodes[i].count;
443 hnodes[bestnode].used = true;
447 void BuildChars (int nodenum, unsigned bits, int bitcount)
454 Error ("bitcount > 32");
455 charbits[nodenum] = bits;
456 charbitscount[nodenum] = bitcount;
460 node = &hnodes[nodenum];
462 BuildChars (node->children[0], bits, bitcount+1);
464 BuildChars (node->children[1], bits, bitcount+1);
473 cblock_t Huffman (cblock_t in)
484 memset (hnodes, 0, sizeof(hnodes));
485 for (i=0 ; i<in.count ; i++)
486 hnodes[in.data[i]].count++;
491 for (i=0 ; i<256 ; i++)
493 if (hnodes[i].count > max)
495 max = hnodes[i].count;
500 Error ("Huffman: max == 0");
502 for (i=0 ; i<256 ; i++)
504 hnodes[i].count = (hnodes[i].count*255+max-1) / max;
509 while (numhnodes != 511)
511 node = &hnodes[numhnodes];
513 // pick two lowest counts
514 node->children[0] = SmallestNode ();
515 if (node->children[0] == -1)
518 node->children[1] = SmallestNode ();
519 if (node->children[1] == -1)
521 if (node->children[0] != numhnodes-1)
522 Error ("Bad smallestnode");
525 node->count = hnodes[node->children[0]].count +
526 hnodes[node->children[1]].count;
530 BuildChars (numhnodes-1, 0, 0);
532 out_p = out.data = malloc(in.count*2 + 1024);
533 memset (out_p, 0, in.count*2+1024);
536 *out_p++ = in.count&255;
537 *out_p++ = (in.count>>8)&255;
538 *out_p++ = (in.count>>16)&255;
539 *out_p++ = (in.count>>24)&255;
541 // save out the 256 normalized counts so the tree can be recreated
542 for (i=0 ; i<256 ; i++)
543 *out_p++ = hnodes[i].count;
547 for (i=0 ; i<in.count ; i++)
549 c = charbitscount[in.data[i]];
550 bits = charbits[in.data[i]];
555 out_p[outbits>>3] |= 1<<(outbits&7);
560 out_p += (outbits+7)>>3;
562 out.count = out_p - out.data;
567 //==========================================================================
574 #define RLE_CODE 0xe8
575 #define RLE_TRIPPLE 0xe9
580 cblock_t RLE (cblock_t in)
588 out_p = out.data = malloc (in.count*2);
591 *out_p++ = in.count&255;
592 *out_p++ = (in.count>>8)&255;
593 *out_p++ = (in.count>>16)&255;
594 *out_p++ = (in.count>>24)&255;
596 for (i=0 ; i<in.count ; )
602 while (i<in.count && repeat < 255 && in.data[i] == val)
608 rle_counts[repeat]++;
609 if (repeat > 3 || val == RLE_CODE)
622 out.count = out_p - out.data;
626 //==========================================================================
628 unsigned lzss_head[256];
629 unsigned lzss_next[0x20000];
636 #define BACK_WINDOW 0x10000
638 #define FRONT_WINDOW 16
640 cblock_t LZSS (cblock_t in)
647 int bestlength, beststart;
650 if (in.count >= sizeof(lzss_next)/4)
651 Error ("LZSS: too big");
653 memset (lzss_head, -1, sizeof(lzss_head));
655 out_p = out.data = malloc (in.count*2);
656 memset (out.data, 0, in.count*2);
659 *out_p++ = in.count&255;
660 *out_p++ = (in.count>>8)&255;
661 *out_p++ = (in.count>>16)&255;
662 *out_p++ = (in.count>>24)&255;
665 for (i=0 ; i<in.count ; )
674 if (i + max > in.count)
677 start = lzss_head[val];
678 while (start != -1 && start >= i-BACK_WINDOW)
680 // count match length
681 for (j=0 ; j<max ; j++)
682 if (in.data[start+j] != in.data[i+j])
689 start = lzss_next[start];
693 // slow simple search
694 // search for a match
696 if (i + max > in.count)
699 start = i - BACK_WINDOW;
704 for ( ; start < i ; start++)
706 if (in.data[start] != val)
708 // count match length
709 for (j=0 ; j<max ; j++)
710 if (in.data[start+j] != in.data[i+j])
719 beststart = BACK_WINDOW - (i-beststart);
722 { // output a single char
725 out_p[outbits>>3] |= 1<<(outbits&7); // set bit to mark char
727 for (j=0 ; j<8 ; j++, outbits++)
729 out_p[outbits>>3] |= 1<<(outbits&7);
733 outbits++; // leave a 0 bit to mark phrase
734 for (j=0 ; j<BACK_BITS ; j++, outbits++)
735 if (beststart & (1<<j) )
736 out_p[outbits>>3] |= 1<<(outbits&7);
737 for (j=0 ; j<FRONT_BITS ; j++, outbits++)
738 if (bestlength & (1<<j) )
739 out_p[outbits>>3] |= 1<<(outbits&7);
745 lzss_next[i] = lzss_head[val];
751 out_p += (outbits+7)>>3;
752 out.count = out_p - out.data;
756 //==========================================================================
760 #define HUF_TOKENS (256+MAX_REPT)
762 unsigned charbits1[256][HUF_TOKENS];
763 int charbitscount1[256][HUF_TOKENS];
765 hnode_t hnodes1[256][HUF_TOKENS*2];
768 int order0counts[256];
775 int SmallestNode1 (hnode_t *hnodes, int numhnodes)
782 for (i=0 ; i<numhnodes ; i++)
786 if (!hnodes[i].count)
788 if (hnodes[i].count < best)
790 best = hnodes[i].count;
798 hnodes[bestnode].used = true;
808 void BuildChars1 (int prev, int nodenum, unsigned bits, int bitcount)
812 if (nodenum < HUF_TOKENS)
815 Error ("bitcount > 32");
816 charbits1[prev][nodenum] = bits;
817 charbitscount1[prev][nodenum] = bitcount;
821 node = &hnodes1[prev][nodenum];
823 BuildChars1 (prev, node->children[0], bits, bitcount+1);
825 BuildChars1 (prev, node->children[1], bits, bitcount+1);
834 void BuildTree1 (int prev)
836 hnode_t *node, *nodebase;
840 numhnodes = HUF_TOKENS;
841 nodebase = hnodes1[prev];
844 node = &nodebase[numhnodes];
846 // pick two lowest counts
847 node->children[0] = SmallestNode1 (nodebase, numhnodes);
848 if (node->children[0] == -1)
851 node->children[1] = SmallestNode1 (nodebase, numhnodes);
852 if (node->children[1] == -1)
855 node->count = nodebase[node->children[0]].count +
856 nodebase[node->children[1]].count;
859 numhnodes1[prev] = numhnodes-1;
860 BuildChars1 (prev, numhnodes-1, 0, 0);
869 void Huffman1_Count (cblock_t in)
877 for (i=0 ; i<in.count ; i++)
881 hnodes1[prev][v].count++;
884 for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
885 if (in.data[i+rept] != v)
889 hnodes1[prev][255+rept].count++;
902 byte scaled[256][HUF_TOKENS];
903 void Huffman1_Build (FILE *f)
909 for (i=0 ; i<256 ; i++)
911 // normalize and save the counts
913 for (j=0 ; j<HUF_TOKENS ; j++)
915 if (hnodes1[i][j].count > max)
916 max = hnodes1[i][j].count;
921 for (j=0 ; j<HUF_TOKENS ; j++)
922 { // easy to overflow 32 bits here!
923 v = (hnodes1[i][j].count*(double)255+max-1)/max;
926 scaled[i][j] = hnodes1[i][j].count = v;
931 { // must have two tokens
933 scaled[i][0] = hnodes1[i][0].count = 1;
935 scaled[i][1] = hnodes1[i][1].count = 1;
942 // count up the total bits
944 for (i=0 ; i<256 ; i++)
945 for (j=0 ; j<256 ; j++)
946 total += charbitscount1[i][j] * hnodes1[i][j].count;
949 printf ("%i bytes huffman1 compressed\n", total);
952 fwrite (scaled, 1, sizeof(scaled), f);
959 Order 1 compression with pre-built table
962 cblock_t Huffman1 (cblock_t in)
973 out_p = out.data = malloc(in.count*2 + 1024);
974 memset (out_p, 0, in.count*2+1024);
977 *out_p++ = in.count&255;
978 *out_p++ = (in.count>>8)&255;
979 *out_p++ = (in.count>>16)&255;
980 *out_p++ = (in.count>>24)&255;
985 for (i=0 ; i<in.count ; i++)
989 c = charbitscount1[prev][v];
990 bits = charbits1[prev][v];
997 out_p[outbits>>3] |= 1<<(outbits&7);
1003 // check for repeat encodes
1004 for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
1005 if (in.data[i+rept] != v)
1007 if (rept > MIN_REPT)
1009 c = charbitscount1[prev][255+rept];
1010 bits = charbits1[prev][255+rept];
1017 out_p[outbits>>3] |= 1<<(outbits&7);
1025 out_p += (outbits+7)>>3;
1027 out.count = out_p - out.data;
1032 //==========================================================================
1040 cblock_t LoadFrame (char *base, int frame, int digits, byte **palette)
1042 int ten3, ten2, ten1, ten0;
1052 ten2 = (frame-ten3*1000)/100;
1053 ten1 = (frame-ten3*1000-ten2*100)/10;
1057 sprintf (name, "%svideo/%s/%s%i%i%i%i.pcx", gamedir, base, base, ten3, ten2, ten1, ten0);
1059 sprintf (name, "%svideo/%s/%s%i%i%i.pcx", gamedir, base, base, ten2, ten1, ten0);
1061 f = fopen(name, "rb");
1069 printf ("%s\n", name);
1070 Load256Image (name, &in.data, palette, &width, &height);
1071 in.count = width*height;
1072 // FIXME: map 0 and 255!
1089 video <directory> <framedigits>
1092 void Cmd_Video (void)
1094 char savename[1024];
1097 int startframe, frame;
1100 byte current_palette[768];
1104 cblock_t in, huffman;
1109 strcpy (base, token);
1112 // sprintf (savename, "video/%s.cin", token);
1113 // ReleaseFile (savename);
1118 digits = atoi(token);
1120 // optionally skip frames
1121 if (TokenAvailable ())
1124 startframe = atoi(token);
1129 sprintf (savename, "%svideo/%s.cin", gamedir, base);
1133 memset (charbits1, 0, sizeof(charbits1));
1134 memset (charbitscount1, 0, sizeof(charbitscount1));
1135 memset (hnodes1, 0, sizeof(hnodes1));
1136 memset (numhnodes1, 0, sizeof(numhnodes1));
1137 memset (order0counts, 0, sizeof(order0counts));
1140 // load the entire sound wav file if present
1144 sprintf (name, "%svideo/%s/%s0000.pcx", gamedir, base, base);
1146 sprintf (name, "%svideo/%s/%s000.pcx", gamedir, base, base);
1148 printf ("%s\n", name);
1149 Load256Image (name, NULL, &palette, &width, &height);
1151 output = fopen (savename, "wb");
1153 Error ("Can't open %s", savename);
1155 // write header info
1156 i = LittleLong (width);
1157 fwrite (&i, 4, 1, output);
1158 i = LittleLong (height);
1159 fwrite (&i, 4, 1, output);
1160 i = LittleLong (wavinfo.rate);
1161 fwrite (&i, 4, 1, output);
1162 i = LittleLong (wavinfo.width);
1163 fwrite (&i, 4, 1, output);
1164 i = LittleLong (wavinfo.channels);
1165 fwrite (&i, 4, 1, output);
1167 // build the dictionary
1168 for ( frame=startframe ; ; frame++)
1170 printf ("counting ", frame);
1171 in = LoadFrame (base, frame, digits, &palette);
1174 Huffman1_Count (in);
1179 // build nodes and write counts
1180 Huffman1_Build (output);
1183 memset (current_palette, 0, sizeof(current_palette));
1185 // compress it with the dictionary
1186 for (frame=startframe ; ; frame++)
1188 printf ("packing ", frame);
1189 in = LoadFrame (base, frame, digits, &palette);
1193 // see if the palette has changed
1194 for (i=0 ; i<768 ; i++)
1195 if (palette[i] != current_palette[i])
1197 // write a palette change
1198 memcpy (current_palette, palette, sizeof(current_palette));
1199 command = LittleLong(1);
1200 fwrite (&command, 1, 4, output);
1201 fwrite (current_palette, 1, sizeof(current_palette), output);
1206 command = 0; // no palette change
1207 fwrite (&command, 1, 4, output);
1211 huffman = Huffman1 (in);
1212 printf ("%5i bytes after huffman1\n", huffman.count);
1214 swap = LittleLong (huffman.count);
1215 fwrite (&swap, 1, sizeof(swap), output);
1217 fwrite (huffman.data, 1, huffman.count, output);
1219 // save some sound samples
1220 WriteSound (output, frame);
1224 free (huffman.data);
1228 // write end-of-file command
1230 fwrite (&command, 1, 4, output);
1232 printf ("Total size: %i\n", ftell (output));