1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Source: r:/prj/cit/src/RCS/vmail.c $
21  * $Revision: 1.31 $
22  * $Author: xemu $
23  * $Date: 1994/11/01 09:17:43 $
24  *
25  */
26 
27 #include "Shock.h"
28 
29 // KLC #include <screen.h>
30 #include "game_screen.h"
31 #include "vmail.h"
32 #include "invent.h"
33 #include "mainloop.h"
34 #include "gameloop.h"
35 #include "tools.h"
36 #include "gametime.h"
37 #include "sfxlist.h"
38 #include "musicai.h"
39 #include "player.h"
40 #include "statics.h"
41 #include "fullscrn.h"
42 #include "render.h"
43 #include "gr2ss.h"
44 #include "criterr.h"
45 
46 #include "anim.h"
47 
48 //#include <mprintf.h>
49 //#define LOTS_O_SPEW
50 uchar vmail_wait_for_input = TRUE;
51 
52 //#define CONTINUOUS_VMAIL_TEST
53 
54 ActAnim *main_anim;
55 
56 #define NUM_VMAIL 6
57 #define INTRO_VMAIL (NUM_VMAIL+1)
58 
59 byte current_vmail = -1;
60 extern LGCursor vmail_cursor;
61 
62 extern void SDLDraw(void);
63 extern void pump_events(void);
64 
65 Ref vmail_frame_anim[NUM_VMAIL] = {
66    RES_FRAMES_shield,
67    RES_FRAMES_grove,
68    RES_FRAMES_bridge,
69    RES_FRAMES_laser1,
70    RES_FRAMES_status,
71    RES_FRAMES_explode1
72 };
73 
74 Ref vmail_res[NUM_VMAIL] = {
75    RES_shield,
76    RES_grove,
77    RES_bridge,
78    RES_laser1,
79    RES_status,
80    RES_explode1
81 };
82 
83 ubyte vmail_len[NUM_VMAIL] = {
84    1, // shield
85    1, // grove
86    1, // bridge
87    2, // laser
88    1, // status
89    5, // explode
90 };
91 
92 #define MAX_VMAIL_SIZE 100000
93 
94 // --------------------------------------------------------------------
95 //
96 //
97 
98 extern grs_canvas *anim_offscreen;
99 uchar copied_background = FALSE;
100 grs_bitmap *vmail_background = NULL;
101 extern uchar uiCheckInput(void);
102 
103 #pragma disable_message(202)
vmail_intro(LGRect * area,ubyte flags)104 void vmail_intro(LGRect *area, ubyte flags)
105 {
106    if (flags & BEFORE_ANIM_BITMAP)
107    {
108       if (vmail_background)
109          gr_bitmap(vmail_background, 0, 0);
110    }
111 }
112 #pragma enable_message(202)
113 
114 // --------------------------------------------------------------------
115 //
116 //
117 
118 #pragma disable_message(202)
vmail_anim_end(ActAnim * paa,AnimCode ancode,AnimCodeData * pdata)119 void vmail_anim_end(ActAnim *paa, AnimCode ancode, AnimCodeData *pdata)
120 {
121 #ifdef PLAYTEST
122    if (current_vmail == -1)
123    {
124       Warning(("Trying to end vmail, with no current vmail!\n"));
125    }
126 #endif
127    current_vmail = -1;
128 }
129 #pragma enable_message(202)
130 
131 // --------------------------------------------------------------------
132 //
133 //
134 
135 #pragma disable_message(202)
vmail_start_anim_end(ActAnim * paa,AnimCode ancode,AnimCodeData * pdata)136 void vmail_start_anim_end(ActAnim *paa, AnimCode ancode, AnimCodeData *pdata)
137 {
138 #ifdef PLAYTEST
139    if (current_vmail == -1)
140    {
141       Warning(("Trying to end vmail, with no current vmail!\n"));
142    }
143 #endif
144    current_vmail = -1;
145 }
146 #pragma enable_message(202)
147 
148 #define EARLY_EXIT ((errtype)200)
149 
150 // ---------------------------------------------
151 //
152 // play_vmail_intro()
153 //
154 
155 #define MOVIE_BUFFER_SIZE  (512 * 1024)
156 
play_vmail_intro(uchar use_texture_buffer)157 errtype play_vmail_intro(uchar use_texture_buffer)
158 {
159    LGPoint animloc = {VINTRO_X, VINTRO_Y};
160    uchar *p, *useBuffer;
161    int bsize;
162    short w,h;
163 
164    DEBUG("Playing vmail intro");
165 
166    main_anim = AnimPlayRegion(REF_ANIM_vintro, mainview_region, animloc, 0, vmail_intro);
167    if (main_anim == NULL)
168       return(ERR_NOEFFECT);
169 
170    if (use_texture_buffer)
171    {
172       AnimSetDataBufferSafe(main_anim, tmap_static_mem,sizeof(tmap_static_mem));
173       AnimPreloadFrames(main_anim, REF_ANIM_vintro);
174    }
175 
176    // let's slork up memory!!!!
177    w = VINTRO_W;
178    h = VINTRO_H;
179    {
180       useBuffer = frameBuffer;
181       bsize = sizeof(frameBuffer);
182    }
183    if ((w * h) + sizeof(grs_bitmap) > bsize)
184       critical_error(CRITERR_MEM|8);
185    p = useBuffer+bsize-(w*h);
186    vmail_background = (grs_bitmap *) (p - sizeof(grs_bitmap));
187 
188    gr_init_bm(vmail_background, p, BMT_FLAT8, 0, w,h);
189    uiHideMouse(NULL);
190 #ifdef SVGA_SUPPORT
191    if (convert_use_mode)
192    {
193       grs_canvas tempcanv;
194       gr_make_canvas(vmail_background,&tempcanv);
195       gr_push_canvas(&tempcanv);
196       gr_clear(1);
197       gr_pop_canvas();
198    }
199    else
200 #endif
201       gr_get_bitmap(vmail_background, VINTRO_X, VINTRO_Y);
202    uiShowMouse(NULL);
203 
204    AnimSetNotify(main_anim, NULL, ANCODE_KILL, vmail_start_anim_end);
205    current_vmail = INTRO_VMAIL;
206    play_digi_fx(SFX_VMAIL, 1);
207 
208 #ifdef LOTS_O_SPEW
209    mprintf("*PLAY INTRO*");
210 #endif
211    while (current_vmail != -1)
212    {
213       AnimRecur();
214       tight_loop(TRUE);
215    }
216 #ifdef LOTS_O_SPEW
217    mprintf("*DONE INTRO*");
218 #endif
219    vmail_background = NULL;
220 
221    return(OK);
222 }
223 
224 // --------------------------------------------------------------------
225 //
226 // play_vmail()
227 //
228 
229 #pragma disable_message(202)
play_vmail(byte vmail_no)230 errtype play_vmail(byte vmail_no)
231 {
232    LGPoint    animloc = {VINTRO_X, VINTRO_Y};
233    errtype  intro_error;
234    int      vmail_animfile_num = 0;
235    uchar     early_exit = FALSE;
236    uchar     preload_animation= TRUE;
237    uchar     use_texture_buffer = FALSE;
238    int      len = vmail_len[vmail_no];
239    int      i;
240    //MemStat  data;
241 
242    // let's extern
243 
244    DEBUG("Playing vmail %i", vmail_no);
245 
246    // the more I look at this procedure - the more I think
247    // art - what were you thinking
248    extern uiSlab fullscreen_slab;
249    extern uiSlab main_slab;
250    extern uchar game_paused;
251    extern uchar checking_mouse_button_emulation;
252    extern uchar citadel_check_input(void);
253    extern void email_page_exit(void);
254    extern short old_invent_page;
255 
256    // make sure we don't have a current vmail, and we're given a valid vmail num
257    if ((current_vmail != -1) || (vmail_no < 0) || (vmail_no >= NUM_VMAIL))
258       return(ERR_NOEFFECT);
259 
260    if (full_game_3d)
261       render_run();
262 
263    // spew the appropriate text for vmail - full screen needs a draw!
264    suspend_game_time();
265    time_passes = FALSE;
266    checking_mouse_button_emulation = game_paused = TRUE;
267 
268    // open the res file
269    vmail_animfile_num = ResOpenFile("res/data/vidmail.res");
270    if (vmail_animfile_num < 0)
271       return(ERR_FOPEN);
272 
273    uiPushSlabCursor(&fullscreen_slab, &vmail_cursor);
274    uiPushSlabCursor(&main_slab, &vmail_cursor);
275 
276    //MemStats(&data);
277    //use_texture_buffer = (data.free.sizeMax < MAX_VMAIL_SIZE);
278 
279 #ifdef LOTS_O_SPEW
280    mprintf("\nBUFFER:(%d)\n", use_texture_buffer);
281 #endif
282 
283    // if we're not using the texture buffer - then we can probably
284    // preload the animations
285    if (!use_texture_buffer)
286    {
287       uchar  cant_preload_all = FALSE;
288 
289       // load the intro in first! before checking for preloading
290       if (ResLock(RES_FRAMES_vintro) == NULL)
291          use_texture_buffer = TRUE;
292       else
293       {
294          for (i=0;i<len && !cant_preload_all;i++)
295          {
296             // check if we have enough memory to preload another segment
297             /*MemStats(&data);
298             if (data.free.sizeMax < MAX_VMAIL_SIZE)
299             {
300                cant_preload_all = TRUE;
301                break;
302             }*/
303 
304             // preload vmail frame animation first, and then play intro -> no pause between the two
305             // if it fails on the lock - then say you can't preload!
306             if(ResLock(vmail_frame_anim[vmail_no]+i) == NULL)
307             {
308                cant_preload_all = TRUE;
309                break;
310             }
311          }
312          // if we failed our preloading for whatever reason
313          // let's unlock it all - drop it so that it doesn't stay
314          // in memory
315          if (cant_preload_all)
316          {
317             int   j;
318             preload_animation = FALSE;
319             for (j=0; j<i;j++)
320             {
321                ResUnlock(vmail_frame_anim[vmail_no]+j);
322                ResDrop(vmail_frame_anim[vmail_no]+j);
323             }
324             ResUnlock(RES_FRAMES_vintro);
325             ResDrop(RES_FRAMES_vintro);
326             use_texture_buffer = TRUE;
327 #ifdef LOTS_O_SPEW
328             mprintf("**TRIED TO PRELOAD-CAN'T PRELOAD**\n");
329 #endif
330          }
331       }
332    }
333    else
334       preload_animation = FALSE;
335 
336 #ifdef LOTS_O_SPEW
337    mprintf("**PREL:(%d) INTRO:(%d)**", preload_animation, use_texture_buffer);
338 #endif
339    intro_error = play_vmail_intro(use_texture_buffer);
340    if (preload_animation)
341    {
342       ResUnlock(RES_FRAMES_vintro);
343       ResDrop(RES_FRAMES_vintro);
344    }
345 
346    if (intro_error != OK)     // did it have no effect - don't worry about texture buffer
347    {
348       // if we had a problem with the intro - then flush
349       // the animation all out - close it and
350       // then return error code
351       DEBUG("Could not play vmail intro");
352       if (preload_animation)
353          for (i=0;i<len;i++)
354          {
355             ResUnlock(vmail_frame_anim[vmail_no]+i);
356             ResDrop(vmail_frame_anim[vmail_no]+i);
357          }
358       ResCloseFile(vmail_animfile_num);
359       return(intro_error);
360    }
361 
362    for (i=0; (i<len) && !early_exit;i++)
363    {
364       DEBUG("Playing segment.");
365       Ref   vmail_ref = MKREF(vmail_res[vmail_no]+i,0);
366       main_anim = AnimPlayRegion(vmail_ref,mainview_region,animloc, 0, NULL);
367       if (main_anim == NULL)
368       {
369          early_exit = TRUE;
370          break;
371       }
372       if(use_texture_buffer)
373       {
374          AnimSetDataBufferSafe(main_anim, tmap_static_mem, sizeof(tmap_static_mem));
375          AnimPreloadFrames(main_anim, vmail_ref);
376       }
377       current_vmail = vmail_no;
378 
379       AnimSetNotify(main_anim, NULL, ANCODE_KILL, vmail_anim_end);
380       uiFlush();
381       while (current_vmail != -1)
382       {
383 #ifdef LOTS_O_SPEW
384 //         mprintf("R");
385 #endif
386          AnimRecur();
387 #ifdef LOTS_O_SPEW
388 //         mprintf("S");
389 #endif
390          if(citadel_check_input())
391          {
392             early_exit = TRUE;
393 #ifdef LOTS_O_SPEW
394             mprintf("Early Exit\n");
395 #endif
396             AnimKill(main_anim);
397          }
398          tight_loop(TRUE);
399       }
400    }
401 
402    DEBUG("Finished playing!");
403    if (preload_animation)
404    {
405       for (i=0;i<len;i++)
406       {
407          ResUnlock(vmail_frame_anim[vmail_no]+i);
408          ResDrop(vmail_frame_anim[vmail_no]+i);
409       }
410    }
411    ResCloseFile(vmail_animfile_num);
412 
413 #ifdef LOTS_O_SPEW
414       mprintf("T");
415 #endif
416    uiFlush();
417 #ifdef LOTS_O_SPEW
418       mprintf("U");
419 #endif
420 
421    if (use_texture_buffer)
422    {
423 #ifdef LOTS_O_SPEW
424       mprintf("V");
425 #endif
426       load_textures();
427 #ifdef LOTS_O_SPEW
428       mprintf("W");
429 #endif
430    }
431 
432 #ifndef CONTINUOUS_VMAIL_TEST
433    if (!early_exit && vmail_wait_for_input)
434       while (!citadel_check_input()) {
435          uiHideMouse(NULL); //trick to prevent
436          uiShowMouse(NULL); //  mouse pointer freeze
437          pump_events();
438          SDLDraw();
439          tight_loop(FALSE); //keep the music playing
440       }
441 #endif
442 
443    email_page_exit();
444 
445    screen_draw();
446    inventory_draw_new_page(old_invent_page);
447 
448    DEBUG("Resuming game time");
449    resume_game_time();
450    checking_mouse_button_emulation = game_paused = FALSE;
451 
452    // let the player wait before firing auto fire weapon
453    player_struct.auto_fire_click = player_struct.game_time + 60;
454    time_passes = TRUE;
455 
456 #ifdef LOTS_O_SPEW
457       mprintf("X");
458 #endif
459    uiPopSlabCursor(&fullscreen_slab);
460    uiPopSlabCursor(&main_slab);
461 #ifdef LOTS_O_SPEW
462       mprintf("Y");
463 #endif
464    chg_set_flg(DEMOVIEW_UPDATE);
465 
466    return(OK);
467 }
468 #pragma enable_message(202)
469 
470 byte test_vmail = 0;
471 #pragma disable_message(202)
shield_test_func(short keycode,ulong context,void * data)472 uchar shield_test_func(short keycode, ulong context, void* data)
473 {
474    int   i;
475    vmail_wait_for_input = FALSE;
476    for (i=0;i<5; i++)
477    {
478       play_vmail(test_vmail);
479       test_vmail = (test_vmail+1)%NUM_VMAIL;
480    }
481    vmail_wait_for_input = TRUE;
482    return(TRUE);
483 }
484 #pragma enable_message(202)
485 
486 #ifdef PLAYTEST
487 #pragma disable_message(202)
shield_off_func(short keycode,ulong context,void * data)488 uchar shield_off_func(short keycode, ulong context, void* data)
489 {
490    return(TRUE);
491 }
492 #pragma enable_message(202)
493 
494 #endif
495