rnd-20020914-1-src
[rocksndiamonds.git] / src / tools.c
index dbd8c5d5b9c567b5e5aca73c7f45c521b8fa4631..0552e4af67d70ebf2d041e2ad1e83b5cbf98fd30 100644 (file)
@@ -1,35 +1,24 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2002 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  tools.c                                                 *
+* tools.c                                                  *
 ***********************************************************/
 
-#include <stdarg.h>
-
-#ifdef __FreeBSD__
-#include <machine/joystick.h>
-#endif
+#include "libgame/libgame.h"
 
 #include "tools.h"
 #include "game.h"
 #include "events.h"
-#include "sound.h"
-#include "misc.h"
-#include "buttons.h"
-#include "joystick.h"
 #include "cartoons.h"
 #include "network.h"
-
-#ifdef MSDOS
-extern boolean wait_for_vsync;
-#endif
+#include "tape.h"
 
 /* tool button identifiers */
 #define TOOL_CTRL_ID_YES       0
@@ -82,10 +71,55 @@ void SetDrawtoField(int mode)
   }
 }
 
+void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
+{
+  if (game_status == PLAYING)
+  {
+    if (force_redraw)
+    {
+      x = gfx.sx - TILEX;
+      y = gfx.sy - TILEY;
+      width = gfx.sxsize + 2 * TILEX;
+      height = gfx.sysize + 2 * TILEY;
+    }
+
+    if (force_redraw || setup.direct_draw)
+    {
+      int xx, yy;
+      int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
+      int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
+
+      if (setup.direct_draw)
+       SetDrawtoField(DRAW_BACKBUFFER);
+
+      for(xx=BX1; xx<=BX2; xx++)
+       for(yy=BY1; yy<=BY2; yy++)
+         if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
+           DrawScreenField(xx, yy);
+      DrawAllPlayers();
+
+      if (setup.direct_draw)
+       SetDrawtoField(DRAW_DIRECT);
+    }
+
+    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);
+    }
+  }
+
+  BlitBitmap(drawto, window, x, y, width, height, x, y);
+}
+
 void BackToFront()
 {
   int x,y;
-  Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
+  DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
 
   if (setup.direct_draw && game_status == PLAYING)
     redraw_mask &= ~REDRAW_MAIN;
@@ -96,21 +130,49 @@ void BackToFront()
   if (redraw_mask & REDRAW_FIELD)
     redraw_mask &= ~REDRAW_TILES;
 
-  if (!redraw_mask)
+  if (redraw_mask == REDRAW_NONE)
     return;
 
+  if (global.fps_slowdown && game_status == PLAYING)
+  {
+    static boolean last_frame_skipped = FALSE;
+    boolean skip_even_when_not_scrolling = TRUE;
+    boolean just_scrolling = (ScreenMovDir != 0);
+    boolean verbose = FALSE;
+
+    if (global.fps_slowdown_factor > 1 &&
+       (FrameCounter % global.fps_slowdown_factor) &&
+       (just_scrolling || skip_even_when_not_scrolling))
+    {
+      redraw_mask &= ~REDRAW_MAIN;
+
+      last_frame_skipped = TRUE;
+
+      if (verbose)
+       printf("FRAME SKIPPED\n");
+    }
+    else
+    {
+      if (last_frame_skipped)
+       redraw_mask |= REDRAW_FIELD;
+
+      last_frame_skipped = FALSE;
+
+      if (verbose)
+       printf("frame not skipped\n");
+    }
+  }
+
   /* synchronize X11 graphics at this point; if we would synchronize the
      display immediately after the buffer switching (after the XFlush),
      this could mean that we have to wait for the graphics to complete,
      although we could go on doing calculations for the next frame */
 
-  XSync(display, FALSE);
+  SyncDisplay();
 
   if (redraw_mask & REDRAW_ALL)
   {
-    XCopyArea(display, backbuffer, window, gc,
-             0, 0, WIN_XSIZE, WIN_YSIZE,
-             0, 0);
+    BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
     redraw_mask = 0;
   }
 
@@ -118,9 +180,8 @@ void BackToFront()
   {
     if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
     {
-      XCopyArea(display, backbuffer, window, gc,
-               REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
-               REAL_SX, REAL_SY);
+      BlitBitmap(backbuffer, window,
+                REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
     }
     else
     {
@@ -137,7 +198,7 @@ void BackToFront()
          ABS(ScreenMovPos) == ScrollStepSize ||
          redraw_tiles > REDRAWTILES_THRESHOLD)
       {
-       XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
+       BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
 
 #ifdef DEBUG
 #if 0
@@ -154,55 +215,50 @@ void BackToFront()
 #endif
       }
     }
+
     redraw_mask &= ~REDRAW_MAIN;
   }
 
   if (redraw_mask & REDRAW_DOORS)
   {
     if (redraw_mask & REDRAW_DOOR_1)
-      XCopyArea(display, backbuffer, window, gc,
-               DX, DY, DXSIZE, DYSIZE,
-               DX, DY);
+      BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
     if (redraw_mask & REDRAW_DOOR_2)
     {
       if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
-       XCopyArea(display,backbuffer,window,gc,
-                 VX,VY, VXSIZE,VYSIZE,
-                 VX,VY);
+       BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
       else
       {
        if (redraw_mask & REDRAW_VIDEO_1)
-         XCopyArea(display,backbuffer,window,gc,
-                   VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
-                   VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
-                   VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
+         BlitBitmap(backbuffer, window,
+                    VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
+                    VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
+                    VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
        if (redraw_mask & REDRAW_VIDEO_2)
-         XCopyArea(display,backbuffer,window,gc,
-                   VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
-                   VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
-                   VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
+         BlitBitmap(backbuffer, window,
+                    VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
+                    VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
+                    VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
        if (redraw_mask & REDRAW_VIDEO_3)
-         XCopyArea(display,backbuffer,window,gc,
-                   VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
-                   VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
-                   VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
+         BlitBitmap(backbuffer, window,
+                    VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
+                    VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
+                    VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
       }
     }
     if (redraw_mask & REDRAW_DOOR_3)
-      XCopyArea(display, backbuffer, window, gc,
-               EX, EY, EXSIZE, EYSIZE,
-               EX, EY);
+      BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
     redraw_mask &= ~REDRAW_DOORS;
   }
 
   if (redraw_mask & REDRAW_MICROLEVEL)
   {
-    XCopyArea(display,backbuffer,window,gc,
-             MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
-             MICROLEV_XPOS, MICROLEV_YPOS);
-    XCopyArea(display,backbuffer,window,gc,
-             SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
-             SX, MICROLABEL_YPOS);
+    BlitBitmap(backbuffer, window,
+              MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
+              MICROLEV_XPOS, MICROLEV_YPOS);
+    BlitBitmap(backbuffer, window,
+              SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
+              SX, MICROLABEL_YPOS);
     redraw_mask &= ~REDRAW_MICROLEVEL;
   }
 
@@ -211,96 +267,111 @@ void BackToFront()
     for(x=0; x<SCR_FIELDX; x++)
       for(y=0; y<SCR_FIELDY; y++)
        if (redraw[redraw_x1 + x][redraw_y1 + y])
-         XCopyArea(display, buffer, window, gc,
-                   FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
-                   SX + x * TILEX, SY + y * TILEY);
+         BlitBitmap(buffer, window,
+                    FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
+                    SX + x * TILEX, SY + y * TILEY);
+  }
+
+  if (redraw_mask & REDRAW_FPS)                /* display frames per second */
+  {
+    char text[100];
+    char info1[100];
+
+    sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
+    if (!global.fps_slowdown)
+      info1[0] = '\0';
+
+    sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
+    DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
   }
 
-  XFlush(display);
+  FlushDisplay();
 
   for(x=0; x<MAX_BUF_XSIZE; x++)
     for(y=0; y<MAX_BUF_YSIZE; y++)
       redraw[x][y] = 0;
   redraw_tiles = 0;
-  redraw_mask = 0;
+  redraw_mask = REDRAW_NONE;
 }
 
 void FadeToFront()
 {
-/*
+#if 0
   long fading_delay = 300;
 
   if (setup.fading && (redraw_mask & REDRAW_FIELD))
   {
-*/
+#endif
 
-/*
+#if 0
     int x,y;
 
-    XFillRectangle(display,window,gc,
-                  REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
-    XFlush(display);
+    ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
+    FlushDisplay();
 
     for(i=0;i<2*FULL_SYSIZE;i++)
     {
       for(y=0;y<FULL_SYSIZE;y++)
       {
-       XCopyArea(display,backbuffer,window,gc,
-                 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
+       BlitBitmap(backbuffer, window,
+                  REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
       }
-      XFlush(display);
+      FlushDisplay();
       Delay(10);
     }
-*/
+#endif
 
-/*
+#if 0
     for(i=1;i<FULL_SYSIZE;i+=2)
-      XCopyArea(display,backbuffer,window,gc,
-               REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
-    XFlush(display);
+      BlitBitmap(backbuffer, window,
+                REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
+    FlushDisplay();
     Delay(fading_delay);
-*/
+#endif
 
-/*
-    XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
-    XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
-             REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
-    XFlush(display);
+#if 0
+    SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
+    BlitBitmapMasked(backbuffer, window,
+                    REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
+                    REAL_SX,REAL_SY);
+    FlushDisplay();
     Delay(fading_delay);
 
-    XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
-    XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
-             REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
-    XFlush(display);
+    SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
+    BlitBitmapMasked(backbuffer, window,
+                    REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
+                    REAL_SX,REAL_SY);
+    FlushDisplay();
     Delay(fading_delay);
 
-    XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
-    XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
-             REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
-    XFlush(display);
+    SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
+    BlitBitmapMasked(backbuffer, window,
+                    REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
+                    REAL_SX,REAL_SY);
+    FlushDisplay();
     Delay(fading_delay);
 
-    XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
-    XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
-             REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
-    XFlush(display);
+    SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
+    BlitBitmapMasked(backbuffer, window,
+                    REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
+                    REAL_SX,REAL_SY);
+    FlushDisplay();
     Delay(fading_delay);
 
     redraw_mask &= ~REDRAW_MAIN;
   }
-*/
+#endif
 
   BackToFront();
 }
 
 void ClearWindow()
 {
-  XFillRectangle(display, backbuffer, gc,
-                REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+  ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
 
   if (setup.soft_scrolling && game_status == PLAYING)
   {
-    XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
+    ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
     SetDrawtoField(DRAW_BUFFERED);
   }
   else
@@ -308,150 +379,41 @@ void ClearWindow()
 
   if (setup.direct_draw && game_status == PLAYING)
   {
-    XFillRectangle(display, window, gc,
-                  REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+    ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
     SetDrawtoField(DRAW_DIRECT);
   }
 
   redraw_mask |= REDRAW_FIELD;
 }
 
-int getFontWidth(int font_size, int font_type)
-{
-  return (font_size == FS_BIG ? FONT1_XSIZE :
-         font_size == FS_MEDIUM ? FONT6_XSIZE :
-         font_type == FC_SPECIAL1 ? FONT3_XSIZE :
-         font_type == FC_SPECIAL2 ? FONT4_XSIZE :
-         font_type == FC_SPECIAL3 ? FONT5_XSIZE :
-         FONT2_XSIZE);
-}
-
-int getFontHeight(int font_size, int font_type)
-{
-  return (font_size == FS_BIG ? FONT1_YSIZE :
-         font_size == FS_MEDIUM ? FONT6_YSIZE :
-         font_type == FC_SPECIAL1 ? FONT3_YSIZE :
-         font_type == FC_SPECIAL2 ? FONT4_YSIZE :
-         font_type == FC_SPECIAL3 ? FONT5_YSIZE :
-         FONT2_YSIZE);
-}
-
-void DrawInitText(char *text, int ypos, int color)
-{
-  if (display && window && pix[PIX_SMALLFONT])
-  {
-    XFillRectangle(display, window, gc, 0, ypos, WIN_XSIZE, FONT2_YSIZE);
-    DrawTextExt(window, gc, (WIN_XSIZE - strlen(text) * FONT2_XSIZE)/2,
-               ypos,text,FS_SMALL,color);
-    XFlush(display);
-  }
-}
-
-void DrawTextFCentered(int y, int font_type, char *format, ...)
-{
-  char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
-  int font_width = getFontWidth(FS_SMALL, font_type);
-  va_list ap;
-
-  va_start(ap, format);
-  vsprintf(buffer, format, ap);
-  va_end(ap);
-
-  DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
-          buffer, FS_SMALL, font_type);
-}
-
-void DrawTextF(int x, int y, int font_type, char *format, ...)
+void MarkTileDirty(int x, int y)
 {
-  char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
-  va_list ap;
+  int xx = redraw_x1 + x;
+  int yy = redraw_y1 + y;
 
-  va_start(ap, format);
-  vsprintf(buffer, format, ap);
-  va_end(ap);
+  if (!redraw[xx][yy])
+    redraw_tiles++;
 
-  DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
+  redraw[xx][yy] = TRUE;
+  redraw_mask |= REDRAW_TILES;
 }
 
-void DrawText(int x, int y, char *text, int font_size, int font_type)
+void SetBorderElement()
 {
-  DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
-
-  if (x < DX)
-    redraw_mask |= REDRAW_FIELD;
-  else if (y < VY)
-    redraw_mask |= REDRAW_DOOR_1;
-}
-
-void DrawTextExt(Drawable d, GC gc, int x, int y,
-                char *text, int font_size, int font_type)
-{
-  int font_width, font_height, font_start;
-  int font_pixmap;
-  boolean print_inverse = FALSE;
-
-  if (font_size != FS_SMALL && font_size != FS_BIG && font_size != FS_MEDIUM)
-    font_size = FS_SMALL;
-  if (font_type < FC_RED || font_type > FC_SPECIAL3)
-    font_type = FC_RED;
-
-  font_width = getFontWidth(font_size, font_type);
-  font_height = getFontHeight(font_size, font_type);
-
-  font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT :
-                font_size == FS_MEDIUM ? PIX_MEDIUMFONT :
-                PIX_SMALLFONT);
-  font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE :
-                            font_size == FS_MEDIUM ? FONT6_YSIZE :
-                            FONT2_YSIZE) *
-               FONT_LINES_PER_FONT);
+  int x, y;
 
-  if (font_type == FC_SPECIAL3)
-    font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
+  BorderElement = EL_LEERRAUM;
 
-  while (*text)
+  for(y=0; y<lev_fieldy && BorderElement == EL_LEERRAUM; y++)
   {
-    char c = *text++;
-
-    if (c == '~' && font_size == FS_SMALL)
+    for(x=0; x<lev_fieldx; x++)
     {
-      print_inverse = TRUE;
-      continue;
-    }
-
-    if (c >= 'a' && c <= 'z')
-      c = 'A' + (c - 'a');
-    else if (c == 'ä' || c == 'Ä')
-      c = 91;
-    else if (c == 'ö' || c == 'Ö')
-      c = 92;
-    else if (c == 'ü' || c == 'Ü')
-      c = 93;
+      if (!IS_MASSIVE(Feld[x][y]))
+       BorderElement = EL_BETON;
 
-    if (c >= 32 && c <= 95)
-    {
-      int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
-      int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
-      int dest_x = x, dest_y = y;
-
-      if (print_inverse)
-      {
-       XCopyArea(display, pix[font_pixmap], d, gc,
-                 FONT_CHARS_PER_LINE * font_width,
-                 3 * font_height + font_start,
-                 font_width, font_height, x, y);
-
-       XSetClipOrigin(display, clip_gc[font_pixmap],
-                      dest_x - src_x, dest_y - src_y);
-       XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
-                 0, 0, font_width, font_height, dest_x, dest_y);
-      }
-      else
-       XCopyArea(display, pix[font_pixmap], d, gc,
-                 src_x, src_y, font_width, font_height, dest_x, dest_y);
+      if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
+       x = lev_fieldx - 2;
     }
-
-    x += font_width;
   }
 }
 
@@ -506,7 +468,10 @@ void DrawPlayer(struct PlayerInfo *player)
     if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
     {
       DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
-      DrawLevelFieldThruMask(last_jx, last_jy);
+      if (last_element == EL_DYNAMITE_ACTIVE)
+       DrawDynamite(last_jx, last_jy);
+      else
+       DrawLevelFieldThruMask(last_jx, last_jy);
     }
     else if (last_element == EL_DYNAMITE_ACTIVE)
       DrawDynamite(last_jx, last_jy);
@@ -539,6 +504,8 @@ void DrawPlayer(struct PlayerInfo *player)
     DrawLevelElement(jx, jy, Store[jx][jy]);
   else if (!IS_ACTIVE_BOMB(element))
     DrawLevelField(jx, jy);
+  else
+    DrawLevelElement(jx, jy, EL_LEERRAUM);
 
   /* draw player himself */
 
@@ -589,7 +556,7 @@ void DrawPlayer(struct PlayerInfo *player)
       else
        graphic = GFX_MURPHY_GO_LEFT;
 
-      graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
+      graphic += getGraphicAnimationPhase(3, 2, ANIM_PINGPONG);
     }
 
     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
@@ -631,7 +598,7 @@ void DrawPlayer(struct PlayerInfo *player)
                   GFX2_SHIELD_PASSIVE);
 
     DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
