rnd-20031202-1-src
[rocksndiamonds.git] / src / libgame / setup.c
index 102d5fd13d92d0bd7fa1fa0ca494d7ecbe34994b..f9063d5d5726037190925b93177bb24fb42fa90b 100644 (file)
 #include "misc.h"
 #include "hash.h"
 
-/* file names and filename extensions */
-#if !defined(PLATFORM_MSDOS)
-#define LEVELSETUP_DIRECTORY   "levelsetup"
-#define SETUP_FILENAME         "setup.conf"
-#define LEVELSETUP_FILENAME    "levelsetup.conf"
-#define LEVELINFO_FILENAME     "levelinfo.conf"
-#define GRAPHICSINFO_FILENAME  "graphicsinfo.conf"
-#define SOUNDSINFO_FILENAME    "soundsinfo.conf"
-#define MUSICINFO_FILENAME     "musicinfo.conf"
-#define LEVELFILE_EXTENSION    "level"
-#define TAPEFILE_EXTENSION     "tape"
-#define SCOREFILE_EXTENSION    "score"
-#else
-#define LEVELSETUP_DIRECTORY   "lvlsetup"
-#define SETUP_FILENAME         "setup.cnf"
-#define LEVELSETUP_FILENAME    "lvlsetup.cnf"
-#define LEVELINFO_FILENAME     "lvlinfo.cnf"
-#define GRAPHICSINFO_FILENAME  "gfxinfo.cnf"
-#define SOUNDSINFO_FILENAME    "sndinfo.cnf"
-#define MUSICINFO_FILENAME     "musinfo.cnf"
-#define LEVELFILE_EXTENSION    "lvl"
-#define TAPEFILE_EXTENSION     "tap"
-#define SCOREFILE_EXTENSION    "sco"
-#endif
 
 #define NUM_LEVELCLASS_DESC    8
+
 static char *levelclass_desc[NUM_LEVELCLASS_DESC] =
 {
   "Tutorial Levels",
@@ -61,64 +38,44 @@ static char *levelclass_desc[NUM_LEVELCLASS_DESC] =
   "DX Boulderdash"
 };
 
-#define LEVELCOLOR(n)  (IS_LEVELCLASS_TUTORIAL(n) ?            FC_BLUE : \
-                        IS_LEVELCLASS_CLASSICS(n) ?            FC_RED : \
-                        IS_LEVELCLASS_BD(n) ?                  FC_GREEN : \
-                        IS_LEVELCLASS_EM(n) ?                  FC_YELLOW : \
-                        IS_LEVELCLASS_SP(n) ?                  FC_GREEN : \
-                        IS_LEVELCLASS_DX(n) ?                  FC_YELLOW : \
-                        IS_LEVELCLASS_CONTRIBUTION(n) ?        FC_GREEN : \
-                        IS_LEVELCLASS_USER(n) ?                FC_RED : \
+
+#define LEVELCOLOR(n)  (IS_LEVELCLASS_TUTORIAL(n) ?            FC_BLUE :    \
+                        IS_LEVELCLASS_CLASSICS(n) ?            FC_RED :     \
+                        IS_LEVELCLASS_BD(n) ?                  FC_GREEN :   \
+                        IS_LEVELCLASS_EM(n) ?                  FC_YELLOW :  \
+                        IS_LEVELCLASS_SP(n) ?                  FC_GREEN :   \
+                        IS_LEVELCLASS_DX(n) ?                  FC_YELLOW :  \
+                        IS_LEVELCLASS_CONTRIB(n) ?             FC_GREEN :   \
+                        IS_LEVELCLASS_PRIVATE(n) ?             FC_RED :     \
                         FC_BLUE)
 
-#define LEVELSORTING(n)        (IS_LEVELCLASS_TUTORIAL(n) ?            0 : \
-                        IS_LEVELCLASS_CLASSICS(n) ?            1 : \
-                        IS_LEVELCLASS_BD(n) ?                  2 : \
-                        IS_LEVELCLASS_EM(n) ?                  3 : \
-                        IS_LEVELCLASS_SP(n) ?                  4 : \
-                        IS_LEVELCLASS_DX(n) ?                  5 : \
-                        IS_LEVELCLASS_CONTRIBUTION(n) ?        6 : \
-                        IS_LEVELCLASS_USER(n) ?                7 : \
+#define LEVELSORTING(n)        (IS_LEVELCLASS_TUTORIAL(n) ?            0 :     \
+                        IS_LEVELCLASS_CLASSICS(n) ?            1 :     \
+                        IS_LEVELCLASS_BD(n) ?                  2 :     \
+                        IS_LEVELCLASS_EM(n) ?                  3 :     \
+                        IS_LEVELCLASS_SP(n) ?                  4 :     \
+                        IS_LEVELCLASS_DX(n) ?                  5 :     \
+                        IS_LEVELCLASS_CONTRIB(n) ?             6 :     \
+                        IS_LEVELCLASS_PRIVATE(n) ?             7 :     \
                         9)
 
-#define ARTWORKCOLOR(n)        (IS_ARTWORKCLASS_CLASSICS(n) ?          FC_RED : \
-                        IS_ARTWORKCLASS_CONTRIBUTION(n) ?      FC_YELLOW : \
-                        IS_ARTWORKCLASS_LEVEL(n) ?             FC_GREEN : \
-                        IS_ARTWORKCLASS_USER(n) ?              FC_RED : \
+#define ARTWORKCOLOR(n)        (IS_ARTWORKCLASS_CLASSICS(n) ?          FC_RED :     \
+                        IS_ARTWORKCLASS_CONTRIB(n) ?           FC_YELLOW :  \
+                        IS_ARTWORKCLASS_PRIVATE(n) ?           FC_RED :     \
+                        IS_ARTWORKCLASS_LEVEL(n) ?             FC_GREEN :   \
                         FC_BLUE)
 
-#define ARTWORKSORTING(n) (IS_ARTWORKCLASS_CLASSICS(n) ?       0 : \
-                        IS_ARTWORKCLASS_CONTRIBUTION(n) ?      1 : \
-                        IS_ARTWORKCLASS_LEVEL(n) ?             2 : \
-                        IS_ARTWORKCLASS_USER(n) ?              3 : \
-                        9)
+#define ARTWORKSORTING(n) (IS_ARTWORKCLASS_CLASSICS(n) ?       0 :     \
+                          IS_ARTWORKCLASS_LEVEL(n) ?           1 :     \
+                          IS_ARTWORKCLASS_CONTRIB(n) ?         2 :     \
+                          IS_ARTWORKCLASS_PRIVATE(n) ?         3 :     \
+                          9)
 
 #define TOKEN_VALUE_POSITION           40
 #define TOKEN_COMMENT_POSITION         60
 
 #define MAX_COOKIE_LEN                 256
 
