fixed bug with handling networking packets if request dialog is active
[rocksndiamonds.git] / src / init.c
index eac5ad1f598e2e75411105c2f65216e6ba71fe72..2167984b663649481289e4d4c0c5f14be1670312 100644 (file)
@@ -21,7 +21,7 @@
 #include "files.h"
 #include "network.h"
 #include "netserv.h"
-#include "cartoons.h"
+#include "anim.h"
 #include "config.h"
 
 #include "conf_e2g.c"  /* include auto-generated data structure definitions */
@@ -84,7 +84,11 @@ static int copy_properties[][5] =
 };
 
 
-void DrawInitAnim()
+/* forward declaration for internal use */
+static int get_graphic_parameter_value(char *, char *, int);
+
+
+static void DrawInitAnim(void)
 {
   struct GraphicInfo *graphic_info_last = graphic_info;
   int graphic = 0;
@@ -93,6 +97,9 @@ void DrawInitAnim()
   int sync_frame = FrameCounter;
   int x, y;
 
+  /* prevent OS (Windows) from complaining about program not responding */
+  CheckQuitEvent();
+
   if (game_status != GAME_MODE_LOADING)
     return;
 
@@ -129,7 +136,21 @@ void DrawInitAnim()
   FrameCounter++;
 }
 
-void FreeGadgets()
+static void DrawProgramInfo(void)
+{
+  int font1_nr = FC_YELLOW;
+  int font2_nr = FC_RED;
+  int font2_height = getFontHeight(font2_nr);
+  int ypos1 = 20;
+  int ypos2 = 50;
+  int ypos3 = WIN_YSIZE - 20 - font2_height;
+
+  DrawInitText(getProgramInitString(),           ypos1, font1_nr);
+  DrawInitText(setup.internal.program_copyright, ypos2, font2_nr);
+  DrawInitText(setup.internal.program_website,   ypos3, font2_nr);
+}
+
+static void FreeGadgets(void)
 {
   FreeLevelEditorGadgets();
   FreeGameButtons();
@@ -138,7 +159,7 @@ void FreeGadgets()
   FreeScreenGadgets();
 }
 
-void InitGadgets()
+void InitGadgets(void)
 {
   static boolean gadgets_initialized = FALSE;
 
@@ -164,7 +185,7 @@ inline static void InitElementSmallImagesScaledUp(int graphic)
   CreateImageWithSmallImages(graphic, g->scale_up_factor, g->tile_size);
 }
 
-void InitElementSmallImages()
+static void InitElementSmallImages(void)
 {
   print_timestamp_init("InitElementSmallImages");
 
@@ -195,22 +216,23 @@ void InitElementSmallImages()
   print_timestamp_time("getImageListPropertyMapping/Size");
 
   print_timestamp_init("InitElementSmallImagesScaledUp (1)");
-  /* initialize normal images from static configuration */
+  /* initialize normal element images from static configuration */
   for (i = 0; element_to_graphic[i].element > -1; i++)
     InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
   print_timestamp_done("InitElementSmallImagesScaledUp (1)");
 
-  /* initialize special images from static configuration */
+  /* initialize special element images from static configuration */
   for (i = 0; element_to_special_graphic[i].element > -1; i++)
     InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
   print_timestamp_time("InitElementSmallImagesScaledUp (2)");
 
-  /* initialize images from dynamic configuration (may be elements or other) */
+  /* initialize element images from dynamic configuration */
   for (i = 0; i < num_property_mappings; i++)
-    InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
+    if (property_mapping[i].base_index < MAX_NUM_ELEMENTS)
+      InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
   print_timestamp_time("InitElementSmallImagesScaledUp (3)");
 
-  /* initialize special images from above list (non-element images) */
+  /* initialize special non-element images from above list */
   for (i = 0; special_graphics[i] > -1; i++)
     InitElementSmallImagesScaledUp(special_graphics[i]);
   print_timestamp_time("InitElementSmallImagesScaledUp (4)");
@@ -218,16 +240,29 @@ void InitElementSmallImages()
   print_timestamp_done("InitElementSmallImages");
 }
 
-void InitScaledImages()
+inline static void InitScaledImagesScaledUp(int graphic)
 {
+  struct GraphicInfo *g = &graphic_info[graphic];
+
+  ScaleImage(graphic, g->scale_up_factor);
+}
+
+static void InitScaledImages(void)
+{
+  struct PropertyMapping *property_mapping = getImageListPropertyMapping();
+  int num_property_mappings = getImageListPropertyMappingSize();
   int i;
 
   /* scale normal images from static configuration, if not already scaled */
   for (i = 0; i < NUM_IMAGE_FILES; i++)
-    ScaleImage(i, graphic_info[i].scale_up_factor);
+    InitScaledImagesScaledUp(i);
+
+  /* scale images from dynamic configuration, if not already scaled */
+  for (i = 0; i < num_property_mappings; i++)
+    InitScaledImagesScaledUp(property_mapping[i].artwork_index);
 }
 
-void InitBitmapPointers()
+static void InitBitmapPointers(void)
 {
   int num_images = getImageListSize();
   int i;
@@ -238,7 +273,7 @@ void InitBitmapPointers()
       graphic_info[i].bitmap = graphic_info[i].bitmaps[IMG_BITMAP_STANDARD];
 }
 
-void InitImageTextures()
+void InitImageTextures(void)
 {
   int i, j, k;
 
@@ -312,7 +347,7 @@ static int getFontFromToken(char *token)
   return FONT_INITIAL_1;
 }
 
