1 /************************************************************************
2 * *
3 * FreeSynd - a remake of the classic Bullfrog game "Syndicate". *
4 * *
5 * Copyright (C) 2005 Stuart Binge <skbinge@gmail.com> *
6 * Copyright (C) 2005 Joost Peters <joostp@users.sourceforge.net> *
7 * Copyright (C) 2006 Trent Waddington <qg@biodome.org> *
8 * *
9 * This program is free software; you can redistribute it and / or *
10 * modify it under the terms of the GNU General Public License as *
11 * published by the Free Software Foundation; either version 2 of the *
12 * License, or (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
17 * General Public License for more details. *
18 * *
19 * You can view the GNU General Public License, online, at the GNU *
20 * project's web site; see <http://www.gnu.org/licenses/gpl.html>. *
21 * The full text of the license is also included in the file COPYING. *
22 * *
23 ************************************************************************/
24
25 #include <cstdio>
26
27 #include "fliplayer.h"
28 #include "screen.h"
29 #include "utils/log.h"
30 #include "menus/menumanager.h"
31
32 #if 0 // TMN: Data for playing samples during intro video. Hardcoded from intro.exe.
33
34 //#include <pshpack1.h>
35 struct sample_timings {
36 int16 m0;
37 uint8 m1, m2, m3, m4, m5, m6;
38 };
39 //#include <poppack.h>
40
41 const sample_timings g_rg_sample_offsets_and_timings[] = {
42 { 0, 0x4C, 0x12, 0x00, 0x00, 0x00 }, // read data from FLC (0x12 (18) bytes)
43 { 1, 0x4C, 0xB2, 0xF2, 0x08, 0x00 }, // read data from FLC (0x08f2b2 (586418) bytes)
44 { 1, 0x45, 0x00, 0x00, 0x00, 0x00 }, // load "data/isnds-0.dat"
45 { 1, 0x41, 0x01, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (1 = 10ms)
46 { 1, 0x53, 0x12, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x12
47 { 15, 0x54, 0x01, 0x00, 0x00, 0x00 }, // draw subtitle string, index
48 { 19, 0x41, 0x06, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (6 = 60ms)
49 { 19, 0x4D, 0x00, 0x00, 0x00, 0x00 }, // start new sequence (sequence # 0)
50 { 34, 0x53, 0x01, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x01
51 { 39, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
52 { 44, 0x54, 0x02, 0x00, 0x00, 0x00 }, // draw subtitle string, index
53 { 60, 0x53, 0x02, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x02
54 { 62, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
55 { 67, 0x54, 0x03, 0x00, 0x00, 0x00 }, // draw subtitle string, index
56 { 85, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
57 { 90, 0x54, 0x04, 0x00, 0x00, 0x00 }, // draw subtitle string, index
58 { 91, 0x41, 0x06, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (6 = 60ms)
59 { 117, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
60 { 119, 0x4C, 0xFA, 0xD6, 0x04, 0x00 }, // read data from FLC (0x04d6fa (317178) bytes)
61 { 119, 0x41, 0x06, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (6 = 60ms)
62 { 121, 0x54, 0x05, 0x00, 0x00, 0x00 }, // draw subtitle string, index
63 { 135, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
64 { 138, 0x54, 0x06, 0x00, 0x00, 0x00 }, // draw subtitle string, index
65 { 153, 0x54, 0x07, 0x00, 0x00, 0x00 }, // draw subtitle string, index
66 { 165, 0x54, 0x08, 0x00, 0x00, 0x00 }, // draw subtitle string, index
67 { 169, 0x53, 0x0B, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0B
68 { 178, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
69 { 180, 0x54, 0x09, 0x00, 0x00, 0x00 }, // draw subtitle string, index
70 { 190, 0x53, 0x0A, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0A
71 { 200, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
72 { 217, 0x4C, 0x16, 0x6E, 0x02, 0x00 }, // read data from FLC (0x026e16 (159254) bytes)
73 { 217, 0x41, 0x06, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (6 = 60ms)
74 { 218, 0x53, 0x03, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x03
75 { 231, 0x54, 0x0A, 0x00, 0x00, 0x00 }, // draw subtitle string, index
76 { 267, 0x4C, 0xC0, 0x52, 0x04, 0x00 }, // read data from FLC (0x0452c0 (283328) bytes)
77 { 267, 0x41, 0x0C, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (12 = 120ms)
78 { 268, 0x53, 0x0C, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0C
79 { 271, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
80 { 291, 0x54, 0x0B, 0x00, 0x00, 0x00 }, // draw subtitle string, index
81 { 305, 0x41, 0x06, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (6 = 60ms)
82 { 316, 0x4C, 0x84, 0x7C, 0x0A, 0x00 }, // read data from FLC (0x0a7c84 (687236) bytes)
83 { 317, 0x41, 0x0C, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (12 = 120ms)
84 { 318, 0x53, 0x0D, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0D
85 { 333, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
86 { 333, 0x53, 0x0D, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0D
87 { 343, 0x53, 0x0D, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0D
88 { 354, 0x53, 0x0D, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0D
89 { 359, 0x54, 0x0C, 0x00, 0x00, 0x00 }, // draw subtitle string, index
90 { 367, 0x41, 0x07, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (7 = 70ms)
91 { 406, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
92 { 414, 0x4C, 0x78, 0x2D, 0x02, 0x00 }, // read data from FLC (0x22d78 (142712) bytes)
93 { 415, 0x41, 0x06, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (6 = 60ms)
94 { 427, 0x53, 0x05, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x05
95 { 439, 0x4C, 0x0A, 0x29, 0x01, 0x00 }, // read data from FLC (0x01290a (76042) bytes)
96 { 439, 0x41, 0x78, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (120 = 1200ms)
97 { 440, 0x41, 0x0C, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (12 = 120ms)
98 { 442, 0x54, 0x0D, 0x00, 0x00, 0x00 }, // draw subtitle string, index
99 { 449, 0x53, 0x11, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x11
100 { 454, 0x53, 0x11, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x11
101 { 459, 0x53, 0x0F, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0F
102 { 467, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
103 { 470, 0x53, 0x10, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x10
104 { 472, 0x4C, 0x42, 0xE2, 0x07, 0x00 }, // read data from FLC (0x07e242 (516674) bytes)
105 { 473, 0x54, 0x0E, 0x00, 0x00, 0x00 }, // draw subtitle string, index
106 { 473, 0x41, 0x0A, 0x00, 0x00, 0x00 }, // wait 1/100 seconds
107 { 489, 0x53, 0x07, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x07
108 { 502, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
109 { 504, 0x41, 0x08, 0x00, 0x00, 0x00 }, // wait 1/100 seconds
110 { 520, 0x53, 0x08, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x08
111 { 528, 0x41, 0x0C, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (12 = 120ms)
112 { 532, 0x53, 0x09, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x09
113 { 541, 0x41, 0x08, 0x00, 0x00, 0x00 }, // wait 1/100 seconds
114 { 542, 0x53, 0x08, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x08
115 { 548, 0x54, 0x0F, 0x00, 0x00, 0x00 }, // draw subtitle string, index
116 { 548, 0x53, 0x07, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x07
117 { 562, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
118 { 565, 0x41, 0x0C, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (12 = 120ms)
119 { 568, 0x53, 0x06, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x06
120 { 569, 0x54, 0x10, 0x00, 0x00, 0x00 }, // draw subtitle string, index
121 { 577, 0x53, 0x07, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x07
122 { 580, 0x53, 0x04, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x04
123 { 583, 0x53, 0x07, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x07
124 { 589, 0x53, 0x04, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x04
125 { 592, 0x53, 0x07, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x07
126 { 602, 0x53, 0x04, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x04
127 { 606, 0x53, 0x07, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x07
128 { 610, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
129 { 617, 0x53, 0x04, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x04
130 { 620, 0x53, 0x07, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x07
131 { 627, 0x4C, 0xAC, 0x5D, 0x00, 0x00 }, // read data from FLC (0x5dac (23980) bytes)
132 { 628, 0x41, 0x28, 0x00, 0x00, 0x00 }, // wait 1/100 seconds
133 { 629, 0x53, 0x0E, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0E
134 { 635, 0x4C, 0x5C, 0x31, 0x01, 0x00 }, // read data from FLC (0x01315c (78172) bytes)
135 { 635, 0x41, 0x01, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (1 = 10ms)
136 { 636, 0x53, 0x00, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x00
137 { 637, 0x45, 0x01, 0x00, 0x00, 0x00 }, // load "data/isnds-1.dat"
138 { 638, 0x41, 0x06, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (6 = 60ms)
139 { 639, 0x54, 0x11, 0x00, 0x00, 0x00 }, // draw subtitle string, index
140 { 641, 0x53, 0x0B, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0B
141 { 646, 0x53, 0x07, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x07
142 { 654, 0x53, 0x05, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x05
143 { 662, 0x53, 0x06, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x06
144 { 673, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
145 { 674, 0x53, 0x04, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x04
146 { 679, 0x53, 0x08, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x08
147 { 691, 0x53, 0x09, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x09
148 { 704, 0x53, 0x0A, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0A
149 { 709, 0x53, 0x0C, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0C
150 { 719, 0x53, 0x0A, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0A
151 { 725, 0x53, 0x0A, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0A
152 { 727, 0x53, 0x0C, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0C
153 { 733, 0x53, 0x0A, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0A
154 { 738, 0x53, 0x0A, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0A
155 { 741, 0x53, 0x0C, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0C
156 { 744, 0x53, 0x0A, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0A
157 { 749, 0x53, 0x0A, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0A
158 { 755, 0x53, 0x0C, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0C
159 { 761, 0x53, 0x0D, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0D
160 { 786, 0x4C, 0xCE, 0x90, 0x04, 0x00 }, // read data from FLC (0x0490ce (299214) bytes)
161 { 787, 0x41, 0x06, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (6 = 60ms)
162 { 788, 0x53, 0x01, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x01
163 { 807, 0x53, 0x02, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x02
164 { 837, 0x4C, 0xF8, 0x03, 0x01, 0x00 }, // read data from FLC (0x0103f8 (66552) bytes)
165 { 848, 0x54, 0x12, 0x00, 0x00, 0x00 }, // draw subtitle string, index
166 { 869, 0x4C, 0x78, 0x92, 0x00, 0x00 }, // read data from FLC (0x9278 (37496) bytes)
167 { 870, 0x41, 0x0C, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (12 = 120ms)
168 { 871, 0x53, 0x03, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x03
169 { 892, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
170 { 902, 0x4C, 0x10, 0x17, 0x05, 0x00 }, // read data from FLC, 0x051710 (333584) bytes
171 { 903, 0x41, 0x0A, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (10 = 100ms)
172 { 903, 0x53, 0x0E, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0E
173 { 904, 0x54, 0x13, 0x00, 0x00, 0x00 }, // draw subtitle string, index
174 { 917, 0x53, 0x07, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x07
175 { 920, 0x41, 0x0B, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (11 = 110ms)
176 { 929, 0x58, 0x00, 0x00, 0x00, 0x00 }, // stop current sequence
177 { 931, 0x53, 0x0F, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x0F
178 { 935, 0x53, 0x10, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x10
179 { 938, 0x53, 0x10, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x10
180 { 941, 0x53, 0x10, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x10
181 { 944, 0x53, 0x10, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x10
182 { 947, 0x53, 0x10, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x10
183 { 950, 0x53, 0x10, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x10
184 { 953, 0x53, 0x10, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x10
185 { 956, 0x53, 0x10, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x10
186 { 959, 0x53, 0x10, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x10
187 { 960, 0x54, 0x00, 0x00, 0x00, 0x00 }, // clear subtitle string area
188 { 963, 0x53, 0x11, 0x00, 0x00, 0x00 }, // maybe play VOC index 0x11
189 { 997, 0x41, 0x78, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (120 = 1200ms)
190 { 998, 0x41, 0x78, 0x00, 0x00, 0x00 }, // wait 1/100 seconds (120 = 1200ms)
191 { -1, 0x00, 0x00, 0x00, 0x00, 0x00 }
192 };
193
194 #endif
195
~FliPlayer()196 FliPlayer::~FliPlayer() {
197 if (offscreen_) {
198 delete[] offscreen_;
199 offscreen_ = NULL;
200 }
201 }
202
loadFliData(uint8 * data)203 void FliPlayer::loadFliData(uint8 *data) {
204 fli_data_ = data;
205
206 fli_info_.size = READ_LE_UINT32(fli_data_);
207 fli_data_ += 4;
208 fli_info_.type = READ_LE_UINT16(fli_data_);
209 fli_data_ += 2;
210 fli_info_.numFrames = READ_LE_UINT16(fli_data_);
211 fli_data_ += 2;
212 fli_info_.width = READ_LE_UINT16(fli_data_);
213 fli_data_ += 2;
214 fli_info_.height = READ_LE_UINT16(fli_data_);
215 fli_data_ += 2;
216
217 if (fli_info_.type != 0xAF12) { //simple check to verify it is indeed a (Bullfrog) FLI
218 FSERR(Log::k_FLG_GFX, "FliPlayer", "loadFliData()", ("Attempted to load non-FLI data (type = 0x%04X)\n", fli_info_.type));
219 fli_info_.width = fli_info_.height = 100;
220 fli_info_.numFrames = 0;
221 return;
222 }
223
224 assert(fli_info_.width == 320 && fli_info_.height == 200);
225 if (offscreen_)
226 delete[] offscreen_;
227 offscreen_ = new uint8[fli_info_.width * fli_info_.height];
228
229 memset(palette_, 0, sizeof(palette_));
230 }
231
isValidChunk(uint16 type)232 bool FliPlayer::isValidChunk(uint16 type) {
233 //Even though it may be a valid chunk type, only return true if we know how to deal with it
234 switch (type) {
235 case 4: //COLOR_256
236 case 7: //DELTA_FLC (FLI_SS2)
237 case 15: //BYTE_RUN
238 case 0xF1FA: //FRAME_TYPE
239 return true;
240
241 default:
242 FSERR(Log::k_FLG_GFX, "FliPlayer", "isValidChunk()", ("ERROR: isValidChunk(0x%04X) is NOT a valid chunk\n", type));
243 return false;
244 }
245 }
246
readChunkHeader(uint8 * mem)247 ChunkHeader FliPlayer::readChunkHeader(uint8 * mem) {
248 ChunkHeader head;
249 head.size = READ_LE_UINT32(mem + 0);
250 head.type = READ_LE_UINT16(mem + 4);
251 return head;
252 }
253
readFrameTypeChunkHeader(ChunkHeader chunkHead,uint8 * & mem)254 FrameTypeChunkHeader FliPlayer::readFrameTypeChunkHeader(ChunkHeader chunkHead,
255 uint8 *&mem) {
256 FrameTypeChunkHeader head;
257
258 head.header = chunkHead;
259 mem += 6;
260 head.numChunks = READ_LE_UINT16(mem);
261 mem += 2;
262 head.delay = READ_LE_UINT16(mem);
263 mem += 2;
264 head.reserved = READ_LE_UINT16(mem);
265 mem += 2;
266 head.widthOverride = READ_LE_UINT16(mem);
267 mem += 2;
268 head.heightOverride = READ_LE_UINT16(mem);
269 mem += 2;
270
271 return head;
272 }
273
decodeByteRun(uint8 * data)274 void FliPlayer::decodeByteRun(uint8 *data) {
275 uint8 *ptr = (uint8 *) offscreen_;
276 while ((ptr - offscreen_) < (fli_info_.width * fli_info_.height)) {
277 uint8 chunks = *data++;
278 while (chunks--) {
279 int8 count = *data++;
280 if (count > 0) {
281 while (count--) {
282 *ptr++ = *data;
283 }
284 data++;
285 } else {
286 uint8 copyBytes = -count;
287 memcpy(ptr, data, copyBytes);
288 ptr += copyBytes;
289 data += copyBytes;
290 }
291 }
292 }
293 }
294
295 #define OP_PACKETCOUNT 0
296 #define OP_UNDEFINED 1
297 #define OP_LASTPIXEL 2
298 #define OP_LINESKIPCOUNT 3
299
decodeDeltaFLC(uint8 * data)300 void FliPlayer::decodeDeltaFLC(uint8 *data) {
301 uint16 linesInChunk = READ_LE_UINT16(data);
302 data += 2;
303 uint16 currentLine = 0;
304 uint16 packetCount = 0;
305
306 while (linesInChunk--) {
307 uint16 opcode;
308
309 // First process all the opcodes.
310 do {
311 opcode = READ_LE_UINT16(data);
312 data += 2;
313
314 switch ((opcode >> 14) & 3) {
315 case OP_PACKETCOUNT:
316 packetCount = opcode;
317 break;
318 case OP_UNDEFINED:
319 break;
320 case OP_LASTPIXEL:
321 *(uint8 *) (offscreen_ + (currentLine * fli_info_.width) +
322 (fli_info_.width - 1)) = (opcode & 0xFF);
323 break;
324 case OP_LINESKIPCOUNT:
325 currentLine += -(int16) opcode;
326 break;
327 }
328 } while (((opcode >> 14) & 3) != OP_PACKETCOUNT);
329
330 uint16 column = 0;
331
332 //Now interpret the RLE data
333 while (packetCount--) {
334 column += *data++;
335 int8 rleCount = (int8) * data++;
336
337 if (rleCount > 0) {
338 memcpy((void *) (offscreen_ +
339 (currentLine * fli_info_.width) + column),
340 data, rleCount * 2);
341 data += rleCount * 2;
342 column += rleCount * 2;
343 }
344 else if (rleCount < 0) {
345 uint16 dataWord = *(uint16 *) data;
346 data += 2;
347 for (int i = 0; i < -(int16) rleCount; ++i) {
348 *(uint16 *) (offscreen_ +
349 (currentLine * fli_info_.width) + column +
350 (i * 2)) = dataWord;
351 }
352
353 column += (-(int16) rleCount) * 2;
354 }
355 else { // End of cutscene ?
356 return;
357 }
358 }
359
360 currentLine++;
361 }
362 }
363
364
365 #define FRAME_TYPE 0xF1FA
366
decodeFrame()367 bool FliPlayer::decodeFrame() {
368 FrameTypeChunkHeader frameHeader;
369 ChunkHeader cHeader = readChunkHeader(fli_data_);
370 do {
371 switch (cHeader.type) {
372 case 4:
373 setPalette(fli_data_ + 6);
374 g_System.setPalette8b3(palette_);
375 break;
376 case 7:
377 decodeDeltaFLC(fli_data_ + 6);
378 break;
379 case 15:
380 decodeByteRun(fli_data_ + 6);
381 break;
382 case FRAME_TYPE:
383 frameHeader = readFrameTypeChunkHeader(cHeader, fli_data_);
384 fli_info_.numFrames--;
385 //printf("Frames Remaining: %d\n", fli_info_.numFrames);
386 break;
387 default:
388 break;
389 }
390
391 if (cHeader.type != FRAME_TYPE)
392 fli_data_ += cHeader.size;
393
394 cHeader = readChunkHeader(fli_data_);
395
396 } while (isValidChunk(cHeader.type) && cHeader.type != FRAME_TYPE);
397
398 return isValidChunk(cHeader.type);
399
400 }
401
setPalette(uint8 * mem)402 void FliPlayer::setPalette(uint8 *mem) {
403 uint16 numPackets = READ_LE_UINT16(mem);
404 mem += 2;
405
406 if (0 == READ_LE_UINT16(mem)) { //special case
407 mem += 2;
408 for (int i = 0; i < 256; ++i)
409 for (int j = 0; j < 3; ++j)
410 palette_[i * 3 + j] =
411 (mem[i * 3 + j] << 2) | (mem[i * 3 + j] & 3);
412 }
413 else {
414 uint8 palPos = 0;
415
416 while (numPackets--) {
417 palPos += *mem++;
418 uint8 change = *mem++;
419
420 for (int i = 0; i < change; ++i)
421 for (int j = 0; j < 3; ++j)
422 palette_[(palPos + i) * 3 + j] =
423 (mem[i * 3 + j] << 2) | (mem[i * 3 + j] & 3);
424
425 palPos += change;
426 mem += (change * 3);
427 }
428 }
429 }
430
copyCurrentFrameToScreen()431 void FliPlayer::copyCurrentFrameToScreen() {
432 g_Screen.scale2x(0, 0, fli_info_.width, fli_info_.height, offscreen(),
433 0, false);
434 }
435
play(bool intro,Font * pIntroFont)436 bool FliPlayer::play(bool intro, Font *pIntroFont) {
437 if (!fli_data_)
438 return false;
439
440 g_Screen.clear(0);
441 int cur_frame = 0;
442 while (hasFrames()) {
443 // Consumes events now so they won't be piled up after the animation
444 pManager_->handleEvents();
445
446 if (!decodeFrame())
447 break;
448 copyCurrentFrameToScreen();
449
450 cur_frame++;
451
452 g_System.updateScreen();
453 g_System.delay(1000 / (intro ? 10 : 15)); //fps
454 }
455
456 //clear the backscreen
457 //bzero(Screen::pixels(), GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT);
458
459 return true;
460 }
461