2 * $Logfile: /Freespace2/src/movie/decoder16.cpp $
7 * 16-bit frame decoder for MVEs
10 * Revision 1.3 2005/10/01 21:48:01 taylor
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
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.
28 extern int g_width, g_height;
29 extern void *g_vBackBuf1, *g_vBackBuf2;
31 /* 16 bit decoding routines */
33 static ushort *backBuf1, *backBuf2;
34 static int lookup_initialized;
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();
39 void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
42 unsigned char *pOffData, *pEnd;
49 if (!lookup_initialized) {
53 backBuf1 = (ushort *)g_vBackBuf1;
54 backBuf2 = (ushort *)g_vBackBuf2;
59 offset = pData[0]|(pData[1]<<8);
61 pOffData = pData + offset;
62 pEnd = pData + offset;
67 length = offset - 2; /*dataRemain-2;*/
69 for (j=0; j<yb; j++) {
70 for (i=0; i<xb/2; i++) {
72 dispatchDecoder16((ushort **)&pFrame, op, &pData, &pOffData, &dataRemain, &i, &j);
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);
81 op = ((*pMap) >> 4) & 0xf;
82 dispatchDecoder16((ushort **)&pFrame, op, &pData, &pOffData, &dataRemain, &i, &j);
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);
95 pFrame += 7*g_width*2;
98 if ((length-(pData-pOrig)) != 0) {
99 nprintf(("MVE", "DEBUG: junk left over: %d,%d,%d\n", (pData-pOrig), length, (length-(pData-pOrig))));
103 static ushort GETPIXEL(unsigned char **buf, int off)
105 ushort val = (*buf)[0+off] | ((*buf)[1+off] << 8);
109 static ushort GETPIXELI(unsigned char **buf, int off)
111 ushort val = (*buf)[0+off] | ((*buf)[1+off] << 8);
116 static void relClose(int i, int *x, int *y)
127 static void relFar(int i, int sign, int *x, int *y)
130 *x = sign * (8 + (i % 7));
133 *x = sign * (-14 + (i - 56) % 29);
134 *y = sign * (8 + (i - 56) / 29);
138 static int close_table[512];
139 static int far_p_table[512];
140 static int far_n_table[512];
142 static void genLoopkupTable()
147 for (i = 0; i < 256; i++) {
150 close_table[i*2+0] = x;
151 close_table[i*2+1] = y;
153 relFar(i, 1, &x, &y);
155 far_p_table[i*2+0] = x;
156 far_p_table[i*2+1] = y;
158 relFar(i, -1, &x, &y);
160 far_n_table[i*2+0] = x;
161 far_n_table[i*2+1] = y;
164 lookup_initialized = 1;
167 static void copyFrame(ushort *pDest, ushort *pSrc)
171 for (i=0; i<8; i++) {
172 memcpy(pDest, pSrc, 16);
178 static void patternRow4Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, ushort *p)
182 ushort pattern = (pat1 << 8) | pat0;
185 *pFrame++ = p[(mask & pattern) >> shift];
191 static void patternRow4Pixels2(ushort *pFrame, unsigned char pat0, ushort *p)
193 unsigned char mask=0x03;
194 unsigned char shift=0;
196 /* ORIGINAL VERSION IS BUGGY
200 pel = p[(mask & pat0) >> shift];
203 pFrame[g_width + 0] = pel;
204 pFrame[g_width + 2] = pel;
212 pel = p[(mask & pat0) >> shift];
215 pFrame[g_width + 0] = pel;
216 pFrame[g_width + 1] = pel;
223 static void patternRow4Pixels2x1(ushort *pFrame, unsigned char pat, ushort *p)
225 unsigned char mask=0x03;
226 unsigned char shift=0;
230 pel = p[(mask & pat) >> shift];
239 static void patternQuadrant4Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, ushort *p)
241 unsigned long mask = 0x00000003UL;
244 unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
246 for (i=0; i<16; i++) {
247 pFrame[i&3] = p[(pat & mask) >> shift];
257 static void patternRow2Pixels(ushort *pFrame, unsigned char pat, ushort *p)
259 unsigned char mask=0x01;
262 *pFrame++ = p[(mask & pat) ? 1 : 0];
267 static void patternRow2Pixels2(ushort *pFrame, unsigned char pat, ushort *p)
270 unsigned char mask=0x1;
272 /* ORIGINAL VERSION IS BUGGY
274 while (mask != 0x10) {
275 pel = p[(mask & pat) ? 1 : 0];
278 pFrame[g_width + 0] = pel;
279 pFrame[g_width + 2] = pel;
285 while (mask != 0x10) {
286 pel = p[(mask & pat) ? 1 : 0];
290 pFrame[g_width + 0] = pel;
291 pFrame[g_width + 1] = pel;
298 static void patternQuadrant2Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, ushort *p)
300 ushort mask = 0x0001;
302 ushort pat = (pat1 << 8) | pat0;
304 for (i=0; i<16; i++) {
305 pFrame[i&3] = p[(pat & mask) ? 1 : 0];
315 static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb)
318 unsigned char pat[16];
329 copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1));
336 /* relFar(*(*pOffData)++, 1, &x, &y); */
339 x = far_p_table[k*2+0];
340 y = far_p_table[k*2+1];
342 copyFrame(*pFrame, *pFrame + x + y*g_width);
347 /* relFar(*(*pOffData)++, -1, &x, &y); */
350 x = far_n_table[k*2+0];
351 y = far_n_table[k*2+1];
353 copyFrame(*pFrame, *pFrame + x + y*g_width);
358 /* relClose(*(*pOffData)++, &x, &y); */
361 x = close_table[k*2+0];
362 y = close_table[k*2+1];
364 copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
369 x = (char)*(*pData)++;
370 y = (char)*(*pData)++;
371 copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
376 nprintf(("MVE", "STUB: encoding 6 not tested\n"));
378 for (i=0; i<2; i++) {
381 if (++*curXb == (g_width >> 3)) {
382 *pFrame += 7*g_width;
385 if (++*curYb == (g_height >> 3))
392 p[0] = GETPIXELI(pData, 0);
393 p[1] = GETPIXELI(pData, 0);
395 if (!((p[0]/*|p[1]*/)&0x8000)) {
396 for (i=0; i<8; i++) {
397 patternRow2Pixels(*pFrame, *(*pData), p);
403 for (i=0; i<2; i++) {
404 patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
405 *pFrame += 2*g_width;
406 patternRow2Pixels2(*pFrame, *(*pData) >> 4, p);
409 *pFrame += 2*g_width;
415 p[0] = GETPIXEL(pData, 0);
417 if (!(p[0] & 0x8000)) {
418 for (i=0; i<4; i++) {
419 p[0] = GETPIXELI(pData, 0);
420 p[1] = GETPIXELI(pData, 0);
422 pat[0] = (*pData)[0];
423 pat[1] = (*pData)[1];
426 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
429 *pFrame -= (4*g_width - 4);
431 *pFrame += 4*g_width;
435 p[2] = GETPIXEL(pData, 8);
437 if (!(p[2]&0x8000)) {
438 for (i=0; i<4; i++) {
440 p[0] = GETPIXELI(pData, 0);
441 p[1] = GETPIXELI(pData, 0);
443 pat[0] = *(*pData)++;
444 pat[1] = *(*pData)++;
445 patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
448 *pFrame -= (4*g_width - 4);
450 *pFrame += 4*g_width;
454 for (i=0; i<8; i++) {
456 p[0] = GETPIXELI(pData, 0);
457 p[1] = GETPIXELI(pData, 0);
459 patternRow2Pixels(*pFrame, *(*pData), p);
469 p[0] = GETPIXELI(pData, 0);
470 p[1] = GETPIXELI(pData, 0);
471 p[2] = GETPIXELI(pData, 0);
472 p[3] = GETPIXELI(pData, 0);
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];
482 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
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);
499 if (!(p[2] & 0x8000)) {
500 for (i=0; i<8; i++) {
501 pat[0] = (*pData)[0];
503 patternRow4Pixels2x1(*pFrame, pat[0], p);
508 for (i=0; i<4; i++) {
509 pat[0] = (*pData)[0];
510 pat[1] = (*pData)[1];
514 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
516 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
525 p[0] = GETPIXEL(pData, 0);
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];
540 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
543 *pFrame -= (4*g_width - 4);
545 *pFrame += 4*g_width;
549 p[0] = GETPIXEL(pData, 16);
551 if (!(p[0] & 0x8000)) {
552 for (i=0; i<4; i++) {
554 p[0] = GETPIXELI(pData, 0);
555 p[1] = GETPIXELI(pData, 0);
556 p[2] = GETPIXELI(pData, 0);
557 p[3] = GETPIXELI(pData, 0);
560 pat[0] = (*pData)[0];
561 pat[1] = (*pData)[1];
562 pat[2] = (*pData)[2];
563 pat[3] = (*pData)[3];
567 patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
570 *pFrame -= (4*g_width - 4);
572 *pFrame += 4*g_width;
576 for (i=0; i<8; i++) {
578 p[0] = GETPIXELI(pData, 0);
579 p[1] = GETPIXELI(pData, 0);
580 p[2] = GETPIXELI(pData, 0);
581 p[3] = GETPIXELI(pData, 0);
584 pat[0] = (*pData)[0];
585 pat[1] = (*pData)[1];
586 patternRow4Pixels(*pFrame, pat[0], pat[1], p);
596 for (i=0; i<8; i++) {
598 memcpy(&frame_tmp, *pData, 16);
600 for (j = 0; j < 16; j += 2) {
601 swap_tmp = (ushort*)(frame_tmp + j);
602 *swap_tmp = INTEL_SHORT(*swap_tmp);
605 memcpy(*pFrame, &frame_tmp, 16);
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);
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];
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];
638 for (i=0; i<2; i++) {
639 p[0] = GETPIXEL(pData, 0);
640 p[1] = GETPIXEL(pData, 2);
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];
649 *pFrame += 4*g_width;
657 p[0] = GETPIXEL(pData, 0);
659 for (i = 0; i < 8; i++) {
660 for (j = 0; j < 8; j++) {
673 p[0] = GETPIXEL(pData, 0);
674 p[1] = GETPIXEL(pData, 1);
676 for (i=0; i<8; i++) {
677 for (j=0; j<8; j++) {
678 (*pFrame)[j] = p[(i+j)&1];