-                                       3, 8, ANIM_OSCILLATE);
+                                       3, 8, ANIM_PINGPONG);
   }
 
   if (player->Pushing && player->GfxPos)
@@ -711,8 +678,8 @@ void DrawPlayer(struct PlayerInfo *player)
     int x_size = TILEX * (1 + ABS(jx - last_jx));
     int y_size = TILEY * (1 + ABS(jy - last_jy));
 
-    XCopyArea(display, drawto_field, window, gc,
-             dest_x, dest_y, x_size, y_size, dest_x, dest_y);
+    BlitBitmap(drawto_field, window,
+              dest_x, dest_y, x_size, y_size, dest_x, dest_y);
     SetDrawtoField(DRAW_DIRECT);
   }
 
@@ -723,9 +690,10 @@ static int getGraphicAnimationPhase(int frames, int delay, int mode)
 {
   int phase;
 
-  if (mode == ANIM_OSCILLATE)
+  if (mode == ANIM_PINGPONG)
   {
     int max_anim_frames = 2 * frames - 2;
+
     phase = (FrameCounter % (delay * max_anim_frames)) / delay;
     phase = (phase < frames ? phase : max_anim_frames - phase);
   }
@@ -735,7 +703,30 @@ static int getGraphicAnimationPhase(int frames, int delay, int mode)
   if (mode == ANIM_REVERSE)
     phase = -phase;
 
-  return(phase);
+  return phase;
+}
+
+static int getNewGraphicAnimationFrame(int graphic)
+{
+  int frames = new_graphic_info[graphic].anim_frames;
+  int delay = new_graphic_info[graphic].anim_delay;
+  int mode = new_graphic_info[graphic].anim_mode;
+  int phase;
+
+  if (mode == ANIM_PINGPONG)
+  {
+    int max_anim_frames = 2 * frames - 2;
+
+    phase = (FrameCounter % (delay * max_anim_frames)) / delay;
+    phase = (phase < frames ? phase : max_anim_frames - phase);
+  }
+  else
+    phase = (FrameCounter % (delay * frames)) / delay;
+
+  if (mode == ANIM_REVERSE)
+    phase = (frames - 1) - phase;
+
+  return phase;
 }
 
 void DrawGraphicAnimationExt(int x, int y, int graphic,
@@ -752,12 +743,32 @@ void DrawGraphicAnimationExt(int x, int y, int graphic,
   }
 }
 
