]> icculus.org git repositories - taylor/freespace2.git/blob - src/movie/decoder16.cpp
const-char warning fixes
[taylor/freespace2.git] / src / movie / decoder16.cpp
1 /*
2  * $Logfile: /Freespace2/src/movie/decoder16.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * 16-bit frame decoder for MVEs
8  *
9  * $Log$
10  * Revision 1.3  2005/10/01 21:48:01  taylor
11  * various cleanups
12  * fix decoder to swap opcode 0xb since it screws up on PPC
13  * the previous opcode 0xc change was wrong since we had already determined that it messes up FS1 movies
14  *
15  * Revision 1.2  2005/03/29 07:50:34  taylor
16  * Update to newest movie code with much better video support and audio support from
17  *   Pierre Willenbrock.  Movies are enabled always now (no longer a build option)
18  *   and but can be skipped with the "--nomovies" or "-n" cmdline options.
19  *
20  *
21  *
22  * $NoKeywords: $
23  *
24  */
25
26 #include "pstypes.h"
27
28 extern int g_width, g_height;
29 extern void *g_vBackBuf1, *g_vBackBuf2;
30
31 /* 16 bit decoding routines */
32
33 static ushort *backBuf1, *backBuf2;
34 static int lookup_initialized;
35
36 static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb);
37 static void genLoopkupTable();
38
39 void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
40 {
41         unsigned char *pOrig;
42         unsigned char *pOffData, *pEnd;
43         ushort offset;
44         int length;
45         int op;
46         int i, j;
47         int xb, yb;
48
49         if (!lookup_initialized) {
50                 genLoopkupTable();
51         }
52
53         backBuf1 = (ushort *)g_vBackBuf1;
54         backBuf2 = (ushort *)g_vBackBuf2;
55
56         xb = g_width >> 3;
57         yb = g_height >> 3;
58
59         offset = pData[0]|(pData[1]<<8);
60
61         pOffData = pData + offset;
62         pEnd = pData + offset;
63
64         pData += 2;
65
66         pOrig = pData;
67         length = offset - 2; /*dataRemain-2;*/
68
69         for (j=0; j<yb; j++) {
70                 for (i=0; i<xb/2; i++) {
71                         op = (*pMap) & 0xf;
72                         dispatchDecoder16((ushort **)&pFrame, op, &pData, &pOffData, &dataRemain, &i, &j);
73
74 /*
75                         if ((ushort *)pFrame < backBuf1)
76                                 fprintf(stderr, "danger!  pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
77                         else if ((ushort *)pFrame >= backBuf1 + g_width*g_height)
78                                 fprintf(stderr, "danger!  pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf);
79 */
80
81                         op = ((*pMap) >> 4) & 0xf;
82                         dispatchDecoder16((ushort **)&pFrame, op, &pData, &pOffData, &dataRemain, &i, &j);
83
84 /*
85                         if ((ushort *)pFrame < backBuf1)
86                                 fprintf(stderr, "danger!  pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
87                         else if ((ushort *)pFrame >= backBuf1 + g_width*g_height)
88                                 fprintf(stderr, "danger!  pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4);
89 */
90
91                         pMap++;
92                         mapRemain--;
93                 }
94
95                 pFrame += 7*g_width*2;
96         }
97
98         if ((length-(pData-pOrig)) != 0) {
99                 nprintf(("MVE", "DEBUG: junk left over: %d,%d,%d\n", (pData-pOrig), length, (length-(pData-pOrig))));
100         }
101 }
102
103 static ushort GETPIXEL(unsigned char **buf, int off)
104 {
105         ushort val = (*buf)[0+off] | ((*buf)[1+off] << 8);
106         return val;
107 }
108
109 static ushort GETPIXELI(unsigned char **buf, int off)
110 {
111         ushort val = (*buf)[0+off] | ((*buf)[1+off] << 8);
112         (*buf) += 2;
113         return val;
114 }
115
116 static void relClose(int i, int *x, int *y)
117 {
118         int ma, mi;
119
120         ma = i >> 4;
121         mi = i & 0xf;
122
123         *x = mi - 8;
124         *y = ma - 8;
125 }
126
127 static void relFar(int i, int sign, int *x, int *y)
128 {
129         if (i < 56) {
130                 *x = sign * (8 + (i % 7));
131                 *y = sign *       (i / 7);
132         } else {
133                 *x = sign * (-14 + (i - 56) % 29);
134                 *y = sign *   (8 + (i - 56) / 29);
135         }
136 }
137
138 static int close_table[512];
139 static int far_p_table[512];
140 static int far_n_table[512];
141
142 static void genLoopkupTable()
143 {
144         int i;
145         int x, y;
146
147         for (i = 0; i < 256; i++) {
148                 relClose(i, &x, &y);
149
150                 close_table[i*2+0] = x;
151                 close_table[i*2+1] = y;
152
153                 relFar(i, 1, &x, &y);
154
155                 far_p_table[i*2+0] = x;
156                 far_p_table[i*2+1] = y;
157
158                 relFar(i, -1, &x, &y);
159
160                 far_n_table[i*2+0] = x;
161                 far_n_table[i*2+1] = y;
162         }
163
164         lookup_initialized = 1;
165 }
166
167 static void copyFrame(ushort *pDest, ushort *pSrc)
168 {
169         int i;
170
171         for (i=0; i<8; i++) {
172                 memcpy(pDest, pSrc, 16);
173                 pDest += g_width;
174                 pSrc += g_width;
175         }
176 }
177
178 static void patternRow4Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, ushort *p)
179 {
180         ushort mask=0x0003;
181         ushort shift=0;
182         ushort pattern = (pat1 << 8) | pat0;
183
184         while (mask != 0) {
185                 *pFrame++ = p[(mask & pattern) >> shift];
186                 mask <<= 2;
187                 shift += 2;
188         }
189 }
190
191 static void patternRow4Pixels2(ushort *pFrame, unsigned char pat0, ushort *p)
192 {
193         unsigned char mask=0x03;
194         unsigned char shift=0;
195         ushort pel;
196 /* ORIGINAL VERSION IS BUGGY
197         int skip=1;
198
199         while (mask != 0) {
200                 pel = p[(mask & pat0) >> shift];
201                 pFrame[0] = pel;
202                 pFrame[2] = pel;
203                 pFrame[g_width + 0] = pel;
204                 pFrame[g_width + 2] = pel;
205                 pFrame += skip;
206                 skip = 4 - skip;
207                 mask <<= 2;
208                 shift += 2;
209         }
210 */
211         while (mask != 0) {
212                 pel = p[(mask & pat0) >> shift];
213                 pFrame[0] = pel;
214                 pFrame[1] = pel;
215                 pFrame[g_width + 0] = pel;
216                 pFrame[g_width + 1] = pel;
217                 pFrame += 2;
218                 mask <<= 2;
219                 shift += 2;
220         }
221 }
222
223 static void patternRow4Pixels2x1(ushort *pFrame, unsigned char pat, ushort *p)
224 {
225         unsigned char mask=0x03;
226         unsigned char shift=0;
227         ushort pel;
228
229         while (mask != 0) {
230                 pel = p[(mask & pat) >> shift];
231                 pFrame[0] = pel;
232                 pFrame[1] = pel;
233                 pFrame += 2;
234                 mask <<= 2;
235                 shift += 2;
236         }
237 }
238
239 static void patternQuadrant4Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, ushort *p)
240 {
241         unsigned long mask = 0x00000003UL;
242         int shift=0;
243         int i;
244         unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
245
246         for (i=0; i<16; i++) {
247                 pFrame[i&3] = p[(pat & mask) >> shift];
248
249                 if ((i&3) == 3)
250                         pFrame += g_width;
251
252                 mask <<= 2;
253                 shift += 2;
254         }
255 }
256
257 static void patternRow2Pixels(ushort *pFrame, unsigned char pat, ushort *p)
258 {
259         unsigned char mask=0x01;
260
261         while (mask != 0) {
262                 *pFrame++ = p[(mask & pat) ? 1 : 0];
263                 mask <<= 1;
264         }
265 }
266
267 static void patternRow2Pixels2(ushort *pFrame, unsigned char pat, ushort *p)
268 {
269         ushort pel;
270         unsigned char mask=0x1;
271
272 /* ORIGINAL VERSION IS BUGGY
273         int skip=1;
274         while (mask != 0x10) {
275                 pel = p[(mask & pat) ? 1 : 0];
276                 pFrame[0] = pel;
277                 pFrame[2] = pel;
278                 pFrame[g_width + 0] = pel;
279                 pFrame[g_width + 2] = pel;
280                 pFrame += skip;
281                 skip = 4 - skip;
282                 mask <<= 1;
283         }
284 */
285         while (mask != 0x10) {
286                 pel = p[(mask & pat) ? 1 : 0];
287
288                 pFrame[0] = pel;
289                 pFrame[1] = pel;
290                 pFrame[g_width + 0] = pel;
291                 pFrame[g_width + 1] = pel;
292                 pFrame += 2;
293
294                 mask <<= 1;
295         }
296 }
297
298 static void patternQuadrant2Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, ushort *p)
299 {
300         ushort mask = 0x0001;
301         int i;
302         ushort pat = (pat1 << 8) | pat0;
303
304         for (i=0; i<16; i++) {
305                 pFrame[i&3] = p[(pat & mask) ? 1 : 0];
306
307                 if ((i&3) == 3)
308                         pFrame += g_width;
309
310                 mask <<= 1;
311         }
312
313 }
314
315 static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb)
316 {
317         ushort p[4];
318         unsigned char pat[16];
319         int i, j, k;
320         int x, y;
321         ushort *pDstBak;
322         ubyte frame_tmp[16];                            
323         ushort *swap_tmp;
324
325         pDstBak = *pFrame;
326
327         switch(codeType) {
328                 case 0x0:
329                         copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1));
330                         break; // ADDED
331
332                 case 0x1:
333                         break;
334
335                 case 0x2:
336                         /* relFar(*(*pOffData)++, 1, &x, &y); */
337
338                         k = *(*pOffData)++;
339                         x = far_p_table[k*2+0];
340                         y = far_p_table[k*2+1];
341
342                         copyFrame(*pFrame, *pFrame + x + y*g_width);
343                         *pDataRemain--;
344                         break;
345
346                 case 0x3:
347                         /* relFar(*(*pOffData)++, -1, &x, &y); */
348
349                         k = *(*pOffData)++;
350                         x = far_n_table[k*2+0];
351                         y = far_n_table[k*2+1];
352
353                         copyFrame(*pFrame, *pFrame + x + y*g_width);
354                         *pDataRemain--;                           
355                         break;
356
357                 case 0x4:
358                         /* relClose(*(*pOffData)++, &x, &y); */
359
360                         k = *(*pOffData)++;
361                         x = close_table[k*2+0];
362                         y = close_table[k*2+1];
363
364                         copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
365                         *pDataRemain--;
366                         break;
367
368                 case 0x5:
369                         x = (char)*(*pData)++;
370                         y = (char)*(*pData)++;
371                         copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
372                         *pDataRemain -= 2;
373                         break;
374
375                 case 0x6:
376                         nprintf(("MVE", "STUB: encoding 6 not tested\n"));
377
378                         for (i=0; i<2; i++) {
379                                 *pFrame += 16;
380
381                                 if (++*curXb == (g_width >> 3)) {
382                                         *pFrame += 7*g_width;
383                                         *curXb = 0;
384
385                                         if (++*curYb == (g_height >> 3))
386                                                 return;
387                                 }
388                         }
389                         break;
390
391                 case 0x7:
392                         p[0] = GETPIXELI(pData, 0);
393                         p[1] = GETPIXELI(pData, 0);
394
395                         if (!((p[0]/*|p[1]*/)&0x8000)) {
396                                 for (i=0; i<8; i++) {
397                                         patternRow2Pixels(*pFrame, *(*pData), p);
398                                         (*pData)++;
399
400                                         *pFrame += g_width;
401                                 }
402                         } else {
403                                 for (i=0; i<2; i++) {
404                                         patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
405                                         *pFrame += 2*g_width;
406                                         patternRow2Pixels2(*pFrame, *(*pData) >> 4, p);
407                                         (*pData)++;
408
409                                         *pFrame += 2*g_width;
410                                 }
411                         }
412                         break;
413
414                 case 0x8:
415                         p[0] = GETPIXEL(pData, 0);
416
417                         if (!(p[0] & 0x8000)) {
418                                 for (i=0; i<4; i++) {
419                                         p[0] = GETPIXELI(pData, 0);
420                                         p[1] = GETPIXELI(pData, 0);
421
422                                         pat[0] = (*pData)[0];
423                                         pat[1] = (*pData)[1];
424                                         (*pData) += 2;
425
426                                         patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
427
428                                         if (i & 1) {
429                                                 *pFrame -= (4*g_width - 4);
430                                         } else {
431                                                 *pFrame += 4*g_width;
432                                         }
433                                 }
434                         } else {
435                                 p[2] = GETPIXEL(pData, 8);
436
437                                 if (!(p[2]&0x8000)) {
438                                         for (i=0; i<4; i++) {
439                                                 if ((i & 1) == 0) {
440                                                         p[0] = GETPIXELI(pData, 0);
441                                                         p[1] = GETPIXELI(pData, 0);
442                                                 }
443                                                 pat[0] = *(*pData)++;
444                                                 pat[1] = *(*pData)++;
445                                                 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
446
447                                                 if (i & 1) {
448                                                         *pFrame -= (4*g_width - 4);
449                                                 } else {
450                                                         *pFrame += 4*g_width;
451                                                 }
452                                         }
453                                 } else {
454                                         for (i=0; i<8; i++) {
455                                                 if ((i & 3) == 0) {
456                                                         p[0] = GETPIXELI(pData, 0);
457                                                         p[1] = GETPIXELI(pData, 0);
458                                                 }
459                                                 patternRow2Pixels(*pFrame, *(*pData), p);
460                                                 (*pData)++;
461
462                                                 *pFrame += g_width;
463                                         }
464                                 }
465                         }
466                         break;
467
468                 case 0x9:
469                         p[0] = GETPIXELI(pData, 0);
470                         p[1] = GETPIXELI(pData, 0);
471                         p[2] = GETPIXELI(pData, 0);
472                         p[3] = GETPIXELI(pData, 0);
473
474                         *pDataRemain -= 8;
475
476                         if (!(p[0] & 0x8000)) {
477                                 if (!(p[2] & 0x8000)) {
478                                         for (i=0; i<8; i++) {
479                                                 pat[0] = (*pData)[0];
480                                                 pat[1] = (*pData)[1];
481                                                 (*pData) += 2;
482                                                 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
483                                                 *pFrame += g_width;
484                                         }
485                                         *pDataRemain -= 16;
486                                 } else {
487                                         patternRow4Pixels2(*pFrame, (*pData)[0], p);
488                                         *pFrame += 2*g_width;
489                                         patternRow4Pixels2(*pFrame, (*pData)[1], p);
490                                         *pFrame += 2*g_width;
491                                         patternRow4Pixels2(*pFrame, (*pData)[2], p);
492                                         *pFrame += 2*g_width;
493                                         patternRow4Pixels2(*pFrame, (*pData)[3], p);
494
495                                         (*pData) += 4;
496                                         *pDataRemain -= 4;
497                                 }
498                         } else {
499                                 if (!(p[2] & 0x8000))  {
500                                         for (i=0; i<8; i++) {
501                                                 pat[0] = (*pData)[0];
502                                                 (*pData) += 1;
503                                                 patternRow4Pixels2x1(*pFrame, pat[0], p);
504                                                 *pFrame += g_width;
505                                         }
506                                         *pDataRemain -= 8;
507                                 } else {
508                                         for (i=0; i<4; i++) {
509                                                 pat[0] = (*pData)[0];
510                                                 pat[1] = (*pData)[1];
511
512                                                 (*pData) += 2;
513
514                                                 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
515                                                 *pFrame += g_width;
516                                                 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
517                                                 *pFrame += g_width;
518                                         }
519                                         *pDataRemain -= 8;
520                                 }
521                         }
522                         break;
523
524                 case 0xa:
525                         p[0] = GETPIXEL(pData, 0);
526
527                         if (!(p[0] & 0x8000)) {
528                                 for (i=0; i<4; i++) {
529                                         p[0] = GETPIXELI(pData, 0);
530                                         p[1] = GETPIXELI(pData, 0);
531                                         p[2] = GETPIXELI(pData, 0);
532                                         p[3] = GETPIXELI(pData, 0);
533                                         pat[0] = (*pData)[0];
534                                         pat[1] = (*pData)[1];
535                                         pat[2] = (*pData)[2];
536                                         pat[3] = (*pData)[3];
537
538                                         (*pData) += 4;
539
540                                         patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
541
542                                         if (i & 1) {
543                                                 *pFrame -= (4*g_width - 4);
544                                         } else {
545                                                 *pFrame += 4*g_width;
546                                         }
547                                 }
548                         } else {
549                                 p[0] = GETPIXEL(pData, 16);
550
551                                 if (!(p[0] & 0x8000)) {
552                                         for (i=0; i<4; i++) {
553                                                 if ((i&1) == 0) {
554                                                         p[0] = GETPIXELI(pData, 0); 
555                                                         p[1] = GETPIXELI(pData, 0);
556                                                         p[2] = GETPIXELI(pData, 0);
557                                                         p[3] = GETPIXELI(pData, 0);
558                                                 }
559
560                                                 pat[0] = (*pData)[0];
561                                                 pat[1] = (*pData)[1];
562                                                 pat[2] = (*pData)[2];
563                                                 pat[3] = (*pData)[3];
564
565                                                 (*pData) += 4;
566
567                                                 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
568
569                                                 if (i & 1) {
570                                                         *pFrame -= (4*g_width - 4);
571                                                 } else {
572                                                         *pFrame += 4*g_width;
573                                                 }
574                                         }
575                                 } else {
576                                         for (i=0; i<8; i++) {
577                                                 if ((i&3) == 0) {
578                                                         p[0] = GETPIXELI(pData, 0);
579                                                         p[1] = GETPIXELI(pData, 0);
580                                                         p[2] = GETPIXELI(pData, 0);
581                                                         p[3] = GETPIXELI(pData, 0);
582                                                 }
583
584                                                 pat[0] = (*pData)[0];
585                                                 pat[1] = (*pData)[1];
586                                                 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
587                                                 *pFrame += g_width;
588
589                                                 (*pData) += 2;
590                                         }
591                                 }
592                         }
593                         break;
594
595                 case 0xb:
596                         for (i=0; i<8; i++) {
597                                 // blah
598                                 memcpy(&frame_tmp, *pData, 16);
599
600                                 for (j = 0; j < 16; j += 2) {
601                                         swap_tmp = (ushort*)(frame_tmp + j);
602                                         *swap_tmp = INTEL_SHORT(*swap_tmp);
603                                 }
604
605                                 memcpy(*pFrame, &frame_tmp, 16);
606
607                                 *pFrame += g_width;
608                                 *pData += 16;
609                                 *pDataRemain -= 16;
610                         }
611                         break;
612
613                 case 0xc:
614                         for (i=0; i<4; i++) {
615                                 p[0] = GETPIXEL(pData, 0);
616                                 p[1] = GETPIXEL(pData, 2);
617                                 p[2] = GETPIXEL(pData, 4);
618                                 p[3] = GETPIXEL(pData, 6);
619
620                                 for (j=0; j<2; j++) {
621                                         for (k=0; k<4; k++) {
622                                                 (*pFrame)[2*k] = p[k];
623                                                 (*pFrame)[2*k+1] = p[k];
624
625                                                 // this is the original code but it messes up FS1 movies
626                                         //      (*pFrame)[j+2*k] = p[k];
627                                         //      (*pFrame)[g_width+j+2*k] = p[k];
628                                         }
629                                         *pFrame += g_width;
630                                 }
631
632                                 *pData += 8;
633                                 *pDataRemain -= 8;
634                         }
635                         break;
636
637                 case 0xd:
638                         for (i=0; i<2; i++) {
639                                 p[0] = GETPIXEL(pData, 0);
640                                 p[1] = GETPIXEL(pData, 2);
641
642                                 for (j=0; j<4; j++) {
643                                         for (k=0; k<4; k++) {
644                                                 (*pFrame)[k*g_width+j] = p[0];
645                                                 (*pFrame)[k*g_width+j+4] = p[1];
646                                         }
647                                 }
648
649                                 *pFrame += 4*g_width;
650
651                                 *pData += 4;
652                                 *pDataRemain -= 4;
653                         }
654                         break;
655
656                 case 0xe:
657                         p[0] = GETPIXEL(pData, 0);
658
659                         for (i = 0; i < 8; i++) {
660                                 for (j = 0; j < 8; j++) {
661                                         (*pFrame)[j] = p[0];
662                                 }
663
664                                 *pFrame += g_width;
665                         }
666
667                         *pData += 2;
668                         *pDataRemain -= 2;
669
670                         break;
671
672                 case 0xf:
673                         p[0] = GETPIXEL(pData, 0);
674                         p[1] = GETPIXEL(pData, 1);
675
676                         for (i=0; i<8; i++) {
677                                 for (j=0; j<8; j++) {
678                                         (*pFrame)[j] = p[(i+j)&1];
679                                 }
680                                 *pFrame += g_width;
681                         }
682
683                         *pData += 4;
684                         *pDataRemain -= 4;
685                         break;
686
687                 default:
688                         break;
689         }
690
691         *pFrame = pDstBak+8;
692 }