rnd-20020917-1-src
[rocksndiamonds.git] / src / tools.c
index 0ab4eec741a9909cc521ff92f9c0a13dd3073de0..7b7bdefbe03585686241febe2422048c7c1bcb1b 100644 (file)
@@ -556,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)
@@ -598,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)
@@ -690,7 +690,7 @@ 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;
 
@@ -703,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,
@@ -720,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)
 {
@@ -790,10 +833,9 @@ void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
   {
     graphic -= GFX_START_ROCKSFONT;
-    *bitmap = pix[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
   {
@@ -806,16 +848,32 @@ void getGraphicSource(int graphic, Bitmap **bitmap, 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, FX + x*TILEX, FY + y*TILEY, graphic);
-  MarkTileDirty(x,y);
+  DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
+  MarkTileDirty(x, y);
+}
+
+void DrawNewGraphic(int x, int y, int graphic, int frame)
+{
+#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)
@@ -827,10 +885,25 @@ void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
   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");
@@ -838,8 +911,24 @@ 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(DrawBuffer *d, int dest_x, int dest_y, int graphic)
@@ -870,12 +959,29 @@ void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
 #endif
 #endif
 
-    SetClipOrigin(src_bitmap, drawing_gc, dest_x-src_x, dest_y-src_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, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
@@ -894,7 +1000,6 @@ void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
   {
     graphic -= GFX_START_ROCKSSP;
-    graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
     *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;
@@ -916,10 +1021,9 @@ void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
   {
     graphic -= GFX_START_ROCKSFONT;
-    *bitmap = 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
   {
@@ -1065,12 +1169,134 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
   MarkTileDirty(x,y);
 }
 
+void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
+                       int cut_mode, int mask_mode)
+{
+  Bitmap *src_bitmap;
+  GC drawing_gc;
+  int src_x;
+  int src_y;
+
+  int width = TILEX, height = TILEY;
+  int cx = 0, cy = 0;
+  int dest_x, dest_y;
+
+  if (graphic < 0)
+  {
+    DrawNewGraphic(x, y, graphic, frame);
+    return;
+  }
+
+  if (dx || dy)                        /* Verschiebung der Grafik? */
+  {
+    if (x < BX1)               /* Element kommt von links ins Bild */
+    {
+      x = BX1;
+      width = dx;
+      cx = TILEX - dx;
+      dx = 0;
+    }
+    else if (x > BX2)          /* Element kommt von rechts ins Bild */
+    {
+      x = BX2;
+      width = -dx;
+      dx = TILEX + dx;
+    }
+    else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
+    {
+      width += dx;
+      cx = -dx;
+      dx = 0;
+    }
+    else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
+      width -= dx;
+    else if (dx)               /* allg. Bewegung in x-Richtung */
+      MarkTileDirty(x + SIGN(dx), y);
+
+    if (y < BY1)               /* Element kommt von oben ins Bild */
+    {
+      if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
+       return;
+
+      y = BY1;
+      height = dy;
+      cy = TILEY - dy;
+      dy = 0;
+    }
+    else if (y > BY2)          /* Element kommt von unten ins Bild */
+    {
+      y = BY2;
+      height = -dy;
+      dy = TILEY + dy;
+    }
+    else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
+    {
+      height += dy;
+      cy = -dy;
+      dy = 0;
+    }
+    else if (dy > 0 && cut_mode == CUT_ABOVE)
+    {
+      if (y == BY2)            /* Element unterhalb des Bildes */
+       return;
+
+      height = dy;
+      cy = TILEY - dy;
+      dy = TILEY;
+      MarkTileDirty(x, y + 1);
+    }                          /* Element verläßt unten das Bild */
+    else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
+      height -= dy;
+    else if (dy)               /* allg. Bewegung in y-Richtung */
+      MarkTileDirty(x, y + SIGN(dy));
+  }
+
+  src_bitmap = new_graphic_info[graphic].bitmap;
+  drawing_gc = src_bitmap->stored_clip_gc;
+  src_x = new_graphic_info[graphic].src_x;
+  src_y = new_graphic_info[graphic].src_y;
+
+  if (new_graphic_info[graphic].anim_vertical)
+    src_y += frame * TILEY;
+  else
+    src_x += frame * TILEX;
+
+  src_x += cx;
+  src_y += cy;
+
+  dest_x = FX + x * TILEX + dx;
+  dest_y = FY + y * TILEY + dy;
+
+#if DEBUG
+  if (!IN_SCR_FIELD(x,y))
+  {
+    printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
+    printf("DrawGraphicShifted(): This should never happen!\n");
+    return;
+  }
+#endif
+
+  if (mask_mode == USE_MASKING)
+    SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
+
+  BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
+            dest_x, dest_y);
+
+  MarkTileDirty(x,y);
+}
+
 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
                                int cut_mode)
 {
   DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
 }
 
+void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
+                                  int frame, int cut_mode)
+{
+  DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
+}
+
 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
                          int cut_mode, int mask_mode)
 {
@@ -1083,14 +1309,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)
   {
@@ -1218,6 +1444,174 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
     DrawGraphic(x, y, graphic);
 }
 
+void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
+                         int cut_mode, int mask_mode)
+{
+  int ux = LEVELX(x), uy = LEVELY(y);
+  int dir = MovDir[ux][uy];
+  int graphic = el_dir2img(element, dir);
+  int frame = getNewGraphicAnimationFrame(graphic);
+  int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
+  int phase4 = phase8 / 2;
+  int phase2  = phase8 / 4;
+
+  if (element == EL_KAEFER)
+  {
+    ;
+  }
+  else if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
+  {
+    graphic += 1 * !phase2;
+
+    if (dir == MV_UP)
+      graphic += 1 * 2;
+    else if (dir == MV_LEFT)
+      graphic += 2 * 2;
+    else if (dir == MV_DOWN)
+      graphic += 3 * 2;
+  }
+  else if (element == EL_SP_SNIKSNAK)
+  {
+    if (dir == MV_LEFT)
+      graphic = GFX_SP_SNIKSNAK_LEFT;
+    else if (dir == MV_RIGHT)
+      graphic = GFX_SP_SNIKSNAK_RIGHT;
+    else if (dir == MV_UP)
+      graphic = GFX_SP_SNIKSNAK_UP;
+    else
+      graphic = GFX_SP_SNIKSNAK_DOWN;
+
+    graphic += (phase8 < 4 ? phase8 : 7 - phase8);
+  }
+  else if (element == EL_SP_ELECTRON)
+  {
+#if 1
+    graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
+#else
+    graphic = GFX2_SP_ELECTRON + getNewGraphicAnimationFrame(graphic);
+#endif
+  }
+  else if (element == EL_MOLE || element == EL_PINGUIN ||
+          element == EL_SCHWEIN || element == EL_DRACHE)
+  {
+    if (dir == MV_LEFT)
+      graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
+                element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
+                element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
+    else if (dir == MV_RIGHT)
+      graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
+                element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
+                element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
+    else if (dir == MV_UP)
+      graphic = (element == EL_MOLE ? GFX_MOLE_UP :
+                element == EL_PINGUIN ? GFX_PINGUIN_UP :
+                element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
+    else
+      graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
+                element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
+                element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
+
+    graphic += phase4;
+  }
+  else if (element == EL_SONDE)
+  {
+#if 1
+    graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
+#else
+    graphic = GFX_SONDE_START + getNewGraphicAnimationFrame(graphic);
+#endif
+  }
+  else if (element == EL_SALZSAEURE)
+  {
+#if 1
+    graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
+#else
+    graphic = GFX_GEBLUBBER + getNewGraphicAnimationFrame(graphic);
+#endif
+  }
+  else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
+  {
+    graphic += !phase2;
+  }
+  else if (element == EL_BALLOON)
+  {
+    graphic += phase4;
+  }
+  else if ((element == EL_FELSBROCKEN ||
+           element == EL_SP_ZONK ||
+           element == EL_BD_ROCK ||
+           element == EL_SP_INFOTRON ||
+           IS_GEM(element))
+          && !cut_mode)
+  {
+    if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
+    {
+      if (element == EL_FELSBROCKEN ||
+         element == EL_SP_ZONK ||
+         element == EL_BD_ROCK)
+      {
+       if (dir == MV_LEFT)
+         graphic += (4 - phase4) % 4;
+       else if (dir == MV_RIGHT)
+         graphic += phase4;
+       else
+         graphic += phase2 * 2;
+      }
+      else if (element != EL_SP_INFOTRON)
+       graphic += phase2;
+    }
+  }
+  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)
+  {
+#if 1
+    graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
+#else
+    graphic += 3 + getNewGraphicAnimationFrame(graphic);
+#endif
+  }
+  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;
+  }
+  else if (element == EL_MAUER_LEBT)
+  {
+    boolean links_massiv = FALSE, rechts_massiv = FALSE;
+
+    if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
+      links_massiv = TRUE;
+    if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
+      rechts_massiv = TRUE;
+
+    if (links_massiv && rechts_massiv)
+      graphic = GFX_MAUERWERK;
+    else if (links_massiv)
+      graphic = GFX_MAUER_R;
+    else if (rechts_massiv)
+      graphic = GFX_MAUER_L;
+  }
+  else if ((element == EL_INVISIBLE_STEEL ||
+           element == EL_UNSICHTBAR ||
+           element == EL_SAND_INVISIBLE) && game.light_time_left)
+  {
+    graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
+              element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
+              GFX_SAND_INVISIBLE_ON);
+  }
+
+  if (dx || dy)
+    DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
+  else if (mask_mode == USE_MASKING)
+    DrawNewGraphicThruMask(x, y, graphic, frame);
+  else
+    DrawNewGraphic(x, y, graphic, frame);
+}
+
 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
                         int cut_mode, int mask_mode)
 {
@@ -1226,35 +1620,72 @@ void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
                         cut_mode, mask_mode);
 }
 