-void InitFontGraphicInfo()
+static void InitFontGraphicInfo(void)
 {
   static struct FontBitmapInfo *font_bitmap_info = NULL;
   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
@@ -395,7 +430,7 @@ void InitFontGraphicInfo()
     int special = property_mapping[i].ext3_index;
     int graphic = property_mapping[i].artwork_index;
 
-    if (font_nr < 0)
+    if (font_nr < 0 || font_nr >= NUM_FONTS)
       continue;
 
     if (IS_SPECIAL_GFX_ARG(special))
@@ -530,6 +565,11 @@ void InitFontGraphicInfo()
       font_bitmap_info[font_bitmap_id].width  = graphic_info[graphic].width;
       font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
 
+      font_bitmap_info[font_bitmap_id].offset_x =
+       graphic_info[graphic].offset_x;
+      font_bitmap_info[font_bitmap_id].offset_y =
+       graphic_info[graphic].offset_y;
+
       font_bitmap_info[font_bitmap_id].draw_xoffset =
        graphic_info[graphic].draw_xoffset;
       font_bitmap_info[font_bitmap_id].draw_yoffset =
@@ -546,7 +586,7 @@ void InitFontGraphicInfo()
               getFontBitmapID, getFontFromToken);
 }
 
-void InitGlobalAnimGraphicInfo()
+static void InitGlobalAnimGraphicInfo(void)
 {
   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
   int num_property_mappings = getImageListPropertyMappingSize();
@@ -590,6 +630,19 @@ void InitGlobalAnimGraphicInfo()
       special = GFX_SPECIAL_ARG_DEFAULT;
 
     global_anim_info[anim_nr].graphic[part_nr][special] = graphic;
+
+    /* fix default value for ".draw_masked" (for backward compatibility) */
+    struct GraphicInfo *g = &graphic_info[graphic];
+    struct FileInfo *image = getImageListEntryFromImageID(graphic);
+    char **parameter_raw = image->parameter;
+    int p = GFX_ARG_DRAW_MASKED;
+    int draw_masked = get_graphic_parameter_value(parameter_raw[p],
+                                                 image_config_suffix[p].token,
+                                                 image_config_suffix[p].type);
+
+    /* if ".draw_masked" parameter is undefined, use default value "TRUE" */
+    if (draw_masked == ARG_UNDEFINED_VALUE)
+      g->draw_masked = TRUE;
   }
 
 #if 0
@@ -605,7 +658,7 @@ void InitGlobalAnimGraphicInfo()
 #endif
 }
 
-void InitGlobalAnimSoundInfo()
+static void InitGlobalAnimSoundInfo(void)
 {
   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
   int num_property_mappings = getSoundListPropertyMappingSize();
@@ -654,7 +707,56 @@ void InitGlobalAnimSoundInfo()
 #endif
 }
 
-void InitElementGraphicInfo()
+static void InitGlobalAnimMusicInfo(void)
+{
+  struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
+  int num_property_mappings = getMusicListPropertyMappingSize();
+  int i, j, k;
+
+  /* always start with reliable default values (no global animation music) */
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+    for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+      for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+       global_anim_info[i].music[j][k] = MUS_UNDEFINED;
+
+  /* initialize global animation music definitions from dynamic configuration */
+  for (i = 0; i < num_property_mappings; i++)
+  {
+    int anim_nr = property_mapping[i].base_index - NUM_MUSIC_PREFIXES;
+    int part_nr = property_mapping[i].ext1_index - ACTION_PART_1;
+    int special = property_mapping[i].ext2_index;
+    int music   = property_mapping[i].artwork_index;
+
+    // music uses control definition; map it to position of graphic (artwork)
+    anim_nr -= GLOBAL_ANIM_ID_CONTROL_FIRST;
+
+    if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS)
+      continue;
+
+    /* set animation part to base part, if not specified */
+    if (!IS_GLOBAL_ANIM_PART(part_nr))
+      part_nr = GLOBAL_ANIM_ID_PART_BASE;
+
+    /* set animation screen to default, if not specified */
+    if (!IS_SPECIAL_GFX_ARG(special))
+      special = GFX_SPECIAL_ARG_DEFAULT;
+
+    global_anim_info[anim_nr].music[part_nr][special] = music;
+  }
+
+#if 0
+  printf("::: InitGlobalAnimMusicInfo\n");
+
+  for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
+    for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
+      for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
+       if (global_anim_info[i].music[j][k] != MUS_UNDEFINED)
+         printf("::: - anim %d, part %d, mode %d => %d\n",
+                i, j, k, global_anim_info[i].music[j][k]);
+#endif
+}
+
+static void InitElementGraphicInfo(void)
 {
   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
   int num_property_mappings = getImageListPropertyMappingSize();
@@ -887,14 +989,12 @@ void InitElementGraphicInfo()
              (move_dir == MV_BIT_UP    && !front_is_left_or_upper) ||
              (move_dir == MV_BIT_RIGHT &&  front_is_left_or_upper) ||
              (move_dir == MV_BIT_DOWN  &&  front_is_left_or_upper)));
-         Bitmap *dummy;
 
          /* swap frontside and backside graphic tile coordinates, if needed */
          if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
          {
            /* get current (wrong) backside tile coordinates */
-           getFixedGraphicSourceExt(graphic, 0, &dummy,
-                                    &src_x_back, &src_y_back, TRUE);
+           getGraphicSourceXY(graphic, 0, &src_x_back, &src_y_back, TRUE);
 
            /* set frontside tile coordinates to backside tile coordinates */
            g->src_x = src_x_back;
@@ -967,6 +1067,8 @@ void InitElementGraphicInfo()
        default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
        default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
+      if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].graphic[act] != -1)
+       default_action_graphic = element_info[EL_MM_DEFAULT].graphic[act];
 
       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
        default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
@@ -974,6 +1076,8 @@ void InitElementGraphicInfo()
        default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
        default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
+      if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].crumbled[act] != -1)
+       default_action_crumbled = element_info[EL_MM_DEFAULT].crumbled[act];
 
       /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
       /* !!! make this better !!! */
@@ -1033,7 +1137,7 @@ void InitElementGraphicInfo()
   UPDATE_BUSY_STATE();
 }
 