+void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
+{
+  int delay = new_graphic_info[graphic].anim_delay;
+
+  if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+  {
+    int frame = getNewGraphicAnimationFrame(graphic);
+
+    if (mask_mode == USE_MASKING)
+      DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
+    else
+      DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+  }
+}
+
 void DrawGraphicAnimation(int x, int y, int graphic,
                          int frames, int delay, int mode)
 {
   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
 }
 
+void DrawNewGraphicAnimation(int x, int y, int graphic)
+{
+  DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
+}
+
 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
                                  int frames, int delay, int mode)
 {
@@ -775,54 +786,60 @@ static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
 }
 
-void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
+void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
 {
-  if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
+  if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
   {
-    graphic -= GFX_START_ROCKSSCREEN;
-    *pixmap_nr = PIX_BACK;
-    *x = SX + (graphic % GFX_PER_LINE) * TILEX;
-    *y = SY + (graphic / GFX_PER_LINE) * TILEY;
+    *bitmap = graphic_info[graphic].bitmap;
+    *x = graphic_info[graphic].src_x;
+    *y = graphic_info[graphic].src_y;
+  }
+  else if (graphic >= GFX_START_ROCKSELEMENTS &&
+          graphic <= GFX_END_ROCKSELEMENTS)
+  {
+    graphic -= GFX_START_ROCKSELEMENTS;
+    *bitmap = pix[PIX_ELEMENTS];
+    *x = (graphic % GFX_PER_LINE) * TILEX;
+    *y = (graphic / GFX_PER_LINE) * TILEY;
   }
   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
   {
     graphic -= GFX_START_ROCKSHEROES;
-    *pixmap_nr = PIX_HEROES;
+    *bitmap = pix[PIX_HEROES];
     *x = (graphic % HEROES_PER_LINE) * TILEX;
     *y = (graphic / HEROES_PER_LINE) * TILEY;
   }
   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
   {
     graphic -= GFX_START_ROCKSSP;
-    *pixmap_nr = PIX_SP;
+    *bitmap = pix[PIX_SP];
     *x = (graphic % SP_PER_LINE) * TILEX;
     *y = (graphic / SP_PER_LINE) * TILEY;
   }
   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
   {
     graphic -= GFX_START_ROCKSDC;
-    *pixmap_nr = PIX_DC;
+    *bitmap = pix[PIX_DC];
     *x = (graphic % DC_PER_LINE) * TILEX;
     *y = (graphic / DC_PER_LINE) * TILEY;
   }
   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
   {
     graphic -= GFX_START_ROCKSMORE;
-    *pixmap_nr = PIX_MORE;
+    *bitmap = pix[PIX_MORE];
     *x = (graphic % MORE_PER_LINE) * TILEX;
     *y = (graphic / MORE_PER_LINE) * TILEY;
   }
   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
   {
     graphic -= GFX_START_ROCKSFONT;
-    *pixmap_nr = PIX_BIGFONT;
+    *bitmap = pix[PIX_FONT_EM];
     *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
-    *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
-         FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
+    *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
   }
   else
   {
-    *pixmap_nr = PIX_SP;
+    *bitmap = pix[PIX_SP];
     *x = 0;
     *y = 0;
   }
@@ -831,32 +848,62 @@ void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
 void DrawGraphic(int x, int y, int graphic)
 {
 #if DEBUG
-  if (!IN_SCR_FIELD(x,y))
+  if (!IN_SCR_FIELD(x, y))
   {
-    printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
+    printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
     printf("DrawGraphic(): This should never happen!\n");
     return;
   }
 #endif
 
-  DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
-  MarkTileDirty(x,y);
+  DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
+  MarkTileDirty(x, y);
 }
 
-void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
+void DrawNewGraphic(int x, int y, int graphic, int frame)
 {
-  int pixmap_nr;
+#if DEBUG
+  if (!IN_SCR_FIELD(x, y))
+  {
+    printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
+    printf("DrawNewGraphic(): This should never happen!\n");
+    return;
+  }
+#endif
+
+  DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
+                   graphic, frame);
+  MarkTileDirty(x, y);
+}
+
+void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
+{
+  Bitmap *src_bitmap;
   int src_x, src_y;
 
-  getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
-  XCopyArea(display, pix[pixmap_nr], d, gc,
-           src_x, src_y, TILEX, TILEY, x, y);
+  getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+  BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
+}
+
+void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
+                      int frame)
+{
+  Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
+  int src_x = new_graphic_info[graphic].src_x;
+  int src_y = new_graphic_info[graphic].src_y;
+
+  if (new_graphic_info[graphic].anim_vertical)
+    src_y += frame * TILEY;
+  else
+    src_x += frame * TILEX;
+
+  BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
 }
 
 void DrawGraphicThruMask(int x, int y, int graphic)
 {
 #if DEBUG
-  if (!IN_SCR_FIELD(x,y))
+  if (!IN_SCR_FIELD(x, y))
   {
     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
     printf("DrawGraphicThruMask(): This should never happen!\n");
@@ -864,105 +911,135 @@ void DrawGraphicThruMask(int x, int y, int graphic)
   }
 #endif
 
-  DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
-  MarkTileDirty(x,y);
+  DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
+  MarkTileDirty(x, y);
+}
+
+void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
+{
+#if DEBUG
+  if (!IN_SCR_FIELD(x, y))
+  {
+    printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
+    printf("DrawGraphicThruMask(): This should never happen!\n");
+    return;
+  }
+#endif
+
+  DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
+                           graphic, frame);
+  MarkTileDirty(x, y);
 }
 