+void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
+                        int cut_mode, int mask_mode)
+{
+  if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+    DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
+                        cut_mode, mask_mode);
+}
+
 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
                              int cut_mode)
 {
   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
 }
 
+void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
+                             int cut_mode)
+{
+  DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
+}
+
 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
                             int cut_mode)
 {
   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
 }
 
+void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
+                            int cut_mode)
+{
+  DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
+}
+
 void DrawScreenElementThruMask(int x, int y, int element)
 {
   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
 }
 
+void DrawNewScreenElementThruMask(int x, int y, int element)
+{
+  DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
+}
+
 void DrawLevelElementThruMask(int x, int y, int element)
 {
   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
 }
 
+void DrawNewLevelElementThruMask(int x, int y, int element)
+{
+  DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
+}
+
 void DrawLevelFieldThruMask(int x, int y)
 {
   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
 }
 
+void DrawNewLevelFieldThruMask(int x, int y)
+{
+  DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
+}
+
 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;
@@ -1282,6 +1713,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;
@@ -1314,9 +1747,7 @@ void ErdreichAnbroeckeln(int x, int y)
        cy = (i == 3 ? TILEY - snip : 0);
       }
 
-      BlitBitmap(pix[PIX_BACK], drawto_field,
-                SX + (graphic % GFX_PER_LINE) * TILEX + cx,
-                SY + (graphic / GFX_PER_LINE) * TILEY + cy,
+      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
                 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
     }
 