-void InitElementSpecialGraphicInfo()
+static void InitElementSpecialGraphicInfo(void)
 {
   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
   int num_property_mappings = getImageListPropertyMappingSize();
@@ -1197,6 +1301,11 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   g->anim_delay_random = 0;
   g->post_delay_fixed = 0;
   g->post_delay_random = 0;
+  g->init_event = ANIM_EVENT_DEFAULT;
+  g->anim_event = ANIM_EVENT_DEFAULT;
+  g->init_event_action = -1;
+  g->anim_event_action = -1;
+  g->draw_masked = FALSE;
   g->draw_order = 0;
   g->fade_mode = FADE_MODE_DEFAULT;
   g->fade_delay = -1;
@@ -1296,13 +1405,13 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
 
     if (parameter[GFX_ARG_TILE_SIZE] != ARG_UNDEFINED_VALUE)
     {
-      anim_frames_per_row = src_image_width  / g->tile_size;
-      anim_frames_per_col = src_image_height / g->tile_size;
+      anim_frames_per_row = MAX(1, src_image_width  / g->tile_size);
+      anim_frames_per_col = MAX(1, src_image_height / g->tile_size);
     }
     else
     {
-      anim_frames_per_row = src_image_width  / g->width;
-      anim_frames_per_col = src_image_height / g->height;
+      anim_frames_per_row = MAX(1, src_image_width  / g->width);
+      anim_frames_per_col = MAX(1, src_image_height / g->height);
     }
 
     g->src_image_width  = src_image_width;
@@ -1413,6 +1522,16 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
     g->post_delay_random = parameter[GFX_ARG_POST_DELAY_RANDOM];
 
+  /* used for global animations */
+  if (parameter[GFX_ARG_INIT_EVENT] != ARG_UNDEFINED_VALUE)
+    g->init_event = parameter[GFX_ARG_INIT_EVENT];
+  if (parameter[GFX_ARG_ANIM_EVENT] != ARG_UNDEFINED_VALUE)
+    g->anim_event = parameter[GFX_ARG_ANIM_EVENT];
+  if (parameter[GFX_ARG_INIT_EVENT_ACTION] != ARG_UNDEFINED_VALUE)
+    g->init_event_action = parameter[GFX_ARG_INIT_EVENT_ACTION];
+  if (parameter[GFX_ARG_ANIM_EVENT_ACTION] != ARG_UNDEFINED_VALUE)
+    g->anim_event_action = parameter[GFX_ARG_ANIM_EVENT_ACTION];
+
   /* used for toon animations and global animations */
   g->step_offset  = parameter[GFX_ARG_STEP_OFFSET];
   g->step_xoffset = parameter[GFX_ARG_STEP_XOFFSET];
@@ -1427,8 +1546,14 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   g->draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET];
   g->draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET];
 
-  /* this is only used for drawing envelope graphics */
-  g->draw_masked = parameter[GFX_ARG_DRAW_MASKED];
+  /* use a different default value for global animations and toons */
+  if ((graphic >= IMG_GFX_GLOBAL_ANIM_1 && graphic <= IMG_GFX_GLOBAL_ANIM_8) ||
+      (graphic >= IMG_TOON_1            && graphic <= IMG_TOON_20))
+    g->draw_masked = TRUE;
+
+  /* this is used for drawing envelopes, global animations and toons */
+  if (parameter[GFX_ARG_DRAW_MASKED] != ARG_UNDEFINED_VALUE)
+    g->draw_masked = parameter[GFX_ARG_DRAW_MASKED];
 
   /* used for toon animations and global animations */
   if (parameter[GFX_ARG_DRAW_ORDER] != ARG_UNDEFINED_VALUE)
@@ -1528,7 +1653,7 @@ static void set_cloned_graphic_parameters(int graphic)
   }
 }
 
-static void InitGraphicInfo()
+static void InitGraphicInfo(void)
 {
   int fallback_graphic = IMG_CHAR_EXCLAM;
   int num_images = getImageListSize();
@@ -1621,10 +1746,10 @@ static void InitGraphicInfo()
 
   for (i = 0; i < num_images; i++)
   {
-    Bitmap *src_bitmap;
+    Bitmap *src_bitmap = graphic_info[i].bitmap;
     int src_x, src_y;
     int width, height;
-    int first_frame, last_frame;
+    int last_frame;
     int src_bitmap_width, src_bitmap_height;
 
     /* now check if no animation frames are outside of the loaded image */
@@ -1642,13 +1767,14 @@ static void InitGraphicInfo()
 
     /* check if first animation frame is inside specified bitmap */
 
-    first_frame = 0;
-    getFixedGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
-
+    /* do not use getGraphicSourceXY() here to get position of first frame; */
     /* this avoids calculating wrong start position for out-of-bounds frame */
     src_x = graphic_info[i].src_x;
     src_y = graphic_info[i].src_y;
 
+    if (program.headless)
+      continue;
+
     if (src_x < 0 || src_y < 0 ||
        src_x + width  > src_bitmap_width ||
        src_y + height > src_bitmap_height)
@@ -1658,6 +1784,7 @@ static void InitGraphicInfo()
       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
+      Error(ERR_INFO, "- frame size: %d, %d", width, height);
       Error(ERR_INFO,
            "error: first animation frame out of bounds (%d, %d) [%d, %d]",
            src_x, src_y, src_bitmap_width, src_bitmap_height);
@@ -1670,12 +1797,15 @@ static void InitGraphicInfo()
       Error(ERR_INFO_LINE, "-");
 
       graphic_info[i] = graphic_info[fallback_graphic];
+
+      /* if first frame out of bounds, do not check last frame anymore */
+      continue;
     }
 
     /* check if last animation frame is inside specified bitmap */
 
     last_frame = graphic_info[i].anim_frames - 1;
-    getFixedGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
+    getGraphicSourceXY(i, last_frame, &src_x, &src_y, FALSE);
 
     if (src_x < 0 || src_y < 0 ||
        src_x + width  > src_bitmap_width ||
@@ -1686,10 +1816,10 @@ static void InitGraphicInfo()
       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
+      Error(ERR_INFO, "- frame size: %d, %d", width, height);
       Error(ERR_INFO,
            "error: last animation frame (%d) out of bounds (%d, %d) [%d, %d]",
            last_frame, src_x, src_y, src_bitmap_width, src_bitmap_height);
-      Error(ERR_INFO, "::: %d, %d", width, height);
       Error(ERR_INFO, "custom graphic rejected for this element/action");
 
       if (i == fallback_graphic)
@@ -1703,7 +1833,7 @@ static void InitGraphicInfo()
   }
 }
 
