rnd-20140228-1-src
[rocksndiamonds.git] / src / tools.c
index 95f12fc1d5ca157f11fbfea1a3f9ee002e725fc0..0348f112c4f07abe7a21c31f2eb9b2178bb20afe 100644 (file)
@@ -11,6 +11,8 @@
 * tools.c                                                  *
 ***********************************************************/
 
+#include <math.h>
+
 #include "libgame/libgame.h"
 
 #include "tools.h"
 
 #define NUM_TOOL_BUTTONS       7
 
+/* constants for number of doors and door parts */
+#define NUM_DOORS              2
+#define NUM_PANELS             NUM_DOORS
+// #define NUM_PANELS          0
+#define MAX_PARTS_PER_DOOR     8
+#define MAX_DOOR_PARTS         (NUM_DOORS * MAX_PARTS_PER_DOOR + NUM_PANELS)
+#define DOOR_PART_IS_PANEL(i)  ((i) >= NUM_DOORS * MAX_PARTS_PER_DOOR)
+
+
+struct DoorPartOrderInfo
+{
+  int nr;
+  int sort_priority;
+};
+
+static struct DoorPartOrderInfo door_part_order[MAX_DOOR_PARTS];
+
+struct DoorPartControlInfo
+{
+  int door_nr;
+  int graphic;
+  struct DoorPartPosInfo *pos;
+};
+
+static struct DoorPartControlInfo door_part_controls[] =
+{
+  {
+    DOOR_1,
+    IMG_DOOR_1_GFX_PART_1,
+    &door_1.part_1
+  },
+  {
+    DOOR_1,
+    IMG_DOOR_1_GFX_PART_2,
+    &door_1.part_2
+  },
+  {
+    DOOR_1,
+    IMG_DOOR_1_GFX_PART_3,
+    &door_1.part_3
+  },
+  {
+    DOOR_1,
+    IMG_DOOR_1_GFX_PART_4,
+    &door_1.part_4
+  },
+  {
+    DOOR_1,
+    IMG_DOOR_1_GFX_PART_5,
+    &door_1.part_5
+  },
+  {
+    DOOR_1,
+    IMG_DOOR_1_GFX_PART_6,
+    &door_1.part_6
+  },
+  {
+    DOOR_1,
+    IMG_DOOR_1_GFX_PART_7,
+    &door_1.part_7
+  },
+  {
+    DOOR_1,
+    IMG_DOOR_1_GFX_PART_8,
+    &door_1.part_8
+  },
+
+  {
+    DOOR_2,
+    IMG_DOOR_2_GFX_PART_1,
+    &door_2.part_1
+  },
+  {
+    DOOR_2,
+    IMG_DOOR_2_GFX_PART_2,
+    &door_2.part_2
+  },
+  {
+    DOOR_2,
+    IMG_DOOR_2_GFX_PART_3,
+    &door_2.part_3
+  },
+  {
+    DOOR_2,
+    IMG_DOOR_2_GFX_PART_4,
+    &door_2.part_4
+  },
+  {
+    DOOR_2,
+    IMG_DOOR_2_GFX_PART_5,
+    &door_2.part_5
+  },
+  {
+    DOOR_2,
+    IMG_DOOR_2_GFX_PART_6,
+    &door_2.part_6
+  },
+  {
+    DOOR_2,
+    IMG_DOOR_2_GFX_PART_7,
+    &door_2.part_7
+  },
+  {
+    DOOR_2,
+    IMG_DOOR_2_GFX_PART_8,
+    &door_2.part_8
+  },
+
+  {
+    DOOR_1,
+    IMG_BACKGROUND_PANEL,
+    &door_1.panel
+  },
+  {
+    DOOR_2,
+    IMG_BACKGROUND_TAPE,
+    &door_2.panel
+  },
+
+  {
+    -1,
+    -1,
+    NULL
+  }
+};
+
+
 /* forward declaration for internal use */
 static void UnmapToolButtons();
 static void HandleToolButtons(struct GadgetInfo *);
@@ -1088,6 +1217,17 @@ void DrawBackground(int x, int y, int width, int height)
 #endif
 
 #if 1
+
+#if 1
+  if (IN_GFX_FIELD_FULL(x, y))
+    redraw_mask |= REDRAW_FIELD;
+  else if (IN_GFX_DOOR_1(x, y))
+    redraw_mask |= REDRAW_DOOR_1;
+  else if (IN_GFX_DOOR_2(x, y))
+    redraw_mask |= REDRAW_DOOR_2;
+  else if (IN_GFX_DOOR_3(x, y))
+    redraw_mask |= REDRAW_DOOR_3;
+#else
   /* (this only works for the current arrangement of playfield and panels) */
   if (x < gfx.dx)
     redraw_mask |= REDRAW_FIELD;
@@ -1095,6 +1235,8 @@ void DrawBackground(int x, int y, int width, int height)
     redraw_mask |= REDRAW_DOOR_1;
   else
     redraw_mask |= REDRAW_DOOR_2;
+#endif
+
 #else
   /* (this is just wrong (when drawing to one of the two door panel areas)) */
   redraw_mask |= REDRAW_FIELD;
@@ -2475,9 +2617,11 @@ void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
   int dst_y = starty + y * tile_height;
   int width  = graphic_info[graphic].width;
   int height = graphic_info[graphic].height;
-  int inner_width  = MAX(width  - 2 * tile_width,  tile_width);
-  int inner_height = MAX(height - 2 * tile_height, tile_height);
-  int inner_sx = (width >= 3 * tile_width ? tile_width : 0);
+  int inner_width_raw  = MAX(width  - 2 * tile_width,  tile_width);
+  int inner_height_raw = MAX(height - 2 * tile_height, tile_height);
+  int inner_width  = inner_width_raw  - (inner_width_raw  % tile_width);
+  int inner_height = inner_height_raw - (inner_height_raw % tile_height);
+  int inner_sx = (width  >= 3 * tile_width  ? tile_width  : 0);
   int inner_sy = (height >= 3 * tile_height ? tile_height : 0);
   boolean draw_masked = graphic_info[graphic].draw_masked;
 