-void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
+void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
 {
   int tile = graphic;
-  int pixmap_nr;
   int src_x, src_y;
-  Pixmap src_pixmap;
+  Bitmap *src_bitmap;
   GC drawing_gc;
 
   if (graphic == GFX_LEERRAUM)
     return;
 
-  getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
-  src_pixmap = pix[pixmap_nr];
-  drawing_gc = clip_gc[pixmap_nr];
+  getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+  drawing_gc = src_bitmap->stored_clip_gc;
 
   if (tile_clipmask[tile] != None)
   {
-    XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
-    XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
-    XCopyArea(display, src_pixmap, d, tile_clip_gc,
-             src_x, src_y, TILEX, TILEY, dest_x, dest_y);
+    SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
+    SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
+    BlitBitmapMasked(src_bitmap, d,
+                    src_x, src_y, TILEX, TILEY, dest_x, dest_y);
   }
   else
   {
 #if DEBUG
+#ifndef TARGET_SDL
     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
+#endif
 #endif
 
-    XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
-    XCopyArea(display, src_pixmap, d, drawing_gc,
-             src_x, src_y, TILEX, TILEY, dest_x, dest_y);
+    SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
+    BlitBitmapMasked(src_bitmap, d,
+                    src_x, src_y, TILEX, TILEY, dest_x, dest_y);
   }
 }
 
+void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
+                              int graphic, int frame)
+{
+  Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
+  GC drawing_gc = src_bitmap->stored_clip_gc;
+  int src_x = new_graphic_info[graphic].src_x;
+  int src_y = new_graphic_info[graphic].src_y;
+
+  if (new_graphic_info[graphic].anim_vertical)
+    src_y += frame * TILEY;
+  else
+    src_x += frame * TILEX;
+
+  SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
+  BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
+}
+
 void DrawMiniGraphic(int x, int y, int graphic)
 {
-  DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
+  DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
   MarkTileDirty(x/2, y/2);
 }
 
-void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
+void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
 {
-  if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
+  if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
   {
-    graphic -= GFX_START_ROCKSSCREEN;
-    *pixmap = pix[PIX_BACK];
+    graphic -= GFX_START_ROCKSELEMENTS;
+    *bitmap = pix[PIX_ELEMENTS];
     *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
     *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
   }
   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
   {
     graphic -= GFX_START_ROCKSSP;
-    graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
-    *pixmap = pix[PIX_SP];
+    *bitmap = pix[PIX_SP];
     *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
     *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
   }
   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
   {
     graphic -= GFX_START_ROCKSDC;
-    *pixmap = pix[PIX_DC];
+    *bitmap = pix[PIX_DC];
     *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
     *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
   }
   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
   {
     graphic -= GFX_START_ROCKSMORE;
-    *pixmap = pix[PIX_MORE];
+    *bitmap = pix[PIX_MORE];
     *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
     *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
   }
   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
   {
     graphic -= GFX_START_ROCKSFONT;
-    *pixmap = pix[PIX_SMALLFONT];
-    *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
-    *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
-             FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
+    *bitmap = pix[PIX_FONT_EM];
+    *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
+    *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
   }
   else
   {
-    *pixmap = pix[PIX_SP];
+    *bitmap = pix[PIX_SP];
     *x = MINI_SP_STARTX;
     *y = MINI_SP_STARTY;
   }
 }
 
-void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
+void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
 {
-  Pixmap pixmap;
+  Bitmap *bitmap;
   int src_x, src_y;
 
-  getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
-  XCopyArea(display, pixmap, d, gc,
-           src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
+  getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
+  BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
 }
 
 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
@@ -972,8 +1049,7 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
   int cx = 0, cy = 0;
   int src_x, src_y, dest_x, dest_y;
   int tile = graphic;
-  int pixmap_nr;
-  Pixmap src_pixmap;
+  Bitmap *src_bitmap;
   GC drawing_gc;
 
   if (graphic < 0)
@@ -1046,9 +1122,8 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
       MarkTileDirty(x, y + SIGN(dy));
   }
 
-  getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
-  src_pixmap = pix[pixmap_nr];
-  drawing_gc = clip_gc[pixmap_nr];
+  getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+  drawing_gc = src_bitmap->stored_clip_gc;
 
   src_x += cx;
   src_y += cy;