-static void InitGraphicCompatibilityInfo()
+static void InitGraphicCompatibilityInfo(void)
 {
   struct FileInfo *fi_global_door =
     getImageListEntryFromImageID(IMG_GLOBAL_DOOR);
@@ -1735,7 +1865,8 @@ static void InitGraphicCompatibilityInfo()
        {
          // printf("::: special treatment needed for token '%s'\n", fi->token);
 
-         graphic_info[i].bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+         graphic_info[i].bitmaps = graphic_info[IMG_GLOBAL_DOOR].bitmaps;
+         graphic_info[i].bitmap  = graphic_info[IMG_GLOBAL_DOOR].bitmap;
        }
       }
     }
@@ -1744,7 +1875,7 @@ static void InitGraphicCompatibilityInfo()
   InitGraphicCompatibilityInfo_Doors();
 }
 
-static void InitElementSoundInfo()
+static void InitElementSoundInfo(void)
 {
   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
   int num_property_mappings = getSoundListPropertyMappingSize();
@@ -1825,6 +1956,8 @@ static void InitElementSoundInfo()
        default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
        default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
+      if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].sound[act] != -1)
+       default_action_sound = element_info[EL_MM_DEFAULT].sound[act];
 
       /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
       /* !!! make this better !!! */
@@ -1846,7 +1979,7 @@ static void InitElementSoundInfo()
          element_info[copy_properties[i][0]].sound[act];
 }
 
-static void InitGameModeSoundInfo()
+static void InitGameModeSoundInfo(void)
 {
   int i;
 
@@ -1895,7 +2028,7 @@ static void set_sound_parameters(int sound, char **parameter_raw)
   sound_info[sound].priority = parameter[SND_ARG_PRIORITY];
 }
 
-static void InitSoundInfo()
+static void InitSoundInfo(void)
 {
   int *sound_effect_properties;
   int num_sounds = getSoundListSize();
@@ -1962,7 +2095,7 @@ static void InitSoundInfo()
   free(sound_effect_properties);
 }
 
-static void InitGameModeMusicInfo()
+static void InitGameModeMusicInfo(void)
 {
   struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
   int num_property_mappings = getMusicListPropertyMappingSize();
@@ -1991,8 +2124,8 @@ static void InitGameModeMusicInfo()
   for (i = 0; i < num_property_mappings; i++)
   {
     int prefix   = property_mapping[i].base_index;
-    int gamemode = property_mapping[i].ext1_index;
-    int level    = property_mapping[i].ext2_index;
+    int gamemode = property_mapping[i].ext2_index;
+    int level    = property_mapping[i].ext3_index;
     int music    = property_mapping[i].artwork_index;
 
     if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
@@ -2045,7 +2178,7 @@ static void set_music_parameters(int music, char **parameter_raw)
     music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
 }
 
-static void InitMusicInfo()
+static void InitMusicInfo(void)
 {
   int num_music = getMusicListSize();
   int i, j;
@@ -2081,7 +2214,7 @@ static void InitMusicInfo()
   }
 }
 
-static void ReinitializeGraphics()
+static void ReinitializeGraphics(void)
 {
   print_timestamp_init("ReinitializeGraphics");
 
@@ -2121,15 +2254,13 @@ static void ReinitializeGraphics()
 
   InitGadgets();
   print_timestamp_time("InitGadgets");
-  InitToons();
-  print_timestamp_time("InitToons");
   InitDoors();
   print_timestamp_time("InitDoors");
 
   print_timestamp_done("ReinitializeGraphics");
 }
 
-static void ReinitializeSounds()
+static void ReinitializeSounds(void)
 {
   InitSoundInfo();             /* sound properties mapping */
   InitElementSoundInfo();      /* element game sound mapping */
@@ -2139,10 +2270,11 @@ static void ReinitializeSounds()
   InitPlayLevelSound();                /* internal game sound settings */
 }
 
-static void ReinitializeMusic()
+static void ReinitializeMusic(void)
 {
   InitMusicInfo();             /* music properties mapping */
   InitGameModeMusicInfo();     /* game mode music mapping */
+  InitGlobalAnimMusicInfo();   /* global animation music settings */
 }
 
 static int get_special_property_bit(int element, int property_bit_nr)
@@ -2330,7 +2462,7 @@ void ResolveGroupElement(int group_element)
   ResolveGroupElementExt(group_element, 0);
 }
 