@@ -2644,6 +2788,8 @@ static void setRequestPosition(int *x, int *y, boolean add_border_size)
 
 void DrawEnvelopeRequest(char *text)
 {
+  char *text_final = text;
+  char *text_door_style = NULL;
   int graphic = IMG_BACKGROUND_REQUEST;
   Bitmap *src_bitmap = graphic_info[graphic].bitmap;
   int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
@@ -2657,8 +2803,6 @@ void DrawEnvelopeRequest(char *text)
   int text_height = request.height - 2 * border_size;
   int line_length = text_width / font_width;
   int max_lines = text_height / line_height;
-  boolean autowrap = FALSE;
-  boolean centered = TRUE;
   int width = request.width;
   int height = request.height;
   int tile_size = request.step_offset;
@@ -2667,6 +2811,33 @@ void DrawEnvelopeRequest(char *text)
   int sx, sy;
   int i, x, y;
 
+  if (request.wrap_single_words)
+  {
+    char *src_text_ptr, *dst_text_ptr;
+
+    text_door_style = checked_malloc(2 * strlen(text) + 1);
+
+    src_text_ptr = text;
+    dst_text_ptr = text_door_style;
+
+    while (*src_text_ptr)
+    {
+      if (*src_text_ptr == ' ' ||
+         *src_text_ptr == '?' ||
+         *src_text_ptr == '!')
+       *dst_text_ptr++ = '\n';
+
+      if (*src_text_ptr != ' ')
+       *dst_text_ptr++ = *src_text_ptr;
+
+      src_text_ptr++;
+    }
+
+    *dst_text_ptr = '\0';
+
+    text_final = text_door_style;
+  }
+
   setRequestPosition(&sx, &sy, FALSE);
 
   ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
@@ -2677,9 +2848,9 @@ void DrawEnvelopeRequest(char *text)
                                  x, y, x_steps, y_steps,
                                  tile_size, tile_size);
 
-  DrawTextBuffer(sx + border_size, sy + border_size, text, font_nr,
+  DrawTextBuffer(sx + border_size, sy + border_size, text_final, font_nr,
                 line_length, -1, max_lines, line_spacing, mask_mode,
-                autowrap, centered, FALSE);
+                request.autowrap, request.centered, FALSE);
 
   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
     RedrawGadget(tool_gadget[i]);
@@ -2704,11 +2875,14 @@ void DrawEnvelopeRequest(char *text)
 
   Delay(1000);
 #endif
+
+  if (text_door_style)
+    free(text_door_style);
 }
 
 #if 1
 
-void AnimateEnvelopeRequest(char *text, int anim_mode, int action)
+void AnimateEnvelopeRequest(int anim_mode, int action)
 {
   int graphic = IMG_BACKGROUND_REQUEST;
   boolean draw_masked = graphic_info[graphic].draw_masked;
@@ -3046,12 +3220,14 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
   int anim_mode = graphic_info[graphic].anim_mode;
   int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
                        anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
+#if 0
   char *text_copy = getStringCopy(text);
   char *text_ptr;
 
   for (text_ptr = text_copy; *text_ptr; text_ptr++)
     if (*text_ptr == ' ')
       *text_ptr = '\n';
+#endif
 
 #if 1
   if (game_status == GAME_MODE_PLAYING)
@@ -3093,7 +3269,11 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
   }
 #endif
 
+#if 1
+    DrawEnvelopeRequest(text);
+#else
     DrawEnvelopeRequest(text_copy);
+#endif
 
     if (game_status != GAME_MODE_MAIN)
       InitAnimation();
@@ -3110,9 +3290,9 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
     PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
 
     if (anim_mode == ANIM_DEFAULT)
-      AnimateEnvelopeRequest(text, ANIM_DEFAULT, ACTION_OPENING);
+      AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
 
-    AnimateEnvelopeRequest(text, main_anim_mode, ACTION_OPENING);
+    AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
 
 #if 0
     if (tape.playing)
@@ -3126,10 +3306,10 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
     PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
 
     if (anim_mode != ANIM_NONE)
-      AnimateEnvelopeRequest(text, main_anim_mode, ACTION_CLOSING);
+      AnimateEnvelopeRequest(main_anim_mode, ACTION_CLOSING);
 
     if (anim_mode == ANIM_DEFAULT)
-      AnimateEnvelopeRequest(text, ANIM_DEFAULT, ACTION_CLOSING);
+      AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_CLOSING);
   }
 
   game.envelope_active = FALSE;
@@ -3181,7 +3361,9 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
   BackToFront();
 #endif
 
+#if 0
   free(text_copy);
+#endif
 }
 
 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
@@ -4394,10 +4576,14 @@ static boolean RequestDoor(char *text, unsigned int req_state)
     for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
     {
       tc = *(text_ptr + tx);
-      if (!tc || tc == ' ')
+      // if (!tc || tc == ' ')
+      if (!tc || tc == ' ' || tc == '?' || tc == '!')
        break;
     }
 
+    if ((tc == '?' || tc == '!') && tl == 0)
+      tl = 1;
+
     if (!tl)
     { 
       text_ptr++; 
@@ -4413,6 +4599,7 @@ static boolean RequestDoor(char *text, unsigned int req_state)
             text_line, font_nr);
 
     text_ptr += tl + (tc == ' ' ? 1 : 0);
+    // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
   }
 
   game_status = last_game_status;      /* restore current game status */
@@ -5125,6 +5312,46 @@ boolean Request(char *text, unsigned int req_state)
 
 #endif
 
