updated contact info in source file headers
[rocksndiamonds.git] / src / tools.c
index 2dd6d5bbac7a3019ad15a5b0d325b9add979da66..0a90d675befda42be650718dc64515d66386981f 100644 (file)
@@ -1,15 +1,13 @@
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
-*----------------------------------------------------------*
-* (c) 1995-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info@artsoft.org                   *
-*----------------------------------------------------------*
-* tools.c                                                  *
-***********************************************************/
+// ============================================================================
+// Rocks'n'Diamonds - McDuffin Strikes Back!
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                         Holger Schemel
+//                 info@artsoft.org
+//                 http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// tools.c
+// ============================================================================
 
 #include <math.h>
 
@@ -296,6 +294,68 @@ void SetDrawtoField(int mode)
   }
 }
 
+#if 1
+
+static void RedrawPlayfield_RND()
+{
+  if (game.envelope_active)
+    return;
+
+#if 1
+  DrawLevel(REDRAW_ALL);
+#else
+  int x, y;
+
+  SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
+  // SetDrawBackgroundMask(REDRAW_FIELD);      // !!! CHECK THIS !!!
+  SetDrawBackgroundMask(REDRAW_ALL);   // !!! CHECK THIS !!!
+
+  for (x = BX1; x <= BX2; x++)
+    for (y = BY1; y <= BY2; y++)
+      DrawScreenField(x, y);
+
+  redraw_mask |= REDRAW_FIELD;
+#endif
+  DrawAllPlayers();
+
+#if 0
+#if NEW_TILESIZE
+  BlitScreenToBitmap(backbuffer);
+#else
+  /* blit playfield from scroll buffer to normal back buffer */
+  if (setup.soft_scrolling)
+  {
+    int fx = FX, fy = FY;
+
+    fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
+    fy += (ScreenMovDir & (MV_UP|MV_DOWN)    ? ScreenGfxPos : 0);
+
+    BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
+  }
+#endif
+#endif
+}
+
+void RedrawPlayfield()
+{
+  if (game_status != GAME_MODE_PLAYING)
+    return;
+
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    RedrawPlayfield_EM(TRUE);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    RedrawPlayfield_SP(TRUE);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
+    RedrawPlayfield_RND();
+
+  BlitScreenToBitmap(backbuffer);
+
+  BlitBitmap(drawto, window, gfx.sx, gfx.sy, gfx.sxsize, gfx.sysize,
+            gfx.sx, gfx.sy);
+}
+
+#else
+
 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
 {
   if (game_status == GAME_MODE_PLAYING &&
@@ -362,6 +422,8 @@ void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
   BlitBitmap(drawto, window, x, y, width, height, x, y);
 }
 
+#endif
+
 void DrawMaskedBorder_Rect(int x, int y, int width, int height)
 {
   Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap;
@@ -433,10 +495,12 @@ void DrawMaskedBorder(int redraw_mask)
   }
 }
 
-void BlitScreenToBitmap(Bitmap *target_bitmap)
+static void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
 {
   DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
   int fx = FX, fy = FY;
+  int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
+  int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
 
 #if NEW_TILESIZE
   int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
@@ -487,6 +551,28 @@ void BlitScreenToBitmap(Bitmap *target_bitmap)
         fx, fy);
 #endif
 
+#if 1
+  if (full_lev_fieldx <= SCR_FIELDX)
+  {
+    // printf(":1: PLAYFIELD FITS TO SCREEN [%d, %d, %d]\n", fx, ffx, dx_var);
+
+    if (EVEN(SCR_FIELDX))
+      fx = 2 * TILEX_VAR - (ODD(lev_fieldx)  ? TILEX_VAR / 2 : 0);
+    else
+      fx = 2 * TILEX_VAR - (EVEN(lev_fieldx) ? TILEX_VAR / 2 : 0);
+
+    // printf(":2: PLAYFIELD FITS TO SCREEN [%d, %d, %d]\n", fx, ffx, dx_var);
+  }
+
+  if (full_lev_fieldy <= SCR_FIELDY)
+  {
+    if (EVEN(SCR_FIELDY))
+      fy = 2 * TILEY_VAR - (ODD(lev_fieldy)  ? TILEY_VAR / 2 : 0);
+    else
+      fy = 2 * TILEY_VAR - (EVEN(lev_fieldy) ? TILEY_VAR / 2 : 0);
+  }
+#endif
+
   if (border.draw_masked[GAME_MODE_PLAYING])
   {
     if (buffer != backbuffer)
@@ -506,6 +592,16 @@ void BlitScreenToBitmap(Bitmap *target_bitmap)
   }
 }
 
