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