@@ -1069,25 +1144,27 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
   {
     if (tile_clipmask[tile] != None)
     {
-      XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
-      XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
-      XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
-               src_x, src_y, TILEX, TILEY, dest_x, dest_y);
+      SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
+      SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
+      BlitBitmapMasked(src_bitmap, drawto_field,
+                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
     }
     else
     {
 #if DEBUG
+#ifndef        TARGET_SDL
       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
+#endif
 #endif
 
-      XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
-      XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
-               src_x, src_y, width, height, dest_x, dest_y);
+      SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
+      BlitBitmapMasked(src_bitmap, drawto_field,
+                      src_x, src_y, width, height, dest_x, dest_y);
     }
   }
   else
-    XCopyArea(display, src_pixmap, drawto_field, gc,
-             src_x, src_y, width, height, dest_x, dest_y);
+    BlitBitmap(src_bitmap, drawto_field,
+              src_x, src_y, width, height, dest_x, dest_y);
 
   MarkTileDirty(x,y);
 }
@@ -1110,14 +1187,14 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
 
   if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
   {
-    graphic += 4 * !phase2;
+    graphic += 1 * !phase2;
 
     if (dir == MV_UP)
-      graphic += 1;
+      graphic += 1 * 2;
     else if (dir == MV_LEFT)
-      graphic += 2;
+      graphic += 2 * 2;
     else if (dir == MV_DOWN)
-      graphic += 3;
+      graphic += 3 * 2;
   }
   else if (element == EL_SP_SNIKSNAK)
   {
@@ -1177,7 +1254,9 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
   else if ((element == EL_FELSBROCKEN ||
            element == EL_SP_ZONK ||
            element == EL_BD_ROCK ||
-           IS_GEM(element)) && !cut_mode)
+           element == EL_SP_INFOTRON ||
+           IS_GEM(element))
+          && !cut_mode)
   {
     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
     {
@@ -1196,12 +1275,16 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
        graphic += phase2;
     }
   }
-  else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
-          element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
+  else if (element == EL_MAGIC_WALL_EMPTY ||
+          element == EL_MAGIC_WALL_EMPTYING ||
+          element == EL_MAGIC_WALL_BD_EMPTY ||
+          element == EL_MAGIC_WALL_BD_EMPTYING ||
+          element == EL_MAGIC_WALL_FULL ||
+          element == EL_MAGIC_WALL_BD_FULL)
   {
     graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
   }
-  else if (IS_AMOEBOID(element))
+  else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
   {
     graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
     graphic += (x + 2 * y + 4) % 4;
@@ -1276,6 +1359,8 @@ void DrawLevelFieldThruMask(int x, int y)
 
 void ErdreichAnbroeckeln(int x, int y)
 {
+  Bitmap *src_bitmap;
+  int src_x, src_y;
   int i, width, height, cx,cy;
   int ux = LEVELX(x), uy = LEVELY(y);
   int element, graphic;
@@ -1303,6 +1388,8 @@ void ErdreichAnbroeckeln(int x, int y)
 
     graphic = GFX_ERDENRAND;
 
+    getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+
     for(i=0; i<4; i++)
     {
       int uxx, uyy;
@@ -1335,10 +1422,8 @@ void ErdreichAnbroeckeln(int x, int y)
        cy = (i == 3 ? TILEY - snip : 0);
       }
 
-      XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
-               SX + (graphic % GFX_PER_LINE) * TILEX + cx,
-               SY + (graphic / GFX_PER_LINE) * TILEY + cy,
-               width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
+      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+                width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
     }
 
     MarkTileDirty(x, y);
@@ -1347,6 +1432,8 @@ void ErdreichAnbroeckeln(int x, int y)
   {
     graphic = GFX_ERDENRAND;
 
+    getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+
     for(i=0; i<4; i++)
     {
       int xx, yy, uxx, uyy;
@@ -1379,10 +1466,8 @@ void ErdreichAnbroeckeln(int x, int y)
        cy = (i==0 ? TILEY-snip : 0);
       }
 
-      XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
-               SX + (graphic % GFX_PER_LINE) * TILEX + cx,
-               SY + (graphic / GFX_PER_LINE) * TILEY + cy,
-               width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
+      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+                width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
 
       MarkTileDirty(xx, yy);
     }
@@ -1404,7 +1489,7 @@ void DrawLevelElement(int x, int y, int element)
 void DrawScreenField(int x, int y)
 {
   int ux = LEVELX(x), uy = LEVELY(y);
-  int element;
+  int element, content;
 
   if (!IN_LEV_FIELD(ux, uy))
   {
@@ -1418,33 +1503,36 @@ void DrawScreenField(int x, int y)
   }
 
   element = Feld[ux][uy];
+  content = Store[ux][uy];
 
   if (IS_MOVING(ux, uy))
   {
     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
     boolean cut_mode = NO_CUTTING;
 
-    if (Store[ux][uy] == EL_MORAST_LEER ||
-       Store[ux][uy] == EL_SIEB_LEER ||
-       Store[ux][uy] == EL_SIEB2_LEER ||
-       Store[ux][uy] == EL_AMOEBE_NASS)
+    if (element == EL_QUICKSAND_EMPTYING ||
+       element == EL_MAGIC_WALL_EMPTYING ||
+       element == EL_MAGIC_WALL_BD_EMPTYING ||
+       element == EL_AMOEBA_DRIPPING)
       cut_mode = CUT_ABOVE;
-    else if (Store[ux][uy] == EL_MORAST_VOLL ||
-            Store[ux][uy] == EL_SIEB_VOLL ||
-            Store[ux][uy] == EL_SIEB2_VOLL)
+    else if (element == EL_QUICKSAND_FILLING ||
+            element == EL_MAGIC_WALL_FILLING ||
+            element == EL_MAGIC_WALL_BD_FILLING)
       cut_mode = CUT_BELOW;
 
     if (cut_mode == CUT_ABOVE)
-      DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
+      DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
     else
       DrawScreenElement(x, y, EL_LEERRAUM);
 
     if (horiz_move)
       DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
-    else
+    else if (cut_mode == NO_CUTTING)
       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
+    else
+      DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
 
-    if (Store[ux][uy] == EL_SALZSAEURE)
+    if (content == EL_SALZSAEURE)
       DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
   }
   else if (IS_BLOCKED(ux, uy))
@@ -1453,6 +1541,7 @@ void DrawScreenField(int x, int y)
     int sx, sy;
     int horiz_move;
     boolean cut_mode = NO_CUTTING;
+    int element_old, content_old;
 
     Blocked2Moving(ux, uy, &oldx, &oldy);
     sx = SCREENX(oldx);
@@ -1460,19 +1549,26 @@ void DrawScreenField(int x, int y)
     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
                  MovDir[oldx][oldy] == MV_RIGHT);
 
-    if (Store[oldx][oldy] == EL_MORAST_LEER ||
-       Store[oldx][oldy] == EL_SIEB_LEER ||
-       Store[oldx][oldy] == EL_SIEB2_LEER ||
-       Store[oldx][oldy] == EL_AMOEBE_NASS)
+    element_old = Feld[oldx][oldy];
+    content_old = Store[oldx][oldy];
+
+    if (element_old == EL_QUICKSAND_EMPTYING ||
+       element_old == EL_MAGIC_WALL_EMPTYING ||
+       element_old == EL_MAGIC_WALL_BD_EMPTYING ||
+       element_old == EL_AMOEBA_DRIPPING)
       cut_mode = CUT_ABOVE;
 
     DrawScreenElement(x, y, EL_LEERRAUM);
-    element = Feld[oldx][oldy];
 
     if (horiz_move)
-      DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
+      DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
+                              NO_CUTTING);
+    else if (cut_mode == NO_CUTTING)
+      DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
+                              cut_mode);
     else