+static int compareDoorPartOrderInfo(const void *object1, const void *object2)
+{
+  const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
+  const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
+  int compare_result;
+
+  if (dpo1->sort_priority != dpo2->sort_priority)
+    compare_result = dpo1->sort_priority - dpo2->sort_priority;
+  else
+    compare_result = dpo1->nr - dpo2->nr;
+
+  return compare_result;
+}
+
+void InitDoors()
+{
+  int i;
+
+  for (i = 0; door_part_controls[i].door_nr != -1; i++)
+  {
+    struct DoorPartControlInfo *dpc = &door_part_controls[i];
+    struct DoorPartOrderInfo *dpo = &door_part_order[i];
+
+    /* fill structure for door part draw order */
+    dpo->nr = i;
+    dpo->sort_priority = dpc->pos->sort_priority;
+
+#if 0
+    struct DoorPartPosInfo *pos = dpc->pos;
+
+    printf(":0: step_xoffset == %d, step_yoffset == %d\n",
+          pos->step_xoffset, pos->step_yoffset);
+#endif
+  }
+
+  /* sort door part controls according to sort_priority and graphic number */
+  qsort(door_part_order, MAX_DOOR_PARTS,
+        sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
+}
+
 unsigned int OpenDoor(unsigned int door_state)
 {
   if (door_state & DOOR_COPY_BACK)
@@ -5175,6 +5402,399 @@ unsigned int SetDoorState(unsigned int door_state)
   return MoveDoor(door_state | DOOR_SET_STATE);
 }
 
+#if 1
+
+// ========== TEST 1 ===========================================================
+
+int euclid(int a, int b)
+{
+  return (b ? euclid(b, a % b) : a);
+}
+
+unsigned int MoveDoor(unsigned int door_state)
+{
+  struct XY panel_pos_list[] =
+  {
+    { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 },
+    { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 },
+  };
+  struct Rect door_rect_list[] =
+  {
+    { DX, DY, DXSIZE, DYSIZE },
+    { VX, VY, VXSIZE, VYSIZE }
+  };
+  static int door1 = DOOR_OPEN_1;
+  static int door2 = DOOR_CLOSE_2;
+  unsigned int door_delay = 0;
+  unsigned int door_delay_value;
+  int i;
+
+#if 1
+  if (door_1.width < 0 || door_1.width > DXSIZE)
+    door_1.width = DXSIZE;
+  if (door_1.height < 0 || door_1.height > DYSIZE)
+    door_1.height = DYSIZE;
+  if (door_2.width < 0 || door_2.width > VXSIZE)
+    door_2.width = VXSIZE;
+  if (door_2.height < 0 || door_2.height > VYSIZE)
+    door_2.height = VYSIZE;
+#endif
+
+  if (door_state == DOOR_GET_STATE)
+    return (door1 | door2);
+
+  if (door_state & DOOR_SET_STATE)
+  {
+    if (door_state & DOOR_ACTION_1)
+      door1 = door_state & DOOR_ACTION_1;
+    if (door_state & DOOR_ACTION_2)
+      door2 = door_state & DOOR_ACTION_2;
+
+    return (door1 | door2);
+  }
+
+  if (!(door_state & DOOR_FORCE_REDRAW))
+  {
+    if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
+      door_state &= ~DOOR_OPEN_1;
+    else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
+      door_state &= ~DOOR_CLOSE_1;
+    if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
+      door_state &= ~DOOR_OPEN_2;
+    else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
+      door_state &= ~DOOR_CLOSE_2;
+  }
+
+#if 0
+  door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
+                     door_2.step_delay);
+
+  if (setup.quick_doors)
+  {
+    stepsize = 20;             /* must be chosen to always draw last frame */
+    door_delay_value = 0;
+  }
+#endif
+
+  if (global.autoplay_leveldir)
+  {
+    door_state |= DOOR_NO_DELAY;
+    door_state &= ~DOOR_CLOSE_ALL;
+  }
+
+#if 1
+  if (game_status == GAME_MODE_EDITOR)
+    door_state |= DOOR_NO_DELAY;
+#endif
+
+  if (door_state & DOOR_ACTION)
+  {
+    boolean door_panel_drawn[NUM_DOORS];
+    boolean door_part_done[MAX_DOOR_PARTS];
+    boolean door_part_done_all;
+    int num_steps[MAX_DOOR_PARTS];
+    int max_move_delay = 0;    // delay for complete animations of all doors
+    int max_step_delay = 0;    // delay (ms) between two animation frames
+    int num_move_steps = 0;    // number of animation steps for all doors
+    int current_move_delay = 0;
+    int k;
+
+    for (i = 0; i < MAX_DOOR_PARTS; i++)
+    {
+      struct DoorPartControlInfo *dpc = &door_part_controls[i];
+      struct GraphicInfo *g = &graphic_info[dpc->graphic];
+      int door_token = dpc->door_nr;
+
+      door_part_done[i] = (!(door_state & door_token) ||
+                          !g->bitmap);
+    }
+
+#if 0
+    for (i = 0; i < MAX_DOOR_PARTS; i++)
+    {
+      struct DoorPartControlInfo *dpc = &door_part_controls[i];
+      struct DoorPartPosInfo *pos = dpc->pos;
+      int start_step = pos->start_step;
+
+      printf("::: ---> %d: start_step == %d [%d]\n",
+            i, start_step, door_part_done[i]);
+    }
+#endif
+
+    for (i = 0; i < MAX_DOOR_PARTS; i++)
+    {
+      struct DoorPartControlInfo *dpc = &door_part_controls[i];
+      struct GraphicInfo *g = &graphic_info[dpc->graphic];
+      struct DoorPartPosInfo *pos = dpc->pos;
+      int step_xoffset = ABS(pos->step_xoffset);
+      int step_yoffset = ABS(pos->step_yoffset);
+      int step_delay = pos->step_delay;
+      int start_step = pos->start_step;
+      float move_xsize = (step_xoffset ? g->width  : 0);
+      float move_ysize = (step_yoffset ? g->height : 0);
+      int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
+      int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0);
+      int move_steps = (move_xsteps && move_ysteps ?
+                       MIN(move_xsteps, move_ysteps) :
+                       move_xsteps ? move_xsteps : move_ysteps) - start_step;
+      int move_delay = move_steps * step_delay;
+
+      if (door_part_done[i])
+       continue;
+
+      max_move_delay = MAX(max_move_delay, move_delay);
+      max_step_delay = (max_step_delay == 0 ? step_delay :
+                       euclid(max_step_delay, step_delay));
+      num_steps[i] = move_steps;
+
+#if 0
+#if 0
+      printf("::: %d: move_delay == %d, start_step == %d [%d]\n",
+            i, move_delay, start_step, door_part_order[i].nr);
+#else
+      if (DOOR_PART_IS_PANEL(i))
+       printf("::: %d: move_delay == %d, start_step == %d\n",
+              i, move_delay, start_step);
+#endif
+#endif
+    }
+
+    num_move_steps = max_move_delay / max_step_delay;
+
+    door_delay_value = max_step_delay;
+
+#if 0
+    door_delay_value *= 10;
+#endif
+
+#if 0
+    printf("::: num_move_steps == %d, max_move_delay == %d, max_step_delay == %d\n", num_move_steps, max_move_delay, max_step_delay);
+#endif
+
+    for (k = 0; k < num_move_steps; k++)
+    {
+      for (i = 0; i < NUM_DOORS; i++)
+       door_panel_drawn[i] = FALSE;
+
+      for (i = 0; i < MAX_DOOR_PARTS; i++)
+      {
+       int nr = door_part_order[i].nr;
+       struct DoorPartControlInfo *dpc = &door_part_controls[nr];
+       int door_token = dpc->door_nr;
+       int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
+       boolean is_panel = DOOR_PART_IS_PANEL(nr);
+       struct GraphicInfo *g = &graphic_info[dpc->graphic];
+       struct DoorPartPosInfo *pos = dpc->pos;
+       struct XY *panel_pos = &panel_pos_list[door_index];
+       struct Rect *door_rect = &door_rect_list[door_index];
+       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);
+       boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
+       boolean mode_opening = (is_panel ? door_closing : door_opening);
+       int start_step = pos->start_step;
+       int step_delay = pos->step_delay;
+       int step_factor = step_delay / max_step_delay;
+       int k1 = (step_factor ? k / step_factor + 1 : k);
+       int k2 = (mode_opening ? k1 + start_step : num_steps[nr] - k1);
+       int kk = (k2 < 0 ? 0 : k2);
+       int src_x, src_y, src_xx, src_yy;
+       int dst_x, dst_y, dst_xx, dst_yy;
+       int width, height;
+
+#if 0
+       if (DOOR_PART_IS_PANEL(nr))
+       {
+         int start_step = pos->start_step;
+
+         k2 = (door_closing ? k1 : num_steps[nr] - k1);// - start_step;
+         kk = (k2 < 0 ? 0 : k2);
+       }
+#endif
+
+#if 0
+       // !!! TEST !!! 
+       if (nr != 16 && nr != 0)
+         continue;
+#endif
+
+#if 0
+       if (door_part_done[nr])
+         continue;
+#endif
+
+       if (!(door_state & door_token))
+         continue;
+
+       if (!g->bitmap)
+         continue;
+
+#if 0
+       if (current_move_delay % step_delay)
+         continue;
+#endif
+
+       // draw door panel
+
+       if (!door_panel_drawn[door_index])
+       {
+#if 1
+         ClearRectangle(drawto, door_rect->x, door_rect->y,
+                        door_rect->width, door_rect->height);
+#else
+         BlitBitmap(bitmap_db_door, drawto, panel_pos->x, panel_pos->y,
+                    door_rect->width, door_rect->height,
+                    door_rect->x, door_rect->y);
+#endif
+
+         door_panel_drawn[door_index] = TRUE;
+       }
+
+       // draw opening or closing door parts
+
+       if (pos->step_xoffset < 0)      // door part on right side
+       {
+         src_xx = 0;
+         dst_xx = pos->x + ABS(kk * pos->step_xoffset);
+         width = g->width;
+
+         if (dst_xx + width > door_rect->width)
+           width = door_rect->width - dst_xx;
+       }
+       else                            // door part on left side
+       {
+         src_xx = 0;
+         dst_xx = pos->x - kk * pos->step_xoffset;
+
+         if (dst_xx < 0)
+         {
+           src_xx = ABS(dst_xx);
+           dst_xx = 0;
+         }
+
+         width = g->width - src_xx;
+
+         // printf("::: k == %d [%d] \n", k, start_step);
+       }
+
+       if (pos->step_yoffset < 0)      // door part on bottom side
+       {
+         src_yy = 0;
+         dst_yy = pos->y + ABS(kk * pos->step_yoffset);
+         height = g->height;
+
+         if (dst_yy + height > door_rect->height)
+           height = door_rect->height - dst_yy;
+       }
+       else                            // door part on top side
+       {
+         src_yy = 0;
+         dst_yy = pos->y - kk * pos->step_yoffset;
+
+         if (dst_yy < 0)
+         {
+           src_yy = ABS(dst_yy);
+           dst_yy = 0;
+         }
+
+         height = g->height - src_yy;
+       }
+
+       if (is_panel)
+       {
+         src_x = panel_pos->x + src_xx;
+         src_y = panel_pos->y + src_yy;
+       }
+       else
+       {
+         src_x = g->src_x + src_xx;
+         src_y = g->src_y + src_yy;
+       }
+
+       dst_x = door_rect->x + dst_xx;
+       dst_y = door_rect->y + dst_yy;
+
+#if 0
+       if (DOOR_PART_IS_PANEL(nr))
+       {
+         printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
+                width, height, g->width, g->height, src_x, src_y);
+       }
+#endif
+
+       if (width  >= 0 && width  <= g->width &&
+           height >= 0 && height <= g->height)
+       {
+         if (is_panel || !pos->draw_masked)
+           BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
+                      dst_x, dst_y);
+         else
+           BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height,
+                            dst_x, dst_y);
+       }
+
+#if 0
+       if (DOOR_PART_IS_PANEL(nr))
+       {
+         bitmap = bitmap_db_door;
+         src_x = panel_pos->x + src_xx;
+         src_y = panel_pos->y + src_yy;
+
+         printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
+                width, height, g->width, g->height, src_x, src_y);
+
+         if (width  >= 0 && width  <= g->width &&
+             height >= 0 && height <= g->height)
+           BlitBitmap(bitmap, drawto, src_x, src_y,
+                            width, height,
+                            dst_x, dst_y);
+       }
+#endif
+
+       redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
+
+       if ((door_opening && (width < 0         || height < 0)) ||
+           (door_closing && (width >= g->width && height >= g->height)))
+         door_part_done[nr] = TRUE;
+      }
+
+      if (!(door_state & DOOR_NO_DELAY))
+      {
+       BackToFront();
+
+       if (game_status == GAME_MODE_MAIN)
+         DoAnimation();
+
+       WaitUntilDelayReached(&door_delay, door_delay_value);
+
+       current_move_delay += max_step_delay;
+      }
+
+      door_part_done_all = TRUE;
+
+      for (i = 0; i < MAX_DOOR_PARTS; i++)
+       if (!door_part_done[i])
+         door_part_done_all = FALSE;
+
+#if 0
+      if (door_part_done_all)
+       break;
+#endif
+    }
+  }
+
+  if (door_state & DOOR_ACTION_1)
+    door1 = door_state & DOOR_ACTION_1;
+  if (door_state & DOOR_ACTION_2)
+    door2 = door_state & DOOR_ACTION_2;
+
+  return (door1 | door2);
+}
+
+#else
+
+// ========== OLD ==============================================================
+
 unsigned int MoveDoor(unsigned int door_state)
 {
   static int door1 = DOOR_OPEN_1;
@@ -5183,6 +5803,7 @@ unsigned int MoveDoor(unsigned int door_state)
   unsigned int door_delay_value;
   int stepsize = 1;
 
+#if 1
   if (door_1.width < 0 || door_1.width > DXSIZE)
     door_1.width = DXSIZE;
   if (door_1.height < 0 || door_1.height > DYSIZE)
@@ -5191,6 +5812,7 @@ unsigned int MoveDoor(unsigned int door_state)
     door_2.width = VXSIZE;
   if (door_2.height < 0 || door_2.height > VYSIZE)
     door_2.height = VYSIZE;
+#endif
 
   if (door_state == DOOR_GET_STATE)
     return (door1 | door2);
@@ -5220,6 +5842,8 @@ unsigned int MoveDoor(unsigned int door_state)
   door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
                      door_2.step_delay);
 
