1 /**
2 * @file movie.c
3 * @brief play start and congratulations animations files
4 * ("movie_congratulation.gca" and "movie_introduction.gca")
5 * @date 2012-08-26
6 * @author Etienne Sobole
7 */
8 /*
9 * copyright (c) 1998-2015 TLK Games all rights reserved
10 * $Id: movie.c,v 1.17 2012/08/26 17:09:14 gurumeditation Exp $
11 *
12 * Powermanga is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * Powermanga is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 * MA 02110-1301, USA.
26 */
27 #include "config.h"
28 #include "powermanga.h"
29 #include "tools.h"
30 #include "assembler.h"
31 #include "tools.h"
32 #include "config_file.h"
33 #include "display.h"
34 #include "log_recorder.h"
35 #include "movie.h"
36
37 /** Wich movie si played: 1=intro or 2=congratulation */
38 Uint32 movie_playing_switch = MOVIE_INTRODUCTION;
39 /** Pointer to the buffer for the current animation movie */
40 unsigned char *movie_buffer = NULL;
41 static unsigned char *image2 = NULL;
42 static unsigned char *icmpr = NULL;
43 static unsigned char *smage1 = NULL;
44 static unsigned char *smage2 = NULL;
45 static unsigned char *scmpr = NULL;
46 /** Pointer to the filedata of the movie in memory */
47 static unsigned char *movie_filedata = NULL;
48 /* pointer to the colormap in the file */
49 static Sint32 movie_counter = 0;
50 static Sint32 images = 0;
51
52 static bool movie_initialize (const char *filename);
53 static bool movie_load (const char *filename);
54 static bool movie_play (void);
55 static unsigned char *decompress (unsigned char *, unsigned char *,
56 unsigned char *);
57
58 /**
59 * Play movie animation compressed
60 * @return TRUE if it completed successfully or 0 otherwise
61 */
62 bool
movie_player(void)63 movie_player (void)
64 {
65 const char *filename;
66 switch (movie_playing_switch)
67 {
68 /* introduction movie */
69 case MOVIE_INTRODUCTION:
70 filename = "graphics/movie_introduction.gca";
71 if (movie_initialize (filename))
72 {
73 movie_playing_switch = MOVIE_PLAYED_CURRENTLY;
74 }
75 else
76 {
77 movie_playing_switch = MOVIE_NOT_PLAYED;
78 LOG_ERR ("movie_initialize(\"%s\") failed", filename);
79 return FALSE;
80 }
81 break;
82 /* congratulation movie */
83 case MOVIE_CONGRATULATIONS:
84 filename = "graphics/movie_congratulation.gca";
85 if (movie_initialize (filename))
86 {
87 movie_playing_switch = MOVIE_PLAYED_CURRENTLY;
88 }
89 else
90 {
91 movie_playing_switch = MOVIE_NOT_PLAYED;
92 LOG_ERR ("movie_initialize(\"%s\") failed", filename);
93 return FALSE;
94 }
95 break;
96 /* play movie animation compressed */
97 case MOVIE_PLAYED_CURRENTLY:
98 {
99 if (!movie_play () || key_code_down > 0 || fire_button_down
100 || mouse_b > 1)
101 {
102 movie_free ();
103 movie_playing_switch = MOVIE_NOT_PLAYED;
104 }
105 }
106 break;
107 }
108 return TRUE;
109 }
110
111 /**
112 * Initialize an animation file, allocate buffers and create offscreen
113 * @param filename: the file which should be loaded.
114 * @return boolean value on success or failure
115 */
116 static bool
movie_initialize(const char * filename)117 movie_initialize (const char *filename)
118 {
119 Sint32 i = 0;
120 smage1 = smage2 = scmpr = NULL;
121 smage1 = ((unsigned char *) memory_allocation (64000));
122 if (smage1 == NULL)
123 {
124 LOG_ERR ("not enough memory to allocate 'smage1'");
125 return FALSE;
126 }
127 smage2 = ((unsigned char *) memory_allocation (64000));
128 if (smage1 == NULL)
129 {
130 LOG_ERR ("not enough memory to allocate 'smage2'");
131 return FALSE;
132 }
133 movie_filedata = ((unsigned char *) memory_allocation ((1024 * 1024 * 4)));
134 if (movie_filedata == NULL)
135 {
136 LOG_ERR ("not enough memory to allocate 'movie_filedata'");
137 return FALSE;
138 }
139 for (i = 0; i < 64000; i++)
140 {
141 smage1[i] = 0;
142 smage2[i] = 0;
143 }
144 if (!movie_load (filename))
145 {
146 LOG_ERR ("movie_load(%s) failed!", filename);
147 return FALSE;
148 }
149 movie_buffer = smage1;
150 image2 = smage2;
151 icmpr = scmpr;
152 movie_counter = 0;
153 if (!create_movie_offscreen ())
154 {
155 LOG_ERR ("create_movie_buffer() failed!");
156 return FALSE;
157 }
158 return TRUE;
159 }
160
161 /**
162 * Deallocates the memory used by the movie player
163 */
164 void
movie_free(void)165 movie_free (void)
166 {
167 if (smage1 != NULL)
168 {
169 free_memory ((char *) smage1);
170 smage1 = NULL;
171 }
172 if (smage2 != NULL)
173 {
174 free_memory ((char *) smage2);
175 smage2 = NULL;
176 }
177 if (movie_filedata != NULL)
178 {
179 free_memory ((char *) movie_filedata);
180 movie_filedata = NULL;
181 }
182 if (pal16PlayAnim != NULL)
183 {
184 free_memory ((char *) pal16PlayAnim);
185 pal16PlayAnim = NULL;
186 }
187 if (pal32PlayAnim != NULL)
188 {
189 free_memory ((char *) pal32PlayAnim);
190 pal32PlayAnim = NULL;
191 }
192 destroy_movie_offscreen ();
193 }
194
195 /**
196 * Load an animation file and convert colors palette
197 * @param filename: the file which should be loaded.
198 * @return boolean value on success or failure
199 */
200 static bool
movie_load(const char * filename)201 movie_load (const char *filename)
202 {
203 Sint32 i, *ptr32;
204 unsigned char *_p8, *_p, *_pPal, *pcxpal;
205 if (!loadfile_into_buffer (filename, (char *) movie_filedata))
206 {
207 return FALSE;
208 }
209 ptr32 = (Sint32 *) movie_filedata;
210 images = little_endian_to_int (ptr32++);
211 _p8 = (unsigned char *) ptr32;
212 pcxpal = _p8;
213 scmpr = _p8 + 768;
214 if (bytes_per_pixel == 2)
215 {
216 if (pal16PlayAnim == NULL)
217 {
218 pal16PlayAnim = (Uint16 *) memory_allocation (256 * 2);
219 if (pal16PlayAnim == NULL)
220 {
221 LOG_ERR ("not enough memory to allocate 'pal16PlayAnim'");
222 return FALSE;
223 }
224 }
225 convert_palette_24_to_16 (pcxpal, pal16PlayAnim);
226 }
227 if (bytes_per_pixel > 2)
228 {
229 if (pal32PlayAnim == NULL)
230 {
231 pal32PlayAnim = (Uint32 *) memory_allocation (256 * 4);
232 if (pal32PlayAnim == NULL)
233 {
234 LOG_ERR ("not enough memory to allocate 'pal32PlayAnim'");
235 return FALSE;
236 }
237 }
238 _p = (unsigned char *) pal32PlayAnim;
239 _pPal = pcxpal;
240 for (i = 0; i < 256; i++)
241 {
242 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
243 _p[3] = _pPal[2];
244 _p[2] = _pPal[1];
245 _p[1] = _pPal[0];
246 _p[0] = 0;
247 #else
248 if (power_conf->scale_x >= 2)
249 {
250 _p[0] = _pPal[2];
251 _p[1] = _pPal[1];
252 _p[2] = _pPal[0];
253 _p[3] = 0;
254 }
255 else
256 {
257 _p[2] = _pPal[2];
258 _p[1] = _pPal[1];
259 _p[0] = _pPal[0];
260 _p[3] = 0;
261 }
262 #endif
263 _p += 4;
264 _pPal += 3;
265 }
266 }
267 return TRUE;
268 }
269
270 /*
271 * Play a movie
272 * @return TRUE if the movie is finished
273 */
274 static bool
movie_play(void)275 movie_play (void)
276 {
277 /* images = 64 + 16 + 2 + 1 + 1 */
278 unsigned char *tmp;
279 movie_counter++;
280 if (movie_counter == images - 1)
281 {
282 return FALSE;
283 }
284 icmpr = decompress (icmpr, movie_buffer, image2);
285 tmp = movie_buffer;
286 movie_buffer = image2;
287 image2 = tmp;
288 return TRUE;
289 }
290
291 /*
292 *
293 */
294 static unsigned char *
decompress(unsigned char * wsc,unsigned char * im1,unsigned char * im2)295 decompress (unsigned char *wsc, unsigned char *im1, unsigned char *im2)
296 {
297 Sint32 i, j, mode;
298 Uint32 wr;
299 unsigned char *idec;
300 unsigned char *wdec;
301 unsigned char c;
302 unsigned char color;
303 Sint32 length = 0;
304 Sint32 retour = 0;
305 Sint32 position = 0;
306 i = 0;
307 idec = im2;
308 while (i < 64000)
309 {
310 mode = 0;
311 /* read a byte */
312 c = *wsc++;
313 if (c == 255)
314 {
315 color = *wsc++;
316 *idec++ = color;
317 i++;
318 mode = 0;
319 }
320 else if ((c & 0xc0) == 0)
321 {
322 wr = 0;
323 wr = c << 16;
324 wr += (*wsc++) << 8;
325 wr += *wsc++;
326 length = wr & 63;
327 position = (wr >> 6) & 65535;
328 mode = 1;
329 }
330 else if ((c & 0xc0) == 0x40)
331 {
332 wr = 0;
333 wr = c << 24;
334 wr += (*wsc++) << 16;
335 wr += (*wsc++) << 8;
336 wr += *wsc++;
337 length = wr & 16383;
338 position = (wr >> 14) & 65535;
339 mode = 1;
340 }
341 else if ((c & 0xe0) == 0x80)
342 {
343 wr = 0;
344 wr = c << 8;
345 wr += *wsc++;
346 length = wr & 63;
347 retour = (wr >> 6) & 255;
348 mode = 2;
349 }
350 else if ((c & 0xe0) == 0xa0)
351 {
352 wr = 0;
353 wr = c << 16;
354 wr += (*wsc++) << 8;
355 wr += *wsc++;
356 length = wr & 255;
357 retour = (wr >> 8) & 8191;
358 mode = 2;
359 }
360 else if ((c & 0xe0) == 0xc0)
361 {
362 wr = 0;
363 wr = c << 24;
364 wr += (*wsc++) << 16;
365 wr += (*wsc++) << 8;
366 wr += *wsc++;
367 length = wr & 8191;
368 position = (wr >> 13) & 65535;
369 mode = 3;
370 }
371 if (i + length > 64000)
372 {
373 length = 64000 - i;
374 }
375 if (mode == 1)
376 {
377 for (j = 0; j < length; j++)
378 {
379 *idec++ = im1[position + j];
380 }
381 i += length;
382 }
383 else if (mode == 2)
384 {
385 wdec = idec - retour;
386 for (j = 0; j < length; j++)
387 {
388 *idec++ = *wdec++;
389 }
390 i += length;
391 }
392 else if (mode == 3)
393 {
394 for (j = 0; j < length; j++)
395 {
396 *idec++ = im2[position + j];
397 }
398 i += length;
399 }
400 }
401 return wsc;
402 }
403