-#define ARTWORKINFO_FILENAME(type)     ((type) == TREE_TYPE_GRAPHICS_DIR ? \
-                                        GRAPHICSINFO_FILENAME :            \
-                                        (type) == TREE_TYPE_SOUNDS_DIR ?   \
-                                        SOUNDSINFO_FILENAME :              \
-                                        (type) == TREE_TYPE_MUSIC_DIR ?    \
-                                        MUSICINFO_FILENAME : "")
-
-#define ARTWORK_DIRECTORY(type)                ((type) == TREE_TYPE_GRAPHICS_DIR ? \
-                                        GRAPHICS_DIRECTORY :               \
-                                        (type) == TREE_TYPE_SOUNDS_DIR ?   \
-                                        SOUNDS_DIRECTORY :                 \
-                                        (type) == TREE_TYPE_MUSIC_DIR ?    \
-                                        MUSIC_DIRECTORY : "")
-
-#define OPTIONS_ARTWORK_DIRECTORY(type)        ((type) == TREE_TYPE_GRAPHICS_DIR ? \
-                                        options.graphics_directory :       \
-                                        (type) == TREE_TYPE_SOUNDS_DIR ?   \
-                                        options.sounds_directory :         \
-                                        (type) == TREE_TYPE_MUSIC_DIR ?    \
-                                        options.music_directory : "")
-
 
 /* ------------------------------------------------------------------------- */
 /* file functions                                                            */
@@ -268,6 +225,23 @@ static char *getDefaultMusicDir(char *music_subdir)
   return music_dir;
 }
 
+static char *getDefaultArtworkSet(int type)
+{
+  return (type == TREE_TYPE_GRAPHICS_DIR ? GFX_CLASSIC_SUBDIR :
+         type == TREE_TYPE_SOUNDS_DIR   ? SND_CLASSIC_SUBDIR :
+         type == TREE_TYPE_MUSIC_DIR    ? MUS_CLASSIC_SUBDIR : "");
+}
+
+static char *getDefaultArtworkDir(int type)
+{
+  return (type == TREE_TYPE_GRAPHICS_DIR ?
+         getDefaultGraphicsDir(GFX_CLASSIC_SUBDIR) :
+         type == TREE_TYPE_SOUNDS_DIR ?
+         getDefaultSoundsDir(SND_CLASSIC_SUBDIR) :
+         type == TREE_TYPE_MUSIC_DIR ?
+         getDefaultMusicDir(MUS_CLASSIC_SUBDIR) : "");
+}
+
 static char *getUserGraphicsDir()
 {
   static char *usergraphics_dir = NULL;
@@ -310,47 +284,67 @@ static char *getSetupArtworkDir(TreeInfo *ti)
   return artwork_dir;
 }
 
-void setLevelArtworkDir(TreeInfo *ti)
+char *setLevelArtworkDir(TreeInfo *ti)
 {
-  char **artwork_path_ptr, *artwork_set;
+  char **artwork_path_ptr, **artwork_set_ptr;
   TreeInfo *level_artwork;
 
   if (ti == NULL || leveldir_current == NULL)
-    return;
-
-  artwork_path_ptr =
-    (ti->type == TREE_TYPE_GRAPHICS_DIR ? &leveldir_current->graphics_path :
-     ti->type == TREE_TYPE_SOUNDS_DIR   ? &leveldir_current->sounds_path :
-     &leveldir_current->music_path);
-
-  artwork_set =
-    (ti->type == TREE_TYPE_GRAPHICS_DIR ? leveldir_current->graphics_set :
-     ti->type == TREE_TYPE_SOUNDS_DIR   ? leveldir_current->sounds_set :
-     leveldir_current->music_set);
+    return NULL;
 
-  if ((level_artwork = getTreeInfoFromIdentifier(ti, artwork_set)) == NULL)
-    return;
+  artwork_path_ptr = &(LEVELDIR_ARTWORK_PATH(leveldir_current, ti->type));
+  artwork_set_ptr  = &(LEVELDIR_ARTWORK_SET( leveldir_current, ti->type));
 
   if (*artwork_path_ptr != NULL)
     free(*artwork_path_ptr);
 
-  *artwork_path_ptr = getStringCopy(getSetupArtworkDir(level_artwork));
+  if ((level_artwork = getTreeInfoFromIdentifier(ti, *artwork_set_ptr)))
+    *artwork_path_ptr = getStringCopy(getSetupArtworkDir(level_artwork));
+  else
+  {
+    /* No (or non-existing) artwork configured in "levelinfo.conf". This would
+       normally result in using the artwork configured in the setup menu. But
+       if an artwork subdirectory exists (which might contain custom artwork
+       or an artwork configuration file), this level artwork must be treated
+       as relative to the default "classic" artwork, not to the artwork that
+       is currently configured in the setup menu. */
+
+    char *dir = getPath2(getCurrentLevelDir(), ARTWORK_DIRECTORY(ti->type));
+
+    if (*artwork_set_ptr != NULL)
+      free(*artwork_set_ptr);
+
+    if (fileExists(dir))
+    {
+      *artwork_path_ptr = getStringCopy(getDefaultArtworkDir(ti->type));
+      *artwork_set_ptr = getStringCopy(getDefaultArtworkSet(ti->type));
+    }
+    else
+    {
+      *artwork_path_ptr = getStringCopy(UNDEFINED_FILENAME);
+      *artwork_set_ptr = NULL;
+    }
+
+    free(dir);
+  }
+
+  return *artwork_set_ptr;
 }
 
-static char *getLevelArtworkDir(int type)
+inline static char *getLevelArtworkSet(int type)
 {
-  char *artwork_path;
+  if (leveldir_current == NULL)
+    return NULL;
+
+  return LEVELDIR_ARTWORK_SET(leveldir_current, type);
+}
 
+inline static char *getLevelArtworkDir(int type)
+{
   if (leveldir_current == NULL)
     return UNDEFINED_FILENAME;
 
-  artwork_path =
-    (type == TREE_TYPE_GRAPHICS_DIR ? leveldir_current->graphics_path :
-     type == TREE_TYPE_SOUNDS_DIR   ? leveldir_current->sounds_path :
-     type == TREE_TYPE_MUSIC_DIR    ? leveldir_current->music_path :
-     UNDEFINED_FILENAME);
-
-  return artwork_path;
+  return LEVELDIR_ARTWORK_PATH(leveldir_current, type);
 }
 
 char *getLevelFilename(int nr)
@@ -361,7 +355,11 @@ char *getLevelFilename(int nr)
   if (filename != NULL)
     free(filename);
 
-  sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
+  if (nr < 0)
+    sprintf(basename, "template.%s", LEVELFILE_EXTENSION);
+  else
+    sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
+
   filename = getPath2(getCurrentLevelDir(), basename);
 
   return filename;
@@ -407,7 +405,71 @@ char *getSetupFilename()
   return filename;
 }
 