+  // door_delay_value *= 4;    // !!! TEST ONLY !!!
+
   if (setup.quick_doors)
   {
     stepsize = 20;             /* must be chosen to always draw last frame */
@@ -5239,17 +5863,46 @@ unsigned int MoveDoor(unsigned int door_state)
 
   if (door_state & DOOR_ACTION)
   {
+#if 1
+    struct GraphicInfo *g1_left  = &graphic_info[IMG_DOOR_1_WING_LEFT];
+    struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
+    struct GraphicInfo *g2_left  = &graphic_info[IMG_DOOR_2_WING_LEFT];
+    struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
+    int door_1_left_width   = g1_left->width;
+    int door_1_left_height  = g1_left->height;
+    int door_1_right_width  = g1_right->width;
+    int door_1_right_height = g1_right->height;
+    int door_2_left_width   = g2_left->width;
+    int door_2_left_height  = g2_left->height;
+    int door_2_right_width  = g2_right->width;
+    int door_2_right_height = g2_right->height;
+    int door_1_width  = MAX(door_1_left_width,  door_1_right_width);
+    int door_1_height = MAX(door_1_left_height, door_1_right_height);
+    int door_2_width  = MAX(door_2_left_width,  door_2_right_width);
+    int door_2_height = MAX(door_2_left_height, door_2_right_height);
+#endif
     boolean handle_door_1 = (door_state & DOOR_ACTION_1);
     boolean handle_door_2 = (door_state & DOOR_ACTION_2);
     boolean door_1_done = (!handle_door_1);
     boolean door_2_done = (!handle_door_2);
     boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
     boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
+#if 1
+#if 1
+    int door_size_1 = (door_1_vertical ? door_1_height : door_1_width);
+    int door_size_2 = (door_2_vertical ? door_2_height : door_2_width);
+#else
+    int door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
+    int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
+#endif
+#else
     int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
     int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
+#endif
     int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
     int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
-    int door_size     = (handle_door_1 ? door_size_1     : door_size_2);
+    // int door_size     = (handle_door_1 ? door_size_1     : door_size_2);
+    int door_size     = (handle_door_2 ? door_size_2     : door_size_1);
     int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
     int door_skip = max_door_size - door_size;
     int end = door_size;
@@ -5268,14 +5921,35 @@ unsigned int MoveDoor(unsigned int door_state)
     for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
     {
       int x = k;
+#if 0
       Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
       GC gc = bitmap->stored_clip_gc;
+#endif
 
-      if (door_state & DOOR_ACTION_1)
+      if (door_state & DOOR_ACTION_1 &&
+         x * door_1.step_offset <= door_size_1)
       {
        int a = MIN(x * door_1.step_offset, end);
        int p = (door_state & DOOR_OPEN_1 ? end - a : a);
+#if 1
+       int i = p;
+#else
        int i = p + door_skip;
+#endif
+
+#if 1
+       struct GraphicInfo *g_left  = &graphic_info[IMG_DOOR_1_WING_LEFT];
+       struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
+       Bitmap *bm_left  = g_left->bitmap;
+       Bitmap *bm_right = g_right->bitmap;
+       GC gc_left  = bm_left->stored_clip_gc;
+       GC gc_right = bm_right->stored_clip_gc;
+#endif
+
+       int classic_dxsize = 100;
+       int classic_dysize = 280;
+       boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
+                                      DYSIZE == classic_dysize);
 
        if (door_1.anim_mode & ANIM_STATIC_PANEL)
        {
@@ -5289,14 +5963,37 @@ unsigned int MoveDoor(unsigned int door_state)
                     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
                     DXSIZE, DYSIZE - p / 2, DX, DY);
 
+#if 1
+         // printf("::: p == %d\n", p);
          ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
+#endif
        }
 
        if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
        {
+#if 1
+         int src1_x = g_right->src_x;
+         int src1_y = g_right->src_y;
+         int src2_x = g_left->src_x + g_left->width - i;
+         int src2_y = g_left->src_y;
+         int dst1_x = DX + DXSIZE - i;
+         int dst1_y = DY;
+         int dst2_x = DX;
+         int dst2_y = DY;
+         int width = i;
+         int height = DYSIZE;
+
+         SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
+         BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
+                          dst1_x, dst1_y);
+
+         SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
+         BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
+                          dst2_x, dst2_y);
+#else
          int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
-         int dst1_x = DX + DXSIZE - i, dst1_y = DY;
          int src2_x = DXSIZE - i,      src2_y = DOOR_GFX_PAGEY1;
+         int dst1_x = DX + DXSIZE - i, dst1_y = DY;
          int dst2_x = DX,              dst2_y = DY;
          int width = i, height = DYSIZE;
 
@@ -5307,12 +6004,33 @@ unsigned int MoveDoor(unsigned int door_state)
          SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
          BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
                           dst2_x, dst2_y);
