1 #include "cutsloop.h"
2 #include "mainloop.h"
3 #include "game_screen.h"
4 #include "gamescr.h"
5 #include "tools.h"
6 #include "faketime.h"
7 #include "setploop.h"
8 #include "hkeyfunc.h"
9 
10 #include "anim.h"
11 #include "statics.h"
12 
13 #include "MacTune.h"
14 #include "gr2ss.h"
15 
16 #include "afile.h"
17 #include "movie.h"
18 
19 #include <SDL.h>
20 
21 
22 
23 SDL_AudioStream *cutscene_audiostream = NULL;
24 
25 static uint8_t *cutscene_audiobuffer = NULL;
26 static uint8_t *cutscene_audiobuffer_pos = NULL;
27 static int cutscene_audiobuffer_size; //in blocks of MOVIE_DEFAULT_BLOCKLEN
28 
29 
30 
31 static int cutscene_filehandle;
32 
33 static uiSlab cutscene_slab;
34 static LGRegion cutscene_root_region;
35 
36 static Afile *amovie = NULL;
37 static Apalette cutscene_pal;
38 static grs_bitmap movie_bitmap;
39 static long next_time;
40 
41 static bool is_first_frame;
42 static bool done_playing_movie;
43 static long start_time;
44 static long next_draw_time;
45 
46 static char *cutscene_files[3] =
47 {
48   "res/data/svgaintr.res",
49   "res/data/svgadeth.res",
50   "res/data/svgaend.res"
51 };
52 
53 static Ref cutscene_anims[3] =
54 {
55   0xbd6,
56   0xbd7,
57   0xbd8
58 };
59 
60 
61 
62 extern uchar sfx_on;
63 extern char which_lang;
64 
65 extern bool UseCutscenePalette; //see Shock.c
66 
67 //filled in amov.c when chunk contains subtitle data
68 extern char EngSubtitle[256];
69 extern char FrnSubtitle[256];
70 extern char GerSubtitle[256];
71 
72 extern SDL_AudioDeviceID device;
73 
74 
75 extern void change_svga_screen_mode(void);
76 extern void CaptureMouse(bool capture);
77 
78 
79 
AudioStreamCallback(void * userdata,unsigned char * stream,int len)80 void AudioStreamCallback(void *userdata, unsigned char *stream, int len)
81 {
82   SDL_AudioStream *as = *(SDL_AudioStream **)userdata;
83 
84   if (as != NULL && SDL_AudioStreamAvailable(as) > 0)
85     SDL_AudioStreamGet(as, stream, len);
86 }
87 
88 
89 
cutscene_key_handler(uiEvent * ev,LGRegion * r,intptr_t user_data)90 uchar cutscene_key_handler(uiEvent *ev, LGRegion *r, intptr_t user_data)
91 {
92   uiCookedKeyData *kd = &ev->cooked_key_data;
93   int code = kd->code & ~(KB_FLAG_DOWN | KB_FLAG_2ND);
94 
95   if (kd->code & KB_FLAG_DOWN)
96   {
97     switch (code)
98     {
99       case KEY_ESC:
100       case KEY_ENTER:
101       case KEY_SPACE:
102         // Go back to the main menu
103         _new_mode = SETUP_LOOP;
104         chg_set_flg(GL_CHG_LOOP);
105       break;
106     }
107   }
108 
109   return TRUE;
110 }
111 
112 
113 
cutscene_mouse_handler(uiEvent * ev,LGRegion * r,intptr_t user_data)114 uchar cutscene_mouse_handler(uiEvent *ev, LGRegion *r, intptr_t user_data)
115 {
116     return TRUE;
117 }
118 
119 
120 
cutscene_start(void)121 void cutscene_start(void)
122 {
123   DEBUG("Cutscene start");
124 
125 #ifdef SVGA_SUPPORT
126   change_svga_screen_mode();
127 #endif
128 
129   generic_reg_init(TRUE, &cutscene_root_region, NULL, &cutscene_slab, cutscene_key_handler, cutscene_mouse_handler);
130 
131   _current_view = &cutscene_root_region;
132   uiSetCurrentSlab(&cutscene_slab);
133 
134   uiHideMouse(NULL);
135 
136   CaptureMouse(FALSE);
137 }
138 
139 
140 
cutscene_exit(void)141 void cutscene_exit(void)
142 {
143   DEBUG("Cutscene exit");
144 
145   if (cutscene_audiostream != NULL)
146   {
147     SDL_PauseAudioDevice(device, 1);
148     SDL_Delay(1);
149 
150     SDL_FreeAudioStream(cutscene_audiostream);
151     cutscene_audiostream = NULL;
152 
153     if (cutscene_audiobuffer)
154     {
155       free(cutscene_audiobuffer);
156       cutscene_audiobuffer = NULL;
157     }
158   }
159 
160   if (cutscene_filehandle > 0) {ResCloseFile(cutscene_filehandle); cutscene_filehandle = 0;}
161 
162   if (movie_bitmap.bits != NULL) {free(movie_bitmap.bits); movie_bitmap.bits = NULL;}
163 
164   if (amovie != NULL) {free(amovie); amovie = NULL;}
165 }
166 
167 
168 
cutscene_loop(void)169 void cutscene_loop(void)
170 {
171   fix time;
172   long cur_time = SDL_GetTicks();
173 
174   static uint8_t palette[3*256];
175 
176   if (cutscene_audiostream)
177   {
178     SDL_PauseAudioDevice(device, 0);
179 
180     if (cutscene_audiobuffer_size > 0)
181     {
182       // === adjust volume in buffer here ===
183 
184       SDL_AudioStreamPut(cutscene_audiostream, cutscene_audiobuffer_pos, MOVIE_DEFAULT_BLOCKLEN);
185       cutscene_audiobuffer_pos += MOVIE_DEFAULT_BLOCKLEN;
186       cutscene_audiobuffer_size--;
187     }
188   }
189 
190   if (is_first_frame)
191   {
192     is_first_frame = FALSE;
193     next_time = cur_time;
194     start_time = SDL_GetTicks();
195 
196     // Read the first frame
197     AfileReadFullFrame(amovie, &movie_bitmap, &time);
198     next_draw_time = start_time + fix_float(time) * 1000.0;
199 
200     // Set the initial palette
201     memcpy(palette, amovie->v.pal.rgb, 3*256);
202 
203     gr_clear(0x00);
204   }
205 
206   if (cur_time > next_draw_time)
207   {
208     // Get the palette for this frame, if any
209     if (AfileGetFramePal(amovie, &cutscene_pal))
210       memcpy(palette+3*cutscene_pal.index, cutscene_pal.rgb, 3*cutscene_pal.numcols);
211 
212     UseCutscenePalette = TRUE; //see Shock.c
213     gr_set_pal(0, 256, palette);
214     UseCutscenePalette = FALSE; //see Shock.c
215 
216     gr_set_fcolor(255);
217 
218     // Draw this frame
219     gr_clear(0x00);
220 
221     float vscale = (float)amovie->v.height / (float)amovie->v.width;
222 
223     int offset = (320 - (amovie->v.width / 2)) / 2;
224     ss_scale_bitmap(&movie_bitmap, offset, offset / 1.25, amovie->v.width / 2, amovie->v.height / 2);
225 
226     //draw subtitles
227 
228     char *buf = 0;
229     switch (which_lang)
230     {
231       case 0: default: buf = EngSubtitle; break;
232       case 1: buf = FrnSubtitle; break;
233       case 2: buf = GerSubtitle; break;
234     }
235 
236     if (buf && *buf)
237     {
238       short w, h, x, y;
239       grs_font *fon = gr_get_font();
240       gr_set_font((grs_font *)ResLock(RES_cutsceneFont));
241       gr_string_size(buf, &w, &h);
242       x = (320-w)/2;
243       y = 158+(200-158-h)/2;
244       ss_string(buf, x, y);
245       ResUnlock(RES_cutsceneFont);
246       gr_set_font(fon);
247     }
248 
249     if (done_playing_movie)
250     {
251       UseCutscenePalette = TRUE; //see Shock.c
252       extern void palfx_fade_down(void);
253       palfx_fade_down();
254       UseCutscenePalette = FALSE; //see Shock.c
255 
256       // Go back to the main menu
257       _new_mode = SETUP_LOOP;
258       chg_set_flg(GL_CHG_LOOP);
259       return;
260     }
261 
262     // Read the next frame
263     if (AfileReadFullFrame(amovie, &movie_bitmap, &time) == -1)
264     {
265       DEBUG("Done playing movie!");
266       done_playing_movie = TRUE;
267       // Still want a bit of a delay before finishing
268       next_draw_time += 5200;
269     }
270    	else next_draw_time = start_time + fix_float(time) * 1000.0;
271   }
272 }
273 
274 
275 
play_cutscene(int id,bool show_credits)276 short play_cutscene(int id, bool show_credits)
277 {
278   MacTuneKillCurrentTheme();
279 
280   cutscene_filehandle = ResOpenFile(cutscene_files[id]);
281   if (cutscene_filehandle <= 0) {
282       // If we failed to play the cutscene, go to setup / credits.
283       _new_mode = SETUP_LOOP;
284       chg_set_flg(GL_CHG_LOOP);
285       return 0;
286   }
287 
288   INFO("Playing Cutscene %i", id);
289 
290   *EngSubtitle = 0;
291   *FrnSubtitle = 0;
292   *GerSubtitle = 0;
293 
294   _new_mode = CUTSCENE_LOOP;
295   chg_set_flg(GL_CHG_LOOP);
296 
297   is_first_frame = TRUE;
298   done_playing_movie = FALSE;
299 
300   amovie = malloc(sizeof(Afile));
301   memset(amovie, 0, sizeof(Afile));
302 
303   if (AfilePrepareRes(cutscene_anims[id], amovie) < 0)
304   {
305     WARN("%s: Cannot open Afile by id $%x", __FUNCTION__, cutscene_anims[id]);
306     free(amovie);
307     amovie = NULL;
308     return ERR_FREAD;
309   }
310 
311   cutscene_audiobuffer_size = AfileAudioLength(amovie);
312   cutscene_audiobuffer = (uint8_t *)malloc(cutscene_audiobuffer_size * MOVIE_DEFAULT_BLOCKLEN);
313   AfileGetAudio(amovie, cutscene_audiobuffer);
314 
315   AfileReadReset(amovie);
316 
317   if (sfx_on)
318   {
319     SDL_PauseAudioDevice(device, 1);
320     SDL_Delay(1);
321 
322     cutscene_audiostream = SDL_NewAudioStream(AUDIO_U8, 1, fix_int(amovie->a.sampleRate), AUDIO_S16SYS, 2, 48000);
323 
324     cutscene_audiobuffer_pos = cutscene_audiobuffer;
325   }
326 
327   return 1;
328 }
329