1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23
24 #include "common/endian.h"
25 #include "common/util.h"
26 #include "common/textconsole.h"
27
28 #include "engines/grim/movie/codecs/blocky8.h"
29
30 namespace Grim {
31
32 #if defined(SYSTEM_NEED_ALIGNMENT)
33
34 #define COPY_4X1_LINE(dst, src) \
35 do { \
36 (dst)[0] = (src)[0]; \
37 (dst)[1] = (src)[1]; \
38 (dst)[2] = (src)[2]; \
39 (dst)[3] = (src)[3]; \
40 } while (0)
41
42 #define COPY_2X1_LINE(dst, src) \
43 do { \
44 (dst)[0] = (src)[0]; \
45 (dst)[1] = (src)[1]; \
46 } while (0)
47
48
49 #else /* SYSTEM_NEED_ALIGNMENT */
50
51 #define COPY_4X1_LINE(dst, src) \
52 *(uint32 *)(dst) = *(const uint32 *)(src)
53
54 #define COPY_2X1_LINE(dst, src) \
55 *(uint16 *)(dst) = *(const uint16 *)(src)
56
57 #endif
58
59 #define FILL_4X1_LINE(dst, val) \
60 do { \
61 (dst)[0] = val; \
62 (dst)[1] = val; \
63 (dst)[2] = val; \
64 (dst)[3] = val; \
65 } while (0)
66
67 #define FILL_2X1_LINE(dst, val) \
68 do { \
69 (dst)[0] = val; \
70 (dst)[1] = val; \
71 } while (0)
72
73 static const int8 blocky8_table_small1[] = {
74 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1,
75 };
76
77 static const int8 blocky8_table_small2[] = {
78 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2,
79 };
80
81 static const int8 blocky8_table_big1[] = {
82 0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0,
83 };
84
85 static const int8 blocky8_table_big2[] = {
86 0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1,
87 };
88
89 static const int8 blocky8_table[] = {
90 0, 0, -1, -43, 6, -43, -9, -42, 13, -41,
91 -16, -40, 19, -39, -23, -36, 26, -34, -2, -33,
92 4, -33, -29, -32, -9, -32, 11, -31, -16, -29,
93 32, -29, 18, -28, -34, -26, -22, -25, -1, -25,
94 3, -25, -7, -24, 8, -24, 24, -23, 36, -23,
95 -12, -22, 13, -21, -38, -20, 0, -20, -27, -19,
96 -4, -19, 4, -19, -17, -18, -8, -17, 8, -17,
97 18, -17, 28, -17, 39, -17, -12, -15, 12, -15,
98 -21, -14, -1, -14, 1, -14, -41, -13, -5, -13,
99 5, -13, 21, -13, -31, -12, -15, -11, -8, -11,
100 8, -11, 15, -11, -2, -10, 1, -10, 31, -10,
101 -23, -9, -11, -9, -5, -9, 4, -9, 11, -9,
102 42, -9, 6, -8, 24, -8, -18, -7, -7, -7,
103 -3, -7, -1, -7, 2, -7, 18, -7, -43, -6,
104 -13, -6, -4, -6, 4, -6, 8, -6, -33, -5,
105 -9, -5, -2, -5, 0, -5, 2, -5, 5, -5,
106 13, -5, -25, -4, -6, -4, -3, -4, 3, -4,
107 9, -4, -19, -3, -7, -3, -4, -3, -2, -3,
108 -1, -3, 0, -3, 1, -3, 2, -3, 4, -3,
109 6, -3, 33, -3, -14, -2, -10, -2, -5, -2,
110 -3, -2, -2, -2, -1, -2, 0, -2, 1, -2,
111 2, -2, 3, -2, 5, -2, 7, -2, 14, -2,
112 19, -2, 25, -2, 43, -2, -7, -1, -3, -1,
113 -2, -1, -1, -1, 0, -1, 1, -1, 2, -1,
114 3, -1, 10, -1, -5, 0, -3, 0, -2, 0,
115 -1, 0, 1, 0, 2, 0, 3, 0, 5, 0,
116 7, 0, -10, 1, -7, 1, -3, 1, -2, 1,
117 -1, 1, 0, 1, 1, 1, 2, 1, 3, 1,
118 -43, 2, -25, 2, -19, 2, -14, 2, -5, 2,
119 -3, 2, -2, 2, -1, 2, 0, 2, 1, 2,
120 2, 2, 3, 2, 5, 2, 7, 2, 10, 2,
121 14, 2, -33, 3, -6, 3, -4, 3, -2, 3,
122 -1, 3, 0, 3, 1, 3, 2, 3, 4, 3,
123 19, 3, -9, 4, -3, 4, 3, 4, 7, 4,
124 25, 4, -13, 5, -5, 5, -2, 5, 0, 5,
125 2, 5, 5, 5, 9, 5, 33, 5, -8, 6,
126 -4, 6, 4, 6, 13, 6, 43, 6, -18, 7,
127 -2, 7, 0, 7, 2, 7, 7, 7, 18, 7,
128 -24, 8, -6, 8, -42, 9, -11, 9, -4, 9,
129 5, 9, 11, 9, 23, 9, -31, 10, -1, 10,
130 2, 10, -15, 11, -8, 11, 8, 11, 15, 11,
131 31, 12, -21, 13, -5, 13, 5, 13, 41, 13,
132 -1, 14, 1, 14, 21, 14, -12, 15, 12, 15,
133 -39, 17, -28, 17, -18, 17, -8, 17, 8, 17,
134 17, 18, -4, 19, 0, 19, 4, 19, 27, 19,
135 38, 20, -13, 21, 12, 22, -36, 23, -24, 23,
136 -8, 24, 7, 24, -3, 25, 1, 25, 22, 25,
137 34, 26, -18, 28, -32, 29, 16, 29, -11, 31,
138 9, 32, 29, 32, -4, 33, 2, 33, -26, 34,
139 23, 36, -19, 39, 16, 40, -13, 41, 9, 42,
140 -6, 43, 1, 43, 0, 0, 0, 0, 0, 0,
141 0, 0, 0
142 };
143
makeTablesInterpolation(int param)144 void Blocky8::makeTablesInterpolation(int param) {
145 int32 variable1, variable2;
146 int32 b1, b2;
147 int32 value_table47_1_2, value_table47_1_1, value_table47_2_2, value_table47_2_1;
148 int32 tableSmallBig[64], tmp, s;
149 const int8 *table47_1 = nullptr, *table47_2 = nullptr;
150 int32 *ptr_small_big;
151 byte *ptr;
152 int i, x, y;
153
154 if (param == 8) {
155 table47_1 = blocky8_table_big1;
156 table47_2 = blocky8_table_big2;
157 ptr = _tableBig;
158 for (i = 0; i < 256; i++) {
159 ptr[384] = 0;
160 ptr[385] = 0;
161 ptr += 388;
162 }
163 } else if (param == 4) {
164 table47_1 = blocky8_table_small1;
165 table47_2 = blocky8_table_small2;
166 ptr = _tableSmall;
167 for (i = 0; i < 256; i++) {
168 ptr[96] = 0;
169 ptr[97] = 0;
170 ptr += 128;
171 }
172 } else {
173 error("Blocky8::makeTablesInterpolation: unknown param %d", param);
174 }
175
176 s = 0;
177 for (x = 0; x < 16; x++) {
178 value_table47_1_1 = table47_1[x];
179 value_table47_2_1 = table47_2[x];
180 for (y = 0; y < 16; y++) {
181 value_table47_1_2 = table47_1[y];
182 value_table47_2_2 = table47_2[y];
183
184 if (value_table47_2_1 == 0) {
185 b1 = 0;
186 } else if (value_table47_2_1 == param - 1) {
187 b1 = 1;
188 } else if (value_table47_1_1 == 0) {
189 b1 = 2;
190 } else if (value_table47_1_1 == param - 1) {
191 b1 = 3;
192 } else {
193 b1 = 4;
194 }
195
196 if (value_table47_2_2 == 0) {
197 b2 = 0;
198 } else if (value_table47_2_2 == param - 1) {
199 b2 = 1;
200 } else if (value_table47_1_2 == 0) {
201 b2 = 2;
202 } else if (value_table47_1_2 == param - 1) {
203 b2 = 3;
204 } else {
205 b2 = 4;
206 }
207
208 memset(tableSmallBig, 0, param * param * 4);
209
210 variable2 = ABS(value_table47_2_2 - value_table47_2_1);
211 tmp = ABS(value_table47_1_2 - value_table47_1_1);
212 if (variable2 <= tmp) {
213 variable2 = tmp;
214 }
215
216 for (variable1 = 0; variable1 <= variable2; variable1++) {
217 int32 variable3, variable4;
218
219 if (variable2 > 0) {
220 // Linearly interpolate between value_table47_1_1 and value_table47_1_2
221 // respectively value_table47_2_1 and value_table47_2_2.
222 variable4 = (value_table47_1_1 * variable1 + value_table47_1_2 * (variable2 - variable1) + variable2 / 2) / variable2;
223 variable3 = (value_table47_2_1 * variable1 + value_table47_2_2 * (variable2 - variable1) + variable2 / 2) / variable2;
224 } else {
225 variable4 = value_table47_1_1;
226 variable3 = value_table47_2_1;
227 }
228 ptr_small_big = &tableSmallBig[param * variable3 + variable4];
229 *ptr_small_big = 1;
230
231 if ((b1 == 2 && b2 == 3) || (b2 == 2 && b1 == 3) ||
232 (b1 == 0 && b2 != 1) || (b2 == 0 && b1 != 1)) {
233 if (variable3 >= 0) {
234 i = variable3 + 1;
235 while (i--) {
236 *ptr_small_big = 1;
237 ptr_small_big -= param;
238 }
239 }
240 } else if ((b2 != 0 && b1 == 1) || (b1 != 0 && b2 == 1)) {
241 if (param > variable3) {
242 i = param - variable3;
243 while (i--) {
244 *ptr_small_big = 1;
245 ptr_small_big += param;
246 }
247 }
248 } else if ((b1 == 2 && b2 != 3) || (b2 == 2 && b1 != 3)) {
249 if (variable4 >= 0) {
250 i = variable4 + 1;
251 while (i--) {
252 *(ptr_small_big--) = 1;
253 }
254 }
255 } else if ((b1 == 0 && b2 == 1) || (b2 == 0 && b1 == 1) ||
256 (b1 == 3 && b2 != 2) || (b2 == 3 && b1 != 2)) {
257 if (param > variable4) {
258 i = param - variable4;
259 while (i--) {
260 *(ptr_small_big++) = 1;
261 }
262 }
263 }
264 }
265
266 if (param == 8) {
267 for (i = 64 - 1; i >= 0; i--) {
268 if (tableSmallBig[i] != 0) {
269 _tableBig[256 + s + _tableBig[384 + s]] = (byte)i;
270 _tableBig[384 + s]++;
271 } else {
272 _tableBig[320 + s + _tableBig[385 + s]] = (byte)i;
273 _tableBig[385 + s]++;
274 }
275 }
276 s += 388;
277 }
278 if (param == 4) {
279 for (i = 16 - 1; i >= 0; i--) {
280 if (tableSmallBig[i] != 0) {
281 _tableSmall[64 + s + _tableSmall[96 + s]] = (byte)i;
282 _tableSmall[96 + s]++;
283 } else {
284 _tableSmall[80 + s + _tableSmall[97 + s]] = (byte)i;
285 _tableSmall[97 + s]++;
286 }
287 }
288 s += 128;
289 }
290 }
291 }
292 }
293
makeTables47(int width)294 void Blocky8::makeTables47(int width) {
295 if (_lastTableWidth == width)
296 return;
297
298 _lastTableWidth = width;
299
300 int32 a, c, d;
301 int16 tmp;
302
303 for (int l = 0; l < 512; l += 2) {
304 _table[l / 2] = (int16)(blocky8_table[l + 1] * width + blocky8_table[l]);
305 }
306
307 a = 0;
308 c = 0;
309 do {
310 for (d = 0; d < _tableSmall[96 + c]; d++) {
311 tmp = _tableSmall[64 + c + d];
312 tmp = (int16)((byte)(tmp >> 2) * width + (tmp & 3));
313 _tableSmall[c + d * 2] = (byte)tmp;
314 _tableSmall[c + d * 2 + 1] = tmp >> 8;
315 }
316 for (d = 0; d < _tableSmall[97 + c]; d++) {
317 tmp = _tableSmall[80 + c + d];
318 tmp = (int16)((byte)(tmp >> 2) * width + (tmp & 3));
319 _tableSmall[32 + c + d * 2] = (byte)tmp;
320 _tableSmall[32 + c + d * 2 + 1] = tmp >> 8;
321 }
322 for (d = 0; d < _tableBig[384 + a]; d++) {
323 tmp = _tableBig[256 + a + d];
324 tmp = (int16)((byte)(tmp >> 3) * width + (tmp & 7));
325 _tableBig[a + d * 2] = (byte)tmp;
326 _tableBig[a + d * 2 + 1] = tmp >> 8;
327 }
328 for (d = 0; d < _tableBig[385 + a]; d++) {
329 tmp = _tableBig[320 + a + d];
330 tmp = (int16)((byte)(tmp >> 3) * width + (tmp & 7));
331 _tableBig[128 + a + d * 2] = (byte)tmp;
332 _tableBig[128 + a + d * 2 + 1] = tmp >> 8;
333 }
334
335 a += 388;
336 c += 128;
337 } while (c < 32768);
338 }
339
340 #ifdef USE_ARM_SMUSH_ASM
341
342 extern "C" {
343 #ifndef IPHONE
344 #define ARM_Blocky8_decode2 _ARM_Blocky8_decode2
345 #endif
346 }
347
348 extern "C" void ARM_Blocky8_decode2( byte *dst,
349 const byte *src,
350 int width,
351 int height,
352 const byte *param_ptr,
353 int16 *_table,
354 byte *_tableBig,
355 int32 offset1,
356 int32 offset2,
357 byte *_tableSmall);
358
359 #define decode2(SRC,DST,WIDTH,HEIGHT,PARAM) \
360 ARM_Blocky8_decode2(SRC,DST,WIDTH,HEIGHT,PARAM,_table,_tableBig, \
361 _offset1,_offset2,_tableSmall)
362
363 #else
level3(byte * d_dst)364 void Blocky8::level3(byte *d_dst) {
365 int32 tmp;
366 byte code = *_d_src++;
367
368 if (code < 0xF8) {
369 tmp = _table[code] + _offset1;
370 COPY_2X1_LINE(d_dst, d_dst + tmp);
371 COPY_2X1_LINE(d_dst + _d_pitch, d_dst + _d_pitch + tmp);
372 } else if (code == 0xFF) {
373 COPY_2X1_LINE(d_dst, _d_src + 0);
374 COPY_2X1_LINE(d_dst + _d_pitch, _d_src + 2);
375 _d_src += 4;
376 } else if (code == 0xFE) {
377 byte t = *_d_src++;
378 FILL_2X1_LINE(d_dst, t);
379 FILL_2X1_LINE(d_dst + _d_pitch, t);
380 } else if (code == 0xFC) {
381 tmp = _offset2;
382 COPY_2X1_LINE(d_dst, d_dst + tmp);
383 COPY_2X1_LINE(d_dst + _d_pitch, d_dst + _d_pitch + tmp);
384 } else {
385 byte t = _paramPtr[code];
386 FILL_2X1_LINE(d_dst, t);
387 FILL_2X1_LINE(d_dst + _d_pitch, t);
388 }
389 }
390
level2(byte * d_dst)391 void Blocky8::level2(byte *d_dst) {
392 int32 tmp;
393 byte code = *_d_src++;
394 int i;
395
396 if (code < 0xF8) {
397 tmp = _table[code] + _offset1;
398 for (i = 0; i < 4; i++) {
399 COPY_4X1_LINE(d_dst, d_dst + tmp);
400 d_dst += _d_pitch;
401 }
402 } else if (code == 0xFF) {
403 level3(d_dst);
404 d_dst += 2;
405 level3(d_dst);
406 d_dst += _d_pitch * 2 - 2;
407 level3(d_dst);
408 d_dst += 2;
409 level3(d_dst);
410 } else if (code == 0xFE) {
411 byte t = *_d_src++;
412 for (i = 0; i < 4; i++) {
413 FILL_4X1_LINE(d_dst, t);
414 d_dst += _d_pitch;
415 }
416 } else if (code == 0xFD) {
417 byte *tmp_ptr = _tableSmall + *_d_src++ * 128;
418 int32 l = tmp_ptr[96];
419 byte val = *_d_src++;
420 int16 *tmp_ptr2 = (int16 *)tmp_ptr;
421 while (l--) {
422 *(d_dst + READ_LE_UINT16(tmp_ptr2)) = val;
423 tmp_ptr2++;
424 }
425 l = tmp_ptr[97];
426 val = *_d_src++;
427 tmp_ptr2 = (int16 *)(tmp_ptr + 32);
428 while (l--) {
429 *(d_dst + READ_LE_UINT16(tmp_ptr2)) = val;
430 tmp_ptr2++;
431 }
432 } else if (code == 0xFC) {
433 tmp = _offset2;
434 for (i = 0; i < 4; i++) {
435 COPY_4X1_LINE(d_dst, d_dst + tmp);
436 d_dst += _d_pitch;
437 }
438 } else {
439 byte t = _paramPtr[code];
440 for (i = 0; i < 4; i++) {
441 FILL_4X1_LINE(d_dst, t);
442 d_dst += _d_pitch;
443 }
444 }
445 }
446
level1(byte * d_dst)447 void Blocky8::level1(byte *d_dst) {
448 int32 tmp, tmp2;
449 byte code = *_d_src++;
450 int i;
451
452 if (code < 0xF8) {
453 tmp2 = _table[code] + _offset1;
454 for (i = 0; i < 8; i++) {
455 COPY_4X1_LINE(d_dst + 0, d_dst + tmp2);
456 COPY_4X1_LINE(d_dst + 4, d_dst + tmp2 + 4);
457 d_dst += _d_pitch;
458 }
459 } else if (code == 0xFF) {
460 level2(d_dst);
461 d_dst += 4;
462 level2(d_dst);
463 d_dst += _d_pitch * 4 - 4;
464 level2(d_dst);
465 d_dst += 4;
466 level2(d_dst);
467 } else if (code == 0xFE) {
468 byte t = *_d_src++;
469 for (i = 0; i < 8; i++) {
470 FILL_4X1_LINE(d_dst, t);
471 FILL_4X1_LINE(d_dst + 4, t);
472 d_dst += _d_pitch;
473 }
474 } else if (code == 0xFD) {
475 tmp = *_d_src++;
476 byte *tmp_ptr = _tableBig + tmp * 388;
477 byte l = tmp_ptr[384];
478 byte val = *_d_src++;
479 int16 *tmp_ptr2 = (int16 *)tmp_ptr;
480 while (l--) {
481 *(d_dst + READ_LE_UINT16(tmp_ptr2)) = val;
482 tmp_ptr2++;
483 }
484 l = tmp_ptr[385];
485 val = *_d_src++;
486 tmp_ptr2 = (int16 *)(tmp_ptr + 128);
487 while (l--) {
488 *(d_dst + READ_LE_UINT16(tmp_ptr2)) = val;
489 tmp_ptr2++;
490 }
491 } else if (code == 0xFC) {
492 tmp2 = _offset2;
493 for (i = 0; i < 8; i++) {
494 COPY_4X1_LINE(d_dst + 0, d_dst + tmp2);
495 COPY_4X1_LINE(d_dst + 4, d_dst + tmp2 + 4);
496 d_dst += _d_pitch;
497 }
498 } else {
499 byte t = _paramPtr[code];
500 for (i = 0; i < 8; i++) {
501 FILL_4X1_LINE(d_dst, t);
502 FILL_4X1_LINE(d_dst + 4, t);
503 d_dst += _d_pitch;
504 }
505 }
506 }
507
decode2(byte * dst,const byte * src,int width,int height,const byte * param_ptr)508 void Blocky8::decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr) {
509 _d_src = src;
510 _paramPtr = param_ptr - 0xf8;
511 int bw = (width + 7) / 8;
512 int bh = (height + 7) / 8;
513 int next_line = width * 7;
514 _d_pitch = width;
515
516 do {
517 int tmp_bw = bw;
518 do {
519 level1(dst);
520 dst += 8;
521 } while (--tmp_bw);
522 dst += next_line;
523 } while (--bh);
524 }
525 #endif
526
bompDecodeLine(byte * dst,const byte * src,int len)527 static void bompDecodeLine(byte *dst, const byte *src, int len) {
528 assert(len > 0);
529
530 int num;
531 byte code, color;
532
533 while (len > 0) {
534 code = *src++;
535 num = (code >> 1) + 1;
536 if (num > len)
537 num = len;
538 len -= num;
539 if (code & 1) {
540 color = *src++;
541 memset(dst, color, num);
542 } else {
543 memcpy(dst, src, num);
544 src += num;
545 }
546 dst += num;
547 }
548 }
549
Blocky8()550 Blocky8::Blocky8() {
551 _tableBig = new byte[99328];
552 _tableSmall = new byte[32768];
553 memset(_tableBig, 0, 99328);
554 memset(_tableSmall, 0, 32768);
555 _deltaBuf = nullptr;
556 _width = -1;
557 _height = -1;
558 _frameSize = 0;
559 _offset1 = 0;
560 _offset2 = 0;
561 _prevSeqNb = 0;
562 _lastTableWidth = 0;
563 _deltaBufs[0] = nullptr;
564 _deltaBufs[1] = nullptr;
565 _curBuf = nullptr;
566 _d_pitch = 0;
567 _d_src = nullptr;
568 _paramPtr = nullptr;
569 }
570
init(int width,int height)571 void Blocky8::init(int width, int height) {
572 if (_width == width && _height == height)
573 return;
574 deinit();
575 _width = width;
576 _height = height;
577 makeTablesInterpolation(4);
578 makeTablesInterpolation(8);
579
580 _frameSize = _width * _height;
581 uint32 deltaSize = _frameSize * 3;
582 _deltaBuf = new byte[deltaSize];
583 memset(_deltaBuf, 0, deltaSize);
584 _deltaBufs[0] = _deltaBuf;
585 _deltaBufs[1] = _deltaBuf + _frameSize;
586 _curBuf = _deltaBuf + _frameSize * 2;
587 }
588
deinit()589 void Blocky8::deinit() {
590 _lastTableWidth = -1;
591 if (_deltaBuf) {
592 delete[] _deltaBuf;
593 _deltaBuf = nullptr;
594 _deltaBufs[0] = nullptr;
595 _deltaBufs[1] = nullptr;
596 }
597 }
598
~Blocky8()599 Blocky8::~Blocky8() {
600 deinit();
601 if (_tableBig) {
602 delete[] _tableBig;
603 _tableBig = nullptr;
604 }
605 if (_tableSmall) {
606 delete[] _tableSmall;
607 _tableSmall = nullptr;
608 }
609 }
610
decode(byte * dst,const byte * src)611 bool Blocky8::decode(byte *dst, const byte *src) {
612 if ((_tableBig == nullptr) || (_tableSmall == nullptr) || (_deltaBuf == nullptr))
613 return false;
614
615 _offset1 = _deltaBufs[1] - _curBuf;
616 _offset2 = _deltaBufs[0] - _curBuf;
617
618 int32 seq_nb = READ_LE_UINT16(src + 0);
619
620 const byte *gfx_data = src + 26;
621
622 if (seq_nb == 0) {
623 makeTables47(_width);
624 memset(_deltaBufs[0], src[12], _frameSize);
625 memset(_deltaBufs[1], src[13], _frameSize);
626 _prevSeqNb = -1;
627 }
628
629 if ((src[4] & 1) != 0) {
630 gfx_data += 32896;
631 }
632
633 switch (src[2]) {
634 case 0:
635 memcpy(_curBuf, gfx_data, _frameSize);
636 break;
637 case 1:
638 // Used by Outlaws, but not by any SCUMM game.
639 error("blocky8: not implemented decode1 proc");
640 break;
641 case 2:
642 if (seq_nb == _prevSeqNb + 1) {
643 decode2(_curBuf, gfx_data, _width, _height, src + 8);
644 }
645 break;
646 case 3:
647 memcpy(_curBuf, _deltaBufs[1], _frameSize);
648 break;
649 case 4:
650 memcpy(_curBuf, _deltaBufs[0], _frameSize);
651 break;
652 case 5:
653 bompDecodeLine(_curBuf, gfx_data, READ_LE_UINT32(src + 14));
654 break;
655 }
656
657 memcpy(dst, _curBuf, _frameSize);
658
659 if (seq_nb == _prevSeqNb + 1) {
660 if (src[3] == 1) {
661 SWAP(_curBuf, _deltaBufs[1]);
662 } else if (src[3] == 2) {
663 SWAP(_deltaBufs[0], _deltaBufs[1]);
664 SWAP(_deltaBufs[1], _curBuf);
665 }
666 }
667 _prevSeqNb = seq_nb;
668
669 return true;
670 }
671
672 } // End of namespace Grim
673