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