@@ -1326,6 +1757,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;
@@ -1358,9 +1791,7 @@ void ErdreichAnbroeckeln(int x, int y)
        cy = (i==0 ? TILEY-snip : 0);
       }
 
-      BlitBitmap(pix[PIX_BACK], drawto_field,
-                SX + (graphic % GFX_PER_LINE) * TILEX + cx,
-                SY + (graphic / GFX_PER_LINE) * 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);
@@ -1374,12 +1805,24 @@ void DrawScreenElement(int x, int y, int element)
   ErdreichAnbroeckeln(x, y);
 }
 
+void DrawNewScreenElement(int x, int y, int element)
+{
+  DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
+  ErdreichAnbroeckeln(x, y);
+}
+
 void DrawLevelElement(int x, int y, int element)
 {
   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
     DrawScreenElement(SCREENX(x), SCREENY(y), element);
 }
 
+void DrawNewLevelElement(int x, int y, int element)
+{
+  if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+    DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
+}
+
 void DrawScreenField(int x, int y)
 {
   int ux = LEVELX(x), uy = LEVELY(y);
@@ -1470,6 +1913,96 @@ void DrawScreenField(int x, int y)
     DrawScreenElement(x, y, EL_LEERRAUM);
 }
 
+void DrawNewScreenField(int x, int y)
+{
+  int ux = LEVELX(x), uy = LEVELY(y);
+  int element, content;
+
+  if (!IN_LEV_FIELD(ux, uy))
+  {
+    if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
+      element = EL_LEERRAUM;
+    else
+      element = BorderElement;
+
+    DrawNewScreenElement(x, y, element);
+    return;
+  }
+
+  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 (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 (element == EL_QUICKSAND_FILLING ||
+            element == EL_MAGIC_WALL_FILLING ||
+            element == EL_MAGIC_WALL_BD_FILLING)
+      cut_mode = CUT_BELOW;
+
+    if (cut_mode == CUT_ABOVE)
+      DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
+    else
+      DrawNewScreenElement(x, y, EL_LEERRAUM);
+
+    if (horiz_move)
+      DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
+    else if (cut_mode == NO_CUTTING)
+      DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
+    else
+      DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
+
+    if (content == EL_SALZSAEURE)
+      DrawNewLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
+  }
+  else if (IS_BLOCKED(ux, uy))
+  {
+    int oldx, oldy;
+    int sx, sy;
+    int horiz_move;
+    boolean cut_mode = NO_CUTTING;
+    int element_old, content_old;
+
+    Blocked2Moving(ux, uy, &oldx, &oldy);
+    sx = SCREENX(oldx);
+    sy = SCREENY(oldy);
+    horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
+                 MovDir[oldx][oldy] == MV_RIGHT);
+
+    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;
+
+    DrawNewScreenElement(x, y, EL_LEERRAUM);
+
+    if (horiz_move)
+      DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
+                              NO_CUTTING);
+    else if (cut_mode == NO_CUTTING)
+      DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
+                              cut_mode);
+    else
+      DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
+                              cut_mode);
+  }
+  else if (IS_DRAWABLE(element))
+    DrawNewScreenElement(x, y, element);
+  else
+    DrawNewScreenElement(x, y, EL_LEERRAUM);
+}
+
 void DrawLevelField(int x, int y)
 {
   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
@@ -1492,6 +2025,28 @@ void DrawLevelField(int x, int y)
   }
 }
 