+#endif
        }
        else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
        {
+#if 1
+         int src1_x = g_right->src_x;
+         int src1_y = g_right->src_y;
+         int src2_x = g_left->src_x;
+         int src2_y = g_left->src_y + g_left->height - i;
+         int dst1_x = DX;
+         int dst1_y = DY + DYSIZE - i;
+         int dst2_x = DX;
+         int dst2_y = DY;
+         int width = DXSIZE;
+         int height = i;
+
+         SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
+         BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
+                          dst1_x, dst1_y);
+
+         SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
+         BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
+                          dst2_x, dst2_y);
+#else
          int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
-         int dst1_x = DX,              dst1_y = DY + DYSIZE - i;
          int src2_x = 0,               src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
+         int dst1_x = DX,              dst1_y = DY + DYSIZE - i;
          int dst2_x = DX,              dst2_y = DY;
          int width = DXSIZE, height = i;
 
@@ -5323,11 +6041,99 @@ unsigned int MoveDoor(unsigned int door_state)
          SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
          BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
                           dst2_x, dst2_y);
+#endif
        }
-       else if (x <= DXSIZE)   /* ANIM_DEFAULT */
+       else if (classic_door_1_size && x <= DXSIZE)    /* ANIM_DEFAULT */
        {
          int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
 
+#if 1
+         int src1_x = g_right->src_x;
+         int src1_y = g_right->src_y;
+         int src2_x = g_left->src_x + g_left->width - i;
+         int src2_y = g_left->src_y;
+         int dst1_x = DX + DXSIZE - i;
+         int dst1_y = DY;
+         int dst2_x = DX;
+         int dst2_y = DY;
+         int width = i;
+         int height1 = 63, height2 = DYSIZE / 2 - height1;
+         int ypos1 = 0, ypos2 = height2;
+         int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
+
+         SetClipOrigin(bm_right, gc_right,
+                       dst1_x - src1_x, dst1_y - src1_y + j);
+         BlitBitmapMasked(bm_right, drawto,
+                          src1_x, src1_y + ypos1, width, height2,
+                          dst1_x, dst1_y + ypos1 + j);
+         BlitBitmapMasked(bm_right, drawto,
+                          src1_x, src1_y + ypos3, width, height1,
+                          dst1_x, dst1_y + ypos3 + j);
+         SetClipOrigin(bm_left, gc_left,
+                       dst2_x - src2_x, dst2_y - src2_y - j);
+         BlitBitmapMasked(bm_left, drawto,
+                          src2_x, src2_y + ypos1 + j, width, height2 - j,
+                          dst2_x, dst2_y + ypos1);
+         BlitBitmapMasked(bm_left, drawto,
+                          src2_x, src2_y + ypos3, width, height1,
+                          dst2_x, dst2_y + ypos3 - j);
+
+         SetClipOrigin(bm_left, gc_left,
+                       dst2_x - src2_x, dst2_y - src2_y - j);
+         BlitBitmapMasked(bm_left, drawto,
+                          src2_x, src2_y + ypos2, width, height1,
+                          dst2_x, dst2_y + ypos2 - j);
+         BlitBitmapMasked(bm_left, drawto,
+                          src2_x, src2_y + ypos4, width, height2,
+                          dst2_x, dst2_y + ypos4 - j);
+         SetClipOrigin(bm_right, gc_right,
+                       dst1_x - src1_x, dst1_y - src1_y + j);
+         BlitBitmapMasked(bm_right, drawto,
+                          src1_x, src1_y + ypos2, width, height1,
+                          dst1_x, dst1_y + ypos2 + j);
+         BlitBitmapMasked(bm_right, drawto,
+                          src1_x, src1_y + ypos4, width, height2 - j,
+                          dst1_x, dst1_y + ypos4 + j);
+
+#else
+         int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
+         int src2_x = DXSIZE - i,      src2_y = DOOR_GFX_PAGEY1;
+         int dst1_x = DX + DXSIZE - i, dst1_y = DY;
+         int dst2_x = DX,              dst2_y = DY;
+         int width = i, height = DYSIZE;
+         int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
+
+         SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src1_x, src1_y, width, ypos2,
+                          dst1_x, dst1_y + j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src1_x, src1_y + ypos3, width, ypos1,
+                          dst1_x, dst1_y + ypos3 + j);
+         SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src2_x, src2_y + j, width, ypos2 - j,
+                          dst2_x, dst2_y);
+         BlitBitmapMasked(bitmap, drawto,
+                          src2_x, src2_y + ypos3, width, ypos1,
+                          dst2_x, dst2_y + ypos3 - j);
+
+         SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src2_x, src2_y + ypos2, width, ypos1,
+                          dst2_x, dst2_y + ypos2 - j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src2_x, src2_y + ypos4, width, ypos2,
+                          dst2_x, dst2_y + ypos4 - j);
+         SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src1_x, src1_y + ypos2, width, ypos1,
+                          dst1_x, dst1_y + ypos2 + j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src1_x, src1_y + ypos4, width, ypos2 - j,
+                          dst1_x, dst1_y + ypos4 + j);
+
+         /*
          SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
          BlitBitmapMasked(bitmap, drawto,
                           DXSIZE, DOOR_GFX_PAGEY1, i, 77,
@@ -5357,18 +6163,35 @@ unsigned int MoveDoor(unsigned int door_state)
          BlitBitmapMasked(bitmap, drawto,
                           DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
                           DX + DXSIZE - i, DY + 203 + j);
+         */
+#endif
        }
 
        redraw_mask |= REDRAW_DOOR_1;
        door_1_done = (a == end);
       }
 
