Ticket #3366: codec47.patch

File codec47.patch, 8.1 KB (added by fingolfin, 12 years ago)

Experimental patch for SMUSH codec47

  • engines/scumm/smush/codec47.cpp

     
    3333
    3434#if defined(SCUMM_NEED_ALIGNMENT)
    3535
    36 #define COPY_4X1_LINE(dst, src)                 \
     36#define COPY_2X1_LINE(dst, src)                 \
    3737        do {                                    \
    3838                (dst)[0] = (src)[0];    \
    3939                (dst)[1] = (src)[1];    \
    40                 (dst)[2] = (src)[2];    \
    41                 (dst)[3] = (src)[3];    \
    4240        } while (0)
    4341
    44 #define COPY_2X1_LINE(dst, src)                 \
     42#define FILL_2X1_LINE(dst, val)                 \
    4543        do {                                    \
    46                 (dst)[0] = (src)[0];    \
    47                 (dst)[1] = (src)[1];    \
     44                (dst)[0] = val; \
     45                (dst)[1] = val; \
    4846        } while (0)
    4947
    50 
    5148#else /* SCUMM_NEED_ALIGNMENT */
    5249
    53 #define COPY_4X1_LINE(dst, src)                 \
    54         *(uint32 *)(dst) = *(const uint32 *)(src)
    55 
    5650#define COPY_2X1_LINE(dst, src)                 \
    5751        *(uint16 *)(dst) = *(const uint16 *)(src)
    5852
     53#define FILL_2X1_LINE(dst, val)                 \
     54        *(uint16 *)(dst) = (val) << 8 | (val)
     55
    5956#endif
    6057
     58#define COPY_4X1_LINE(dst, src)                 \
     59        *(uint32 *)(dst) = *(const uint32 *)(src)
     60
    6161#define FILL_4X1_LINE(dst, val)                 \
    62         do {                                    \
    63                 (dst)[0] = val; \
    64                 (dst)[1] = val; \
    65                 (dst)[2] = val; \
    66                 (dst)[3] = val; \
    67         } while (0)
     62        *(uint32 *)(dst) = (val) << 24 | (val) << 16 | (val) << 8 | (val)
    6863
    69 #define FILL_2X1_LINE(dst, val)                 \
    70         do {                                    \
    71                 (dst)[0] = val; \
    72                 (dst)[1] = val; \
    73         } while (0)
    7464
     65
    7566static const  int8 codec47_table_small1[] = {
    7667  0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1,
    7768};
     
    362353                   _offset1,_offset2,_tableSmall)
    363354
    364355#else
    365 void Codec47Decoder::level3(byte *d_dst) {
    366         int32 tmp;
    367         byte code = *_d_src++;
     356void Codec47Decoder::level3(byte *d_dst, const int pitch, uint16 &valA, uint16 &valB) {
     357        const byte code = *_d_src++;
    368358
    369359        if (code < 0xF8) {
    370                 tmp = _table[code] + _offset1;
    371                 COPY_2X1_LINE(d_dst, d_dst + tmp);
    372                 COPY_2X1_LINE(d_dst + _d_pitch, d_dst + _d_pitch + tmp);
     360                const int tmp = _table[code] + _offset1;
     361                // FIXME: The following read might be misaligned. Problem???
     362                valA = *(const uint16 *)(d_dst + tmp);
     363                valB = *(const uint16 *)(d_dst + tmp + pitch);
    373364        } else if (code == 0xFF) {
    374                 COPY_2X1_LINE(d_dst, _d_src + 0);
    375                 COPY_2X1_LINE(d_dst + _d_pitch, _d_src + 2);
     365                // FIXME: The following read might be misaligned. Problem???
     366                valA = *(const uint16 *)(_d_src + 0);
     367                valB = *(const uint16 *)(_d_src + 2);
    376368                _d_src += 4;
    377369        } else if (code == 0xFE) {
    378                 byte t = *_d_src++;
    379                 FILL_2X1_LINE(d_dst, t);
    380                 FILL_2X1_LINE(d_dst + _d_pitch, t);
     370                const byte t = *_d_src++;
     371                valA = valB = (t << 8) | t;
    381372        } else if (code == 0xFC) {
    382                 tmp = _offset2;
    383                 COPY_2X1_LINE(d_dst, d_dst + tmp);
    384                 COPY_2X1_LINE(d_dst + _d_pitch, d_dst + _d_pitch + tmp);
     373                const int tmp = _offset2;
     374                // FIXME: The following read might be misaligned. Problem???
     375                valA = *(const uint16 *)(d_dst + tmp);
     376                valB = *(const uint16 *)(d_dst + tmp + pitch);
    385377        } else {
    386                 byte t = _paramPtr[code];
    387                 FILL_2X1_LINE(d_dst, t);
    388                 FILL_2X1_LINE(d_dst + _d_pitch, t);
     378                const byte t = _paramPtr[code];
     379                valA = valB = (t << 8) | t;
    389380        }
    390381}
    391382
    392 void Codec47Decoder::level2(byte *d_dst) {
    393         int32 tmp;
    394         byte code = *_d_src++;
    395         int i;
     383void Codec47Decoder::level2(byte *d_dst, const int pitch) {
     384        const byte code = *_d_src++;
    396385
    397386        if (code < 0xF8) {
    398                 tmp = _table[code] + _offset1;
    399                 for (i = 0; i < 4; i++) {
     387                const int tmp = _table[code] + _offset1;
     388                for (int i = 0; i < 4; i++) {
    400389                        COPY_4X1_LINE(d_dst, d_dst + tmp);
    401                         d_dst += _d_pitch;
     390                        d_dst += pitch;
    402391                }
    403392        } else if (code == 0xFF) {
    404                 level3(d_dst);
    405                 d_dst += 2;
    406                 level3(d_dst);
    407                 d_dst += _d_pitch * 2 - 2;
    408                 level3(d_dst);
    409                 d_dst += 2;
    410                 level3(d_dst);
     393                uint16 valA1, valB1, valA2, valB2;
     394
     395                level3(d_dst, pitch, valA1, valB1);
     396                level3(d_dst + 2, pitch, valA2, valB2);
     397#ifdef SCUMM_BIG_ENDIAN
     398                *(uint32 *)d_dst = ((uint32)valA1 << 16) | (uint32)valA2;
     399                *(uint32 *)(d_dst + pitch) = ((uint32)valB1 << 16) | (uint32)valB2;
     400#else
     401                *(uint32 *)d_dst = ((uint32)valA2 << 16) | (uint32)valA1;
     402                *(uint32 *)(d_dst + pitch) = ((uint32)valB2 << 16) | (uint32)valB1;
     403#endif
     404
     405                d_dst += pitch * 2;
     406
     407                level3(d_dst, pitch, valA1, valB1);
     408                level3(d_dst + 2, pitch, valA2, valB2);
     409#ifdef SCUMM_BIG_ENDIAN
     410                *(uint32 *)d_dst = ((uint32)valA1 << 16) | (uint32)valA2;
     411                *(uint32 *)(d_dst + pitch) = ((uint32)valB1 << 16) | (uint32)valB2;
     412#else
     413                *(uint32 *)d_dst = ((uint32)valA2 << 16) | (uint32)valA1;
     414                *(uint32 *)(d_dst + pitch) = ((uint32)valB2 << 16) | (uint32)valB1;
     415#endif
    411416        } else if (code == 0xFE) {
    412                 byte t = *_d_src++;
    413                 for (i = 0; i < 4; i++) {
     417                const byte t = *_d_src++;
     418                for (int i = 0; i < 4; i++) {
    414419                        FILL_4X1_LINE(d_dst, t);
    415                         d_dst += _d_pitch;
     420                        d_dst += pitch;
    416421                }
    417422        } else if (code == 0xFD) {
    418423                byte *tmp_ptr = _tableSmall + *_d_src++ * 128;
     
    431436                        tmp_ptr2++;
    432437                }
    433438        } else if (code == 0xFC) {
    434                 tmp = _offset2;
    435                 for (i = 0; i < 4; i++) {
     439                const int tmp = _offset2;
     440                for (int i = 0; i < 4; i++) {
    436441                        COPY_4X1_LINE(d_dst, d_dst + tmp);
    437                         d_dst += _d_pitch;
     442                        d_dst += pitch;
    438443                }
    439444        } else {
    440                 byte t = _paramPtr[code];
    441                 for (i = 0; i < 4; i++) {
     445                const byte t = _paramPtr[code];
     446                for (int i = 0; i < 4; i++) {
    442447                        FILL_4X1_LINE(d_dst, t);
    443                         d_dst += _d_pitch;
     448                        d_dst += pitch;
    444449                }
    445450        }
    446451}
    447452
    448 void Codec47Decoder::level1(byte *d_dst) {
    449         int32 tmp, tmp2;
    450         byte code = *_d_src++;
    451         int i;
     453void Codec47Decoder::level1(byte *d_dst, const int pitch) {
     454        const byte code = *_d_src++;
    452455
    453456        if (code < 0xF8) {
    454                 tmp2 = _table[code] + _offset1;
    455                 for (i = 0; i < 8; i++) {
    456                         COPY_4X1_LINE(d_dst + 0, d_dst + tmp2);
    457                         COPY_4X1_LINE(d_dst + 4, d_dst + tmp2 + 4);
    458                         d_dst += _d_pitch;
     457                const int tmp = _table[code] + _offset1;
     458                for (int i = 0; i < 8; i++) {
     459                        memcpy(d_dst, d_dst + tmp, 8);
     460                        d_dst += pitch;
    459461                }
    460462        } else if (code == 0xFF) {
    461                 level2(d_dst);
    462                 d_dst += 4;
    463                 level2(d_dst);
    464                 d_dst += _d_pitch * 4 - 4;
    465                 level2(d_dst);
    466                 d_dst += 4;
    467                 level2(d_dst);
     463                level2(d_dst, pitch);
     464                level2(d_dst + 4, pitch);
     465                d_dst += pitch * 4;
     466                level2(d_dst, pitch);
     467                level2(d_dst + 4, pitch);
    468468        } else if (code == 0xFE) {
    469                 byte t = *_d_src++;
    470                 for (i = 0; i < 8; i++) {
    471                         FILL_4X1_LINE(d_dst, t);
    472                         FILL_4X1_LINE(d_dst + 4, t);
    473                         d_dst += _d_pitch;
     469                const byte t = *_d_src++;
     470                for (int i = 0; i < 8; i++) {
     471                        memset(d_dst, t, 8);
     472                        d_dst += pitch;
    474473                }
    475474        } else if (code == 0xFD) {
    476                 tmp = *_d_src++;
     475                const int tmp = *_d_src++;
    477476                byte *tmp_ptr = _tableBig + tmp * 388;
    478477                byte l = tmp_ptr[384];
    479478                byte val = *_d_src++;
     
    490489                        tmp_ptr2++;
    491490                }
    492491        } else if (code == 0xFC) {
    493                 tmp2 = _offset2;
    494                 for (i = 0; i < 8; i++) {
    495                         COPY_4X1_LINE(d_dst + 0, d_dst + tmp2);
    496                         COPY_4X1_LINE(d_dst + 4, d_dst + tmp2 + 4);
    497                         d_dst += _d_pitch;
     492                const int tmp = _offset2;
     493                for (int i = 0; i < 8; i++) {
     494                        memcpy(d_dst, d_dst + tmp, 8);
     495                        d_dst += pitch;
    498496                }
    499497        } else {
    500                 byte t = _paramPtr[code];
    501                 for (i = 0; i < 8; i++) {
    502                         FILL_4X1_LINE(d_dst, t);
    503                         FILL_4X1_LINE(d_dst + 4, t);
    504                         d_dst += _d_pitch;
     498                const byte t = _paramPtr[code];
     499                for (int i = 0; i < 8; i++) {
     500                        memset(d_dst, t, 8);
     501                        d_dst += pitch;
    505502                }
    506503        }
    507504}
     
    512509        int bw = (width + 7) / 8;
    513510        int bh = (height + 7) / 8;
    514511        int next_line = width * 7;
    515         _d_pitch = width;
    516512
    517513        do {
    518514                int tmp_bw = bw;
    519515                do {
    520                         level1(dst);
     516                        level1(dst, width);
    521517                        dst += 8;
    522518                } while (--tmp_bw);
    523519                dst += next_line;
  • engines/scumm/smush/codec47.h

     
    4040        int32 _prevSeqNb;
    4141        int _lastTableWidth;
    4242        const byte *_d_src, *_paramPtr;
    43         int _d_pitch;
    4443        int32 _offset1, _offset2;
    4544        byte *_tableBig;
    4645        byte *_tableSmall;
     
    5049
    5150        void makeTablesInterpolation(int param);
    5251        void makeTables47(int width);
    53         void level1(byte *d_dst);
    54         void level2(byte *d_dst);
    55         void level3(byte *d_dst);
     52        void level1(byte *d_dst, const int pitch);
     53        void level2(byte *d_dst, const int pitch);
     54        void level3(byte *d_dst, const int pitch, uint16 &valA, uint16 &valB);
    5655        void decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr);
    5756
    5857public: