added optional button to restart game (door, panel and touch variants)
[rocksndiamonds.git] / src / libgame / setup.c
index ee7733fcd5216b97df49d184b9a0b1e87d2b8892..b419875a580e8fd1f87eab476ec4b496f232db7c 100644 (file)
@@ -1326,7 +1326,9 @@ static char *getCustomMusicDirectoryExt(boolean check_music)
     {
       // 2nd try: look for special artwork configured in level series config
       directory = getStringCopy(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR));
-      if (directoryExists_CheckMusic(directory, check_music))
+
+      // directory also valid if no unconfigured music found (no game music)
+      if (directoryExists_CheckMusic(directory, FALSE))
        return directory;
 
       free(directory);
@@ -1340,7 +1342,9 @@ static char *getCustomMusicDirectoryExt(boolean check_music)
   {
     // 3rd try: look for special artwork in configured artwork directory
     directory = getStringCopy(getSetupArtworkDir(artwork.mus_current));
-    if (directoryExists_CheckMusic(directory, check_music))
+
+    // directory also valid if no unconfigured music found (no game music)
+    if (directoryExists_CheckMusic(directory, FALSE))
       return directory;
 
     free(directory);
@@ -1705,30 +1709,56 @@ static void cloneTree(TreeInfo **ti_new, TreeInfo *ti, boolean skip_empty_sets)
   *ti_new = ti_cloned;
 }
 
-static boolean adjustTreeGraphicsForEMC(TreeInfo *node)
+static boolean adjustTreeArtworkForEMC(char **artwork_set_1,
+                                      char **artwork_set_2,
+                                      char **artwork_set, boolean prefer_2)
 {
-  boolean settings_changed = FALSE;
+  // do nothing if neither special artwork set 1 nor 2 are defined
+  if (!*artwork_set_1 && !*artwork_set_2)
+    return FALSE;
 
-  while (node)
+  boolean want_1 = (prefer_2 == FALSE);
+  boolean want_2 = (prefer_2 == TRUE);
+  boolean has_only_1 = (!*artwork_set && !*artwork_set_2);
+  boolean has_only_2 = (!*artwork_set && !*artwork_set_1);
+  char *artwork_set_new = NULL;
+
+  // replace missing special artwork 1 or 2 with (optional) standard artwork
+
+  if (!*artwork_set_1)
+    setString(artwork_set_1, *artwork_set);
+
+  if (!*artwork_set_2)
+    setString(artwork_set_2, *artwork_set);
+
+  // set standard artwork to either special artwork 1 or 2, as requested
+
+  if (*artwork_set_1 && (want_1 || has_only_1))
+    artwork_set_new = *artwork_set_1;
+
+  if (*artwork_set_2 && (want_2 || has_only_2))
+    artwork_set_new = *artwork_set_2;
+
+  if (artwork_set_new && !strEqual(*artwork_set, artwork_set_new))
   {
-    boolean want_ecs = (setup.prefer_aga_graphics == FALSE);
-    boolean want_aga = (setup.prefer_aga_graphics == TRUE);
-    boolean has_only_ecs = (!node->graphics_set && !node->graphics_set_aga);
-    boolean has_only_aga = (!node->graphics_set && !node->graphics_set_ecs);
-    char *graphics_set = NULL;
+    setString(artwork_set, artwork_set_new);
 
-    if (node->graphics_set_ecs && (want_ecs || has_only_ecs))
-      graphics_set = node->graphics_set_ecs;
+    return TRUE;
+  }
 
-    if (node->graphics_set_aga && (want_aga || has_only_aga))
-      graphics_set = node->graphics_set_aga;
+  return FALSE;
+}
 
