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 /* CHECK AGAIN (previous code reactivated) */
2997 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3007 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
3013 void AnimateEnvelopeRequest(char *text, int anim_mode, int action)
3016 int envelope_nr = 0;
3019 int graphic = IMG_BACKGROUND_REQUEST;
3021 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3023 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
3024 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
3025 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3026 boolean no_delay = (tape.warp_forward);
3027 unsigned int anim_delay = 0;
3028 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
3029 int anim_delay_value = (no_delay ? 0 : frame_delay_value + 500 * 0);
3031 int max_word_len = maxWordLengthInString(text);
3032 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
3034 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
3036 int font_width = getFontWidth(font_nr);
3037 int font_height = getFontHeight(font_nr);
3038 int line_spacing = 2 * 1;
3042 int max_xsize = DXSIZE / font_width;
3043 // int max_ysize = DYSIZE / font_height;
3044 int max_ysize = DYSIZE / (font_height + line_spacing);
3046 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3047 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
3051 int max_xsize = level.envelope[envelope_nr].xsize;
3052 int max_ysize = level.envelope[envelope_nr].ysize;
3054 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
3055 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
3056 int xend = max_xsize;
3057 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
3058 int xstep = (xstart < xend ? 1 : 0);
3059 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
3064 char *text_copy = getStringCopy(text);
3067 font_nr = FONT_TEXT_2;
3069 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
3071 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3072 font_nr = FONT_TEXT_1;
3075 int max_word_len = 0;
3077 char *text_copy = getStringCopy(text);
3079 font_nr = FONT_TEXT_2;
3081 for (text_ptr = text; *text_ptr; text_ptr++)
3083 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
3085 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3087 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3088 font_nr = FONT_TEXT_1;
3097 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3098 if (*text_ptr == ' ')
3103 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
3104 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
3106 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
3107 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
3110 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
3112 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
3113 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
3114 int sx = SX + (SXSIZE - xsize * font_width) / 2;
3115 // int sy = SX + (SYSIZE - ysize * font_height) / 2;
3116 int sy = SY + (SYSIZE - ysize * (font_height + line_spacing)) / 2;
3120 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3122 SetDrawtoField(DRAW_BUFFERED);
3125 BlitScreenToBitmap(backbuffer);
3127 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3130 SetDrawtoField(DRAW_BACKBUFFER);
3133 for (yy = 0; yy < ysize; yy++)
3134 for (xx = 0; xx < xsize; xx++)
3135 DrawEnvelopeBackgroundTiles(graphic, sx, sy, xx, yy, xsize, ysize,
3136 getFontWidth(font_nr),
3137 getFontHeight(font_nr) + line_spacing);
3142 DrawTextBuffer(sx + font_width, sy + font_height + 8,
3143 text_copy, font_nr, max_xsize,
3144 xsize - 2, ysize - 2, line_spacing, mask_mode,
3145 FALSE, TRUE, FALSE);
3147 DrawTextBuffer(sx + font_width, sy + font_height,
3148 level.envelope[envelope_nr].text, font_nr, max_xsize,
3149 xsize - 2, ysize - 2, 0, mask_mode,
3150 level.envelope[envelope_nr].autowrap,
3151 level.envelope[envelope_nr].centered, FALSE);
3155 DrawTextToTextArea(sx + font_width, sy + font_height,
3156 level.envelope[envelope_nr].text, font_nr, max_xsize,
3157 xsize - 2, ysize - 2, mask_mode);
3160 /* copy request gadgets to door backbuffer */
3163 if ((ysize - 2) > 13)
3164 BlitBitmap(bitmap_db_door, drawto,
3165 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3166 DOOR_GFX_PAGEY1 + 13 * font_height,
3167 (xsize - 2) * font_width,
3168 (ysize - 2 - 13) * font_height,
3170 sy + font_height * (1 + 13));
3172 if ((ysize - 2) > 13)
3173 BlitBitmap(bitmap_db_door, drawto,
3174 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3175 DOOR_GFX_PAGEY1 + 11 * (font_height + line_spacing * 0),
3176 (xsize - 2) * font_width,
3177 (ysize - 2 - 13) * (font_height + line_spacing),
3179 sy + (font_height + line_spacing) * (1 + 13));
3181 if ((ysize - 2) > 13)
3182 BlitBitmap(bitmap_db_door, drawto,
3183 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3184 DOOR_GFX_PAGEY1 + 13 * font_height,
3185 (xsize - 2) * font_width,
3186 (ysize - 2 - 13) * font_height,
3188 sy + font_height * (1 + 13));
3192 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3193 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
3195 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3205 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
3215 void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
3218 int last_game_status = game_status; /* save current game status */
3219 // int last_draw_background_mask = gfx.draw_background_mask;
3222 int graphic = IMG_BACKGROUND_REQUEST;
3223 int sound_opening = SND_REQUEST_OPENING;
3224 int sound_closing = SND_REQUEST_CLOSING;
3226 int envelope_nr = 0;
3227 int element = EL_ENVELOPE_1 + envelope_nr;
3228 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3229 int sound_opening = element_info[element].sound[ACTION_OPENING];
3230 int sound_closing = element_info[element].sound[ACTION_CLOSING];
3233 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3234 boolean no_delay = (tape.warp_forward);
3235 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
3236 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
3238 int anim_mode = graphic_info[graphic].anim_mode;
3239 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
3240 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
3242 char *text_copy = getStringCopy(text);
3245 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3246 if (*text_ptr == ' ')
3251 if (game_status == GAME_MODE_PLAYING)
3253 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3254 BlitScreenToBitmap_EM(backbuffer);
3255 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3256 BlitScreenToBitmap_SP(backbuffer);
3259 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3263 SetDrawtoField(DRAW_BACKBUFFER);
3265 // SetDrawBackgroundMask(REDRAW_NONE);
3267 if (action == ACTION_OPENING)
3269 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3272 if (req_state & REQ_ASK)
3274 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
3275 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
3277 else if (req_state & REQ_CONFIRM)
3279 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
3281 else if (req_state & REQ_PLAYER)
3283 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
3284 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
3285 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
3286 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
3291 DrawEnvelopeRequest(text);
3293 DrawEnvelopeRequest(text_copy);
3296 if (game_status != GAME_MODE_MAIN)
3300 /* force DOOR font inside door area */
3301 game_status = GAME_MODE_PSEUDO_DOOR;
3304 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
3306 if (action == ACTION_OPENING)
3308 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
3310 if (anim_mode == ANIM_DEFAULT)
3311 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
3313 AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
3317 Delay(wait_delay_value);
3319 WaitForEventToContinue();
3324 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
3326 if (anim_mode != ANIM_NONE)
3327 AnimateEnvelopeRequest(main_anim_mode, ACTION_CLOSING);
3329 if (anim_mode == ANIM_DEFAULT)
3330 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_CLOSING);
3333 game.envelope_active = FALSE;
3336 // game_status = last_game_status; /* restore current game status */
3339 /* !!! CHECK AGAIN (SEE BELOW) !!! */
3340 game_status = last_game_status; /* restore current game status */
3343 if (action == ACTION_CLOSING)
3345 if (game_status != GAME_MODE_MAIN)
3348 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3351 SetDrawtoField(DRAW_BUFFERED);
3354 // SetDrawBackgroundMask(last_draw_background_mask);
3357 redraw_mask = REDRAW_FIELD;
3358 // redraw_mask |= REDRAW_ALL;
3360 /* CHECK AGAIN (previous code reactivated) */
3361 redraw_mask |= REDRAW_FIELD;
3365 if (game_status == GAME_MODE_MAIN)
3371 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
3372 game_status = last_game_status; /* restore current game status */
3376 if (action == ACTION_CLOSING &&
3377 game_status == GAME_MODE_PLAYING &&
3378 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3379 SetDrawtoField(DRAW_BUFFERED);
3381 if (game_status == GAME_MODE_PLAYING &&
3382 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3383 SetDrawtoField(DRAW_BUFFERED);
3395 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
3399 int graphic = el2preimg(element);
3401 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
3402 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
3410 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
3411 SetDrawBackgroundMask(REDRAW_FIELD);
3413 SetDrawBackgroundMask(REDRAW_NONE);
3418 for (x = BX1; x <= BX2; x++)
3419 for (y = BY1; y <= BY2; y++)
3420 DrawScreenField(x, y);
3422 redraw_mask |= REDRAW_FIELD;
3425 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
3429 for (x = 0; x < size_x; x++)
3430 for (y = 0; y < size_y; y++)
3431 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
3433 redraw_mask |= REDRAW_FIELD;
3436 static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
3438 boolean show_level_border = (BorderElement != EL_EMPTY);
3439 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3440 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3441 int tile_size = preview.tile_size;
3442 int preview_width = preview.xsize * tile_size;
3443 int preview_height = preview.ysize * tile_size;
3444 int real_preview_xsize = MIN(level_xsize, preview.xsize);
3445 int real_preview_ysize = MIN(level_ysize, preview.ysize);
3446 int real_preview_width = real_preview_xsize * tile_size;
3447 int real_preview_height = real_preview_ysize * tile_size;
3448 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
3449 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
3453 if (!IN_GFX_FIELD_FULL(dst_x, dst_y + preview_height - 1))
3458 dst_x += (preview_width - real_preview_width) / 2;
3459 dst_y += (preview_height - real_preview_height) / 2;
3461 DrawBackground(dst_x, dst_y, real_preview_width, real_preview_height);
3463 DrawBackground(dst_x, dst_y, preview_width, preview_height);
3465 dst_x += (preview_width - real_preview_width) / 2;
3466 dst_y += (preview_height - real_preview_height) / 2;
3469 for (x = 0; x < real_preview_xsize; x++)
3471 for (y = 0; y < real_preview_ysize; y++)
3473 int lx = from_x + x + (show_level_border ? -1 : 0);
3474 int ly = from_y + y + (show_level_border ? -1 : 0);
3475 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
3476 getBorderElement(lx, ly));
3478 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
3479 element, tile_size);
3483 redraw_mask |= REDRAW_MICROLEVEL;
3486 #define MICROLABEL_EMPTY 0
3487 #define MICROLABEL_LEVEL_NAME 1
3488 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
3489 #define MICROLABEL_LEVEL_AUTHOR 3
3490 #define MICROLABEL_IMPORTED_FROM_HEAD 4
3491 #define MICROLABEL_IMPORTED_FROM 5
3492 #define MICROLABEL_IMPORTED_BY_HEAD 6
3493 #define MICROLABEL_IMPORTED_BY 7
3495 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
3497 int max_text_width = SXSIZE;
3498 int font_width = getFontWidth(font_nr);
3500 if (pos->align == ALIGN_CENTER)
3501 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
3502 else if (pos->align == ALIGN_RIGHT)
3503 max_text_width = pos->x;
3505 max_text_width = SXSIZE - pos->x;
3507 return max_text_width / font_width;
3510 static void DrawPreviewLevelLabelExt(int mode)
3512 struct TextPosInfo *pos = &menu.main.text.level_info_2;
3513 char label_text[MAX_OUTPUT_LINESIZE + 1];
3514 int max_len_label_text;
3516 int font_nr = pos->font;
3519 if (!IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3522 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3523 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3524 mode == MICROLABEL_IMPORTED_BY_HEAD)
3525 font_nr = pos->font_alt;
3527 int font_nr = FONT_TEXT_2;
3530 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3531 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3532 mode == MICROLABEL_IMPORTED_BY_HEAD)
3533 font_nr = FONT_TEXT_3;
3537 max_len_label_text = getMaxTextLength(pos, font_nr);
3539 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3543 if (pos->size != -1)
3544 max_len_label_text = pos->size;
3547 for (i = 0; i < max_len_label_text; i++)
3548 label_text[i] = ' ';
3549 label_text[max_len_label_text] = '\0';
3551 if (strlen(label_text) > 0)
3554 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3556 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3557 int lypos = MICROLABEL2_YPOS;
3559 DrawText(lxpos, lypos, label_text, font_nr);
3564 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3565 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3566 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3567 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3568 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3569 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3570 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3571 max_len_label_text);
3572 label_text[max_len_label_text] = '\0';
3574 if (strlen(label_text) > 0)
3577 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3579 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3580 int lypos = MICROLABEL2_YPOS;
3582 DrawText(lxpos, lypos, label_text, font_nr);
3586 redraw_mask |= REDRAW_MICROLEVEL;
3589 static void DrawPreviewLevelExt(boolean restart)
3591 static unsigned int scroll_delay = 0;
3592 static unsigned int label_delay = 0;
3593 static int from_x, from_y, scroll_direction;
3594 static int label_state, label_counter;
3595 unsigned int scroll_delay_value = preview.step_delay;
3596 boolean show_level_border = (BorderElement != EL_EMPTY);
3597 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3598 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3599 int last_game_status = game_status; /* save current game status */
3602 /* force PREVIEW font on preview level */
3603 game_status = GAME_MODE_PSEUDO_PREVIEW;
3611 if (preview.anim_mode == ANIM_CENTERED)
3613 if (level_xsize > preview.xsize)
3614 from_x = (level_xsize - preview.xsize) / 2;
3615 if (level_ysize > preview.ysize)
3616 from_y = (level_ysize - preview.ysize) / 2;
3619 from_x += preview.xoffset;
3620 from_y += preview.yoffset;
3622 scroll_direction = MV_RIGHT;
3626 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3627 DrawPreviewLevelLabelExt(label_state);
3629 /* initialize delay counters */
3630 DelayReached(&scroll_delay, 0);
3631 DelayReached(&label_delay, 0);
3633 if (leveldir_current->name)
3635 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3636 char label_text[MAX_OUTPUT_LINESIZE + 1];
3638 int font_nr = pos->font;
3640 int font_nr = FONT_TEXT_1;
3643 int max_len_label_text = getMaxTextLength(pos, font_nr);
3645 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3653 if (pos->size != -1)
3654 max_len_label_text = pos->size;
3657 strncpy(label_text, leveldir_current->name, max_len_label_text);
3658 label_text[max_len_label_text] = '\0';
3661 if (IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3662 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3664 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3665 lypos = SY + MICROLABEL1_YPOS;
3667 DrawText(lxpos, lypos, label_text, font_nr);
3671 game_status = last_game_status; /* restore current game status */
3676 /* scroll preview level, if needed */
3677 if (preview.anim_mode != ANIM_NONE &&
3678 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3679 DelayReached(&scroll_delay, scroll_delay_value))
3681 switch (scroll_direction)
3686 from_x -= preview.step_offset;
3687 from_x = (from_x < 0 ? 0 : from_x);
3690 scroll_direction = MV_UP;
3694 if (from_x < level_xsize - preview.xsize)
3696 from_x += preview.step_offset;
3697 from_x = (from_x > level_xsize - preview.xsize ?
3698 level_xsize - preview.xsize : from_x);
3701 scroll_direction = MV_DOWN;
3707 from_y -= preview.step_offset;
3708 from_y = (from_y < 0 ? 0 : from_y);
3711 scroll_direction = MV_RIGHT;
3715 if (from_y < level_ysize - preview.ysize)
3717 from_y += preview.step_offset;
3718 from_y = (from_y > level_ysize - preview.ysize ?
3719 level_ysize - preview.ysize : from_y);
3722 scroll_direction = MV_LEFT;
3729 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3732 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3733 /* redraw micro level label, if needed */
3734 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3735 !strEqual(level.author, ANONYMOUS_NAME) &&
3736 !strEqual(level.author, leveldir_current->name) &&
3737 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3739 int max_label_counter = 23;
3741 if (leveldir_current->imported_from != NULL &&
3742 strlen(leveldir_current->imported_from) > 0)
3743 max_label_counter += 14;
3744 if (leveldir_current->imported_by != NULL &&
3745 strlen(leveldir_current->imported_by) > 0)
3746 max_label_counter += 14;
3748 label_counter = (label_counter + 1) % max_label_counter;
3749 label_state = (label_counter >= 0 && label_counter <= 7 ?
3750 MICROLABEL_LEVEL_NAME :
3751 label_counter >= 9 && label_counter <= 12 ?
3752 MICROLABEL_LEVEL_AUTHOR_HEAD :
3753 label_counter >= 14 && label_counter <= 21 ?
3754 MICROLABEL_LEVEL_AUTHOR :
3755 label_counter >= 23 && label_counter <= 26 ?
3756 MICROLABEL_IMPORTED_FROM_HEAD :
3757 label_counter >= 28 && label_counter <= 35 ?
3758 MICROLABEL_IMPORTED_FROM :
3759 label_counter >= 37 && label_counter <= 40 ?
3760 MICROLABEL_IMPORTED_BY_HEAD :
3761 label_counter >= 42 && label_counter <= 49 ?
3762 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3764 if (leveldir_current->imported_from == NULL &&
3765 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3766 label_state == MICROLABEL_IMPORTED_FROM))
3767 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3768 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3770 DrawPreviewLevelLabelExt(label_state);
3773 game_status = last_game_status; /* restore current game status */
3776 void DrawPreviewLevelInitial()
3778 DrawPreviewLevelExt(TRUE);
3781 void DrawPreviewLevelAnimation()
3783 DrawPreviewLevelExt(FALSE);
3786 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3787 int graphic, int sync_frame, int mask_mode)
3789 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3791 if (mask_mode == USE_MASKING)
3792 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3794 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3797 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3798 int graphic, int sync_frame,
3801 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3803 if (mask_mode == USE_MASKING)
3804 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3806 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3809 inline void DrawGraphicAnimation(int x, int y, int graphic)
3811 int lx = LEVELX(x), ly = LEVELY(y);
3813 if (!IN_SCR_FIELD(x, y))
3817 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3818 graphic, GfxFrame[lx][ly], NO_MASKING);
3820 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3821 graphic, GfxFrame[lx][ly], NO_MASKING);
3823 MarkTileDirty(x, y);
3826 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3828 int lx = LEVELX(x), ly = LEVELY(y);
3830 if (!IN_SCR_FIELD(x, y))
3833 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3834 graphic, GfxFrame[lx][ly], NO_MASKING);
3835 MarkTileDirty(x, y);
3838 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3840 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3843 void DrawLevelElementAnimation(int x, int y, int element)
3845 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3847 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3850 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3852 int sx = SCREENX(x), sy = SCREENY(y);
3854 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3857 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3860 DrawGraphicAnimation(sx, sy, graphic);
3863 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3864 DrawLevelFieldCrumbled(x, y);
3866 if (GFX_CRUMBLED(Feld[x][y]))
3867 DrawLevelFieldCrumbled(x, y);
3871 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3873 int sx = SCREENX(x), sy = SCREENY(y);
3876 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3879 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3881 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3884 DrawGraphicAnimation(sx, sy, graphic);
3886 if (GFX_CRUMBLED(element))
3887 DrawLevelFieldCrumbled(x, y);
3890 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3892 if (player->use_murphy)
3894 /* this works only because currently only one player can be "murphy" ... */
3895 static int last_horizontal_dir = MV_LEFT;
3896 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3898 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3899 last_horizontal_dir = move_dir;
3901 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3903 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3905 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3911 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3914 static boolean equalGraphics(int graphic1, int graphic2)
3916 struct GraphicInfo *g1 = &graphic_info[graphic1];
3917 struct GraphicInfo *g2 = &graphic_info[graphic2];
3919 return (g1->bitmap == g2->bitmap &&
3920 g1->src_x == g2->src_x &&
3921 g1->src_y == g2->src_y &&
3922 g1->anim_frames == g2->anim_frames &&
3923 g1->anim_delay == g2->anim_delay &&
3924 g1->anim_mode == g2->anim_mode);
3927 void DrawAllPlayers()
3931 for (i = 0; i < MAX_PLAYERS; i++)
3932 if (stored_player[i].active)
3933 DrawPlayer(&stored_player[i]);
3936 void DrawPlayerField(int x, int y)
3938 if (!IS_PLAYER(x, y))
3941 DrawPlayer(PLAYERINFO(x, y));
3944 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3946 void DrawPlayer(struct PlayerInfo *player)
3948 int jx = player->jx;
3949 int jy = player->jy;
3950 int move_dir = player->MovDir;
3951 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3952 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3953 int last_jx = (player->is_moving ? jx - dx : jx);
3954 int last_jy = (player->is_moving ? jy - dy : jy);
3955 int next_jx = jx + dx;
3956 int next_jy = jy + dy;
3957 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3958 boolean player_is_opaque = FALSE;
3959 int sx = SCREENX(jx), sy = SCREENY(jy);
3960 int sxx = 0, syy = 0;
3961 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3963 int action = ACTION_DEFAULT;
3964 int last_player_graphic = getPlayerGraphic(player, move_dir);
3965 int last_player_frame = player->Frame;
3968 /* GfxElement[][] is set to the element the player is digging or collecting;
3969 remove also for off-screen player if the player is not moving anymore */
3970 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3971 GfxElement[jx][jy] = EL_UNDEFINED;
3973 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3977 if (!IN_LEV_FIELD(jx, jy))
3979 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3980 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3981 printf("DrawPlayerField(): This should never happen!\n");
3986 if (element == EL_EXPLOSION)
3989 action = (player->is_pushing ? ACTION_PUSHING :
3990 player->is_digging ? ACTION_DIGGING :
3991 player->is_collecting ? ACTION_COLLECTING :
3992 player->is_moving ? ACTION_MOVING :
3993 player->is_snapping ? ACTION_SNAPPING :
3994 player->is_dropping ? ACTION_DROPPING :
3995 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3997 if (player->is_waiting)
3998 move_dir = player->dir_waiting;
4000 InitPlayerGfxAnimation(player, action, move_dir);
4002 /* ----------------------------------------------------------------------- */
4003 /* draw things in the field the player is leaving, if needed */
4004 /* ----------------------------------------------------------------------- */
4006 if (player->is_moving)
4008 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
4010 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
4012 if (last_element == EL_DYNAMITE_ACTIVE ||
4013 last_element == EL_EM_DYNAMITE_ACTIVE ||
4014 last_element == EL_SP_DISK_RED_ACTIVE)
4015 DrawDynamite(last_jx, last_jy);
4017 DrawLevelFieldThruMask(last_jx, last_jy);
4019 else if (last_element == EL_DYNAMITE_ACTIVE ||
4020 last_element == EL_EM_DYNAMITE_ACTIVE ||
4021 last_element == EL_SP_DISK_RED_ACTIVE)
4022 DrawDynamite(last_jx, last_jy);
4024 /* !!! this is not enough to prevent flickering of players which are
4025 moving next to each others without a free tile between them -- this
4026 can only be solved by drawing all players layer by layer (first the
4027 background, then the foreground etc.) !!! => TODO */
4028 else if (!IS_PLAYER(last_jx, last_jy))
4029 DrawLevelField(last_jx, last_jy);
4032 DrawLevelField(last_jx, last_jy);
4035 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
4036 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4039 if (!IN_SCR_FIELD(sx, sy))
4042 /* ----------------------------------------------------------------------- */
4043 /* draw things behind the player, if needed */
4044 /* ----------------------------------------------------------------------- */
4047 DrawLevelElement(jx, jy, Back[jx][jy]);
4048 else if (IS_ACTIVE_BOMB(element))
4049 DrawLevelElement(jx, jy, EL_EMPTY);
4052 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
4054 int old_element = GfxElement[jx][jy];
4055 int old_graphic = el_act_dir2img(old_element, action, move_dir);
4056 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
4058 if (GFX_CRUMBLED(old_element))
4059 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
4061 DrawGraphic(sx, sy, old_graphic, frame);
4063 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
4064 player_is_opaque = TRUE;
4068 GfxElement[jx][jy] = EL_UNDEFINED;
4070 /* make sure that pushed elements are drawn with correct frame rate */
4072 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4074 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
4075 GfxFrame[jx][jy] = player->StepFrame;
4077 if (player->is_pushing && player->is_moving)
4078 GfxFrame[jx][jy] = player->StepFrame;
4081 DrawLevelField(jx, jy);
4085 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
4086 /* ----------------------------------------------------------------------- */
4087 /* draw player himself */
4088 /* ----------------------------------------------------------------------- */
4090 graphic = getPlayerGraphic(player, move_dir);
4092 /* in the case of changed player action or direction, prevent the current
4093 animation frame from being restarted for identical animations */
4094 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4095 player->Frame = last_player_frame;
4097 frame = getGraphicAnimationFrame(graphic, player->Frame);
4101 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4102 sxx = player->GfxPos;
4104 syy = player->GfxPos;
4107 if (!setup.soft_scrolling && ScreenMovPos)
4110 if (player_is_opaque)
4111 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4113 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4115 if (SHIELD_ON(player))
4117 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4118 IMG_SHIELD_NORMAL_ACTIVE);
4119 int frame = getGraphicAnimationFrame(graphic, -1);
4121 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4125 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4128 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4129 sxx = player->GfxPos;
4131 syy = player->GfxPos;
4135 /* ----------------------------------------------------------------------- */
4136 /* draw things the player is pushing, if needed */
4137 /* ----------------------------------------------------------------------- */
4140 printf("::: %d, %d [%d, %d] [%d]\n",
4141 player->is_pushing, player_is_moving, player->GfxAction,
4142 player->is_moving, player_is_moving);
4146 if (player->is_pushing && player->is_moving)
4148 int px = SCREENX(jx), py = SCREENY(jy);
4149 int pxx = (TILEX - ABS(sxx)) * dx;
4150 int pyy = (TILEY - ABS(syy)) * dy;
4151 int gfx_frame = GfxFrame[jx][jy];
4157 if (!IS_MOVING(jx, jy)) /* push movement already finished */
4159 element = Feld[next_jx][next_jy];
4160 gfx_frame = GfxFrame[next_jx][next_jy];
4163 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4166 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
4167 frame = getGraphicAnimationFrame(graphic, sync_frame);
4169 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
4172 /* draw background element under pushed element (like the Sokoban field) */
4174 if (game.use_masked_pushing && IS_MOVING(jx, jy))
4176 /* this allows transparent pushing animation over non-black background */
4179 DrawLevelElement(jx, jy, Back[jx][jy]);
4181 DrawLevelElement(jx, jy, EL_EMPTY);
4183 if (Back[next_jx][next_jy])
4184 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4186 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4188 else if (Back[next_jx][next_jy])
4189 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4191 if (Back[next_jx][next_jy])
4192 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4196 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
4197 jx, px, player->GfxPos, player->StepFrame,
4202 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
4206 /* do not draw (EM style) pushing animation when pushing is finished */
4207 /* (two-tile animations usually do not contain start and end frame) */
4208 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
4209 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
4211 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4213 /* masked drawing is needed for EMC style (double) movement graphics */
4214 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
4215 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4220 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4221 /* ----------------------------------------------------------------------- */
4222 /* draw player himself */
4223 /* ----------------------------------------------------------------------- */
4225 graphic = getPlayerGraphic(player, move_dir);
4227 /* in the case of changed player action or direction, prevent the current
4228 animation frame from being restarted for identical animations */
4229 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4230 player->Frame = last_player_frame;
4232 frame = getGraphicAnimationFrame(graphic, player->Frame);
4236 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4237 sxx = player->GfxPos;
4239 syy = player->GfxPos;
4242 if (!setup.soft_scrolling && ScreenMovPos)
4245 if (player_is_opaque)
4246 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4248 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4250 if (SHIELD_ON(player))
4252 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4253 IMG_SHIELD_NORMAL_ACTIVE);
4254 int frame = getGraphicAnimationFrame(graphic, -1);
4256 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4260 /* ----------------------------------------------------------------------- */
4261 /* draw things in front of player (active dynamite or dynabombs) */
4262 /* ----------------------------------------------------------------------- */
4264 if (IS_ACTIVE_BOMB(element))
4266 graphic = el2img(element);
4267 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
4269 if (game.emulation == EMU_SUPAPLEX)
4270 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
4272 DrawGraphicThruMask(sx, sy, graphic, frame);
4275 if (player_is_moving && last_element == EL_EXPLOSION)
4277 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
4278 GfxElement[last_jx][last_jy] : EL_EMPTY);
4279 int graphic = el_act2img(element, ACTION_EXPLODING);
4280 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
4281 int phase = ExplodePhase[last_jx][last_jy] - 1;
4282 int frame = getGraphicAnimationFrame(graphic, phase - delay);
4285 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
4288 /* ----------------------------------------------------------------------- */
4289 /* draw elements the player is just walking/passing through/under */
4290 /* ----------------------------------------------------------------------- */
4292 if (player_is_moving)
4294 /* handle the field the player is leaving ... */
4295 if (IS_ACCESSIBLE_INSIDE(last_element))
4296 DrawLevelField(last_jx, last_jy);
4297 else if (IS_ACCESSIBLE_UNDER(last_element))
4298 DrawLevelFieldThruMask(last_jx, last_jy);
4301 /* do not redraw accessible elements if the player is just pushing them */
4302 if (!player_is_moving || !player->is_pushing)
4304 /* ... and the field the player is entering */
4305 if (IS_ACCESSIBLE_INSIDE(element))
4306 DrawLevelField(jx, jy);
4307 else if (IS_ACCESSIBLE_UNDER(element))
4308 DrawLevelFieldThruMask(jx, jy);
4311 MarkTileDirty(sx, sy);
4314 /* ------------------------------------------------------------------------- */
4316 void WaitForEventToContinue()
4318 boolean still_wait = TRUE;
4320 /* simulate releasing mouse button over last gadget, if still pressed */
4322 HandleGadgets(-1, -1, 0);
4324 button_status = MB_RELEASED;
4340 case EVENT_BUTTONPRESS:
4341 case EVENT_KEYPRESS:
4345 case EVENT_KEYRELEASE:
4346 ClearPlayerAction();
4350 HandleOtherEvents(&event);
4354 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4361 /* don't eat all CPU time */
4366 #define MAX_REQUEST_LINES 13
4367 #define MAX_REQUEST_LINE_FONT1_LEN 7
4368 #define MAX_REQUEST_LINE_FONT2_LEN 10
4372 static int RequestHandleEvents(unsigned int req_state)
4374 int last_game_status = game_status; /* save current game status */
4378 button_status = MB_RELEASED;
4380 request_gadget_id = -1;
4393 case EVENT_BUTTONPRESS:
4394 case EVENT_BUTTONRELEASE:
4395 case EVENT_MOTIONNOTIFY:
4397 if (event.type == EVENT_MOTIONNOTIFY)
4399 if (!PointerInWindow(window))
4400 continue; /* window and pointer are on different screens */
4405 motion_status = TRUE;
4406 mx = ((MotionEvent *) &event)->x;
4407 my = ((MotionEvent *) &event)->y;
4411 motion_status = FALSE;
4412 mx = ((ButtonEvent *) &event)->x;
4413 my = ((ButtonEvent *) &event)->y;
4414 if (event.type == EVENT_BUTTONPRESS)
4415 button_status = ((ButtonEvent *) &event)->button;
4417 button_status = MB_RELEASED;
4420 /* this sets 'request_gadget_id' */
4421 HandleGadgets(mx, my, button_status);
4423 switch (request_gadget_id)
4425 case TOOL_CTRL_ID_YES:
4428 case TOOL_CTRL_ID_NO:
4431 case TOOL_CTRL_ID_CONFIRM:
4432 result = TRUE | FALSE;
4435 case TOOL_CTRL_ID_PLAYER_1:
4438 case TOOL_CTRL_ID_PLAYER_2:
4441 case TOOL_CTRL_ID_PLAYER_3:
4444 case TOOL_CTRL_ID_PLAYER_4:
4455 case EVENT_KEYPRESS:
4456 switch (GetEventKey((KeyEvent *)&event, TRUE))
4459 if (req_state & REQ_CONFIRM)
4468 #if defined(TARGET_SDL2)
4478 if (req_state & REQ_PLAYER)
4482 case EVENT_KEYRELEASE:
4483 ClearPlayerAction();
4487 HandleOtherEvents(&event);
4491 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4493 int joy = AnyJoystick();
4495 if (joy & JOY_BUTTON_1)
4497 else if (joy & JOY_BUTTON_2)
4503 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4505 HandleGameActions();
4511 if (!PendingEvent()) /* delay only if no pending events */
4516 game_status = GAME_MODE_PSEUDO_DOOR;
4522 game_status = last_game_status; /* restore current game status */
4530 if (!PendingEvent()) /* delay only if no pending events */
4533 /* don't eat all CPU time */
4543 static boolean RequestDoor(char *text, unsigned int req_state)
4545 unsigned int old_door_state;
4546 int last_game_status = game_status; /* save current game status */
4547 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4548 int font_nr = FONT_TEXT_2;
4553 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4555 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4556 font_nr = FONT_TEXT_1;
4559 if (game_status == GAME_MODE_PLAYING)
4561 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4562 BlitScreenToBitmap_EM(backbuffer);
4563 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4564 BlitScreenToBitmap_SP(backbuffer);
4567 /* disable deactivated drawing when quick-loading level tape recording */
4568 if (tape.playing && tape.deactivate_display)
4569 TapeDeactivateDisplayOff(TRUE);
4571 SetMouseCursor(CURSOR_DEFAULT);
4573 #if defined(NETWORK_AVALIABLE)
4574 /* pause network game while waiting for request to answer */
4575 if (options.network &&
4576 game_status == GAME_MODE_PLAYING &&
4577 req_state & REQUEST_WAIT_FOR_INPUT)
4578 SendToServer_PausePlaying();
4581 old_door_state = GetDoorState();
4583 /* simulate releasing mouse button over last gadget, if still pressed */
4585 HandleGadgets(-1, -1, 0);
4589 /* draw released gadget before proceeding */
4592 if (old_door_state & DOOR_OPEN_1)
4594 CloseDoor(DOOR_CLOSE_1);
4596 /* save old door content */
4598 BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
4599 0 * DXSIZE, 0, DXSIZE, DYSIZE, 1 * DXSIZE, 0);
4601 BlitBitmap(bitmap_db_door, bitmap_db_door,
4602 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4603 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4607 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4608 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4610 /* clear door drawing field */
4611 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4613 /* force DOOR font inside door area */
4614 game_status = GAME_MODE_PSEUDO_DOOR;
4616 /* write text for request */
4617 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4619 char text_line[max_request_line_len + 1];
4625 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4627 tc = *(text_ptr + tx);
4628 // if (!tc || tc == ' ')
4629 if (!tc || tc == ' ' || tc == '?' || tc == '!')
4633 if ((tc == '?' || tc == '!') && tl == 0)
4643 strncpy(text_line, text_ptr, tl);
4646 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4647 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4648 text_line, font_nr);
4650 text_ptr += tl + (tc == ' ' ? 1 : 0);
4651 // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
4654 game_status = last_game_status; /* restore current game status */
4656 if (req_state & REQ_ASK)
4658 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4659 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4661 else if (req_state & REQ_CONFIRM)
4663 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4665 else if (req_state & REQ_PLAYER)
4667 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4668 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4669 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4670 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4673 /* copy request gadgets to door backbuffer */
4675 BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
4677 BlitBitmap(drawto, bitmap_db_door,
4678 DX, DY, DXSIZE, DYSIZE,
4679 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4682 OpenDoor(DOOR_OPEN_1);
4684 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4686 if (game_status == GAME_MODE_PLAYING)
4688 SetPanelBackground();
4689 SetDrawBackgroundMask(REDRAW_DOOR_1);
4693 SetDrawBackgroundMask(REDRAW_FIELD);
4699 if (game_status != GAME_MODE_MAIN)
4702 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4704 // ---------- handle request buttons ----------
4705 result = RequestHandleEvents(req_state);
4707 if (game_status != GAME_MODE_MAIN)
4712 if (!(req_state & REQ_STAY_OPEN))
4714 CloseDoor(DOOR_CLOSE_1);
4716 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4717 (req_state & REQ_REOPEN))
4718 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4723 if (game_status == GAME_MODE_PLAYING)
4725 SetPanelBackground();
4726 SetDrawBackgroundMask(REDRAW_DOOR_1);
4730 SetDrawBackgroundMask(REDRAW_FIELD);
4733 #if defined(NETWORK_AVALIABLE)
4734 /* continue network game after request */
4735 if (options.network &&
4736 game_status == GAME_MODE_PLAYING &&
4737 req_state & REQUEST_WAIT_FOR_INPUT)
4738 SendToServer_ContinuePlaying();
4741 /* restore deactivated drawing when quick-loading level tape recording */
4742 if (tape.playing && tape.deactivate_display)
4743 TapeDeactivateDisplayOn();
4748 static boolean RequestEnvelope(char *text, unsigned int req_state)
4755 if (game_status == GAME_MODE_PLAYING)
4757 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4758 BlitScreenToBitmap_EM(backbuffer);
4759 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4760 BlitScreenToBitmap_SP(backbuffer);
4763 /* disable deactivated drawing when quick-loading level tape recording */
4764 if (tape.playing && tape.deactivate_display)
4765 TapeDeactivateDisplayOff(TRUE);
4767 SetMouseCursor(CURSOR_DEFAULT);
4769 #if defined(NETWORK_AVALIABLE)
4770 /* pause network game while waiting for request to answer */
4771 if (options.network &&
4772 game_status == GAME_MODE_PLAYING &&
4773 req_state & REQUEST_WAIT_FOR_INPUT)
4774 SendToServer_PausePlaying();
4777 /* simulate releasing mouse button over last gadget, if still pressed */
4779 HandleGadgets(-1, -1, 0);
4783 // (replace with setting corresponding request background)
4784 // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4785 // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4787 /* clear door drawing field */
4788 // DrawBackground(DX, DY, DXSIZE, DYSIZE);
4791 if (global.use_envelope_request)
4795 CreateToolButtons();
4801 if (req_state & REQ_ASK)
4803 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_YES], FALSE);
4804 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_NO], FALSE);
4806 else if (req_state & REQ_CONFIRM)
4808 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_CONFIRM], FALSE);
4810 else if (req_state & REQ_PLAYER)
4812 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_1], FALSE);
4813 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_2], FALSE);
4814 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_3], FALSE);
4815 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_4], FALSE);
4818 if (req_state & REQ_ASK)
4820 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4821 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4823 else if (req_state & REQ_CONFIRM)
4825 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4827 else if (req_state & REQ_PLAYER)
4829 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4830 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4831 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4832 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4837 ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
4840 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4842 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4843 i == TOOL_CTRL_ID_NO)) ||
4844 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4845 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4846 i == TOOL_CTRL_ID_PLAYER_2 &&
4847 i == TOOL_CTRL_ID_PLAYER_3 &&
4848 i == TOOL_CTRL_ID_PLAYER_4)))
4850 int x = tool_gadget[i]->x + dDX;
4851 int y = tool_gadget[i]->y + dDY;
4853 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4858 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4860 if (game_status == GAME_MODE_PLAYING)
4862 SetPanelBackground();
4863 SetDrawBackgroundMask(REDRAW_DOOR_1);
4867 SetDrawBackgroundMask(REDRAW_FIELD);
4874 if (game_status != GAME_MODE_MAIN)
4878 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4880 // ---------- handle request buttons ----------
4881 result = RequestHandleEvents(req_state);
4883 if (game_status != GAME_MODE_MAIN)
4888 ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
4892 if (game_status == GAME_MODE_PLAYING)
4894 SetPanelBackground();
4895 SetDrawBackgroundMask(REDRAW_DOOR_1);
4899 SetDrawBackgroundMask(REDRAW_FIELD);
4902 #if defined(NETWORK_AVALIABLE)
4903 /* continue network game after request */
4904 if (options.network &&
4905 game_status == GAME_MODE_PLAYING &&
4906 req_state & REQUEST_WAIT_FOR_INPUT)
4907 SendToServer_ContinuePlaying();
4910 /* restore deactivated drawing when quick-loading level tape recording */
4911 if (tape.playing && tape.deactivate_display)
4912 TapeDeactivateDisplayOn();
4917 boolean Request(char *text, unsigned int req_state)
4919 if (global.use_envelope_request)
4920 return RequestEnvelope(text, req_state);
4922 return RequestDoor(text, req_state);
4925 #else // =====================================================================
4927 boolean Request(char *text, unsigned int req_state)
4929 int mx, my, ty, result = -1;
4930 unsigned int old_door_state;
4931 int last_game_status = game_status; /* save current game status */
4932 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4933 int font_nr = FONT_TEXT_2;
4935 int max_word_len = 0;
4941 global.use_envelope_request = 1;
4945 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4947 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4948 font_nr = FONT_TEXT_1;
4951 for (text_ptr = text; *text_ptr; text_ptr++)
4953 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
4955 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
4957 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4959 font_nr = FONT_TEXT_1;
4961 font_nr = FONT_LEVEL_NUMBER;
4969 if (game_status == GAME_MODE_PLAYING)
4971 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4972 BlitScreenToBitmap_EM(backbuffer);
4973 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4974 BlitScreenToBitmap_SP(backbuffer);
4977 /* disable deactivated drawing when quick-loading level tape recording */
4978 if (tape.playing && tape.deactivate_display)
4979 TapeDeactivateDisplayOff(TRUE);
4981 SetMouseCursor(CURSOR_DEFAULT);
4983 #if defined(NETWORK_AVALIABLE)
4984 /* pause network game while waiting for request to answer */
4985 if (options.network &&
4986 game_status == GAME_MODE_PLAYING &&
4987 req_state & REQUEST_WAIT_FOR_INPUT)
4988 SendToServer_PausePlaying();
4991 old_door_state = GetDoorState();
4993 /* simulate releasing mouse button over last gadget, if still pressed */
4995 HandleGadgets(-1, -1, 0);
4999 /* draw released gadget before proceeding */
5003 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
5005 if (old_door_state & DOOR_OPEN_1)
5009 if (!global.use_envelope_request)
5010 CloseDoor(DOOR_CLOSE_1);
5012 CloseDoor(DOOR_CLOSE_1);
5015 /* save old door content */
5016 BlitBitmap(bitmap_db_door, bitmap_db_door,
5017 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5018 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
5022 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
5025 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5027 /* clear door drawing field */
5028 DrawBackground(DX, DY, DXSIZE, DYSIZE);
5030 /* force DOOR font inside door area */
5031 game_status = GAME_MODE_PSEUDO_DOOR;
5033 /* write text for request */
5034 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
5036 char text_line[max_request_line_len + 1];
5042 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
5044 tc = *(text_ptr + tx);
5045 if (!tc || tc == ' ')
5056 strncpy(text_line, text_ptr, tl);
5059 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
5060 DY + 8 + ty * (getFontHeight(font_nr) + 2),
5061 text_line, font_nr);
5063 text_ptr += tl + (tc == ' ' ? 1 : 0);
5066 game_status = last_game_status; /* restore current game status */
5069 if (global.use_envelope_request)
5073 CreateToolButtons();
5077 if (req_state & REQ_ASK)
5079 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
5080 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
5082 else if (req_state & REQ_CONFIRM)
5084 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
5086 else if (req_state & REQ_PLAYER)
5088 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
5089 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
5090 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
5091 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
5094 /* copy request gadgets to door backbuffer */
5095 BlitBitmap(drawto, bitmap_db_door,
5096 DX, DY, DXSIZE, DYSIZE,
5097 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5100 if (global.use_envelope_request)
5102 ShowEnvelopeRequest(text, ACTION_OPENING);
5104 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
5106 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
5107 i == TOOL_CTRL_ID_NO)) ||
5108 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
5109 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
5110 i == TOOL_CTRL_ID_PLAYER_2 &&
5111 i == TOOL_CTRL_ID_PLAYER_3 &&
5112 i == TOOL_CTRL_ID_PLAYER_4)))
5114 int x = tool_gadget[i]->x + dDX;
5115 int y = tool_gadget[i]->y + dDY;
5117 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
5124 if (!global.use_envelope_request)
5125 OpenDoor(DOOR_OPEN_1);
5127 OpenDoor(DOOR_OPEN_1);
5130 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
5132 if (game_status == GAME_MODE_PLAYING)
5134 SetPanelBackground();
5135 SetDrawBackgroundMask(REDRAW_DOOR_1);
5139 SetDrawBackgroundMask(REDRAW_FIELD);
5146 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
5149 if (game_status != GAME_MODE_MAIN)
5153 button_status = MB_RELEASED;
5155 request_gadget_id = -1;
5157 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5169 case EVENT_BUTTONPRESS:
5170 case EVENT_BUTTONRELEASE:
5171 case EVENT_MOTIONNOTIFY:
5173 if (event.type == EVENT_MOTIONNOTIFY)
5175 if (!PointerInWindow(window))
5176 continue; /* window and pointer are on different screens */
5181 motion_status = TRUE;
5182 mx = ((MotionEvent *) &event)->x;
5183 my = ((MotionEvent *) &event)->y;
5187 motion_status = FALSE;
5188 mx = ((ButtonEvent *) &event)->x;
5189 my = ((ButtonEvent *) &event)->y;
5190 if (event.type == EVENT_BUTTONPRESS)
5191 button_status = ((ButtonEvent *) &event)->button;
5193 button_status = MB_RELEASED;
5196 /* this sets 'request_gadget_id' */
5197 HandleGadgets(mx, my, button_status);
5199 switch (request_gadget_id)
5201 case TOOL_CTRL_ID_YES:
5204 case TOOL_CTRL_ID_NO:
5207 case TOOL_CTRL_ID_CONFIRM:
5208 result = TRUE | FALSE;
5211 case TOOL_CTRL_ID_PLAYER_1:
5214 case TOOL_CTRL_ID_PLAYER_2:
5217 case TOOL_CTRL_ID_PLAYER_3:
5220 case TOOL_CTRL_ID_PLAYER_4:
5231 case EVENT_KEYPRESS:
5232 switch (GetEventKey((KeyEvent *)&event, TRUE))
5235 if (req_state & REQ_CONFIRM)
5244 #if defined(TARGET_SDL2)
5254 if (req_state & REQ_PLAYER)
5258 case EVENT_KEYRELEASE:
5259 ClearPlayerAction();
5263 HandleOtherEvents(&event);
5267 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
5269 int joy = AnyJoystick();
5271 if (joy & JOY_BUTTON_1)
5273 else if (joy & JOY_BUTTON_2)
5279 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
5281 HandleGameActions();
5287 if (!PendingEvent()) /* delay only if no pending events */
5292 game_status = GAME_MODE_PSEUDO_DOOR;
5298 game_status = last_game_status; /* restore current game status */
5306 if (!PendingEvent()) /* delay only if no pending events */
5309 /* don't eat all CPU time */
5316 if (game_status != GAME_MODE_MAIN)
5322 if (global.use_envelope_request)
5323 ShowEnvelopeRequest(text, ACTION_CLOSING);
5327 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
5329 if (!(req_state & REQ_STAY_OPEN))
5332 CloseDoor(DOOR_CLOSE_1);
5334 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
5335 (req_state & REQ_REOPEN))
5336 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
5341 if (game_status == GAME_MODE_PLAYING)
5343 SetPanelBackground();
5344 SetDrawBackgroundMask(REDRAW_DOOR_1);
5348 SetDrawBackgroundMask(REDRAW_FIELD);
5351 #if defined(NETWORK_AVALIABLE)
5352 /* continue network game after request */
5353 if (options.network &&
5354 game_status == GAME_MODE_PLAYING &&
5355 req_state & REQUEST_WAIT_FOR_INPUT)
5356 SendToServer_ContinuePlaying();
5359 /* restore deactivated drawing when quick-loading level tape recording */
5360 if (tape.playing && tape.deactivate_display)
5361 TapeDeactivateDisplayOn();
5368 static int compareDoorPartOrderInfo(const void *object1, const void *object2)
5370 const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
5371 const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
5374 if (dpo1->sort_priority != dpo2->sort_priority)
5375 compare_result = dpo1->sort_priority - dpo2->sort_priority;
5377 compare_result = dpo1->nr - dpo2->nr;
5379 return compare_result;
5382 void InitGraphicCompatibilityInfo_Doors()
5388 struct DoorInfo *door;
5392 { DOOR_1, IMG_DOOR_1_GFX_PART_1, IMG_DOOR_1_GFX_PART_8, &door_1 },
5393 { DOOR_2, IMG_DOOR_2_GFX_PART_1, IMG_DOOR_2_GFX_PART_8, &door_2 },
5395 { -1, -1, -1, NULL }
5397 struct Rect door_rect_list[] =
5399 { DX, DY, DXSIZE, DYSIZE },
5400 { VX, VY, VXSIZE, VYSIZE }
5404 for (i = 0; doors[i].door_token != -1; i++)
5406 int door_token = doors[i].door_token;
5407 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5408 int part_1 = doors[i].part_1;
5409 int part_8 = doors[i].part_8;
5410 int part_2 = part_1 + 1;
5411 int part_3 = part_1 + 2;
5412 struct DoorInfo *door = doors[i].door;
5413 struct Rect *door_rect = &door_rect_list[door_index];
5414 boolean door_gfx_redefined = FALSE;
5416 /* check if any door part graphic definitions have been redefined */
5418 for (j = 0; door_part_controls[j].door_token != -1; j++)
5420 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5421 struct FileInfo *fi = getImageListEntryFromImageID(dpc->graphic);
5423 if (dpc->door_token == door_token && fi->redefined)
5424 door_gfx_redefined = TRUE;
5427 /* check for old-style door graphic/animation modifications */
5429 if (!door_gfx_redefined)
5431 if (door->anim_mode & ANIM_STATIC_PANEL)
5433 door->panel.step_xoffset = 0;
5434 door->panel.step_yoffset = 0;
5437 if (door->anim_mode & (ANIM_HORIZONTAL | ANIM_VERTICAL))
5439 struct GraphicInfo *g_part_1 = &graphic_info[part_1];
5440 struct GraphicInfo *g_part_2 = &graphic_info[part_2];
5441 int num_door_steps, num_panel_steps;
5443 /* remove door part graphics other than the two default wings */
5445 for (j = 0; door_part_controls[j].door_token != -1; j++)
5447 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5448 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5450 if (dpc->graphic >= part_3 &&
5451 dpc->graphic <= part_8)
5455 /* set graphics and screen positions of the default wings */
5457 g_part_1->width = door_rect->width;
5458 g_part_1->height = door_rect->height;
5459 g_part_2->width = door_rect->width;
5460 g_part_2->height = door_rect->height;
5461 g_part_2->src_x = door_rect->width;
5462 g_part_2->src_y = g_part_1->src_y;
5464 door->part_2.x = door->part_1.x;
5465 door->part_2.y = door->part_1.y;
5467 if (door->width != -1)
5469 g_part_1->width = door->width;
5470 g_part_2->width = door->width;
5472 // special treatment for graphics and screen position of right wing
5473 g_part_2->src_x += door_rect->width - door->width;
5474 door->part_2.x += door_rect->width - door->width;
5477 if (door->height != -1)
5479 g_part_1->height = door->height;
5480 g_part_2->height = door->height;
5482 // special treatment for graphics and screen position of bottom wing
5483 g_part_2->src_y += door_rect->height - door->height;
5484 door->part_2.y += door_rect->height - door->height;
5487 /* set animation delays for the default wings and panels */
5489 door->part_1.step_delay = door->step_delay;
5490 door->part_2.step_delay = door->step_delay;
5491 door->panel.step_delay = door->step_delay;
5493 /* set animation draw order for the default wings */
5495 door->part_1.sort_priority = 2; /* draw left wing over ... */
5496 door->part_2.sort_priority = 1; /* ... right wing */
5498 /* set animation draw offset for the default wings */
5500 if (door->anim_mode & ANIM_HORIZONTAL)
5502 door->part_1.step_xoffset = door->step_offset;
5503 door->part_1.step_yoffset = 0;
5504 door->part_2.step_xoffset = door->step_offset * -1;
5505 door->part_2.step_yoffset = 0;
5507 num_door_steps = g_part_1->width / door->step_offset;
5509 else // ANIM_VERTICAL
5511 door->part_1.step_xoffset = 0;
5512 door->part_1.step_yoffset = door->step_offset;
5513 door->part_2.step_xoffset = 0;
5514 door->part_2.step_yoffset = door->step_offset * -1;
5516 num_door_steps = g_part_1->height / door->step_offset;
5519 /* set animation draw offset for the default panels */
5521 if (door->step_offset > 1)
5523 num_panel_steps = 2 * door_rect->height / door->step_offset;
5524 door->panel.start_step = num_panel_steps - num_door_steps;
5528 num_panel_steps = door_rect->height / door->step_offset;
5529 door->panel.start_step = num_panel_steps - num_door_steps / 2;
5530 door->panel.step_delay *= 2;
5541 for (i = 0; door_part_controls[i].door_token != -1; i++)
5543 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5544 struct DoorPartOrderInfo *dpo = &door_part_order[i];
5546 /* initialize "start_step_opening" and "start_step_closing", if needed */
5547 if (dpc->pos->start_step_opening == 0 &&
5548 dpc->pos->start_step_closing == 0)
5550 // dpc->pos->start_step_opening = dpc->pos->start_step;
5551 dpc->pos->start_step_closing = dpc->pos->start_step;
5554 /* fill structure for door part draw order (sorted below) */
5556 dpo->sort_priority = dpc->pos->sort_priority;
5559 struct DoorPartPosInfo *pos = dpc->pos;
5561 printf(":0: step_xoffset == %d, step_yoffset == %d\n",
5562 pos->step_xoffset, pos->step_yoffset);
5566 /* sort door part controls according to sort_priority and graphic number */
5567 qsort(door_part_order, MAX_DOOR_PARTS,
5568 sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
5571 unsigned int OpenDoor(unsigned int door_state)
5573 if (door_state & DOOR_COPY_BACK)
5576 if (door_state & DOOR_OPEN_1)
5577 BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
5578 1 * DXSIZE, 0, DXSIZE, DYSIZE, 0 * DXSIZE, 0);
5580 if (door_state & DOOR_OPEN_2)
5581 BlitBitmap(bitmap_db_door_2, bitmap_db_door_2,
5582 1 * VXSIZE, 0, VXSIZE, VYSIZE, 0 * VXSIZE, 0);
5584 if (door_state & DOOR_OPEN_1)
5585 BlitBitmap(bitmap_db_door, bitmap_db_door,
5586 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5587 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5589 if (door_state & DOOR_OPEN_2)
5590 BlitBitmap(bitmap_db_door, bitmap_db_door,
5591 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
5592 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5595 door_state &= ~DOOR_COPY_BACK;
5598 return MoveDoor(door_state);
5601 unsigned int CloseDoor(unsigned int door_state)
5603 unsigned int old_door_state = GetDoorState();
5605 if (!(door_state & DOOR_NO_COPY_BACK))
5608 if (old_door_state & DOOR_OPEN_1)
5609 BlitBitmap(backbuffer, bitmap_db_door_1,
5610 DX, DY, DXSIZE, DYSIZE, 0, 0);
5612 if (old_door_state & DOOR_OPEN_2)
5613 BlitBitmap(backbuffer, bitmap_db_door_2,
5614 VX, VY, VXSIZE, VYSIZE, 0, 0);
5616 if (old_door_state & DOOR_OPEN_1)
5617 BlitBitmap(backbuffer, bitmap_db_door,
5618 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5620 if (old_door_state & DOOR_OPEN_2)
5621 BlitBitmap(backbuffer, bitmap_db_door,
5622 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5625 door_state &= ~DOOR_NO_COPY_BACK;
5628 return MoveDoor(door_state);
5631 unsigned int GetDoorState()
5633 return MoveDoor(DOOR_GET_STATE);
5636 unsigned int SetDoorState(unsigned int door_state)
5638 return MoveDoor(door_state | DOOR_SET_STATE);
5643 // ========== TEST 1 ===========================================================
5645 int euclid(int a, int b)
5647 return (b ? euclid(b, a % b) : a);
5650 unsigned int MoveDoor(unsigned int door_state)
5653 struct XY panel_pos_list[] =
5655 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 },
5656 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 },
5659 struct Rect door_rect_list[] =
5661 { DX, DY, DXSIZE, DYSIZE },
5662 { VX, VY, VXSIZE, VYSIZE }
5664 static int door1 = DOOR_OPEN_1;
5665 static int door2 = DOOR_CLOSE_2;
5666 unsigned int door_delay = 0;
5667 unsigned int door_delay_value;
5671 if (door_1.width < 0 || door_1.width > DXSIZE)
5672 door_1.width = DXSIZE;
5673 if (door_1.height < 0 || door_1.height > DYSIZE)
5674 door_1.height = DYSIZE;
5675 if (door_2.width < 0 || door_2.width > VXSIZE)
5676 door_2.width = VXSIZE;
5677 if (door_2.height < 0 || door_2.height > VYSIZE)
5678 door_2.height = VYSIZE;
5681 if (door_state == DOOR_GET_STATE)
5682 return (door1 | door2);
5684 if (door_state & DOOR_SET_STATE)
5686 if (door_state & DOOR_ACTION_1)
5687 door1 = door_state & DOOR_ACTION_1;
5688 if (door_state & DOOR_ACTION_2)
5689 door2 = door_state & DOOR_ACTION_2;
5691 return (door1 | door2);
5694 if (!(door_state & DOOR_FORCE_REDRAW))
5696 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
5697 door_state &= ~DOOR_OPEN_1;
5698 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
5699 door_state &= ~DOOR_CLOSE_1;
5700 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
5701 door_state &= ~DOOR_OPEN_2;
5702 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
5703 door_state &= ~DOOR_CLOSE_2;
5707 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
5710 if (setup.quick_doors)
5712 stepsize = 20; /* must be chosen to always draw last frame */
5713 door_delay_value = 0;
5717 if (global.autoplay_leveldir)
5719 door_state |= DOOR_NO_DELAY;
5720 door_state &= ~DOOR_CLOSE_ALL;
5724 if (game_status == GAME_MODE_EDITOR)
5725 door_state |= DOOR_NO_DELAY;
5728 if (door_state & DOOR_ACTION)
5730 boolean door_panel_drawn[NUM_DOORS];
5731 boolean panel_has_doors[NUM_DOORS];
5732 boolean door_part_skip[MAX_DOOR_PARTS];
5733 boolean door_part_done[MAX_DOOR_PARTS];
5734 boolean door_part_done_all;
5735 int num_steps[MAX_DOOR_PARTS];
5736 int max_move_delay = 0; // delay for complete animations of all doors
5737 int max_step_delay = 0; // delay (ms) between two animation frames
5738 int num_move_steps = 0; // number of animation steps for all doors
5739 int current_move_delay = 0;
5742 for (i = 0; i < NUM_DOORS; i++)
5743 panel_has_doors[i] = FALSE;
5745 for (i = 0; i < MAX_DOOR_PARTS; i++)
5747 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5748 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5749 int door_token = dpc->door_token;
5751 door_part_done[i] = FALSE;
5752 door_part_skip[i] = (!(door_state & door_token) ||
5757 for (i = 0; i < MAX_DOOR_PARTS; i++)
5759 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5760 struct DoorPartPosInfo *pos = dpc->pos;
5761 int start_step = pos->start_step;
5763 printf("::: ---> %d: start_step == %d [%d]\n",
5764 i, start_step, door_part_done[i]);
5768 for (i = 0; i < MAX_DOOR_PARTS; i++)
5770 int nr = door_part_order[i].nr;
5771 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5772 struct DoorPartPosInfo *pos = dpc->pos;
5773 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5774 int door_token = dpc->door_token;
5775 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5776 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5777 int step_xoffset = ABS(pos->step_xoffset);
5778 int step_yoffset = ABS(pos->step_yoffset);
5779 int step_delay = pos->step_delay;
5780 int current_door_state = door_state & door_token;
5781 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5782 boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
5783 boolean part_opening = (is_panel ? door_closing : door_opening);
5784 int start_step = (part_opening ? pos->start_step_opening :
5785 pos->start_step_closing);
5786 float move_xsize = (step_xoffset ? g->width : 0);
5787 float move_ysize = (step_yoffset ? g->height : 0);
5788 int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
5789 int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0);
5790 int move_steps = (move_xsteps && move_ysteps ?
5791 MIN(move_xsteps, move_ysteps) :
5792 move_xsteps ? move_xsteps : move_ysteps) - start_step;
5793 int move_delay = move_steps * step_delay;
5795 if (door_part_skip[nr])
5799 panel_has_doors[door_index] = TRUE;
5801 max_move_delay = MAX(max_move_delay, move_delay);
5802 max_step_delay = (max_step_delay == 0 ? step_delay :
5803 euclid(max_step_delay, step_delay));
5804 num_steps[nr] = move_steps;
5808 printf("::: %d: move_delay == %d, start_step == %d [%d]\n",
5809 i, move_delay, start_step, door_part_order[i].nr);
5811 if (DOOR_PART_IS_PANEL(i))
5812 printf("::: %d: move_delay == %d, start_step == %d\n",
5813 i, move_delay, start_step);
5818 num_move_steps = max_move_delay / max_step_delay;
5820 door_delay_value = max_step_delay;
5823 door_delay_value *= 10;
5827 printf("::: num_move_steps == %d, max_move_delay == %d, max_step_delay == %d\n", num_move_steps, max_move_delay, max_step_delay);
5830 for (k = 0; k < num_move_steps; k++)
5832 door_part_done_all = TRUE;
5834 for (i = 0; i < NUM_DOORS; i++)
5835 door_panel_drawn[i] = FALSE;
5837 for (i = 0; i < MAX_DOOR_PARTS; i++)
5839 int nr = door_part_order[i].nr;
5840 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5841 struct DoorPartPosInfo *pos = dpc->pos;
5842 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5843 int door_token = dpc->door_token;
5844 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5845 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5847 struct XY *panel_pos = &panel_pos_list[door_index];
5849 struct Rect *door_rect = &door_rect_list[door_index];
5850 Bitmap *bitmap_db_door = (door_token == DOOR_1 ? bitmap_db_door_1 :
5852 Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
5853 int current_door_state = door_state & door_token;
5854 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5855 boolean door_closing = !door_opening;
5856 boolean part_opening = (is_panel ? door_closing : door_opening);
5857 boolean part_closing = !part_opening;
5858 int start_step = (part_opening ? pos->start_step_opening :
5859 pos->start_step_closing);
5860 int step_delay = pos->step_delay;
5861 int step_factor = step_delay / max_step_delay;
5862 int k1 = (step_factor ? k / step_factor + 1 : k);
5863 int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
5864 int kk = (k2 < 0 ? 0 : k2);
5865 int src_x, src_y, src_xx, src_yy;
5866 int dst_x, dst_y, dst_xx, dst_yy;
5870 if (k == 0 && is_panel && door_token == DOOR_2)
5871 printf("::: %d, %d\n", g->width, g->height);
5875 if (DOOR_PART_IS_PANEL(nr))
5877 int start_step = pos->start_step;
5879 k2 = (door_closing ? k1 : num_steps[nr] - k1);// - start_step;
5880 kk = (k2 < 0 ? 0 : k2);
5886 if (nr != 16 && nr != 0)
5897 if (door_part_skip[nr])
5901 if (!(door_state & door_token))
5908 if (current_move_delay % step_delay)
5914 if (!door_panel_drawn[door_index])
5917 ClearRectangle(drawto, door_rect->x, door_rect->y,
5918 door_rect->width, door_rect->height);
5920 BlitBitmap(bitmap_db_door, drawto, panel_pos->x, panel_pos->y,
5921 door_rect->width, door_rect->height,
5922 door_rect->x, door_rect->y);
5925 door_panel_drawn[door_index] = TRUE;
5928 // draw opening or closing door parts
5930 if (pos->step_xoffset < 0) // door part on right side
5933 dst_xx = pos->x + ABS(kk * pos->step_xoffset);
5936 if (dst_xx + width > door_rect->width)
5937 width = door_rect->width - dst_xx;
5939 else // door part on left side
5942 dst_xx = pos->x - kk * pos->step_xoffset;
5946 src_xx = ABS(dst_xx);
5950 width = g->width - src_xx;
5952 // printf("::: k == %d [%d] \n", k, start_step);
5955 if (pos->step_yoffset < 0) // door part on bottom side
5958 dst_yy = pos->y + ABS(kk * pos->step_yoffset);
5961 if (dst_yy + height > door_rect->height)
5962 height = door_rect->height - dst_yy;
5964 else // door part on top side
5967 dst_yy = pos->y - kk * pos->step_yoffset;
5971 src_yy = ABS(dst_yy);
5975 height = g->height - src_yy;
5984 src_x = panel_pos->x + src_xx;
5985 src_y = panel_pos->y + src_yy;
5990 src_x = g->src_x + src_xx;
5991 src_y = g->src_y + src_yy;
5994 dst_x = door_rect->x + dst_xx;
5995 dst_y = door_rect->y + dst_yy;
5998 if (DOOR_PART_IS_PANEL(nr))
6000 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
6001 width, height, g->width, g->height, src_x, src_y);
6005 if (width >= 0 && width <= g->width &&
6006 height >= 0 && height <= g->height)
6008 if (is_panel || !pos->draw_masked)
6009 BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
6012 BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height,
6017 if (DOOR_PART_IS_PANEL(nr))
6019 bitmap = bitmap_db_door;
6020 src_x = panel_pos->x + src_xx;
6021 src_y = panel_pos->y + src_yy;
6023 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
6024 width, height, g->width, g->height, src_x, src_y);
6026 if (width >= 0 && width <= g->width &&
6027 height >= 0 && height <= g->height)
6028 BlitBitmap(bitmap, drawto, src_x, src_y,
6034 redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
6037 if ((part_opening && (width < 0 || height < 0)) ||
6038 (part_closing && (width >= g->width && height >= g->height)))
6039 door_part_done[nr] = TRUE;
6041 if ((door_opening && (width < 0 || height < 0)) ||
6042 (door_closing && (width >= g->width && height >= g->height)))
6043 door_part_done[nr] = TRUE;
6047 // continue door part animations, but not panel after door has closed
6048 if (!door_part_done[nr] &&
6049 !(is_panel && door_closing && panel_has_doors[door_index]))
6050 door_part_done_all = FALSE;
6052 // continue door part animations, but not panel after door has closed
6053 if (!door_part_done[nr] && !(is_panel && door_closing))
6054 door_part_done_all = FALSE;
6058 if (!door_part_done[nr])
6059 printf("::: k == %d, nr == %d\n", k, nr);
6063 if (!(door_state & DOOR_NO_DELAY))
6067 if (game_status == GAME_MODE_MAIN)
6070 WaitUntilDelayReached(&door_delay, door_delay_value);
6072 current_move_delay += max_step_delay;
6076 door_part_done_all = TRUE;
6078 for (i = 0; i < MAX_DOOR_PARTS; i++)
6079 if (!door_part_done[i] &&
6080 !(DOOR_PART_IS_PANEL(i) && door_closing))
6081 door_part_done_all = FALSE;
6084 if (door_part_done_all)
6090 if (door_state & DOOR_ACTION_1)
6091 door1 = door_state & DOOR_ACTION_1;
6092 if (door_state & DOOR_ACTION_2)
6093 door2 = door_state & DOOR_ACTION_2;
6096 printf("::: DOORS DONE %08x\n", door_state);
6098 printf("::: GO!\n");
6101 return (door1 | door2);
6106 // ========== OLD ==============================================================
6108 unsigned int MoveDoor(unsigned int door_state)
6110 static int door1 = DOOR_OPEN_1;
6111 static int door2 = DOOR_CLOSE_2;
6112 unsigned int door_delay = 0;
6113 unsigned int door_delay_value;
6117 if (door_1.width < 0 || door_1.width > DXSIZE)
6118 door_1.width = DXSIZE;
6119 if (door_1.height < 0 || door_1.height > DYSIZE)
6120 door_1.height = DYSIZE;
6121 if (door_2.width < 0 || door_2.width > VXSIZE)
6122 door_2.width = VXSIZE;
6123 if (door_2.height < 0 || door_2.height > VYSIZE)
6124 door_2.height = VYSIZE;
6127 if (door_state == DOOR_GET_STATE)
6128 return (door1 | door2);
6130 if (door_state & DOOR_SET_STATE)
6132 if (door_state & DOOR_ACTION_1)
6133 door1 = door_state & DOOR_ACTION_1;
6134 if (door_state & DOOR_ACTION_2)
6135 door2 = door_state & DOOR_ACTION_2;
6137 return (door1 | door2);
6140 if (!(door_state & DOOR_FORCE_REDRAW))
6142 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
6143 door_state &= ~DOOR_OPEN_1;
6144 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
6145 door_state &= ~DOOR_CLOSE_1;
6146 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
6147 door_state &= ~DOOR_OPEN_2;
6148 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
6149 door_state &= ~DOOR_CLOSE_2;
6152 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
6155 // door_delay_value *= 4; // !!! TEST ONLY !!!
6157 if (setup.quick_doors)
6159 stepsize = 20; /* must be chosen to always draw last frame */
6160 door_delay_value = 0;
6163 if (global.autoplay_leveldir)
6165 door_state |= DOOR_NO_DELAY;
6166 door_state &= ~DOOR_CLOSE_ALL;
6170 if (game_status == GAME_MODE_EDITOR)
6171 door_state |= DOOR_NO_DELAY;
6174 if (door_state & DOOR_ACTION)
6177 struct GraphicInfo *g1_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6178 struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6179 struct GraphicInfo *g2_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6180 struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6181 int door_1_left_width = g1_left->width;
6182 int door_1_left_height = g1_left->height;
6183 int door_1_right_width = g1_right->width;
6184 int door_1_right_height = g1_right->height;
6185 int door_2_left_width = g2_left->width;
6186 int door_2_left_height = g2_left->height;
6187 int door_2_right_width = g2_right->width;
6188 int door_2_right_height = g2_right->height;
6189 int door_1_width = MAX(door_1_left_width, door_1_right_width);
6190 int door_1_height = MAX(door_1_left_height, door_1_right_height);
6191 int door_2_width = MAX(door_2_left_width, door_2_right_width);
6192 int door_2_height = MAX(door_2_left_height, door_2_right_height);
6194 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
6195 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
6196 boolean door_1_done = (!handle_door_1);
6197 boolean door_2_done = (!handle_door_2);
6198 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
6199 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
6202 int door_size_1 = (door_1_vertical ? door_1_height : door_1_width);
6203 int door_size_2 = (door_2_vertical ? door_2_height : door_2_width);
6205 int door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6206 int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6209 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
6210 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
6212 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6213 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6214 // int door_size = (handle_door_1 ? door_size_1 : door_size_2);
6215 int door_size = (handle_door_2 ? door_size_2 : door_size_1);
6216 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
6217 int door_skip = max_door_size - door_size;
6218 int end = door_size;
6219 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
6222 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
6224 /* opening door sound has priority over simultaneously closing door */
6225 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
6226 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
6227 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
6228 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
6231 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
6235 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6236 GC gc = bitmap->stored_clip_gc;
6239 if (door_state & DOOR_ACTION_1 &&
6240 x * door_1.step_offset <= door_size_1)
6242 int a = MIN(x * door_1.step_offset, end);
6243 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
6247 int i = p + door_skip;
6251 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6252 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6253 Bitmap *bm_left = g_left->bitmap;
6254 Bitmap *bm_right = g_right->bitmap;
6255 GC gc_left = bm_left->stored_clip_gc;
6256 GC gc_right = bm_right->stored_clip_gc;
6259 int classic_dxsize = 100;
6260 int classic_dysize = 280;
6261 boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
6262 DYSIZE == classic_dysize);
6264 if (door_1.anim_mode & ANIM_STATIC_PANEL)
6266 BlitBitmap(bitmap_db_door, drawto,
6267 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
6268 DXSIZE, DYSIZE, DX, DY);
6272 BlitBitmap(bitmap_db_door, drawto,
6273 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
6274 DXSIZE, DYSIZE - p / 2, DX, DY);
6277 // printf("::: p == %d\n", p);
6278 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
6282 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
6285 int src1_x = g_right->src_x;
6286 int src1_y = g_right->src_y;
6287 int src2_x = g_left->src_x + g_left->width - i;
6288 int src2_y = g_left->src_y;
6289 int dst1_x = DX + DXSIZE - i;
6294 int height = DYSIZE;
6296 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6297 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6300 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6301 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6304 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6305 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6306 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6307 int dst2_x = DX, dst2_y = DY;
6308 int width = i, height = DYSIZE;
6310 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6311 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6314 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6315 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6319 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
6322 int src1_x = g_right->src_x;
6323 int src1_y = g_right->src_y;
6324 int src2_x = g_left->src_x;
6325 int src2_y = g_left->src_y + g_left->height - i;
6327 int dst1_y = DY + DYSIZE - i;
6333 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6334 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6337 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6338 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6341 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6342 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
6343 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
6344 int dst2_x = DX, dst2_y = DY;
6345 int width = DXSIZE, height = i;
6347 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6348 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6351 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6352 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6356 else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */
6358 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
6361 int src1_x = g_right->src_x;
6362 int src1_y = g_right->src_y;
6363 int src2_x = g_left->src_x + g_left->width - i;
6364 int src2_y = g_left->src_y;
6365 int dst1_x = DX + DXSIZE - i;
6370 int height1 = 63, height2 = DYSIZE / 2 - height1;
6371 int ypos1 = 0, ypos2 = height2;
6372 int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
6374 SetClipOrigin(bm_right, gc_right,
6375 dst1_x - src1_x, dst1_y - src1_y + j);
6376 BlitBitmapMasked(bm_right, drawto,
6377 src1_x, src1_y + ypos1, width, height2,
6378 dst1_x, dst1_y + ypos1 + j);
6379 BlitBitmapMasked(bm_right, drawto,
6380 src1_x, src1_y + ypos3, width, height1,
6381 dst1_x, dst1_y + ypos3 + j);
6382 SetClipOrigin(bm_left, gc_left,
6383 dst2_x - src2_x, dst2_y - src2_y - j);
6384 BlitBitmapMasked(bm_left, drawto,
6385 src2_x, src2_y + ypos1 + j, width, height2 - j,
6386 dst2_x, dst2_y + ypos1);
6387 BlitBitmapMasked(bm_left, drawto,
6388 src2_x, src2_y + ypos3, width, height1,
6389 dst2_x, dst2_y + ypos3 - j);
6391 SetClipOrigin(bm_left, gc_left,
6392 dst2_x - src2_x, dst2_y - src2_y - j);
6393 BlitBitmapMasked(bm_left, drawto,
6394 src2_x, src2_y + ypos2, width, height1,
6395 dst2_x, dst2_y + ypos2 - j);
6396 BlitBitmapMasked(bm_left, drawto,
6397 src2_x, src2_y + ypos4, width, height2,
6398 dst2_x, dst2_y + ypos4 - j);
6399 SetClipOrigin(bm_right, gc_right,
6400 dst1_x - src1_x, dst1_y - src1_y + j);
6401 BlitBitmapMasked(bm_right, drawto,
6402 src1_x, src1_y + ypos2, width, height1,
6403 dst1_x, dst1_y + ypos2 + j);
6404 BlitBitmapMasked(bm_right, drawto,
6405 src1_x, src1_y + ypos4, width, height2 - j,
6406 dst1_x, dst1_y + ypos4 + j);
6409 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6410 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6411 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6412 int dst2_x = DX, dst2_y = DY;
6413 int width = i, height = DYSIZE;
6414 int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
6416 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6417 BlitBitmapMasked(bitmap, drawto,
6418 src1_x, src1_y, width, ypos2,
6419 dst1_x, dst1_y + j);
6420 BlitBitmapMasked(bitmap, drawto,
6421 src1_x, src1_y + ypos3, width, ypos1,
6422 dst1_x, dst1_y + ypos3 + j);
6423 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6424 BlitBitmapMasked(bitmap, drawto,
6425 src2_x, src2_y + j, width, ypos2 - j,
6427 BlitBitmapMasked(bitmap, drawto,
6428 src2_x, src2_y + ypos3, width, ypos1,
6429 dst2_x, dst2_y + ypos3 - j);
6431 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6432 BlitBitmapMasked(bitmap, drawto,
6433 src2_x, src2_y + ypos2, width, ypos1,
6434 dst2_x, dst2_y + ypos2 - j);
6435 BlitBitmapMasked(bitmap, drawto,
6436 src2_x, src2_y + ypos4, width, ypos2,
6437 dst2_x, dst2_y + ypos4 - j);
6438 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6439 BlitBitmapMasked(bitmap, drawto,
6440 src1_x, src1_y + ypos2, width, ypos1,
6441 dst1_x, dst1_y + ypos2 + j);
6442 BlitBitmapMasked(bitmap, drawto,
6443 src1_x, src1_y + ypos4, width, ypos2 - j,
6444 dst1_x, dst1_y + ypos4 + j);
6447 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6448 BlitBitmapMasked(bitmap, drawto,
6449 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
6450 DX + DXSIZE - i, DY + j);
6451 BlitBitmapMasked(bitmap, drawto,
6452 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
6453 DX + DXSIZE - i, DY + 140 + j);
6454 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
6455 DY - (DOOR_GFX_PAGEY1 + j));
6456 BlitBitmapMasked(bitmap, drawto,
6457 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
6459 BlitBitmapMasked(bitmap, drawto,
6460 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
6463 BlitBitmapMasked(bitmap, drawto,
6464 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
6466 BlitBitmapMasked(bitmap, drawto,
6467 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
6469 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6470 BlitBitmapMasked(bitmap, drawto,
6471 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
6472 DX + DXSIZE - i, DY + 77 + j);
6473 BlitBitmapMasked(bitmap, drawto,
6474 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
6475 DX + DXSIZE - i, DY + 203 + j);
6480 redraw_mask |= REDRAW_DOOR_1;
6481 door_1_done = (a == end);
6484 if (door_state & DOOR_ACTION_2 &&
6485 x * door_2.step_offset <= door_size_2)
6487 int a = MIN(x * door_2.step_offset, door_size);
6488 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
6489 int i = p + door_skip;
6492 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6493 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6494 Bitmap *bm_left = g_left->bitmap;
6495 Bitmap *bm_right = g_right->bitmap;
6496 GC gc_left = bm_left->stored_clip_gc;
6497 GC gc_right = bm_right->stored_clip_gc;
6500 int classic_vxsize = 100;
6501 int classic_vysize = 100;
6502 boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
6503 VYSIZE == classic_vysize);
6505 if (door_2.anim_mode & ANIM_STATIC_PANEL)
6507 BlitBitmap(bitmap_db_door, drawto,
6508 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
6509 VXSIZE, VYSIZE, VX, VY);
6511 else if (x <= VYSIZE)
6513 BlitBitmap(bitmap_db_door, drawto,
6514 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
6515 VXSIZE, VYSIZE - p / 2, VX, VY);
6517 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
6520 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
6523 int src1_x = g_right->src_x;
6524 int src1_y = g_right->src_y;
6525 int src2_x = g_left->src_x + g_left->width - i;
6526 int src2_y = g_left->src_y;
6527 int dst1_x = VX + VXSIZE - i;
6532 int height = VYSIZE;
6534 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6535 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6538 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6539 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6542 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6543 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6544 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6545 int dst2_x = VX, dst2_y = VY;
6546 int width = i, height = VYSIZE;
6548 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6549 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6552 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6553 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6557 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
6560 int src1_x = g_right->src_x;
6561 int src1_y = g_right->src_y;
6562 int src2_x = g_left->src_x;
6563 int src2_y = g_left->src_y + g_left->height - i;
6565 int dst1_y = VY + VYSIZE - i;
6571 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6572 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6575 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6576 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6579 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6580 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
6581 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
6582 int dst2_x = VX, dst2_y = VY;
6583 int width = VXSIZE, height = i;
6585 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6586 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6589 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6590 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6594 else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */
6596 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
6599 int src1_x = g_right->src_x;
6600 int src1_y = g_right->src_y;
6601 int src2_x = g_left->src_x + g_left->width - i;
6602 int src2_y = g_left->src_y;
6603 int dst1_x = VX + VXSIZE - i;
6608 int height = VYSIZE / 2;
6609 int ypos1 = 0, ypos2 = VYSIZE / 2;
6611 SetClipOrigin(bm_right, gc_right,
6612 dst1_x - src1_x, dst1_y - src1_y + j);
6613 BlitBitmapMasked(bm_right, drawto,
6614 src1_x, src1_y + ypos1, width, height,
6615 dst1_x, dst1_y + ypos1 + j);
6616 SetClipOrigin(bm_left, gc_left,
6617 dst2_x - src2_x, dst2_y - src2_y - j);
6618 BlitBitmapMasked(bm_left, drawto,
6619 src2_x, src2_y + ypos1 + j, width, height - j,
6620 dst2_x, dst2_y + ypos1);
6622 SetClipOrigin(bm_left, gc_left,
6623 dst2_x - src2_x, dst2_y - src2_y - j);
6624 BlitBitmapMasked(bm_left, drawto,
6625 src2_x, src2_y + ypos2, width, height,
6626 dst2_x, dst2_y + ypos2 - j);
6627 SetClipOrigin(bm_right, gc_right,
6628 dst1_x - src1_x, dst1_y - src1_y + j);
6629 BlitBitmapMasked(bm_right, drawto,
6630 src1_x, src1_y + ypos2, width, height - j,
6631 dst1_x, dst1_y + ypos2 + j);
6633 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6634 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6635 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6636 int dst2_x = VX, dst2_y = VY;
6637 int width = i, height = VYSIZE;
6638 int ypos = VYSIZE / 2;
6640 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6641 BlitBitmapMasked(bitmap, drawto,
6642 src1_x, src1_y, width, ypos,
6643 dst1_x, dst1_y + j);
6644 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6645 BlitBitmapMasked(bitmap, drawto,
6646 src2_x, src2_y + j, width, ypos - j,
6649 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6650 BlitBitmapMasked(bitmap, drawto,
6651 src2_x, src2_y + ypos, width, ypos,
6652 dst2_x, dst2_y + ypos - j);
6653 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6654 BlitBitmapMasked(bitmap, drawto,
6655 src1_x, src1_y + ypos, width, ypos - j,
6656 dst1_x, dst1_y + ypos + j);
6659 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6660 BlitBitmapMasked(bitmap, drawto,
6661 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
6662 VX + VXSIZE - i, VY + j);
6663 SetClipOrigin(bitmap, gc,
6664 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
6665 BlitBitmapMasked(bitmap, drawto,
6666 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
6669 BlitBitmapMasked(bitmap, drawto,
6670 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6671 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
6672 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6673 BlitBitmapMasked(bitmap, drawto,
6674 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6676 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
6681 redraw_mask |= REDRAW_DOOR_2;
6682 door_2_done = (a == VXSIZE);
6685 if (!(door_state & DOOR_NO_DELAY))
6689 if (game_status == GAME_MODE_MAIN)
6692 WaitUntilDelayReached(&door_delay, door_delay_value);
6697 if (door_state & DOOR_ACTION_1)
6698 door1 = door_state & DOOR_ACTION_1;
6699 if (door_state & DOOR_ACTION_2)
6700 door2 = door_state & DOOR_ACTION_2;
6702 return (door1 | door2);
6707 void DrawSpecialEditorDoor()
6710 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6711 int top_border_width = gfx1->width;
6712 int top_border_height = gfx1->height;
6713 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6714 int ex = EX - outer_border;
6715 int ey = EY - outer_border;
6716 int vy = VY - outer_border;
6717 int exsize = EXSIZE + 2 * outer_border;
6719 CloseDoor(DOOR_CLOSE_2);
6721 /* draw bigger level editor toolbox window */
6722 BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
6723 top_border_width, top_border_height, ex, ey - top_border_height);
6724 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
6725 exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
6727 /* draw bigger level editor toolbox window */
6728 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
6729 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
6731 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6732 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
6736 redraw_mask |= REDRAW_ALL;
6739 void UndrawSpecialEditorDoor()
6742 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6743 int top_border_width = gfx1->width;
6744 int top_border_height = gfx1->height;
6745 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6746 int ex = EX - outer_border;
6747 int ey = EY - outer_border;
6748 int ey_top = ey - top_border_height;
6749 int exsize = EXSIZE + 2 * outer_border;
6750 int eysize = EYSIZE + 2 * outer_border;
6752 /* draw normal tape recorder window */
6753 if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
6755 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6756 ex, ey_top, top_border_width, top_border_height,
6758 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6759 ex, ey, exsize, eysize, ex, ey);
6763 // if screen background is set to "[NONE]", clear editor toolbox window
6764 ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
6765 ClearRectangle(drawto, ex, ey, exsize, eysize);
6768 /* draw normal tape recorder window */
6769 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6770 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
6774 redraw_mask |= REDRAW_ALL;
6778 /* ---------- new tool button stuff ---------------------------------------- */
6785 struct TextPosInfo *pos;
6788 } toolbutton_info[NUM_TOOL_BUTTONS] =
6791 IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
6792 TOOL_CTRL_ID_YES, "yes"
6795 IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
6796 TOOL_CTRL_ID_NO, "no"
6799 IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
6800 TOOL_CTRL_ID_CONFIRM, "confirm"
6803 IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
6804 TOOL_CTRL_ID_PLAYER_1, "player 1"
6807 IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
6808 TOOL_CTRL_ID_PLAYER_2, "player 2"
6811 IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
6812 TOOL_CTRL_ID_PLAYER_3, "player 3"
6815 IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
6816 TOOL_CTRL_ID_PLAYER_4, "player 4"
6820 void CreateToolButtons()
6824 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6826 struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
6827 struct TextPosInfo *pos = toolbutton_info[i].pos;
6828 struct GadgetInfo *gi;
6829 Bitmap *deco_bitmap = None;
6830 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6831 unsigned int event_mask = GD_EVENT_RELEASED;
6834 int gd_x = gfx->src_x;
6835 int gd_y = gfx->src_y;
6836 int gd_xp = gfx->src_x + gfx->pressed_xoffset;
6837 int gd_yp = gfx->src_y + gfx->pressed_yoffset;
6840 if (global.use_envelope_request)
6841 setRequestPosition(&dx, &dy, TRUE);
6843 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6845 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6847 getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
6848 pos->size, &deco_bitmap, &deco_x, &deco_y);
6849 deco_xpos = (gfx->width - pos->size) / 2;
6850 deco_ypos = (gfx->height - pos->size) / 2;
6853 gi = CreateGadget(GDI_CUSTOM_ID, id,
6854 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6855 GDI_X, dx + GDI_ACTIVE_POS(pos->x),
6856 GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
6857 GDI_WIDTH, gfx->width,
6858 GDI_HEIGHT, gfx->height,
6859 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6860 GDI_STATE, GD_BUTTON_UNPRESSED,
6861 GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
6862 GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
6863 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6864 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6865 GDI_DECORATION_SIZE, pos->size, pos->size,
6866 GDI_DECORATION_SHIFTING, 1, 1,
6867 GDI_DIRECT_DRAW, FALSE,
6868 GDI_EVENT_MASK, event_mask,
6869 GDI_CALLBACK_ACTION, HandleToolButtons,
6873 Error(ERR_EXIT, "cannot create gadget");
6875 tool_gadget[id] = gi;
6881 /* graphic position values for tool buttons */
6882 #define TOOL_BUTTON_YES_XPOS 2
6883 #define TOOL_BUTTON_YES_YPOS 250
6884 #define TOOL_BUTTON_YES_GFX_YPOS 0
6885 #define TOOL_BUTTON_YES_XSIZE 46
6886 #define TOOL_BUTTON_YES_YSIZE 28
6887 #define TOOL_BUTTON_NO_XPOS 52
6888 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
6889 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
6890 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
6891 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
6892 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
6893 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
6894 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
6895 #define TOOL_BUTTON_CONFIRM_XSIZE 96
6896 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
6897 #define TOOL_BUTTON_PLAYER_XSIZE 30
6898 #define TOOL_BUTTON_PLAYER_YSIZE 30
6899 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
6900 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
6901 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
6902 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
6903 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6904 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6905 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6906 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6907 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6908 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6909 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6910 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6911 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6912 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6913 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6914 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6915 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6916 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6917 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6918 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6927 } toolbutton_info[NUM_TOOL_BUTTONS] =
6930 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
6931 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
6932 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
6937 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
6938 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
6939 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
6944 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
6945 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
6946 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
6947 TOOL_CTRL_ID_CONFIRM,
6951 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6952 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
6953 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6954 TOOL_CTRL_ID_PLAYER_1,
6958 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6959 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
6960 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6961 TOOL_CTRL_ID_PLAYER_2,
6965 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6966 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
6967 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6968 TOOL_CTRL_ID_PLAYER_3,
6972 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6973 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
6974 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6975 TOOL_CTRL_ID_PLAYER_4,
6980 void CreateToolButtons()
6984 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6986 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6987 Bitmap *deco_bitmap = None;
6988 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6989 struct GadgetInfo *gi;
6990 unsigned int event_mask;
6991 int gd_xoffset, gd_yoffset;
6992 int gd_x1, gd_x2, gd_y;
6995 event_mask = GD_EVENT_RELEASED;
6997 gd_xoffset = toolbutton_info[i].xpos;
6998 gd_yoffset = toolbutton_info[i].ypos;
6999 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
7000 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
7001 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
7003 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
7005 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
7007 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
7008 &deco_bitmap, &deco_x, &deco_y);
7009 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
7010 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
7013 gi = CreateGadget(GDI_CUSTOM_ID, id,
7014 GDI_INFO_TEXT, toolbutton_info[i].infotext,
7015 GDI_X, DX + GDI_ACTIVE_POS(toolbutton_info[i].x),
7016 GDI_Y, DY + GDI_ACTIVE_POS(toolbutton_info[i].y),
7017 GDI_WIDTH, toolbutton_info[i].width,
7018 GDI_HEIGHT, toolbutton_info[i].height,
7019 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
7020 GDI_STATE, GD_BUTTON_UNPRESSED,
7021 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
7022 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
7023 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
7024 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
7025 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
7026 GDI_DECORATION_SHIFTING, 1, 1,
7027 GDI_DIRECT_DRAW, FALSE,
7028 GDI_EVENT_MASK, event_mask,
7029 GDI_CALLBACK_ACTION, HandleToolButtons,
7033 Error(ERR_EXIT, "cannot create gadget");
7035 tool_gadget[id] = gi;
7041 void FreeToolButtons()
7045 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7046 FreeGadget(tool_gadget[i]);
7049 static void UnmapToolButtons()
7053 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7054 UnmapGadget(tool_gadget[i]);
7057 static void HandleToolButtons(struct GadgetInfo *gi)
7059 request_gadget_id = gi->custom_id;
7062 static struct Mapping_EM_to_RND_object
7065 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
7066 boolean is_backside; /* backside of moving element */
7072 em_object_mapping_list[] =
7075 Xblank, TRUE, FALSE,
7079 Yacid_splash_eB, FALSE, FALSE,
7080 EL_ACID_SPLASH_RIGHT, -1, -1
7083 Yacid_splash_wB, FALSE, FALSE,
7084 EL_ACID_SPLASH_LEFT, -1, -1
7087 #ifdef EM_ENGINE_BAD_ROLL
7089 Xstone_force_e, FALSE, FALSE,
7090 EL_ROCK, -1, MV_BIT_RIGHT
7093 Xstone_force_w, FALSE, FALSE,
7094 EL_ROCK, -1, MV_BIT_LEFT
7097 Xnut_force_e, FALSE, FALSE,
7098 EL_NUT, -1, MV_BIT_RIGHT
7101 Xnut_force_w, FALSE, FALSE,
7102 EL_NUT, -1, MV_BIT_LEFT
7105 Xspring_force_e, FALSE, FALSE,
7106 EL_SPRING, -1, MV_BIT_RIGHT
7109 Xspring_force_w, FALSE, FALSE,
7110 EL_SPRING, -1, MV_BIT_LEFT
7113 Xemerald_force_e, FALSE, FALSE,
7114 EL_EMERALD, -1, MV_BIT_RIGHT
7117 Xemerald_force_w, FALSE, FALSE,
7118 EL_EMERALD, -1, MV_BIT_LEFT
7121 Xdiamond_force_e, FALSE, FALSE,
7122 EL_DIAMOND, -1, MV_BIT_RIGHT
7125 Xdiamond_force_w, FALSE, FALSE,
7126 EL_DIAMOND, -1, MV_BIT_LEFT
7129 Xbomb_force_e, FALSE, FALSE,
7130 EL_BOMB, -1, MV_BIT_RIGHT
7133 Xbomb_force_w, FALSE, FALSE,
7134 EL_BOMB, -1, MV_BIT_LEFT
7136 #endif /* EM_ENGINE_BAD_ROLL */
7139 Xstone, TRUE, FALSE,
7143 Xstone_pause, FALSE, FALSE,
7147 Xstone_fall, FALSE, FALSE,
7151 Ystone_s, FALSE, FALSE,
7152 EL_ROCK, ACTION_FALLING, -1
7155 Ystone_sB, FALSE, TRUE,
7156 EL_ROCK, ACTION_FALLING, -1
7159 Ystone_e, FALSE, FALSE,
7160 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7163 Ystone_eB, FALSE, TRUE,
7164 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7167 Ystone_w, FALSE, FALSE,
7168 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7171 Ystone_wB, FALSE, TRUE,
7172 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7179 Xnut_pause, FALSE, FALSE,
7183 Xnut_fall, FALSE, FALSE,
7187 Ynut_s, FALSE, FALSE,
7188 EL_NUT, ACTION_FALLING, -1
7191 Ynut_sB, FALSE, TRUE,
7192 EL_NUT, ACTION_FALLING, -1
7195 Ynut_e, FALSE, FALSE,
7196 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7199 Ynut_eB, FALSE, TRUE,
7200 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7203 Ynut_w, FALSE, FALSE,
7204 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7207 Ynut_wB, FALSE, TRUE,
7208 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7211 Xbug_n, TRUE, FALSE,
7215 Xbug_e, TRUE, FALSE,
7216 EL_BUG_RIGHT, -1, -1
7219 Xbug_s, TRUE, FALSE,
7223 Xbug_w, TRUE, FALSE,
7227 Xbug_gon, FALSE, FALSE,
7231 Xbug_goe, FALSE, FALSE,
7232 EL_BUG_RIGHT, -1, -1
7235 Xbug_gos, FALSE, FALSE,
7239 Xbug_gow, FALSE, FALSE,
7243 Ybug_n, FALSE, FALSE,
7244 EL_BUG, ACTION_MOVING, MV_BIT_UP
7247 Ybug_nB, FALSE, TRUE,
7248 EL_BUG, ACTION_MOVING, MV_BIT_UP
7251 Ybug_e, FALSE, FALSE,
7252 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7255 Ybug_eB, FALSE, TRUE,
7256 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7259 Ybug_s, FALSE, FALSE,
7260 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7263 Ybug_sB, FALSE, TRUE,
7264 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7267 Ybug_w, FALSE, FALSE,
7268 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7271 Ybug_wB, FALSE, TRUE,
7272 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7275 Ybug_w_n, FALSE, FALSE,
7276 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7279 Ybug_n_e, FALSE, FALSE,
7280 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7283 Ybug_e_s, FALSE, FALSE,
7284 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7287 Ybug_s_w, FALSE, FALSE,
7288 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7291 Ybug_e_n, FALSE, FALSE,
7292 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7295 Ybug_s_e, FALSE, FALSE,
7296 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7299 Ybug_w_s, FALSE, FALSE,
7300 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7303 Ybug_n_w, FALSE, FALSE,
7304 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7307 Ybug_stone, FALSE, FALSE,
7308 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
7311 Ybug_spring, FALSE, FALSE,
7312 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
7315 Xtank_n, TRUE, FALSE,
7316 EL_SPACESHIP_UP, -1, -1
7319 Xtank_e, TRUE, FALSE,
7320 EL_SPACESHIP_RIGHT, -1, -1
7323 Xtank_s, TRUE, FALSE,
7324 EL_SPACESHIP_DOWN, -1, -1
7327 Xtank_w, TRUE, FALSE,
7328 EL_SPACESHIP_LEFT, -1, -1
7331 Xtank_gon, FALSE, FALSE,
7332 EL_SPACESHIP_UP, -1, -1
7335 Xtank_goe, FALSE, FALSE,
7336 EL_SPACESHIP_RIGHT, -1, -1
7339 Xtank_gos, FALSE, FALSE,
7340 EL_SPACESHIP_DOWN, -1, -1
7343 Xtank_gow, FALSE, FALSE,
7344 EL_SPACESHIP_LEFT, -1, -1
7347 Ytank_n, FALSE, FALSE,
7348 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7351 Ytank_nB, FALSE, TRUE,
7352 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7355 Ytank_e, FALSE, FALSE,
7356 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7359 Ytank_eB, FALSE, TRUE,
7360 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7363 Ytank_s, FALSE, FALSE,
7364 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7367 Ytank_sB, FALSE, TRUE,
7368 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7371 Ytank_w, FALSE, FALSE,
7372 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7375 Ytank_wB, FALSE, TRUE,
7376 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7379 Ytank_w_n, FALSE, FALSE,
7380 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7383 Ytank_n_e, FALSE, FALSE,
7384 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7387 Ytank_e_s, FALSE, FALSE,
7388 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7391 Ytank_s_w, FALSE, FALSE,
7392 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7395 Ytank_e_n, FALSE, FALSE,
7396 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7399 Ytank_s_e, FALSE, FALSE,
7400 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7403 Ytank_w_s, FALSE, FALSE,
7404 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7407 Ytank_n_w, FALSE, FALSE,
7408 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7411 Ytank_stone, FALSE, FALSE,
7412 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
7415 Ytank_spring, FALSE, FALSE,
7416 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
7419 Xandroid, TRUE, FALSE,
7420 EL_EMC_ANDROID, ACTION_ACTIVE, -1
7423 Xandroid_1_n, FALSE, FALSE,
7424 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7427 Xandroid_2_n, FALSE, FALSE,
7428 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7431 Xandroid_1_e, FALSE, FALSE,
7432 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7435 Xandroid_2_e, FALSE, FALSE,
7436 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7439 Xandroid_1_w, FALSE, FALSE,
7440 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7443 Xandroid_2_w, FALSE, FALSE,
7444 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7447 Xandroid_1_s, FALSE, FALSE,
7448 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7451 Xandroid_2_s, FALSE, FALSE,
7452 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7455 Yandroid_n, FALSE, FALSE,
7456 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7459 Yandroid_nB, FALSE, TRUE,
7460 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7463 Yandroid_ne, FALSE, FALSE,
7464 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
7467 Yandroid_neB, FALSE, TRUE,
7468 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
7471 Yandroid_e, FALSE, FALSE,
7472 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7475 Yandroid_eB, FALSE, TRUE,
7476 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7479 Yandroid_se, FALSE, FALSE,
7480 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
7483 Yandroid_seB, FALSE, TRUE,
7484 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
7487 Yandroid_s, FALSE, FALSE,
7488 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7491 Yandroid_sB, FALSE, TRUE,
7492 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7495 Yandroid_sw, FALSE, FALSE,
7496 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
7499 Yandroid_swB, FALSE, TRUE,
7500 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
7503 Yandroid_w, FALSE, FALSE,
7504 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7507 Yandroid_wB, FALSE, TRUE,
7508 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7511 Yandroid_nw, FALSE, FALSE,
7512 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
7515 Yandroid_nwB, FALSE, TRUE,
7516 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
7519 Xspring, TRUE, FALSE,
7523 Xspring_pause, FALSE, FALSE,
7527 Xspring_e, FALSE, FALSE,
7531 Xspring_w, FALSE, FALSE,
7535 Xspring_fall, FALSE, FALSE,
7539 Yspring_s, FALSE, FALSE,
7540 EL_SPRING, ACTION_FALLING, -1
7543 Yspring_sB, FALSE, TRUE,
7544 EL_SPRING, ACTION_FALLING, -1
7547 Yspring_e, FALSE, FALSE,
7548 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7551 Yspring_eB, FALSE, TRUE,
7552 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7555 Yspring_w, FALSE, FALSE,
7556 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7559 Yspring_wB, FALSE, TRUE,
7560 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7563 Yspring_kill_e, FALSE, FALSE,
7564 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7567 Yspring_kill_eB, FALSE, TRUE,
7568 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7571 Yspring_kill_w, FALSE, FALSE,
7572 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7575 Yspring_kill_wB, FALSE, TRUE,
7576 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7579 Xeater_n, TRUE, FALSE,
7580 EL_YAMYAM_UP, -1, -1
7583 Xeater_e, TRUE, FALSE,
7584 EL_YAMYAM_RIGHT, -1, -1
7587 Xeater_w, TRUE, FALSE,
7588 EL_YAMYAM_LEFT, -1, -1
7591 Xeater_s, TRUE, FALSE,
7592 EL_YAMYAM_DOWN, -1, -1
7595 Yeater_n, FALSE, FALSE,
7596 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7599 Yeater_nB, FALSE, TRUE,
7600 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7603 Yeater_e, FALSE, FALSE,
7604 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7607 Yeater_eB, FALSE, TRUE,
7608 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7611 Yeater_s, FALSE, FALSE,
7612 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7615 Yeater_sB, FALSE, TRUE,
7616 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7619 Yeater_w, FALSE, FALSE,
7620 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7623 Yeater_wB, FALSE, TRUE,
7624 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7627 Yeater_stone, FALSE, FALSE,
7628 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
7631 Yeater_spring, FALSE, FALSE,
7632 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
7635 Xalien, TRUE, FALSE,
7639 Xalien_pause, FALSE, FALSE,
7643 Yalien_n, FALSE, FALSE,
7644 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7647 Yalien_nB, FALSE, TRUE,
7648 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7651 Yalien_e, FALSE, FALSE,
7652 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7655 Yalien_eB, FALSE, TRUE,
7656 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7659 Yalien_s, FALSE, FALSE,
7660 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7663 Yalien_sB, FALSE, TRUE,
7664 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7667 Yalien_w, FALSE, FALSE,
7668 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7671 Yalien_wB, FALSE, TRUE,
7672 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7675 Yalien_stone, FALSE, FALSE,
7676 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
7679 Yalien_spring, FALSE, FALSE,
7680 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
7683 Xemerald, TRUE, FALSE,
7687 Xemerald_pause, FALSE, FALSE,
7691 Xemerald_fall, FALSE, FALSE,
7695 Xemerald_shine, FALSE, FALSE,
7696 EL_EMERALD, ACTION_TWINKLING, -1
7699 Yemerald_s, FALSE, FALSE,
7700 EL_EMERALD, ACTION_FALLING, -1
7703 Yemerald_sB, FALSE, TRUE,
7704 EL_EMERALD, ACTION_FALLING, -1
7707 Yemerald_e, FALSE, FALSE,
7708 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7711 Yemerald_eB, FALSE, TRUE,
7712 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7715 Yemerald_w, FALSE, FALSE,
7716 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7719 Yemerald_wB, FALSE, TRUE,
7720 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7723 Yemerald_eat, FALSE, FALSE,
7724 EL_EMERALD, ACTION_COLLECTING, -1
7727 Yemerald_stone, FALSE, FALSE,
7728 EL_NUT, ACTION_BREAKING, -1
7731 Xdiamond, TRUE, FALSE,
7735 Xdiamond_pause, FALSE, FALSE,
7739 Xdiamond_fall, FALSE, FALSE,
7743 Xdiamond_shine, FALSE, FALSE,
7744 EL_DIAMOND, ACTION_TWINKLING, -1
7747 Ydiamond_s, FALSE, FALSE,
7748 EL_DIAMOND, ACTION_FALLING, -1
7751 Ydiamond_sB, FALSE, TRUE,
7752 EL_DIAMOND, ACTION_FALLING, -1
7755 Ydiamond_e, FALSE, FALSE,
7756 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7759 Ydiamond_eB, FALSE, TRUE,
7760 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7763 Ydiamond_w, FALSE, FALSE,
7764 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7767 Ydiamond_wB, FALSE, TRUE,
7768 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7771 Ydiamond_eat, FALSE, FALSE,
7772 EL_DIAMOND, ACTION_COLLECTING, -1
7775 Ydiamond_stone, FALSE, FALSE,
7776 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
7779 Xdrip_fall, TRUE, FALSE,
7780 EL_AMOEBA_DROP, -1, -1
7783 Xdrip_stretch, FALSE, FALSE,
7784 EL_AMOEBA_DROP, ACTION_FALLING, -1
7787 Xdrip_stretchB, FALSE, TRUE,
7788 EL_AMOEBA_DROP, ACTION_FALLING, -1
7791 Xdrip_eat, FALSE, FALSE,
7792 EL_AMOEBA_DROP, ACTION_GROWING, -1
7795 Ydrip_s1, FALSE, FALSE,
7796 EL_AMOEBA_DROP, ACTION_FALLING, -1
7799 Ydrip_s1B, FALSE, TRUE,
7800 EL_AMOEBA_DROP, ACTION_FALLING, -1
7803 Ydrip_s2, FALSE, FALSE,
7804 EL_AMOEBA_DROP, ACTION_FALLING, -1
7807 Ydrip_s2B, FALSE, TRUE,
7808 EL_AMOEBA_DROP, ACTION_FALLING, -1
7815 Xbomb_pause, FALSE, FALSE,
7819 Xbomb_fall, FALSE, FALSE,
7823 Ybomb_s, FALSE, FALSE,
7824 EL_BOMB, ACTION_FALLING, -1
7827 Ybomb_sB, FALSE, TRUE,
7828 EL_BOMB, ACTION_FALLING, -1
7831 Ybomb_e, FALSE, FALSE,
7832 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7835 Ybomb_eB, FALSE, TRUE,
7836 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7839 Ybomb_w, FALSE, FALSE,
7840 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7843 Ybomb_wB, FALSE, TRUE,
7844 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7847 Ybomb_eat, FALSE, FALSE,
7848 EL_BOMB, ACTION_ACTIVATING, -1
7851 Xballoon, TRUE, FALSE,
7855 Yballoon_n, FALSE, FALSE,
7856 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7859 Yballoon_nB, FALSE, TRUE,
7860 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7863 Yballoon_e, FALSE, FALSE,
7864 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7867 Yballoon_eB, FALSE, TRUE,
7868 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7871 Yballoon_s, FALSE, FALSE,
7872 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7875 Yballoon_sB, FALSE, TRUE,
7876 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7879 Yballoon_w, FALSE, FALSE,
7880 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7883 Yballoon_wB, FALSE, TRUE,
7884 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7887 Xgrass, TRUE, FALSE,
7888 EL_EMC_GRASS, -1, -1
7891 Ygrass_nB, FALSE, FALSE,
7892 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
7895 Ygrass_eB, FALSE, FALSE,
7896 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
7899 Ygrass_sB, FALSE, FALSE,
7900 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
7903 Ygrass_wB, FALSE, FALSE,
7904 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
7911 Ydirt_nB, FALSE, FALSE,
7912 EL_SAND, ACTION_DIGGING, MV_BIT_UP
7915 Ydirt_eB, FALSE, FALSE,
7916 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
7919 Ydirt_sB, FALSE, FALSE,
7920 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
7923 Ydirt_wB, FALSE, FALSE,
7924 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
7927 Xacid_ne, TRUE, FALSE,
7928 EL_ACID_POOL_TOPRIGHT, -1, -1
7931 Xacid_se, TRUE, FALSE,
7932 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
7935 Xacid_s, TRUE, FALSE,
7936 EL_ACID_POOL_BOTTOM, -1, -1
7939 Xacid_sw, TRUE, FALSE,
7940 EL_ACID_POOL_BOTTOMLEFT, -1, -1
7943 Xacid_nw, TRUE, FALSE,
7944 EL_ACID_POOL_TOPLEFT, -1, -1
7947 Xacid_1, TRUE, FALSE,
7951 Xacid_2, FALSE, FALSE,
7955 Xacid_3, FALSE, FALSE,
7959 Xacid_4, FALSE, FALSE,
7963 Xacid_5, FALSE, FALSE,
7967 Xacid_6, FALSE, FALSE,
7971 Xacid_7, FALSE, FALSE,
7975 Xacid_8, FALSE, FALSE,
7979 Xball_1, TRUE, FALSE,
7980 EL_EMC_MAGIC_BALL, -1, -1
7983 Xball_1B, FALSE, FALSE,
7984 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7987 Xball_2, FALSE, FALSE,
7988 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7991 Xball_2B, FALSE, FALSE,
7992 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7995 Yball_eat, FALSE, FALSE,
7996 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
7999 Ykey_1_eat, FALSE, FALSE,
8000 EL_EM_KEY_1, ACTION_COLLECTING, -1
8003 Ykey_2_eat, FALSE, FALSE,
8004 EL_EM_KEY_2, ACTION_COLLECTING, -1
8007 Ykey_3_eat, FALSE, FALSE,
8008 EL_EM_KEY_3, ACTION_COLLECTING, -1
8011 Ykey_4_eat, FALSE, FALSE,
8012 EL_EM_KEY_4, ACTION_COLLECTING, -1
8015 Ykey_5_eat, FALSE, FALSE,
8016 EL_EMC_KEY_5, ACTION_COLLECTING, -1
8019 Ykey_6_eat, FALSE, FALSE,
8020 EL_EMC_KEY_6, ACTION_COLLECTING, -1
8023 Ykey_7_eat, FALSE, FALSE,
8024 EL_EMC_KEY_7, ACTION_COLLECTING, -1
8027 Ykey_8_eat, FALSE, FALSE,
8028 EL_EMC_KEY_8, ACTION_COLLECTING, -1
8031 Ylenses_eat, FALSE, FALSE,
8032 EL_EMC_LENSES, ACTION_COLLECTING, -1
8035 Ymagnify_eat, FALSE, FALSE,
8036 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
8039 Ygrass_eat, FALSE, FALSE,
8040 EL_EMC_GRASS, ACTION_SNAPPING, -1
8043 Ydirt_eat, FALSE, FALSE,
8044 EL_SAND, ACTION_SNAPPING, -1
8047 Xgrow_ns, TRUE, FALSE,
8048 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
8051 Ygrow_ns_eat, FALSE, FALSE,
8052 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
8055 Xgrow_ew, TRUE, FALSE,
8056 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
8059 Ygrow_ew_eat, FALSE, FALSE,
8060 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
8063 Xwonderwall, TRUE, FALSE,
8064 EL_MAGIC_WALL, -1, -1
8067 XwonderwallB, FALSE, FALSE,
8068 EL_MAGIC_WALL, ACTION_ACTIVE, -1
8071 Xamoeba_1, TRUE, FALSE,
8072 EL_AMOEBA_DRY, ACTION_OTHER, -1
8075 Xamoeba_2, FALSE, FALSE,
8076 EL_AMOEBA_DRY, ACTION_OTHER, -1
8079 Xamoeba_3, FALSE, FALSE,
8080 EL_AMOEBA_DRY, ACTION_OTHER, -1
8083 Xamoeba_4, FALSE, FALSE,
8084 EL_AMOEBA_DRY, ACTION_OTHER, -1
8087 Xamoeba_5, TRUE, FALSE,
8088 EL_AMOEBA_WET, ACTION_OTHER, -1
8091 Xamoeba_6, FALSE, FALSE,
8092 EL_AMOEBA_WET, ACTION_OTHER, -1
8095 Xamoeba_7, FALSE, FALSE,
8096 EL_AMOEBA_WET, ACTION_OTHER, -1
8099 Xamoeba_8, FALSE, FALSE,
8100 EL_AMOEBA_WET, ACTION_OTHER, -1
8103 Xdoor_1, TRUE, FALSE,
8104 EL_EM_GATE_1, -1, -1
8107 Xdoor_2, TRUE, FALSE,
8108 EL_EM_GATE_2, -1, -1
8111 Xdoor_3, TRUE, FALSE,
8112 EL_EM_GATE_3, -1, -1
8115 Xdoor_4, TRUE, FALSE,
8116 EL_EM_GATE_4, -1, -1
8119 Xdoor_5, TRUE, FALSE,
8120 EL_EMC_GATE_5, -1, -1
8123 Xdoor_6, TRUE, FALSE,
8124 EL_EMC_GATE_6, -1, -1
8127 Xdoor_7, TRUE, FALSE,
8128 EL_EMC_GATE_7, -1, -1
8131 Xdoor_8, TRUE, FALSE,
8132 EL_EMC_GATE_8, -1, -1
8135 Xkey_1, TRUE, FALSE,
8139 Xkey_2, TRUE, FALSE,
8143 Xkey_3, TRUE, FALSE,
8147 Xkey_4, TRUE, FALSE,
8151 Xkey_5, TRUE, FALSE,
8152 EL_EMC_KEY_5, -1, -1
8155 Xkey_6, TRUE, FALSE,
8156 EL_EMC_KEY_6, -1, -1
8159 Xkey_7, TRUE, FALSE,
8160 EL_EMC_KEY_7, -1, -1
8163 Xkey_8, TRUE, FALSE,
8164 EL_EMC_KEY_8, -1, -1
8167 Xwind_n, TRUE, FALSE,
8168 EL_BALLOON_SWITCH_UP, -1, -1
8171 Xwind_e, TRUE, FALSE,
8172 EL_BALLOON_SWITCH_RIGHT, -1, -1
8175 Xwind_s, TRUE, FALSE,
8176 EL_BALLOON_SWITCH_DOWN, -1, -1
8179 Xwind_w, TRUE, FALSE,
8180 EL_BALLOON_SWITCH_LEFT, -1, -1
8183 Xwind_nesw, TRUE, FALSE,
8184 EL_BALLOON_SWITCH_ANY, -1, -1
8187 Xwind_stop, TRUE, FALSE,
8188 EL_BALLOON_SWITCH_NONE, -1, -1
8192 EL_EM_EXIT_CLOSED, -1, -1
8195 Xexit_1, TRUE, FALSE,
8196 EL_EM_EXIT_OPEN, -1, -1
8199 Xexit_2, FALSE, FALSE,
8200 EL_EM_EXIT_OPEN, -1, -1
8203 Xexit_3, FALSE, FALSE,
8204 EL_EM_EXIT_OPEN, -1, -1
8207 Xdynamite, TRUE, FALSE,
8208 EL_EM_DYNAMITE, -1, -1
8211 Ydynamite_eat, FALSE, FALSE,
8212 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
8215 Xdynamite_1, TRUE, FALSE,
8216 EL_EM_DYNAMITE_ACTIVE, -1, -1
8219 Xdynamite_2, FALSE, FALSE,
8220 EL_EM_DYNAMITE_ACTIVE, -1, -1
8223 Xdynamite_3, FALSE, FALSE,
8224 EL_EM_DYNAMITE_ACTIVE, -1, -1
8227 Xdynamite_4, FALSE, FALSE,
8228 EL_EM_DYNAMITE_ACTIVE, -1, -1
8231 Xbumper, TRUE, FALSE,
8232 EL_EMC_SPRING_BUMPER, -1, -1
8235 XbumperB, FALSE, FALSE,
8236 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
8239 Xwheel, TRUE, FALSE,
8240 EL_ROBOT_WHEEL, -1, -1
8243 XwheelB, FALSE, FALSE,
8244 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
8247 Xswitch, TRUE, FALSE,
8248 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
8251 XswitchB, FALSE, FALSE,
8252 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
8256 EL_QUICKSAND_EMPTY, -1, -1
8259 Xsand_stone, TRUE, FALSE,
8260 EL_QUICKSAND_FULL, -1, -1
8263 Xsand_stonein_1, FALSE, TRUE,
8264 EL_ROCK, ACTION_FILLING, -1
8267 Xsand_stonein_2, FALSE, TRUE,
8268 EL_ROCK, ACTION_FILLING, -1
8271 Xsand_stonein_3, FALSE, TRUE,
8272 EL_ROCK, ACTION_FILLING, -1
8275 Xsand_stonein_4, FALSE, TRUE,
8276 EL_ROCK, ACTION_FILLING, -1
8280 Xsand_stonesand_1, FALSE, FALSE,
8281 EL_QUICKSAND_EMPTYING, -1, -1
8284 Xsand_stonesand_2, FALSE, FALSE,
8285 EL_QUICKSAND_EMPTYING, -1, -1
8288 Xsand_stonesand_3, FALSE, FALSE,
8289 EL_QUICKSAND_EMPTYING, -1, -1
8292 Xsand_stonesand_4, FALSE, FALSE,
8293 EL_QUICKSAND_EMPTYING, -1, -1
8296 Xsand_stonesand_quickout_1, FALSE, FALSE,
8297 EL_QUICKSAND_EMPTYING, -1, -1
8300 Xsand_stonesand_quickout_2, FALSE, FALSE,
8301 EL_QUICKSAND_EMPTYING, -1, -1
8305 Xsand_stonesand_1, FALSE, FALSE,
8306 EL_QUICKSAND_FULL, -1, -1
8309 Xsand_stonesand_2, FALSE, FALSE,
8310 EL_QUICKSAND_FULL, -1, -1
8313 Xsand_stonesand_3, FALSE, FALSE,
8314 EL_QUICKSAND_FULL, -1, -1
8317 Xsand_stonesand_4, FALSE, FALSE,
8318 EL_QUICKSAND_FULL, -1, -1
8322 Xsand_stoneout_1, FALSE, FALSE,
8323 EL_ROCK, ACTION_EMPTYING, -1
8326 Xsand_stoneout_2, FALSE, FALSE,
8327 EL_ROCK, ACTION_EMPTYING, -1
8331 Xsand_sandstone_1, FALSE, FALSE,
8332 EL_QUICKSAND_FILLING, -1, -1
8335 Xsand_sandstone_2, FALSE, FALSE,
8336 EL_QUICKSAND_FILLING, -1, -1
8339 Xsand_sandstone_3, FALSE, FALSE,
8340 EL_QUICKSAND_FILLING, -1, -1
8343 Xsand_sandstone_4, FALSE, FALSE,
8344 EL_QUICKSAND_FILLING, -1, -1
8348 Xsand_sandstone_1, FALSE, FALSE,
8349 EL_QUICKSAND_FULL, -1, -1
8352 Xsand_sandstone_2, FALSE, FALSE,
8353 EL_QUICKSAND_FULL, -1, -1
8356 Xsand_sandstone_3, FALSE, FALSE,
8357 EL_QUICKSAND_FULL, -1, -1
8360 Xsand_sandstone_4, FALSE, FALSE,
8361 EL_QUICKSAND_FULL, -1, -1
8365 Xplant, TRUE, FALSE,
8366 EL_EMC_PLANT, -1, -1
8369 Yplant, FALSE, FALSE,
8370 EL_EMC_PLANT, -1, -1
8373 Xlenses, TRUE, FALSE,
8374 EL_EMC_LENSES, -1, -1
8377 Xmagnify, TRUE, FALSE,
8378 EL_EMC_MAGNIFIER, -1, -1
8381 Xdripper, TRUE, FALSE,
8382 EL_EMC_DRIPPER, -1, -1
8385 XdripperB, FALSE, FALSE,
8386 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
8389 Xfake_blank, TRUE, FALSE,
8390 EL_INVISIBLE_WALL, -1, -1
8393 Xfake_blankB, FALSE, FALSE,
8394 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
8397 Xfake_grass, TRUE, FALSE,
8398 EL_EMC_FAKE_GRASS, -1, -1
8401 Xfake_grassB, FALSE, FALSE,
8402 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
8405 Xfake_door_1, TRUE, FALSE,
8406 EL_EM_GATE_1_GRAY, -1, -1
8409 Xfake_door_2, TRUE, FALSE,
8410 EL_EM_GATE_2_GRAY, -1, -1
8413 Xfake_door_3, TRUE, FALSE,
8414 EL_EM_GATE_3_GRAY, -1, -1
8417 Xfake_door_4, TRUE, FALSE,
8418 EL_EM_GATE_4_GRAY, -1, -1
8421 Xfake_door_5, TRUE, FALSE,
8422 EL_EMC_GATE_5_GRAY, -1, -1
8425 Xfake_door_6, TRUE, FALSE,
8426 EL_EMC_GATE_6_GRAY, -1, -1
8429 Xfake_door_7, TRUE, FALSE,
8430 EL_EMC_GATE_7_GRAY, -1, -1
8433 Xfake_door_8, TRUE, FALSE,
8434 EL_EMC_GATE_8_GRAY, -1, -1
8437 Xfake_acid_1, TRUE, FALSE,
8438 EL_EMC_FAKE_ACID, -1, -1
8441 Xfake_acid_2, FALSE, FALSE,
8442 EL_EMC_FAKE_ACID, -1, -1
8445 Xfake_acid_3, FALSE, FALSE,
8446 EL_EMC_FAKE_ACID, -1, -1
8449 Xfake_acid_4, FALSE, FALSE,
8450 EL_EMC_FAKE_ACID, -1, -1
8453 Xfake_acid_5, FALSE, FALSE,
8454 EL_EMC_FAKE_ACID, -1, -1
8457 Xfake_acid_6, FALSE, FALSE,
8458 EL_EMC_FAKE_ACID, -1, -1
8461 Xfake_acid_7, FALSE, FALSE,
8462 EL_EMC_FAKE_ACID, -1, -1
8465 Xfake_acid_8, FALSE, FALSE,
8466 EL_EMC_FAKE_ACID, -1, -1
8469 Xsteel_1, TRUE, FALSE,
8470 EL_STEELWALL, -1, -1
8473 Xsteel_2, TRUE, FALSE,
8474 EL_EMC_STEELWALL_2, -1, -1
8477 Xsteel_3, TRUE, FALSE,
8478 EL_EMC_STEELWALL_3, -1, -1
8481 Xsteel_4, TRUE, FALSE,
8482 EL_EMC_STEELWALL_4, -1, -1
8485 Xwall_1, TRUE, FALSE,
8489 Xwall_2, TRUE, FALSE,
8490 EL_EMC_WALL_14, -1, -1
8493 Xwall_3, TRUE, FALSE,
8494 EL_EMC_WALL_15, -1, -1
8497 Xwall_4, TRUE, FALSE,
8498 EL_EMC_WALL_16, -1, -1
8501 Xround_wall_1, TRUE, FALSE,
8502 EL_WALL_SLIPPERY, -1, -1
8505 Xround_wall_2, TRUE, FALSE,
8506 EL_EMC_WALL_SLIPPERY_2, -1, -1
8509 Xround_wall_3, TRUE, FALSE,
8510 EL_EMC_WALL_SLIPPERY_3, -1, -1
8513 Xround_wall_4, TRUE, FALSE,
8514 EL_EMC_WALL_SLIPPERY_4, -1, -1
8517 Xdecor_1, TRUE, FALSE,
8518 EL_EMC_WALL_8, -1, -1
8521 Xdecor_2, TRUE, FALSE,
8522 EL_EMC_WALL_6, -1, -1
8525 Xdecor_3, TRUE, FALSE,
8526 EL_EMC_WALL_4, -1, -1
8529 Xdecor_4, TRUE, FALSE,
8530 EL_EMC_WALL_7, -1, -1
8533 Xdecor_5, TRUE, FALSE,
8534 EL_EMC_WALL_5, -1, -1
8537 Xdecor_6, TRUE, FALSE,
8538 EL_EMC_WALL_9, -1, -1
8541 Xdecor_7, TRUE, FALSE,
8542 EL_EMC_WALL_10, -1, -1
8545 Xdecor_8, TRUE, FALSE,
8546 EL_EMC_WALL_1, -1, -1
8549 Xdecor_9, TRUE, FALSE,
8550 EL_EMC_WALL_2, -1, -1
8553 Xdecor_10, TRUE, FALSE,
8554 EL_EMC_WALL_3, -1, -1
8557 Xdecor_11, TRUE, FALSE,
8558 EL_EMC_WALL_11, -1, -1
8561 Xdecor_12, TRUE, FALSE,
8562 EL_EMC_WALL_12, -1, -1
8565 Xalpha_0, TRUE, FALSE,
8566 EL_CHAR('0'), -1, -1
8569 Xalpha_1, TRUE, FALSE,
8570 EL_CHAR('1'), -1, -1
8573 Xalpha_2, TRUE, FALSE,
8574 EL_CHAR('2'), -1, -1
8577 Xalpha_3, TRUE, FALSE,
8578 EL_CHAR('3'), -1, -1
8581 Xalpha_4, TRUE, FALSE,
8582 EL_CHAR('4'), -1, -1
8585 Xalpha_5, TRUE, FALSE,
8586 EL_CHAR('5'), -1, -1
8589 Xalpha_6, TRUE, FALSE,
8590 EL_CHAR('6'), -1, -1
8593 Xalpha_7, TRUE, FALSE,
8594 EL_CHAR('7'), -1, -1
8597 Xalpha_8, TRUE, FALSE,
8598 EL_CHAR('8'), -1, -1
8601 Xalpha_9, TRUE, FALSE,
8602 EL_CHAR('9'), -1, -1
8605 Xalpha_excla, TRUE, FALSE,
8606 EL_CHAR('!'), -1, -1
8609 Xalpha_quote, TRUE, FALSE,
8610 EL_CHAR('"'), -1, -1
8613 Xalpha_comma, TRUE, FALSE,
8614 EL_CHAR(','), -1, -1
8617 Xalpha_minus, TRUE, FALSE,
8618 EL_CHAR('-'), -1, -1
8621 Xalpha_perio, TRUE, FALSE,
8622 EL_CHAR('.'), -1, -1
8625 Xalpha_colon, TRUE, FALSE,
8626 EL_CHAR(':'), -1, -1
8629 Xalpha_quest, TRUE, FALSE,
8630 EL_CHAR('?'), -1, -1
8633 Xalpha_a, TRUE, FALSE,
8634 EL_CHAR('A'), -1, -1
8637 Xalpha_b, TRUE, FALSE,
8638 EL_CHAR('B'), -1, -1
8641 Xalpha_c, TRUE, FALSE,
8642 EL_CHAR('C'), -1, -1
8645 Xalpha_d, TRUE, FALSE,
8646 EL_CHAR('D'), -1, -1
8649 Xalpha_e, TRUE, FALSE,
8650 EL_CHAR('E'), -1, -1
8653 Xalpha_f, TRUE, FALSE,
8654 EL_CHAR('F'), -1, -1
8657 Xalpha_g, TRUE, FALSE,
8658 EL_CHAR('G'), -1, -1
8661 Xalpha_h, TRUE, FALSE,
8662 EL_CHAR('H'), -1, -1
8665 Xalpha_i, TRUE, FALSE,
8666 EL_CHAR('I'), -1, -1
8669 Xalpha_j, TRUE, FALSE,
8670 EL_CHAR('J'), -1, -1
8673 Xalpha_k, TRUE, FALSE,
8674 EL_CHAR('K'), -1, -1
8677 Xalpha_l, TRUE, FALSE,
8678 EL_CHAR('L'), -1, -1
8681 Xalpha_m, TRUE, FALSE,
8682 EL_CHAR('M'), -1, -1
8685 Xalpha_n, TRUE, FALSE,
8686 EL_CHAR('N'), -1, -1
8689 Xalpha_o, TRUE, FALSE,
8690 EL_CHAR('O'), -1, -1
8693 Xalpha_p, TRUE, FALSE,
8694 EL_CHAR('P'), -1, -1
8697 Xalpha_q, TRUE, FALSE,
8698 EL_CHAR('Q'), -1, -1
8701 Xalpha_r, TRUE, FALSE,
8702 EL_CHAR('R'), -1, -1
8705 Xalpha_s, TRUE, FALSE,
8706 EL_CHAR('S'), -1, -1
8709 Xalpha_t, TRUE, FALSE,
8710 EL_CHAR('T'), -1, -1
8713 Xalpha_u, TRUE, FALSE,
8714 EL_CHAR('U'), -1, -1
8717 Xalpha_v, TRUE, FALSE,
8718 EL_CHAR('V'), -1, -1
8721 Xalpha_w, TRUE, FALSE,
8722 EL_CHAR('W'), -1, -1
8725 Xalpha_x, TRUE, FALSE,
8726 EL_CHAR('X'), -1, -1
8729 Xalpha_y, TRUE, FALSE,
8730 EL_CHAR('Y'), -1, -1
8733 Xalpha_z, TRUE, FALSE,
8734 EL_CHAR('Z'), -1, -1
8737 Xalpha_arrow_e, TRUE, FALSE,
8738 EL_CHAR('>'), -1, -1
8741 Xalpha_arrow_w, TRUE, FALSE,
8742 EL_CHAR('<'), -1, -1
8745 Xalpha_copyr, TRUE, FALSE,
8746 EL_CHAR('©'), -1, -1
8750 Xboom_bug, FALSE, FALSE,
8751 EL_BUG, ACTION_EXPLODING, -1
8754 Xboom_bomb, FALSE, FALSE,
8755 EL_BOMB, ACTION_EXPLODING, -1
8758 Xboom_android, FALSE, FALSE,
8759 EL_EMC_ANDROID, ACTION_OTHER, -1
8762 Xboom_1, FALSE, FALSE,
8763 EL_DEFAULT, ACTION_EXPLODING, -1
8766 Xboom_2, FALSE, FALSE,
8767 EL_DEFAULT, ACTION_EXPLODING, -1
8770 Znormal, FALSE, FALSE,
8774 Zdynamite, FALSE, FALSE,
8778 Zplayer, FALSE, FALSE,
8782 ZBORDER, FALSE, FALSE,
8792 static struct Mapping_EM_to_RND_player
8801 em_player_mapping_list[] =
8805 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
8809 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
8813 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
8817 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
8821 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
8825 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
8829 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
8833 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
8837 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
8841 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
8845 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
8849 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
8853 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
8857 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
8861 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
8865 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
8869 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
8873 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
8877 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
8881 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
8885 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
8889 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
8893 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
8897 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
8901 EL_PLAYER_1, ACTION_DEFAULT, -1,
8905 EL_PLAYER_2, ACTION_DEFAULT, -1,
8909 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
8913 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
8917 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
8921 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
8925 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
8929 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
8933 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
8937 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
8941 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
8945 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
8949 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
8953 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
8957 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
8961 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
8965 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
8969 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
8973 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
8977 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
8981 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
8985 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
8989 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
8993 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
8997 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
9001 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
9005 EL_PLAYER_3, ACTION_DEFAULT, -1,
9009 EL_PLAYER_4, ACTION_DEFAULT, -1,
9018 int map_element_RND_to_EM(int element_rnd)
9020 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
9021 static boolean mapping_initialized = FALSE;
9023 if (!mapping_initialized)
9027 /* return "Xalpha_quest" for all undefined elements in mapping array */
9028 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
9029 mapping_RND_to_EM[i] = Xalpha_quest;
9031 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9032 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
9033 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
9034 em_object_mapping_list[i].element_em;
9036 mapping_initialized = TRUE;
9039 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
9040 return mapping_RND_to_EM[element_rnd];
9042 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
9047 int map_element_EM_to_RND(int element_em)
9049 static unsigned short mapping_EM_to_RND[TILE_MAX];
9050 static boolean mapping_initialized = FALSE;
9052 if (!mapping_initialized)
9056 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
9057 for (i = 0; i < TILE_MAX; i++)
9058 mapping_EM_to_RND[i] = EL_UNKNOWN;
9060 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9061 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
9062 em_object_mapping_list[i].element_rnd;
9064 mapping_initialized = TRUE;
9067 if (element_em >= 0 && element_em < TILE_MAX)
9068 return mapping_EM_to_RND[element_em];
9070 Error(ERR_WARN, "invalid EM level element %d", element_em);
9075 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
9077 struct LevelInfo_EM *level_em = level->native_em_level;
9078 struct LEVEL *lev = level_em->lev;
9081 for (i = 0; i < TILE_MAX; i++)
9082 lev->android_array[i] = Xblank;
9084 for (i = 0; i < level->num_android_clone_elements; i++)
9086 int element_rnd = level->android_clone_element[i];
9087 int element_em = map_element_RND_to_EM(element_rnd);
9089 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
9090 if (em_object_mapping_list[j].element_rnd == element_rnd)
9091 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
9095 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
9097 struct LevelInfo_EM *level_em = level->native_em_level;
9098 struct LEVEL *lev = level_em->lev;
9101 level->num_android_clone_elements = 0;
9103 for (i = 0; i < TILE_MAX; i++)
9105 int element_em = lev->android_array[i];
9107 boolean element_found = FALSE;
9109 if (element_em == Xblank)
9112 element_rnd = map_element_EM_to_RND(element_em);
9114 for (j = 0; j < level->num_android_clone_elements; j++)
9115 if (level->android_clone_element[j] == element_rnd)
9116 element_found = TRUE;
9120 level->android_clone_element[level->num_android_clone_elements++] =
9123 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
9128 if (level->num_android_clone_elements == 0)
9130 level->num_android_clone_elements = 1;
9131 level->android_clone_element[0] = EL_EMPTY;
9135 int map_direction_RND_to_EM(int direction)
9137 return (direction == MV_UP ? 0 :
9138 direction == MV_RIGHT ? 1 :
9139 direction == MV_DOWN ? 2 :
9140 direction == MV_LEFT ? 3 :
9144 int map_direction_EM_to_RND(int direction)
9146 return (direction == 0 ? MV_UP :
9147 direction == 1 ? MV_RIGHT :
9148 direction == 2 ? MV_DOWN :
9149 direction == 3 ? MV_LEFT :
9153 int map_element_RND_to_SP(int element_rnd)
9155 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
9157 if (element_rnd >= EL_SP_START &&
9158 element_rnd <= EL_SP_END)
9159 element_sp = element_rnd - EL_SP_START;
9160 else if (element_rnd == EL_EMPTY_SPACE)
9162 else if (element_rnd == EL_INVISIBLE_WALL)
9168 int map_element_SP_to_RND(int element_sp)
9170 int element_rnd = EL_UNKNOWN;
9172 if (element_sp >= 0x00 &&
9174 element_rnd = EL_SP_START + element_sp;
9175 else if (element_sp == 0x28)
9176 element_rnd = EL_INVISIBLE_WALL;
9181 int map_action_SP_to_RND(int action_sp)
9185 case actActive: return ACTION_ACTIVE;
9186 case actImpact: return ACTION_IMPACT;
9187 case actExploding: return ACTION_EXPLODING;
9188 case actDigging: return ACTION_DIGGING;
9189 case actSnapping: return ACTION_SNAPPING;
9190 case actCollecting: return ACTION_COLLECTING;
9191 case actPassing: return ACTION_PASSING;
9192 case actPushing: return ACTION_PUSHING;
9193 case actDropping: return ACTION_DROPPING;
9195 default: return ACTION_DEFAULT;
9199 int get_next_element(int element)
9203 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
9204 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
9205 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
9206 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
9207 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
9208 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
9209 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
9210 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
9211 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
9212 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
9213 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
9215 default: return element;
9220 int el_act_dir2img(int element, int action, int direction)
9222 element = GFX_ELEMENT(element);
9224 if (direction == MV_NONE)
9225 return element_info[element].graphic[action];
9227 direction = MV_DIR_TO_BIT(direction);
9229 return element_info[element].direction_graphic[action][direction];
9232 int el_act_dir2img(int element, int action, int direction)
9234 element = GFX_ELEMENT(element);
9235 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9237 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9238 return element_info[element].direction_graphic[action][direction];
9243 static int el_act_dir2crm(int element, int action, int direction)
9245 element = GFX_ELEMENT(element);
9247 if (direction == MV_NONE)
9248 return element_info[element].crumbled[action];
9250 direction = MV_DIR_TO_BIT(direction);
9252 return element_info[element].direction_crumbled[action][direction];
9255 static int el_act_dir2crm(int element, int action, int direction)
9257 element = GFX_ELEMENT(element);
9258 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9260 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9261 return element_info[element].direction_crumbled[action][direction];
9265 int el_act2img(int element, int action)
9267 element = GFX_ELEMENT(element);
9269 return element_info[element].graphic[action];
9272 int el_act2crm(int element, int action)
9274 element = GFX_ELEMENT(element);
9276 return element_info[element].crumbled[action];
9279 int el_dir2img(int element, int direction)
9281 element = GFX_ELEMENT(element);
9283 return el_act_dir2img(element, ACTION_DEFAULT, direction);
9286 int el2baseimg(int element)
9288 return element_info[element].graphic[ACTION_DEFAULT];
9291 int el2img(int element)
9293 element = GFX_ELEMENT(element);
9295 return element_info[element].graphic[ACTION_DEFAULT];
9298 int el2edimg(int element)
9300 element = GFX_ELEMENT(element);
9302 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
9305 int el2preimg(int element)
9307 element = GFX_ELEMENT(element);
9309 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
9312 int el2panelimg(int element)
9314 element = GFX_ELEMENT(element);
9316 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
9319 int font2baseimg(int font_nr)
9321 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
9324 int getBeltNrFromBeltElement(int element)
9326 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
9327 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
9328 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
9331 int getBeltNrFromBeltActiveElement(int element)
9333 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
9334 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
9335 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
9338 int getBeltNrFromBeltSwitchElement(int element)
9340 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
9341 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
9342 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
9345 int getBeltDirNrFromBeltElement(int element)
9347 static int belt_base_element[4] =
9349 EL_CONVEYOR_BELT_1_LEFT,
9350 EL_CONVEYOR_BELT_2_LEFT,
9351 EL_CONVEYOR_BELT_3_LEFT,
9352 EL_CONVEYOR_BELT_4_LEFT
9355 int belt_nr = getBeltNrFromBeltElement(element);
9356 int belt_dir_nr = element - belt_base_element[belt_nr];
9358 return (belt_dir_nr % 3);
9361 int getBeltDirNrFromBeltSwitchElement(int element)
9363 static int belt_base_element[4] =
9365 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9366 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9367 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9368 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9371 int belt_nr = getBeltNrFromBeltSwitchElement(element);
9372 int belt_dir_nr = element - belt_base_element[belt_nr];
9374 return (belt_dir_nr % 3);
9377 int getBeltDirFromBeltElement(int element)
9379 static int belt_move_dir[3] =
9386 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
9388 return belt_move_dir[belt_dir_nr];
9391 int getBeltDirFromBeltSwitchElement(int element)
9393 static int belt_move_dir[3] =
9400 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
9402 return belt_move_dir[belt_dir_nr];
9405 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9407 static int belt_base_element[4] =
9409 EL_CONVEYOR_BELT_1_LEFT,
9410 EL_CONVEYOR_BELT_2_LEFT,
9411 EL_CONVEYOR_BELT_3_LEFT,
9412 EL_CONVEYOR_BELT_4_LEFT
9415 return belt_base_element[belt_nr] + belt_dir_nr;
9418 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9420 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9422 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9425 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9427 static int belt_base_element[4] =
9429 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9430 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9431 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9432 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9435 return belt_base_element[belt_nr] + belt_dir_nr;
9438 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9440 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9442 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9446 boolean getTeamMode_EM()
9448 return game.team_mode;
9451 int getNumActivePlayers_EM()
9454 int num_players = 0;
9458 return (setup.team_mode ? MAX_PLAYERS : 1);
9460 for (i = 0; i < MAX_PLAYERS; i++)
9461 if (tape.player_participates[i])
9464 return (num_players > 1 ? MAX_PLAYERS : 1);
9468 int num_players = 0;
9471 /* when recording game, activate all connected players */
9475 for (i = 0; i < MAX_PLAYERS; i++)
9476 if (tape.player_participates[i])
9484 int getGameFrameDelay_EM(int native_em_game_frame_delay)
9486 int game_frame_delay_value;
9488 game_frame_delay_value =
9489 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
9490 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
9493 if (tape.playing && tape.warp_forward && !tape.pausing)
9494 game_frame_delay_value = 0;
9496 return game_frame_delay_value;
9499 unsigned int InitRND(int seed)
9501 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
9502 return InitEngineRandom_EM(seed);
9503 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
9504 return InitEngineRandom_SP(seed);
9506 return InitEngineRandom_RND(seed);
9510 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
9511 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
9514 inline static int get_effective_element_EM(int tile, int frame_em)
9516 int element = object_mapping[tile].element_rnd;
9517 int action = object_mapping[tile].action;
9518 boolean is_backside = object_mapping[tile].is_backside;
9519 boolean action_removing = (action == ACTION_DIGGING ||
9520 action == ACTION_SNAPPING ||
9521 action == ACTION_COLLECTING);
9527 case Yacid_splash_eB:
9528 case Yacid_splash_wB:
9529 return (frame_em > 5 ? EL_EMPTY : element);
9533 case Ydiamond_stone:
9534 // if (!game.use_native_emc_graphics_engine)
9542 else /* frame_em == 7 */
9546 case Yacid_splash_eB:
9547 case Yacid_splash_wB:
9550 case Yemerald_stone:
9553 case Ydiamond_stone:
9557 case Xdrip_stretchB:
9576 case Xsand_stonein_1:
9577 case Xsand_stonein_2:
9578 case Xsand_stonein_3:
9579 case Xsand_stonein_4:
9583 return (is_backside || action_removing ? EL_EMPTY : element);
9588 inline static boolean check_linear_animation_EM(int tile)
9592 case Xsand_stonesand_1:
9593 case Xsand_stonesand_quickout_1:
9594 case Xsand_sandstone_1:
9595 case Xsand_stonein_1:
9596 case Xsand_stoneout_1:
9616 case Yacid_splash_eB:
9617 case Yacid_splash_wB:
9618 case Yemerald_stone:
9626 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
9627 boolean has_crumbled_graphics,
9628 int crumbled, int sync_frame)
9630 /* if element can be crumbled, but certain action graphics are just empty
9631 space (like instantly snapping sand to empty space in 1 frame), do not
9632 treat these empty space graphics as crumbled graphics in EMC engine */
9633 if (crumbled == IMG_EMPTY_SPACE)
9634 has_crumbled_graphics = FALSE;
9636 if (has_crumbled_graphics)
9638 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9639 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9640 g_crumbled->anim_delay,
9641 g_crumbled->anim_mode,
9642 g_crumbled->anim_start_frame,
9645 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
9646 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
9648 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
9650 g_em->has_crumbled_graphics = TRUE;
9654 g_em->crumbled_bitmap = NULL;
9655 g_em->crumbled_src_x = 0;
9656 g_em->crumbled_src_y = 0;
9657 g_em->crumbled_border_size = 0;
9659 g_em->has_crumbled_graphics = FALSE;
9663 void ResetGfxAnimation_EM(int x, int y, int tile)
9668 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
9669 int tile, int frame_em, int x, int y)
9671 int action = object_mapping[tile].action;
9673 int direction = object_mapping[tile].direction;
9674 int effective_element = get_effective_element_EM(tile, frame_em);
9675 int graphic = (direction == MV_NONE ?
9676 el_act2img(effective_element, action) :
9677 el_act_dir2img(effective_element, action, direction));
9678 struct GraphicInfo *g = &graphic_info[graphic];
9681 boolean action_removing = (action == ACTION_DIGGING ||
9682 action == ACTION_SNAPPING ||
9683 action == ACTION_COLLECTING);
9684 boolean action_moving = (action == ACTION_FALLING ||
9685 action == ACTION_MOVING ||
9686 action == ACTION_PUSHING ||
9687 action == ACTION_EATING ||
9688 action == ACTION_FILLING ||
9689 action == ACTION_EMPTYING);
9690 boolean action_falling = (action == ACTION_FALLING ||
9691 action == ACTION_FILLING ||
9692 action == ACTION_EMPTYING);
9694 /* special case: graphic uses "2nd movement tile" and has defined
9695 7 frames for movement animation (or less) => use default graphic
9696 for last (8th) frame which ends the movement animation */
9697 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9699 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
9700 graphic = (direction == MV_NONE ?
9701 el_act2img(effective_element, action) :
9702 el_act_dir2img(effective_element, action, direction));
9704 g = &graphic_info[graphic];
9708 if (tile == Xsand_stonesand_1 ||
9709 tile == Xsand_stonesand_2 ||
9710 tile == Xsand_stonesand_3 ||
9711 tile == Xsand_stonesand_4)
9712 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9716 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
9720 // printf("::: resetting... [%d]\n", tile);
9723 if (action_removing || check_linear_animation_EM(tile))
9725 GfxFrame[x][y] = frame_em;
9727 // printf("::: resetting... [%d]\n", tile);
9730 else if (action_moving)
9732 boolean is_backside = object_mapping[tile].is_backside;
9736 int direction = object_mapping[tile].direction;
9737 int move_dir = (action_falling ? MV_DOWN : direction);
9742 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
9743 if (g->double_movement && frame_em == 0)
9747 // printf("::: resetting... [%d]\n", tile);
9751 if (move_dir == MV_LEFT)
9752 GfxFrame[x - 1][y] = GfxFrame[x][y];
9753 else if (move_dir == MV_RIGHT)
9754 GfxFrame[x + 1][y] = GfxFrame[x][y];
9755 else if (move_dir == MV_UP)
9756 GfxFrame[x][y - 1] = GfxFrame[x][y];
9757 else if (move_dir == MV_DOWN)
9758 GfxFrame[x][y + 1] = GfxFrame[x][y];
9765 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
9766 if (tile == Xsand_stonesand_quickout_1 ||
9767 tile == Xsand_stonesand_quickout_2)
9772 if (tile == Xsand_stonesand_1 ||
9773 tile == Xsand_stonesand_2 ||
9774 tile == Xsand_stonesand_3 ||
9775 tile == Xsand_stonesand_4)
9776 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9780 if (graphic_info[graphic].anim_global_sync)
9781 sync_frame = FrameCounter;
9782 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9783 sync_frame = GfxFrame[x][y];
9785 sync_frame = 0; /* playfield border (pseudo steel) */
9787 SetRandomAnimationValue(x, y);
9789 int frame = getAnimationFrame(g->anim_frames,
9792 g->anim_start_frame,
9795 g_em->unique_identifier =
9796 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
9800 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
9801 int tile, int frame_em, int x, int y)
9803 int action = object_mapping[tile].action;
9804 int direction = object_mapping[tile].direction;
9805 boolean is_backside = object_mapping[tile].is_backside;
9806 int effective_element = get_effective_element_EM(tile, frame_em);
9808 int effective_action = action;
9810 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
9812 int graphic = (direction == MV_NONE ?
9813 el_act2img(effective_element, effective_action) :
9814 el_act_dir2img(effective_element, effective_action,
9816 int crumbled = (direction == MV_NONE ?
9817 el_act2crm(effective_element, effective_action) :
9818 el_act_dir2crm(effective_element, effective_action,
9820 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9821 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9822 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9823 struct GraphicInfo *g = &graphic_info[graphic];
9825 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9829 /* special case: graphic uses "2nd movement tile" and has defined
9830 7 frames for movement animation (or less) => use default graphic
9831 for last (8th) frame which ends the movement animation */
9832 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9834 effective_action = ACTION_DEFAULT;
9835 graphic = (direction == MV_NONE ?
9836 el_act2img(effective_element, effective_action) :
9837 el_act_dir2img(effective_element, effective_action,
9839 crumbled = (direction == MV_NONE ?
9840 el_act2crm(effective_element, effective_action) :
9841 el_act_dir2crm(effective_element, effective_action,
9844 g = &graphic_info[graphic];
9854 if (frame_em == 0) /* reset animation frame for certain elements */
9856 if (check_linear_animation_EM(tile))
9861 if (graphic_info[graphic].anim_global_sync)
9862 sync_frame = FrameCounter;
9863 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9864 sync_frame = GfxFrame[x][y];
9866 sync_frame = 0; /* playfield border (pseudo steel) */
9868 SetRandomAnimationValue(x, y);
9873 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9874 i == Xdrip_stretchB ? 7 :
9875 i == Ydrip_s2 ? j + 8 :
9876 i == Ydrip_s2B ? j + 8 :
9885 i == Xfake_acid_1 ? 0 :
9886 i == Xfake_acid_2 ? 10 :
9887 i == Xfake_acid_3 ? 20 :
9888 i == Xfake_acid_4 ? 30 :
9889 i == Xfake_acid_5 ? 40 :
9890 i == Xfake_acid_6 ? 50 :
9891 i == Xfake_acid_7 ? 60 :
9892 i == Xfake_acid_8 ? 70 :
9894 i == Xball_2B ? j + 8 :
9895 i == Yball_eat ? j + 1 :
9896 i == Ykey_1_eat ? j + 1 :
9897 i == Ykey_2_eat ? j + 1 :
9898 i == Ykey_3_eat ? j + 1 :
9899 i == Ykey_4_eat ? j + 1 :
9900 i == Ykey_5_eat ? j + 1 :
9901 i == Ykey_6_eat ? j + 1 :
9902 i == Ykey_7_eat ? j + 1 :
9903 i == Ykey_8_eat ? j + 1 :
9904 i == Ylenses_eat ? j + 1 :
9905 i == Ymagnify_eat ? j + 1 :
9906 i == Ygrass_eat ? j + 1 :
9907 i == Ydirt_eat ? j + 1 :
9908 i == Xamoeba_1 ? 0 :
9909 i == Xamoeba_2 ? 1 :
9910 i == Xamoeba_3 ? 2 :
9911 i == Xamoeba_4 ? 3 :
9912 i == Xamoeba_5 ? 0 :
9913 i == Xamoeba_6 ? 1 :
9914 i == Xamoeba_7 ? 2 :
9915 i == Xamoeba_8 ? 3 :
9916 i == Xexit_2 ? j + 8 :
9917 i == Xexit_3 ? j + 16 :
9918 i == Xdynamite_1 ? 0 :
9919 i == Xdynamite_2 ? 8 :
9920 i == Xdynamite_3 ? 16 :
9921 i == Xdynamite_4 ? 24 :
9922 i == Xsand_stonein_1 ? j + 1 :
9923 i == Xsand_stonein_2 ? j + 9 :
9924 i == Xsand_stonein_3 ? j + 17 :
9925 i == Xsand_stonein_4 ? j + 25 :
9926 i == Xsand_stoneout_1 && j == 0 ? 0 :
9927 i == Xsand_stoneout_1 && j == 1 ? 0 :
9928 i == Xsand_stoneout_1 && j == 2 ? 1 :
9929 i == Xsand_stoneout_1 && j == 3 ? 2 :
9930 i == Xsand_stoneout_1 && j == 4 ? 2 :
9931 i == Xsand_stoneout_1 && j == 5 ? 3 :
9932 i == Xsand_stoneout_1 && j == 6 ? 4 :
9933 i == Xsand_stoneout_1 && j == 7 ? 4 :
9934 i == Xsand_stoneout_2 && j == 0 ? 5 :
9935 i == Xsand_stoneout_2 && j == 1 ? 6 :
9936 i == Xsand_stoneout_2 && j == 2 ? 7 :
9937 i == Xsand_stoneout_2 && j == 3 ? 8 :
9938 i == Xsand_stoneout_2 && j == 4 ? 9 :
9939 i == Xsand_stoneout_2 && j == 5 ? 11 :
9940 i == Xsand_stoneout_2 && j == 6 ? 13 :
9941 i == Xsand_stoneout_2 && j == 7 ? 15 :
9942 i == Xboom_bug && j == 1 ? 2 :
9943 i == Xboom_bug && j == 2 ? 2 :
9944 i == Xboom_bug && j == 3 ? 4 :
9945 i == Xboom_bug && j == 4 ? 4 :
9946 i == Xboom_bug && j == 5 ? 2 :
9947 i == Xboom_bug && j == 6 ? 2 :
9948 i == Xboom_bug && j == 7 ? 0 :
9949 i == Xboom_bomb && j == 1 ? 2 :
9950 i == Xboom_bomb && j == 2 ? 2 :
9951 i == Xboom_bomb && j == 3 ? 4 :
9952 i == Xboom_bomb && j == 4 ? 4 :
9953 i == Xboom_bomb && j == 5 ? 2 :
9954 i == Xboom_bomb && j == 6 ? 2 :
9955 i == Xboom_bomb && j == 7 ? 0 :
9956 i == Xboom_android && j == 7 ? 6 :
9957 i == Xboom_1 && j == 1 ? 2 :
9958 i == Xboom_1 && j == 2 ? 2 :
9959 i == Xboom_1 && j == 3 ? 4 :
9960 i == Xboom_1 && j == 4 ? 4 :
9961 i == Xboom_1 && j == 5 ? 6 :
9962 i == Xboom_1 && j == 6 ? 6 :
9963 i == Xboom_1 && j == 7 ? 8 :
9964 i == Xboom_2 && j == 0 ? 8 :
9965 i == Xboom_2 && j == 1 ? 8 :
9966 i == Xboom_2 && j == 2 ? 10 :
9967 i == Xboom_2 && j == 3 ? 10 :
9968 i == Xboom_2 && j == 4 ? 10 :
9969 i == Xboom_2 && j == 5 ? 12 :
9970 i == Xboom_2 && j == 6 ? 12 :
9971 i == Xboom_2 && j == 7 ? 12 :
9973 special_animation && j == 4 ? 3 :
9974 effective_action != action ? 0 :
9980 int xxx_effective_action;
9981 int xxx_has_action_graphics;
9984 int element = object_mapping[i].element_rnd;
9985 int action = object_mapping[i].action;
9986 int direction = object_mapping[i].direction;
9987 boolean is_backside = object_mapping[i].is_backside;
9989 boolean action_removing = (action == ACTION_DIGGING ||
9990 action == ACTION_SNAPPING ||
9991 action == ACTION_COLLECTING);
9993 boolean action_exploding = ((action == ACTION_EXPLODING ||
9994 action == ACTION_SMASHED_BY_ROCK ||
9995 action == ACTION_SMASHED_BY_SPRING) &&
9996 element != EL_DIAMOND);
9997 boolean action_active = (action == ACTION_ACTIVE);
9998 boolean action_other = (action == ACTION_OTHER);
10002 int effective_element = get_effective_element_EM(i, j);
10004 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
10005 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
10007 i == Xdrip_stretch ? element :
10008 i == Xdrip_stretchB ? element :
10009 i == Ydrip_s1 ? element :
10010 i == Ydrip_s1B ? element :
10011 i == Xball_1B ? element :
10012 i == Xball_2 ? element :
10013 i == Xball_2B ? element :
10014 i == Yball_eat ? element :
10015 i == Ykey_1_eat ? element :
10016 i == Ykey_2_eat ? element :
10017 i == Ykey_3_eat ? element :
10018 i == Ykey_4_eat ? element :
10019 i == Ykey_5_eat ? element :
10020 i == Ykey_6_eat ? element :
10021 i == Ykey_7_eat ? element :
10022 i == Ykey_8_eat ? element :
10023 i == Ylenses_eat ? element :
10024 i == Ymagnify_eat ? element :
10025 i == Ygrass_eat ? element :
10026 i == Ydirt_eat ? element :
10027 i == Yemerald_stone ? EL_EMERALD :
10028 i == Ydiamond_stone ? EL_ROCK :
10029 i == Xsand_stonein_1 ? element :
10030 i == Xsand_stonein_2 ? element :
10031 i == Xsand_stonein_3 ? element :
10032 i == Xsand_stonein_4 ? element :
10033 is_backside ? EL_EMPTY :
10034 action_removing ? EL_EMPTY :
10037 int effective_action = (j < 7 ? action :
10038 i == Xdrip_stretch ? action :
10039 i == Xdrip_stretchB ? action :
10040 i == Ydrip_s1 ? action :
10041 i == Ydrip_s1B ? action :
10042 i == Xball_1B ? action :
10043 i == Xball_2 ? action :
10044 i == Xball_2B ? action :
10045 i == Yball_eat ? action :
10046 i == Ykey_1_eat ? action :
10047 i == Ykey_2_eat ? action :
10048 i == Ykey_3_eat ? action :
10049 i == Ykey_4_eat ? action :
10050 i == Ykey_5_eat ? action :
10051 i == Ykey_6_eat ? action :
10052 i == Ykey_7_eat ? action :
10053 i == Ykey_8_eat ? action :
10054 i == Ylenses_eat ? action :
10055 i == Ymagnify_eat ? action :
10056 i == Ygrass_eat ? action :
10057 i == Ydirt_eat ? action :
10058 i == Xsand_stonein_1 ? action :
10059 i == Xsand_stonein_2 ? action :
10060 i == Xsand_stonein_3 ? action :
10061 i == Xsand_stonein_4 ? action :
10062 i == Xsand_stoneout_1 ? action :
10063 i == Xsand_stoneout_2 ? action :
10064 i == Xboom_android ? ACTION_EXPLODING :
10065 action_exploding ? ACTION_EXPLODING :
10066 action_active ? action :
10067 action_other ? action :
10069 int graphic = (el_act_dir2img(effective_element, effective_action,
10071 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10073 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10074 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10075 boolean has_action_graphics = (graphic != base_graphic);
10076 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10077 struct GraphicInfo *g = &graphic_info[graphic];
10079 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10081 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10082 Bitmap *src_bitmap;
10084 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10085 boolean special_animation = (action != ACTION_DEFAULT &&
10086 g->anim_frames == 3 &&
10087 g->anim_delay == 2 &&
10088 g->anim_mode & ANIM_LINEAR);
10089 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
10090 i == Xdrip_stretchB ? 7 :
10091 i == Ydrip_s2 ? j + 8 :
10092 i == Ydrip_s2B ? j + 8 :
10094 i == Xacid_2 ? 10 :
10095 i == Xacid_3 ? 20 :
10096 i == Xacid_4 ? 30 :
10097 i == Xacid_5 ? 40 :
10098 i == Xacid_6 ? 50 :
10099 i == Xacid_7 ? 60 :
10100 i == Xacid_8 ? 70 :
10101 i == Xfake_acid_1 ? 0 :
10102 i == Xfake_acid_2 ? 10 :
10103 i == Xfake_acid_3 ? 20 :
10104 i == Xfake_acid_4 ? 30 :
10105 i == Xfake_acid_5 ? 40 :
10106 i == Xfake_acid_6 ? 50 :
10107 i == Xfake_acid_7 ? 60 :
10108 i == Xfake_acid_8 ? 70 :
10110 i == Xball_2B ? j + 8 :
10111 i == Yball_eat ? j + 1 :
10112 i == Ykey_1_eat ? j + 1 :
10113 i == Ykey_2_eat ? j + 1 :
10114 i == Ykey_3_eat ? j + 1 :
10115 i == Ykey_4_eat ? j + 1 :
10116 i == Ykey_5_eat ? j + 1 :
10117 i == Ykey_6_eat ? j + 1 :
10118 i == Ykey_7_eat ? j + 1 :
10119 i == Ykey_8_eat ? j + 1 :
10120 i == Ylenses_eat ? j + 1 :
10121 i == Ymagnify_eat ? j + 1 :
10122 i == Ygrass_eat ? j + 1 :
10123 i == Ydirt_eat ? j + 1 :
10124 i == Xamoeba_1 ? 0 :
10125 i == Xamoeba_2 ? 1 :
10126 i == Xamoeba_3 ? 2 :
10127 i == Xamoeba_4 ? 3 :
10128 i == Xamoeba_5 ? 0 :
10129 i == Xamoeba_6 ? 1 :
10130 i == Xamoeba_7 ? 2 :
10131 i == Xamoeba_8 ? 3 :
10132 i == Xexit_2 ? j + 8 :
10133 i == Xexit_3 ? j + 16 :
10134 i == Xdynamite_1 ? 0 :
10135 i == Xdynamite_2 ? 8 :
10136 i == Xdynamite_3 ? 16 :
10137 i == Xdynamite_4 ? 24 :
10138 i == Xsand_stonein_1 ? j + 1 :
10139 i == Xsand_stonein_2 ? j + 9 :
10140 i == Xsand_stonein_3 ? j + 17 :
10141 i == Xsand_stonein_4 ? j + 25 :
10142 i == Xsand_stoneout_1 && j == 0 ? 0 :
10143 i == Xsand_stoneout_1 && j == 1 ? 0 :
10144 i == Xsand_stoneout_1 && j == 2 ? 1 :
10145 i == Xsand_stoneout_1 && j == 3 ? 2 :
10146 i == Xsand_stoneout_1 && j == 4 ? 2 :
10147 i == Xsand_stoneout_1 && j == 5 ? 3 :
10148 i == Xsand_stoneout_1 && j == 6 ? 4 :
10149 i == Xsand_stoneout_1 && j == 7 ? 4 :
10150 i == Xsand_stoneout_2 && j == 0 ? 5 :
10151 i == Xsand_stoneout_2 && j == 1 ? 6 :
10152 i == Xsand_stoneout_2 && j == 2 ? 7 :
10153 i == Xsand_stoneout_2 && j == 3 ? 8 :
10154 i == Xsand_stoneout_2 && j == 4 ? 9 :
10155 i == Xsand_stoneout_2 && j == 5 ? 11 :
10156 i == Xsand_stoneout_2 && j == 6 ? 13 :
10157 i == Xsand_stoneout_2 && j == 7 ? 15 :
10158 i == Xboom_bug && j == 1 ? 2 :
10159 i == Xboom_bug && j == 2 ? 2 :
10160 i == Xboom_bug && j == 3 ? 4 :
10161 i == Xboom_bug && j == 4 ? 4 :
10162 i == Xboom_bug && j == 5 ? 2 :
10163 i == Xboom_bug && j == 6 ? 2 :
10164 i == Xboom_bug && j == 7 ? 0 :
10165 i == Xboom_bomb && j == 1 ? 2 :
10166 i == Xboom_bomb && j == 2 ? 2 :
10167 i == Xboom_bomb && j == 3 ? 4 :
10168 i == Xboom_bomb && j == 4 ? 4 :
10169 i == Xboom_bomb && j == 5 ? 2 :
10170 i == Xboom_bomb && j == 6 ? 2 :
10171 i == Xboom_bomb && j == 7 ? 0 :
10172 i == Xboom_android && j == 7 ? 6 :
10173 i == Xboom_1 && j == 1 ? 2 :
10174 i == Xboom_1 && j == 2 ? 2 :
10175 i == Xboom_1 && j == 3 ? 4 :
10176 i == Xboom_1 && j == 4 ? 4 :
10177 i == Xboom_1 && j == 5 ? 6 :
10178 i == Xboom_1 && j == 6 ? 6 :
10179 i == Xboom_1 && j == 7 ? 8 :
10180 i == Xboom_2 && j == 0 ? 8 :
10181 i == Xboom_2 && j == 1 ? 8 :
10182 i == Xboom_2 && j == 2 ? 10 :
10183 i == Xboom_2 && j == 3 ? 10 :
10184 i == Xboom_2 && j == 4 ? 10 :
10185 i == Xboom_2 && j == 5 ? 12 :
10186 i == Xboom_2 && j == 6 ? 12 :
10187 i == Xboom_2 && j == 7 ? 12 :
10188 special_animation && j == 4 ? 3 :
10189 effective_action != action ? 0 :
10192 xxx_effective_action = effective_action;
10193 xxx_has_action_graphics = has_action_graphics;
10198 int frame = getAnimationFrame(g->anim_frames,
10201 g->anim_start_frame,
10215 int old_src_x = g_em->src_x;
10216 int old_src_y = g_em->src_y;
10220 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
10221 g->double_movement && is_backside);
10223 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10224 &g_em->src_x, &g_em->src_y, FALSE);
10229 if (tile == Ydiamond_stone)
10230 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
10235 g->anim_start_frame,
10238 g_em->src_x, g_em->src_y,
10239 g_em->src_offset_x, g_em->src_offset_y,
10240 g_em->dst_offset_x, g_em->dst_offset_y,
10252 if (graphic == IMG_BUG_MOVING_RIGHT)
10253 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
10254 g->double_movement, is_backside,
10255 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
10263 g_em->src_offset_x = 0;
10264 g_em->src_offset_y = 0;
10265 g_em->dst_offset_x = 0;
10266 g_em->dst_offset_y = 0;
10267 g_em->width = TILEX;
10268 g_em->height = TILEY;
10270 g_em->preserve_background = FALSE;
10273 /* (updating the "crumbled" graphic definitions is probably not really needed,
10274 as animations for crumbled graphics can't be longer than one EMC cycle) */
10276 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10281 g_em->crumbled_bitmap = NULL;
10282 g_em->crumbled_src_x = 0;
10283 g_em->crumbled_src_y = 0;
10285 g_em->has_crumbled_graphics = FALSE;
10287 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10289 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10290 g_crumbled->anim_delay,
10291 g_crumbled->anim_mode,
10292 g_crumbled->anim_start_frame,
10295 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
10296 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
10298 g_em->has_crumbled_graphics = TRUE;
10304 int effective_action = xxx_effective_action;
10305 int has_action_graphics = xxx_has_action_graphics;
10307 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10308 effective_action == ACTION_MOVING ||
10309 effective_action == ACTION_PUSHING ||
10310 effective_action == ACTION_EATING)) ||
10311 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10312 effective_action == ACTION_EMPTYING)))
10315 (effective_action == ACTION_FALLING ||
10316 effective_action == ACTION_FILLING ||
10317 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10318 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10319 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10320 int num_steps = (i == Ydrip_s1 ? 16 :
10321 i == Ydrip_s1B ? 16 :
10322 i == Ydrip_s2 ? 16 :
10323 i == Ydrip_s2B ? 16 :
10324 i == Xsand_stonein_1 ? 32 :
10325 i == Xsand_stonein_2 ? 32 :
10326 i == Xsand_stonein_3 ? 32 :
10327 i == Xsand_stonein_4 ? 32 :
10328 i == Xsand_stoneout_1 ? 16 :
10329 i == Xsand_stoneout_2 ? 16 : 8);
10330 int cx = ABS(dx) * (TILEX / num_steps);
10331 int cy = ABS(dy) * (TILEY / num_steps);
10332 int step_frame = (i == Ydrip_s2 ? j + 8 :
10333 i == Ydrip_s2B ? j + 8 :
10334 i == Xsand_stonein_2 ? j + 8 :
10335 i == Xsand_stonein_3 ? j + 16 :
10336 i == Xsand_stonein_4 ? j + 24 :
10337 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10338 int step = (is_backside ? step_frame : num_steps - step_frame);
10340 if (is_backside) /* tile where movement starts */
10342 if (dx < 0 || dy < 0)
10344 g_em->src_offset_x = cx * step;
10345 g_em->src_offset_y = cy * step;
10349 g_em->dst_offset_x = cx * step;
10350 g_em->dst_offset_y = cy * step;
10353 else /* tile where movement ends */
10355 if (dx < 0 || dy < 0)
10357 g_em->dst_offset_x = cx * step;
10358 g_em->dst_offset_y = cy * step;
10362 g_em->src_offset_x = cx * step;
10363 g_em->src_offset_y = cy * step;
10367 g_em->width = TILEX - cx * step;
10368 g_em->height = TILEY - cy * step;
10371 /* create unique graphic identifier to decide if tile must be redrawn */
10372 /* bit 31 - 16 (16 bit): EM style graphic
10373 bit 15 - 12 ( 4 bit): EM style frame
10374 bit 11 - 6 ( 6 bit): graphic width
10375 bit 5 - 0 ( 6 bit): graphic height */
10376 g_em->unique_identifier =
10377 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10383 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
10384 int player_nr, int anim, int frame_em)
10386 int element = player_mapping[player_nr][anim].element_rnd;
10387 int action = player_mapping[player_nr][anim].action;
10388 int direction = player_mapping[player_nr][anim].direction;
10389 int graphic = (direction == MV_NONE ?
10390 el_act2img(element, action) :
10391 el_act_dir2img(element, action, direction));
10392 struct GraphicInfo *g = &graphic_info[graphic];
10395 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
10397 stored_player[player_nr].StepFrame = frame_em;
10399 sync_frame = stored_player[player_nr].Frame;
10401 int frame = getAnimationFrame(g->anim_frames,
10404 g->anim_start_frame,
10407 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10408 &g_em->src_x, &g_em->src_y, FALSE);
10411 printf("::: %d: %d, %d [%d]\n",
10413 stored_player[player_nr].Frame,
10414 stored_player[player_nr].StepFrame,
10419 void InitGraphicInfo_EM(void)
10422 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
10423 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
10428 int num_em_gfx_errors = 0;
10430 if (graphic_info_em_object[0][0].bitmap == NULL)
10432 /* EM graphics not yet initialized in em_open_all() */
10437 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
10440 /* always start with reliable default values */
10441 for (i = 0; i < TILE_MAX; i++)
10443 object_mapping[i].element_rnd = EL_UNKNOWN;
10444 object_mapping[i].is_backside = FALSE;
10445 object_mapping[i].action = ACTION_DEFAULT;
10446 object_mapping[i].direction = MV_NONE;
10449 /* always start with reliable default values */
10450 for (p = 0; p < MAX_PLAYERS; p++)
10452 for (i = 0; i < SPR_MAX; i++)
10454 player_mapping[p][i].element_rnd = EL_UNKNOWN;
10455 player_mapping[p][i].action = ACTION_DEFAULT;
10456 player_mapping[p][i].direction = MV_NONE;
10460 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
10462 int e = em_object_mapping_list[i].element_em;
10464 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
10465 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
10467 if (em_object_mapping_list[i].action != -1)
10468 object_mapping[e].action = em_object_mapping_list[i].action;
10470 if (em_object_mapping_list[i].direction != -1)
10471 object_mapping[e].direction =
10472 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
10475 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
10477 int a = em_player_mapping_list[i].action_em;
10478 int p = em_player_mapping_list[i].player_nr;
10480 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
10482 if (em_player_mapping_list[i].action != -1)
10483 player_mapping[p][a].action = em_player_mapping_list[i].action;
10485 if (em_player_mapping_list[i].direction != -1)
10486 player_mapping[p][a].direction =
10487 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
10490 for (i = 0; i < TILE_MAX; i++)
10492 int element = object_mapping[i].element_rnd;
10493 int action = object_mapping[i].action;
10494 int direction = object_mapping[i].direction;
10495 boolean is_backside = object_mapping[i].is_backside;
10497 boolean action_removing = (action == ACTION_DIGGING ||
10498 action == ACTION_SNAPPING ||
10499 action == ACTION_COLLECTING);
10501 boolean action_exploding = ((action == ACTION_EXPLODING ||
10502 action == ACTION_SMASHED_BY_ROCK ||
10503 action == ACTION_SMASHED_BY_SPRING) &&
10504 element != EL_DIAMOND);
10505 boolean action_active = (action == ACTION_ACTIVE);
10506 boolean action_other = (action == ACTION_OTHER);
10508 for (j = 0; j < 8; j++)
10511 int effective_element = get_effective_element_EM(i, j);
10513 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
10514 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
10516 i == Xdrip_stretch ? element :
10517 i == Xdrip_stretchB ? element :
10518 i == Ydrip_s1 ? element :
10519 i == Ydrip_s1B ? element :
10520 i == Xball_1B ? element :
10521 i == Xball_2 ? element :
10522 i == Xball_2B ? element :
10523 i == Yball_eat ? element :
10524 i == Ykey_1_eat ? element :
10525 i == Ykey_2_eat ? element :
10526 i == Ykey_3_eat ? element :
10527 i == Ykey_4_eat ? element :
10528 i == Ykey_5_eat ? element :
10529 i == Ykey_6_eat ? element :
10530 i == Ykey_7_eat ? element :
10531 i == Ykey_8_eat ? element :
10532 i == Ylenses_eat ? element :
10533 i == Ymagnify_eat ? element :
10534 i == Ygrass_eat ? element :
10535 i == Ydirt_eat ? element :
10536 i == Yemerald_stone ? EL_EMERALD :
10537 i == Ydiamond_stone ? EL_ROCK :
10538 i == Xsand_stonein_1 ? element :
10539 i == Xsand_stonein_2 ? element :
10540 i == Xsand_stonein_3 ? element :
10541 i == Xsand_stonein_4 ? element :
10542 is_backside ? EL_EMPTY :
10543 action_removing ? EL_EMPTY :
10546 int effective_action = (j < 7 ? action :
10547 i == Xdrip_stretch ? action :
10548 i == Xdrip_stretchB ? action :
10549 i == Ydrip_s1 ? action :
10550 i == Ydrip_s1B ? action :
10551 i == Xball_1B ? action :
10552 i == Xball_2 ? action :
10553 i == Xball_2B ? action :
10554 i == Yball_eat ? action :
10555 i == Ykey_1_eat ? action :
10556 i == Ykey_2_eat ? action :
10557 i == Ykey_3_eat ? action :
10558 i == Ykey_4_eat ? action :
10559 i == Ykey_5_eat ? action :
10560 i == Ykey_6_eat ? action :
10561 i == Ykey_7_eat ? action :
10562 i == Ykey_8_eat ? action :
10563 i == Ylenses_eat ? action :
10564 i == Ymagnify_eat ? action :
10565 i == Ygrass_eat ? action :
10566 i == Ydirt_eat ? action :
10567 i == Xsand_stonein_1 ? action :
10568 i == Xsand_stonein_2 ? action :
10569 i == Xsand_stonein_3 ? action :
10570 i == Xsand_stonein_4 ? action :
10571 i == Xsand_stoneout_1 ? action :
10572 i == Xsand_stoneout_2 ? action :
10573 i == Xboom_android ? ACTION_EXPLODING :
10574 action_exploding ? ACTION_EXPLODING :
10575 action_active ? action :
10576 action_other ? action :
10578 int graphic = (el_act_dir2img(effective_element, effective_action,
10580 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10582 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10583 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10584 boolean has_action_graphics = (graphic != base_graphic);
10585 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10586 struct GraphicInfo *g = &graphic_info[graphic];
10588 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10590 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10591 Bitmap *src_bitmap;
10593 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10594 boolean special_animation = (action != ACTION_DEFAULT &&
10595 g->anim_frames == 3 &&
10596 g->anim_delay == 2 &&
10597 g->anim_mode & ANIM_LINEAR);
10598 int sync_frame = (i == Xdrip_stretch ? 7 :
10599 i == Xdrip_stretchB ? 7 :
10600 i == Ydrip_s2 ? j + 8 :
10601 i == Ydrip_s2B ? j + 8 :
10603 i == Xacid_2 ? 10 :
10604 i == Xacid_3 ? 20 :
10605 i == Xacid_4 ? 30 :
10606 i == Xacid_5 ? 40 :
10607 i == Xacid_6 ? 50 :
10608 i == Xacid_7 ? 60 :
10609 i == Xacid_8 ? 70 :
10610 i == Xfake_acid_1 ? 0 :
10611 i == Xfake_acid_2 ? 10 :
10612 i == Xfake_acid_3 ? 20 :
10613 i == Xfake_acid_4 ? 30 :
10614 i == Xfake_acid_5 ? 40 :
10615 i == Xfake_acid_6 ? 50 :
10616 i == Xfake_acid_7 ? 60 :
10617 i == Xfake_acid_8 ? 70 :
10619 i == Xball_2B ? j + 8 :
10620 i == Yball_eat ? j + 1 :
10621 i == Ykey_1_eat ? j + 1 :
10622 i == Ykey_2_eat ? j + 1 :
10623 i == Ykey_3_eat ? j + 1 :
10624 i == Ykey_4_eat ? j + 1 :
10625 i == Ykey_5_eat ? j + 1 :
10626 i == Ykey_6_eat ? j + 1 :
10627 i == Ykey_7_eat ? j + 1 :
10628 i == Ykey_8_eat ? j + 1 :
10629 i == Ylenses_eat ? j + 1 :
10630 i == Ymagnify_eat ? j + 1 :
10631 i == Ygrass_eat ? j + 1 :
10632 i == Ydirt_eat ? j + 1 :
10633 i == Xamoeba_1 ? 0 :
10634 i == Xamoeba_2 ? 1 :
10635 i == Xamoeba_3 ? 2 :
10636 i == Xamoeba_4 ? 3 :
10637 i == Xamoeba_5 ? 0 :
10638 i == Xamoeba_6 ? 1 :
10639 i == Xamoeba_7 ? 2 :
10640 i == Xamoeba_8 ? 3 :
10641 i == Xexit_2 ? j + 8 :
10642 i == Xexit_3 ? j + 16 :
10643 i == Xdynamite_1 ? 0 :
10644 i == Xdynamite_2 ? 8 :
10645 i == Xdynamite_3 ? 16 :
10646 i == Xdynamite_4 ? 24 :
10647 i == Xsand_stonein_1 ? j + 1 :
10648 i == Xsand_stonein_2 ? j + 9 :
10649 i == Xsand_stonein_3 ? j + 17 :
10650 i == Xsand_stonein_4 ? j + 25 :
10651 i == Xsand_stoneout_1 && j == 0 ? 0 :
10652 i == Xsand_stoneout_1 && j == 1 ? 0 :
10653 i == Xsand_stoneout_1 && j == 2 ? 1 :
10654 i == Xsand_stoneout_1 && j == 3 ? 2 :
10655 i == Xsand_stoneout_1 && j == 4 ? 2 :
10656 i == Xsand_stoneout_1 && j == 5 ? 3 :
10657 i == Xsand_stoneout_1 && j == 6 ? 4 :
10658 i == Xsand_stoneout_1 && j == 7 ? 4 :
10659 i == Xsand_stoneout_2 && j == 0 ? 5 :
10660 i == Xsand_stoneout_2 && j == 1 ? 6 :
10661 i == Xsand_stoneout_2 && j == 2 ? 7 :
10662 i == Xsand_stoneout_2 && j == 3 ? 8 :
10663 i == Xsand_stoneout_2 && j == 4 ? 9 :
10664 i == Xsand_stoneout_2 && j == 5 ? 11 :
10665 i == Xsand_stoneout_2 && j == 6 ? 13 :
10666 i == Xsand_stoneout_2 && j == 7 ? 15 :
10667 i == Xboom_bug && j == 1 ? 2 :
10668 i == Xboom_bug && j == 2 ? 2 :
10669 i == Xboom_bug && j == 3 ? 4 :
10670 i == Xboom_bug && j == 4 ? 4 :
10671 i == Xboom_bug && j == 5 ? 2 :
10672 i == Xboom_bug && j == 6 ? 2 :
10673 i == Xboom_bug && j == 7 ? 0 :
10674 i == Xboom_bomb && j == 1 ? 2 :
10675 i == Xboom_bomb && j == 2 ? 2 :
10676 i == Xboom_bomb && j == 3 ? 4 :
10677 i == Xboom_bomb && j == 4 ? 4 :
10678 i == Xboom_bomb && j == 5 ? 2 :
10679 i == Xboom_bomb && j == 6 ? 2 :
10680 i == Xboom_bomb && j == 7 ? 0 :
10681 i == Xboom_android && j == 7 ? 6 :
10682 i == Xboom_1 && j == 1 ? 2 :
10683 i == Xboom_1 && j == 2 ? 2 :
10684 i == Xboom_1 && j == 3 ? 4 :
10685 i == Xboom_1 && j == 4 ? 4 :
10686 i == Xboom_1 && j == 5 ? 6 :
10687 i == Xboom_1 && j == 6 ? 6 :
10688 i == Xboom_1 && j == 7 ? 8 :
10689 i == Xboom_2 && j == 0 ? 8 :
10690 i == Xboom_2 && j == 1 ? 8 :
10691 i == Xboom_2 && j == 2 ? 10 :
10692 i == Xboom_2 && j == 3 ? 10 :
10693 i == Xboom_2 && j == 4 ? 10 :
10694 i == Xboom_2 && j == 5 ? 12 :
10695 i == Xboom_2 && j == 6 ? 12 :
10696 i == Xboom_2 && j == 7 ? 12 :
10697 special_animation && j == 4 ? 3 :
10698 effective_action != action ? 0 :
10702 Bitmap *debug_bitmap = g_em->bitmap;
10703 int debug_src_x = g_em->src_x;
10704 int debug_src_y = g_em->src_y;
10707 int frame = getAnimationFrame(g->anim_frames,
10710 g->anim_start_frame,
10713 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
10714 g->double_movement && is_backside);
10716 g_em->bitmap = src_bitmap;
10717 g_em->src_x = src_x;
10718 g_em->src_y = src_y;
10719 g_em->src_offset_x = 0;
10720 g_em->src_offset_y = 0;
10721 g_em->dst_offset_x = 0;
10722 g_em->dst_offset_y = 0;
10723 g_em->width = TILEX;
10724 g_em->height = TILEY;
10726 g_em->preserve_background = FALSE;
10729 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10734 g_em->crumbled_bitmap = NULL;
10735 g_em->crumbled_src_x = 0;
10736 g_em->crumbled_src_y = 0;
10737 g_em->crumbled_border_size = 0;
10739 g_em->has_crumbled_graphics = FALSE;
10742 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
10743 printf("::: empty crumbled: %d [%s], %d, %d\n",
10744 effective_element, element_info[effective_element].token_name,
10745 effective_action, direction);
10748 /* if element can be crumbled, but certain action graphics are just empty
10749 space (like instantly snapping sand to empty space in 1 frame), do not
10750 treat these empty space graphics as crumbled graphics in EMC engine */
10751 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10753 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10754 g_crumbled->anim_delay,
10755 g_crumbled->anim_mode,
10756 g_crumbled->anim_start_frame,
10759 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
10761 g_em->has_crumbled_graphics = TRUE;
10762 g_em->crumbled_bitmap = src_bitmap;
10763 g_em->crumbled_src_x = src_x;
10764 g_em->crumbled_src_y = src_y;
10765 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
10769 if (g_em == &graphic_info_em_object[207][0])
10770 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
10771 graphic_info_em_object[207][0].crumbled_src_x,
10772 graphic_info_em_object[207][0].crumbled_src_y,
10774 crumbled, frame, src_x, src_y,
10779 g->anim_start_frame,
10781 gfx.anim_random_frame,
10786 printf("::: EMC tile %d is crumbled\n", i);
10792 if (element == EL_ROCK &&
10793 effective_action == ACTION_FILLING)
10794 printf("::: has_action_graphics == %d\n", has_action_graphics);
10797 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10798 effective_action == ACTION_MOVING ||
10799 effective_action == ACTION_PUSHING ||
10800 effective_action == ACTION_EATING)) ||
10801 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10802 effective_action == ACTION_EMPTYING)))
10805 (effective_action == ACTION_FALLING ||
10806 effective_action == ACTION_FILLING ||
10807 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10808 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10809 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10810 int num_steps = (i == Ydrip_s1 ? 16 :
10811 i == Ydrip_s1B ? 16 :
10812 i == Ydrip_s2 ? 16 :
10813 i == Ydrip_s2B ? 16 :
10814 i == Xsand_stonein_1 ? 32 :
10815 i == Xsand_stonein_2 ? 32 :
10816 i == Xsand_stonein_3 ? 32 :
10817 i == Xsand_stonein_4 ? 32 :
10818 i == Xsand_stoneout_1 ? 16 :
10819 i == Xsand_stoneout_2 ? 16 : 8);
10820 int cx = ABS(dx) * (TILEX / num_steps);
10821 int cy = ABS(dy) * (TILEY / num_steps);
10822 int step_frame = (i == Ydrip_s2 ? j + 8 :
10823 i == Ydrip_s2B ? j + 8 :
10824 i == Xsand_stonein_2 ? j + 8 :
10825 i == Xsand_stonein_3 ? j + 16 :
10826 i == Xsand_stonein_4 ? j + 24 :
10827 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10828 int step = (is_backside ? step_frame : num_steps - step_frame);
10830 if (is_backside) /* tile where movement starts */
10832 if (dx < 0 || dy < 0)
10834 g_em->src_offset_x = cx * step;
10835 g_em->src_offset_y = cy * step;
10839 g_em->dst_offset_x = cx * step;
10840 g_em->dst_offset_y = cy * step;
10843 else /* tile where movement ends */
10845 if (dx < 0 || dy < 0)
10847 g_em->dst_offset_x = cx * step;
10848 g_em->dst_offset_y = cy * step;
10852 g_em->src_offset_x = cx * step;
10853 g_em->src_offset_y = cy * step;
10857 g_em->width = TILEX - cx * step;
10858 g_em->height = TILEY - cy * step;
10861 /* create unique graphic identifier to decide if tile must be redrawn */
10862 /* bit 31 - 16 (16 bit): EM style graphic
10863 bit 15 - 12 ( 4 bit): EM style frame
10864 bit 11 - 6 ( 6 bit): graphic width
10865 bit 5 - 0 ( 6 bit): graphic height */
10866 g_em->unique_identifier =
10867 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10871 /* skip check for EMC elements not contained in original EMC artwork */
10872 if (element == EL_EMC_FAKE_ACID)
10875 if (g_em->bitmap != debug_bitmap ||
10876 g_em->src_x != debug_src_x ||
10877 g_em->src_y != debug_src_y ||
10878 g_em->src_offset_x != 0 ||
10879 g_em->src_offset_y != 0 ||
10880 g_em->dst_offset_x != 0 ||
10881 g_em->dst_offset_y != 0 ||
10882 g_em->width != TILEX ||
10883 g_em->height != TILEY)
10885 static int last_i = -1;
10893 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
10894 i, element, element_info[element].token_name,
10895 element_action_info[effective_action].suffix, direction);
10897 if (element != effective_element)
10898 printf(" [%d ('%s')]",
10900 element_info[effective_element].token_name);
10904 if (g_em->bitmap != debug_bitmap)
10905 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
10906 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
10908 if (g_em->src_x != debug_src_x ||
10909 g_em->src_y != debug_src_y)
10910 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10911 j, (is_backside ? 'B' : 'F'),
10912 g_em->src_x, g_em->src_y,
10913 g_em->src_x / 32, g_em->src_y / 32,
10914 debug_src_x, debug_src_y,
10915 debug_src_x / 32, debug_src_y / 32);
10917 if (g_em->src_offset_x != 0 ||
10918 g_em->src_offset_y != 0 ||
10919 g_em->dst_offset_x != 0 ||
10920 g_em->dst_offset_y != 0)
10921 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
10923 g_em->src_offset_x, g_em->src_offset_y,
10924 g_em->dst_offset_x, g_em->dst_offset_y);
10926 if (g_em->width != TILEX ||
10927 g_em->height != TILEY)
10928 printf(" %d (%d): size %d,%d should be %d,%d\n",
10930 g_em->width, g_em->height, TILEX, TILEY);
10932 num_em_gfx_errors++;
10939 for (i = 0; i < TILE_MAX; i++)
10941 for (j = 0; j < 8; j++)
10943 int element = object_mapping[i].element_rnd;
10944 int action = object_mapping[i].action;
10945 int direction = object_mapping[i].direction;
10946 boolean is_backside = object_mapping[i].is_backside;
10947 int graphic_action = el_act_dir2img(element, action, direction);
10948 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
10950 if ((action == ACTION_SMASHED_BY_ROCK ||
10951 action == ACTION_SMASHED_BY_SPRING ||
10952 action == ACTION_EATING) &&
10953 graphic_action == graphic_default)
10955 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
10956 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
10957 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
10958 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
10961 /* no separate animation for "smashed by rock" -- use rock instead */
10962 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10963 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
10965 g_em->bitmap = g_xx->bitmap;
10966 g_em->src_x = g_xx->src_x;
10967 g_em->src_y = g_xx->src_y;
10968 g_em->src_offset_x = g_xx->src_offset_x;
10969 g_em->src_offset_y = g_xx->src_offset_y;
10970 g_em->dst_offset_x = g_xx->dst_offset_x;
10971 g_em->dst_offset_y = g_xx->dst_offset_y;
10972 g_em->width = g_xx->width;
10973 g_em->height = g_xx->height;
10974 g_em->unique_identifier = g_xx->unique_identifier;
10977 g_em->preserve_background = TRUE;
10982 for (p = 0; p < MAX_PLAYERS; p++)
10984 for (i = 0; i < SPR_MAX; i++)
10986 int element = player_mapping[p][i].element_rnd;
10987 int action = player_mapping[p][i].action;
10988 int direction = player_mapping[p][i].direction;
10990 for (j = 0; j < 8; j++)
10992 int effective_element = element;
10993 int effective_action = action;
10994 int graphic = (direction == MV_NONE ?
10995 el_act2img(effective_element, effective_action) :
10996 el_act_dir2img(effective_element, effective_action,
10998 struct GraphicInfo *g = &graphic_info[graphic];
10999 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
11000 Bitmap *src_bitmap;
11002 int sync_frame = j;
11005 Bitmap *debug_bitmap = g_em->bitmap;
11006 int debug_src_x = g_em->src_x;
11007 int debug_src_y = g_em->src_y;
11010 int frame = getAnimationFrame(g->anim_frames,
11013 g->anim_start_frame,
11016 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
11018 g_em->bitmap = src_bitmap;
11019 g_em->src_x = src_x;
11020 g_em->src_y = src_y;
11021 g_em->src_offset_x = 0;
11022 g_em->src_offset_y = 0;
11023 g_em->dst_offset_x = 0;
11024 g_em->dst_offset_y = 0;
11025 g_em->width = TILEX;
11026 g_em->height = TILEY;
11030 /* skip check for EMC elements not contained in original EMC artwork */
11031 if (element == EL_PLAYER_3 ||
11032 element == EL_PLAYER_4)
11035 if (g_em->bitmap != debug_bitmap ||
11036 g_em->src_x != debug_src_x ||
11037 g_em->src_y != debug_src_y)
11039 static int last_i = -1;
11047 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
11048 p, i, element, element_info[element].token_name,
11049 element_action_info[effective_action].suffix, direction);
11051 if (element != effective_element)
11052 printf(" [%d ('%s')]",
11054 element_info[effective_element].token_name);
11058 if (g_em->bitmap != debug_bitmap)
11059 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
11060 j, (int)(g_em->bitmap), (int)(debug_bitmap));
11062 if (g_em->src_x != debug_src_x ||
11063 g_em->src_y != debug_src_y)
11064 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
11066 g_em->src_x, g_em->src_y,
11067 g_em->src_x / 32, g_em->src_y / 32,
11068 debug_src_x, debug_src_y,
11069 debug_src_x / 32, debug_src_y / 32);
11071 num_em_gfx_errors++;
11081 printf("::: [%d errors found]\n", num_em_gfx_errors);
11087 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
11088 boolean any_player_moving,
11089 boolean player_is_dropping)
11091 if (tape.single_step && tape.recording && !tape.pausing)
11094 boolean active_players = FALSE;
11097 for (i = 0; i < MAX_PLAYERS; i++)
11098 if (action[i] != JOY_NO_ACTION)
11099 active_players = TRUE;
11103 if (frame == 0 && !player_is_dropping)
11104 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11108 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
11109 boolean murphy_is_dropping)
11112 printf("::: waiting: %d, dropping: %d\n",
11113 murphy_is_waiting, murphy_is_dropping);
11116 if (tape.single_step && tape.recording && !tape.pausing)
11118 // if (murphy_is_waiting || murphy_is_dropping)
11119 if (murphy_is_waiting)
11122 printf("::: murphy is waiting -> pause mode\n");
11125 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11130 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
11131 int graphic, int sync_frame, int x, int y)
11133 int frame = getGraphicAnimationFrame(graphic, sync_frame);
11135 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
11138 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
11140 return (IS_NEXT_FRAME(sync_frame, graphic));
11143 int getGraphicInfo_Delay(int graphic)
11145 return graphic_info[graphic].anim_delay;
11148 void PlayMenuSoundExt(int sound)
11150 if (sound == SND_UNDEFINED)
11153 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11154 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11157 if (IS_LOOP_SOUND(sound))
11158 PlaySoundLoop(sound);
11163 void PlayMenuSound()
11165 PlayMenuSoundExt(menu.sound[game_status]);
11168 void PlayMenuSoundStereo(int sound, int stereo_position)
11170 if (sound == SND_UNDEFINED)
11173 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11174 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11177 if (IS_LOOP_SOUND(sound))
11178 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
11180 PlaySoundStereo(sound, stereo_position);
11183 void PlayMenuSoundIfLoopExt(int sound)
11185 if (sound == SND_UNDEFINED)
11188 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11189 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11192 if (IS_LOOP_SOUND(sound))
11193 PlaySoundLoop(sound);
11196 void PlayMenuSoundIfLoop()
11198 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
11201 void PlayMenuMusicExt(int music)
11203 if (music == MUS_UNDEFINED)
11206 if (!setup.sound_music)
11212 void PlayMenuMusic()
11214 PlayMenuMusicExt(menu.music[game_status]);
11217 void PlaySoundActivating()
11220 PlaySound(SND_MENU_ITEM_ACTIVATING);
11224 void PlaySoundSelecting()
11227 PlaySound(SND_MENU_ITEM_SELECTING);
11231 void ToggleFullscreenOrChangeWindowScalingIfNeeded()
11233 boolean change_fullscreen = (setup.fullscreen !=
11234 video.fullscreen_enabled);
11235 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
11236 !strEqual(setup.fullscreen_mode,
11237 video.fullscreen_mode_current));
11238 boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
11239 setup.window_scaling_percent !=
11240 video.window_scaling_percent);
11242 if (change_window_scaling_percent && video.fullscreen_enabled)
11245 if (!change_window_scaling_percent && !video.fullscreen_available)
11248 #if defined(TARGET_SDL2)
11249 if (change_window_scaling_percent)
11251 SDLSetWindowScaling(setup.window_scaling_percent);
11255 else if (change_fullscreen)
11257 SDLSetWindowFullscreen(setup.fullscreen);
11259 /* set setup value according to successfully changed fullscreen mode */
11260 setup.fullscreen = video.fullscreen_enabled;
11266 if (change_fullscreen ||
11267 change_fullscreen_mode ||
11268 change_window_scaling_percent)
11270 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
11272 /* save backbuffer content which gets lost when toggling fullscreen mode */
11273 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11275 if (change_fullscreen_mode)
11277 /* keep fullscreen, but change fullscreen mode (screen resolution) */
11278 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
11281 if (change_window_scaling_percent)
11283 /* keep window mode, but change window scaling */
11284 video.fullscreen_enabled = TRUE; /* force new window scaling */
11287 /* toggle fullscreen */
11288 ChangeVideoModeIfNeeded(setup.fullscreen);
11290 /* set setup value according to successfully changed fullscreen mode */
11291 setup.fullscreen = video.fullscreen_enabled;
11293 /* restore backbuffer content from temporary backbuffer backup bitmap */
11294 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11296 FreeBitmap(tmp_backbuffer);
11299 /* update visible window/screen */
11300 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11302 redraw_mask = REDRAW_ALL;
11307 void ChangeViewportPropertiesIfNeeded()
11310 int *door_1_x = &DX;
11311 int *door_1_y = &DY;
11312 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
11313 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
11316 int gfx_game_mode = game_status;
11318 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
11319 game_status == GAME_MODE_EDITOR ? game_status :
11322 int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
11324 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
11325 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
11326 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
11327 struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
11328 int border_size = vp_playfield->border_size;
11329 int new_sx = vp_playfield->x + border_size;
11330 int new_sy = vp_playfield->y + border_size;
11331 int new_sxsize = vp_playfield->width - 2 * border_size;
11332 int new_sysize = vp_playfield->height - 2 * border_size;
11333 int new_real_sx = vp_playfield->x;
11334 int new_real_sy = vp_playfield->y;
11335 int new_full_sxsize = vp_playfield->width;
11336 int new_full_sysize = vp_playfield->height;
11337 int new_dx = vp_door_1->x;
11338 int new_dy = vp_door_1->y;
11339 int new_dxsize = vp_door_1->width;
11340 int new_dysize = vp_door_1->height;
11341 int new_vx = vp_door_2->x;
11342 int new_vy = vp_door_2->y;
11343 int new_vxsize = vp_door_2->width;
11344 int new_vysize = vp_door_2->height;
11345 int new_ex = vp_door_3->x;
11346 int new_ey = vp_door_3->y;
11347 int new_exsize = vp_door_3->width;
11348 int new_eysize = vp_door_3->height;
11350 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
11351 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
11352 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
11353 int new_scr_fieldx = new_sxsize / tilesize;
11354 int new_scr_fieldy = new_sysize / tilesize;
11355 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
11356 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
11358 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
11359 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
11361 boolean init_gfx_buffers = FALSE;
11362 boolean init_video_buffer = FALSE;
11363 boolean init_gadgets_and_toons = FALSE;
11366 /* !!! TEST ONLY !!! */
11367 // InitGfxBuffers();
11371 if (viewport.window.width != WIN_XSIZE ||
11372 viewport.window.height != WIN_YSIZE)
11374 WIN_XSIZE = viewport.window.width;
11375 WIN_YSIZE = viewport.window.height;
11378 init_video_buffer = TRUE;
11379 init_gfx_buffers = TRUE;
11381 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11385 SetDrawDeactivationMask(REDRAW_NONE);
11386 SetDrawBackgroundMask(REDRAW_FIELD);
11388 // RedrawBackground();
11392 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
11395 if (new_scr_fieldx != SCR_FIELDX ||
11396 new_scr_fieldy != SCR_FIELDY)
11398 /* this always toggles between MAIN and GAME when using small tile size */
11400 SCR_FIELDX = new_scr_fieldx;
11401 SCR_FIELDY = new_scr_fieldy;
11403 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
11407 if (new_tilesize_var != TILESIZE_VAR &&
11408 gfx_game_mode == GAME_MODE_PLAYING)
11410 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
11412 TILESIZE_VAR = new_tilesize_var;
11414 init_gfx_buffers = TRUE;
11416 // printf("::: tilesize: init_gfx_buffers\n");
11420 if (new_sx != SX ||
11428 new_sxsize != SXSIZE ||
11429 new_sysize != SYSIZE ||
11430 new_dxsize != DXSIZE ||
11431 new_dysize != DYSIZE ||
11432 new_vxsize != VXSIZE ||
11433 new_vysize != VYSIZE ||
11434 new_exsize != EXSIZE ||
11435 new_eysize != EYSIZE ||
11436 new_real_sx != REAL_SX ||
11437 new_real_sy != REAL_SY ||
11438 new_full_sxsize != FULL_SXSIZE ||
11439 new_full_sysize != FULL_SYSIZE ||
11440 new_tilesize_var != TILESIZE_VAR
11443 vp_door_1->x != *door_1_x ||
11444 vp_door_1->y != *door_1_y ||
11445 vp_door_2->x != *door_2_x ||
11446 vp_door_2->y != *door_2_y
11458 SXSIZE = new_sxsize;
11459 SYSIZE = new_sysize;
11460 DXSIZE = new_dxsize;
11461 DYSIZE = new_dysize;
11462 VXSIZE = new_vxsize;
11463 VYSIZE = new_vysize;
11464 EXSIZE = new_exsize;
11465 EYSIZE = new_eysize;
11466 REAL_SX = new_real_sx;
11467 REAL_SY = new_real_sy;
11468 FULL_SXSIZE = new_full_sxsize;
11469 FULL_SYSIZE = new_full_sysize;
11470 TILESIZE_VAR = new_tilesize_var;
11473 printf("::: %d, %d, %d [%d]\n",
11474 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
11475 setup.small_game_graphics);
11479 *door_1_x = vp_door_1->x;
11480 *door_1_y = vp_door_1->y;
11481 *door_2_x = vp_door_2->x;
11482 *door_2_y = vp_door_2->y;
11486 init_gfx_buffers = TRUE;
11488 // printf("::: viewports: init_gfx_buffers\n");
11494 if (gfx_game_mode == GAME_MODE_MAIN)
11498 init_gadgets_and_toons = TRUE;
11500 // printf("::: viewports: init_gadgets_and_toons\n");
11508 if (init_gfx_buffers)
11510 // printf("::: init_gfx_buffers\n");
11512 SCR_FIELDX = new_scr_fieldx_buffers;
11513 SCR_FIELDY = new_scr_fieldy_buffers;
11517 SCR_FIELDX = new_scr_fieldx;
11518 SCR_FIELDY = new_scr_fieldy;
11521 if (init_video_buffer)
11523 // printf("::: init_video_buffer\n");
11525 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11527 SetDrawDeactivationMask(REDRAW_NONE);
11528 SetDrawBackgroundMask(REDRAW_FIELD);
11531 if (init_gadgets_and_toons)
11533 // printf("::: init_gadgets_and_toons\n");
11540 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);