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