]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/video.c
Merge branch 'sysfprintf' into 'master'
[xonotic/netradiant.git] / 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         signed char *inp;       /* Input buffer pointer */
160         short *outp;        /* output buffer pointer */
161         int sign;           /* Current adpcm sign bit */
162         int delta;          /* Current adpcm output value */
163         int step;           /* Stepsize */
164         int valpred;        /* Predicted value */
165         int vpdiff;         /* Current change to valpred */
166         int index;          /* Current step change index */
167         int inputbuffer;        /* place to keep next 4-bit value */
168         int bufferstep;     /* toggle between inputbuffer/input */
169
170         outp = outdata;
171         inp = (signed char *)indata;
172
173         valpred = state->valprev;
174         index = state->index;
175         step = stepsizeTable[index];
176
177         bufferstep = 0;
178
179         for (; len > 0; len-- )
180         {
181                 /* Step 1 - get the delta value */
182                 if ( bufferstep ) {
183                         delta = inputbuffer & 0xf;
184                 }
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                 }
197                 if ( index > 88 ) {
198                         index = 88;
199                 }
200
201                 /* Step 3 - Separate sign and magnitude */
202                 sign = delta & 8;
203                 delta = delta & 7;
204
205                 /* Step 4 - Compute difference and new predicted value */
206                 /*
207                 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
208                 ** in adpcm_coder.
209                 */
210                 vpdiff = step >> 3;
211                 if ( delta & 4 ) {
212                         vpdiff += step;
213                 }
214                 if ( delta & 2 ) {
215                         vpdiff += step >> 1;
216                 }
217                 if ( delta & 1 ) {
218                         vpdiff += step >> 2;
219                 }
220
221                 if ( sign ) {
222                         valpred -= vpdiff;
223                 }
224                 else{
225                         valpred += vpdiff;
226                 }
227
228                 /* Step 5 - clamp output value */
229                 if ( valpred > 32767 ) {
230                         valpred = 32767;
231                 }
232                 else if ( valpred < -32768 ) {
233                         valpred = -32768;
234                 }
235
236                 /* Step 6 - Update step value */
237                 step = stepsizeTable[index];
238
239                 /* Step 7 - Output value */
240                 *outp++ = valpred;
241         }
242
243         state->valprev = valpred;
244         state->index = index;
245 }
246 #endif
247
248 void adpcm_coder( short *inp, adpcm_t *adpcm ){
249         int val;                        /* Current input sample value */
250         int sign;                       /* Current adpcm sign bit */
251         int delta;                      /* Current adpcm output value */
252         int diff;                       /* Difference between val and valprev */
253         int step;                       /* Stepsize */
254         int valpred;                    /* Predicted output value */
255         int vpdiff;                     /* Current change to valpred */
256         int index;                      /* Current step change index */
257         int outputbuffer;               /* place to keep previous 4-bit value */
258         int bufferstep;                 /* toggle between outputbuffer/output */
259         adpcm_state_t   *state;
260         char            *outp;
261         int len;
262
263         state = &adpcm->state;
264         len = state->count;
265         outp = adpcm->adpcm;
266
267         valpred = state->in_valprev;
268         index = state->in_index;
269         step = stepsizeTable[index];
270
271         bufferstep = 1;
272         while ( len-- )
273         {
274                 val = *inp++;
275
276                 /* Step 1 - compute difference with previous value */
277                 diff = val - valpred;
278                 sign = ( diff < 0 ) ? 8 : 0;
279                 if ( sign ) {
280                         diff = -diff;
281                 }
282
283                 /* Step 2 - Divide and clamp */
284                 /* Note:
285                 ** This code *approximately* computes:
286                 **        delta = diff*4/step;
287                 **        vpdiff = (delta+0.5)*step/4;
288                 ** but in shift step bits are dropped. The net result of this is
289                 ** that even if you have fast mul/div hardware you cannot put it to
290                 ** good use since the fixup would be too expensive.
291                 */
292                 delta = 0;
293                 vpdiff = ( step >> 3 );
294
295                 if ( diff >= step ) {
296                         delta = 4;
297                         diff -= step;
298                         vpdiff += step;
299                 }
300                 step >>= 1;
301                 if ( diff >= step ) {
302                         delta |= 2;
303                         diff -= step;
304                         vpdiff += step;
305                 }
306                 step >>= 1;
307                 if ( diff >= step ) {
308                         delta |= 1;
309                         vpdiff += step;
310                 }
311
312                 /* Step 3 - Update previous value */
313                 if ( sign ) {
314                         valpred -= vpdiff;
315                 }
316                 else{
317                         valpred += vpdiff;
318                 }
319
320                 /* Step 4 - Clamp previous value to 16 bits */
321                 if ( valpred > 32767 ) {
322                         valpred = 32767;
323                 }
324                 else if ( valpred < -32768 ) {
325                         valpred = -32768;
326                 }
327
328                 /* Step 5 - Assemble value, update index and step values */
329                 delta |= sign;
330
331                 index += indexTable[delta];
332                 if ( index < 0 ) {
333                         index = 0;
334                 }
335                 if ( index > 88 ) {
336                         index = 88;
337                 }
338                 step = stepsizeTable[index];
339
340                 /* Step 6 - Output value */
341                 if ( bufferstep ) {
342                         outputbuffer = ( delta << 4 ) & 0xf0;
343                 }
344                 else{
345                         *outp++ = ( delta & 0x0f ) | outputbuffer;
346                 }
347
348                 bufferstep = !bufferstep;
349         }
350
351         /* Output last step, if needed */
352         if ( !bufferstep ) {
353                 *outp++ = outputbuffer;
354         }
355
356         state->out_valprev = valpred;
357         state->out_index = index;
358 }
359
360 void FindNextChunk( char *name ){
361         while ( 1 )
362         {
363                 data_p = last_chunk;
364
365                 if ( data_p >= iff_end ) {         // didn't find the chunk
366                         data_p = NULL;
367                         return;
368                 }
369
370                 data_p += 4;
371                 iff_chunk_len = *(long *)data_p;
372                 data_p += 4;
373                 if ( iff_chunk_len < 0 ) {
374                         data_p = NULL;
375                         return;
376                 }
377
378                 data_p -= 8;
379                 last_chunk = data_p + 8 + ( ( iff_chunk_len + 1 ) & ~1 );
380                 if ( !strncmp( data_p, name, 4 ) ) {
381                         return;
382                 }
383         }
384 }
385
386 void FindChunk( char *name ){
387         last_chunk = iff_data;
388         FindNextChunk( name );
389 }
390
391 void DumpChunks( void ){
392         char str[5];
393
394         str[4] = 0;
395         data_p = iff_data;
396         do
397         {
398                 memcpy( str, data_p, 4 );
399                 data_p += 4;
400                 iff_chunk_len = *(long *)data_p;
401                 data_p += 4;
402                 printf( "0x%x : %s (%d)\n", (int)( data_p - 4 ), str, iff_chunk_len );
403                 data_p += ( iff_chunk_len + 1 ) & ~1;
404         }
405         while ( data_p < iff_end );
406 }
407
408 /*
409    ============
410    GetWavinfo
411    ============
412  */
413 wavinfo_t GetWavinfo( char *name, byte *wav, int wavlength ){
414         wavinfo_t info;
415         int i;
416         int format;
417         int samples;
418
419         memset( &info, 0, sizeof( info ) );
420
421         if ( !wav ) {
422                 return( info );
423         }
424
425         iff_data = wav;
426         iff_end = wav + wavlength;
427
428 // find "RIFF" chunk
429         FindChunk( "RIFF" );
430         if ( !( data_p && !strncmp( data_p + 8, "WAVE", 4 ) ) ) {
431                 printf( "Missing RIFF/WAVE chunks\n" );
432                 return( info );
433         }
434
435 // get "fmt " chunk
436         iff_data = data_p + 12;
437
438         FindChunk( "fmt " );
439         if ( !data_p ) {
440                 printf( "Missing fmt chunk\n" );
441                 return( info );
442         }
443         data_p += 8;
444         format = *(short *)data_p;
445         data_p += 2;
446         if ( format != 1 ) {
447                 printf( "Microsoft PCM format only\n" );
448                 return( info );
449         }
450
451         info.channels = *(short *)data_p;
452         data_p += 2;
453         info.rate = *(long *)data_p;
454         data_p += 4;
455         data_p += 6;
456         info.width = *(short *)data_p / 8;
457         data_p += 2;
458
459 // get cue chunk
460         FindChunk( "cue " );
461         if ( data_p ) {
462                 data_p += 32;
463                 info.loopstart = *(long *)data_p;
464                 data_p += 4;
465
466 // if the next chunk is a LIST chunk, look for a cue length marker
467                 FindNextChunk( "LIST" );
468                 if ( data_p ) {
469 // this is not a proper parse, but it works with cooledit...
470                         if ( !strncmp( data_p + 28, "mark", 4 ) ) {
471                                 data_p += 24;
472                                 i = *(long *)data_p;                    // samples in loop
473                                 data_p += 4;
474                                 info.samples = info.loopstart + i;
475                         }
476                 }
477         }
478         else{
479                 info.loopstart = -1;
480         }
481
482 // find data chunk
483         FindChunk( "data" );
484         if ( !data_p ) {
485                 printf( "Missing data chunk\n" );
486                 return( info );
487         }
488
489         data_p += 4;
490         samples = *(long *)data_p;
491         data_p += 4;
492
493         if ( info.samples ) {
494                 if ( samples < info.samples ) {
495                         Error( "Sound %s has a bad loop length", name );
496                 }
497         }
498         else{
499                 info.samples = samples;
500         }
501
502         info.dataofs = data_p - wav;
503         return( info );
504 }
505
506 // ==============
507 // LoadSoundtrack
508 // ==============
509
510 void LoadSoundtrack(){
511         char name[1024];
512         FILE    *f;
513         int len;
514
515         soundtrack = NULL;
516         sprintf( name, "%svideo/%s/%s.wav", gamedir, base, base );
517         printf( "\nLoading sound    : %s\n", name );
518         f = fopen( name, "rb" );
519         if ( !f ) {
520                 printf( "\nNo soundtrack for %s\n", base );
521                 return;
522         }
523         len = Q_filelength( f );
524         soundtrack = SafeMalloc( len, "LoadSoundtrack" );
525         fread( soundtrack, 1, len, f );
526         fclose( f );
527
528         wavinfo = GetWavinfo( name, soundtrack, len );
529         adpcm.state.out_valprev = 0;
530         adpcm.state.out_index = 0;
531 }
532
533 // ==================
534 // WriteSound
535 // ==================
536
537 int WriteSound( FILE *output, int frame, int numframes ){
538         int start, end;
539         int count;
540         int empty = 0;
541         int width;
542         char    *work;
543
544         width = wavinfo.width * wavinfo.channels;
545         start = ( ( frame * wavinfo.rate / 14 ) + 31 ) & 0xffffffe0;                // start sample
546         end = ( ( ( frame + numframes ) * wavinfo.rate / 14 ) + 31 ) & 0xffffffe0;    // end sample
547         count = end - start;
548
549         work = soundtrack + wavinfo.dataofs + ( start * width );
550         adpcm.state.count = count * wavinfo.channels;           // Number of samples
551         adpcm.state.in_valprev = adpcm.state.out_valprev;
552         adpcm.state.in_index = adpcm.state.out_index;
553         adpcm_coder( (short *)work, &adpcm );
554         WriteHeader( output, FC_SOUND_22KMADPCM, FC_ADPCM_VERSION, ( adpcm.state.count / 2 ) + sizeof( adpcm_state_t ), (char *)&adpcm );
555         return( count / 2 );
556 }
557 // ==============================
558 // Basic run length encoder
559 // ==============================
560
561 char *RLEZZ( char *in, char *out ){
562         int srun;
563         char count;
564         int idx = 0;
565
566         while ( idx < 64 )
567         {
568                 srun = idx;                             // Start of run
569
570                 while ( idx < 63 )
571                 {
572                         if ( in[LUT_ZZ[idx]] != in[LUT_ZZ[idx + 1]] ) {
573                                 break;
574                         }
575                         idx++;
576                 }
577                 count = (char)( idx - srun );             // count of repeated bytes
578
579                 if ( !count ) {
580                         while ( idx < 63 )
581                         {
582                                 if ( in[LUT_ZZ[idx]] == in[LUT_ZZ[idx + 1]] ) {
583                                         break;
584                                 }
585                                 idx++;
586                         }
587                         if ( idx == 63 ) {
588                                 idx++;
589                         }
590
591                         count = (char)( idx - srun );         // count of unique bytes
592                         *out++ = count;
593                         while ( count-- )
594                                 *out++ = in[LUT_ZZ[srun++]];
595                 }
596                 else
597                 {
598                         *out++ = -( count + 1 );
599                         *out++ = in[LUT_ZZ[idx]];
600                         idx++;
601                 }
602         }
603         return( out );
604 }
605
606 // ==============================
607 // Discrete Cosine Transformation
608 // ==============================
609
610 void init_base( float quant ){
611         int y, x;
612
613         for ( y = 0; y < BLOCKSIZE; y++ )
614                 for ( x = 0; x < BLOCKSIZE; x++ )
615                 {
616                         if ( y == 0 ) {
617                                 dctbase[y][x] = 1;
618                         }
619                         else{
620                                 dctbase[y][x] = SQRT2 * cos( ( ( x * 2 + 1 ) * y * M_PI ) / ( BLOCKSIZE * 2 ) );
621                         }
622                 }
623
624         for ( y = 0; y < BLOCKSIZE * BLOCKSIZE; y++ )
625                 Quantise[y] = LUT_Quantise[y] / quant;
626 }
627
628 void SplitComponents( byte *src, int width, int height ){
629         int i, j;
630         float   *tr = red;
631         float   *tg = green;
632         float   *tb = blue;
633
634         for ( i = 0; i < BLOCKSIZE; i++, src += ( width - BLOCKSIZE ) * 4 )
635                 for ( j = 0; j < BLOCKSIZE; j++ )
636                 {
637                         *tr++ = ( (float)*src++ ) - 128.0F;
638                         *tg++ = ( (float)*src++ ) - 128.0F;
639                         *tb++ = ( (float)*src++ ) - 128.0F;
640                         src++;
641                 }
642 }
643
644 void transferH( float *src, float *dst ){
645         int y, dx, dy;
646         float sum;
647         float   *work;
648
649         for ( y = 0; y < BLOCKSIZE; y++, src += BLOCKSIZE )
650         {
651                 for ( dy = 0; dy < BLOCKSIZE; dy++ )
652                 {
653                         sum = 0;
654                         work = src;
655                         for ( dx = 0; dx < BLOCKSIZE; dx++, work++ )
656                                 sum += dctbase[dy][dx] * *work;
657
658                         *dst++ = sum / BLOCKSIZE;
659                 }
660         }
661 }
662
663 void transferV( float *src, float *dst ){
664         int x, dy, fy;
665         float sum;
666         float   *work;
667
668         for ( x = 0; x < BLOCKSIZE; x++, src++, dst++ )
669         {
670                 for ( fy = 0; fy < BLOCKSIZE; fy++ )
671                 {
672                         sum = 0;
673                         work = src;
674                         for ( dy = 0; dy < BLOCKSIZE; dy++, work += BLOCKSIZE )
675                                 sum += dctbase[fy][dy] * *work;
676
677                         dst[fy * BLOCKSIZE] = sum / BLOCKSIZE;
678                 }
679         }
680 }
681
682 char *Combine( byte *dst, float *p, float *q ){
683         int i, j;
684         byte rlesrc[BLOCKSIZE * BLOCKSIZE];
685         int c;
686         byte    *work;
687
688         work = rlesrc;
689         for ( j = 0; j < BLOCKSIZE; j++ )
690                 for ( i = 0; i < BLOCKSIZE; i++ )
691                 {
692                         c = (int)( ( *p++ / *q++ ) + 128.5F );
693                         c -= 128;
694
695                         if ( c < -128 ) {
696                                 c = -128;
697                         }
698                         if ( c > 127 ) {
699                                 c = 127;
700                         }
701
702                         *work++ = (char)c;
703                 }
704
705         dst = RLEZZ( rlesrc, dst );
706         return( dst );
707 }
708
709 char *CombineComponents( char *dst, int width, int height ){
710         dst = Combine( dst, red, Quantise );
711         dst = Combine( dst, green, Quantise );
712         dst = Combine( dst, blue, Quantise );
713         return( dst );
714 }
715
716 void DCT( cblock_t *out, cblock_t in, int width, int height ){
717         int x, y;
718         char    *cursrc;
719         char    *curdst;
720
721         curdst = out->data;
722         for ( y = 0; y < height; y += BLOCKSIZE )
723                 for ( x = 0; x < width; x += BLOCKSIZE )
724                 {
725                         cursrc = in.data + ( ( y * width ) + x ) * 4;
726                         SplitComponents( cursrc, width, height );
727                         transferH( red, temp );
728                         transferV( temp, red );
729                         transferH( green, temp );
730                         transferV( temp, green );
731                         transferH( blue, temp );
732                         transferV( temp, blue );
733                         curdst = CombineComponents( curdst, width, height );
734                 }
735         out->count = curdst - out->data;
736 }
737
738 // ==================
739 // BuildChars1
740 // ==================
741
742 void BuildChars1( int prev, int nodenum, unsigned bits, int bitcount ){
743         hnode_t     *node;
744
745         if ( nodenum < HUF_TOKENS ) {
746                 if ( bitcount > 32 ) {
747                         Error( "bitcount > 32" );
748                 }
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         int i;
767         int best, bestnode;
768
769         best = 99999999;
770         bestnode = -1;
771         for ( i = 0; i < numhnodes; i++ )
772         {
773                 if ( hnodes[i].used ) {
774                         continue;
775                 }
776                 if ( !hnodes[i].count ) {
777                         continue;
778                 }
779                 if ( hnodes[i].count < best ) {
780                         best = hnodes[i].count;
781                         bestnode = i;
782                 }
783         }
784
785         if ( bestnode == -1 ) {
786                 return( -1 );
787         }
788
789         hnodes[bestnode].used = true;
790         return( bestnode );
791 }
792
793 // ==================
794 // BuildTree1
795 // ==================
796
797 void BuildTree1( int prev ){
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                 }
814                 node->children[1] = SmallestNode1( nodebase, numhnodes );
815                 if ( node->children[1] == -1 ) {
816                         break;
817                 }
818
819                 node->count = nodebase[node->children[0]].count +
820                                           nodebase[node->children[1]].count;
821                 numhnodes++;
822         }
823         numhnodes1[prev] = numhnodes - 1;
824         BuildChars1( prev, numhnodes - 1, 0, 0 );
825 }
826
827 // ==================
828 // Huffman1_Count
829 // ==================
830
831 void Huffman1_Count( cblock_t in ){
832         int i;
833         int prev;
834         int v;
835         int rept;
836
837         prev = 0;
838         for ( i = 0; i < in.count; i++ )
839         {
840                 v = in.data[i];
841                 order0counts[v]++;
842                 hnodes1[prev][v].count++;
843                 prev = v;
844
845                 for ( rept = 1; ( i + rept < in.count ) && ( rept < MAX_REPT ); rept++ )
846                         if ( in.data[i + rept] != v ) {
847                                 break;
848                         }
849                 if ( rept > MIN_REPT ) {
850                         hnodes1[prev][255 + rept].count++;
851                         i += rept - 1;
852                 }
853         }
854 }
855
856 // ==================
857 // Huffman1_Build
858 // ==================
859
860 void Huffman1_Build(){
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                 }
875                 if ( max == 0 ) {
876                         max = 1;
877                 }
878                 total = 0;
879 // easy to overflow 32 bits here!
880                 for ( j = 0; j < HUF_TOKENS; j++ )
881                 {
882                         v = ( hnodes1[i][j].count * (double) 255 + max - 1 ) / max;
883                         if ( v > 255 ) {
884                                 Error( "v > 255" );
885                         }
886                         scaled[i][j] = hnodes1[i][j].count = v;
887                         if ( v ) {
888                                 total++;
889                         }
890                 }
891                 if ( total == 1 ) { // must have two tokens
892                         if ( !scaled[i][0] ) {
893                                 scaled[i][0] = hnodes1[i][0].count = 1;
894                         }
895                         else{
896                                 scaled[i][1] = hnodes1[i][1].count = 1;
897                         }
898                 }
899                 BuildTree1( i );
900         }
901 }
902
903 // ==================
904 // Huffman1
905 // Order 1 compression with pre-built table
906 // ==================
907
908 cblock_t Huffman1( cblock_t in ){
909         int i;
910         int outbits, c;
911         unsigned bits;
912         byte        *out_p;
913         cblock_t out;
914         int prev;
915         int v;
916         int rept;
917
918         out_p = out.data = SafeMalloc( ( in.count * 2 ) + 1024 + 4, "Huffman" );
919         memset( out_p, 0, ( in.count * 2 ) + 1024 + 4 );
920
921         // leave space for compressed count
922         out_p += 4;
923         // write count
924         *(long *)out_p = in.count;
925         out_p += 4;
926
927         // write bits
928         outbits = 0;
929         prev = 0;
930         for ( i = 0; i < in.count; i++ )
931         {
932                 v = in.data[i];
933
934                 c = charbitscount1[prev][v];
935                 bits = charbits1[prev][v];
936                 if ( !c ) {
937                         Error( "!bits" );
938                 }
939                 while ( c )
940                 {
941                         c--;
942                         if ( bits & ( 1 << c ) ) {
943                                 out_p[outbits >> 3] |= 1 << ( outbits & 7 );
944                         }
945                         outbits++;
946                 }
947
948                 prev = v;
949                 // check for repeat encodes
950                 for ( rept = 1; ( i + rept < in.count ) && ( rept < MAX_REPT ); rept++ )
951                         if ( in.data[i + rept] != v ) {
952                                 break;
953                         }
954                 if ( rept > MIN_REPT ) {
955                         c = charbitscount1[prev][255 + rept];
956                         bits = charbits1[prev][255 + rept];
957                         if ( !c ) {
958                                 Error( "!bits" );
959                         }
960                         while ( c )
961                         {
962                                 c--;
963                                 if ( bits & ( 1 << c ) ) {
964                                         out_p[outbits >> 3] |= 1 << ( outbits & 7 );
965                                 }
966                                 outbits++;
967                         }
968                         i += rept - 1;
969                 }
970         }
971         out_p += ( outbits + 7 ) >> 3;
972         out.count = out_p - out.data;
973
974         out_p = out.data;
975         *(long *)out_p = out.count;
976         return( out );
977 }
978 // ===================
979 // LoadFrame
980 // ===================
981
982 void LoadFrame( cblock_t *out, char *base, int frame ){
983         cblock_t in;
984         int width, height;
985         char name[1024];
986         FILE        *f;
987
988         in.data = NULL;
989         in.count = -1;
990         sprintf( name, "%svideo/%s/%s%04i.tga", gamedir, base, base, frame );
991
992         f = fopen( name, "rb" );
993         if ( !f ) {
994                 out->data = NULL;
995                 return;
996         }
997         fclose( f );
998
999         LoadTGA( name, &in.data, &width, &height );
1000         if ( ( width != cinehead.Width ) || ( height != cinehead.Height ) ) {
1001                 free( in.data );
1002                 printf( "Invalid picture size\n" );
1003                 out->data = NULL;
1004                 return;
1005         }
1006         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)
1007         DCT( out, in, width, height );
1008         free( in.data );
1009 }
1010
1011 // ==================================
1012 // Cmd_Video
1013 //
1014 // video <directory> <framedigits>
1015 // ==================================
1016
1017 void Cmd_Video(){
1018         char savename[256];
1019         char name[256];
1020         FILE        *output;
1021         int frame;
1022         int width, height;
1023         cblock_t in, huffman;
1024         int size;
1025         float dctconst;
1026         int maxsize, ssize;
1027         int min_rle_size, warnings;
1028         int ave_image, ave_sound;
1029
1030         GetScriptToken( false );
1031         strcpy( base, token );
1032         if ( g_release ) {
1033                 return;
1034         }
1035
1036         GetScriptToken( false );
1037         dctconst = atof( token );
1038         GetScriptToken( false );
1039         maxsize = atoi( token );
1040
1041         sprintf( savename, "%svideo/%s.cin", gamedir, base );
1042
1043         // clear stuff
1044         memset( charbits1, 0, sizeof( charbits1 ) );
1045         memset( charbitscount1, 0, sizeof( charbitscount1 ) );
1046         memset( hnodes1, 0, sizeof( hnodes1 ) );
1047         memset( numhnodes1, 0, sizeof( numhnodes1 ) );
1048         memset( order0counts, 0, sizeof( order0counts ) );
1049
1050         // load the entire sound wav file if present
1051         LoadSoundtrack();
1052
1053         cinehead.SndRate = wavinfo.rate;
1054         cinehead.SndWidth = wavinfo.width;
1055         cinehead.SndChannels = wavinfo.channels;
1056
1057         sprintf( name, "%svideo/%s/%s0000.tga", gamedir, base, base );
1058         printf( "Loading sequence : %s\n", name );
1059         printf( "DCT constant     : %f\n", dctconst );
1060
1061         LoadTGA( name, NULL, &width, &height );
1062
1063         output = fopen( savename, "wb" );
1064         if ( !output ) {
1065                 Error( "Can't open %s", savename );
1066         }
1067
1068         if ( ( width % BLOCKSIZE ) || ( height % BLOCKSIZE ) ) {
1069                 Error( "Width and height must be a multiple of %d", BLOCKSIZE );
1070         }
1071
1072         cinehead.Width = width;
1073         cinehead.Height = height;
1074         init_base( dctconst );
1075
1076         // build the dictionary
1077         printf( "Counting         : " );
1078         min_rle_size = 0;
1079         for ( frame = 0;  ; frame++ )
1080         {
1081                 printf( "." );
1082                 LoadFrame( &in, base, frame );
1083                 if ( !in.data ) {
1084                         break;
1085                 }
1086                 Huffman1_Count( in );
1087                 if ( in.count > min_rle_size ) {
1088                         min_rle_size = in.count;
1089                 }
1090                 free( in.data );
1091         }
1092         printf( "\n" );
1093         cinehead.NumFrames = frame;
1094         printf( "Num Frames       : %d\n", frame );
1095         cinehead.MaxRleSize = ( min_rle_size + 0x1f ) & 0xfffffe0;
1096         cinehead.MaxSndSize = ( ( 4 * wavinfo.rate * wavinfo.channels / 14 ) + 0x1f ) & 0xffffffe0;
1097
1098         WriteHeader( output, FC_HEADER_NAME, FC_HEADER_VERSION, sizeof( CineHead_t ), &cinehead );
1099
1100         // build nodes and write counts
1101         Huffman1_Build();
1102         WriteHeader( output, FC_HUFFBITS_NAME, FC_HUFFBITS_VERSION, sizeof( scaled ), scaled );
1103         WriteHeader( output, FC_QUANT_NAME, FC_QUANT_VERSION, sizeof( Quantise ), Quantise );
1104
1105         ave_image = 0;
1106         ave_sound = 0;
1107         warnings = 0;
1108         // compress it with the dictionary
1109         if ( soundtrack ) {
1110                 ssize = WriteSound( output, frame, 4 );
1111                 ave_sound += ssize;
1112         }
1113
1114         for ( frame = 0; frame < cinehead.NumFrames; frame++ )
1115         {
1116                 // save some sound samples
1117                 printf( "Packing          : ", frame );
1118                 LoadFrame( &in, base, frame );
1119
1120                 // save the image
1121                 huffman = Huffman1( in );
1122                 printf( "%d bytes rle, %d bytes huffman", in.count, huffman.count );
1123                 size = ( huffman.count + 3 ) & 0xfffffffc;                    // round up to longwords
1124                 if ( size > maxsize ) {
1125                         printf( " ** WARNING **" );
1126                         warnings++;
1127                 }
1128                 printf( "\n" );
1129                 ave_image += huffman.count;
1130
1131                 WriteHeader( output, FC_IMAGE_NAME, FC_IMAGE_VERSION, size, huffman.data );
1132                 if ( soundtrack ) {
1133                         ssize = WriteSound( output, frame + 4, 1 );
1134                         ave_sound += ssize;
1135                 }
1136
1137                 free( in.data );
1138                 free( huffman.data );
1139         }
1140         printf( "\nTotal size: %d (headers + %d image + %d sound)\n", ftell( output ), ave_image, ave_sound );
1141         printf( "Data rate : %d bytes per sec (image and sound)\n", ( ave_image + ave_sound ) / cinehead.NumFrames );
1142         printf( "Cin created ok with %d warnings.\n", warnings );
1143         fclose( output );
1144
1145         if ( soundtrack ) {
1146                 free( soundtrack );
1147         }
1148 }
1149 #endif
1150
1151 void Cmd_Video(){
1152 }
1153
1154 // end