55edfe522f53404d2ec665763905c333f7300ab4
[rocksndiamonds.git] / src / cartoons.c
1 // ============================================================================
2 // Rocks'n'Diamonds - McDuffin Strikes Back!
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
5 //                  Holger Schemel
6 //                  info@artsoft.org
7 //                  http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
9 // cartoons.c
10 // ============================================================================
11
12 #include "cartoons.h"
13 #include "main.h"
14 #include "tools.h"
15
16
17 /* values for global toon animation definition */
18 #define NUM_GLOBAL_TOON_ANIMS           1
19 #define NUM_GLOBAL_TOON_PARTS           MAX_NUM_TOONS
20
21 /* values for global animation definition (including toons) */
22 #define NUM_GLOBAL_ANIMS_AND_TOONS      (NUM_GLOBAL_ANIMS +             \
23                                          NUM_GLOBAL_TOON_ANIMS)
24 #define NUM_GLOBAL_ANIM_PARTS_AND_TOONS MAX(NUM_GLOBAL_ANIM_PARTS_ALL,  \
25                                             NUM_GLOBAL_TOON_PARTS)
26
27 struct GlobalAnimPartControlInfo
28 {
29   int nr;
30   int anim_nr;
31   int mode_nr;
32
33   int graphic;
34   struct GraphicInfo graphic_info;
35   struct GraphicInfo control_info;
36
37   int viewport_x;
38   int viewport_y;
39   int viewport_width;
40   int viewport_height;
41
42   int x, y;
43   int step_xoffset, step_yoffset;
44
45   unsigned int initial_anim_sync_frame;
46   unsigned int step_delay, step_delay_value;
47
48   int init_delay_counter;
49   int anim_delay_counter;
50   int post_delay_counter;
51
52   int state;
53   int last_game_status;
54 };
55
56 struct GlobalAnimMainControlInfo
57 {
58   struct GlobalAnimPartControlInfo base;
59   struct GlobalAnimPartControlInfo part[NUM_GLOBAL_ANIM_PARTS_AND_TOONS];
60
61   int nr;
62   int mode_nr;
63
64   struct GraphicInfo control_info;
65
66   int num_parts;
67   int part_counter;
68   int active_part_nr;
69
70   boolean has_base;
71
72   int init_delay_counter;
73
74   int state;
75 };
76
77 struct GlobalAnimControlInfo
78 {
79   struct GlobalAnimMainControlInfo anim[NUM_GLOBAL_ANIMS_AND_TOONS];
80
81   int nr;
82   int num_anims;
83 };
84
85
86 /* forward declaration for internal use */
87 static void DoAnimationExt(void);
88
89 static struct GlobalAnimControlInfo global_anim_ctrl[NUM_SPECIAL_GFX_ARGS];
90 static struct ToonInfo toons[MAX_NUM_TOONS];
91
92 static unsigned int anim_sync_frame = 0;
93 static unsigned int anim_sync_frame_delay = 0;
94 static unsigned int anim_sync_frame_delay_value = GAME_FRAME_DELAY;
95
96 static boolean do_animations = FALSE;
97
98
99 static int getGlobalAnimationPart(struct GlobalAnimMainControlInfo *anim)
100 {
101   struct GraphicInfo *c = &anim->control_info;
102   int last_anim_random_frame = gfx.anim_random_frame;
103   int part_nr;
104
105   gfx.anim_random_frame = -1;   // (use simple, ad-hoc random numbers)
106
107   part_nr = getAnimationFrame(anim->num_parts, 1,
108                               c->anim_mode, c->anim_start_frame,
109                               anim->part_counter);
110
111   gfx.anim_random_frame = last_anim_random_frame;
112
113   return part_nr;
114 }
115
116 static void PrepareBackbuffer()
117 {
118   if (game_status != GAME_MODE_PLAYING)
119     return;
120
121   BlitScreenToBitmap(backbuffer);
122 }
123
124 boolean ToonNeedsRedraw()
125 {
126   return TRUE;
127 }
128
129 void InitToons()
130 {
131   int num_toons = MAX_NUM_TOONS;
132   int i;
133
134   if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS)
135     num_toons = global.num_toons;
136
137   for (i = 0; i < num_toons; i++)
138   {
139     int graphic = IMG_TOON_1 + i;
140     struct FileInfo *image = getImageListEntryFromImageID(graphic);
141
142     toons[i].bitmap = graphic_info[graphic].bitmap;
143
144     toons[i].src_x = graphic_info[graphic].src_x;
145     toons[i].src_y = graphic_info[graphic].src_y;
146
147     toons[i].width  = graphic_info[graphic].width;
148     toons[i].height = graphic_info[graphic].height;
149
150     toons[i].anim_frames      = graphic_info[graphic].anim_frames;
151     toons[i].anim_delay       = graphic_info[graphic].anim_delay;
152     toons[i].anim_mode        = graphic_info[graphic].anim_mode;
153     toons[i].anim_start_frame = graphic_info[graphic].anim_start_frame;
154
155     toons[i].step_offset = graphic_info[graphic].step_offset;
156     toons[i].step_delay  = graphic_info[graphic].step_delay;
157
158     toons[i].direction = image->parameter[GFX_ARG_DIRECTION];
159     toons[i].position = image->parameter[GFX_ARG_POSITION];
160   }
161
162   InitToonScreen(bitmap_db_toons,
163                  BackToFront, PrepareBackbuffer, ToonNeedsRedraw,
164                  toons, num_toons,
165                  REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
166                  GAME_FRAME_DELAY);
167 }
168
169 static void InitToonControls()
170 {
171   struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[GAME_MODE_DEFAULT];
172   struct GlobalAnimMainControlInfo *anim = &ctrl->anim[ctrl->num_anims];
173   int mode_nr, anim_nr, part_nr;
174   int control = IMG_INTERNAL_GLOBAL_TOON_DEFAULT;
175   int num_toons = MAX_NUM_TOONS;
176   int i;
177
178   if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS)
179     num_toons = global.num_toons;
180
181   mode_nr = GAME_MODE_DEFAULT;
182   anim_nr = ctrl->num_anims;
183
184   anim->nr = anim_nr;
185   anim->mode_nr = mode_nr;
186   anim->control_info = graphic_info[control];
187
188   anim->num_parts = 0;
189   anim->part_counter = 0;
190   anim->active_part_nr = 0;
191
192   anim->has_base = FALSE;
193
194   anim->init_delay_counter = 0;
195
196   anim->state = ANIM_STATE_INACTIVE;
197
198   part_nr = 0;
199
200   for (i = 0; i < num_toons; i++)
201   {
202     struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
203     int graphic = IMG_TOON_1 + i;
204     int control = graphic;
205
206     part->nr = part_nr;
207     part->anim_nr = anim_nr;
208     part->mode_nr = mode_nr;
209     part->graphic = graphic;
210     part->graphic_info = graphic_info[graphic];
211     part->control_info = graphic_info[control];
212
213     part->graphic_info.anim_delay *= part->graphic_info.step_delay;
214
215     part->control_info.init_delay_fixed = 0;
216     part->control_info.init_delay_random = 150;
217
218     part->control_info.x = ARG_UNDEFINED_VALUE;
219     part->control_info.y = ARG_UNDEFINED_VALUE;
220
221     part->initial_anim_sync_frame = 0;
222
223     part->step_delay = 0;
224     part->step_delay_value = graphic_info[control].step_delay;
225
226     part->state = ANIM_STATE_INACTIVE;
227     part->last_game_status = -1;
228
229     anim->num_parts++;
230     part_nr++;
231   }
232
233   ctrl->num_anims++;
234 }
235
236 void InitGlobalAnimControls()
237 {
238   int m, a, p;
239   int mode_nr, anim_nr, part_nr;
240   int graphic, control;
241
242   anim_sync_frame = 0;
243
244   ResetDelayCounter(&anim_sync_frame_delay);
245
246   for (m = 0; m < NUM_SPECIAL_GFX_ARGS; m++)
247   {
248     mode_nr = m;
249
250     struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
251
252     ctrl->nr = mode_nr;
253     ctrl->num_anims = 0;
254
255     anim_nr = 0;
256
257     for (a = 0; a < NUM_GLOBAL_ANIMS; a++)
258     {
259       struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
260       int ctrl_id = GLOBAL_ANIM_ID_CONTROL_FIRST + a;
261
262       control = global_anim_info[ctrl_id].graphic[GLOBAL_ANIM_ID_PART_BASE][m];
263
264       // if no base animation parameters defined, use default values
265       if (control == IMG_UNDEFINED)
266         control = IMG_INTERNAL_GLOBAL_ANIM_DEFAULT;
267
268       anim->nr = anim_nr;
269       anim->mode_nr = mode_nr;
270       anim->control_info = graphic_info[control];
271
272       anim->num_parts = 0;
273       anim->part_counter = 0;
274       anim->active_part_nr = 0;
275
276       anim->has_base = FALSE;
277
278       anim->init_delay_counter = 0;
279
280       anim->state = ANIM_STATE_INACTIVE;
281
282       part_nr = 0;
283
284       for (p = 0; p < NUM_GLOBAL_ANIM_PARTS_ALL; p++)
285       {
286         struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
287
288         graphic = global_anim_info[a].graphic[p][m];
289         control = global_anim_info[ctrl_id].graphic[p][m];
290
291         if (graphic == IMG_UNDEFINED || graphic_info[graphic].bitmap == NULL ||
292             control == IMG_UNDEFINED)
293           continue;
294
295 #if 0
296         printf("::: mode == %d, anim = %d, part = %d [%d, %d, %d] [%d]\n",
297                m, a, p, mode_nr, anim_nr, part_nr, control);
298 #endif
299
300         part->nr = part_nr;
301         part->anim_nr = anim_nr;
302         part->mode_nr = mode_nr;
303         part->graphic = graphic;
304         part->graphic_info = graphic_info[graphic];
305         part->control_info = graphic_info[control];
306
307         part->initial_anim_sync_frame = 0;
308
309         part->step_delay = 0;
310         part->step_delay_value = graphic_info[control].step_delay;
311
312         part->state = ANIM_STATE_INACTIVE;
313         part->last_game_status = -1;
314
315         if (p < GLOBAL_ANIM_ID_PART_BASE)
316         {
317           anim->num_parts++;
318           part_nr++;
319         }
320         else
321         {
322           anim->base = *part;
323           anim->has_base = TRUE;
324         }
325       }
326
327       if (anim->num_parts > 0 || anim->has_base)
328       {
329         ctrl->num_anims++;
330         anim_nr++;
331       }
332     }
333   }
334
335   InitToonControls();
336 }
337
338 void DrawGlobalAnim()
339 {
340   int mode_nr;
341
342   if (game_status == GAME_MODE_LOADING)
343     do_animations = FALSE;
344
345   if (!do_animations || !setup.toons)
346     return;
347
348   DoAnimationExt();
349
350   for (mode_nr = 0; mode_nr < NUM_SPECIAL_GFX_ARGS; mode_nr++)
351   {
352     struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
353     int anim_nr;
354
355     if (mode_nr != GFX_SPECIAL_ARG_DEFAULT &&
356         mode_nr != game_status)
357       continue;
358
359     for (anim_nr = 0; anim_nr < ctrl->num_anims; anim_nr++)
360     {
361       struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
362       struct GraphicInfo *c = &anim->control_info;
363       int part_first, part_last;
364       int part_nr;
365
366       if (!(anim->state & ANIM_STATE_RUNNING))
367         continue;
368
369       part_first = part_last = anim->active_part_nr;
370
371       if (c->anim_mode & ANIM_ALL || anim->num_parts == 0)
372       {
373         int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
374
375         part_first = 0;
376         part_last = num_parts - 1;
377       }
378
379       for (part_nr = part_first; part_nr <= part_last; part_nr++)
380       {
381         struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
382         struct GraphicInfo *g = &part->graphic_info;
383         Bitmap *src_bitmap;
384         int src_x, src_y;
385         int width  = g->width;
386         int height = g->height;
387         int dst_x = part->x;
388         int dst_y = part->y;
389         int cut_x = 0;
390         int cut_y = 0;
391         int sync_frame;
392         int frame;
393
394         if (!(part->state & ANIM_STATE_RUNNING))
395           continue;
396
397         if (part->x < 0)
398         {
399           dst_x = 0;
400           width += part->x;
401           cut_x = -part->x;
402         }
403         else if (part->x > part->viewport_width - g->width)
404           width -= (part->x - (part->viewport_width - g->width));
405
406         if (part->y < 0)
407         {
408           dst_y = 0;
409           height += part->y;
410           cut_y = -part->y;
411         }
412         else if (part->y > part->viewport_height - g->height)
413           height -= (part->y - (part->viewport_height - g->height));
414
415         dst_x += part->viewport_x;
416         dst_y += part->viewport_y;
417
418         sync_frame = anim_sync_frame - part->initial_anim_sync_frame;
419         frame = getAnimationFrame(g->anim_frames, g->anim_delay,
420                                   g->anim_mode, g->anim_start_frame,
421                                   sync_frame);
422
423         getFixedGraphicSource(part->graphic, frame, &src_bitmap,
424                               &src_x, &src_y);
425
426         src_x += cut_x;
427         src_y += cut_y;
428
429         BlitToScreenMasked(src_bitmap, src_x, src_y, width, height,
430                            dst_x, dst_y);
431       }
432     }
433   }
434 }
435
436 boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part)
437 {
438   int viewport_x;
439   int viewport_y;
440   int viewport_width;
441   int viewport_height;
442   boolean changed = FALSE;
443
444   if (part->last_game_status == game_status)
445     return FALSE;
446
447   part->last_game_status = game_status;
448
449   if (part->control_info.class == get_hash_from_key("window") ||
450       part->control_info.class == get_hash_from_key("border"))
451   {
452     viewport_x = 0;
453     viewport_y = 0;
454     viewport_width  = WIN_XSIZE;
455     viewport_height = WIN_YSIZE;
456   }
457   else if (part->control_info.class == get_hash_from_key("door_1"))
458   {
459     viewport_x = DX;
460     viewport_y = DY;
461     viewport_width  = DXSIZE;
462     viewport_height = DYSIZE;
463   }
464   else if (part->control_info.class == get_hash_from_key("door_2"))
465   {
466     viewport_x = VX;
467     viewport_y = VY;
468     viewport_width  = VXSIZE;
469     viewport_height = VYSIZE;
470   }
471   else          // default: "playfield"
472   {
473     viewport_x = REAL_SX;
474     viewport_y = REAL_SY;
475     viewport_width  = FULL_SXSIZE;
476     viewport_height = FULL_SYSIZE;
477   }
478
479   if (viewport_x != part->viewport_x ||
480       viewport_y != part->viewport_y ||
481       viewport_width  != part->viewport_width ||
482       viewport_height != part->viewport_height)
483   {
484     part->viewport_x = viewport_x;
485     part->viewport_y = viewport_y;
486     part->viewport_width  = viewport_width;
487     part->viewport_height = viewport_height;
488
489     changed = TRUE;
490   }
491
492   return changed;
493 }
494
495 int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
496 {
497   struct GraphicInfo *g = &part->graphic_info;
498   struct GraphicInfo *c = &part->control_info;
499   boolean viewport_changed = SetGlobalAnimPart_Viewport(part);
500
501   if (viewport_changed)
502     state |= ANIM_STATE_RESTART;
503
504   if (state & ANIM_STATE_RESTART)
505   {
506     ResetDelayCounterExt(&part->step_delay, anim_sync_frame);
507
508     part->init_delay_counter =
509       (c->init_delay_fixed + GetSimpleRandom(c->init_delay_random));
510
511     part->anim_delay_counter =
512       (c->anim_delay_fixed + GetSimpleRandom(c->anim_delay_random));
513
514     part->initial_anim_sync_frame =
515       (g->anim_global_sync ? 0 : anim_sync_frame + part->init_delay_counter);
516
517     if (c->direction & MV_HORIZONTAL)
518     {
519       int pos_bottom = part->viewport_height - g->height;
520
521       if (c->position == POS_TOP)
522         part->y = 0;
523       else if (c->position == POS_UPPER)
524         part->y = GetSimpleRandom(pos_bottom / 2);
525       else if (c->position == POS_MIDDLE)
526         part->y = pos_bottom / 2;
527       else if (c->position == POS_LOWER)
528         part->y = pos_bottom / 2 + GetSimpleRandom(pos_bottom / 2);
529       else if (c->position == POS_BOTTOM)
530         part->y = pos_bottom;
531       else
532         part->y = GetSimpleRandom(pos_bottom);
533
534       if (c->direction == MV_RIGHT)
535       {
536         part->step_xoffset = c->step_offset;
537         part->x = -g->width + part->step_xoffset;
538       }
539       else
540       {
541         part->step_xoffset = -c->step_offset;
542         part->x = part->viewport_width + part->step_xoffset;
543       }
544
545       part->step_yoffset = 0;
546     }
547     else if (c->direction & MV_VERTICAL)
548     {
549       int pos_right = part->viewport_width - g->width;
550
551       if (c->position == POS_LEFT)
552         part->x = 0;
553       else if (c->position == POS_RIGHT)
554         part->x = pos_right;
555       else
556         part->x = GetSimpleRandom(pos_right);
557
558       if (c->direction == MV_DOWN)
559       {
560         part->step_yoffset = c->step_offset;
561         part->y = -g->height + part->step_yoffset;
562       }
563       else
564       {
565         part->step_yoffset = -c->step_offset;
566         part->y = part->viewport_height + part->step_yoffset;
567       }
568
569       part->step_xoffset = 0;
570     }
571     else
572     {
573       part->x = 0;
574       part->y = 0;
575
576       part->step_xoffset = 0;
577       part->step_yoffset = 0;
578     }
579
580     if (c->x != ARG_UNDEFINED_VALUE)
581       part->x = c->x;
582     if (c->y != ARG_UNDEFINED_VALUE)
583       part->y = c->y;
584
585     if (c->step_xoffset != ARG_UNDEFINED_VALUE)
586       part->step_xoffset = c->step_xoffset;
587     if (c->step_yoffset != ARG_UNDEFINED_VALUE)
588       part->step_yoffset = c->step_yoffset;
589   }
590
591   if (part->init_delay_counter > 0)
592   {
593     part->init_delay_counter--;
594
595     return ANIM_STATE_WAITING;
596   }
597
598   if ((part->x <= -g->width              && part->step_xoffset <= 0) ||
599       (part->x >=  part->viewport_width  && part->step_xoffset >= 0) ||
600       (part->y <= -g->height             && part->step_yoffset <= 0) ||
601       (part->y >=  part->viewport_height && part->step_yoffset >= 0))
602     return ANIM_STATE_RESTART;
603
604   if (part->anim_delay_counter > 0)
605   {
606     part->anim_delay_counter--;
607
608     if (part->anim_delay_counter == 0)
609     {
610       part->post_delay_counter =
611         (c->post_delay_fixed + GetSimpleRandom(c->post_delay_random));
612
613       if (part->post_delay_counter > 0)
614         return ANIM_STATE_RUNNING;
615
616       return ANIM_STATE_RESTART | ANIM_STATE_RUNNING;
617     }
618   }
619
620   if (part->post_delay_counter > 0)
621   {
622     part->post_delay_counter--;
623
624     if (part->post_delay_counter == 0)
625       return ANIM_STATE_RESTART;
626
627     return ANIM_STATE_WAITING;
628   }
629
630   if (!DelayReachedExt(&part->step_delay, part->step_delay_value,
631                        anim_sync_frame))
632     return ANIM_STATE_RUNNING;
633
634 #if 0
635   {
636     static unsigned int last_counter = -1;
637     unsigned int counter = Counter();
638
639     printf("::: NEXT ANIM PART [%d, %d]\n",
640            anim_sync_frame, counter - last_counter);
641
642     last_counter = counter;
643   }
644 #endif
645
646   part->x += part->step_xoffset;
647   part->y += part->step_yoffset;
648
649   return ANIM_STATE_RUNNING;
650 }
651
652 void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action)
653 {
654   struct GlobalAnimPartControlInfo *part;
655   struct GraphicInfo *c = &anim->control_info;
656   boolean skip = FALSE;
657
658 #if 0
659   printf("::: HandleGlobalAnim_Main: %d, %d => %d\n",
660          anim->mode_nr, anim->nr, anim->num_parts);
661   printf("::: %d, %d, %d\n", global.num_toons, setup.toons, num_toons);
662 #endif
663
664 #if 0
665   printf("::: %s(%d): %d, %d, %d [%d]\n",
666          (action == ANIM_START ? "ANIM_START" :
667           action == ANIM_CONTINUE ? "ANIM_CONTINUE" :
668           action == ANIM_STOP ? "ANIM_STOP" : "(should not happen)"),
669          anim->nr,
670          anim->state & ANIM_STATE_RESTART,
671          anim->state & ANIM_STATE_WAITING,
672          anim->state & ANIM_STATE_RUNNING,
673          anim->num_parts);
674 #endif
675
676   switch (action)
677   {
678     case ANIM_START:
679       anim->state = ANIM_STATE_RESTART;
680       anim->part_counter = 0;
681       anim->active_part_nr = 0;
682       skip = TRUE;
683
684       break;
685
686     case ANIM_CONTINUE:
687       if (anim->state == ANIM_STATE_INACTIVE)
688         skip = TRUE;
689
690       break;
691
692     case ANIM_STOP:
693       anim->state = ANIM_STATE_INACTIVE;
694       skip = TRUE;
695
696       break;
697
698     default:
699       break;
700   }
701
702   if (c->anim_mode & ANIM_ALL || anim->num_parts == 0)
703   {
704     int num_parts = anim->num_parts + (anim->has_base ? 1 : 0);
705     int i;
706
707 #if 0
708     printf("::: HandleGlobalAnim_Main: %d, %d => %d\n",
709            anim->mode_nr, anim->nr, num_parts);
710 #endif
711
712     for (i = 0; i < num_parts; i++)
713     {
714       part = &anim->part[i];
715
716       switch (action)
717       {
718         case ANIM_START:
719           anim->state = ANIM_STATE_RUNNING;
720           part->state = ANIM_STATE_RESTART;
721           skip = TRUE;
722
723           break;
724
725         case ANIM_CONTINUE:
726           if (part->state == ANIM_STATE_INACTIVE)
727             skip = TRUE;
728
729           break;
730
731         case ANIM_STOP:
732           part->state = ANIM_STATE_INACTIVE;
733           skip = TRUE;
734
735           break;
736
737         default:
738           break;
739       }
740
741       if (skip)
742         continue;
743
744       part->state = HandleGlobalAnim_Part(part, part->state);
745     }
746
747     return;
748   }
749
750   if (skip)
751     return;
752
753   if (anim->state & ANIM_STATE_RESTART)         // directly after restart
754     anim->active_part_nr = getGlobalAnimationPart(anim);
755
756   part = &anim->part[anim->active_part_nr];
757
758   part->state = ANIM_STATE_RUNNING;
759
760   anim->state = HandleGlobalAnim_Part(part, anim->state);
761
762   if (anim->state & ANIM_STATE_RESTART)
763     anim->part_counter++;
764 }
765
766 void HandleGlobalAnim_Mode(struct GlobalAnimControlInfo *ctrl, int action)
767 {
768   int i;
769
770 #if 0
771   printf("::: HandleGlobalAnim_Mode: %d => %d\n",
772          ctrl->nr, ctrl->num_anims);
773 #endif
774
775   for (i = 0; i < ctrl->num_anims; i++)
776     HandleGlobalAnim_Main(&ctrl->anim[i], action);
777 }
778
779 void HandleGlobalAnim(int action)
780 {
781 #if 0
782   printf("::: HandleGlobalAnim [mode == %d]\n", game_status);
783 #endif
784
785   HandleGlobalAnim_Mode(&global_anim_ctrl[GAME_MODE_DEFAULT], action);
786   HandleGlobalAnim_Mode(&global_anim_ctrl[game_status], action);
787 }
788
789 void InitAnimation()
790 {
791   // HandleAnimation(ANIM_START);
792
793 #if 0
794   printf("::: InitAnimation\n");
795 #endif
796
797   // InitCounter();
798
799   InitGlobalAnimControls();
800
801   HandleGlobalAnim(ANIM_START);
802
803   do_animations = TRUE;
804 }
805
806 void StopAnimation()
807 {
808   // HandleAnimation(ANIM_STOP);
809
810 #if 0
811   printf("::: StopAnimation\n");
812 #endif
813
814   HandleGlobalAnim(ANIM_STOP);
815
816   do_animations = FALSE;
817 }
818
819 static void DoAnimationExt()
820 {
821 #if 0
822   printf("::: DoAnimation [%d, %d]\n", anim_sync_frame, Counter());
823 #endif
824
825 #if 1
826   WaitUntilDelayReached(&anim_sync_frame_delay, anim_sync_frame_delay_value);
827   anim_sync_frame++;
828 #else
829   if (DelayReached(&anim_sync_frame_delay, anim_sync_frame_delay_value))
830     anim_sync_frame++;
831 #endif
832
833   HandleGlobalAnim(ANIM_CONTINUE);
834
835 #if 1
836   // force screen redraw in next frame to continue drawing global animations
837   redraw_mask = REDRAW_ALL;
838 #endif
839 }
840
841 void DoAnimation()
842 {
843   // HandleAnimation(ANIM_CONTINUE);
844
845 #if 1
846   // force screen redraw in next frame to continue drawing global animations
847   redraw_mask = REDRAW_ALL;
848 #endif
849 }