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 ***********************************************************/
16 #include "libgame/libgame.h"
28 /* select level set with EMC X11 graphics before activating EM GFX debugging */
29 #define DEBUG_EM_GFX 0
31 /* tool button identifiers */
32 #define TOOL_CTRL_ID_YES 0
33 #define TOOL_CTRL_ID_NO 1
34 #define TOOL_CTRL_ID_CONFIRM 2
35 #define TOOL_CTRL_ID_PLAYER_1 3
36 #define TOOL_CTRL_ID_PLAYER_2 4
37 #define TOOL_CTRL_ID_PLAYER_3 5
38 #define TOOL_CTRL_ID_PLAYER_4 6
40 #define NUM_TOOL_BUTTONS 7
42 /* constants for number of doors and door parts */
44 #define NUM_PANELS NUM_DOORS
45 // #define NUM_PANELS 0
46 #define MAX_PARTS_PER_DOOR 8
47 #define MAX_DOOR_PARTS (NUM_DOORS * MAX_PARTS_PER_DOOR + NUM_PANELS)
48 #define DOOR_PART_IS_PANEL(i) ((i) >= NUM_DOORS * MAX_PARTS_PER_DOOR)
51 struct DoorPartOrderInfo
57 static struct DoorPartOrderInfo door_part_order[MAX_DOOR_PARTS];
59 struct DoorPartControlInfo
63 struct DoorPartPosInfo *pos;
66 static struct DoorPartControlInfo door_part_controls[] =
70 IMG_DOOR_1_GFX_PART_1,
75 IMG_DOOR_1_GFX_PART_2,
80 IMG_DOOR_1_GFX_PART_3,
85 IMG_DOOR_1_GFX_PART_4,
90 IMG_DOOR_1_GFX_PART_5,
95 IMG_DOOR_1_GFX_PART_6,
100 IMG_DOOR_1_GFX_PART_7,
105 IMG_DOOR_1_GFX_PART_8,
111 IMG_DOOR_2_GFX_PART_1,
116 IMG_DOOR_2_GFX_PART_2,
121 IMG_DOOR_2_GFX_PART_3,
126 IMG_DOOR_2_GFX_PART_4,
131 IMG_DOOR_2_GFX_PART_5,
136 IMG_DOOR_2_GFX_PART_6,
141 IMG_DOOR_2_GFX_PART_7,
146 IMG_DOOR_2_GFX_PART_8,
152 IMG_BACKGROUND_PANEL,
169 /* forward declaration for internal use */
170 static void UnmapToolButtons();
171 static void HandleToolButtons(struct GadgetInfo *);
172 static int el_act_dir2crm(int, int, int);
173 static int el_act2crm(int, int);
175 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
176 static int request_gadget_id = -1;
178 static char *print_if_not_empty(int element)
180 static char *s = NULL;
181 char *token_name = element_info[element].token_name;
186 s = checked_malloc(strlen(token_name) + 10 + 1);
188 if (element != EL_EMPTY)
189 sprintf(s, "%d\t['%s']", element, token_name);
191 sprintf(s, "%d", element);
196 void DumpTile(int x, int y)
201 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
207 printf_line("-", 79);
208 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
209 printf_line("-", 79);
211 if (!IN_LEV_FIELD(x, y))
213 printf("(not in level field)\n");
219 printf(" Feld: %d\t['%s']\n", Feld[x][y],
220 element_info[Feld[x][y]].token_name);
221 printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
222 printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
223 printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
224 printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
225 printf(" MovPos: %d\n", MovPos[x][y]);
226 printf(" MovDir: %d\n", MovDir[x][y]);
227 printf(" MovDelay: %d\n", MovDelay[x][y]);
228 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
229 printf(" CustomValue: %d\n", CustomValue[x][y]);
230 printf(" GfxElement: %d\n", GfxElement[x][y]);
231 printf(" GfxAction: %d\n", GfxAction[x][y]);
232 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
236 void SetDrawtoField(int mode)
238 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
246 BX2 = SCR_FIELDX + 1;
247 BY2 = SCR_FIELDY + 1;
266 BX2 = SCR_FIELDX + 1;
267 BY2 = SCR_FIELDY + 1;
282 drawto_field = fieldbuffer;
284 else /* DRAW_BACKBUFFER */
290 BX2 = SCR_FIELDX - 1;
291 BY2 = SCR_FIELDY - 1;
295 drawto_field = backbuffer;
299 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
301 if (game_status == GAME_MODE_PLAYING &&
302 level.game_engine_type == GAME_ENGINE_TYPE_EM)
304 /* currently there is no partial redraw -- always redraw whole playfield */
305 RedrawPlayfield_EM(TRUE);
307 /* blit playfield from scroll buffer to normal back buffer for fading in */
308 BlitScreenToBitmap_EM(backbuffer);
310 else if (game_status == GAME_MODE_PLAYING &&
311 level.game_engine_type == GAME_ENGINE_TYPE_SP)
313 /* currently there is no partial redraw -- always redraw whole playfield */
314 RedrawPlayfield_SP(TRUE);
316 /* blit playfield from scroll buffer to normal back buffer for fading in */
317 BlitScreenToBitmap_SP(backbuffer);
319 else if (game_status == GAME_MODE_PLAYING &&
320 !game.envelope_active)
326 width = gfx.sxsize + 2 * TILEX;
327 height = gfx.sysize + 2 * TILEY;
333 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
334 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
336 for (xx = BX1; xx <= BX2; xx++)
337 for (yy = BY1; yy <= BY2; yy++)
338 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
339 DrawScreenField(xx, yy);
343 if (setup.soft_scrolling)
345 int fx = FX, fy = FY;
347 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
348 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
350 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
362 BlitBitmap(drawto, window, x, y, width, height, x, y);
365 void DrawMaskedBorder_Rect(int x, int y, int width, int height)
367 Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap;
369 SetClipOrigin(bitmap, bitmap->stored_clip_gc, 0, 0);
370 BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
373 void DrawMaskedBorder_FIELD()
375 if (global.border_status >= GAME_MODE_TITLE &&
376 global.border_status <= GAME_MODE_PLAYING &&
377 border.draw_masked[global.border_status])
378 DrawMaskedBorder_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
381 void DrawMaskedBorder_DOOR_1()
383 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
384 (global.border_status != GAME_MODE_EDITOR ||
385 border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
386 DrawMaskedBorder_Rect(DX, DY, DXSIZE, DYSIZE);
389 void DrawMaskedBorder_DOOR_2()
391 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
392 global.border_status != GAME_MODE_EDITOR)
393 DrawMaskedBorder_Rect(VX, VY, VXSIZE, VYSIZE);
396 void DrawMaskedBorder_DOOR_3()
398 /* currently not available */
401 void DrawMaskedBorder_ALL()
403 DrawMaskedBorder_FIELD();
404 DrawMaskedBorder_DOOR_1();
405 DrawMaskedBorder_DOOR_2();
406 DrawMaskedBorder_DOOR_3();
409 void DrawMaskedBorder(int redraw_mask)
411 /* never draw masked screen borders on borderless screens */
412 if (effectiveGameStatus() == GAME_MODE_LOADING ||
413 effectiveGameStatus() == GAME_MODE_TITLE)
416 /* never draw masked screen borders when displaying request outside door */
417 if (effectiveGameStatus() == GAME_MODE_PSEUDO_DOOR &&
418 global.use_envelope_request)
421 if (redraw_mask & REDRAW_ALL)
422 DrawMaskedBorder_ALL();
425 if (redraw_mask & REDRAW_FIELD)
426 DrawMaskedBorder_FIELD();
427 if (redraw_mask & REDRAW_DOOR_1)
428 DrawMaskedBorder_DOOR_1();
429 if (redraw_mask & REDRAW_DOOR_2)
430 DrawMaskedBorder_DOOR_2();
431 if (redraw_mask & REDRAW_DOOR_3)
432 DrawMaskedBorder_DOOR_3();
436 void BlitScreenToBitmap(Bitmap *target_bitmap)
438 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
439 int fx = FX, fy = FY;
442 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
443 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
444 int dx_var = dx * TILESIZE_VAR / TILESIZE;
445 int dy_var = dy * TILESIZE_VAR / TILESIZE;
448 // fx += dx * TILESIZE_VAR / TILESIZE;
449 // fy += dy * TILESIZE_VAR / TILESIZE;
451 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
452 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
455 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
456 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
458 if (EVEN(SCR_FIELDX))
460 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
461 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
463 fx += (dx_var > 0 ? TILEX_VAR : 0);
470 if (EVEN(SCR_FIELDY))
472 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
473 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
475 fy += (dy_var > 0 ? TILEY_VAR : 0);
483 printf("::: (%d, %d) [(%d / %d, %d / %d)] => %d, %d\n",
486 SBY_Upper, SBY_Lower,
490 if (border.draw_masked[GAME_MODE_PLAYING])
492 if (buffer != backbuffer)
494 /* copy playfield buffer to backbuffer to add masked border */
495 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
496 DrawMaskedBorder(REDRAW_FIELD);
499 BlitBitmap(backbuffer, target_bitmap,
500 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
505 BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
512 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
515 printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
516 for (x = 0; x < SCR_FIELDX; x++)
517 for (y = 0 ; y < SCR_FIELDY; y++)
518 if (redraw[redraw_x1 + x][redraw_y1 + y])
519 printf("::: - %d, %d [%s]\n",
520 LEVELX(x), LEVELY(y),
521 EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
524 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
525 redraw_mask |= REDRAW_FIELD;
528 // never redraw single tiles, always redraw the whole field
529 // (redrawing single tiles up to a certain threshold was faster on old,
530 // now legacy graphics, but slows things down on modern graphics now)
531 // UPDATE: this is now globally defined by value of REDRAWTILES_THRESHOLD
532 if (redraw_mask & REDRAW_TILES)
533 redraw_mask |= REDRAW_FIELD;
537 /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
538 /* (force full redraw) */
539 if (game_status == GAME_MODE_PLAYING)
540 redraw_mask |= REDRAW_FIELD;
543 if (redraw_mask & REDRAW_FIELD)
544 redraw_mask &= ~REDRAW_TILES;
546 if (redraw_mask == REDRAW_NONE)
551 if (redraw_mask & REDRAW_ALL)
552 printf("[REDRAW_ALL]");
553 if (redraw_mask & REDRAW_FIELD)
554 printf("[REDRAW_FIELD]");
555 if (redraw_mask & REDRAW_TILES)
556 printf("[REDRAW_TILES]");
557 if (redraw_mask & REDRAW_DOOR_1)
558 printf("[REDRAW_DOOR_1]");
559 if (redraw_mask & REDRAW_DOOR_2)
560 printf("[REDRAW_DOOR_2]");
561 if (redraw_mask & REDRAW_FROM_BACKBUFFER)
562 printf("[REDRAW_FROM_BACKBUFFER]");
563 printf(" [%d]\n", FrameCounter);
566 if (redraw_mask & REDRAW_TILES &&
567 game_status == GAME_MODE_PLAYING &&
568 border.draw_masked[GAME_MODE_PLAYING])
569 redraw_mask |= REDRAW_FIELD;
571 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
573 static boolean last_frame_skipped = FALSE;
574 boolean skip_even_when_not_scrolling = TRUE;
575 boolean just_scrolling = (ScreenMovDir != 0);
576 boolean verbose = FALSE;
578 if (global.fps_slowdown_factor > 1 &&
579 (FrameCounter % global.fps_slowdown_factor) &&
580 (just_scrolling || skip_even_when_not_scrolling))
582 redraw_mask &= ~REDRAW_MAIN;
584 last_frame_skipped = TRUE;
587 printf("FRAME SKIPPED\n");
591 if (last_frame_skipped)
592 redraw_mask |= REDRAW_FIELD;
594 last_frame_skipped = FALSE;
597 printf("frame not skipped\n");
601 /* synchronize X11 graphics at this point; if we would synchronize the
602 display immediately after the buffer switching (after the XFlush),
603 this could mean that we have to wait for the graphics to complete,
604 although we could go on doing calculations for the next frame */
608 /* never draw masked border to backbuffer when using playfield buffer */
609 if (game_status != GAME_MODE_PLAYING ||
610 redraw_mask & REDRAW_FROM_BACKBUFFER ||
611 buffer == backbuffer)
612 DrawMaskedBorder(redraw_mask);
614 DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
616 if (redraw_mask & REDRAW_ALL)
618 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
620 redraw_mask = REDRAW_NONE;
623 if (redraw_mask & REDRAW_FIELD)
626 printf("::: REDRAW_FIELD\n");
629 if (game_status != GAME_MODE_PLAYING ||
630 redraw_mask & REDRAW_FROM_BACKBUFFER)
632 BlitBitmap(backbuffer, window,
633 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
638 BlitScreenToBitmap(window);
640 int fx = FX, fy = FY;
643 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
644 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
645 int dx_var = dx * TILESIZE_VAR / TILESIZE;
646 int dy_var = dy * TILESIZE_VAR / TILESIZE;
649 // fx += dx * TILESIZE_VAR / TILESIZE;
650 // fy += dy * TILESIZE_VAR / TILESIZE;
652 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
653 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
656 /* !!! THIS WORKS !!! */
658 printf("::: %d, %d\n", scroll_x, scroll_y);
660 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
661 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
663 if (EVEN(SCR_FIELDX))
665 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
666 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
668 fx += (dx > 0 ? TILEX_VAR : 0);
675 if (EVEN(SCR_FIELDY))
677 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
678 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
680 fy += (dy > 0 ? TILEY_VAR : 0);
687 if (border.draw_masked[GAME_MODE_PLAYING])
689 if (buffer != backbuffer)
691 /* copy playfield buffer to backbuffer to add masked border */
692 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
693 DrawMaskedBorder(REDRAW_FIELD);
696 BlitBitmap(backbuffer, window,
697 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
702 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
708 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
710 (setup.soft_scrolling ?
711 "setup.soft_scrolling" :
712 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
713 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
714 ABS(ScreenGfxPos) == ScrollStepSize ?
715 "ABS(ScreenGfxPos) == ScrollStepSize" :
716 "redraw_tiles > REDRAWTILES_THRESHOLD"));
721 redraw_mask &= ~REDRAW_MAIN;
724 if (redraw_mask & REDRAW_DOORS)
726 if (redraw_mask & REDRAW_DOOR_1)
727 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
729 if (redraw_mask & REDRAW_DOOR_2)
730 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
732 if (redraw_mask & REDRAW_DOOR_3)
733 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
735 redraw_mask &= ~REDRAW_DOORS;
738 if (redraw_mask & REDRAW_MICROLEVEL)
740 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
741 SX, SY + 10 * TILEY);
743 redraw_mask &= ~REDRAW_MICROLEVEL;
746 if (redraw_mask & REDRAW_TILES)
749 printf("::: REDRAW_TILES\n");
755 InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
758 int sx = SX; // - (EVEN(SCR_FIELDX) ? TILEX_VAR / 2 : 0);
759 int sy = SY; // + (EVEN(SCR_FIELDY) ? TILEY_VAR / 2 : 0);
762 int dx_var = dx * TILESIZE_VAR / TILESIZE;
763 int dy_var = dy * TILESIZE_VAR / TILESIZE;
765 int fx = FX, fy = FY;
767 int scr_fieldx = SCR_FIELDX + (EVEN(SCR_FIELDX) ? 2 : 0);
768 int scr_fieldy = SCR_FIELDY + (EVEN(SCR_FIELDY) ? 2 : 0);
770 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
771 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
773 if (EVEN(SCR_FIELDX))
775 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
777 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
786 fx += (dx_var > 0 ? TILEX_VAR : 0);
790 if (EVEN(SCR_FIELDY))
792 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
794 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
803 fy += (dy_var > 0 ? TILEY_VAR : 0);
808 printf("::: %d, %d, %d, %d\n", sx, sy, SCR_FIELDX, SCR_FIELDY);
811 for (x = 0; x < scr_fieldx; x++)
812 for (y = 0 ; y < scr_fieldy; y++)
813 if (redraw[redraw_x1 + x][redraw_y1 + y])
814 BlitBitmap(buffer, window,
815 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
816 TILEX_VAR, TILEY_VAR,
817 sx + x * TILEX_VAR, sy + y * TILEY_VAR);
820 InitGfxClipRegion(FALSE, -1, -1, -1, -1);
822 for (x = 0; x < SCR_FIELDX; x++)
823 for (y = 0 ; y < SCR_FIELDY; y++)
824 if (redraw[redraw_x1 + x][redraw_y1 + y])
825 BlitBitmap(buffer, window,
826 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
827 TILEX_VAR, TILEY_VAR,
828 SX + x * TILEX_VAR, SY + y * TILEY_VAR);
832 for (x = 0; x < SCR_FIELDX; x++)
833 for (y = 0 ; y < SCR_FIELDY; y++)
834 if (redraw[redraw_x1 + x][redraw_y1 + y])
835 BlitBitmap(buffer, window,
836 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
837 SX + x * TILEX, SY + y * TILEY);
841 if (redraw_mask & REDRAW_FPS) /* display frames per second */
846 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
847 if (!global.fps_slowdown)
850 sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
852 DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
854 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
860 for (x = 0; x < MAX_BUF_XSIZE; x++)
861 for (y = 0; y < MAX_BUF_YSIZE; y++)
864 redraw_mask = REDRAW_NONE;
867 static void FadeCrossSaveBackbuffer()
869 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
872 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
874 static int fade_type_skip = FADE_TYPE_NONE;
875 void (*draw_border_function)(void) = NULL;
876 Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
877 int x, y, width, height;
878 int fade_delay, post_delay;
880 if (fade_type == FADE_TYPE_FADE_OUT)
882 if (fade_type_skip != FADE_TYPE_NONE)
885 printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
888 /* skip all fade operations until specified fade operation */
889 if (fade_type & fade_type_skip)
890 fade_type_skip = FADE_TYPE_NONE;
895 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
897 FadeCrossSaveBackbuffer();
903 redraw_mask |= fade_mask;
905 if (fade_type == FADE_TYPE_SKIP)
908 printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
911 fade_type_skip = fade_mode;
917 printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
922 fade_delay = fading.fade_delay;
923 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
926 if (fade_type_skip != FADE_TYPE_NONE)
929 printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
932 /* skip all fade operations until specified fade operation */
933 if (fade_type & fade_type_skip)
934 fade_type_skip = FADE_TYPE_NONE;
944 if (global.autoplay_leveldir)
946 // fading.fade_mode = FADE_MODE_NONE;
953 if (fading.fade_mode == FADE_MODE_NONE)
961 /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
964 printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
968 if (fade_mask == REDRAW_NONE)
969 fade_mask = REDRAW_FIELD;
972 // if (fade_mask & REDRAW_FIELD)
973 if (fade_mask == REDRAW_FIELD)
978 height = FULL_SYSIZE;
981 fade_delay = fading.fade_delay;
982 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
985 if (border.draw_masked_when_fading)
986 draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
988 DrawMaskedBorder_FIELD(); /* draw once */
990 else /* REDRAW_ALL */
998 fade_delay = fading.fade_delay;
999 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
1004 if (!setup.fade_screens ||
1006 fading.fade_mode == FADE_MODE_NONE)
1008 if (!setup.fade_screens || fade_delay == 0)
1011 if (fade_mode == FADE_MODE_FADE_OUT)
1015 if (fade_mode == FADE_MODE_FADE_OUT &&
1016 fading.fade_mode != FADE_MODE_NONE)
1017 ClearRectangle(backbuffer, x, y, width, height);
1023 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
1025 redraw_mask &= ~fade_mask;
1027 /* always redraw area that was explicitly marked to fade */
1028 redraw_mask |= fade_mask;
1036 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
1037 redraw_mask = REDRAW_NONE;
1038 // (^^^ WRONG; should be "redraw_mask &= ~fade_mask" if done this way)
1047 FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
1048 draw_border_function);
1050 redraw_mask &= ~fade_mask;
1053 void FadeIn(int fade_mask)
1055 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
1056 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
1058 FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
1061 void FadeOut(int fade_mask)
1063 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
1064 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
1066 FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
1068 global.border_status = game_status;
1071 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
1073 static struct TitleFadingInfo fading_leave_stored;
1076 fading_leave_stored = fading_leave;
1078 fading = fading_leave_stored;
1081 void FadeSetEnterMenu()
1083 fading = menu.enter_menu;
1086 printf("::: storing enter_menu\n");
1089 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1092 void FadeSetLeaveMenu()
1094 fading = menu.leave_menu;
1097 printf("::: storing leave_menu\n");
1100 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1103 void FadeSetEnterScreen()
1105 fading = menu.enter_screen[game_status];
1108 printf("::: storing leave_screen[%d]\n", game_status);
1111 FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
1114 void FadeSetNextScreen()
1116 fading = menu.next_screen;
1119 printf("::: storing next_screen\n");
1122 // (do not overwrite fade mode set by FadeSetEnterScreen)
1123 // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1126 void FadeSetLeaveScreen()
1129 printf("::: recalling last stored value\n");
1132 FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
1135 void FadeSetFromType(int type)
1137 if (type & TYPE_ENTER_SCREEN)
1138 FadeSetEnterScreen();
1139 else if (type & TYPE_ENTER)
1141 else if (type & TYPE_LEAVE)
1145 void FadeSetDisabled()
1147 static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
1149 fading = fading_none;
1152 void FadeSkipNextFadeIn()
1154 FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
1157 void FadeSkipNextFadeOut()
1159 FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
1162 void SetWindowBackgroundImageIfDefined(int graphic)
1164 if (graphic_info[graphic].bitmap)
1165 SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
1168 void SetMainBackgroundImageIfDefined(int graphic)
1170 if (graphic_info[graphic].bitmap)
1171 SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
1174 void SetDoorBackgroundImageIfDefined(int graphic)
1176 if (graphic_info[graphic].bitmap)
1177 SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
1180 void SetWindowBackgroundImage(int graphic)
1182 SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1183 graphic_info[graphic].bitmap ?
1184 graphic_info[graphic].bitmap :
1185 graphic_info[IMG_BACKGROUND].bitmap);
1188 void SetMainBackgroundImage(int graphic)
1190 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1191 graphic_info[graphic].bitmap ?
1192 graphic_info[graphic].bitmap :
1193 graphic_info[IMG_BACKGROUND].bitmap);
1196 void SetDoorBackgroundImage(int graphic)
1198 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1199 graphic_info[graphic].bitmap ?
1200 graphic_info[graphic].bitmap :
1201 graphic_info[IMG_BACKGROUND].bitmap);
1204 void SetPanelBackground()
1207 struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
1210 BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1211 gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
1213 /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */
1214 ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE);
1215 BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1216 MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0);
1219 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
1220 DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
1223 SetDoorBackgroundBitmap(bitmap_db_panel);
1226 void DrawBackground(int x, int y, int width, int height)
1228 /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
1229 /* (when entering hall of fame after playing) */
1231 ClearRectangleOnBackground(drawto, x, y, width, height);
1233 ClearRectangleOnBackground(backbuffer, x, y, width, height);
1239 if (IN_GFX_FIELD_FULL(x, y))
1240 redraw_mask |= REDRAW_FIELD;
1241 else if (IN_GFX_DOOR_1(x, y))
1242 redraw_mask |= REDRAW_DOOR_1;
1243 else if (IN_GFX_DOOR_2(x, y))
1244 redraw_mask |= REDRAW_DOOR_2;
1245 else if (IN_GFX_DOOR_3(x, y))
1246 redraw_mask |= REDRAW_DOOR_3;
1248 /* (this only works for the current arrangement of playfield and panels) */
1250 redraw_mask |= REDRAW_FIELD;
1251 else if (y < gfx.vy)
1252 redraw_mask |= REDRAW_DOOR_1;
1254 redraw_mask |= REDRAW_DOOR_2;
1258 /* (this is just wrong (when drawing to one of the two door panel areas)) */
1259 redraw_mask |= REDRAW_FIELD;
1263 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
1265 struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
1267 if (font->bitmap == NULL)
1270 DrawBackground(x, y, width, height);
1273 void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
1275 struct GraphicInfo *g = &graphic_info[graphic];
1277 if (g->bitmap == NULL)
1280 DrawBackground(x, y, width, height);
1285 /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
1286 /* (when entering hall of fame after playing) */
1287 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
1289 /* !!! maybe this should be done before clearing the background !!! */
1290 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
1292 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
1293 SetDrawtoField(DRAW_BUFFERED);
1296 SetDrawtoField(DRAW_BACKBUFFER);
1299 void MarkTileDirty(int x, int y)
1301 int xx = redraw_x1 + x;
1302 int yy = redraw_y1 + y;
1304 if (!redraw[xx][yy])
1307 redraw[xx][yy] = TRUE;
1308 redraw_mask |= REDRAW_TILES;
1311 void SetBorderElement()
1315 BorderElement = EL_EMPTY;
1317 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
1319 for (x = 0; x < lev_fieldx; x++)
1321 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
1322 BorderElement = EL_STEELWALL;
1324 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
1330 void FloodFillLevel(int from_x, int from_y, int fill_element,
1331 short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
1332 int max_fieldx, int max_fieldy)
1336 static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
1337 static int safety = 0;
1339 /* check if starting field still has the desired content */
1340 if (field[from_x][from_y] == fill_element)
1345 if (safety > max_fieldx * max_fieldy)
1346 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1348 old_element = field[from_x][from_y];
1349 field[from_x][from_y] = fill_element;
1351 for (i = 0; i < 4; i++)
1353 x = from_x + check[i][0];
1354 y = from_y + check[i][1];
1356 if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
1357 FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
1363 void SetRandomAnimationValue(int x, int y)
1365 gfx.anim_random_frame = GfxRandom[x][y];
1368 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
1370 /* animation synchronized with global frame counter, not move position */
1371 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
1372 sync_frame = FrameCounter;
1374 return getAnimationFrame(graphic_info[graphic].anim_frames,
1375 graphic_info[graphic].anim_delay,
1376 graphic_info[graphic].anim_mode,
1377 graphic_info[graphic].anim_start_frame,
1381 void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
1382 Bitmap **bitmap, int *x, int *y,
1383 boolean get_backside)
1387 int width_mult, width_div;
1388 int height_mult, height_div;
1392 { 15, 16, 2, 3 }, /* 1 x 1 */
1393 { 7, 8, 2, 3 }, /* 2 x 2 */
1394 { 3, 4, 2, 3 }, /* 4 x 4 */
1395 { 1, 2, 2, 3 }, /* 8 x 8 */
1396 { 0, 1, 2, 3 }, /* 16 x 16 */
1397 { 0, 1, 0, 1 }, /* 32 x 32 */
1399 struct GraphicInfo *g = &graphic_info[graphic];
1400 Bitmap *src_bitmap = g->bitmap;
1401 int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
1402 int offset_calc_pos = log_2(tilesize);
1403 int width_mult = offset_calc[offset_calc_pos].width_mult;
1404 int width_div = offset_calc[offset_calc_pos].width_div;
1405 int height_mult = offset_calc[offset_calc_pos].height_mult;
1406 int height_div = offset_calc[offset_calc_pos].height_div;
1407 int startx = src_bitmap->width * width_mult / width_div;
1408 int starty = src_bitmap->height * height_mult / height_div;
1410 int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
1411 tilesize / TILESIZE;
1412 int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
1413 tilesize / TILESIZE;
1415 int src_x = g->src_x * tilesize / TILESIZE;
1416 int src_y = g->src_y * tilesize / TILESIZE;
1418 int width = g->width * tilesize / TILESIZE;
1419 int height = g->height * tilesize / TILESIZE;
1420 int offset_x = g->offset_x * tilesize / TILESIZE;
1421 int offset_y = g->offset_y * tilesize / TILESIZE;
1423 if (g->offset_y == 0) /* frames are ordered horizontally */
1425 int max_width = g->anim_frames_per_line * width;
1426 int pos = (src_y / height) * max_width + src_x + frame * offset_x;
1428 src_x = pos % max_width;
1429 src_y = src_y % height + pos / max_width * height;
1431 else if (g->offset_x == 0) /* frames are ordered vertically */
1433 int max_height = g->anim_frames_per_line * height;
1434 int pos = (src_x / width) * max_height + src_y + frame * offset_y;
1436 src_x = src_x % width + pos / max_height * width;
1437 src_y = pos % max_height;
1439 else /* frames are ordered diagonally */
1441 src_x = src_x + frame * offset_x;
1442 src_y = src_y + frame * offset_y;
1445 *bitmap = src_bitmap;
1446 *x = startx + src_x;
1447 *y = starty + src_y;
1450 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1451 int *x, int *y, boolean get_backside)
1453 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
1457 void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
1458 Bitmap **bitmap, int *x, int *y)
1460 getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
1463 void getFixedGraphicSource(int graphic, int frame,
1464 Bitmap **bitmap, int *x, int *y)
1466 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
1469 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1472 getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
1474 struct GraphicInfo *g = &graphic_info[graphic];
1475 int mini_startx = 0;
1476 int mini_starty = g->bitmap->height * 2 / 3;
1478 *bitmap = g->bitmap;
1479 *x = mini_startx + g->src_x / 2;
1480 *y = mini_starty + g->src_y / 2;
1484 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1485 int *x, int *y, boolean get_backside)
1487 struct GraphicInfo *g = &graphic_info[graphic];
1488 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
1489 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
1492 if (TILESIZE_VAR != TILESIZE)
1493 return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
1497 *bitmap = g->bitmap;
1499 if (g->offset_y == 0) /* frames are ordered horizontally */
1501 int max_width = g->anim_frames_per_line * g->width;
1502 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
1504 *x = pos % max_width;
1505 *y = src_y % g->height + pos / max_width * g->height;
1507 else if (g->offset_x == 0) /* frames are ordered vertically */
1509 int max_height = g->anim_frames_per_line * g->height;
1510 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
1512 *x = src_x % g->width + pos / max_height * g->width;
1513 *y = pos % max_height;
1515 else /* frames are ordered diagonally */
1517 *x = src_x + frame * g->offset_x;
1518 *y = src_y + frame * g->offset_y;
1522 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
1524 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
1527 void DrawGraphic(int x, int y, int graphic, int frame)
1530 if (!IN_SCR_FIELD(x, y))
1532 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1533 printf("DrawGraphic(): This should never happen!\n");
1539 DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
1542 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1544 MarkTileDirty(x, y);
1547 void DrawFixedGraphic(int x, int y, int graphic, int frame)
1550 if (!IN_SCR_FIELD(x, y))
1552 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1553 printf("DrawGraphic(): This should never happen!\n");
1558 DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1560 MarkTileDirty(x, y);
1563 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1569 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1571 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
1573 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1577 void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1583 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1584 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1587 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1590 if (!IN_SCR_FIELD(x, y))
1592 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1593 printf("DrawGraphicThruMask(): This should never happen!\n");
1599 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
1602 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1605 MarkTileDirty(x, y);
1608 void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
1611 if (!IN_SCR_FIELD(x, y))
1613 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1614 printf("DrawGraphicThruMask(): This should never happen!\n");
1619 DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1621 MarkTileDirty(x, y);
1624 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
1630 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1632 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1633 dst_x - src_x, dst_y - src_y);
1635 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
1638 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1642 void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
1643 int graphic, int frame)
1648 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1650 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1651 dst_x - src_x, dst_y - src_y);
1652 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1655 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
1657 DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
1659 MarkTileDirty(x / tilesize, y / tilesize);
1662 void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
1668 getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
1669 BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
1672 void DrawMiniGraphic(int x, int y, int graphic)
1674 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1675 MarkTileDirty(x / 2, y / 2);
1678 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1683 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1684 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1687 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
1688 int graphic, int frame,
1689 int cut_mode, int mask_mode)
1694 int width = TILEX, height = TILEY;
1697 if (dx || dy) /* shifted graphic */
1699 if (x < BX1) /* object enters playfield from the left */
1706 else if (x > BX2) /* object enters playfield from the right */
1712 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1718 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1720 else if (dx) /* general horizontal movement */
1721 MarkTileDirty(x + SIGN(dx), y);
1723 if (y < BY1) /* object enters playfield from the top */
1725 if (cut_mode==CUT_BELOW) /* object completely above top border */
1733 else if (y > BY2) /* object enters playfield from the bottom */
1739 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1745 else if (dy > 0 && cut_mode == CUT_ABOVE)
1747 if (y == BY2) /* object completely above bottom border */
1753 MarkTileDirty(x, y + 1);
1754 } /* object leaves playfield to the bottom */
1755 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1757 else if (dy) /* general vertical movement */
1758 MarkTileDirty(x, y + SIGN(dy));
1762 if (!IN_SCR_FIELD(x, y))
1764 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1765 printf("DrawGraphicShifted(): This should never happen!\n");
1771 width = width * TILESIZE_VAR / TILESIZE;
1772 height = height * TILESIZE_VAR / TILESIZE;
1773 cx = cx * TILESIZE_VAR / TILESIZE;
1774 cy = cy * TILESIZE_VAR / TILESIZE;
1775 dx = dx * TILESIZE_VAR / TILESIZE;
1776 dy = dy * TILESIZE_VAR / TILESIZE;
1779 if (width > 0 && height > 0)
1781 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1787 dst_x = FX + x * TILEX_VAR + dx;
1788 dst_y = FY + y * TILEY_VAR + dy;
1790 dst_x = FX + x * TILEX + dx;
1791 dst_y = FY + y * TILEY + dy;
1794 if (mask_mode == USE_MASKING)
1796 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1797 dst_x - src_x, dst_y - src_y);
1798 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1802 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1805 MarkTileDirty(x, y);
1809 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
1810 int graphic, int frame,
1811 int cut_mode, int mask_mode)
1817 int width = TILEX_VAR, height = TILEY_VAR;
1819 int width = TILEX, height = TILEY;
1823 int x2 = x + SIGN(dx);
1824 int y2 = y + SIGN(dy);
1826 /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
1827 int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
1829 /* movement with two-tile animations must be sync'ed with movement position,
1830 not with current GfxFrame (which can be higher when using slow movement) */
1831 int anim_pos = (dx ? ABS(dx) : ABS(dy));
1832 int anim_frames = graphic_info[graphic].anim_frames;
1834 /* (we also need anim_delay here for movement animations with less frames) */
1835 int anim_delay = graphic_info[graphic].anim_delay;
1836 int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
1838 int sync_frame = anim_pos * anim_frames / TILESIZE;
1841 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
1842 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
1844 /* re-calculate animation frame for two-tile movement animation */
1845 frame = getGraphicAnimationFrame(graphic, sync_frame);
1849 printf("::: %d, %d, %d => %d [%d]\n",
1850 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
1852 printf("::: %d, %d => %d\n",
1853 anim_pos, anim_frames, sync_frame);
1858 printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
1859 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
1862 /* check if movement start graphic inside screen area and should be drawn */
1863 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
1865 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
1868 dst_x = FX + x1 * TILEX_VAR;
1869 dst_y = FY + y1 * TILEY_VAR;
1871 dst_x = FX + x1 * TILEX;
1872 dst_y = FY + y1 * TILEY;
1875 if (mask_mode == USE_MASKING)
1877 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1878 dst_x - src_x, dst_y - src_y);
1879 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1883 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1886 MarkTileDirty(x1, y1);
1889 /* check if movement end graphic inside screen area and should be drawn */
1890 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
1892 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
1895 dst_x = FX + x2 * TILEX_VAR;
1896 dst_y = FY + y2 * TILEY_VAR;
1898 dst_x = FX + x2 * TILEX;
1899 dst_y = FY + y2 * TILEY;
1902 if (mask_mode == USE_MASKING)
1904 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1905 dst_x - src_x, dst_y - src_y);
1906 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1910 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1913 MarkTileDirty(x2, y2);
1917 static void DrawGraphicShifted(int x, int y, int dx, int dy,
1918 int graphic, int frame,
1919 int cut_mode, int mask_mode)
1923 DrawGraphic(x, y, graphic, frame);
1928 if (graphic_info[graphic].double_movement) /* EM style movement images */
1929 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1931 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1934 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1935 int frame, int cut_mode)
1937 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1940 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1941 int cut_mode, int mask_mode)
1943 int lx = LEVELX(x), ly = LEVELY(y);
1947 if (IN_LEV_FIELD(lx, ly))
1949 SetRandomAnimationValue(lx, ly);
1951 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1952 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1954 /* do not use double (EM style) movement graphic when not moving */
1955 if (graphic_info[graphic].double_movement && !dx && !dy)
1957 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
1958 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1961 else /* border element */
1963 graphic = el2img(element);
1964 frame = getGraphicAnimationFrame(graphic, -1);
1967 if (element == EL_EXPANDABLE_WALL)
1969 boolean left_stopped = FALSE, right_stopped = FALSE;
1971 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1972 left_stopped = TRUE;
1973 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1974 right_stopped = TRUE;
1976 if (left_stopped && right_stopped)
1978 else if (left_stopped)
1980 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1981 frame = graphic_info[graphic].anim_frames - 1;
1983 else if (right_stopped)
1985 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1986 frame = graphic_info[graphic].anim_frames - 1;
1991 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1992 else if (mask_mode == USE_MASKING)
1993 DrawGraphicThruMask(x, y, graphic, frame);
1995 DrawGraphic(x, y, graphic, frame);
1998 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1999 int cut_mode, int mask_mode)
2001 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2002 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
2003 cut_mode, mask_mode);
2006 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
2009 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
2012 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
2015 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
2018 void DrawLevelElementThruMask(int x, int y, int element)
2020 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
2023 void DrawLevelFieldThruMask(int x, int y)
2025 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
2028 /* !!! implementation of quicksand is totally broken !!! */
2029 #define IS_CRUMBLED_TILE(x, y, e) \
2030 (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
2031 !IS_MOVING(x, y) || \
2032 (e) == EL_QUICKSAND_EMPTYING || \
2033 (e) == EL_QUICKSAND_FAST_EMPTYING))
2035 static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
2040 int width, height, cx, cy;
2041 int sx = SCREENX(x), sy = SCREENY(y);
2042 int crumbled_border_size = graphic_info[graphic].border_size;
2045 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2047 for (i = 1; i < 4; i++)
2049 int dxx = (i & 1 ? dx : 0);
2050 int dyy = (i & 2 ? dy : 0);
2053 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2056 /* check if neighbour field is of same crumble type */
2057 boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
2058 graphic_info[graphic].class ==
2059 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
2061 /* return if check prevents inner corner */
2062 if (same == (dxx == dx && dyy == dy))
2066 /* if we reach this point, we have an inner corner */
2068 getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
2071 width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
2072 height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
2073 cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
2074 cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
2076 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2077 width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
2079 width = crumbled_border_size;
2080 height = crumbled_border_size;
2081 cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
2082 cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
2084 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2085 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2089 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
2094 int width, height, bx, by, cx, cy;
2095 int sx = SCREENX(x), sy = SCREENY(y);
2096 int crumbled_border_size = graphic_info[graphic].border_size;
2099 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
2101 /* draw simple, sloppy, non-corner-accurate crumbled border */
2104 width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
2105 height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
2106 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2107 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2109 if (dir == 1 || dir == 2) /* left or right crumbled border */
2111 width = crumbled_border_size;
2113 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2116 else /* top or bottom crumbled border */
2119 height = crumbled_border_size;
2121 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2126 BlitBitmap(src_bitmap, drawto_field,
2127 src_x + cx * TILESIZE_VAR / TILESIZE,
2128 src_y + cy * TILESIZE_VAR / TILESIZE,
2129 width * TILESIZE_VAR / TILESIZE,
2130 height * TILESIZE_VAR / TILESIZE,
2131 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2132 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2134 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2135 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2138 /* (remaining middle border part must be at least as big as corner part) */
2139 if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
2140 crumbled_border_size >= TILESIZE / 3)
2143 /* correct corners of crumbled border, if needed */
2146 for (i = -1; i <= 1; i+=2)
2148 int xx = x + (dir == 0 || dir == 3 ? i : 0);
2149 int yy = y + (dir == 1 || dir == 2 ? i : 0);
2150 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2153 /* check if neighbour field is of same crumble type */
2154 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2155 graphic_info[graphic].class ==
2156 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2158 /* no crumbled corner, but continued crumbled border */
2160 int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
2161 int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
2162 int b1 = (i == 1 ? crumbled_border_size :
2163 TILESIZE - 2 * crumbled_border_size);
2165 width = crumbled_border_size;
2166 height = crumbled_border_size;
2168 if (dir == 1 || dir == 2)
2184 BlitBitmap(src_bitmap, drawto_field,
2185 src_x + bx * TILESIZE_VAR / TILESIZE,
2186 src_y + by * TILESIZE_VAR / TILESIZE,
2187 width * TILESIZE_VAR / TILESIZE,
2188 height * TILESIZE_VAR / TILESIZE,
2189 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2190 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2192 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2193 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2198 if (dir == 1 || dir == 2) /* left or right crumbled border */
2200 for (i = -1; i <= 1; i+=2)
2204 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2207 /* check if neighbour field is of same crumble type */
2208 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2209 graphic_info[graphic].class ==
2210 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2212 /* no crumbled corner, but continued crumbled border */
2214 width = crumbled_border_size;
2215 height = crumbled_border_size;
2216 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2217 cy = (i == 1 ? TILEY - crumbled_border_size : 0);
2219 by = (i == 1 ? crumbled_border_size :
2220 TILEY - 2 * crumbled_border_size);
2222 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2223 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2227 else /* top or bottom crumbled border */
2229 for (i = -1; i <= 1; i+=2)
2233 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2236 /* check if neighbour field is of same crumble type */
2237 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2238 graphic_info[graphic].class ==
2239 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2241 /* no crumbled corner, but continued crumbled border */
2243 width = crumbled_border_size;
2244 height = crumbled_border_size;
2245 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
2246 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2247 bx = (i == 1 ? crumbled_border_size :
2248 TILEX - 2 * crumbled_border_size);
2251 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2252 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2259 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
2261 int sx = SCREENX(x), sy = SCREENY(y);
2264 static int xy[4][2] =
2272 if (!IN_LEV_FIELD(x, y))
2275 element = TILE_GFX_ELEMENT(x, y);
2277 /* crumble field itself */
2278 if (IS_CRUMBLED_TILE(x, y, element))
2280 if (!IN_SCR_FIELD(sx, sy))
2283 for (i = 0; i < 4; i++)
2285 int xx = x + xy[i][0];
2286 int yy = y + xy[i][1];
2288 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2291 /* check if neighbour field is of same crumble type */
2293 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2294 graphic_info[graphic].class ==
2295 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2298 if (IS_CRUMBLED_TILE(xx, yy, element))
2302 DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
2305 if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
2306 graphic_info[graphic].anim_frames == 2)
2308 for (i = 0; i < 4; i++)
2310 int dx = (i & 1 ? +1 : -1);
2311 int dy = (i & 2 ? +1 : -1);
2313 DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
2317 MarkTileDirty(sx, sy);
2319 else /* center field not crumbled -- crumble neighbour fields */
2321 for (i = 0; i < 4; i++)
2323 int xx = x + xy[i][0];
2324 int yy = y + xy[i][1];
2325 int sxx = sx + xy[i][0];
2326 int syy = sy + xy[i][1];
2328 if (!IN_LEV_FIELD(xx, yy) ||
2329 !IN_SCR_FIELD(sxx, syy))
2332 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
2335 element = TILE_GFX_ELEMENT(xx, yy);
2337 if (!IS_CRUMBLED_TILE(xx, yy, element))
2340 graphic = el_act2crm(element, ACTION_DEFAULT);
2342 DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
2344 MarkTileDirty(sxx, syy);
2349 void DrawLevelFieldCrumbled(int x, int y)
2353 if (!IN_LEV_FIELD(x, y))
2357 /* !!! CHECK THIS !!! */
2360 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2361 GFX_CRUMBLED(GfxElement[x][y]))
2364 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2365 GfxElement[x][y] != EL_UNDEFINED &&
2366 GFX_CRUMBLED(GfxElement[x][y]))
2368 DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
2375 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
2377 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
2380 DrawLevelFieldCrumbledExt(x, y, graphic, 0);
2383 void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
2386 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
2387 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
2388 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
2389 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
2390 int sx = SCREENX(x), sy = SCREENY(y);
2392 DrawGraphic(sx, sy, graphic1, frame1);
2393 DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
2396 void DrawLevelFieldCrumbledNeighbours(int x, int y)
2398 int sx = SCREENX(x), sy = SCREENY(y);
2399 static int xy[4][2] =
2408 for (i = 0; i < 4; i++)
2410 int xx = x + xy[i][0];
2411 int yy = y + xy[i][1];
2412 int sxx = sx + xy[i][0];
2413 int syy = sy + xy[i][1];
2415 if (!IN_LEV_FIELD(xx, yy) ||
2416 !IN_SCR_FIELD(sxx, syy) ||
2417 !GFX_CRUMBLED(Feld[xx][yy]) ||
2421 DrawLevelField(xx, yy);
2425 static int getBorderElement(int x, int y)
2429 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
2430 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
2431 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
2432 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2433 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
2434 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
2435 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
2437 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2438 int steel_position = (x == -1 && y == -1 ? 0 :
2439 x == lev_fieldx && y == -1 ? 1 :
2440 x == -1 && y == lev_fieldy ? 2 :
2441 x == lev_fieldx && y == lev_fieldy ? 3 :
2442 x == -1 || x == lev_fieldx ? 4 :
2443 y == -1 || y == lev_fieldy ? 5 : 6);
2445 return border[steel_position][steel_type];
2448 void DrawScreenElement(int x, int y, int element)
2450 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2451 DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
2454 void DrawLevelElement(int x, int y, int element)
2456 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2457 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2460 void DrawScreenField(int x, int y)
2462 int lx = LEVELX(x), ly = LEVELY(y);
2463 int element, content;
2465 if (!IN_LEV_FIELD(lx, ly))
2467 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
2470 element = getBorderElement(lx, ly);
2472 DrawScreenElement(x, y, element);
2477 element = Feld[lx][ly];
2478 content = Store[lx][ly];
2480 if (IS_MOVING(lx, ly))
2482 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
2483 boolean cut_mode = NO_CUTTING;
2485 if (element == EL_QUICKSAND_EMPTYING ||
2486 element == EL_QUICKSAND_FAST_EMPTYING ||
2487 element == EL_MAGIC_WALL_EMPTYING ||
2488 element == EL_BD_MAGIC_WALL_EMPTYING ||
2489 element == EL_DC_MAGIC_WALL_EMPTYING ||
2490 element == EL_AMOEBA_DROPPING)
2491 cut_mode = CUT_ABOVE;
2492 else if (element == EL_QUICKSAND_FILLING ||
2493 element == EL_QUICKSAND_FAST_FILLING ||
2494 element == EL_MAGIC_WALL_FILLING ||
2495 element == EL_BD_MAGIC_WALL_FILLING ||
2496 element == EL_DC_MAGIC_WALL_FILLING)
2497 cut_mode = CUT_BELOW;
2500 if (lx == 9 && ly == 1)
2501 printf("::: %s [%d] [%d, %d] [%d]\n",
2502 EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
2503 el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
2504 element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
2505 element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
2506 GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
2509 if (cut_mode == CUT_ABOVE)
2511 DrawScreenElement(x, y, element);
2513 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2516 DrawScreenElement(x, y, EL_EMPTY);
2519 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
2520 else if (cut_mode == NO_CUTTING)
2521 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
2524 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
2527 if (cut_mode == CUT_BELOW &&
2528 IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
2529 DrawLevelElement(lx, ly + 1, element);
2533 if (content == EL_ACID)
2535 int dir = MovDir[lx][ly];
2536 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
2537 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
2539 DrawLevelElementThruMask(newlx, newly, EL_ACID);
2542 else if (IS_BLOCKED(lx, ly))
2547 boolean cut_mode = NO_CUTTING;
2548 int element_old, content_old;
2550 Blocked2Moving(lx, ly, &oldx, &oldy);
2553 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2554 MovDir[oldx][oldy] == MV_RIGHT);
2556 element_old = Feld[oldx][oldy];
2557 content_old = Store[oldx][oldy];
2559 if (element_old == EL_QUICKSAND_EMPTYING ||
2560 element_old == EL_QUICKSAND_FAST_EMPTYING ||
2561 element_old == EL_MAGIC_WALL_EMPTYING ||
2562 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2563 element_old == EL_DC_MAGIC_WALL_EMPTYING ||
2564 element_old == EL_AMOEBA_DROPPING)
2565 cut_mode = CUT_ABOVE;
2567 DrawScreenElement(x, y, EL_EMPTY);
2570 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2572 else if (cut_mode == NO_CUTTING)
2573 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2576 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2579 else if (IS_DRAWABLE(element))
2580 DrawScreenElement(x, y, element);
2582 DrawScreenElement(x, y, EL_EMPTY);
2585 void DrawLevelField(int x, int y)
2587 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2588 DrawScreenField(SCREENX(x), SCREENY(y));
2589 else if (IS_MOVING(x, y))
2593 Moving2Blocked(x, y, &newx, &newy);
2594 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2595 DrawScreenField(SCREENX(newx), SCREENY(newy));
2597 else if (IS_BLOCKED(x, y))
2601 Blocked2Moving(x, y, &oldx, &oldy);
2602 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2603 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2607 void DrawMiniElement(int x, int y, int element)
2611 graphic = el2edimg(element);
2612 DrawMiniGraphic(x, y, graphic);
2615 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2617 int x = sx + scroll_x, y = sy + scroll_y;
2619 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2620 DrawMiniElement(sx, sy, EL_EMPTY);
2621 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2622 DrawMiniElement(sx, sy, Feld[x][y]);
2624 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
2627 void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
2628 int x, int y, int xsize, int ysize,
2629 int tile_width, int tile_height)
2633 int dst_x = startx + x * tile_width;
2634 int dst_y = starty + y * tile_height;
2635 int width = graphic_info[graphic].width;
2636 int height = graphic_info[graphic].height;
2637 int inner_width_raw = MAX(width - 2 * tile_width, tile_width);
2638 int inner_height_raw = MAX(height - 2 * tile_height, tile_height);
2639 int inner_width = inner_width_raw - (inner_width_raw % tile_width);
2640 int inner_height = inner_height_raw - (inner_height_raw % tile_height);
2641 int inner_sx = (width >= 3 * tile_width ? tile_width : 0);
2642 int inner_sy = (height >= 3 * tile_height ? tile_height : 0);
2643 boolean draw_masked = graphic_info[graphic].draw_masked;
2645 getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2647 if (src_bitmap == NULL || width < tile_width || height < tile_height)
2649 ClearRectangle(drawto, dst_x, dst_y, tile_width, tile_height);
2653 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - tile_width :
2654 inner_sx + (x - 1) * tile_width % inner_width);
2655 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - tile_height :
2656 inner_sy + (y - 1) * tile_height % inner_height);
2660 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
2661 dst_x - src_x, dst_y - src_y);
2662 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2666 BlitBitmap(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2670 void DrawEnvelopeBackground(int graphic, int startx, int starty,
2671 int x, int y, int xsize, int ysize, int font_nr)
2673 int font_width = getFontWidth(font_nr);
2674 int font_height = getFontHeight(font_nr);
2676 DrawEnvelopeBackgroundTiles(graphic, startx, starty, x, y, xsize, ysize,
2677 font_width, font_height);
2680 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
2682 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2683 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2684 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2685 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2686 boolean no_delay = (tape.warp_forward);
2687 unsigned int anim_delay = 0;
2688 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2689 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2690 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2691 int font_width = getFontWidth(font_nr);
2692 int font_height = getFontHeight(font_nr);
2693 int max_xsize = level.envelope[envelope_nr].xsize;
2694 int max_ysize = level.envelope[envelope_nr].ysize;
2695 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2696 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2697 int xend = max_xsize;
2698 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2699 int xstep = (xstart < xend ? 1 : 0);
2700 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2703 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2705 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2706 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2707 int sx = SX + (SXSIZE - xsize * font_width) / 2;
2708 int sy = SY + (SYSIZE - ysize * font_height) / 2;
2711 SetDrawtoField(DRAW_BUFFERED);
2714 BlitScreenToBitmap(backbuffer);
2716 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2719 SetDrawtoField(DRAW_BACKBUFFER);
2721 for (yy = 0; yy < ysize; yy++)
2722 for (xx = 0; xx < xsize; xx++)
2723 DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
2726 DrawTextBuffer(sx + font_width, sy + font_height,
2727 level.envelope[envelope_nr].text, font_nr, max_xsize,
2728 xsize - 2, ysize - 2, 0, mask_mode,
2729 level.envelope[envelope_nr].autowrap,
2730 level.envelope[envelope_nr].centered, FALSE);
2732 DrawTextToTextArea(sx + font_width, sy + font_height,
2733 level.envelope[envelope_nr].text, font_nr, max_xsize,
2734 xsize - 2, ysize - 2, mask_mode);
2737 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2740 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2744 void ShowEnvelope(int envelope_nr)
2746 int element = EL_ENVELOPE_1 + envelope_nr;
2747 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2748 int sound_opening = element_info[element].sound[ACTION_OPENING];
2749 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2750 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2751 boolean no_delay = (tape.warp_forward);
2752 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2753 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2754 int anim_mode = graphic_info[graphic].anim_mode;
2755 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2756 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2758 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2760 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2762 if (anim_mode == ANIM_DEFAULT)
2763 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
2765 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
2768 Delay(wait_delay_value);
2770 WaitForEventToContinue();
2772 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2774 if (anim_mode != ANIM_NONE)
2775 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
2777 if (anim_mode == ANIM_DEFAULT)
2778 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
2780 game.envelope_active = FALSE;
2782 SetDrawtoField(DRAW_BUFFERED);
2784 redraw_mask |= REDRAW_FIELD;
2788 static void setRequestPosition(int *x, int *y, boolean add_border_size)
2790 int border_size = request.border_size;
2791 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2792 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2793 int sx = sx_center - request.width / 2;
2794 int sy = sy_center - request.height / 2;
2796 if (add_border_size)
2806 void DrawEnvelopeRequest(char *text)
2808 char *text_final = text;
2809 char *text_door_style = NULL;
2810 int graphic = IMG_BACKGROUND_REQUEST;
2811 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2812 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2813 int font_nr = FONT_REQUEST;
2814 int font_width = getFontWidth(font_nr);
2815 int font_height = getFontHeight(font_nr);
2816 int border_size = request.border_size;
2817 int line_spacing = request.line_spacing;
2818 int line_height = font_height + line_spacing;
2819 int text_width = request.width - 2 * border_size;
2820 int text_height = request.height - 2 * border_size;
2821 int line_length = text_width / font_width;
2822 int max_lines = text_height / line_height;
2823 int width = request.width;
2824 int height = request.height;
2825 int tile_size = request.step_offset;
2826 int x_steps = width / tile_size;
2827 int y_steps = height / tile_size;
2831 if (request.wrap_single_words)
2833 char *src_text_ptr, *dst_text_ptr;
2835 text_door_style = checked_malloc(2 * strlen(text) + 1);
2837 src_text_ptr = text;
2838 dst_text_ptr = text_door_style;
2840 while (*src_text_ptr)
2842 if (*src_text_ptr == ' ' ||
2843 *src_text_ptr == '?' ||
2844 *src_text_ptr == '!')
2845 *dst_text_ptr++ = '\n';
2847 if (*src_text_ptr != ' ')
2848 *dst_text_ptr++ = *src_text_ptr;
2853 *dst_text_ptr = '\0';
2855 text_final = text_door_style;
2858 setRequestPosition(&sx, &sy, FALSE);
2860 ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
2862 for (y = 0; y < y_steps; y++)
2863 for (x = 0; x < x_steps; x++)
2864 DrawEnvelopeBackgroundTiles(graphic, sx, sy,
2865 x, y, x_steps, y_steps,
2866 tile_size, tile_size);
2868 DrawTextBuffer(sx + border_size, sy + border_size, text_final, font_nr,
2869 line_length, -1, max_lines, line_spacing, mask_mode,
2870 request.autowrap, request.centered, FALSE);
2872 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2873 RedrawGadget(tool_gadget[i]);
2875 // store readily prepared envelope request for later use when animating
2876 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2880 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2881 BlitBitmap(bitmap_db_cross, backbuffer, sx, sy, width, height, sx, sy);
2883 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2888 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2890 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2896 if (text_door_style)
2897 free(text_door_style);
2902 void AnimateEnvelopeRequest(int anim_mode, int action)
2904 int graphic = IMG_BACKGROUND_REQUEST;
2905 boolean draw_masked = graphic_info[graphic].draw_masked;
2907 int delay_value_normal = request.step_delay;
2908 int delay_value_fast = delay_value_normal / 2;
2910 int delay_value_normal = GameFrameDelay;
2911 int delay_value_fast = FfwdFrameDelay;
2913 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2914 boolean no_delay = (tape.warp_forward);
2915 int delay_value = (ffwd_delay ? delay_value_fast : delay_value_normal);
2916 int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0);
2917 unsigned int anim_delay = 0;
2919 int width = request.width;
2920 int height = request.height;
2921 int tile_size = request.step_offset;
2922 int max_xsize = width / tile_size;
2923 int max_ysize = height / tile_size;
2924 int max_xsize_inner = max_xsize - 2;
2925 int max_ysize_inner = max_ysize - 2;
2927 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize_inner : 0);
2928 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize_inner : 0);
2929 int xend = max_xsize_inner;
2930 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize_inner : 0);
2931 int xstep = (xstart < xend ? 1 : 0);
2932 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2935 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2937 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2938 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2939 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2940 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2941 int src_x = sx_center - width / 2;
2942 int src_y = sy_center - height / 2;
2943 int dst_x = sx_center - xsize * tile_size / 2;
2944 int dst_y = sy_center - ysize * tile_size / 2;
2945 int xsize_size_left = (xsize - 1) * tile_size;
2946 int ysize_size_top = (ysize - 1) * tile_size;
2947 int max_xsize_pos = (max_xsize - 1) * tile_size;
2948 int max_ysize_pos = (max_ysize - 1) * tile_size;
2951 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2954 for (yy = 0; yy < 2; yy++)
2956 for (xx = 0; xx < 2; xx++)
2958 int src_xx = src_x + xx * max_xsize_pos;
2959 int src_yy = src_y + yy * max_ysize_pos;
2960 int dst_xx = dst_x + xx * xsize_size_left;
2961 int dst_yy = dst_y + yy * ysize_size_top;
2962 int xx_size = (xx ? tile_size : xsize_size_left);
2963 int yy_size = (yy ? tile_size : ysize_size_top);
2966 BlitBitmapMasked(bitmap_db_cross, backbuffer,
2967 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2969 BlitBitmap(bitmap_db_cross, backbuffer,
2970 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2974 BlitBitmap(bitmap_db_cross, backbuffer,
2976 xsize_size_left, ysize_size_top,
2978 BlitBitmap(bitmap_db_cross, backbuffer,
2979 src_x + max_xsize_pos, src_y,
2980 tile_size, ysize_size_top,
2981 dst_x + xsize_size_left, dst_y);
2982 BlitBitmap(bitmap_db_cross, backbuffer,
2983 src_x, src_y + max_ysize_pos,
2984 xsize_size_left, tile_size,
2985 dst_x, dst_y + ysize_size_top);
2986 BlitBitmap(bitmap_db_cross, backbuffer,
2987 src_x + max_xsize_pos, src_y + max_ysize_pos,
2988 tile_size, tile_size,
2989 dst_x + xsize_size_left, dst_y + ysize_size_top);
2993 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2994 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
2996 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3006 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
3012 void AnimateEnvelopeRequest(char *text, int anim_mode, int action)
3015 int envelope_nr = 0;
3018 int graphic = IMG_BACKGROUND_REQUEST;
3020 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3022 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
3023 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
3024 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3025 boolean no_delay = (tape.warp_forward);
3026 unsigned int anim_delay = 0;
3027 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
3028 int anim_delay_value = (no_delay ? 0 : frame_delay_value + 500 * 0);
3030 int max_word_len = maxWordLengthInString(text);
3031 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
3033 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
3035 int font_width = getFontWidth(font_nr);
3036 int font_height = getFontHeight(font_nr);
3037 int line_spacing = 2 * 1;
3041 int max_xsize = DXSIZE / font_width;
3042 // int max_ysize = DYSIZE / font_height;
3043 int max_ysize = DYSIZE / (font_height + line_spacing);
3045 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3046 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
3050 int max_xsize = level.envelope[envelope_nr].xsize;
3051 int max_ysize = level.envelope[envelope_nr].ysize;
3053 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
3054 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
3055 int xend = max_xsize;
3056 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
3057 int xstep = (xstart < xend ? 1 : 0);
3058 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
3063 char *text_copy = getStringCopy(text);
3066 font_nr = FONT_TEXT_2;
3068 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
3070 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3071 font_nr = FONT_TEXT_1;
3074 int max_word_len = 0;
3076 char *text_copy = getStringCopy(text);
3078 font_nr = FONT_TEXT_2;
3080 for (text_ptr = text; *text_ptr; text_ptr++)
3082 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
3084 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3086 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3087 font_nr = FONT_TEXT_1;
3096 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3097 if (*text_ptr == ' ')
3102 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
3103 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
3105 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
3106 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
3109 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
3111 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
3112 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
3113 int sx = SX + (SXSIZE - xsize * font_width) / 2;
3114 // int sy = SX + (SYSIZE - ysize * font_height) / 2;
3115 int sy = SY + (SYSIZE - ysize * (font_height + line_spacing)) / 2;
3119 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3121 SetDrawtoField(DRAW_BUFFERED);
3124 BlitScreenToBitmap(backbuffer);
3126 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3129 SetDrawtoField(DRAW_BACKBUFFER);
3132 for (yy = 0; yy < ysize; yy++)
3133 for (xx = 0; xx < xsize; xx++)
3134 DrawEnvelopeBackgroundTiles(graphic, sx, sy, xx, yy, xsize, ysize,
3135 getFontWidth(font_nr),
3136 getFontHeight(font_nr) + line_spacing);
3141 DrawTextBuffer(sx + font_width, sy + font_height + 8,
3142 text_copy, font_nr, max_xsize,
3143 xsize - 2, ysize - 2, line_spacing, mask_mode,
3144 FALSE, TRUE, FALSE);
3146 DrawTextBuffer(sx + font_width, sy + font_height,
3147 level.envelope[envelope_nr].text, font_nr, max_xsize,
3148 xsize - 2, ysize - 2, 0, mask_mode,
3149 level.envelope[envelope_nr].autowrap,
3150 level.envelope[envelope_nr].centered, FALSE);
3154 DrawTextToTextArea(sx + font_width, sy + font_height,
3155 level.envelope[envelope_nr].text, font_nr, max_xsize,
3156 xsize - 2, ysize - 2, mask_mode);
3159 /* copy request gadgets to door backbuffer */
3162 if ((ysize - 2) > 13)
3163 BlitBitmap(bitmap_db_door, drawto,
3164 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3165 DOOR_GFX_PAGEY1 + 13 * font_height,
3166 (xsize - 2) * font_width,
3167 (ysize - 2 - 13) * font_height,
3169 sy + font_height * (1 + 13));
3171 if ((ysize - 2) > 13)
3172 BlitBitmap(bitmap_db_door, drawto,
3173 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3174 DOOR_GFX_PAGEY1 + 11 * (font_height + line_spacing * 0),
3175 (xsize - 2) * font_width,
3176 (ysize - 2 - 13) * (font_height + line_spacing),
3178 sy + (font_height + line_spacing) * (1 + 13));
3180 if ((ysize - 2) > 13)
3181 BlitBitmap(bitmap_db_door, drawto,
3182 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3183 DOOR_GFX_PAGEY1 + 13 * font_height,
3184 (xsize - 2) * font_width,
3185 (ysize - 2 - 13) * font_height,
3187 sy + font_height * (1 + 13));
3191 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3192 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
3194 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3204 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
3214 void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
3217 int last_game_status = game_status; /* save current game status */
3218 // int last_draw_background_mask = gfx.draw_background_mask;
3221 int graphic = IMG_BACKGROUND_REQUEST;
3222 int sound_opening = SND_REQUEST_OPENING;
3223 int sound_closing = SND_REQUEST_CLOSING;
3225 int envelope_nr = 0;
3226 int element = EL_ENVELOPE_1 + envelope_nr;
3227 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3228 int sound_opening = element_info[element].sound[ACTION_OPENING];
3229 int sound_closing = element_info[element].sound[ACTION_CLOSING];
3232 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3233 boolean no_delay = (tape.warp_forward);
3234 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
3235 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
3237 int anim_mode = graphic_info[graphic].anim_mode;
3238 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
3239 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
3241 char *text_copy = getStringCopy(text);
3244 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3245 if (*text_ptr == ' ')
3250 if (game_status == GAME_MODE_PLAYING)
3252 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3253 BlitScreenToBitmap_EM(backbuffer);
3254 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3255 BlitScreenToBitmap_SP(backbuffer);
3258 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3262 SetDrawtoField(DRAW_BACKBUFFER);
3264 // SetDrawBackgroundMask(REDRAW_NONE);
3266 if (action == ACTION_OPENING)
3268 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3271 if (req_state & REQ_ASK)
3273 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
3274 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
3276 else if (req_state & REQ_CONFIRM)
3278 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
3280 else if (req_state & REQ_PLAYER)
3282 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
3283 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
3284 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
3285 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
3290 DrawEnvelopeRequest(text);
3292 DrawEnvelopeRequest(text_copy);
3295 if (game_status != GAME_MODE_MAIN)
3299 /* force DOOR font inside door area */
3300 game_status = GAME_MODE_PSEUDO_DOOR;
3303 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
3305 if (action == ACTION_OPENING)
3307 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
3309 if (anim_mode == ANIM_DEFAULT)
3310 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
3312 AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
3316 Delay(wait_delay_value);
3318 WaitForEventToContinue();
3323 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
3325 if (anim_mode != ANIM_NONE)
3326 AnimateEnvelopeRequest(main_anim_mode, ACTION_CLOSING);
3328 if (anim_mode == ANIM_DEFAULT)
3329 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_CLOSING);
3332 game.envelope_active = FALSE;
3335 // game_status = last_game_status; /* restore current game status */
3337 if (action == ACTION_CLOSING)
3339 if (game_status != GAME_MODE_MAIN)
3342 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3345 SetDrawtoField(DRAW_BUFFERED);
3348 // SetDrawBackgroundMask(last_draw_background_mask);
3351 redraw_mask = REDRAW_FIELD;
3352 // redraw_mask |= REDRAW_ALL;
3354 redraw_mask |= REDRAW_FIELD;
3358 if (game_status == GAME_MODE_MAIN)
3363 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
3364 game_status = last_game_status; /* restore current game status */
3367 if (action == ACTION_CLOSING &&
3368 game_status == GAME_MODE_PLAYING &&
3369 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3370 SetDrawtoField(DRAW_BUFFERED);
3372 if (game_status == GAME_MODE_PLAYING &&
3373 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3374 SetDrawtoField(DRAW_BUFFERED);
3386 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
3390 int graphic = el2preimg(element);
3392 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
3393 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
3401 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
3402 SetDrawBackgroundMask(REDRAW_FIELD);
3404 SetDrawBackgroundMask(REDRAW_NONE);
3409 for (x = BX1; x <= BX2; x++)
3410 for (y = BY1; y <= BY2; y++)
3411 DrawScreenField(x, y);
3413 redraw_mask |= REDRAW_FIELD;
3416 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
3420 for (x = 0; x < size_x; x++)
3421 for (y = 0; y < size_y; y++)
3422 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
3424 redraw_mask |= REDRAW_FIELD;
3427 static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
3429 boolean show_level_border = (BorderElement != EL_EMPTY);
3430 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3431 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3432 int tile_size = preview.tile_size;
3433 int preview_width = preview.xsize * tile_size;
3434 int preview_height = preview.ysize * tile_size;
3435 int real_preview_xsize = MIN(level_xsize, preview.xsize);
3436 int real_preview_ysize = MIN(level_ysize, preview.ysize);
3437 int real_preview_width = real_preview_xsize * tile_size;
3438 int real_preview_height = real_preview_ysize * tile_size;
3439 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
3440 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
3444 if (!IN_GFX_FIELD_FULL(dst_x, dst_y + preview_height - 1))
3449 dst_x += (preview_width - real_preview_width) / 2;
3450 dst_y += (preview_height - real_preview_height) / 2;
3452 DrawBackground(dst_x, dst_y, real_preview_width, real_preview_height);
3454 DrawBackground(dst_x, dst_y, preview_width, preview_height);
3456 dst_x += (preview_width - real_preview_width) / 2;
3457 dst_y += (preview_height - real_preview_height) / 2;
3460 for (x = 0; x < real_preview_xsize; x++)
3462 for (y = 0; y < real_preview_ysize; y++)
3464 int lx = from_x + x + (show_level_border ? -1 : 0);
3465 int ly = from_y + y + (show_level_border ? -1 : 0);
3466 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
3467 getBorderElement(lx, ly));
3469 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
3470 element, tile_size);
3474 redraw_mask |= REDRAW_MICROLEVEL;
3477 #define MICROLABEL_EMPTY 0
3478 #define MICROLABEL_LEVEL_NAME 1
3479 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
3480 #define MICROLABEL_LEVEL_AUTHOR 3
3481 #define MICROLABEL_IMPORTED_FROM_HEAD 4
3482 #define MICROLABEL_IMPORTED_FROM 5
3483 #define MICROLABEL_IMPORTED_BY_HEAD 6
3484 #define MICROLABEL_IMPORTED_BY 7
3486 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
3488 int max_text_width = SXSIZE;
3489 int font_width = getFontWidth(font_nr);
3491 if (pos->align == ALIGN_CENTER)
3492 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
3493 else if (pos->align == ALIGN_RIGHT)
3494 max_text_width = pos->x;
3496 max_text_width = SXSIZE - pos->x;
3498 return max_text_width / font_width;
3501 static void DrawPreviewLevelLabelExt(int mode)
3503 struct TextPosInfo *pos = &menu.main.text.level_info_2;
3504 char label_text[MAX_OUTPUT_LINESIZE + 1];
3505 int max_len_label_text;
3507 int font_nr = pos->font;
3510 if (!IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3513 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3514 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3515 mode == MICROLABEL_IMPORTED_BY_HEAD)
3516 font_nr = pos->font_alt;
3518 int font_nr = FONT_TEXT_2;
3521 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3522 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3523 mode == MICROLABEL_IMPORTED_BY_HEAD)
3524 font_nr = FONT_TEXT_3;
3528 max_len_label_text = getMaxTextLength(pos, font_nr);
3530 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3534 if (pos->size != -1)
3535 max_len_label_text = pos->size;
3538 for (i = 0; i < max_len_label_text; i++)
3539 label_text[i] = ' ';
3540 label_text[max_len_label_text] = '\0';
3542 if (strlen(label_text) > 0)
3545 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3547 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3548 int lypos = MICROLABEL2_YPOS;
3550 DrawText(lxpos, lypos, label_text, font_nr);
3555 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3556 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3557 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3558 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3559 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3560 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3561 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3562 max_len_label_text);
3563 label_text[max_len_label_text] = '\0';
3565 if (strlen(label_text) > 0)
3568 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3570 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3571 int lypos = MICROLABEL2_YPOS;
3573 DrawText(lxpos, lypos, label_text, font_nr);
3577 redraw_mask |= REDRAW_MICROLEVEL;
3580 static void DrawPreviewLevelExt(boolean restart)
3582 static unsigned int scroll_delay = 0;
3583 static unsigned int label_delay = 0;
3584 static int from_x, from_y, scroll_direction;
3585 static int label_state, label_counter;
3586 unsigned int scroll_delay_value = preview.step_delay;
3587 boolean show_level_border = (BorderElement != EL_EMPTY);
3588 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3589 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3590 int last_game_status = game_status; /* save current game status */
3593 /* force PREVIEW font on preview level */
3594 game_status = GAME_MODE_PSEUDO_PREVIEW;
3602 if (preview.anim_mode == ANIM_CENTERED)
3604 if (level_xsize > preview.xsize)
3605 from_x = (level_xsize - preview.xsize) / 2;
3606 if (level_ysize > preview.ysize)
3607 from_y = (level_ysize - preview.ysize) / 2;
3610 from_x += preview.xoffset;
3611 from_y += preview.yoffset;
3613 scroll_direction = MV_RIGHT;
3617 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3618 DrawPreviewLevelLabelExt(label_state);
3620 /* initialize delay counters */
3621 DelayReached(&scroll_delay, 0);
3622 DelayReached(&label_delay, 0);
3624 if (leveldir_current->name)
3626 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3627 char label_text[MAX_OUTPUT_LINESIZE + 1];
3629 int font_nr = pos->font;
3631 int font_nr = FONT_TEXT_1;
3634 int max_len_label_text = getMaxTextLength(pos, font_nr);
3636 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3644 if (pos->size != -1)
3645 max_len_label_text = pos->size;
3648 strncpy(label_text, leveldir_current->name, max_len_label_text);
3649 label_text[max_len_label_text] = '\0';
3652 if (IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3653 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3655 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3656 lypos = SY + MICROLABEL1_YPOS;
3658 DrawText(lxpos, lypos, label_text, font_nr);
3662 game_status = last_game_status; /* restore current game status */
3667 /* scroll preview level, if needed */
3668 if (preview.anim_mode != ANIM_NONE &&
3669 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3670 DelayReached(&scroll_delay, scroll_delay_value))
3672 switch (scroll_direction)
3677 from_x -= preview.step_offset;
3678 from_x = (from_x < 0 ? 0 : from_x);
3681 scroll_direction = MV_UP;
3685 if (from_x < level_xsize - preview.xsize)
3687 from_x += preview.step_offset;
3688 from_x = (from_x > level_xsize - preview.xsize ?
3689 level_xsize - preview.xsize : from_x);
3692 scroll_direction = MV_DOWN;
3698 from_y -= preview.step_offset;
3699 from_y = (from_y < 0 ? 0 : from_y);
3702 scroll_direction = MV_RIGHT;
3706 if (from_y < level_ysize - preview.ysize)
3708 from_y += preview.step_offset;
3709 from_y = (from_y > level_ysize - preview.ysize ?
3710 level_ysize - preview.ysize : from_y);
3713 scroll_direction = MV_LEFT;
3720 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3723 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3724 /* redraw micro level label, if needed */
3725 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3726 !strEqual(level.author, ANONYMOUS_NAME) &&
3727 !strEqual(level.author, leveldir_current->name) &&
3728 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3730 int max_label_counter = 23;
3732 if (leveldir_current->imported_from != NULL &&
3733 strlen(leveldir_current->imported_from) > 0)
3734 max_label_counter += 14;
3735 if (leveldir_current->imported_by != NULL &&
3736 strlen(leveldir_current->imported_by) > 0)
3737 max_label_counter += 14;
3739 label_counter = (label_counter + 1) % max_label_counter;
3740 label_state = (label_counter >= 0 && label_counter <= 7 ?
3741 MICROLABEL_LEVEL_NAME :
3742 label_counter >= 9 && label_counter <= 12 ?
3743 MICROLABEL_LEVEL_AUTHOR_HEAD :
3744 label_counter >= 14 && label_counter <= 21 ?
3745 MICROLABEL_LEVEL_AUTHOR :
3746 label_counter >= 23 && label_counter <= 26 ?
3747 MICROLABEL_IMPORTED_FROM_HEAD :
3748 label_counter >= 28 && label_counter <= 35 ?
3749 MICROLABEL_IMPORTED_FROM :
3750 label_counter >= 37 && label_counter <= 40 ?
3751 MICROLABEL_IMPORTED_BY_HEAD :
3752 label_counter >= 42 && label_counter <= 49 ?
3753 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3755 if (leveldir_current->imported_from == NULL &&
3756 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3757 label_state == MICROLABEL_IMPORTED_FROM))
3758 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3759 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3761 DrawPreviewLevelLabelExt(label_state);
3764 game_status = last_game_status; /* restore current game status */
3767 void DrawPreviewLevelInitial()
3769 DrawPreviewLevelExt(TRUE);
3772 void DrawPreviewLevelAnimation()
3774 DrawPreviewLevelExt(FALSE);
3777 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3778 int graphic, int sync_frame, int mask_mode)
3780 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3782 if (mask_mode == USE_MASKING)
3783 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3785 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3788 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3789 int graphic, int sync_frame,
3792 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3794 if (mask_mode == USE_MASKING)
3795 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3797 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3800 inline void DrawGraphicAnimation(int x, int y, int graphic)
3802 int lx = LEVELX(x), ly = LEVELY(y);
3804 if (!IN_SCR_FIELD(x, y))
3808 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3809 graphic, GfxFrame[lx][ly], NO_MASKING);
3811 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3812 graphic, GfxFrame[lx][ly], NO_MASKING);
3814 MarkTileDirty(x, y);
3817 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3819 int lx = LEVELX(x), ly = LEVELY(y);
3821 if (!IN_SCR_FIELD(x, y))
3824 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3825 graphic, GfxFrame[lx][ly], NO_MASKING);
3826 MarkTileDirty(x, y);
3829 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3831 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3834 void DrawLevelElementAnimation(int x, int y, int element)
3836 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3838 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3841 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3843 int sx = SCREENX(x), sy = SCREENY(y);
3845 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3848 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3851 DrawGraphicAnimation(sx, sy, graphic);
3854 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3855 DrawLevelFieldCrumbled(x, y);
3857 if (GFX_CRUMBLED(Feld[x][y]))
3858 DrawLevelFieldCrumbled(x, y);
3862 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3864 int sx = SCREENX(x), sy = SCREENY(y);
3867 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3870 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3872 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3875 DrawGraphicAnimation(sx, sy, graphic);
3877 if (GFX_CRUMBLED(element))
3878 DrawLevelFieldCrumbled(x, y);
3881 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3883 if (player->use_murphy)
3885 /* this works only because currently only one player can be "murphy" ... */
3886 static int last_horizontal_dir = MV_LEFT;
3887 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3889 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3890 last_horizontal_dir = move_dir;
3892 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3894 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3896 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3902 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3905 static boolean equalGraphics(int graphic1, int graphic2)
3907 struct GraphicInfo *g1 = &graphic_info[graphic1];
3908 struct GraphicInfo *g2 = &graphic_info[graphic2];
3910 return (g1->bitmap == g2->bitmap &&
3911 g1->src_x == g2->src_x &&
3912 g1->src_y == g2->src_y &&
3913 g1->anim_frames == g2->anim_frames &&
3914 g1->anim_delay == g2->anim_delay &&
3915 g1->anim_mode == g2->anim_mode);
3918 void DrawAllPlayers()
3922 for (i = 0; i < MAX_PLAYERS; i++)
3923 if (stored_player[i].active)
3924 DrawPlayer(&stored_player[i]);
3927 void DrawPlayerField(int x, int y)
3929 if (!IS_PLAYER(x, y))
3932 DrawPlayer(PLAYERINFO(x, y));
3935 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3937 void DrawPlayer(struct PlayerInfo *player)
3939 int jx = player->jx;
3940 int jy = player->jy;
3941 int move_dir = player->MovDir;
3942 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3943 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3944 int last_jx = (player->is_moving ? jx - dx : jx);
3945 int last_jy = (player->is_moving ? jy - dy : jy);
3946 int next_jx = jx + dx;
3947 int next_jy = jy + dy;
3948 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3949 boolean player_is_opaque = FALSE;
3950 int sx = SCREENX(jx), sy = SCREENY(jy);
3951 int sxx = 0, syy = 0;
3952 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3954 int action = ACTION_DEFAULT;
3955 int last_player_graphic = getPlayerGraphic(player, move_dir);
3956 int last_player_frame = player->Frame;
3959 /* GfxElement[][] is set to the element the player is digging or collecting;
3960 remove also for off-screen player if the player is not moving anymore */
3961 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3962 GfxElement[jx][jy] = EL_UNDEFINED;
3964 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3968 if (!IN_LEV_FIELD(jx, jy))
3970 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3971 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3972 printf("DrawPlayerField(): This should never happen!\n");
3977 if (element == EL_EXPLOSION)
3980 action = (player->is_pushing ? ACTION_PUSHING :
3981 player->is_digging ? ACTION_DIGGING :
3982 player->is_collecting ? ACTION_COLLECTING :
3983 player->is_moving ? ACTION_MOVING :
3984 player->is_snapping ? ACTION_SNAPPING :
3985 player->is_dropping ? ACTION_DROPPING :
3986 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3988 if (player->is_waiting)
3989 move_dir = player->dir_waiting;
3991 InitPlayerGfxAnimation(player, action, move_dir);
3993 /* ----------------------------------------------------------------------- */
3994 /* draw things in the field the player is leaving, if needed */
3995 /* ----------------------------------------------------------------------- */
3997 if (player->is_moving)
3999 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
4001 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
4003 if (last_element == EL_DYNAMITE_ACTIVE ||
4004 last_element == EL_EM_DYNAMITE_ACTIVE ||
4005 last_element == EL_SP_DISK_RED_ACTIVE)
4006 DrawDynamite(last_jx, last_jy);
4008 DrawLevelFieldThruMask(last_jx, last_jy);
4010 else if (last_element == EL_DYNAMITE_ACTIVE ||
4011 last_element == EL_EM_DYNAMITE_ACTIVE ||
4012 last_element == EL_SP_DISK_RED_ACTIVE)
4013 DrawDynamite(last_jx, last_jy);
4015 /* !!! this is not enough to prevent flickering of players which are
4016 moving next to each others without a free tile between them -- this
4017 can only be solved by drawing all players layer by layer (first the
4018 background, then the foreground etc.) !!! => TODO */
4019 else if (!IS_PLAYER(last_jx, last_jy))
4020 DrawLevelField(last_jx, last_jy);
4023 DrawLevelField(last_jx, last_jy);
4026 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
4027 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4030 if (!IN_SCR_FIELD(sx, sy))
4033 /* ----------------------------------------------------------------------- */
4034 /* draw things behind the player, if needed */
4035 /* ----------------------------------------------------------------------- */
4038 DrawLevelElement(jx, jy, Back[jx][jy]);
4039 else if (IS_ACTIVE_BOMB(element))
4040 DrawLevelElement(jx, jy, EL_EMPTY);
4043 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
4045 int old_element = GfxElement[jx][jy];
4046 int old_graphic = el_act_dir2img(old_element, action, move_dir);
4047 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
4049 if (GFX_CRUMBLED(old_element))
4050 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
4052 DrawGraphic(sx, sy, old_graphic, frame);
4054 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
4055 player_is_opaque = TRUE;
4059 GfxElement[jx][jy] = EL_UNDEFINED;
4061 /* make sure that pushed elements are drawn with correct frame rate */
4063 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4065 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
4066 GfxFrame[jx][jy] = player->StepFrame;
4068 if (player->is_pushing && player->is_moving)
4069 GfxFrame[jx][jy] = player->StepFrame;
4072 DrawLevelField(jx, jy);
4076 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
4077 /* ----------------------------------------------------------------------- */
4078 /* draw player himself */
4079 /* ----------------------------------------------------------------------- */
4081 graphic = getPlayerGraphic(player, move_dir);
4083 /* in the case of changed player action or direction, prevent the current
4084 animation frame from being restarted for identical animations */
4085 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4086 player->Frame = last_player_frame;
4088 frame = getGraphicAnimationFrame(graphic, player->Frame);
4092 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4093 sxx = player->GfxPos;
4095 syy = player->GfxPos;
4098 if (!setup.soft_scrolling && ScreenMovPos)
4101 if (player_is_opaque)
4102 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4104 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4106 if (SHIELD_ON(player))
4108 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4109 IMG_SHIELD_NORMAL_ACTIVE);
4110 int frame = getGraphicAnimationFrame(graphic, -1);
4112 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4116 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4119 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4120 sxx = player->GfxPos;
4122 syy = player->GfxPos;
4126 /* ----------------------------------------------------------------------- */
4127 /* draw things the player is pushing, if needed */
4128 /* ----------------------------------------------------------------------- */
4131 printf("::: %d, %d [%d, %d] [%d]\n",
4132 player->is_pushing, player_is_moving, player->GfxAction,
4133 player->is_moving, player_is_moving);
4137 if (player->is_pushing && player->is_moving)
4139 int px = SCREENX(jx), py = SCREENY(jy);
4140 int pxx = (TILEX - ABS(sxx)) * dx;
4141 int pyy = (TILEY - ABS(syy)) * dy;
4142 int gfx_frame = GfxFrame[jx][jy];
4148 if (!IS_MOVING(jx, jy)) /* push movement already finished */
4150 element = Feld[next_jx][next_jy];
4151 gfx_frame = GfxFrame[next_jx][next_jy];
4154 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4157 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
4158 frame = getGraphicAnimationFrame(graphic, sync_frame);
4160 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
4163 /* draw background element under pushed element (like the Sokoban field) */
4165 if (game.use_masked_pushing && IS_MOVING(jx, jy))
4167 /* this allows transparent pushing animation over non-black background */
4170 DrawLevelElement(jx, jy, Back[jx][jy]);
4172 DrawLevelElement(jx, jy, EL_EMPTY);
4174 if (Back[next_jx][next_jy])
4175 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4177 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4179 else if (Back[next_jx][next_jy])
4180 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4182 if (Back[next_jx][next_jy])
4183 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4187 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
4188 jx, px, player->GfxPos, player->StepFrame,
4193 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
4197 /* do not draw (EM style) pushing animation when pushing is finished */
4198 /* (two-tile animations usually do not contain start and end frame) */
4199 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
4200 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
4202 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4204 /* masked drawing is needed for EMC style (double) movement graphics */
4205 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
4206 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4211 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4212 /* ----------------------------------------------------------------------- */
4213 /* draw player himself */
4214 /* ----------------------------------------------------------------------- */
4216 graphic = getPlayerGraphic(player, move_dir);
4218 /* in the case of changed player action or direction, prevent the current
4219 animation frame from being restarted for identical animations */
4220 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4221 player->Frame = last_player_frame;
4223 frame = getGraphicAnimationFrame(graphic, player->Frame);
4227 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4228 sxx = player->GfxPos;
4230 syy = player->GfxPos;
4233 if (!setup.soft_scrolling && ScreenMovPos)
4236 if (player_is_opaque)
4237 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4239 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4241 if (SHIELD_ON(player))
4243 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4244 IMG_SHIELD_NORMAL_ACTIVE);
4245 int frame = getGraphicAnimationFrame(graphic, -1);
4247 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4251 /* ----------------------------------------------------------------------- */
4252 /* draw things in front of player (active dynamite or dynabombs) */
4253 /* ----------------------------------------------------------------------- */
4255 if (IS_ACTIVE_BOMB(element))
4257 graphic = el2img(element);
4258 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
4260 if (game.emulation == EMU_SUPAPLEX)
4261 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
4263 DrawGraphicThruMask(sx, sy, graphic, frame);
4266 if (player_is_moving && last_element == EL_EXPLOSION)
4268 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
4269 GfxElement[last_jx][last_jy] : EL_EMPTY);
4270 int graphic = el_act2img(element, ACTION_EXPLODING);
4271 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
4272 int phase = ExplodePhase[last_jx][last_jy] - 1;
4273 int frame = getGraphicAnimationFrame(graphic, phase - delay);
4276 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
4279 /* ----------------------------------------------------------------------- */
4280 /* draw elements the player is just walking/passing through/under */
4281 /* ----------------------------------------------------------------------- */
4283 if (player_is_moving)
4285 /* handle the field the player is leaving ... */
4286 if (IS_ACCESSIBLE_INSIDE(last_element))
4287 DrawLevelField(last_jx, last_jy);
4288 else if (IS_ACCESSIBLE_UNDER(last_element))
4289 DrawLevelFieldThruMask(last_jx, last_jy);
4292 /* do not redraw accessible elements if the player is just pushing them */
4293 if (!player_is_moving || !player->is_pushing)
4295 /* ... and the field the player is entering */
4296 if (IS_ACCESSIBLE_INSIDE(element))
4297 DrawLevelField(jx, jy);
4298 else if (IS_ACCESSIBLE_UNDER(element))
4299 DrawLevelFieldThruMask(jx, jy);
4302 MarkTileDirty(sx, sy);
4305 /* ------------------------------------------------------------------------- */
4307 void WaitForEventToContinue()
4309 boolean still_wait = TRUE;
4311 /* simulate releasing mouse button over last gadget, if still pressed */
4313 HandleGadgets(-1, -1, 0);
4315 button_status = MB_RELEASED;
4331 case EVENT_BUTTONPRESS:
4332 case EVENT_KEYPRESS:
4336 case EVENT_KEYRELEASE:
4337 ClearPlayerAction();
4341 HandleOtherEvents(&event);
4345 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4352 /* don't eat all CPU time */
4357 #define MAX_REQUEST_LINES 13
4358 #define MAX_REQUEST_LINE_FONT1_LEN 7
4359 #define MAX_REQUEST_LINE_FONT2_LEN 10
4363 static int RequestHandleEvents(unsigned int req_state)
4365 int last_game_status = game_status; /* save current game status */
4369 button_status = MB_RELEASED;
4371 request_gadget_id = -1;
4384 case EVENT_BUTTONPRESS:
4385 case EVENT_BUTTONRELEASE:
4386 case EVENT_MOTIONNOTIFY:
4388 if (event.type == EVENT_MOTIONNOTIFY)
4390 if (!PointerInWindow(window))
4391 continue; /* window and pointer are on different screens */
4396 motion_status = TRUE;
4397 mx = ((MotionEvent *) &event)->x;
4398 my = ((MotionEvent *) &event)->y;
4402 motion_status = FALSE;
4403 mx = ((ButtonEvent *) &event)->x;
4404 my = ((ButtonEvent *) &event)->y;
4405 if (event.type == EVENT_BUTTONPRESS)
4406 button_status = ((ButtonEvent *) &event)->button;
4408 button_status = MB_RELEASED;
4411 /* this sets 'request_gadget_id' */
4412 HandleGadgets(mx, my, button_status);
4414 switch (request_gadget_id)
4416 case TOOL_CTRL_ID_YES:
4419 case TOOL_CTRL_ID_NO:
4422 case TOOL_CTRL_ID_CONFIRM:
4423 result = TRUE | FALSE;
4426 case TOOL_CTRL_ID_PLAYER_1:
4429 case TOOL_CTRL_ID_PLAYER_2:
4432 case TOOL_CTRL_ID_PLAYER_3:
4435 case TOOL_CTRL_ID_PLAYER_4:
4446 case EVENT_KEYPRESS:
4447 switch (GetEventKey((KeyEvent *)&event, TRUE))
4450 if (req_state & REQ_CONFIRM)
4459 #if defined(TARGET_SDL2)
4469 if (req_state & REQ_PLAYER)
4473 case EVENT_KEYRELEASE:
4474 ClearPlayerAction();
4478 HandleOtherEvents(&event);
4482 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4484 int joy = AnyJoystick();
4486 if (joy & JOY_BUTTON_1)
4488 else if (joy & JOY_BUTTON_2)
4494 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4496 HandleGameActions();
4502 if (!PendingEvent()) /* delay only if no pending events */
4507 game_status = GAME_MODE_PSEUDO_DOOR;
4513 game_status = last_game_status; /* restore current game status */
4521 if (!PendingEvent()) /* delay only if no pending events */
4524 /* don't eat all CPU time */
4534 static boolean RequestDoor(char *text, unsigned int req_state)
4536 unsigned int old_door_state;
4537 int last_game_status = game_status; /* save current game status */
4538 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4539 int font_nr = FONT_TEXT_2;
4544 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4546 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4547 font_nr = FONT_TEXT_1;
4550 if (game_status == GAME_MODE_PLAYING)
4552 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4553 BlitScreenToBitmap_EM(backbuffer);
4554 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4555 BlitScreenToBitmap_SP(backbuffer);
4558 /* disable deactivated drawing when quick-loading level tape recording */
4559 if (tape.playing && tape.deactivate_display)
4560 TapeDeactivateDisplayOff(TRUE);
4562 SetMouseCursor(CURSOR_DEFAULT);
4564 #if defined(NETWORK_AVALIABLE)
4565 /* pause network game while waiting for request to answer */
4566 if (options.network &&
4567 game_status == GAME_MODE_PLAYING &&
4568 req_state & REQUEST_WAIT_FOR_INPUT)
4569 SendToServer_PausePlaying();
4572 old_door_state = GetDoorState();
4574 /* simulate releasing mouse button over last gadget, if still pressed */
4576 HandleGadgets(-1, -1, 0);
4580 /* draw released gadget before proceeding */
4583 if (old_door_state & DOOR_OPEN_1)
4585 CloseDoor(DOOR_CLOSE_1);
4587 /* save old door content */
4589 BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
4590 0 * DXSIZE, 0, DXSIZE, DYSIZE, 1 * DXSIZE, 0);
4592 BlitBitmap(bitmap_db_door, bitmap_db_door,
4593 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4594 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4598 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4599 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4601 /* clear door drawing field */
4602 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4604 /* force DOOR font inside door area */
4605 game_status = GAME_MODE_PSEUDO_DOOR;
4607 /* write text for request */
4608 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4610 char text_line[max_request_line_len + 1];
4616 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4618 tc = *(text_ptr + tx);
4619 // if (!tc || tc == ' ')
4620 if (!tc || tc == ' ' || tc == '?' || tc == '!')
4624 if ((tc == '?' || tc == '!') && tl == 0)
4634 strncpy(text_line, text_ptr, tl);
4637 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4638 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4639 text_line, font_nr);
4641 text_ptr += tl + (tc == ' ' ? 1 : 0);
4642 // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
4645 game_status = last_game_status; /* restore current game status */
4647 if (req_state & REQ_ASK)
4649 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4650 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4652 else if (req_state & REQ_CONFIRM)
4654 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4656 else if (req_state & REQ_PLAYER)
4658 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4659 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4660 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4661 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4664 /* copy request gadgets to door backbuffer */
4666 BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
4668 BlitBitmap(drawto, bitmap_db_door,
4669 DX, DY, DXSIZE, DYSIZE,
4670 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4673 OpenDoor(DOOR_OPEN_1);
4675 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4677 if (game_status == GAME_MODE_PLAYING)
4679 SetPanelBackground();
4680 SetDrawBackgroundMask(REDRAW_DOOR_1);
4684 SetDrawBackgroundMask(REDRAW_FIELD);
4690 if (game_status != GAME_MODE_MAIN)
4693 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4695 // ---------- handle request buttons ----------
4696 result = RequestHandleEvents(req_state);
4698 if (game_status != GAME_MODE_MAIN)
4703 if (!(req_state & REQ_STAY_OPEN))
4705 CloseDoor(DOOR_CLOSE_1);
4707 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4708 (req_state & REQ_REOPEN))
4709 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4714 if (game_status == GAME_MODE_PLAYING)
4716 SetPanelBackground();
4717 SetDrawBackgroundMask(REDRAW_DOOR_1);
4721 SetDrawBackgroundMask(REDRAW_FIELD);
4724 #if defined(NETWORK_AVALIABLE)
4725 /* continue network game after request */
4726 if (options.network &&
4727 game_status == GAME_MODE_PLAYING &&
4728 req_state & REQUEST_WAIT_FOR_INPUT)
4729 SendToServer_ContinuePlaying();
4732 /* restore deactivated drawing when quick-loading level tape recording */
4733 if (tape.playing && tape.deactivate_display)
4734 TapeDeactivateDisplayOn();
4739 static boolean RequestEnvelope(char *text, unsigned int req_state)
4746 if (game_status == GAME_MODE_PLAYING)
4748 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4749 BlitScreenToBitmap_EM(backbuffer);
4750 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4751 BlitScreenToBitmap_SP(backbuffer);
4754 /* disable deactivated drawing when quick-loading level tape recording */
4755 if (tape.playing && tape.deactivate_display)
4756 TapeDeactivateDisplayOff(TRUE);
4758 SetMouseCursor(CURSOR_DEFAULT);
4760 #if defined(NETWORK_AVALIABLE)
4761 /* pause network game while waiting for request to answer */
4762 if (options.network &&
4763 game_status == GAME_MODE_PLAYING &&
4764 req_state & REQUEST_WAIT_FOR_INPUT)
4765 SendToServer_PausePlaying();
4768 /* simulate releasing mouse button over last gadget, if still pressed */
4770 HandleGadgets(-1, -1, 0);
4774 // (replace with setting corresponding request background)
4775 // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4776 // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4778 /* clear door drawing field */
4779 // DrawBackground(DX, DY, DXSIZE, DYSIZE);
4782 if (global.use_envelope_request)
4786 CreateToolButtons();
4792 if (req_state & REQ_ASK)
4794 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_YES], FALSE);
4795 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_NO], FALSE);
4797 else if (req_state & REQ_CONFIRM)
4799 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_CONFIRM], FALSE);
4801 else if (req_state & REQ_PLAYER)
4803 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_1], FALSE);
4804 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_2], FALSE);
4805 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_3], FALSE);
4806 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_4], FALSE);
4809 if (req_state & REQ_ASK)
4811 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4812 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4814 else if (req_state & REQ_CONFIRM)
4816 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4818 else if (req_state & REQ_PLAYER)
4820 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4821 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4822 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4823 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4828 ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
4831 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4833 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4834 i == TOOL_CTRL_ID_NO)) ||
4835 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4836 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4837 i == TOOL_CTRL_ID_PLAYER_2 &&
4838 i == TOOL_CTRL_ID_PLAYER_3 &&
4839 i == TOOL_CTRL_ID_PLAYER_4)))
4841 int x = tool_gadget[i]->x + dDX;
4842 int y = tool_gadget[i]->y + dDY;
4844 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4849 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4851 if (game_status == GAME_MODE_PLAYING)
4853 SetPanelBackground();
4854 SetDrawBackgroundMask(REDRAW_DOOR_1);
4858 SetDrawBackgroundMask(REDRAW_FIELD);
4865 if (game_status != GAME_MODE_MAIN)
4869 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4871 // ---------- handle request buttons ----------
4872 result = RequestHandleEvents(req_state);
4874 if (game_status != GAME_MODE_MAIN)
4879 ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
4883 if (game_status == GAME_MODE_PLAYING)
4885 SetPanelBackground();
4886 SetDrawBackgroundMask(REDRAW_DOOR_1);
4890 SetDrawBackgroundMask(REDRAW_FIELD);
4893 #if defined(NETWORK_AVALIABLE)
4894 /* continue network game after request */
4895 if (options.network &&
4896 game_status == GAME_MODE_PLAYING &&
4897 req_state & REQUEST_WAIT_FOR_INPUT)
4898 SendToServer_ContinuePlaying();
4901 /* restore deactivated drawing when quick-loading level tape recording */
4902 if (tape.playing && tape.deactivate_display)
4903 TapeDeactivateDisplayOn();
4908 boolean Request(char *text, unsigned int req_state)
4910 if (global.use_envelope_request)
4911 return RequestEnvelope(text, req_state);
4913 return RequestDoor(text, req_state);
4916 #else // =====================================================================
4918 boolean Request(char *text, unsigned int req_state)
4920 int mx, my, ty, result = -1;
4921 unsigned int old_door_state;
4922 int last_game_status = game_status; /* save current game status */
4923 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4924 int font_nr = FONT_TEXT_2;
4926 int max_word_len = 0;
4932 global.use_envelope_request = 1;
4936 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4938 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4939 font_nr = FONT_TEXT_1;
4942 for (text_ptr = text; *text_ptr; text_ptr++)
4944 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
4946 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
4948 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4950 font_nr = FONT_TEXT_1;
4952 font_nr = FONT_LEVEL_NUMBER;
4960 if (game_status == GAME_MODE_PLAYING)
4962 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4963 BlitScreenToBitmap_EM(backbuffer);
4964 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4965 BlitScreenToBitmap_SP(backbuffer);
4968 /* disable deactivated drawing when quick-loading level tape recording */
4969 if (tape.playing && tape.deactivate_display)
4970 TapeDeactivateDisplayOff(TRUE);
4972 SetMouseCursor(CURSOR_DEFAULT);
4974 #if defined(NETWORK_AVALIABLE)
4975 /* pause network game while waiting for request to answer */
4976 if (options.network &&
4977 game_status == GAME_MODE_PLAYING &&
4978 req_state & REQUEST_WAIT_FOR_INPUT)
4979 SendToServer_PausePlaying();
4982 old_door_state = GetDoorState();
4984 /* simulate releasing mouse button over last gadget, if still pressed */
4986 HandleGadgets(-1, -1, 0);
4990 /* draw released gadget before proceeding */
4994 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
4996 if (old_door_state & DOOR_OPEN_1)
5000 if (!global.use_envelope_request)
5001 CloseDoor(DOOR_CLOSE_1);
5003 CloseDoor(DOOR_CLOSE_1);
5006 /* save old door content */
5007 BlitBitmap(bitmap_db_door, bitmap_db_door,
5008 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5009 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
5013 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
5016 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5018 /* clear door drawing field */
5019 DrawBackground(DX, DY, DXSIZE, DYSIZE);
5021 /* force DOOR font inside door area */
5022 game_status = GAME_MODE_PSEUDO_DOOR;
5024 /* write text for request */
5025 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
5027 char text_line[max_request_line_len + 1];
5033 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
5035 tc = *(text_ptr + tx);
5036 if (!tc || tc == ' ')
5047 strncpy(text_line, text_ptr, tl);
5050 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
5051 DY + 8 + ty * (getFontHeight(font_nr) + 2),
5052 text_line, font_nr);
5054 text_ptr += tl + (tc == ' ' ? 1 : 0);
5057 game_status = last_game_status; /* restore current game status */
5060 if (global.use_envelope_request)
5064 CreateToolButtons();
5068 if (req_state & REQ_ASK)
5070 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
5071 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
5073 else if (req_state & REQ_CONFIRM)
5075 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
5077 else if (req_state & REQ_PLAYER)
5079 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
5080 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
5081 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
5082 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
5085 /* copy request gadgets to door backbuffer */
5086 BlitBitmap(drawto, bitmap_db_door,
5087 DX, DY, DXSIZE, DYSIZE,
5088 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5091 if (global.use_envelope_request)
5093 ShowEnvelopeRequest(text, ACTION_OPENING);
5095 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
5097 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
5098 i == TOOL_CTRL_ID_NO)) ||
5099 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
5100 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
5101 i == TOOL_CTRL_ID_PLAYER_2 &&
5102 i == TOOL_CTRL_ID_PLAYER_3 &&
5103 i == TOOL_CTRL_ID_PLAYER_4)))
5105 int x = tool_gadget[i]->x + dDX;
5106 int y = tool_gadget[i]->y + dDY;
5108 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
5115 if (!global.use_envelope_request)
5116 OpenDoor(DOOR_OPEN_1);
5118 OpenDoor(DOOR_OPEN_1);
5121 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
5123 if (game_status == GAME_MODE_PLAYING)
5125 SetPanelBackground();
5126 SetDrawBackgroundMask(REDRAW_DOOR_1);
5130 SetDrawBackgroundMask(REDRAW_FIELD);
5137 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
5140 if (game_status != GAME_MODE_MAIN)
5144 button_status = MB_RELEASED;
5146 request_gadget_id = -1;
5148 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5160 case EVENT_BUTTONPRESS:
5161 case EVENT_BUTTONRELEASE:
5162 case EVENT_MOTIONNOTIFY:
5164 if (event.type == EVENT_MOTIONNOTIFY)
5166 if (!PointerInWindow(window))
5167 continue; /* window and pointer are on different screens */
5172 motion_status = TRUE;
5173 mx = ((MotionEvent *) &event)->x;
5174 my = ((MotionEvent *) &event)->y;
5178 motion_status = FALSE;
5179 mx = ((ButtonEvent *) &event)->x;
5180 my = ((ButtonEvent *) &event)->y;
5181 if (event.type == EVENT_BUTTONPRESS)
5182 button_status = ((ButtonEvent *) &event)->button;
5184 button_status = MB_RELEASED;
5187 /* this sets 'request_gadget_id' */
5188 HandleGadgets(mx, my, button_status);
5190 switch (request_gadget_id)
5192 case TOOL_CTRL_ID_YES:
5195 case TOOL_CTRL_ID_NO:
5198 case TOOL_CTRL_ID_CONFIRM:
5199 result = TRUE | FALSE;
5202 case TOOL_CTRL_ID_PLAYER_1:
5205 case TOOL_CTRL_ID_PLAYER_2:
5208 case TOOL_CTRL_ID_PLAYER_3:
5211 case TOOL_CTRL_ID_PLAYER_4:
5222 case EVENT_KEYPRESS:
5223 switch (GetEventKey((KeyEvent *)&event, TRUE))
5226 if (req_state & REQ_CONFIRM)
5235 #if defined(TARGET_SDL2)
5245 if (req_state & REQ_PLAYER)
5249 case EVENT_KEYRELEASE:
5250 ClearPlayerAction();
5254 HandleOtherEvents(&event);
5258 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
5260 int joy = AnyJoystick();
5262 if (joy & JOY_BUTTON_1)
5264 else if (joy & JOY_BUTTON_2)
5270 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
5272 HandleGameActions();
5278 if (!PendingEvent()) /* delay only if no pending events */
5283 game_status = GAME_MODE_PSEUDO_DOOR;
5289 game_status = last_game_status; /* restore current game status */
5297 if (!PendingEvent()) /* delay only if no pending events */
5300 /* don't eat all CPU time */
5307 if (game_status != GAME_MODE_MAIN)
5313 if (global.use_envelope_request)
5314 ShowEnvelopeRequest(text, ACTION_CLOSING);
5318 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
5320 if (!(req_state & REQ_STAY_OPEN))
5323 CloseDoor(DOOR_CLOSE_1);
5325 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
5326 (req_state & REQ_REOPEN))
5327 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
5332 if (game_status == GAME_MODE_PLAYING)
5334 SetPanelBackground();
5335 SetDrawBackgroundMask(REDRAW_DOOR_1);
5339 SetDrawBackgroundMask(REDRAW_FIELD);
5342 #if defined(NETWORK_AVALIABLE)
5343 /* continue network game after request */
5344 if (options.network &&
5345 game_status == GAME_MODE_PLAYING &&
5346 req_state & REQUEST_WAIT_FOR_INPUT)
5347 SendToServer_ContinuePlaying();
5350 /* restore deactivated drawing when quick-loading level tape recording */
5351 if (tape.playing && tape.deactivate_display)
5352 TapeDeactivateDisplayOn();
5359 static int compareDoorPartOrderInfo(const void *object1, const void *object2)
5361 const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
5362 const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
5365 if (dpo1->sort_priority != dpo2->sort_priority)
5366 compare_result = dpo1->sort_priority - dpo2->sort_priority;
5368 compare_result = dpo1->nr - dpo2->nr;
5370 return compare_result;
5373 void InitGraphicCompatibilityInfo_Doors()
5379 struct DoorInfo *door;
5383 { DOOR_1, IMG_DOOR_1_GFX_PART_1, IMG_DOOR_1_GFX_PART_8, &door_1 },
5384 { DOOR_2, IMG_DOOR_2_GFX_PART_1, IMG_DOOR_2_GFX_PART_8, &door_2 },
5386 { -1, -1, -1, NULL }
5388 struct Rect door_rect_list[] =
5390 { DX, DY, DXSIZE, DYSIZE },
5391 { VX, VY, VXSIZE, VYSIZE }
5395 for (i = 0; doors[i].door_token != -1; i++)
5397 int door_token = doors[i].door_token;
5398 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5399 int part_1 = doors[i].part_1;
5400 int part_8 = doors[i].part_8;
5401 int part_2 = part_1 + 1;
5402 int part_3 = part_1 + 2;
5403 struct DoorInfo *door = doors[i].door;
5404 struct Rect *door_rect = &door_rect_list[door_index];
5405 boolean door_gfx_redefined = FALSE;
5407 /* check if any door part graphic definitions have been redefined */
5409 for (j = 0; door_part_controls[j].door_token != -1; j++)
5411 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5412 struct FileInfo *fi = getImageListEntryFromImageID(dpc->graphic);
5414 if (dpc->door_token == door_token && fi->redefined)
5415 door_gfx_redefined = TRUE;
5418 /* check for old-style door graphic/animation modifications */
5420 if (!door_gfx_redefined)
5422 if (door->anim_mode & ANIM_STATIC_PANEL)
5424 door->panel.step_xoffset = 0;
5425 door->panel.step_yoffset = 0;
5428 if (door->anim_mode & (ANIM_HORIZONTAL | ANIM_VERTICAL))
5430 struct GraphicInfo *g_part_1 = &graphic_info[part_1];
5431 struct GraphicInfo *g_part_2 = &graphic_info[part_2];
5432 int num_door_steps, num_panel_steps;
5434 /* remove door part graphics other than the two default wings */
5436 for (j = 0; door_part_controls[j].door_token != -1; j++)
5438 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5439 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5441 if (dpc->graphic >= part_3 &&
5442 dpc->graphic <= part_8)
5446 /* set graphics and screen positions of the default wings */
5448 g_part_1->width = door_rect->width;
5449 g_part_1->height = door_rect->height;
5450 g_part_2->width = door_rect->width;
5451 g_part_2->height = door_rect->height;
5452 g_part_2->src_x = door_rect->width;
5453 g_part_2->src_y = g_part_1->src_y;
5455 door->part_2.x = door->part_1.x;
5456 door->part_2.y = door->part_1.y;
5458 if (door->width != -1)
5460 g_part_1->width = door->width;
5461 g_part_2->width = door->width;
5463 // special treatment for graphics and screen position of right wing
5464 g_part_2->src_x += door_rect->width - door->width;
5465 door->part_2.x += door_rect->width - door->width;
5468 if (door->height != -1)
5470 g_part_1->height = door->height;
5471 g_part_2->height = door->height;
5473 // special treatment for graphics and screen position of bottom wing
5474 g_part_2->src_y += door_rect->height - door->height;
5475 door->part_2.y += door_rect->height - door->height;
5478 /* set animation delays for the default wings and panels */
5480 door->part_1.step_delay = door->step_delay;
5481 door->part_2.step_delay = door->step_delay;
5482 door->panel.step_delay = door->step_delay;
5484 /* set animation draw order for the default wings */
5486 door->part_1.sort_priority = 2; /* draw left wing over ... */
5487 door->part_2.sort_priority = 1; /* ... right wing */
5489 /* set animation draw offset for the default wings */
5491 if (door->anim_mode & ANIM_HORIZONTAL)
5493 door->part_1.step_xoffset = door->step_offset;
5494 door->part_1.step_yoffset = 0;
5495 door->part_2.step_xoffset = door->step_offset * -1;
5496 door->part_2.step_yoffset = 0;
5498 num_door_steps = g_part_1->width / door->step_offset;
5500 else // ANIM_VERTICAL
5502 door->part_1.step_xoffset = 0;
5503 door->part_1.step_yoffset = door->step_offset;
5504 door->part_2.step_xoffset = 0;
5505 door->part_2.step_yoffset = door->step_offset * -1;
5507 num_door_steps = g_part_1->height / door->step_offset;
5510 /* set animation draw offset for the default panels */
5512 if (door->step_offset > 1)
5514 num_panel_steps = 2 * door_rect->height / door->step_offset;
5515 door->panel.start_step = num_panel_steps - num_door_steps;
5519 num_panel_steps = door_rect->height / door->step_offset;
5520 door->panel.start_step = num_panel_steps - num_door_steps / 2;
5521 door->panel.step_delay *= 2;
5532 for (i = 0; door_part_controls[i].door_token != -1; i++)
5534 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5535 struct DoorPartOrderInfo *dpo = &door_part_order[i];
5537 /* initialize "start_step_opening" and "start_step_closing", if needed */
5538 if (dpc->pos->start_step_opening == 0 &&
5539 dpc->pos->start_step_closing == 0)
5541 // dpc->pos->start_step_opening = dpc->pos->start_step;
5542 dpc->pos->start_step_closing = dpc->pos->start_step;
5545 /* fill structure for door part draw order (sorted below) */
5547 dpo->sort_priority = dpc->pos->sort_priority;
5550 struct DoorPartPosInfo *pos = dpc->pos;
5552 printf(":0: step_xoffset == %d, step_yoffset == %d\n",
5553 pos->step_xoffset, pos->step_yoffset);
5557 /* sort door part controls according to sort_priority and graphic number */
5558 qsort(door_part_order, MAX_DOOR_PARTS,
5559 sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
5562 unsigned int OpenDoor(unsigned int door_state)
5564 if (door_state & DOOR_COPY_BACK)
5567 if (door_state & DOOR_OPEN_1)
5568 BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
5569 1 * DXSIZE, 0, DXSIZE, DYSIZE, 0 * DXSIZE, 0);
5571 if (door_state & DOOR_OPEN_2)
5572 BlitBitmap(bitmap_db_door_2, bitmap_db_door_2,
5573 1 * VXSIZE, 0, VXSIZE, VYSIZE, 0 * VXSIZE, 0);
5575 if (door_state & DOOR_OPEN_1)
5576 BlitBitmap(bitmap_db_door, bitmap_db_door,
5577 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5578 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5580 if (door_state & DOOR_OPEN_2)
5581 BlitBitmap(bitmap_db_door, bitmap_db_door,
5582 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
5583 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5586 door_state &= ~DOOR_COPY_BACK;
5589 return MoveDoor(door_state);
5592 unsigned int CloseDoor(unsigned int door_state)
5594 unsigned int old_door_state = GetDoorState();
5596 if (!(door_state & DOOR_NO_COPY_BACK))
5599 if (old_door_state & DOOR_OPEN_1)
5600 BlitBitmap(backbuffer, bitmap_db_door_1,
5601 DX, DY, DXSIZE, DYSIZE, 0, 0);
5603 if (old_door_state & DOOR_OPEN_2)
5604 BlitBitmap(backbuffer, bitmap_db_door_2,
5605 VX, VY, VXSIZE, VYSIZE, 0, 0);
5607 if (old_door_state & DOOR_OPEN_1)
5608 BlitBitmap(backbuffer, bitmap_db_door,
5609 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5611 if (old_door_state & DOOR_OPEN_2)
5612 BlitBitmap(backbuffer, bitmap_db_door,
5613 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5616 door_state &= ~DOOR_NO_COPY_BACK;
5619 return MoveDoor(door_state);
5622 unsigned int GetDoorState()
5624 return MoveDoor(DOOR_GET_STATE);
5627 unsigned int SetDoorState(unsigned int door_state)
5629 return MoveDoor(door_state | DOOR_SET_STATE);
5634 // ========== TEST 1 ===========================================================
5636 int euclid(int a, int b)
5638 return (b ? euclid(b, a % b) : a);
5641 unsigned int MoveDoor(unsigned int door_state)
5644 struct XY panel_pos_list[] =
5646 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 },
5647 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 },
5650 struct Rect door_rect_list[] =
5652 { DX, DY, DXSIZE, DYSIZE },
5653 { VX, VY, VXSIZE, VYSIZE }
5655 static int door1 = DOOR_OPEN_1;
5656 static int door2 = DOOR_CLOSE_2;
5657 unsigned int door_delay = 0;
5658 unsigned int door_delay_value;
5662 if (door_1.width < 0 || door_1.width > DXSIZE)
5663 door_1.width = DXSIZE;
5664 if (door_1.height < 0 || door_1.height > DYSIZE)
5665 door_1.height = DYSIZE;
5666 if (door_2.width < 0 || door_2.width > VXSIZE)
5667 door_2.width = VXSIZE;
5668 if (door_2.height < 0 || door_2.height > VYSIZE)
5669 door_2.height = VYSIZE;
5672 if (door_state == DOOR_GET_STATE)
5673 return (door1 | door2);
5675 if (door_state & DOOR_SET_STATE)
5677 if (door_state & DOOR_ACTION_1)
5678 door1 = door_state & DOOR_ACTION_1;
5679 if (door_state & DOOR_ACTION_2)
5680 door2 = door_state & DOOR_ACTION_2;
5682 return (door1 | door2);
5685 if (!(door_state & DOOR_FORCE_REDRAW))
5687 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
5688 door_state &= ~DOOR_OPEN_1;
5689 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
5690 door_state &= ~DOOR_CLOSE_1;
5691 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
5692 door_state &= ~DOOR_OPEN_2;
5693 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
5694 door_state &= ~DOOR_CLOSE_2;
5698 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
5701 if (setup.quick_doors)
5703 stepsize = 20; /* must be chosen to always draw last frame */
5704 door_delay_value = 0;
5708 if (global.autoplay_leveldir)
5710 door_state |= DOOR_NO_DELAY;
5711 door_state &= ~DOOR_CLOSE_ALL;
5715 if (game_status == GAME_MODE_EDITOR)
5716 door_state |= DOOR_NO_DELAY;
5719 if (door_state & DOOR_ACTION)
5721 boolean door_panel_drawn[NUM_DOORS];
5722 boolean panel_has_doors[NUM_DOORS];
5723 boolean door_part_skip[MAX_DOOR_PARTS];
5724 boolean door_part_done[MAX_DOOR_PARTS];
5725 boolean door_part_done_all;
5726 int num_steps[MAX_DOOR_PARTS];
5727 int max_move_delay = 0; // delay for complete animations of all doors
5728 int max_step_delay = 0; // delay (ms) between two animation frames
5729 int num_move_steps = 0; // number of animation steps for all doors
5730 int current_move_delay = 0;
5733 for (i = 0; i < NUM_DOORS; i++)
5734 panel_has_doors[i] = FALSE;
5736 for (i = 0; i < MAX_DOOR_PARTS; i++)
5738 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5739 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5740 int door_token = dpc->door_token;
5742 door_part_done[i] = FALSE;
5743 door_part_skip[i] = (!(door_state & door_token) ||
5748 for (i = 0; i < MAX_DOOR_PARTS; i++)
5750 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5751 struct DoorPartPosInfo *pos = dpc->pos;
5752 int start_step = pos->start_step;
5754 printf("::: ---> %d: start_step == %d [%d]\n",
5755 i, start_step, door_part_done[i]);
5759 for (i = 0; i < MAX_DOOR_PARTS; i++)
5761 int nr = door_part_order[i].nr;
5762 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5763 struct DoorPartPosInfo *pos = dpc->pos;
5764 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5765 int door_token = dpc->door_token;
5766 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5767 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5768 int step_xoffset = ABS(pos->step_xoffset);
5769 int step_yoffset = ABS(pos->step_yoffset);
5770 int step_delay = pos->step_delay;
5771 int current_door_state = door_state & door_token;
5772 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5773 boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
5774 boolean part_opening = (is_panel ? door_closing : door_opening);
5775 int start_step = (part_opening ? pos->start_step_opening :
5776 pos->start_step_closing);
5777 float move_xsize = (step_xoffset ? g->width : 0);
5778 float move_ysize = (step_yoffset ? g->height : 0);
5779 int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
5780 int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0);
5781 int move_steps = (move_xsteps && move_ysteps ?
5782 MIN(move_xsteps, move_ysteps) :
5783 move_xsteps ? move_xsteps : move_ysteps) - start_step;
5784 int move_delay = move_steps * step_delay;
5786 if (door_part_skip[nr])
5790 panel_has_doors[door_index] = TRUE;
5792 max_move_delay = MAX(max_move_delay, move_delay);
5793 max_step_delay = (max_step_delay == 0 ? step_delay :
5794 euclid(max_step_delay, step_delay));
5795 num_steps[nr] = move_steps;
5799 printf("::: %d: move_delay == %d, start_step == %d [%d]\n",
5800 i, move_delay, start_step, door_part_order[i].nr);
5802 if (DOOR_PART_IS_PANEL(i))
5803 printf("::: %d: move_delay == %d, start_step == %d\n",
5804 i, move_delay, start_step);
5809 num_move_steps = max_move_delay / max_step_delay;
5811 door_delay_value = max_step_delay;
5814 door_delay_value *= 10;
5818 printf("::: num_move_steps == %d, max_move_delay == %d, max_step_delay == %d\n", num_move_steps, max_move_delay, max_step_delay);
5821 for (k = 0; k < num_move_steps; k++)
5823 door_part_done_all = TRUE;
5825 for (i = 0; i < NUM_DOORS; i++)
5826 door_panel_drawn[i] = FALSE;
5828 for (i = 0; i < MAX_DOOR_PARTS; i++)
5830 int nr = door_part_order[i].nr;
5831 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5832 struct DoorPartPosInfo *pos = dpc->pos;
5833 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5834 int door_token = dpc->door_token;
5835 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5836 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5838 struct XY *panel_pos = &panel_pos_list[door_index];
5840 struct Rect *door_rect = &door_rect_list[door_index];
5841 Bitmap *bitmap_db_door = (door_token == DOOR_1 ? bitmap_db_door_1 :
5843 Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
5844 int current_door_state = door_state & door_token;
5845 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5846 boolean door_closing = !door_opening;
5847 boolean part_opening = (is_panel ? door_closing : door_opening);
5848 boolean part_closing = !part_opening;
5849 int start_step = (part_opening ? pos->start_step_opening :
5850 pos->start_step_closing);
5851 int step_delay = pos->step_delay;
5852 int step_factor = step_delay / max_step_delay;
5853 int k1 = (step_factor ? k / step_factor + 1 : k);
5854 int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
5855 int kk = (k2 < 0 ? 0 : k2);
5856 int src_x, src_y, src_xx, src_yy;
5857 int dst_x, dst_y, dst_xx, dst_yy;
5861 if (k == 0 && is_panel && door_token == DOOR_2)
5862 printf("::: %d, %d\n", g->width, g->height);
5866 if (DOOR_PART_IS_PANEL(nr))
5868 int start_step = pos->start_step;
5870 k2 = (door_closing ? k1 : num_steps[nr] - k1);// - start_step;
5871 kk = (k2 < 0 ? 0 : k2);
5877 if (nr != 16 && nr != 0)
5888 if (door_part_skip[nr])
5892 if (!(door_state & door_token))
5899 if (current_move_delay % step_delay)
5905 if (!door_panel_drawn[door_index])
5908 ClearRectangle(drawto, door_rect->x, door_rect->y,
5909 door_rect->width, door_rect->height);
5911 BlitBitmap(bitmap_db_door, drawto, panel_pos->x, panel_pos->y,
5912 door_rect->width, door_rect->height,
5913 door_rect->x, door_rect->y);
5916 door_panel_drawn[door_index] = TRUE;
5919 // draw opening or closing door parts
5921 if (pos->step_xoffset < 0) // door part on right side
5924 dst_xx = pos->x + ABS(kk * pos->step_xoffset);
5927 if (dst_xx + width > door_rect->width)
5928 width = door_rect->width - dst_xx;
5930 else // door part on left side
5933 dst_xx = pos->x - kk * pos->step_xoffset;
5937 src_xx = ABS(dst_xx);
5941 width = g->width - src_xx;
5943 // printf("::: k == %d [%d] \n", k, start_step);
5946 if (pos->step_yoffset < 0) // door part on bottom side
5949 dst_yy = pos->y + ABS(kk * pos->step_yoffset);
5952 if (dst_yy + height > door_rect->height)
5953 height = door_rect->height - dst_yy;
5955 else // door part on top side
5958 dst_yy = pos->y - kk * pos->step_yoffset;
5962 src_yy = ABS(dst_yy);
5966 height = g->height - src_yy;
5975 src_x = panel_pos->x + src_xx;
5976 src_y = panel_pos->y + src_yy;
5981 src_x = g->src_x + src_xx;
5982 src_y = g->src_y + src_yy;
5985 dst_x = door_rect->x + dst_xx;
5986 dst_y = door_rect->y + dst_yy;
5989 if (DOOR_PART_IS_PANEL(nr))
5991 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
5992 width, height, g->width, g->height, src_x, src_y);
5996 if (width >= 0 && width <= g->width &&
5997 height >= 0 && height <= g->height)
5999 if (is_panel || !pos->draw_masked)
6000 BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
6003 BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height,
6008 if (DOOR_PART_IS_PANEL(nr))
6010 bitmap = bitmap_db_door;
6011 src_x = panel_pos->x + src_xx;
6012 src_y = panel_pos->y + src_yy;
6014 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
6015 width, height, g->width, g->height, src_x, src_y);
6017 if (width >= 0 && width <= g->width &&
6018 height >= 0 && height <= g->height)
6019 BlitBitmap(bitmap, drawto, src_x, src_y,
6025 redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
6028 if ((part_opening && (width < 0 || height < 0)) ||
6029 (part_closing && (width >= g->width && height >= g->height)))
6030 door_part_done[nr] = TRUE;
6032 if ((door_opening && (width < 0 || height < 0)) ||
6033 (door_closing && (width >= g->width && height >= g->height)))
6034 door_part_done[nr] = TRUE;
6038 // continue door part animations, but not panel after door has closed
6039 if (!door_part_done[nr] &&
6040 !(is_panel && door_closing && panel_has_doors[door_index]))
6041 door_part_done_all = FALSE;
6043 // continue door part animations, but not panel after door has closed
6044 if (!door_part_done[nr] && !(is_panel && door_closing))
6045 door_part_done_all = FALSE;
6049 if (!door_part_done[nr])
6050 printf("::: k == %d, nr == %d\n", k, nr);
6054 if (!(door_state & DOOR_NO_DELAY))
6058 if (game_status == GAME_MODE_MAIN)
6061 WaitUntilDelayReached(&door_delay, door_delay_value);
6063 current_move_delay += max_step_delay;
6067 door_part_done_all = TRUE;
6069 for (i = 0; i < MAX_DOOR_PARTS; i++)
6070 if (!door_part_done[i] &&
6071 !(DOOR_PART_IS_PANEL(i) && door_closing))
6072 door_part_done_all = FALSE;
6075 if (door_part_done_all)
6081 if (door_state & DOOR_ACTION_1)
6082 door1 = door_state & DOOR_ACTION_1;
6083 if (door_state & DOOR_ACTION_2)
6084 door2 = door_state & DOOR_ACTION_2;
6087 printf("::: DOORS DONE %08x\n", door_state);
6089 printf("::: GO!\n");
6092 return (door1 | door2);
6097 // ========== OLD ==============================================================
6099 unsigned int MoveDoor(unsigned int door_state)
6101 static int door1 = DOOR_OPEN_1;
6102 static int door2 = DOOR_CLOSE_2;
6103 unsigned int door_delay = 0;
6104 unsigned int door_delay_value;
6108 if (door_1.width < 0 || door_1.width > DXSIZE)
6109 door_1.width = DXSIZE;
6110 if (door_1.height < 0 || door_1.height > DYSIZE)
6111 door_1.height = DYSIZE;
6112 if (door_2.width < 0 || door_2.width > VXSIZE)
6113 door_2.width = VXSIZE;
6114 if (door_2.height < 0 || door_2.height > VYSIZE)
6115 door_2.height = VYSIZE;
6118 if (door_state == DOOR_GET_STATE)
6119 return (door1 | door2);
6121 if (door_state & DOOR_SET_STATE)
6123 if (door_state & DOOR_ACTION_1)
6124 door1 = door_state & DOOR_ACTION_1;
6125 if (door_state & DOOR_ACTION_2)
6126 door2 = door_state & DOOR_ACTION_2;
6128 return (door1 | door2);
6131 if (!(door_state & DOOR_FORCE_REDRAW))
6133 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
6134 door_state &= ~DOOR_OPEN_1;
6135 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
6136 door_state &= ~DOOR_CLOSE_1;
6137 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
6138 door_state &= ~DOOR_OPEN_2;
6139 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
6140 door_state &= ~DOOR_CLOSE_2;
6143 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
6146 // door_delay_value *= 4; // !!! TEST ONLY !!!
6148 if (setup.quick_doors)
6150 stepsize = 20; /* must be chosen to always draw last frame */
6151 door_delay_value = 0;
6154 if (global.autoplay_leveldir)
6156 door_state |= DOOR_NO_DELAY;
6157 door_state &= ~DOOR_CLOSE_ALL;
6161 if (game_status == GAME_MODE_EDITOR)
6162 door_state |= DOOR_NO_DELAY;
6165 if (door_state & DOOR_ACTION)
6168 struct GraphicInfo *g1_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6169 struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6170 struct GraphicInfo *g2_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6171 struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6172 int door_1_left_width = g1_left->width;
6173 int door_1_left_height = g1_left->height;
6174 int door_1_right_width = g1_right->width;
6175 int door_1_right_height = g1_right->height;
6176 int door_2_left_width = g2_left->width;
6177 int door_2_left_height = g2_left->height;
6178 int door_2_right_width = g2_right->width;
6179 int door_2_right_height = g2_right->height;
6180 int door_1_width = MAX(door_1_left_width, door_1_right_width);
6181 int door_1_height = MAX(door_1_left_height, door_1_right_height);
6182 int door_2_width = MAX(door_2_left_width, door_2_right_width);
6183 int door_2_height = MAX(door_2_left_height, door_2_right_height);
6185 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
6186 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
6187 boolean door_1_done = (!handle_door_1);
6188 boolean door_2_done = (!handle_door_2);
6189 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
6190 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
6193 int door_size_1 = (door_1_vertical ? door_1_height : door_1_width);
6194 int door_size_2 = (door_2_vertical ? door_2_height : door_2_width);
6196 int door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6197 int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6200 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
6201 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
6203 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6204 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6205 // int door_size = (handle_door_1 ? door_size_1 : door_size_2);
6206 int door_size = (handle_door_2 ? door_size_2 : door_size_1);
6207 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
6208 int door_skip = max_door_size - door_size;
6209 int end = door_size;
6210 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
6213 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
6215 /* opening door sound has priority over simultaneously closing door */
6216 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
6217 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
6218 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
6219 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
6222 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
6226 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6227 GC gc = bitmap->stored_clip_gc;
6230 if (door_state & DOOR_ACTION_1 &&
6231 x * door_1.step_offset <= door_size_1)
6233 int a = MIN(x * door_1.step_offset, end);
6234 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
6238 int i = p + door_skip;
6242 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6243 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6244 Bitmap *bm_left = g_left->bitmap;
6245 Bitmap *bm_right = g_right->bitmap;
6246 GC gc_left = bm_left->stored_clip_gc;
6247 GC gc_right = bm_right->stored_clip_gc;
6250 int classic_dxsize = 100;
6251 int classic_dysize = 280;
6252 boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
6253 DYSIZE == classic_dysize);
6255 if (door_1.anim_mode & ANIM_STATIC_PANEL)
6257 BlitBitmap(bitmap_db_door, drawto,
6258 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
6259 DXSIZE, DYSIZE, DX, DY);
6263 BlitBitmap(bitmap_db_door, drawto,
6264 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
6265 DXSIZE, DYSIZE - p / 2, DX, DY);
6268 // printf("::: p == %d\n", p);
6269 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
6273 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
6276 int src1_x = g_right->src_x;
6277 int src1_y = g_right->src_y;
6278 int src2_x = g_left->src_x + g_left->width - i;
6279 int src2_y = g_left->src_y;
6280 int dst1_x = DX + DXSIZE - i;
6285 int height = DYSIZE;
6287 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6288 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6291 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6292 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6295 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6296 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6297 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6298 int dst2_x = DX, dst2_y = DY;
6299 int width = i, height = DYSIZE;
6301 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6302 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6305 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6306 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6310 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
6313 int src1_x = g_right->src_x;
6314 int src1_y = g_right->src_y;
6315 int src2_x = g_left->src_x;
6316 int src2_y = g_left->src_y + g_left->height - i;
6318 int dst1_y = DY + DYSIZE - i;
6324 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6325 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6328 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6329 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6332 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6333 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
6334 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
6335 int dst2_x = DX, dst2_y = DY;
6336 int width = DXSIZE, height = i;
6338 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6339 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6342 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6343 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6347 else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */
6349 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
6352 int src1_x = g_right->src_x;
6353 int src1_y = g_right->src_y;
6354 int src2_x = g_left->src_x + g_left->width - i;
6355 int src2_y = g_left->src_y;
6356 int dst1_x = DX + DXSIZE - i;
6361 int height1 = 63, height2 = DYSIZE / 2 - height1;
6362 int ypos1 = 0, ypos2 = height2;
6363 int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
6365 SetClipOrigin(bm_right, gc_right,
6366 dst1_x - src1_x, dst1_y - src1_y + j);
6367 BlitBitmapMasked(bm_right, drawto,
6368 src1_x, src1_y + ypos1, width, height2,
6369 dst1_x, dst1_y + ypos1 + j);
6370 BlitBitmapMasked(bm_right, drawto,
6371 src1_x, src1_y + ypos3, width, height1,
6372 dst1_x, dst1_y + ypos3 + j);
6373 SetClipOrigin(bm_left, gc_left,
6374 dst2_x - src2_x, dst2_y - src2_y - j);
6375 BlitBitmapMasked(bm_left, drawto,
6376 src2_x, src2_y + ypos1 + j, width, height2 - j,
6377 dst2_x, dst2_y + ypos1);
6378 BlitBitmapMasked(bm_left, drawto,
6379 src2_x, src2_y + ypos3, width, height1,
6380 dst2_x, dst2_y + ypos3 - j);
6382 SetClipOrigin(bm_left, gc_left,
6383 dst2_x - src2_x, dst2_y - src2_y - j);
6384 BlitBitmapMasked(bm_left, drawto,
6385 src2_x, src2_y + ypos2, width, height1,
6386 dst2_x, dst2_y + ypos2 - j);
6387 BlitBitmapMasked(bm_left, drawto,
6388 src2_x, src2_y + ypos4, width, height2,
6389 dst2_x, dst2_y + ypos4 - j);
6390 SetClipOrigin(bm_right, gc_right,
6391 dst1_x - src1_x, dst1_y - src1_y + j);
6392 BlitBitmapMasked(bm_right, drawto,
6393 src1_x, src1_y + ypos2, width, height1,
6394 dst1_x, dst1_y + ypos2 + j);
6395 BlitBitmapMasked(bm_right, drawto,
6396 src1_x, src1_y + ypos4, width, height2 - j,
6397 dst1_x, dst1_y + ypos4 + j);
6400 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6401 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6402 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6403 int dst2_x = DX, dst2_y = DY;
6404 int width = i, height = DYSIZE;
6405 int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
6407 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6408 BlitBitmapMasked(bitmap, drawto,
6409 src1_x, src1_y, width, ypos2,
6410 dst1_x, dst1_y + j);
6411 BlitBitmapMasked(bitmap, drawto,
6412 src1_x, src1_y + ypos3, width, ypos1,
6413 dst1_x, dst1_y + ypos3 + j);
6414 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6415 BlitBitmapMasked(bitmap, drawto,
6416 src2_x, src2_y + j, width, ypos2 - j,
6418 BlitBitmapMasked(bitmap, drawto,
6419 src2_x, src2_y + ypos3, width, ypos1,
6420 dst2_x, dst2_y + ypos3 - j);
6422 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6423 BlitBitmapMasked(bitmap, drawto,
6424 src2_x, src2_y + ypos2, width, ypos1,
6425 dst2_x, dst2_y + ypos2 - j);
6426 BlitBitmapMasked(bitmap, drawto,
6427 src2_x, src2_y + ypos4, width, ypos2,
6428 dst2_x, dst2_y + ypos4 - j);
6429 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6430 BlitBitmapMasked(bitmap, drawto,
6431 src1_x, src1_y + ypos2, width, ypos1,
6432 dst1_x, dst1_y + ypos2 + j);
6433 BlitBitmapMasked(bitmap, drawto,
6434 src1_x, src1_y + ypos4, width, ypos2 - j,
6435 dst1_x, dst1_y + ypos4 + j);
6438 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6439 BlitBitmapMasked(bitmap, drawto,
6440 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
6441 DX + DXSIZE - i, DY + j);
6442 BlitBitmapMasked(bitmap, drawto,
6443 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
6444 DX + DXSIZE - i, DY + 140 + j);
6445 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
6446 DY - (DOOR_GFX_PAGEY1 + j));
6447 BlitBitmapMasked(bitmap, drawto,
6448 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
6450 BlitBitmapMasked(bitmap, drawto,
6451 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
6454 BlitBitmapMasked(bitmap, drawto,
6455 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
6457 BlitBitmapMasked(bitmap, drawto,
6458 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
6460 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6461 BlitBitmapMasked(bitmap, drawto,
6462 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
6463 DX + DXSIZE - i, DY + 77 + j);
6464 BlitBitmapMasked(bitmap, drawto,
6465 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
6466 DX + DXSIZE - i, DY + 203 + j);
6471 redraw_mask |= REDRAW_DOOR_1;
6472 door_1_done = (a == end);
6475 if (door_state & DOOR_ACTION_2 &&
6476 x * door_2.step_offset <= door_size_2)
6478 int a = MIN(x * door_2.step_offset, door_size);
6479 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
6480 int i = p + door_skip;
6483 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6484 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6485 Bitmap *bm_left = g_left->bitmap;
6486 Bitmap *bm_right = g_right->bitmap;
6487 GC gc_left = bm_left->stored_clip_gc;
6488 GC gc_right = bm_right->stored_clip_gc;
6491 int classic_vxsize = 100;
6492 int classic_vysize = 100;
6493 boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
6494 VYSIZE == classic_vysize);
6496 if (door_2.anim_mode & ANIM_STATIC_PANEL)
6498 BlitBitmap(bitmap_db_door, drawto,
6499 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
6500 VXSIZE, VYSIZE, VX, VY);
6502 else if (x <= VYSIZE)
6504 BlitBitmap(bitmap_db_door, drawto,
6505 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
6506 VXSIZE, VYSIZE - p / 2, VX, VY);
6508 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
6511 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
6514 int src1_x = g_right->src_x;
6515 int src1_y = g_right->src_y;
6516 int src2_x = g_left->src_x + g_left->width - i;
6517 int src2_y = g_left->src_y;
6518 int dst1_x = VX + VXSIZE - i;
6523 int height = VYSIZE;
6525 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6526 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6529 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6530 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6533 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6534 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6535 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6536 int dst2_x = VX, dst2_y = VY;
6537 int width = i, height = VYSIZE;
6539 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6540 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6543 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6544 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6548 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
6551 int src1_x = g_right->src_x;
6552 int src1_y = g_right->src_y;
6553 int src2_x = g_left->src_x;
6554 int src2_y = g_left->src_y + g_left->height - i;
6556 int dst1_y = VY + VYSIZE - i;
6562 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6563 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6566 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6567 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6570 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6571 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
6572 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
6573 int dst2_x = VX, dst2_y = VY;
6574 int width = VXSIZE, height = i;
6576 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6577 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6580 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6581 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6585 else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */
6587 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
6590 int src1_x = g_right->src_x;
6591 int src1_y = g_right->src_y;
6592 int src2_x = g_left->src_x + g_left->width - i;
6593 int src2_y = g_left->src_y;
6594 int dst1_x = VX + VXSIZE - i;
6599 int height = VYSIZE / 2;
6600 int ypos1 = 0, ypos2 = VYSIZE / 2;
6602 SetClipOrigin(bm_right, gc_right,
6603 dst1_x - src1_x, dst1_y - src1_y + j);
6604 BlitBitmapMasked(bm_right, drawto,
6605 src1_x, src1_y + ypos1, width, height,
6606 dst1_x, dst1_y + ypos1 + j);
6607 SetClipOrigin(bm_left, gc_left,
6608 dst2_x - src2_x, dst2_y - src2_y - j);
6609 BlitBitmapMasked(bm_left, drawto,
6610 src2_x, src2_y + ypos1 + j, width, height - j,
6611 dst2_x, dst2_y + ypos1);
6613 SetClipOrigin(bm_left, gc_left,
6614 dst2_x - src2_x, dst2_y - src2_y - j);
6615 BlitBitmapMasked(bm_left, drawto,
6616 src2_x, src2_y + ypos2, width, height,
6617 dst2_x, dst2_y + ypos2 - j);
6618 SetClipOrigin(bm_right, gc_right,
6619 dst1_x - src1_x, dst1_y - src1_y + j);
6620 BlitBitmapMasked(bm_right, drawto,
6621 src1_x, src1_y + ypos2, width, height - j,
6622 dst1_x, dst1_y + ypos2 + j);
6624 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6625 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6626 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6627 int dst2_x = VX, dst2_y = VY;
6628 int width = i, height = VYSIZE;
6629 int ypos = VYSIZE / 2;
6631 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6632 BlitBitmapMasked(bitmap, drawto,
6633 src1_x, src1_y, width, ypos,
6634 dst1_x, dst1_y + j);
6635 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6636 BlitBitmapMasked(bitmap, drawto,
6637 src2_x, src2_y + j, width, ypos - j,
6640 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6641 BlitBitmapMasked(bitmap, drawto,
6642 src2_x, src2_y + ypos, width, ypos,
6643 dst2_x, dst2_y + ypos - j);
6644 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6645 BlitBitmapMasked(bitmap, drawto,
6646 src1_x, src1_y + ypos, width, ypos - j,
6647 dst1_x, dst1_y + ypos + j);
6650 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6651 BlitBitmapMasked(bitmap, drawto,
6652 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
6653 VX + VXSIZE - i, VY + j);
6654 SetClipOrigin(bitmap, gc,
6655 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
6656 BlitBitmapMasked(bitmap, drawto,
6657 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
6660 BlitBitmapMasked(bitmap, drawto,
6661 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6662 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
6663 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6664 BlitBitmapMasked(bitmap, drawto,
6665 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6667 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
6672 redraw_mask |= REDRAW_DOOR_2;
6673 door_2_done = (a == VXSIZE);
6676 if (!(door_state & DOOR_NO_DELAY))
6680 if (game_status == GAME_MODE_MAIN)
6683 WaitUntilDelayReached(&door_delay, door_delay_value);
6688 if (door_state & DOOR_ACTION_1)
6689 door1 = door_state & DOOR_ACTION_1;
6690 if (door_state & DOOR_ACTION_2)
6691 door2 = door_state & DOOR_ACTION_2;
6693 return (door1 | door2);
6698 void DrawSpecialEditorDoor()
6701 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6702 int top_border_width = gfx1->width;
6703 int top_border_height = gfx1->height;
6704 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6705 int ex = EX - outer_border;
6706 int ey = EY - outer_border;
6707 int vy = VY - outer_border;
6708 int exsize = EXSIZE + 2 * outer_border;
6710 CloseDoor(DOOR_CLOSE_2);
6712 /* draw bigger level editor toolbox window */
6713 BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
6714 top_border_width, top_border_height, ex, ey - top_border_height);
6715 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
6716 exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
6718 /* draw bigger level editor toolbox window */
6719 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
6720 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
6722 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6723 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
6727 redraw_mask |= REDRAW_ALL;
6730 void UndrawSpecialEditorDoor()
6733 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6734 int top_border_width = gfx1->width;
6735 int top_border_height = gfx1->height;
6736 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6737 int ex = EX - outer_border;
6738 int ey = EY - outer_border;
6739 int ey_top = ey - top_border_height;
6740 int exsize = EXSIZE + 2 * outer_border;
6741 int eysize = EYSIZE + 2 * outer_border;
6743 /* draw normal tape recorder window */
6744 if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
6746 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6747 ex, ey_top, top_border_width, top_border_height,
6749 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6750 ex, ey, exsize, eysize, ex, ey);
6754 // if screen background is set to "[NONE]", clear editor toolbox window
6755 ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
6756 ClearRectangle(drawto, ex, ey, exsize, eysize);
6759 /* draw normal tape recorder window */
6760 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6761 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
6765 redraw_mask |= REDRAW_ALL;
6769 /* ---------- new tool button stuff ---------------------------------------- */
6776 struct TextPosInfo *pos;
6779 } toolbutton_info[NUM_TOOL_BUTTONS] =
6782 IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
6783 TOOL_CTRL_ID_YES, "yes"
6786 IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
6787 TOOL_CTRL_ID_NO, "no"
6790 IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
6791 TOOL_CTRL_ID_CONFIRM, "confirm"
6794 IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
6795 TOOL_CTRL_ID_PLAYER_1, "player 1"
6798 IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
6799 TOOL_CTRL_ID_PLAYER_2, "player 2"
6802 IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
6803 TOOL_CTRL_ID_PLAYER_3, "player 3"
6806 IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
6807 TOOL_CTRL_ID_PLAYER_4, "player 4"
6811 void CreateToolButtons()
6815 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6817 struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
6818 struct TextPosInfo *pos = toolbutton_info[i].pos;
6819 struct GadgetInfo *gi;
6820 Bitmap *deco_bitmap = None;
6821 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6822 unsigned int event_mask = GD_EVENT_RELEASED;
6825 int gd_x = gfx->src_x;
6826 int gd_y = gfx->src_y;
6827 int gd_xp = gfx->src_x + gfx->pressed_xoffset;
6828 int gd_yp = gfx->src_y + gfx->pressed_yoffset;
6831 if (global.use_envelope_request)
6832 setRequestPosition(&dx, &dy, TRUE);
6834 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6836 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6838 getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
6839 pos->size, &deco_bitmap, &deco_x, &deco_y);
6840 deco_xpos = (gfx->width - pos->size) / 2;
6841 deco_ypos = (gfx->height - pos->size) / 2;
6844 gi = CreateGadget(GDI_CUSTOM_ID, id,
6845 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6846 GDI_X, dx + GDI_ACTIVE_POS(pos->x),
6847 GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
6848 GDI_WIDTH, gfx->width,
6849 GDI_HEIGHT, gfx->height,
6850 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6851 GDI_STATE, GD_BUTTON_UNPRESSED,
6852 GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
6853 GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
6854 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6855 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6856 GDI_DECORATION_SIZE, pos->size, pos->size,
6857 GDI_DECORATION_SHIFTING, 1, 1,
6858 GDI_DIRECT_DRAW, FALSE,
6859 GDI_EVENT_MASK, event_mask,
6860 GDI_CALLBACK_ACTION, HandleToolButtons,
6864 Error(ERR_EXIT, "cannot create gadget");
6866 tool_gadget[id] = gi;
6872 /* graphic position values for tool buttons */
6873 #define TOOL_BUTTON_YES_XPOS 2
6874 #define TOOL_BUTTON_YES_YPOS 250
6875 #define TOOL_BUTTON_YES_GFX_YPOS 0
6876 #define TOOL_BUTTON_YES_XSIZE 46
6877 #define TOOL_BUTTON_YES_YSIZE 28
6878 #define TOOL_BUTTON_NO_XPOS 52
6879 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
6880 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
6881 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
6882 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
6883 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
6884 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
6885 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
6886 #define TOOL_BUTTON_CONFIRM_XSIZE 96
6887 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
6888 #define TOOL_BUTTON_PLAYER_XSIZE 30
6889 #define TOOL_BUTTON_PLAYER_YSIZE 30
6890 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
6891 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
6892 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
6893 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
6894 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6895 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6896 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6897 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6898 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6899 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6900 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6901 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6902 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6903 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6904 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6905 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6906 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6907 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6908 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6909 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6918 } toolbutton_info[NUM_TOOL_BUTTONS] =
6921 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
6922 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
6923 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
6928 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
6929 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
6930 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
6935 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
6936 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
6937 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
6938 TOOL_CTRL_ID_CONFIRM,
6942 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6943 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
6944 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6945 TOOL_CTRL_ID_PLAYER_1,
6949 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6950 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
6951 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6952 TOOL_CTRL_ID_PLAYER_2,
6956 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6957 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
6958 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6959 TOOL_CTRL_ID_PLAYER_3,
6963 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6964 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
6965 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6966 TOOL_CTRL_ID_PLAYER_4,
6971 void CreateToolButtons()
6975 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6977 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6978 Bitmap *deco_bitmap = None;
6979 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6980 struct GadgetInfo *gi;
6981 unsigned int event_mask;
6982 int gd_xoffset, gd_yoffset;
6983 int gd_x1, gd_x2, gd_y;
6986 event_mask = GD_EVENT_RELEASED;
6988 gd_xoffset = toolbutton_info[i].xpos;
6989 gd_yoffset = toolbutton_info[i].ypos;
6990 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
6991 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
6992 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
6994 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6996 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6998 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
6999 &deco_bitmap, &deco_x, &deco_y);
7000 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
7001 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
7004 gi = CreateGadget(GDI_CUSTOM_ID, id,
7005 GDI_INFO_TEXT, toolbutton_info[i].infotext,
7006 GDI_X, DX + GDI_ACTIVE_POS(toolbutton_info[i].x),
7007 GDI_Y, DY + GDI_ACTIVE_POS(toolbutton_info[i].y),
7008 GDI_WIDTH, toolbutton_info[i].width,
7009 GDI_HEIGHT, toolbutton_info[i].height,
7010 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
7011 GDI_STATE, GD_BUTTON_UNPRESSED,
7012 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
7013 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
7014 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
7015 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
7016 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
7017 GDI_DECORATION_SHIFTING, 1, 1,
7018 GDI_DIRECT_DRAW, FALSE,
7019 GDI_EVENT_MASK, event_mask,
7020 GDI_CALLBACK_ACTION, HandleToolButtons,
7024 Error(ERR_EXIT, "cannot create gadget");
7026 tool_gadget[id] = gi;
7032 void FreeToolButtons()
7036 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7037 FreeGadget(tool_gadget[i]);
7040 static void UnmapToolButtons()
7044 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7045 UnmapGadget(tool_gadget[i]);
7048 static void HandleToolButtons(struct GadgetInfo *gi)
7050 request_gadget_id = gi->custom_id;
7053 static struct Mapping_EM_to_RND_object
7056 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
7057 boolean is_backside; /* backside of moving element */
7063 em_object_mapping_list[] =
7066 Xblank, TRUE, FALSE,
7070 Yacid_splash_eB, FALSE, FALSE,
7071 EL_ACID_SPLASH_RIGHT, -1, -1
7074 Yacid_splash_wB, FALSE, FALSE,
7075 EL_ACID_SPLASH_LEFT, -1, -1
7078 #ifdef EM_ENGINE_BAD_ROLL
7080 Xstone_force_e, FALSE, FALSE,
7081 EL_ROCK, -1, MV_BIT_RIGHT
7084 Xstone_force_w, FALSE, FALSE,
7085 EL_ROCK, -1, MV_BIT_LEFT
7088 Xnut_force_e, FALSE, FALSE,
7089 EL_NUT, -1, MV_BIT_RIGHT
7092 Xnut_force_w, FALSE, FALSE,
7093 EL_NUT, -1, MV_BIT_LEFT
7096 Xspring_force_e, FALSE, FALSE,
7097 EL_SPRING, -1, MV_BIT_RIGHT
7100 Xspring_force_w, FALSE, FALSE,
7101 EL_SPRING, -1, MV_BIT_LEFT
7104 Xemerald_force_e, FALSE, FALSE,
7105 EL_EMERALD, -1, MV_BIT_RIGHT
7108 Xemerald_force_w, FALSE, FALSE,
7109 EL_EMERALD, -1, MV_BIT_LEFT
7112 Xdiamond_force_e, FALSE, FALSE,
7113 EL_DIAMOND, -1, MV_BIT_RIGHT
7116 Xdiamond_force_w, FALSE, FALSE,
7117 EL_DIAMOND, -1, MV_BIT_LEFT
7120 Xbomb_force_e, FALSE, FALSE,
7121 EL_BOMB, -1, MV_BIT_RIGHT
7124 Xbomb_force_w, FALSE, FALSE,
7125 EL_BOMB, -1, MV_BIT_LEFT
7127 #endif /* EM_ENGINE_BAD_ROLL */
7130 Xstone, TRUE, FALSE,
7134 Xstone_pause, FALSE, FALSE,
7138 Xstone_fall, FALSE, FALSE,
7142 Ystone_s, FALSE, FALSE,
7143 EL_ROCK, ACTION_FALLING, -1
7146 Ystone_sB, FALSE, TRUE,
7147 EL_ROCK, ACTION_FALLING, -1
7150 Ystone_e, FALSE, FALSE,
7151 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7154 Ystone_eB, FALSE, TRUE,
7155 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7158 Ystone_w, FALSE, FALSE,
7159 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7162 Ystone_wB, FALSE, TRUE,
7163 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7170 Xnut_pause, FALSE, FALSE,
7174 Xnut_fall, FALSE, FALSE,
7178 Ynut_s, FALSE, FALSE,
7179 EL_NUT, ACTION_FALLING, -1
7182 Ynut_sB, FALSE, TRUE,
7183 EL_NUT, ACTION_FALLING, -1
7186 Ynut_e, FALSE, FALSE,
7187 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7190 Ynut_eB, FALSE, TRUE,
7191 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7194 Ynut_w, FALSE, FALSE,
7195 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7198 Ynut_wB, FALSE, TRUE,
7199 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7202 Xbug_n, TRUE, FALSE,
7206 Xbug_e, TRUE, FALSE,
7207 EL_BUG_RIGHT, -1, -1
7210 Xbug_s, TRUE, FALSE,
7214 Xbug_w, TRUE, FALSE,
7218 Xbug_gon, FALSE, FALSE,
7222 Xbug_goe, FALSE, FALSE,
7223 EL_BUG_RIGHT, -1, -1
7226 Xbug_gos, FALSE, FALSE,
7230 Xbug_gow, FALSE, FALSE,
7234 Ybug_n, FALSE, FALSE,
7235 EL_BUG, ACTION_MOVING, MV_BIT_UP
7238 Ybug_nB, FALSE, TRUE,
7239 EL_BUG, ACTION_MOVING, MV_BIT_UP
7242 Ybug_e, FALSE, FALSE,
7243 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7246 Ybug_eB, FALSE, TRUE,
7247 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7250 Ybug_s, FALSE, FALSE,
7251 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7254 Ybug_sB, FALSE, TRUE,
7255 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7258 Ybug_w, FALSE, FALSE,
7259 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7262 Ybug_wB, FALSE, TRUE,
7263 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7266 Ybug_w_n, FALSE, FALSE,
7267 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7270 Ybug_n_e, FALSE, FALSE,
7271 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7274 Ybug_e_s, FALSE, FALSE,
7275 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7278 Ybug_s_w, FALSE, FALSE,
7279 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7282 Ybug_e_n, FALSE, FALSE,
7283 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7286 Ybug_s_e, FALSE, FALSE,
7287 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7290 Ybug_w_s, FALSE, FALSE,
7291 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7294 Ybug_n_w, FALSE, FALSE,
7295 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7298 Ybug_stone, FALSE, FALSE,
7299 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
7302 Ybug_spring, FALSE, FALSE,
7303 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
7306 Xtank_n, TRUE, FALSE,
7307 EL_SPACESHIP_UP, -1, -1
7310 Xtank_e, TRUE, FALSE,
7311 EL_SPACESHIP_RIGHT, -1, -1
7314 Xtank_s, TRUE, FALSE,
7315 EL_SPACESHIP_DOWN, -1, -1
7318 Xtank_w, TRUE, FALSE,
7319 EL_SPACESHIP_LEFT, -1, -1
7322 Xtank_gon, FALSE, FALSE,
7323 EL_SPACESHIP_UP, -1, -1
7326 Xtank_goe, FALSE, FALSE,
7327 EL_SPACESHIP_RIGHT, -1, -1
7330 Xtank_gos, FALSE, FALSE,
7331 EL_SPACESHIP_DOWN, -1, -1
7334 Xtank_gow, FALSE, FALSE,
7335 EL_SPACESHIP_LEFT, -1, -1
7338 Ytank_n, FALSE, FALSE,
7339 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7342 Ytank_nB, FALSE, TRUE,
7343 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7346 Ytank_e, FALSE, FALSE,
7347 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7350 Ytank_eB, FALSE, TRUE,
7351 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7354 Ytank_s, FALSE, FALSE,
7355 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7358 Ytank_sB, FALSE, TRUE,
7359 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7362 Ytank_w, FALSE, FALSE,
7363 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7366 Ytank_wB, FALSE, TRUE,
7367 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7370 Ytank_w_n, FALSE, FALSE,
7371 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7374 Ytank_n_e, FALSE, FALSE,
7375 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7378 Ytank_e_s, FALSE, FALSE,
7379 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7382 Ytank_s_w, FALSE, FALSE,
7383 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7386 Ytank_e_n, FALSE, FALSE,
7387 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7390 Ytank_s_e, FALSE, FALSE,
7391 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7394 Ytank_w_s, FALSE, FALSE,
7395 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7398 Ytank_n_w, FALSE, FALSE,
7399 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7402 Ytank_stone, FALSE, FALSE,
7403 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
7406 Ytank_spring, FALSE, FALSE,
7407 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
7410 Xandroid, TRUE, FALSE,
7411 EL_EMC_ANDROID, ACTION_ACTIVE, -1
7414 Xandroid_1_n, FALSE, FALSE,
7415 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7418 Xandroid_2_n, FALSE, FALSE,
7419 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7422 Xandroid_1_e, FALSE, FALSE,
7423 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7426 Xandroid_2_e, FALSE, FALSE,
7427 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7430 Xandroid_1_w, FALSE, FALSE,
7431 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7434 Xandroid_2_w, FALSE, FALSE,
7435 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7438 Xandroid_1_s, FALSE, FALSE,
7439 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7442 Xandroid_2_s, FALSE, FALSE,
7443 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7446 Yandroid_n, FALSE, FALSE,
7447 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7450 Yandroid_nB, FALSE, TRUE,
7451 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7454 Yandroid_ne, FALSE, FALSE,
7455 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
7458 Yandroid_neB, FALSE, TRUE,
7459 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
7462 Yandroid_e, FALSE, FALSE,
7463 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7466 Yandroid_eB, FALSE, TRUE,
7467 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7470 Yandroid_se, FALSE, FALSE,
7471 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
7474 Yandroid_seB, FALSE, TRUE,
7475 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
7478 Yandroid_s, FALSE, FALSE,
7479 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7482 Yandroid_sB, FALSE, TRUE,
7483 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7486 Yandroid_sw, FALSE, FALSE,
7487 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
7490 Yandroid_swB, FALSE, TRUE,
7491 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
7494 Yandroid_w, FALSE, FALSE,
7495 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7498 Yandroid_wB, FALSE, TRUE,
7499 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7502 Yandroid_nw, FALSE, FALSE,
7503 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
7506 Yandroid_nwB, FALSE, TRUE,
7507 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
7510 Xspring, TRUE, FALSE,
7514 Xspring_pause, FALSE, FALSE,
7518 Xspring_e, FALSE, FALSE,
7522 Xspring_w, FALSE, FALSE,
7526 Xspring_fall, FALSE, FALSE,
7530 Yspring_s, FALSE, FALSE,
7531 EL_SPRING, ACTION_FALLING, -1
7534 Yspring_sB, FALSE, TRUE,
7535 EL_SPRING, ACTION_FALLING, -1
7538 Yspring_e, FALSE, FALSE,
7539 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7542 Yspring_eB, FALSE, TRUE,
7543 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7546 Yspring_w, FALSE, FALSE,
7547 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7550 Yspring_wB, FALSE, TRUE,
7551 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7554 Yspring_kill_e, FALSE, FALSE,
7555 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7558 Yspring_kill_eB, FALSE, TRUE,
7559 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7562 Yspring_kill_w, FALSE, FALSE,
7563 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7566 Yspring_kill_wB, FALSE, TRUE,
7567 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7570 Xeater_n, TRUE, FALSE,
7571 EL_YAMYAM_UP, -1, -1
7574 Xeater_e, TRUE, FALSE,
7575 EL_YAMYAM_RIGHT, -1, -1
7578 Xeater_w, TRUE, FALSE,
7579 EL_YAMYAM_LEFT, -1, -1
7582 Xeater_s, TRUE, FALSE,
7583 EL_YAMYAM_DOWN, -1, -1
7586 Yeater_n, FALSE, FALSE,
7587 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7590 Yeater_nB, FALSE, TRUE,
7591 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7594 Yeater_e, FALSE, FALSE,
7595 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7598 Yeater_eB, FALSE, TRUE,
7599 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7602 Yeater_s, FALSE, FALSE,
7603 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7606 Yeater_sB, FALSE, TRUE,
7607 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7610 Yeater_w, FALSE, FALSE,
7611 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7614 Yeater_wB, FALSE, TRUE,
7615 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7618 Yeater_stone, FALSE, FALSE,
7619 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
7622 Yeater_spring, FALSE, FALSE,
7623 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
7626 Xalien, TRUE, FALSE,
7630 Xalien_pause, FALSE, FALSE,
7634 Yalien_n, FALSE, FALSE,
7635 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7638 Yalien_nB, FALSE, TRUE,
7639 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7642 Yalien_e, FALSE, FALSE,
7643 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7646 Yalien_eB, FALSE, TRUE,
7647 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7650 Yalien_s, FALSE, FALSE,
7651 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7654 Yalien_sB, FALSE, TRUE,
7655 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7658 Yalien_w, FALSE, FALSE,
7659 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7662 Yalien_wB, FALSE, TRUE,
7663 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7666 Yalien_stone, FALSE, FALSE,
7667 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
7670 Yalien_spring, FALSE, FALSE,
7671 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
7674 Xemerald, TRUE, FALSE,
7678 Xemerald_pause, FALSE, FALSE,
7682 Xemerald_fall, FALSE, FALSE,
7686 Xemerald_shine, FALSE, FALSE,
7687 EL_EMERALD, ACTION_TWINKLING, -1
7690 Yemerald_s, FALSE, FALSE,
7691 EL_EMERALD, ACTION_FALLING, -1
7694 Yemerald_sB, FALSE, TRUE,
7695 EL_EMERALD, ACTION_FALLING, -1
7698 Yemerald_e, FALSE, FALSE,
7699 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7702 Yemerald_eB, FALSE, TRUE,
7703 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7706 Yemerald_w, FALSE, FALSE,
7707 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7710 Yemerald_wB, FALSE, TRUE,
7711 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7714 Yemerald_eat, FALSE, FALSE,
7715 EL_EMERALD, ACTION_COLLECTING, -1
7718 Yemerald_stone, FALSE, FALSE,
7719 EL_NUT, ACTION_BREAKING, -1
7722 Xdiamond, TRUE, FALSE,
7726 Xdiamond_pause, FALSE, FALSE,
7730 Xdiamond_fall, FALSE, FALSE,
7734 Xdiamond_shine, FALSE, FALSE,
7735 EL_DIAMOND, ACTION_TWINKLING, -1
7738 Ydiamond_s, FALSE, FALSE,
7739 EL_DIAMOND, ACTION_FALLING, -1
7742 Ydiamond_sB, FALSE, TRUE,
7743 EL_DIAMOND, ACTION_FALLING, -1
7746 Ydiamond_e, FALSE, FALSE,
7747 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7750 Ydiamond_eB, FALSE, TRUE,
7751 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7754 Ydiamond_w, FALSE, FALSE,
7755 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7758 Ydiamond_wB, FALSE, TRUE,
7759 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7762 Ydiamond_eat, FALSE, FALSE,
7763 EL_DIAMOND, ACTION_COLLECTING, -1
7766 Ydiamond_stone, FALSE, FALSE,
7767 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
7770 Xdrip_fall, TRUE, FALSE,
7771 EL_AMOEBA_DROP, -1, -1
7774 Xdrip_stretch, FALSE, FALSE,
7775 EL_AMOEBA_DROP, ACTION_FALLING, -1
7778 Xdrip_stretchB, FALSE, TRUE,
7779 EL_AMOEBA_DROP, ACTION_FALLING, -1
7782 Xdrip_eat, FALSE, FALSE,
7783 EL_AMOEBA_DROP, ACTION_GROWING, -1
7786 Ydrip_s1, FALSE, FALSE,
7787 EL_AMOEBA_DROP, ACTION_FALLING, -1
7790 Ydrip_s1B, FALSE, TRUE,
7791 EL_AMOEBA_DROP, ACTION_FALLING, -1
7794 Ydrip_s2, FALSE, FALSE,
7795 EL_AMOEBA_DROP, ACTION_FALLING, -1
7798 Ydrip_s2B, FALSE, TRUE,
7799 EL_AMOEBA_DROP, ACTION_FALLING, -1
7806 Xbomb_pause, FALSE, FALSE,
7810 Xbomb_fall, FALSE, FALSE,
7814 Ybomb_s, FALSE, FALSE,
7815 EL_BOMB, ACTION_FALLING, -1
7818 Ybomb_sB, FALSE, TRUE,
7819 EL_BOMB, ACTION_FALLING, -1
7822 Ybomb_e, FALSE, FALSE,
7823 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7826 Ybomb_eB, FALSE, TRUE,
7827 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7830 Ybomb_w, FALSE, FALSE,
7831 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7834 Ybomb_wB, FALSE, TRUE,
7835 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7838 Ybomb_eat, FALSE, FALSE,
7839 EL_BOMB, ACTION_ACTIVATING, -1
7842 Xballoon, TRUE, FALSE,
7846 Yballoon_n, FALSE, FALSE,
7847 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7850 Yballoon_nB, FALSE, TRUE,
7851 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7854 Yballoon_e, FALSE, FALSE,
7855 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7858 Yballoon_eB, FALSE, TRUE,
7859 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7862 Yballoon_s, FALSE, FALSE,
7863 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7866 Yballoon_sB, FALSE, TRUE,
7867 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7870 Yballoon_w, FALSE, FALSE,
7871 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7874 Yballoon_wB, FALSE, TRUE,
7875 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7878 Xgrass, TRUE, FALSE,
7879 EL_EMC_GRASS, -1, -1
7882 Ygrass_nB, FALSE, FALSE,
7883 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
7886 Ygrass_eB, FALSE, FALSE,
7887 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
7890 Ygrass_sB, FALSE, FALSE,
7891 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
7894 Ygrass_wB, FALSE, FALSE,
7895 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
7902 Ydirt_nB, FALSE, FALSE,
7903 EL_SAND, ACTION_DIGGING, MV_BIT_UP
7906 Ydirt_eB, FALSE, FALSE,
7907 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
7910 Ydirt_sB, FALSE, FALSE,
7911 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
7914 Ydirt_wB, FALSE, FALSE,
7915 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
7918 Xacid_ne, TRUE, FALSE,
7919 EL_ACID_POOL_TOPRIGHT, -1, -1
7922 Xacid_se, TRUE, FALSE,
7923 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
7926 Xacid_s, TRUE, FALSE,
7927 EL_ACID_POOL_BOTTOM, -1, -1
7930 Xacid_sw, TRUE, FALSE,
7931 EL_ACID_POOL_BOTTOMLEFT, -1, -1
7934 Xacid_nw, TRUE, FALSE,
7935 EL_ACID_POOL_TOPLEFT, -1, -1
7938 Xacid_1, TRUE, FALSE,
7942 Xacid_2, FALSE, FALSE,
7946 Xacid_3, FALSE, FALSE,
7950 Xacid_4, FALSE, FALSE,
7954 Xacid_5, FALSE, FALSE,
7958 Xacid_6, FALSE, FALSE,
7962 Xacid_7, FALSE, FALSE,
7966 Xacid_8, FALSE, FALSE,
7970 Xball_1, TRUE, FALSE,
7971 EL_EMC_MAGIC_BALL, -1, -1
7974 Xball_1B, FALSE, FALSE,
7975 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7978 Xball_2, FALSE, FALSE,
7979 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7982 Xball_2B, FALSE, FALSE,
7983 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7986 Yball_eat, FALSE, FALSE,
7987 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
7990 Ykey_1_eat, FALSE, FALSE,
7991 EL_EM_KEY_1, ACTION_COLLECTING, -1
7994 Ykey_2_eat, FALSE, FALSE,
7995 EL_EM_KEY_2, ACTION_COLLECTING, -1
7998 Ykey_3_eat, FALSE, FALSE,
7999 EL_EM_KEY_3, ACTION_COLLECTING, -1
8002 Ykey_4_eat, FALSE, FALSE,
8003 EL_EM_KEY_4, ACTION_COLLECTING, -1
8006 Ykey_5_eat, FALSE, FALSE,
8007 EL_EMC_KEY_5, ACTION_COLLECTING, -1
8010 Ykey_6_eat, FALSE, FALSE,
8011 EL_EMC_KEY_6, ACTION_COLLECTING, -1
8014 Ykey_7_eat, FALSE, FALSE,
8015 EL_EMC_KEY_7, ACTION_COLLECTING, -1
8018 Ykey_8_eat, FALSE, FALSE,
8019 EL_EMC_KEY_8, ACTION_COLLECTING, -1
8022 Ylenses_eat, FALSE, FALSE,
8023 EL_EMC_LENSES, ACTION_COLLECTING, -1
8026 Ymagnify_eat, FALSE, FALSE,
8027 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
8030 Ygrass_eat, FALSE, FALSE,
8031 EL_EMC_GRASS, ACTION_SNAPPING, -1
8034 Ydirt_eat, FALSE, FALSE,
8035 EL_SAND, ACTION_SNAPPING, -1
8038 Xgrow_ns, TRUE, FALSE,
8039 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
8042 Ygrow_ns_eat, FALSE, FALSE,
8043 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
8046 Xgrow_ew, TRUE, FALSE,
8047 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
8050 Ygrow_ew_eat, FALSE, FALSE,
8051 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
8054 Xwonderwall, TRUE, FALSE,
8055 EL_MAGIC_WALL, -1, -1
8058 XwonderwallB, FALSE, FALSE,
8059 EL_MAGIC_WALL, ACTION_ACTIVE, -1
8062 Xamoeba_1, TRUE, FALSE,
8063 EL_AMOEBA_DRY, ACTION_OTHER, -1
8066 Xamoeba_2, FALSE, FALSE,
8067 EL_AMOEBA_DRY, ACTION_OTHER, -1
8070 Xamoeba_3, FALSE, FALSE,
8071 EL_AMOEBA_DRY, ACTION_OTHER, -1
8074 Xamoeba_4, FALSE, FALSE,
8075 EL_AMOEBA_DRY, ACTION_OTHER, -1
8078 Xamoeba_5, TRUE, FALSE,
8079 EL_AMOEBA_WET, ACTION_OTHER, -1
8082 Xamoeba_6, FALSE, FALSE,
8083 EL_AMOEBA_WET, ACTION_OTHER, -1
8086 Xamoeba_7, FALSE, FALSE,
8087 EL_AMOEBA_WET, ACTION_OTHER, -1
8090 Xamoeba_8, FALSE, FALSE,
8091 EL_AMOEBA_WET, ACTION_OTHER, -1
8094 Xdoor_1, TRUE, FALSE,
8095 EL_EM_GATE_1, -1, -1
8098 Xdoor_2, TRUE, FALSE,
8099 EL_EM_GATE_2, -1, -1
8102 Xdoor_3, TRUE, FALSE,
8103 EL_EM_GATE_3, -1, -1
8106 Xdoor_4, TRUE, FALSE,
8107 EL_EM_GATE_4, -1, -1
8110 Xdoor_5, TRUE, FALSE,
8111 EL_EMC_GATE_5, -1, -1
8114 Xdoor_6, TRUE, FALSE,
8115 EL_EMC_GATE_6, -1, -1
8118 Xdoor_7, TRUE, FALSE,
8119 EL_EMC_GATE_7, -1, -1
8122 Xdoor_8, TRUE, FALSE,
8123 EL_EMC_GATE_8, -1, -1
8126 Xkey_1, TRUE, FALSE,
8130 Xkey_2, TRUE, FALSE,
8134 Xkey_3, TRUE, FALSE,
8138 Xkey_4, TRUE, FALSE,
8142 Xkey_5, TRUE, FALSE,
8143 EL_EMC_KEY_5, -1, -1
8146 Xkey_6, TRUE, FALSE,
8147 EL_EMC_KEY_6, -1, -1
8150 Xkey_7, TRUE, FALSE,
8151 EL_EMC_KEY_7, -1, -1
8154 Xkey_8, TRUE, FALSE,
8155 EL_EMC_KEY_8, -1, -1
8158 Xwind_n, TRUE, FALSE,
8159 EL_BALLOON_SWITCH_UP, -1, -1
8162 Xwind_e, TRUE, FALSE,
8163 EL_BALLOON_SWITCH_RIGHT, -1, -1
8166 Xwind_s, TRUE, FALSE,
8167 EL_BALLOON_SWITCH_DOWN, -1, -1
8170 Xwind_w, TRUE, FALSE,
8171 EL_BALLOON_SWITCH_LEFT, -1, -1
8174 Xwind_nesw, TRUE, FALSE,
8175 EL_BALLOON_SWITCH_ANY, -1, -1
8178 Xwind_stop, TRUE, FALSE,
8179 EL_BALLOON_SWITCH_NONE, -1, -1
8183 EL_EM_EXIT_CLOSED, -1, -1
8186 Xexit_1, TRUE, FALSE,
8187 EL_EM_EXIT_OPEN, -1, -1
8190 Xexit_2, FALSE, FALSE,
8191 EL_EM_EXIT_OPEN, -1, -1
8194 Xexit_3, FALSE, FALSE,
8195 EL_EM_EXIT_OPEN, -1, -1
8198 Xdynamite, TRUE, FALSE,
8199 EL_EM_DYNAMITE, -1, -1
8202 Ydynamite_eat, FALSE, FALSE,
8203 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
8206 Xdynamite_1, TRUE, FALSE,
8207 EL_EM_DYNAMITE_ACTIVE, -1, -1
8210 Xdynamite_2, FALSE, FALSE,
8211 EL_EM_DYNAMITE_ACTIVE, -1, -1
8214 Xdynamite_3, FALSE, FALSE,
8215 EL_EM_DYNAMITE_ACTIVE, -1, -1
8218 Xdynamite_4, FALSE, FALSE,
8219 EL_EM_DYNAMITE_ACTIVE, -1, -1
8222 Xbumper, TRUE, FALSE,
8223 EL_EMC_SPRING_BUMPER, -1, -1
8226 XbumperB, FALSE, FALSE,
8227 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
8230 Xwheel, TRUE, FALSE,
8231 EL_ROBOT_WHEEL, -1, -1
8234 XwheelB, FALSE, FALSE,
8235 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
8238 Xswitch, TRUE, FALSE,
8239 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
8242 XswitchB, FALSE, FALSE,
8243 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
8247 EL_QUICKSAND_EMPTY, -1, -1
8250 Xsand_stone, TRUE, FALSE,
8251 EL_QUICKSAND_FULL, -1, -1
8254 Xsand_stonein_1, FALSE, TRUE,
8255 EL_ROCK, ACTION_FILLING, -1
8258 Xsand_stonein_2, FALSE, TRUE,
8259 EL_ROCK, ACTION_FILLING, -1
8262 Xsand_stonein_3, FALSE, TRUE,
8263 EL_ROCK, ACTION_FILLING, -1
8266 Xsand_stonein_4, FALSE, TRUE,
8267 EL_ROCK, ACTION_FILLING, -1
8271 Xsand_stonesand_1, FALSE, FALSE,
8272 EL_QUICKSAND_EMPTYING, -1, -1
8275 Xsand_stonesand_2, FALSE, FALSE,
8276 EL_QUICKSAND_EMPTYING, -1, -1
8279 Xsand_stonesand_3, FALSE, FALSE,
8280 EL_QUICKSAND_EMPTYING, -1, -1
8283 Xsand_stonesand_4, FALSE, FALSE,
8284 EL_QUICKSAND_EMPTYING, -1, -1
8287 Xsand_stonesand_quickout_1, FALSE, FALSE,
8288 EL_QUICKSAND_EMPTYING, -1, -1
8291 Xsand_stonesand_quickout_2, FALSE, FALSE,
8292 EL_QUICKSAND_EMPTYING, -1, -1
8296 Xsand_stonesand_1, FALSE, FALSE,
8297 EL_QUICKSAND_FULL, -1, -1
8300 Xsand_stonesand_2, FALSE, FALSE,
8301 EL_QUICKSAND_FULL, -1, -1
8304 Xsand_stonesand_3, FALSE, FALSE,
8305 EL_QUICKSAND_FULL, -1, -1
8308 Xsand_stonesand_4, FALSE, FALSE,
8309 EL_QUICKSAND_FULL, -1, -1
8313 Xsand_stoneout_1, FALSE, FALSE,
8314 EL_ROCK, ACTION_EMPTYING, -1
8317 Xsand_stoneout_2, FALSE, FALSE,
8318 EL_ROCK, ACTION_EMPTYING, -1
8322 Xsand_sandstone_1, FALSE, FALSE,
8323 EL_QUICKSAND_FILLING, -1, -1
8326 Xsand_sandstone_2, FALSE, FALSE,
8327 EL_QUICKSAND_FILLING, -1, -1
8330 Xsand_sandstone_3, FALSE, FALSE,
8331 EL_QUICKSAND_FILLING, -1, -1
8334 Xsand_sandstone_4, FALSE, FALSE,
8335 EL_QUICKSAND_FILLING, -1, -1
8339 Xsand_sandstone_1, FALSE, FALSE,
8340 EL_QUICKSAND_FULL, -1, -1
8343 Xsand_sandstone_2, FALSE, FALSE,
8344 EL_QUICKSAND_FULL, -1, -1
8347 Xsand_sandstone_3, FALSE, FALSE,
8348 EL_QUICKSAND_FULL, -1, -1
8351 Xsand_sandstone_4, FALSE, FALSE,
8352 EL_QUICKSAND_FULL, -1, -1
8356 Xplant, TRUE, FALSE,
8357 EL_EMC_PLANT, -1, -1
8360 Yplant, FALSE, FALSE,
8361 EL_EMC_PLANT, -1, -1
8364 Xlenses, TRUE, FALSE,
8365 EL_EMC_LENSES, -1, -1
8368 Xmagnify, TRUE, FALSE,
8369 EL_EMC_MAGNIFIER, -1, -1
8372 Xdripper, TRUE, FALSE,
8373 EL_EMC_DRIPPER, -1, -1
8376 XdripperB, FALSE, FALSE,
8377 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
8380 Xfake_blank, TRUE, FALSE,
8381 EL_INVISIBLE_WALL, -1, -1
8384 Xfake_blankB, FALSE, FALSE,
8385 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
8388 Xfake_grass, TRUE, FALSE,
8389 EL_EMC_FAKE_GRASS, -1, -1
8392 Xfake_grassB, FALSE, FALSE,
8393 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
8396 Xfake_door_1, TRUE, FALSE,
8397 EL_EM_GATE_1_GRAY, -1, -1
8400 Xfake_door_2, TRUE, FALSE,
8401 EL_EM_GATE_2_GRAY, -1, -1
8404 Xfake_door_3, TRUE, FALSE,
8405 EL_EM_GATE_3_GRAY, -1, -1
8408 Xfake_door_4, TRUE, FALSE,
8409 EL_EM_GATE_4_GRAY, -1, -1
8412 Xfake_door_5, TRUE, FALSE,
8413 EL_EMC_GATE_5_GRAY, -1, -1
8416 Xfake_door_6, TRUE, FALSE,
8417 EL_EMC_GATE_6_GRAY, -1, -1
8420 Xfake_door_7, TRUE, FALSE,
8421 EL_EMC_GATE_7_GRAY, -1, -1
8424 Xfake_door_8, TRUE, FALSE,
8425 EL_EMC_GATE_8_GRAY, -1, -1
8428 Xfake_acid_1, TRUE, FALSE,
8429 EL_EMC_FAKE_ACID, -1, -1
8432 Xfake_acid_2, FALSE, FALSE,
8433 EL_EMC_FAKE_ACID, -1, -1
8436 Xfake_acid_3, FALSE, FALSE,
8437 EL_EMC_FAKE_ACID, -1, -1
8440 Xfake_acid_4, FALSE, FALSE,
8441 EL_EMC_FAKE_ACID, -1, -1
8444 Xfake_acid_5, FALSE, FALSE,
8445 EL_EMC_FAKE_ACID, -1, -1
8448 Xfake_acid_6, FALSE, FALSE,
8449 EL_EMC_FAKE_ACID, -1, -1
8452 Xfake_acid_7, FALSE, FALSE,
8453 EL_EMC_FAKE_ACID, -1, -1
8456 Xfake_acid_8, FALSE, FALSE,
8457 EL_EMC_FAKE_ACID, -1, -1
8460 Xsteel_1, TRUE, FALSE,
8461 EL_STEELWALL, -1, -1
8464 Xsteel_2, TRUE, FALSE,
8465 EL_EMC_STEELWALL_2, -1, -1
8468 Xsteel_3, TRUE, FALSE,
8469 EL_EMC_STEELWALL_3, -1, -1
8472 Xsteel_4, TRUE, FALSE,
8473 EL_EMC_STEELWALL_4, -1, -1
8476 Xwall_1, TRUE, FALSE,
8480 Xwall_2, TRUE, FALSE,
8481 EL_EMC_WALL_14, -1, -1
8484 Xwall_3, TRUE, FALSE,
8485 EL_EMC_WALL_15, -1, -1
8488 Xwall_4, TRUE, FALSE,
8489 EL_EMC_WALL_16, -1, -1
8492 Xround_wall_1, TRUE, FALSE,
8493 EL_WALL_SLIPPERY, -1, -1
8496 Xround_wall_2, TRUE, FALSE,
8497 EL_EMC_WALL_SLIPPERY_2, -1, -1
8500 Xround_wall_3, TRUE, FALSE,
8501 EL_EMC_WALL_SLIPPERY_3, -1, -1
8504 Xround_wall_4, TRUE, FALSE,
8505 EL_EMC_WALL_SLIPPERY_4, -1, -1
8508 Xdecor_1, TRUE, FALSE,
8509 EL_EMC_WALL_8, -1, -1
8512 Xdecor_2, TRUE, FALSE,
8513 EL_EMC_WALL_6, -1, -1
8516 Xdecor_3, TRUE, FALSE,
8517 EL_EMC_WALL_4, -1, -1
8520 Xdecor_4, TRUE, FALSE,
8521 EL_EMC_WALL_7, -1, -1
8524 Xdecor_5, TRUE, FALSE,
8525 EL_EMC_WALL_5, -1, -1
8528 Xdecor_6, TRUE, FALSE,
8529 EL_EMC_WALL_9, -1, -1
8532 Xdecor_7, TRUE, FALSE,
8533 EL_EMC_WALL_10, -1, -1
8536 Xdecor_8, TRUE, FALSE,
8537 EL_EMC_WALL_1, -1, -1
8540 Xdecor_9, TRUE, FALSE,
8541 EL_EMC_WALL_2, -1, -1
8544 Xdecor_10, TRUE, FALSE,
8545 EL_EMC_WALL_3, -1, -1
8548 Xdecor_11, TRUE, FALSE,
8549 EL_EMC_WALL_11, -1, -1
8552 Xdecor_12, TRUE, FALSE,
8553 EL_EMC_WALL_12, -1, -1
8556 Xalpha_0, TRUE, FALSE,
8557 EL_CHAR('0'), -1, -1
8560 Xalpha_1, TRUE, FALSE,
8561 EL_CHAR('1'), -1, -1
8564 Xalpha_2, TRUE, FALSE,
8565 EL_CHAR('2'), -1, -1
8568 Xalpha_3, TRUE, FALSE,
8569 EL_CHAR('3'), -1, -1
8572 Xalpha_4, TRUE, FALSE,
8573 EL_CHAR('4'), -1, -1
8576 Xalpha_5, TRUE, FALSE,
8577 EL_CHAR('5'), -1, -1
8580 Xalpha_6, TRUE, FALSE,
8581 EL_CHAR('6'), -1, -1
8584 Xalpha_7, TRUE, FALSE,
8585 EL_CHAR('7'), -1, -1
8588 Xalpha_8, TRUE, FALSE,
8589 EL_CHAR('8'), -1, -1
8592 Xalpha_9, TRUE, FALSE,
8593 EL_CHAR('9'), -1, -1
8596 Xalpha_excla, TRUE, FALSE,
8597 EL_CHAR('!'), -1, -1
8600 Xalpha_quote, TRUE, FALSE,
8601 EL_CHAR('"'), -1, -1
8604 Xalpha_comma, TRUE, FALSE,
8605 EL_CHAR(','), -1, -1
8608 Xalpha_minus, TRUE, FALSE,
8609 EL_CHAR('-'), -1, -1
8612 Xalpha_perio, TRUE, FALSE,
8613 EL_CHAR('.'), -1, -1
8616 Xalpha_colon, TRUE, FALSE,
8617 EL_CHAR(':'), -1, -1
8620 Xalpha_quest, TRUE, FALSE,
8621 EL_CHAR('?'), -1, -1
8624 Xalpha_a, TRUE, FALSE,
8625 EL_CHAR('A'), -1, -1
8628 Xalpha_b, TRUE, FALSE,
8629 EL_CHAR('B'), -1, -1
8632 Xalpha_c, TRUE, FALSE,
8633 EL_CHAR('C'), -1, -1
8636 Xalpha_d, TRUE, FALSE,
8637 EL_CHAR('D'), -1, -1
8640 Xalpha_e, TRUE, FALSE,
8641 EL_CHAR('E'), -1, -1
8644 Xalpha_f, TRUE, FALSE,
8645 EL_CHAR('F'), -1, -1
8648 Xalpha_g, TRUE, FALSE,
8649 EL_CHAR('G'), -1, -1
8652 Xalpha_h, TRUE, FALSE,
8653 EL_CHAR('H'), -1, -1
8656 Xalpha_i, TRUE, FALSE,
8657 EL_CHAR('I'), -1, -1
8660 Xalpha_j, TRUE, FALSE,
8661 EL_CHAR('J'), -1, -1
8664 Xalpha_k, TRUE, FALSE,
8665 EL_CHAR('K'), -1, -1
8668 Xalpha_l, TRUE, FALSE,
8669 EL_CHAR('L'), -1, -1
8672 Xalpha_m, TRUE, FALSE,
8673 EL_CHAR('M'), -1, -1
8676 Xalpha_n, TRUE, FALSE,
8677 EL_CHAR('N'), -1, -1
8680 Xalpha_o, TRUE, FALSE,
8681 EL_CHAR('O'), -1, -1
8684 Xalpha_p, TRUE, FALSE,
8685 EL_CHAR('P'), -1, -1
8688 Xalpha_q, TRUE, FALSE,
8689 EL_CHAR('Q'), -1, -1
8692 Xalpha_r, TRUE, FALSE,
8693 EL_CHAR('R'), -1, -1
8696 Xalpha_s, TRUE, FALSE,
8697 EL_CHAR('S'), -1, -1
8700 Xalpha_t, TRUE, FALSE,
8701 EL_CHAR('T'), -1, -1
8704 Xalpha_u, TRUE, FALSE,
8705 EL_CHAR('U'), -1, -1
8708 Xalpha_v, TRUE, FALSE,
8709 EL_CHAR('V'), -1, -1
8712 Xalpha_w, TRUE, FALSE,
8713 EL_CHAR('W'), -1, -1
8716 Xalpha_x, TRUE, FALSE,
8717 EL_CHAR('X'), -1, -1
8720 Xalpha_y, TRUE, FALSE,
8721 EL_CHAR('Y'), -1, -1
8724 Xalpha_z, TRUE, FALSE,
8725 EL_CHAR('Z'), -1, -1
8728 Xalpha_arrow_e, TRUE, FALSE,
8729 EL_CHAR('>'), -1, -1
8732 Xalpha_arrow_w, TRUE, FALSE,
8733 EL_CHAR('<'), -1, -1
8736 Xalpha_copyr, TRUE, FALSE,
8737 EL_CHAR('©'), -1, -1
8741 Xboom_bug, FALSE, FALSE,
8742 EL_BUG, ACTION_EXPLODING, -1
8745 Xboom_bomb, FALSE, FALSE,
8746 EL_BOMB, ACTION_EXPLODING, -1
8749 Xboom_android, FALSE, FALSE,
8750 EL_EMC_ANDROID, ACTION_OTHER, -1
8753 Xboom_1, FALSE, FALSE,
8754 EL_DEFAULT, ACTION_EXPLODING, -1
8757 Xboom_2, FALSE, FALSE,
8758 EL_DEFAULT, ACTION_EXPLODING, -1
8761 Znormal, FALSE, FALSE,
8765 Zdynamite, FALSE, FALSE,
8769 Zplayer, FALSE, FALSE,
8773 ZBORDER, FALSE, FALSE,
8783 static struct Mapping_EM_to_RND_player
8792 em_player_mapping_list[] =
8796 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
8800 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
8804 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
8808 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
8812 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
8816 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
8820 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
8824 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
8828 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
8832 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
8836 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
8840 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
8844 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
8848 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
8852 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
8856 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
8860 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
8864 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
8868 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
8872 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
8876 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
8880 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
8884 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
8888 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
8892 EL_PLAYER_1, ACTION_DEFAULT, -1,
8896 EL_PLAYER_2, ACTION_DEFAULT, -1,
8900 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
8904 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
8908 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
8912 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
8916 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
8920 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
8924 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
8928 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
8932 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
8936 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
8940 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
8944 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
8948 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
8952 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
8956 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
8960 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
8964 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
8968 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
8972 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
8976 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
8980 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
8984 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
8988 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
8992 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
8996 EL_PLAYER_3, ACTION_DEFAULT, -1,
9000 EL_PLAYER_4, ACTION_DEFAULT, -1,
9009 int map_element_RND_to_EM(int element_rnd)
9011 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
9012 static boolean mapping_initialized = FALSE;
9014 if (!mapping_initialized)
9018 /* return "Xalpha_quest" for all undefined elements in mapping array */
9019 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
9020 mapping_RND_to_EM[i] = Xalpha_quest;
9022 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9023 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
9024 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
9025 em_object_mapping_list[i].element_em;
9027 mapping_initialized = TRUE;
9030 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
9031 return mapping_RND_to_EM[element_rnd];
9033 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
9038 int map_element_EM_to_RND(int element_em)
9040 static unsigned short mapping_EM_to_RND[TILE_MAX];
9041 static boolean mapping_initialized = FALSE;
9043 if (!mapping_initialized)
9047 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
9048 for (i = 0; i < TILE_MAX; i++)
9049 mapping_EM_to_RND[i] = EL_UNKNOWN;
9051 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9052 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
9053 em_object_mapping_list[i].element_rnd;
9055 mapping_initialized = TRUE;
9058 if (element_em >= 0 && element_em < TILE_MAX)
9059 return mapping_EM_to_RND[element_em];
9061 Error(ERR_WARN, "invalid EM level element %d", element_em);
9066 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
9068 struct LevelInfo_EM *level_em = level->native_em_level;
9069 struct LEVEL *lev = level_em->lev;
9072 for (i = 0; i < TILE_MAX; i++)
9073 lev->android_array[i] = Xblank;
9075 for (i = 0; i < level->num_android_clone_elements; i++)
9077 int element_rnd = level->android_clone_element[i];
9078 int element_em = map_element_RND_to_EM(element_rnd);
9080 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
9081 if (em_object_mapping_list[j].element_rnd == element_rnd)
9082 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
9086 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
9088 struct LevelInfo_EM *level_em = level->native_em_level;
9089 struct LEVEL *lev = level_em->lev;
9092 level->num_android_clone_elements = 0;
9094 for (i = 0; i < TILE_MAX; i++)
9096 int element_em = lev->android_array[i];
9098 boolean element_found = FALSE;
9100 if (element_em == Xblank)
9103 element_rnd = map_element_EM_to_RND(element_em);
9105 for (j = 0; j < level->num_android_clone_elements; j++)
9106 if (level->android_clone_element[j] == element_rnd)
9107 element_found = TRUE;
9111 level->android_clone_element[level->num_android_clone_elements++] =
9114 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
9119 if (level->num_android_clone_elements == 0)
9121 level->num_android_clone_elements = 1;
9122 level->android_clone_element[0] = EL_EMPTY;
9126 int map_direction_RND_to_EM(int direction)
9128 return (direction == MV_UP ? 0 :
9129 direction == MV_RIGHT ? 1 :
9130 direction == MV_DOWN ? 2 :
9131 direction == MV_LEFT ? 3 :
9135 int map_direction_EM_to_RND(int direction)
9137 return (direction == 0 ? MV_UP :
9138 direction == 1 ? MV_RIGHT :
9139 direction == 2 ? MV_DOWN :
9140 direction == 3 ? MV_LEFT :
9144 int map_element_RND_to_SP(int element_rnd)
9146 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
9148 if (element_rnd >= EL_SP_START &&
9149 element_rnd <= EL_SP_END)
9150 element_sp = element_rnd - EL_SP_START;
9151 else if (element_rnd == EL_EMPTY_SPACE)
9153 else if (element_rnd == EL_INVISIBLE_WALL)
9159 int map_element_SP_to_RND(int element_sp)
9161 int element_rnd = EL_UNKNOWN;
9163 if (element_sp >= 0x00 &&
9165 element_rnd = EL_SP_START + element_sp;
9166 else if (element_sp == 0x28)
9167 element_rnd = EL_INVISIBLE_WALL;
9172 int map_action_SP_to_RND(int action_sp)
9176 case actActive: return ACTION_ACTIVE;
9177 case actImpact: return ACTION_IMPACT;
9178 case actExploding: return ACTION_EXPLODING;
9179 case actDigging: return ACTION_DIGGING;
9180 case actSnapping: return ACTION_SNAPPING;
9181 case actCollecting: return ACTION_COLLECTING;
9182 case actPassing: return ACTION_PASSING;
9183 case actPushing: return ACTION_PUSHING;
9184 case actDropping: return ACTION_DROPPING;
9186 default: return ACTION_DEFAULT;
9190 int get_next_element(int element)
9194 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
9195 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
9196 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
9197 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
9198 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
9199 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
9200 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
9201 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
9202 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
9203 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
9204 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
9206 default: return element;
9211 int el_act_dir2img(int element, int action, int direction)
9213 element = GFX_ELEMENT(element);
9215 if (direction == MV_NONE)
9216 return element_info[element].graphic[action];
9218 direction = MV_DIR_TO_BIT(direction);
9220 return element_info[element].direction_graphic[action][direction];
9223 int el_act_dir2img(int element, int action, int direction)
9225 element = GFX_ELEMENT(element);
9226 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9228 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9229 return element_info[element].direction_graphic[action][direction];
9234 static int el_act_dir2crm(int element, int action, int direction)
9236 element = GFX_ELEMENT(element);
9238 if (direction == MV_NONE)
9239 return element_info[element].crumbled[action];
9241 direction = MV_DIR_TO_BIT(direction);
9243 return element_info[element].direction_crumbled[action][direction];
9246 static int el_act_dir2crm(int element, int action, int direction)
9248 element = GFX_ELEMENT(element);
9249 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9251 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9252 return element_info[element].direction_crumbled[action][direction];
9256 int el_act2img(int element, int action)
9258 element = GFX_ELEMENT(element);
9260 return element_info[element].graphic[action];
9263 int el_act2crm(int element, int action)
9265 element = GFX_ELEMENT(element);
9267 return element_info[element].crumbled[action];
9270 int el_dir2img(int element, int direction)
9272 element = GFX_ELEMENT(element);
9274 return el_act_dir2img(element, ACTION_DEFAULT, direction);
9277 int el2baseimg(int element)
9279 return element_info[element].graphic[ACTION_DEFAULT];
9282 int el2img(int element)
9284 element = GFX_ELEMENT(element);
9286 return element_info[element].graphic[ACTION_DEFAULT];
9289 int el2edimg(int element)
9291 element = GFX_ELEMENT(element);
9293 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
9296 int el2preimg(int element)
9298 element = GFX_ELEMENT(element);
9300 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
9303 int el2panelimg(int element)
9305 element = GFX_ELEMENT(element);
9307 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
9310 int font2baseimg(int font_nr)
9312 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
9315 int getBeltNrFromBeltElement(int element)
9317 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
9318 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
9319 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
9322 int getBeltNrFromBeltActiveElement(int element)
9324 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
9325 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
9326 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
9329 int getBeltNrFromBeltSwitchElement(int element)
9331 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
9332 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
9333 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
9336 int getBeltDirNrFromBeltElement(int element)
9338 static int belt_base_element[4] =
9340 EL_CONVEYOR_BELT_1_LEFT,
9341 EL_CONVEYOR_BELT_2_LEFT,
9342 EL_CONVEYOR_BELT_3_LEFT,
9343 EL_CONVEYOR_BELT_4_LEFT
9346 int belt_nr = getBeltNrFromBeltElement(element);
9347 int belt_dir_nr = element - belt_base_element[belt_nr];
9349 return (belt_dir_nr % 3);
9352 int getBeltDirNrFromBeltSwitchElement(int element)
9354 static int belt_base_element[4] =
9356 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9357 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9358 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9359 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9362 int belt_nr = getBeltNrFromBeltSwitchElement(element);
9363 int belt_dir_nr = element - belt_base_element[belt_nr];
9365 return (belt_dir_nr % 3);
9368 int getBeltDirFromBeltElement(int element)
9370 static int belt_move_dir[3] =
9377 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
9379 return belt_move_dir[belt_dir_nr];
9382 int getBeltDirFromBeltSwitchElement(int element)
9384 static int belt_move_dir[3] =
9391 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
9393 return belt_move_dir[belt_dir_nr];
9396 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9398 static int belt_base_element[4] =
9400 EL_CONVEYOR_BELT_1_LEFT,
9401 EL_CONVEYOR_BELT_2_LEFT,
9402 EL_CONVEYOR_BELT_3_LEFT,
9403 EL_CONVEYOR_BELT_4_LEFT
9406 return belt_base_element[belt_nr] + belt_dir_nr;
9409 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9411 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9413 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9416 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9418 static int belt_base_element[4] =
9420 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9421 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9422 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9423 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9426 return belt_base_element[belt_nr] + belt_dir_nr;
9429 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9431 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9433 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9437 boolean getTeamMode_EM()
9439 return game.team_mode;
9442 int getNumActivePlayers_EM()
9445 int num_players = 0;
9449 return (setup.team_mode ? MAX_PLAYERS : 1);
9451 for (i = 0; i < MAX_PLAYERS; i++)
9452 if (tape.player_participates[i])
9455 return (num_players > 1 ? MAX_PLAYERS : 1);
9459 int num_players = 0;
9462 /* when recording game, activate all connected players */
9466 for (i = 0; i < MAX_PLAYERS; i++)
9467 if (tape.player_participates[i])
9475 int getGameFrameDelay_EM(int native_em_game_frame_delay)
9477 int game_frame_delay_value;
9479 game_frame_delay_value =
9480 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
9481 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
9484 if (tape.playing && tape.warp_forward && !tape.pausing)
9485 game_frame_delay_value = 0;
9487 return game_frame_delay_value;
9490 unsigned int InitRND(int seed)
9492 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
9493 return InitEngineRandom_EM(seed);
9494 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
9495 return InitEngineRandom_SP(seed);
9497 return InitEngineRandom_RND(seed);
9501 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
9502 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
9505 inline static int get_effective_element_EM(int tile, int frame_em)
9507 int element = object_mapping[tile].element_rnd;
9508 int action = object_mapping[tile].action;
9509 boolean is_backside = object_mapping[tile].is_backside;
9510 boolean action_removing = (action == ACTION_DIGGING ||
9511 action == ACTION_SNAPPING ||
9512 action == ACTION_COLLECTING);
9518 case Yacid_splash_eB:
9519 case Yacid_splash_wB:
9520 return (frame_em > 5 ? EL_EMPTY : element);
9524 case Ydiamond_stone:
9525 // if (!game.use_native_emc_graphics_engine)
9533 else /* frame_em == 7 */
9537 case Yacid_splash_eB:
9538 case Yacid_splash_wB:
9541 case Yemerald_stone:
9544 case Ydiamond_stone:
9548 case Xdrip_stretchB:
9567 case Xsand_stonein_1:
9568 case Xsand_stonein_2:
9569 case Xsand_stonein_3:
9570 case Xsand_stonein_4:
9574 return (is_backside || action_removing ? EL_EMPTY : element);
9579 inline static boolean check_linear_animation_EM(int tile)
9583 case Xsand_stonesand_1:
9584 case Xsand_stonesand_quickout_1:
9585 case Xsand_sandstone_1:
9586 case Xsand_stonein_1:
9587 case Xsand_stoneout_1:
9607 case Yacid_splash_eB:
9608 case Yacid_splash_wB:
9609 case Yemerald_stone:
9617 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
9618 boolean has_crumbled_graphics,
9619 int crumbled, int sync_frame)
9621 /* if element can be crumbled, but certain action graphics are just empty
9622 space (like instantly snapping sand to empty space in 1 frame), do not
9623 treat these empty space graphics as crumbled graphics in EMC engine */
9624 if (crumbled == IMG_EMPTY_SPACE)
9625 has_crumbled_graphics = FALSE;
9627 if (has_crumbled_graphics)
9629 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9630 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9631 g_crumbled->anim_delay,
9632 g_crumbled->anim_mode,
9633 g_crumbled->anim_start_frame,
9636 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
9637 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
9639 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
9641 g_em->has_crumbled_graphics = TRUE;
9645 g_em->crumbled_bitmap = NULL;
9646 g_em->crumbled_src_x = 0;
9647 g_em->crumbled_src_y = 0;
9648 g_em->crumbled_border_size = 0;
9650 g_em->has_crumbled_graphics = FALSE;
9654 void ResetGfxAnimation_EM(int x, int y, int tile)
9659 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
9660 int tile, int frame_em, int x, int y)
9662 int action = object_mapping[tile].action;
9664 int direction = object_mapping[tile].direction;
9665 int effective_element = get_effective_element_EM(tile, frame_em);
9666 int graphic = (direction == MV_NONE ?
9667 el_act2img(effective_element, action) :
9668 el_act_dir2img(effective_element, action, direction));
9669 struct GraphicInfo *g = &graphic_info[graphic];
9672 boolean action_removing = (action == ACTION_DIGGING ||
9673 action == ACTION_SNAPPING ||
9674 action == ACTION_COLLECTING);
9675 boolean action_moving = (action == ACTION_FALLING ||
9676 action == ACTION_MOVING ||
9677 action == ACTION_PUSHING ||
9678 action == ACTION_EATING ||
9679 action == ACTION_FILLING ||
9680 action == ACTION_EMPTYING);
9681 boolean action_falling = (action == ACTION_FALLING ||
9682 action == ACTION_FILLING ||
9683 action == ACTION_EMPTYING);
9685 /* special case: graphic uses "2nd movement tile" and has defined
9686 7 frames for movement animation (or less) => use default graphic
9687 for last (8th) frame which ends the movement animation */
9688 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9690 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
9691 graphic = (direction == MV_NONE ?
9692 el_act2img(effective_element, action) :
9693 el_act_dir2img(effective_element, action, direction));
9695 g = &graphic_info[graphic];
9699 if (tile == Xsand_stonesand_1 ||
9700 tile == Xsand_stonesand_2 ||
9701 tile == Xsand_stonesand_3 ||
9702 tile == Xsand_stonesand_4)
9703 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9707 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
9711 // printf("::: resetting... [%d]\n", tile);
9714 if (action_removing || check_linear_animation_EM(tile))
9716 GfxFrame[x][y] = frame_em;
9718 // printf("::: resetting... [%d]\n", tile);
9721 else if (action_moving)
9723 boolean is_backside = object_mapping[tile].is_backside;
9727 int direction = object_mapping[tile].direction;
9728 int move_dir = (action_falling ? MV_DOWN : direction);
9733 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
9734 if (g->double_movement && frame_em == 0)
9738 // printf("::: resetting... [%d]\n", tile);
9742 if (move_dir == MV_LEFT)
9743 GfxFrame[x - 1][y] = GfxFrame[x][y];
9744 else if (move_dir == MV_RIGHT)
9745 GfxFrame[x + 1][y] = GfxFrame[x][y];
9746 else if (move_dir == MV_UP)
9747 GfxFrame[x][y - 1] = GfxFrame[x][y];
9748 else if (move_dir == MV_DOWN)
9749 GfxFrame[x][y + 1] = GfxFrame[x][y];
9756 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
9757 if (tile == Xsand_stonesand_quickout_1 ||
9758 tile == Xsand_stonesand_quickout_2)
9763 if (tile == Xsand_stonesand_1 ||
9764 tile == Xsand_stonesand_2 ||
9765 tile == Xsand_stonesand_3 ||
9766 tile == Xsand_stonesand_4)
9767 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9771 if (graphic_info[graphic].anim_global_sync)
9772 sync_frame = FrameCounter;
9773 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9774 sync_frame = GfxFrame[x][y];
9776 sync_frame = 0; /* playfield border (pseudo steel) */
9778 SetRandomAnimationValue(x, y);
9780 int frame = getAnimationFrame(g->anim_frames,
9783 g->anim_start_frame,
9786 g_em->unique_identifier =
9787 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
9791 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
9792 int tile, int frame_em, int x, int y)
9794 int action = object_mapping[tile].action;
9795 int direction = object_mapping[tile].direction;
9796 boolean is_backside = object_mapping[tile].is_backside;
9797 int effective_element = get_effective_element_EM(tile, frame_em);
9799 int effective_action = action;
9801 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
9803 int graphic = (direction == MV_NONE ?
9804 el_act2img(effective_element, effective_action) :
9805 el_act_dir2img(effective_element, effective_action,
9807 int crumbled = (direction == MV_NONE ?
9808 el_act2crm(effective_element, effective_action) :
9809 el_act_dir2crm(effective_element, effective_action,
9811 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9812 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9813 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9814 struct GraphicInfo *g = &graphic_info[graphic];
9816 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9820 /* special case: graphic uses "2nd movement tile" and has defined
9821 7 frames for movement animation (or less) => use default graphic
9822 for last (8th) frame which ends the movement animation */
9823 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9825 effective_action = ACTION_DEFAULT;
9826 graphic = (direction == MV_NONE ?
9827 el_act2img(effective_element, effective_action) :
9828 el_act_dir2img(effective_element, effective_action,
9830 crumbled = (direction == MV_NONE ?
9831 el_act2crm(effective_element, effective_action) :
9832 el_act_dir2crm(effective_element, effective_action,
9835 g = &graphic_info[graphic];
9845 if (frame_em == 0) /* reset animation frame for certain elements */
9847 if (check_linear_animation_EM(tile))
9852 if (graphic_info[graphic].anim_global_sync)
9853 sync_frame = FrameCounter;
9854 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9855 sync_frame = GfxFrame[x][y];
9857 sync_frame = 0; /* playfield border (pseudo steel) */
9859 SetRandomAnimationValue(x, y);
9864 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9865 i == Xdrip_stretchB ? 7 :
9866 i == Ydrip_s2 ? j + 8 :
9867 i == Ydrip_s2B ? j + 8 :
9876 i == Xfake_acid_1 ? 0 :
9877 i == Xfake_acid_2 ? 10 :
9878 i == Xfake_acid_3 ? 20 :
9879 i == Xfake_acid_4 ? 30 :
9880 i == Xfake_acid_5 ? 40 :
9881 i == Xfake_acid_6 ? 50 :
9882 i == Xfake_acid_7 ? 60 :
9883 i == Xfake_acid_8 ? 70 :
9885 i == Xball_2B ? j + 8 :
9886 i == Yball_eat ? j + 1 :
9887 i == Ykey_1_eat ? j + 1 :
9888 i == Ykey_2_eat ? j + 1 :
9889 i == Ykey_3_eat ? j + 1 :
9890 i == Ykey_4_eat ? j + 1 :
9891 i == Ykey_5_eat ? j + 1 :
9892 i == Ykey_6_eat ? j + 1 :
9893 i == Ykey_7_eat ? j + 1 :
9894 i == Ykey_8_eat ? j + 1 :
9895 i == Ylenses_eat ? j + 1 :
9896 i == Ymagnify_eat ? j + 1 :
9897 i == Ygrass_eat ? j + 1 :
9898 i == Ydirt_eat ? j + 1 :
9899 i == Xamoeba_1 ? 0 :
9900 i == Xamoeba_2 ? 1 :
9901 i == Xamoeba_3 ? 2 :
9902 i == Xamoeba_4 ? 3 :
9903 i == Xamoeba_5 ? 0 :
9904 i == Xamoeba_6 ? 1 :
9905 i == Xamoeba_7 ? 2 :
9906 i == Xamoeba_8 ? 3 :
9907 i == Xexit_2 ? j + 8 :
9908 i == Xexit_3 ? j + 16 :
9909 i == Xdynamite_1 ? 0 :
9910 i == Xdynamite_2 ? 8 :
9911 i == Xdynamite_3 ? 16 :
9912 i == Xdynamite_4 ? 24 :
9913 i == Xsand_stonein_1 ? j + 1 :
9914 i == Xsand_stonein_2 ? j + 9 :
9915 i == Xsand_stonein_3 ? j + 17 :
9916 i == Xsand_stonein_4 ? j + 25 :
9917 i == Xsand_stoneout_1 && j == 0 ? 0 :
9918 i == Xsand_stoneout_1 && j == 1 ? 0 :
9919 i == Xsand_stoneout_1 && j == 2 ? 1 :
9920 i == Xsand_stoneout_1 && j == 3 ? 2 :
9921 i == Xsand_stoneout_1 && j == 4 ? 2 :
9922 i == Xsand_stoneout_1 && j == 5 ? 3 :
9923 i == Xsand_stoneout_1 && j == 6 ? 4 :
9924 i == Xsand_stoneout_1 && j == 7 ? 4 :
9925 i == Xsand_stoneout_2 && j == 0 ? 5 :
9926 i == Xsand_stoneout_2 && j == 1 ? 6 :
9927 i == Xsand_stoneout_2 && j == 2 ? 7 :
9928 i == Xsand_stoneout_2 && j == 3 ? 8 :
9929 i == Xsand_stoneout_2 && j == 4 ? 9 :
9930 i == Xsand_stoneout_2 && j == 5 ? 11 :
9931 i == Xsand_stoneout_2 && j == 6 ? 13 :
9932 i == Xsand_stoneout_2 && j == 7 ? 15 :
9933 i == Xboom_bug && j == 1 ? 2 :
9934 i == Xboom_bug && j == 2 ? 2 :
9935 i == Xboom_bug && j == 3 ? 4 :
9936 i == Xboom_bug && j == 4 ? 4 :
9937 i == Xboom_bug && j == 5 ? 2 :
9938 i == Xboom_bug && j == 6 ? 2 :
9939 i == Xboom_bug && j == 7 ? 0 :
9940 i == Xboom_bomb && j == 1 ? 2 :
9941 i == Xboom_bomb && j == 2 ? 2 :
9942 i == Xboom_bomb && j == 3 ? 4 :
9943 i == Xboom_bomb && j == 4 ? 4 :
9944 i == Xboom_bomb && j == 5 ? 2 :
9945 i == Xboom_bomb && j == 6 ? 2 :
9946 i == Xboom_bomb && j == 7 ? 0 :
9947 i == Xboom_android && j == 7 ? 6 :
9948 i == Xboom_1 && j == 1 ? 2 :
9949 i == Xboom_1 && j == 2 ? 2 :
9950 i == Xboom_1 && j == 3 ? 4 :
9951 i == Xboom_1 && j == 4 ? 4 :
9952 i == Xboom_1 && j == 5 ? 6 :
9953 i == Xboom_1 && j == 6 ? 6 :
9954 i == Xboom_1 && j == 7 ? 8 :
9955 i == Xboom_2 && j == 0 ? 8 :
9956 i == Xboom_2 && j == 1 ? 8 :
9957 i == Xboom_2 && j == 2 ? 10 :
9958 i == Xboom_2 && j == 3 ? 10 :
9959 i == Xboom_2 && j == 4 ? 10 :
9960 i == Xboom_2 && j == 5 ? 12 :
9961 i == Xboom_2 && j == 6 ? 12 :
9962 i == Xboom_2 && j == 7 ? 12 :
9964 special_animation && j == 4 ? 3 :
9965 effective_action != action ? 0 :
9971 int xxx_effective_action;
9972 int xxx_has_action_graphics;
9975 int element = object_mapping[i].element_rnd;
9976 int action = object_mapping[i].action;
9977 int direction = object_mapping[i].direction;
9978 boolean is_backside = object_mapping[i].is_backside;
9980 boolean action_removing = (action == ACTION_DIGGING ||
9981 action == ACTION_SNAPPING ||
9982 action == ACTION_COLLECTING);
9984 boolean action_exploding = ((action == ACTION_EXPLODING ||
9985 action == ACTION_SMASHED_BY_ROCK ||
9986 action == ACTION_SMASHED_BY_SPRING) &&
9987 element != EL_DIAMOND);
9988 boolean action_active = (action == ACTION_ACTIVE);
9989 boolean action_other = (action == ACTION_OTHER);
9993 int effective_element = get_effective_element_EM(i, j);
9995 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
9996 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
9998 i == Xdrip_stretch ? element :
9999 i == Xdrip_stretchB ? element :
10000 i == Ydrip_s1 ? element :
10001 i == Ydrip_s1B ? element :
10002 i == Xball_1B ? element :
10003 i == Xball_2 ? element :
10004 i == Xball_2B ? element :
10005 i == Yball_eat ? element :
10006 i == Ykey_1_eat ? element :
10007 i == Ykey_2_eat ? element :
10008 i == Ykey_3_eat ? element :
10009 i == Ykey_4_eat ? element :
10010 i == Ykey_5_eat ? element :
10011 i == Ykey_6_eat ? element :
10012 i == Ykey_7_eat ? element :
10013 i == Ykey_8_eat ? element :
10014 i == Ylenses_eat ? element :
10015 i == Ymagnify_eat ? element :
10016 i == Ygrass_eat ? element :
10017 i == Ydirt_eat ? element :
10018 i == Yemerald_stone ? EL_EMERALD :
10019 i == Ydiamond_stone ? EL_ROCK :
10020 i == Xsand_stonein_1 ? element :
10021 i == Xsand_stonein_2 ? element :
10022 i == Xsand_stonein_3 ? element :
10023 i == Xsand_stonein_4 ? element :
10024 is_backside ? EL_EMPTY :
10025 action_removing ? EL_EMPTY :
10028 int effective_action = (j < 7 ? action :
10029 i == Xdrip_stretch ? action :
10030 i == Xdrip_stretchB ? action :
10031 i == Ydrip_s1 ? action :
10032 i == Ydrip_s1B ? action :
10033 i == Xball_1B ? action :
10034 i == Xball_2 ? action :
10035 i == Xball_2B ? action :
10036 i == Yball_eat ? action :
10037 i == Ykey_1_eat ? action :
10038 i == Ykey_2_eat ? action :
10039 i == Ykey_3_eat ? action :
10040 i == Ykey_4_eat ? action :
10041 i == Ykey_5_eat ? action :
10042 i == Ykey_6_eat ? action :
10043 i == Ykey_7_eat ? action :
10044 i == Ykey_8_eat ? action :
10045 i == Ylenses_eat ? action :
10046 i == Ymagnify_eat ? action :
10047 i == Ygrass_eat ? action :
10048 i == Ydirt_eat ? action :
10049 i == Xsand_stonein_1 ? action :
10050 i == Xsand_stonein_2 ? action :
10051 i == Xsand_stonein_3 ? action :
10052 i == Xsand_stonein_4 ? action :
10053 i == Xsand_stoneout_1 ? action :
10054 i == Xsand_stoneout_2 ? action :
10055 i == Xboom_android ? ACTION_EXPLODING :
10056 action_exploding ? ACTION_EXPLODING :
10057 action_active ? action :
10058 action_other ? action :
10060 int graphic = (el_act_dir2img(effective_element, effective_action,
10062 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10064 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10065 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10066 boolean has_action_graphics = (graphic != base_graphic);
10067 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10068 struct GraphicInfo *g = &graphic_info[graphic];
10070 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10072 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10073 Bitmap *src_bitmap;
10075 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10076 boolean special_animation = (action != ACTION_DEFAULT &&
10077 g->anim_frames == 3 &&
10078 g->anim_delay == 2 &&
10079 g->anim_mode & ANIM_LINEAR);
10080 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
10081 i == Xdrip_stretchB ? 7 :
10082 i == Ydrip_s2 ? j + 8 :
10083 i == Ydrip_s2B ? j + 8 :
10085 i == Xacid_2 ? 10 :
10086 i == Xacid_3 ? 20 :
10087 i == Xacid_4 ? 30 :
10088 i == Xacid_5 ? 40 :
10089 i == Xacid_6 ? 50 :
10090 i == Xacid_7 ? 60 :
10091 i == Xacid_8 ? 70 :
10092 i == Xfake_acid_1 ? 0 :
10093 i == Xfake_acid_2 ? 10 :
10094 i == Xfake_acid_3 ? 20 :
10095 i == Xfake_acid_4 ? 30 :
10096 i == Xfake_acid_5 ? 40 :
10097 i == Xfake_acid_6 ? 50 :
10098 i == Xfake_acid_7 ? 60 :
10099 i == Xfake_acid_8 ? 70 :
10101 i == Xball_2B ? j + 8 :
10102 i == Yball_eat ? j + 1 :
10103 i == Ykey_1_eat ? j + 1 :
10104 i == Ykey_2_eat ? j + 1 :
10105 i == Ykey_3_eat ? j + 1 :
10106 i == Ykey_4_eat ? j + 1 :
10107 i == Ykey_5_eat ? j + 1 :
10108 i == Ykey_6_eat ? j + 1 :
10109 i == Ykey_7_eat ? j + 1 :
10110 i == Ykey_8_eat ? j + 1 :
10111 i == Ylenses_eat ? j + 1 :
10112 i == Ymagnify_eat ? j + 1 :
10113 i == Ygrass_eat ? j + 1 :
10114 i == Ydirt_eat ? j + 1 :
10115 i == Xamoeba_1 ? 0 :
10116 i == Xamoeba_2 ? 1 :
10117 i == Xamoeba_3 ? 2 :
10118 i == Xamoeba_4 ? 3 :
10119 i == Xamoeba_5 ? 0 :
10120 i == Xamoeba_6 ? 1 :
10121 i == Xamoeba_7 ? 2 :
10122 i == Xamoeba_8 ? 3 :
10123 i == Xexit_2 ? j + 8 :
10124 i == Xexit_3 ? j + 16 :
10125 i == Xdynamite_1 ? 0 :
10126 i == Xdynamite_2 ? 8 :
10127 i == Xdynamite_3 ? 16 :
10128 i == Xdynamite_4 ? 24 :
10129 i == Xsand_stonein_1 ? j + 1 :
10130 i == Xsand_stonein_2 ? j + 9 :
10131 i == Xsand_stonein_3 ? j + 17 :
10132 i == Xsand_stonein_4 ? j + 25 :
10133 i == Xsand_stoneout_1 && j == 0 ? 0 :
10134 i == Xsand_stoneout_1 && j == 1 ? 0 :
10135 i == Xsand_stoneout_1 && j == 2 ? 1 :
10136 i == Xsand_stoneout_1 && j == 3 ? 2 :
10137 i == Xsand_stoneout_1 && j == 4 ? 2 :
10138 i == Xsand_stoneout_1 && j == 5 ? 3 :
10139 i == Xsand_stoneout_1 && j == 6 ? 4 :
10140 i == Xsand_stoneout_1 && j == 7 ? 4 :
10141 i == Xsand_stoneout_2 && j == 0 ? 5 :
10142 i == Xsand_stoneout_2 && j == 1 ? 6 :
10143 i == Xsand_stoneout_2 && j == 2 ? 7 :
10144 i == Xsand_stoneout_2 && j == 3 ? 8 :
10145 i == Xsand_stoneout_2 && j == 4 ? 9 :
10146 i == Xsand_stoneout_2 && j == 5 ? 11 :
10147 i == Xsand_stoneout_2 && j == 6 ? 13 :
10148 i == Xsand_stoneout_2 && j == 7 ? 15 :
10149 i == Xboom_bug && j == 1 ? 2 :
10150 i == Xboom_bug && j == 2 ? 2 :
10151 i == Xboom_bug && j == 3 ? 4 :
10152 i == Xboom_bug && j == 4 ? 4 :
10153 i == Xboom_bug && j == 5 ? 2 :
10154 i == Xboom_bug && j == 6 ? 2 :
10155 i == Xboom_bug && j == 7 ? 0 :
10156 i == Xboom_bomb && j == 1 ? 2 :
10157 i == Xboom_bomb && j == 2 ? 2 :
10158 i == Xboom_bomb && j == 3 ? 4 :
10159 i == Xboom_bomb && j == 4 ? 4 :
10160 i == Xboom_bomb && j == 5 ? 2 :
10161 i == Xboom_bomb && j == 6 ? 2 :
10162 i == Xboom_bomb && j == 7 ? 0 :
10163 i == Xboom_android && j == 7 ? 6 :
10164 i == Xboom_1 && j == 1 ? 2 :
10165 i == Xboom_1 && j == 2 ? 2 :
10166 i == Xboom_1 && j == 3 ? 4 :
10167 i == Xboom_1 && j == 4 ? 4 :
10168 i == Xboom_1 && j == 5 ? 6 :
10169 i == Xboom_1 && j == 6 ? 6 :
10170 i == Xboom_1 && j == 7 ? 8 :
10171 i == Xboom_2 && j == 0 ? 8 :
10172 i == Xboom_2 && j == 1 ? 8 :
10173 i == Xboom_2 && j == 2 ? 10 :
10174 i == Xboom_2 && j == 3 ? 10 :
10175 i == Xboom_2 && j == 4 ? 10 :
10176 i == Xboom_2 && j == 5 ? 12 :
10177 i == Xboom_2 && j == 6 ? 12 :
10178 i == Xboom_2 && j == 7 ? 12 :
10179 special_animation && j == 4 ? 3 :
10180 effective_action != action ? 0 :
10183 xxx_effective_action = effective_action;
10184 xxx_has_action_graphics = has_action_graphics;
10189 int frame = getAnimationFrame(g->anim_frames,
10192 g->anim_start_frame,
10206 int old_src_x = g_em->src_x;
10207 int old_src_y = g_em->src_y;
10211 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
10212 g->double_movement && is_backside);
10214 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10215 &g_em->src_x, &g_em->src_y, FALSE);
10220 if (tile == Ydiamond_stone)
10221 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
10226 g->anim_start_frame,
10229 g_em->src_x, g_em->src_y,
10230 g_em->src_offset_x, g_em->src_offset_y,
10231 g_em->dst_offset_x, g_em->dst_offset_y,
10243 if (graphic == IMG_BUG_MOVING_RIGHT)
10244 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
10245 g->double_movement, is_backside,
10246 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
10254 g_em->src_offset_x = 0;
10255 g_em->src_offset_y = 0;
10256 g_em->dst_offset_x = 0;
10257 g_em->dst_offset_y = 0;
10258 g_em->width = TILEX;
10259 g_em->height = TILEY;
10261 g_em->preserve_background = FALSE;
10264 /* (updating the "crumbled" graphic definitions is probably not really needed,
10265 as animations for crumbled graphics can't be longer than one EMC cycle) */
10267 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10272 g_em->crumbled_bitmap = NULL;
10273 g_em->crumbled_src_x = 0;
10274 g_em->crumbled_src_y = 0;
10276 g_em->has_crumbled_graphics = FALSE;
10278 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10280 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10281 g_crumbled->anim_delay,
10282 g_crumbled->anim_mode,
10283 g_crumbled->anim_start_frame,
10286 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
10287 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
10289 g_em->has_crumbled_graphics = TRUE;
10295 int effective_action = xxx_effective_action;
10296 int has_action_graphics = xxx_has_action_graphics;
10298 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10299 effective_action == ACTION_MOVING ||
10300 effective_action == ACTION_PUSHING ||
10301 effective_action == ACTION_EATING)) ||
10302 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10303 effective_action == ACTION_EMPTYING)))
10306 (effective_action == ACTION_FALLING ||
10307 effective_action == ACTION_FILLING ||
10308 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10309 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10310 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10311 int num_steps = (i == Ydrip_s1 ? 16 :
10312 i == Ydrip_s1B ? 16 :
10313 i == Ydrip_s2 ? 16 :
10314 i == Ydrip_s2B ? 16 :
10315 i == Xsand_stonein_1 ? 32 :
10316 i == Xsand_stonein_2 ? 32 :
10317 i == Xsand_stonein_3 ? 32 :
10318 i == Xsand_stonein_4 ? 32 :
10319 i == Xsand_stoneout_1 ? 16 :
10320 i == Xsand_stoneout_2 ? 16 : 8);
10321 int cx = ABS(dx) * (TILEX / num_steps);
10322 int cy = ABS(dy) * (TILEY / num_steps);
10323 int step_frame = (i == Ydrip_s2 ? j + 8 :
10324 i == Ydrip_s2B ? j + 8 :
10325 i == Xsand_stonein_2 ? j + 8 :
10326 i == Xsand_stonein_3 ? j + 16 :
10327 i == Xsand_stonein_4 ? j + 24 :
10328 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10329 int step = (is_backside ? step_frame : num_steps - step_frame);
10331 if (is_backside) /* tile where movement starts */
10333 if (dx < 0 || dy < 0)
10335 g_em->src_offset_x = cx * step;
10336 g_em->src_offset_y = cy * step;
10340 g_em->dst_offset_x = cx * step;
10341 g_em->dst_offset_y = cy * step;
10344 else /* tile where movement ends */
10346 if (dx < 0 || dy < 0)
10348 g_em->dst_offset_x = cx * step;
10349 g_em->dst_offset_y = cy * step;
10353 g_em->src_offset_x = cx * step;
10354 g_em->src_offset_y = cy * step;
10358 g_em->width = TILEX - cx * step;
10359 g_em->height = TILEY - cy * step;
10362 /* create unique graphic identifier to decide if tile must be redrawn */
10363 /* bit 31 - 16 (16 bit): EM style graphic
10364 bit 15 - 12 ( 4 bit): EM style frame
10365 bit 11 - 6 ( 6 bit): graphic width
10366 bit 5 - 0 ( 6 bit): graphic height */
10367 g_em->unique_identifier =
10368 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10374 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
10375 int player_nr, int anim, int frame_em)
10377 int element = player_mapping[player_nr][anim].element_rnd;
10378 int action = player_mapping[player_nr][anim].action;
10379 int direction = player_mapping[player_nr][anim].direction;
10380 int graphic = (direction == MV_NONE ?
10381 el_act2img(element, action) :
10382 el_act_dir2img(element, action, direction));
10383 struct GraphicInfo *g = &graphic_info[graphic];
10386 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
10388 stored_player[player_nr].StepFrame = frame_em;
10390 sync_frame = stored_player[player_nr].Frame;
10392 int frame = getAnimationFrame(g->anim_frames,
10395 g->anim_start_frame,
10398 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10399 &g_em->src_x, &g_em->src_y, FALSE);
10402 printf("::: %d: %d, %d [%d]\n",
10404 stored_player[player_nr].Frame,
10405 stored_player[player_nr].StepFrame,
10410 void InitGraphicInfo_EM(void)
10413 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
10414 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
10419 int num_em_gfx_errors = 0;
10421 if (graphic_info_em_object[0][0].bitmap == NULL)
10423 /* EM graphics not yet initialized in em_open_all() */
10428 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
10431 /* always start with reliable default values */
10432 for (i = 0; i < TILE_MAX; i++)
10434 object_mapping[i].element_rnd = EL_UNKNOWN;
10435 object_mapping[i].is_backside = FALSE;
10436 object_mapping[i].action = ACTION_DEFAULT;
10437 object_mapping[i].direction = MV_NONE;
10440 /* always start with reliable default values */
10441 for (p = 0; p < MAX_PLAYERS; p++)
10443 for (i = 0; i < SPR_MAX; i++)
10445 player_mapping[p][i].element_rnd = EL_UNKNOWN;
10446 player_mapping[p][i].action = ACTION_DEFAULT;
10447 player_mapping[p][i].direction = MV_NONE;
10451 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
10453 int e = em_object_mapping_list[i].element_em;
10455 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
10456 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
10458 if (em_object_mapping_list[i].action != -1)
10459 object_mapping[e].action = em_object_mapping_list[i].action;
10461 if (em_object_mapping_list[i].direction != -1)
10462 object_mapping[e].direction =
10463 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
10466 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
10468 int a = em_player_mapping_list[i].action_em;
10469 int p = em_player_mapping_list[i].player_nr;
10471 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
10473 if (em_player_mapping_list[i].action != -1)
10474 player_mapping[p][a].action = em_player_mapping_list[i].action;
10476 if (em_player_mapping_list[i].direction != -1)
10477 player_mapping[p][a].direction =
10478 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
10481 for (i = 0; i < TILE_MAX; i++)
10483 int element = object_mapping[i].element_rnd;
10484 int action = object_mapping[i].action;
10485 int direction = object_mapping[i].direction;
10486 boolean is_backside = object_mapping[i].is_backside;
10488 boolean action_removing = (action == ACTION_DIGGING ||
10489 action == ACTION_SNAPPING ||
10490 action == ACTION_COLLECTING);
10492 boolean action_exploding = ((action == ACTION_EXPLODING ||
10493 action == ACTION_SMASHED_BY_ROCK ||
10494 action == ACTION_SMASHED_BY_SPRING) &&
10495 element != EL_DIAMOND);
10496 boolean action_active = (action == ACTION_ACTIVE);
10497 boolean action_other = (action == ACTION_OTHER);
10499 for (j = 0; j < 8; j++)
10502 int effective_element = get_effective_element_EM(i, j);
10504 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
10505 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
10507 i == Xdrip_stretch ? element :
10508 i == Xdrip_stretchB ? element :
10509 i == Ydrip_s1 ? element :
10510 i == Ydrip_s1B ? element :
10511 i == Xball_1B ? element :
10512 i == Xball_2 ? element :
10513 i == Xball_2B ? element :
10514 i == Yball_eat ? element :
10515 i == Ykey_1_eat ? element :
10516 i == Ykey_2_eat ? element :
10517 i == Ykey_3_eat ? element :
10518 i == Ykey_4_eat ? element :
10519 i == Ykey_5_eat ? element :
10520 i == Ykey_6_eat ? element :
10521 i == Ykey_7_eat ? element :
10522 i == Ykey_8_eat ? element :
10523 i == Ylenses_eat ? element :
10524 i == Ymagnify_eat ? element :
10525 i == Ygrass_eat ? element :
10526 i == Ydirt_eat ? element :
10527 i == Yemerald_stone ? EL_EMERALD :
10528 i == Ydiamond_stone ? EL_ROCK :
10529 i == Xsand_stonein_1 ? element :
10530 i == Xsand_stonein_2 ? element :
10531 i == Xsand_stonein_3 ? element :
10532 i == Xsand_stonein_4 ? element :
10533 is_backside ? EL_EMPTY :
10534 action_removing ? EL_EMPTY :
10537 int effective_action = (j < 7 ? action :
10538 i == Xdrip_stretch ? action :
10539 i == Xdrip_stretchB ? action :
10540 i == Ydrip_s1 ? action :
10541 i == Ydrip_s1B ? action :
10542 i == Xball_1B ? action :
10543 i == Xball_2 ? action :
10544 i == Xball_2B ? action :
10545 i == Yball_eat ? action :
10546 i == Ykey_1_eat ? action :
10547 i == Ykey_2_eat ? action :
10548 i == Ykey_3_eat ? action :
10549 i == Ykey_4_eat ? action :
10550 i == Ykey_5_eat ? action :
10551 i == Ykey_6_eat ? action :
10552 i == Ykey_7_eat ? action :
10553 i == Ykey_8_eat ? action :
10554 i == Ylenses_eat ? action :
10555 i == Ymagnify_eat ? action :
10556 i == Ygrass_eat ? action :
10557 i == Ydirt_eat ? action :
10558 i == Xsand_stonein_1 ? action :
10559 i == Xsand_stonein_2 ? action :
10560 i == Xsand_stonein_3 ? action :
10561 i == Xsand_stonein_4 ? action :
10562 i == Xsand_stoneout_1 ? action :
10563 i == Xsand_stoneout_2 ? action :
10564 i == Xboom_android ? ACTION_EXPLODING :
10565 action_exploding ? ACTION_EXPLODING :
10566 action_active ? action :
10567 action_other ? action :
10569 int graphic = (el_act_dir2img(effective_element, effective_action,
10571 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10573 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10574 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10575 boolean has_action_graphics = (graphic != base_graphic);
10576 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10577 struct GraphicInfo *g = &graphic_info[graphic];
10579 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10581 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10582 Bitmap *src_bitmap;
10584 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10585 boolean special_animation = (action != ACTION_DEFAULT &&
10586 g->anim_frames == 3 &&
10587 g->anim_delay == 2 &&
10588 g->anim_mode & ANIM_LINEAR);
10589 int sync_frame = (i == Xdrip_stretch ? 7 :
10590 i == Xdrip_stretchB ? 7 :
10591 i == Ydrip_s2 ? j + 8 :
10592 i == Ydrip_s2B ? j + 8 :
10594 i == Xacid_2 ? 10 :
10595 i == Xacid_3 ? 20 :
10596 i == Xacid_4 ? 30 :
10597 i == Xacid_5 ? 40 :
10598 i == Xacid_6 ? 50 :
10599 i == Xacid_7 ? 60 :
10600 i == Xacid_8 ? 70 :
10601 i == Xfake_acid_1 ? 0 :
10602 i == Xfake_acid_2 ? 10 :
10603 i == Xfake_acid_3 ? 20 :
10604 i == Xfake_acid_4 ? 30 :
10605 i == Xfake_acid_5 ? 40 :
10606 i == Xfake_acid_6 ? 50 :
10607 i == Xfake_acid_7 ? 60 :
10608 i == Xfake_acid_8 ? 70 :
10610 i == Xball_2B ? j + 8 :
10611 i == Yball_eat ? j + 1 :
10612 i == Ykey_1_eat ? j + 1 :
10613 i == Ykey_2_eat ? j + 1 :
10614 i == Ykey_3_eat ? j + 1 :
10615 i == Ykey_4_eat ? j + 1 :
10616 i == Ykey_5_eat ? j + 1 :
10617 i == Ykey_6_eat ? j + 1 :
10618 i == Ykey_7_eat ? j + 1 :
10619 i == Ykey_8_eat ? j + 1 :
10620 i == Ylenses_eat ? j + 1 :
10621 i == Ymagnify_eat ? j + 1 :
10622 i == Ygrass_eat ? j + 1 :
10623 i == Ydirt_eat ? j + 1 :
10624 i == Xamoeba_1 ? 0 :
10625 i == Xamoeba_2 ? 1 :
10626 i == Xamoeba_3 ? 2 :
10627 i == Xamoeba_4 ? 3 :
10628 i == Xamoeba_5 ? 0 :
10629 i == Xamoeba_6 ? 1 :
10630 i == Xamoeba_7 ? 2 :
10631 i == Xamoeba_8 ? 3 :
10632 i == Xexit_2 ? j + 8 :
10633 i == Xexit_3 ? j + 16 :
10634 i == Xdynamite_1 ? 0 :
10635 i == Xdynamite_2 ? 8 :
10636 i == Xdynamite_3 ? 16 :
10637 i == Xdynamite_4 ? 24 :
10638 i == Xsand_stonein_1 ? j + 1 :
10639 i == Xsand_stonein_2 ? j + 9 :
10640 i == Xsand_stonein_3 ? j + 17 :
10641 i == Xsand_stonein_4 ? j + 25 :
10642 i == Xsand_stoneout_1 && j == 0 ? 0 :
10643 i == Xsand_stoneout_1 && j == 1 ? 0 :
10644 i == Xsand_stoneout_1 && j == 2 ? 1 :
10645 i == Xsand_stoneout_1 && j == 3 ? 2 :
10646 i == Xsand_stoneout_1 && j == 4 ? 2 :
10647 i == Xsand_stoneout_1 && j == 5 ? 3 :
10648 i == Xsand_stoneout_1 && j == 6 ? 4 :
10649 i == Xsand_stoneout_1 && j == 7 ? 4 :
10650 i == Xsand_stoneout_2 && j == 0 ? 5 :
10651 i == Xsand_stoneout_2 && j == 1 ? 6 :
10652 i == Xsand_stoneout_2 && j == 2 ? 7 :
10653 i == Xsand_stoneout_2 && j == 3 ? 8 :
10654 i == Xsand_stoneout_2 && j == 4 ? 9 :
10655 i == Xsand_stoneout_2 && j == 5 ? 11 :
10656 i == Xsand_stoneout_2 && j == 6 ? 13 :
10657 i == Xsand_stoneout_2 && j == 7 ? 15 :
10658 i == Xboom_bug && j == 1 ? 2 :
10659 i == Xboom_bug && j == 2 ? 2 :
10660 i == Xboom_bug && j == 3 ? 4 :
10661 i == Xboom_bug && j == 4 ? 4 :
10662 i == Xboom_bug && j == 5 ? 2 :
10663 i == Xboom_bug && j == 6 ? 2 :
10664 i == Xboom_bug && j == 7 ? 0 :
10665 i == Xboom_bomb && j == 1 ? 2 :
10666 i == Xboom_bomb && j == 2 ? 2 :
10667 i == Xboom_bomb && j == 3 ? 4 :
10668 i == Xboom_bomb && j == 4 ? 4 :
10669 i == Xboom_bomb && j == 5 ? 2 :
10670 i == Xboom_bomb && j == 6 ? 2 :
10671 i == Xboom_bomb && j == 7 ? 0 :
10672 i == Xboom_android && j == 7 ? 6 :
10673 i == Xboom_1 && j == 1 ? 2 :
10674 i == Xboom_1 && j == 2 ? 2 :
10675 i == Xboom_1 && j == 3 ? 4 :
10676 i == Xboom_1 && j == 4 ? 4 :
10677 i == Xboom_1 && j == 5 ? 6 :
10678 i == Xboom_1 && j == 6 ? 6 :
10679 i == Xboom_1 && j == 7 ? 8 :
10680 i == Xboom_2 && j == 0 ? 8 :
10681 i == Xboom_2 && j == 1 ? 8 :
10682 i == Xboom_2 && j == 2 ? 10 :
10683 i == Xboom_2 && j == 3 ? 10 :
10684 i == Xboom_2 && j == 4 ? 10 :
10685 i == Xboom_2 && j == 5 ? 12 :
10686 i == Xboom_2 && j == 6 ? 12 :
10687 i == Xboom_2 && j == 7 ? 12 :
10688 special_animation && j == 4 ? 3 :
10689 effective_action != action ? 0 :
10693 Bitmap *debug_bitmap = g_em->bitmap;
10694 int debug_src_x = g_em->src_x;
10695 int debug_src_y = g_em->src_y;
10698 int frame = getAnimationFrame(g->anim_frames,
10701 g->anim_start_frame,
10704 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
10705 g->double_movement && is_backside);
10707 g_em->bitmap = src_bitmap;
10708 g_em->src_x = src_x;
10709 g_em->src_y = src_y;
10710 g_em->src_offset_x = 0;
10711 g_em->src_offset_y = 0;
10712 g_em->dst_offset_x = 0;
10713 g_em->dst_offset_y = 0;
10714 g_em->width = TILEX;
10715 g_em->height = TILEY;
10717 g_em->preserve_background = FALSE;
10720 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10725 g_em->crumbled_bitmap = NULL;
10726 g_em->crumbled_src_x = 0;
10727 g_em->crumbled_src_y = 0;
10728 g_em->crumbled_border_size = 0;
10730 g_em->has_crumbled_graphics = FALSE;
10733 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
10734 printf("::: empty crumbled: %d [%s], %d, %d\n",
10735 effective_element, element_info[effective_element].token_name,
10736 effective_action, direction);
10739 /* if element can be crumbled, but certain action graphics are just empty
10740 space (like instantly snapping sand to empty space in 1 frame), do not
10741 treat these empty space graphics as crumbled graphics in EMC engine */
10742 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10744 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10745 g_crumbled->anim_delay,
10746 g_crumbled->anim_mode,
10747 g_crumbled->anim_start_frame,
10750 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
10752 g_em->has_crumbled_graphics = TRUE;
10753 g_em->crumbled_bitmap = src_bitmap;
10754 g_em->crumbled_src_x = src_x;
10755 g_em->crumbled_src_y = src_y;
10756 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
10760 if (g_em == &graphic_info_em_object[207][0])
10761 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
10762 graphic_info_em_object[207][0].crumbled_src_x,
10763 graphic_info_em_object[207][0].crumbled_src_y,
10765 crumbled, frame, src_x, src_y,
10770 g->anim_start_frame,
10772 gfx.anim_random_frame,
10777 printf("::: EMC tile %d is crumbled\n", i);
10783 if (element == EL_ROCK &&
10784 effective_action == ACTION_FILLING)
10785 printf("::: has_action_graphics == %d\n", has_action_graphics);
10788 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10789 effective_action == ACTION_MOVING ||
10790 effective_action == ACTION_PUSHING ||
10791 effective_action == ACTION_EATING)) ||
10792 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10793 effective_action == ACTION_EMPTYING)))
10796 (effective_action == ACTION_FALLING ||
10797 effective_action == ACTION_FILLING ||
10798 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10799 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10800 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10801 int num_steps = (i == Ydrip_s1 ? 16 :
10802 i == Ydrip_s1B ? 16 :
10803 i == Ydrip_s2 ? 16 :
10804 i == Ydrip_s2B ? 16 :
10805 i == Xsand_stonein_1 ? 32 :
10806 i == Xsand_stonein_2 ? 32 :
10807 i == Xsand_stonein_3 ? 32 :
10808 i == Xsand_stonein_4 ? 32 :
10809 i == Xsand_stoneout_1 ? 16 :
10810 i == Xsand_stoneout_2 ? 16 : 8);
10811 int cx = ABS(dx) * (TILEX / num_steps);
10812 int cy = ABS(dy) * (TILEY / num_steps);
10813 int step_frame = (i == Ydrip_s2 ? j + 8 :
10814 i == Ydrip_s2B ? j + 8 :
10815 i == Xsand_stonein_2 ? j + 8 :
10816 i == Xsand_stonein_3 ? j + 16 :
10817 i == Xsand_stonein_4 ? j + 24 :
10818 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10819 int step = (is_backside ? step_frame : num_steps - step_frame);
10821 if (is_backside) /* tile where movement starts */
10823 if (dx < 0 || dy < 0)
10825 g_em->src_offset_x = cx * step;
10826 g_em->src_offset_y = cy * step;
10830 g_em->dst_offset_x = cx * step;
10831 g_em->dst_offset_y = cy * step;
10834 else /* tile where movement ends */
10836 if (dx < 0 || dy < 0)
10838 g_em->dst_offset_x = cx * step;
10839 g_em->dst_offset_y = cy * step;
10843 g_em->src_offset_x = cx * step;
10844 g_em->src_offset_y = cy * step;
10848 g_em->width = TILEX - cx * step;
10849 g_em->height = TILEY - cy * step;
10852 /* create unique graphic identifier to decide if tile must be redrawn */
10853 /* bit 31 - 16 (16 bit): EM style graphic
10854 bit 15 - 12 ( 4 bit): EM style frame
10855 bit 11 - 6 ( 6 bit): graphic width
10856 bit 5 - 0 ( 6 bit): graphic height */
10857 g_em->unique_identifier =
10858 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10862 /* skip check for EMC elements not contained in original EMC artwork */
10863 if (element == EL_EMC_FAKE_ACID)
10866 if (g_em->bitmap != debug_bitmap ||
10867 g_em->src_x != debug_src_x ||
10868 g_em->src_y != debug_src_y ||
10869 g_em->src_offset_x != 0 ||
10870 g_em->src_offset_y != 0 ||
10871 g_em->dst_offset_x != 0 ||
10872 g_em->dst_offset_y != 0 ||
10873 g_em->width != TILEX ||
10874 g_em->height != TILEY)
10876 static int last_i = -1;
10884 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
10885 i, element, element_info[element].token_name,
10886 element_action_info[effective_action].suffix, direction);
10888 if (element != effective_element)
10889 printf(" [%d ('%s')]",
10891 element_info[effective_element].token_name);
10895 if (g_em->bitmap != debug_bitmap)
10896 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
10897 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
10899 if (g_em->src_x != debug_src_x ||
10900 g_em->src_y != debug_src_y)
10901 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10902 j, (is_backside ? 'B' : 'F'),
10903 g_em->src_x, g_em->src_y,
10904 g_em->src_x / 32, g_em->src_y / 32,
10905 debug_src_x, debug_src_y,
10906 debug_src_x / 32, debug_src_y / 32);
10908 if (g_em->src_offset_x != 0 ||
10909 g_em->src_offset_y != 0 ||
10910 g_em->dst_offset_x != 0 ||
10911 g_em->dst_offset_y != 0)
10912 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
10914 g_em->src_offset_x, g_em->src_offset_y,
10915 g_em->dst_offset_x, g_em->dst_offset_y);
10917 if (g_em->width != TILEX ||
10918 g_em->height != TILEY)
10919 printf(" %d (%d): size %d,%d should be %d,%d\n",
10921 g_em->width, g_em->height, TILEX, TILEY);
10923 num_em_gfx_errors++;
10930 for (i = 0; i < TILE_MAX; i++)
10932 for (j = 0; j < 8; j++)
10934 int element = object_mapping[i].element_rnd;
10935 int action = object_mapping[i].action;
10936 int direction = object_mapping[i].direction;
10937 boolean is_backside = object_mapping[i].is_backside;
10938 int graphic_action = el_act_dir2img(element, action, direction);
10939 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
10941 if ((action == ACTION_SMASHED_BY_ROCK ||
10942 action == ACTION_SMASHED_BY_SPRING ||
10943 action == ACTION_EATING) &&
10944 graphic_action == graphic_default)
10946 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
10947 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
10948 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
10949 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
10952 /* no separate animation for "smashed by rock" -- use rock instead */
10953 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10954 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
10956 g_em->bitmap = g_xx->bitmap;
10957 g_em->src_x = g_xx->src_x;
10958 g_em->src_y = g_xx->src_y;
10959 g_em->src_offset_x = g_xx->src_offset_x;
10960 g_em->src_offset_y = g_xx->src_offset_y;
10961 g_em->dst_offset_x = g_xx->dst_offset_x;
10962 g_em->dst_offset_y = g_xx->dst_offset_y;
10963 g_em->width = g_xx->width;
10964 g_em->height = g_xx->height;
10965 g_em->unique_identifier = g_xx->unique_identifier;
10968 g_em->preserve_background = TRUE;
10973 for (p = 0; p < MAX_PLAYERS; p++)
10975 for (i = 0; i < SPR_MAX; i++)
10977 int element = player_mapping[p][i].element_rnd;
10978 int action = player_mapping[p][i].action;
10979 int direction = player_mapping[p][i].direction;
10981 for (j = 0; j < 8; j++)
10983 int effective_element = element;
10984 int effective_action = action;
10985 int graphic = (direction == MV_NONE ?
10986 el_act2img(effective_element, effective_action) :
10987 el_act_dir2img(effective_element, effective_action,
10989 struct GraphicInfo *g = &graphic_info[graphic];
10990 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
10991 Bitmap *src_bitmap;
10993 int sync_frame = j;
10996 Bitmap *debug_bitmap = g_em->bitmap;
10997 int debug_src_x = g_em->src_x;
10998 int debug_src_y = g_em->src_y;
11001 int frame = getAnimationFrame(g->anim_frames,
11004 g->anim_start_frame,
11007 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
11009 g_em->bitmap = src_bitmap;
11010 g_em->src_x = src_x;
11011 g_em->src_y = src_y;
11012 g_em->src_offset_x = 0;
11013 g_em->src_offset_y = 0;
11014 g_em->dst_offset_x = 0;
11015 g_em->dst_offset_y = 0;
11016 g_em->width = TILEX;
11017 g_em->height = TILEY;
11021 /* skip check for EMC elements not contained in original EMC artwork */
11022 if (element == EL_PLAYER_3 ||
11023 element == EL_PLAYER_4)
11026 if (g_em->bitmap != debug_bitmap ||
11027 g_em->src_x != debug_src_x ||
11028 g_em->src_y != debug_src_y)
11030 static int last_i = -1;
11038 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
11039 p, i, element, element_info[element].token_name,
11040 element_action_info[effective_action].suffix, direction);
11042 if (element != effective_element)
11043 printf(" [%d ('%s')]",
11045 element_info[effective_element].token_name);
11049 if (g_em->bitmap != debug_bitmap)
11050 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
11051 j, (int)(g_em->bitmap), (int)(debug_bitmap));
11053 if (g_em->src_x != debug_src_x ||
11054 g_em->src_y != debug_src_y)
11055 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
11057 g_em->src_x, g_em->src_y,
11058 g_em->src_x / 32, g_em->src_y / 32,
11059 debug_src_x, debug_src_y,
11060 debug_src_x / 32, debug_src_y / 32);
11062 num_em_gfx_errors++;
11072 printf("::: [%d errors found]\n", num_em_gfx_errors);
11078 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
11079 boolean any_player_moving,
11080 boolean player_is_dropping)
11082 if (tape.single_step && tape.recording && !tape.pausing)
11085 boolean active_players = FALSE;
11088 for (i = 0; i < MAX_PLAYERS; i++)
11089 if (action[i] != JOY_NO_ACTION)
11090 active_players = TRUE;
11094 if (frame == 0 && !player_is_dropping)
11095 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11099 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
11100 boolean murphy_is_dropping)
11103 printf("::: waiting: %d, dropping: %d\n",
11104 murphy_is_waiting, murphy_is_dropping);
11107 if (tape.single_step && tape.recording && !tape.pausing)
11109 // if (murphy_is_waiting || murphy_is_dropping)
11110 if (murphy_is_waiting)
11113 printf("::: murphy is waiting -> pause mode\n");
11116 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11121 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
11122 int graphic, int sync_frame, int x, int y)
11124 int frame = getGraphicAnimationFrame(graphic, sync_frame);
11126 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
11129 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
11131 return (IS_NEXT_FRAME(sync_frame, graphic));
11134 int getGraphicInfo_Delay(int graphic)
11136 return graphic_info[graphic].anim_delay;
11139 void PlayMenuSoundExt(int sound)
11141 if (sound == SND_UNDEFINED)
11144 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11145 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11148 if (IS_LOOP_SOUND(sound))
11149 PlaySoundLoop(sound);
11154 void PlayMenuSound()
11156 PlayMenuSoundExt(menu.sound[game_status]);
11159 void PlayMenuSoundStereo(int sound, int stereo_position)
11161 if (sound == SND_UNDEFINED)
11164 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11165 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11168 if (IS_LOOP_SOUND(sound))
11169 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
11171 PlaySoundStereo(sound, stereo_position);
11174 void PlayMenuSoundIfLoopExt(int sound)
11176 if (sound == SND_UNDEFINED)
11179 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11180 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11183 if (IS_LOOP_SOUND(sound))
11184 PlaySoundLoop(sound);
11187 void PlayMenuSoundIfLoop()
11189 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
11192 void PlayMenuMusicExt(int music)
11194 if (music == MUS_UNDEFINED)
11197 if (!setup.sound_music)
11203 void PlayMenuMusic()
11205 PlayMenuMusicExt(menu.music[game_status]);
11208 void PlaySoundActivating()
11211 PlaySound(SND_MENU_ITEM_ACTIVATING);
11215 void PlaySoundSelecting()
11218 PlaySound(SND_MENU_ITEM_SELECTING);
11222 void ToggleFullscreenOrChangeWindowScalingIfNeeded()
11224 boolean change_fullscreen = (setup.fullscreen !=
11225 video.fullscreen_enabled);
11226 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
11227 !strEqual(setup.fullscreen_mode,
11228 video.fullscreen_mode_current));
11229 boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
11230 setup.window_scaling_percent !=
11231 video.window_scaling_percent);
11233 if (change_window_scaling_percent && video.fullscreen_enabled)
11236 if (!change_window_scaling_percent && !video.fullscreen_available)
11239 #if defined(TARGET_SDL2)
11240 if (change_window_scaling_percent)
11242 SDLSetWindowScaling(setup.window_scaling_percent);
11246 else if (change_fullscreen)
11248 SDLSetWindowFullscreen(setup.fullscreen);
11250 /* set setup value according to successfully changed fullscreen mode */
11251 setup.fullscreen = video.fullscreen_enabled;
11257 if (change_fullscreen ||
11258 change_fullscreen_mode ||
11259 change_window_scaling_percent)
11261 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
11263 /* save backbuffer content which gets lost when toggling fullscreen mode */
11264 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11266 if (change_fullscreen_mode)
11268 /* keep fullscreen, but change fullscreen mode (screen resolution) */
11269 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
11272 if (change_window_scaling_percent)
11274 /* keep window mode, but change window scaling */
11275 video.fullscreen_enabled = TRUE; /* force new window scaling */
11278 /* toggle fullscreen */
11279 ChangeVideoModeIfNeeded(setup.fullscreen);
11281 /* set setup value according to successfully changed fullscreen mode */
11282 setup.fullscreen = video.fullscreen_enabled;
11284 /* restore backbuffer content from temporary backbuffer backup bitmap */
11285 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11287 FreeBitmap(tmp_backbuffer);
11290 /* update visible window/screen */
11291 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11293 redraw_mask = REDRAW_ALL;
11298 void ChangeViewportPropertiesIfNeeded()
11301 int *door_1_x = &DX;
11302 int *door_1_y = &DY;
11303 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
11304 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
11307 int gfx_game_mode = game_status;
11309 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
11310 game_status == GAME_MODE_EDITOR ? game_status :
11313 int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
11315 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
11316 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
11317 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
11318 struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
11319 int border_size = vp_playfield->border_size;
11320 int new_sx = vp_playfield->x + border_size;
11321 int new_sy = vp_playfield->y + border_size;
11322 int new_sxsize = vp_playfield->width - 2 * border_size;
11323 int new_sysize = vp_playfield->height - 2 * border_size;
11324 int new_real_sx = vp_playfield->x;
11325 int new_real_sy = vp_playfield->y;
11326 int new_full_sxsize = vp_playfield->width;
11327 int new_full_sysize = vp_playfield->height;
11328 int new_dx = vp_door_1->x;
11329 int new_dy = vp_door_1->y;
11330 int new_dxsize = vp_door_1->width;
11331 int new_dysize = vp_door_1->height;
11332 int new_vx = vp_door_2->x;
11333 int new_vy = vp_door_2->y;
11334 int new_vxsize = vp_door_2->width;
11335 int new_vysize = vp_door_2->height;
11336 int new_ex = vp_door_3->x;
11337 int new_ey = vp_door_3->y;
11338 int new_exsize = vp_door_3->width;
11339 int new_eysize = vp_door_3->height;
11341 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
11342 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
11343 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
11344 int new_scr_fieldx = new_sxsize / tilesize;
11345 int new_scr_fieldy = new_sysize / tilesize;
11346 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
11347 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
11349 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
11350 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
11352 boolean init_gfx_buffers = FALSE;
11353 boolean init_video_buffer = FALSE;
11354 boolean init_gadgets_and_toons = FALSE;
11357 /* !!! TEST ONLY !!! */
11358 // InitGfxBuffers();
11362 if (viewport.window.width != WIN_XSIZE ||
11363 viewport.window.height != WIN_YSIZE)
11365 WIN_XSIZE = viewport.window.width;
11366 WIN_YSIZE = viewport.window.height;
11369 init_video_buffer = TRUE;
11370 init_gfx_buffers = TRUE;
11372 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11376 SetDrawDeactivationMask(REDRAW_NONE);
11377 SetDrawBackgroundMask(REDRAW_FIELD);
11379 // RedrawBackground();
11383 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
11386 if (new_scr_fieldx != SCR_FIELDX ||
11387 new_scr_fieldy != SCR_FIELDY)
11389 /* this always toggles between MAIN and GAME when using small tile size */
11391 SCR_FIELDX = new_scr_fieldx;
11392 SCR_FIELDY = new_scr_fieldy;
11394 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
11398 if (new_tilesize_var != TILESIZE_VAR &&
11399 gfx_game_mode == GAME_MODE_PLAYING)
11401 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
11403 TILESIZE_VAR = new_tilesize_var;
11405 init_gfx_buffers = TRUE;
11407 // printf("::: tilesize: init_gfx_buffers\n");
11411 if (new_sx != SX ||
11419 new_sxsize != SXSIZE ||
11420 new_sysize != SYSIZE ||
11421 new_dxsize != DXSIZE ||
11422 new_dysize != DYSIZE ||
11423 new_vxsize != VXSIZE ||
11424 new_vysize != VYSIZE ||
11425 new_exsize != EXSIZE ||
11426 new_eysize != EYSIZE ||
11427 new_real_sx != REAL_SX ||
11428 new_real_sy != REAL_SY ||
11429 new_full_sxsize != FULL_SXSIZE ||
11430 new_full_sysize != FULL_SYSIZE ||
11431 new_tilesize_var != TILESIZE_VAR
11434 vp_door_1->x != *door_1_x ||
11435 vp_door_1->y != *door_1_y ||
11436 vp_door_2->x != *door_2_x ||
11437 vp_door_2->y != *door_2_y
11449 SXSIZE = new_sxsize;
11450 SYSIZE = new_sysize;
11451 DXSIZE = new_dxsize;
11452 DYSIZE = new_dysize;
11453 VXSIZE = new_vxsize;
11454 VYSIZE = new_vysize;
11455 EXSIZE = new_exsize;
11456 EYSIZE = new_eysize;
11457 REAL_SX = new_real_sx;
11458 REAL_SY = new_real_sy;
11459 FULL_SXSIZE = new_full_sxsize;
11460 FULL_SYSIZE = new_full_sysize;
11461 TILESIZE_VAR = new_tilesize_var;
11464 printf("::: %d, %d, %d [%d]\n",
11465 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
11466 setup.small_game_graphics);
11470 *door_1_x = vp_door_1->x;
11471 *door_1_y = vp_door_1->y;
11472 *door_2_x = vp_door_2->x;
11473 *door_2_y = vp_door_2->y;
11477 init_gfx_buffers = TRUE;
11479 // printf("::: viewports: init_gfx_buffers\n");
11485 if (gfx_game_mode == GAME_MODE_MAIN)
11489 init_gadgets_and_toons = TRUE;
11491 // printf("::: viewports: init_gadgets_and_toons\n");
11499 if (init_gfx_buffers)
11501 // printf("::: init_gfx_buffers\n");
11503 SCR_FIELDX = new_scr_fieldx_buffers;
11504 SCR_FIELDY = new_scr_fieldy_buffers;
11508 SCR_FIELDX = new_scr_fieldx;
11509 SCR_FIELDY = new_scr_fieldy;
11512 if (init_video_buffer)
11514 // printf("::: init_video_buffer\n");
11516 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11518 SetDrawDeactivationMask(REDRAW_NONE);
11519 SetDrawBackgroundMask(REDRAW_FIELD);
11522 if (init_gadgets_and_toons)
11524 // printf("::: init_gadgets_and_toons\n");
11531 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);