rnd-20020914-1-src
[rocksndiamonds.git] / src / tools.c
index fe5c9f690cc89031b9db3b3f4998170e6cca3191..0552e4af67d70ebf2d041e2ad1e83b5cbf98fd30 100644 (file)
@@ -1,7 +1,7 @@
 /***********************************************************
 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-* (c) 1995-2001 Artsoft Entertainment                      *
+* (c) 1995-2002 Artsoft Entertainment                      *
 *               Holger Schemel                             *
 *               Detmolder Strasse 189                      *
 *               33604 Bielefeld                            *
 #include "network.h"
 #include "tape.h"
 
-#if defined(PLATFORM_MSDOS)
-extern boolean wait_for_vsync;
-#endif
-
 /* tool button identifiers */
 #define TOOL_CTRL_ID_YES       0
 #define TOOL_CTRL_ID_NO                1
@@ -560,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)
@@ -602,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)
@@ -694,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);
   }
@@ -706,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,
@@ -723,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)
 {
@@ -746,54 +786,60 @@ static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
 }
 
-void getGraphicSource(int graphic, int *bitmap_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;
-    *bitmap_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;
-    *bitmap_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;
-    *bitmap_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;
-    *bitmap_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;
-    *bitmap_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;
-    *bitmap_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
   {
-    *bitmap_nr = PIX_SP;
+    *bitmap = pix[PIX_SP];
     *x = 0;
     *y = 0;
   }
@@ -802,31 +848,62 @@ void getGraphicSource(int graphic, int *bitmap_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, 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 *bitmap, int x, int y, int graphic)
+void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
 {
-  int bitmap_nr;
+  Bitmap *src_bitmap;
   int src_x, src_y;
 
-  getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
-  BlitBitmap(pix[bitmap_nr], bitmap, 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");
@@ -834,14 +911,29 @@ 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)
 {
   int tile = graphic;
-  int bitmap_nr;
   int src_x, src_y;
   Bitmap *src_bitmap;
   GC drawing_gc;
@@ -849,9 +941,8 @@ void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
   if (graphic == GFX_LEERRAUM)
     return;
 
-  getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
-  src_bitmap = pix[bitmap_nr];
-  drawing_gc = pix[bitmap_nr]->stored_clip_gc;
+  getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+  drawing_gc = src_bitmap->stored_clip_gc;
 
   if (tile_clipmask[tile] != None)
   {
@@ -868,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);
@@ -882,17 +990,16 @@ void DrawMiniGraphic(int x, int y, int graphic)
 
 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;
-    *bitmap = 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;
     *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;
@@ -914,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
   {
@@ -943,7 +1049,6 @@ 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 bitmap_nr;
   Bitmap *src_bitmap;
   GC drawing_gc;
 
@@ -1017,9 +1122,8 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
       MarkTileDirty(x, y + SIGN(dy));
   }
 
-  getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
-  src_bitmap = pix[bitmap_nr];
-  drawing_gc = pix[bitmap_nr]->stored_clip_gc;
+  getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+  drawing_gc = src_bitmap->stored_clip_gc;
 
   src_x += cx;
   src_y += cy;
@@ -1059,7 +1163,7 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
     }
   }
   else
-    BlitBitmap(pix[bitmap_nr], drawto_field,
+    BlitBitmap(src_bitmap, drawto_field,
               src_x, src_y, width, height, dest_x, dest_y);
 
   MarkTileDirty(x,y);
@@ -1083,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)
   {
@@ -1255,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;
@@ -1282,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;
@@ -1314,9 +1422,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 +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;
@@ -1358,9 +1466,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);
@@ -1552,7 +1658,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,8 +1679,16 @@ 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_BACK], drawto,
+    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);
@@ -1775,6 +1888,9 @@ 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;
@@ -1803,31 +1919,35 @@ boolean Request(char *text, unsigned int req_state)
   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, 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)
@@ -1959,7 +2079,7 @@ boolean Request(char *text, unsigned int req_state)
          break;
 
        case EVENT_KEYRELEASE:
-         key_joystick_mapping = 0;
+         ClearPlayerAction();
          break;
 
        default:
@@ -2047,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)
@@ -2061,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)
@@ -2074,13 +2209,20 @@ 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);
 
@@ -2175,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;
@@ -2405,7 +2550,7 @@ int get_next_element(int element)
   }
 }
 
-int el2gfx(int element)
+int el2gfx_OLD(int element)
 {
   switch(element)
   {
@@ -2686,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;
+}