-static char *getCorrectedImageBasename(char *basename)
+char *getEditorSetupFilename()
+{
+  static char *filename = NULL;
+
+  if (filename != NULL)
+    free(filename);
+
+  filename = getPath2(getSetupDir(), EDITORSETUP_FILENAME);
+
+  return filename;
+}
+
+char *getHelpAnimFilename()
+{
+  static char *filename = NULL;
+
+  if (filename != NULL)
+    free(filename);
+
+  filename = getPath2(getCurrentLevelDir(), HELPANIM_FILENAME);
+
+  return filename;
+}
+
+char *getHelpTextFilename()
+{
+  static char *filename = NULL;
+
+  if (filename != NULL)
+    free(filename);
+
+  filename = getPath2(getCurrentLevelDir(), HELPTEXT_FILENAME);
+
+  return filename;
+}
+
+char *getLevelSetInfoFilename()
+{
+  static char *filename = NULL;
+  char *basenames[] =
+  {
+    "readme",
+    "readme.txt",
+    "README",
+    "README.txt",
+    "README.TXT",
+
+    NULL
+  };
+  int i;
+
+  for (i = 0; basenames[i] != NULL; i++)
+  {
+    if (filename != NULL)
+      free(filename);
+
+    filename = getPath2(getCurrentLevelDir(), basenames[i]);
+    if (fileExists(filename))
+      return filename;
+  }
+
+  return NULL;
+}
+
+static char *getCorrectedArtworkBasename(char *basename)
 {
   char *basename_corrected = basename;
 
@@ -422,7 +484,7 @@ static char *getCorrectedImageBasename(char *basename)
     /* if corrected filename is still longer than standard MS-DOS filename
        size (8 characters + 1 dot + 3 characters file extension), shorten
        filename by writing file extension after 8th basename character */
-    if (strlen(basename_corrected) > 8+1+3)
+    if (strlen(basename_corrected) > 8 + 1 + 3)
     {
       static char *msdos_filename = NULL;
 
@@ -430,7 +492,9 @@ static char *getCorrectedImageBasename(char *basename)
        free(msdos_filename);
 
       msdos_filename = getStringCopy(basename_corrected);
-      strncpy(&msdos_filename[8], &basename[strlen(basename) - 1+3], 1+3 + 1);
+      strncpy(&msdos_filename[8], &basename[strlen(basename) - (1+3)], 1+3 +1);
+
+      basename_corrected = msdos_filename;
     }
   }
 #endif
@@ -441,38 +505,49 @@ static char *getCorrectedImageBasename(char *basename)
 char *getCustomImageFilename(char *basename)
 {
   static char *filename = NULL;
+  boolean skip_setup_artwork = FALSE;
 
   if (filename != NULL)
     free(filename);
 
-  basename = getCorrectedImageBasename(basename);
+  basename = getCorrectedArtworkBasename(basename);
 
   if (!setup.override_level_graphics)
   {
-    /* 1st try: look for special artwork configured in level series config */
-    filename = getPath2(getLevelArtworkDir(TREE_TYPE_GRAPHICS_DIR), basename);
+    /* 1st try: look for special artwork in current level series directory */
+    filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename);
     if (fileExists(filename))
       return filename;
 
     free(filename);
 
-    /* 2nd try: look for special artwork in current level series directory */
-    filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename);
+    /* check if there is special artwork configured in level series config */
+    if (getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) != NULL)
+    {
+      /* 2nd try: look for special artwork configured in level series config */
+      filename = getPath2(getLevelArtworkDir(ARTWORK_TYPE_GRAPHICS), basename);
+      if (fileExists(filename))
+       return filename;
+
+      free(filename);
+
+      /* take missing artwork configured in level set config from default */
+      skip_setup_artwork = TRUE;
+    }
+  }
+
+  if (!skip_setup_artwork)
+  {
+    /* 3rd try: look for special artwork in configured artwork directory */
+    filename = getPath2(getSetupArtworkDir(artwork.gfx_current), basename);
     if (fileExists(filename))
       return filename;
 
     free(filename);
   }
 
-  /* 3rd try: look for special artwork in configured artwork directory */
-  filename = getPath2(getSetupArtworkDir(artwork.gfx_current), basename);
-  if (fileExists(filename))
-    return filename;
-
-  free(filename);
-
   /* 4th try: look for default artwork in new default artwork directory */
-  filename = getPath2(getDefaultGraphicsDir(GRAPHICS_SUBDIR), basename);
+  filename = getPath2(getDefaultGraphicsDir(GFX_CLASSIC_SUBDIR), basename);
   if (fileExists(filename))
     return filename;
 
@@ -489,43 +564,115 @@ char *getCustomImageFilename(char *basename)
 char *getCustomSoundFilename(char *basename)
 {
   static char *filename = NULL;
+  boolean skip_setup_artwork = FALSE;
 
   if (filename != NULL)
     free(filename);
 
+  basename = getCorrectedArtworkBasename(basename);
+
   if (!setup.override_level_sounds)
   {
-    /* 1st try: look for special artwork configured in level series config */
-    filename = getPath2(getLevelArtworkDir(TREE_TYPE_SOUNDS_DIR), basename);
+    /* 1st try: look for special artwork in current level series directory */
+    filename = getPath3(getCurrentLevelDir(), SOUNDS_DIRECTORY, basename);
     if (fileExists(filename))
       return filename;
 
     free(filename);
 
-    /* 2nd try: look for special artwork in current level series directory */
-    filename = getPath3(getCurrentLevelDir(), SOUNDS_DIRECTORY, basename);
+    /* check if there is special artwork configured in level series config */
+    if (getLevelArtworkSet(ARTWORK_TYPE_SOUNDS) != NULL)
+    {
+      /* 2nd try: look for special artwork configured in level series config */
+      filename = getPath2(getLevelArtworkDir(TREE_TYPE_SOUNDS_DIR), basename);
+      if (fileExists(filename))
+       return filename;
+
+      free(filename);
+
+      /* take missing artwork configured in level set config from default */
+      skip_setup_artwork = TRUE;
+    }
+  }
+
+  if (!skip_setup_artwork)
+  {
+    /* 3rd try: look for special artwork in configured artwork directory */
+    filename = getPath2(getSetupArtworkDir(artwork.snd_current), basename);
     if (fileExists(filename))
       return filename;
 
     free(filename);
   }
 
-  /* 3rd try: look for special artwork in configured artwork directory */
-  filename = getPath2(getSetupArtworkDir(artwork.snd_current), basename);
+  /* 4th try: look for default artwork in new default artwork directory */
+  filename = getPath2(getDefaultSoundsDir(SND_CLASSIC_SUBDIR), basename);
   if (fileExists(filename))
     return filename;
 
   free(filename);
 
+  /* 5th try: look for default artwork in old default artwork directory */
+  filename = getPath2(options.sounds_directory, basename);
+  if (fileExists(filename))
+    return filename;
+
+  return NULL;         /* cannot find specified artwork file anywhere */
+}
+
+char *getCustomMusicFilename(char *basename)
+{
+  static char *filename = NULL;
+  boolean skip_setup_artwork = FALSE;
+
+  if (filename != NULL)
+    free(filename);
+
+  basename = getCorrectedArtworkBasename(basename);
+
+  if (!setup.override_level_music)
+  {
+    /* 1st try: look for special artwork in current level series directory */
+    filename = getPath3(getCurrentLevelDir(), MUSIC_DIRECTORY, basename);
+    if (fileExists(filename))
+      return filename;
+
+    free(filename);
+
+    /* check if there is special artwork configured in level series config */
+    if (getLevelArtworkSet(ARTWORK_TYPE_MUSIC) != NULL)
+    {
+      /* 2nd try: look for special artwork configured in level series config */
+      filename = getPath2(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR), basename);
+      if (fileExists(filename))
+       return filename;
+
+      free(filename);
+
+      /* take missing artwork configured in level set config from default */
+      skip_setup_artwork = TRUE;
+    }
+  }
+
+  if (!skip_setup_artwork)
+  {
+    /* 3rd try: look for special artwork in configured artwork directory */
+    filename = getPath2(getSetupArtworkDir(artwork.mus_current), basename);
+    if (fileExists(filename))
+      return filename;
+
+    free(filename);
+  }
+
   /* 4th try: look for default artwork in new default artwork directory */
