1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
26 /* select level set with EMC X11 graphics before activating EM GFX debugging */
27 #define DEBUG_EM_GFX 0
29 /* tool button identifiers */
30 #define TOOL_CTRL_ID_YES 0
31 #define TOOL_CTRL_ID_NO 1
32 #define TOOL_CTRL_ID_CONFIRM 2
33 #define TOOL_CTRL_ID_PLAYER_1 3
34 #define TOOL_CTRL_ID_PLAYER_2 4
35 #define TOOL_CTRL_ID_PLAYER_3 5
36 #define TOOL_CTRL_ID_PLAYER_4 6
38 #define NUM_TOOL_BUTTONS 7
40 /* forward declaration for internal use */
41 static void UnmapToolButtons();
42 static void HandleToolButtons(struct GadgetInfo *);
43 static int el_act_dir2crm(int, int, int);
44 static int el_act2crm(int, int);
46 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
47 static int request_gadget_id = -1;
49 static char *print_if_not_empty(int element)
51 static char *s = NULL;
52 char *token_name = element_info[element].token_name;
57 s = checked_malloc(strlen(token_name) + 10 + 1);
59 if (element != EL_EMPTY)
60 sprintf(s, "%d\t['%s']", element, token_name);
62 sprintf(s, "%d", element);
67 void DumpTile(int x, int y)
72 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
79 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
82 if (!IN_LEV_FIELD(x, y))
84 printf("(not in level field)\n");
90 printf(" Feld: %d\t['%s']\n", Feld[x][y],
91 element_info[Feld[x][y]].token_name);
92 printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
93 printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
94 printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
95 printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
96 printf(" MovPos: %d\n", MovPos[x][y]);
97 printf(" MovDir: %d\n", MovDir[x][y]);
98 printf(" MovDelay: %d\n", MovDelay[x][y]);
99 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
100 printf(" CustomValue: %d\n", CustomValue[x][y]);
101 printf(" GfxElement: %d\n", GfxElement[x][y]);
102 printf(" GfxAction: %d\n", GfxAction[x][y]);
103 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
107 void SetDrawtoField(int mode)
109 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
117 BX2 = SCR_FIELDX + 1;
118 BY2 = SCR_FIELDY + 1;
137 BX2 = SCR_FIELDX + 1;
138 BY2 = SCR_FIELDY + 1;
153 drawto_field = fieldbuffer;
155 else /* DRAW_BACKBUFFER */
161 BX2 = SCR_FIELDX - 1;
162 BY2 = SCR_FIELDY - 1;
166 drawto_field = backbuffer;
170 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
172 if (game_status == GAME_MODE_PLAYING &&
173 level.game_engine_type == GAME_ENGINE_TYPE_EM)
175 /* currently there is no partial redraw -- always redraw whole playfield */
176 RedrawPlayfield_EM(TRUE);
178 /* blit playfield from scroll buffer to normal back buffer for fading in */
179 BlitScreenToBitmap_EM(backbuffer);
181 else if (game_status == GAME_MODE_PLAYING &&
182 level.game_engine_type == GAME_ENGINE_TYPE_SP)
184 /* currently there is no partial redraw -- always redraw whole playfield */
185 RedrawPlayfield_SP(TRUE);
187 /* blit playfield from scroll buffer to normal back buffer for fading in */
188 BlitScreenToBitmap_SP(backbuffer);
190 else if (game_status == GAME_MODE_PLAYING &&
191 !game.envelope_active)
197 width = gfx.sxsize + 2 * TILEX;
198 height = gfx.sysize + 2 * TILEY;
204 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
205 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
207 for (xx = BX1; xx <= BX2; xx++)
208 for (yy = BY1; yy <= BY2; yy++)
209 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
210 DrawScreenField(xx, yy);
214 if (setup.soft_scrolling)
216 int fx = FX, fy = FY;
218 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
219 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
221 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
233 BlitBitmap(drawto, window, x, y, width, height, x, y);
236 void DrawMaskedBorder_Rect(int x, int y, int width, int height)
238 Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap;
240 SetClipOrigin(bitmap, bitmap->stored_clip_gc, 0, 0);
241 BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
244 void DrawMaskedBorder_FIELD()
246 if (global.border_status >= GAME_MODE_TITLE &&
247 global.border_status <= GAME_MODE_PLAYING &&
248 border.draw_masked[global.border_status])
249 DrawMaskedBorder_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
252 void DrawMaskedBorder_DOOR_1()
254 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
255 (global.border_status != GAME_MODE_EDITOR ||
256 border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
257 DrawMaskedBorder_Rect(DX, DY, DXSIZE, DYSIZE);
260 void DrawMaskedBorder_DOOR_2()
262 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
263 global.border_status != GAME_MODE_EDITOR)
264 DrawMaskedBorder_Rect(VX, VY, VXSIZE, VYSIZE);
267 void DrawMaskedBorder_DOOR_3()
269 /* currently not available */
272 void DrawMaskedBorder_ALL()
274 DrawMaskedBorder_FIELD();
275 DrawMaskedBorder_DOOR_1();
276 DrawMaskedBorder_DOOR_2();
277 DrawMaskedBorder_DOOR_3();
280 void DrawMaskedBorder(int redraw_mask)
282 /* never draw masked screen borders on borderless screens */
283 if (effectiveGameStatus() == GAME_MODE_LOADING ||
284 effectiveGameStatus() == GAME_MODE_TITLE)
287 /* never draw masked screen borders when displaying request outside door */
288 if (effectiveGameStatus() == GAME_MODE_PSEUDO_DOOR &&
289 global.use_envelope_request)
292 if (redraw_mask & REDRAW_ALL)
293 DrawMaskedBorder_ALL();
296 if (redraw_mask & REDRAW_FIELD)
297 DrawMaskedBorder_FIELD();
298 if (redraw_mask & REDRAW_DOOR_1)
299 DrawMaskedBorder_DOOR_1();
300 if (redraw_mask & REDRAW_DOOR_2)
301 DrawMaskedBorder_DOOR_2();
302 if (redraw_mask & REDRAW_DOOR_3)
303 DrawMaskedBorder_DOOR_3();
307 void BlitScreenToBitmap(Bitmap *target_bitmap)
309 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
310 int fx = FX, fy = FY;
313 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
314 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
315 int dx_var = dx * TILESIZE_VAR / TILESIZE;
316 int dy_var = dy * TILESIZE_VAR / TILESIZE;
319 // fx += dx * TILESIZE_VAR / TILESIZE;
320 // fy += dy * TILESIZE_VAR / TILESIZE;
322 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
323 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
326 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
327 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
329 if (EVEN(SCR_FIELDX))
331 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
332 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
334 fx += (dx_var > 0 ? TILEX_VAR : 0);
341 if (EVEN(SCR_FIELDY))
343 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
344 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
346 fy += (dy_var > 0 ? TILEY_VAR : 0);
354 printf("::: (%d, %d) [(%d / %d, %d / %d)] => %d, %d\n",
357 SBY_Upper, SBY_Lower,
361 if (border.draw_masked[GAME_MODE_PLAYING])
363 if (buffer != backbuffer)
365 /* copy playfield buffer to backbuffer to add masked border */
366 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
367 DrawMaskedBorder(REDRAW_FIELD);
370 BlitBitmap(backbuffer, target_bitmap,
371 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
376 BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
383 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
386 printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
387 for (x = 0; x < SCR_FIELDX; x++)
388 for (y = 0 ; y < SCR_FIELDY; y++)
389 if (redraw[redraw_x1 + x][redraw_y1 + y])
390 printf("::: - %d, %d [%s]\n",
391 LEVELX(x), LEVELY(y),
392 EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
395 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
396 redraw_mask |= REDRAW_FIELD;
399 // never redraw single tiles, always redraw the whole field
400 // (redrawing single tiles up to a certain threshold was faster on old,
401 // now legacy graphics, but slows things down on modern graphics now)
402 // UPDATE: this is now globally defined by value of REDRAWTILES_THRESHOLD
403 if (redraw_mask & REDRAW_TILES)
404 redraw_mask |= REDRAW_FIELD;
408 /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
409 /* (force full redraw) */
410 if (game_status == GAME_MODE_PLAYING)
411 redraw_mask |= REDRAW_FIELD;
414 if (redraw_mask & REDRAW_FIELD)
415 redraw_mask &= ~REDRAW_TILES;
417 if (redraw_mask == REDRAW_NONE)
422 if (redraw_mask & REDRAW_ALL)
423 printf("[REDRAW_ALL]");
424 if (redraw_mask & REDRAW_FIELD)
425 printf("[REDRAW_FIELD]");
426 if (redraw_mask & REDRAW_TILES)
427 printf("[REDRAW_TILES]");
428 if (redraw_mask & REDRAW_DOOR_1)
429 printf("[REDRAW_DOOR_1]");
430 if (redraw_mask & REDRAW_DOOR_2)
431 printf("[REDRAW_DOOR_2]");
432 if (redraw_mask & REDRAW_FROM_BACKBUFFER)
433 printf("[REDRAW_FROM_BACKBUFFER]");
434 printf(" [%d]\n", FrameCounter);
437 if (redraw_mask & REDRAW_TILES &&
438 game_status == GAME_MODE_PLAYING &&
439 border.draw_masked[GAME_MODE_PLAYING])
440 redraw_mask |= REDRAW_FIELD;
442 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
444 static boolean last_frame_skipped = FALSE;
445 boolean skip_even_when_not_scrolling = TRUE;
446 boolean just_scrolling = (ScreenMovDir != 0);
447 boolean verbose = FALSE;
449 if (global.fps_slowdown_factor > 1 &&
450 (FrameCounter % global.fps_slowdown_factor) &&
451 (just_scrolling || skip_even_when_not_scrolling))
453 redraw_mask &= ~REDRAW_MAIN;
455 last_frame_skipped = TRUE;
458 printf("FRAME SKIPPED\n");
462 if (last_frame_skipped)
463 redraw_mask |= REDRAW_FIELD;
465 last_frame_skipped = FALSE;
468 printf("frame not skipped\n");
472 /* synchronize X11 graphics at this point; if we would synchronize the
473 display immediately after the buffer switching (after the XFlush),
474 this could mean that we have to wait for the graphics to complete,
475 although we could go on doing calculations for the next frame */
479 /* never draw masked border to backbuffer when using playfield buffer */
480 if (game_status != GAME_MODE_PLAYING ||
481 redraw_mask & REDRAW_FROM_BACKBUFFER ||
482 buffer == backbuffer)
483 DrawMaskedBorder(redraw_mask);
485 DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
487 if (redraw_mask & REDRAW_ALL)
489 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
491 redraw_mask = REDRAW_NONE;
494 if (redraw_mask & REDRAW_FIELD)
497 printf("::: REDRAW_FIELD\n");
500 if (game_status != GAME_MODE_PLAYING ||
501 redraw_mask & REDRAW_FROM_BACKBUFFER)
503 BlitBitmap(backbuffer, window,
504 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
509 BlitScreenToBitmap(window);
511 int fx = FX, fy = FY;
514 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
515 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
516 int dx_var = dx * TILESIZE_VAR / TILESIZE;
517 int dy_var = dy * TILESIZE_VAR / TILESIZE;
520 // fx += dx * TILESIZE_VAR / TILESIZE;
521 // fy += dy * TILESIZE_VAR / TILESIZE;
523 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
524 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
527 /* !!! THIS WORKS !!! */
529 printf("::: %d, %d\n", scroll_x, scroll_y);
531 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
532 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
534 if (EVEN(SCR_FIELDX))
536 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
537 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
539 fx += (dx > 0 ? TILEX_VAR : 0);
546 if (EVEN(SCR_FIELDY))
548 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
549 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
551 fy += (dy > 0 ? TILEY_VAR : 0);
558 if (border.draw_masked[GAME_MODE_PLAYING])
560 if (buffer != backbuffer)
562 /* copy playfield buffer to backbuffer to add masked border */
563 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
564 DrawMaskedBorder(REDRAW_FIELD);
567 BlitBitmap(backbuffer, window,
568 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
573 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
579 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
581 (setup.soft_scrolling ?
582 "setup.soft_scrolling" :
583 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
584 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
585 ABS(ScreenGfxPos) == ScrollStepSize ?
586 "ABS(ScreenGfxPos) == ScrollStepSize" :
587 "redraw_tiles > REDRAWTILES_THRESHOLD"));
592 redraw_mask &= ~REDRAW_MAIN;
595 if (redraw_mask & REDRAW_DOORS)
597 if (redraw_mask & REDRAW_DOOR_1)
598 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
600 if (redraw_mask & REDRAW_DOOR_2)
601 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
603 if (redraw_mask & REDRAW_DOOR_3)
604 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
606 redraw_mask &= ~REDRAW_DOORS;
609 if (redraw_mask & REDRAW_MICROLEVEL)
611 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
612 SX, SY + 10 * TILEY);
614 redraw_mask &= ~REDRAW_MICROLEVEL;
617 if (redraw_mask & REDRAW_TILES)
620 printf("::: REDRAW_TILES\n");
626 InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
629 int sx = SX; // - (EVEN(SCR_FIELDX) ? TILEX_VAR / 2 : 0);
630 int sy = SY; // + (EVEN(SCR_FIELDY) ? TILEY_VAR / 2 : 0);
633 int dx_var = dx * TILESIZE_VAR / TILESIZE;
634 int dy_var = dy * TILESIZE_VAR / TILESIZE;
636 int fx = FX, fy = FY;
638 int scr_fieldx = SCR_FIELDX + (EVEN(SCR_FIELDX) ? 2 : 0);
639 int scr_fieldy = SCR_FIELDY + (EVEN(SCR_FIELDY) ? 2 : 0);
641 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
642 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
644 if (EVEN(SCR_FIELDX))
646 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
648 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
657 fx += (dx_var > 0 ? TILEX_VAR : 0);
661 if (EVEN(SCR_FIELDY))
663 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
665 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
674 fy += (dy_var > 0 ? TILEY_VAR : 0);
679 printf("::: %d, %d, %d, %d\n", sx, sy, SCR_FIELDX, SCR_FIELDY);
682 for (x = 0; x < scr_fieldx; x++)
683 for (y = 0 ; y < scr_fieldy; y++)
684 if (redraw[redraw_x1 + x][redraw_y1 + y])
685 BlitBitmap(buffer, window,
686 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
687 TILEX_VAR, TILEY_VAR,
688 sx + x * TILEX_VAR, sy + y * TILEY_VAR);
691 InitGfxClipRegion(FALSE, -1, -1, -1, -1);
693 for (x = 0; x < SCR_FIELDX; x++)
694 for (y = 0 ; y < SCR_FIELDY; y++)
695 if (redraw[redraw_x1 + x][redraw_y1 + y])
696 BlitBitmap(buffer, window,
697 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
698 TILEX_VAR, TILEY_VAR,
699 SX + x * TILEX_VAR, SY + y * TILEY_VAR);
703 for (x = 0; x < SCR_FIELDX; x++)
704 for (y = 0 ; y < SCR_FIELDY; y++)
705 if (redraw[redraw_x1 + x][redraw_y1 + y])
706 BlitBitmap(buffer, window,
707 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
708 SX + x * TILEX, SY + y * TILEY);
712 if (redraw_mask & REDRAW_FPS) /* display frames per second */
717 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
718 if (!global.fps_slowdown)
721 sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
723 DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
725 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
731 for (x = 0; x < MAX_BUF_XSIZE; x++)
732 for (y = 0; y < MAX_BUF_YSIZE; y++)
735 redraw_mask = REDRAW_NONE;
738 static void FadeCrossSaveBackbuffer()
740 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
743 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
745 static int fade_type_skip = FADE_TYPE_NONE;
746 void (*draw_border_function)(void) = NULL;
747 Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
748 int x, y, width, height;
749 int fade_delay, post_delay;
751 if (fade_type == FADE_TYPE_FADE_OUT)
753 if (fade_type_skip != FADE_TYPE_NONE)
756 printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
759 /* skip all fade operations until specified fade operation */
760 if (fade_type & fade_type_skip)
761 fade_type_skip = FADE_TYPE_NONE;
766 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
768 FadeCrossSaveBackbuffer();
774 redraw_mask |= fade_mask;
776 if (fade_type == FADE_TYPE_SKIP)
779 printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
782 fade_type_skip = fade_mode;
788 printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
793 fade_delay = fading.fade_delay;
794 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
797 if (fade_type_skip != FADE_TYPE_NONE)
800 printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
803 /* skip all fade operations until specified fade operation */
804 if (fade_type & fade_type_skip)
805 fade_type_skip = FADE_TYPE_NONE;
815 if (global.autoplay_leveldir)
817 // fading.fade_mode = FADE_MODE_NONE;
824 if (fading.fade_mode == FADE_MODE_NONE)
832 /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
835 printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
839 if (fade_mask == REDRAW_NONE)
840 fade_mask = REDRAW_FIELD;
843 // if (fade_mask & REDRAW_FIELD)
844 if (fade_mask == REDRAW_FIELD)
849 height = FULL_SYSIZE;
852 fade_delay = fading.fade_delay;
853 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
856 if (border.draw_masked_when_fading)
857 draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
859 DrawMaskedBorder_FIELD(); /* draw once */
861 else /* REDRAW_ALL */
869 fade_delay = fading.fade_delay;
870 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
875 if (!setup.fade_screens ||
877 fading.fade_mode == FADE_MODE_NONE)
879 if (!setup.fade_screens || fade_delay == 0)
882 if (fade_mode == FADE_MODE_FADE_OUT)
886 if (fade_mode == FADE_MODE_FADE_OUT &&
887 fading.fade_mode != FADE_MODE_NONE)
888 ClearRectangle(backbuffer, x, y, width, height);
892 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
893 redraw_mask = REDRAW_NONE;
901 FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
902 draw_border_function);
904 redraw_mask &= ~fade_mask;
907 void FadeIn(int fade_mask)
909 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
910 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
912 FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
915 void FadeOut(int fade_mask)
917 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
918 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
920 FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
922 global.border_status = game_status;
925 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
927 static struct TitleFadingInfo fading_leave_stored;
930 fading_leave_stored = fading_leave;
932 fading = fading_leave_stored;
935 void FadeSetEnterMenu()
937 fading = menu.enter_menu;
940 printf("::: storing enter_menu\n");
943 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
946 void FadeSetLeaveMenu()
948 fading = menu.leave_menu;
951 printf("::: storing leave_menu\n");
954 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
957 void FadeSetEnterScreen()
959 fading = menu.enter_screen[game_status];
962 printf("::: storing leave_screen[%d]\n", game_status);
965 FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
968 void FadeSetNextScreen()
970 fading = menu.next_screen;
973 printf("::: storing next_screen\n");
976 // (do not overwrite fade mode set by FadeSetEnterScreen)
977 // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
980 void FadeSetLeaveScreen()
983 printf("::: recalling last stored value\n");
986 FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
989 void FadeSetFromType(int type)
991 if (type & TYPE_ENTER_SCREEN)
992 FadeSetEnterScreen();
993 else if (type & TYPE_ENTER)
995 else if (type & TYPE_LEAVE)
999 void FadeSetDisabled()
1001 static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
1003 fading = fading_none;
1006 void FadeSkipNextFadeIn()
1008 FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
1011 void FadeSkipNextFadeOut()
1013 FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
1016 void SetWindowBackgroundImageIfDefined(int graphic)
1018 if (graphic_info[graphic].bitmap)
1019 SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
1022 void SetMainBackgroundImageIfDefined(int graphic)
1024 if (graphic_info[graphic].bitmap)
1025 SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
1028 void SetDoorBackgroundImageIfDefined(int graphic)
1030 if (graphic_info[graphic].bitmap)
1031 SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
1034 void SetWindowBackgroundImage(int graphic)
1036 SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1037 graphic_info[graphic].bitmap ?
1038 graphic_info[graphic].bitmap :
1039 graphic_info[IMG_BACKGROUND].bitmap);
1042 void SetMainBackgroundImage(int graphic)
1044 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1045 graphic_info[graphic].bitmap ?
1046 graphic_info[graphic].bitmap :
1047 graphic_info[IMG_BACKGROUND].bitmap);
1050 void SetDoorBackgroundImage(int graphic)
1052 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1053 graphic_info[graphic].bitmap ?
1054 graphic_info[graphic].bitmap :
1055 graphic_info[IMG_BACKGROUND].bitmap);
1058 void SetPanelBackground()
1061 struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
1064 BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1065 gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
1067 /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */
1068 ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE);
1069 BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1070 MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0);
1073 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
1074 DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
1077 SetDoorBackgroundBitmap(bitmap_db_panel);
1080 void DrawBackground(int x, int y, int width, int height)
1082 /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
1083 /* (when entering hall of fame after playing) */
1085 ClearRectangleOnBackground(drawto, x, y, width, height);
1087 ClearRectangleOnBackground(backbuffer, x, y, width, height);
1091 /* (this only works for the current arrangement of playfield and panels) */
1093 redraw_mask |= REDRAW_FIELD;
1094 else if (y < gfx.vy)
1095 redraw_mask |= REDRAW_DOOR_1;
1097 redraw_mask |= REDRAW_DOOR_2;
1099 /* (this is just wrong (when drawing to one of the two door panel areas)) */
1100 redraw_mask |= REDRAW_FIELD;
1104 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
1106 struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
1108 if (font->bitmap == NULL)
1111 DrawBackground(x, y, width, height);
1114 void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
1116 struct GraphicInfo *g = &graphic_info[graphic];
1118 if (g->bitmap == NULL)
1121 DrawBackground(x, y, width, height);
1126 /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
1127 /* (when entering hall of fame after playing) */
1128 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
1130 /* !!! maybe this should be done before clearing the background !!! */
1131 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
1133 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
1134 SetDrawtoField(DRAW_BUFFERED);
1137 SetDrawtoField(DRAW_BACKBUFFER);
1140 void MarkTileDirty(int x, int y)
1142 int xx = redraw_x1 + x;
1143 int yy = redraw_y1 + y;
1145 if (!redraw[xx][yy])
1148 redraw[xx][yy] = TRUE;
1149 redraw_mask |= REDRAW_TILES;
1152 void SetBorderElement()
1156 BorderElement = EL_EMPTY;
1158 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
1160 for (x = 0; x < lev_fieldx; x++)
1162 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
1163 BorderElement = EL_STEELWALL;
1165 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
1171 void FloodFillLevel(int from_x, int from_y, int fill_element,
1172 short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
1173 int max_fieldx, int max_fieldy)
1177 static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
1178 static int safety = 0;
1180 /* check if starting field still has the desired content */
1181 if (field[from_x][from_y] == fill_element)
1186 if (safety > max_fieldx * max_fieldy)
1187 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1189 old_element = field[from_x][from_y];
1190 field[from_x][from_y] = fill_element;
1192 for (i = 0; i < 4; i++)
1194 x = from_x + check[i][0];
1195 y = from_y + check[i][1];
1197 if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
1198 FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
1204 void SetRandomAnimationValue(int x, int y)
1206 gfx.anim_random_frame = GfxRandom[x][y];
1209 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
1211 /* animation synchronized with global frame counter, not move position */
1212 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
1213 sync_frame = FrameCounter;
1215 return getAnimationFrame(graphic_info[graphic].anim_frames,
1216 graphic_info[graphic].anim_delay,
1217 graphic_info[graphic].anim_mode,
1218 graphic_info[graphic].anim_start_frame,
1222 void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
1223 Bitmap **bitmap, int *x, int *y,
1224 boolean get_backside)
1228 int width_mult, width_div;
1229 int height_mult, height_div;
1233 { 15, 16, 2, 3 }, /* 1 x 1 */
1234 { 7, 8, 2, 3 }, /* 2 x 2 */
1235 { 3, 4, 2, 3 }, /* 4 x 4 */
1236 { 1, 2, 2, 3 }, /* 8 x 8 */
1237 { 0, 1, 2, 3 }, /* 16 x 16 */
1238 { 0, 1, 0, 1 }, /* 32 x 32 */
1240 struct GraphicInfo *g = &graphic_info[graphic];
1241 Bitmap *src_bitmap = g->bitmap;
1242 int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
1243 int offset_calc_pos = log_2(tilesize);
1244 int width_mult = offset_calc[offset_calc_pos].width_mult;
1245 int width_div = offset_calc[offset_calc_pos].width_div;
1246 int height_mult = offset_calc[offset_calc_pos].height_mult;
1247 int height_div = offset_calc[offset_calc_pos].height_div;
1248 int startx = src_bitmap->width * width_mult / width_div;
1249 int starty = src_bitmap->height * height_mult / height_div;
1251 int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
1252 tilesize / TILESIZE;
1253 int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
1254 tilesize / TILESIZE;
1256 int src_x = g->src_x * tilesize / TILESIZE;
1257 int src_y = g->src_y * tilesize / TILESIZE;
1259 int width = g->width * tilesize / TILESIZE;
1260 int height = g->height * tilesize / TILESIZE;
1261 int offset_x = g->offset_x * tilesize / TILESIZE;
1262 int offset_y = g->offset_y * tilesize / TILESIZE;
1264 if (g->offset_y == 0) /* frames are ordered horizontally */
1266 int max_width = g->anim_frames_per_line * width;
1267 int pos = (src_y / height) * max_width + src_x + frame * offset_x;
1269 src_x = pos % max_width;
1270 src_y = src_y % height + pos / max_width * height;
1272 else if (g->offset_x == 0) /* frames are ordered vertically */
1274 int max_height = g->anim_frames_per_line * height;
1275 int pos = (src_x / width) * max_height + src_y + frame * offset_y;
1277 src_x = src_x % width + pos / max_height * width;
1278 src_y = pos % max_height;
1280 else /* frames are ordered diagonally */
1282 src_x = src_x + frame * offset_x;
1283 src_y = src_y + frame * offset_y;
1286 *bitmap = src_bitmap;
1287 *x = startx + src_x;
1288 *y = starty + src_y;
1291 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1292 int *x, int *y, boolean get_backside)
1294 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
1298 void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
1299 Bitmap **bitmap, int *x, int *y)
1301 getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
1304 void getFixedGraphicSource(int graphic, int frame,
1305 Bitmap **bitmap, int *x, int *y)
1307 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
1310 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1313 getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
1315 struct GraphicInfo *g = &graphic_info[graphic];
1316 int mini_startx = 0;
1317 int mini_starty = g->bitmap->height * 2 / 3;
1319 *bitmap = g->bitmap;
1320 *x = mini_startx + g->src_x / 2;
1321 *y = mini_starty + g->src_y / 2;
1325 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1326 int *x, int *y, boolean get_backside)
1328 struct GraphicInfo *g = &graphic_info[graphic];
1329 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
1330 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
1333 if (TILESIZE_VAR != TILESIZE)
1334 return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
1338 *bitmap = g->bitmap;
1340 if (g->offset_y == 0) /* frames are ordered horizontally */
1342 int max_width = g->anim_frames_per_line * g->width;
1343 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
1345 *x = pos % max_width;
1346 *y = src_y % g->height + pos / max_width * g->height;
1348 else if (g->offset_x == 0) /* frames are ordered vertically */
1350 int max_height = g->anim_frames_per_line * g->height;
1351 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
1353 *x = src_x % g->width + pos / max_height * g->width;
1354 *y = pos % max_height;
1356 else /* frames are ordered diagonally */
1358 *x = src_x + frame * g->offset_x;
1359 *y = src_y + frame * g->offset_y;
1363 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
1365 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
1368 void DrawGraphic(int x, int y, int graphic, int frame)
1371 if (!IN_SCR_FIELD(x, y))
1373 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1374 printf("DrawGraphic(): This should never happen!\n");
1380 DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
1383 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1385 MarkTileDirty(x, y);
1388 void DrawFixedGraphic(int x, int y, int graphic, int frame)
1391 if (!IN_SCR_FIELD(x, y))
1393 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1394 printf("DrawGraphic(): This should never happen!\n");
1399 DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1401 MarkTileDirty(x, y);
1404 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1410 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1412 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
1414 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1418 void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1424 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1425 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1428 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1431 if (!IN_SCR_FIELD(x, y))
1433 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1434 printf("DrawGraphicThruMask(): This should never happen!\n");
1440 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
1443 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1446 MarkTileDirty(x, y);
1449 void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
1452 if (!IN_SCR_FIELD(x, y))
1454 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1455 printf("DrawGraphicThruMask(): This should never happen!\n");
1460 DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1462 MarkTileDirty(x, y);
1465 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
1471 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1473 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1474 dst_x - src_x, dst_y - src_y);
1476 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
1479 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1483 void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
1484 int graphic, int frame)
1489 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1491 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1492 dst_x - src_x, dst_y - src_y);
1493 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1496 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
1498 DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
1500 MarkTileDirty(x / tilesize, y / tilesize);
1503 void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
1509 getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
1510 BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
1513 void DrawMiniGraphic(int x, int y, int graphic)
1515 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1516 MarkTileDirty(x / 2, y / 2);
1519 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1524 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1525 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1528 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
1529 int graphic, int frame,
1530 int cut_mode, int mask_mode)
1535 int width = TILEX, height = TILEY;
1538 if (dx || dy) /* shifted graphic */
1540 if (x < BX1) /* object enters playfield from the left */
1547 else if (x > BX2) /* object enters playfield from the right */
1553 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1559 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1561 else if (dx) /* general horizontal movement */
1562 MarkTileDirty(x + SIGN(dx), y);
1564 if (y < BY1) /* object enters playfield from the top */
1566 if (cut_mode==CUT_BELOW) /* object completely above top border */
1574 else if (y > BY2) /* object enters playfield from the bottom */
1580 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1586 else if (dy > 0 && cut_mode == CUT_ABOVE)
1588 if (y == BY2) /* object completely above bottom border */
1594 MarkTileDirty(x, y + 1);
1595 } /* object leaves playfield to the bottom */
1596 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1598 else if (dy) /* general vertical movement */
1599 MarkTileDirty(x, y + SIGN(dy));
1603 if (!IN_SCR_FIELD(x, y))
1605 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1606 printf("DrawGraphicShifted(): This should never happen!\n");
1612 width = width * TILESIZE_VAR / TILESIZE;
1613 height = height * TILESIZE_VAR / TILESIZE;
1614 cx = cx * TILESIZE_VAR / TILESIZE;
1615 cy = cy * TILESIZE_VAR / TILESIZE;
1616 dx = dx * TILESIZE_VAR / TILESIZE;
1617 dy = dy * TILESIZE_VAR / TILESIZE;
1620 if (width > 0 && height > 0)
1622 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1628 dst_x = FX + x * TILEX_VAR + dx;
1629 dst_y = FY + y * TILEY_VAR + dy;
1631 dst_x = FX + x * TILEX + dx;
1632 dst_y = FY + y * TILEY + dy;
1635 if (mask_mode == USE_MASKING)
1637 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1638 dst_x - src_x, dst_y - src_y);
1639 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1643 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1646 MarkTileDirty(x, y);
1650 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
1651 int graphic, int frame,
1652 int cut_mode, int mask_mode)
1658 int width = TILEX_VAR, height = TILEY_VAR;
1660 int width = TILEX, height = TILEY;
1664 int x2 = x + SIGN(dx);
1665 int y2 = y + SIGN(dy);
1667 /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
1668 int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
1670 /* movement with two-tile animations must be sync'ed with movement position,
1671 not with current GfxFrame (which can be higher when using slow movement) */
1672 int anim_pos = (dx ? ABS(dx) : ABS(dy));
1673 int anim_frames = graphic_info[graphic].anim_frames;
1675 /* (we also need anim_delay here for movement animations with less frames) */
1676 int anim_delay = graphic_info[graphic].anim_delay;
1677 int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
1679 int sync_frame = anim_pos * anim_frames / TILESIZE;
1682 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
1683 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
1685 /* re-calculate animation frame for two-tile movement animation */
1686 frame = getGraphicAnimationFrame(graphic, sync_frame);
1690 printf("::: %d, %d, %d => %d [%d]\n",
1691 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
1693 printf("::: %d, %d => %d\n",
1694 anim_pos, anim_frames, sync_frame);
1699 printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
1700 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
1703 /* check if movement start graphic inside screen area and should be drawn */
1704 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
1706 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
1709 dst_x = FX + x1 * TILEX_VAR;
1710 dst_y = FY + y1 * TILEY_VAR;
1712 dst_x = FX + x1 * TILEX;
1713 dst_y = FY + y1 * TILEY;
1716 if (mask_mode == USE_MASKING)
1718 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1719 dst_x - src_x, dst_y - src_y);
1720 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1724 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1727 MarkTileDirty(x1, y1);
1730 /* check if movement end graphic inside screen area and should be drawn */
1731 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
1733 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
1736 dst_x = FX + x2 * TILEX_VAR;
1737 dst_y = FY + y2 * TILEY_VAR;
1739 dst_x = FX + x2 * TILEX;
1740 dst_y = FY + y2 * TILEY;
1743 if (mask_mode == USE_MASKING)
1745 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1746 dst_x - src_x, dst_y - src_y);
1747 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1751 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1754 MarkTileDirty(x2, y2);
1758 static void DrawGraphicShifted(int x, int y, int dx, int dy,
1759 int graphic, int frame,
1760 int cut_mode, int mask_mode)
1764 DrawGraphic(x, y, graphic, frame);
1769 if (graphic_info[graphic].double_movement) /* EM style movement images */
1770 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1772 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1775 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1776 int frame, int cut_mode)
1778 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1781 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1782 int cut_mode, int mask_mode)
1784 int lx = LEVELX(x), ly = LEVELY(y);
1788 if (IN_LEV_FIELD(lx, ly))
1790 SetRandomAnimationValue(lx, ly);
1792 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1793 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1795 /* do not use double (EM style) movement graphic when not moving */
1796 if (graphic_info[graphic].double_movement && !dx && !dy)
1798 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
1799 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1802 else /* border element */
1804 graphic = el2img(element);
1805 frame = getGraphicAnimationFrame(graphic, -1);
1808 if (element == EL_EXPANDABLE_WALL)
1810 boolean left_stopped = FALSE, right_stopped = FALSE;
1812 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1813 left_stopped = TRUE;
1814 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1815 right_stopped = TRUE;
1817 if (left_stopped && right_stopped)
1819 else if (left_stopped)
1821 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1822 frame = graphic_info[graphic].anim_frames - 1;
1824 else if (right_stopped)
1826 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1827 frame = graphic_info[graphic].anim_frames - 1;
1832 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1833 else if (mask_mode == USE_MASKING)
1834 DrawGraphicThruMask(x, y, graphic, frame);
1836 DrawGraphic(x, y, graphic, frame);
1839 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1840 int cut_mode, int mask_mode)
1842 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1843 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1844 cut_mode, mask_mode);
1847 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1850 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1853 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1856 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1859 void DrawLevelElementThruMask(int x, int y, int element)
1861 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1864 void DrawLevelFieldThruMask(int x, int y)
1866 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1869 /* !!! implementation of quicksand is totally broken !!! */
1870 #define IS_CRUMBLED_TILE(x, y, e) \
1871 (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
1872 !IS_MOVING(x, y) || \
1873 (e) == EL_QUICKSAND_EMPTYING || \
1874 (e) == EL_QUICKSAND_FAST_EMPTYING))
1876 static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
1881 int width, height, cx, cy;
1882 int sx = SCREENX(x), sy = SCREENY(y);
1883 int crumbled_border_size = graphic_info[graphic].border_size;
1886 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1888 for (i = 1; i < 4; i++)
1890 int dxx = (i & 1 ? dx : 0);
1891 int dyy = (i & 2 ? dy : 0);
1894 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1897 /* check if neighbour field is of same crumble type */
1898 boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
1899 graphic_info[graphic].class ==
1900 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
1902 /* return if check prevents inner corner */
1903 if (same == (dxx == dx && dyy == dy))
1907 /* if we reach this point, we have an inner corner */
1909 getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
1912 width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
1913 height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
1914 cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
1915 cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
1917 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1918 width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
1920 width = crumbled_border_size;
1921 height = crumbled_border_size;
1922 cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
1923 cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
1925 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1926 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1930 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
1935 int width, height, bx, by, cx, cy;
1936 int sx = SCREENX(x), sy = SCREENY(y);
1937 int crumbled_border_size = graphic_info[graphic].border_size;
1940 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1942 /* draw simple, sloppy, non-corner-accurate crumbled border */
1945 width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
1946 height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
1947 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1948 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1950 if (dir == 1 || dir == 2) /* left or right crumbled border */
1952 width = crumbled_border_size;
1954 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1957 else /* top or bottom crumbled border */
1960 height = crumbled_border_size;
1962 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1967 BlitBitmap(src_bitmap, drawto_field,
1968 src_x + cx * TILESIZE_VAR / TILESIZE,
1969 src_y + cy * TILESIZE_VAR / TILESIZE,
1970 width * TILESIZE_VAR / TILESIZE,
1971 height * TILESIZE_VAR / TILESIZE,
1972 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
1973 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
1975 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1976 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1979 /* (remaining middle border part must be at least as big as corner part) */
1980 if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
1981 crumbled_border_size >= TILESIZE / 3)
1984 /* correct corners of crumbled border, if needed */
1987 for (i = -1; i <= 1; i+=2)
1989 int xx = x + (dir == 0 || dir == 3 ? i : 0);
1990 int yy = y + (dir == 1 || dir == 2 ? i : 0);
1991 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1994 /* check if neighbour field is of same crumble type */
1995 if (IS_CRUMBLED_TILE(xx, yy, element) &&
1996 graphic_info[graphic].class ==
1997 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
1999 /* no crumbled corner, but continued crumbled border */
2001 int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
2002 int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
2003 int b1 = (i == 1 ? crumbled_border_size :
2004 TILESIZE - 2 * crumbled_border_size);
2006 width = crumbled_border_size;
2007 height = crumbled_border_size;
2009 if (dir == 1 || dir == 2)
2025 BlitBitmap(src_bitmap, drawto_field,
2026 src_x + bx * TILESIZE_VAR / TILESIZE,
2027 src_y + by * TILESIZE_VAR / TILESIZE,
2028 width * TILESIZE_VAR / TILESIZE,
2029 height * TILESIZE_VAR / TILESIZE,
2030 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2031 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2033 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2034 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2039 if (dir == 1 || dir == 2) /* left or right crumbled border */
2041 for (i = -1; i <= 1; i+=2)
2045 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2048 /* check if neighbour field is of same crumble type */
2049 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2050 graphic_info[graphic].class ==
2051 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2053 /* no crumbled corner, but continued crumbled border */
2055 width = crumbled_border_size;
2056 height = crumbled_border_size;
2057 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2058 cy = (i == 1 ? TILEY - crumbled_border_size : 0);
2060 by = (i == 1 ? crumbled_border_size :
2061 TILEY - 2 * crumbled_border_size);
2063 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2064 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2068 else /* top or bottom crumbled border */
2070 for (i = -1; i <= 1; i+=2)
2074 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2077 /* check if neighbour field is of same crumble type */
2078 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2079 graphic_info[graphic].class ==
2080 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2082 /* no crumbled corner, but continued crumbled border */
2084 width = crumbled_border_size;
2085 height = crumbled_border_size;
2086 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
2087 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2088 bx = (i == 1 ? crumbled_border_size :
2089 TILEX - 2 * crumbled_border_size);
2092 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2093 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2100 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
2102 int sx = SCREENX(x), sy = SCREENY(y);
2105 static int xy[4][2] =
2113 if (!IN_LEV_FIELD(x, y))
2116 element = TILE_GFX_ELEMENT(x, y);
2118 /* crumble field itself */
2119 if (IS_CRUMBLED_TILE(x, y, element))
2121 if (!IN_SCR_FIELD(sx, sy))
2124 for (i = 0; i < 4; i++)
2126 int xx = x + xy[i][0];
2127 int yy = y + xy[i][1];
2129 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2132 /* check if neighbour field is of same crumble type */
2134 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2135 graphic_info[graphic].class ==
2136 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2139 if (IS_CRUMBLED_TILE(xx, yy, element))
2143 DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
2146 if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
2147 graphic_info[graphic].anim_frames == 2)
2149 for (i = 0; i < 4; i++)
2151 int dx = (i & 1 ? +1 : -1);
2152 int dy = (i & 2 ? +1 : -1);
2154 DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
2158 MarkTileDirty(sx, sy);
2160 else /* center field not crumbled -- crumble neighbour fields */
2162 for (i = 0; i < 4; i++)
2164 int xx = x + xy[i][0];
2165 int yy = y + xy[i][1];
2166 int sxx = sx + xy[i][0];
2167 int syy = sy + xy[i][1];
2169 if (!IN_LEV_FIELD(xx, yy) ||
2170 !IN_SCR_FIELD(sxx, syy))
2173 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
2176 element = TILE_GFX_ELEMENT(xx, yy);
2178 if (!IS_CRUMBLED_TILE(xx, yy, element))
2181 graphic = el_act2crm(element, ACTION_DEFAULT);
2183 DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
2185 MarkTileDirty(sxx, syy);
2190 void DrawLevelFieldCrumbled(int x, int y)
2194 if (!IN_LEV_FIELD(x, y))
2198 /* !!! CHECK THIS !!! */
2201 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2202 GFX_CRUMBLED(GfxElement[x][y]))
2205 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2206 GfxElement[x][y] != EL_UNDEFINED &&
2207 GFX_CRUMBLED(GfxElement[x][y]))
2209 DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
2216 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
2218 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
2221 DrawLevelFieldCrumbledExt(x, y, graphic, 0);
2224 void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
2227 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
2228 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
2229 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
2230 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
2231 int sx = SCREENX(x), sy = SCREENY(y);
2233 DrawGraphic(sx, sy, graphic1, frame1);
2234 DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
2237 void DrawLevelFieldCrumbledNeighbours(int x, int y)
2239 int sx = SCREENX(x), sy = SCREENY(y);
2240 static int xy[4][2] =
2249 for (i = 0; i < 4; i++)
2251 int xx = x + xy[i][0];
2252 int yy = y + xy[i][1];
2253 int sxx = sx + xy[i][0];
2254 int syy = sy + xy[i][1];
2256 if (!IN_LEV_FIELD(xx, yy) ||
2257 !IN_SCR_FIELD(sxx, syy) ||
2258 !GFX_CRUMBLED(Feld[xx][yy]) ||
2262 DrawLevelField(xx, yy);
2266 static int getBorderElement(int x, int y)
2270 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
2271 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
2272 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
2273 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2274 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
2275 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
2276 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
2278 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2279 int steel_position = (x == -1 && y == -1 ? 0 :
2280 x == lev_fieldx && y == -1 ? 1 :
2281 x == -1 && y == lev_fieldy ? 2 :
2282 x == lev_fieldx && y == lev_fieldy ? 3 :
2283 x == -1 || x == lev_fieldx ? 4 :
2284 y == -1 || y == lev_fieldy ? 5 : 6);
2286 return border[steel_position][steel_type];
2289 void DrawScreenElement(int x, int y, int element)
2291 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2292 DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
2295 void DrawLevelElement(int x, int y, int element)
2297 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2298 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2301 void DrawScreenField(int x, int y)
2303 int lx = LEVELX(x), ly = LEVELY(y);
2304 int element, content;
2306 if (!IN_LEV_FIELD(lx, ly))
2308 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
2311 element = getBorderElement(lx, ly);
2313 DrawScreenElement(x, y, element);
2318 element = Feld[lx][ly];
2319 content = Store[lx][ly];
2321 if (IS_MOVING(lx, ly))
2323 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
2324 boolean cut_mode = NO_CUTTING;
2326 if (element == EL_QUICKSAND_EMPTYING ||
2327 element == EL_QUICKSAND_FAST_EMPTYING ||
2328 element == EL_MAGIC_WALL_EMPTYING ||
2329 element == EL_BD_MAGIC_WALL_EMPTYING ||
2330 element == EL_DC_MAGIC_WALL_EMPTYING ||
2331 element == EL_AMOEBA_DROPPING)
2332 cut_mode = CUT_ABOVE;
2333 else if (element == EL_QUICKSAND_FILLING ||
2334 element == EL_QUICKSAND_FAST_FILLING ||
2335 element == EL_MAGIC_WALL_FILLING ||
2336 element == EL_BD_MAGIC_WALL_FILLING ||
2337 element == EL_DC_MAGIC_WALL_FILLING)
2338 cut_mode = CUT_BELOW;
2341 if (lx == 9 && ly == 1)
2342 printf("::: %s [%d] [%d, %d] [%d]\n",
2343 EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
2344 el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
2345 element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
2346 element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
2347 GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
2350 if (cut_mode == CUT_ABOVE)
2352 DrawScreenElement(x, y, element);
2354 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2357 DrawScreenElement(x, y, EL_EMPTY);
2360 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
2361 else if (cut_mode == NO_CUTTING)
2362 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
2365 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
2368 if (cut_mode == CUT_BELOW &&
2369 IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
2370 DrawLevelElement(lx, ly + 1, element);
2374 if (content == EL_ACID)
2376 int dir = MovDir[lx][ly];
2377 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
2378 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
2380 DrawLevelElementThruMask(newlx, newly, EL_ACID);
2383 else if (IS_BLOCKED(lx, ly))
2388 boolean cut_mode = NO_CUTTING;
2389 int element_old, content_old;
2391 Blocked2Moving(lx, ly, &oldx, &oldy);
2394 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2395 MovDir[oldx][oldy] == MV_RIGHT);
2397 element_old = Feld[oldx][oldy];
2398 content_old = Store[oldx][oldy];
2400 if (element_old == EL_QUICKSAND_EMPTYING ||
2401 element_old == EL_QUICKSAND_FAST_EMPTYING ||
2402 element_old == EL_MAGIC_WALL_EMPTYING ||
2403 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2404 element_old == EL_DC_MAGIC_WALL_EMPTYING ||
2405 element_old == EL_AMOEBA_DROPPING)
2406 cut_mode = CUT_ABOVE;
2408 DrawScreenElement(x, y, EL_EMPTY);
2411 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2413 else if (cut_mode == NO_CUTTING)
2414 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2417 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2420 else if (IS_DRAWABLE(element))
2421 DrawScreenElement(x, y, element);
2423 DrawScreenElement(x, y, EL_EMPTY);
2426 void DrawLevelField(int x, int y)
2428 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2429 DrawScreenField(SCREENX(x), SCREENY(y));
2430 else if (IS_MOVING(x, y))
2434 Moving2Blocked(x, y, &newx, &newy);
2435 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2436 DrawScreenField(SCREENX(newx), SCREENY(newy));
2438 else if (IS_BLOCKED(x, y))
2442 Blocked2Moving(x, y, &oldx, &oldy);
2443 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2444 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2448 void DrawMiniElement(int x, int y, int element)
2452 graphic = el2edimg(element);
2453 DrawMiniGraphic(x, y, graphic);
2456 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2458 int x = sx + scroll_x, y = sy + scroll_y;
2460 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2461 DrawMiniElement(sx, sy, EL_EMPTY);
2462 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2463 DrawMiniElement(sx, sy, Feld[x][y]);
2465 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
2468 void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
2469 int x, int y, int xsize, int ysize,
2470 int tile_width, int tile_height)
2474 int dst_x = startx + x * tile_width;
2475 int dst_y = starty + y * tile_height;
2476 int width = graphic_info[graphic].width;
2477 int height = graphic_info[graphic].height;
2478 int inner_width_raw = MAX(width - 2 * tile_width, tile_width);
2479 int inner_height_raw = MAX(height - 2 * tile_height, tile_height);
2480 int inner_width = inner_width_raw - (inner_width_raw % tile_width);
2481 int inner_height = inner_height_raw - (inner_height_raw % tile_height);
2482 int inner_sx = (width >= 3 * tile_width ? tile_width : 0);
2483 int inner_sy = (height >= 3 * tile_height ? tile_height : 0);
2484 boolean draw_masked = graphic_info[graphic].draw_masked;
2486 getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2488 if (src_bitmap == NULL || width < tile_width || height < tile_height)
2490 ClearRectangle(drawto, dst_x, dst_y, tile_width, tile_height);
2494 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - tile_width :
2495 inner_sx + (x - 1) * tile_width % inner_width);
2496 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - tile_height :
2497 inner_sy + (y - 1) * tile_height % inner_height);
2501 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
2502 dst_x - src_x, dst_y - src_y);
2503 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2507 BlitBitmap(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2511 void DrawEnvelopeBackground(int graphic, int startx, int starty,
2512 int x, int y, int xsize, int ysize, int font_nr)
2514 int font_width = getFontWidth(font_nr);
2515 int font_height = getFontHeight(font_nr);
2517 DrawEnvelopeBackgroundTiles(graphic, startx, starty, x, y, xsize, ysize,
2518 font_width, font_height);
2521 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
2523 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2524 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2525 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2526 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2527 boolean no_delay = (tape.warp_forward);
2528 unsigned int anim_delay = 0;
2529 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2530 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2531 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2532 int font_width = getFontWidth(font_nr);
2533 int font_height = getFontHeight(font_nr);
2534 int max_xsize = level.envelope[envelope_nr].xsize;
2535 int max_ysize = level.envelope[envelope_nr].ysize;
2536 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2537 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2538 int xend = max_xsize;
2539 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2540 int xstep = (xstart < xend ? 1 : 0);
2541 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2544 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2546 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2547 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2548 int sx = SX + (SXSIZE - xsize * font_width) / 2;
2549 int sy = SY + (SYSIZE - ysize * font_height) / 2;
2552 SetDrawtoField(DRAW_BUFFERED);
2555 BlitScreenToBitmap(backbuffer);
2557 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2560 SetDrawtoField(DRAW_BACKBUFFER);
2562 for (yy = 0; yy < ysize; yy++)
2563 for (xx = 0; xx < xsize; xx++)
2564 DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
2567 DrawTextBuffer(sx + font_width, sy + font_height,
2568 level.envelope[envelope_nr].text, font_nr, max_xsize,
2569 xsize - 2, ysize - 2, 0, mask_mode,
2570 level.envelope[envelope_nr].autowrap,
2571 level.envelope[envelope_nr].centered, FALSE);
2573 DrawTextToTextArea(sx + font_width, sy + font_height,
2574 level.envelope[envelope_nr].text, font_nr, max_xsize,
2575 xsize - 2, ysize - 2, mask_mode);
2578 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2581 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2585 void ShowEnvelope(int envelope_nr)
2587 int element = EL_ENVELOPE_1 + envelope_nr;
2588 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2589 int sound_opening = element_info[element].sound[ACTION_OPENING];
2590 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2591 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2592 boolean no_delay = (tape.warp_forward);
2593 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2594 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2595 int anim_mode = graphic_info[graphic].anim_mode;
2596 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2597 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2599 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2601 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2603 if (anim_mode == ANIM_DEFAULT)
2604 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
2606 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
2609 Delay(wait_delay_value);
2611 WaitForEventToContinue();
2613 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2615 if (anim_mode != ANIM_NONE)
2616 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
2618 if (anim_mode == ANIM_DEFAULT)
2619 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
2621 game.envelope_active = FALSE;
2623 SetDrawtoField(DRAW_BUFFERED);
2625 redraw_mask |= REDRAW_FIELD;
2629 static void setRequestPosition(int *x, int *y, boolean add_border_size)
2631 int border_size = request.border_size;
2632 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2633 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2634 int sx = sx_center - request.width / 2;
2635 int sy = sy_center - request.height / 2;
2637 if (add_border_size)
2647 void DrawEnvelopeRequest(char *text)
2649 char *text_final = text;
2650 char *text_door_style = NULL;
2651 int graphic = IMG_BACKGROUND_REQUEST;
2652 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2653 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2654 int font_nr = FONT_REQUEST;
2655 int font_width = getFontWidth(font_nr);
2656 int font_height = getFontHeight(font_nr);
2657 int border_size = request.border_size;
2658 int line_spacing = request.line_spacing;
2659 int line_height = font_height + line_spacing;
2660 int text_width = request.width - 2 * border_size;
2661 int text_height = request.height - 2 * border_size;
2662 int line_length = text_width / font_width;
2663 int max_lines = text_height / line_height;
2664 int width = request.width;
2665 int height = request.height;
2666 int tile_size = request.step_offset;
2667 int x_steps = width / tile_size;
2668 int y_steps = height / tile_size;
2672 if (request.wrap_single_words)
2674 char *src_text_ptr, *dst_text_ptr;
2676 text_door_style = checked_malloc(2 * strlen(text) + 1);
2678 src_text_ptr = text;
2679 dst_text_ptr = text_door_style;
2681 while (*src_text_ptr)
2683 if (*src_text_ptr == ' ' ||
2684 *src_text_ptr == '?' ||
2685 *src_text_ptr == '!')
2686 *dst_text_ptr++ = '\n';
2688 if (*src_text_ptr != ' ')
2689 *dst_text_ptr++ = *src_text_ptr;
2694 *dst_text_ptr = '\0';
2696 text_final = text_door_style;
2699 setRequestPosition(&sx, &sy, FALSE);
2701 ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
2703 for (y = 0; y < y_steps; y++)
2704 for (x = 0; x < x_steps; x++)
2705 DrawEnvelopeBackgroundTiles(graphic, sx, sy,
2706 x, y, x_steps, y_steps,
2707 tile_size, tile_size);
2709 DrawTextBuffer(sx + border_size, sy + border_size, text_final, font_nr,
2710 line_length, -1, max_lines, line_spacing, mask_mode,
2711 request.autowrap, request.centered, FALSE);
2713 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2714 RedrawGadget(tool_gadget[i]);
2716 // store readily prepared envelope request for later use when animating
2717 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2721 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2722 BlitBitmap(bitmap_db_cross, backbuffer, sx, sy, width, height, sx, sy);
2724 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2729 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2731 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2737 if (text_door_style)
2738 free(text_door_style);
2743 void AnimateEnvelopeRequest(int anim_mode, int action)
2745 int graphic = IMG_BACKGROUND_REQUEST;
2746 boolean draw_masked = graphic_info[graphic].draw_masked;
2748 int delay_value_normal = request.step_delay;
2749 int delay_value_fast = delay_value_normal / 2;
2751 int delay_value_normal = GameFrameDelay;
2752 int delay_value_fast = FfwdFrameDelay;
2754 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2755 boolean no_delay = (tape.warp_forward);
2756 int delay_value = (ffwd_delay ? delay_value_fast : delay_value_normal);
2757 int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0);
2758 unsigned int anim_delay = 0;
2760 int width = request.width;
2761 int height = request.height;
2762 int tile_size = request.step_offset;
2763 int max_xsize = width / tile_size;
2764 int max_ysize = height / tile_size;
2765 int max_xsize_inner = max_xsize - 2;
2766 int max_ysize_inner = max_ysize - 2;
2768 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize_inner : 0);
2769 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize_inner : 0);
2770 int xend = max_xsize_inner;
2771 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize_inner : 0);
2772 int xstep = (xstart < xend ? 1 : 0);
2773 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2776 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2778 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2779 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2780 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2781 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2782 int src_x = sx_center - width / 2;
2783 int src_y = sy_center - height / 2;
2784 int dst_x = sx_center - xsize * tile_size / 2;
2785 int dst_y = sy_center - ysize * tile_size / 2;
2786 int xsize_size_left = (xsize - 1) * tile_size;
2787 int ysize_size_top = (ysize - 1) * tile_size;
2788 int max_xsize_pos = (max_xsize - 1) * tile_size;
2789 int max_ysize_pos = (max_ysize - 1) * tile_size;
2792 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2795 for (yy = 0; yy < 2; yy++)
2797 for (xx = 0; xx < 2; xx++)
2799 int src_xx = src_x + xx * max_xsize_pos;
2800 int src_yy = src_y + yy * max_ysize_pos;
2801 int dst_xx = dst_x + xx * xsize_size_left;
2802 int dst_yy = dst_y + yy * ysize_size_top;
2803 int xx_size = (xx ? tile_size : xsize_size_left);
2804 int yy_size = (yy ? tile_size : ysize_size_top);
2807 BlitBitmapMasked(bitmap_db_cross, backbuffer,
2808 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2810 BlitBitmap(bitmap_db_cross, backbuffer,
2811 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2815 BlitBitmap(bitmap_db_cross, backbuffer,
2817 xsize_size_left, ysize_size_top,
2819 BlitBitmap(bitmap_db_cross, backbuffer,
2820 src_x + max_xsize_pos, src_y,
2821 tile_size, ysize_size_top,
2822 dst_x + xsize_size_left, dst_y);
2823 BlitBitmap(bitmap_db_cross, backbuffer,
2824 src_x, src_y + max_ysize_pos,
2825 xsize_size_left, tile_size,
2826 dst_x, dst_y + ysize_size_top);
2827 BlitBitmap(bitmap_db_cross, backbuffer,
2828 src_x + max_xsize_pos, src_y + max_ysize_pos,
2829 tile_size, tile_size,
2830 dst_x + xsize_size_left, dst_y + ysize_size_top);
2834 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2835 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
2837 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2847 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2853 void AnimateEnvelopeRequest(char *text, int anim_mode, int action)
2856 int envelope_nr = 0;
2859 int graphic = IMG_BACKGROUND_REQUEST;
2861 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2863 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2864 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2865 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2866 boolean no_delay = (tape.warp_forward);
2867 unsigned int anim_delay = 0;
2868 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2869 int anim_delay_value = (no_delay ? 0 : frame_delay_value + 500 * 0);
2871 int max_word_len = maxWordLengthInString(text);
2872 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
2874 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2876 int font_width = getFontWidth(font_nr);
2877 int font_height = getFontHeight(font_nr);
2878 int line_spacing = 2 * 1;
2882 int max_xsize = DXSIZE / font_width;
2883 // int max_ysize = DYSIZE / font_height;
2884 int max_ysize = DYSIZE / (font_height + line_spacing);
2886 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
2887 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
2891 int max_xsize = level.envelope[envelope_nr].xsize;
2892 int max_ysize = level.envelope[envelope_nr].ysize;
2894 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2895 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2896 int xend = max_xsize;
2897 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2898 int xstep = (xstart < xend ? 1 : 0);
2899 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2904 char *text_copy = getStringCopy(text);
2907 font_nr = FONT_TEXT_2;
2909 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
2911 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
2912 font_nr = FONT_TEXT_1;
2915 int max_word_len = 0;
2917 char *text_copy = getStringCopy(text);
2919 font_nr = FONT_TEXT_2;
2921 for (text_ptr = text; *text_ptr; text_ptr++)
2923 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2925 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
2927 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
2928 font_nr = FONT_TEXT_1;
2937 for (text_ptr = text_copy; *text_ptr; text_ptr++)
2938 if (*text_ptr == ' ')
2943 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
2944 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
2946 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
2947 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
2950 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2952 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2953 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2954 int sx = SX + (SXSIZE - xsize * font_width) / 2;
2955 // int sy = SX + (SYSIZE - ysize * font_height) / 2;
2956 int sy = SY + (SYSIZE - ysize * (font_height + line_spacing)) / 2;
2960 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2962 SetDrawtoField(DRAW_BUFFERED);
2965 BlitScreenToBitmap(backbuffer);
2967 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2970 SetDrawtoField(DRAW_BACKBUFFER);
2973 for (yy = 0; yy < ysize; yy++)
2974 for (xx = 0; xx < xsize; xx++)
2975 DrawEnvelopeBackgroundTiles(graphic, sx, sy, xx, yy, xsize, ysize,
2976 getFontWidth(font_nr),
2977 getFontHeight(font_nr) + line_spacing);
2982 DrawTextBuffer(sx + font_width, sy + font_height + 8,
2983 text_copy, font_nr, max_xsize,
2984 xsize - 2, ysize - 2, line_spacing, mask_mode,
2985 FALSE, TRUE, FALSE);
2987 DrawTextBuffer(sx + font_width, sy + font_height,
2988 level.envelope[envelope_nr].text, font_nr, max_xsize,
2989 xsize - 2, ysize - 2, 0, mask_mode,
2990 level.envelope[envelope_nr].autowrap,
2991 level.envelope[envelope_nr].centered, FALSE);
2995 DrawTextToTextArea(sx + font_width, sy + font_height,
2996 level.envelope[envelope_nr].text, font_nr, max_xsize,
2997 xsize - 2, ysize - 2, mask_mode);
3000 /* copy request gadgets to door backbuffer */
3003 if ((ysize - 2) > 13)
3004 BlitBitmap(bitmap_db_door, drawto,
3005 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3006 DOOR_GFX_PAGEY1 + 13 * font_height,
3007 (xsize - 2) * font_width,
3008 (ysize - 2 - 13) * font_height,
3010 sy + font_height * (1 + 13));
3012 if ((ysize - 2) > 13)
3013 BlitBitmap(bitmap_db_door, drawto,
3014 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3015 DOOR_GFX_PAGEY1 + 11 * (font_height + line_spacing * 0),
3016 (xsize - 2) * font_width,
3017 (ysize - 2 - 13) * (font_height + line_spacing),
3019 sy + (font_height + line_spacing) * (1 + 13));
3021 if ((ysize - 2) > 13)
3022 BlitBitmap(bitmap_db_door, drawto,
3023 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3024 DOOR_GFX_PAGEY1 + 13 * font_height,
3025 (xsize - 2) * font_width,
3026 (ysize - 2 - 13) * font_height,
3028 sy + font_height * (1 + 13));
3032 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3033 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
3035 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3045 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
3055 void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
3058 int last_game_status = game_status; /* save current game status */
3059 // int last_draw_background_mask = gfx.draw_background_mask;
3062 int graphic = IMG_BACKGROUND_REQUEST;
3063 int sound_opening = SND_REQUEST_OPENING;
3064 int sound_closing = SND_REQUEST_CLOSING;
3066 int envelope_nr = 0;
3067 int element = EL_ENVELOPE_1 + envelope_nr;
3068 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3069 int sound_opening = element_info[element].sound[ACTION_OPENING];
3070 int sound_closing = element_info[element].sound[ACTION_CLOSING];
3073 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3074 boolean no_delay = (tape.warp_forward);
3075 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
3076 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
3078 int anim_mode = graphic_info[graphic].anim_mode;
3079 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
3080 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
3082 char *text_copy = getStringCopy(text);
3085 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3086 if (*text_ptr == ' ')
3091 if (game_status == GAME_MODE_PLAYING)
3093 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3094 BlitScreenToBitmap_EM(backbuffer);
3095 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3096 BlitScreenToBitmap_SP(backbuffer);
3099 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3103 SetDrawtoField(DRAW_BACKBUFFER);
3105 // SetDrawBackgroundMask(REDRAW_NONE);
3107 if (action == ACTION_OPENING)
3109 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3112 if (req_state & REQ_ASK)
3114 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
3115 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
3117 else if (req_state & REQ_CONFIRM)
3119 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
3121 else if (req_state & REQ_PLAYER)
3123 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
3124 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
3125 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
3126 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
3131 DrawEnvelopeRequest(text);
3133 DrawEnvelopeRequest(text_copy);
3136 if (game_status != GAME_MODE_MAIN)
3140 /* force DOOR font inside door area */
3141 game_status = GAME_MODE_PSEUDO_DOOR;
3144 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
3146 if (action == ACTION_OPENING)
3148 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
3150 if (anim_mode == ANIM_DEFAULT)
3151 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
3153 AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
3157 Delay(wait_delay_value);
3159 WaitForEventToContinue();
3164 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
3166 if (anim_mode != ANIM_NONE)
3167 AnimateEnvelopeRequest(main_anim_mode, ACTION_CLOSING);
3169 if (anim_mode == ANIM_DEFAULT)
3170 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_CLOSING);
3173 game.envelope_active = FALSE;
3176 // game_status = last_game_status; /* restore current game status */
3178 if (action == ACTION_CLOSING)
3180 if (game_status != GAME_MODE_MAIN)
3183 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3186 SetDrawtoField(DRAW_BUFFERED);
3189 // SetDrawBackgroundMask(last_draw_background_mask);
3192 redraw_mask = REDRAW_FIELD;
3193 // redraw_mask |= REDRAW_ALL;
3195 redraw_mask |= REDRAW_FIELD;
3199 if (game_status == GAME_MODE_MAIN)
3204 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
3205 game_status = last_game_status; /* restore current game status */
3208 if (action == ACTION_CLOSING &&
3209 game_status == GAME_MODE_PLAYING &&
3210 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3211 SetDrawtoField(DRAW_BUFFERED);
3213 if (game_status == GAME_MODE_PLAYING &&
3214 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3215 SetDrawtoField(DRAW_BUFFERED);
3227 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
3231 int graphic = el2preimg(element);
3233 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
3234 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
3242 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
3243 SetDrawBackgroundMask(REDRAW_FIELD);
3245 SetDrawBackgroundMask(REDRAW_NONE);
3250 for (x = BX1; x <= BX2; x++)
3251 for (y = BY1; y <= BY2; y++)
3252 DrawScreenField(x, y);
3254 redraw_mask |= REDRAW_FIELD;
3257 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
3261 for (x = 0; x < size_x; x++)
3262 for (y = 0; y < size_y; y++)
3263 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
3265 redraw_mask |= REDRAW_FIELD;
3268 static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
3270 boolean show_level_border = (BorderElement != EL_EMPTY);
3271 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3272 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3273 int tile_size = preview.tile_size;
3274 int preview_width = preview.xsize * tile_size;
3275 int preview_height = preview.ysize * tile_size;
3276 int real_preview_xsize = MIN(level_xsize, preview.xsize);
3277 int real_preview_ysize = MIN(level_ysize, preview.ysize);
3278 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
3279 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
3282 DrawBackground(dst_x, dst_y, preview_width, preview_height);
3284 dst_x += (preview_width - real_preview_xsize * tile_size) / 2;
3285 dst_y += (preview_height - real_preview_ysize * tile_size) / 2;
3287 for (x = 0; x < real_preview_xsize; x++)
3289 for (y = 0; y < real_preview_ysize; y++)
3291 int lx = from_x + x + (show_level_border ? -1 : 0);
3292 int ly = from_y + y + (show_level_border ? -1 : 0);
3293 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
3294 getBorderElement(lx, ly));
3296 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
3297 element, tile_size);
3301 redraw_mask |= REDRAW_MICROLEVEL;
3304 #define MICROLABEL_EMPTY 0
3305 #define MICROLABEL_LEVEL_NAME 1
3306 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
3307 #define MICROLABEL_LEVEL_AUTHOR 3
3308 #define MICROLABEL_IMPORTED_FROM_HEAD 4
3309 #define MICROLABEL_IMPORTED_FROM 5
3310 #define MICROLABEL_IMPORTED_BY_HEAD 6
3311 #define MICROLABEL_IMPORTED_BY 7
3313 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
3315 int max_text_width = SXSIZE;
3316 int font_width = getFontWidth(font_nr);
3318 if (pos->align == ALIGN_CENTER)
3319 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
3320 else if (pos->align == ALIGN_RIGHT)
3321 max_text_width = pos->x;
3323 max_text_width = SXSIZE - pos->x;
3325 return max_text_width / font_width;
3328 static void DrawPreviewLevelLabelExt(int mode)
3330 struct TextPosInfo *pos = &menu.main.text.level_info_2;
3331 char label_text[MAX_OUTPUT_LINESIZE + 1];
3332 int max_len_label_text;
3334 int font_nr = pos->font;
3337 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3338 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3339 mode == MICROLABEL_IMPORTED_BY_HEAD)
3340 font_nr = pos->font_alt;
3342 int font_nr = FONT_TEXT_2;
3345 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3346 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3347 mode == MICROLABEL_IMPORTED_BY_HEAD)
3348 font_nr = FONT_TEXT_3;
3352 max_len_label_text = getMaxTextLength(pos, font_nr);
3354 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3358 if (pos->size != -1)
3359 max_len_label_text = pos->size;
3362 for (i = 0; i < max_len_label_text; i++)
3363 label_text[i] = ' ';
3364 label_text[max_len_label_text] = '\0';
3366 if (strlen(label_text) > 0)
3369 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3371 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3372 int lypos = MICROLABEL2_YPOS;
3374 DrawText(lxpos, lypos, label_text, font_nr);
3379 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3380 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3381 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3382 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3383 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3384 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3385 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3386 max_len_label_text);
3387 label_text[max_len_label_text] = '\0';
3389 if (strlen(label_text) > 0)
3392 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3394 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3395 int lypos = MICROLABEL2_YPOS;
3397 DrawText(lxpos, lypos, label_text, font_nr);
3401 redraw_mask |= REDRAW_MICROLEVEL;
3404 static void DrawPreviewLevelExt(boolean restart)
3406 static unsigned int scroll_delay = 0;
3407 static unsigned int label_delay = 0;
3408 static int from_x, from_y, scroll_direction;
3409 static int label_state, label_counter;
3410 unsigned int scroll_delay_value = preview.step_delay;
3411 boolean show_level_border = (BorderElement != EL_EMPTY);
3412 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3413 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3414 int last_game_status = game_status; /* save current game status */
3417 /* force PREVIEW font on preview level */
3418 game_status = GAME_MODE_PSEUDO_PREVIEW;
3426 if (preview.anim_mode == ANIM_CENTERED)
3428 if (level_xsize > preview.xsize)
3429 from_x = (level_xsize - preview.xsize) / 2;
3430 if (level_ysize > preview.ysize)
3431 from_y = (level_ysize - preview.ysize) / 2;
3434 from_x += preview.xoffset;
3435 from_y += preview.yoffset;
3437 scroll_direction = MV_RIGHT;
3441 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3442 DrawPreviewLevelLabelExt(label_state);
3444 /* initialize delay counters */
3445 DelayReached(&scroll_delay, 0);
3446 DelayReached(&label_delay, 0);
3448 if (leveldir_current->name)
3450 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3451 char label_text[MAX_OUTPUT_LINESIZE + 1];
3453 int font_nr = pos->font;
3455 int font_nr = FONT_TEXT_1;
3458 int max_len_label_text = getMaxTextLength(pos, font_nr);
3460 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3468 if (pos->size != -1)
3469 max_len_label_text = pos->size;
3472 strncpy(label_text, leveldir_current->name, max_len_label_text);
3473 label_text[max_len_label_text] = '\0';
3476 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3478 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3479 lypos = SY + MICROLABEL1_YPOS;
3481 DrawText(lxpos, lypos, label_text, font_nr);
3485 game_status = last_game_status; /* restore current game status */
3490 /* scroll preview level, if needed */
3491 if (preview.anim_mode != ANIM_NONE &&
3492 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3493 DelayReached(&scroll_delay, scroll_delay_value))
3495 switch (scroll_direction)
3500 from_x -= preview.step_offset;
3501 from_x = (from_x < 0 ? 0 : from_x);
3504 scroll_direction = MV_UP;
3508 if (from_x < level_xsize - preview.xsize)
3510 from_x += preview.step_offset;
3511 from_x = (from_x > level_xsize - preview.xsize ?
3512 level_xsize - preview.xsize : from_x);
3515 scroll_direction = MV_DOWN;
3521 from_y -= preview.step_offset;
3522 from_y = (from_y < 0 ? 0 : from_y);
3525 scroll_direction = MV_RIGHT;
3529 if (from_y < level_ysize - preview.ysize)
3531 from_y += preview.step_offset;
3532 from_y = (from_y > level_ysize - preview.ysize ?
3533 level_ysize - preview.ysize : from_y);
3536 scroll_direction = MV_LEFT;
3543 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3546 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3547 /* redraw micro level label, if needed */
3548 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3549 !strEqual(level.author, ANONYMOUS_NAME) &&
3550 !strEqual(level.author, leveldir_current->name) &&
3551 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3553 int max_label_counter = 23;
3555 if (leveldir_current->imported_from != NULL &&
3556 strlen(leveldir_current->imported_from) > 0)
3557 max_label_counter += 14;
3558 if (leveldir_current->imported_by != NULL &&
3559 strlen(leveldir_current->imported_by) > 0)
3560 max_label_counter += 14;
3562 label_counter = (label_counter + 1) % max_label_counter;
3563 label_state = (label_counter >= 0 && label_counter <= 7 ?
3564 MICROLABEL_LEVEL_NAME :
3565 label_counter >= 9 && label_counter <= 12 ?
3566 MICROLABEL_LEVEL_AUTHOR_HEAD :
3567 label_counter >= 14 && label_counter <= 21 ?
3568 MICROLABEL_LEVEL_AUTHOR :
3569 label_counter >= 23 && label_counter <= 26 ?
3570 MICROLABEL_IMPORTED_FROM_HEAD :
3571 label_counter >= 28 && label_counter <= 35 ?
3572 MICROLABEL_IMPORTED_FROM :
3573 label_counter >= 37 && label_counter <= 40 ?
3574 MICROLABEL_IMPORTED_BY_HEAD :
3575 label_counter >= 42 && label_counter <= 49 ?
3576 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3578 if (leveldir_current->imported_from == NULL &&
3579 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3580 label_state == MICROLABEL_IMPORTED_FROM))
3581 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3582 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3584 DrawPreviewLevelLabelExt(label_state);
3587 game_status = last_game_status; /* restore current game status */
3590 void DrawPreviewLevelInitial()
3592 DrawPreviewLevelExt(TRUE);
3595 void DrawPreviewLevelAnimation()
3597 DrawPreviewLevelExt(FALSE);
3600 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3601 int graphic, int sync_frame, int mask_mode)
3603 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3605 if (mask_mode == USE_MASKING)
3606 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3608 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3611 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3612 int graphic, int sync_frame,
3615 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3617 if (mask_mode == USE_MASKING)
3618 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3620 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3623 inline void DrawGraphicAnimation(int x, int y, int graphic)
3625 int lx = LEVELX(x), ly = LEVELY(y);
3627 if (!IN_SCR_FIELD(x, y))
3631 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3632 graphic, GfxFrame[lx][ly], NO_MASKING);
3634 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3635 graphic, GfxFrame[lx][ly], NO_MASKING);
3637 MarkTileDirty(x, y);
3640 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3642 int lx = LEVELX(x), ly = LEVELY(y);
3644 if (!IN_SCR_FIELD(x, y))
3647 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3648 graphic, GfxFrame[lx][ly], NO_MASKING);
3649 MarkTileDirty(x, y);
3652 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3654 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3657 void DrawLevelElementAnimation(int x, int y, int element)
3659 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3661 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3664 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3666 int sx = SCREENX(x), sy = SCREENY(y);
3668 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3671 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3674 DrawGraphicAnimation(sx, sy, graphic);
3677 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3678 DrawLevelFieldCrumbled(x, y);
3680 if (GFX_CRUMBLED(Feld[x][y]))
3681 DrawLevelFieldCrumbled(x, y);
3685 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3687 int sx = SCREENX(x), sy = SCREENY(y);
3690 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3693 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3695 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3698 DrawGraphicAnimation(sx, sy, graphic);
3700 if (GFX_CRUMBLED(element))
3701 DrawLevelFieldCrumbled(x, y);
3704 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3706 if (player->use_murphy)
3708 /* this works only because currently only one player can be "murphy" ... */
3709 static int last_horizontal_dir = MV_LEFT;
3710 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3712 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3713 last_horizontal_dir = move_dir;
3715 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3717 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3719 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3725 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3728 static boolean equalGraphics(int graphic1, int graphic2)
3730 struct GraphicInfo *g1 = &graphic_info[graphic1];
3731 struct GraphicInfo *g2 = &graphic_info[graphic2];
3733 return (g1->bitmap == g2->bitmap &&
3734 g1->src_x == g2->src_x &&
3735 g1->src_y == g2->src_y &&
3736 g1->anim_frames == g2->anim_frames &&
3737 g1->anim_delay == g2->anim_delay &&
3738 g1->anim_mode == g2->anim_mode);
3741 void DrawAllPlayers()
3745 for (i = 0; i < MAX_PLAYERS; i++)
3746 if (stored_player[i].active)
3747 DrawPlayer(&stored_player[i]);
3750 void DrawPlayerField(int x, int y)
3752 if (!IS_PLAYER(x, y))
3755 DrawPlayer(PLAYERINFO(x, y));
3758 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3760 void DrawPlayer(struct PlayerInfo *player)
3762 int jx = player->jx;
3763 int jy = player->jy;
3764 int move_dir = player->MovDir;
3765 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3766 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3767 int last_jx = (player->is_moving ? jx - dx : jx);
3768 int last_jy = (player->is_moving ? jy - dy : jy);
3769 int next_jx = jx + dx;
3770 int next_jy = jy + dy;
3771 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3772 boolean player_is_opaque = FALSE;
3773 int sx = SCREENX(jx), sy = SCREENY(jy);
3774 int sxx = 0, syy = 0;
3775 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3777 int action = ACTION_DEFAULT;
3778 int last_player_graphic = getPlayerGraphic(player, move_dir);
3779 int last_player_frame = player->Frame;
3782 /* GfxElement[][] is set to the element the player is digging or collecting;
3783 remove also for off-screen player if the player is not moving anymore */
3784 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3785 GfxElement[jx][jy] = EL_UNDEFINED;
3787 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3791 if (!IN_LEV_FIELD(jx, jy))
3793 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3794 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3795 printf("DrawPlayerField(): This should never happen!\n");
3800 if (element == EL_EXPLOSION)
3803 action = (player->is_pushing ? ACTION_PUSHING :
3804 player->is_digging ? ACTION_DIGGING :
3805 player->is_collecting ? ACTION_COLLECTING :
3806 player->is_moving ? ACTION_MOVING :
3807 player->is_snapping ? ACTION_SNAPPING :
3808 player->is_dropping ? ACTION_DROPPING :
3809 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3811 if (player->is_waiting)
3812 move_dir = player->dir_waiting;
3814 InitPlayerGfxAnimation(player, action, move_dir);
3816 /* ----------------------------------------------------------------------- */
3817 /* draw things in the field the player is leaving, if needed */
3818 /* ----------------------------------------------------------------------- */
3820 if (player->is_moving)
3822 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
3824 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
3826 if (last_element == EL_DYNAMITE_ACTIVE ||
3827 last_element == EL_EM_DYNAMITE_ACTIVE ||
3828 last_element == EL_SP_DISK_RED_ACTIVE)
3829 DrawDynamite(last_jx, last_jy);
3831 DrawLevelFieldThruMask(last_jx, last_jy);
3833 else if (last_element == EL_DYNAMITE_ACTIVE ||
3834 last_element == EL_EM_DYNAMITE_ACTIVE ||
3835 last_element == EL_SP_DISK_RED_ACTIVE)
3836 DrawDynamite(last_jx, last_jy);
3838 /* !!! this is not enough to prevent flickering of players which are
3839 moving next to each others without a free tile between them -- this
3840 can only be solved by drawing all players layer by layer (first the
3841 background, then the foreground etc.) !!! => TODO */
3842 else if (!IS_PLAYER(last_jx, last_jy))
3843 DrawLevelField(last_jx, last_jy);
3846 DrawLevelField(last_jx, last_jy);
3849 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
3850 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3853 if (!IN_SCR_FIELD(sx, sy))
3856 /* ----------------------------------------------------------------------- */
3857 /* draw things behind the player, if needed */
3858 /* ----------------------------------------------------------------------- */
3861 DrawLevelElement(jx, jy, Back[jx][jy]);
3862 else if (IS_ACTIVE_BOMB(element))
3863 DrawLevelElement(jx, jy, EL_EMPTY);
3866 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
3868 int old_element = GfxElement[jx][jy];
3869 int old_graphic = el_act_dir2img(old_element, action, move_dir);
3870 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
3872 if (GFX_CRUMBLED(old_element))
3873 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
3875 DrawGraphic(sx, sy, old_graphic, frame);
3877 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
3878 player_is_opaque = TRUE;
3882 GfxElement[jx][jy] = EL_UNDEFINED;
3884 /* make sure that pushed elements are drawn with correct frame rate */
3886 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
3888 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
3889 GfxFrame[jx][jy] = player->StepFrame;
3891 if (player->is_pushing && player->is_moving)
3892 GfxFrame[jx][jy] = player->StepFrame;
3895 DrawLevelField(jx, jy);
3899 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
3900 /* ----------------------------------------------------------------------- */
3901 /* draw player himself */
3902 /* ----------------------------------------------------------------------- */
3904 graphic = getPlayerGraphic(player, move_dir);
3906 /* in the case of changed player action or direction, prevent the current
3907 animation frame from being restarted for identical animations */
3908 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
3909 player->Frame = last_player_frame;
3911 frame = getGraphicAnimationFrame(graphic, player->Frame);
3915 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3916 sxx = player->GfxPos;
3918 syy = player->GfxPos;
3921 if (!setup.soft_scrolling && ScreenMovPos)
3924 if (player_is_opaque)
3925 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
3927 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3929 if (SHIELD_ON(player))
3931 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
3932 IMG_SHIELD_NORMAL_ACTIVE);
3933 int frame = getGraphicAnimationFrame(graphic, -1);
3935 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3939 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
3942 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3943 sxx = player->GfxPos;
3945 syy = player->GfxPos;
3949 /* ----------------------------------------------------------------------- */
3950 /* draw things the player is pushing, if needed */
3951 /* ----------------------------------------------------------------------- */
3954 printf("::: %d, %d [%d, %d] [%d]\n",
3955 player->is_pushing, player_is_moving, player->GfxAction,
3956 player->is_moving, player_is_moving);
3960 if (player->is_pushing && player->is_moving)
3962 int px = SCREENX(jx), py = SCREENY(jy);
3963 int pxx = (TILEX - ABS(sxx)) * dx;
3964 int pyy = (TILEY - ABS(syy)) * dy;
3965 int gfx_frame = GfxFrame[jx][jy];
3971 if (!IS_MOVING(jx, jy)) /* push movement already finished */
3973 element = Feld[next_jx][next_jy];
3974 gfx_frame = GfxFrame[next_jx][next_jy];
3977 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
3980 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
3981 frame = getGraphicAnimationFrame(graphic, sync_frame);
3983 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
3986 /* draw background element under pushed element (like the Sokoban field) */
3988 if (game.use_masked_pushing && IS_MOVING(jx, jy))
3990 /* this allows transparent pushing animation over non-black background */
3993 DrawLevelElement(jx, jy, Back[jx][jy]);
3995 DrawLevelElement(jx, jy, EL_EMPTY);
3997 if (Back[next_jx][next_jy])
3998 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4000 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4002 else if (Back[next_jx][next_jy])
4003 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4005 if (Back[next_jx][next_jy])
4006 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4010 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
4011 jx, px, player->GfxPos, player->StepFrame,
4016 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
4020 /* do not draw (EM style) pushing animation when pushing is finished */
4021 /* (two-tile animations usually do not contain start and end frame) */
4022 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
4023 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
4025 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4027 /* masked drawing is needed for EMC style (double) movement graphics */
4028 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
4029 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4034 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4035 /* ----------------------------------------------------------------------- */
4036 /* draw player himself */
4037 /* ----------------------------------------------------------------------- */
4039 graphic = getPlayerGraphic(player, move_dir);
4041 /* in the case of changed player action or direction, prevent the current
4042 animation frame from being restarted for identical animations */
4043 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4044 player->Frame = last_player_frame;
4046 frame = getGraphicAnimationFrame(graphic, player->Frame);
4050 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4051 sxx = player->GfxPos;
4053 syy = player->GfxPos;
4056 if (!setup.soft_scrolling && ScreenMovPos)
4059 if (player_is_opaque)
4060 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4062 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4064 if (SHIELD_ON(player))
4066 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4067 IMG_SHIELD_NORMAL_ACTIVE);
4068 int frame = getGraphicAnimationFrame(graphic, -1);
4070 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4074 /* ----------------------------------------------------------------------- */
4075 /* draw things in front of player (active dynamite or dynabombs) */
4076 /* ----------------------------------------------------------------------- */
4078 if (IS_ACTIVE_BOMB(element))
4080 graphic = el2img(element);
4081 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
4083 if (game.emulation == EMU_SUPAPLEX)
4084 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
4086 DrawGraphicThruMask(sx, sy, graphic, frame);
4089 if (player_is_moving && last_element == EL_EXPLOSION)
4091 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
4092 GfxElement[last_jx][last_jy] : EL_EMPTY);
4093 int graphic = el_act2img(element, ACTION_EXPLODING);
4094 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
4095 int phase = ExplodePhase[last_jx][last_jy] - 1;
4096 int frame = getGraphicAnimationFrame(graphic, phase - delay);
4099 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
4102 /* ----------------------------------------------------------------------- */
4103 /* draw elements the player is just walking/passing through/under */
4104 /* ----------------------------------------------------------------------- */
4106 if (player_is_moving)
4108 /* handle the field the player is leaving ... */
4109 if (IS_ACCESSIBLE_INSIDE(last_element))
4110 DrawLevelField(last_jx, last_jy);
4111 else if (IS_ACCESSIBLE_UNDER(last_element))
4112 DrawLevelFieldThruMask(last_jx, last_jy);
4115 /* do not redraw accessible elements if the player is just pushing them */
4116 if (!player_is_moving || !player->is_pushing)
4118 /* ... and the field the player is entering */
4119 if (IS_ACCESSIBLE_INSIDE(element))
4120 DrawLevelField(jx, jy);
4121 else if (IS_ACCESSIBLE_UNDER(element))
4122 DrawLevelFieldThruMask(jx, jy);
4125 MarkTileDirty(sx, sy);
4128 /* ------------------------------------------------------------------------- */
4130 void WaitForEventToContinue()
4132 boolean still_wait = TRUE;
4134 /* simulate releasing mouse button over last gadget, if still pressed */
4136 HandleGadgets(-1, -1, 0);
4138 button_status = MB_RELEASED;
4154 case EVENT_BUTTONPRESS:
4155 case EVENT_KEYPRESS:
4159 case EVENT_KEYRELEASE:
4160 ClearPlayerAction();
4164 HandleOtherEvents(&event);
4168 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4175 /* don't eat all CPU time */
4180 #define MAX_REQUEST_LINES 13
4181 #define MAX_REQUEST_LINE_FONT1_LEN 7
4182 #define MAX_REQUEST_LINE_FONT2_LEN 10
4186 static int RequestHandleEvents(unsigned int req_state)
4188 int last_game_status = game_status; /* save current game status */
4192 button_status = MB_RELEASED;
4194 request_gadget_id = -1;
4207 case EVENT_BUTTONPRESS:
4208 case EVENT_BUTTONRELEASE:
4209 case EVENT_MOTIONNOTIFY:
4211 if (event.type == EVENT_MOTIONNOTIFY)
4213 if (!PointerInWindow(window))
4214 continue; /* window and pointer are on different screens */
4219 motion_status = TRUE;
4220 mx = ((MotionEvent *) &event)->x;
4221 my = ((MotionEvent *) &event)->y;
4225 motion_status = FALSE;
4226 mx = ((ButtonEvent *) &event)->x;
4227 my = ((ButtonEvent *) &event)->y;
4228 if (event.type == EVENT_BUTTONPRESS)
4229 button_status = ((ButtonEvent *) &event)->button;
4231 button_status = MB_RELEASED;
4234 /* this sets 'request_gadget_id' */
4235 HandleGadgets(mx, my, button_status);
4237 switch (request_gadget_id)
4239 case TOOL_CTRL_ID_YES:
4242 case TOOL_CTRL_ID_NO:
4245 case TOOL_CTRL_ID_CONFIRM:
4246 result = TRUE | FALSE;
4249 case TOOL_CTRL_ID_PLAYER_1:
4252 case TOOL_CTRL_ID_PLAYER_2:
4255 case TOOL_CTRL_ID_PLAYER_3:
4258 case TOOL_CTRL_ID_PLAYER_4:
4269 case EVENT_KEYPRESS:
4270 switch (GetEventKey((KeyEvent *)&event, TRUE))
4273 if (req_state & REQ_CONFIRM)
4282 #if defined(TARGET_SDL2)
4292 if (req_state & REQ_PLAYER)
4296 case EVENT_KEYRELEASE:
4297 ClearPlayerAction();
4301 HandleOtherEvents(&event);
4305 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4307 int joy = AnyJoystick();
4309 if (joy & JOY_BUTTON_1)
4311 else if (joy & JOY_BUTTON_2)
4317 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4319 HandleGameActions();
4325 if (!PendingEvent()) /* delay only if no pending events */
4330 game_status = GAME_MODE_PSEUDO_DOOR;
4336 game_status = last_game_status; /* restore current game status */
4344 if (!PendingEvent()) /* delay only if no pending events */
4347 /* don't eat all CPU time */
4357 static boolean RequestDoor(char *text, unsigned int req_state)
4359 unsigned int old_door_state;
4360 int last_game_status = game_status; /* save current game status */
4361 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4362 int font_nr = FONT_TEXT_2;
4367 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4369 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4370 font_nr = FONT_TEXT_1;
4373 if (game_status == GAME_MODE_PLAYING)
4375 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4376 BlitScreenToBitmap_EM(backbuffer);
4377 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4378 BlitScreenToBitmap_SP(backbuffer);
4381 /* disable deactivated drawing when quick-loading level tape recording */
4382 if (tape.playing && tape.deactivate_display)
4383 TapeDeactivateDisplayOff(TRUE);
4385 SetMouseCursor(CURSOR_DEFAULT);
4387 #if defined(NETWORK_AVALIABLE)
4388 /* pause network game while waiting for request to answer */
4389 if (options.network &&
4390 game_status == GAME_MODE_PLAYING &&
4391 req_state & REQUEST_WAIT_FOR_INPUT)
4392 SendToServer_PausePlaying();
4395 old_door_state = GetDoorState();
4397 /* simulate releasing mouse button over last gadget, if still pressed */
4399 HandleGadgets(-1, -1, 0);
4403 /* draw released gadget before proceeding */
4406 if (old_door_state & DOOR_OPEN_1)
4408 CloseDoor(DOOR_CLOSE_1);
4410 /* save old door content */
4411 BlitBitmap(bitmap_db_door, bitmap_db_door,
4412 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4413 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4416 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4417 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4419 /* clear door drawing field */
4420 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4422 /* force DOOR font inside door area */
4423 game_status = GAME_MODE_PSEUDO_DOOR;
4425 /* write text for request */
4426 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4428 char text_line[max_request_line_len + 1];
4434 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4436 tc = *(text_ptr + tx);
4437 // if (!tc || tc == ' ')
4438 if (!tc || tc == ' ' || tc == '?' || tc == '!')
4442 if ((tc == '?' || tc == '!') && tl == 0)
4452 strncpy(text_line, text_ptr, tl);
4455 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4456 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4457 text_line, font_nr);
4459 text_ptr += tl + (tc == ' ' ? 1 : 0);
4460 // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
4463 game_status = last_game_status; /* restore current game status */
4465 if (req_state & REQ_ASK)
4467 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4468 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4470 else if (req_state & REQ_CONFIRM)
4472 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4474 else if (req_state & REQ_PLAYER)
4476 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4477 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4478 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4479 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4482 /* copy request gadgets to door backbuffer */
4483 BlitBitmap(drawto, bitmap_db_door,
4484 DX, DY, DXSIZE, DYSIZE,
4485 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4487 OpenDoor(DOOR_OPEN_1);
4489 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4491 if (game_status == GAME_MODE_PLAYING)
4493 SetPanelBackground();
4494 SetDrawBackgroundMask(REDRAW_DOOR_1);
4498 SetDrawBackgroundMask(REDRAW_FIELD);
4504 if (game_status != GAME_MODE_MAIN)
4507 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4509 // ---------- handle request buttons ----------
4510 result = RequestHandleEvents(req_state);
4512 if (game_status != GAME_MODE_MAIN)
4517 if (!(req_state & REQ_STAY_OPEN))
4519 CloseDoor(DOOR_CLOSE_1);
4521 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4522 (req_state & REQ_REOPEN))
4523 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4528 if (game_status == GAME_MODE_PLAYING)
4530 SetPanelBackground();
4531 SetDrawBackgroundMask(REDRAW_DOOR_1);
4535 SetDrawBackgroundMask(REDRAW_FIELD);
4538 #if defined(NETWORK_AVALIABLE)
4539 /* continue network game after request */
4540 if (options.network &&
4541 game_status == GAME_MODE_PLAYING &&
4542 req_state & REQUEST_WAIT_FOR_INPUT)
4543 SendToServer_ContinuePlaying();
4546 /* restore deactivated drawing when quick-loading level tape recording */
4547 if (tape.playing && tape.deactivate_display)
4548 TapeDeactivateDisplayOn();
4553 static boolean RequestEnvelope(char *text, unsigned int req_state)
4560 if (game_status == GAME_MODE_PLAYING)
4562 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4563 BlitScreenToBitmap_EM(backbuffer);
4564 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4565 BlitScreenToBitmap_SP(backbuffer);
4568 /* disable deactivated drawing when quick-loading level tape recording */
4569 if (tape.playing && tape.deactivate_display)
4570 TapeDeactivateDisplayOff(TRUE);
4572 SetMouseCursor(CURSOR_DEFAULT);
4574 #if defined(NETWORK_AVALIABLE)
4575 /* pause network game while waiting for request to answer */
4576 if (options.network &&
4577 game_status == GAME_MODE_PLAYING &&
4578 req_state & REQUEST_WAIT_FOR_INPUT)
4579 SendToServer_PausePlaying();
4582 /* simulate releasing mouse button over last gadget, if still pressed */
4584 HandleGadgets(-1, -1, 0);
4588 // (replace with setting corresponding request background)
4589 // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4590 // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4592 /* clear door drawing field */
4593 // DrawBackground(DX, DY, DXSIZE, DYSIZE);
4596 if (global.use_envelope_request)
4600 CreateToolButtons();
4606 if (req_state & REQ_ASK)
4608 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_YES], FALSE);
4609 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_NO], FALSE);
4611 else if (req_state & REQ_CONFIRM)
4613 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_CONFIRM], FALSE);
4615 else if (req_state & REQ_PLAYER)
4617 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_1], FALSE);
4618 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_2], FALSE);
4619 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_3], FALSE);
4620 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_4], FALSE);
4623 if (req_state & REQ_ASK)
4625 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4626 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4628 else if (req_state & REQ_CONFIRM)
4630 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4632 else if (req_state & REQ_PLAYER)
4634 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4635 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4636 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4637 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4642 ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
4645 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4647 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4648 i == TOOL_CTRL_ID_NO)) ||
4649 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4650 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4651 i == TOOL_CTRL_ID_PLAYER_2 &&
4652 i == TOOL_CTRL_ID_PLAYER_3 &&
4653 i == TOOL_CTRL_ID_PLAYER_4)))
4655 int x = tool_gadget[i]->x + dDX;
4656 int y = tool_gadget[i]->y + dDY;
4658 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4663 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4665 if (game_status == GAME_MODE_PLAYING)
4667 SetPanelBackground();
4668 SetDrawBackgroundMask(REDRAW_DOOR_1);
4672 SetDrawBackgroundMask(REDRAW_FIELD);
4679 if (game_status != GAME_MODE_MAIN)
4683 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4685 // ---------- handle request buttons ----------
4686 result = RequestHandleEvents(req_state);
4688 if (game_status != GAME_MODE_MAIN)
4693 ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
4697 if (game_status == GAME_MODE_PLAYING)
4699 SetPanelBackground();
4700 SetDrawBackgroundMask(REDRAW_DOOR_1);
4704 SetDrawBackgroundMask(REDRAW_FIELD);
4707 #if defined(NETWORK_AVALIABLE)
4708 /* continue network game after request */
4709 if (options.network &&
4710 game_status == GAME_MODE_PLAYING &&
4711 req_state & REQUEST_WAIT_FOR_INPUT)
4712 SendToServer_ContinuePlaying();
4715 /* restore deactivated drawing when quick-loading level tape recording */
4716 if (tape.playing && tape.deactivate_display)
4717 TapeDeactivateDisplayOn();
4722 boolean Request(char *text, unsigned int req_state)
4724 if (global.use_envelope_request)
4725 return RequestEnvelope(text, req_state);
4727 return RequestDoor(text, req_state);
4730 #else // =====================================================================
4732 boolean Request(char *text, unsigned int req_state)
4734 int mx, my, ty, result = -1;
4735 unsigned int old_door_state;
4736 int last_game_status = game_status; /* save current game status */
4737 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4738 int font_nr = FONT_TEXT_2;
4740 int max_word_len = 0;
4746 global.use_envelope_request = 1;
4750 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4752 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4753 font_nr = FONT_TEXT_1;
4756 for (text_ptr = text; *text_ptr; text_ptr++)
4758 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
4760 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
4762 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4764 font_nr = FONT_TEXT_1;
4766 font_nr = FONT_LEVEL_NUMBER;
4774 if (game_status == GAME_MODE_PLAYING)
4776 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4777 BlitScreenToBitmap_EM(backbuffer);
4778 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4779 BlitScreenToBitmap_SP(backbuffer);
4782 /* disable deactivated drawing when quick-loading level tape recording */
4783 if (tape.playing && tape.deactivate_display)
4784 TapeDeactivateDisplayOff(TRUE);
4786 SetMouseCursor(CURSOR_DEFAULT);
4788 #if defined(NETWORK_AVALIABLE)
4789 /* pause network game while waiting for request to answer */
4790 if (options.network &&
4791 game_status == GAME_MODE_PLAYING &&
4792 req_state & REQUEST_WAIT_FOR_INPUT)
4793 SendToServer_PausePlaying();
4796 old_door_state = GetDoorState();
4798 /* simulate releasing mouse button over last gadget, if still pressed */
4800 HandleGadgets(-1, -1, 0);
4804 /* draw released gadget before proceeding */
4808 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
4810 if (old_door_state & DOOR_OPEN_1)
4814 if (!global.use_envelope_request)
4815 CloseDoor(DOOR_CLOSE_1);
4817 CloseDoor(DOOR_CLOSE_1);
4820 /* save old door content */
4821 BlitBitmap(bitmap_db_door, bitmap_db_door,
4822 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4823 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4827 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4830 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4832 /* clear door drawing field */
4833 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4835 /* force DOOR font inside door area */
4836 game_status = GAME_MODE_PSEUDO_DOOR;
4838 /* write text for request */
4839 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4841 char text_line[max_request_line_len + 1];
4847 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4849 tc = *(text_ptr + tx);
4850 if (!tc || tc == ' ')
4861 strncpy(text_line, text_ptr, tl);
4864 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4865 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4866 text_line, font_nr);
4868 text_ptr += tl + (tc == ' ' ? 1 : 0);
4871 game_status = last_game_status; /* restore current game status */
4874 if (global.use_envelope_request)
4878 CreateToolButtons();
4882 if (req_state & REQ_ASK)
4884 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4885 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4887 else if (req_state & REQ_CONFIRM)
4889 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4891 else if (req_state & REQ_PLAYER)
4893 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4894 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4895 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4896 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4899 /* copy request gadgets to door backbuffer */
4900 BlitBitmap(drawto, bitmap_db_door,
4901 DX, DY, DXSIZE, DYSIZE,
4902 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4905 if (global.use_envelope_request)
4907 ShowEnvelopeRequest(text, ACTION_OPENING);
4909 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4911 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4912 i == TOOL_CTRL_ID_NO)) ||
4913 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4914 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4915 i == TOOL_CTRL_ID_PLAYER_2 &&
4916 i == TOOL_CTRL_ID_PLAYER_3 &&
4917 i == TOOL_CTRL_ID_PLAYER_4)))
4919 int x = tool_gadget[i]->x + dDX;
4920 int y = tool_gadget[i]->y + dDY;
4922 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4929 if (!global.use_envelope_request)
4930 OpenDoor(DOOR_OPEN_1);
4932 OpenDoor(DOOR_OPEN_1);
4935 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4937 if (game_status == GAME_MODE_PLAYING)
4939 SetPanelBackground();
4940 SetDrawBackgroundMask(REDRAW_DOOR_1);
4944 SetDrawBackgroundMask(REDRAW_FIELD);
4951 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
4954 if (game_status != GAME_MODE_MAIN)
4958 button_status = MB_RELEASED;
4960 request_gadget_id = -1;
4962 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4974 case EVENT_BUTTONPRESS:
4975 case EVENT_BUTTONRELEASE:
4976 case EVENT_MOTIONNOTIFY:
4978 if (event.type == EVENT_MOTIONNOTIFY)
4980 if (!PointerInWindow(window))
4981 continue; /* window and pointer are on different screens */
4986 motion_status = TRUE;
4987 mx = ((MotionEvent *) &event)->x;
4988 my = ((MotionEvent *) &event)->y;
4992 motion_status = FALSE;
4993 mx = ((ButtonEvent *) &event)->x;
4994 my = ((ButtonEvent *) &event)->y;
4995 if (event.type == EVENT_BUTTONPRESS)
4996 button_status = ((ButtonEvent *) &event)->button;
4998 button_status = MB_RELEASED;
5001 /* this sets 'request_gadget_id' */
5002 HandleGadgets(mx, my, button_status);
5004 switch (request_gadget_id)
5006 case TOOL_CTRL_ID_YES:
5009 case TOOL_CTRL_ID_NO:
5012 case TOOL_CTRL_ID_CONFIRM:
5013 result = TRUE | FALSE;
5016 case TOOL_CTRL_ID_PLAYER_1:
5019 case TOOL_CTRL_ID_PLAYER_2:
5022 case TOOL_CTRL_ID_PLAYER_3:
5025 case TOOL_CTRL_ID_PLAYER_4:
5036 case EVENT_KEYPRESS:
5037 switch (GetEventKey((KeyEvent *)&event, TRUE))
5040 if (req_state & REQ_CONFIRM)
5049 #if defined(TARGET_SDL2)
5059 if (req_state & REQ_PLAYER)
5063 case EVENT_KEYRELEASE:
5064 ClearPlayerAction();
5068 HandleOtherEvents(&event);
5072 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
5074 int joy = AnyJoystick();
5076 if (joy & JOY_BUTTON_1)
5078 else if (joy & JOY_BUTTON_2)
5084 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
5086 HandleGameActions();
5092 if (!PendingEvent()) /* delay only if no pending events */
5097 game_status = GAME_MODE_PSEUDO_DOOR;
5103 game_status = last_game_status; /* restore current game status */
5111 if (!PendingEvent()) /* delay only if no pending events */
5114 /* don't eat all CPU time */
5121 if (game_status != GAME_MODE_MAIN)
5127 if (global.use_envelope_request)
5128 ShowEnvelopeRequest(text, ACTION_CLOSING);
5132 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
5134 if (!(req_state & REQ_STAY_OPEN))
5137 CloseDoor(DOOR_CLOSE_1);
5139 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
5140 (req_state & REQ_REOPEN))
5141 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
5146 if (game_status == GAME_MODE_PLAYING)
5148 SetPanelBackground();
5149 SetDrawBackgroundMask(REDRAW_DOOR_1);
5153 SetDrawBackgroundMask(REDRAW_FIELD);
5156 #if defined(NETWORK_AVALIABLE)
5157 /* continue network game after request */
5158 if (options.network &&
5159 game_status == GAME_MODE_PLAYING &&
5160 req_state & REQUEST_WAIT_FOR_INPUT)
5161 SendToServer_ContinuePlaying();
5164 /* restore deactivated drawing when quick-loading level tape recording */
5165 if (tape.playing && tape.deactivate_display)
5166 TapeDeactivateDisplayOn();
5173 unsigned int OpenDoor(unsigned int door_state)
5175 if (door_state & DOOR_COPY_BACK)
5177 if (door_state & DOOR_OPEN_1)
5178 BlitBitmap(bitmap_db_door, bitmap_db_door,
5179 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5180 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5182 if (door_state & DOOR_OPEN_2)
5183 BlitBitmap(bitmap_db_door, bitmap_db_door,
5184 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
5185 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5187 door_state &= ~DOOR_COPY_BACK;
5190 return MoveDoor(door_state);
5193 unsigned int CloseDoor(unsigned int door_state)
5195 unsigned int old_door_state = GetDoorState();
5197 if (!(door_state & DOOR_NO_COPY_BACK))
5199 if (old_door_state & DOOR_OPEN_1)
5200 BlitBitmap(backbuffer, bitmap_db_door,
5201 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5203 if (old_door_state & DOOR_OPEN_2)
5204 BlitBitmap(backbuffer, bitmap_db_door,
5205 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5207 door_state &= ~DOOR_NO_COPY_BACK;
5210 return MoveDoor(door_state);
5213 unsigned int GetDoorState()
5215 return MoveDoor(DOOR_GET_STATE);
5218 unsigned int SetDoorState(unsigned int door_state)
5220 return MoveDoor(door_state | DOOR_SET_STATE);
5223 unsigned int MoveDoor(unsigned int door_state)
5225 static int door1 = DOOR_OPEN_1;
5226 static int door2 = DOOR_CLOSE_2;
5227 unsigned int door_delay = 0;
5228 unsigned int door_delay_value;
5232 if (door_1.width < 0 || door_1.width > DXSIZE)
5233 door_1.width = DXSIZE;
5234 if (door_1.height < 0 || door_1.height > DYSIZE)
5235 door_1.height = DYSIZE;
5236 if (door_2.width < 0 || door_2.width > VXSIZE)
5237 door_2.width = VXSIZE;
5238 if (door_2.height < 0 || door_2.height > VYSIZE)
5239 door_2.height = VYSIZE;
5242 if (door_state == DOOR_GET_STATE)
5243 return (door1 | door2);
5245 if (door_state & DOOR_SET_STATE)
5247 if (door_state & DOOR_ACTION_1)
5248 door1 = door_state & DOOR_ACTION_1;
5249 if (door_state & DOOR_ACTION_2)
5250 door2 = door_state & DOOR_ACTION_2;
5252 return (door1 | door2);
5255 if (!(door_state & DOOR_FORCE_REDRAW))
5257 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
5258 door_state &= ~DOOR_OPEN_1;
5259 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
5260 door_state &= ~DOOR_CLOSE_1;
5261 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
5262 door_state &= ~DOOR_OPEN_2;
5263 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
5264 door_state &= ~DOOR_CLOSE_2;
5267 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
5270 // door_delay_value *= 4; // !!! TEST ONLY !!!
5272 if (setup.quick_doors)
5274 stepsize = 20; /* must be chosen to always draw last frame */
5275 door_delay_value = 0;
5278 if (global.autoplay_leveldir)
5280 door_state |= DOOR_NO_DELAY;
5281 door_state &= ~DOOR_CLOSE_ALL;
5285 if (game_status == GAME_MODE_EDITOR)
5286 door_state |= DOOR_NO_DELAY;
5289 if (door_state & DOOR_ACTION)
5292 struct GraphicInfo *g1_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
5293 struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
5294 struct GraphicInfo *g2_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
5295 struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
5296 int door_1_left_width = g1_left->width;
5297 int door_1_left_height = g1_left->height;
5298 int door_1_right_width = g1_right->width;
5299 int door_1_right_height = g1_right->height;
5300 int door_2_left_width = g2_left->width;
5301 int door_2_left_height = g2_left->height;
5302 int door_2_right_width = g2_right->width;
5303 int door_2_right_height = g2_right->height;
5304 int door_1_width = MAX(door_1_left_width, door_1_right_width);
5305 int door_1_height = MAX(door_1_left_height, door_1_right_height);
5306 int door_2_width = MAX(door_2_left_width, door_2_right_width);
5307 int door_2_height = MAX(door_2_left_height, door_2_right_height);
5309 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
5310 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
5311 boolean door_1_done = (!handle_door_1);
5312 boolean door_2_done = (!handle_door_2);
5313 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
5314 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
5317 int door_size_1 = (door_1_vertical ? door_1_height : door_1_width);
5318 int door_size_2 = (door_2_vertical ? door_2_height : door_2_width);
5320 int door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
5321 int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
5324 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
5325 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
5327 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
5328 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
5329 // int door_size = (handle_door_1 ? door_size_1 : door_size_2);
5330 int door_size = (handle_door_2 ? door_size_2 : door_size_1);
5331 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
5332 int door_skip = max_door_size - door_size;
5333 int end = door_size;
5334 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
5337 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
5339 /* opening door sound has priority over simultaneously closing door */
5340 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
5341 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
5342 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
5343 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
5346 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
5350 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
5351 GC gc = bitmap->stored_clip_gc;
5354 if (door_state & DOOR_ACTION_1 &&
5355 x * door_1.step_offset <= door_size_1)
5357 int a = MIN(x * door_1.step_offset, end);
5358 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
5362 int i = p + door_skip;
5366 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
5367 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
5368 Bitmap *bm_left = g_left->bitmap;
5369 Bitmap *bm_right = g_right->bitmap;
5370 GC gc_left = bm_left->stored_clip_gc;
5371 GC gc_right = bm_right->stored_clip_gc;
5374 int classic_dxsize = 100;
5375 int classic_dysize = 280;
5376 boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
5377 DYSIZE == classic_dysize);
5379 if (door_1.anim_mode & ANIM_STATIC_PANEL)
5381 BlitBitmap(bitmap_db_door, drawto,
5382 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
5383 DXSIZE, DYSIZE, DX, DY);
5387 BlitBitmap(bitmap_db_door, drawto,
5388 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
5389 DXSIZE, DYSIZE - p / 2, DX, DY);
5392 // printf("::: p == %d\n", p);
5393 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
5397 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
5400 int src1_x = g_right->src_x;
5401 int src1_y = g_right->src_y;
5402 int src2_x = g_left->src_x + g_left->width - i;
5403 int src2_y = g_left->src_y;
5404 int dst1_x = DX + DXSIZE - i;
5409 int height = DYSIZE;
5411 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
5412 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
5415 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
5416 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
5419 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
5420 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
5421 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
5422 int dst2_x = DX, dst2_y = DY;
5423 int width = i, height = DYSIZE;
5425 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
5426 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
5429 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
5430 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
5434 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
5437 int src1_x = g_right->src_x;
5438 int src1_y = g_right->src_y;
5439 int src2_x = g_left->src_x;
5440 int src2_y = g_left->src_y + g_left->height - i;
5442 int dst1_y = DY + DYSIZE - i;
5448 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
5449 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
5452 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
5453 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
5456 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
5457 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
5458 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
5459 int dst2_x = DX, dst2_y = DY;
5460 int width = DXSIZE, height = i;
5462 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
5463 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
5466 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
5467 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
5471 else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */
5473 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
5476 int src1_x = g_right->src_x;
5477 int src1_y = g_right->src_y;
5478 int src2_x = g_left->src_x + g_left->width - i;
5479 int src2_y = g_left->src_y;
5480 int dst1_x = DX + DXSIZE - i;
5485 int height1 = 63, height2 = DYSIZE / 2 - height1;
5486 int ypos1 = 0, ypos2 = height2;
5487 int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
5489 SetClipOrigin(bm_right, gc_right,
5490 dst1_x - src1_x, dst1_y - src1_y + j);
5491 BlitBitmapMasked(bm_right, drawto,
5492 src1_x, src1_y + ypos1, width, height2,
5493 dst1_x, dst1_y + ypos1 + j);
5494 BlitBitmapMasked(bm_right, drawto,
5495 src1_x, src1_y + ypos3, width, height1,
5496 dst1_x, dst1_y + ypos3 + j);
5497 SetClipOrigin(bm_left, gc_left,
5498 dst2_x - src2_x, dst2_y - src2_y - j);
5499 BlitBitmapMasked(bm_left, drawto,
5500 src2_x, src2_y + ypos1 + j, width, height2 - j,
5501 dst2_x, dst2_y + ypos1);
5502 BlitBitmapMasked(bm_left, drawto,
5503 src2_x, src2_y + ypos3, width, height1,
5504 dst2_x, dst2_y + ypos3 - j);
5506 SetClipOrigin(bm_left, gc_left,
5507 dst2_x - src2_x, dst2_y - src2_y - j);
5508 BlitBitmapMasked(bm_left, drawto,
5509 src2_x, src2_y + ypos2, width, height1,
5510 dst2_x, dst2_y + ypos2 - j);
5511 BlitBitmapMasked(bm_left, drawto,
5512 src2_x, src2_y + ypos4, width, height2,
5513 dst2_x, dst2_y + ypos4 - j);
5514 SetClipOrigin(bm_right, gc_right,
5515 dst1_x - src1_x, dst1_y - src1_y + j);
5516 BlitBitmapMasked(bm_right, drawto,
5517 src1_x, src1_y + ypos2, width, height1,
5518 dst1_x, dst1_y + ypos2 + j);
5519 BlitBitmapMasked(bm_right, drawto,
5520 src1_x, src1_y + ypos4, width, height2 - j,
5521 dst1_x, dst1_y + ypos4 + j);
5524 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
5525 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
5526 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
5527 int dst2_x = DX, dst2_y = DY;
5528 int width = i, height = DYSIZE;
5529 int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
5531 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
5532 BlitBitmapMasked(bitmap, drawto,
5533 src1_x, src1_y, width, ypos2,
5534 dst1_x, dst1_y + j);
5535 BlitBitmapMasked(bitmap, drawto,
5536 src1_x, src1_y + ypos3, width, ypos1,
5537 dst1_x, dst1_y + ypos3 + j);
5538 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
5539 BlitBitmapMasked(bitmap, drawto,
5540 src2_x, src2_y + j, width, ypos2 - j,
5542 BlitBitmapMasked(bitmap, drawto,
5543 src2_x, src2_y + ypos3, width, ypos1,
5544 dst2_x, dst2_y + ypos3 - j);
5546 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
5547 BlitBitmapMasked(bitmap, drawto,
5548 src2_x, src2_y + ypos2, width, ypos1,
5549 dst2_x, dst2_y + ypos2 - j);
5550 BlitBitmapMasked(bitmap, drawto,
5551 src2_x, src2_y + ypos4, width, ypos2,
5552 dst2_x, dst2_y + ypos4 - j);
5553 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
5554 BlitBitmapMasked(bitmap, drawto,
5555 src1_x, src1_y + ypos2, width, ypos1,
5556 dst1_x, dst1_y + ypos2 + j);
5557 BlitBitmapMasked(bitmap, drawto,
5558 src1_x, src1_y + ypos4, width, ypos2 - j,
5559 dst1_x, dst1_y + ypos4 + j);
5562 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
5563 BlitBitmapMasked(bitmap, drawto,
5564 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
5565 DX + DXSIZE - i, DY + j);
5566 BlitBitmapMasked(bitmap, drawto,
5567 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
5568 DX + DXSIZE - i, DY + 140 + j);
5569 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
5570 DY - (DOOR_GFX_PAGEY1 + j));
5571 BlitBitmapMasked(bitmap, drawto,
5572 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
5574 BlitBitmapMasked(bitmap, drawto,
5575 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
5578 BlitBitmapMasked(bitmap, drawto,
5579 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
5581 BlitBitmapMasked(bitmap, drawto,
5582 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
5584 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
5585 BlitBitmapMasked(bitmap, drawto,
5586 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
5587 DX + DXSIZE - i, DY + 77 + j);
5588 BlitBitmapMasked(bitmap, drawto,
5589 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
5590 DX + DXSIZE - i, DY + 203 + j);
5595 redraw_mask |= REDRAW_DOOR_1;
5596 door_1_done = (a == end);
5599 if (door_state & DOOR_ACTION_2 &&
5600 x * door_2.step_offset <= door_size_2)
5602 int a = MIN(x * door_2.step_offset, door_size);
5603 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
5604 int i = p + door_skip;
5607 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
5608 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
5609 Bitmap *bm_left = g_left->bitmap;
5610 Bitmap *bm_right = g_right->bitmap;
5611 GC gc_left = bm_left->stored_clip_gc;
5612 GC gc_right = bm_right->stored_clip_gc;
5615 int classic_vxsize = 100;
5616 int classic_vysize = 100;
5617 boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
5618 VYSIZE == classic_vysize);
5620 if (door_2.anim_mode & ANIM_STATIC_PANEL)
5622 BlitBitmap(bitmap_db_door, drawto,
5623 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
5624 VXSIZE, VYSIZE, VX, VY);
5626 else if (x <= VYSIZE)
5628 BlitBitmap(bitmap_db_door, drawto,
5629 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
5630 VXSIZE, VYSIZE - p / 2, VX, VY);
5632 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
5635 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
5638 int src1_x = g_right->src_x;
5639 int src1_y = g_right->src_y;
5640 int src2_x = g_left->src_x + g_left->width - i;
5641 int src2_y = g_left->src_y;
5642 int dst1_x = VX + VXSIZE - i;
5647 int height = VYSIZE;
5649 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
5650 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
5653 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
5654 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
5657 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
5658 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
5659 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
5660 int dst2_x = VX, dst2_y = VY;
5661 int width = i, height = VYSIZE;
5663 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
5664 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
5667 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
5668 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
5672 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
5675 int src1_x = g_right->src_x;
5676 int src1_y = g_right->src_y;
5677 int src2_x = g_left->src_x;
5678 int src2_y = g_left->src_y + g_left->height - i;
5680 int dst1_y = VY + VYSIZE - i;
5686 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
5687 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
5690 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
5691 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
5694 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
5695 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
5696 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
5697 int dst2_x = VX, dst2_y = VY;
5698 int width = VXSIZE, height = i;
5700 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
5701 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
5704 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
5705 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
5709 else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */
5711 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
5714 int src1_x = g_right->src_x;
5715 int src1_y = g_right->src_y;
5716 int src2_x = g_left->src_x + g_left->width - i;
5717 int src2_y = g_left->src_y;
5718 int dst1_x = VX + VXSIZE - i;
5723 int height = VYSIZE / 2;
5724 int ypos1 = 0, ypos2 = VYSIZE / 2;
5726 SetClipOrigin(bm_right, gc_right,
5727 dst1_x - src1_x, dst1_y - src1_y + j);
5728 BlitBitmapMasked(bm_right, drawto,
5729 src1_x, src1_y + ypos1, width, height,
5730 dst1_x, dst1_y + ypos1 + j);
5731 SetClipOrigin(bm_left, gc_left,
5732 dst2_x - src2_x, dst2_y - src2_y - j);
5733 BlitBitmapMasked(bm_left, drawto,
5734 src2_x, src2_y + ypos1 + j, width, height - j,
5735 dst2_x, dst2_y + ypos1);
5737 SetClipOrigin(bm_left, gc_left,
5738 dst2_x - src2_x, dst2_y - src2_y - j);
5739 BlitBitmapMasked(bm_left, drawto,
5740 src2_x, src2_y + ypos2, width, height,
5741 dst2_x, dst2_y + ypos2 - j);
5742 SetClipOrigin(bm_right, gc_right,
5743 dst1_x - src1_x, dst1_y - src1_y + j);
5744 BlitBitmapMasked(bm_right, drawto,
5745 src1_x, src1_y + ypos2, width, height - j,
5746 dst1_x, dst1_y + ypos2 + j);
5748 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
5749 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
5750 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
5751 int dst2_x = VX, dst2_y = VY;
5752 int width = i, height = VYSIZE;
5753 int ypos = VYSIZE / 2;
5755 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
5756 BlitBitmapMasked(bitmap, drawto,
5757 src1_x, src1_y, width, ypos,
5758 dst1_x, dst1_y + j);
5759 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
5760 BlitBitmapMasked(bitmap, drawto,
5761 src2_x, src2_y + j, width, ypos - j,
5764 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
5765 BlitBitmapMasked(bitmap, drawto,
5766 src2_x, src2_y + ypos, width, ypos,
5767 dst2_x, dst2_y + ypos - j);
5768 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
5769 BlitBitmapMasked(bitmap, drawto,
5770 src1_x, src1_y + ypos, width, ypos - j,
5771 dst1_x, dst1_y + ypos + j);
5774 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
5775 BlitBitmapMasked(bitmap, drawto,
5776 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
5777 VX + VXSIZE - i, VY + j);
5778 SetClipOrigin(bitmap, gc,
5779 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
5780 BlitBitmapMasked(bitmap, drawto,
5781 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
5784 BlitBitmapMasked(bitmap, drawto,
5785 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
5786 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
5787 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
5788 BlitBitmapMasked(bitmap, drawto,
5789 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
5791 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
5796 redraw_mask |= REDRAW_DOOR_2;
5797 door_2_done = (a == VXSIZE);
5800 if (!(door_state & DOOR_NO_DELAY))
5804 if (game_status == GAME_MODE_MAIN)
5807 WaitUntilDelayReached(&door_delay, door_delay_value);
5812 if (door_state & DOOR_ACTION_1)
5813 door1 = door_state & DOOR_ACTION_1;
5814 if (door_state & DOOR_ACTION_2)
5815 door2 = door_state & DOOR_ACTION_2;
5817 return (door1 | door2);
5820 void DrawSpecialEditorDoor()
5823 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
5824 int top_border_width = gfx1->width;
5825 int top_border_height = gfx1->height;
5826 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
5827 int ex = EX - outer_border;
5828 int ey = EY - outer_border;
5829 int vy = VY - outer_border;
5830 int exsize = EXSIZE + 2 * outer_border;
5832 CloseDoor(DOOR_CLOSE_2);
5834 /* draw bigger level editor toolbox window */
5835 BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
5836 top_border_width, top_border_height, ex, ey - top_border_height);
5837 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
5838 exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
5840 /* draw bigger level editor toolbox window */
5841 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
5842 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
5844 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
5845 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
5849 redraw_mask |= REDRAW_ALL;
5852 void UndrawSpecialEditorDoor()
5855 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
5856 int top_border_width = gfx1->width;
5857 int top_border_height = gfx1->height;
5858 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
5859 int ex = EX - outer_border;
5860 int ey = EY - outer_border;
5861 int ey_top = ey - top_border_height;
5862 int exsize = EXSIZE + 2 * outer_border;
5863 int eysize = EYSIZE + 2 * outer_border;
5865 /* draw normal tape recorder window */
5866 if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
5868 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
5869 ex, ey_top, top_border_width, top_border_height,
5871 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
5872 ex, ey, exsize, eysize, ex, ey);
5876 // if screen background is set to "[NONE]", clear editor toolbox window
5877 ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
5878 ClearRectangle(drawto, ex, ey, exsize, eysize);
5881 /* draw normal tape recorder window */
5882 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
5883 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
5887 redraw_mask |= REDRAW_ALL;
5891 /* ---------- new tool button stuff ---------------------------------------- */
5898 struct TextPosInfo *pos;
5901 } toolbutton_info[NUM_TOOL_BUTTONS] =
5904 IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
5905 TOOL_CTRL_ID_YES, "yes"
5908 IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
5909 TOOL_CTRL_ID_NO, "no"
5912 IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
5913 TOOL_CTRL_ID_CONFIRM, "confirm"
5916 IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
5917 TOOL_CTRL_ID_PLAYER_1, "player 1"
5920 IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
5921 TOOL_CTRL_ID_PLAYER_2, "player 2"
5924 IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
5925 TOOL_CTRL_ID_PLAYER_3, "player 3"
5928 IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
5929 TOOL_CTRL_ID_PLAYER_4, "player 4"
5933 void CreateToolButtons()
5937 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
5939 struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
5940 struct TextPosInfo *pos = toolbutton_info[i].pos;
5941 struct GadgetInfo *gi;
5942 Bitmap *deco_bitmap = None;
5943 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
5944 unsigned int event_mask = GD_EVENT_RELEASED;
5947 int gd_x = gfx->src_x;
5948 int gd_y = gfx->src_y;
5949 int gd_xp = gfx->src_x + gfx->pressed_xoffset;
5950 int gd_yp = gfx->src_y + gfx->pressed_yoffset;
5953 if (global.use_envelope_request)
5954 setRequestPosition(&dx, &dy, TRUE);
5956 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
5958 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
5960 getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
5961 pos->size, &deco_bitmap, &deco_x, &deco_y);
5962 deco_xpos = (gfx->width - pos->size) / 2;
5963 deco_ypos = (gfx->height - pos->size) / 2;
5966 gi = CreateGadget(GDI_CUSTOM_ID, id,
5967 GDI_INFO_TEXT, toolbutton_info[i].infotext,
5970 GDI_WIDTH, gfx->width,
5971 GDI_HEIGHT, gfx->height,
5972 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
5973 GDI_STATE, GD_BUTTON_UNPRESSED,
5974 GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
5975 GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
5976 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
5977 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
5978 GDI_DECORATION_SIZE, pos->size, pos->size,
5979 GDI_DECORATION_SHIFTING, 1, 1,
5980 GDI_DIRECT_DRAW, FALSE,
5981 GDI_EVENT_MASK, event_mask,
5982 GDI_CALLBACK_ACTION, HandleToolButtons,
5986 Error(ERR_EXIT, "cannot create gadget");
5988 tool_gadget[id] = gi;
5994 /* graphic position values for tool buttons */
5995 #define TOOL_BUTTON_YES_XPOS 2
5996 #define TOOL_BUTTON_YES_YPOS 250
5997 #define TOOL_BUTTON_YES_GFX_YPOS 0
5998 #define TOOL_BUTTON_YES_XSIZE 46
5999 #define TOOL_BUTTON_YES_YSIZE 28
6000 #define TOOL_BUTTON_NO_XPOS 52
6001 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
6002 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
6003 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
6004 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
6005 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
6006 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
6007 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
6008 #define TOOL_BUTTON_CONFIRM_XSIZE 96
6009 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
6010 #define TOOL_BUTTON_PLAYER_XSIZE 30
6011 #define TOOL_BUTTON_PLAYER_YSIZE 30
6012 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
6013 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
6014 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
6015 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
6016 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6017 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6018 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6019 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6020 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6021 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6022 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6023 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6024 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6025 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6026 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6027 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6028 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6029 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6030 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6031 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6040 } toolbutton_info[NUM_TOOL_BUTTONS] =
6043 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
6044 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
6045 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
6050 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
6051 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
6052 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
6057 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
6058 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
6059 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
6060 TOOL_CTRL_ID_CONFIRM,
6064 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6065 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
6066 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6067 TOOL_CTRL_ID_PLAYER_1,
6071 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6072 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
6073 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6074 TOOL_CTRL_ID_PLAYER_2,
6078 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6079 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
6080 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6081 TOOL_CTRL_ID_PLAYER_3,
6085 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6086 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
6087 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6088 TOOL_CTRL_ID_PLAYER_4,
6093 void CreateToolButtons()
6097 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6099 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6100 Bitmap *deco_bitmap = None;
6101 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6102 struct GadgetInfo *gi;
6103 unsigned int event_mask;
6104 int gd_xoffset, gd_yoffset;
6105 int gd_x1, gd_x2, gd_y;
6108 event_mask = GD_EVENT_RELEASED;
6110 gd_xoffset = toolbutton_info[i].xpos;
6111 gd_yoffset = toolbutton_info[i].ypos;
6112 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
6113 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
6114 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
6116 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6118 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6120 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
6121 &deco_bitmap, &deco_x, &deco_y);
6122 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
6123 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
6126 gi = CreateGadget(GDI_CUSTOM_ID, id,
6127 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6128 GDI_X, DX + toolbutton_info[i].x,
6129 GDI_Y, DY + toolbutton_info[i].y,
6130 GDI_WIDTH, toolbutton_info[i].width,
6131 GDI_HEIGHT, toolbutton_info[i].height,
6132 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6133 GDI_STATE, GD_BUTTON_UNPRESSED,
6134 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
6135 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
6136 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6137 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6138 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
6139 GDI_DECORATION_SHIFTING, 1, 1,
6140 GDI_DIRECT_DRAW, FALSE,
6141 GDI_EVENT_MASK, event_mask,
6142 GDI_CALLBACK_ACTION, HandleToolButtons,
6146 Error(ERR_EXIT, "cannot create gadget");
6148 tool_gadget[id] = gi;
6154 void FreeToolButtons()
6158 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6159 FreeGadget(tool_gadget[i]);
6162 static void UnmapToolButtons()
6166 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6167 UnmapGadget(tool_gadget[i]);
6170 static void HandleToolButtons(struct GadgetInfo *gi)
6172 request_gadget_id = gi->custom_id;
6175 static struct Mapping_EM_to_RND_object
6178 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
6179 boolean is_backside; /* backside of moving element */
6185 em_object_mapping_list[] =
6188 Xblank, TRUE, FALSE,
6192 Yacid_splash_eB, FALSE, FALSE,
6193 EL_ACID_SPLASH_RIGHT, -1, -1
6196 Yacid_splash_wB, FALSE, FALSE,
6197 EL_ACID_SPLASH_LEFT, -1, -1
6200 #ifdef EM_ENGINE_BAD_ROLL
6202 Xstone_force_e, FALSE, FALSE,
6203 EL_ROCK, -1, MV_BIT_RIGHT
6206 Xstone_force_w, FALSE, FALSE,
6207 EL_ROCK, -1, MV_BIT_LEFT
6210 Xnut_force_e, FALSE, FALSE,
6211 EL_NUT, -1, MV_BIT_RIGHT
6214 Xnut_force_w, FALSE, FALSE,
6215 EL_NUT, -1, MV_BIT_LEFT
6218 Xspring_force_e, FALSE, FALSE,
6219 EL_SPRING, -1, MV_BIT_RIGHT
6222 Xspring_force_w, FALSE, FALSE,
6223 EL_SPRING, -1, MV_BIT_LEFT
6226 Xemerald_force_e, FALSE, FALSE,
6227 EL_EMERALD, -1, MV_BIT_RIGHT
6230 Xemerald_force_w, FALSE, FALSE,
6231 EL_EMERALD, -1, MV_BIT_LEFT
6234 Xdiamond_force_e, FALSE, FALSE,
6235 EL_DIAMOND, -1, MV_BIT_RIGHT
6238 Xdiamond_force_w, FALSE, FALSE,
6239 EL_DIAMOND, -1, MV_BIT_LEFT
6242 Xbomb_force_e, FALSE, FALSE,
6243 EL_BOMB, -1, MV_BIT_RIGHT
6246 Xbomb_force_w, FALSE, FALSE,
6247 EL_BOMB, -1, MV_BIT_LEFT
6249 #endif /* EM_ENGINE_BAD_ROLL */
6252 Xstone, TRUE, FALSE,
6256 Xstone_pause, FALSE, FALSE,
6260 Xstone_fall, FALSE, FALSE,
6264 Ystone_s, FALSE, FALSE,
6265 EL_ROCK, ACTION_FALLING, -1
6268 Ystone_sB, FALSE, TRUE,
6269 EL_ROCK, ACTION_FALLING, -1
6272 Ystone_e, FALSE, FALSE,
6273 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
6276 Ystone_eB, FALSE, TRUE,
6277 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
6280 Ystone_w, FALSE, FALSE,
6281 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
6284 Ystone_wB, FALSE, TRUE,
6285 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
6292 Xnut_pause, FALSE, FALSE,
6296 Xnut_fall, FALSE, FALSE,
6300 Ynut_s, FALSE, FALSE,
6301 EL_NUT, ACTION_FALLING, -1
6304 Ynut_sB, FALSE, TRUE,
6305 EL_NUT, ACTION_FALLING, -1
6308 Ynut_e, FALSE, FALSE,
6309 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
6312 Ynut_eB, FALSE, TRUE,
6313 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
6316 Ynut_w, FALSE, FALSE,
6317 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
6320 Ynut_wB, FALSE, TRUE,
6321 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
6324 Xbug_n, TRUE, FALSE,
6328 Xbug_e, TRUE, FALSE,
6329 EL_BUG_RIGHT, -1, -1
6332 Xbug_s, TRUE, FALSE,
6336 Xbug_w, TRUE, FALSE,
6340 Xbug_gon, FALSE, FALSE,
6344 Xbug_goe, FALSE, FALSE,
6345 EL_BUG_RIGHT, -1, -1
6348 Xbug_gos, FALSE, FALSE,
6352 Xbug_gow, FALSE, FALSE,
6356 Ybug_n, FALSE, FALSE,
6357 EL_BUG, ACTION_MOVING, MV_BIT_UP
6360 Ybug_nB, FALSE, TRUE,
6361 EL_BUG, ACTION_MOVING, MV_BIT_UP
6364 Ybug_e, FALSE, FALSE,
6365 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
6368 Ybug_eB, FALSE, TRUE,
6369 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
6372 Ybug_s, FALSE, FALSE,
6373 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
6376 Ybug_sB, FALSE, TRUE,
6377 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
6380 Ybug_w, FALSE, FALSE,
6381 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
6384 Ybug_wB, FALSE, TRUE,
6385 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
6388 Ybug_w_n, FALSE, FALSE,
6389 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
6392 Ybug_n_e, FALSE, FALSE,
6393 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
6396 Ybug_e_s, FALSE, FALSE,
6397 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
6400 Ybug_s_w, FALSE, FALSE,
6401 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
6404 Ybug_e_n, FALSE, FALSE,
6405 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
6408 Ybug_s_e, FALSE, FALSE,
6409 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
6412 Ybug_w_s, FALSE, FALSE,
6413 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
6416 Ybug_n_w, FALSE, FALSE,
6417 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
6420 Ybug_stone, FALSE, FALSE,
6421 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
6424 Ybug_spring, FALSE, FALSE,
6425 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
6428 Xtank_n, TRUE, FALSE,
6429 EL_SPACESHIP_UP, -1, -1
6432 Xtank_e, TRUE, FALSE,
6433 EL_SPACESHIP_RIGHT, -1, -1
6436 Xtank_s, TRUE, FALSE,
6437 EL_SPACESHIP_DOWN, -1, -1
6440 Xtank_w, TRUE, FALSE,
6441 EL_SPACESHIP_LEFT, -1, -1
6444 Xtank_gon, FALSE, FALSE,
6445 EL_SPACESHIP_UP, -1, -1
6448 Xtank_goe, FALSE, FALSE,
6449 EL_SPACESHIP_RIGHT, -1, -1
6452 Xtank_gos, FALSE, FALSE,
6453 EL_SPACESHIP_DOWN, -1, -1
6456 Xtank_gow, FALSE, FALSE,
6457 EL_SPACESHIP_LEFT, -1, -1
6460 Ytank_n, FALSE, FALSE,
6461 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
6464 Ytank_nB, FALSE, TRUE,
6465 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
6468 Ytank_e, FALSE, FALSE,
6469 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
6472 Ytank_eB, FALSE, TRUE,
6473 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
6476 Ytank_s, FALSE, FALSE,
6477 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
6480 Ytank_sB, FALSE, TRUE,
6481 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
6484 Ytank_w, FALSE, FALSE,
6485 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
6488 Ytank_wB, FALSE, TRUE,
6489 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
6492 Ytank_w_n, FALSE, FALSE,
6493 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
6496 Ytank_n_e, FALSE, FALSE,
6497 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
6500 Ytank_e_s, FALSE, FALSE,
6501 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
6504 Ytank_s_w, FALSE, FALSE,
6505 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
6508 Ytank_e_n, FALSE, FALSE,
6509 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
6512 Ytank_s_e, FALSE, FALSE,
6513 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
6516 Ytank_w_s, FALSE, FALSE,
6517 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
6520 Ytank_n_w, FALSE, FALSE,
6521 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
6524 Ytank_stone, FALSE, FALSE,
6525 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
6528 Ytank_spring, FALSE, FALSE,
6529 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
6532 Xandroid, TRUE, FALSE,
6533 EL_EMC_ANDROID, ACTION_ACTIVE, -1
6536 Xandroid_1_n, FALSE, FALSE,
6537 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
6540 Xandroid_2_n, FALSE, FALSE,
6541 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
6544 Xandroid_1_e, FALSE, FALSE,
6545 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
6548 Xandroid_2_e, FALSE, FALSE,
6549 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
6552 Xandroid_1_w, FALSE, FALSE,
6553 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
6556 Xandroid_2_w, FALSE, FALSE,
6557 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
6560 Xandroid_1_s, FALSE, FALSE,
6561 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
6564 Xandroid_2_s, FALSE, FALSE,
6565 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
6568 Yandroid_n, FALSE, FALSE,
6569 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
6572 Yandroid_nB, FALSE, TRUE,
6573 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
6576 Yandroid_ne, FALSE, FALSE,
6577 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
6580 Yandroid_neB, FALSE, TRUE,
6581 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
6584 Yandroid_e, FALSE, FALSE,
6585 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
6588 Yandroid_eB, FALSE, TRUE,
6589 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
6592 Yandroid_se, FALSE, FALSE,
6593 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
6596 Yandroid_seB, FALSE, TRUE,
6597 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
6600 Yandroid_s, FALSE, FALSE,
6601 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
6604 Yandroid_sB, FALSE, TRUE,
6605 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
6608 Yandroid_sw, FALSE, FALSE,
6609 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
6612 Yandroid_swB, FALSE, TRUE,
6613 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
6616 Yandroid_w, FALSE, FALSE,
6617 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
6620 Yandroid_wB, FALSE, TRUE,
6621 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
6624 Yandroid_nw, FALSE, FALSE,
6625 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
6628 Yandroid_nwB, FALSE, TRUE,
6629 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
6632 Xspring, TRUE, FALSE,
6636 Xspring_pause, FALSE, FALSE,
6640 Xspring_e, FALSE, FALSE,
6644 Xspring_w, FALSE, FALSE,
6648 Xspring_fall, FALSE, FALSE,
6652 Yspring_s, FALSE, FALSE,
6653 EL_SPRING, ACTION_FALLING, -1
6656 Yspring_sB, FALSE, TRUE,
6657 EL_SPRING, ACTION_FALLING, -1
6660 Yspring_e, FALSE, FALSE,
6661 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
6664 Yspring_eB, FALSE, TRUE,
6665 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
6668 Yspring_w, FALSE, FALSE,
6669 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
6672 Yspring_wB, FALSE, TRUE,
6673 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
6676 Yspring_kill_e, FALSE, FALSE,
6677 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
6680 Yspring_kill_eB, FALSE, TRUE,
6681 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
6684 Yspring_kill_w, FALSE, FALSE,
6685 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
6688 Yspring_kill_wB, FALSE, TRUE,
6689 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
6692 Xeater_n, TRUE, FALSE,
6693 EL_YAMYAM_UP, -1, -1
6696 Xeater_e, TRUE, FALSE,
6697 EL_YAMYAM_RIGHT, -1, -1
6700 Xeater_w, TRUE, FALSE,
6701 EL_YAMYAM_LEFT, -1, -1
6704 Xeater_s, TRUE, FALSE,
6705 EL_YAMYAM_DOWN, -1, -1
6708 Yeater_n, FALSE, FALSE,
6709 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
6712 Yeater_nB, FALSE, TRUE,
6713 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
6716 Yeater_e, FALSE, FALSE,
6717 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
6720 Yeater_eB, FALSE, TRUE,
6721 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
6724 Yeater_s, FALSE, FALSE,
6725 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
6728 Yeater_sB, FALSE, TRUE,
6729 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
6732 Yeater_w, FALSE, FALSE,
6733 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
6736 Yeater_wB, FALSE, TRUE,
6737 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
6740 Yeater_stone, FALSE, FALSE,
6741 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
6744 Yeater_spring, FALSE, FALSE,
6745 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
6748 Xalien, TRUE, FALSE,
6752 Xalien_pause, FALSE, FALSE,
6756 Yalien_n, FALSE, FALSE,
6757 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
6760 Yalien_nB, FALSE, TRUE,
6761 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
6764 Yalien_e, FALSE, FALSE,
6765 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
6768 Yalien_eB, FALSE, TRUE,
6769 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
6772 Yalien_s, FALSE, FALSE,
6773 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
6776 Yalien_sB, FALSE, TRUE,
6777 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
6780 Yalien_w, FALSE, FALSE,
6781 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
6784 Yalien_wB, FALSE, TRUE,
6785 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
6788 Yalien_stone, FALSE, FALSE,
6789 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
6792 Yalien_spring, FALSE, FALSE,
6793 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
6796 Xemerald, TRUE, FALSE,
6800 Xemerald_pause, FALSE, FALSE,
6804 Xemerald_fall, FALSE, FALSE,
6808 Xemerald_shine, FALSE, FALSE,
6809 EL_EMERALD, ACTION_TWINKLING, -1
6812 Yemerald_s, FALSE, FALSE,
6813 EL_EMERALD, ACTION_FALLING, -1
6816 Yemerald_sB, FALSE, TRUE,
6817 EL_EMERALD, ACTION_FALLING, -1
6820 Yemerald_e, FALSE, FALSE,
6821 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
6824 Yemerald_eB, FALSE, TRUE,
6825 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
6828 Yemerald_w, FALSE, FALSE,
6829 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
6832 Yemerald_wB, FALSE, TRUE,
6833 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
6836 Yemerald_eat, FALSE, FALSE,
6837 EL_EMERALD, ACTION_COLLECTING, -1
6840 Yemerald_stone, FALSE, FALSE,
6841 EL_NUT, ACTION_BREAKING, -1
6844 Xdiamond, TRUE, FALSE,
6848 Xdiamond_pause, FALSE, FALSE,
6852 Xdiamond_fall, FALSE, FALSE,
6856 Xdiamond_shine, FALSE, FALSE,
6857 EL_DIAMOND, ACTION_TWINKLING, -1
6860 Ydiamond_s, FALSE, FALSE,
6861 EL_DIAMOND, ACTION_FALLING, -1
6864 Ydiamond_sB, FALSE, TRUE,
6865 EL_DIAMOND, ACTION_FALLING, -1
6868 Ydiamond_e, FALSE, FALSE,
6869 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
6872 Ydiamond_eB, FALSE, TRUE,
6873 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
6876 Ydiamond_w, FALSE, FALSE,
6877 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
6880 Ydiamond_wB, FALSE, TRUE,
6881 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
6884 Ydiamond_eat, FALSE, FALSE,
6885 EL_DIAMOND, ACTION_COLLECTING, -1
6888 Ydiamond_stone, FALSE, FALSE,
6889 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
6892 Xdrip_fall, TRUE, FALSE,
6893 EL_AMOEBA_DROP, -1, -1
6896 Xdrip_stretch, FALSE, FALSE,
6897 EL_AMOEBA_DROP, ACTION_FALLING, -1
6900 Xdrip_stretchB, FALSE, TRUE,
6901 EL_AMOEBA_DROP, ACTION_FALLING, -1
6904 Xdrip_eat, FALSE, FALSE,
6905 EL_AMOEBA_DROP, ACTION_GROWING, -1
6908 Ydrip_s1, FALSE, FALSE,
6909 EL_AMOEBA_DROP, ACTION_FALLING, -1
6912 Ydrip_s1B, FALSE, TRUE,
6913 EL_AMOEBA_DROP, ACTION_FALLING, -1
6916 Ydrip_s2, FALSE, FALSE,
6917 EL_AMOEBA_DROP, ACTION_FALLING, -1
6920 Ydrip_s2B, FALSE, TRUE,
6921 EL_AMOEBA_DROP, ACTION_FALLING, -1
6928 Xbomb_pause, FALSE, FALSE,
6932 Xbomb_fall, FALSE, FALSE,
6936 Ybomb_s, FALSE, FALSE,
6937 EL_BOMB, ACTION_FALLING, -1
6940 Ybomb_sB, FALSE, TRUE,
6941 EL_BOMB, ACTION_FALLING, -1
6944 Ybomb_e, FALSE, FALSE,
6945 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
6948 Ybomb_eB, FALSE, TRUE,
6949 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
6952 Ybomb_w, FALSE, FALSE,
6953 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
6956 Ybomb_wB, FALSE, TRUE,
6957 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
6960 Ybomb_eat, FALSE, FALSE,
6961 EL_BOMB, ACTION_ACTIVATING, -1
6964 Xballoon, TRUE, FALSE,
6968 Yballoon_n, FALSE, FALSE,
6969 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
6972 Yballoon_nB, FALSE, TRUE,
6973 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
6976 Yballoon_e, FALSE, FALSE,
6977 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
6980 Yballoon_eB, FALSE, TRUE,
6981 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
6984 Yballoon_s, FALSE, FALSE,
6985 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
6988 Yballoon_sB, FALSE, TRUE,
6989 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
6992 Yballoon_w, FALSE, FALSE,
6993 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
6996 Yballoon_wB, FALSE, TRUE,
6997 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7000 Xgrass, TRUE, FALSE,
7001 EL_EMC_GRASS, -1, -1
7004 Ygrass_nB, FALSE, FALSE,
7005 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
7008 Ygrass_eB, FALSE, FALSE,
7009 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
7012 Ygrass_sB, FALSE, FALSE,
7013 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
7016 Ygrass_wB, FALSE, FALSE,
7017 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
7024 Ydirt_nB, FALSE, FALSE,
7025 EL_SAND, ACTION_DIGGING, MV_BIT_UP
7028 Ydirt_eB, FALSE, FALSE,
7029 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
7032 Ydirt_sB, FALSE, FALSE,
7033 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
7036 Ydirt_wB, FALSE, FALSE,
7037 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
7040 Xacid_ne, TRUE, FALSE,
7041 EL_ACID_POOL_TOPRIGHT, -1, -1
7044 Xacid_se, TRUE, FALSE,
7045 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
7048 Xacid_s, TRUE, FALSE,
7049 EL_ACID_POOL_BOTTOM, -1, -1
7052 Xacid_sw, TRUE, FALSE,
7053 EL_ACID_POOL_BOTTOMLEFT, -1, -1
7056 Xacid_nw, TRUE, FALSE,
7057 EL_ACID_POOL_TOPLEFT, -1, -1
7060 Xacid_1, TRUE, FALSE,
7064 Xacid_2, FALSE, FALSE,
7068 Xacid_3, FALSE, FALSE,
7072 Xacid_4, FALSE, FALSE,
7076 Xacid_5, FALSE, FALSE,
7080 Xacid_6, FALSE, FALSE,
7084 Xacid_7, FALSE, FALSE,
7088 Xacid_8, FALSE, FALSE,
7092 Xball_1, TRUE, FALSE,
7093 EL_EMC_MAGIC_BALL, -1, -1
7096 Xball_1B, FALSE, FALSE,
7097 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7100 Xball_2, FALSE, FALSE,
7101 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7104 Xball_2B, FALSE, FALSE,
7105 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7108 Yball_eat, FALSE, FALSE,
7109 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
7112 Ykey_1_eat, FALSE, FALSE,
7113 EL_EM_KEY_1, ACTION_COLLECTING, -1
7116 Ykey_2_eat, FALSE, FALSE,
7117 EL_EM_KEY_2, ACTION_COLLECTING, -1
7120 Ykey_3_eat, FALSE, FALSE,
7121 EL_EM_KEY_3, ACTION_COLLECTING, -1
7124 Ykey_4_eat, FALSE, FALSE,
7125 EL_EM_KEY_4, ACTION_COLLECTING, -1
7128 Ykey_5_eat, FALSE, FALSE,
7129 EL_EMC_KEY_5, ACTION_COLLECTING, -1
7132 Ykey_6_eat, FALSE, FALSE,
7133 EL_EMC_KEY_6, ACTION_COLLECTING, -1
7136 Ykey_7_eat, FALSE, FALSE,
7137 EL_EMC_KEY_7, ACTION_COLLECTING, -1
7140 Ykey_8_eat, FALSE, FALSE,
7141 EL_EMC_KEY_8, ACTION_COLLECTING, -1
7144 Ylenses_eat, FALSE, FALSE,
7145 EL_EMC_LENSES, ACTION_COLLECTING, -1
7148 Ymagnify_eat, FALSE, FALSE,
7149 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
7152 Ygrass_eat, FALSE, FALSE,
7153 EL_EMC_GRASS, ACTION_SNAPPING, -1
7156 Ydirt_eat, FALSE, FALSE,
7157 EL_SAND, ACTION_SNAPPING, -1
7160 Xgrow_ns, TRUE, FALSE,
7161 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
7164 Ygrow_ns_eat, FALSE, FALSE,
7165 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
7168 Xgrow_ew, TRUE, FALSE,
7169 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
7172 Ygrow_ew_eat, FALSE, FALSE,
7173 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
7176 Xwonderwall, TRUE, FALSE,
7177 EL_MAGIC_WALL, -1, -1
7180 XwonderwallB, FALSE, FALSE,
7181 EL_MAGIC_WALL, ACTION_ACTIVE, -1
7184 Xamoeba_1, TRUE, FALSE,
7185 EL_AMOEBA_DRY, ACTION_OTHER, -1
7188 Xamoeba_2, FALSE, FALSE,
7189 EL_AMOEBA_DRY, ACTION_OTHER, -1
7192 Xamoeba_3, FALSE, FALSE,
7193 EL_AMOEBA_DRY, ACTION_OTHER, -1
7196 Xamoeba_4, FALSE, FALSE,
7197 EL_AMOEBA_DRY, ACTION_OTHER, -1
7200 Xamoeba_5, TRUE, FALSE,
7201 EL_AMOEBA_WET, ACTION_OTHER, -1
7204 Xamoeba_6, FALSE, FALSE,
7205 EL_AMOEBA_WET, ACTION_OTHER, -1
7208 Xamoeba_7, FALSE, FALSE,
7209 EL_AMOEBA_WET, ACTION_OTHER, -1
7212 Xamoeba_8, FALSE, FALSE,
7213 EL_AMOEBA_WET, ACTION_OTHER, -1
7216 Xdoor_1, TRUE, FALSE,
7217 EL_EM_GATE_1, -1, -1
7220 Xdoor_2, TRUE, FALSE,
7221 EL_EM_GATE_2, -1, -1
7224 Xdoor_3, TRUE, FALSE,
7225 EL_EM_GATE_3, -1, -1
7228 Xdoor_4, TRUE, FALSE,
7229 EL_EM_GATE_4, -1, -1
7232 Xdoor_5, TRUE, FALSE,
7233 EL_EMC_GATE_5, -1, -1
7236 Xdoor_6, TRUE, FALSE,
7237 EL_EMC_GATE_6, -1, -1
7240 Xdoor_7, TRUE, FALSE,
7241 EL_EMC_GATE_7, -1, -1
7244 Xdoor_8, TRUE, FALSE,
7245 EL_EMC_GATE_8, -1, -1
7248 Xkey_1, TRUE, FALSE,
7252 Xkey_2, TRUE, FALSE,
7256 Xkey_3, TRUE, FALSE,
7260 Xkey_4, TRUE, FALSE,
7264 Xkey_5, TRUE, FALSE,
7265 EL_EMC_KEY_5, -1, -1
7268 Xkey_6, TRUE, FALSE,
7269 EL_EMC_KEY_6, -1, -1
7272 Xkey_7, TRUE, FALSE,
7273 EL_EMC_KEY_7, -1, -1
7276 Xkey_8, TRUE, FALSE,
7277 EL_EMC_KEY_8, -1, -1
7280 Xwind_n, TRUE, FALSE,
7281 EL_BALLOON_SWITCH_UP, -1, -1
7284 Xwind_e, TRUE, FALSE,
7285 EL_BALLOON_SWITCH_RIGHT, -1, -1
7288 Xwind_s, TRUE, FALSE,
7289 EL_BALLOON_SWITCH_DOWN, -1, -1
7292 Xwind_w, TRUE, FALSE,
7293 EL_BALLOON_SWITCH_LEFT, -1, -1
7296 Xwind_nesw, TRUE, FALSE,
7297 EL_BALLOON_SWITCH_ANY, -1, -1
7300 Xwind_stop, TRUE, FALSE,
7301 EL_BALLOON_SWITCH_NONE, -1, -1
7305 EL_EM_EXIT_CLOSED, -1, -1
7308 Xexit_1, TRUE, FALSE,
7309 EL_EM_EXIT_OPEN, -1, -1
7312 Xexit_2, FALSE, FALSE,
7313 EL_EM_EXIT_OPEN, -1, -1
7316 Xexit_3, FALSE, FALSE,
7317 EL_EM_EXIT_OPEN, -1, -1
7320 Xdynamite, TRUE, FALSE,
7321 EL_EM_DYNAMITE, -1, -1
7324 Ydynamite_eat, FALSE, FALSE,
7325 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
7328 Xdynamite_1, TRUE, FALSE,
7329 EL_EM_DYNAMITE_ACTIVE, -1, -1
7332 Xdynamite_2, FALSE, FALSE,
7333 EL_EM_DYNAMITE_ACTIVE, -1, -1
7336 Xdynamite_3, FALSE, FALSE,
7337 EL_EM_DYNAMITE_ACTIVE, -1, -1
7340 Xdynamite_4, FALSE, FALSE,
7341 EL_EM_DYNAMITE_ACTIVE, -1, -1
7344 Xbumper, TRUE, FALSE,
7345 EL_EMC_SPRING_BUMPER, -1, -1
7348 XbumperB, FALSE, FALSE,
7349 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
7352 Xwheel, TRUE, FALSE,
7353 EL_ROBOT_WHEEL, -1, -1
7356 XwheelB, FALSE, FALSE,
7357 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
7360 Xswitch, TRUE, FALSE,
7361 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
7364 XswitchB, FALSE, FALSE,
7365 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
7369 EL_QUICKSAND_EMPTY, -1, -1
7372 Xsand_stone, TRUE, FALSE,
7373 EL_QUICKSAND_FULL, -1, -1
7376 Xsand_stonein_1, FALSE, TRUE,
7377 EL_ROCK, ACTION_FILLING, -1
7380 Xsand_stonein_2, FALSE, TRUE,
7381 EL_ROCK, ACTION_FILLING, -1
7384 Xsand_stonein_3, FALSE, TRUE,
7385 EL_ROCK, ACTION_FILLING, -1
7388 Xsand_stonein_4, FALSE, TRUE,
7389 EL_ROCK, ACTION_FILLING, -1
7393 Xsand_stonesand_1, FALSE, FALSE,
7394 EL_QUICKSAND_EMPTYING, -1, -1
7397 Xsand_stonesand_2, FALSE, FALSE,
7398 EL_QUICKSAND_EMPTYING, -1, -1
7401 Xsand_stonesand_3, FALSE, FALSE,
7402 EL_QUICKSAND_EMPTYING, -1, -1
7405 Xsand_stonesand_4, FALSE, FALSE,
7406 EL_QUICKSAND_EMPTYING, -1, -1
7409 Xsand_stonesand_quickout_1, FALSE, FALSE,
7410 EL_QUICKSAND_EMPTYING, -1, -1
7413 Xsand_stonesand_quickout_2, FALSE, FALSE,
7414 EL_QUICKSAND_EMPTYING, -1, -1
7418 Xsand_stonesand_1, FALSE, FALSE,
7419 EL_QUICKSAND_FULL, -1, -1
7422 Xsand_stonesand_2, FALSE, FALSE,
7423 EL_QUICKSAND_FULL, -1, -1
7426 Xsand_stonesand_3, FALSE, FALSE,
7427 EL_QUICKSAND_FULL, -1, -1
7430 Xsand_stonesand_4, FALSE, FALSE,
7431 EL_QUICKSAND_FULL, -1, -1
7435 Xsand_stoneout_1, FALSE, FALSE,
7436 EL_ROCK, ACTION_EMPTYING, -1
7439 Xsand_stoneout_2, FALSE, FALSE,
7440 EL_ROCK, ACTION_EMPTYING, -1
7444 Xsand_sandstone_1, FALSE, FALSE,
7445 EL_QUICKSAND_FILLING, -1, -1
7448 Xsand_sandstone_2, FALSE, FALSE,
7449 EL_QUICKSAND_FILLING, -1, -1
7452 Xsand_sandstone_3, FALSE, FALSE,
7453 EL_QUICKSAND_FILLING, -1, -1
7456 Xsand_sandstone_4, FALSE, FALSE,
7457 EL_QUICKSAND_FILLING, -1, -1
7461 Xsand_sandstone_1, FALSE, FALSE,
7462 EL_QUICKSAND_FULL, -1, -1
7465 Xsand_sandstone_2, FALSE, FALSE,
7466 EL_QUICKSAND_FULL, -1, -1
7469 Xsand_sandstone_3, FALSE, FALSE,
7470 EL_QUICKSAND_FULL, -1, -1
7473 Xsand_sandstone_4, FALSE, FALSE,
7474 EL_QUICKSAND_FULL, -1, -1
7478 Xplant, TRUE, FALSE,
7479 EL_EMC_PLANT, -1, -1
7482 Yplant, FALSE, FALSE,
7483 EL_EMC_PLANT, -1, -1
7486 Xlenses, TRUE, FALSE,
7487 EL_EMC_LENSES, -1, -1
7490 Xmagnify, TRUE, FALSE,
7491 EL_EMC_MAGNIFIER, -1, -1
7494 Xdripper, TRUE, FALSE,
7495 EL_EMC_DRIPPER, -1, -1
7498 XdripperB, FALSE, FALSE,
7499 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
7502 Xfake_blank, TRUE, FALSE,
7503 EL_INVISIBLE_WALL, -1, -1
7506 Xfake_blankB, FALSE, FALSE,
7507 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
7510 Xfake_grass, TRUE, FALSE,
7511 EL_EMC_FAKE_GRASS, -1, -1
7514 Xfake_grassB, FALSE, FALSE,
7515 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
7518 Xfake_door_1, TRUE, FALSE,
7519 EL_EM_GATE_1_GRAY, -1, -1
7522 Xfake_door_2, TRUE, FALSE,
7523 EL_EM_GATE_2_GRAY, -1, -1
7526 Xfake_door_3, TRUE, FALSE,
7527 EL_EM_GATE_3_GRAY, -1, -1
7530 Xfake_door_4, TRUE, FALSE,
7531 EL_EM_GATE_4_GRAY, -1, -1
7534 Xfake_door_5, TRUE, FALSE,
7535 EL_EMC_GATE_5_GRAY, -1, -1
7538 Xfake_door_6, TRUE, FALSE,
7539 EL_EMC_GATE_6_GRAY, -1, -1
7542 Xfake_door_7, TRUE, FALSE,
7543 EL_EMC_GATE_7_GRAY, -1, -1
7546 Xfake_door_8, TRUE, FALSE,
7547 EL_EMC_GATE_8_GRAY, -1, -1
7550 Xfake_acid_1, TRUE, FALSE,
7551 EL_EMC_FAKE_ACID, -1, -1
7554 Xfake_acid_2, FALSE, FALSE,
7555 EL_EMC_FAKE_ACID, -1, -1
7558 Xfake_acid_3, FALSE, FALSE,
7559 EL_EMC_FAKE_ACID, -1, -1
7562 Xfake_acid_4, FALSE, FALSE,
7563 EL_EMC_FAKE_ACID, -1, -1
7566 Xfake_acid_5, FALSE, FALSE,
7567 EL_EMC_FAKE_ACID, -1, -1
7570 Xfake_acid_6, FALSE, FALSE,
7571 EL_EMC_FAKE_ACID, -1, -1
7574 Xfake_acid_7, FALSE, FALSE,
7575 EL_EMC_FAKE_ACID, -1, -1
7578 Xfake_acid_8, FALSE, FALSE,
7579 EL_EMC_FAKE_ACID, -1, -1
7582 Xsteel_1, TRUE, FALSE,
7583 EL_STEELWALL, -1, -1
7586 Xsteel_2, TRUE, FALSE,
7587 EL_EMC_STEELWALL_2, -1, -1
7590 Xsteel_3, TRUE, FALSE,
7591 EL_EMC_STEELWALL_3, -1, -1
7594 Xsteel_4, TRUE, FALSE,
7595 EL_EMC_STEELWALL_4, -1, -1
7598 Xwall_1, TRUE, FALSE,
7602 Xwall_2, TRUE, FALSE,
7603 EL_EMC_WALL_14, -1, -1
7606 Xwall_3, TRUE, FALSE,
7607 EL_EMC_WALL_15, -1, -1
7610 Xwall_4, TRUE, FALSE,
7611 EL_EMC_WALL_16, -1, -1
7614 Xround_wall_1, TRUE, FALSE,
7615 EL_WALL_SLIPPERY, -1, -1
7618 Xround_wall_2, TRUE, FALSE,
7619 EL_EMC_WALL_SLIPPERY_2, -1, -1
7622 Xround_wall_3, TRUE, FALSE,
7623 EL_EMC_WALL_SLIPPERY_3, -1, -1
7626 Xround_wall_4, TRUE, FALSE,
7627 EL_EMC_WALL_SLIPPERY_4, -1, -1
7630 Xdecor_1, TRUE, FALSE,
7631 EL_EMC_WALL_8, -1, -1
7634 Xdecor_2, TRUE, FALSE,
7635 EL_EMC_WALL_6, -1, -1
7638 Xdecor_3, TRUE, FALSE,
7639 EL_EMC_WALL_4, -1, -1
7642 Xdecor_4, TRUE, FALSE,
7643 EL_EMC_WALL_7, -1, -1
7646 Xdecor_5, TRUE, FALSE,
7647 EL_EMC_WALL_5, -1, -1
7650 Xdecor_6, TRUE, FALSE,
7651 EL_EMC_WALL_9, -1, -1
7654 Xdecor_7, TRUE, FALSE,
7655 EL_EMC_WALL_10, -1, -1
7658 Xdecor_8, TRUE, FALSE,
7659 EL_EMC_WALL_1, -1, -1
7662 Xdecor_9, TRUE, FALSE,
7663 EL_EMC_WALL_2, -1, -1
7666 Xdecor_10, TRUE, FALSE,
7667 EL_EMC_WALL_3, -1, -1
7670 Xdecor_11, TRUE, FALSE,
7671 EL_EMC_WALL_11, -1, -1
7674 Xdecor_12, TRUE, FALSE,
7675 EL_EMC_WALL_12, -1, -1
7678 Xalpha_0, TRUE, FALSE,
7679 EL_CHAR('0'), -1, -1
7682 Xalpha_1, TRUE, FALSE,
7683 EL_CHAR('1'), -1, -1
7686 Xalpha_2, TRUE, FALSE,
7687 EL_CHAR('2'), -1, -1
7690 Xalpha_3, TRUE, FALSE,
7691 EL_CHAR('3'), -1, -1
7694 Xalpha_4, TRUE, FALSE,
7695 EL_CHAR('4'), -1, -1
7698 Xalpha_5, TRUE, FALSE,
7699 EL_CHAR('5'), -1, -1
7702 Xalpha_6, TRUE, FALSE,
7703 EL_CHAR('6'), -1, -1
7706 Xalpha_7, TRUE, FALSE,
7707 EL_CHAR('7'), -1, -1
7710 Xalpha_8, TRUE, FALSE,
7711 EL_CHAR('8'), -1, -1
7714 Xalpha_9, TRUE, FALSE,
7715 EL_CHAR('9'), -1, -1
7718 Xalpha_excla, TRUE, FALSE,
7719 EL_CHAR('!'), -1, -1
7722 Xalpha_quote, TRUE, FALSE,
7723 EL_CHAR('"'), -1, -1
7726 Xalpha_comma, TRUE, FALSE,
7727 EL_CHAR(','), -1, -1
7730 Xalpha_minus, TRUE, FALSE,
7731 EL_CHAR('-'), -1, -1
7734 Xalpha_perio, TRUE, FALSE,
7735 EL_CHAR('.'), -1, -1
7738 Xalpha_colon, TRUE, FALSE,
7739 EL_CHAR(':'), -1, -1
7742 Xalpha_quest, TRUE, FALSE,
7743 EL_CHAR('?'), -1, -1
7746 Xalpha_a, TRUE, FALSE,
7747 EL_CHAR('A'), -1, -1
7750 Xalpha_b, TRUE, FALSE,
7751 EL_CHAR('B'), -1, -1
7754 Xalpha_c, TRUE, FALSE,
7755 EL_CHAR('C'), -1, -1
7758 Xalpha_d, TRUE, FALSE,
7759 EL_CHAR('D'), -1, -1
7762 Xalpha_e, TRUE, FALSE,
7763 EL_CHAR('E'), -1, -1
7766 Xalpha_f, TRUE, FALSE,
7767 EL_CHAR('F'), -1, -1
7770 Xalpha_g, TRUE, FALSE,
7771 EL_CHAR('G'), -1, -1
7774 Xalpha_h, TRUE, FALSE,
7775 EL_CHAR('H'), -1, -1
7778 Xalpha_i, TRUE, FALSE,
7779 EL_CHAR('I'), -1, -1
7782 Xalpha_j, TRUE, FALSE,
7783 EL_CHAR('J'), -1, -1
7786 Xalpha_k, TRUE, FALSE,
7787 EL_CHAR('K'), -1, -1
7790 Xalpha_l, TRUE, FALSE,
7791 EL_CHAR('L'), -1, -1
7794 Xalpha_m, TRUE, FALSE,
7795 EL_CHAR('M'), -1, -1
7798 Xalpha_n, TRUE, FALSE,
7799 EL_CHAR('N'), -1, -1
7802 Xalpha_o, TRUE, FALSE,
7803 EL_CHAR('O'), -1, -1
7806 Xalpha_p, TRUE, FALSE,
7807 EL_CHAR('P'), -1, -1
7810 Xalpha_q, TRUE, FALSE,
7811 EL_CHAR('Q'), -1, -1
7814 Xalpha_r, TRUE, FALSE,
7815 EL_CHAR('R'), -1, -1
7818 Xalpha_s, TRUE, FALSE,
7819 EL_CHAR('S'), -1, -1
7822 Xalpha_t, TRUE, FALSE,
7823 EL_CHAR('T'), -1, -1
7826 Xalpha_u, TRUE, FALSE,
7827 EL_CHAR('U'), -1, -1
7830 Xalpha_v, TRUE, FALSE,
7831 EL_CHAR('V'), -1, -1
7834 Xalpha_w, TRUE, FALSE,
7835 EL_CHAR('W'), -1, -1
7838 Xalpha_x, TRUE, FALSE,
7839 EL_CHAR('X'), -1, -1
7842 Xalpha_y, TRUE, FALSE,
7843 EL_CHAR('Y'), -1, -1
7846 Xalpha_z, TRUE, FALSE,
7847 EL_CHAR('Z'), -1, -1
7850 Xalpha_arrow_e, TRUE, FALSE,
7851 EL_CHAR('>'), -1, -1
7854 Xalpha_arrow_w, TRUE, FALSE,
7855 EL_CHAR('<'), -1, -1
7858 Xalpha_copyr, TRUE, FALSE,
7859 EL_CHAR('©'), -1, -1
7863 Xboom_bug, FALSE, FALSE,
7864 EL_BUG, ACTION_EXPLODING, -1
7867 Xboom_bomb, FALSE, FALSE,
7868 EL_BOMB, ACTION_EXPLODING, -1
7871 Xboom_android, FALSE, FALSE,
7872 EL_EMC_ANDROID, ACTION_OTHER, -1
7875 Xboom_1, FALSE, FALSE,
7876 EL_DEFAULT, ACTION_EXPLODING, -1
7879 Xboom_2, FALSE, FALSE,
7880 EL_DEFAULT, ACTION_EXPLODING, -1
7883 Znormal, FALSE, FALSE,
7887 Zdynamite, FALSE, FALSE,
7891 Zplayer, FALSE, FALSE,
7895 ZBORDER, FALSE, FALSE,
7905 static struct Mapping_EM_to_RND_player
7914 em_player_mapping_list[] =
7918 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
7922 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
7926 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
7930 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
7934 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
7938 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
7942 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
7946 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
7950 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
7954 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
7958 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
7962 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
7966 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
7970 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
7974 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
7978 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
7982 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
7986 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
7990 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
7994 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
7998 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
8002 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
8006 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
8010 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
8014 EL_PLAYER_1, ACTION_DEFAULT, -1,
8018 EL_PLAYER_2, ACTION_DEFAULT, -1,
8022 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
8026 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
8030 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
8034 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
8038 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
8042 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
8046 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
8050 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
8054 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
8058 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
8062 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
8066 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
8070 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
8074 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
8078 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
8082 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
8086 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
8090 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
8094 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
8098 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
8102 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
8106 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
8110 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
8114 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
8118 EL_PLAYER_3, ACTION_DEFAULT, -1,
8122 EL_PLAYER_4, ACTION_DEFAULT, -1,
8131 int map_element_RND_to_EM(int element_rnd)
8133 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
8134 static boolean mapping_initialized = FALSE;
8136 if (!mapping_initialized)
8140 /* return "Xalpha_quest" for all undefined elements in mapping array */
8141 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
8142 mapping_RND_to_EM[i] = Xalpha_quest;
8144 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8145 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
8146 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
8147 em_object_mapping_list[i].element_em;
8149 mapping_initialized = TRUE;
8152 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
8153 return mapping_RND_to_EM[element_rnd];
8155 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
8160 int map_element_EM_to_RND(int element_em)
8162 static unsigned short mapping_EM_to_RND[TILE_MAX];
8163 static boolean mapping_initialized = FALSE;
8165 if (!mapping_initialized)
8169 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
8170 for (i = 0; i < TILE_MAX; i++)
8171 mapping_EM_to_RND[i] = EL_UNKNOWN;
8173 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8174 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
8175 em_object_mapping_list[i].element_rnd;
8177 mapping_initialized = TRUE;
8180 if (element_em >= 0 && element_em < TILE_MAX)
8181 return mapping_EM_to_RND[element_em];
8183 Error(ERR_WARN, "invalid EM level element %d", element_em);
8188 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
8190 struct LevelInfo_EM *level_em = level->native_em_level;
8191 struct LEVEL *lev = level_em->lev;
8194 for (i = 0; i < TILE_MAX; i++)
8195 lev->android_array[i] = Xblank;
8197 for (i = 0; i < level->num_android_clone_elements; i++)
8199 int element_rnd = level->android_clone_element[i];
8200 int element_em = map_element_RND_to_EM(element_rnd);
8202 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
8203 if (em_object_mapping_list[j].element_rnd == element_rnd)
8204 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
8208 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
8210 struct LevelInfo_EM *level_em = level->native_em_level;
8211 struct LEVEL *lev = level_em->lev;
8214 level->num_android_clone_elements = 0;
8216 for (i = 0; i < TILE_MAX; i++)
8218 int element_em = lev->android_array[i];
8220 boolean element_found = FALSE;
8222 if (element_em == Xblank)
8225 element_rnd = map_element_EM_to_RND(element_em);
8227 for (j = 0; j < level->num_android_clone_elements; j++)
8228 if (level->android_clone_element[j] == element_rnd)
8229 element_found = TRUE;
8233 level->android_clone_element[level->num_android_clone_elements++] =
8236 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
8241 if (level->num_android_clone_elements == 0)
8243 level->num_android_clone_elements = 1;
8244 level->android_clone_element[0] = EL_EMPTY;
8248 int map_direction_RND_to_EM(int direction)
8250 return (direction == MV_UP ? 0 :
8251 direction == MV_RIGHT ? 1 :
8252 direction == MV_DOWN ? 2 :
8253 direction == MV_LEFT ? 3 :
8257 int map_direction_EM_to_RND(int direction)
8259 return (direction == 0 ? MV_UP :
8260 direction == 1 ? MV_RIGHT :
8261 direction == 2 ? MV_DOWN :
8262 direction == 3 ? MV_LEFT :
8266 int map_element_RND_to_SP(int element_rnd)
8268 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
8270 if (element_rnd >= EL_SP_START &&
8271 element_rnd <= EL_SP_END)
8272 element_sp = element_rnd - EL_SP_START;
8273 else if (element_rnd == EL_EMPTY_SPACE)
8275 else if (element_rnd == EL_INVISIBLE_WALL)
8281 int map_element_SP_to_RND(int element_sp)
8283 int element_rnd = EL_UNKNOWN;
8285 if (element_sp >= 0x00 &&
8287 element_rnd = EL_SP_START + element_sp;
8288 else if (element_sp == 0x28)
8289 element_rnd = EL_INVISIBLE_WALL;
8294 int map_action_SP_to_RND(int action_sp)
8298 case actActive: return ACTION_ACTIVE;
8299 case actImpact: return ACTION_IMPACT;
8300 case actExploding: return ACTION_EXPLODING;
8301 case actDigging: return ACTION_DIGGING;
8302 case actSnapping: return ACTION_SNAPPING;
8303 case actCollecting: return ACTION_COLLECTING;
8304 case actPassing: return ACTION_PASSING;
8305 case actPushing: return ACTION_PUSHING;
8306 case actDropping: return ACTION_DROPPING;
8308 default: return ACTION_DEFAULT;
8312 int get_next_element(int element)
8316 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
8317 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
8318 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
8319 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
8320 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
8321 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
8322 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
8323 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
8324 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
8325 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
8326 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
8328 default: return element;
8333 int el_act_dir2img(int element, int action, int direction)
8335 element = GFX_ELEMENT(element);
8337 if (direction == MV_NONE)
8338 return element_info[element].graphic[action];
8340 direction = MV_DIR_TO_BIT(direction);
8342 return element_info[element].direction_graphic[action][direction];
8345 int el_act_dir2img(int element, int action, int direction)
8347 element = GFX_ELEMENT(element);
8348 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
8350 /* direction_graphic[][] == graphic[] for undefined direction graphics */
8351 return element_info[element].direction_graphic[action][direction];
8356 static int el_act_dir2crm(int element, int action, int direction)
8358 element = GFX_ELEMENT(element);
8360 if (direction == MV_NONE)
8361 return element_info[element].crumbled[action];
8363 direction = MV_DIR_TO_BIT(direction);
8365 return element_info[element].direction_crumbled[action][direction];
8368 static int el_act_dir2crm(int element, int action, int direction)
8370 element = GFX_ELEMENT(element);
8371 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
8373 /* direction_graphic[][] == graphic[] for undefined direction graphics */
8374 return element_info[element].direction_crumbled[action][direction];
8378 int el_act2img(int element, int action)
8380 element = GFX_ELEMENT(element);
8382 return element_info[element].graphic[action];
8385 int el_act2crm(int element, int action)
8387 element = GFX_ELEMENT(element);
8389 return element_info[element].crumbled[action];
8392 int el_dir2img(int element, int direction)
8394 element = GFX_ELEMENT(element);
8396 return el_act_dir2img(element, ACTION_DEFAULT, direction);
8399 int el2baseimg(int element)
8401 return element_info[element].graphic[ACTION_DEFAULT];
8404 int el2img(int element)
8406 element = GFX_ELEMENT(element);
8408 return element_info[element].graphic[ACTION_DEFAULT];
8411 int el2edimg(int element)
8413 element = GFX_ELEMENT(element);
8415 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
8418 int el2preimg(int element)
8420 element = GFX_ELEMENT(element);
8422 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
8425 int el2panelimg(int element)
8427 element = GFX_ELEMENT(element);
8429 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
8432 int font2baseimg(int font_nr)
8434 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
8437 int getBeltNrFromBeltElement(int element)
8439 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
8440 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
8441 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
8444 int getBeltNrFromBeltActiveElement(int element)
8446 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
8447 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
8448 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
8451 int getBeltNrFromBeltSwitchElement(int element)
8453 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
8454 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
8455 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
8458 int getBeltDirNrFromBeltElement(int element)
8460 static int belt_base_element[4] =
8462 EL_CONVEYOR_BELT_1_LEFT,
8463 EL_CONVEYOR_BELT_2_LEFT,
8464 EL_CONVEYOR_BELT_3_LEFT,
8465 EL_CONVEYOR_BELT_4_LEFT
8468 int belt_nr = getBeltNrFromBeltElement(element);
8469 int belt_dir_nr = element - belt_base_element[belt_nr];
8471 return (belt_dir_nr % 3);
8474 int getBeltDirNrFromBeltSwitchElement(int element)
8476 static int belt_base_element[4] =
8478 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
8479 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
8480 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
8481 EL_CONVEYOR_BELT_4_SWITCH_LEFT
8484 int belt_nr = getBeltNrFromBeltSwitchElement(element);
8485 int belt_dir_nr = element - belt_base_element[belt_nr];
8487 return (belt_dir_nr % 3);
8490 int getBeltDirFromBeltElement(int element)
8492 static int belt_move_dir[3] =
8499 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
8501 return belt_move_dir[belt_dir_nr];
8504 int getBeltDirFromBeltSwitchElement(int element)
8506 static int belt_move_dir[3] =
8513 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
8515 return belt_move_dir[belt_dir_nr];
8518 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
8520 static int belt_base_element[4] =
8522 EL_CONVEYOR_BELT_1_LEFT,
8523 EL_CONVEYOR_BELT_2_LEFT,
8524 EL_CONVEYOR_BELT_3_LEFT,
8525 EL_CONVEYOR_BELT_4_LEFT
8528 return belt_base_element[belt_nr] + belt_dir_nr;
8531 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
8533 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
8535 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
8538 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
8540 static int belt_base_element[4] =
8542 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
8543 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
8544 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
8545 EL_CONVEYOR_BELT_4_SWITCH_LEFT
8548 return belt_base_element[belt_nr] + belt_dir_nr;
8551 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
8553 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
8555 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
8559 boolean getTeamMode_EM()
8561 return game.team_mode;
8564 int getNumActivePlayers_EM()
8567 int num_players = 0;
8571 return (setup.team_mode ? MAX_PLAYERS : 1);
8573 for (i = 0; i < MAX_PLAYERS; i++)
8574 if (tape.player_participates[i])
8577 return (num_players > 1 ? MAX_PLAYERS : 1);
8581 int num_players = 0;
8584 /* when recording game, activate all connected players */
8588 for (i = 0; i < MAX_PLAYERS; i++)
8589 if (tape.player_participates[i])
8597 int getGameFrameDelay_EM(int native_em_game_frame_delay)
8599 int game_frame_delay_value;
8601 game_frame_delay_value =
8602 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
8603 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
8606 if (tape.playing && tape.warp_forward && !tape.pausing)
8607 game_frame_delay_value = 0;
8609 return game_frame_delay_value;
8612 unsigned int InitRND(int seed)
8614 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
8615 return InitEngineRandom_EM(seed);
8616 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
8617 return InitEngineRandom_SP(seed);
8619 return InitEngineRandom_RND(seed);
8623 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
8624 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
8627 inline static int get_effective_element_EM(int tile, int frame_em)
8629 int element = object_mapping[tile].element_rnd;
8630 int action = object_mapping[tile].action;
8631 boolean is_backside = object_mapping[tile].is_backside;
8632 boolean action_removing = (action == ACTION_DIGGING ||
8633 action == ACTION_SNAPPING ||
8634 action == ACTION_COLLECTING);
8640 case Yacid_splash_eB:
8641 case Yacid_splash_wB:
8642 return (frame_em > 5 ? EL_EMPTY : element);
8646 case Ydiamond_stone:
8647 // if (!game.use_native_emc_graphics_engine)
8655 else /* frame_em == 7 */
8659 case Yacid_splash_eB:
8660 case Yacid_splash_wB:
8663 case Yemerald_stone:
8666 case Ydiamond_stone:
8670 case Xdrip_stretchB:
8689 case Xsand_stonein_1:
8690 case Xsand_stonein_2:
8691 case Xsand_stonein_3:
8692 case Xsand_stonein_4:
8696 return (is_backside || action_removing ? EL_EMPTY : element);
8701 inline static boolean check_linear_animation_EM(int tile)
8705 case Xsand_stonesand_1:
8706 case Xsand_stonesand_quickout_1:
8707 case Xsand_sandstone_1:
8708 case Xsand_stonein_1:
8709 case Xsand_stoneout_1:
8729 case Yacid_splash_eB:
8730 case Yacid_splash_wB:
8731 case Yemerald_stone:
8739 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
8740 boolean has_crumbled_graphics,
8741 int crumbled, int sync_frame)
8743 /* if element can be crumbled, but certain action graphics are just empty
8744 space (like instantly snapping sand to empty space in 1 frame), do not
8745 treat these empty space graphics as crumbled graphics in EMC engine */
8746 if (crumbled == IMG_EMPTY_SPACE)
8747 has_crumbled_graphics = FALSE;
8749 if (has_crumbled_graphics)
8751 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
8752 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
8753 g_crumbled->anim_delay,
8754 g_crumbled->anim_mode,
8755 g_crumbled->anim_start_frame,
8758 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
8759 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
8761 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
8763 g_em->has_crumbled_graphics = TRUE;
8767 g_em->crumbled_bitmap = NULL;
8768 g_em->crumbled_src_x = 0;
8769 g_em->crumbled_src_y = 0;
8770 g_em->crumbled_border_size = 0;
8772 g_em->has_crumbled_graphics = FALSE;
8776 void ResetGfxAnimation_EM(int x, int y, int tile)
8781 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
8782 int tile, int frame_em, int x, int y)
8784 int action = object_mapping[tile].action;
8786 int direction = object_mapping[tile].direction;
8787 int effective_element = get_effective_element_EM(tile, frame_em);
8788 int graphic = (direction == MV_NONE ?
8789 el_act2img(effective_element, action) :
8790 el_act_dir2img(effective_element, action, direction));
8791 struct GraphicInfo *g = &graphic_info[graphic];
8794 boolean action_removing = (action == ACTION_DIGGING ||
8795 action == ACTION_SNAPPING ||
8796 action == ACTION_COLLECTING);
8797 boolean action_moving = (action == ACTION_FALLING ||
8798 action == ACTION_MOVING ||
8799 action == ACTION_PUSHING ||
8800 action == ACTION_EATING ||
8801 action == ACTION_FILLING ||
8802 action == ACTION_EMPTYING);
8803 boolean action_falling = (action == ACTION_FALLING ||
8804 action == ACTION_FILLING ||
8805 action == ACTION_EMPTYING);
8807 /* special case: graphic uses "2nd movement tile" and has defined
8808 7 frames for movement animation (or less) => use default graphic
8809 for last (8th) frame which ends the movement animation */
8810 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
8812 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
8813 graphic = (direction == MV_NONE ?
8814 el_act2img(effective_element, action) :
8815 el_act_dir2img(effective_element, action, direction));
8817 g = &graphic_info[graphic];
8821 if (tile == Xsand_stonesand_1 ||
8822 tile == Xsand_stonesand_2 ||
8823 tile == Xsand_stonesand_3 ||
8824 tile == Xsand_stonesand_4)
8825 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
8829 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
8833 // printf("::: resetting... [%d]\n", tile);
8836 if (action_removing || check_linear_animation_EM(tile))
8838 GfxFrame[x][y] = frame_em;
8840 // printf("::: resetting... [%d]\n", tile);
8843 else if (action_moving)
8845 boolean is_backside = object_mapping[tile].is_backside;
8849 int direction = object_mapping[tile].direction;
8850 int move_dir = (action_falling ? MV_DOWN : direction);
8855 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
8856 if (g->double_movement && frame_em == 0)
8860 // printf("::: resetting... [%d]\n", tile);
8864 if (move_dir == MV_LEFT)
8865 GfxFrame[x - 1][y] = GfxFrame[x][y];
8866 else if (move_dir == MV_RIGHT)
8867 GfxFrame[x + 1][y] = GfxFrame[x][y];
8868 else if (move_dir == MV_UP)
8869 GfxFrame[x][y - 1] = GfxFrame[x][y];
8870 else if (move_dir == MV_DOWN)
8871 GfxFrame[x][y + 1] = GfxFrame[x][y];
8878 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
8879 if (tile == Xsand_stonesand_quickout_1 ||
8880 tile == Xsand_stonesand_quickout_2)
8885 if (tile == Xsand_stonesand_1 ||
8886 tile == Xsand_stonesand_2 ||
8887 tile == Xsand_stonesand_3 ||
8888 tile == Xsand_stonesand_4)
8889 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
8893 if (graphic_info[graphic].anim_global_sync)
8894 sync_frame = FrameCounter;
8895 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
8896 sync_frame = GfxFrame[x][y];
8898 sync_frame = 0; /* playfield border (pseudo steel) */
8900 SetRandomAnimationValue(x, y);
8902 int frame = getAnimationFrame(g->anim_frames,
8905 g->anim_start_frame,
8908 g_em->unique_identifier =
8909 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
8913 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
8914 int tile, int frame_em, int x, int y)
8916 int action = object_mapping[tile].action;
8917 int direction = object_mapping[tile].direction;
8918 boolean is_backside = object_mapping[tile].is_backside;
8919 int effective_element = get_effective_element_EM(tile, frame_em);
8921 int effective_action = action;
8923 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
8925 int graphic = (direction == MV_NONE ?
8926 el_act2img(effective_element, effective_action) :
8927 el_act_dir2img(effective_element, effective_action,
8929 int crumbled = (direction == MV_NONE ?
8930 el_act2crm(effective_element, effective_action) :
8931 el_act_dir2crm(effective_element, effective_action,
8933 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
8934 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
8935 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
8936 struct GraphicInfo *g = &graphic_info[graphic];
8938 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
8942 /* special case: graphic uses "2nd movement tile" and has defined
8943 7 frames for movement animation (or less) => use default graphic
8944 for last (8th) frame which ends the movement animation */
8945 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
8947 effective_action = ACTION_DEFAULT;
8948 graphic = (direction == MV_NONE ?
8949 el_act2img(effective_element, effective_action) :
8950 el_act_dir2img(effective_element, effective_action,
8952 crumbled = (direction == MV_NONE ?
8953 el_act2crm(effective_element, effective_action) :
8954 el_act_dir2crm(effective_element, effective_action,
8957 g = &graphic_info[graphic];
8967 if (frame_em == 0) /* reset animation frame for certain elements */
8969 if (check_linear_animation_EM(tile))
8974 if (graphic_info[graphic].anim_global_sync)
8975 sync_frame = FrameCounter;
8976 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
8977 sync_frame = GfxFrame[x][y];
8979 sync_frame = 0; /* playfield border (pseudo steel) */
8981 SetRandomAnimationValue(x, y);
8986 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
8987 i == Xdrip_stretchB ? 7 :
8988 i == Ydrip_s2 ? j + 8 :
8989 i == Ydrip_s2B ? j + 8 :
8998 i == Xfake_acid_1 ? 0 :
8999 i == Xfake_acid_2 ? 10 :
9000 i == Xfake_acid_3 ? 20 :
9001 i == Xfake_acid_4 ? 30 :
9002 i == Xfake_acid_5 ? 40 :
9003 i == Xfake_acid_6 ? 50 :
9004 i == Xfake_acid_7 ? 60 :
9005 i == Xfake_acid_8 ? 70 :
9007 i == Xball_2B ? j + 8 :
9008 i == Yball_eat ? j + 1 :
9009 i == Ykey_1_eat ? j + 1 :
9010 i == Ykey_2_eat ? j + 1 :
9011 i == Ykey_3_eat ? j + 1 :
9012 i == Ykey_4_eat ? j + 1 :
9013 i == Ykey_5_eat ? j + 1 :
9014 i == Ykey_6_eat ? j + 1 :
9015 i == Ykey_7_eat ? j + 1 :
9016 i == Ykey_8_eat ? j + 1 :
9017 i == Ylenses_eat ? j + 1 :
9018 i == Ymagnify_eat ? j + 1 :
9019 i == Ygrass_eat ? j + 1 :
9020 i == Ydirt_eat ? j + 1 :
9021 i == Xamoeba_1 ? 0 :
9022 i == Xamoeba_2 ? 1 :
9023 i == Xamoeba_3 ? 2 :
9024 i == Xamoeba_4 ? 3 :
9025 i == Xamoeba_5 ? 0 :
9026 i == Xamoeba_6 ? 1 :
9027 i == Xamoeba_7 ? 2 :
9028 i == Xamoeba_8 ? 3 :
9029 i == Xexit_2 ? j + 8 :
9030 i == Xexit_3 ? j + 16 :
9031 i == Xdynamite_1 ? 0 :
9032 i == Xdynamite_2 ? 8 :
9033 i == Xdynamite_3 ? 16 :
9034 i == Xdynamite_4 ? 24 :
9035 i == Xsand_stonein_1 ? j + 1 :
9036 i == Xsand_stonein_2 ? j + 9 :
9037 i == Xsand_stonein_3 ? j + 17 :
9038 i == Xsand_stonein_4 ? j + 25 :
9039 i == Xsand_stoneout_1 && j == 0 ? 0 :
9040 i == Xsand_stoneout_1 && j == 1 ? 0 :
9041 i == Xsand_stoneout_1 && j == 2 ? 1 :
9042 i == Xsand_stoneout_1 && j == 3 ? 2 :
9043 i == Xsand_stoneout_1 && j == 4 ? 2 :
9044 i == Xsand_stoneout_1 && j == 5 ? 3 :
9045 i == Xsand_stoneout_1 && j == 6 ? 4 :
9046 i == Xsand_stoneout_1 && j == 7 ? 4 :
9047 i == Xsand_stoneout_2 && j == 0 ? 5 :
9048 i == Xsand_stoneout_2 && j == 1 ? 6 :
9049 i == Xsand_stoneout_2 && j == 2 ? 7 :
9050 i == Xsand_stoneout_2 && j == 3 ? 8 :
9051 i == Xsand_stoneout_2 && j == 4 ? 9 :
9052 i == Xsand_stoneout_2 && j == 5 ? 11 :
9053 i == Xsand_stoneout_2 && j == 6 ? 13 :
9054 i == Xsand_stoneout_2 && j == 7 ? 15 :
9055 i == Xboom_bug && j == 1 ? 2 :
9056 i == Xboom_bug && j == 2 ? 2 :
9057 i == Xboom_bug && j == 3 ? 4 :
9058 i == Xboom_bug && j == 4 ? 4 :
9059 i == Xboom_bug && j == 5 ? 2 :
9060 i == Xboom_bug && j == 6 ? 2 :
9061 i == Xboom_bug && j == 7 ? 0 :
9062 i == Xboom_bomb && j == 1 ? 2 :
9063 i == Xboom_bomb && j == 2 ? 2 :
9064 i == Xboom_bomb && j == 3 ? 4 :
9065 i == Xboom_bomb && j == 4 ? 4 :
9066 i == Xboom_bomb && j == 5 ? 2 :
9067 i == Xboom_bomb && j == 6 ? 2 :
9068 i == Xboom_bomb && j == 7 ? 0 :
9069 i == Xboom_android && j == 7 ? 6 :
9070 i == Xboom_1 && j == 1 ? 2 :
9071 i == Xboom_1 && j == 2 ? 2 :
9072 i == Xboom_1 && j == 3 ? 4 :
9073 i == Xboom_1 && j == 4 ? 4 :
9074 i == Xboom_1 && j == 5 ? 6 :
9075 i == Xboom_1 && j == 6 ? 6 :
9076 i == Xboom_1 && j == 7 ? 8 :
9077 i == Xboom_2 && j == 0 ? 8 :
9078 i == Xboom_2 && j == 1 ? 8 :
9079 i == Xboom_2 && j == 2 ? 10 :
9080 i == Xboom_2 && j == 3 ? 10 :
9081 i == Xboom_2 && j == 4 ? 10 :
9082 i == Xboom_2 && j == 5 ? 12 :
9083 i == Xboom_2 && j == 6 ? 12 :
9084 i == Xboom_2 && j == 7 ? 12 :
9086 special_animation && j == 4 ? 3 :
9087 effective_action != action ? 0 :
9093 int xxx_effective_action;
9094 int xxx_has_action_graphics;
9097 int element = object_mapping[i].element_rnd;
9098 int action = object_mapping[i].action;
9099 int direction = object_mapping[i].direction;
9100 boolean is_backside = object_mapping[i].is_backside;
9102 boolean action_removing = (action == ACTION_DIGGING ||
9103 action == ACTION_SNAPPING ||
9104 action == ACTION_COLLECTING);
9106 boolean action_exploding = ((action == ACTION_EXPLODING ||
9107 action == ACTION_SMASHED_BY_ROCK ||
9108 action == ACTION_SMASHED_BY_SPRING) &&
9109 element != EL_DIAMOND);
9110 boolean action_active = (action == ACTION_ACTIVE);
9111 boolean action_other = (action == ACTION_OTHER);
9115 int effective_element = get_effective_element_EM(i, j);
9117 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
9118 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
9120 i == Xdrip_stretch ? element :
9121 i == Xdrip_stretchB ? element :
9122 i == Ydrip_s1 ? element :
9123 i == Ydrip_s1B ? element :
9124 i == Xball_1B ? element :
9125 i == Xball_2 ? element :
9126 i == Xball_2B ? element :
9127 i == Yball_eat ? element :
9128 i == Ykey_1_eat ? element :
9129 i == Ykey_2_eat ? element :
9130 i == Ykey_3_eat ? element :
9131 i == Ykey_4_eat ? element :
9132 i == Ykey_5_eat ? element :
9133 i == Ykey_6_eat ? element :
9134 i == Ykey_7_eat ? element :
9135 i == Ykey_8_eat ? element :
9136 i == Ylenses_eat ? element :
9137 i == Ymagnify_eat ? element :
9138 i == Ygrass_eat ? element :
9139 i == Ydirt_eat ? element :
9140 i == Yemerald_stone ? EL_EMERALD :
9141 i == Ydiamond_stone ? EL_ROCK :
9142 i == Xsand_stonein_1 ? element :
9143 i == Xsand_stonein_2 ? element :
9144 i == Xsand_stonein_3 ? element :
9145 i == Xsand_stonein_4 ? element :
9146 is_backside ? EL_EMPTY :
9147 action_removing ? EL_EMPTY :
9150 int effective_action = (j < 7 ? action :
9151 i == Xdrip_stretch ? action :
9152 i == Xdrip_stretchB ? action :
9153 i == Ydrip_s1 ? action :
9154 i == Ydrip_s1B ? action :
9155 i == Xball_1B ? action :
9156 i == Xball_2 ? action :
9157 i == Xball_2B ? action :
9158 i == Yball_eat ? action :
9159 i == Ykey_1_eat ? action :
9160 i == Ykey_2_eat ? action :
9161 i == Ykey_3_eat ? action :
9162 i == Ykey_4_eat ? action :
9163 i == Ykey_5_eat ? action :
9164 i == Ykey_6_eat ? action :
9165 i == Ykey_7_eat ? action :
9166 i == Ykey_8_eat ? action :
9167 i == Ylenses_eat ? action :
9168 i == Ymagnify_eat ? action :
9169 i == Ygrass_eat ? action :
9170 i == Ydirt_eat ? action :
9171 i == Xsand_stonein_1 ? action :
9172 i == Xsand_stonein_2 ? action :
9173 i == Xsand_stonein_3 ? action :
9174 i == Xsand_stonein_4 ? action :
9175 i == Xsand_stoneout_1 ? action :
9176 i == Xsand_stoneout_2 ? action :
9177 i == Xboom_android ? ACTION_EXPLODING :
9178 action_exploding ? ACTION_EXPLODING :
9179 action_active ? action :
9180 action_other ? action :
9182 int graphic = (el_act_dir2img(effective_element, effective_action,
9184 int crumbled = (el_act_dir2crm(effective_element, effective_action,
9186 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9187 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9188 boolean has_action_graphics = (graphic != base_graphic);
9189 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9190 struct GraphicInfo *g = &graphic_info[graphic];
9192 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9194 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
9197 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
9198 boolean special_animation = (action != ACTION_DEFAULT &&
9199 g->anim_frames == 3 &&
9200 g->anim_delay == 2 &&
9201 g->anim_mode & ANIM_LINEAR);
9202 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9203 i == Xdrip_stretchB ? 7 :
9204 i == Ydrip_s2 ? j + 8 :
9205 i == Ydrip_s2B ? j + 8 :
9214 i == Xfake_acid_1 ? 0 :
9215 i == Xfake_acid_2 ? 10 :
9216 i == Xfake_acid_3 ? 20 :
9217 i == Xfake_acid_4 ? 30 :
9218 i == Xfake_acid_5 ? 40 :
9219 i == Xfake_acid_6 ? 50 :
9220 i == Xfake_acid_7 ? 60 :
9221 i == Xfake_acid_8 ? 70 :
9223 i == Xball_2B ? j + 8 :
9224 i == Yball_eat ? j + 1 :
9225 i == Ykey_1_eat ? j + 1 :
9226 i == Ykey_2_eat ? j + 1 :
9227 i == Ykey_3_eat ? j + 1 :
9228 i == Ykey_4_eat ? j + 1 :
9229 i == Ykey_5_eat ? j + 1 :
9230 i == Ykey_6_eat ? j + 1 :
9231 i == Ykey_7_eat ? j + 1 :
9232 i == Ykey_8_eat ? j + 1 :
9233 i == Ylenses_eat ? j + 1 :
9234 i == Ymagnify_eat ? j + 1 :
9235 i == Ygrass_eat ? j + 1 :
9236 i == Ydirt_eat ? j + 1 :
9237 i == Xamoeba_1 ? 0 :
9238 i == Xamoeba_2 ? 1 :
9239 i == Xamoeba_3 ? 2 :
9240 i == Xamoeba_4 ? 3 :
9241 i == Xamoeba_5 ? 0 :
9242 i == Xamoeba_6 ? 1 :
9243 i == Xamoeba_7 ? 2 :
9244 i == Xamoeba_8 ? 3 :
9245 i == Xexit_2 ? j + 8 :
9246 i == Xexit_3 ? j + 16 :
9247 i == Xdynamite_1 ? 0 :
9248 i == Xdynamite_2 ? 8 :
9249 i == Xdynamite_3 ? 16 :
9250 i == Xdynamite_4 ? 24 :
9251 i == Xsand_stonein_1 ? j + 1 :
9252 i == Xsand_stonein_2 ? j + 9 :
9253 i == Xsand_stonein_3 ? j + 17 :
9254 i == Xsand_stonein_4 ? j + 25 :
9255 i == Xsand_stoneout_1 && j == 0 ? 0 :
9256 i == Xsand_stoneout_1 && j == 1 ? 0 :
9257 i == Xsand_stoneout_1 && j == 2 ? 1 :
9258 i == Xsand_stoneout_1 && j == 3 ? 2 :
9259 i == Xsand_stoneout_1 && j == 4 ? 2 :
9260 i == Xsand_stoneout_1 && j == 5 ? 3 :
9261 i == Xsand_stoneout_1 && j == 6 ? 4 :
9262 i == Xsand_stoneout_1 && j == 7 ? 4 :
9263 i == Xsand_stoneout_2 && j == 0 ? 5 :
9264 i == Xsand_stoneout_2 && j == 1 ? 6 :
9265 i == Xsand_stoneout_2 && j == 2 ? 7 :
9266 i == Xsand_stoneout_2 && j == 3 ? 8 :
9267 i == Xsand_stoneout_2 && j == 4 ? 9 :
9268 i == Xsand_stoneout_2 && j == 5 ? 11 :
9269 i == Xsand_stoneout_2 && j == 6 ? 13 :
9270 i == Xsand_stoneout_2 && j == 7 ? 15 :
9271 i == Xboom_bug && j == 1 ? 2 :
9272 i == Xboom_bug && j == 2 ? 2 :
9273 i == Xboom_bug && j == 3 ? 4 :
9274 i == Xboom_bug && j == 4 ? 4 :
9275 i == Xboom_bug && j == 5 ? 2 :
9276 i == Xboom_bug && j == 6 ? 2 :
9277 i == Xboom_bug && j == 7 ? 0 :
9278 i == Xboom_bomb && j == 1 ? 2 :
9279 i == Xboom_bomb && j == 2 ? 2 :
9280 i == Xboom_bomb && j == 3 ? 4 :
9281 i == Xboom_bomb && j == 4 ? 4 :
9282 i == Xboom_bomb && j == 5 ? 2 :
9283 i == Xboom_bomb && j == 6 ? 2 :
9284 i == Xboom_bomb && j == 7 ? 0 :
9285 i == Xboom_android && j == 7 ? 6 :
9286 i == Xboom_1 && j == 1 ? 2 :
9287 i == Xboom_1 && j == 2 ? 2 :
9288 i == Xboom_1 && j == 3 ? 4 :
9289 i == Xboom_1 && j == 4 ? 4 :
9290 i == Xboom_1 && j == 5 ? 6 :
9291 i == Xboom_1 && j == 6 ? 6 :
9292 i == Xboom_1 && j == 7 ? 8 :
9293 i == Xboom_2 && j == 0 ? 8 :
9294 i == Xboom_2 && j == 1 ? 8 :
9295 i == Xboom_2 && j == 2 ? 10 :
9296 i == Xboom_2 && j == 3 ? 10 :
9297 i == Xboom_2 && j == 4 ? 10 :
9298 i == Xboom_2 && j == 5 ? 12 :
9299 i == Xboom_2 && j == 6 ? 12 :
9300 i == Xboom_2 && j == 7 ? 12 :
9301 special_animation && j == 4 ? 3 :
9302 effective_action != action ? 0 :
9305 xxx_effective_action = effective_action;
9306 xxx_has_action_graphics = has_action_graphics;
9311 int frame = getAnimationFrame(g->anim_frames,
9314 g->anim_start_frame,
9328 int old_src_x = g_em->src_x;
9329 int old_src_y = g_em->src_y;
9333 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
9334 g->double_movement && is_backside);
9336 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
9337 &g_em->src_x, &g_em->src_y, FALSE);
9342 if (tile == Ydiamond_stone)
9343 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
9348 g->anim_start_frame,
9351 g_em->src_x, g_em->src_y,
9352 g_em->src_offset_x, g_em->src_offset_y,
9353 g_em->dst_offset_x, g_em->dst_offset_y,
9365 if (graphic == IMG_BUG_MOVING_RIGHT)
9366 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
9367 g->double_movement, is_backside,
9368 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
9376 g_em->src_offset_x = 0;
9377 g_em->src_offset_y = 0;
9378 g_em->dst_offset_x = 0;
9379 g_em->dst_offset_y = 0;
9380 g_em->width = TILEX;
9381 g_em->height = TILEY;
9383 g_em->preserve_background = FALSE;
9386 /* (updating the "crumbled" graphic definitions is probably not really needed,
9387 as animations for crumbled graphics can't be longer than one EMC cycle) */
9389 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
9394 g_em->crumbled_bitmap = NULL;
9395 g_em->crumbled_src_x = 0;
9396 g_em->crumbled_src_y = 0;
9398 g_em->has_crumbled_graphics = FALSE;
9400 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
9402 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9403 g_crumbled->anim_delay,
9404 g_crumbled->anim_mode,
9405 g_crumbled->anim_start_frame,
9408 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
9409 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
9411 g_em->has_crumbled_graphics = TRUE;
9417 int effective_action = xxx_effective_action;
9418 int has_action_graphics = xxx_has_action_graphics;
9420 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
9421 effective_action == ACTION_MOVING ||
9422 effective_action == ACTION_PUSHING ||
9423 effective_action == ACTION_EATING)) ||
9424 (!has_action_graphics && (effective_action == ACTION_FILLING ||
9425 effective_action == ACTION_EMPTYING)))
9428 (effective_action == ACTION_FALLING ||
9429 effective_action == ACTION_FILLING ||
9430 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
9431 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
9432 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
9433 int num_steps = (i == Ydrip_s1 ? 16 :
9434 i == Ydrip_s1B ? 16 :
9435 i == Ydrip_s2 ? 16 :
9436 i == Ydrip_s2B ? 16 :
9437 i == Xsand_stonein_1 ? 32 :
9438 i == Xsand_stonein_2 ? 32 :
9439 i == Xsand_stonein_3 ? 32 :
9440 i == Xsand_stonein_4 ? 32 :
9441 i == Xsand_stoneout_1 ? 16 :
9442 i == Xsand_stoneout_2 ? 16 : 8);
9443 int cx = ABS(dx) * (TILEX / num_steps);
9444 int cy = ABS(dy) * (TILEY / num_steps);
9445 int step_frame = (i == Ydrip_s2 ? j + 8 :
9446 i == Ydrip_s2B ? j + 8 :
9447 i == Xsand_stonein_2 ? j + 8 :
9448 i == Xsand_stonein_3 ? j + 16 :
9449 i == Xsand_stonein_4 ? j + 24 :
9450 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
9451 int step = (is_backside ? step_frame : num_steps - step_frame);
9453 if (is_backside) /* tile where movement starts */
9455 if (dx < 0 || dy < 0)
9457 g_em->src_offset_x = cx * step;
9458 g_em->src_offset_y = cy * step;
9462 g_em->dst_offset_x = cx * step;
9463 g_em->dst_offset_y = cy * step;
9466 else /* tile where movement ends */
9468 if (dx < 0 || dy < 0)
9470 g_em->dst_offset_x = cx * step;
9471 g_em->dst_offset_y = cy * step;
9475 g_em->src_offset_x = cx * step;
9476 g_em->src_offset_y = cy * step;
9480 g_em->width = TILEX - cx * step;
9481 g_em->height = TILEY - cy * step;
9484 /* create unique graphic identifier to decide if tile must be redrawn */
9485 /* bit 31 - 16 (16 bit): EM style graphic
9486 bit 15 - 12 ( 4 bit): EM style frame
9487 bit 11 - 6 ( 6 bit): graphic width
9488 bit 5 - 0 ( 6 bit): graphic height */
9489 g_em->unique_identifier =
9490 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
9496 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
9497 int player_nr, int anim, int frame_em)
9499 int element = player_mapping[player_nr][anim].element_rnd;
9500 int action = player_mapping[player_nr][anim].action;
9501 int direction = player_mapping[player_nr][anim].direction;
9502 int graphic = (direction == MV_NONE ?
9503 el_act2img(element, action) :
9504 el_act_dir2img(element, action, direction));
9505 struct GraphicInfo *g = &graphic_info[graphic];
9508 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
9510 stored_player[player_nr].StepFrame = frame_em;
9512 sync_frame = stored_player[player_nr].Frame;
9514 int frame = getAnimationFrame(g->anim_frames,
9517 g->anim_start_frame,
9520 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
9521 &g_em->src_x, &g_em->src_y, FALSE);
9524 printf("::: %d: %d, %d [%d]\n",
9526 stored_player[player_nr].Frame,
9527 stored_player[player_nr].StepFrame,
9532 void InitGraphicInfo_EM(void)
9535 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
9536 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
9541 int num_em_gfx_errors = 0;
9543 if (graphic_info_em_object[0][0].bitmap == NULL)
9545 /* EM graphics not yet initialized in em_open_all() */
9550 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
9553 /* always start with reliable default values */
9554 for (i = 0; i < TILE_MAX; i++)
9556 object_mapping[i].element_rnd = EL_UNKNOWN;
9557 object_mapping[i].is_backside = FALSE;
9558 object_mapping[i].action = ACTION_DEFAULT;
9559 object_mapping[i].direction = MV_NONE;
9562 /* always start with reliable default values */
9563 for (p = 0; p < MAX_PLAYERS; p++)
9565 for (i = 0; i < SPR_MAX; i++)
9567 player_mapping[p][i].element_rnd = EL_UNKNOWN;
9568 player_mapping[p][i].action = ACTION_DEFAULT;
9569 player_mapping[p][i].direction = MV_NONE;
9573 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9575 int e = em_object_mapping_list[i].element_em;
9577 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
9578 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
9580 if (em_object_mapping_list[i].action != -1)
9581 object_mapping[e].action = em_object_mapping_list[i].action;
9583 if (em_object_mapping_list[i].direction != -1)
9584 object_mapping[e].direction =
9585 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
9588 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
9590 int a = em_player_mapping_list[i].action_em;
9591 int p = em_player_mapping_list[i].player_nr;
9593 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
9595 if (em_player_mapping_list[i].action != -1)
9596 player_mapping[p][a].action = em_player_mapping_list[i].action;
9598 if (em_player_mapping_list[i].direction != -1)
9599 player_mapping[p][a].direction =
9600 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
9603 for (i = 0; i < TILE_MAX; i++)
9605 int element = object_mapping[i].element_rnd;
9606 int action = object_mapping[i].action;
9607 int direction = object_mapping[i].direction;
9608 boolean is_backside = object_mapping[i].is_backside;
9610 boolean action_removing = (action == ACTION_DIGGING ||
9611 action == ACTION_SNAPPING ||
9612 action == ACTION_COLLECTING);
9614 boolean action_exploding = ((action == ACTION_EXPLODING ||
9615 action == ACTION_SMASHED_BY_ROCK ||
9616 action == ACTION_SMASHED_BY_SPRING) &&
9617 element != EL_DIAMOND);
9618 boolean action_active = (action == ACTION_ACTIVE);
9619 boolean action_other = (action == ACTION_OTHER);
9621 for (j = 0; j < 8; j++)
9624 int effective_element = get_effective_element_EM(i, j);
9626 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
9627 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
9629 i == Xdrip_stretch ? element :
9630 i == Xdrip_stretchB ? element :
9631 i == Ydrip_s1 ? element :
9632 i == Ydrip_s1B ? element :
9633 i == Xball_1B ? element :
9634 i == Xball_2 ? element :
9635 i == Xball_2B ? element :
9636 i == Yball_eat ? element :
9637 i == Ykey_1_eat ? element :
9638 i == Ykey_2_eat ? element :
9639 i == Ykey_3_eat ? element :
9640 i == Ykey_4_eat ? element :
9641 i == Ykey_5_eat ? element :
9642 i == Ykey_6_eat ? element :
9643 i == Ykey_7_eat ? element :
9644 i == Ykey_8_eat ? element :
9645 i == Ylenses_eat ? element :
9646 i == Ymagnify_eat ? element :
9647 i == Ygrass_eat ? element :
9648 i == Ydirt_eat ? element :
9649 i == Yemerald_stone ? EL_EMERALD :
9650 i == Ydiamond_stone ? EL_ROCK :
9651 i == Xsand_stonein_1 ? element :
9652 i == Xsand_stonein_2 ? element :
9653 i == Xsand_stonein_3 ? element :
9654 i == Xsand_stonein_4 ? element :
9655 is_backside ? EL_EMPTY :
9656 action_removing ? EL_EMPTY :
9659 int effective_action = (j < 7 ? action :
9660 i == Xdrip_stretch ? action :
9661 i == Xdrip_stretchB ? action :
9662 i == Ydrip_s1 ? action :
9663 i == Ydrip_s1B ? action :
9664 i == Xball_1B ? action :
9665 i == Xball_2 ? action :
9666 i == Xball_2B ? action :
9667 i == Yball_eat ? action :
9668 i == Ykey_1_eat ? action :
9669 i == Ykey_2_eat ? action :
9670 i == Ykey_3_eat ? action :
9671 i == Ykey_4_eat ? action :
9672 i == Ykey_5_eat ? action :
9673 i == Ykey_6_eat ? action :
9674 i == Ykey_7_eat ? action :
9675 i == Ykey_8_eat ? action :
9676 i == Ylenses_eat ? action :
9677 i == Ymagnify_eat ? action :
9678 i == Ygrass_eat ? action :
9679 i == Ydirt_eat ? action :
9680 i == Xsand_stonein_1 ? action :
9681 i == Xsand_stonein_2 ? action :
9682 i == Xsand_stonein_3 ? action :
9683 i == Xsand_stonein_4 ? action :
9684 i == Xsand_stoneout_1 ? action :
9685 i == Xsand_stoneout_2 ? action :
9686 i == Xboom_android ? ACTION_EXPLODING :
9687 action_exploding ? ACTION_EXPLODING :
9688 action_active ? action :
9689 action_other ? action :
9691 int graphic = (el_act_dir2img(effective_element, effective_action,
9693 int crumbled = (el_act_dir2crm(effective_element, effective_action,
9695 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9696 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9697 boolean has_action_graphics = (graphic != base_graphic);
9698 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9699 struct GraphicInfo *g = &graphic_info[graphic];
9701 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9703 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
9706 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
9707 boolean special_animation = (action != ACTION_DEFAULT &&
9708 g->anim_frames == 3 &&
9709 g->anim_delay == 2 &&
9710 g->anim_mode & ANIM_LINEAR);
9711 int sync_frame = (i == Xdrip_stretch ? 7 :
9712 i == Xdrip_stretchB ? 7 :
9713 i == Ydrip_s2 ? j + 8 :
9714 i == Ydrip_s2B ? j + 8 :
9723 i == Xfake_acid_1 ? 0 :
9724 i == Xfake_acid_2 ? 10 :
9725 i == Xfake_acid_3 ? 20 :
9726 i == Xfake_acid_4 ? 30 :
9727 i == Xfake_acid_5 ? 40 :
9728 i == Xfake_acid_6 ? 50 :
9729 i == Xfake_acid_7 ? 60 :
9730 i == Xfake_acid_8 ? 70 :
9732 i == Xball_2B ? j + 8 :
9733 i == Yball_eat ? j + 1 :
9734 i == Ykey_1_eat ? j + 1 :
9735 i == Ykey_2_eat ? j + 1 :
9736 i == Ykey_3_eat ? j + 1 :
9737 i == Ykey_4_eat ? j + 1 :
9738 i == Ykey_5_eat ? j + 1 :
9739 i == Ykey_6_eat ? j + 1 :
9740 i == Ykey_7_eat ? j + 1 :
9741 i == Ykey_8_eat ? j + 1 :
9742 i == Ylenses_eat ? j + 1 :
9743 i == Ymagnify_eat ? j + 1 :
9744 i == Ygrass_eat ? j + 1 :
9745 i == Ydirt_eat ? j + 1 :
9746 i == Xamoeba_1 ? 0 :
9747 i == Xamoeba_2 ? 1 :
9748 i == Xamoeba_3 ? 2 :
9749 i == Xamoeba_4 ? 3 :
9750 i == Xamoeba_5 ? 0 :
9751 i == Xamoeba_6 ? 1 :
9752 i == Xamoeba_7 ? 2 :
9753 i == Xamoeba_8 ? 3 :
9754 i == Xexit_2 ? j + 8 :
9755 i == Xexit_3 ? j + 16 :
9756 i == Xdynamite_1 ? 0 :
9757 i == Xdynamite_2 ? 8 :
9758 i == Xdynamite_3 ? 16 :
9759 i == Xdynamite_4 ? 24 :
9760 i == Xsand_stonein_1 ? j + 1 :
9761 i == Xsand_stonein_2 ? j + 9 :
9762 i == Xsand_stonein_3 ? j + 17 :
9763 i == Xsand_stonein_4 ? j + 25 :
9764 i == Xsand_stoneout_1 && j == 0 ? 0 :
9765 i == Xsand_stoneout_1 && j == 1 ? 0 :
9766 i == Xsand_stoneout_1 && j == 2 ? 1 :
9767 i == Xsand_stoneout_1 && j == 3 ? 2 :
9768 i == Xsand_stoneout_1 && j == 4 ? 2 :
9769 i == Xsand_stoneout_1 && j == 5 ? 3 :
9770 i == Xsand_stoneout_1 && j == 6 ? 4 :
9771 i == Xsand_stoneout_1 && j == 7 ? 4 :
9772 i == Xsand_stoneout_2 && j == 0 ? 5 :
9773 i == Xsand_stoneout_2 && j == 1 ? 6 :
9774 i == Xsand_stoneout_2 && j == 2 ? 7 :
9775 i == Xsand_stoneout_2 && j == 3 ? 8 :
9776 i == Xsand_stoneout_2 && j == 4 ? 9 :
9777 i == Xsand_stoneout_2 && j == 5 ? 11 :
9778 i == Xsand_stoneout_2 && j == 6 ? 13 :
9779 i == Xsand_stoneout_2 && j == 7 ? 15 :
9780 i == Xboom_bug && j == 1 ? 2 :
9781 i == Xboom_bug && j == 2 ? 2 :
9782 i == Xboom_bug && j == 3 ? 4 :
9783 i == Xboom_bug && j == 4 ? 4 :
9784 i == Xboom_bug && j == 5 ? 2 :
9785 i == Xboom_bug && j == 6 ? 2 :
9786 i == Xboom_bug && j == 7 ? 0 :
9787 i == Xboom_bomb && j == 1 ? 2 :
9788 i == Xboom_bomb && j == 2 ? 2 :
9789 i == Xboom_bomb && j == 3 ? 4 :
9790 i == Xboom_bomb && j == 4 ? 4 :
9791 i == Xboom_bomb && j == 5 ? 2 :
9792 i == Xboom_bomb && j == 6 ? 2 :
9793 i == Xboom_bomb && j == 7 ? 0 :
9794 i == Xboom_android && j == 7 ? 6 :
9795 i == Xboom_1 && j == 1 ? 2 :
9796 i == Xboom_1 && j == 2 ? 2 :
9797 i == Xboom_1 && j == 3 ? 4 :
9798 i == Xboom_1 && j == 4 ? 4 :
9799 i == Xboom_1 && j == 5 ? 6 :
9800 i == Xboom_1 && j == 6 ? 6 :
9801 i == Xboom_1 && j == 7 ? 8 :
9802 i == Xboom_2 && j == 0 ? 8 :
9803 i == Xboom_2 && j == 1 ? 8 :
9804 i == Xboom_2 && j == 2 ? 10 :
9805 i == Xboom_2 && j == 3 ? 10 :
9806 i == Xboom_2 && j == 4 ? 10 :
9807 i == Xboom_2 && j == 5 ? 12 :
9808 i == Xboom_2 && j == 6 ? 12 :
9809 i == Xboom_2 && j == 7 ? 12 :
9810 special_animation && j == 4 ? 3 :
9811 effective_action != action ? 0 :
9815 Bitmap *debug_bitmap = g_em->bitmap;
9816 int debug_src_x = g_em->src_x;
9817 int debug_src_y = g_em->src_y;
9820 int frame = getAnimationFrame(g->anim_frames,
9823 g->anim_start_frame,
9826 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
9827 g->double_movement && is_backside);
9829 g_em->bitmap = src_bitmap;
9830 g_em->src_x = src_x;
9831 g_em->src_y = src_y;
9832 g_em->src_offset_x = 0;
9833 g_em->src_offset_y = 0;
9834 g_em->dst_offset_x = 0;
9835 g_em->dst_offset_y = 0;
9836 g_em->width = TILEX;
9837 g_em->height = TILEY;
9839 g_em->preserve_background = FALSE;
9842 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
9847 g_em->crumbled_bitmap = NULL;
9848 g_em->crumbled_src_x = 0;
9849 g_em->crumbled_src_y = 0;
9850 g_em->crumbled_border_size = 0;
9852 g_em->has_crumbled_graphics = FALSE;
9855 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
9856 printf("::: empty crumbled: %d [%s], %d, %d\n",
9857 effective_element, element_info[effective_element].token_name,
9858 effective_action, direction);
9861 /* if element can be crumbled, but certain action graphics are just empty
9862 space (like instantly snapping sand to empty space in 1 frame), do not
9863 treat these empty space graphics as crumbled graphics in EMC engine */
9864 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
9866 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9867 g_crumbled->anim_delay,
9868 g_crumbled->anim_mode,
9869 g_crumbled->anim_start_frame,
9872 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
9874 g_em->has_crumbled_graphics = TRUE;
9875 g_em->crumbled_bitmap = src_bitmap;
9876 g_em->crumbled_src_x = src_x;
9877 g_em->crumbled_src_y = src_y;
9878 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
9882 if (g_em == &graphic_info_em_object[207][0])
9883 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
9884 graphic_info_em_object[207][0].crumbled_src_x,
9885 graphic_info_em_object[207][0].crumbled_src_y,
9887 crumbled, frame, src_x, src_y,
9892 g->anim_start_frame,
9894 gfx.anim_random_frame,
9899 printf("::: EMC tile %d is crumbled\n", i);
9905 if (element == EL_ROCK &&
9906 effective_action == ACTION_FILLING)
9907 printf("::: has_action_graphics == %d\n", has_action_graphics);
9910 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
9911 effective_action == ACTION_MOVING ||
9912 effective_action == ACTION_PUSHING ||
9913 effective_action == ACTION_EATING)) ||
9914 (!has_action_graphics && (effective_action == ACTION_FILLING ||
9915 effective_action == ACTION_EMPTYING)))
9918 (effective_action == ACTION_FALLING ||
9919 effective_action == ACTION_FILLING ||
9920 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
9921 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
9922 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
9923 int num_steps = (i == Ydrip_s1 ? 16 :
9924 i == Ydrip_s1B ? 16 :
9925 i == Ydrip_s2 ? 16 :
9926 i == Ydrip_s2B ? 16 :
9927 i == Xsand_stonein_1 ? 32 :
9928 i == Xsand_stonein_2 ? 32 :
9929 i == Xsand_stonein_3 ? 32 :
9930 i == Xsand_stonein_4 ? 32 :
9931 i == Xsand_stoneout_1 ? 16 :
9932 i == Xsand_stoneout_2 ? 16 : 8);
9933 int cx = ABS(dx) * (TILEX / num_steps);
9934 int cy = ABS(dy) * (TILEY / num_steps);
9935 int step_frame = (i == Ydrip_s2 ? j + 8 :
9936 i == Ydrip_s2B ? j + 8 :
9937 i == Xsand_stonein_2 ? j + 8 :
9938 i == Xsand_stonein_3 ? j + 16 :
9939 i == Xsand_stonein_4 ? j + 24 :
9940 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
9941 int step = (is_backside ? step_frame : num_steps - step_frame);
9943 if (is_backside) /* tile where movement starts */
9945 if (dx < 0 || dy < 0)
9947 g_em->src_offset_x = cx * step;
9948 g_em->src_offset_y = cy * step;
9952 g_em->dst_offset_x = cx * step;
9953 g_em->dst_offset_y = cy * step;
9956 else /* tile where movement ends */
9958 if (dx < 0 || dy < 0)
9960 g_em->dst_offset_x = cx * step;
9961 g_em->dst_offset_y = cy * step;
9965 g_em->src_offset_x = cx * step;
9966 g_em->src_offset_y = cy * step;
9970 g_em->width = TILEX - cx * step;
9971 g_em->height = TILEY - cy * step;
9974 /* create unique graphic identifier to decide if tile must be redrawn */
9975 /* bit 31 - 16 (16 bit): EM style graphic
9976 bit 15 - 12 ( 4 bit): EM style frame
9977 bit 11 - 6 ( 6 bit): graphic width
9978 bit 5 - 0 ( 6 bit): graphic height */
9979 g_em->unique_identifier =
9980 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
9984 /* skip check for EMC elements not contained in original EMC artwork */
9985 if (element == EL_EMC_FAKE_ACID)
9988 if (g_em->bitmap != debug_bitmap ||
9989 g_em->src_x != debug_src_x ||
9990 g_em->src_y != debug_src_y ||
9991 g_em->src_offset_x != 0 ||
9992 g_em->src_offset_y != 0 ||
9993 g_em->dst_offset_x != 0 ||
9994 g_em->dst_offset_y != 0 ||
9995 g_em->width != TILEX ||
9996 g_em->height != TILEY)
9998 static int last_i = -1;
10006 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
10007 i, element, element_info[element].token_name,
10008 element_action_info[effective_action].suffix, direction);
10010 if (element != effective_element)
10011 printf(" [%d ('%s')]",
10013 element_info[effective_element].token_name);
10017 if (g_em->bitmap != debug_bitmap)
10018 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
10019 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
10021 if (g_em->src_x != debug_src_x ||
10022 g_em->src_y != debug_src_y)
10023 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10024 j, (is_backside ? 'B' : 'F'),
10025 g_em->src_x, g_em->src_y,
10026 g_em->src_x / 32, g_em->src_y / 32,
10027 debug_src_x, debug_src_y,
10028 debug_src_x / 32, debug_src_y / 32);
10030 if (g_em->src_offset_x != 0 ||
10031 g_em->src_offset_y != 0 ||
10032 g_em->dst_offset_x != 0 ||
10033 g_em->dst_offset_y != 0)
10034 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
10036 g_em->src_offset_x, g_em->src_offset_y,
10037 g_em->dst_offset_x, g_em->dst_offset_y);
10039 if (g_em->width != TILEX ||
10040 g_em->height != TILEY)
10041 printf(" %d (%d): size %d,%d should be %d,%d\n",
10043 g_em->width, g_em->height, TILEX, TILEY);
10045 num_em_gfx_errors++;
10052 for (i = 0; i < TILE_MAX; i++)
10054 for (j = 0; j < 8; j++)
10056 int element = object_mapping[i].element_rnd;
10057 int action = object_mapping[i].action;
10058 int direction = object_mapping[i].direction;
10059 boolean is_backside = object_mapping[i].is_backside;
10060 int graphic_action = el_act_dir2img(element, action, direction);
10061 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
10063 if ((action == ACTION_SMASHED_BY_ROCK ||
10064 action == ACTION_SMASHED_BY_SPRING ||
10065 action == ACTION_EATING) &&
10066 graphic_action == graphic_default)
10068 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
10069 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
10070 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
10071 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
10074 /* no separate animation for "smashed by rock" -- use rock instead */
10075 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10076 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
10078 g_em->bitmap = g_xx->bitmap;
10079 g_em->src_x = g_xx->src_x;
10080 g_em->src_y = g_xx->src_y;
10081 g_em->src_offset_x = g_xx->src_offset_x;
10082 g_em->src_offset_y = g_xx->src_offset_y;
10083 g_em->dst_offset_x = g_xx->dst_offset_x;
10084 g_em->dst_offset_y = g_xx->dst_offset_y;
10085 g_em->width = g_xx->width;
10086 g_em->height = g_xx->height;
10087 g_em->unique_identifier = g_xx->unique_identifier;
10090 g_em->preserve_background = TRUE;
10095 for (p = 0; p < MAX_PLAYERS; p++)
10097 for (i = 0; i < SPR_MAX; i++)
10099 int element = player_mapping[p][i].element_rnd;
10100 int action = player_mapping[p][i].action;
10101 int direction = player_mapping[p][i].direction;
10103 for (j = 0; j < 8; j++)
10105 int effective_element = element;
10106 int effective_action = action;
10107 int graphic = (direction == MV_NONE ?
10108 el_act2img(effective_element, effective_action) :
10109 el_act_dir2img(effective_element, effective_action,
10111 struct GraphicInfo *g = &graphic_info[graphic];
10112 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
10113 Bitmap *src_bitmap;
10115 int sync_frame = j;
10118 Bitmap *debug_bitmap = g_em->bitmap;
10119 int debug_src_x = g_em->src_x;
10120 int debug_src_y = g_em->src_y;
10123 int frame = getAnimationFrame(g->anim_frames,
10126 g->anim_start_frame,
10129 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
10131 g_em->bitmap = src_bitmap;
10132 g_em->src_x = src_x;
10133 g_em->src_y = src_y;
10134 g_em->src_offset_x = 0;
10135 g_em->src_offset_y = 0;
10136 g_em->dst_offset_x = 0;
10137 g_em->dst_offset_y = 0;
10138 g_em->width = TILEX;
10139 g_em->height = TILEY;
10143 /* skip check for EMC elements not contained in original EMC artwork */
10144 if (element == EL_PLAYER_3 ||
10145 element == EL_PLAYER_4)
10148 if (g_em->bitmap != debug_bitmap ||
10149 g_em->src_x != debug_src_x ||
10150 g_em->src_y != debug_src_y)
10152 static int last_i = -1;
10160 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
10161 p, i, element, element_info[element].token_name,
10162 element_action_info[effective_action].suffix, direction);
10164 if (element != effective_element)
10165 printf(" [%d ('%s')]",
10167 element_info[effective_element].token_name);
10171 if (g_em->bitmap != debug_bitmap)
10172 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
10173 j, (int)(g_em->bitmap), (int)(debug_bitmap));
10175 if (g_em->src_x != debug_src_x ||
10176 g_em->src_y != debug_src_y)
10177 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10179 g_em->src_x, g_em->src_y,
10180 g_em->src_x / 32, g_em->src_y / 32,
10181 debug_src_x, debug_src_y,
10182 debug_src_x / 32, debug_src_y / 32);
10184 num_em_gfx_errors++;
10194 printf("::: [%d errors found]\n", num_em_gfx_errors);
10200 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
10201 boolean any_player_moving,
10202 boolean player_is_dropping)
10204 if (tape.single_step && tape.recording && !tape.pausing)
10207 boolean active_players = FALSE;
10210 for (i = 0; i < MAX_PLAYERS; i++)
10211 if (action[i] != JOY_NO_ACTION)
10212 active_players = TRUE;
10216 if (frame == 0 && !player_is_dropping)
10217 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
10221 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
10222 boolean murphy_is_dropping)
10225 printf("::: waiting: %d, dropping: %d\n",
10226 murphy_is_waiting, murphy_is_dropping);
10229 if (tape.single_step && tape.recording && !tape.pausing)
10231 // if (murphy_is_waiting || murphy_is_dropping)
10232 if (murphy_is_waiting)
10235 printf("::: murphy is waiting -> pause mode\n");
10238 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
10243 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
10244 int graphic, int sync_frame, int x, int y)
10246 int frame = getGraphicAnimationFrame(graphic, sync_frame);
10248 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
10251 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
10253 return (IS_NEXT_FRAME(sync_frame, graphic));
10256 int getGraphicInfo_Delay(int graphic)
10258 return graphic_info[graphic].anim_delay;
10261 void PlayMenuSoundExt(int sound)
10263 if (sound == SND_UNDEFINED)
10266 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
10267 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
10270 if (IS_LOOP_SOUND(sound))
10271 PlaySoundLoop(sound);
10276 void PlayMenuSound()
10278 PlayMenuSoundExt(menu.sound[game_status]);
10281 void PlayMenuSoundStereo(int sound, int stereo_position)
10283 if (sound == SND_UNDEFINED)
10286 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
10287 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
10290 if (IS_LOOP_SOUND(sound))
10291 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
10293 PlaySoundStereo(sound, stereo_position);
10296 void PlayMenuSoundIfLoopExt(int sound)
10298 if (sound == SND_UNDEFINED)
10301 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
10302 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
10305 if (IS_LOOP_SOUND(sound))
10306 PlaySoundLoop(sound);
10309 void PlayMenuSoundIfLoop()
10311 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
10314 void PlayMenuMusicExt(int music)
10316 if (music == MUS_UNDEFINED)
10319 if (!setup.sound_music)
10325 void PlayMenuMusic()
10327 PlayMenuMusicExt(menu.music[game_status]);
10330 void PlaySoundActivating()
10333 PlaySound(SND_MENU_ITEM_ACTIVATING);
10337 void PlaySoundSelecting()
10340 PlaySound(SND_MENU_ITEM_SELECTING);
10344 void ToggleFullscreenOrChangeWindowScalingIfNeeded()
10346 boolean change_fullscreen = (setup.fullscreen !=
10347 video.fullscreen_enabled);
10348 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
10349 !strEqual(setup.fullscreen_mode,
10350 video.fullscreen_mode_current));
10351 boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
10352 setup.window_scaling_percent !=
10353 video.window_scaling_percent);
10355 if (change_window_scaling_percent && video.fullscreen_enabled)
10358 if (!change_window_scaling_percent && !video.fullscreen_available)
10361 #if defined(TARGET_SDL2)
10362 if (change_window_scaling_percent)
10364 SDLSetWindowScaling(setup.window_scaling_percent);
10368 else if (change_fullscreen)
10370 SDLSetWindowFullscreen(setup.fullscreen);
10372 /* set setup value according to successfully changed fullscreen mode */
10373 setup.fullscreen = video.fullscreen_enabled;
10379 if (change_fullscreen ||
10380 change_fullscreen_mode ||
10381 change_window_scaling_percent)
10383 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
10385 /* save backbuffer content which gets lost when toggling fullscreen mode */
10386 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
10388 if (change_fullscreen_mode)
10390 /* keep fullscreen, but change fullscreen mode (screen resolution) */
10391 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
10394 if (change_window_scaling_percent)
10396 /* keep window mode, but change window scaling */
10397 video.fullscreen_enabled = TRUE; /* force new window scaling */
10400 /* toggle fullscreen */
10401 ChangeVideoModeIfNeeded(setup.fullscreen);
10403 /* set setup value according to successfully changed fullscreen mode */
10404 setup.fullscreen = video.fullscreen_enabled;
10406 /* restore backbuffer content from temporary backbuffer backup bitmap */
10407 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
10409 FreeBitmap(tmp_backbuffer);
10412 /* update visible window/screen */
10413 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
10415 redraw_mask = REDRAW_ALL;
10420 void ChangeViewportPropertiesIfNeeded()
10423 int *door_1_x = &DX;
10424 int *door_1_y = &DY;
10425 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
10426 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
10428 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
10429 game_status == GAME_MODE_EDITOR ? game_status :
10431 int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
10433 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
10434 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
10435 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
10436 struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
10437 int border_size = vp_playfield->border_size;
10438 int new_sx = vp_playfield->x + border_size;
10439 int new_sy = vp_playfield->y + border_size;
10440 int new_sxsize = vp_playfield->width - 2 * border_size;
10441 int new_sysize = vp_playfield->height - 2 * border_size;
10442 int new_real_sx = vp_playfield->x;
10443 int new_real_sy = vp_playfield->y;
10444 int new_full_sxsize = vp_playfield->width;
10445 int new_full_sysize = vp_playfield->height;
10446 int new_dx = vp_door_1->x;
10447 int new_dy = vp_door_1->y;
10448 int new_dxsize = vp_door_1->width;
10449 int new_dysize = vp_door_1->height;
10450 int new_vx = vp_door_2->x;
10451 int new_vy = vp_door_2->y;
10452 int new_vxsize = vp_door_2->width;
10453 int new_vysize = vp_door_2->height;
10454 int new_ex = vp_door_3->x;
10455 int new_ey = vp_door_3->y;
10456 int new_exsize = vp_door_3->width;
10457 int new_eysize = vp_door_3->height;
10459 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
10460 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
10461 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
10462 int new_scr_fieldx = new_sxsize / tilesize;
10463 int new_scr_fieldy = new_sysize / tilesize;
10464 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
10465 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
10467 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
10468 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
10470 boolean init_gfx_buffers = FALSE;
10471 boolean init_video_buffer = FALSE;
10472 boolean init_gadgets_and_toons = FALSE;
10475 /* !!! TEST ONLY !!! */
10476 // InitGfxBuffers();
10480 if (viewport.window.width != WIN_XSIZE ||
10481 viewport.window.height != WIN_YSIZE)
10483 WIN_XSIZE = viewport.window.width;
10484 WIN_YSIZE = viewport.window.height;
10487 init_video_buffer = TRUE;
10488 init_gfx_buffers = TRUE;
10490 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
10494 SetDrawDeactivationMask(REDRAW_NONE);
10495 SetDrawBackgroundMask(REDRAW_FIELD);
10497 // RedrawBackground();
10501 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
10504 if (new_scr_fieldx != SCR_FIELDX ||
10505 new_scr_fieldy != SCR_FIELDY)
10507 /* this always toggles between MAIN and GAME when using small tile size */
10509 SCR_FIELDX = new_scr_fieldx;
10510 SCR_FIELDY = new_scr_fieldy;
10512 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
10516 if (new_tilesize_var != TILESIZE_VAR &&
10517 gfx_game_mode == GAME_MODE_PLAYING)
10519 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
10521 TILESIZE_VAR = new_tilesize_var;
10523 init_gfx_buffers = TRUE;
10525 // printf("::: tilesize: init_gfx_buffers\n");
10529 if (new_sx != SX ||
10537 new_sxsize != SXSIZE ||
10538 new_sysize != SYSIZE ||
10539 new_dxsize != DXSIZE ||
10540 new_dysize != DYSIZE ||
10541 new_vxsize != VXSIZE ||
10542 new_vysize != VYSIZE ||
10543 new_exsize != EXSIZE ||
10544 new_eysize != EYSIZE ||
10545 new_real_sx != REAL_SX ||
10546 new_real_sy != REAL_SY ||
10547 new_full_sxsize != FULL_SXSIZE ||
10548 new_full_sysize != FULL_SYSIZE ||
10549 new_tilesize_var != TILESIZE_VAR
10552 vp_door_1->x != *door_1_x ||
10553 vp_door_1->y != *door_1_y ||
10554 vp_door_2->x != *door_2_x ||
10555 vp_door_2->y != *door_2_y
10567 SXSIZE = new_sxsize;
10568 SYSIZE = new_sysize;
10569 DXSIZE = new_dxsize;
10570 DYSIZE = new_dysize;
10571 VXSIZE = new_vxsize;
10572 VYSIZE = new_vysize;
10573 EXSIZE = new_exsize;
10574 EYSIZE = new_eysize;
10575 REAL_SX = new_real_sx;
10576 REAL_SY = new_real_sy;
10577 FULL_SXSIZE = new_full_sxsize;
10578 FULL_SYSIZE = new_full_sysize;
10579 TILESIZE_VAR = new_tilesize_var;
10582 printf("::: %d, %d, %d [%d]\n",
10583 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
10584 setup.small_game_graphics);
10588 *door_1_x = vp_door_1->x;
10589 *door_1_y = vp_door_1->y;
10590 *door_2_x = vp_door_2->x;
10591 *door_2_y = vp_door_2->y;
10595 init_gfx_buffers = TRUE;
10597 // printf("::: viewports: init_gfx_buffers\n");
10602 if (gfx_game_mode == GAME_MODE_MAIN)
10605 init_gadgets_and_toons = TRUE;
10607 // printf("::: viewports: init_gadgets_and_toons\n");
10615 if (init_gfx_buffers)
10617 // printf("::: init_gfx_buffers\n");
10619 SCR_FIELDX = new_scr_fieldx_buffers;
10620 SCR_FIELDY = new_scr_fieldy_buffers;
10624 SCR_FIELDX = new_scr_fieldx;
10625 SCR_FIELDY = new_scr_fieldy;
10628 if (init_video_buffer)
10630 // printf("::: init_video_buffer\n");
10632 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
10634 SetDrawDeactivationMask(REDRAW_NONE);
10635 SetDrawBackgroundMask(REDRAW_FIELD);
10638 if (init_gadgets_and_toons)
10640 // printf("::: init_gadgets_and_toons\n");
10647 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);