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