-      DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
+      DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
+                              cut_mode);
   }
   else if (IS_DRAWABLE(element))
     DrawScreenElement(x, y, element);
@@ -1562,33 +1658,40 @@ void DrawMicroElement(int xpos, int ypos, int element)
   if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
   {
     graphic -= GFX_START_ROCKSSP;
-    graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
-    XCopyArea(display, pix[PIX_SP], drawto, gc,
-             MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
-             MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
-             MICRO_TILEX, MICRO_TILEY, xpos, ypos);
+    BlitBitmap(pix[PIX_SP], drawto,
+              MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
+              MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
+              MICRO_TILEX, MICRO_TILEY, xpos, ypos);
   }
   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
   {
     graphic -= GFX_START_ROCKSDC;
-    XCopyArea(display, pix[PIX_DC], drawto, gc,
-             MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
-             MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
-             MICRO_TILEX, MICRO_TILEY, xpos, ypos);
+    BlitBitmap(pix[PIX_DC], drawto,
+              MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
+              MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
+              MICRO_TILEX, MICRO_TILEY, xpos, ypos);
   }
   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
   {
     graphic -= GFX_START_ROCKSMORE;
-    XCopyArea(display, pix[PIX_MORE], drawto, gc,
-             MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
-             MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
-             MICRO_TILEX, MICRO_TILEY, xpos, ypos);
+    BlitBitmap(pix[PIX_MORE], drawto,
+              MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
+              MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
+              MICRO_TILEX, MICRO_TILEY, xpos, ypos);
+  }
+  else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
+  {
+    graphic -= GFX_CHAR_START;
+    BlitBitmap(pix[PIX_FONT_EM], drawto,
+              MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
+              MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
+              MICRO_TILEX, MICRO_TILEY, xpos, ypos);
   }
   else
-    XCopyArea(display, pix[PIX_BACK], drawto, gc,
-             MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
-             MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
-             MICRO_TILEX, MICRO_TILEY, xpos, ypos);
+    BlitBitmap(pix[PIX_ELEMENTS], drawto,
+              MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
+              MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
+              MICRO_TILEX, MICRO_TILEY, xpos, ypos);
 }
 
 void DrawLevel()
@@ -1619,8 +1722,7 @@ static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
 {
   int x, y;
 
-  XFillRectangle(display, drawto, gc,
-                xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
+  ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
 
   if (lev_fieldx < STD_LEV_FIELDX)
     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
@@ -1661,8 +1763,7 @@ static void DrawMicroLevelLabelExt(int mode)
 {
   char label_text[MAX_MICROLABEL_SIZE + 1];
 
-  XFillRectangle(display, drawto,gc,
-                SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
+  ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
 
   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
                       mode == MICROLABEL_CREATED_BY ? "created by" :
@@ -1787,12 +1888,15 @@ int REQ_in_range(int x, int y)
   return 0;
 }
 
+#define MAX_REQUEST_LINES              13
+#define MAX_REQUEST_LINE_LEN           7
+
 boolean Request(char *text, unsigned int req_state)
 {
   int mx, my, ty, result = -1;
   unsigned int old_door_state;
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
   /* pause network game while waiting for request to answer */
   if (options.network &&
       game_status == PLAYING &&
@@ -1807,40 +1911,43 @@ boolean Request(char *text, unsigned int req_state)
   CloseDoor(DOOR_CLOSE_1);
 
   /* save old door content */
-  XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
-           DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
-           DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
+  BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
+            DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
+            DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
 
   /* clear door drawing field */
-  XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
+  ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
 
   /* write text for request */
-  for(ty=0; ty<13; ty++)
+  for(ty=0; ty < MAX_REQUEST_LINES; ty++)
   {
+    char text_line[MAX_REQUEST_LINE_LEN + 1];
     int tx, tl, tc;
-    char txt[256];
 
     if (!*text)
       break;
 
-    for(tl=0,tx=0; tx<7; tl++,tx++)
+    for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
     {
       tc = *(text + tx);
-      if (!tc || tc == 32)
+      if (!tc || tc == ' ')
        break;
     }
+
     if (!tl)
     { 
       text++; 
       ty--; 
       continue; 
     }
-    sprintf(txt, text); 
-    txt[tl] = 0;
-    DrawTextExt(drawto, gc,
-               DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
-               txt, FS_SMALL, FC_YELLOW);
-    text += tl + (tc == 32 ? 1 : 0);
+
+    strncpy(text_line, text, tl);
+    text_line[tl] = 0;
+
+    DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
+               text_line, FS_SMALL, FC_YELLOW);
+
+    text += tl + (tc == ' ' ? 1 : 0);
   }
 
   if (req_state & REQ_ASK)
@@ -1861,9 +1968,9 @@ boolean Request(char *text, unsigned int req_state)
   }
 
   /* copy request gadgets to door backbuffer */
-  XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
-           DX, DY, DXSIZE, DYSIZE,
-           DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+  BlitBitmap(drawto, pix[PIX_DB_DOOR],
+            DX, DY, DXSIZE, DYSIZE,
+            DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
 
   OpenDoor(DOOR_OPEN_1);
 
@@ -1883,43 +1990,37 @@ boolean Request(char *text, unsigned int req_state)
 
   while(result < 0)
   {
-    if (XPending(display))
+    if (PendingEvent())
     {
-      XEvent event;
+      Event event;
 
-      XNextEvent(display, &event);
+      NextEvent(&event);
 
       switch(event.type)
       {
-       case ButtonPress:
-       case ButtonRelease:
-       case MotionNotify:
+       case EVENT_BUTTONPRESS:
+       case EVENT_BUTTONRELEASE:
+       case EVENT_MOTIONNOTIFY:
        {
-         if (event.type == MotionNotify)
+         if (event.type == EVENT_MOTIONNOTIFY)
          {
-           Window root, child;
-           int root_x, root_y;
-           int win_x, win_y;
-           unsigned int mask;
-
-           if (!XQueryPointer(display, window, &root, &child,
-                              &root_x, &root_y, &win_x, &win_y, &mask))
-             continue;
+           if (!PointerInWindow(window))
+             continue; /* window and pointer are on different screens */
 
            if (!button_status)
              continue;
 
            motion_status = TRUE;
-           mx = ((XMotionEvent *) &event)->x;
-           my = ((XMotionEvent *) &event)->y;
+           mx = ((MotionEvent *) &event)->x;
+           my = ((MotionEvent *) &event)->y;
          }
          else
          {
            motion_status = FALSE;
-           mx = ((XButtonEvent *) &event)->x;
-           my = ((XButtonEvent *) &event)->y;
-           if (event.type==ButtonPress)
-             button_status = ((XButtonEvent *) &event)->button;
+           mx = ((ButtonEvent *) &event)->x;
+           my = ((ButtonEvent *) &event)->y;
+           if (event.type == EVENT_BUTTONPRESS)
+             button_status = ((ButtonEvent *) &event)->button;
            else
              button_status = MB_RELEASED;
          }
@@ -1959,15 +2060,14 @@ boolean Request(char *text, unsigned int req_state)
          break;
        }
 
-       case KeyPress:
-         switch(XLookupKeysym((XKeyEvent *)&event,
-                              ((XKeyEvent *)&event)->state))
+       case EVENT_KEYPRESS:
+         switch(GetEventKey((KeyEvent *)&event, TRUE))
          {
-           case XK_Return:
+           case KSYM_Return:
              result = 1;
              break;
 
-           case XK_Escape:
+           case KSYM_Escape:
              result = 0;
              break;
 
@@ -1978,8 +2078,8 @@ boolean Request(char *text, unsigned int req_state)
            result = 0;
          break;
 
-       case KeyRelease:
-         key_joystick_mapping = 0;
+       case EVENT_KEYRELEASE:
+         ClearPlayerAction();
          break;
 
        default:
@@ -2014,16 +2114,16 @@ boolean Request(char *text, unsigned int req_state)
 
     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
     {
-      XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
-               DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
-               DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
+      BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
+                DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
+                DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
       OpenDoor(DOOR_OPEN_1);
     }
   }
 
   RemapAllGadgets();
 
-#ifndef MSDOS
+#if defined(PLATFORM_UNIX)
   /* continue network game after request */
   if (options.network &&
       game_status == PLAYING &&
@@ -2040,9 +2140,9 @@ unsigned int OpenDoor(unsigned int door_state)
 
   if (door_state & DOOR_COPY_BACK)
   {
-    XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
-             DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
-             DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+    BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
+              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
+              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
     door_state &= ~DOOR_COPY_BACK;
   }
 
@@ -2055,10 +2155,10 @@ unsigned int CloseDoor(unsigned int door_state)
 {
   unsigned int new_door_state;
 
-  XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
-           DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
-  XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
-           VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+  BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
+            DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+  BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
+            VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
 
   new_door_state = MoveDoor(door_state);
 
@@ -2067,7 +2167,12 @@ unsigned int CloseDoor(unsigned int door_state)
 
 unsigned int GetDoorState()
 {
-  return(MoveDoor(DOOR_GET_STATE));
+  return MoveDoor(DOOR_GET_STATE);
+}
+
+unsigned int SetDoorState(unsigned int door_state)
+{
+  return MoveDoor(door_state | DOOR_SET_STATE);
 }
 
 unsigned int MoveDoor(unsigned int door_state)
@@ -2081,6 +2186,16 @@ unsigned int MoveDoor(unsigned int door_state)
   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 (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)
@@ -2094,18 +2209,28 @@ unsigned int MoveDoor(unsigned int door_state)
   {
     stepsize = 20;
     door_delay_value = 0;
-    StopSound(SND_OEFFNEN);
+    StopSound(SND_MENU_DOOR_OPENING);
+    StopSound(SND_MENU_DOOR_CLOSING);
   }
 
   if (door_state & DOOR_ACTION)
   {
     if (!(door_state & DOOR_NO_DELAY))
-      PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
+    {
+      /* opening door sound has priority over simultaneously closing door */
+      if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
+       PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
+      else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
+       PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
+    }
 
     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
 
     for(x=start; x<=DXSIZE; x+=stepsize)
     {
+      Bitmap *bitmap = pix[PIX_DOOR];
+      GC gc = bitmap->stored_clip_gc;
+
       WaitUntilDelayReached(&door_delay, door_delay_value);
 
       if (door_state & DOOR_ACTION_1)
@@ -2113,40 +2238,40 @@ unsigned int MoveDoor(unsigned int door_state)
        int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
        int j = (DXSIZE - i) / 3;
 
-       XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
-                 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
-                 DXSIZE,DYSIZE - i/2, DX, DY);
-
-       XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
-
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      DX - i, (DY + j) - DOOR_GFX_PAGEY1);
-       XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
-                 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
-                 DY + 140 + j);
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
-
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
-                 DX, DY + 77 - j);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
-                 DX, DY + 203 - j);
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      DX - i, (DY + j) - DOOR_GFX_PAGEY1);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
-                 DX + DXSIZE - i, DY + 77 + j);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
-                 DX + DXSIZE - i, DY + 203 + j);
+       BlitBitmap(pix[PIX_DB_DOOR], drawto,
+                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
+                  DXSIZE,DYSIZE - i/2, DX, DY);
+
+       ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
+
+       SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE, DOOR_GFX_PAGEY1, i, 77,
+                        DX + DXSIZE - i, DY + j);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
+                        DX + DXSIZE - i, DY + 140 + j);
+       SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
+                        DX, DY);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
+                        DX, DY + 140 - j);
+
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
+                        DX, DY + 77 - j);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
+                        DX, DY + 203 - j);
+       SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
+                        DX + DXSIZE - i, DY + 77 + j);
+       BlitBitmapMasked(bitmap, drawto,
+                        DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
+                        DX + DXSIZE - i, DY + 203 + j);
 
        redraw_mask |= REDRAW_DOOR_1;
       }
