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 */
3338 /* !!! CHECK AGAIN (SEE BELOW) !!! */
3339 game_status = last_game_status; /* restore current game status */
3342 if (action == ACTION_CLOSING)
3344 if (game_status != GAME_MODE_MAIN)
3347 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3350 SetDrawtoField(DRAW_BUFFERED);
3353 // SetDrawBackgroundMask(last_draw_background_mask);
3356 redraw_mask = REDRAW_FIELD;
3357 // redraw_mask |= REDRAW_ALL;
3359 redraw_mask |= REDRAW_FIELD;
3363 if (game_status == GAME_MODE_MAIN)
3369 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
3370 game_status = last_game_status; /* restore current game status */
3374 if (action == ACTION_CLOSING &&
3375 game_status == GAME_MODE_PLAYING &&
3376 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3377 SetDrawtoField(DRAW_BUFFERED);
3379 if (game_status == GAME_MODE_PLAYING &&
3380 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3381 SetDrawtoField(DRAW_BUFFERED);
3393 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
3397 int graphic = el2preimg(element);
3399 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
3400 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
3408 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
3409 SetDrawBackgroundMask(REDRAW_FIELD);
3411 SetDrawBackgroundMask(REDRAW_NONE);
3416 for (x = BX1; x <= BX2; x++)
3417 for (y = BY1; y <= BY2; y++)
3418 DrawScreenField(x, y);
3420 redraw_mask |= REDRAW_FIELD;
3423 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
3427 for (x = 0; x < size_x; x++)
3428 for (y = 0; y < size_y; y++)
3429 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
3431 redraw_mask |= REDRAW_FIELD;
3434 static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
3436 boolean show_level_border = (BorderElement != EL_EMPTY);
3437 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3438 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3439 int tile_size = preview.tile_size;
3440 int preview_width = preview.xsize * tile_size;
3441 int preview_height = preview.ysize * tile_size;
3442 int real_preview_xsize = MIN(level_xsize, preview.xsize);
3443 int real_preview_ysize = MIN(level_ysize, preview.ysize);
3444 int real_preview_width = real_preview_xsize * tile_size;
3445 int real_preview_height = real_preview_ysize * tile_size;
3446 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
3447 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
3451 if (!IN_GFX_FIELD_FULL(dst_x, dst_y + preview_height - 1))
3456 dst_x += (preview_width - real_preview_width) / 2;
3457 dst_y += (preview_height - real_preview_height) / 2;
3459 DrawBackground(dst_x, dst_y, real_preview_width, real_preview_height);
3461 DrawBackground(dst_x, dst_y, preview_width, preview_height);
3463 dst_x += (preview_width - real_preview_width) / 2;
3464 dst_y += (preview_height - real_preview_height) / 2;
3467 for (x = 0; x < real_preview_xsize; x++)
3469 for (y = 0; y < real_preview_ysize; y++)
3471 int lx = from_x + x + (show_level_border ? -1 : 0);
3472 int ly = from_y + y + (show_level_border ? -1 : 0);
3473 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
3474 getBorderElement(lx, ly));
3476 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
3477 element, tile_size);
3481 redraw_mask |= REDRAW_MICROLEVEL;
3484 #define MICROLABEL_EMPTY 0
3485 #define MICROLABEL_LEVEL_NAME 1
3486 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
3487 #define MICROLABEL_LEVEL_AUTHOR 3
3488 #define MICROLABEL_IMPORTED_FROM_HEAD 4
3489 #define MICROLABEL_IMPORTED_FROM 5
3490 #define MICROLABEL_IMPORTED_BY_HEAD 6
3491 #define MICROLABEL_IMPORTED_BY 7
3493 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
3495 int max_text_width = SXSIZE;
3496 int font_width = getFontWidth(font_nr);
3498 if (pos->align == ALIGN_CENTER)
3499 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
3500 else if (pos->align == ALIGN_RIGHT)
3501 max_text_width = pos->x;
3503 max_text_width = SXSIZE - pos->x;
3505 return max_text_width / font_width;
3508 static void DrawPreviewLevelLabelExt(int mode)
3510 struct TextPosInfo *pos = &menu.main.text.level_info_2;
3511 char label_text[MAX_OUTPUT_LINESIZE + 1];
3512 int max_len_label_text;
3514 int font_nr = pos->font;
3517 if (!IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3520 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3521 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3522 mode == MICROLABEL_IMPORTED_BY_HEAD)
3523 font_nr = pos->font_alt;
3525 int font_nr = FONT_TEXT_2;
3528 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3529 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3530 mode == MICROLABEL_IMPORTED_BY_HEAD)
3531 font_nr = FONT_TEXT_3;
3535 max_len_label_text = getMaxTextLength(pos, font_nr);
3537 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3541 if (pos->size != -1)
3542 max_len_label_text = pos->size;
3545 for (i = 0; i < max_len_label_text; i++)
3546 label_text[i] = ' ';
3547 label_text[max_len_label_text] = '\0';
3549 if (strlen(label_text) > 0)
3552 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3554 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3555 int lypos = MICROLABEL2_YPOS;
3557 DrawText(lxpos, lypos, label_text, font_nr);
3562 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3563 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3564 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3565 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3566 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3567 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3568 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3569 max_len_label_text);
3570 label_text[max_len_label_text] = '\0';
3572 if (strlen(label_text) > 0)
3575 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3577 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3578 int lypos = MICROLABEL2_YPOS;
3580 DrawText(lxpos, lypos, label_text, font_nr);
3584 redraw_mask |= REDRAW_MICROLEVEL;
3587 static void DrawPreviewLevelExt(boolean restart)
3589 static unsigned int scroll_delay = 0;
3590 static unsigned int label_delay = 0;
3591 static int from_x, from_y, scroll_direction;
3592 static int label_state, label_counter;
3593 unsigned int scroll_delay_value = preview.step_delay;
3594 boolean show_level_border = (BorderElement != EL_EMPTY);
3595 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3596 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3597 int last_game_status = game_status; /* save current game status */
3600 /* force PREVIEW font on preview level */
3601 game_status = GAME_MODE_PSEUDO_PREVIEW;
3609 if (preview.anim_mode == ANIM_CENTERED)
3611 if (level_xsize > preview.xsize)
3612 from_x = (level_xsize - preview.xsize) / 2;
3613 if (level_ysize > preview.ysize)
3614 from_y = (level_ysize - preview.ysize) / 2;
3617 from_x += preview.xoffset;
3618 from_y += preview.yoffset;
3620 scroll_direction = MV_RIGHT;
3624 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3625 DrawPreviewLevelLabelExt(label_state);
3627 /* initialize delay counters */
3628 DelayReached(&scroll_delay, 0);
3629 DelayReached(&label_delay, 0);
3631 if (leveldir_current->name)
3633 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3634 char label_text[MAX_OUTPUT_LINESIZE + 1];
3636 int font_nr = pos->font;
3638 int font_nr = FONT_TEXT_1;
3641 int max_len_label_text = getMaxTextLength(pos, font_nr);
3643 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3651 if (pos->size != -1)
3652 max_len_label_text = pos->size;
3655 strncpy(label_text, leveldir_current->name, max_len_label_text);
3656 label_text[max_len_label_text] = '\0';
3659 if (IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3660 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3662 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3663 lypos = SY + MICROLABEL1_YPOS;
3665 DrawText(lxpos, lypos, label_text, font_nr);
3669 game_status = last_game_status; /* restore current game status */
3674 /* scroll preview level, if needed */
3675 if (preview.anim_mode != ANIM_NONE &&
3676 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3677 DelayReached(&scroll_delay, scroll_delay_value))
3679 switch (scroll_direction)
3684 from_x -= preview.step_offset;
3685 from_x = (from_x < 0 ? 0 : from_x);
3688 scroll_direction = MV_UP;
3692 if (from_x < level_xsize - preview.xsize)
3694 from_x += preview.step_offset;
3695 from_x = (from_x > level_xsize - preview.xsize ?
3696 level_xsize - preview.xsize : from_x);
3699 scroll_direction = MV_DOWN;
3705 from_y -= preview.step_offset;
3706 from_y = (from_y < 0 ? 0 : from_y);
3709 scroll_direction = MV_RIGHT;
3713 if (from_y < level_ysize - preview.ysize)
3715 from_y += preview.step_offset;
3716 from_y = (from_y > level_ysize - preview.ysize ?
3717 level_ysize - preview.ysize : from_y);
3720 scroll_direction = MV_LEFT;
3727 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3730 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3731 /* redraw micro level label, if needed */
3732 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3733 !strEqual(level.author, ANONYMOUS_NAME) &&
3734 !strEqual(level.author, leveldir_current->name) &&
3735 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3737 int max_label_counter = 23;
3739 if (leveldir_current->imported_from != NULL &&
3740 strlen(leveldir_current->imported_from) > 0)
3741 max_label_counter += 14;
3742 if (leveldir_current->imported_by != NULL &&
3743 strlen(leveldir_current->imported_by) > 0)
3744 max_label_counter += 14;
3746 label_counter = (label_counter + 1) % max_label_counter;
3747 label_state = (label_counter >= 0 && label_counter <= 7 ?
3748 MICROLABEL_LEVEL_NAME :
3749 label_counter >= 9 && label_counter <= 12 ?
3750 MICROLABEL_LEVEL_AUTHOR_HEAD :
3751 label_counter >= 14 && label_counter <= 21 ?
3752 MICROLABEL_LEVEL_AUTHOR :
3753 label_counter >= 23 && label_counter <= 26 ?
3754 MICROLABEL_IMPORTED_FROM_HEAD :
3755 label_counter >= 28 && label_counter <= 35 ?
3756 MICROLABEL_IMPORTED_FROM :
3757 label_counter >= 37 && label_counter <= 40 ?
3758 MICROLABEL_IMPORTED_BY_HEAD :
3759 label_counter >= 42 && label_counter <= 49 ?
3760 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3762 if (leveldir_current->imported_from == NULL &&
3763 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3764 label_state == MICROLABEL_IMPORTED_FROM))
3765 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3766 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3768 DrawPreviewLevelLabelExt(label_state);
3771 game_status = last_game_status; /* restore current game status */
3774 void DrawPreviewLevelInitial()
3776 DrawPreviewLevelExt(TRUE);
3779 void DrawPreviewLevelAnimation()
3781 DrawPreviewLevelExt(FALSE);
3784 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3785 int graphic, int sync_frame, int mask_mode)
3787 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3789 if (mask_mode == USE_MASKING)
3790 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3792 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3795 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3796 int graphic, int sync_frame,
3799 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3801 if (mask_mode == USE_MASKING)
3802 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3804 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3807 inline void DrawGraphicAnimation(int x, int y, int graphic)
3809 int lx = LEVELX(x), ly = LEVELY(y);
3811 if (!IN_SCR_FIELD(x, y))
3815 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3816 graphic, GfxFrame[lx][ly], NO_MASKING);
3818 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3819 graphic, GfxFrame[lx][ly], NO_MASKING);
3821 MarkTileDirty(x, y);
3824 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3826 int lx = LEVELX(x), ly = LEVELY(y);
3828 if (!IN_SCR_FIELD(x, y))
3831 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3832 graphic, GfxFrame[lx][ly], NO_MASKING);
3833 MarkTileDirty(x, y);
3836 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3838 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3841 void DrawLevelElementAnimation(int x, int y, int element)
3843 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3845 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3848 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3850 int sx = SCREENX(x), sy = SCREENY(y);
3852 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3855 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3858 DrawGraphicAnimation(sx, sy, graphic);
3861 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3862 DrawLevelFieldCrumbled(x, y);
3864 if (GFX_CRUMBLED(Feld[x][y]))
3865 DrawLevelFieldCrumbled(x, y);
3869 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3871 int sx = SCREENX(x), sy = SCREENY(y);
3874 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3877 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3879 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3882 DrawGraphicAnimation(sx, sy, graphic);
3884 if (GFX_CRUMBLED(element))
3885 DrawLevelFieldCrumbled(x, y);
3888 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3890 if (player->use_murphy)
3892 /* this works only because currently only one player can be "murphy" ... */
3893 static int last_horizontal_dir = MV_LEFT;
3894 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3896 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3897 last_horizontal_dir = move_dir;
3899 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3901 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3903 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3909 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3912 static boolean equalGraphics(int graphic1, int graphic2)
3914 struct GraphicInfo *g1 = &graphic_info[graphic1];
3915 struct GraphicInfo *g2 = &graphic_info[graphic2];
3917 return (g1->bitmap == g2->bitmap &&
3918 g1->src_x == g2->src_x &&
3919 g1->src_y == g2->src_y &&
3920 g1->anim_frames == g2->anim_frames &&
3921 g1->anim_delay == g2->anim_delay &&
3922 g1->anim_mode == g2->anim_mode);
3925 void DrawAllPlayers()
3929 for (i = 0; i < MAX_PLAYERS; i++)
3930 if (stored_player[i].active)
3931 DrawPlayer(&stored_player[i]);
3934 void DrawPlayerField(int x, int y)
3936 if (!IS_PLAYER(x, y))
3939 DrawPlayer(PLAYERINFO(x, y));
3942 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3944 void DrawPlayer(struct PlayerInfo *player)
3946 int jx = player->jx;
3947 int jy = player->jy;
3948 int move_dir = player->MovDir;
3949 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3950 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3951 int last_jx = (player->is_moving ? jx - dx : jx);
3952 int last_jy = (player->is_moving ? jy - dy : jy);
3953 int next_jx = jx + dx;
3954 int next_jy = jy + dy;
3955 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3956 boolean player_is_opaque = FALSE;
3957 int sx = SCREENX(jx), sy = SCREENY(jy);
3958 int sxx = 0, syy = 0;
3959 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3961 int action = ACTION_DEFAULT;
3962 int last_player_graphic = getPlayerGraphic(player, move_dir);
3963 int last_player_frame = player->Frame;
3966 /* GfxElement[][] is set to the element the player is digging or collecting;
3967 remove also for off-screen player if the player is not moving anymore */
3968 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3969 GfxElement[jx][jy] = EL_UNDEFINED;
3971 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3975 if (!IN_LEV_FIELD(jx, jy))
3977 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3978 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3979 printf("DrawPlayerField(): This should never happen!\n");
3984 if (element == EL_EXPLOSION)
3987 action = (player->is_pushing ? ACTION_PUSHING :
3988 player->is_digging ? ACTION_DIGGING :
3989 player->is_collecting ? ACTION_COLLECTING :
3990 player->is_moving ? ACTION_MOVING :
3991 player->is_snapping ? ACTION_SNAPPING :
3992 player->is_dropping ? ACTION_DROPPING :
3993 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3995 if (player->is_waiting)
3996 move_dir = player->dir_waiting;
3998 InitPlayerGfxAnimation(player, action, move_dir);
4000 /* ----------------------------------------------------------------------- */
4001 /* draw things in the field the player is leaving, if needed */
4002 /* ----------------------------------------------------------------------- */
4004 if (player->is_moving)
4006 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
4008 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
4010 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 DrawLevelFieldThruMask(last_jx, last_jy);
4017 else if (last_element == EL_DYNAMITE_ACTIVE ||
4018 last_element == EL_EM_DYNAMITE_ACTIVE ||
4019 last_element == EL_SP_DISK_RED_ACTIVE)
4020 DrawDynamite(last_jx, last_jy);
4022 /* !!! this is not enough to prevent flickering of players which are
4023 moving next to each others without a free tile between them -- this
4024 can only be solved by drawing all players layer by layer (first the
4025 background, then the foreground etc.) !!! => TODO */
4026 else if (!IS_PLAYER(last_jx, last_jy))
4027 DrawLevelField(last_jx, last_jy);
4030 DrawLevelField(last_jx, last_jy);
4033 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
4034 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4037 if (!IN_SCR_FIELD(sx, sy))
4040 /* ----------------------------------------------------------------------- */
4041 /* draw things behind the player, if needed */
4042 /* ----------------------------------------------------------------------- */
4045 DrawLevelElement(jx, jy, Back[jx][jy]);
4046 else if (IS_ACTIVE_BOMB(element))
4047 DrawLevelElement(jx, jy, EL_EMPTY);
4050 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
4052 int old_element = GfxElement[jx][jy];
4053 int old_graphic = el_act_dir2img(old_element, action, move_dir);
4054 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
4056 if (GFX_CRUMBLED(old_element))
4057 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
4059 DrawGraphic(sx, sy, old_graphic, frame);
4061 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
4062 player_is_opaque = TRUE;
4066 GfxElement[jx][jy] = EL_UNDEFINED;
4068 /* make sure that pushed elements are drawn with correct frame rate */
4070 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4072 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
4073 GfxFrame[jx][jy] = player->StepFrame;
4075 if (player->is_pushing && player->is_moving)
4076 GfxFrame[jx][jy] = player->StepFrame;
4079 DrawLevelField(jx, jy);
4083 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
4084 /* ----------------------------------------------------------------------- */
4085 /* draw player himself */
4086 /* ----------------------------------------------------------------------- */
4088 graphic = getPlayerGraphic(player, move_dir);
4090 /* in the case of changed player action or direction, prevent the current
4091 animation frame from being restarted for identical animations */
4092 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4093 player->Frame = last_player_frame;
4095 frame = getGraphicAnimationFrame(graphic, player->Frame);
4099 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4100 sxx = player->GfxPos;
4102 syy = player->GfxPos;
4105 if (!setup.soft_scrolling && ScreenMovPos)
4108 if (player_is_opaque)
4109 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4111 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4113 if (SHIELD_ON(player))
4115 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4116 IMG_SHIELD_NORMAL_ACTIVE);
4117 int frame = getGraphicAnimationFrame(graphic, -1);
4119 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4123 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4126 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4127 sxx = player->GfxPos;
4129 syy = player->GfxPos;
4133 /* ----------------------------------------------------------------------- */
4134 /* draw things the player is pushing, if needed */
4135 /* ----------------------------------------------------------------------- */
4138 printf("::: %d, %d [%d, %d] [%d]\n",
4139 player->is_pushing, player_is_moving, player->GfxAction,
4140 player->is_moving, player_is_moving);
4144 if (player->is_pushing && player->is_moving)
4146 int px = SCREENX(jx), py = SCREENY(jy);
4147 int pxx = (TILEX - ABS(sxx)) * dx;
4148 int pyy = (TILEY - ABS(syy)) * dy;
4149 int gfx_frame = GfxFrame[jx][jy];
4155 if (!IS_MOVING(jx, jy)) /* push movement already finished */
4157 element = Feld[next_jx][next_jy];
4158 gfx_frame = GfxFrame[next_jx][next_jy];
4161 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4164 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
4165 frame = getGraphicAnimationFrame(graphic, sync_frame);
4167 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
4170 /* draw background element under pushed element (like the Sokoban field) */
4172 if (game.use_masked_pushing && IS_MOVING(jx, jy))
4174 /* this allows transparent pushing animation over non-black background */
4177 DrawLevelElement(jx, jy, Back[jx][jy]);
4179 DrawLevelElement(jx, jy, EL_EMPTY);
4181 if (Back[next_jx][next_jy])
4182 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4184 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4186 else if (Back[next_jx][next_jy])
4187 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4189 if (Back[next_jx][next_jy])
4190 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4194 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
4195 jx, px, player->GfxPos, player->StepFrame,
4200 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
4204 /* do not draw (EM style) pushing animation when pushing is finished */
4205 /* (two-tile animations usually do not contain start and end frame) */
4206 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
4207 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
4209 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4211 /* masked drawing is needed for EMC style (double) movement graphics */
4212 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
4213 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4218 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4219 /* ----------------------------------------------------------------------- */
4220 /* draw player himself */
4221 /* ----------------------------------------------------------------------- */
4223 graphic = getPlayerGraphic(player, move_dir);
4225 /* in the case of changed player action or direction, prevent the current
4226 animation frame from being restarted for identical animations */
4227 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4228 player->Frame = last_player_frame;
4230 frame = getGraphicAnimationFrame(graphic, player->Frame);
4234 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4235 sxx = player->GfxPos;
4237 syy = player->GfxPos;
4240 if (!setup.soft_scrolling && ScreenMovPos)
4243 if (player_is_opaque)
4244 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4246 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4248 if (SHIELD_ON(player))
4250 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4251 IMG_SHIELD_NORMAL_ACTIVE);
4252 int frame = getGraphicAnimationFrame(graphic, -1);
4254 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4258 /* ----------------------------------------------------------------------- */
4259 /* draw things in front of player (active dynamite or dynabombs) */
4260 /* ----------------------------------------------------------------------- */
4262 if (IS_ACTIVE_BOMB(element))
4264 graphic = el2img(element);
4265 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
4267 if (game.emulation == EMU_SUPAPLEX)
4268 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
4270 DrawGraphicThruMask(sx, sy, graphic, frame);
4273 if (player_is_moving && last_element == EL_EXPLOSION)
4275 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
4276 GfxElement[last_jx][last_jy] : EL_EMPTY);
4277 int graphic = el_act2img(element, ACTION_EXPLODING);
4278 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
4279 int phase = ExplodePhase[last_jx][last_jy] - 1;
4280 int frame = getGraphicAnimationFrame(graphic, phase - delay);
4283 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
4286 /* ----------------------------------------------------------------------- */
4287 /* draw elements the player is just walking/passing through/under */
4288 /* ----------------------------------------------------------------------- */
4290 if (player_is_moving)
4292 /* handle the field the player is leaving ... */
4293 if (IS_ACCESSIBLE_INSIDE(last_element))
4294 DrawLevelField(last_jx, last_jy);
4295 else if (IS_ACCESSIBLE_UNDER(last_element))
4296 DrawLevelFieldThruMask(last_jx, last_jy);
4299 /* do not redraw accessible elements if the player is just pushing them */
4300 if (!player_is_moving || !player->is_pushing)
4302 /* ... and the field the player is entering */
4303 if (IS_ACCESSIBLE_INSIDE(element))
4304 DrawLevelField(jx, jy);
4305 else if (IS_ACCESSIBLE_UNDER(element))
4306 DrawLevelFieldThruMask(jx, jy);
4309 MarkTileDirty(sx, sy);
4312 /* ------------------------------------------------------------------------- */
4314 void WaitForEventToContinue()
4316 boolean still_wait = TRUE;
4318 /* simulate releasing mouse button over last gadget, if still pressed */
4320 HandleGadgets(-1, -1, 0);
4322 button_status = MB_RELEASED;
4338 case EVENT_BUTTONPRESS:
4339 case EVENT_KEYPRESS:
4343 case EVENT_KEYRELEASE:
4344 ClearPlayerAction();
4348 HandleOtherEvents(&event);
4352 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4359 /* don't eat all CPU time */
4364 #define MAX_REQUEST_LINES 13
4365 #define MAX_REQUEST_LINE_FONT1_LEN 7
4366 #define MAX_REQUEST_LINE_FONT2_LEN 10
4370 static int RequestHandleEvents(unsigned int req_state)
4372 int last_game_status = game_status; /* save current game status */
4376 button_status = MB_RELEASED;
4378 request_gadget_id = -1;
4391 case EVENT_BUTTONPRESS:
4392 case EVENT_BUTTONRELEASE:
4393 case EVENT_MOTIONNOTIFY:
4395 if (event.type == EVENT_MOTIONNOTIFY)
4397 if (!PointerInWindow(window))
4398 continue; /* window and pointer are on different screens */
4403 motion_status = TRUE;
4404 mx = ((MotionEvent *) &event)->x;
4405 my = ((MotionEvent *) &event)->y;
4409 motion_status = FALSE;
4410 mx = ((ButtonEvent *) &event)->x;
4411 my = ((ButtonEvent *) &event)->y;
4412 if (event.type == EVENT_BUTTONPRESS)
4413 button_status = ((ButtonEvent *) &event)->button;
4415 button_status = MB_RELEASED;
4418 /* this sets 'request_gadget_id' */
4419 HandleGadgets(mx, my, button_status);
4421 switch (request_gadget_id)
4423 case TOOL_CTRL_ID_YES:
4426 case TOOL_CTRL_ID_NO:
4429 case TOOL_CTRL_ID_CONFIRM:
4430 result = TRUE | FALSE;
4433 case TOOL_CTRL_ID_PLAYER_1:
4436 case TOOL_CTRL_ID_PLAYER_2:
4439 case TOOL_CTRL_ID_PLAYER_3:
4442 case TOOL_CTRL_ID_PLAYER_4:
4453 case EVENT_KEYPRESS:
4454 switch (GetEventKey((KeyEvent *)&event, TRUE))
4457 if (req_state & REQ_CONFIRM)
4466 #if defined(TARGET_SDL2)
4476 if (req_state & REQ_PLAYER)
4480 case EVENT_KEYRELEASE:
4481 ClearPlayerAction();
4485 HandleOtherEvents(&event);
4489 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4491 int joy = AnyJoystick();
4493 if (joy & JOY_BUTTON_1)
4495 else if (joy & JOY_BUTTON_2)
4501 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4503 HandleGameActions();
4509 if (!PendingEvent()) /* delay only if no pending events */
4514 game_status = GAME_MODE_PSEUDO_DOOR;
4520 game_status = last_game_status; /* restore current game status */
4528 if (!PendingEvent()) /* delay only if no pending events */
4531 /* don't eat all CPU time */
4541 static boolean RequestDoor(char *text, unsigned int req_state)
4543 unsigned int old_door_state;
4544 int last_game_status = game_status; /* save current game status */
4545 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4546 int font_nr = FONT_TEXT_2;
4551 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4553 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4554 font_nr = FONT_TEXT_1;
4557 if (game_status == GAME_MODE_PLAYING)
4559 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4560 BlitScreenToBitmap_EM(backbuffer);
4561 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4562 BlitScreenToBitmap_SP(backbuffer);
4565 /* disable deactivated drawing when quick-loading level tape recording */
4566 if (tape.playing && tape.deactivate_display)
4567 TapeDeactivateDisplayOff(TRUE);
4569 SetMouseCursor(CURSOR_DEFAULT);
4571 #if defined(NETWORK_AVALIABLE)
4572 /* pause network game while waiting for request to answer */
4573 if (options.network &&
4574 game_status == GAME_MODE_PLAYING &&
4575 req_state & REQUEST_WAIT_FOR_INPUT)
4576 SendToServer_PausePlaying();
4579 old_door_state = GetDoorState();
4581 /* simulate releasing mouse button over last gadget, if still pressed */
4583 HandleGadgets(-1, -1, 0);
4587 /* draw released gadget before proceeding */
4590 if (old_door_state & DOOR_OPEN_1)
4592 CloseDoor(DOOR_CLOSE_1);
4594 /* save old door content */
4596 BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
4597 0 * DXSIZE, 0, DXSIZE, DYSIZE, 1 * DXSIZE, 0);
4599 BlitBitmap(bitmap_db_door, bitmap_db_door,
4600 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4601 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4605 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4606 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4608 /* clear door drawing field */
4609 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4611 /* force DOOR font inside door area */
4612 game_status = GAME_MODE_PSEUDO_DOOR;
4614 /* write text for request */
4615 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4617 char text_line[max_request_line_len + 1];
4623 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4625 tc = *(text_ptr + tx);
4626 // if (!tc || tc == ' ')
4627 if (!tc || tc == ' ' || tc == '?' || tc == '!')
4631 if ((tc == '?' || tc == '!') && tl == 0)
4641 strncpy(text_line, text_ptr, tl);
4644 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4645 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4646 text_line, font_nr);
4648 text_ptr += tl + (tc == ' ' ? 1 : 0);
4649 // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
4652 game_status = last_game_status; /* restore current game status */
4654 if (req_state & REQ_ASK)
4656 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4657 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4659 else if (req_state & REQ_CONFIRM)
4661 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4663 else if (req_state & REQ_PLAYER)
4665 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4666 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4667 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4668 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4671 /* copy request gadgets to door backbuffer */
4673 BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
4675 BlitBitmap(drawto, bitmap_db_door,
4676 DX, DY, DXSIZE, DYSIZE,
4677 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4680 OpenDoor(DOOR_OPEN_1);
4682 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4684 if (game_status == GAME_MODE_PLAYING)
4686 SetPanelBackground();
4687 SetDrawBackgroundMask(REDRAW_DOOR_1);
4691 SetDrawBackgroundMask(REDRAW_FIELD);
4697 if (game_status != GAME_MODE_MAIN)
4700 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4702 // ---------- handle request buttons ----------
4703 result = RequestHandleEvents(req_state);
4705 if (game_status != GAME_MODE_MAIN)
4710 if (!(req_state & REQ_STAY_OPEN))
4712 CloseDoor(DOOR_CLOSE_1);
4714 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4715 (req_state & REQ_REOPEN))
4716 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4721 if (game_status == GAME_MODE_PLAYING)
4723 SetPanelBackground();
4724 SetDrawBackgroundMask(REDRAW_DOOR_1);
4728 SetDrawBackgroundMask(REDRAW_FIELD);
4731 #if defined(NETWORK_AVALIABLE)
4732 /* continue network game after request */
4733 if (options.network &&
4734 game_status == GAME_MODE_PLAYING &&
4735 req_state & REQUEST_WAIT_FOR_INPUT)
4736 SendToServer_ContinuePlaying();
4739 /* restore deactivated drawing when quick-loading level tape recording */
4740 if (tape.playing && tape.deactivate_display)
4741 TapeDeactivateDisplayOn();
4746 static boolean RequestEnvelope(char *text, unsigned int req_state)
4753 if (game_status == GAME_MODE_PLAYING)
4755 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4756 BlitScreenToBitmap_EM(backbuffer);
4757 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4758 BlitScreenToBitmap_SP(backbuffer);
4761 /* disable deactivated drawing when quick-loading level tape recording */
4762 if (tape.playing && tape.deactivate_display)
4763 TapeDeactivateDisplayOff(TRUE);
4765 SetMouseCursor(CURSOR_DEFAULT);
4767 #if defined(NETWORK_AVALIABLE)
4768 /* pause network game while waiting for request to answer */
4769 if (options.network &&
4770 game_status == GAME_MODE_PLAYING &&
4771 req_state & REQUEST_WAIT_FOR_INPUT)
4772 SendToServer_PausePlaying();
4775 /* simulate releasing mouse button over last gadget, if still pressed */
4777 HandleGadgets(-1, -1, 0);
4781 // (replace with setting corresponding request background)
4782 // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4783 // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4785 /* clear door drawing field */
4786 // DrawBackground(DX, DY, DXSIZE, DYSIZE);
4789 if (global.use_envelope_request)
4793 CreateToolButtons();
4799 if (req_state & REQ_ASK)
4801 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_YES], FALSE);
4802 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_NO], FALSE);
4804 else if (req_state & REQ_CONFIRM)
4806 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_CONFIRM], FALSE);
4808 else if (req_state & REQ_PLAYER)
4810 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_1], FALSE);
4811 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_2], FALSE);
4812 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_3], FALSE);
4813 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_4], FALSE);
4816 if (req_state & REQ_ASK)
4818 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4819 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4821 else if (req_state & REQ_CONFIRM)
4823 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4825 else if (req_state & REQ_PLAYER)
4827 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4828 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4829 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4830 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4835 ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
4838 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4840 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4841 i == TOOL_CTRL_ID_NO)) ||
4842 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4843 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4844 i == TOOL_CTRL_ID_PLAYER_2 &&
4845 i == TOOL_CTRL_ID_PLAYER_3 &&
4846 i == TOOL_CTRL_ID_PLAYER_4)))
4848 int x = tool_gadget[i]->x + dDX;
4849 int y = tool_gadget[i]->y + dDY;
4851 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4856 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4858 if (game_status == GAME_MODE_PLAYING)
4860 SetPanelBackground();
4861 SetDrawBackgroundMask(REDRAW_DOOR_1);
4865 SetDrawBackgroundMask(REDRAW_FIELD);
4872 if (game_status != GAME_MODE_MAIN)
4876 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4878 // ---------- handle request buttons ----------
4879 result = RequestHandleEvents(req_state);
4881 if (game_status != GAME_MODE_MAIN)
4886 ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
4890 if (game_status == GAME_MODE_PLAYING)
4892 SetPanelBackground();
4893 SetDrawBackgroundMask(REDRAW_DOOR_1);
4897 SetDrawBackgroundMask(REDRAW_FIELD);
4900 #if defined(NETWORK_AVALIABLE)
4901 /* continue network game after request */
4902 if (options.network &&
4903 game_status == GAME_MODE_PLAYING &&
4904 req_state & REQUEST_WAIT_FOR_INPUT)
4905 SendToServer_ContinuePlaying();
4908 /* restore deactivated drawing when quick-loading level tape recording */
4909 if (tape.playing && tape.deactivate_display)
4910 TapeDeactivateDisplayOn();
4915 boolean Request(char *text, unsigned int req_state)
4917 if (global.use_envelope_request)
4918 return RequestEnvelope(text, req_state);
4920 return RequestDoor(text, req_state);
4923 #else // =====================================================================
4925 boolean Request(char *text, unsigned int req_state)
4927 int mx, my, ty, result = -1;
4928 unsigned int old_door_state;
4929 int last_game_status = game_status; /* save current game status */
4930 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4931 int font_nr = FONT_TEXT_2;
4933 int max_word_len = 0;
4939 global.use_envelope_request = 1;
4943 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4945 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4946 font_nr = FONT_TEXT_1;
4949 for (text_ptr = text; *text_ptr; text_ptr++)
4951 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
4953 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
4955 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4957 font_nr = FONT_TEXT_1;
4959 font_nr = FONT_LEVEL_NUMBER;
4967 if (game_status == GAME_MODE_PLAYING)
4969 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4970 BlitScreenToBitmap_EM(backbuffer);
4971 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4972 BlitScreenToBitmap_SP(backbuffer);
4975 /* disable deactivated drawing when quick-loading level tape recording */
4976 if (tape.playing && tape.deactivate_display)
4977 TapeDeactivateDisplayOff(TRUE);
4979 SetMouseCursor(CURSOR_DEFAULT);
4981 #if defined(NETWORK_AVALIABLE)
4982 /* pause network game while waiting for request to answer */
4983 if (options.network &&
4984 game_status == GAME_MODE_PLAYING &&
4985 req_state & REQUEST_WAIT_FOR_INPUT)
4986 SendToServer_PausePlaying();
4989 old_door_state = GetDoorState();
4991 /* simulate releasing mouse button over last gadget, if still pressed */
4993 HandleGadgets(-1, -1, 0);
4997 /* draw released gadget before proceeding */
5001 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
5003 if (old_door_state & DOOR_OPEN_1)
5007 if (!global.use_envelope_request)
5008 CloseDoor(DOOR_CLOSE_1);
5010 CloseDoor(DOOR_CLOSE_1);
5013 /* save old door content */
5014 BlitBitmap(bitmap_db_door, bitmap_db_door,
5015 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5016 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
5020 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
5023 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5025 /* clear door drawing field */
5026 DrawBackground(DX, DY, DXSIZE, DYSIZE);
5028 /* force DOOR font inside door area */
5029 game_status = GAME_MODE_PSEUDO_DOOR;
5031 /* write text for request */
5032 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
5034 char text_line[max_request_line_len + 1];
5040 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
5042 tc = *(text_ptr + tx);
5043 if (!tc || tc == ' ')
5054 strncpy(text_line, text_ptr, tl);
5057 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
5058 DY + 8 + ty * (getFontHeight(font_nr) + 2),
5059 text_line, font_nr);
5061 text_ptr += tl + (tc == ' ' ? 1 : 0);
5064 game_status = last_game_status; /* restore current game status */
5067 if (global.use_envelope_request)
5071 CreateToolButtons();
5075 if (req_state & REQ_ASK)
5077 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
5078 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
5080 else if (req_state & REQ_CONFIRM)
5082 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
5084 else if (req_state & REQ_PLAYER)
5086 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
5087 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
5088 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
5089 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
5092 /* copy request gadgets to door backbuffer */
5093 BlitBitmap(drawto, bitmap_db_door,
5094 DX, DY, DXSIZE, DYSIZE,
5095 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5098 if (global.use_envelope_request)
5100 ShowEnvelopeRequest(text, ACTION_OPENING);
5102 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
5104 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
5105 i == TOOL_CTRL_ID_NO)) ||
5106 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
5107 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
5108 i == TOOL_CTRL_ID_PLAYER_2 &&
5109 i == TOOL_CTRL_ID_PLAYER_3 &&
5110 i == TOOL_CTRL_ID_PLAYER_4)))
5112 int x = tool_gadget[i]->x + dDX;
5113 int y = tool_gadget[i]->y + dDY;
5115 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
5122 if (!global.use_envelope_request)
5123 OpenDoor(DOOR_OPEN_1);
5125 OpenDoor(DOOR_OPEN_1);
5128 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
5130 if (game_status == GAME_MODE_PLAYING)
5132 SetPanelBackground();
5133 SetDrawBackgroundMask(REDRAW_DOOR_1);
5137 SetDrawBackgroundMask(REDRAW_FIELD);
5144 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
5147 if (game_status != GAME_MODE_MAIN)
5151 button_status = MB_RELEASED;
5153 request_gadget_id = -1;
5155 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5167 case EVENT_BUTTONPRESS:
5168 case EVENT_BUTTONRELEASE:
5169 case EVENT_MOTIONNOTIFY:
5171 if (event.type == EVENT_MOTIONNOTIFY)
5173 if (!PointerInWindow(window))
5174 continue; /* window and pointer are on different screens */
5179 motion_status = TRUE;
5180 mx = ((MotionEvent *) &event)->x;
5181 my = ((MotionEvent *) &event)->y;
5185 motion_status = FALSE;
5186 mx = ((ButtonEvent *) &event)->x;
5187 my = ((ButtonEvent *) &event)->y;
5188 if (event.type == EVENT_BUTTONPRESS)
5189 button_status = ((ButtonEvent *) &event)->button;
5191 button_status = MB_RELEASED;
5194 /* this sets 'request_gadget_id' */
5195 HandleGadgets(mx, my, button_status);
5197 switch (request_gadget_id)
5199 case TOOL_CTRL_ID_YES:
5202 case TOOL_CTRL_ID_NO:
5205 case TOOL_CTRL_ID_CONFIRM:
5206 result = TRUE | FALSE;
5209 case TOOL_CTRL_ID_PLAYER_1:
5212 case TOOL_CTRL_ID_PLAYER_2:
5215 case TOOL_CTRL_ID_PLAYER_3:
5218 case TOOL_CTRL_ID_PLAYER_4:
5229 case EVENT_KEYPRESS:
5230 switch (GetEventKey((KeyEvent *)&event, TRUE))
5233 if (req_state & REQ_CONFIRM)
5242 #if defined(TARGET_SDL2)
5252 if (req_state & REQ_PLAYER)
5256 case EVENT_KEYRELEASE:
5257 ClearPlayerAction();
5261 HandleOtherEvents(&event);
5265 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
5267 int joy = AnyJoystick();
5269 if (joy & JOY_BUTTON_1)
5271 else if (joy & JOY_BUTTON_2)
5277 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
5279 HandleGameActions();
5285 if (!PendingEvent()) /* delay only if no pending events */
5290 game_status = GAME_MODE_PSEUDO_DOOR;
5296 game_status = last_game_status; /* restore current game status */
5304 if (!PendingEvent()) /* delay only if no pending events */
5307 /* don't eat all CPU time */
5314 if (game_status != GAME_MODE_MAIN)
5320 if (global.use_envelope_request)
5321 ShowEnvelopeRequest(text, ACTION_CLOSING);
5325 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
5327 if (!(req_state & REQ_STAY_OPEN))
5330 CloseDoor(DOOR_CLOSE_1);
5332 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
5333 (req_state & REQ_REOPEN))
5334 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
5339 if (game_status == GAME_MODE_PLAYING)
5341 SetPanelBackground();
5342 SetDrawBackgroundMask(REDRAW_DOOR_1);
5346 SetDrawBackgroundMask(REDRAW_FIELD);
5349 #if defined(NETWORK_AVALIABLE)
5350 /* continue network game after request */
5351 if (options.network &&
5352 game_status == GAME_MODE_PLAYING &&
5353 req_state & REQUEST_WAIT_FOR_INPUT)
5354 SendToServer_ContinuePlaying();
5357 /* restore deactivated drawing when quick-loading level tape recording */
5358 if (tape.playing && tape.deactivate_display)
5359 TapeDeactivateDisplayOn();
5366 static int compareDoorPartOrderInfo(const void *object1, const void *object2)
5368 const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
5369 const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
5372 if (dpo1->sort_priority != dpo2->sort_priority)
5373 compare_result = dpo1->sort_priority - dpo2->sort_priority;
5375 compare_result = dpo1->nr - dpo2->nr;
5377 return compare_result;
5380 void InitGraphicCompatibilityInfo_Doors()
5386 struct DoorInfo *door;
5390 { DOOR_1, IMG_DOOR_1_GFX_PART_1, IMG_DOOR_1_GFX_PART_8, &door_1 },
5391 { DOOR_2, IMG_DOOR_2_GFX_PART_1, IMG_DOOR_2_GFX_PART_8, &door_2 },
5393 { -1, -1, -1, NULL }
5395 struct Rect door_rect_list[] =
5397 { DX, DY, DXSIZE, DYSIZE },
5398 { VX, VY, VXSIZE, VYSIZE }
5402 for (i = 0; doors[i].door_token != -1; i++)
5404 int door_token = doors[i].door_token;
5405 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5406 int part_1 = doors[i].part_1;
5407 int part_8 = doors[i].part_8;
5408 int part_2 = part_1 + 1;
5409 int part_3 = part_1 + 2;
5410 struct DoorInfo *door = doors[i].door;
5411 struct Rect *door_rect = &door_rect_list[door_index];
5412 boolean door_gfx_redefined = FALSE;
5414 /* check if any door part graphic definitions have been redefined */
5416 for (j = 0; door_part_controls[j].door_token != -1; j++)
5418 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5419 struct FileInfo *fi = getImageListEntryFromImageID(dpc->graphic);
5421 if (dpc->door_token == door_token && fi->redefined)
5422 door_gfx_redefined = TRUE;
5425 /* check for old-style door graphic/animation modifications */
5427 if (!door_gfx_redefined)
5429 if (door->anim_mode & ANIM_STATIC_PANEL)
5431 door->panel.step_xoffset = 0;
5432 door->panel.step_yoffset = 0;
5435 if (door->anim_mode & (ANIM_HORIZONTAL | ANIM_VERTICAL))
5437 struct GraphicInfo *g_part_1 = &graphic_info[part_1];
5438 struct GraphicInfo *g_part_2 = &graphic_info[part_2];
5439 int num_door_steps, num_panel_steps;
5441 /* remove door part graphics other than the two default wings */
5443 for (j = 0; door_part_controls[j].door_token != -1; j++)
5445 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5446 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5448 if (dpc->graphic >= part_3 &&
5449 dpc->graphic <= part_8)
5453 /* set graphics and screen positions of the default wings */
5455 g_part_1->width = door_rect->width;
5456 g_part_1->height = door_rect->height;
5457 g_part_2->width = door_rect->width;
5458 g_part_2->height = door_rect->height;
5459 g_part_2->src_x = door_rect->width;
5460 g_part_2->src_y = g_part_1->src_y;
5462 door->part_2.x = door->part_1.x;
5463 door->part_2.y = door->part_1.y;
5465 if (door->width != -1)
5467 g_part_1->width = door->width;
5468 g_part_2->width = door->width;
5470 // special treatment for graphics and screen position of right wing
5471 g_part_2->src_x += door_rect->width - door->width;
5472 door->part_2.x += door_rect->width - door->width;
5475 if (door->height != -1)
5477 g_part_1->height = door->height;
5478 g_part_2->height = door->height;
5480 // special treatment for graphics and screen position of bottom wing
5481 g_part_2->src_y += door_rect->height - door->height;
5482 door->part_2.y += door_rect->height - door->height;
5485 /* set animation delays for the default wings and panels */
5487 door->part_1.step_delay = door->step_delay;
5488 door->part_2.step_delay = door->step_delay;
5489 door->panel.step_delay = door->step_delay;
5491 /* set animation draw order for the default wings */
5493 door->part_1.sort_priority = 2; /* draw left wing over ... */
5494 door->part_2.sort_priority = 1; /* ... right wing */
5496 /* set animation draw offset for the default wings */
5498 if (door->anim_mode & ANIM_HORIZONTAL)
5500 door->part_1.step_xoffset = door->step_offset;
5501 door->part_1.step_yoffset = 0;
5502 door->part_2.step_xoffset = door->step_offset * -1;
5503 door->part_2.step_yoffset = 0;
5505 num_door_steps = g_part_1->width / door->step_offset;
5507 else // ANIM_VERTICAL
5509 door->part_1.step_xoffset = 0;
5510 door->part_1.step_yoffset = door->step_offset;
5511 door->part_2.step_xoffset = 0;
5512 door->part_2.step_yoffset = door->step_offset * -1;
5514 num_door_steps = g_part_1->height / door->step_offset;
5517 /* set animation draw offset for the default panels */
5519 if (door->step_offset > 1)
5521 num_panel_steps = 2 * door_rect->height / door->step_offset;
5522 door->panel.start_step = num_panel_steps - num_door_steps;
5526 num_panel_steps = door_rect->height / door->step_offset;
5527 door->panel.start_step = num_panel_steps - num_door_steps / 2;
5528 door->panel.step_delay *= 2;
5539 for (i = 0; door_part_controls[i].door_token != -1; i++)
5541 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5542 struct DoorPartOrderInfo *dpo = &door_part_order[i];
5544 /* initialize "start_step_opening" and "start_step_closing", if needed */
5545 if (dpc->pos->start_step_opening == 0 &&
5546 dpc->pos->start_step_closing == 0)
5548 // dpc->pos->start_step_opening = dpc->pos->start_step;
5549 dpc->pos->start_step_closing = dpc->pos->start_step;
5552 /* fill structure for door part draw order (sorted below) */
5554 dpo->sort_priority = dpc->pos->sort_priority;
5557 struct DoorPartPosInfo *pos = dpc->pos;
5559 printf(":0: step_xoffset == %d, step_yoffset == %d\n",
5560 pos->step_xoffset, pos->step_yoffset);
5564 /* sort door part controls according to sort_priority and graphic number */
5565 qsort(door_part_order, MAX_DOOR_PARTS,
5566 sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
5569 unsigned int OpenDoor(unsigned int door_state)
5571 if (door_state & DOOR_COPY_BACK)
5574 if (door_state & DOOR_OPEN_1)
5575 BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
5576 1 * DXSIZE, 0, DXSIZE, DYSIZE, 0 * DXSIZE, 0);
5578 if (door_state & DOOR_OPEN_2)
5579 BlitBitmap(bitmap_db_door_2, bitmap_db_door_2,
5580 1 * VXSIZE, 0, VXSIZE, VYSIZE, 0 * VXSIZE, 0);
5582 if (door_state & DOOR_OPEN_1)
5583 BlitBitmap(bitmap_db_door, bitmap_db_door,
5584 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5585 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5587 if (door_state & DOOR_OPEN_2)
5588 BlitBitmap(bitmap_db_door, bitmap_db_door,
5589 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
5590 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5593 door_state &= ~DOOR_COPY_BACK;
5596 return MoveDoor(door_state);
5599 unsigned int CloseDoor(unsigned int door_state)
5601 unsigned int old_door_state = GetDoorState();
5603 if (!(door_state & DOOR_NO_COPY_BACK))
5606 if (old_door_state & DOOR_OPEN_1)
5607 BlitBitmap(backbuffer, bitmap_db_door_1,
5608 DX, DY, DXSIZE, DYSIZE, 0, 0);
5610 if (old_door_state & DOOR_OPEN_2)
5611 BlitBitmap(backbuffer, bitmap_db_door_2,
5612 VX, VY, VXSIZE, VYSIZE, 0, 0);
5614 if (old_door_state & DOOR_OPEN_1)
5615 BlitBitmap(backbuffer, bitmap_db_door,
5616 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5618 if (old_door_state & DOOR_OPEN_2)
5619 BlitBitmap(backbuffer, bitmap_db_door,
5620 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5623 door_state &= ~DOOR_NO_COPY_BACK;
5626 return MoveDoor(door_state);
5629 unsigned int GetDoorState()
5631 return MoveDoor(DOOR_GET_STATE);
5634 unsigned int SetDoorState(unsigned int door_state)
5636 return MoveDoor(door_state | DOOR_SET_STATE);
5641 // ========== TEST 1 ===========================================================
5643 int euclid(int a, int b)
5645 return (b ? euclid(b, a % b) : a);
5648 unsigned int MoveDoor(unsigned int door_state)
5651 struct XY panel_pos_list[] =
5653 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 },
5654 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 },
5657 struct Rect door_rect_list[] =
5659 { DX, DY, DXSIZE, DYSIZE },
5660 { VX, VY, VXSIZE, VYSIZE }
5662 static int door1 = DOOR_OPEN_1;
5663 static int door2 = DOOR_CLOSE_2;
5664 unsigned int door_delay = 0;
5665 unsigned int door_delay_value;
5669 if (door_1.width < 0 || door_1.width > DXSIZE)
5670 door_1.width = DXSIZE;
5671 if (door_1.height < 0 || door_1.height > DYSIZE)
5672 door_1.height = DYSIZE;
5673 if (door_2.width < 0 || door_2.width > VXSIZE)
5674 door_2.width = VXSIZE;
5675 if (door_2.height < 0 || door_2.height > VYSIZE)
5676 door_2.height = VYSIZE;
5679 if (door_state == DOOR_GET_STATE)
5680 return (door1 | door2);
5682 if (door_state & DOOR_SET_STATE)
5684 if (door_state & DOOR_ACTION_1)
5685 door1 = door_state & DOOR_ACTION_1;
5686 if (door_state & DOOR_ACTION_2)
5687 door2 = door_state & DOOR_ACTION_2;
5689 return (door1 | door2);
5692 if (!(door_state & DOOR_FORCE_REDRAW))
5694 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
5695 door_state &= ~DOOR_OPEN_1;
5696 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
5697 door_state &= ~DOOR_CLOSE_1;
5698 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
5699 door_state &= ~DOOR_OPEN_2;
5700 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
5701 door_state &= ~DOOR_CLOSE_2;
5705 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
5708 if (setup.quick_doors)
5710 stepsize = 20; /* must be chosen to always draw last frame */
5711 door_delay_value = 0;
5715 if (global.autoplay_leveldir)
5717 door_state |= DOOR_NO_DELAY;
5718 door_state &= ~DOOR_CLOSE_ALL;
5722 if (game_status == GAME_MODE_EDITOR)
5723 door_state |= DOOR_NO_DELAY;
5726 if (door_state & DOOR_ACTION)
5728 boolean door_panel_drawn[NUM_DOORS];
5729 boolean panel_has_doors[NUM_DOORS];
5730 boolean door_part_skip[MAX_DOOR_PARTS];
5731 boolean door_part_done[MAX_DOOR_PARTS];
5732 boolean door_part_done_all;
5733 int num_steps[MAX_DOOR_PARTS];
5734 int max_move_delay = 0; // delay for complete animations of all doors
5735 int max_step_delay = 0; // delay (ms) between two animation frames
5736 int num_move_steps = 0; // number of animation steps for all doors
5737 int current_move_delay = 0;
5740 for (i = 0; i < NUM_DOORS; i++)
5741 panel_has_doors[i] = FALSE;
5743 for (i = 0; i < MAX_DOOR_PARTS; i++)
5745 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5746 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5747 int door_token = dpc->door_token;
5749 door_part_done[i] = FALSE;
5750 door_part_skip[i] = (!(door_state & door_token) ||
5755 for (i = 0; i < MAX_DOOR_PARTS; i++)
5757 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5758 struct DoorPartPosInfo *pos = dpc->pos;
5759 int start_step = pos->start_step;
5761 printf("::: ---> %d: start_step == %d [%d]\n",
5762 i, start_step, door_part_done[i]);
5766 for (i = 0; i < MAX_DOOR_PARTS; i++)
5768 int nr = door_part_order[i].nr;
5769 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5770 struct DoorPartPosInfo *pos = dpc->pos;
5771 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5772 int door_token = dpc->door_token;
5773 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5774 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5775 int step_xoffset = ABS(pos->step_xoffset);
5776 int step_yoffset = ABS(pos->step_yoffset);
5777 int step_delay = pos->step_delay;
5778 int current_door_state = door_state & door_token;
5779 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5780 boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
5781 boolean part_opening = (is_panel ? door_closing : door_opening);
5782 int start_step = (part_opening ? pos->start_step_opening :
5783 pos->start_step_closing);
5784 float move_xsize = (step_xoffset ? g->width : 0);
5785 float move_ysize = (step_yoffset ? g->height : 0);
5786 int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
5787 int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0);
5788 int move_steps = (move_xsteps && move_ysteps ?
5789 MIN(move_xsteps, move_ysteps) :
5790 move_xsteps ? move_xsteps : move_ysteps) - start_step;
5791 int move_delay = move_steps * step_delay;
5793 if (door_part_skip[nr])
5797 panel_has_doors[door_index] = TRUE;
5799 max_move_delay = MAX(max_move_delay, move_delay);
5800 max_step_delay = (max_step_delay == 0 ? step_delay :
5801 euclid(max_step_delay, step_delay));
5802 num_steps[nr] = move_steps;
5806 printf("::: %d: move_delay == %d, start_step == %d [%d]\n",
5807 i, move_delay, start_step, door_part_order[i].nr);
5809 if (DOOR_PART_IS_PANEL(i))
5810 printf("::: %d: move_delay == %d, start_step == %d\n",
5811 i, move_delay, start_step);
5816 num_move_steps = max_move_delay / max_step_delay;
5818 door_delay_value = max_step_delay;
5821 door_delay_value *= 10;
5825 printf("::: num_move_steps == %d, max_move_delay == %d, max_step_delay == %d\n", num_move_steps, max_move_delay, max_step_delay);
5828 for (k = 0; k < num_move_steps; k++)
5830 door_part_done_all = TRUE;
5832 for (i = 0; i < NUM_DOORS; i++)
5833 door_panel_drawn[i] = FALSE;
5835 for (i = 0; i < MAX_DOOR_PARTS; i++)
5837 int nr = door_part_order[i].nr;
5838 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5839 struct DoorPartPosInfo *pos = dpc->pos;
5840 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5841 int door_token = dpc->door_token;
5842 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5843 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5845 struct XY *panel_pos = &panel_pos_list[door_index];
5847 struct Rect *door_rect = &door_rect_list[door_index];
5848 Bitmap *bitmap_db_door = (door_token == DOOR_1 ? bitmap_db_door_1 :
5850 Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
5851 int current_door_state = door_state & door_token;
5852 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5853 boolean door_closing = !door_opening;
5854 boolean part_opening = (is_panel ? door_closing : door_opening);
5855 boolean part_closing = !part_opening;
5856 int start_step = (part_opening ? pos->start_step_opening :
5857 pos->start_step_closing);
5858 int step_delay = pos->step_delay;
5859 int step_factor = step_delay / max_step_delay;
5860 int k1 = (step_factor ? k / step_factor + 1 : k);
5861 int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
5862 int kk = (k2 < 0 ? 0 : k2);
5863 int src_x, src_y, src_xx, src_yy;
5864 int dst_x, dst_y, dst_xx, dst_yy;
5868 if (k == 0 && is_panel && door_token == DOOR_2)
5869 printf("::: %d, %d\n", g->width, g->height);
5873 if (DOOR_PART_IS_PANEL(nr))
5875 int start_step = pos->start_step;
5877 k2 = (door_closing ? k1 : num_steps[nr] - k1);// - start_step;
5878 kk = (k2 < 0 ? 0 : k2);
5884 if (nr != 16 && nr != 0)
5895 if (door_part_skip[nr])
5899 if (!(door_state & door_token))
5906 if (current_move_delay % step_delay)
5912 if (!door_panel_drawn[door_index])
5915 ClearRectangle(drawto, door_rect->x, door_rect->y,
5916 door_rect->width, door_rect->height);
5918 BlitBitmap(bitmap_db_door, drawto, panel_pos->x, panel_pos->y,
5919 door_rect->width, door_rect->height,
5920 door_rect->x, door_rect->y);
5923 door_panel_drawn[door_index] = TRUE;
5926 // draw opening or closing door parts
5928 if (pos->step_xoffset < 0) // door part on right side
5931 dst_xx = pos->x + ABS(kk * pos->step_xoffset);
5934 if (dst_xx + width > door_rect->width)
5935 width = door_rect->width - dst_xx;
5937 else // door part on left side
5940 dst_xx = pos->x - kk * pos->step_xoffset;
5944 src_xx = ABS(dst_xx);
5948 width = g->width - src_xx;
5950 // printf("::: k == %d [%d] \n", k, start_step);
5953 if (pos->step_yoffset < 0) // door part on bottom side
5956 dst_yy = pos->y + ABS(kk * pos->step_yoffset);
5959 if (dst_yy + height > door_rect->height)
5960 height = door_rect->height - dst_yy;
5962 else // door part on top side
5965 dst_yy = pos->y - kk * pos->step_yoffset;
5969 src_yy = ABS(dst_yy);
5973 height = g->height - src_yy;
5982 src_x = panel_pos->x + src_xx;
5983 src_y = panel_pos->y + src_yy;
5988 src_x = g->src_x + src_xx;
5989 src_y = g->src_y + src_yy;
5992 dst_x = door_rect->x + dst_xx;
5993 dst_y = door_rect->y + dst_yy;
5996 if (DOOR_PART_IS_PANEL(nr))
5998 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
5999 width, height, g->width, g->height, src_x, src_y);
6003 if (width >= 0 && width <= g->width &&
6004 height >= 0 && height <= g->height)
6006 if (is_panel || !pos->draw_masked)
6007 BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
6010 BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height,
6015 if (DOOR_PART_IS_PANEL(nr))
6017 bitmap = bitmap_db_door;
6018 src_x = panel_pos->x + src_xx;
6019 src_y = panel_pos->y + src_yy;
6021 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
6022 width, height, g->width, g->height, src_x, src_y);
6024 if (width >= 0 && width <= g->width &&
6025 height >= 0 && height <= g->height)
6026 BlitBitmap(bitmap, drawto, src_x, src_y,
6032 redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
6035 if ((part_opening && (width < 0 || height < 0)) ||
6036 (part_closing && (width >= g->width && height >= g->height)))
6037 door_part_done[nr] = TRUE;
6039 if ((door_opening && (width < 0 || height < 0)) ||
6040 (door_closing && (width >= g->width && height >= g->height)))
6041 door_part_done[nr] = TRUE;
6045 // continue door part animations, but not panel after door has closed
6046 if (!door_part_done[nr] &&
6047 !(is_panel && door_closing && panel_has_doors[door_index]))
6048 door_part_done_all = FALSE;
6050 // continue door part animations, but not panel after door has closed
6051 if (!door_part_done[nr] && !(is_panel && door_closing))
6052 door_part_done_all = FALSE;
6056 if (!door_part_done[nr])
6057 printf("::: k == %d, nr == %d\n", k, nr);
6061 if (!(door_state & DOOR_NO_DELAY))
6065 if (game_status == GAME_MODE_MAIN)
6068 WaitUntilDelayReached(&door_delay, door_delay_value);
6070 current_move_delay += max_step_delay;
6074 door_part_done_all = TRUE;
6076 for (i = 0; i < MAX_DOOR_PARTS; i++)
6077 if (!door_part_done[i] &&
6078 !(DOOR_PART_IS_PANEL(i) && door_closing))
6079 door_part_done_all = FALSE;
6082 if (door_part_done_all)
6088 if (door_state & DOOR_ACTION_1)
6089 door1 = door_state & DOOR_ACTION_1;
6090 if (door_state & DOOR_ACTION_2)
6091 door2 = door_state & DOOR_ACTION_2;
6094 printf("::: DOORS DONE %08x\n", door_state);
6096 printf("::: GO!\n");
6099 return (door1 | door2);
6104 // ========== OLD ==============================================================
6106 unsigned int MoveDoor(unsigned int door_state)
6108 static int door1 = DOOR_OPEN_1;
6109 static int door2 = DOOR_CLOSE_2;
6110 unsigned int door_delay = 0;
6111 unsigned int door_delay_value;
6115 if (door_1.width < 0 || door_1.width > DXSIZE)
6116 door_1.width = DXSIZE;
6117 if (door_1.height < 0 || door_1.height > DYSIZE)
6118 door_1.height = DYSIZE;
6119 if (door_2.width < 0 || door_2.width > VXSIZE)
6120 door_2.width = VXSIZE;
6121 if (door_2.height < 0 || door_2.height > VYSIZE)
6122 door_2.height = VYSIZE;
6125 if (door_state == DOOR_GET_STATE)
6126 return (door1 | door2);
6128 if (door_state & DOOR_SET_STATE)
6130 if (door_state & DOOR_ACTION_1)
6131 door1 = door_state & DOOR_ACTION_1;
6132 if (door_state & DOOR_ACTION_2)
6133 door2 = door_state & DOOR_ACTION_2;
6135 return (door1 | door2);
6138 if (!(door_state & DOOR_FORCE_REDRAW))
6140 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
6141 door_state &= ~DOOR_OPEN_1;
6142 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
6143 door_state &= ~DOOR_CLOSE_1;
6144 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
6145 door_state &= ~DOOR_OPEN_2;
6146 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
6147 door_state &= ~DOOR_CLOSE_2;
6150 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
6153 // door_delay_value *= 4; // !!! TEST ONLY !!!
6155 if (setup.quick_doors)
6157 stepsize = 20; /* must be chosen to always draw last frame */
6158 door_delay_value = 0;
6161 if (global.autoplay_leveldir)
6163 door_state |= DOOR_NO_DELAY;
6164 door_state &= ~DOOR_CLOSE_ALL;
6168 if (game_status == GAME_MODE_EDITOR)
6169 door_state |= DOOR_NO_DELAY;
6172 if (door_state & DOOR_ACTION)
6175 struct GraphicInfo *g1_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6176 struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6177 struct GraphicInfo *g2_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6178 struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6179 int door_1_left_width = g1_left->width;
6180 int door_1_left_height = g1_left->height;
6181 int door_1_right_width = g1_right->width;
6182 int door_1_right_height = g1_right->height;
6183 int door_2_left_width = g2_left->width;
6184 int door_2_left_height = g2_left->height;
6185 int door_2_right_width = g2_right->width;
6186 int door_2_right_height = g2_right->height;
6187 int door_1_width = MAX(door_1_left_width, door_1_right_width);
6188 int door_1_height = MAX(door_1_left_height, door_1_right_height);
6189 int door_2_width = MAX(door_2_left_width, door_2_right_width);
6190 int door_2_height = MAX(door_2_left_height, door_2_right_height);
6192 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
6193 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
6194 boolean door_1_done = (!handle_door_1);
6195 boolean door_2_done = (!handle_door_2);
6196 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
6197 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
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 door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6204 int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6207 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
6208 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
6210 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6211 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6212 // int door_size = (handle_door_1 ? door_size_1 : door_size_2);
6213 int door_size = (handle_door_2 ? door_size_2 : door_size_1);
6214 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
6215 int door_skip = max_door_size - door_size;
6216 int end = door_size;
6217 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
6220 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
6222 /* opening door sound has priority over simultaneously closing door */
6223 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
6224 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
6225 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
6226 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
6229 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
6233 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6234 GC gc = bitmap->stored_clip_gc;
6237 if (door_state & DOOR_ACTION_1 &&
6238 x * door_1.step_offset <= door_size_1)
6240 int a = MIN(x * door_1.step_offset, end);
6241 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
6245 int i = p + door_skip;
6249 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6250 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6251 Bitmap *bm_left = g_left->bitmap;
6252 Bitmap *bm_right = g_right->bitmap;
6253 GC gc_left = bm_left->stored_clip_gc;
6254 GC gc_right = bm_right->stored_clip_gc;
6257 int classic_dxsize = 100;
6258 int classic_dysize = 280;
6259 boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
6260 DYSIZE == classic_dysize);
6262 if (door_1.anim_mode & ANIM_STATIC_PANEL)
6264 BlitBitmap(bitmap_db_door, drawto,
6265 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
6266 DXSIZE, DYSIZE, DX, DY);
6270 BlitBitmap(bitmap_db_door, drawto,
6271 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
6272 DXSIZE, DYSIZE - p / 2, DX, DY);
6275 // printf("::: p == %d\n", p);
6276 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
6280 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
6283 int src1_x = g_right->src_x;
6284 int src1_y = g_right->src_y;
6285 int src2_x = g_left->src_x + g_left->width - i;
6286 int src2_y = g_left->src_y;
6287 int dst1_x = DX + DXSIZE - i;
6292 int height = DYSIZE;
6294 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6295 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6298 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6299 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6302 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6303 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6304 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6305 int dst2_x = DX, dst2_y = DY;
6306 int width = i, height = DYSIZE;
6308 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6309 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6312 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6313 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6317 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
6320 int src1_x = g_right->src_x;
6321 int src1_y = g_right->src_y;
6322 int src2_x = g_left->src_x;
6323 int src2_y = g_left->src_y + g_left->height - i;
6325 int dst1_y = DY + DYSIZE - i;
6331 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6332 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6335 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6336 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6339 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6340 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
6341 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
6342 int dst2_x = DX, dst2_y = DY;
6343 int width = DXSIZE, height = i;
6345 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6346 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6349 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6350 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6354 else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */
6356 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
6359 int src1_x = g_right->src_x;
6360 int src1_y = g_right->src_y;
6361 int src2_x = g_left->src_x + g_left->width - i;
6362 int src2_y = g_left->src_y;
6363 int dst1_x = DX + DXSIZE - i;
6368 int height1 = 63, height2 = DYSIZE / 2 - height1;
6369 int ypos1 = 0, ypos2 = height2;
6370 int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
6372 SetClipOrigin(bm_right, gc_right,
6373 dst1_x - src1_x, dst1_y - src1_y + j);
6374 BlitBitmapMasked(bm_right, drawto,
6375 src1_x, src1_y + ypos1, width, height2,
6376 dst1_x, dst1_y + ypos1 + j);
6377 BlitBitmapMasked(bm_right, drawto,
6378 src1_x, src1_y + ypos3, width, height1,
6379 dst1_x, dst1_y + ypos3 + j);
6380 SetClipOrigin(bm_left, gc_left,
6381 dst2_x - src2_x, dst2_y - src2_y - j);
6382 BlitBitmapMasked(bm_left, drawto,
6383 src2_x, src2_y + ypos1 + j, width, height2 - j,
6384 dst2_x, dst2_y + ypos1);
6385 BlitBitmapMasked(bm_left, drawto,
6386 src2_x, src2_y + ypos3, width, height1,
6387 dst2_x, dst2_y + ypos3 - j);
6389 SetClipOrigin(bm_left, gc_left,
6390 dst2_x - src2_x, dst2_y - src2_y - j);
6391 BlitBitmapMasked(bm_left, drawto,
6392 src2_x, src2_y + ypos2, width, height1,
6393 dst2_x, dst2_y + ypos2 - j);
6394 BlitBitmapMasked(bm_left, drawto,
6395 src2_x, src2_y + ypos4, width, height2,
6396 dst2_x, dst2_y + ypos4 - j);
6397 SetClipOrigin(bm_right, gc_right,
6398 dst1_x - src1_x, dst1_y - src1_y + j);
6399 BlitBitmapMasked(bm_right, drawto,
6400 src1_x, src1_y + ypos2, width, height1,
6401 dst1_x, dst1_y + ypos2 + j);
6402 BlitBitmapMasked(bm_right, drawto,
6403 src1_x, src1_y + ypos4, width, height2 - j,
6404 dst1_x, dst1_y + ypos4 + j);
6407 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6408 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6409 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6410 int dst2_x = DX, dst2_y = DY;
6411 int width = i, height = DYSIZE;
6412 int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
6414 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6415 BlitBitmapMasked(bitmap, drawto,
6416 src1_x, src1_y, width, ypos2,
6417 dst1_x, dst1_y + j);
6418 BlitBitmapMasked(bitmap, drawto,
6419 src1_x, src1_y + ypos3, width, ypos1,
6420 dst1_x, dst1_y + ypos3 + j);
6421 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6422 BlitBitmapMasked(bitmap, drawto,
6423 src2_x, src2_y + j, width, ypos2 - j,
6425 BlitBitmapMasked(bitmap, drawto,
6426 src2_x, src2_y + ypos3, width, ypos1,
6427 dst2_x, dst2_y + ypos3 - j);
6429 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6430 BlitBitmapMasked(bitmap, drawto,
6431 src2_x, src2_y + ypos2, width, ypos1,
6432 dst2_x, dst2_y + ypos2 - j);
6433 BlitBitmapMasked(bitmap, drawto,
6434 src2_x, src2_y + ypos4, width, ypos2,
6435 dst2_x, dst2_y + ypos4 - j);
6436 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6437 BlitBitmapMasked(bitmap, drawto,
6438 src1_x, src1_y + ypos2, width, ypos1,
6439 dst1_x, dst1_y + ypos2 + j);
6440 BlitBitmapMasked(bitmap, drawto,
6441 src1_x, src1_y + ypos4, width, ypos2 - j,
6442 dst1_x, dst1_y + ypos4 + j);
6445 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6446 BlitBitmapMasked(bitmap, drawto,
6447 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
6448 DX + DXSIZE - i, DY + j);
6449 BlitBitmapMasked(bitmap, drawto,
6450 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
6451 DX + DXSIZE - i, DY + 140 + j);
6452 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
6453 DY - (DOOR_GFX_PAGEY1 + j));
6454 BlitBitmapMasked(bitmap, drawto,
6455 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
6457 BlitBitmapMasked(bitmap, drawto,
6458 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
6461 BlitBitmapMasked(bitmap, drawto,
6462 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
6464 BlitBitmapMasked(bitmap, drawto,
6465 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
6467 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6468 BlitBitmapMasked(bitmap, drawto,
6469 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
6470 DX + DXSIZE - i, DY + 77 + j);
6471 BlitBitmapMasked(bitmap, drawto,
6472 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
6473 DX + DXSIZE - i, DY + 203 + j);
6478 redraw_mask |= REDRAW_DOOR_1;
6479 door_1_done = (a == end);
6482 if (door_state & DOOR_ACTION_2 &&
6483 x * door_2.step_offset <= door_size_2)
6485 int a = MIN(x * door_2.step_offset, door_size);
6486 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
6487 int i = p + door_skip;
6490 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6491 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6492 Bitmap *bm_left = g_left->bitmap;
6493 Bitmap *bm_right = g_right->bitmap;
6494 GC gc_left = bm_left->stored_clip_gc;
6495 GC gc_right = bm_right->stored_clip_gc;
6498 int classic_vxsize = 100;
6499 int classic_vysize = 100;
6500 boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
6501 VYSIZE == classic_vysize);
6503 if (door_2.anim_mode & ANIM_STATIC_PANEL)
6505 BlitBitmap(bitmap_db_door, drawto,
6506 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
6507 VXSIZE, VYSIZE, VX, VY);
6509 else if (x <= VYSIZE)
6511 BlitBitmap(bitmap_db_door, drawto,
6512 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
6513 VXSIZE, VYSIZE - p / 2, VX, VY);
6515 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
6518 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
6521 int src1_x = g_right->src_x;
6522 int src1_y = g_right->src_y;
6523 int src2_x = g_left->src_x + g_left->width - i;
6524 int src2_y = g_left->src_y;
6525 int dst1_x = VX + VXSIZE - i;
6530 int height = VYSIZE;
6532 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6533 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6536 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6537 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6540 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6541 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6542 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6543 int dst2_x = VX, dst2_y = VY;
6544 int width = i, height = VYSIZE;
6546 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6547 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6550 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6551 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6555 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
6558 int src1_x = g_right->src_x;
6559 int src1_y = g_right->src_y;
6560 int src2_x = g_left->src_x;
6561 int src2_y = g_left->src_y + g_left->height - i;
6563 int dst1_y = VY + VYSIZE - i;
6569 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6570 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6573 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6574 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6577 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6578 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
6579 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
6580 int dst2_x = VX, dst2_y = VY;
6581 int width = VXSIZE, height = i;
6583 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6584 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6587 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6588 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6592 else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */
6594 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
6597 int src1_x = g_right->src_x;
6598 int src1_y = g_right->src_y;
6599 int src2_x = g_left->src_x + g_left->width - i;
6600 int src2_y = g_left->src_y;
6601 int dst1_x = VX + VXSIZE - i;
6606 int height = VYSIZE / 2;
6607 int ypos1 = 0, ypos2 = VYSIZE / 2;
6609 SetClipOrigin(bm_right, gc_right,
6610 dst1_x - src1_x, dst1_y - src1_y + j);
6611 BlitBitmapMasked(bm_right, drawto,
6612 src1_x, src1_y + ypos1, width, height,
6613 dst1_x, dst1_y + ypos1 + j);
6614 SetClipOrigin(bm_left, gc_left,
6615 dst2_x - src2_x, dst2_y - src2_y - j);
6616 BlitBitmapMasked(bm_left, drawto,
6617 src2_x, src2_y + ypos1 + j, width, height - j,
6618 dst2_x, dst2_y + ypos1);
6620 SetClipOrigin(bm_left, gc_left,
6621 dst2_x - src2_x, dst2_y - src2_y - j);
6622 BlitBitmapMasked(bm_left, drawto,
6623 src2_x, src2_y + ypos2, width, height,
6624 dst2_x, dst2_y + ypos2 - j);
6625 SetClipOrigin(bm_right, gc_right,
6626 dst1_x - src1_x, dst1_y - src1_y + j);
6627 BlitBitmapMasked(bm_right, drawto,
6628 src1_x, src1_y + ypos2, width, height - j,
6629 dst1_x, dst1_y + ypos2 + j);
6631 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6632 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6633 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6634 int dst2_x = VX, dst2_y = VY;
6635 int width = i, height = VYSIZE;
6636 int ypos = VYSIZE / 2;
6638 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6639 BlitBitmapMasked(bitmap, drawto,
6640 src1_x, src1_y, width, ypos,
6641 dst1_x, dst1_y + j);
6642 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6643 BlitBitmapMasked(bitmap, drawto,
6644 src2_x, src2_y + j, width, ypos - j,
6647 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6648 BlitBitmapMasked(bitmap, drawto,
6649 src2_x, src2_y + ypos, width, ypos,
6650 dst2_x, dst2_y + ypos - j);
6651 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6652 BlitBitmapMasked(bitmap, drawto,
6653 src1_x, src1_y + ypos, width, ypos - j,
6654 dst1_x, dst1_y + ypos + j);
6657 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6658 BlitBitmapMasked(bitmap, drawto,
6659 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
6660 VX + VXSIZE - i, VY + j);
6661 SetClipOrigin(bitmap, gc,
6662 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
6663 BlitBitmapMasked(bitmap, drawto,
6664 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
6667 BlitBitmapMasked(bitmap, drawto,
6668 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6669 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
6670 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6671 BlitBitmapMasked(bitmap, drawto,
6672 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6674 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
6679 redraw_mask |= REDRAW_DOOR_2;
6680 door_2_done = (a == VXSIZE);
6683 if (!(door_state & DOOR_NO_DELAY))
6687 if (game_status == GAME_MODE_MAIN)
6690 WaitUntilDelayReached(&door_delay, door_delay_value);
6695 if (door_state & DOOR_ACTION_1)
6696 door1 = door_state & DOOR_ACTION_1;
6697 if (door_state & DOOR_ACTION_2)
6698 door2 = door_state & DOOR_ACTION_2;
6700 return (door1 | door2);
6705 void DrawSpecialEditorDoor()
6708 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6709 int top_border_width = gfx1->width;
6710 int top_border_height = gfx1->height;
6711 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6712 int ex = EX - outer_border;
6713 int ey = EY - outer_border;
6714 int vy = VY - outer_border;
6715 int exsize = EXSIZE + 2 * outer_border;
6717 CloseDoor(DOOR_CLOSE_2);
6719 /* draw bigger level editor toolbox window */
6720 BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
6721 top_border_width, top_border_height, ex, ey - top_border_height);
6722 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
6723 exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
6725 /* draw bigger level editor toolbox window */
6726 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
6727 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
6729 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6730 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
6734 redraw_mask |= REDRAW_ALL;
6737 void UndrawSpecialEditorDoor()
6740 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6741 int top_border_width = gfx1->width;
6742 int top_border_height = gfx1->height;
6743 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6744 int ex = EX - outer_border;
6745 int ey = EY - outer_border;
6746 int ey_top = ey - top_border_height;
6747 int exsize = EXSIZE + 2 * outer_border;
6748 int eysize = EYSIZE + 2 * outer_border;
6750 /* draw normal tape recorder window */
6751 if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
6753 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6754 ex, ey_top, top_border_width, top_border_height,
6756 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6757 ex, ey, exsize, eysize, ex, ey);
6761 // if screen background is set to "[NONE]", clear editor toolbox window
6762 ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
6763 ClearRectangle(drawto, ex, ey, exsize, eysize);
6766 /* draw normal tape recorder window */
6767 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6768 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
6772 redraw_mask |= REDRAW_ALL;
6776 /* ---------- new tool button stuff ---------------------------------------- */
6783 struct TextPosInfo *pos;
6786 } toolbutton_info[NUM_TOOL_BUTTONS] =
6789 IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
6790 TOOL_CTRL_ID_YES, "yes"
6793 IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
6794 TOOL_CTRL_ID_NO, "no"
6797 IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
6798 TOOL_CTRL_ID_CONFIRM, "confirm"
6801 IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
6802 TOOL_CTRL_ID_PLAYER_1, "player 1"
6805 IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
6806 TOOL_CTRL_ID_PLAYER_2, "player 2"
6809 IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
6810 TOOL_CTRL_ID_PLAYER_3, "player 3"
6813 IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
6814 TOOL_CTRL_ID_PLAYER_4, "player 4"
6818 void CreateToolButtons()
6822 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6824 struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
6825 struct TextPosInfo *pos = toolbutton_info[i].pos;
6826 struct GadgetInfo *gi;
6827 Bitmap *deco_bitmap = None;
6828 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6829 unsigned int event_mask = GD_EVENT_RELEASED;
6832 int gd_x = gfx->src_x;
6833 int gd_y = gfx->src_y;
6834 int gd_xp = gfx->src_x + gfx->pressed_xoffset;
6835 int gd_yp = gfx->src_y + gfx->pressed_yoffset;
6838 if (global.use_envelope_request)
6839 setRequestPosition(&dx, &dy, TRUE);
6841 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6843 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6845 getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
6846 pos->size, &deco_bitmap, &deco_x, &deco_y);
6847 deco_xpos = (gfx->width - pos->size) / 2;
6848 deco_ypos = (gfx->height - pos->size) / 2;
6851 gi = CreateGadget(GDI_CUSTOM_ID, id,
6852 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6853 GDI_X, dx + GDI_ACTIVE_POS(pos->x),
6854 GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
6855 GDI_WIDTH, gfx->width,
6856 GDI_HEIGHT, gfx->height,
6857 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6858 GDI_STATE, GD_BUTTON_UNPRESSED,
6859 GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
6860 GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
6861 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6862 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6863 GDI_DECORATION_SIZE, pos->size, pos->size,
6864 GDI_DECORATION_SHIFTING, 1, 1,
6865 GDI_DIRECT_DRAW, FALSE,
6866 GDI_EVENT_MASK, event_mask,
6867 GDI_CALLBACK_ACTION, HandleToolButtons,
6871 Error(ERR_EXIT, "cannot create gadget");
6873 tool_gadget[id] = gi;
6879 /* graphic position values for tool buttons */
6880 #define TOOL_BUTTON_YES_XPOS 2
6881 #define TOOL_BUTTON_YES_YPOS 250
6882 #define TOOL_BUTTON_YES_GFX_YPOS 0
6883 #define TOOL_BUTTON_YES_XSIZE 46
6884 #define TOOL_BUTTON_YES_YSIZE 28
6885 #define TOOL_BUTTON_NO_XPOS 52
6886 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
6887 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
6888 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
6889 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
6890 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
6891 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
6892 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
6893 #define TOOL_BUTTON_CONFIRM_XSIZE 96
6894 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
6895 #define TOOL_BUTTON_PLAYER_XSIZE 30
6896 #define TOOL_BUTTON_PLAYER_YSIZE 30
6897 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
6898 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
6899 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
6900 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
6901 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6902 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6903 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6904 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6905 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6906 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6907 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6908 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6909 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6910 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6911 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6912 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6913 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6914 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6915 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6916 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6925 } toolbutton_info[NUM_TOOL_BUTTONS] =
6928 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
6929 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
6930 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
6935 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
6936 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
6937 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
6942 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
6943 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
6944 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
6945 TOOL_CTRL_ID_CONFIRM,
6949 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6950 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
6951 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6952 TOOL_CTRL_ID_PLAYER_1,
6956 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6957 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
6958 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6959 TOOL_CTRL_ID_PLAYER_2,
6963 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6964 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
6965 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6966 TOOL_CTRL_ID_PLAYER_3,
6970 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6971 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
6972 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6973 TOOL_CTRL_ID_PLAYER_4,
6978 void CreateToolButtons()
6982 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6984 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6985 Bitmap *deco_bitmap = None;
6986 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6987 struct GadgetInfo *gi;
6988 unsigned int event_mask;
6989 int gd_xoffset, gd_yoffset;
6990 int gd_x1, gd_x2, gd_y;
6993 event_mask = GD_EVENT_RELEASED;
6995 gd_xoffset = toolbutton_info[i].xpos;
6996 gd_yoffset = toolbutton_info[i].ypos;
6997 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
6998 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
6999 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
7001 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
7003 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
7005 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
7006 &deco_bitmap, &deco_x, &deco_y);
7007 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
7008 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
7011 gi = CreateGadget(GDI_CUSTOM_ID, id,
7012 GDI_INFO_TEXT, toolbutton_info[i].infotext,
7013 GDI_X, DX + GDI_ACTIVE_POS(toolbutton_info[i].x),
7014 GDI_Y, DY + GDI_ACTIVE_POS(toolbutton_info[i].y),
7015 GDI_WIDTH, toolbutton_info[i].width,
7016 GDI_HEIGHT, toolbutton_info[i].height,
7017 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
7018 GDI_STATE, GD_BUTTON_UNPRESSED,
7019 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
7020 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
7021 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
7022 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
7023 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
7024 GDI_DECORATION_SHIFTING, 1, 1,
7025 GDI_DIRECT_DRAW, FALSE,
7026 GDI_EVENT_MASK, event_mask,
7027 GDI_CALLBACK_ACTION, HandleToolButtons,
7031 Error(ERR_EXIT, "cannot create gadget");
7033 tool_gadget[id] = gi;
7039 void FreeToolButtons()
7043 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7044 FreeGadget(tool_gadget[i]);
7047 static void UnmapToolButtons()
7051 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7052 UnmapGadget(tool_gadget[i]);
7055 static void HandleToolButtons(struct GadgetInfo *gi)
7057 request_gadget_id = gi->custom_id;
7060 static struct Mapping_EM_to_RND_object
7063 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
7064 boolean is_backside; /* backside of moving element */
7070 em_object_mapping_list[] =
7073 Xblank, TRUE, FALSE,
7077 Yacid_splash_eB, FALSE, FALSE,
7078 EL_ACID_SPLASH_RIGHT, -1, -1
7081 Yacid_splash_wB, FALSE, FALSE,
7082 EL_ACID_SPLASH_LEFT, -1, -1
7085 #ifdef EM_ENGINE_BAD_ROLL
7087 Xstone_force_e, FALSE, FALSE,
7088 EL_ROCK, -1, MV_BIT_RIGHT
7091 Xstone_force_w, FALSE, FALSE,
7092 EL_ROCK, -1, MV_BIT_LEFT
7095 Xnut_force_e, FALSE, FALSE,
7096 EL_NUT, -1, MV_BIT_RIGHT
7099 Xnut_force_w, FALSE, FALSE,
7100 EL_NUT, -1, MV_BIT_LEFT
7103 Xspring_force_e, FALSE, FALSE,
7104 EL_SPRING, -1, MV_BIT_RIGHT
7107 Xspring_force_w, FALSE, FALSE,
7108 EL_SPRING, -1, MV_BIT_LEFT
7111 Xemerald_force_e, FALSE, FALSE,
7112 EL_EMERALD, -1, MV_BIT_RIGHT
7115 Xemerald_force_w, FALSE, FALSE,
7116 EL_EMERALD, -1, MV_BIT_LEFT
7119 Xdiamond_force_e, FALSE, FALSE,
7120 EL_DIAMOND, -1, MV_BIT_RIGHT
7123 Xdiamond_force_w, FALSE, FALSE,
7124 EL_DIAMOND, -1, MV_BIT_LEFT
7127 Xbomb_force_e, FALSE, FALSE,
7128 EL_BOMB, -1, MV_BIT_RIGHT
7131 Xbomb_force_w, FALSE, FALSE,
7132 EL_BOMB, -1, MV_BIT_LEFT
7134 #endif /* EM_ENGINE_BAD_ROLL */
7137 Xstone, TRUE, FALSE,
7141 Xstone_pause, FALSE, FALSE,
7145 Xstone_fall, FALSE, FALSE,
7149 Ystone_s, FALSE, FALSE,
7150 EL_ROCK, ACTION_FALLING, -1
7153 Ystone_sB, FALSE, TRUE,
7154 EL_ROCK, ACTION_FALLING, -1
7157 Ystone_e, FALSE, FALSE,
7158 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7161 Ystone_eB, FALSE, TRUE,
7162 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7165 Ystone_w, FALSE, FALSE,
7166 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7169 Ystone_wB, FALSE, TRUE,
7170 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7177 Xnut_pause, FALSE, FALSE,
7181 Xnut_fall, FALSE, FALSE,
7185 Ynut_s, FALSE, FALSE,
7186 EL_NUT, ACTION_FALLING, -1
7189 Ynut_sB, FALSE, TRUE,
7190 EL_NUT, ACTION_FALLING, -1
7193 Ynut_e, FALSE, FALSE,
7194 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7197 Ynut_eB, FALSE, TRUE,
7198 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7201 Ynut_w, FALSE, FALSE,
7202 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7205 Ynut_wB, FALSE, TRUE,
7206 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7209 Xbug_n, TRUE, FALSE,
7213 Xbug_e, TRUE, FALSE,
7214 EL_BUG_RIGHT, -1, -1
7217 Xbug_s, TRUE, FALSE,
7221 Xbug_w, TRUE, FALSE,
7225 Xbug_gon, FALSE, FALSE,
7229 Xbug_goe, FALSE, FALSE,
7230 EL_BUG_RIGHT, -1, -1
7233 Xbug_gos, FALSE, FALSE,
7237 Xbug_gow, FALSE, FALSE,
7241 Ybug_n, FALSE, FALSE,
7242 EL_BUG, ACTION_MOVING, MV_BIT_UP
7245 Ybug_nB, FALSE, TRUE,
7246 EL_BUG, ACTION_MOVING, MV_BIT_UP
7249 Ybug_e, FALSE, FALSE,
7250 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7253 Ybug_eB, FALSE, TRUE,
7254 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7257 Ybug_s, FALSE, FALSE,
7258 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7261 Ybug_sB, FALSE, TRUE,
7262 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7265 Ybug_w, FALSE, FALSE,
7266 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7269 Ybug_wB, FALSE, TRUE,
7270 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7273 Ybug_w_n, FALSE, FALSE,
7274 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7277 Ybug_n_e, FALSE, FALSE,
7278 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7281 Ybug_e_s, FALSE, FALSE,
7282 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7285 Ybug_s_w, FALSE, FALSE,
7286 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7289 Ybug_e_n, FALSE, FALSE,
7290 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7293 Ybug_s_e, FALSE, FALSE,
7294 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7297 Ybug_w_s, FALSE, FALSE,
7298 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7301 Ybug_n_w, FALSE, FALSE,
7302 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7305 Ybug_stone, FALSE, FALSE,
7306 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
7309 Ybug_spring, FALSE, FALSE,
7310 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
7313 Xtank_n, TRUE, FALSE,
7314 EL_SPACESHIP_UP, -1, -1
7317 Xtank_e, TRUE, FALSE,
7318 EL_SPACESHIP_RIGHT, -1, -1
7321 Xtank_s, TRUE, FALSE,
7322 EL_SPACESHIP_DOWN, -1, -1
7325 Xtank_w, TRUE, FALSE,
7326 EL_SPACESHIP_LEFT, -1, -1
7329 Xtank_gon, FALSE, FALSE,
7330 EL_SPACESHIP_UP, -1, -1
7333 Xtank_goe, FALSE, FALSE,
7334 EL_SPACESHIP_RIGHT, -1, -1
7337 Xtank_gos, FALSE, FALSE,
7338 EL_SPACESHIP_DOWN, -1, -1
7341 Xtank_gow, FALSE, FALSE,
7342 EL_SPACESHIP_LEFT, -1, -1
7345 Ytank_n, FALSE, FALSE,
7346 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7349 Ytank_nB, FALSE, TRUE,
7350 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7353 Ytank_e, FALSE, FALSE,
7354 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7357 Ytank_eB, FALSE, TRUE,
7358 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7361 Ytank_s, FALSE, FALSE,
7362 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7365 Ytank_sB, FALSE, TRUE,
7366 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7369 Ytank_w, FALSE, FALSE,
7370 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7373 Ytank_wB, FALSE, TRUE,
7374 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7377 Ytank_w_n, FALSE, FALSE,
7378 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7381 Ytank_n_e, FALSE, FALSE,
7382 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7385 Ytank_e_s, FALSE, FALSE,
7386 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7389 Ytank_s_w, FALSE, FALSE,
7390 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7393 Ytank_e_n, FALSE, FALSE,
7394 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7397 Ytank_s_e, FALSE, FALSE,
7398 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7401 Ytank_w_s, FALSE, FALSE,
7402 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7405 Ytank_n_w, FALSE, FALSE,
7406 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7409 Ytank_stone, FALSE, FALSE,
7410 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
7413 Ytank_spring, FALSE, FALSE,
7414 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
7417 Xandroid, TRUE, FALSE,
7418 EL_EMC_ANDROID, ACTION_ACTIVE, -1
7421 Xandroid_1_n, FALSE, FALSE,
7422 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7425 Xandroid_2_n, FALSE, FALSE,
7426 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7429 Xandroid_1_e, FALSE, FALSE,
7430 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7433 Xandroid_2_e, FALSE, FALSE,
7434 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7437 Xandroid_1_w, FALSE, FALSE,
7438 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7441 Xandroid_2_w, FALSE, FALSE,
7442 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7445 Xandroid_1_s, FALSE, FALSE,
7446 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7449 Xandroid_2_s, FALSE, FALSE,
7450 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7453 Yandroid_n, FALSE, FALSE,
7454 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7457 Yandroid_nB, FALSE, TRUE,
7458 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7461 Yandroid_ne, FALSE, FALSE,
7462 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
7465 Yandroid_neB, FALSE, TRUE,
7466 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
7469 Yandroid_e, FALSE, FALSE,
7470 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7473 Yandroid_eB, FALSE, TRUE,
7474 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7477 Yandroid_se, FALSE, FALSE,
7478 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
7481 Yandroid_seB, FALSE, TRUE,
7482 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
7485 Yandroid_s, FALSE, FALSE,
7486 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7489 Yandroid_sB, FALSE, TRUE,
7490 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7493 Yandroid_sw, FALSE, FALSE,
7494 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
7497 Yandroid_swB, FALSE, TRUE,
7498 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
7501 Yandroid_w, FALSE, FALSE,
7502 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7505 Yandroid_wB, FALSE, TRUE,
7506 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7509 Yandroid_nw, FALSE, FALSE,
7510 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
7513 Yandroid_nwB, FALSE, TRUE,
7514 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
7517 Xspring, TRUE, FALSE,
7521 Xspring_pause, FALSE, FALSE,
7525 Xspring_e, FALSE, FALSE,
7529 Xspring_w, FALSE, FALSE,
7533 Xspring_fall, FALSE, FALSE,
7537 Yspring_s, FALSE, FALSE,
7538 EL_SPRING, ACTION_FALLING, -1
7541 Yspring_sB, FALSE, TRUE,
7542 EL_SPRING, ACTION_FALLING, -1
7545 Yspring_e, FALSE, FALSE,
7546 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7549 Yspring_eB, FALSE, TRUE,
7550 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7553 Yspring_w, FALSE, FALSE,
7554 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7557 Yspring_wB, FALSE, TRUE,
7558 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7561 Yspring_kill_e, FALSE, FALSE,
7562 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7565 Yspring_kill_eB, FALSE, TRUE,
7566 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7569 Yspring_kill_w, FALSE, FALSE,
7570 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7573 Yspring_kill_wB, FALSE, TRUE,
7574 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7577 Xeater_n, TRUE, FALSE,
7578 EL_YAMYAM_UP, -1, -1
7581 Xeater_e, TRUE, FALSE,
7582 EL_YAMYAM_RIGHT, -1, -1
7585 Xeater_w, TRUE, FALSE,
7586 EL_YAMYAM_LEFT, -1, -1
7589 Xeater_s, TRUE, FALSE,
7590 EL_YAMYAM_DOWN, -1, -1
7593 Yeater_n, FALSE, FALSE,
7594 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7597 Yeater_nB, FALSE, TRUE,
7598 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7601 Yeater_e, FALSE, FALSE,
7602 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7605 Yeater_eB, FALSE, TRUE,
7606 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7609 Yeater_s, FALSE, FALSE,
7610 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7613 Yeater_sB, FALSE, TRUE,
7614 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7617 Yeater_w, FALSE, FALSE,
7618 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7621 Yeater_wB, FALSE, TRUE,
7622 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7625 Yeater_stone, FALSE, FALSE,
7626 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
7629 Yeater_spring, FALSE, FALSE,
7630 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
7633 Xalien, TRUE, FALSE,
7637 Xalien_pause, FALSE, FALSE,
7641 Yalien_n, FALSE, FALSE,
7642 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7645 Yalien_nB, FALSE, TRUE,
7646 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7649 Yalien_e, FALSE, FALSE,
7650 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7653 Yalien_eB, FALSE, TRUE,
7654 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7657 Yalien_s, FALSE, FALSE,
7658 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7661 Yalien_sB, FALSE, TRUE,
7662 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7665 Yalien_w, FALSE, FALSE,
7666 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7669 Yalien_wB, FALSE, TRUE,
7670 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7673 Yalien_stone, FALSE, FALSE,
7674 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
7677 Yalien_spring, FALSE, FALSE,
7678 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
7681 Xemerald, TRUE, FALSE,
7685 Xemerald_pause, FALSE, FALSE,
7689 Xemerald_fall, FALSE, FALSE,
7693 Xemerald_shine, FALSE, FALSE,
7694 EL_EMERALD, ACTION_TWINKLING, -1
7697 Yemerald_s, FALSE, FALSE,
7698 EL_EMERALD, ACTION_FALLING, -1
7701 Yemerald_sB, FALSE, TRUE,
7702 EL_EMERALD, ACTION_FALLING, -1
7705 Yemerald_e, FALSE, FALSE,
7706 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7709 Yemerald_eB, FALSE, TRUE,
7710 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7713 Yemerald_w, FALSE, FALSE,
7714 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7717 Yemerald_wB, FALSE, TRUE,
7718 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7721 Yemerald_eat, FALSE, FALSE,
7722 EL_EMERALD, ACTION_COLLECTING, -1
7725 Yemerald_stone, FALSE, FALSE,
7726 EL_NUT, ACTION_BREAKING, -1
7729 Xdiamond, TRUE, FALSE,
7733 Xdiamond_pause, FALSE, FALSE,
7737 Xdiamond_fall, FALSE, FALSE,
7741 Xdiamond_shine, FALSE, FALSE,
7742 EL_DIAMOND, ACTION_TWINKLING, -1
7745 Ydiamond_s, FALSE, FALSE,
7746 EL_DIAMOND, ACTION_FALLING, -1
7749 Ydiamond_sB, FALSE, TRUE,
7750 EL_DIAMOND, ACTION_FALLING, -1
7753 Ydiamond_e, FALSE, FALSE,
7754 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7757 Ydiamond_eB, FALSE, TRUE,
7758 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7761 Ydiamond_w, FALSE, FALSE,
7762 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7765 Ydiamond_wB, FALSE, TRUE,
7766 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7769 Ydiamond_eat, FALSE, FALSE,
7770 EL_DIAMOND, ACTION_COLLECTING, -1
7773 Ydiamond_stone, FALSE, FALSE,
7774 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
7777 Xdrip_fall, TRUE, FALSE,
7778 EL_AMOEBA_DROP, -1, -1
7781 Xdrip_stretch, FALSE, FALSE,
7782 EL_AMOEBA_DROP, ACTION_FALLING, -1
7785 Xdrip_stretchB, FALSE, TRUE,
7786 EL_AMOEBA_DROP, ACTION_FALLING, -1
7789 Xdrip_eat, FALSE, FALSE,
7790 EL_AMOEBA_DROP, ACTION_GROWING, -1
7793 Ydrip_s1, FALSE, FALSE,
7794 EL_AMOEBA_DROP, ACTION_FALLING, -1
7797 Ydrip_s1B, FALSE, TRUE,
7798 EL_AMOEBA_DROP, ACTION_FALLING, -1
7801 Ydrip_s2, FALSE, FALSE,
7802 EL_AMOEBA_DROP, ACTION_FALLING, -1
7805 Ydrip_s2B, FALSE, TRUE,
7806 EL_AMOEBA_DROP, ACTION_FALLING, -1
7813 Xbomb_pause, FALSE, FALSE,
7817 Xbomb_fall, FALSE, FALSE,
7821 Ybomb_s, FALSE, FALSE,
7822 EL_BOMB, ACTION_FALLING, -1
7825 Ybomb_sB, FALSE, TRUE,
7826 EL_BOMB, ACTION_FALLING, -1
7829 Ybomb_e, FALSE, FALSE,
7830 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7833 Ybomb_eB, FALSE, TRUE,
7834 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7837 Ybomb_w, FALSE, FALSE,
7838 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7841 Ybomb_wB, FALSE, TRUE,
7842 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7845 Ybomb_eat, FALSE, FALSE,
7846 EL_BOMB, ACTION_ACTIVATING, -1
7849 Xballoon, TRUE, FALSE,
7853 Yballoon_n, FALSE, FALSE,
7854 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7857 Yballoon_nB, FALSE, TRUE,
7858 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7861 Yballoon_e, FALSE, FALSE,
7862 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7865 Yballoon_eB, FALSE, TRUE,
7866 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7869 Yballoon_s, FALSE, FALSE,
7870 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7873 Yballoon_sB, FALSE, TRUE,
7874 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7877 Yballoon_w, FALSE, FALSE,
7878 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7881 Yballoon_wB, FALSE, TRUE,
7882 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7885 Xgrass, TRUE, FALSE,
7886 EL_EMC_GRASS, -1, -1
7889 Ygrass_nB, FALSE, FALSE,
7890 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
7893 Ygrass_eB, FALSE, FALSE,
7894 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
7897 Ygrass_sB, FALSE, FALSE,
7898 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
7901 Ygrass_wB, FALSE, FALSE,
7902 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
7909 Ydirt_nB, FALSE, FALSE,
7910 EL_SAND, ACTION_DIGGING, MV_BIT_UP
7913 Ydirt_eB, FALSE, FALSE,
7914 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
7917 Ydirt_sB, FALSE, FALSE,
7918 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
7921 Ydirt_wB, FALSE, FALSE,
7922 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
7925 Xacid_ne, TRUE, FALSE,
7926 EL_ACID_POOL_TOPRIGHT, -1, -1
7929 Xacid_se, TRUE, FALSE,
7930 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
7933 Xacid_s, TRUE, FALSE,
7934 EL_ACID_POOL_BOTTOM, -1, -1
7937 Xacid_sw, TRUE, FALSE,
7938 EL_ACID_POOL_BOTTOMLEFT, -1, -1
7941 Xacid_nw, TRUE, FALSE,
7942 EL_ACID_POOL_TOPLEFT, -1, -1
7945 Xacid_1, TRUE, FALSE,
7949 Xacid_2, FALSE, FALSE,
7953 Xacid_3, FALSE, FALSE,
7957 Xacid_4, FALSE, FALSE,
7961 Xacid_5, FALSE, FALSE,
7965 Xacid_6, FALSE, FALSE,
7969 Xacid_7, FALSE, FALSE,
7973 Xacid_8, FALSE, FALSE,
7977 Xball_1, TRUE, FALSE,
7978 EL_EMC_MAGIC_BALL, -1, -1
7981 Xball_1B, FALSE, FALSE,
7982 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7985 Xball_2, FALSE, FALSE,
7986 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7989 Xball_2B, FALSE, FALSE,
7990 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7993 Yball_eat, FALSE, FALSE,
7994 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
7997 Ykey_1_eat, FALSE, FALSE,
7998 EL_EM_KEY_1, ACTION_COLLECTING, -1
8001 Ykey_2_eat, FALSE, FALSE,
8002 EL_EM_KEY_2, ACTION_COLLECTING, -1
8005 Ykey_3_eat, FALSE, FALSE,
8006 EL_EM_KEY_3, ACTION_COLLECTING, -1
8009 Ykey_4_eat, FALSE, FALSE,
8010 EL_EM_KEY_4, ACTION_COLLECTING, -1
8013 Ykey_5_eat, FALSE, FALSE,
8014 EL_EMC_KEY_5, ACTION_COLLECTING, -1
8017 Ykey_6_eat, FALSE, FALSE,
8018 EL_EMC_KEY_6, ACTION_COLLECTING, -1
8021 Ykey_7_eat, FALSE, FALSE,
8022 EL_EMC_KEY_7, ACTION_COLLECTING, -1
8025 Ykey_8_eat, FALSE, FALSE,
8026 EL_EMC_KEY_8, ACTION_COLLECTING, -1
8029 Ylenses_eat, FALSE, FALSE,
8030 EL_EMC_LENSES, ACTION_COLLECTING, -1
8033 Ymagnify_eat, FALSE, FALSE,
8034 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
8037 Ygrass_eat, FALSE, FALSE,
8038 EL_EMC_GRASS, ACTION_SNAPPING, -1
8041 Ydirt_eat, FALSE, FALSE,
8042 EL_SAND, ACTION_SNAPPING, -1
8045 Xgrow_ns, TRUE, FALSE,
8046 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
8049 Ygrow_ns_eat, FALSE, FALSE,
8050 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
8053 Xgrow_ew, TRUE, FALSE,
8054 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
8057 Ygrow_ew_eat, FALSE, FALSE,
8058 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
8061 Xwonderwall, TRUE, FALSE,
8062 EL_MAGIC_WALL, -1, -1
8065 XwonderwallB, FALSE, FALSE,
8066 EL_MAGIC_WALL, ACTION_ACTIVE, -1
8069 Xamoeba_1, TRUE, FALSE,
8070 EL_AMOEBA_DRY, ACTION_OTHER, -1
8073 Xamoeba_2, FALSE, FALSE,
8074 EL_AMOEBA_DRY, ACTION_OTHER, -1
8077 Xamoeba_3, FALSE, FALSE,
8078 EL_AMOEBA_DRY, ACTION_OTHER, -1
8081 Xamoeba_4, FALSE, FALSE,
8082 EL_AMOEBA_DRY, ACTION_OTHER, -1
8085 Xamoeba_5, TRUE, FALSE,
8086 EL_AMOEBA_WET, ACTION_OTHER, -1
8089 Xamoeba_6, FALSE, FALSE,
8090 EL_AMOEBA_WET, ACTION_OTHER, -1
8093 Xamoeba_7, FALSE, FALSE,
8094 EL_AMOEBA_WET, ACTION_OTHER, -1
8097 Xamoeba_8, FALSE, FALSE,
8098 EL_AMOEBA_WET, ACTION_OTHER, -1
8101 Xdoor_1, TRUE, FALSE,
8102 EL_EM_GATE_1, -1, -1
8105 Xdoor_2, TRUE, FALSE,
8106 EL_EM_GATE_2, -1, -1
8109 Xdoor_3, TRUE, FALSE,
8110 EL_EM_GATE_3, -1, -1
8113 Xdoor_4, TRUE, FALSE,
8114 EL_EM_GATE_4, -1, -1
8117 Xdoor_5, TRUE, FALSE,
8118 EL_EMC_GATE_5, -1, -1
8121 Xdoor_6, TRUE, FALSE,
8122 EL_EMC_GATE_6, -1, -1
8125 Xdoor_7, TRUE, FALSE,
8126 EL_EMC_GATE_7, -1, -1
8129 Xdoor_8, TRUE, FALSE,
8130 EL_EMC_GATE_8, -1, -1
8133 Xkey_1, TRUE, FALSE,
8137 Xkey_2, TRUE, FALSE,
8141 Xkey_3, TRUE, FALSE,
8145 Xkey_4, TRUE, FALSE,
8149 Xkey_5, TRUE, FALSE,
8150 EL_EMC_KEY_5, -1, -1
8153 Xkey_6, TRUE, FALSE,
8154 EL_EMC_KEY_6, -1, -1
8157 Xkey_7, TRUE, FALSE,
8158 EL_EMC_KEY_7, -1, -1
8161 Xkey_8, TRUE, FALSE,
8162 EL_EMC_KEY_8, -1, -1
8165 Xwind_n, TRUE, FALSE,
8166 EL_BALLOON_SWITCH_UP, -1, -1
8169 Xwind_e, TRUE, FALSE,
8170 EL_BALLOON_SWITCH_RIGHT, -1, -1
8173 Xwind_s, TRUE, FALSE,
8174 EL_BALLOON_SWITCH_DOWN, -1, -1
8177 Xwind_w, TRUE, FALSE,
8178 EL_BALLOON_SWITCH_LEFT, -1, -1
8181 Xwind_nesw, TRUE, FALSE,
8182 EL_BALLOON_SWITCH_ANY, -1, -1
8185 Xwind_stop, TRUE, FALSE,
8186 EL_BALLOON_SWITCH_NONE, -1, -1
8190 EL_EM_EXIT_CLOSED, -1, -1
8193 Xexit_1, TRUE, FALSE,
8194 EL_EM_EXIT_OPEN, -1, -1
8197 Xexit_2, FALSE, FALSE,
8198 EL_EM_EXIT_OPEN, -1, -1
8201 Xexit_3, FALSE, FALSE,
8202 EL_EM_EXIT_OPEN, -1, -1
8205 Xdynamite, TRUE, FALSE,
8206 EL_EM_DYNAMITE, -1, -1
8209 Ydynamite_eat, FALSE, FALSE,
8210 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
8213 Xdynamite_1, TRUE, FALSE,
8214 EL_EM_DYNAMITE_ACTIVE, -1, -1
8217 Xdynamite_2, FALSE, FALSE,
8218 EL_EM_DYNAMITE_ACTIVE, -1, -1
8221 Xdynamite_3, FALSE, FALSE,
8222 EL_EM_DYNAMITE_ACTIVE, -1, -1
8225 Xdynamite_4, FALSE, FALSE,
8226 EL_EM_DYNAMITE_ACTIVE, -1, -1
8229 Xbumper, TRUE, FALSE,
8230 EL_EMC_SPRING_BUMPER, -1, -1
8233 XbumperB, FALSE, FALSE,
8234 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
8237 Xwheel, TRUE, FALSE,
8238 EL_ROBOT_WHEEL, -1, -1
8241 XwheelB, FALSE, FALSE,
8242 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
8245 Xswitch, TRUE, FALSE,
8246 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
8249 XswitchB, FALSE, FALSE,
8250 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
8254 EL_QUICKSAND_EMPTY, -1, -1
8257 Xsand_stone, TRUE, FALSE,
8258 EL_QUICKSAND_FULL, -1, -1
8261 Xsand_stonein_1, FALSE, TRUE,
8262 EL_ROCK, ACTION_FILLING, -1
8265 Xsand_stonein_2, FALSE, TRUE,
8266 EL_ROCK, ACTION_FILLING, -1
8269 Xsand_stonein_3, FALSE, TRUE,
8270 EL_ROCK, ACTION_FILLING, -1
8273 Xsand_stonein_4, FALSE, TRUE,
8274 EL_ROCK, ACTION_FILLING, -1
8278 Xsand_stonesand_1, FALSE, FALSE,
8279 EL_QUICKSAND_EMPTYING, -1, -1
8282 Xsand_stonesand_2, FALSE, FALSE,
8283 EL_QUICKSAND_EMPTYING, -1, -1
8286 Xsand_stonesand_3, FALSE, FALSE,
8287 EL_QUICKSAND_EMPTYING, -1, -1
8290 Xsand_stonesand_4, FALSE, FALSE,
8291 EL_QUICKSAND_EMPTYING, -1, -1
8294 Xsand_stonesand_quickout_1, FALSE, FALSE,
8295 EL_QUICKSAND_EMPTYING, -1, -1
8298 Xsand_stonesand_quickout_2, FALSE, FALSE,
8299 EL_QUICKSAND_EMPTYING, -1, -1
8303 Xsand_stonesand_1, FALSE, FALSE,
8304 EL_QUICKSAND_FULL, -1, -1
8307 Xsand_stonesand_2, FALSE, FALSE,
8308 EL_QUICKSAND_FULL, -1, -1
8311 Xsand_stonesand_3, FALSE, FALSE,
8312 EL_QUICKSAND_FULL, -1, -1
8315 Xsand_stonesand_4, FALSE, FALSE,
8316 EL_QUICKSAND_FULL, -1, -1
8320 Xsand_stoneout_1, FALSE, FALSE,
8321 EL_ROCK, ACTION_EMPTYING, -1
8324 Xsand_stoneout_2, FALSE, FALSE,
8325 EL_ROCK, ACTION_EMPTYING, -1
8329 Xsand_sandstone_1, FALSE, FALSE,
8330 EL_QUICKSAND_FILLING, -1, -1
8333 Xsand_sandstone_2, FALSE, FALSE,
8334 EL_QUICKSAND_FILLING, -1, -1
8337 Xsand_sandstone_3, FALSE, FALSE,
8338 EL_QUICKSAND_FILLING, -1, -1
8341 Xsand_sandstone_4, FALSE, FALSE,
8342 EL_QUICKSAND_FILLING, -1, -1
8346 Xsand_sandstone_1, FALSE, FALSE,
8347 EL_QUICKSAND_FULL, -1, -1
8350 Xsand_sandstone_2, FALSE, FALSE,
8351 EL_QUICKSAND_FULL, -1, -1
8354 Xsand_sandstone_3, FALSE, FALSE,
8355 EL_QUICKSAND_FULL, -1, -1
8358 Xsand_sandstone_4, FALSE, FALSE,
8359 EL_QUICKSAND_FULL, -1, -1
8363 Xplant, TRUE, FALSE,
8364 EL_EMC_PLANT, -1, -1
8367 Yplant, FALSE, FALSE,
8368 EL_EMC_PLANT, -1, -1
8371 Xlenses, TRUE, FALSE,
8372 EL_EMC_LENSES, -1, -1
8375 Xmagnify, TRUE, FALSE,
8376 EL_EMC_MAGNIFIER, -1, -1
8379 Xdripper, TRUE, FALSE,
8380 EL_EMC_DRIPPER, -1, -1
8383 XdripperB, FALSE, FALSE,
8384 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
8387 Xfake_blank, TRUE, FALSE,
8388 EL_INVISIBLE_WALL, -1, -1
8391 Xfake_blankB, FALSE, FALSE,
8392 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
8395 Xfake_grass, TRUE, FALSE,
8396 EL_EMC_FAKE_GRASS, -1, -1
8399 Xfake_grassB, FALSE, FALSE,
8400 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
8403 Xfake_door_1, TRUE, FALSE,
8404 EL_EM_GATE_1_GRAY, -1, -1
8407 Xfake_door_2, TRUE, FALSE,
8408 EL_EM_GATE_2_GRAY, -1, -1
8411 Xfake_door_3, TRUE, FALSE,
8412 EL_EM_GATE_3_GRAY, -1, -1
8415 Xfake_door_4, TRUE, FALSE,
8416 EL_EM_GATE_4_GRAY, -1, -1
8419 Xfake_door_5, TRUE, FALSE,
8420 EL_EMC_GATE_5_GRAY, -1, -1
8423 Xfake_door_6, TRUE, FALSE,
8424 EL_EMC_GATE_6_GRAY, -1, -1
8427 Xfake_door_7, TRUE, FALSE,
8428 EL_EMC_GATE_7_GRAY, -1, -1
8431 Xfake_door_8, TRUE, FALSE,
8432 EL_EMC_GATE_8_GRAY, -1, -1
8435 Xfake_acid_1, TRUE, FALSE,
8436 EL_EMC_FAKE_ACID, -1, -1
8439 Xfake_acid_2, FALSE, FALSE,
8440 EL_EMC_FAKE_ACID, -1, -1
8443 Xfake_acid_3, FALSE, FALSE,
8444 EL_EMC_FAKE_ACID, -1, -1
8447 Xfake_acid_4, FALSE, FALSE,
8448 EL_EMC_FAKE_ACID, -1, -1
8451 Xfake_acid_5, FALSE, FALSE,
8452 EL_EMC_FAKE_ACID, -1, -1
8455 Xfake_acid_6, FALSE, FALSE,
8456 EL_EMC_FAKE_ACID, -1, -1
8459 Xfake_acid_7, FALSE, FALSE,
8460 EL_EMC_FAKE_ACID, -1, -1
8463 Xfake_acid_8, FALSE, FALSE,
8464 EL_EMC_FAKE_ACID, -1, -1
8467 Xsteel_1, TRUE, FALSE,
8468 EL_STEELWALL, -1, -1
8471 Xsteel_2, TRUE, FALSE,
8472 EL_EMC_STEELWALL_2, -1, -1
8475 Xsteel_3, TRUE, FALSE,
8476 EL_EMC_STEELWALL_3, -1, -1
8479 Xsteel_4, TRUE, FALSE,
8480 EL_EMC_STEELWALL_4, -1, -1
8483 Xwall_1, TRUE, FALSE,
8487 Xwall_2, TRUE, FALSE,
8488 EL_EMC_WALL_14, -1, -1
8491 Xwall_3, TRUE, FALSE,
8492 EL_EMC_WALL_15, -1, -1
8495 Xwall_4, TRUE, FALSE,
8496 EL_EMC_WALL_16, -1, -1
8499 Xround_wall_1, TRUE, FALSE,
8500 EL_WALL_SLIPPERY, -1, -1
8503 Xround_wall_2, TRUE, FALSE,
8504 EL_EMC_WALL_SLIPPERY_2, -1, -1
8507 Xround_wall_3, TRUE, FALSE,
8508 EL_EMC_WALL_SLIPPERY_3, -1, -1
8511 Xround_wall_4, TRUE, FALSE,
8512 EL_EMC_WALL_SLIPPERY_4, -1, -1
8515 Xdecor_1, TRUE, FALSE,
8516 EL_EMC_WALL_8, -1, -1
8519 Xdecor_2, TRUE, FALSE,
8520 EL_EMC_WALL_6, -1, -1
8523 Xdecor_3, TRUE, FALSE,
8524 EL_EMC_WALL_4, -1, -1
8527 Xdecor_4, TRUE, FALSE,
8528 EL_EMC_WALL_7, -1, -1
8531 Xdecor_5, TRUE, FALSE,
8532 EL_EMC_WALL_5, -1, -1
8535 Xdecor_6, TRUE, FALSE,
8536 EL_EMC_WALL_9, -1, -1
8539 Xdecor_7, TRUE, FALSE,
8540 EL_EMC_WALL_10, -1, -1
8543 Xdecor_8, TRUE, FALSE,
8544 EL_EMC_WALL_1, -1, -1
8547 Xdecor_9, TRUE, FALSE,
8548 EL_EMC_WALL_2, -1, -1
8551 Xdecor_10, TRUE, FALSE,
8552 EL_EMC_WALL_3, -1, -1
8555 Xdecor_11, TRUE, FALSE,
8556 EL_EMC_WALL_11, -1, -1
8559 Xdecor_12, TRUE, FALSE,
8560 EL_EMC_WALL_12, -1, -1
8563 Xalpha_0, TRUE, FALSE,
8564 EL_CHAR('0'), -1, -1
8567 Xalpha_1, TRUE, FALSE,
8568 EL_CHAR('1'), -1, -1
8571 Xalpha_2, TRUE, FALSE,
8572 EL_CHAR('2'), -1, -1
8575 Xalpha_3, TRUE, FALSE,
8576 EL_CHAR('3'), -1, -1
8579 Xalpha_4, TRUE, FALSE,
8580 EL_CHAR('4'), -1, -1
8583 Xalpha_5, TRUE, FALSE,
8584 EL_CHAR('5'), -1, -1
8587 Xalpha_6, TRUE, FALSE,
8588 EL_CHAR('6'), -1, -1
8591 Xalpha_7, TRUE, FALSE,
8592 EL_CHAR('7'), -1, -1
8595 Xalpha_8, TRUE, FALSE,
8596 EL_CHAR('8'), -1, -1
8599 Xalpha_9, TRUE, FALSE,
8600 EL_CHAR('9'), -1, -1
8603 Xalpha_excla, TRUE, FALSE,
8604 EL_CHAR('!'), -1, -1
8607 Xalpha_quote, TRUE, FALSE,
8608 EL_CHAR('"'), -1, -1
8611 Xalpha_comma, TRUE, FALSE,
8612 EL_CHAR(','), -1, -1
8615 Xalpha_minus, TRUE, FALSE,
8616 EL_CHAR('-'), -1, -1
8619 Xalpha_perio, TRUE, FALSE,
8620 EL_CHAR('.'), -1, -1
8623 Xalpha_colon, TRUE, FALSE,
8624 EL_CHAR(':'), -1, -1
8627 Xalpha_quest, TRUE, FALSE,
8628 EL_CHAR('?'), -1, -1
8631 Xalpha_a, TRUE, FALSE,
8632 EL_CHAR('A'), -1, -1
8635 Xalpha_b, TRUE, FALSE,
8636 EL_CHAR('B'), -1, -1
8639 Xalpha_c, TRUE, FALSE,
8640 EL_CHAR('C'), -1, -1
8643 Xalpha_d, TRUE, FALSE,
8644 EL_CHAR('D'), -1, -1
8647 Xalpha_e, TRUE, FALSE,
8648 EL_CHAR('E'), -1, -1
8651 Xalpha_f, TRUE, FALSE,
8652 EL_CHAR('F'), -1, -1
8655 Xalpha_g, TRUE, FALSE,
8656 EL_CHAR('G'), -1, -1
8659 Xalpha_h, TRUE, FALSE,
8660 EL_CHAR('H'), -1, -1
8663 Xalpha_i, TRUE, FALSE,
8664 EL_CHAR('I'), -1, -1
8667 Xalpha_j, TRUE, FALSE,
8668 EL_CHAR('J'), -1, -1
8671 Xalpha_k, TRUE, FALSE,
8672 EL_CHAR('K'), -1, -1
8675 Xalpha_l, TRUE, FALSE,
8676 EL_CHAR('L'), -1, -1
8679 Xalpha_m, TRUE, FALSE,
8680 EL_CHAR('M'), -1, -1
8683 Xalpha_n, TRUE, FALSE,
8684 EL_CHAR('N'), -1, -1
8687 Xalpha_o, TRUE, FALSE,
8688 EL_CHAR('O'), -1, -1
8691 Xalpha_p, TRUE, FALSE,
8692 EL_CHAR('P'), -1, -1
8695 Xalpha_q, TRUE, FALSE,
8696 EL_CHAR('Q'), -1, -1
8699 Xalpha_r, TRUE, FALSE,
8700 EL_CHAR('R'), -1, -1
8703 Xalpha_s, TRUE, FALSE,
8704 EL_CHAR('S'), -1, -1
8707 Xalpha_t, TRUE, FALSE,
8708 EL_CHAR('T'), -1, -1
8711 Xalpha_u, TRUE, FALSE,
8712 EL_CHAR('U'), -1, -1
8715 Xalpha_v, TRUE, FALSE,
8716 EL_CHAR('V'), -1, -1
8719 Xalpha_w, TRUE, FALSE,
8720 EL_CHAR('W'), -1, -1
8723 Xalpha_x, TRUE, FALSE,
8724 EL_CHAR('X'), -1, -1
8727 Xalpha_y, TRUE, FALSE,
8728 EL_CHAR('Y'), -1, -1
8731 Xalpha_z, TRUE, FALSE,
8732 EL_CHAR('Z'), -1, -1
8735 Xalpha_arrow_e, TRUE, FALSE,
8736 EL_CHAR('>'), -1, -1
8739 Xalpha_arrow_w, TRUE, FALSE,
8740 EL_CHAR('<'), -1, -1
8743 Xalpha_copyr, TRUE, FALSE,
8744 EL_CHAR('©'), -1, -1
8748 Xboom_bug, FALSE, FALSE,
8749 EL_BUG, ACTION_EXPLODING, -1
8752 Xboom_bomb, FALSE, FALSE,
8753 EL_BOMB, ACTION_EXPLODING, -1
8756 Xboom_android, FALSE, FALSE,
8757 EL_EMC_ANDROID, ACTION_OTHER, -1
8760 Xboom_1, FALSE, FALSE,
8761 EL_DEFAULT, ACTION_EXPLODING, -1
8764 Xboom_2, FALSE, FALSE,
8765 EL_DEFAULT, ACTION_EXPLODING, -1
8768 Znormal, FALSE, FALSE,
8772 Zdynamite, FALSE, FALSE,
8776 Zplayer, FALSE, FALSE,
8780 ZBORDER, FALSE, FALSE,
8790 static struct Mapping_EM_to_RND_player
8799 em_player_mapping_list[] =
8803 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
8807 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
8811 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
8815 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
8819 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
8823 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
8827 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
8831 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
8835 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
8839 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
8843 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
8847 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
8851 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
8855 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
8859 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
8863 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
8867 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
8871 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
8875 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
8879 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
8883 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
8887 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
8891 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
8895 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
8899 EL_PLAYER_1, ACTION_DEFAULT, -1,
8903 EL_PLAYER_2, ACTION_DEFAULT, -1,
8907 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
8911 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
8915 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
8919 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
8923 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
8927 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
8931 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
8935 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
8939 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
8943 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
8947 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
8951 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
8955 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
8959 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
8963 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
8967 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
8971 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
8975 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
8979 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
8983 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
8987 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
8991 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
8995 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
8999 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
9003 EL_PLAYER_3, ACTION_DEFAULT, -1,
9007 EL_PLAYER_4, ACTION_DEFAULT, -1,
9016 int map_element_RND_to_EM(int element_rnd)
9018 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
9019 static boolean mapping_initialized = FALSE;
9021 if (!mapping_initialized)
9025 /* return "Xalpha_quest" for all undefined elements in mapping array */
9026 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
9027 mapping_RND_to_EM[i] = Xalpha_quest;
9029 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9030 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
9031 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
9032 em_object_mapping_list[i].element_em;
9034 mapping_initialized = TRUE;
9037 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
9038 return mapping_RND_to_EM[element_rnd];
9040 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
9045 int map_element_EM_to_RND(int element_em)
9047 static unsigned short mapping_EM_to_RND[TILE_MAX];
9048 static boolean mapping_initialized = FALSE;
9050 if (!mapping_initialized)
9054 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
9055 for (i = 0; i < TILE_MAX; i++)
9056 mapping_EM_to_RND[i] = EL_UNKNOWN;
9058 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9059 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
9060 em_object_mapping_list[i].element_rnd;
9062 mapping_initialized = TRUE;
9065 if (element_em >= 0 && element_em < TILE_MAX)
9066 return mapping_EM_to_RND[element_em];
9068 Error(ERR_WARN, "invalid EM level element %d", element_em);
9073 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
9075 struct LevelInfo_EM *level_em = level->native_em_level;
9076 struct LEVEL *lev = level_em->lev;
9079 for (i = 0; i < TILE_MAX; i++)
9080 lev->android_array[i] = Xblank;
9082 for (i = 0; i < level->num_android_clone_elements; i++)
9084 int element_rnd = level->android_clone_element[i];
9085 int element_em = map_element_RND_to_EM(element_rnd);
9087 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
9088 if (em_object_mapping_list[j].element_rnd == element_rnd)
9089 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
9093 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
9095 struct LevelInfo_EM *level_em = level->native_em_level;
9096 struct LEVEL *lev = level_em->lev;
9099 level->num_android_clone_elements = 0;
9101 for (i = 0; i < TILE_MAX; i++)
9103 int element_em = lev->android_array[i];
9105 boolean element_found = FALSE;
9107 if (element_em == Xblank)
9110 element_rnd = map_element_EM_to_RND(element_em);
9112 for (j = 0; j < level->num_android_clone_elements; j++)
9113 if (level->android_clone_element[j] == element_rnd)
9114 element_found = TRUE;
9118 level->android_clone_element[level->num_android_clone_elements++] =
9121 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
9126 if (level->num_android_clone_elements == 0)
9128 level->num_android_clone_elements = 1;
9129 level->android_clone_element[0] = EL_EMPTY;
9133 int map_direction_RND_to_EM(int direction)
9135 return (direction == MV_UP ? 0 :
9136 direction == MV_RIGHT ? 1 :
9137 direction == MV_DOWN ? 2 :
9138 direction == MV_LEFT ? 3 :
9142 int map_direction_EM_to_RND(int direction)
9144 return (direction == 0 ? MV_UP :
9145 direction == 1 ? MV_RIGHT :
9146 direction == 2 ? MV_DOWN :
9147 direction == 3 ? MV_LEFT :
9151 int map_element_RND_to_SP(int element_rnd)
9153 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
9155 if (element_rnd >= EL_SP_START &&
9156 element_rnd <= EL_SP_END)
9157 element_sp = element_rnd - EL_SP_START;
9158 else if (element_rnd == EL_EMPTY_SPACE)
9160 else if (element_rnd == EL_INVISIBLE_WALL)
9166 int map_element_SP_to_RND(int element_sp)
9168 int element_rnd = EL_UNKNOWN;
9170 if (element_sp >= 0x00 &&
9172 element_rnd = EL_SP_START + element_sp;
9173 else if (element_sp == 0x28)
9174 element_rnd = EL_INVISIBLE_WALL;
9179 int map_action_SP_to_RND(int action_sp)
9183 case actActive: return ACTION_ACTIVE;
9184 case actImpact: return ACTION_IMPACT;
9185 case actExploding: return ACTION_EXPLODING;
9186 case actDigging: return ACTION_DIGGING;
9187 case actSnapping: return ACTION_SNAPPING;
9188 case actCollecting: return ACTION_COLLECTING;
9189 case actPassing: return ACTION_PASSING;
9190 case actPushing: return ACTION_PUSHING;
9191 case actDropping: return ACTION_DROPPING;
9193 default: return ACTION_DEFAULT;
9197 int get_next_element(int element)
9201 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
9202 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
9203 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
9204 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
9205 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
9206 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
9207 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
9208 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
9209 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
9210 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
9211 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
9213 default: return element;
9218 int el_act_dir2img(int element, int action, int direction)
9220 element = GFX_ELEMENT(element);
9222 if (direction == MV_NONE)
9223 return element_info[element].graphic[action];
9225 direction = MV_DIR_TO_BIT(direction);
9227 return element_info[element].direction_graphic[action][direction];
9230 int el_act_dir2img(int element, int action, int direction)
9232 element = GFX_ELEMENT(element);
9233 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9235 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9236 return element_info[element].direction_graphic[action][direction];
9241 static int el_act_dir2crm(int element, int action, int direction)
9243 element = GFX_ELEMENT(element);
9245 if (direction == MV_NONE)
9246 return element_info[element].crumbled[action];
9248 direction = MV_DIR_TO_BIT(direction);
9250 return element_info[element].direction_crumbled[action][direction];
9253 static int el_act_dir2crm(int element, int action, int direction)
9255 element = GFX_ELEMENT(element);
9256 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9258 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9259 return element_info[element].direction_crumbled[action][direction];
9263 int el_act2img(int element, int action)
9265 element = GFX_ELEMENT(element);
9267 return element_info[element].graphic[action];
9270 int el_act2crm(int element, int action)
9272 element = GFX_ELEMENT(element);
9274 return element_info[element].crumbled[action];
9277 int el_dir2img(int element, int direction)
9279 element = GFX_ELEMENT(element);
9281 return el_act_dir2img(element, ACTION_DEFAULT, direction);
9284 int el2baseimg(int element)
9286 return element_info[element].graphic[ACTION_DEFAULT];
9289 int el2img(int element)
9291 element = GFX_ELEMENT(element);
9293 return element_info[element].graphic[ACTION_DEFAULT];
9296 int el2edimg(int element)
9298 element = GFX_ELEMENT(element);
9300 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
9303 int el2preimg(int element)
9305 element = GFX_ELEMENT(element);
9307 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
9310 int el2panelimg(int element)
9312 element = GFX_ELEMENT(element);
9314 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
9317 int font2baseimg(int font_nr)
9319 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
9322 int getBeltNrFromBeltElement(int element)
9324 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
9325 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
9326 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
9329 int getBeltNrFromBeltActiveElement(int element)
9331 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
9332 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
9333 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
9336 int getBeltNrFromBeltSwitchElement(int element)
9338 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
9339 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
9340 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
9343 int getBeltDirNrFromBeltElement(int element)
9345 static int belt_base_element[4] =
9347 EL_CONVEYOR_BELT_1_LEFT,
9348 EL_CONVEYOR_BELT_2_LEFT,
9349 EL_CONVEYOR_BELT_3_LEFT,
9350 EL_CONVEYOR_BELT_4_LEFT
9353 int belt_nr = getBeltNrFromBeltElement(element);
9354 int belt_dir_nr = element - belt_base_element[belt_nr];
9356 return (belt_dir_nr % 3);
9359 int getBeltDirNrFromBeltSwitchElement(int element)
9361 static int belt_base_element[4] =
9363 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9364 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9365 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9366 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9369 int belt_nr = getBeltNrFromBeltSwitchElement(element);
9370 int belt_dir_nr = element - belt_base_element[belt_nr];
9372 return (belt_dir_nr % 3);
9375 int getBeltDirFromBeltElement(int element)
9377 static int belt_move_dir[3] =
9384 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
9386 return belt_move_dir[belt_dir_nr];
9389 int getBeltDirFromBeltSwitchElement(int element)
9391 static int belt_move_dir[3] =
9398 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
9400 return belt_move_dir[belt_dir_nr];
9403 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9405 static int belt_base_element[4] =
9407 EL_CONVEYOR_BELT_1_LEFT,
9408 EL_CONVEYOR_BELT_2_LEFT,
9409 EL_CONVEYOR_BELT_3_LEFT,
9410 EL_CONVEYOR_BELT_4_LEFT
9413 return belt_base_element[belt_nr] + belt_dir_nr;
9416 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9418 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9420 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9423 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9425 static int belt_base_element[4] =
9427 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9428 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9429 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9430 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9433 return belt_base_element[belt_nr] + belt_dir_nr;
9436 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9438 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9440 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9444 boolean getTeamMode_EM()
9446 return game.team_mode;
9449 int getNumActivePlayers_EM()
9452 int num_players = 0;
9456 return (setup.team_mode ? MAX_PLAYERS : 1);
9458 for (i = 0; i < MAX_PLAYERS; i++)
9459 if (tape.player_participates[i])
9462 return (num_players > 1 ? MAX_PLAYERS : 1);
9466 int num_players = 0;
9469 /* when recording game, activate all connected players */
9473 for (i = 0; i < MAX_PLAYERS; i++)
9474 if (tape.player_participates[i])
9482 int getGameFrameDelay_EM(int native_em_game_frame_delay)
9484 int game_frame_delay_value;
9486 game_frame_delay_value =
9487 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
9488 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
9491 if (tape.playing && tape.warp_forward && !tape.pausing)
9492 game_frame_delay_value = 0;
9494 return game_frame_delay_value;
9497 unsigned int InitRND(int seed)
9499 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
9500 return InitEngineRandom_EM(seed);
9501 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
9502 return InitEngineRandom_SP(seed);
9504 return InitEngineRandom_RND(seed);
9508 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
9509 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
9512 inline static int get_effective_element_EM(int tile, int frame_em)
9514 int element = object_mapping[tile].element_rnd;
9515 int action = object_mapping[tile].action;
9516 boolean is_backside = object_mapping[tile].is_backside;
9517 boolean action_removing = (action == ACTION_DIGGING ||
9518 action == ACTION_SNAPPING ||
9519 action == ACTION_COLLECTING);
9525 case Yacid_splash_eB:
9526 case Yacid_splash_wB:
9527 return (frame_em > 5 ? EL_EMPTY : element);
9531 case Ydiamond_stone:
9532 // if (!game.use_native_emc_graphics_engine)
9540 else /* frame_em == 7 */
9544 case Yacid_splash_eB:
9545 case Yacid_splash_wB:
9548 case Yemerald_stone:
9551 case Ydiamond_stone:
9555 case Xdrip_stretchB:
9574 case Xsand_stonein_1:
9575 case Xsand_stonein_2:
9576 case Xsand_stonein_3:
9577 case Xsand_stonein_4:
9581 return (is_backside || action_removing ? EL_EMPTY : element);
9586 inline static boolean check_linear_animation_EM(int tile)
9590 case Xsand_stonesand_1:
9591 case Xsand_stonesand_quickout_1:
9592 case Xsand_sandstone_1:
9593 case Xsand_stonein_1:
9594 case Xsand_stoneout_1:
9614 case Yacid_splash_eB:
9615 case Yacid_splash_wB:
9616 case Yemerald_stone:
9624 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
9625 boolean has_crumbled_graphics,
9626 int crumbled, int sync_frame)
9628 /* if element can be crumbled, but certain action graphics are just empty
9629 space (like instantly snapping sand to empty space in 1 frame), do not
9630 treat these empty space graphics as crumbled graphics in EMC engine */
9631 if (crumbled == IMG_EMPTY_SPACE)
9632 has_crumbled_graphics = FALSE;
9634 if (has_crumbled_graphics)
9636 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9637 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9638 g_crumbled->anim_delay,
9639 g_crumbled->anim_mode,
9640 g_crumbled->anim_start_frame,
9643 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
9644 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
9646 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
9648 g_em->has_crumbled_graphics = TRUE;
9652 g_em->crumbled_bitmap = NULL;
9653 g_em->crumbled_src_x = 0;
9654 g_em->crumbled_src_y = 0;
9655 g_em->crumbled_border_size = 0;
9657 g_em->has_crumbled_graphics = FALSE;
9661 void ResetGfxAnimation_EM(int x, int y, int tile)
9666 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
9667 int tile, int frame_em, int x, int y)
9669 int action = object_mapping[tile].action;
9671 int direction = object_mapping[tile].direction;
9672 int effective_element = get_effective_element_EM(tile, frame_em);
9673 int graphic = (direction == MV_NONE ?
9674 el_act2img(effective_element, action) :
9675 el_act_dir2img(effective_element, action, direction));
9676 struct GraphicInfo *g = &graphic_info[graphic];
9679 boolean action_removing = (action == ACTION_DIGGING ||
9680 action == ACTION_SNAPPING ||
9681 action == ACTION_COLLECTING);
9682 boolean action_moving = (action == ACTION_FALLING ||
9683 action == ACTION_MOVING ||
9684 action == ACTION_PUSHING ||
9685 action == ACTION_EATING ||
9686 action == ACTION_FILLING ||
9687 action == ACTION_EMPTYING);
9688 boolean action_falling = (action == ACTION_FALLING ||
9689 action == ACTION_FILLING ||
9690 action == ACTION_EMPTYING);
9692 /* special case: graphic uses "2nd movement tile" and has defined
9693 7 frames for movement animation (or less) => use default graphic
9694 for last (8th) frame which ends the movement animation */
9695 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9697 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
9698 graphic = (direction == MV_NONE ?
9699 el_act2img(effective_element, action) :
9700 el_act_dir2img(effective_element, action, direction));
9702 g = &graphic_info[graphic];
9706 if (tile == Xsand_stonesand_1 ||
9707 tile == Xsand_stonesand_2 ||
9708 tile == Xsand_stonesand_3 ||
9709 tile == Xsand_stonesand_4)
9710 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9714 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
9718 // printf("::: resetting... [%d]\n", tile);
9721 if (action_removing || check_linear_animation_EM(tile))
9723 GfxFrame[x][y] = frame_em;
9725 // printf("::: resetting... [%d]\n", tile);
9728 else if (action_moving)
9730 boolean is_backside = object_mapping[tile].is_backside;
9734 int direction = object_mapping[tile].direction;
9735 int move_dir = (action_falling ? MV_DOWN : direction);
9740 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
9741 if (g->double_movement && frame_em == 0)
9745 // printf("::: resetting... [%d]\n", tile);
9749 if (move_dir == MV_LEFT)
9750 GfxFrame[x - 1][y] = GfxFrame[x][y];
9751 else if (move_dir == MV_RIGHT)
9752 GfxFrame[x + 1][y] = GfxFrame[x][y];
9753 else if (move_dir == MV_UP)
9754 GfxFrame[x][y - 1] = GfxFrame[x][y];
9755 else if (move_dir == MV_DOWN)
9756 GfxFrame[x][y + 1] = GfxFrame[x][y];
9763 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
9764 if (tile == Xsand_stonesand_quickout_1 ||
9765 tile == Xsand_stonesand_quickout_2)
9770 if (tile == Xsand_stonesand_1 ||
9771 tile == Xsand_stonesand_2 ||
9772 tile == Xsand_stonesand_3 ||
9773 tile == Xsand_stonesand_4)
9774 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9778 if (graphic_info[graphic].anim_global_sync)
9779 sync_frame = FrameCounter;
9780 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9781 sync_frame = GfxFrame[x][y];
9783 sync_frame = 0; /* playfield border (pseudo steel) */
9785 SetRandomAnimationValue(x, y);
9787 int frame = getAnimationFrame(g->anim_frames,
9790 g->anim_start_frame,
9793 g_em->unique_identifier =
9794 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
9798 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
9799 int tile, int frame_em, int x, int y)
9801 int action = object_mapping[tile].action;
9802 int direction = object_mapping[tile].direction;
9803 boolean is_backside = object_mapping[tile].is_backside;
9804 int effective_element = get_effective_element_EM(tile, frame_em);
9806 int effective_action = action;
9808 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
9810 int graphic = (direction == MV_NONE ?
9811 el_act2img(effective_element, effective_action) :
9812 el_act_dir2img(effective_element, effective_action,
9814 int crumbled = (direction == MV_NONE ?
9815 el_act2crm(effective_element, effective_action) :
9816 el_act_dir2crm(effective_element, effective_action,
9818 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9819 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9820 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9821 struct GraphicInfo *g = &graphic_info[graphic];
9823 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9827 /* special case: graphic uses "2nd movement tile" and has defined
9828 7 frames for movement animation (or less) => use default graphic
9829 for last (8th) frame which ends the movement animation */
9830 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9832 effective_action = ACTION_DEFAULT;
9833 graphic = (direction == MV_NONE ?
9834 el_act2img(effective_element, effective_action) :
9835 el_act_dir2img(effective_element, effective_action,
9837 crumbled = (direction == MV_NONE ?
9838 el_act2crm(effective_element, effective_action) :
9839 el_act_dir2crm(effective_element, effective_action,
9842 g = &graphic_info[graphic];
9852 if (frame_em == 0) /* reset animation frame for certain elements */
9854 if (check_linear_animation_EM(tile))
9859 if (graphic_info[graphic].anim_global_sync)
9860 sync_frame = FrameCounter;
9861 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9862 sync_frame = GfxFrame[x][y];
9864 sync_frame = 0; /* playfield border (pseudo steel) */
9866 SetRandomAnimationValue(x, y);
9871 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9872 i == Xdrip_stretchB ? 7 :
9873 i == Ydrip_s2 ? j + 8 :
9874 i == Ydrip_s2B ? j + 8 :
9883 i == Xfake_acid_1 ? 0 :
9884 i == Xfake_acid_2 ? 10 :
9885 i == Xfake_acid_3 ? 20 :
9886 i == Xfake_acid_4 ? 30 :
9887 i == Xfake_acid_5 ? 40 :
9888 i == Xfake_acid_6 ? 50 :
9889 i == Xfake_acid_7 ? 60 :
9890 i == Xfake_acid_8 ? 70 :
9892 i == Xball_2B ? j + 8 :
9893 i == Yball_eat ? j + 1 :
9894 i == Ykey_1_eat ? j + 1 :
9895 i == Ykey_2_eat ? j + 1 :
9896 i == Ykey_3_eat ? j + 1 :
9897 i == Ykey_4_eat ? j + 1 :
9898 i == Ykey_5_eat ? j + 1 :
9899 i == Ykey_6_eat ? j + 1 :
9900 i == Ykey_7_eat ? j + 1 :
9901 i == Ykey_8_eat ? j + 1 :
9902 i == Ylenses_eat ? j + 1 :
9903 i == Ymagnify_eat ? j + 1 :
9904 i == Ygrass_eat ? j + 1 :
9905 i == Ydirt_eat ? j + 1 :
9906 i == Xamoeba_1 ? 0 :
9907 i == Xamoeba_2 ? 1 :
9908 i == Xamoeba_3 ? 2 :
9909 i == Xamoeba_4 ? 3 :
9910 i == Xamoeba_5 ? 0 :
9911 i == Xamoeba_6 ? 1 :
9912 i == Xamoeba_7 ? 2 :
9913 i == Xamoeba_8 ? 3 :
9914 i == Xexit_2 ? j + 8 :
9915 i == Xexit_3 ? j + 16 :
9916 i == Xdynamite_1 ? 0 :
9917 i == Xdynamite_2 ? 8 :
9918 i == Xdynamite_3 ? 16 :
9919 i == Xdynamite_4 ? 24 :
9920 i == Xsand_stonein_1 ? j + 1 :
9921 i == Xsand_stonein_2 ? j + 9 :
9922 i == Xsand_stonein_3 ? j + 17 :
9923 i == Xsand_stonein_4 ? j + 25 :
9924 i == Xsand_stoneout_1 && j == 0 ? 0 :
9925 i == Xsand_stoneout_1 && j == 1 ? 0 :
9926 i == Xsand_stoneout_1 && j == 2 ? 1 :
9927 i == Xsand_stoneout_1 && j == 3 ? 2 :
9928 i == Xsand_stoneout_1 && j == 4 ? 2 :
9929 i == Xsand_stoneout_1 && j == 5 ? 3 :
9930 i == Xsand_stoneout_1 && j == 6 ? 4 :
9931 i == Xsand_stoneout_1 && j == 7 ? 4 :
9932 i == Xsand_stoneout_2 && j == 0 ? 5 :
9933 i == Xsand_stoneout_2 && j == 1 ? 6 :
9934 i == Xsand_stoneout_2 && j == 2 ? 7 :
9935 i == Xsand_stoneout_2 && j == 3 ? 8 :
9936 i == Xsand_stoneout_2 && j == 4 ? 9 :
9937 i == Xsand_stoneout_2 && j == 5 ? 11 :
9938 i == Xsand_stoneout_2 && j == 6 ? 13 :
9939 i == Xsand_stoneout_2 && j == 7 ? 15 :
9940 i == Xboom_bug && j == 1 ? 2 :
9941 i == Xboom_bug && j == 2 ? 2 :
9942 i == Xboom_bug && j == 3 ? 4 :
9943 i == Xboom_bug && j == 4 ? 4 :
9944 i == Xboom_bug && j == 5 ? 2 :
9945 i == Xboom_bug && j == 6 ? 2 :
9946 i == Xboom_bug && j == 7 ? 0 :
9947 i == Xboom_bomb && j == 1 ? 2 :
9948 i == Xboom_bomb && j == 2 ? 2 :
9949 i == Xboom_bomb && j == 3 ? 4 :
9950 i == Xboom_bomb && j == 4 ? 4 :
9951 i == Xboom_bomb && j == 5 ? 2 :
9952 i == Xboom_bomb && j == 6 ? 2 :
9953 i == Xboom_bomb && j == 7 ? 0 :
9954 i == Xboom_android && j == 7 ? 6 :
9955 i == Xboom_1 && j == 1 ? 2 :
9956 i == Xboom_1 && j == 2 ? 2 :
9957 i == Xboom_1 && j == 3 ? 4 :
9958 i == Xboom_1 && j == 4 ? 4 :
9959 i == Xboom_1 && j == 5 ? 6 :
9960 i == Xboom_1 && j == 6 ? 6 :
9961 i == Xboom_1 && j == 7 ? 8 :
9962 i == Xboom_2 && j == 0 ? 8 :
9963 i == Xboom_2 && j == 1 ? 8 :
9964 i == Xboom_2 && j == 2 ? 10 :
9965 i == Xboom_2 && j == 3 ? 10 :
9966 i == Xboom_2 && j == 4 ? 10 :
9967 i == Xboom_2 && j == 5 ? 12 :
9968 i == Xboom_2 && j == 6 ? 12 :
9969 i == Xboom_2 && j == 7 ? 12 :
9971 special_animation && j == 4 ? 3 :
9972 effective_action != action ? 0 :
9978 int xxx_effective_action;
9979 int xxx_has_action_graphics;
9982 int element = object_mapping[i].element_rnd;
9983 int action = object_mapping[i].action;
9984 int direction = object_mapping[i].direction;
9985 boolean is_backside = object_mapping[i].is_backside;
9987 boolean action_removing = (action == ACTION_DIGGING ||
9988 action == ACTION_SNAPPING ||
9989 action == ACTION_COLLECTING);
9991 boolean action_exploding = ((action == ACTION_EXPLODING ||
9992 action == ACTION_SMASHED_BY_ROCK ||
9993 action == ACTION_SMASHED_BY_SPRING) &&
9994 element != EL_DIAMOND);
9995 boolean action_active = (action == ACTION_ACTIVE);
9996 boolean action_other = (action == ACTION_OTHER);
10000 int effective_element = get_effective_element_EM(i, j);
10002 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
10003 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
10005 i == Xdrip_stretch ? element :
10006 i == Xdrip_stretchB ? element :
10007 i == Ydrip_s1 ? element :
10008 i == Ydrip_s1B ? element :
10009 i == Xball_1B ? element :
10010 i == Xball_2 ? element :
10011 i == Xball_2B ? element :
10012 i == Yball_eat ? element :
10013 i == Ykey_1_eat ? element :
10014 i == Ykey_2_eat ? element :
10015 i == Ykey_3_eat ? element :
10016 i == Ykey_4_eat ? element :
10017 i == Ykey_5_eat ? element :
10018 i == Ykey_6_eat ? element :
10019 i == Ykey_7_eat ? element :
10020 i == Ykey_8_eat ? element :
10021 i == Ylenses_eat ? element :
10022 i == Ymagnify_eat ? element :
10023 i == Ygrass_eat ? element :
10024 i == Ydirt_eat ? element :
10025 i == Yemerald_stone ? EL_EMERALD :
10026 i == Ydiamond_stone ? EL_ROCK :
10027 i == Xsand_stonein_1 ? element :
10028 i == Xsand_stonein_2 ? element :
10029 i == Xsand_stonein_3 ? element :
10030 i == Xsand_stonein_4 ? element :
10031 is_backside ? EL_EMPTY :
10032 action_removing ? EL_EMPTY :
10035 int effective_action = (j < 7 ? action :
10036 i == Xdrip_stretch ? action :
10037 i == Xdrip_stretchB ? action :
10038 i == Ydrip_s1 ? action :
10039 i == Ydrip_s1B ? action :
10040 i == Xball_1B ? action :
10041 i == Xball_2 ? action :
10042 i == Xball_2B ? action :
10043 i == Yball_eat ? action :
10044 i == Ykey_1_eat ? action :
10045 i == Ykey_2_eat ? action :
10046 i == Ykey_3_eat ? action :
10047 i == Ykey_4_eat ? action :
10048 i == Ykey_5_eat ? action :
10049 i == Ykey_6_eat ? action :
10050 i == Ykey_7_eat ? action :
10051 i == Ykey_8_eat ? action :
10052 i == Ylenses_eat ? action :
10053 i == Ymagnify_eat ? action :
10054 i == Ygrass_eat ? action :
10055 i == Ydirt_eat ? action :
10056 i == Xsand_stonein_1 ? action :
10057 i == Xsand_stonein_2 ? action :
10058 i == Xsand_stonein_3 ? action :
10059 i == Xsand_stonein_4 ? action :
10060 i == Xsand_stoneout_1 ? action :
10061 i == Xsand_stoneout_2 ? action :
10062 i == Xboom_android ? ACTION_EXPLODING :
10063 action_exploding ? ACTION_EXPLODING :
10064 action_active ? action :
10065 action_other ? action :
10067 int graphic = (el_act_dir2img(effective_element, effective_action,
10069 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10071 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10072 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10073 boolean has_action_graphics = (graphic != base_graphic);
10074 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10075 struct GraphicInfo *g = &graphic_info[graphic];
10077 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10079 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10080 Bitmap *src_bitmap;
10082 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10083 boolean special_animation = (action != ACTION_DEFAULT &&
10084 g->anim_frames == 3 &&
10085 g->anim_delay == 2 &&
10086 g->anim_mode & ANIM_LINEAR);
10087 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
10088 i == Xdrip_stretchB ? 7 :
10089 i == Ydrip_s2 ? j + 8 :
10090 i == Ydrip_s2B ? j + 8 :
10092 i == Xacid_2 ? 10 :
10093 i == Xacid_3 ? 20 :
10094 i == Xacid_4 ? 30 :
10095 i == Xacid_5 ? 40 :
10096 i == Xacid_6 ? 50 :
10097 i == Xacid_7 ? 60 :
10098 i == Xacid_8 ? 70 :
10099 i == Xfake_acid_1 ? 0 :
10100 i == Xfake_acid_2 ? 10 :
10101 i == Xfake_acid_3 ? 20 :
10102 i == Xfake_acid_4 ? 30 :
10103 i == Xfake_acid_5 ? 40 :
10104 i == Xfake_acid_6 ? 50 :
10105 i == Xfake_acid_7 ? 60 :
10106 i == Xfake_acid_8 ? 70 :
10108 i == Xball_2B ? j + 8 :
10109 i == Yball_eat ? j + 1 :
10110 i == Ykey_1_eat ? j + 1 :
10111 i == Ykey_2_eat ? j + 1 :
10112 i == Ykey_3_eat ? j + 1 :
10113 i == Ykey_4_eat ? j + 1 :
10114 i == Ykey_5_eat ? j + 1 :
10115 i == Ykey_6_eat ? j + 1 :
10116 i == Ykey_7_eat ? j + 1 :
10117 i == Ykey_8_eat ? j + 1 :
10118 i == Ylenses_eat ? j + 1 :
10119 i == Ymagnify_eat ? j + 1 :
10120 i == Ygrass_eat ? j + 1 :
10121 i == Ydirt_eat ? j + 1 :
10122 i == Xamoeba_1 ? 0 :
10123 i == Xamoeba_2 ? 1 :
10124 i == Xamoeba_3 ? 2 :
10125 i == Xamoeba_4 ? 3 :
10126 i == Xamoeba_5 ? 0 :
10127 i == Xamoeba_6 ? 1 :
10128 i == Xamoeba_7 ? 2 :
10129 i == Xamoeba_8 ? 3 :
10130 i == Xexit_2 ? j + 8 :
10131 i == Xexit_3 ? j + 16 :
10132 i == Xdynamite_1 ? 0 :
10133 i == Xdynamite_2 ? 8 :
10134 i == Xdynamite_3 ? 16 :
10135 i == Xdynamite_4 ? 24 :
10136 i == Xsand_stonein_1 ? j + 1 :
10137 i == Xsand_stonein_2 ? j + 9 :
10138 i == Xsand_stonein_3 ? j + 17 :
10139 i == Xsand_stonein_4 ? j + 25 :
10140 i == Xsand_stoneout_1 && j == 0 ? 0 :
10141 i == Xsand_stoneout_1 && j == 1 ? 0 :
10142 i == Xsand_stoneout_1 && j == 2 ? 1 :
10143 i == Xsand_stoneout_1 && j == 3 ? 2 :
10144 i == Xsand_stoneout_1 && j == 4 ? 2 :
10145 i == Xsand_stoneout_1 && j == 5 ? 3 :
10146 i == Xsand_stoneout_1 && j == 6 ? 4 :
10147 i == Xsand_stoneout_1 && j == 7 ? 4 :
10148 i == Xsand_stoneout_2 && j == 0 ? 5 :
10149 i == Xsand_stoneout_2 && j == 1 ? 6 :
10150 i == Xsand_stoneout_2 && j == 2 ? 7 :
10151 i == Xsand_stoneout_2 && j == 3 ? 8 :
10152 i == Xsand_stoneout_2 && j == 4 ? 9 :
10153 i == Xsand_stoneout_2 && j == 5 ? 11 :
10154 i == Xsand_stoneout_2 && j == 6 ? 13 :
10155 i == Xsand_stoneout_2 && j == 7 ? 15 :
10156 i == Xboom_bug && j == 1 ? 2 :
10157 i == Xboom_bug && j == 2 ? 2 :
10158 i == Xboom_bug && j == 3 ? 4 :
10159 i == Xboom_bug && j == 4 ? 4 :
10160 i == Xboom_bug && j == 5 ? 2 :
10161 i == Xboom_bug && j == 6 ? 2 :
10162 i == Xboom_bug && j == 7 ? 0 :
10163 i == Xboom_bomb && j == 1 ? 2 :
10164 i == Xboom_bomb && j == 2 ? 2 :
10165 i == Xboom_bomb && j == 3 ? 4 :
10166 i == Xboom_bomb && j == 4 ? 4 :
10167 i == Xboom_bomb && j == 5 ? 2 :
10168 i == Xboom_bomb && j == 6 ? 2 :
10169 i == Xboom_bomb && j == 7 ? 0 :
10170 i == Xboom_android && j == 7 ? 6 :
10171 i == Xboom_1 && j == 1 ? 2 :
10172 i == Xboom_1 && j == 2 ? 2 :
10173 i == Xboom_1 && j == 3 ? 4 :
10174 i == Xboom_1 && j == 4 ? 4 :
10175 i == Xboom_1 && j == 5 ? 6 :
10176 i == Xboom_1 && j == 6 ? 6 :
10177 i == Xboom_1 && j == 7 ? 8 :
10178 i == Xboom_2 && j == 0 ? 8 :
10179 i == Xboom_2 && j == 1 ? 8 :
10180 i == Xboom_2 && j == 2 ? 10 :
10181 i == Xboom_2 && j == 3 ? 10 :
10182 i == Xboom_2 && j == 4 ? 10 :
10183 i == Xboom_2 && j == 5 ? 12 :
10184 i == Xboom_2 && j == 6 ? 12 :
10185 i == Xboom_2 && j == 7 ? 12 :
10186 special_animation && j == 4 ? 3 :
10187 effective_action != action ? 0 :
10190 xxx_effective_action = effective_action;
10191 xxx_has_action_graphics = has_action_graphics;
10196 int frame = getAnimationFrame(g->anim_frames,
10199 g->anim_start_frame,
10213 int old_src_x = g_em->src_x;
10214 int old_src_y = g_em->src_y;
10218 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
10219 g->double_movement && is_backside);
10221 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10222 &g_em->src_x, &g_em->src_y, FALSE);
10227 if (tile == Ydiamond_stone)
10228 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
10233 g->anim_start_frame,
10236 g_em->src_x, g_em->src_y,
10237 g_em->src_offset_x, g_em->src_offset_y,
10238 g_em->dst_offset_x, g_em->dst_offset_y,
10250 if (graphic == IMG_BUG_MOVING_RIGHT)
10251 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
10252 g->double_movement, is_backside,
10253 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
10261 g_em->src_offset_x = 0;
10262 g_em->src_offset_y = 0;
10263 g_em->dst_offset_x = 0;
10264 g_em->dst_offset_y = 0;
10265 g_em->width = TILEX;
10266 g_em->height = TILEY;
10268 g_em->preserve_background = FALSE;
10271 /* (updating the "crumbled" graphic definitions is probably not really needed,
10272 as animations for crumbled graphics can't be longer than one EMC cycle) */
10274 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10279 g_em->crumbled_bitmap = NULL;
10280 g_em->crumbled_src_x = 0;
10281 g_em->crumbled_src_y = 0;
10283 g_em->has_crumbled_graphics = FALSE;
10285 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10287 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10288 g_crumbled->anim_delay,
10289 g_crumbled->anim_mode,
10290 g_crumbled->anim_start_frame,
10293 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
10294 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
10296 g_em->has_crumbled_graphics = TRUE;
10302 int effective_action = xxx_effective_action;
10303 int has_action_graphics = xxx_has_action_graphics;
10305 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10306 effective_action == ACTION_MOVING ||
10307 effective_action == ACTION_PUSHING ||
10308 effective_action == ACTION_EATING)) ||
10309 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10310 effective_action == ACTION_EMPTYING)))
10313 (effective_action == ACTION_FALLING ||
10314 effective_action == ACTION_FILLING ||
10315 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10316 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10317 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10318 int num_steps = (i == Ydrip_s1 ? 16 :
10319 i == Ydrip_s1B ? 16 :
10320 i == Ydrip_s2 ? 16 :
10321 i == Ydrip_s2B ? 16 :
10322 i == Xsand_stonein_1 ? 32 :
10323 i == Xsand_stonein_2 ? 32 :
10324 i == Xsand_stonein_3 ? 32 :
10325 i == Xsand_stonein_4 ? 32 :
10326 i == Xsand_stoneout_1 ? 16 :
10327 i == Xsand_stoneout_2 ? 16 : 8);
10328 int cx = ABS(dx) * (TILEX / num_steps);
10329 int cy = ABS(dy) * (TILEY / num_steps);
10330 int step_frame = (i == Ydrip_s2 ? j + 8 :
10331 i == Ydrip_s2B ? j + 8 :
10332 i == Xsand_stonein_2 ? j + 8 :
10333 i == Xsand_stonein_3 ? j + 16 :
10334 i == Xsand_stonein_4 ? j + 24 :
10335 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10336 int step = (is_backside ? step_frame : num_steps - step_frame);
10338 if (is_backside) /* tile where movement starts */
10340 if (dx < 0 || dy < 0)
10342 g_em->src_offset_x = cx * step;
10343 g_em->src_offset_y = cy * step;
10347 g_em->dst_offset_x = cx * step;
10348 g_em->dst_offset_y = cy * step;
10351 else /* tile where movement ends */
10353 if (dx < 0 || dy < 0)
10355 g_em->dst_offset_x = cx * step;
10356 g_em->dst_offset_y = cy * step;
10360 g_em->src_offset_x = cx * step;
10361 g_em->src_offset_y = cy * step;
10365 g_em->width = TILEX - cx * step;
10366 g_em->height = TILEY - cy * step;
10369 /* create unique graphic identifier to decide if tile must be redrawn */
10370 /* bit 31 - 16 (16 bit): EM style graphic
10371 bit 15 - 12 ( 4 bit): EM style frame
10372 bit 11 - 6 ( 6 bit): graphic width
10373 bit 5 - 0 ( 6 bit): graphic height */
10374 g_em->unique_identifier =
10375 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10381 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
10382 int player_nr, int anim, int frame_em)
10384 int element = player_mapping[player_nr][anim].element_rnd;
10385 int action = player_mapping[player_nr][anim].action;
10386 int direction = player_mapping[player_nr][anim].direction;
10387 int graphic = (direction == MV_NONE ?
10388 el_act2img(element, action) :
10389 el_act_dir2img(element, action, direction));
10390 struct GraphicInfo *g = &graphic_info[graphic];
10393 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
10395 stored_player[player_nr].StepFrame = frame_em;
10397 sync_frame = stored_player[player_nr].Frame;
10399 int frame = getAnimationFrame(g->anim_frames,
10402 g->anim_start_frame,
10405 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10406 &g_em->src_x, &g_em->src_y, FALSE);
10409 printf("::: %d: %d, %d [%d]\n",
10411 stored_player[player_nr].Frame,
10412 stored_player[player_nr].StepFrame,
10417 void InitGraphicInfo_EM(void)
10420 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
10421 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
10426 int num_em_gfx_errors = 0;
10428 if (graphic_info_em_object[0][0].bitmap == NULL)
10430 /* EM graphics not yet initialized in em_open_all() */
10435 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
10438 /* always start with reliable default values */
10439 for (i = 0; i < TILE_MAX; i++)
10441 object_mapping[i].element_rnd = EL_UNKNOWN;
10442 object_mapping[i].is_backside = FALSE;
10443 object_mapping[i].action = ACTION_DEFAULT;
10444 object_mapping[i].direction = MV_NONE;
10447 /* always start with reliable default values */
10448 for (p = 0; p < MAX_PLAYERS; p++)
10450 for (i = 0; i < SPR_MAX; i++)
10452 player_mapping[p][i].element_rnd = EL_UNKNOWN;
10453 player_mapping[p][i].action = ACTION_DEFAULT;
10454 player_mapping[p][i].direction = MV_NONE;
10458 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
10460 int e = em_object_mapping_list[i].element_em;
10462 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
10463 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
10465 if (em_object_mapping_list[i].action != -1)
10466 object_mapping[e].action = em_object_mapping_list[i].action;
10468 if (em_object_mapping_list[i].direction != -1)
10469 object_mapping[e].direction =
10470 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
10473 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
10475 int a = em_player_mapping_list[i].action_em;
10476 int p = em_player_mapping_list[i].player_nr;
10478 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
10480 if (em_player_mapping_list[i].action != -1)
10481 player_mapping[p][a].action = em_player_mapping_list[i].action;
10483 if (em_player_mapping_list[i].direction != -1)
10484 player_mapping[p][a].direction =
10485 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
10488 for (i = 0; i < TILE_MAX; i++)
10490 int element = object_mapping[i].element_rnd;
10491 int action = object_mapping[i].action;
10492 int direction = object_mapping[i].direction;
10493 boolean is_backside = object_mapping[i].is_backside;
10495 boolean action_removing = (action == ACTION_DIGGING ||
10496 action == ACTION_SNAPPING ||
10497 action == ACTION_COLLECTING);
10499 boolean action_exploding = ((action == ACTION_EXPLODING ||
10500 action == ACTION_SMASHED_BY_ROCK ||
10501 action == ACTION_SMASHED_BY_SPRING) &&
10502 element != EL_DIAMOND);
10503 boolean action_active = (action == ACTION_ACTIVE);
10504 boolean action_other = (action == ACTION_OTHER);
10506 for (j = 0; j < 8; j++)
10509 int effective_element = get_effective_element_EM(i, j);
10511 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
10512 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
10514 i == Xdrip_stretch ? element :
10515 i == Xdrip_stretchB ? element :
10516 i == Ydrip_s1 ? element :
10517 i == Ydrip_s1B ? element :
10518 i == Xball_1B ? element :
10519 i == Xball_2 ? element :
10520 i == Xball_2B ? element :
10521 i == Yball_eat ? element :
10522 i == Ykey_1_eat ? element :
10523 i == Ykey_2_eat ? element :
10524 i == Ykey_3_eat ? element :
10525 i == Ykey_4_eat ? element :
10526 i == Ykey_5_eat ? element :
10527 i == Ykey_6_eat ? element :
10528 i == Ykey_7_eat ? element :
10529 i == Ykey_8_eat ? element :
10530 i == Ylenses_eat ? element :
10531 i == Ymagnify_eat ? element :
10532 i == Ygrass_eat ? element :
10533 i == Ydirt_eat ? element :
10534 i == Yemerald_stone ? EL_EMERALD :
10535 i == Ydiamond_stone ? EL_ROCK :
10536 i == Xsand_stonein_1 ? element :
10537 i == Xsand_stonein_2 ? element :
10538 i == Xsand_stonein_3 ? element :
10539 i == Xsand_stonein_4 ? element :
10540 is_backside ? EL_EMPTY :
10541 action_removing ? EL_EMPTY :
10544 int effective_action = (j < 7 ? action :
10545 i == Xdrip_stretch ? action :
10546 i == Xdrip_stretchB ? action :
10547 i == Ydrip_s1 ? action :
10548 i == Ydrip_s1B ? action :
10549 i == Xball_1B ? action :
10550 i == Xball_2 ? action :
10551 i == Xball_2B ? action :
10552 i == Yball_eat ? action :
10553 i == Ykey_1_eat ? action :
10554 i == Ykey_2_eat ? action :
10555 i == Ykey_3_eat ? action :
10556 i == Ykey_4_eat ? action :
10557 i == Ykey_5_eat ? action :
10558 i == Ykey_6_eat ? action :
10559 i == Ykey_7_eat ? action :
10560 i == Ykey_8_eat ? action :
10561 i == Ylenses_eat ? action :
10562 i == Ymagnify_eat ? action :
10563 i == Ygrass_eat ? action :
10564 i == Ydirt_eat ? action :
10565 i == Xsand_stonein_1 ? action :
10566 i == Xsand_stonein_2 ? action :
10567 i == Xsand_stonein_3 ? action :
10568 i == Xsand_stonein_4 ? action :
10569 i == Xsand_stoneout_1 ? action :
10570 i == Xsand_stoneout_2 ? action :
10571 i == Xboom_android ? ACTION_EXPLODING :
10572 action_exploding ? ACTION_EXPLODING :
10573 action_active ? action :
10574 action_other ? action :
10576 int graphic = (el_act_dir2img(effective_element, effective_action,
10578 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10580 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10581 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10582 boolean has_action_graphics = (graphic != base_graphic);
10583 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10584 struct GraphicInfo *g = &graphic_info[graphic];
10586 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10588 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10589 Bitmap *src_bitmap;
10591 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10592 boolean special_animation = (action != ACTION_DEFAULT &&
10593 g->anim_frames == 3 &&
10594 g->anim_delay == 2 &&
10595 g->anim_mode & ANIM_LINEAR);
10596 int sync_frame = (i == Xdrip_stretch ? 7 :
10597 i == Xdrip_stretchB ? 7 :
10598 i == Ydrip_s2 ? j + 8 :
10599 i == Ydrip_s2B ? j + 8 :
10601 i == Xacid_2 ? 10 :
10602 i == Xacid_3 ? 20 :
10603 i == Xacid_4 ? 30 :
10604 i == Xacid_5 ? 40 :
10605 i == Xacid_6 ? 50 :
10606 i == Xacid_7 ? 60 :
10607 i == Xacid_8 ? 70 :
10608 i == Xfake_acid_1 ? 0 :
10609 i == Xfake_acid_2 ? 10 :
10610 i == Xfake_acid_3 ? 20 :
10611 i == Xfake_acid_4 ? 30 :
10612 i == Xfake_acid_5 ? 40 :
10613 i == Xfake_acid_6 ? 50 :
10614 i == Xfake_acid_7 ? 60 :
10615 i == Xfake_acid_8 ? 70 :
10617 i == Xball_2B ? j + 8 :
10618 i == Yball_eat ? j + 1 :
10619 i == Ykey_1_eat ? j + 1 :
10620 i == Ykey_2_eat ? j + 1 :
10621 i == Ykey_3_eat ? j + 1 :
10622 i == Ykey_4_eat ? j + 1 :
10623 i == Ykey_5_eat ? j + 1 :
10624 i == Ykey_6_eat ? j + 1 :
10625 i == Ykey_7_eat ? j + 1 :
10626 i == Ykey_8_eat ? j + 1 :
10627 i == Ylenses_eat ? j + 1 :
10628 i == Ymagnify_eat ? j + 1 :
10629 i == Ygrass_eat ? j + 1 :
10630 i == Ydirt_eat ? j + 1 :
10631 i == Xamoeba_1 ? 0 :
10632 i == Xamoeba_2 ? 1 :
10633 i == Xamoeba_3 ? 2 :
10634 i == Xamoeba_4 ? 3 :
10635 i == Xamoeba_5 ? 0 :
10636 i == Xamoeba_6 ? 1 :
10637 i == Xamoeba_7 ? 2 :
10638 i == Xamoeba_8 ? 3 :
10639 i == Xexit_2 ? j + 8 :
10640 i == Xexit_3 ? j + 16 :
10641 i == Xdynamite_1 ? 0 :
10642 i == Xdynamite_2 ? 8 :
10643 i == Xdynamite_3 ? 16 :
10644 i == Xdynamite_4 ? 24 :
10645 i == Xsand_stonein_1 ? j + 1 :
10646 i == Xsand_stonein_2 ? j + 9 :
10647 i == Xsand_stonein_3 ? j + 17 :
10648 i == Xsand_stonein_4 ? j + 25 :
10649 i == Xsand_stoneout_1 && j == 0 ? 0 :
10650 i == Xsand_stoneout_1 && j == 1 ? 0 :
10651 i == Xsand_stoneout_1 && j == 2 ? 1 :
10652 i == Xsand_stoneout_1 && j == 3 ? 2 :
10653 i == Xsand_stoneout_1 && j == 4 ? 2 :
10654 i == Xsand_stoneout_1 && j == 5 ? 3 :
10655 i == Xsand_stoneout_1 && j == 6 ? 4 :
10656 i == Xsand_stoneout_1 && j == 7 ? 4 :
10657 i == Xsand_stoneout_2 && j == 0 ? 5 :
10658 i == Xsand_stoneout_2 && j == 1 ? 6 :
10659 i == Xsand_stoneout_2 && j == 2 ? 7 :
10660 i == Xsand_stoneout_2 && j == 3 ? 8 :
10661 i == Xsand_stoneout_2 && j == 4 ? 9 :
10662 i == Xsand_stoneout_2 && j == 5 ? 11 :
10663 i == Xsand_stoneout_2 && j == 6 ? 13 :
10664 i == Xsand_stoneout_2 && j == 7 ? 15 :
10665 i == Xboom_bug && j == 1 ? 2 :
10666 i == Xboom_bug && j == 2 ? 2 :
10667 i == Xboom_bug && j == 3 ? 4 :
10668 i == Xboom_bug && j == 4 ? 4 :
10669 i == Xboom_bug && j == 5 ? 2 :
10670 i == Xboom_bug && j == 6 ? 2 :
10671 i == Xboom_bug && j == 7 ? 0 :
10672 i == Xboom_bomb && j == 1 ? 2 :
10673 i == Xboom_bomb && j == 2 ? 2 :
10674 i == Xboom_bomb && j == 3 ? 4 :
10675 i == Xboom_bomb && j == 4 ? 4 :
10676 i == Xboom_bomb && j == 5 ? 2 :
10677 i == Xboom_bomb && j == 6 ? 2 :
10678 i == Xboom_bomb && j == 7 ? 0 :
10679 i == Xboom_android && j == 7 ? 6 :
10680 i == Xboom_1 && j == 1 ? 2 :
10681 i == Xboom_1 && j == 2 ? 2 :
10682 i == Xboom_1 && j == 3 ? 4 :
10683 i == Xboom_1 && j == 4 ? 4 :
10684 i == Xboom_1 && j == 5 ? 6 :
10685 i == Xboom_1 && j == 6 ? 6 :
10686 i == Xboom_1 && j == 7 ? 8 :
10687 i == Xboom_2 && j == 0 ? 8 :
10688 i == Xboom_2 && j == 1 ? 8 :
10689 i == Xboom_2 && j == 2 ? 10 :
10690 i == Xboom_2 && j == 3 ? 10 :
10691 i == Xboom_2 && j == 4 ? 10 :
10692 i == Xboom_2 && j == 5 ? 12 :
10693 i == Xboom_2 && j == 6 ? 12 :
10694 i == Xboom_2 && j == 7 ? 12 :
10695 special_animation && j == 4 ? 3 :
10696 effective_action != action ? 0 :
10700 Bitmap *debug_bitmap = g_em->bitmap;
10701 int debug_src_x = g_em->src_x;
10702 int debug_src_y = g_em->src_y;
10705 int frame = getAnimationFrame(g->anim_frames,
10708 g->anim_start_frame,
10711 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
10712 g->double_movement && is_backside);
10714 g_em->bitmap = src_bitmap;
10715 g_em->src_x = src_x;
10716 g_em->src_y = src_y;
10717 g_em->src_offset_x = 0;
10718 g_em->src_offset_y = 0;
10719 g_em->dst_offset_x = 0;
10720 g_em->dst_offset_y = 0;
10721 g_em->width = TILEX;
10722 g_em->height = TILEY;
10724 g_em->preserve_background = FALSE;
10727 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10732 g_em->crumbled_bitmap = NULL;
10733 g_em->crumbled_src_x = 0;
10734 g_em->crumbled_src_y = 0;
10735 g_em->crumbled_border_size = 0;
10737 g_em->has_crumbled_graphics = FALSE;
10740 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
10741 printf("::: empty crumbled: %d [%s], %d, %d\n",
10742 effective_element, element_info[effective_element].token_name,
10743 effective_action, direction);
10746 /* if element can be crumbled, but certain action graphics are just empty
10747 space (like instantly snapping sand to empty space in 1 frame), do not
10748 treat these empty space graphics as crumbled graphics in EMC engine */
10749 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10751 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10752 g_crumbled->anim_delay,
10753 g_crumbled->anim_mode,
10754 g_crumbled->anim_start_frame,
10757 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
10759 g_em->has_crumbled_graphics = TRUE;
10760 g_em->crumbled_bitmap = src_bitmap;
10761 g_em->crumbled_src_x = src_x;
10762 g_em->crumbled_src_y = src_y;
10763 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
10767 if (g_em == &graphic_info_em_object[207][0])
10768 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
10769 graphic_info_em_object[207][0].crumbled_src_x,
10770 graphic_info_em_object[207][0].crumbled_src_y,
10772 crumbled, frame, src_x, src_y,
10777 g->anim_start_frame,
10779 gfx.anim_random_frame,
10784 printf("::: EMC tile %d is crumbled\n", i);
10790 if (element == EL_ROCK &&
10791 effective_action == ACTION_FILLING)
10792 printf("::: has_action_graphics == %d\n", has_action_graphics);
10795 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10796 effective_action == ACTION_MOVING ||
10797 effective_action == ACTION_PUSHING ||
10798 effective_action == ACTION_EATING)) ||
10799 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10800 effective_action == ACTION_EMPTYING)))
10803 (effective_action == ACTION_FALLING ||
10804 effective_action == ACTION_FILLING ||
10805 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10806 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10807 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10808 int num_steps = (i == Ydrip_s1 ? 16 :
10809 i == Ydrip_s1B ? 16 :
10810 i == Ydrip_s2 ? 16 :
10811 i == Ydrip_s2B ? 16 :
10812 i == Xsand_stonein_1 ? 32 :
10813 i == Xsand_stonein_2 ? 32 :
10814 i == Xsand_stonein_3 ? 32 :
10815 i == Xsand_stonein_4 ? 32 :
10816 i == Xsand_stoneout_1 ? 16 :
10817 i == Xsand_stoneout_2 ? 16 : 8);
10818 int cx = ABS(dx) * (TILEX / num_steps);
10819 int cy = ABS(dy) * (TILEY / num_steps);
10820 int step_frame = (i == Ydrip_s2 ? j + 8 :
10821 i == Ydrip_s2B ? j + 8 :
10822 i == Xsand_stonein_2 ? j + 8 :
10823 i == Xsand_stonein_3 ? j + 16 :
10824 i == Xsand_stonein_4 ? j + 24 :
10825 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10826 int step = (is_backside ? step_frame : num_steps - step_frame);
10828 if (is_backside) /* tile where movement starts */
10830 if (dx < 0 || dy < 0)
10832 g_em->src_offset_x = cx * step;
10833 g_em->src_offset_y = cy * step;
10837 g_em->dst_offset_x = cx * step;
10838 g_em->dst_offset_y = cy * step;
10841 else /* tile where movement ends */
10843 if (dx < 0 || dy < 0)
10845 g_em->dst_offset_x = cx * step;
10846 g_em->dst_offset_y = cy * step;
10850 g_em->src_offset_x = cx * step;
10851 g_em->src_offset_y = cy * step;
10855 g_em->width = TILEX - cx * step;
10856 g_em->height = TILEY - cy * step;
10859 /* create unique graphic identifier to decide if tile must be redrawn */
10860 /* bit 31 - 16 (16 bit): EM style graphic
10861 bit 15 - 12 ( 4 bit): EM style frame
10862 bit 11 - 6 ( 6 bit): graphic width
10863 bit 5 - 0 ( 6 bit): graphic height */
10864 g_em->unique_identifier =
10865 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10869 /* skip check for EMC elements not contained in original EMC artwork */
10870 if (element == EL_EMC_FAKE_ACID)
10873 if (g_em->bitmap != debug_bitmap ||
10874 g_em->src_x != debug_src_x ||
10875 g_em->src_y != debug_src_y ||
10876 g_em->src_offset_x != 0 ||
10877 g_em->src_offset_y != 0 ||
10878 g_em->dst_offset_x != 0 ||
10879 g_em->dst_offset_y != 0 ||
10880 g_em->width != TILEX ||
10881 g_em->height != TILEY)
10883 static int last_i = -1;
10891 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
10892 i, element, element_info[element].token_name,
10893 element_action_info[effective_action].suffix, direction);
10895 if (element != effective_element)
10896 printf(" [%d ('%s')]",
10898 element_info[effective_element].token_name);
10902 if (g_em->bitmap != debug_bitmap)
10903 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
10904 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
10906 if (g_em->src_x != debug_src_x ||
10907 g_em->src_y != debug_src_y)
10908 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10909 j, (is_backside ? 'B' : 'F'),
10910 g_em->src_x, g_em->src_y,
10911 g_em->src_x / 32, g_em->src_y / 32,
10912 debug_src_x, debug_src_y,
10913 debug_src_x / 32, debug_src_y / 32);
10915 if (g_em->src_offset_x != 0 ||
10916 g_em->src_offset_y != 0 ||
10917 g_em->dst_offset_x != 0 ||
10918 g_em->dst_offset_y != 0)
10919 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
10921 g_em->src_offset_x, g_em->src_offset_y,
10922 g_em->dst_offset_x, g_em->dst_offset_y);
10924 if (g_em->width != TILEX ||
10925 g_em->height != TILEY)
10926 printf(" %d (%d): size %d,%d should be %d,%d\n",
10928 g_em->width, g_em->height, TILEX, TILEY);
10930 num_em_gfx_errors++;
10937 for (i = 0; i < TILE_MAX; i++)
10939 for (j = 0; j < 8; j++)
10941 int element = object_mapping[i].element_rnd;
10942 int action = object_mapping[i].action;
10943 int direction = object_mapping[i].direction;
10944 boolean is_backside = object_mapping[i].is_backside;
10945 int graphic_action = el_act_dir2img(element, action, direction);
10946 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
10948 if ((action == ACTION_SMASHED_BY_ROCK ||
10949 action == ACTION_SMASHED_BY_SPRING ||
10950 action == ACTION_EATING) &&
10951 graphic_action == graphic_default)
10953 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
10954 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
10955 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
10956 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
10959 /* no separate animation for "smashed by rock" -- use rock instead */
10960 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10961 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
10963 g_em->bitmap = g_xx->bitmap;
10964 g_em->src_x = g_xx->src_x;
10965 g_em->src_y = g_xx->src_y;
10966 g_em->src_offset_x = g_xx->src_offset_x;
10967 g_em->src_offset_y = g_xx->src_offset_y;
10968 g_em->dst_offset_x = g_xx->dst_offset_x;
10969 g_em->dst_offset_y = g_xx->dst_offset_y;
10970 g_em->width = g_xx->width;
10971 g_em->height = g_xx->height;
10972 g_em->unique_identifier = g_xx->unique_identifier;
10975 g_em->preserve_background = TRUE;
10980 for (p = 0; p < MAX_PLAYERS; p++)
10982 for (i = 0; i < SPR_MAX; i++)
10984 int element = player_mapping[p][i].element_rnd;
10985 int action = player_mapping[p][i].action;
10986 int direction = player_mapping[p][i].direction;
10988 for (j = 0; j < 8; j++)
10990 int effective_element = element;
10991 int effective_action = action;
10992 int graphic = (direction == MV_NONE ?
10993 el_act2img(effective_element, effective_action) :
10994 el_act_dir2img(effective_element, effective_action,
10996 struct GraphicInfo *g = &graphic_info[graphic];
10997 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
10998 Bitmap *src_bitmap;
11000 int sync_frame = j;
11003 Bitmap *debug_bitmap = g_em->bitmap;
11004 int debug_src_x = g_em->src_x;
11005 int debug_src_y = g_em->src_y;
11008 int frame = getAnimationFrame(g->anim_frames,
11011 g->anim_start_frame,
11014 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
11016 g_em->bitmap = src_bitmap;
11017 g_em->src_x = src_x;
11018 g_em->src_y = src_y;
11019 g_em->src_offset_x = 0;
11020 g_em->src_offset_y = 0;
11021 g_em->dst_offset_x = 0;
11022 g_em->dst_offset_y = 0;
11023 g_em->width = TILEX;
11024 g_em->height = TILEY;
11028 /* skip check for EMC elements not contained in original EMC artwork */
11029 if (element == EL_PLAYER_3 ||
11030 element == EL_PLAYER_4)
11033 if (g_em->bitmap != debug_bitmap ||
11034 g_em->src_x != debug_src_x ||
11035 g_em->src_y != debug_src_y)
11037 static int last_i = -1;
11045 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
11046 p, i, element, element_info[element].token_name,
11047 element_action_info[effective_action].suffix, direction);
11049 if (element != effective_element)
11050 printf(" [%d ('%s')]",
11052 element_info[effective_element].token_name);
11056 if (g_em->bitmap != debug_bitmap)
11057 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
11058 j, (int)(g_em->bitmap), (int)(debug_bitmap));
11060 if (g_em->src_x != debug_src_x ||
11061 g_em->src_y != debug_src_y)
11062 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
11064 g_em->src_x, g_em->src_y,
11065 g_em->src_x / 32, g_em->src_y / 32,
11066 debug_src_x, debug_src_y,
11067 debug_src_x / 32, debug_src_y / 32);
11069 num_em_gfx_errors++;
11079 printf("::: [%d errors found]\n", num_em_gfx_errors);
11085 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
11086 boolean any_player_moving,
11087 boolean player_is_dropping)
11089 if (tape.single_step && tape.recording && !tape.pausing)
11092 boolean active_players = FALSE;
11095 for (i = 0; i < MAX_PLAYERS; i++)
11096 if (action[i] != JOY_NO_ACTION)
11097 active_players = TRUE;
11101 if (frame == 0 && !player_is_dropping)
11102 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11106 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
11107 boolean murphy_is_dropping)
11110 printf("::: waiting: %d, dropping: %d\n",
11111 murphy_is_waiting, murphy_is_dropping);
11114 if (tape.single_step && tape.recording && !tape.pausing)
11116 // if (murphy_is_waiting || murphy_is_dropping)
11117 if (murphy_is_waiting)
11120 printf("::: murphy is waiting -> pause mode\n");
11123 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11128 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
11129 int graphic, int sync_frame, int x, int y)
11131 int frame = getGraphicAnimationFrame(graphic, sync_frame);
11133 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
11136 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
11138 return (IS_NEXT_FRAME(sync_frame, graphic));
11141 int getGraphicInfo_Delay(int graphic)
11143 return graphic_info[graphic].anim_delay;
11146 void PlayMenuSoundExt(int sound)
11148 if (sound == SND_UNDEFINED)
11151 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11152 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11155 if (IS_LOOP_SOUND(sound))
11156 PlaySoundLoop(sound);
11161 void PlayMenuSound()
11163 PlayMenuSoundExt(menu.sound[game_status]);
11166 void PlayMenuSoundStereo(int sound, int stereo_position)
11168 if (sound == SND_UNDEFINED)
11171 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11172 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11175 if (IS_LOOP_SOUND(sound))
11176 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
11178 PlaySoundStereo(sound, stereo_position);
11181 void PlayMenuSoundIfLoopExt(int sound)
11183 if (sound == SND_UNDEFINED)
11186 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11187 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11190 if (IS_LOOP_SOUND(sound))
11191 PlaySoundLoop(sound);
11194 void PlayMenuSoundIfLoop()
11196 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
11199 void PlayMenuMusicExt(int music)
11201 if (music == MUS_UNDEFINED)
11204 if (!setup.sound_music)
11210 void PlayMenuMusic()
11212 PlayMenuMusicExt(menu.music[game_status]);
11215 void PlaySoundActivating()
11218 PlaySound(SND_MENU_ITEM_ACTIVATING);
11222 void PlaySoundSelecting()
11225 PlaySound(SND_MENU_ITEM_SELECTING);
11229 void ToggleFullscreenOrChangeWindowScalingIfNeeded()
11231 boolean change_fullscreen = (setup.fullscreen !=
11232 video.fullscreen_enabled);
11233 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
11234 !strEqual(setup.fullscreen_mode,
11235 video.fullscreen_mode_current));
11236 boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
11237 setup.window_scaling_percent !=
11238 video.window_scaling_percent);
11240 if (change_window_scaling_percent && video.fullscreen_enabled)
11243 if (!change_window_scaling_percent && !video.fullscreen_available)
11246 #if defined(TARGET_SDL2)
11247 if (change_window_scaling_percent)
11249 SDLSetWindowScaling(setup.window_scaling_percent);
11253 else if (change_fullscreen)
11255 SDLSetWindowFullscreen(setup.fullscreen);
11257 /* set setup value according to successfully changed fullscreen mode */
11258 setup.fullscreen = video.fullscreen_enabled;
11264 if (change_fullscreen ||
11265 change_fullscreen_mode ||
11266 change_window_scaling_percent)
11268 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
11270 /* save backbuffer content which gets lost when toggling fullscreen mode */
11271 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11273 if (change_fullscreen_mode)
11275 /* keep fullscreen, but change fullscreen mode (screen resolution) */
11276 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
11279 if (change_window_scaling_percent)
11281 /* keep window mode, but change window scaling */
11282 video.fullscreen_enabled = TRUE; /* force new window scaling */
11285 /* toggle fullscreen */
11286 ChangeVideoModeIfNeeded(setup.fullscreen);
11288 /* set setup value according to successfully changed fullscreen mode */
11289 setup.fullscreen = video.fullscreen_enabled;
11291 /* restore backbuffer content from temporary backbuffer backup bitmap */
11292 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11294 FreeBitmap(tmp_backbuffer);
11297 /* update visible window/screen */
11298 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11300 redraw_mask = REDRAW_ALL;
11305 void ChangeViewportPropertiesIfNeeded()
11308 int *door_1_x = &DX;
11309 int *door_1_y = &DY;
11310 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
11311 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
11314 int gfx_game_mode = game_status;
11316 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
11317 game_status == GAME_MODE_EDITOR ? game_status :
11320 int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
11322 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
11323 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
11324 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
11325 struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
11326 int border_size = vp_playfield->border_size;
11327 int new_sx = vp_playfield->x + border_size;
11328 int new_sy = vp_playfield->y + border_size;
11329 int new_sxsize = vp_playfield->width - 2 * border_size;
11330 int new_sysize = vp_playfield->height - 2 * border_size;
11331 int new_real_sx = vp_playfield->x;
11332 int new_real_sy = vp_playfield->y;
11333 int new_full_sxsize = vp_playfield->width;
11334 int new_full_sysize = vp_playfield->height;
11335 int new_dx = vp_door_1->x;
11336 int new_dy = vp_door_1->y;
11337 int new_dxsize = vp_door_1->width;
11338 int new_dysize = vp_door_1->height;
11339 int new_vx = vp_door_2->x;
11340 int new_vy = vp_door_2->y;
11341 int new_vxsize = vp_door_2->width;
11342 int new_vysize = vp_door_2->height;
11343 int new_ex = vp_door_3->x;
11344 int new_ey = vp_door_3->y;
11345 int new_exsize = vp_door_3->width;
11346 int new_eysize = vp_door_3->height;
11348 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
11349 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
11350 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
11351 int new_scr_fieldx = new_sxsize / tilesize;
11352 int new_scr_fieldy = new_sysize / tilesize;
11353 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
11354 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
11356 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
11357 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
11359 boolean init_gfx_buffers = FALSE;
11360 boolean init_video_buffer = FALSE;
11361 boolean init_gadgets_and_toons = FALSE;
11364 /* !!! TEST ONLY !!! */
11365 // InitGfxBuffers();
11369 if (viewport.window.width != WIN_XSIZE ||
11370 viewport.window.height != WIN_YSIZE)
11372 WIN_XSIZE = viewport.window.width;
11373 WIN_YSIZE = viewport.window.height;
11376 init_video_buffer = TRUE;
11377 init_gfx_buffers = TRUE;
11379 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11383 SetDrawDeactivationMask(REDRAW_NONE);
11384 SetDrawBackgroundMask(REDRAW_FIELD);
11386 // RedrawBackground();
11390 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
11393 if (new_scr_fieldx != SCR_FIELDX ||
11394 new_scr_fieldy != SCR_FIELDY)
11396 /* this always toggles between MAIN and GAME when using small tile size */
11398 SCR_FIELDX = new_scr_fieldx;
11399 SCR_FIELDY = new_scr_fieldy;
11401 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
11405 if (new_tilesize_var != TILESIZE_VAR &&
11406 gfx_game_mode == GAME_MODE_PLAYING)
11408 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
11410 TILESIZE_VAR = new_tilesize_var;
11412 init_gfx_buffers = TRUE;
11414 // printf("::: tilesize: init_gfx_buffers\n");
11418 if (new_sx != SX ||
11426 new_sxsize != SXSIZE ||
11427 new_sysize != SYSIZE ||
11428 new_dxsize != DXSIZE ||
11429 new_dysize != DYSIZE ||
11430 new_vxsize != VXSIZE ||
11431 new_vysize != VYSIZE ||
11432 new_exsize != EXSIZE ||
11433 new_eysize != EYSIZE ||
11434 new_real_sx != REAL_SX ||
11435 new_real_sy != REAL_SY ||
11436 new_full_sxsize != FULL_SXSIZE ||
11437 new_full_sysize != FULL_SYSIZE ||
11438 new_tilesize_var != TILESIZE_VAR
11441 vp_door_1->x != *door_1_x ||
11442 vp_door_1->y != *door_1_y ||
11443 vp_door_2->x != *door_2_x ||
11444 vp_door_2->y != *door_2_y
11456 SXSIZE = new_sxsize;
11457 SYSIZE = new_sysize;
11458 DXSIZE = new_dxsize;
11459 DYSIZE = new_dysize;
11460 VXSIZE = new_vxsize;
11461 VYSIZE = new_vysize;
11462 EXSIZE = new_exsize;
11463 EYSIZE = new_eysize;
11464 REAL_SX = new_real_sx;
11465 REAL_SY = new_real_sy;
11466 FULL_SXSIZE = new_full_sxsize;
11467 FULL_SYSIZE = new_full_sysize;
11468 TILESIZE_VAR = new_tilesize_var;
11471 printf("::: %d, %d, %d [%d]\n",
11472 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
11473 setup.small_game_graphics);
11477 *door_1_x = vp_door_1->x;
11478 *door_1_y = vp_door_1->y;
11479 *door_2_x = vp_door_2->x;
11480 *door_2_y = vp_door_2->y;
11484 init_gfx_buffers = TRUE;
11486 // printf("::: viewports: init_gfx_buffers\n");
11492 if (gfx_game_mode == GAME_MODE_MAIN)
11496 init_gadgets_and_toons = TRUE;
11498 // printf("::: viewports: init_gadgets_and_toons\n");
11506 if (init_gfx_buffers)
11508 // printf("::: init_gfx_buffers\n");
11510 SCR_FIELDX = new_scr_fieldx_buffers;
11511 SCR_FIELDY = new_scr_fieldy_buffers;
11515 SCR_FIELDX = new_scr_fieldx;
11516 SCR_FIELDY = new_scr_fieldy;
11519 if (init_video_buffer)
11521 // printf("::: init_video_buffer\n");
11523 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11525 SetDrawDeactivationMask(REDRAW_NONE);
11526 SetDrawBackgroundMask(REDRAW_FIELD);
11529 if (init_gadgets_and_toons)
11531 // printf("::: init_gadgets_and_toons\n");
11538 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);