+void DrawNewLevelField(int x, int y)
+{
+  if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+    DrawNewScreenField(SCREENX(x), SCREENY(y));
+  else if (IS_MOVING(x, y))
+  {
+    int newx,newy;
+
+    Moving2Blocked(x, y, &newx, &newy);
+    if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
+      DrawNewScreenField(SCREENX(newx), SCREENY(newy));
+  }
+  else if (IS_BLOCKED(x, y))
+  {
+    int oldx, oldy;
+
+    Blocked2Moving(x, y, &oldx, &oldy);
+    if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
+      DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
+  }
+}
+
 void DrawMiniElement(int x, int y, int element)
 {
   int graphic;
@@ -1552,7 +2107,6 @@ 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;
     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,
@@ -1574,6 +2128,14 @@ void DrawMicroElement(int xpos, int ypos, int element)
               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
     BlitBitmap(pix[PIX_ELEMENTS], drawto,
               MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
@@ -2740,3 +3302,25 @@ int el2gfx(int element)
 
   return graphic_NEW;
 }
+
+int el2img(int element)
+{
+  switch(element)
+  {
+    case EL_BUTTERFLY:         return IMG_BD_BUTTERFLY;
+    case EL_FIREFLY:           return IMG_BD_FIREFLY;
+
+    default:
+      break;
+  }
+
+  return IMG_EMPTY_SPACE;
+}
+
+int el_dir2img(int element, int direction)
+{
+  if (element_info[element].has_direction_graphic)
+    return element_info[element].direction_graphic[LOG_MV_DIR(direction)];
+  else
+    return el2img(element);
+}