-  filename = getPath2(getDefaultSoundsDir(SOUNDS_SUBDIR), basename);
+  filename = getPath2(getDefaultMusicDir(MUS_CLASSIC_SUBDIR), basename);
   if (fileExists(filename))
     return filename;
 
   free(filename);
 
   /* 5th try: look for default artwork in old default artwork directory */
-  filename = getPath2(options.sounds_directory, basename);
+  filename = getPath2(options.music_directory, basename);
   if (fileExists(filename))
     return filename;
 
@@ -538,6 +685,8 @@ char *getCustomArtworkFilename(char *basename, int type)
     return getCustomImageFilename(basename);
   else if (type == ARTWORK_TYPE_SOUNDS)
     return getCustomSoundFilename(basename);
+  else if (type == ARTWORK_TYPE_MUSIC)
+    return getCustomMusicFilename(basename);
   else
     return UNDEFINED_FILENAME;
 }
@@ -547,39 +696,62 @@ char *getCustomArtworkConfigFilename(int type)
   return getCustomArtworkFilename(ARTWORKINFO_FILENAME(type), type);
 }
 
+char *getCustomArtworkLevelConfigFilename(int type)
+{
+  static char *filename = NULL;
+
+  if (filename != NULL)
+    free(filename);
+
+  filename = getPath2(getLevelArtworkDir(type), ARTWORKINFO_FILENAME(type));
+
+  return filename;
+}
+
 char *getCustomMusicDirectory(void)
 {
   static char *directory = NULL;
+  boolean skip_setup_artwork = FALSE;
 
   if (directory != NULL)
     free(directory);
 
   if (!setup.override_level_music)
   {
-    /* 1st try: look for special artwork configured in level series config */
-    directory = getStringCopy(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR));
+    /* 1st try: look for special artwork in current level series directory */
+    directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY);
     if (fileExists(directory))
       return directory;
 
     free(directory);
 
-    /* 2nd try: look for special artwork in current level series directory */
-    directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY);
+    /* check if there is special artwork configured in level series config */
+    if (getLevelArtworkSet(ARTWORK_TYPE_MUSIC) != NULL)
+    {
+      /* 2nd try: look for special artwork configured in level series config */
+      directory = getStringCopy(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR));
+      if (fileExists(directory))
+       return directory;
+
+      free(directory);
+
+      /* take missing artwork configured in level set config from default */
+      skip_setup_artwork = TRUE;
+    }
+  }
+
+  if (!skip_setup_artwork)
+  {
+    /* 3rd try: look for special artwork in configured artwork directory */
+    directory = getStringCopy(getSetupArtworkDir(artwork.mus_current));
     if (fileExists(directory))
       return directory;
 
     free(directory);
   }
 
-  /* 3rd try: look for special artwork in configured artwork directory */
-  directory = getStringCopy(getSetupArtworkDir(artwork.mus_current));
-  if (fileExists(directory))
-    return directory;
-
-  free(directory);
-
   /* 4th try: look for default artwork in new default artwork directory */
-  directory = getStringCopy(getDefaultMusicDir(MUSIC_SUBDIR));
+  directory = getStringCopy(getDefaultMusicDir(MUS_CLASSIC_SUBDIR));
   if (fileExists(directory))
     return directory;
 
@@ -766,11 +938,16 @@ void dumpTreeInfo(TreeInfo *node, int depth)
 
   while (node)
   {
-    for (i=0; i<(depth + 1) * 3; i++)
+    for (i = 0; i < (depth + 1) * 3; i++)
       printf(" ");
 
+#if 1
+    printf("filename == '%s' ['%s', '%s'] [%d])\n",
+          node->filename, node->fullpath, node->basepath, node->user_defined);
+#else
     printf("filename == '%s' (%s) [%s] (%d)\n",
           node->filename, node->name, node->identifier, node->sort_priority);
+#endif
 
     if (node->node_group != NULL)
       dumpTreeInfo(node->node_group, depth + 1);
@@ -807,7 +984,7 @@ void sortTreeInfo(TreeInfo **node_first,
        compare_function);
 
   /* update the linkage of list elements with the sorted node array */
-  for (i=0; i<num_nodes - 1; i++)
+  for (i = 0; i < num_nodes - 1; i++)
     sort_array[i]->next = sort_array[i + 1];
   sort_array[num_nodes - 1]->next = NULL;
 
@@ -1001,7 +1178,7 @@ int getFileVersionFromCookieString(const char *cookie)
   version_major = ptr_cookie2[0] - '0';
   version_minor = ptr_cookie2[2] - '0';
 
-  return VERSION_IDENT(version_major, version_minor, 0);
+  return VERSION_IDENT(version_major, version_minor, 0, 0);
 }
 
 boolean checkCookieString(const char *cookie, const char *template)
@@ -1031,7 +1208,7 @@ char *getFormattedSetupEntry(char *token, char *value)
 
   /* start with the token and some spaces to format output line */
   sprintf(entry, "%s:", token);
-  for (i=strlen(entry); i<TOKEN_VALUE_POSITION; i++)
+  for (i = strlen(entry); i < TOKEN_VALUE_POSITION; i++)
     strcat(entry, " ");
 
   /* continue with the token's value */
@@ -1077,10 +1254,10 @@ char *getListEntry(SetupFileList *list, char *token)
     return getListEntry(list->next, token);
 }
 
-void setListEntry(SetupFileList *list, char *token, char *value)
+SetupFileList *setListEntry(SetupFileList *list, char *token, char *value)
 {
   if (list == NULL)
-    return;
+    return NULL;
 
   if (strcmp(list->token, token) == 0)
   {
@@ -1088,11 +1265,24 @@ void setListEntry(SetupFileList *list, char *token, char *value)
       free(list->value);
 
     list->value = getStringCopy(value);
+
+    return list;
   }
   else if (list->next == NULL)
-    list->next = newSetupFileList(token, value);
+    return (list->next = newSetupFileList(token, value));
+  else
+    return setListEntry(list->next, token, value);
+}
+
+SetupFileList *addListEntry(SetupFileList *list, char *token, char *value)
+{
+  if (list == NULL)
+    return NULL;
+
+  if (list->next == NULL)
+    return (list->next = newSetupFileList(token, value));
   else
-    setListEntry(list->next, token, value);
+    return addListEntry(list->next, token, value);
 }
 
 #ifdef DEBUG
