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