-void InitElementPropertiesStatic()
+void InitElementPropertiesStatic(void)
 {
   static boolean clipboard_elements_initialized = FALSE;
 
@@ -3542,12 +3674,8 @@ void InitElementPropertiesStatic()
     EL_INVISIBLE_WALL_ACTIVE,
     EL_SWITCHGATE_SWITCH_UP,
     EL_SWITCHGATE_SWITCH_DOWN,
-    EL_DC_SWITCHGATE_SWITCH_UP,
-    EL_DC_SWITCHGATE_SWITCH_DOWN,
     EL_TIMEGATE_SWITCH,
     EL_TIMEGATE_SWITCH_ACTIVE,
-    EL_DC_TIMEGATE_SWITCH,
-    EL_DC_TIMEGATE_SWITCH_ACTIVE,
     EL_EMC_WALL_1,
     EL_EMC_WALL_2,
     EL_EMC_WALL_3,
@@ -3616,6 +3744,12 @@ void InitElementPropertiesStatic()
     EL_SIGN_FRANKIE,
     EL_STEEL_EXIT_CLOSED,
     EL_STEEL_EXIT_OPEN,
+    EL_STEEL_EXIT_OPENING,
+    EL_STEEL_EXIT_CLOSING,
+    EL_EM_STEEL_EXIT_CLOSED,
+    EL_EM_STEEL_EXIT_OPEN,
+    EL_EM_STEEL_EXIT_OPENING,
+    EL_EM_STEEL_EXIT_CLOSING,
     EL_DC_STEELWALL_1_LEFT,
     EL_DC_STEELWALL_1_RIGHT,
     EL_DC_STEELWALL_1_TOP,
@@ -3668,14 +3802,34 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY_ACTIVE,
     EL_EM_GATE_3_GRAY_ACTIVE,
     EL_EM_GATE_4_GRAY_ACTIVE,
+    EL_EMC_GATE_5,
+    EL_EMC_GATE_6,
+    EL_EMC_GATE_7,
+    EL_EMC_GATE_8,
+    EL_EMC_GATE_5_GRAY,
+    EL_EMC_GATE_6_GRAY,
+    EL_EMC_GATE_7_GRAY,
+    EL_EMC_GATE_8_GRAY,
+    EL_EMC_GATE_5_GRAY_ACTIVE,
+    EL_EMC_GATE_6_GRAY_ACTIVE,
+    EL_EMC_GATE_7_GRAY_ACTIVE,
+    EL_EMC_GATE_8_GRAY_ACTIVE,
+    EL_DC_GATE_WHITE,
+    EL_DC_GATE_WHITE_GRAY,
+    EL_DC_GATE_WHITE_GRAY_ACTIVE,
+    EL_DC_GATE_FAKE_GRAY,
     EL_SWITCHGATE_OPEN,
     EL_SWITCHGATE_OPENING,
     EL_SWITCHGATE_CLOSED,
     EL_SWITCHGATE_CLOSING,
+    EL_DC_SWITCHGATE_SWITCH_UP,
+    EL_DC_SWITCHGATE_SWITCH_DOWN,
     EL_TIMEGATE_OPEN,
     EL_TIMEGATE_OPENING,
     EL_TIMEGATE_CLOSED,
     EL_TIMEGATE_CLOSING,
+    EL_DC_TIMEGATE_SWITCH,
+    EL_DC_TIMEGATE_SWITCH_ACTIVE,
     EL_TUBE_ANY,
     EL_TUBE_VERTICAL,
     EL_TUBE_HORIZONTAL,
@@ -3687,6 +3841,9 @@ void InitElementPropertiesStatic()
     EL_TUBE_LEFT_DOWN,
     EL_TUBE_RIGHT_UP,
     EL_TUBE_RIGHT_DOWN,
+    EL_EXPANDABLE_STEELWALL_HORIZONTAL,
+    EL_EXPANDABLE_STEELWALL_VERTICAL,
+    EL_EXPANDABLE_STEELWALL_ANY,
 
     -1
   };
@@ -4160,6 +4317,8 @@ void InitElementPropertiesStatic()
     EL_INTERNAL_CASCADE_SP_ACTIVE,
     EL_INTERNAL_CASCADE_DC_ACTIVE,
     EL_INTERNAL_CASCADE_DX_ACTIVE,
+    EL_INTERNAL_CASCADE_MM_ACTIVE,
+    EL_INTERNAL_CASCADE_DF_ACTIVE,
     EL_INTERNAL_CASCADE_CHARS_ACTIVE,
     EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE,
     EL_INTERNAL_CASCADE_CE_ACTIVE,
@@ -4181,6 +4340,8 @@ void InitElementPropertiesStatic()
     EL_INTERNAL_CASCADE_SP,
     EL_INTERNAL_CASCADE_DC,
     EL_INTERNAL_CASCADE_DX,
+    EL_INTERNAL_CASCADE_MM,
+    EL_INTERNAL_CASCADE_DF,
     EL_INTERNAL_CASCADE_CHARS,
     EL_INTERNAL_CASCADE_STEEL_CHARS,
     EL_INTERNAL_CASCADE_CE,
@@ -4423,8 +4584,8 @@ void InitElementPropertiesEngine(int engine_version)
     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
     else
-      SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
-                                           IS_INDESTRUCTIBLE(i)));
+      SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_INDESTRUCTIBLE(i) &&
+                                           i != EL_ACID));
 
     /* ---------- EXPLOSION_PROOF ------------------------------------------ */
     if (i == EL_FLAMES)
@@ -4578,26 +4739,7 @@ void InitElementPropertiesEngine(int engine_version)
     InitElementGraphicInfo();
 }
 
-void InitElementPropertiesAfterLoading(int engine_version)
-{
-  int i;
-
-  /* set some other uninitialized values of custom elements in older levels */
-  if (engine_version < VERSION_IDENT(3,1,0,0))
-  {
-    for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
-    {
-      int element = EL_CUSTOM_START + i;
-
-      element_info[element].access_direction = MV_ALL_DIRECTIONS;
-
-      element_info[element].explosion_delay = 17;
-      element_info[element].ignition_delay = 8;
-    }
-  }
-}
-
-void InitElementPropertiesGfxElement()
+void InitElementPropertiesGfxElement(void)
 {
   int i;
 
@@ -4609,7 +4751,7 @@ void InitElementPropertiesGfxElement()
   }
 }
 
-static void InitGlobal()
+static void InitGlobal(void)
 {
   int graphic;
   int i;
@@ -4625,6 +4767,16 @@ static void InitGlobal()
     element_info[i].editor_description= element_name_info[i].editor_description;
   }
 
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS + 1; i++)
+  {
+    /* check if global_anim_name_info defined for each entry in "main.h" */
+    if (i < NUM_GLOBAL_ANIM_TOKENS &&
+       global_anim_name_info[i].token_name == NULL)
+      Error(ERR_EXIT, "undefined 'global_anim_name_info' entry for anim %d", i);
+
+    global_anim_info[i].token_name = global_anim_name_info[i].token_name;
+  }
+
   /* create hash from image config list */
   image_config_hash = newSetupFileHash();
   for (i = 0; image_config[i].token != NULL; i++)
@@ -4728,6 +4880,7 @@ static void InitGlobal()
   global.create_images_dir = NULL;
 
   global.frames_per_second = 0;
+  global.show_frames_per_second = FALSE;
 
   global.border_status = GAME_MODE_LOADING;
   global.anim_status = global.anim_status_next = GAME_MODE_LOADING;