@@ -1160,6 +1350,9 @@ SetupFileHash *newSetupFileHash()
   SetupFileHash *new_hash =
     create_hashtable(16, 0.75, get_hash_from_key, keys_are_equal);
 
+  if (new_hash == NULL)
+    Error(ERR_EXIT, "create_hashtable() failed -- out of memory");
+
   return new_hash;
 }
 
@@ -1211,15 +1404,16 @@ static void printSetupFileHash(SetupFileHash *hash)
 static void *loadSetupFileData(char *filename, boolean use_hash)
 {
   int line_len;
-  char line[MAX_LINE_LEN];
+  char line[MAX_LINE_LEN], previous_line[MAX_LINE_LEN];
   char *token, *value, *line_ptr;
-  void *setup_file_data;
+  void *setup_file_data, *insert_ptr = NULL;
+  boolean read_continued_line = FALSE;
   FILE *file;
 
   if (use_hash)
     setup_file_data = newSetupFileHash();
   else
-    setup_file_data = newSetupFileList("", "");
+    insert_ptr = setup_file_data = newSetupFileList("", "");
 
   if (!(file = fopen(filename, MODE_READ)))
   {
@@ -1227,16 +1421,48 @@ static void *loadSetupFileData(char *filename, boolean use_hash)
     return NULL;
   }
 
-  while(!feof(file))
+  while (!feof(file))
   {
     /* read next line of input file */
     if (!fgets(line, MAX_LINE_LEN, file))
       break;
 
-    /* cut trailing comment or whitespace from input line */
+    /* cut trailing newline or carriage return */
+    for (line_ptr = &line[strlen(line)]; line_ptr >= line; line_ptr--)
+      if ((*line_ptr == '\n' || *line_ptr == '\r') && *(line_ptr + 1) == '\0')
+       *line_ptr = '\0';
+
+    if (read_continued_line)
+    {
+      /* cut leading whitespaces from input line */
+      for (line_ptr = line; *line_ptr; line_ptr++)
+       if (*line_ptr != ' ' && *line_ptr != '\t')
+         break;
+
+      /* append new line to existing line, if there is enough space */
+      if (strlen(previous_line) + strlen(line_ptr) < MAX_LINE_LEN)
+       strcat(previous_line, line_ptr);
+
+      strcpy(line, previous_line);     /* copy storage buffer to line */
+
+      read_continued_line = FALSE;
+    }
+
+    /* if the last character is '\', continue at next line */
+    if (strlen(line) > 0 && line[strlen(line) - 1] == '\\')
+    {
+      line[strlen(line) - 1] = '\0';   /* cut off trailing backslash */
+      strcpy(previous_line, line);     /* copy line to storage buffer */
+
+      read_continued_line = TRUE;
+
+      continue;
+    }
+
+    /* cut trailing comment from input line */
     for (line_ptr = line; *line_ptr; line_ptr++)
     {
-      if (*line_ptr == '#' || *line_ptr == '\n' || *line_ptr == '\r')
+      if (*line_ptr == '#')
       {
        *line_ptr = '\0';
        break;
@@ -1244,8 +1470,8 @@ static void *loadSetupFileData(char *filename, boolean use_hash)
     }
 
     /* cut trailing whitespaces from input line */
-    for (line_ptr = &line[strlen(line)]; line_ptr > line; line_ptr--)
-      if ((*line_ptr == ' ' || *line_ptr == '\t') && line_ptr[1] == '\0')
+    for (line_ptr = &line[strlen(line)]; line_ptr >= line; line_ptr--)
+      if ((*line_ptr == ' ' || *line_ptr == '\t') && *(line_ptr + 1) == '\0')
        *line_ptr = '\0';
 
     /* ignore empty lines */
@@ -1272,7 +1498,11 @@ static void *loadSetupFileData(char *filename, boolean use_hash)
     if (line_ptr < line + line_len)
       value = line_ptr + 1;
     else
+#if 1
+      value = "true";  /* treat tokens without value as "true" */
+#else
       value = "\0";
+#endif
 
     /* cut leading whitespaces from value */
     for (; *value; value++)
@@ -1284,7 +1514,7 @@ static void *loadSetupFileData(char *filename, boolean use_hash)
       if (use_hash)
        setHashEntry((SetupFileHash *)setup_file_data, token, value);
       else
-       setListEntry((SetupFileList *)setup_file_data, token, value);
+       insert_ptr = addListEntry((SetupFileList *)insert_ptr, token, value);
     }
   }
 
@@ -1351,13 +1581,14 @@ void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash,
 #define LEVELINFO_TOKEN_LEVELS         5
 #define LEVELINFO_TOKEN_FIRST_LEVEL    6
 #define LEVELINFO_TOKEN_SORT_PRIORITY  7
-#define LEVELINFO_TOKEN_LEVEL_GROUP    8
-#define LEVELINFO_TOKEN_READONLY       9
-#define LEVELINFO_TOKEN_GRAPHICS_SET   10
-#define LEVELINFO_TOKEN_SOUNDS_SET     11
-#define LEVELINFO_TOKEN_MUSIC_SET      12
+#define LEVELINFO_TOKEN_LATEST_ENGINE  8
+#define LEVELINFO_TOKEN_LEVEL_GROUP    9
+#define LEVELINFO_TOKEN_READONLY       10
+#define LEVELINFO_TOKEN_GRAPHICS_SET   11
+#define LEVELINFO_TOKEN_SOUNDS_SET     12
+#define LEVELINFO_TOKEN_MUSIC_SET      13
 
-#define NUM_LEVELINFO_TOKENS           13
+#define NUM_LEVELINFO_TOKENS           14
 
 static LevelDirTree ldi;
 
@@ -1372,6 +1603,7 @@ static struct TokenInfo levelinfo_tokens[] =
   { TYPE_INTEGER, &ldi.levels,         "levels"        },
   { TYPE_INTEGER, &ldi.first_level,    "first_level"   },
   { TYPE_INTEGER, &ldi.sort_priority,  "sort_priority" },
+  { TYPE_BOOLEAN, &ldi.latest_engine,  "latest_engine" },
   { TYPE_BOOLEAN, &ldi.level_group,    "level_group"   },
   { TYPE_BOOLEAN, &ldi.readonly,       "readonly"      },
   { TYPE_STRING,  &ldi.graphics_set,   "graphics_set"  },
@@ -1405,6 +1637,7 @@ static void setTreeInfoToDefaults(TreeInfo *ldi, int type)
   ldi->author = getStringCopy(ANONYMOUS_NAME);
 
   ldi->sort_priority = LEVELCLASS_UNDEFINED;   /* default: least priority */
+  ldi->latest_engine = FALSE;                  /* default: get from level */
   ldi->parent_link = FALSE;
   ldi->user_defined = FALSE;
   ldi->color = 0;
@@ -1413,12 +1646,14 @@ static void setTreeInfoToDefaults(TreeInfo *ldi, int type)
   if (ldi->type == TREE_TYPE_LEVEL_DIR)
   {
     ldi->imported_from = NULL;
+
     ldi->graphics_set = NULL;
     ldi->sounds_set = NULL;
     ldi->music_set = NULL;
     ldi->graphics_path = getStringCopy(UNDEFINED_FILENAME);
     ldi->sounds_path = getStringCopy(UNDEFINED_FILENAME);
     ldi->music_path = getStringCopy(UNDEFINED_FILENAME);
+
     ldi->levels = 0;
     ldi->first_level = 0;
     ldi->last_level = 0;
@@ -1434,10 +1669,61 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent)
   {
     Error(ERR_WARN, "setTreeInfoToDefaultsFromParent(): parent == NULL");
 
-    setTreeInfoToDefaults(ldi, TREE_TYPE_GENERIC);
+    setTreeInfoToDefaults(ldi, TREE_TYPE_UNDEFINED);
+
     return;
   }
 
+#if 1
+  /* copy all values from the parent structure */
+
+  ldi->type = parent->type;
+
+  ldi->node_top = parent->node_top;
+  ldi->node_parent = parent;
+  ldi->node_group = NULL;
+  ldi->next = NULL;
+
+  ldi->cl_first = -1;
+  ldi->cl_cursor = -1;
+
+  ldi->filename = NULL;
+  ldi->fullpath = NULL;
+  ldi->basepath = NULL;
+  ldi->identifier = NULL;
+  ldi->name = getStringCopy(ANONYMOUS_NAME);
+  ldi->name_sorting = NULL;
+  ldi->author = getStringCopy(parent->author);
+
+  ldi->sort_priority = parent->sort_priority;
+  ldi->latest_engine = parent->latest_engine;
+  ldi->parent_link = FALSE;
+  ldi->user_defined = parent->user_defined;
+  ldi->color = parent->color;
+  ldi->class_desc = getStringCopy(parent->class_desc);
+
+  if (ldi->type == TREE_TYPE_LEVEL_DIR)
+  {
+    ldi->imported_from = getStringCopy(parent->imported_from);
+
+    ldi->graphics_set = NULL;
+    ldi->sounds_set = NULL;
+    ldi->music_set = NULL;
+    ldi->graphics_path = getStringCopy(UNDEFINED_FILENAME);
+    ldi->sounds_path = getStringCopy(UNDEFINED_FILENAME);
+    ldi->music_path = getStringCopy(UNDEFINED_FILENAME);
+
+    ldi->levels = 0;
+    ldi->first_level = 0;
+    ldi->last_level = 0;
+    ldi->level_group = FALSE;
+    ldi->handicap_level = 0;
+    ldi->readonly = TRUE;
+  }
+
+
+#else
+
   /* first copy all values from the parent structure ... */
   *ldi = *parent;
 
@@ -1455,7 +1741,16 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent)
   ldi->name = getStringCopy(ANONYMOUS_NAME);
   ldi->name_sorting = NULL;
   ldi->author = getStringCopy(parent->author);
