]> git.xonotic.org Git - voretournament/voretournament.git/blob - misc/source/netradiant-src/tools/quake2/qdata_heretic2/video.c
Rename mediasource to source
[voretournament/voretournament.git] / misc / source / netradiant-src / tools / quake2 / qdata_heretic2 / video.c
1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 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.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 // To do
23
24 // Sound error handling (when sound too short)
25 // rle b4 huffing
26 // adpcm encoding of sound
27
28 #if     0
29 #include "qdata.h"
30 #include "flex.h"
31 #include "fc.h"
32 #include "adpcm.h"
33
34 #define MIN_REPT        15
35 #define MAX_REPT        0
36 #define HUF_TOKENS      (256 + MAX_REPT)
37
38 #define BLOCKSIZE       8
39
40 #define M_PI            3.14159265358979323846  // matches value in gcc v2 math.h
41 #define SQRT2           1.414213562
42
43 typedef struct hnode_s
44 {
45         int                     count;
46         qboolean        used;
47         int                     children[2];
48 } hnode_t;
49
50 typedef struct
51 {
52         int                     rate;
53         int                     width;
54         int                     channels;
55         int                     loopstart;
56         int                     samples;
57         int                     dataofs;                // chunk starts this many bytes from file start
58 } wavinfo_t;
59
60 // These weren`t picked out my ass....
61 // They were defined at http://www.rahul.net/jfm/dct.html
62 // However, I think he plucked them out of his ass.....
63
64 float Quantise[BLOCKSIZE * BLOCKSIZE];
65
66 float LUT_Quantise[BLOCKSIZE * BLOCKSIZE] =
67 {
68         16.0F/16.0F, 11.0F/16.0F, 10.0F/16.0F, 16.0F/16.0F, 24.0F/16.0F, 40.0F/16.0F, 51.0F/16.0F, 61.0F/16.0F,
69         12.0F/16.0F, 13.0F/16.0F, 14.0F/16.0F, 19.0F/16.0F, 26.0F/16.0F, 58.0F/16.0F, 60.0F/16.0F, 55.0F/16.0F,
70         14.0F/16.0F, 13.0F/16.0F, 16.0F/16.0F, 24.0F/16.0F, 40.0F/16.0F, 57.0F/16.0F, 69.0F/16.0F, 56.0F/16.0F,
71         14.0F/16.0F, 17.0F/16.0F, 22.0F/16.0F, 29.0F/16.0F, 51.0F/16.0F, 87.0F/16.0F, 80.0F/16.0F, 62.0F/16.0F,
72         18.0F/16.0F, 22.0F/16.0F, 37.0F/16.0F, 56.0F/16.0F, 68.0F/16.0F,109.0F/16.0F,103.0F/16.0F, 77.0F/16.0F,
73         24.0F/16.0F, 35.0F/16.0F, 55.0F/16.0F, 64.0F/16.0F, 81.0F/16.0F,104.0F/16.0F,113.0F/16.0F, 92.0F/16.0F,
74         49.0F/16.0F, 64.0F/16.0F, 78.0F/16.0F, 87.0F/16.0F,103.0F/16.0F,121.0F/16.0F,120.0F/16.0F,101.0F/16.0F,
75         72.0F/16.0F, 92.0F/16.0F, 95.0F/16.0F, 98.0F/16.0F,112.0F/16.0F,100.0F/16.0F,103.0F/16.0F, 99.0F/16.0F
76 };
77
78 int LUT_ZZ[BLOCKSIZE * BLOCKSIZE] =
79 {
80          0,
81          1,  8, 
82         16,  9,  2,
83          3, 10, 17, 24,
84         32, 25, 18, 11,  4,
85          5, 12, 19, 26, 33, 40,
86         48, 41, 34, 27, 20, 13, 6,
87          7, 14, 21, 28, 35, 42, 49, 56,
88         57, 50, 43, 36, 29, 22, 15,
89         23, 30, 37, 44, 51, 58,
90         59, 52, 45, 38, 31, 
91         39, 46, 53, 60,
92         61, 54, 47,
93         55, 62, 
94         63
95 };
96
97 char                    base[32];
98
99 byte                    *soundtrack;
100
101 byte                    scaled[256][HUF_TOKENS];
102 unsigned int    charbits1[256][HUF_TOKENS];
103 int                             charbitscount1[256][HUF_TOKENS];
104 hnode_t                 hnodes1[256][HUF_TOKENS * 2];
105 int                             numhnodes1[256];
106 int                             order0counts[256];
107 int                             numhnodes;
108 hnode_t                 hnodes[512];
109 unsigned                charbits[256];
110 int                             charbitscount[256];
111
112 CineHead_t              cinehead;
113
114 byte                    *data_p;
115 byte                    *iff_end;
116 byte                    *last_chunk;
117 byte                    *iff_data;
118 int                             iff_chunk_len;
119
120 float                   dctbase[BLOCKSIZE][BLOCKSIZE];
121 float                   red[BLOCKSIZE * BLOCKSIZE];
122 float                   green[BLOCKSIZE * BLOCKSIZE];
123 float                   blue[BLOCKSIZE * BLOCKSIZE];
124 float                   temp[BLOCKSIZE * BLOCKSIZE];
125
126 wavinfo_t               wavinfo;
127 adpcm_t                 adpcm;
128
129 /*
130 ===============================================================================
131
132 WAV loading
133
134 ===============================================================================
135 */
136
137 /* Intel ADPCM step variation table */
138 static int indexTable[16] = 
139 {
140         -1, -1, -1, -1, 2, 4, 6, 8,
141         -1, -1, -1, -1, 2, 4, 6, 8,
142 };
143
144 static int stepsizeTable[89] = 
145 {
146         7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
147         19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
148         50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
149         130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
150         337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
151         876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
152         2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
153         5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
154         15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
155 };
156
157 #if     0
158 static void adpcm_decoder(char *indata, short *outdata, int len, adpcm_state_t *state)
159 {
160         signed char *inp;               /* Input buffer pointer */
161         short *outp;            /* output buffer pointer */
162         int sign;                       /* Current adpcm sign bit */
163         int delta;                      /* Current adpcm output value */
164         int step;                       /* Stepsize */
165         int valpred;            /* Predicted value */
166         int vpdiff;             /* Current change to valpred */
167         int index;                      /* Current step change index */
168         int inputbuffer;                /* place to keep next 4-bit value */
169         int bufferstep;         /* toggle between inputbuffer/input */
170
171         outp = outdata;
172         inp = (signed char *)indata;
173
174         valpred = state->valprev;
175         index = state->index;
176         step = stepsizeTable[index];
177
178         bufferstep = 0;
179         
180         for(; len > 0; len--)
181         {
182                 /* Step 1 - get the delta value */
183                 if (bufferstep)
184                         delta = inputbuffer & 0xf;
185                 else
186                 {
187                         inputbuffer = *inp++;
188                         delta = (inputbuffer >> 4) & 0xf;
189                 }
190                 bufferstep = !bufferstep;
191
192                 /* Step 2 - Find new index value (for later) */
193                 index += indexTable[delta];
194                 if(index < 0)
195                         index = 0;
196                 if(index > 88)
197                         index = 88;
198
199                 /* Step 3 - Separate sign and magnitude */
200                 sign = delta & 8;
201                 delta = delta & 7;
202
203                 /* Step 4 - Compute difference and new predicted value */
204                 /*
205                 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
206                 ** in adpcm_coder.
207                 */
208                 vpdiff = step >> 3;
209                 if(delta & 4)
210                         vpdiff += step;
211                 if(delta & 2)
212                         vpdiff += step>>1;
213                 if(delta & 1)
214                         vpdiff += step>>2;
215
216                 if (sign)
217                   valpred -= vpdiff;
218                 else
219                   valpred += vpdiff;
220
221                 /* Step 5 - clamp output value */
222                 if (valpred > 32767)
223                   valpred = 32767;
224                 else if (valpred < -32768)
225                   valpred = -32768;
226
227                 /* Step 6 - Update step value */
228                 step = stepsizeTable[index];
229
230                 /* Step 7 - Output value */
231                 *outp++ = valpred;
232         }
233
234         state->valprev = valpred;
235         state->index = index;
236 }
237 #endif
238
239 void adpcm_coder(short *inp, adpcm_t *adpcm)
240 {
241         int                             val;                    /* Current input sample value */
242         int                             sign;                   /* Current adpcm sign bit */
243         int                             delta;                  /* Current adpcm output value */
244         int                             diff;                   /* Difference between val and valprev */
245         int                             step;                   /* Stepsize */
246         int                             valpred;                /* Predicted output value */
247         int                             vpdiff;                 /* Current change to valpred */
248         int                             index;                  /* Current step change index */
249         int                             outputbuffer;   /* place to keep previous 4-bit value */
250         int                             bufferstep;     /* toggle between outputbuffer/output */
251         adpcm_state_t   *state;
252         char                    *outp;
253         int                             len;
254
255         state = &adpcm->state;
256         len = state->count;
257         outp = adpcm->adpcm;
258
259         valpred = state->in_valprev;
260         index = state->in_index;
261         step = stepsizeTable[index];
262         
263         bufferstep = 1;
264         while(len--)
265         {
266                 val = *inp++;
267
268                 /* Step 1 - compute difference with previous value */
269                 diff = val - valpred;
270                 sign = (diff < 0) ? 8 : 0;
271                 if (sign)
272                         diff = -diff;
273
274                 /* Step 2 - Divide and clamp */
275                 /* Note:
276                 ** This code *approximately* computes:
277                 **        delta = diff*4/step;
278                 **        vpdiff = (delta+0.5)*step/4;
279                 ** but in shift step bits are dropped. The net result of this is
280                 ** that even if you have fast mul/div hardware you cannot put it to
281                 ** good use since the fixup would be too expensive.
282                 */
283                 delta = 0;
284                 vpdiff = (step >> 3);
285                 
286                 if (diff >= step)
287                 {
288                         delta = 4;
289                         diff -= step;
290                         vpdiff += step;
291                 }
292                 step >>= 1;
293                 if (diff >= step)
294                 {
295                         delta |= 2;
296                         diff -= step;
297                         vpdiff += step;
298                 }
299                 step >>= 1;
300                 if (diff >= step)
301                 {
302                         delta |= 1;
303                         vpdiff += step;
304                 }
305
306                 /* Step 3 - Update previous value */
307                 if (sign)
308                   valpred -= vpdiff;
309                 else
310                   valpred += vpdiff;
311
312                 /* Step 4 - Clamp previous value to 16 bits */
313                 if (valpred > 32767)
314                   valpred = 32767;
315                 else if (valpred < -32768)
316                   valpred = -32768;
317
318                 /* Step 5 - Assemble value, update index and step values */
319                 delta |= sign;
320                 
321                 index += indexTable[delta];
322                 if (index < 0)
323                         index = 0;
324                 if (index > 88)
325                         index = 88;
326                 step = stepsizeTable[index];
327
328                 /* Step 6 - Output value */
329                 if (bufferstep)
330                         outputbuffer = (delta << 4) & 0xf0;
331                 else
332                         *outp++ = (delta & 0x0f) | outputbuffer;
333
334                 bufferstep = !bufferstep;
335         }
336
337         /* Output last step, if needed */
338         if(!bufferstep)
339           *outp++ = outputbuffer;
340         
341         state->out_valprev = valpred;
342         state->out_index = index;
343 }
344
345 void FindNextChunk(char *name)
346 {
347         while(1)
348         {
349                 data_p = last_chunk;
350
351                 if(data_p >= iff_end)
352                 {                                                               // didn't find the chunk
353                         data_p = NULL;
354                         return;
355                 }
356                 
357                 data_p += 4;
358                 iff_chunk_len = *(long *)data_p;
359                 data_p += 4;
360                 if(iff_chunk_len < 0)
361                 {
362                         data_p = NULL;
363                         return;
364                 }
365
366                 data_p -= 8;
367                 last_chunk = data_p + 8 + ((iff_chunk_len + 1) & ~1);
368                 if (!strncmp(data_p, name, 4))
369                         return;
370         }
371 }
372
373 void FindChunk(char *name)
374 {
375         last_chunk = iff_data;
376         FindNextChunk (name);
377 }
378
379 void DumpChunks(void)
380 {
381         char    str[5];
382         
383         str[4] = 0;
384         data_p = iff_data;
385         do
386         {
387                 memcpy (str, data_p, 4);
388                 data_p += 4;
389                 iff_chunk_len = *(long *)data_p;
390                 data_p += 4;
391                 printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
392                 data_p += (iff_chunk_len + 1) & ~1;
393         }
394         while(data_p < iff_end);
395 }
396
397 /*
398 ============
399 GetWavinfo
400 ============
401 */
402 wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
403 {
404         wavinfo_t       info;
405         int                     i;
406         int                     format;
407         int                     samples;
408
409         memset(&info, 0, sizeof(info));
410
411         if (!wav)
412                 return(info);
413                 
414         iff_data = wav;
415         iff_end = wav + wavlength;
416
417 // find "RIFF" chunk
418         FindChunk("RIFF");
419         if (!(data_p && !strncmp(data_p + 8, "WAVE", 4)))
420         {
421                 printf("Missing RIFF/WAVE chunks\n");
422                 return(info);
423         }
424
425 // get "fmt " chunk
426         iff_data = data_p + 12;
427
428         FindChunk("fmt ");
429         if(!data_p)
430         {
431                 printf("Missing fmt chunk\n");
432                 return(info);
433         }
434         data_p += 8;
435         format = *(short *)data_p;
436         data_p += 2;
437         if (format != 1)
438         {
439                 printf("Microsoft PCM format only\n");
440                 return(info);
441         }
442
443         info.channels = *(short *)data_p;
444         data_p += 2;
445         info.rate = *(long *)data_p;
446         data_p += 4;
447         data_p += 6;
448         info.width = *(short *)data_p / 8;
449         data_p += 2;
450
451 // get cue chunk
452         FindChunk("cue ");
453         if(data_p)
454         {
455                 data_p += 32;
456                 info.loopstart = *(long *)data_p;
457                 data_p += 4;
458
459 // if the next chunk is a LIST chunk, look for a cue length marker
460                 FindNextChunk ("LIST");
461                 if(data_p)
462                 {
463 // this is not a proper parse, but it works with cooledit...
464                         if (!strncmp (data_p + 28, "mark", 4))
465                         {
466                                 data_p += 24;
467                                 i = *(long *)data_p;                                    // samples in loop
468                                 data_p += 4;
469                                 info.samples = info.loopstart + i;
470                         }
471                 }
472         }
473         else
474                 info.loopstart = -1;
475
476 // find data chunk
477         FindChunk("data");
478         if (!data_p)
479         {
480                 printf("Missing data chunk\n");
481                 return(info);
482         }
483
484         data_p += 4;
485         samples = *(long *)data_p;
486         data_p += 4;
487
488         if (info.samples)
489         {
490                 if(samples < info.samples)
491                         Error ("Sound %s has a bad loop length", name);
492         }
493         else
494                 info.samples = samples;
495
496         info.dataofs = data_p - wav;
497         return(info);
498 }
499
500 // ==============
501 // LoadSoundtrack
502 // ==============
503
504 void LoadSoundtrack()
505 {
506         char    name[1024];
507         FILE    *f;
508         int             len;
509
510         soundtrack = NULL;
511         sprintf (name, "%svideo/%s/%s.wav", gamedir, base, base);
512         printf ("\nLoading sound    : %s\n", name);
513         f = fopen (name, "rb");
514         if (!f)
515         {
516                 printf ("\nNo soundtrack for %s\n", base);
517                 return;
518         }
519         len = Q_filelength(f);
520         soundtrack = SafeMalloc(len, "LoadSoundtrack");
521         fread(soundtrack, 1, len, f);
522         fclose(f);
523
524         wavinfo = GetWavinfo(name, soundtrack, len);
525         adpcm.state.out_valprev = 0;
526         adpcm.state.out_index = 0;
527 }
528
529 // ==================
530 // WriteSound
531 // ==================
532
533 int WriteSound(FILE *output, int frame, int numframes)
534 {
535         int             start, end;
536         int             count;
537         int             empty = 0;
538         int             width;
539         char    *work;
540
541         width = wavinfo.width * wavinfo.channels;
542         start = ((frame * wavinfo.rate / 14) + 31) & 0xffffffe0;                                // start sample
543         end = (((frame + numframes) * wavinfo.rate / 14) + 31) & 0xffffffe0;    // end sample
544         count = end - start;
545
546         work = soundtrack + wavinfo.dataofs + (start * width);
547         adpcm.state.count = count * wavinfo.channels;                   // Number of samples
548         adpcm.state.in_valprev = adpcm.state.out_valprev;
549         adpcm.state.in_index = adpcm.state.out_index;
550         adpcm_coder((short *)work, &adpcm);
551         WriteHeader(output, FC_SOUND_22KMADPCM, FC_ADPCM_VERSION, (adpcm.state.count / 2) + sizeof(adpcm_state_t), (char *)&adpcm);
552         return(count / 2);
553 }
554 // ==============================
555 // Basic run length encoder
556 // ==============================
557
558 char *RLEZZ(char *in, char *out)
559 {
560         int             srun;
561         char    count;
562         int             idx = 0;
563
564         while(idx < 64)
565         {
566                 srun = idx;                                                             // Start of run
567
568                 while(idx < 63)
569                 {
570                         if(in[LUT_ZZ[idx]] != in[LUT_ZZ[idx + 1]])
571                                 break;
572                         idx++;
573                 }
574                 count = (char)(idx - srun);                             // count of repeated bytes
575
576                 if(!count)
577                 {
578                         while(idx < 63)
579                         {
580                                 if(in[LUT_ZZ[idx]] == in[LUT_ZZ[idx + 1]])
581                                         break;
582                                 idx++;
583                         }
584                         if(idx == 63)
585                                 idx++;
586
587                         count = (char)(idx - srun);                     // count of unique bytes
588                         *out++ = count;
589                         while(count--)
590                                 *out++ = in[LUT_ZZ[srun++]];
591                 }
592                 else
593                 {
594                         *out++ = -(count + 1);
595                         *out++ = in[LUT_ZZ[idx]];
596                         idx++;
597                 }
598         }
599         return(out);
600 }
601
602 // ==============================
603 // Discrete Cosine Transformation
604 // ==============================
605
606 void init_base(float quant)
607 {
608         int                     y, x;
609
610         for(y = 0; y < BLOCKSIZE; y++)
611                 for(x = 0; x < BLOCKSIZE; x++)
612                 {
613                         if(y == 0)
614                                 dctbase[y][x] = 1;
615                         else
616                                 dctbase[y][x] = SQRT2 * cos(((x * 2 + 1) * y * M_PI) / (BLOCKSIZE * 2));
617                 }
618
619         for(y = 0; y < BLOCKSIZE * BLOCKSIZE; y++)
620                 Quantise[y] = LUT_Quantise[y] / quant;
621 }
622
623 void SplitComponents(byte *src, int width, int height)
624 {
625         int             i, j;
626         float   *tr = red;
627         float   *tg = green;
628         float   *tb = blue;
629
630         for(i = 0; i < BLOCKSIZE; i++, src += (width - BLOCKSIZE) * 4)
631                 for(j = 0; j < BLOCKSIZE; j++)
632                 {
633                         *tr++ = ((float)*src++) - 128.0F;
634                         *tg++ = ((float)*src++) - 128.0F;
635                         *tb++ = ((float)*src++) - 128.0F;
636                         src++;
637                 }
638 }
639
640 void transferH(float *src, float *dst)
641 {
642         int             y, dx, dy;
643         float   sum;
644         float   *work;
645
646         for(y = 0; y < BLOCKSIZE; y++, src += BLOCKSIZE)
647         {
648                 for(dy = 0; dy < BLOCKSIZE; dy++)
649                 {
650                         sum = 0;
651                         work = src;
652                         for(dx = 0; dx < BLOCKSIZE; dx++, work++)
653                                 sum += dctbase[dy][dx] * *work;
654
655                         *dst++ = sum / BLOCKSIZE;
656                 }
657         }
658 }
659
660 void transferV(float *src, float *dst)
661 {
662         int             x, dy, fy;
663         float   sum;
664         float   *work;
665
666         for(x = 0; x < BLOCKSIZE; x++, src++, dst++)
667         {
668                 for(fy = 0; fy < BLOCKSIZE; fy++)
669                 {
670                         sum = 0;
671                         work = src;
672                         for(dy = 0; dy < BLOCKSIZE; dy++, work += BLOCKSIZE)
673                                 sum += dctbase[fy][dy] * *work;
674
675                         dst[fy * BLOCKSIZE] = sum / BLOCKSIZE;
676                 }
677         }
678 }
679
680 char *Combine(byte *dst, float *p, float *q)
681 {
682         int             i, j;
683         byte    rlesrc[BLOCKSIZE * BLOCKSIZE];
684         int             c;
685         byte    *work;
686
687         work = rlesrc;
688         for(j = 0; j < BLOCKSIZE; j++)
689                 for(i = 0; i < BLOCKSIZE; i++)
690                 {
691                         c = (int)((*p++ / *q++) + 128.5F);
692                         c -= 128;
693
694                         if(c < -128)
695                                 c = -128;
696                         if(c > 127)
697                                 c = 127;
698
699                         *work++ = (char)c;
700                 }
701
702         dst = RLEZZ(rlesrc, dst);
703         return(dst);
704 }
705
706 char *CombineComponents(char *dst, int width, int height)
707 {
708         dst = Combine(dst, red, Quantise);
709         dst = Combine(dst, green, Quantise);
710         dst = Combine(dst, blue, Quantise);
711         return(dst);
712 }
713
714 void DCT(cblock_t *out, cblock_t in, int width, int height)
715 {
716         int             x, y;
717         char    *cursrc;
718         char    *curdst;
719
720         curdst = out->data;
721         for(y = 0; y < height; y += BLOCKSIZE)
722                 for(x = 0; x < width; x += BLOCKSIZE)
723                 {
724                         cursrc = in.data + ((y * width) + x) * 4;
725                         SplitComponents(cursrc, width, height);
726                         transferH(red, temp);
727                         transferV(temp, red);
728                         transferH(green, temp);
729                         transferV(temp, green);
730                         transferH(blue, temp);
731                         transferV(temp, blue);
732                         curdst = CombineComponents(curdst, width, height);
733                 }
734         out->count = curdst - out->data;
735 }
736
737 // ==================
738 // BuildChars1
739 // ==================
740
741 void BuildChars1(int prev, int nodenum, unsigned bits, int bitcount)
742 {
743         hnode_t         *node;
744
745         if(nodenum < HUF_TOKENS)
746         {
747                 if (bitcount > 32)
748                         Error("bitcount > 32");
749                 charbits1[prev][nodenum] = bits;
750                 charbitscount1[prev][nodenum] = bitcount;
751                 return;
752         }
753
754         node = &hnodes1[prev][nodenum];
755         bits <<= 1;
756         BuildChars1(prev, node->children[0], bits, bitcount+1);
757         bits |= 1;
758         BuildChars1(prev, node->children[1], bits, bitcount+1);
759 }
760
761 // ==================
762 // SmallestNode1
763 // ==================
764
765 int     SmallestNode1(hnode_t *hnodes, int numhnodes)
766 {
767         int             i;
768         int             best, bestnode;
769
770         best = 99999999;
771         bestnode = -1;
772         for(i = 0; i < numhnodes; i++)
773         {
774                 if(hnodes[i].used)
775                         continue;
776                 if(!hnodes[i].count)
777                         continue;
778                 if(hnodes[i].count < best)
779                 {
780                         best = hnodes[i].count;
781                         bestnode = i;
782                 }
783         }
784
785         if (bestnode == -1)
786                 return(-1);
787
788         hnodes[bestnode].used = true;
789         return(bestnode);
790 }
791
792 // ==================
793 // BuildTree1
794 // ==================
795
796 void BuildTree1(int prev)
797 {
798         hnode_t         *node, *nodebase;
799         int                     numhnodes;
800
801         // build the nodes
802         numhnodes = HUF_TOKENS;
803         nodebase = hnodes1[prev];
804         while(1)
805         {
806                 node = &nodebase[numhnodes];
807
808                 // pick two lowest counts
809                 node->children[0] = SmallestNode1 (nodebase, numhnodes);
810                 if (node->children[0] == -1)
811                         break;  // no more
812
813                 node->children[1] = SmallestNode1 (nodebase, numhnodes);
814                 if (node->children[1] == -1)
815                         break;
816
817                 node->count = nodebase[node->children[0]].count + 
818                         nodebase[node->children[1]].count;
819                 numhnodes++;
820         }
821         numhnodes1[prev] = numhnodes-1;
822         BuildChars1 (prev, numhnodes-1, 0, 0);
823 }
824
825 // ==================
826 // Huffman1_Count
827 // ==================
828
829 void Huffman1_Count(cblock_t in)
830 {
831         int             i;
832         int             prev;
833         int             v;
834         int             rept;
835
836         prev = 0;
837         for(i = 0; i < in.count; i++)
838         {
839                 v = in.data[i];
840                 order0counts[v]++;
841                 hnodes1[prev][v].count++;
842                 prev = v;
843
844                 for(rept = 1; (i + rept < in.count) && (rept < MAX_REPT); rept++)
845                         if(in.data[i+rept] != v)
846                                 break;
847                 if(rept > MIN_REPT)
848                 {
849                         hnodes1[prev][255 + rept].count++;
850                         i += rept - 1;
851                 }
852         }
853 }
854
855 // ==================
856 // Huffman1_Build
857 // ==================
858
859 void Huffman1_Build()
860 {
861         int             i, j, v;
862         int             max;
863         int             total;
864
865         for(i = 0; i < 256; i++)
866         {
867 // normalize and save the counts
868                 max = 0;
869                 for (j = 0; j < HUF_TOKENS; j++)
870                 {
871                         if (hnodes1[i][j].count > max)
872                                 max = hnodes1[i][j].count;
873                 }
874                 if (max == 0)
875                         max = 1;
876                 total = 0;
877 // easy to overflow 32 bits here!
878                 for(j = 0; j < HUF_TOKENS; j++)
879                 {
880                         v = (hnodes1[i][j].count * (double) 255 + max - 1) / max;
881                         if (v > 255)
882                                 Error ("v > 255");
883                         scaled[i][j] = hnodes1[i][j].count = v;
884                         if (v)
885                                 total++;
886                 }
887                 if (total == 1)
888                 {       // must have two tokens
889                         if (!scaled[i][0])
890                                 scaled[i][0] = hnodes1[i][0].count = 1;
891                         else
892                                 scaled[i][1] = hnodes1[i][1].count = 1;
893                 }
894                 BuildTree1 (i);
895         }
896 }
897
898 // ==================
899 // Huffman1
900 // Order 1 compression with pre-built table
901 // ==================
902
903 cblock_t Huffman1(cblock_t in)
904 {
905         int                     i;
906         int                     outbits, c;
907         unsigned        bits;
908         byte            *out_p;
909         cblock_t        out;
910         int                     prev;
911         int                     v;
912         int                     rept;
913
914         out_p = out.data = SafeMalloc((in.count * 2) + 1024 + 4, "Huffman");
915         memset(out_p, 0, (in.count * 2) + 1024 + 4);
916
917         // leave space for compressed count
918         out_p += 4;
919         // write count
920         *(long *)out_p = in.count;
921         out_p += 4;
922
923         // write bits
924         outbits = 0;
925         prev = 0;
926         for(i = 0; i < in.count; i++)
927         {
928                 v = in.data[i];
929
930                 c = charbitscount1[prev][v];
931                 bits = charbits1[prev][v];
932                 if (!c)
933                         Error ("!bits");
934                 while (c)
935                 {
936                         c--;
937                         if (bits & (1 << c))
938                                 out_p[outbits>>3] |= 1 << (outbits & 7);
939                         outbits++;
940                 }
941
942                 prev = v;
943                 // check for repeat encodes
944                 for(rept = 1; (i + rept < in.count) && (rept < MAX_REPT); rept++)
945                         if(in.data[i + rept] != v)
946                                 break;
947                 if (rept > MIN_REPT)
948                 {
949                         c = charbitscount1[prev][255 + rept];
950                         bits = charbits1[prev][255 + rept];
951                         if (!c)
952                                 Error ("!bits");
953                         while (c)
954                         {
955                                 c--;
956                                 if(bits & (1 << c))
957                                         out_p[outbits >> 3] |= 1 << (outbits & 7);
958                                 outbits++;
959                         }
960                         i += rept - 1;
961                 }
962         }
963         out_p += (outbits + 7) >> 3;
964         out.count = out_p - out.data;
965
966         out_p = out.data;
967         *(long *)out_p = out.count;
968         return(out);
969 }
970 // ===================
971 // LoadFrame
972 // ===================
973
974 void LoadFrame(cblock_t *out, char *base, int frame)
975 {
976         cblock_t        in;
977         int                     width, height;
978         char            name[1024];
979         FILE            *f;
980
981         in.data = NULL;
982         in.count = -1;
983         sprintf (name, "%svideo/%s/%s%04i.tga", gamedir, base, base, frame);
984
985         f = fopen(name, "rb");
986         if (!f)
987         {
988                 out->data = NULL;
989                 return;
990         }
991         fclose (f);
992
993         LoadTGA(name, &in.data, &width, &height);
994         if((width != cinehead.Width) || (height != cinehead.Height))
995         {
996                 free(in.data);
997                 printf("Invalid picture size\n");
998                 out->data = NULL;
999                 return;
1000         }
1001         out->data = SafeMalloc(width * height * 3, "LoadFrame");                // rle could possibly expand file so this not 100% safe (however DCT should force a lot of compression)
1002         DCT(out, in, width, height);
1003         free(in.data);
1004 }
1005
1006 // ==================================
1007 // Cmd_Video
1008 // 
1009 // video <directory> <framedigits>
1010 // ==================================
1011
1012 void Cmd_Video()
1013 {
1014         char            savename[256];
1015         char            name[256];
1016         FILE            *output;
1017         int                     frame;
1018         int                     width, height;
1019         cblock_t        in, huffman;
1020         int                     size;
1021         float           dctconst;
1022         int                     maxsize, ssize;
1023         int                     min_rle_size, warnings;
1024         int                     ave_image, ave_sound;
1025
1026         GetScriptToken(false);
1027         strcpy(base, token);
1028         if (g_release)
1029                 return;
1030
1031         GetScriptToken(false);
1032         dctconst = atof(token);
1033         GetScriptToken(false);
1034         maxsize = atoi(token);
1035
1036         sprintf (savename, "%svideo/%s.cin", gamedir, base);
1037
1038         // clear stuff
1039         memset(charbits1, 0, sizeof(charbits1));
1040         memset(charbitscount1, 0, sizeof(charbitscount1));
1041         memset(hnodes1, 0, sizeof(hnodes1));
1042         memset(numhnodes1, 0, sizeof(numhnodes1));
1043         memset(order0counts, 0, sizeof(order0counts));
1044
1045         // load the entire sound wav file if present
1046         LoadSoundtrack();
1047
1048         cinehead.SndRate = wavinfo.rate;
1049         cinehead.SndWidth = wavinfo.width;
1050         cinehead.SndChannels = wavinfo.channels;
1051
1052         sprintf(name, "%svideo/%s/%s0000.tga", gamedir, base, base);
1053         printf("Loading sequence : %s\n", name);
1054         printf("DCT constant     : %f\n", dctconst);
1055
1056         LoadTGA (name, NULL, &width, &height);
1057
1058         output = fopen (savename, "wb");
1059         if (!output)
1060                 Error ("Can't open %s", savename);
1061
1062         if((width % BLOCKSIZE) || (height % BLOCKSIZE))
1063                 Error("Width and height must be a multiple of %d", BLOCKSIZE);
1064
1065         cinehead.Width = width;
1066         cinehead.Height = height;
1067         init_base(dctconst);
1068
1069         // build the dictionary
1070         printf("Counting         : ");
1071         min_rle_size = 0;
1072         for (frame = 0;  ; frame++)
1073         {
1074                 printf(".");
1075                 LoadFrame(&in, base, frame);
1076                 if(!in.data)
1077                         break;
1078                 Huffman1_Count(in);
1079                 if(in.count > min_rle_size)
1080                         min_rle_size = in.count;
1081                 free(in.data);
1082         }
1083         printf ("\n");
1084         cinehead.NumFrames = frame;
1085         printf("Num Frames       : %d\n", frame);
1086         cinehead.MaxRleSize = (min_rle_size + 0x1f) & 0xfffffe0;
1087         cinehead.MaxSndSize = ((4 * wavinfo.rate * wavinfo.channels / 14) + 0x1f) & 0xffffffe0;
1088
1089         WriteHeader(output, FC_HEADER_NAME, FC_HEADER_VERSION, sizeof(CineHead_t), &cinehead);
1090
1091         // build nodes and write counts
1092         Huffman1_Build();
1093         WriteHeader(output, FC_HUFFBITS_NAME, FC_HUFFBITS_VERSION, sizeof(scaled), scaled);
1094         WriteHeader(output, FC_QUANT_NAME, FC_QUANT_VERSION, sizeof(Quantise), Quantise);
1095
1096         ave_image = 0;
1097         ave_sound = 0;
1098         warnings = 0;
1099         // compress it with the dictionary
1100         if(soundtrack)
1101         {
1102                 ssize = WriteSound(output, frame, 4);
1103                 ave_sound += ssize;
1104         }
1105
1106         for (frame = 0; frame < cinehead.NumFrames; frame++)
1107         {
1108                 // save some sound samples
1109                 printf ("Packing          : ", frame);
1110                 LoadFrame(&in, base, frame);
1111
1112                 // save the image
1113                 huffman = Huffman1(in);
1114                 printf ("%d bytes rle, %d bytes huffman", in.count, huffman.count);
1115                 size = (huffman.count + 3) & 0xfffffffc;                                        // round up to longwords
1116                 if(size > maxsize)
1117                 {
1118                         printf(" ** WARNING **");
1119                         warnings++;
1120                 }
1121                 printf("\n");
1122                 ave_image += huffman.count;
1123
1124                 WriteHeader(output, FC_IMAGE_NAME, FC_IMAGE_VERSION, size, huffman.data);
1125                 if(soundtrack)
1126                 {
1127                         ssize = WriteSound(output, frame + 4, 1);
1128                         ave_sound += ssize;
1129                 }
1130
1131                 free (in.data);
1132                 free (huffman.data);
1133         }
1134         printf("\nTotal size: %d (headers + %d image + %d sound)\n", ftell(output), ave_image, ave_sound);
1135         printf("Data rate : %d bytes per sec (image and sound)\n", (ave_image + ave_sound) / cinehead.NumFrames);
1136         printf("Cin created ok with %d warnings.\n", warnings);
1137         fclose (output);
1138
1139         if (soundtrack)
1140                 free (soundtrack);
1141 }
1142 #endif
1143
1144 void Cmd_Video()
1145 {
1146 }
1147
1148 // end
1149