@@ -4735,7 +4888,7 @@ static void InitGlobal()
   global.use_envelope_request = FALSE;
 }
 
-void Execute_Command(char *command)
+static void Execute_Command(char *command)
 {
   int i;
 
@@ -4856,13 +5009,17 @@ void Execute_Command(char *command)
   }
   else if (strPrefix(command, "autotest ") ||
           strPrefix(command, "autoplay ") ||
-          strPrefix(command, "autoffwd "))
+          strPrefix(command, "autoffwd ") ||
+          strPrefix(command, "autowarp "))
   {
     char *str_ptr = getStringCopy(&command[9]);        /* read command parameters */
 
-    global.autoplay_mode = (strPrefix(command, "autotest") ? AUTOPLAY_TEST :
-                           strPrefix(command, "autoplay") ? AUTOPLAY_PLAY :
-                           strPrefix(command, "autoffwd") ? AUTOPLAY_FFWD : 0);
+    global.autoplay_mode =
+      (strPrefix(command, "autotest") ? AUTOPLAY_MODE_TEST :
+       strPrefix(command, "autoplay") ? AUTOPLAY_MODE_PLAY :
+       strPrefix(command, "autoffwd") ? AUTOPLAY_MODE_FFWD :
+       strPrefix(command, "autowarp") ? AUTOPLAY_MODE_WARP :
+       AUTOPLAY_MODE_NONE);
 
     while (*str_ptr != '\0')                   /* continue parsing string */
     {
@@ -4895,6 +5052,9 @@ void Execute_Command(char *command)
       while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
        str_ptr++;
     }
+
+    if (global.autoplay_mode == AUTOPLAY_MODE_TEST)
+      program.headless = TRUE;
   }
   else if (strPrefix(command, "convert "))
   {
@@ -4909,6 +5069,8 @@ void Execute_Command(char *command)
       *str_ptr++ = '\0';                       /* terminate leveldir string */
       global.convert_level_nr = atoi(str_ptr); /* get level_nr value */
     }
+
+    program.headless = TRUE;
   }
   else if (strPrefix(command, "create images "))
   {
@@ -4928,24 +5090,33 @@ void Execute_Command(char *command)
   {
     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
   }
+
+  /* disable networking if any valid command was recognized */
+  options.network = setup.network_mode = FALSE;
 }
 
-static void InitSetup()
+static void InitSetup(void)
 {
   LoadSetup();                                 /* global setup info */
+  LoadSetup_AutoSetup();                       /* global auto setup info */
 
   /* set some options from setup file */
 
   if (setup.options.verbose)
     options.verbose = TRUE;
+
+  if (setup.debug.show_frames_per_second)
+    global.show_frames_per_second = TRUE;
 }
 
-static void InitGameInfo()
+static void InitGameInfo(void)
 {
   game.restart_level = FALSE;
+  game.restart_game_message = NULL;
+  game.request_active = FALSE;
 }
 
-static void InitPlayerInfo()
+static void InitPlayerInfo(void)
 {
   int i;
 
@@ -4953,12 +5124,15 @@ static void InitPlayerInfo()
   local_player = &stored_player[0];
 
   for (i = 0; i < MAX_PLAYERS; i++)
-    stored_player[i].connected = FALSE;
+  {
+    stored_player[i].connected_locally = FALSE;
+    stored_player[i].connected_network = FALSE;
+  }
 
-  local_player->connected = TRUE;
+  local_player->connected_locally = TRUE;
 }
 
-static void InitArtworkInfo()
+static void InitArtworkInfo(void)
 {
   LoadArtworkInfo();
 }
@@ -4984,14 +5158,15 @@ static char *get_level_id_suffix(int id_nr)
   return id_suffix;
 }
 
-static void InitArtworkConfig()
+static void InitArtworkConfig(void)
 {
   static char *image_id_prefix[MAX_NUM_ELEMENTS +
                               NUM_FONTS +
                               NUM_GLOBAL_ANIM_TOKENS + 1];
   static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS +
                               NUM_GLOBAL_ANIM_TOKENS + 1];
-  static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
+  static char *music_id_prefix[NUM_MUSIC_PREFIXES +
+                              NUM_GLOBAL_ANIM_TOKENS + 1];
   static char *action_id_suffix[NUM_ACTIONS + 1];
   static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
@@ -5001,6 +5176,10 @@ static void InitArtworkConfig()
   {
     "name",
     "sort_priority",
+    "program_title",
+    "program_copyright",
+    "program_company",
+
     NULL
   };
   static char **ignore_image_tokens;
@@ -5067,7 +5246,10 @@ static void InitArtworkConfig()
 
   for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
     music_id_prefix[i] = music_prefix_info[i].prefix;
-  music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
+    music_id_prefix[NUM_MUSIC_PREFIXES + i] =
+      global_anim_info[i].token_name;
+  music_id_prefix[NUM_MUSIC_PREFIXES + NUM_GLOBAL_ANIM_TOKENS] = NULL;
 
   for (i = 0; i < NUM_ACTIONS; i++)
     action_id_suffix[i] = element_action_info[i].suffix;
@@ -5092,18 +5274,29 @@ static void InitArtworkConfig()
                sound_id_prefix, action_id_suffix, dummy,
                special_id_suffix, ignore_sound_tokens);
   InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
-               music_id_prefix, special_id_suffix, level_id_suffix,
-               dummy, ignore_music_tokens);
+               music_id_prefix, action_id_suffix, special_id_suffix,
+               level_id_suffix, ignore_music_tokens);
 }
 
-static void InitMixer()
+static void InitMixer(void)
 {
   OpenAudio();
 
   StartMixer();
 }
 