+
   ldi->imported_from = getStringCopy(parent->imported_from);
+  ldi->class_desc = getStringCopy(parent->class_desc);
+
+  ldi->graphics_set = NULL;
+  ldi->sounds_set = NULL;
+  ldi->music_set = NULL;
+  ldi->graphics_path = NULL;
+  ldi->sounds_path = NULL;
+  ldi->music_path = NULL;
 
   ldi->level_group = FALSE;
   ldi->parent_link = FALSE;
@@ -1464,6 +1759,47 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent)
   ldi->node_parent = parent;
   ldi->node_group = NULL;
   ldi->next = NULL;
+
+#endif
+}
+
+static void freeTreeInfo(TreeInfo *ldi)
+{
+  if (ldi->filename)
+    free(ldi->filename);
+  if (ldi->fullpath)
+    free(ldi->fullpath);
+  if (ldi->basepath)
+    free(ldi->basepath);
+  if (ldi->identifier)
+    free(ldi->identifier);
+
+  if (ldi->name)
+    free(ldi->name);
+  if (ldi->name_sorting)
+    free(ldi->name_sorting);
+  if (ldi->author)
+    free(ldi->author);
+
+  if (ldi->class_desc)
+    free(ldi->class_desc);
+
+  if (ldi->type == TREE_TYPE_LEVEL_DIR)
+  {
+    if (ldi->graphics_set)
+      free(ldi->graphics_set);
+    if (ldi->sounds_set)
+      free(ldi->sounds_set);
+    if (ldi->music_set)
+      free(ldi->music_set);
+
+    if (ldi->graphics_path)
+      free(ldi->graphics_path);
+    if (ldi->sounds_path)
+      free(ldi->sounds_path);
+    if (ldi->music_path)
+      free(ldi->music_path);
+  }
 }
 
 void setSetupInfo(struct TokenInfo *token_info,
@@ -1557,6 +1893,19 @@ static void createParentTreeInfoNode(TreeInfo *node_parent)
   ti_new->node_parent = node_parent;
   ti_new->parent_link = TRUE;
 
+#if 1
+  setString(&ti_new->identifier, node_parent->identifier);
+  setString(&ti_new->name, ".. (parent directory)");
+  setString(&ti_new->name_sorting, ti_new->name);
+
+  setString(&ti_new->filename, "..");
+  setString(&ti_new->fullpath, node_parent->fullpath);
+
+  ti_new->sort_priority = node_parent->sort_priority;
+  ti_new->latest_engine = node_parent->latest_engine;
+
+  setString(&ti_new->class_desc, getLevelClassDescription(ti_new));
+#else
   ti_new->identifier = getStringCopy(node_parent->identifier);
   ti_new->name = ".. (parent directory)";
   ti_new->name_sorting = getStringCopy(ti_new->name);
@@ -1565,7 +1914,10 @@ static void createParentTreeInfoNode(TreeInfo *node_parent)
   ti_new->fullpath = getStringCopy(node_parent->fullpath);
 
   ti_new->sort_priority = node_parent->sort_priority;
+  ti_new->latest_engine = node_parent->latest_engine;
+
   ti_new->class_desc = getLevelClassDescription(ti_new);
+#endif
 
   pushTreeInfo(&node_parent->node_group, ti_new);
 }
@@ -1607,16 +1959,21 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
 
   /* set all structure fields according to the token/value pairs */
   ldi = *leveldir_new;
-  for (i=0; i<NUM_LEVELINFO_TOKENS; i++)
+  for (i = 0; i < NUM_LEVELINFO_TOKENS; i++)
     setSetupInfo(levelinfo_tokens, i,
                 getHashEntry(setup_file_hash, levelinfo_tokens[i].text));
   *leveldir_new = ldi;
 
+#if 1
+  if (strcmp(leveldir_new->name, ANONYMOUS_NAME) == 0)
+    setString(&leveldir_new->name, leveldir_new->filename);
+#else
   if (strcmp(leveldir_new->name, ANONYMOUS_NAME) == 0)
   {
     free(leveldir_new->name);
     leveldir_new->name = getStringCopy(leveldir_new->filename);
   }
+#endif
 
   DrawInitText(leveldir_new->name, 150, FC_YELLOW);
 
