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