-void InitGfxBuffers()
+static void InitVideoOverlay(void)
+{
+  // if virtual buttons are not loaded from setup file, repeat initializing
+  // virtual buttons grid with default values now that video is initialized
+  if (!setup.touch.grid_initialized)
+    InitSetup();
+
+  InitTileCursorInfo();
+  InitOverlayInfo();
+}
+
+void InitGfxBuffers(void)
 {
   static int win_xsize_last = -1;
   static int win_ysize_last = -1;
@@ -5112,19 +5305,18 @@ void InitGfxBuffers()
 
   if (WIN_XSIZE != win_xsize_last || WIN_YSIZE != win_ysize_last)
   {
-    /* may contain content for cross-fading -- only re-create if changed */
-    ReCreateBitmap(&bitmap_db_store, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
-    ReCreateBitmap(&bitmap_db_cross, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
+    /* used to temporarily store the backbuffer -- only re-create if changed */
+    ReCreateBitmap(&bitmap_db_store_1, WIN_XSIZE, WIN_YSIZE);
+    ReCreateBitmap(&bitmap_db_store_2, WIN_XSIZE, WIN_YSIZE);
 
     win_xsize_last = WIN_XSIZE;
     win_ysize_last = WIN_YSIZE;
   }
 
-  ReCreateBitmap(&bitmap_db_field, FXSIZE, FYSIZE, DEFAULT_DEPTH);
-  ReCreateBitmap(&bitmap_db_panel, DXSIZE, DYSIZE, DEFAULT_DEPTH);
-  ReCreateBitmap(&bitmap_db_door_1, 3 * DXSIZE, DYSIZE, DEFAULT_DEPTH);
-  ReCreateBitmap(&bitmap_db_door_2, 3 * VXSIZE, VYSIZE, DEFAULT_DEPTH);
-  ReCreateBitmap(&bitmap_db_toons, FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH);
+  ReCreateBitmap(&bitmap_db_field, FXSIZE, FYSIZE);
+  ReCreateBitmap(&bitmap_db_panel, DXSIZE, DYSIZE);
+  ReCreateBitmap(&bitmap_db_door_1, 3 * DXSIZE, DYSIZE);
+  ReCreateBitmap(&bitmap_db_door_2, 3 * VXSIZE, VYSIZE);
 
   /* initialize screen properties */
   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
@@ -5144,13 +5336,12 @@ void InitGfxBuffers()
   InitGfxBuffers_SP();
 }
 
-void InitGfx()
+static void InitGfx(void)
 {
   struct GraphicInfo *graphic_info_last = graphic_info;
   char *filename_font_initial = NULL;
   char *filename_anim_initial = NULL;
   Bitmap *bitmap_font_initial = NULL;
-  int font_height;
   int i, j;
 
   /* determine settings for initial font (for displaying startup messages) */
@@ -5201,12 +5392,7 @@ void InitGfx()
 
   InitFontGraphicInfo();
 
-  font_height = getFontHeight(FC_RED);
-
-  DrawInitText(getProgramInitString(), 20, FC_YELLOW);
-  DrawInitText(setup.internal.program_copyright, 50, FC_RED);
-  DrawInitText(setup.internal.program_website, WIN_YSIZE - 20 - font_height,
-              FC_RED);
+  DrawProgramInfo();
 
   DrawInitText("Loading graphics", 120, FC_GREEN);
 
@@ -5301,8 +5487,9 @@ void InitGfx()
   InitMenuDesignSettings_Static();
 
   InitGfxDrawBusyAnimFunction(DrawInitAnim);
-  InitGfxDrawGlobalAnimFunction(DrawGlobalAnim);
+  InitGfxDrawGlobalAnimFunction(DrawGlobalAnimations);
   InitGfxDrawGlobalBorderFunction(DrawMaskedBorderToTarget);
+  InitGfxDrawTileCursorFunction(DrawTileCursor);
 
   gfx.fade_border_source_status = global.border_status;
   gfx.fade_border_target_status = global.border_status;
@@ -5312,38 +5499,40 @@ void InitGfx()
   init_last = init;
 }
 
-void InitGfxBackground()
+static void InitGfxBackground(void)
 {
   fieldbuffer = bitmap_db_field;
-  SetDrawtoField(DRAW_BACKBUFFER);
+  SetDrawtoField(DRAW_TO_BACKBUFFER);
 
   ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
 
   redraw_mask = REDRAW_ALL;
 }
 
-static void InitLevelInfo()
+static void InitLevelInfo(void)
 {
   LoadLevelInfo();                             /* global level info */
   LoadLevelSetup_LastSeries();                 /* last played series info */
   LoadLevelSetup_SeriesInfo();                 /* last played level info */
 
   if (global.autoplay_leveldir &&
-      global.autoplay_mode != AUTOPLAY_TEST)
+      global.autoplay_mode != AUTOPLAY_MODE_TEST)
   {
     leveldir_current = getTreeInfoFromIdentifier(leveldir_first,
                                                  global.autoplay_leveldir);
     if (leveldir_current == NULL)
       leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
   }
+
+  SetLevelSetInfo(leveldir_current->identifier, level_nr);
 }
 
-static void InitLevelArtworkInfo()
+static void InitLevelArtworkInfo(void)
 {
   LoadLevelArtworkInfo();
 }
 
-static void InitImages()
+static void InitImages(void)
 {
   print_timestamp_init("InitImages");
 
@@ -5400,6 +5589,9 @@ static void InitImages()
   ReinitializeGraphics();
   print_timestamp_time("ReinitializeGraphics");
 
+  LoadMenuDesignSettings_AfterGraphics();
+  print_timestamp_time("LoadMenuDesignSettings_AfterGraphics");
+
   UPDATE_BUSY_STATE();
 
   print_timestamp_done("InitImages");
@@ -5443,32 +5635,58 @@ static void InitMusic(char *identifier)
   print_timestamp_done("InitMusic");
 }
 
-static void InitArtworkDone()
+static void InitArtworkDone(void)
 {
+  if (program.headless)
+    return;
+
   InitGlobalAnimations();
 }
 
-void InitNetworkServer()
+static void InitNetworkSettings(void)
 {
-#if defined(NETWORK_AVALIABLE)
-  int nr_wanted;
-#endif
+  boolean network_enabled = (options.network || setup.network_mode);
+  char *network_server = (options.server_host != NULL ? options.server_host :
+                         setup.network_server_hostname);
+
+  if (strEqual(network_server, STR_NETWORK_AUTO_DETECT))
+    network_server = NULL;
+
+  InitNetworkInfo(network_enabled,
+                 FALSE,
+                 options.serveronly,
+                 network_server,
+                 options.server_port);
+}
 
-  if (!options.network)
+void InitNetworkServer(void)
+{
+  if (!network.enabled || network.connected)
     return;
 
-#if defined(NETWORK_AVALIABLE)
-  nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
+  LimitScreenUpdates(FALSE);
 
-  if (!ConnectToServer(options.server_host, options.server_port))
-    Error(ERR_EXIT, "cannot connect to network game server");
+  if (game_status == GAME_MODE_LOADING)
+    DrawProgramInfo();
 
-  SendToServer_PlayerName(setup.player_name);
-  SendToServer_ProtocolVersion();
+  if (!ConnectToServer(network.server_host, network.server_port))
+  {
+    network.enabled = FALSE;
 
-  if (nr_wanted)
-    SendToServer_NrWanted(nr_wanted);
-#endif
+    setup.network_mode = FALSE;
+  }
+  else
+  {
+    SendToServer_ProtocolVersion();
+    SendToServer_PlayerName(setup.player_name);
+    SendToServer_NrWanted(setup.network_player_nr + 1);
+
+    network.connected = TRUE;
+  }
+
+  /* short time to recognize result of network initialization */
+  if (game_status == GAME_MODE_LOADING)
+    Delay_WithScreenUpdates(1000);
 }
 
 static boolean CheckArtworkConfigForCustomElements(char *filename)
@@ -5544,7 +5762,7 @@ static boolean CheckArtworkTypeForRedefinedCustomElements(int type)
   return redefined_ce_found;
 }
 