-      if (door_state & DOOR_ACTION_2)
+      if (door_state & DOOR_ACTION_2 &&
+         x * door_2.step_offset <= door_size_2)
       {
        int a = MIN(x * door_2.step_offset, door_size);
        int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
        int i = p + door_skip;
 
+#if 1
+       struct GraphicInfo *g_left  = &graphic_info[IMG_DOOR_2_WING_LEFT];
+       struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
+       Bitmap *bm_left  = g_left->bitmap;
+       Bitmap *bm_right = g_right->bitmap;
+       GC gc_left  = bm_left->stored_clip_gc;
+       GC gc_right = bm_right->stored_clip_gc;
+#endif
+
+       int classic_vxsize = 100;
+       int classic_vysize = 100;
+       boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
+                                      VYSIZE == classic_vysize);
+
        if (door_2.anim_mode & ANIM_STATIC_PANEL)
        {
          BlitBitmap(bitmap_db_door, drawto,
@@ -5386,9 +6209,29 @@ unsigned int MoveDoor(unsigned int door_state)
 
        if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
        {
+#if 1
+         int src1_x = g_right->src_x;
+         int src1_y = g_right->src_y;
+         int src2_x = g_left->src_x + g_left->width - i;
+         int src2_y = g_left->src_y;
+         int dst1_x = VX + VXSIZE - i;
+         int dst1_y = VY;
+         int dst2_x = VX;
+         int dst2_y = VY;
+         int width = i;
+         int height = VYSIZE;
+
+         SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
+         BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
+                          dst1_x, dst1_y);
+
+         SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
+         BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
+                          dst2_x, dst2_y);
+#else
          int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
-         int dst1_x = VX + VXSIZE - i, dst1_y = VY;
          int src2_x = VXSIZE - i,      src2_y = DOOR_GFX_PAGEY2;
+         int dst1_x = VX + VXSIZE - i, dst1_y = VY;
          int dst2_x = VX,              dst2_y = VY;
          int width = i, height = VYSIZE;
 
@@ -5399,12 +6242,33 @@ unsigned int MoveDoor(unsigned int door_state)
          SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
          BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
                           dst2_x, dst2_y);