@@ -2156,29 +2281,30 @@ unsigned int MoveDoor(unsigned int door_state)
        int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
        int j = (VXSIZE - i) / 3;
 
-       XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
-                 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
-                 VXSIZE, VYSIZE - i/2, VX, VY);
-
-       XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
-
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      VX - i, (VY + j) - DOOR_GFX_PAGEY2);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
-       XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
-                 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
-
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
-                 VX, VY + VYSIZE / 2 - j);
-       XSetClipOrigin(display, clip_gc[PIX_DOOR],
-                      VX - i, (VY + j) - DOOR_GFX_PAGEY2);
-       XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
-                 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
-                 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
+       BlitBitmap(pix[PIX_DB_DOOR], drawto,
+                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
+                  VXSIZE, VYSIZE - i/2, VX, VY);
+
+       ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
+
+       SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
+       BlitBitmapMasked(bitmap, drawto,
+                        VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
+                        VX + VXSIZE-i, VY+j);
+       SetClipOrigin(bitmap, gc,
+                     VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
+       BlitBitmapMasked(bitmap, drawto,
+                        VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
+                        VX, VY);
+
+       BlitBitmapMasked(bitmap, drawto,
+                        VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
+                        i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
+       SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
+       BlitBitmapMasked(bitmap, drawto,
+                        VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
+                        i, VYSIZE / 2 - j,
+                        VX + VXSIZE - i, VY + VYSIZE / 2 + j);
 
        redraw_mask |= REDRAW_DOOR_2;
       }
@@ -2191,7 +2317,10 @@ unsigned int MoveDoor(unsigned int door_state)
   }
 
   if (setup.quick_doors)
-    StopSound(SND_OEFFNEN);
+  {
+    StopSound(SND_MENU_DOOR_OPENING);
+    StopSound(SND_MENU_DOOR_CLOSING);
+  }
 
   if (door_state & DOOR_ACTION_1)
     door1 = door_state & DOOR_ACTION_1;
@@ -2204,8 +2333,8 @@ unsigned int MoveDoor(unsigned int door_state)
 void DrawSpecialEditorDoor()
 {
   /* draw bigger toolbox window */
-  XCopyArea(display, pix[PIX_DOOR], drawto, gc,
-           DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
+  BlitBitmap(pix[PIX_DOOR], drawto,
+            DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
 
   redraw_mask |= REDRAW_ALL;
 }
@@ -2213,24 +2342,27 @@ void DrawSpecialEditorDoor()
 void UndrawSpecialEditorDoor()
 {
   /* draw normal tape recorder window */
-  XCopyArea(display, pix[PIX_BACK], drawto, gc,
-           562, 344, 108, 56, EX - 4, EY - 12);
+  BlitBitmap(pix[PIX_BACK], drawto,
+            562, 344, 108, 56, EX - 4, EY - 12);
 
   redraw_mask |= REDRAW_ALL;
 }
 
-int ReadPixel(Drawable d, int x, int y)
+#ifndef        TARGET_SDL
+int ReadPixel(DrawBuffer *bitmap, int x, int y)
 {
   XImage *pixel_image;
   unsigned long pixel_value;
 
-  pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
+  pixel_image = XGetImage(display, bitmap->drawable,
+                         x, y, 1, 1, AllPlanes, ZPixmap);
   pixel_value = XGetPixel(pixel_image, 0, 0);
 
   XDestroyImage(pixel_image);
 
   return pixel_value;
 }
+#endif
 
 /* ---------- new tool button stuff ---------------------------------------- */
 
@@ -2333,19 +2465,14 @@ static struct
   }
 };
 