-static void InitOverrideArtwork()
+static void InitOverrideArtwork(void)
 {
   boolean redefined_ce_found = FALSE;
 
@@ -5745,7 +5963,7 @@ void ReloadCustomArtwork(int force_reload)
   LimitScreenUpdates(FALSE);
 }
 
-void KeyboardAutoRepeatOffUnlessAutoplay()
+void KeyboardAutoRepeatOffUnlessAutoplay(void)
 {
   if (global.autoplay_leveldir == NULL)
     KeyboardAutoRepeatOff();
@@ -5753,6 +5971,10 @@ void KeyboardAutoRepeatOffUnlessAutoplay()
 
 void DisplayExitMessage(char *format, va_list ap)
 {
+  // also check for initialized video (headless flag may be temporarily unset)
+  if (program.headless || !video.initialized)
+    return;
+
   // check if draw buffer and fonts for exit message are already available
   if (drawto == NULL || font_initial[NUM_INITIAL_FONTS - 1].bitmap == NULL)
     return;
@@ -5816,7 +6038,7 @@ void DisplayExitMessage(char *format, va_list ap)
 /* OpenAll()                                                                 */
 /* ========================================================================= */
 
-void OpenAll()
+void OpenAll(void)
 {
   print_timestamp_init("OpenAll");
 
@@ -5832,13 +6054,17 @@ void OpenAll()
 
   print_timestamp_time("[init setup/config stuff (1)]");
 
+  InitScoresInfo();
+
   if (options.execute_command)
     Execute_Command(options.execute_command);
 
-  if (options.serveronly)
+  InitNetworkSettings();
+
+  if (network.serveronly)
   {
 #if defined(PLATFORM_UNIX)
-    NetworkServer(options.server_port, options.serveronly);
+    NetworkServer(network.server_port, TRUE);
 #else
     Error(ERR_WARN, "networking only supported in Unix version");
 #endif
@@ -5864,10 +6090,10 @@ void OpenAll()
 
   print_timestamp_time("[init setup/config stuff]");
 
+  InitVideoDefaults();
   InitVideoDisplay();
   InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
-
-  InitEventFilter(FilterEvents);
+  InitVideoOverlay();
 
   print_timestamp_time("[init video stuff]");
 
@@ -5905,6 +6131,7 @@ void OpenAll()
 
   em_open_all();
   sp_open_all();
+  mm_open_all();
 
   if (global.autoplay_leveldir)
   {
@@ -5922,6 +6149,8 @@ void OpenAll()
     return;
   }
 
+  InitNetworkServer();
+
   SetGameStatus(GAME_MODE_MAIN);
 
   FadeSetEnterScreen();
@@ -5934,8 +6163,6 @@ void OpenAll()
 
   DrawMainMenu();
 
-  InitNetworkServer();
-
 #if 0
   Error(ERR_DEBUG, "::: SDL_GetBasePath() == '%s'",
        SDL_GetBasePath());
@@ -5947,10 +6174,10 @@ void OpenAll()
   Error(ERR_DEBUG, "::: SDL_AndroidGetExternalStoragePath() == '%s'",
        SDL_AndroidGetExternalStoragePath());
   Error(ERR_DEBUG, "::: SDL_AndroidGetExternalStorageState() == '%s'",
-       (SDL_AndroidGetExternalStorageState() ==
-        SDL_ANDROID_EXTERNAL_STORAGE_READ ? "read" :
-        SDL_AndroidGetExternalStorageState() ==
-        SDL_ANDROID_EXTERNAL_STORAGE_WRITE ? "write" : "not available"));
+       (SDL_AndroidGetExternalStorageState() &
+        SDL_ANDROID_EXTERNAL_STORAGE_WRITE ? "writable" :
+        SDL_AndroidGetExternalStorageState() &
+        SDL_ANDROID_EXTERNAL_STORAGE_READ ? "readable" : "not available"));
 #endif
 #endif
 }
@@ -5981,7 +6208,7 @@ void CloseAllAndExit(int exit_value)
   CloseVideoDisplay();
   ClosePlatformDependentStuff();
 
-  if (exit_value != 0)
+  if (exit_value != 0 && !options.execute_command)
   {
     /* fall back to default level set (current set may have caused an error) */
     SaveLevelSetup_LastSeries_Deactivate();