+#endif
        }
        else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
        {
+#if 1
+         int src1_x = g_right->src_x;
+         int src1_y = g_right->src_y;
+         int src2_x = g_left->src_x;
+         int src2_y = g_left->src_y + g_left->height - i;
+         int dst1_x = VX;
+         int dst1_y = VY + VYSIZE - i;
+         int dst2_x = VX;
+         int dst2_y = VY;
+         int width = VXSIZE;
+         int height = i;
+
+         SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
+         BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
+                          dst1_x, dst1_y);
+
+         SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
+         BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
+                          dst2_x, dst2_y);
+#else
          int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
-         int dst1_x = VX,              dst1_y = VY + VYSIZE - i;
          int src2_x = 0,               src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
+         int dst1_x = VX,              dst1_y = VY + VYSIZE - i;
          int dst2_x = VX,              dst2_y = VY;
          int width = VXSIZE, height = i;
 
@@ -5415,11 +6279,73 @@ unsigned int MoveDoor(unsigned int door_state)
          SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
          BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
                           dst2_x, dst2_y);
+#endif
        }
-       else if (x <= VXSIZE)   /* ANIM_DEFAULT */
+       else if (classic_door_2_size && x <= VXSIZE)    /* ANIM_DEFAULT */
        {
          int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
 
+#if 1
+         int src1_x = g_right->src_x;
+         int src1_y = g_right->src_y;
+         int src2_x = g_left->src_x + g_left->width - i;
+         int src2_y = g_left->src_y;
+         int dst1_x = VX + VXSIZE - i;
+         int dst1_y = VY;
+         int dst2_x = VX;
+         int dst2_y = VY;
+         int width = i;
+         int height = VYSIZE / 2;
+         int ypos1 = 0, ypos2 = VYSIZE / 2;
+
+         SetClipOrigin(bm_right, gc_right,
+                       dst1_x - src1_x, dst1_y - src1_y + j);
+         BlitBitmapMasked(bm_right, drawto,
+                          src1_x, src1_y + ypos1, width, height,
+                          dst1_x, dst1_y + ypos1 + j);
+         SetClipOrigin(bm_left, gc_left,
+                       dst2_x - src2_x, dst2_y - src2_y - j);
+         BlitBitmapMasked(bm_left, drawto,
+                          src2_x, src2_y + ypos1 + j, width, height - j,
+                          dst2_x, dst2_y + ypos1);
+
+         SetClipOrigin(bm_left, gc_left,
+                       dst2_x - src2_x, dst2_y - src2_y - j);
+         BlitBitmapMasked(bm_left, drawto,
+                          src2_x, src2_y + ypos2, width, height,
+                          dst2_x, dst2_y + ypos2 - j);
+         SetClipOrigin(bm_right, gc_right,
+                       dst1_x - src1_x, dst1_y - src1_y + j);
+         BlitBitmapMasked(bm_right, drawto,
+                          src1_x, src1_y + ypos2, width, height - j,
+                          dst1_x, dst1_y + ypos2 + j);
+#else
+         int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
+         int src2_x = VXSIZE - i,      src2_y = DOOR_GFX_PAGEY2;
+         int dst1_x = VX + VXSIZE - i, dst1_y = VY;
+         int dst2_x = VX,              dst2_y = VY;
+         int width = i, height = VYSIZE;
+         int ypos = VYSIZE / 2;
+
+         SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src1_x, src1_y, width, ypos,
+                          dst1_x, dst1_y + j);
+         SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src2_x, src2_y + j, width, ypos - j,
+                          dst2_x, dst2_y);
+
+         SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src2_x, src2_y + ypos, width, ypos,
+                          dst2_x, dst2_y + ypos - j);
+         SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
+         BlitBitmapMasked(bitmap, drawto,
+                          src1_x, src1_y + ypos, width, ypos - j,
+                          dst1_x, dst1_y + ypos + j);
+
+         /*
          SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
          BlitBitmapMasked(bitmap, drawto,
                           VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
@@ -5438,6 +6364,8 @@ unsigned int MoveDoor(unsigned int door_state)
                           VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
                           i, VYSIZE / 2 - j,
                           VX + VXSIZE - i, VY + VYSIZE / 2 + j);
+         */
+#endif
        }
 
        redraw_mask |= REDRAW_DOOR_2;
@@ -5464,25 +6392,74 @@ unsigned int MoveDoor(unsigned int door_state)
   return (door1 | door2);
 }
 
+#endif
+
 void DrawSpecialEditorDoor()
 {
-  /* draw bigger toolbox window */
+#if 1
+  struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
+  int top_border_width = gfx1->width;
+  int top_border_height = gfx1->height;
+  int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
+  int ex = EX - outer_border;
+  int ey = EY - outer_border;
+  int vy = VY - outer_border;
+  int exsize = EXSIZE + 2 * outer_border;
+
+  CloseDoor(DOOR_CLOSE_2);
+
+  /* draw bigger level editor toolbox window */
+  BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
+            top_border_width, top_border_height, ex, ey - top_border_height);
+  BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
+            exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
+#else
+  /* draw bigger level editor toolbox window */
   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-            DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
-            EX - 4, EY - 12);
+             DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
+             EX - 4, EY - 12);
   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