+void BlitScreenToBitmap(Bitmap *target_bitmap)
+{
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    BlitScreenToBitmap_EM(target_bitmap);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    BlitScreenToBitmap_SP(target_bitmap);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
+    BlitScreenToBitmap_RND(target_bitmap);
+}
+
 void BackToFront()
 {
   int x, y;
@@ -615,15 +711,37 @@ void BackToFront()
 
   if (redraw_mask & REDRAW_ALL)
   {
+#if 0
+    if (game_status != GAME_MODE_PLAYING ||
+       redraw_mask & REDRAW_FROM_BACKBUFFER)
+    {
+#if 0
+      printf("::: REDRAW_ALL [%d]\n", FrameCounter);
+#endif
+
+      BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+      redraw_mask = REDRAW_NONE;
+    }
+    else
+    {
+      redraw_mask &= ~REDRAW_ALL;
+    }
+#else
+#if 0
+    printf("::: REDRAW_ALL [%d]\n", FrameCounter);
+#endif
+
     BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
 
     redraw_mask = REDRAW_NONE;
+#endif
   }
 
   if (redraw_mask & REDRAW_FIELD)
   {
 #if 0
-    printf("::: REDRAW_FIELD\n");
+    printf("::: REDRAW_FIELD [%d]\n", FrameCounter);
 #endif
 
     if (game_status != GAME_MODE_PLAYING ||
@@ -635,7 +753,7 @@ void BackToFront()
     else
     {
 #if 1
-      BlitScreenToBitmap(window);
+      BlitScreenToBitmap_RND(window);
 #else
       int fx = FX, fy = FY;
 
@@ -1017,11 +1135,28 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
       ClearRectangle(backbuffer, x, y, width, height);
 #endif
 
+#if 1
+
+#if 1
+    BlitBitmap(backbuffer, window, x, y, width, height, x, y);
+
+    redraw_mask &= ~fade_mask;
+#else
+    /* always redraw area that was explicitly marked to fade */
+    redraw_mask |= fade_mask;
+
+    BackToFront();
+#endif
+
+#else
+
 #if 1
     BlitBitmap(backbuffer, window, x, y, width, height, x, y);
     redraw_mask = REDRAW_NONE;
+    // (^^^ WRONG; should be "redraw_mask &= ~fade_mask" if done this way)
 #else
     BackToFront();
+#endif
 #endif
 
     return;
@@ -1383,12 +1518,28 @@ void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
   Bitmap *src_bitmap = g->bitmap;
   int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
   int offset_calc_pos = log_2(tilesize);
+  int bitmap_width  = src_bitmap->width;
+  int bitmap_height = src_bitmap->height;
   int width_mult  = offset_calc[offset_calc_pos].width_mult;
   int width_div   = offset_calc[offset_calc_pos].width_div;
   int height_mult = offset_calc[offset_calc_pos].height_mult;
   int height_div  = offset_calc[offset_calc_pos].height_div;
-  int startx = src_bitmap->width * width_mult / width_div;
-  int starty = src_bitmap->height * height_mult / height_div;
+  int startx = bitmap_width * width_mult / width_div;
+  int starty = bitmap_height * height_mult / height_div;
+
+#if NEW_GAME_TILESIZE
+
+  int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
+    tilesize_raw / TILESIZE;
+  int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
+    tilesize_raw / TILESIZE;
+  int width = g->width * tilesize_raw / TILESIZE;
+  int height = g->height * tilesize_raw / TILESIZE;
+  int offset_x = g->offset_x * tilesize_raw / TILESIZE;
+  int offset_y = g->offset_y * tilesize_raw / TILESIZE;
+
+#else
+
 #if NEW_TILESIZE
   int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
     tilesize / TILESIZE;
@@ -1403,6 +1554,34 @@ void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
   int offset_x = g->offset_x * tilesize / TILESIZE;
   int offset_y = g->offset_y * tilesize / TILESIZE;
 
+#endif
+
+#if NEW_GAME_TILESIZE
+  if (game.tile_size != TILESIZE)
+  {
+    int bitmap_width_std =
+      bitmap_width * TILESIZE / (TILESIZE + game.tile_size);
+    int bitmap_height_std =
+      bitmap_height * TILESIZE / game.tile_size * 3 / 2;
+
+    if (tilesize_raw == game.tile_size)
+    {
+      startx = bitmap_width_std;
+      starty = 0;
+    }
+    else
+    {
+      bitmap_width = bitmap_width_std;
+
+      if (game.tile_size > TILESIZE * 3 / 2)
+       bitmap_height = bitmap_height_std;
+
+      startx = bitmap_width * width_mult / width_div;
+      starty = bitmap_height * height_mult / height_div;
+    }
+  }
+#endif
+
   if (g->offset_y == 0)                /* frames are ordered horizontally */
   {
     int max_width = g->anim_frames_per_line * width;
@@ -2053,8 +2232,8 @@ static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
 #if NEW_TILESIZE
   width  = crumbled_border_size * TILESIZE_VAR / TILESIZE;
   height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
-  cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
-  cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
+  cx = (dx > 0 ? TILESIZE_VAR - width  : 0);
+  cy = (dy > 0 ? TILESIZE_VAR - height : 0);
 
   BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
             width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
@@ -2077,6 +2256,8 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
   int width, height, bx, by, cx, cy;
   int sx = SCREENX(x), sy = SCREENY(y);
   int crumbled_border_size = graphic_info[graphic].border_size;
+  int crumbled_border_size_var = crumbled_border_size * TILESIZE_VAR / TILESIZE;
+  int crumbled_border_pos_var = TILESIZE_VAR - crumbled_border_size_var;
   int i;
 
   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
@@ -2084,10 +2265,10 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
   /* draw simple, sloppy, non-corner-accurate crumbled border */
 
 #if 1
-  width  = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
-  height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
-  cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
-  cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
+  width  = (dir == 1 || dir == 2 ? crumbled_border_size_var : TILESIZE_VAR);
+  height = (dir == 0 || dir == 3 ? crumbled_border_size_var : TILESIZE_VAR);
+  cx = (dir == 2 ? crumbled_border_pos_var : 0);
+  cy = (dir == 3 ? crumbled_border_pos_var : 0);
 #else
   if (dir == 1 || dir == 2)            /* left or right crumbled border */
   {
@@ -2107,12 +2288,12 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
 
 #if NEW_TILESIZE
   BlitBitmap(src_bitmap, drawto_field,
-            src_x + cx * TILESIZE_VAR / TILESIZE,
-            src_y + cy * TILESIZE_VAR / TILESIZE,
-            width * TILESIZE_VAR / TILESIZE,
-            height * TILESIZE_VAR / TILESIZE,
-            FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
-            FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
+            src_x + cx,
+            src_y + cy,
+            width,
+            height,
+            FX + sx * TILEX_VAR + cx,
+            FY + sy * TILEY_VAR + cy);
 #else
   BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
             width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
@@ -2126,7 +2307,7 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
   /* correct corners of crumbled border, if needed */
 
 #if 1
-  for (i = -1; i <= 1; i+=2)
+  for (i = -1; i <= 1; i += 2)
   {
     int xx = x + (dir == 0 || dir == 3 ? i : 0);
     int yy = y + (dir == 1 || dir == 2 ? i : 0);
@@ -2140,13 +2321,13 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
     {
       /* no crumbled corner, but continued crumbled border */
 
-      int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
-      int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
-      int b1 = (i == 1 ? crumbled_border_size :
-               TILESIZE - 2 * crumbled_border_size);
+      int c1 = (dir == 2 || dir == 3 ? crumbled_border_pos_var : 0);
+      int c2 = (i == 1 ? crumbled_border_pos_var : 0);
+      int b1 = (i == 1 ? crumbled_border_size_var :
+               TILESIZE_VAR - 2 * crumbled_border_size_var);
 
-      width  = crumbled_border_size;
-      height = crumbled_border_size;
+      width  = crumbled_border_size_var;
+      height = crumbled_border_size_var;
 
       if (dir == 1 || dir == 2)
       {
@@ -2165,12 +2346,12 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
 
 #if NEW_TILESIZE
       BlitBitmap(src_bitmap, drawto_field,
-                src_x + bx * TILESIZE_VAR / TILESIZE,
-                src_y + by * TILESIZE_VAR / TILESIZE,
-                width * TILESIZE_VAR / TILESIZE,
-                height * TILESIZE_VAR / TILESIZE,
-                FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
-                FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
+                src_x + bx,
+                src_y + by,
+                width,
+                height,
+                FX + sx * TILEX_VAR + cx,
+                FY + sy * TILEY_VAR + cy);
 #else
       BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
                 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
@@ -2972,10 +3153,11 @@ void AnimateEnvelopeRequest(int anim_mode, int action)
               dst_x + xsize_size_left, dst_y + ysize_size_top);
 #endif
 
-#if 1
+#if 0
     redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
     // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
 #else
+  /* CHECK AGAIN (previous code reactivated) */
     redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
 #endif
 
@@ -3232,6 +3414,18 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
 #if 1
   if (game_status == GAME_MODE_PLAYING)
   {
+#if 1
+#if 1
+    BlitScreenToBitmap(backbuffer);
+#else
+    if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+      BlitScreenToBitmap_EM(backbuffer);
+    else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+      BlitScreenToBitmap_SP(backbuffer);
+    else
+      BlitScreenToBitmap_RND(backbuffer);
+#endif
+#else
     if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
       BlitScreenToBitmap_EM(backbuffer);
     else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
@@ -3240,6 +3434,7 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
     {
       BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
     }
+#endif
   }
 
   SetDrawtoField(DRAW_BACKBUFFER);
@@ -3317,6 +3512,11 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
 #if 1
   // game_status = last_game_status;   /* restore current game status */
 
+#if 1
+  /* !!! CHECK AGAIN (SEE BELOW) !!! */
+  game_status = last_game_status;      /* restore current game status */
+#endif
+
   if (action == ACTION_CLOSING)
   {
     if (game_status != GAME_MODE_MAIN)
@@ -3330,10 +3530,11 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
 
   // SetDrawBackgroundMask(last_draw_background_mask);
 
-#if 1
+#if 0
   redraw_mask = REDRAW_FIELD;
   // redraw_mask |= REDRAW_ALL;
 #else
+  /* CHECK AGAIN (previous code reactivated) */
   redraw_mask |= REDRAW_FIELD;
 #endif
 
@@ -3343,8 +3544,10 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
 
   BackToFront();
 
+#if 0
   /* (important: after "BackToFront()", but before "SetDrawtoField()") */
   game_status = last_game_status;      /* restore current game status */
+#endif
 
 #if 1
   if (action == ACTION_CLOSING &&
@@ -3376,15 +3579,20 @@ void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
   BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
 }
 
-void DrawLevel()
+void DrawLevel(int draw_background_mask)
 {
   int x,y;
 
+#if 1
+  SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
+  SetDrawBackgroundMask(draw_background_mask);
+#else
 #if 1
   SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
   SetDrawBackgroundMask(REDRAW_FIELD);
 #else
   SetDrawBackgroundMask(REDRAW_NONE);
+#endif
 #endif
 
   ClearField();
@@ -3417,14 +3625,28 @@ static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
   int preview_height = preview.ysize * tile_size;
   int real_preview_xsize = MIN(level_xsize, preview.xsize);
   int real_preview_ysize = MIN(level_ysize, preview.ysize);
+  int real_preview_width  = real_preview_xsize * tile_size;
+  int real_preview_height = real_preview_ysize * tile_size;
   int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
   int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
   int x, y;
 
+#if 1
+  if (!IN_GFX_FIELD_FULL(dst_x, dst_y + preview_height - 1))
+    return;
+#endif
+
+#if 0
+  dst_x += (preview_width  - real_preview_width)  / 2;
+  dst_y += (preview_height - real_preview_height) / 2;
+
+  DrawBackground(dst_x, dst_y, real_preview_width, real_preview_height);
+#else
   DrawBackground(dst_x, dst_y, preview_width, preview_height);
 
-  dst_x += (preview_width  - real_preview_xsize * tile_size) / 2;
-  dst_y += (preview_height - real_preview_ysize * tile_size) / 2;
+  dst_x += (preview_width  - real_preview_width)  / 2;
+  dst_y += (preview_height - real_preview_height) / 2;
+#endif
 
   for (x = 0; x < real_preview_xsize; x++)
   {
@@ -3476,6 +3698,9 @@ static void DrawPreviewLevelLabelExt(int mode)
   int font_nr = pos->font;
   int i;
 
+  if (!IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
+    return;
+
   if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
       mode == MICROLABEL_IMPORTED_FROM_HEAD ||
       mode == MICROLABEL_IMPORTED_BY_HEAD)
@@ -3615,7 +3840,8 @@ static void DrawPreviewLevelExt(boolean restart)
       label_text[max_len_label_text] = '\0';
 
 #if 1
-      DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
+      if (IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
+       DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
 #else
       lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
       lypos = SY + MICROLABEL1_YPOS;
@@ -4417,6 +4643,9 @@ static int RequestHandleEvents(unsigned int req_state)
              break;
 
            case KSYM_Return:
+#if defined(TARGET_SDL2)
+           case KSYM_Menu:
+#endif
              result = 1;
              break;
 
@@ -4514,10 +4743,14 @@ static boolean RequestDoor(char *text, unsigned int req_state)
 
   if (game_status == GAME_MODE_PLAYING)
   {
+#if 1
+    BlitScreenToBitmap(backbuffer);
+#else
     if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
       BlitScreenToBitmap_EM(backbuffer);
     else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
       BlitScreenToBitmap_SP(backbuffer);
+#endif
   }
 
   /* disable deactivated drawing when quick-loading level tape recording */
@@ -4550,9 +4783,14 @@ static boolean RequestDoor(char *text, unsigned int req_state)
     CloseDoor(DOOR_CLOSE_1);
 
     /* save old door content */
+#if 1
+    BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
+              0 * DXSIZE, 0, DXSIZE, DYSIZE, 1 * DXSIZE, 0);
+#else
     BlitBitmap(bitmap_db_door, bitmap_db_door,
               DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
               DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
+#endif
   }
 
   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
@@ -4622,9 +4860,13 @@ static boolean RequestDoor(char *text, unsigned int req_state)
   }
 
   /* copy request gadgets to door backbuffer */
+#if 1
+  BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
+#else
   BlitBitmap(drawto, bitmap_db_door,
             DX, DY, DXSIZE, DYSIZE,
             DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+#endif
 
   OpenDoor(DOOR_OPEN_1);
 
@@ -4701,10 +4943,23 @@ static boolean RequestEnvelope(char *text, unsigned int req_state)
 
   if (game_status == GAME_MODE_PLAYING)
   {
+#if 1
+#if 1
+    BlitScreenToBitmap(backbuffer);
+#else
     if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
       BlitScreenToBitmap_EM(backbuffer);
     else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
       BlitScreenToBitmap_SP(backbuffer);
+    else
+      BlitScreenToBitmap_RND(backbuffer);
+#endif
+#else
+    if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+      BlitScreenToBitmap_EM(backbuffer);
+    else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+      BlitScreenToBitmap_SP(backbuffer);
+#endif
   }
 
   /* disable deactivated drawing when quick-loading level tape recording */
@@ -4915,10 +5170,14 @@ boolean Request(char *text, unsigned int req_state)
 
   if (game_status == GAME_MODE_PLAYING)
   {
+#if 1
+    BlitScreenToBitmap(backbuffer);
+#else
     if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
       BlitScreenToBitmap_EM(backbuffer);
     else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
       BlitScreenToBitmap_SP(backbuffer);
+#endif
   }
 
   /* disable deactivated drawing when quick-loading level tape recording */
@@ -5519,6 +5778,15 @@ unsigned int OpenDoor(unsigned int door_state)
 {
   if (door_state & DOOR_COPY_BACK)
   {
+#if 1
+    if (door_state & DOOR_OPEN_1)
+      BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
+                1 * DXSIZE, 0, DXSIZE, DYSIZE, 0 * DXSIZE, 0);
+
+    if (door_state & DOOR_OPEN_2)
+      BlitBitmap(bitmap_db_door_2, bitmap_db_door_2,
+                1 * VXSIZE, 0, VXSIZE, VYSIZE, 0 * VXSIZE, 0);
+#else
     if (door_state & DOOR_OPEN_1)
       BlitBitmap(bitmap_db_door, bitmap_db_door,
                 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
@@ -5528,6 +5796,7 @@ unsigned int OpenDoor(unsigned int door_state)
       BlitBitmap(bitmap_db_door, bitmap_db_door,
                 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
                 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+#endif
 
     door_state &= ~DOOR_COPY_BACK;
   }
@@ -5541,6 +5810,15 @@ unsigned int CloseDoor(unsigned int door_state)
 
   if (!(door_state & DOOR_NO_COPY_BACK))
   {
+#if 1
+    if (old_door_state & DOOR_OPEN_1)
+      BlitBitmap(backbuffer, bitmap_db_door_1,
+                DX, DY, DXSIZE, DYSIZE, 0, 0);
+
+    if (old_door_state & DOOR_OPEN_2)
+      BlitBitmap(backbuffer, bitmap_db_door_2,
+                VX, VY, VXSIZE, VYSIZE, 0, 0);
+#else
     if (old_door_state & DOOR_OPEN_1)
       BlitBitmap(backbuffer, bitmap_db_door,
                 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
@@ -5548,6 +5826,7 @@ unsigned int CloseDoor(unsigned int door_state)
     if (old_door_state & DOOR_OPEN_2)
       BlitBitmap(backbuffer, bitmap_db_door,
                 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+#endif
 
     door_state &= ~DOOR_NO_COPY_BACK;
   }
@@ -5576,11 +5855,13 @@ int euclid(int a, int b)
 
 unsigned int MoveDoor(unsigned int door_state)
 {
+#if 0
   struct XY panel_pos_list[] =
   {
     { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 },
     { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 },
   };
+#endif
   struct Rect door_rect_list[] =
   {
     { DX, DY, DXSIZE, DYSIZE },
@@ -5653,6 +5934,7 @@ unsigned int MoveDoor(unsigned int door_state)
   if (door_state & DOOR_ACTION)
   {
     boolean door_panel_drawn[NUM_DOORS];
+    boolean panel_has_doors[NUM_DOORS];
     boolean door_part_skip[MAX_DOOR_PARTS];
     boolean door_part_done[MAX_DOOR_PARTS];
     boolean door_part_done_all;
@@ -5663,6 +5945,9 @@ unsigned int MoveDoor(unsigned int door_state)
     int current_move_delay = 0;
     int k;
 
+    for (i = 0; i < NUM_DOORS; i++)
+      panel_has_doors[i] = FALSE;
+
     for (i = 0; i < MAX_DOOR_PARTS; i++)
     {
       struct DoorPartControlInfo *dpc = &door_part_controls[i];
@@ -5693,6 +5978,7 @@ unsigned int MoveDoor(unsigned int door_state)
       struct DoorPartPosInfo *pos = dpc->pos;
       struct GraphicInfo *g = &graphic_info[dpc->graphic];
       int door_token = dpc->door_token;
+      int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
       boolean is_panel = DOOR_PART_IS_PANEL(nr);
       int step_xoffset = ABS(pos->step_xoffset);
       int step_yoffset = ABS(pos->step_yoffset);
@@ -5715,6 +6001,9 @@ unsigned int MoveDoor(unsigned int door_state)
       if (door_part_skip[nr])
        continue;
 
+      if (!is_panel)
+       panel_has_doors[door_index] = TRUE;
+
       max_move_delay = MAX(max_move_delay, move_delay);
       max_step_delay = (max_step_delay == 0 ? step_delay :
                        euclid(max_step_delay, step_delay));
@@ -5760,8 +6049,12 @@ unsigned int MoveDoor(unsigned int door_state)
        int door_token = dpc->door_token;
        int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
        boolean is_panel = DOOR_PART_IS_PANEL(nr);
+#if 0
        struct XY *panel_pos = &panel_pos_list[door_index];
+#endif
        struct Rect *door_rect = &door_rect_list[door_index];
+       Bitmap *bitmap_db_door = (door_token == DOOR_1 ? bitmap_db_door_1 :
+                                 bitmap_db_door_2);
        Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
        int current_door_state = door_state & door_token;
        boolean door_opening = ((current_door_state & DOOR_OPEN)  != 0);
@@ -5779,6 +6072,11 @@ unsigned int MoveDoor(unsigned int door_state)
        int dst_x, dst_y, dst_xx, dst_yy;
        int width, height;
 
+#if 0
+       if (k == 0 && is_panel && door_token == DOOR_2)
+         printf("::: %d, %d\n", g->width, g->height);
+#endif
+
 #if 0
        if (DOOR_PART_IS_PANEL(nr))
        {
@@ -5885,8 +6183,13 @@ unsigned int MoveDoor(unsigned int door_state)
 
        if (is_panel)
        {
+#if 1
+         src_x = src_xx;
+         src_y = src_yy;
+#else
          src_x = panel_pos->x + src_xx;
          src_y = panel_pos->y + src_yy;
+#endif
        }
        else
        {
@@ -5946,9 +6249,16 @@ unsigned int MoveDoor(unsigned int door_state)
          door_part_done[nr] = TRUE;
 #endif
 
+#if 1
+       // continue door part animations, but not panel after door has closed
+       if (!door_part_done[nr] &&
+           !(is_panel && door_closing && panel_has_doors[door_index]))
+         door_part_done_all = FALSE;
+#else
        // continue door part animations, but not panel after door has closed
        if (!door_part_done[nr] && !(is_panel && door_closing))
          door_part_done_all = FALSE;
+#endif
 
 #if 0
        if (!door_part_done[nr])
@@ -6748,8 +7058,8 @@ void CreateToolButtons()
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_INFO_TEXT, toolbutton_info[i].infotext,
-                     GDI_X, dx + pos->x,
-                     GDI_Y, dy + pos->y,
+                     GDI_X, dx + GDI_ACTIVE_POS(pos->x),
+                     GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
                      GDI_WIDTH, gfx->width,
                      GDI_HEIGHT, gfx->height,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
@@ -6908,8 +7218,8 @@ void CreateToolButtons()
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_INFO_TEXT, toolbutton_info[i].infotext,
-                     GDI_X, DX + toolbutton_info[i].x,
-                     GDI_Y, DY + toolbutton_info[i].y,
+                     GDI_X, DX + GDI_ACTIVE_POS(toolbutton_info[i].x),
+                     GDI_Y, DY + GDI_ACTIVE_POS(toolbutton_info[i].y),
                      GDI_WIDTH, toolbutton_info[i].width,
                      GDI_HEIGHT, toolbutton_info[i].height,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
@@ -11208,9 +11518,13 @@ void ChangeViewportPropertiesIfNeeded()
   int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
   int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
 #endif
+#if 1
+  int gfx_game_mode = game_status;
+#else
   int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
                       game_status == GAME_MODE_EDITOR ? game_status :
                       GAME_MODE_MAIN);
+#endif
   int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
                        game_status);
   struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
@@ -11239,7 +11553,14 @@ void ChangeViewportPropertiesIfNeeded()
   int new_exsize       = vp_door_3->width;
   int new_eysize       = vp_door_3->height;
 #if NEW_TILESIZE
+
+#if NEW_GAME_TILESIZE
+  int new_tilesize_var =
+    (setup.small_game_graphics ? MINI_TILESIZE : game.tile_size);
+#else
   int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
+#endif
+
   int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
                  gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
   int new_scr_fieldx = new_sxsize / tilesize;
@@ -11253,6 +11574,7 @@ void ChangeViewportPropertiesIfNeeded()
   boolean init_gfx_buffers = FALSE;
   boolean init_video_buffer = FALSE;
   boolean init_gadgets_and_toons = FALSE;
+  boolean init_em_graphics = FALSE;
 
 #if 0
   /* !!! TEST ONLY !!! */
@@ -11339,6 +11661,19 @@ void ChangeViewportPropertiesIfNeeded()
 #endif
       )
   {
+#if 1
+    if (new_tilesize_var != TILESIZE_VAR)
+    {
+      // printf("::: new_tilesize_var != TILESIZE_VAR\n");
+
+      // changing tile size invalidates scroll values of engine snapshots
+      FreeEngineSnapshot();
+
+      // changing tile size requires update of graphic mapping for EM engine
+      init_em_graphics = TRUE;
+    }
+#endif
+
     SX = new_sx;
     SY = new_sy;
     DX = new_dx;
@@ -11382,7 +11717,9 @@ void ChangeViewportPropertiesIfNeeded()
     InitGfxBuffers();
 #endif
 
+#if 0
     if (gfx_game_mode == GAME_MODE_MAIN)
+#endif
     {
 #if 1
       init_gadgets_and_toons = TRUE;
@@ -11426,6 +11763,11 @@ void ChangeViewportPropertiesIfNeeded()
     InitToons();
   }
 
+  if (init_em_graphics)
+  {
+      InitGraphicInfo_EM();
+  }
+
 #if 0
   printf("::: %d, %d  /  %d, %d [%d]\n", VX, VY, EX, EY, game_status);
 #endif