@@ -1628,12 +1985,12 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
 
   if (node_parent == NULL)             /* top level group */
   {
-    leveldir_new->basepath = level_directory;
-    leveldir_new->fullpath = leveldir_new->filename;
+    leveldir_new->basepath = getStringCopy(level_directory);
+    leveldir_new->fullpath = getStringCopy(leveldir_new->filename);
   }
   else                                 /* sub level group */
   {
-    leveldir_new->basepath = node_parent->basepath;
+    leveldir_new->basepath = getStringCopy(node_parent->basepath);
     leveldir_new->fullpath = getPath2(node_parent->fullpath, directory_name);
   }
 
@@ -1643,11 +2000,20 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
   leveldir_new->last_level =
     leveldir_new->first_level + leveldir_new->levels - 1;
 
+#if 1
+  leveldir_new->user_defined =
+    (strcmp(leveldir_new->basepath, options.level_directory) != 0);
+#else
   leveldir_new->user_defined =
     (leveldir_new->basepath == options.level_directory ? FALSE : TRUE);
+#endif
 
   leveldir_new->color = LEVELCOLOR(leveldir_new);
+#if 1
+  setString(&leveldir_new->class_desc, getLevelClassDescription(leveldir_new));
+#else
   leveldir_new->class_desc = getLevelClassDescription(leveldir_new);
+#endif
 
   leveldir_new->handicap_level =       /* set handicap to default value */
     (leveldir_new->user_defined ?
@@ -1823,16 +2189,21 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
 
     /* set all structure fields according to the token/value pairs */
     ldi = *artwork_new;
-    for (i=0; i<NUM_LEVELINFO_TOKENS; i++)
+    for (i = 0; i < NUM_LEVELINFO_TOKENS; i++)
       setSetupInfo(levelinfo_tokens, i,
                   getHashEntry(setup_file_hash, levelinfo_tokens[i].text));
     *artwork_new = ldi;
 
+#if 1
+    if (strcmp(artwork_new->name, ANONYMOUS_NAME) == 0)
+      setString(&artwork_new->name, artwork_new->filename);
+#else
     if (strcmp(artwork_new->name, ANONYMOUS_NAME) == 0)
     {
       free(artwork_new->name);
       artwork_new->name = getStringCopy(artwork_new->filename);
     }
+#endif
 
 #if 0
     DrawInitText(artwork_new->name, 150, FC_YELLOW);
@@ -1856,42 +2227,86 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
     artwork_new->fullpath = getPath2(node_parent->fullpath, directory_name);
   }
 
+#if 1
+  artwork_new->user_defined =
+    (strcmp(artwork_new->basepath, OPTIONS_ARTWORK_DIRECTORY(type)) != 0);
+#else
   artwork_new->user_defined =
     (artwork_new->basepath == OPTIONS_ARTWORK_DIRECTORY(type) ? FALSE : TRUE);
+#endif
 
   /* (may use ".sort_priority" from "setup_file_hash" above) */
   artwork_new->color = ARTWORKCOLOR(artwork_new);
+#if 1
+  setString(&artwork_new->class_desc, getLevelClassDescription(artwork_new));
+#else
   artwork_new->class_desc = getLevelClassDescription(artwork_new);
+#endif
 
   if (setup_file_hash == NULL) /* (after determining ".user_defined") */
   {
+#if 0
     if (artwork_new->name != NULL)
+    {
       free(artwork_new->name);
+      artwork_new->name = NULL;
+    }
+#endif
+
+#if 0
+    if (artwork_new->identifier != NULL)
+    {
+      free(artwork_new->identifier);
+      artwork_new->identifier = NULL;
+    }
+#endif
 
     if (strcmp(artwork_new->filename, ".") == 0)
     {
       if (artwork_new->user_defined)
       {
+#if 1
+       setString(&artwork_new->identifier, "private");
+#else
        artwork_new->identifier = getStringCopy("private");
-       artwork_new->sort_priority = ARTWORKCLASS_USER;
+#endif
+       artwork_new->sort_priority = ARTWORKCLASS_PRIVATE;
       }
       else
       {
+#if 1
+       setString(&artwork_new->identifier, "classic");
+#else
        artwork_new->identifier = getStringCopy("classic");
+#endif
        artwork_new->sort_priority = ARTWORKCLASS_CLASSICS;
       }
 
       /* set to new values after changing ".sort_priority" */
       artwork_new->color = ARTWORKCOLOR(artwork_new);
+#if 1
+      setString(&artwork_new->class_desc,
+               getLevelClassDescription(artwork_new));
+#else
       artwork_new->class_desc = getLevelClassDescription(artwork_new);
+#endif
     }
     else
     {
+#if 1
+      setString(&artwork_new->identifier, artwork_new->filename);
+#else
       artwork_new->identifier = getStringCopy(artwork_new->filename);
+#endif
     }
 
+#if 1
+    setString(&artwork_new->name, artwork_new->identifier);
+    setString(&artwork_new->name_sorting, artwork_new->name);
+#else
     artwork_new->name = getStringCopy(artwork_new->identifier);
     artwork_new->name_sorting = getStringCopy(artwork_new->name);
+#endif
   }
 
   DrawInitText(artwork_new->name, 150, FC_YELLOW);
@@ -1969,6 +2384,15 @@ static TreeInfo *getDummyArtworkInfo(int type)
 
   setTreeInfoToDefaults(artwork_new, type);
 
+#if 1
+  setString(&artwork_new->filename, UNDEFINED_FILENAME);
+  setString(&artwork_new->fullpath, UNDEFINED_FILENAME);
+  setString(&artwork_new->basepath, UNDEFINED_FILENAME);
+
+  setString(&artwork_new->identifier,   UNDEFINED_FILENAME);
+  setString(&artwork_new->name,         UNDEFINED_FILENAME);
+  setString(&artwork_new->name_sorting, UNDEFINED_FILENAME);
+#else
   artwork_new->filename = getStringCopy(UNDEFINED_FILENAME);
   artwork_new->fullpath = getStringCopy(UNDEFINED_FILENAME);
   artwork_new->basepath = getStringCopy(UNDEFINED_FILENAME);
@@ -1979,6 +2403,7 @@ static TreeInfo *getDummyArtworkInfo(int type)
   artwork_new->identifier   = getStringCopy(UNDEFINED_FILENAME);
   artwork_new->name         = getStringCopy(UNDEFINED_FILENAME);
   artwork_new->name_sorting = getStringCopy(UNDEFINED_FILENAME);
+#endif
 
   return artwork_new;
 }
@@ -2018,16 +2443,25 @@ void LoadArtworkInfo()
   /* before sorting, the first entries will be from the user directory */
   artwork.gfx_current =
     getTreeInfoFromIdentifier(artwork.gfx_first, setup.graphics_set);
+  if (artwork.gfx_current == NULL)
+    artwork.gfx_current =
+      getTreeInfoFromIdentifier(artwork.gfx_first, GFX_CLASSIC_SUBDIR);
   if (artwork.gfx_current == NULL)
     artwork.gfx_current = getFirstValidTreeInfoEntry(artwork.gfx_first);
 
   artwork.snd_current =
     getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set);
+  if (artwork.snd_current == NULL)
+    artwork.snd_current =
+      getTreeInfoFromIdentifier(artwork.snd_first, SND_CLASSIC_SUBDIR);
   if (artwork.snd_current == NULL)
     artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first);
 
   artwork.mus_current =
     getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set);