-static void DoNotDisplayInfoText(void *ptr)
-{
-  return;
-}
-
 void CreateToolButtons()
 {
   int i;
 
   for (i=0; i<NUM_TOOL_BUTTONS; i++)
   {
-    Pixmap gd_pixmap = pix[PIX_DOOR];
-    Pixmap deco_pixmap = None;
+    Bitmap *gd_bitmap = pix[PIX_DOOR];
+    Bitmap *deco_bitmap = None;
     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
     struct GadgetInfo *gi;
     unsigned long event_mask;
@@ -2364,7 +2491,7 @@ void CreateToolButtons()
     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
     {
       getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
-                          &deco_pixmap, &deco_x, &deco_y);
+                          &deco_bitmap, &deco_x, &deco_y);
       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
     }
@@ -2377,15 +2504,14 @@ void CreateToolButtons()
                      GDI_HEIGHT, toolbutton_info[i].height,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
                      GDI_STATE, GD_BUTTON_UNPRESSED,
-                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
-                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
-                     GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+                     GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
                      GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
                      GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
                      GDI_DECORATION_SHIFTING, 1, 1,
                      GDI_EVENT_MASK, event_mask,
                      GDI_CALLBACK_ACTION, HandleToolButtons,
-                     GDI_CALLBACK_INFO, DoNotDisplayInfoText,
                      GDI_END);
 
     if (gi == NULL)
@@ -2408,7 +2534,23 @@ static void HandleToolButtons(struct GadgetInfo *gi)
   request_gadget_id = gi->custom_id;
 }
 
-int el2gfx(int element)
+int get_next_element(int element)
+{
+  switch(element)
+  {
+    case EL_QUICKSAND_FILLING:         return EL_MORAST_VOLL;
+    case EL_QUICKSAND_EMPTYING:                return EL_MORAST_LEER;
+    case EL_MAGIC_WALL_FILLING:                return EL_MAGIC_WALL_FULL;
+    case EL_MAGIC_WALL_EMPTYING:       return EL_MAGIC_WALL_EMPTY;
+    case EL_MAGIC_WALL_BD_FILLING:     return EL_MAGIC_WALL_BD_FULL;
+    case EL_MAGIC_WALL_BD_EMPTYING:    return EL_MAGIC_WALL_BD_EMPTY;
+    case EL_AMOEBA_DRIPPING:           return EL_AMOEBE_NASS;
+
+    default:                           return element;
+  }
+}
+
+int el2gfx_OLD(int element)
 {
   switch(element)
   {
@@ -2453,12 +2595,14 @@ int el2gfx(int element)
     case EL_DIAMANT:           return GFX_DIAMANT;
     case EL_MORAST_LEER:       return GFX_MORAST_LEER;
     case EL_MORAST_VOLL:       return GFX_MORAST_VOLL;
+    case EL_QUICKSAND_EMPTYING:        return GFX_MORAST_LEER;
     case EL_TROPFEN:           return GFX_TROPFEN;
     case EL_BOMBE:             return GFX_BOMBE;
-    case EL_SIEB_INAKTIV:      return GFX_SIEB_INAKTIV;
-    case EL_SIEB_LEER:         return GFX_SIEB_LEER;
-    case EL_SIEB_VOLL:         return GFX_SIEB_VOLL;
-    case EL_SIEB_TOT:          return GFX_SIEB_TOT;
+    case EL_MAGIC_WALL_OFF:    return GFX_MAGIC_WALL_OFF;
+    case EL_MAGIC_WALL_EMPTY:  return GFX_MAGIC_WALL_EMPTY;
+    case EL_MAGIC_WALL_EMPTYING:return GFX_MAGIC_WALL_EMPTY;
+    case EL_MAGIC_WALL_FULL:   return GFX_MAGIC_WALL_FULL;
+    case EL_MAGIC_WALL_DEAD:   return GFX_MAGIC_WALL_DEAD;
     case EL_SALZSAEURE:                return GFX_SALZSAEURE;
     case EL_AMOEBE_TOT:                return GFX_AMOEBE_TOT;
     case EL_AMOEBE_NASS:       return GFX_AMOEBE_NASS;
@@ -2466,6 +2610,7 @@ int el2gfx(int element)
     case EL_AMOEBE_VOLL:       return GFX_AMOEBE_VOLL;
     case EL_AMOEBE_BD:         return GFX_AMOEBE_BD;
     case EL_AMOEBA2DIAM:       return GFX_AMOEBA2DIAM;
+    case EL_AMOEBA_DRIPPING:   return GFX_AMOEBE_NASS;
     case EL_KOKOSNUSS:         return GFX_KOKOSNUSS;
     case EL_LIFE:              return GFX_LIFE;
     case EL_LIFE_ASYNC:                return GFX_LIFE_ASYNC;
@@ -2516,10 +2661,11 @@ int el2gfx(int element)
     case EL_ERZ_EDEL_ROT:      return GFX_ERZ_EDEL_ROT;
     case EL_ERZ_EDEL_LILA:     return GFX_ERZ_EDEL_LILA;
     case EL_MAMPFER2:          return GFX_MAMPFER2;
-    case EL_SIEB2_INAKTIV:     return GFX_SIEB2_INAKTIV;
-    case EL_SIEB2_LEER:                return GFX_SIEB2_LEER;
-    case EL_SIEB2_VOLL:                return GFX_SIEB2_VOLL;
-    case EL_SIEB2_TOT:         return GFX_SIEB2_TOT;
+    case EL_MAGIC_WALL_BD_OFF: return GFX_MAGIC_WALL_BD_OFF;
+    case EL_MAGIC_WALL_BD_EMPTY:return GFX_MAGIC_WALL_BD_EMPTY;
+    case EL_MAGIC_WALL_BD_EMPTYING:return GFX_MAGIC_WALL_BD_EMPTY;
+    case EL_MAGIC_WALL_BD_FULL:        return GFX_MAGIC_WALL_BD_FULL;
+    case EL_MAGIC_WALL_BD_DEAD:        return GFX_MAGIC_WALL_BD_DEAD;
     case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
     case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
     case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
@@ -2664,6 +2810,7 @@ int el2gfx(int element)
     case EL_BD_WALL:           return GFX_BD_WALL;
     case EL_BD_ROCK:           return GFX_BD_ROCK;
     case EL_DX_SUPABOMB:       return GFX_DX_SUPABOMB;
+    case EL_SP_MURPHY_CLONE:   return GFX_SP_MURPHY_CLONE;
 
     default:
     {
@@ -2684,3 +2831,25 @@ int el2gfx(int element)
     }
   }
 }
+
+int el2gfx(int element)
+{
+  int graphic_NEW = element_info[element].graphic;
+
+#if DEBUG
+  int graphic_OLD = el2gfx_OLD(element);
+
+  if (element >= MAX_ELEMENTS)
+  {
+    Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
+  }
+
+  if (graphic_NEW != graphic_OLD)
+  {
+    Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
+         graphic_NEW, graphic_OLD);
+  }
+#endif
+
+  return graphic_NEW;
+}