Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
3
 * It is copyright by its individual contributors, as recorded in the
4
 * project's Git history.  See COPYING.txt at the top level for license
5
 * terms and a link to the Git history.
6
 */
7
/* 16 bit decoding routines */
8
 
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <string.h>
12
#include <cstdint>
13
 
14
#include "decoders.h"
15
#include "console.h"
16
 
17
#include "dxxsconf.h"
18
#include <array>
19
#include <utility>
20
 
21
static unsigned short *backBuf1, *backBuf2;
22
 
23
static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, const unsigned char **pData, const unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb);
24
 
25
void decodeFrame16(unsigned char *pFrame, const unsigned char *pMap, int mapRemain, const unsigned char *pData, int dataRemain)
26
{
27
    unsigned short offset;
28
        auto FramePtr = reinterpret_cast<uint16_t *>(pFrame);
29
    int length;
30
    int op;
31
    int i, j;
32
    int xb, yb;
33
 
34
        backBuf1 = reinterpret_cast<uint16_t *>(g_vBackBuf1);
35
        backBuf2 = reinterpret_cast<uint16_t *>(g_vBackBuf2);
36
 
37
    xb = g_width >> 3;
38
    yb = g_height >> 3;
39
 
40
    offset = pData[0]|(pData[1]<<8);
41
 
42
        auto pOffData = pData + offset;
43
 
44
    pData += 2;
45
 
46
        auto pOrig = pData;
47
    length = offset - 2; /*dataRemain-2;*/
48
 
49
    for (j=0; j<yb; j++)
50
    {
51
        for (i=0; i<xb/2; i++)
52
        {
53
            op = (*pMap) & 0xf;
54
            dispatchDecoder16(&FramePtr, op, &pData, &pOffData, &dataRemain, &i, &j);
55
 
56
                        /*
57
                          if (FramePtr < backBuf1)
58
                          con_printf(CON_CRITICAL, "danger!  pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]", i, j, (*pMap) & 0xf);
59
                          else if (FramePtr >= backBuf1 + g_width*g_height)
60
                          con_printf(CON_CRITICAL, "danger!  pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]", i, j, (*pMap) & 0xf);
61
                        */
62
 
63
                        op = ((*pMap) >> 4) & 0xf;
64
            dispatchDecoder16(&FramePtr, op, &pData, &pOffData, &dataRemain, &i, &j);
65
 
66
                        /*
67
                          if (FramePtr < backBuf1)
68
                          con_printf(CON_CRITICAL, "danger!  pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]", i, j, (*pMap) >> 4);
69
                          else if (FramePtr >= backBuf1 + g_width*g_height)
70
                          con_printf(CON_CRITICAL, "danger!  pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]", i, j, (*pMap) >> 4);
71
                        */
72
 
73
            ++pMap;
74
            --mapRemain;
75
        }
76
 
77
        FramePtr += 7*g_width;
78
    }
79
 
80
        const std::ptrdiff_t remaining = (pData - pOrig);
81
        if (const std::ptrdiff_t difference = length - remaining)
82
        {
83
                con_printf(CON_CRITICAL, "DEBUG: junk left over: %d,%d,%d", DXX_ptrdiff_cast_int(remaining), length, DXX_ptrdiff_cast_int(difference));
84
    }
85
}
86
 
87
static uint16_t GETPIXEL(const unsigned char **buf, int off)
88
{
89
        unsigned short val = (*buf)[0+off] | ((*buf)[1+off] << 8);
90
        return val;
91
}
92
 
93
static uint16_t GETPIXELI(const unsigned char **buf, int off)
94
{
95
        unsigned short val = (*buf)[0+off] | ((*buf)[1+off] << 8);
96
        (*buf) += 2;
97
        return val;
98
}
99
 
100
struct position_t
101
{
102
        int x, y;
103
};
104
 
105
static inline constexpr position_t relClose(int i)
106
{
107
        return {(i & 0xf) - 8, (i >> 4) - 8};
108
}
109
 
110
static inline constexpr position_t relFar0(int i, int sign)
111
{
112
        return {
113
                sign * (8 + (i % 7)),
114
                sign *      (i / 7)
115
        };
116
}
117
 
118
static inline constexpr position_t relFar56(int i, int sign)
119
{
120
        return {
121
                sign * (-14 + (i - 56) % 29),
122
                sign *   (8 + (i - 56) / 29)
123
        };
124
}
125
 
126
static inline constexpr position_t relFar(int i, int sign)
127
{
128
        return (i < 56) ? relFar0(i, sign) : relFar56(i, sign);
129
}
130
 
131
struct lookup_table_t
132
{
133
        std::array<position_t, 256> close, far_p, far_n;
134
};
135
 
136
template <std::size_t... N>
137
static inline constexpr lookup_table_t genLoopkupTable(std::index_sequence<N...>)
138
{
139
        return lookup_table_t{
140
                {{relClose(N)...}},
141
                {{relFar(N, 1)...}},
142
                {{relFar(N, -1)...}}
143
        };
144
}
145
 
146
constexpr lookup_table_t lookup_table = genLoopkupTable(std::make_index_sequence<256>());
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
                              const std::array<uint16_t, 4> &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
                               const std::array<uint16_t, 4> &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
                                                                 const std::array<uint16_t, 4> &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, const std::array<uint16_t, 4> &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
                                                          const std::array<uint16_t, 4> &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
                                                           const std::array<uint16_t, 4> &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, const std::array<uint16_t, 4> &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, const unsigned char **pData, const unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb)
316
{
317
        std::array<uint16_t, 4> p;
318
        std::array<uint8_t, 4> pat;
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 = lookup_table.far_p[k].x;
337
                y = lookup_table.far_p[k].y;
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 = lookup_table.far_n[k].x;
348
                y = lookup_table.far_n[k].y;
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 = lookup_table.close[k].x;
359
                y = lookup_table.close[k].y;
360
 
361
                copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
362
                --*pDataRemain;
363
                break;
364
        case 0x5:
365
                x = static_cast<char>(*(*pData)++);
366
                y = static_cast<char>(*(*pData)++);
367
                copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
368
                *pDataRemain -= 2;
369
                break;
370
        case 0x6:
371
                con_puts(CON_CRITICAL, "STUB: encoding 6 not tested");
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
}