+  if (artwork.mus_current == NULL)
+    artwork.mus_current =
+      getTreeInfoFromIdentifier(artwork.mus_first, MUS_CLASSIC_SUBDIR);
   if (artwork.mus_current == NULL)
     artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first);
 
@@ -2108,10 +2542,14 @@ void LoadLevelArtworkInfo()
   LoadArtworkInfoFromLevelInfo(&artwork.mus_first, leveldir_first);
 
   /* needed for reloading level artwork not known at ealier stage */
+
   if (strcmp(artwork.gfx_current_identifier, setup.graphics_set) != 0)
   {
     artwork.gfx_current =
       getTreeInfoFromIdentifier(artwork.gfx_first, setup.graphics_set);
+    if (artwork.gfx_current == NULL)
+      artwork.gfx_current =
+       getTreeInfoFromIdentifier(artwork.gfx_first, GFX_CLASSIC_SUBDIR);
     if (artwork.gfx_current == NULL)
       artwork.gfx_current = getFirstValidTreeInfoEntry(artwork.gfx_first);
   }
@@ -2120,6 +2558,9 @@ void LoadLevelArtworkInfo()
   {
     artwork.snd_current =
       getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set);
+    if (artwork.snd_current == NULL)
+      artwork.snd_current =
+       getTreeInfoFromIdentifier(artwork.snd_first, SND_CLASSIC_SUBDIR);
     if (artwork.snd_current == NULL)
       artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first);
   }
@@ -2128,6 +2569,9 @@ void LoadLevelArtworkInfo()
   {
     artwork.mus_current =
       getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set);
+    if (artwork.mus_current == NULL)
+      artwork.mus_current =
+       getTreeInfoFromIdentifier(artwork.mus_first, MUS_CLASSIC_SUBDIR);
     if (artwork.mus_current == NULL)
       artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first);
   }
@@ -2145,6 +2589,7 @@ void LoadLevelArtworkInfo()
 
 static void SaveUserLevelInfo()
 {
+  LevelDirTree *level_info;
   char *filename;
   FILE *file;
   int i;
@@ -2158,32 +2603,49 @@ static void SaveUserLevelInfo()
     return;
   }
 
-  /* always start with reliable default values */
-  setTreeInfoToDefaults(&ldi, TREE_TYPE_LEVEL_DIR);
+  level_info = newTreeInfo();
 
+  /* always start with reliable default values */
+  setTreeInfoToDefaults(level_info, TREE_TYPE_LEVEL_DIR);
+
+#if 1
+  setString(&level_info->name, getLoginName());
+  setString(&level_info->author, getRealName());
+  level_info->levels = 100;
+  level_info->first_level = 1;
+  level_info->sort_priority = LEVELCLASS_PRIVATE_START;
+  level_info->readonly = FALSE;
+  setString(&level_info->graphics_set, GFX_CLASSIC_SUBDIR);
+  setString(&level_info->sounds_set,   SND_CLASSIC_SUBDIR);
+  setString(&level_info->music_set,    MUS_CLASSIC_SUBDIR);
+#else
   ldi.name = getStringCopy(getLoginName());
   ldi.author = getStringCopy(getRealName());
   ldi.levels = 100;
   ldi.first_level = 1;
-  ldi.sort_priority = LEVELCLASS_USER_START;
+  ldi.sort_priority = LEVELCLASS_PRIVATE_START;
   ldi.readonly = FALSE;
-  ldi.graphics_set = getStringCopy(GRAPHICS_SUBDIR);
-  ldi.sounds_set = getStringCopy(SOUNDS_SUBDIR);
-  ldi.music_set = getStringCopy(MUSIC_SUBDIR);
+  ldi.graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR);
+  ldi.sounds_set = getStringCopy(SND_CLASSIC_SUBDIR);
+  ldi.music_set = getStringCopy(MUS_CLASSIC_SUBDIR);
+#endif
 
   fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
                                                 getCookie("LEVELINFO")));
 
-  for (i=0; i<NUM_LEVELINFO_TOKENS; i++)
+  ldi = *level_info;
+  for (i = 0; i < NUM_LEVELINFO_TOKENS; i++)
     if (i != LEVELINFO_TOKEN_IDENTIFIER &&
        i != LEVELINFO_TOKEN_NAME_SORTING &&
        i != LEVELINFO_TOKEN_IMPORTED_FROM)
       fprintf(file, "%s\n", getSetupLine(levelinfo_tokens, "", i));
 
   fclose(file);
-  free(filename);
 
   SetFilePermissions(filename, PERMS_PRIVATE);
+
+  freeTreeInfo(level_info);
+  free(filename);
 }
 
 char *getSetupValue(int type, void *value)
@@ -2258,7 +2720,7 @@ char *getSetupLine(struct TokenInfo *token_info, char *prefix, int token_nr)
     {
       /* add at least one whitespace */
       strcat(line, " ");
-      for (i=strlen(line); i<TOKEN_COMMENT_POSITION; i++)
+      for (i = strlen(line); i < TOKEN_COMMENT_POSITION; i++)
        strcat(line, " ");
 
       strcat(line, "# ");
@@ -2271,17 +2733,15 @@ char *getSetupLine(struct TokenInfo *token_info, char *prefix, int token_nr)
 
 void LoadLevelSetup_LastSeries()
 {
-  char *filename;
-  SetupFileHash *level_setup_hash = NULL;
-
-  /* always start with reliable default values */
-  leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
-
   /* ----------------------------------------------------------------------- */
   /* ~/.<program>/levelsetup.conf                                            */
   /* ----------------------------------------------------------------------- */
 
-  filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
+  char *filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
+  SetupFileHash *level_setup_hash = NULL;
+
+  /* always start with reliable default values */
+  leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
 
   if ((level_setup_hash = loadSetupFileHash(filename)))
   {
@@ -2305,17 +2765,15 @@ void LoadLevelSetup_LastSeries()
 
 void SaveLevelSetup_LastSeries()
 {
-  char *filename;
-  char *level_subdir = leveldir_current->filename;
-  FILE *file;
-
   /* ----------------------------------------------------------------------- */
   /* ~/.<program>/levelsetup.conf                                            */
   /* ----------------------------------------------------------------------- */
 
-  InitUserDataDirectory();
+  char *filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
+  char *level_subdir = leveldir_current->filename;
+  FILE *file;
 
-  filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
+  InitUserDataDirectory();
 
   if (!(file = fopen(filename, MODE_WRITE)))
   {
@@ -2330,9 +2788,10 @@ void SaveLevelSetup_LastSeries()
                                               level_subdir));
 
   fclose(file);
-  free(filename);
 
   SetFilePermissions(filename, PERMS_PRIVATE);
+
+  free(filename);
 }
 
 static void checkSeriesInfo()
@@ -2479,7 +2938,8 @@ void SaveLevelSetup_SeriesInfo()
                                               handicap_level_str));
 
   fclose(file);
-  free(filename);
 
   SetFilePermissions(filename, PERMS_PRIVATE);
+
+  free(filename);
 }