ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

blocky16.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/endian.h"
00024 #include "common/util.h"
00025 #include "common/textconsole.h"
00026 
00027 #include "engines/grim/movie/codecs/blocky16.h"
00028 
00029 namespace Grim {
00030 
00031 #if defined(SCUMM_NEED_ALIGNMENT)
00032 
00033 #define COPY_4X1_LINE(dst, src)         \
00034     do {                    \
00035         (dst)[0] = (src)[0];    \
00036         (dst)[1] = (src)[1];    \
00037         (dst)[2] = (src)[2];    \
00038         (dst)[3] = (src)[3];    \
00039     } while (0)
00040 
00041 #if defined(SCUMM_BIG_ENDIAN)
00042 
00043 #define WRITE_2X1_LINE(dst, v)      \
00044     do {                \
00045         (dst)[0] = (byte)((v >> 8) & 0xFF); \
00046         (dst)[1] = (byte)((v >> 0) & 0xFF); \
00047     } while (0)
00048 
00049 #define WRITE_4X1_LINE(dst, v)      \
00050     do {                \
00051         (dst)[0] = (byte)((v >> 24) & 0xFF);    \
00052         (dst)[1] = (byte)((v >> 16) & 0XFF);    \
00053         (dst)[2] = (byte)((v >>  8) & 0xFF);    \
00054         (dst)[3] = (byte)((v >>  0) & 0xFF);    \
00055     } while (0)
00056 
00057 #else /* SCUMM_BIG_ENDIAN */
00058 
00059 #define WRITE_2X1_LINE(dst, v)      \
00060     do {                \
00061         (dst)[0] = (byte)((v >> 0) & 0xFF); \
00062         (dst)[1] = (byte)((v >> 8) & 0xFF); \
00063     } while (0)
00064 
00065 #define WRITE_4X1_LINE(dst, v)      \
00066     do {                \
00067         (dst)[0] = (byte)((v >>  0) & 0xFF);    \
00068         (dst)[1] = (byte)((v >>  8) & 0XFF);    \
00069         (dst)[2] = (byte)((v >> 16) & 0xFF);    \
00070         (dst)[3] = (byte)((v >> 24) & 0xFF);    \
00071     } while (0)
00072 
00073 #endif
00074 
00075 #else /* SCUMM_NEED_ALIGNMENT */
00076 
00077 #define COPY_4X1_LINE(dst, src)         \
00078     *(uint32 *)(dst) = *(const uint32 *)(src);
00079 
00080 #define WRITE_2X1_LINE(dst, v)      \
00081     *(uint16 *)(dst) = v;
00082 
00083 #define WRITE_4X1_LINE(dst, v)      \
00084     *(uint32 *)(dst) = v;
00085 
00086 #endif
00087 
00088 static int8 blocky16_table_small1[] = {
00089     0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1,
00090 };
00091 
00092 static int8 blocky16_table_small2[] = {
00093     0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2,
00094 };
00095 
00096 static int8 blocky16_table_big1[] = {
00097     0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0,
00098 };
00099 
00100 static int8 blocky16_table_big2[] = {
00101     0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1,
00102 };
00103 
00104 static int8 blocky16_table[] = {
00105       0,   0,  -1, -43,   6, -43,  -9, -42,  13, -41,
00106     -16, -40,  19, -39, -23, -36,  26, -34,  -2, -33,
00107       4, -33, -29, -32,  -9, -32,  11, -31, -16, -29,
00108      32, -29,  18, -28, -34, -26, -22, -25,  -1, -25,
00109       3, -25,  -7, -24,   8, -24,  24, -23,  36, -23,
00110     -12, -22,  13, -21, -38, -20,   0, -20, -27, -19,
00111      -4, -19,   4, -19, -17, -18,  -8, -17,   8, -17,
00112      18, -17,  28, -17,  39, -17, -12, -15,  12, -15,
00113     -21, -14,  -1, -14,   1, -14, -41, -13,  -5, -13,
00114       5, -13,  21, -13, -31, -12, -15, -11,  -8, -11,
00115       8, -11,  15, -11,  -2, -10,   1, -10,  31, -10,
00116     -23,  -9, -11,  -9,  -5,  -9,   4,  -9,  11,  -9,
00117      42,  -9,   6,  -8,  24,  -8, -18,  -7,  -7,  -7,
00118      -3,  -7,  -1,  -7,   2,  -7,  18,  -7, -43,  -6,
00119     -13,  -6,  -4,  -6,   4,  -6,   8,  -6, -33,  -5,
00120      -9,  -5,  -2,  -5,   0,  -5,   2,  -5,   5,  -5,
00121      13,  -5, -25,  -4,  -6,  -4,  -3,  -4,   3,  -4,
00122       9,  -4, -19,  -3,  -7,  -3,  -4,  -3,  -2,  -3,
00123      -1,  -3,   0,  -3,   1,  -3,   2,  -3,   4,  -3,
00124       6,  -3,  33,  -3, -14,  -2, -10,  -2,  -5,  -2,
00125      -3,  -2,  -2,  -2,  -1,  -2,   0,  -2,   1,  -2,
00126       2,  -2,   3,  -2,   5,  -2,   7,  -2,  14,  -2,
00127      19,  -2,  25,  -2,  43,  -2,  -7,  -1,  -3,  -1,
00128      -2,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,
00129       3,  -1,  10,  -1,  -5,   0,  -3,   0,  -2,   0,
00130      -1,   0,   1,   0,   2,   0,   3,   0,   5,   0,
00131       7,   0, -10,   1,  -7,   1,  -3,   1,  -2,   1,
00132      -1,   1,   0,   1,   1,   1,   2,   1,   3,   1,
00133     -43,   2, -25,   2, -19,   2, -14,   2,  -5,   2,
00134      -3,   2,  -2,   2,  -1,   2,   0,   2,   1,   2,
00135       2,   2,   3,   2,   5,   2,   7,   2,  10,   2,
00136      14,   2, -33,   3,  -6,   3,  -4,   3,  -2,   3,
00137      -1,   3,   0,   3,   1,   3,   2,   3,   4,   3,
00138      19,   3,  -9,   4,  -3,   4,   3,   4,   7,   4,
00139      25,   4, -13,   5,  -5,   5,  -2,   5,   0,   5,
00140       2,   5,   5,   5,   9,   5,  33,   5,  -8,   6,
00141      -4,   6,   4,   6,  13,   6,  43,   6, -18,   7,
00142      -2,   7,   0,   7,   2,   7,   7,   7,  18,   7,
00143     -24,   8,  -6,   8, -42,   9, -11,   9,  -4,   9,
00144       5,   9,  11,   9,  23,   9, -31,  10,  -1,  10,
00145       2,  10, -15,  11,  -8,  11,   8,  11,  15,  11,
00146      31,  12, -21,  13,  -5,  13,   5,  13,  41,  13,
00147      -1,  14,   1,  14,  21,  14, -12,  15,  12,  15,
00148     -39,  17, -28,  17, -18,  17,  -8,  17,   8,  17,
00149      17,  18,  -4,  19,   0,  19,   4,  19,  27,  19,
00150      38,  20, -13,  21,  12,  22, -36,  23, -24,  23,
00151      -8,  24,   7,  24,  -3,  25,   1,  25,  22,  25,
00152      34,  26, -18,  28, -32,  29,  16,  29, -11,  31,
00153       9,  32,  29,  32,  -4,  33,   2,  33, -26,  34,
00154      23,  36, -19,  39,  16,  40, -13,  41,   9,  42,
00155      -6,  43,   1,  43,   0,   0,   0,   0,   0,   0,
00156       0,   0,   0
00157 };
00158 
00159 void Blocky16::makeTablesInterpolation(int param) {
00160     int32 variable1, variable2;
00161     int32 b1, b2;
00162     int32 value_table47_1_2, value_table47_1_1, value_table47_2_2, value_table47_2_1;
00163     int32 tableSmallBig[64], tmp, s;
00164     int8 *table47_1 = nullptr, *table47_2 = nullptr;
00165     int32 *ptr_small_big;
00166     byte *ptr;
00167     int i, x, y;
00168 
00169     if (param == 8) {
00170         table47_1 = blocky16_table_big1;
00171         table47_2 = blocky16_table_big2;
00172         ptr = _tableBig + 384;
00173         for (i = 0; i < 256; i++) {
00174             *ptr = 0;
00175             ptr += 388;
00176         }
00177         ptr = _tableBig + 385;
00178         for (i = 0; i < 256; i++) {
00179             *ptr = 0;
00180             ptr += 388;
00181         }
00182     } else if (param == 4) {
00183         table47_1 = blocky16_table_small1;
00184         table47_2 = blocky16_table_small2;
00185         ptr = _tableSmall + 96;
00186         for (i = 0; i < 256; i++) {
00187             *ptr = 0;
00188             ptr += 128;
00189         }
00190         ptr = _tableSmall + 97;
00191         for (i = 0; i < 256; i++) {
00192             *ptr = 0;
00193             ptr += 128;
00194         }
00195     } else {
00196         error("Blocky16::makeTablesInterpolation: unknown param %d", param);
00197     }
00198 
00199     s = 0;
00200     for (x = 0; x < 16; x++) {
00201         value_table47_1_1 = table47_1[x];
00202         value_table47_2_1 = table47_2[x];
00203         for (y = 0; y < 16; y++) {
00204             value_table47_1_2 = table47_1[y];
00205             value_table47_2_2 = table47_2[y];
00206 
00207             if (value_table47_2_1 == 0) {
00208                 b1 = 0;
00209             } else if (value_table47_2_1 == param - 1) {
00210                 b1 = 1;
00211             } else if (value_table47_1_1 == 0) {
00212                 b1 = 2;
00213             } else if (value_table47_1_1 == param - 1) {
00214                 b1 = 3;
00215             } else {
00216                 b1 = 4;
00217             }
00218 
00219             if (value_table47_2_2 == 0) {
00220                 b2 = 0;
00221             } else if (value_table47_2_2 == param - 1) {
00222                 b2 = 1;
00223             } else if (value_table47_1_2 == 0) {
00224                 b2 = 2;
00225             } else if (value_table47_1_2 == param - 1) {
00226                 b2 = 3;
00227             } else {
00228                 b2 = 4;
00229             }
00230 
00231             memset(tableSmallBig, 0, param * param * 4);
00232 
00233             variable2 = abs(value_table47_2_2 - value_table47_2_1);
00234             tmp = abs(value_table47_1_2 - value_table47_1_1);
00235             if (variable2 <= tmp) {
00236                 variable2 = tmp;
00237             }
00238 
00239             for (variable1 = 0; variable1 <= variable2; variable1++) {
00240                 int32 variable3, variable4;
00241 
00242                 if (variable2 > 0) {
00243                     // Linearly interpolate between value_table47_1_1 and value_table47_1_2
00244                     // respectively value_table47_2_1 and value_table47_2_2.
00245                     variable4 = (value_table47_1_1 * variable1 + value_table47_1_2 * (variable2 - variable1) + variable2 / 2) / variable2;
00246                     variable3 = (value_table47_2_1 * variable1 + value_table47_2_2 * (variable2 - variable1) + variable2 / 2) / variable2;
00247                 } else {
00248                     variable4 = value_table47_1_1;
00249                     variable3 = value_table47_2_1;
00250                 }
00251                 ptr_small_big = &tableSmallBig[param * variable3 + variable4];
00252                 *ptr_small_big = 1;
00253 
00254                 if ((b1 == 2 && b2 == 3) || (b2 == 2 && b1 == 3) ||
00255                     (b1 == 0 && b2 != 1) || (b2 == 0 && b1 != 1)) {
00256                     if (variable3 >= 0) {
00257                         i = variable3 + 1;
00258                         while (i--) {
00259                             *ptr_small_big = 1;
00260                             ptr_small_big -= param;
00261                         }
00262                     }
00263                 } else if ((b2 != 0 && b1 == 1) || (b1 != 0 && b2 == 1)) {
00264                     if (param > variable3) {
00265                         i = param - variable3;
00266                         while (i--) {
00267                             *ptr_small_big = 1;
00268                             ptr_small_big += param;
00269                         }
00270                     }
00271                 } else if ((b1 == 2 && b2 != 3) || (b2 == 2 && b1 != 3)) {
00272                     if (variable4 >= 0) {
00273                         i = variable4 + 1;
00274                         while (i--) {
00275                             *(ptr_small_big--) = 1;
00276                         }
00277                     }
00278                 } else if ((b1 == 0 && b2 == 1) || (b2 == 0 && b1 == 1) ||
00279                            (b1 == 3 && b2 != 2) || (b2 == 3 && b1 != 2)) {
00280                     if (param > variable4) {
00281                         i = param - variable4;
00282                         while (i--) {
00283                             *(ptr_small_big++) = 1;
00284                         }
00285                     }
00286                 }
00287             }
00288 
00289             if (param == 8) {
00290                 for (i = 64 - 1; i >= 0; i--) {
00291                     if (tableSmallBig[i] != 0) {
00292                         _tableBig[256 + s + _tableBig[384 + s]] = (byte)i;
00293                         _tableBig[384 + s]++;
00294                     } else {
00295                         _tableBig[320 + s + _tableBig[385 + s]] = (byte)i;
00296                         _tableBig[385 + s]++;
00297                     }
00298                 }
00299                 s += 388;
00300             }
00301             if (param == 4) {
00302                 for (i = 16 - 1; i >= 0; i--) {
00303                     if (tableSmallBig[i] != 0) {
00304                         _tableSmall[64 + s + _tableSmall[96 + s]] = (byte)i;
00305                         _tableSmall[96 + s]++;
00306                     } else {
00307                         _tableSmall[80 + s + _tableSmall[97 + s]] = (byte)i;
00308                         _tableSmall[97 + s]++;
00309                     }
00310                 }
00311                 s += 128;
00312             }
00313         }
00314     }
00315 }
00316 
00317 void Blocky16::makeTables47(int width) {
00318     if (_lastTableWidth == width)
00319         return;
00320 
00321     _lastTableWidth = width;
00322 
00323     int32 a, c, d;
00324     int16 tmp;
00325 
00326     for (int l = 0; l < 512; l += 2) {
00327         _table[l / 2] = (int16)(blocky16_table[l + 1] * width + blocky16_table[l]);
00328     }
00329 
00330     a = 0;
00331     c = 0;
00332     do {
00333         for (d = 0; d < _tableSmall[96 + c]; d++) {
00334             tmp = _tableSmall[64 + c + d];
00335             tmp = (int16)((byte)(tmp >> 2) * width + (tmp & 3));
00336             _tableSmall[c + d * 2] = (byte)tmp;
00337             _tableSmall[c + d * 2 + 1] = tmp >> 8;
00338         }
00339         for (d = 0; d < _tableSmall[97 + c]; d++) {
00340             tmp = _tableSmall[80 + c + d];
00341             tmp = (int16)((byte)(tmp >> 2) * width + (tmp & 3));
00342             _tableSmall[32 + c + d * 2] = (byte)tmp;
00343             _tableSmall[32 + c + d * 2 + 1] = tmp >> 8;
00344         }
00345         for (d = 0; d < _tableBig[384 + a]; d++) {
00346             tmp = _tableBig[256 + a + d];
00347             tmp = (int16)((byte)(tmp >> 3) * width + (tmp & 7));
00348             _tableBig[a + d * 2] = (byte)tmp;
00349             _tableBig[a + d * 2 + 1] = tmp >> 8;
00350         }
00351         for (d = 0; d < _tableBig[385 + a]; d++) {
00352             tmp = _tableBig[320 + a + d];
00353             tmp = (int16)((byte)(tmp >> 3) * width + (tmp & 7));
00354             _tableBig[128 + a + d * 2] = (byte)tmp;
00355             _tableBig[128 + a + d * 2 + 1] = tmp >> 8;
00356         }
00357 
00358         a += 388;
00359         c += 128;
00360     } while (c < 32768);
00361 }
00362 
00363 void Blocky16::level3(byte *d_dst) {
00364     int32 tmp2;
00365     uint32 t;
00366     byte code = *_d_src++;
00367     int i;
00368 
00369     if (code <= 0xF5) {
00370         if (code == 0xF5) {
00371             int16 tmp = READ_LE_UINT16(_d_src);
00372             tmp2 = tmp * 2;
00373             _d_src += 2;
00374         } else {
00375             tmp2 = _table[code] * 2;
00376         }
00377         tmp2 += _offset1;
00378         for (i = 0; i < 2; i++) {
00379             COPY_4X1_LINE(d_dst + 0, d_dst + tmp2 + 0);
00380             d_dst += _d_pitch;
00381         }
00382     } else if ((code == 0xFF) || (code == 0xF8)) {
00383         WRITE_2X1_LINE(d_dst + 0, READ_LE_UINT16(_d_src + 0));
00384         WRITE_2X1_LINE(d_dst + 2, READ_LE_UINT16(_d_src + 2));
00385         d_dst += _d_pitch;
00386         WRITE_2X1_LINE(d_dst + 0, READ_LE_UINT16(_d_src + 4));
00387         WRITE_2X1_LINE(d_dst + 2, READ_LE_UINT16(_d_src + 6));
00388         _d_src += 8;
00389     } else if (code == 0xFD) {
00390         t = *_d_src++;
00391         t = READ_LE_UINT16(_param6_7Ptr + t * 2);
00392         t = (t << 16) | t;
00393         for (i = 0; i < 2; i++) {
00394             WRITE_4X1_LINE(d_dst + 0, t);
00395             d_dst += _d_pitch;
00396         }
00397     } else if (code == 0xFE) {
00398         t = READ_LE_UINT16(_d_src);
00399         _d_src += 2;
00400         t = (t << 16) | t;
00401         for (i = 0; i < 2; i++) {
00402             WRITE_4X1_LINE(d_dst + 0, t);
00403             d_dst += _d_pitch;
00404         }
00405     } else if (code == 0xF6) {
00406         tmp2 = _offset2;
00407         for (i = 0; i < 2; i++) {
00408             COPY_4X1_LINE(d_dst + 0, d_dst + tmp2 + 0);
00409             d_dst += _d_pitch;
00410         }
00411     } else if (code == 0xF7) {
00412         tmp2 = READ_LE_UINT32(_d_src);
00413         _d_src += 4;
00414         WRITE_2X1_LINE(d_dst + 0, READ_LE_UINT16(_param6_7Ptr + (byte)tmp2 * 2));
00415         WRITE_2X1_LINE(d_dst + 2, READ_LE_UINT16(_param6_7Ptr + (byte)(tmp2 >> 8) * 2));
00416         tmp2 >>= 16;
00417         d_dst += _d_pitch;
00418         WRITE_2X1_LINE(d_dst + 0, READ_LE_UINT16(_param6_7Ptr + (byte)tmp2 * 2));
00419         WRITE_2X1_LINE(d_dst + 2, READ_LE_UINT16(_param6_7Ptr + (byte)(tmp2 >> 8) * 2));
00420     } else if ((code >= 0xF9) && (code <= 0xFC))  {
00421         t = READ_LE_UINT16(_paramPtr + code * 2);
00422         t = (t << 16) | t;
00423         for (i = 0; i < 2; i++) {
00424             WRITE_4X1_LINE(d_dst + 0, t);
00425             d_dst += _d_pitch;
00426         }
00427     }
00428 }
00429 
00430 void Blocky16::level2(byte *d_dst) {
00431     int32 tmp2;
00432     uint32 t = 0, val;
00433     byte code = *_d_src++;
00434     int i;
00435 
00436     if (code <= 0xF5) {
00437         if (code == 0xF5) {
00438             int16 tmp = READ_LE_UINT16(_d_src);
00439             tmp2 = tmp * 2;
00440             _d_src += 2;
00441         } else {
00442             tmp2 = _table[code] * 2;
00443         }
00444         tmp2 += _offset1;
00445         for (i = 0; i < 4; i++) {
00446             COPY_4X1_LINE(d_dst +  0, d_dst + tmp2 +  0);
00447             COPY_4X1_LINE(d_dst +  4, d_dst + tmp2 +  4);
00448             d_dst += _d_pitch;
00449         }
00450     } else if (code == 0xFF) {
00451         level3(d_dst);
00452         d_dst += 4;
00453         level3(d_dst);
00454         d_dst += _d_pitch * 2 - 4;
00455         level3(d_dst);
00456         d_dst += 4;
00457         level3(d_dst);
00458     } else if (code == 0xF6) {
00459         tmp2 = _offset2;
00460         for (i = 0; i < 4; i++) {
00461             COPY_4X1_LINE(d_dst +  0, d_dst + tmp2 +  0);
00462             COPY_4X1_LINE(d_dst +  4, d_dst + tmp2 +  4);
00463             d_dst += _d_pitch;
00464         }
00465     } else if ((code == 0xF7) || (code == 0xF8)) {
00466         byte tmp = *_d_src++;
00467         if (code == 0xF8) {
00468             val = READ_LE_UINT32(_d_src);
00469             _d_src += 4;
00470         } else {
00471             tmp2 = READ_LE_UINT16(_d_src);
00472             val = READ_LE_UINT16(_param6_7Ptr + (byte)(tmp2 >> 8) * 2) << 16;
00473             val |= READ_LE_UINT16(_param6_7Ptr + (byte)tmp2 * 2);
00474             _d_src += 2;
00475         }
00476         byte *tmp_ptr = _tableSmall + (tmp * 128);
00477         byte l = tmp_ptr[96];
00478         int16 *tmp_ptr2 = (int16 *)tmp_ptr;
00479         while (l--) {
00480             WRITE_2X1_LINE(d_dst + READ_LE_UINT16(tmp_ptr2) * 2, val);
00481             tmp_ptr2++;
00482         }
00483         l = tmp_ptr[97];
00484         val >>= 16;
00485         tmp_ptr2 = (int16 *)(tmp_ptr + 32);
00486         while (l--) {
00487             WRITE_2X1_LINE(d_dst + READ_LE_UINT16(tmp_ptr2) * 2, val);
00488             tmp_ptr2++;
00489         }
00490     } else if (code >= 0xF9) {
00491         if (code == 0xFD) {
00492             t = *_d_src++;
00493             t = READ_LE_UINT16(_param6_7Ptr + t * 2);
00494             t = (t << 16) | t;
00495         } else if (code == 0xFE) {
00496             t = READ_LE_UINT16(_d_src);
00497             t = (t << 16) | t;
00498             _d_src += 2;
00499         } else if ((code >= 0xF9) && (code <= 0xFC))  {
00500             t = READ_LE_UINT16(_paramPtr + code * 2);
00501             t = (t << 16) | t;
00502         }
00503         for (i = 0; i < 4; i++) {
00504             WRITE_4X1_LINE(d_dst + 0, t);
00505             WRITE_4X1_LINE(d_dst + 4, t);
00506             d_dst += _d_pitch;
00507         }
00508     }
00509 }
00510 
00511 void Blocky16::level1(byte *d_dst) {
00512     int32 tmp2;
00513     uint32 t = 0, val;
00514     byte code = *_d_src++;
00515     int i;
00516 
00517     if (code <= 0xF5) {
00518         if (code == 0xF5) {
00519             int16 tmp = READ_LE_UINT16(_d_src);
00520             tmp2 = tmp * 2;
00521             _d_src += 2;
00522         } else {
00523             tmp2 = _table[code] * 2;
00524         }
00525         tmp2 += _offset1;
00526         for (i = 0; i < 8; i++) {
00527             COPY_4X1_LINE(d_dst +  0, d_dst + tmp2 +  0);
00528             COPY_4X1_LINE(d_dst +  4, d_dst + tmp2 +  4);
00529             COPY_4X1_LINE(d_dst +  8, d_dst + tmp2 +  8);
00530             COPY_4X1_LINE(d_dst + 12, d_dst + tmp2 + 12);
00531             d_dst += _d_pitch;
00532         }
00533     } else if (code == 0xFF) {
00534         level2(d_dst);
00535         d_dst += 8;
00536         level2(d_dst);
00537         d_dst += _d_pitch * 4 - 8;
00538         level2(d_dst);
00539         d_dst += 8;
00540         level2(d_dst);
00541     } else if (code == 0xF6) {
00542         tmp2 = _offset2;
00543         for (i = 0; i < 8; i++) {
00544             COPY_4X1_LINE(d_dst +  0, d_dst + tmp2 +  0);
00545             COPY_4X1_LINE(d_dst +  4, d_dst + tmp2 +  4);
00546             COPY_4X1_LINE(d_dst +  8, d_dst + tmp2 +  8);
00547             COPY_4X1_LINE(d_dst + 12, d_dst + tmp2 + 12);
00548             d_dst += _d_pitch;
00549         }
00550     } else if ((code == 0xF7) || (code == 0xF8)) {
00551         byte tmp = *_d_src++;
00552         if (code == 0xF8) {
00553             val = READ_LE_UINT32(_d_src);
00554             _d_src += 4;
00555         } else {
00556             tmp2 = READ_LE_UINT16(_d_src);
00557             val = READ_LE_UINT16(_param6_7Ptr + (byte)(tmp2 >> 8) * 2) << 16;
00558             val |= READ_LE_UINT16(_param6_7Ptr + (byte)tmp2 * 2);
00559             _d_src += 2;
00560         }
00561         byte *tmp_ptr = _tableBig + (tmp * 388);
00562         byte l = tmp_ptr[384];
00563         int16 *tmp_ptr2 = (int16 *)tmp_ptr;
00564         while (l--) {
00565             WRITE_2X1_LINE(d_dst + READ_LE_UINT16(tmp_ptr2) * 2, val);
00566             tmp_ptr2++;
00567         }
00568         l = tmp_ptr[385];
00569         val >>= 16;
00570         tmp_ptr2 = (int16 *)(tmp_ptr + 128);
00571         while (l--) {
00572             WRITE_2X1_LINE(d_dst + READ_LE_UINT16(tmp_ptr2) * 2, val);
00573             tmp_ptr2++;
00574         }
00575     } else if (code >= 0xF9) {
00576         if (code == 0xFD) {
00577             t = *_d_src++;
00578             t = READ_LE_UINT16(_param6_7Ptr + t * 2);
00579             t = (t << 16) | t;
00580         } else if (code == 0xFE) {
00581             t = READ_LE_UINT16(_d_src);
00582             t = (t << 16) | t;
00583             _d_src += 2;
00584         } else if ((code >= 0xF9) && (code <= 0xFC))  {
00585             t = READ_LE_UINT16(_paramPtr + code * 2);
00586             t = (t << 16) | t;
00587         }
00588         for (i = 0; i < 8; i++) {
00589             WRITE_4X1_LINE(d_dst +  0, t);
00590             WRITE_4X1_LINE(d_dst +  4, t);
00591             WRITE_4X1_LINE(d_dst +  8, t);
00592             WRITE_4X1_LINE(d_dst + 12, t);
00593             d_dst += _d_pitch;
00594         }
00595     }
00596 }
00597 
00598 void Blocky16::decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr, const byte *param6_7_ptr) {
00599     _d_src = src;
00600     _paramPtr = param_ptr - 0xf9 - 0xf9;
00601     _param6_7Ptr = param6_7_ptr;
00602     int bh = _blocksHeight;
00603     int next_line = width * 2 * 7;
00604     _d_pitch = width * 2;
00605 
00606     do {
00607         int tmp_bw = _blocksWidth;
00608         do {
00609             level1(dst);
00610             dst += 16;
00611         } while (--tmp_bw);
00612         dst += next_line;
00613     } while (--bh);
00614 }
00615 
00616 void Blocky16::init(int width, int height) {
00617     deinit();
00618     _width = width;
00619     _height = height;
00620     makeTablesInterpolation(4);
00621     makeTablesInterpolation(8);
00622 
00623     _blocksWidth = (width + 7) / 8;
00624     _blocksHeight = (height + 7) / 8;
00625 
00626     _frameSize = _width * _height * 2;
00627 
00628     // some animations, like tb_kitty.snm don't have a multiple of 8 width or height,
00629     // so set the size of the buffer in _blocksWidth * 8 * _blocksHeight * 8, instead
00630     // of using _frameSize.
00631     int size = _blocksWidth * 8 * _blocksHeight * 8 * 2;
00632     _offset = size - _frameSize;
00633     // workaround for read over buffer by increasing buffer
00634     // 200 bytes is enough for smush anims:
00635     // lol, byeruba, crushed, eldepot, heltrain, hostage
00636     uint32 deltaSize = size * 3 + 200;
00637     _deltaBuf = new byte[deltaSize];
00638     memset(_deltaBuf, 0, deltaSize);
00639     _deltaBufs[0] = _deltaBuf;
00640     _deltaBufs[1] = _deltaBuf + _frameSize;
00641     _curBuf = _deltaBuf + _frameSize * 2;
00642 }
00643 
00644 Blocky16::Blocky16() {
00645     _tableBig = new byte[99328];
00646     _tableSmall = new byte[32768];
00647     memset(_tableBig, 0, 99328);
00648     memset(_tableSmall, 0, 32768);
00649     _deltaBuf = nullptr;
00650     _deltaBufs[0] = nullptr;
00651     _deltaBufs[1] = nullptr;
00652     _curBuf = nullptr;
00653     _prevSeqNb = 0;
00654     _lastTableWidth = 0;
00655     _d_src = nullptr;
00656     _paramPtr = nullptr;
00657     _param6_7Ptr = nullptr;
00658     _blocksHeight = _blocksWidth = 0;
00659     _height = _width = 0;
00660     _offset = _offset1 = _offset2 = 0;
00661     _frameSize = 0;
00662     _d_pitch = 0;
00663 }
00664 
00665 void Blocky16::deinit() {
00666     _lastTableWidth = -1;
00667     if (_deltaBuf) {
00668         delete[] _deltaBuf;
00669         _deltaBuf = nullptr;
00670         _deltaBufs[0] = nullptr;
00671         _deltaBufs[1] = nullptr;
00672     }
00673 }
00674 
00675 Blocky16::~Blocky16() {
00676     deinit();
00677     if (_tableBig) {
00678         delete[] _tableBig;
00679         _tableBig = nullptr;
00680     }
00681     if (_tableSmall) {
00682         delete[] _tableSmall;
00683         _tableSmall = nullptr;
00684     }
00685 }
00686 
00687 static int bomp_left;
00688 static int bomp_num;
00689 static int bomp_color;
00690 static const byte *bomp_src;
00691 
00692 static byte bompDecode() {
00693     byte code, result;
00694     const byte *src;
00695 
00696     if (bomp_left == 2) {
00697         src = bomp_src;
00698         bomp_num = (*src >> 1) + 1;
00699         code = *(src++) & 1;
00700         bomp_src = src;
00701         if (code != 0) {
00702             bomp_left = 1;
00703             bomp_color = *src++;
00704             bomp_src = src;
00705         } else {
00706             bomp_left = 0;
00707         }
00708     } else {
00709         src = bomp_src;
00710     }
00711     if (bomp_left != 0) {
00712         if (bomp_left - 1 == 0) {
00713             result = bomp_color;
00714         } else {
00715             result = 255;
00716         }
00717     } else {
00718         result = *(src++);
00719         bomp_src = src;
00720     }
00721 
00722     bomp_num--;
00723     if (bomp_num == 0) {
00724         bomp_left = 2;
00725     }
00726 
00727     return result;
00728 }
00729 
00730 static void bompInit(const byte *src) {
00731     bomp_left = 2;
00732     bomp_src = src;
00733 }
00734 
00735 static void bompDecodeMain(byte *dst, const byte *src, int size) {
00736     size /= 2;
00737     bompInit(src);
00738     while (size--) {
00739 #ifdef SCUMM_BIG_ENDIAN
00740         *(dst + 1) = bompDecode();
00741         *(dst + 0) = bompDecode();
00742 #else
00743         *(dst + 0) = bompDecode();
00744         *(dst + 1) = bompDecode();
00745 #endif
00746         dst += 2;
00747     }
00748 }
00749 
00750 void Blocky16::decode(byte *dst, const byte *src) {
00751     _offset1 = ((_deltaBufs[1] - _curBuf) / 2) * 2;
00752     _offset2 = ((_deltaBufs[0] - _curBuf) / 2) * 2;
00753 
00754     int32 seq_nb = READ_LE_UINT16(src + 16);
00755 
00756     const byte *gfx_data = src + 560;
00757 
00758     if (seq_nb == 0) {
00759         makeTables47(_width);
00760         if (src[32] == src[33]) {
00761             memset(_deltaBufs[0], src[32], _frameSize);
00762             memset(_deltaBufs[1], src[32], _frameSize);
00763         } else {
00764             int count = _frameSize / 2;
00765             uint16 *ptr1 = (uint16 *)_deltaBufs[0];
00766             uint16 *ptr2 = (uint16 *)_deltaBufs[1];
00767             uint16 val = READ_LE_UINT16(src + 32);
00768             while (count--) {
00769                 *(uint16 *)(ptr1++) = val;
00770                 *(uint16 *)(ptr2++) = val;
00771             };
00772 
00773         }
00774         _prevSeqNb = -1;
00775     }
00776 
00777     switch (src[18]) {
00778     case 0:
00779 #if defined(SCUMM_BIG_ENDIAN)
00780         for (int i = 0; i < _width * _height; i++) {
00781             ((uint16 *)_curBuf)[i] = READ_LE_UINT16(gfx_data + i * 2);
00782         }
00783 #else
00784         memcpy(_curBuf, gfx_data, _frameSize);
00785 #endif
00786         break;
00787     case 1:
00788         error("blocky16: not implemented decode1 proc");
00789         break;
00790     case 2:
00791         if (seq_nb == _prevSeqNb + 1) {
00792             decode2(_curBuf, gfx_data, _width, _height, src + 24, src + 40);
00793         }
00794 
00795         break;
00796     case 3:
00797         memcpy(_curBuf, _deltaBufs[1], _frameSize);
00798         break;
00799     case 4:
00800         memcpy(_curBuf, _deltaBufs[0], _frameSize);
00801         break;
00802     case 5:
00803         bompDecodeMain(_curBuf, gfx_data, READ_LE_UINT32(src + 36));
00804         break;
00805     case 6:
00806         {
00807             int count = _frameSize / 2;
00808             uint16 *ptr = (uint16 *)_curBuf;
00809             while (count--) {
00810                 int offset = *gfx_data++ * 2;
00811                 *(uint16 *)ptr++ = READ_LE_UINT16(src + 40 + offset);
00812             };
00813             break;
00814         }
00815     case 7:
00816         error("blocky16: not implemented decode7 proc");
00817         break;
00818     case 8:
00819         {
00820             bompInit(gfx_data);
00821             int count = _frameSize / 2;
00822             uint16 *ptr = (uint16 *)_curBuf;
00823             while (count--) {
00824                 int offset = bompDecode() * 2;
00825                 *(uint16 *)ptr++ = READ_LE_UINT16(src + 40 + offset);
00826             };
00827             break;
00828         }
00829     }
00830 
00831     memcpy(dst, _curBuf, _frameSize);
00832 
00833     if (seq_nb == _prevSeqNb + 1) {
00834         byte *tmp_ptr = nullptr;
00835         if (src[19] == 1) {
00836             tmp_ptr = _curBuf;
00837             _curBuf = _deltaBufs[1];
00838             _deltaBufs[1] = tmp_ptr;
00839         } else if (src[19] == 2) {
00840             tmp_ptr = _deltaBufs[0];
00841             _deltaBufs[0] = _deltaBufs[1];
00842             _deltaBufs[1] = _curBuf - _offset; // subtract the offset here or else a black bar will appear
00843             _curBuf = tmp_ptr;                 // on top of tb_kitty.snm.
00844         }
00845     }
00846     _prevSeqNb = seq_nb;
00847 }
00848 
00849 } // end of namespace Grim


Generated on Sat Feb 23 2019 05:00:58 for ResidualVM by doxygen 1.7.1
curved edge   curved edge