-            EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
-            EX - 6, EY - 4);
+             EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
+             EX - 6, EY - 4);
+#endif
 
   redraw_mask |= REDRAW_ALL;
 }
 
 void UndrawSpecialEditorDoor()
 {
+#if 1
+  struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
+  int top_border_width = gfx1->width;
+  int top_border_height = gfx1->height;
+  int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
+  int ex = EX - outer_border;
+  int ey = EY - outer_border;
+  int ey_top = ey - top_border_height;
+  int exsize = EXSIZE + 2 * outer_border;
+  int eysize = EYSIZE + 2 * outer_border;
+
+  /* draw normal tape recorder window */
+  if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
+  {
+    BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
+              ex, ey_top, top_border_width, top_border_height,
+              ex, ey_top);
+    BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
+              ex, ey, exsize, eysize, ex, ey);
+  }
+  else
+  {
+    // if screen background is set to "[NONE]", clear editor toolbox window
+    ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
+    ClearRectangle(drawto, ex, ey, exsize, eysize);
+  }
+#else
   /* draw normal tape recorder window */
   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
-            EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
-            EX - 6, EY - 12);
+             EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
+             EX - 6, EY - 12);
+#endif
 
   redraw_mask |= REDRAW_ALL;
 }
@@ -8155,11 +9132,33 @@ int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
   return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
 }
 
+#if 1
+boolean getTeamMode_EM()
+{
+  return game.team_mode;
+}
+#else
 int getNumActivePlayers_EM()
 {
+#if 1
+  int num_players = 0;
+  int i;
+
+  if (!tape.playing)
+    return (setup.team_mode ? MAX_PLAYERS : 1);
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    if (tape.player_participates[i])
+      num_players++;
+
+  return (num_players > 1 ? MAX_PLAYERS : 1);
+
+#else
+
   int num_players = 0;
   int i;
 
+  /* when recording game, activate all connected players */
   if (!tape.playing)
     return -1;
 
@@ -8168,7 +9167,9 @@ int getNumActivePlayers_EM()
       num_players++;
 
   return num_players;
+#endif
 }
+#endif
 
 int getGameFrameDelay_EM(int native_em_game_frame_delay)
 {
@@ -9995,25 +10996,42 @@ void ToggleFullscreenOrChangeWindowScalingIfNeeded()
 
 void ChangeViewportPropertiesIfNeeded()
 {
+#if 0
   int *door_1_x = &DX;
   int *door_1_y = &DY;
   int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
   int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
+#endif
   int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
                       game_status == GAME_MODE_EDITOR ? game_status :
                       GAME_MODE_MAIN);
+  int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
+                       game_status);
   struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
   struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
-  struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode];
-  int border_size = vp_playfield->border_size;
-  int new_sx = vp_playfield->x + border_size;
-  int new_sy = vp_playfield->y + border_size;
-  int new_sxsize = vp_playfield->width  - 2 * border_size;
-  int new_sysize = vp_playfield->height - 2 * border_size;
-  int new_real_sx = vp_playfield->x;
-  int new_real_sy = vp_playfield->y;
-  int new_full_sxsize = vp_playfield->width;
-  int new_full_sysize = vp_playfield->height;
+  struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
+  struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
+  int border_size      = vp_playfield->border_size;
+  int new_sx           = vp_playfield->x + border_size;
+  int new_sy           = vp_playfield->y + border_size;
+  int new_sxsize       = vp_playfield->width  - 2 * border_size;
+  int new_sysize       = vp_playfield->height - 2 * border_size;
+  int new_real_sx      = vp_playfield->x;
+  int new_real_sy      = vp_playfield->y;
+  int new_full_sxsize  = vp_playfield->width;
+  int new_full_sysize  = vp_playfield->height;
+  int new_dx           = vp_door_1->x;
+  int new_dy           = vp_door_1->y;
+  int new_dxsize       = vp_door_1->width;
+  int new_dysize       = vp_door_1->height;
+  int new_vx           = vp_door_2->x;
+  int new_vy           = vp_door_2->y;
+  int new_vxsize       = vp_door_2->width;
+  int new_vysize       = vp_door_2->height;
+  int new_ex           = vp_door_3->x;
+  int new_ey           = vp_door_3->y;
+  int new_exsize       = vp_door_3->width;
+  int new_eysize       = vp_door_3->height;
 #if NEW_TILESIZE
   int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
   int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
@@ -10087,22 +11105,50 @@ void ChangeViewportPropertiesIfNeeded()
 
   if (new_sx != SX ||
       new_sy != SY ||
+      new_dx != DX ||
+      new_dy != DY ||
+      new_vx != VX ||
+      new_vy != VY ||
+      new_ex != EX ||
+      new_ey != EY ||
       new_sxsize != SXSIZE ||
       new_sysize != SYSIZE ||
+      new_dxsize != DXSIZE ||
+      new_dysize != DYSIZE ||
+      new_vxsize != VXSIZE ||
+      new_vysize != VYSIZE ||
+      new_exsize != EXSIZE ||
+      new_eysize != EYSIZE ||
       new_real_sx != REAL_SX ||
       new_real_sy != REAL_SY ||
       new_full_sxsize != FULL_SXSIZE ||
       new_full_sysize != FULL_SYSIZE ||
-      new_tilesize_var != TILESIZE_VAR ||
+      new_tilesize_var != TILESIZE_VAR
+#if 0
+      ||
       vp_door_1->x != *door_1_x ||
       vp_door_1->y != *door_1_y ||
       vp_door_2->x != *door_2_x ||
-      vp_door_2->y != *door_2_y)
+      vp_door_2->y != *door_2_y
+#endif
+      )
   {
     SX = new_sx;
     SY = new_sy;
+    DX = new_dx;
+    DY = new_dy;
+    VX = new_vx;
+    VY = new_vy;
+    EX = new_ex;
+    EY = new_ey;
     SXSIZE = new_sxsize;
     SYSIZE = new_sysize;
+    DXSIZE = new_dxsize;
+    DYSIZE = new_dysize;
+    VXSIZE = new_vxsize;
+    VYSIZE = new_vysize;
+    EXSIZE = new_exsize;
+    EYSIZE = new_eysize;
     REAL_SX = new_real_sx;
     REAL_SY = new_real_sy;
     FULL_SXSIZE = new_full_sxsize;
@@ -10115,10 +11161,12 @@ void ChangeViewportPropertiesIfNeeded()
           setup.small_game_graphics);
 #endif
 
+#if 0
     *door_1_x = vp_door_1->x;
     *door_1_y = vp_door_1->y;
     *door_2_x = vp_door_2->x;
     *door_2_y = vp_door_2->y;
+#endif
 
 #if 1
     init_gfx_buffers = TRUE;