-    if (graphics_set && !strEqual(node->graphics_set, graphics_set))
-    {
-      setString(&node->graphics_set, graphics_set);
-      settings_changed = TRUE;
-    }
+static boolean adjustTreeGraphicsForEMC(TreeInfo *node)
+{
+  boolean settings_changed = FALSE;
 
+  while (node)
+  {
+    settings_changed |= adjustTreeArtworkForEMC(&node->graphics_set_ecs,
+                                               &node->graphics_set_aga,
+                                               &node->graphics_set,
+                                               setup.prefer_aga_graphics);
     if (node->node_group != NULL)
       settings_changed |= adjustTreeGraphicsForEMC(node->node_group);
 
@@ -1744,24 +1774,10 @@ static boolean adjustTreeSoundsForEMC(TreeInfo *node)
 
   while (node)
   {
-    boolean want_default = (setup.prefer_lowpass_sounds == FALSE);
-    boolean want_lowpass = (setup.prefer_lowpass_sounds == TRUE);
-    boolean has_only_default = (!node->sounds_set && !node->sounds_set_lowpass);
-    boolean has_only_lowpass = (!node->sounds_set && !node->sounds_set_default);
-    char *sounds_set = NULL;
-
-    if (node->sounds_set_default && (want_default || has_only_default))
-      sounds_set = node->sounds_set_default;
-
-    if (node->sounds_set_lowpass && (want_lowpass || has_only_lowpass))
-      sounds_set = node->sounds_set_lowpass;
-
-    if (sounds_set && !strEqual(node->sounds_set, sounds_set))
-    {
-      setString(&node->sounds_set, sounds_set);
-      settings_changed = TRUE;
-    }
-
+    settings_changed |= adjustTreeArtworkForEMC(&node->sounds_set_default,
+                                               &node->sounds_set_lowpass,
+                                               &node->sounds_set,
+                                               setup.prefer_lowpass_sounds);
     if (node->node_group != NULL)
       settings_changed |= adjustTreeSoundsForEMC(node->node_group);
 
@@ -2765,6 +2781,7 @@ SetupFileHash *loadSetupFileHash(char *filename)
 // ============================================================================
 
 #define TOKEN_STR_LAST_LEVEL_SERIES            "last_level_series"
+#define TOKEN_STR_LAST_PLAYED_MENU_USED                "last_played_menu_used"
 #define TOKEN_STR_LAST_PLAYED_LEVEL            "last_played_level"
 #define TOKEN_STR_HANDICAP_LEVEL               "handicap_level"
 #define TOKEN_STR_LAST_USER                    "last_user"
@@ -4577,6 +4594,12 @@ static boolean AddTreeSetToTreeInfoExt(TreeInfo *tree_node_old, char *tree_dir,
   TreeInfo *tree_node_new = getTreeInfoFromIdentifier(*tree_node_first,
                                                      tree_subdir_new);
 
+  // if not found, check if added node is level group or artwork group
+  if (tree_node_new == NULL)
+    tree_node_new = getTreeInfoFromIdentifierExt(*tree_node_first,
+                                                tree_subdir_new,
+                                                TREE_NODE_TYPE_GROUP);
+
   if (tree_node_new == NULL)           // should not happen
     return FALSE;
 
@@ -5006,33 +5029,51 @@ static void UpdateLastPlayedLevels_List(void)
   setString(&last_level_series[0], leveldir_current->identifier);
 }
 
-static TreeInfo *StoreOrRestoreLastPlayedLevels(TreeInfo *node, boolean store)
+#define LAST_PLAYED_MODE_SET                   1
+#define LAST_PLAYED_MODE_SET_FORCED            2
+#define LAST_PLAYED_MODE_GET                   3
+
+static TreeInfo *StoreOrRestoreLastPlayedLevels(TreeInfo *node, int mode)
 {
   static char *identifier = NULL;
 
-  if (store)
+  if (mode == LAST_PLAYED_MODE_SET)
   {
     setString(&identifier, (node && node->is_copy ? node->identifier : NULL));
-
-    return NULL;       // not used
   }
-  else
+  else if (mode == LAST_PLAYED_MODE_SET_FORCED)
+  {
+    setString(&identifier, (node ? node->identifier : NULL));
+  }
+  else if (mode == LAST_PLAYED_MODE_GET)
   {
     TreeInfo *node_new = getTreeInfoFromIdentifierExt(leveldir_first,
                                                      identifier,
                                                      TREE_NODE_TYPE_COPY);
     return (node_new != NULL ? node_new : node);
   }
+
+  return NULL;         // not used
 }
 
 void StoreLastPlayedLevels(TreeInfo *node)
 {
-  StoreOrRestoreLastPlayedLevels(node, TRUE);
+  StoreOrRestoreLastPlayedLevels(node, LAST_PLAYED_MODE_SET);
+}
+
+void ForcedStoreLastPlayedLevels(TreeInfo *node)
+{
+  StoreOrRestoreLastPlayedLevels(node, LAST_PLAYED_MODE_SET_FORCED);
 }
 
 void RestoreLastPlayedLevels(TreeInfo **node)
 {
-  *node = StoreOrRestoreLastPlayedLevels(*node, FALSE);
+  *node = StoreOrRestoreLastPlayedLevels(*node, LAST_PLAYED_MODE_GET);
+}
+
+boolean CheckLastPlayedLevels(void)
+{
+  return (StoreOrRestoreLastPlayedLevels(NULL, LAST_PLAYED_MODE_GET) != NULL);
 }
 
 void LoadLevelSetup_LastSeries(void)
@@ -5070,6 +5111,13 @@ void LoadLevelSetup_LastSeries(void)
     if (leveldir_current == NULL)
       leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
 
+    char *last_played_menu_used =
+      getHashEntry(level_setup_hash, TOKEN_STR_LAST_PLAYED_MENU_USED);
+
+    // store if last level set was selected from "last played" menu
+    if (strEqual(last_played_menu_used, "true"))
+      ForcedStoreLastPlayedLevels(leveldir_current);
+
     for (i = 0; i < MAX_LEVELDIR_HISTORY; i++)
     {
       char token[strlen(TOKEN_STR_LAST_LEVEL_SERIES) + 10];
@@ -5132,7 +5180,14 @@ static void SaveLevelSetup_LastSeries_Ext(boolean deactivate_last_level_series)
     fprintf(file, "# %s\n# ", "the following level set may have caused a problem and was deactivated");
 
   fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_LAST_LEVEL_SERIES,
-                                              leveldir_current->identifier));
+                                                leveldir_current->identifier));
+
+  // store if last level set was selected from "last played" menu
+  boolean last_played_menu_used = CheckLastPlayedLevels();
+  char *setup_value = getSetupValue(TYPE_BOOLEAN, &last_played_menu_used);
+
+  fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_LAST_PLAYED_MENU_USED,
+                                                setup_value));
 
   for (i = 0; last_level_series[i] != NULL; i++)
   {