added program config file support for run-time special edition support
[rocksndiamonds.git] / src / files.c
index bfa9f8160f1d6f9f88630477d8e7ca4209ed4148..62bab2023a81ae4acb279af213678824a6d0dec6 100644 (file)
@@ -1608,18 +1608,21 @@ static void setLevelInfoToDefaults_Level(struct LevelInfo *level)
   level->encoding_16bit_yamyam = TRUE;
   level->encoding_16bit_amoeba = TRUE;
 
-  for (x = 0; x < MAX_LEV_FIELDX; x++)
-    for (y = 0; y < MAX_LEV_FIELDY; y++)
-      level->field[x][y] = EL_SAND;
-
+  /* clear level name and level author string buffers */
   for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
     level->name[i] = '\0';
   for (i = 0; i < MAX_LEVEL_AUTHOR_LEN; i++)
     level->author[i] = '\0';
 
+  /* set level name and level author to default values */
   strcpy(level->name, NAMELESS_LEVEL_NAME);
   strcpy(level->author, ANONYMOUS_NAME);
 
+  /* set level playfield to playable default level with player and exit */
+  for (x = 0; x < MAX_LEV_FIELDX; x++)
+    for (y = 0; y < MAX_LEV_FIELDY; y++)
+      level->field[x][y] = EL_SAND;
+
   level->field[0][0] = EL_PLAYER_1;
   level->field[STD_LEV_FIELDX - 1][STD_LEV_FIELDY - 1] = EL_EXIT_CLOSED;
 
@@ -6218,6 +6221,12 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename)
       level->field[x][y] = getMappedElementByVersion(level->field[x][y],
                                                     level->game_version);
 
+  /* clear unused playfield data (nicer if level gets resized in editor) */
+  for (x = 0; x < MAX_LEV_FIELDX; x++)
+    for (y = 0; y < MAX_LEV_FIELDY; y++)
+      if (x >= level->fieldx || y >= level->fieldy)
+       level->field[x][y] = EL_EMPTY;
+
   /* copy elements to runtime playfield array */
   for (x = 0; x < MAX_LEV_FIELDX; x++)
     for (y = 0; y < MAX_LEV_FIELDY; y++)
@@ -7883,41 +7892,42 @@ void SaveScore(int nr)
 #define SETUP_TOKEN_TOONS                      5
 #define SETUP_TOKEN_SCROLL_DELAY               6
 #define SETUP_TOKEN_SCROLL_DELAY_VALUE         7
-#define SETUP_TOKEN_SOFT_SCROLLING             8
-#define SETUP_TOKEN_FADE_SCREENS               9
-#define SETUP_TOKEN_AUTORECORD                 10
-#define SETUP_TOKEN_SHOW_TITLESCREEN           11
-#define SETUP_TOKEN_QUICK_DOORS                        12
-#define SETUP_TOKEN_TEAM_MODE                  13
-#define SETUP_TOKEN_HANDICAP                   14
-#define SETUP_TOKEN_SKIP_LEVELS                        15
-#define SETUP_TOKEN_TIME_LIMIT                 16
-#define SETUP_TOKEN_FULLSCREEN                 17
-#define SETUP_TOKEN_FULLSCREEN_MODE            18
-#define SETUP_TOKEN_WINDOW_SCALING_PERCENT     19
-#define SETUP_TOKEN_WINDOW_SCALING_QUALITY     20
-#define SETUP_TOKEN_ASK_ON_ESCAPE              21
-#define SETUP_TOKEN_ASK_ON_ESCAPE_EDITOR       22
-#define SETUP_TOKEN_QUICK_SWITCH               23
-#define SETUP_TOKEN_INPUT_ON_FOCUS             24
-#define SETUP_TOKEN_PREFER_AGA_GRAPHICS                25
-#define SETUP_TOKEN_GAME_FRAME_DELAY           26
-#define SETUP_TOKEN_SP_SHOW_BORDER_ELEMENTS    27
-#define SETUP_TOKEN_SMALL_GAME_GRAPHICS                28
-#define SETUP_TOKEN_GRAPHICS_SET               29
-#define SETUP_TOKEN_SOUNDS_SET                 30
-#define SETUP_TOKEN_MUSIC_SET                  31
-#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS    32
-#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS      33
-#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC       34
-#define SETUP_TOKEN_VOLUME_SIMPLE              35
-#define SETUP_TOKEN_VOLUME_LOOPS               36
-#define SETUP_TOKEN_VOLUME_MUSIC               37
-#define SETUP_TOKEN_TOUCH_CONTROL_TYPE         38
-#define SETUP_TOKEN_TOUCH_MOVE_DISTANCE                39
-#define SETUP_TOKEN_TOUCH_DROP_DISTANCE                40
-
-#define NUM_GLOBAL_SETUP_TOKENS                        41
+#define SETUP_TOKEN_ENGINE_SNAPSHOT_MODE       8
+#define SETUP_TOKEN_SOFT_SCROLLING             9
+#define SETUP_TOKEN_FADE_SCREENS               10
+#define SETUP_TOKEN_AUTORECORD                 11
+#define SETUP_TOKEN_SHOW_TITLESCREEN           12
+#define SETUP_TOKEN_QUICK_DOORS                        13
+#define SETUP_TOKEN_TEAM_MODE                  14
+#define SETUP_TOKEN_HANDICAP                   15
+#define SETUP_TOKEN_SKIP_LEVELS                        16
+#define SETUP_TOKEN_TIME_LIMIT                 17
+#define SETUP_TOKEN_FULLSCREEN                 18
+#define SETUP_TOKEN_FULLSCREEN_MODE            19
+#define SETUP_TOKEN_WINDOW_SCALING_PERCENT     20
+#define SETUP_TOKEN_WINDOW_SCALING_QUALITY     21
+#define SETUP_TOKEN_ASK_ON_ESCAPE              22
+#define SETUP_TOKEN_ASK_ON_ESCAPE_EDITOR       23
+#define SETUP_TOKEN_QUICK_SWITCH               24
+#define SETUP_TOKEN_INPUT_ON_FOCUS             25
+#define SETUP_TOKEN_PREFER_AGA_GRAPHICS                26
+#define SETUP_TOKEN_GAME_FRAME_DELAY           27
+#define SETUP_TOKEN_SP_SHOW_BORDER_ELEMENTS    28
+#define SETUP_TOKEN_SMALL_GAME_GRAPHICS                29
+#define SETUP_TOKEN_GRAPHICS_SET               30
+#define SETUP_TOKEN_SOUNDS_SET                 31
+#define SETUP_TOKEN_MUSIC_SET                  32
+#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS    33
+#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS      34
+#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC       35
+#define SETUP_TOKEN_VOLUME_SIMPLE              36
+#define SETUP_TOKEN_VOLUME_LOOPS               37
+#define SETUP_TOKEN_VOLUME_MUSIC               38
+#define SETUP_TOKEN_TOUCH_CONTROL_TYPE         39
+#define SETUP_TOKEN_TOUCH_MOVE_DISTANCE                40
+#define SETUP_TOKEN_TOUCH_DROP_DISTANCE                41
+
+#define NUM_GLOBAL_SETUP_TOKENS                        42
 
 /* editor setup */
 #define SETUP_TOKEN_EDITOR_EL_BOULDERDASH      0
@@ -8011,6 +8021,24 @@ void SaveScore(int nr)
 
 #define NUM_SYSTEM_SETUP_TOKENS                        3
 
+/* internal setup */
+#define SETUP_TOKEN_INT_PROGRAM_TITLE          0
+#define SETUP_TOKEN_INT_PROGRAM_AUTHOR         1
+#define SETUP_TOKEN_INT_PROGRAM_EMAIL          2
+#define SETUP_TOKEN_INT_PROGRAM_WEBSITE                3
+#define SETUP_TOKEN_INT_PROGRAM_COPYRIGHT      4
+#define SETUP_TOKEN_INT_PROGRAM_COMPANY                5
+#define SETUP_TOKEN_INT_DEFAULT_GRAPHICS_SET   6
+#define SETUP_TOKEN_INT_DEFAULT_SOUNDS_SET     7
+#define SETUP_TOKEN_INT_DEFAULT_MUSIC_SET      8
+#define SETUP_TOKEN_INT_FALLBACK_GRAPHICS_FILE 9
+#define SETUP_TOKEN_INT_FALLBACK_SOUNDS_FILE   10
+#define SETUP_TOKEN_INT_FALLBACK_MUSIC_FILE    11
+#define SETUP_TOKEN_INT_DEFAULT_LEVEL_SERIES   12
+#define SETUP_TOKEN_INT_CHOOSE_FROM_TOP_LEVELDIR 13
+
+#define NUM_INTERNAL_SETUP_TOKENS              14
+
 /* options setup */
 #define SETUP_TOKEN_OPTIONS_VERBOSE            0
 
@@ -8023,6 +8051,7 @@ static struct SetupEditorCascadeInfo seci;
 static struct SetupShortcutInfo ssi;
 static struct SetupInputInfo sii;
 static struct SetupSystemInfo syi;
+static struct SetupInternalInfo sxi;
 static struct OptionInfo soi;
 
 static struct TokenInfo global_setup_tokens[] =
@@ -8035,6 +8064,7 @@ static struct TokenInfo global_setup_tokens[] =
   { TYPE_SWITCH, &si.toons,                   "toons"                  },
   { TYPE_SWITCH, &si.scroll_delay,            "scroll_delay"           },
   { TYPE_INTEGER,&si.scroll_delay_value,      "scroll_delay_value"     },
+  { TYPE_STRING, &si.engine_snapshot_mode,    "engine_snapshot_mode"   },
   { TYPE_SWITCH, &si.soft_scrolling,          "soft_scrolling"         },
   { TYPE_SWITCH, &si.fade_screens,            "fade_screens"           },
   { TYPE_SWITCH, &si.autorecord,              "automatic_tape_recording"},
@@ -8157,11 +8187,29 @@ static struct TokenInfo player_setup_tokens[] =
 
 static struct TokenInfo system_setup_tokens[] =
 {
-  { TYPE_STRING,  &syi.sdl_videodriver,        "system.sdl_videodriver"        },
-  { TYPE_STRING,  &syi.sdl_audiodriver,        "system.sdl_audiodriver"        },
+  { TYPE_STRING,  &syi.sdl_videodriver,    "system.sdl_videodriver"    },
+  { TYPE_STRING,  &syi.sdl_audiodriver,           "system.sdl_audiodriver"     },
   { TYPE_INTEGER, &syi.audio_fragment_size,"system.audio_fragment_size"        },
 };
 
+static struct TokenInfo internal_setup_tokens[] =
+{
+  { TYPE_STRING, &sxi.program_title,           "program_title"         },
+  { TYPE_STRING, &sxi.program_author,          "program_author"        },
+  { TYPE_STRING, &sxi.program_email,           "program_email"         },
+  { TYPE_STRING, &sxi.program_website,         "program_website"       },
+  { TYPE_STRING, &sxi.program_copyright,       "program_copyright"     },
+  { TYPE_STRING, &sxi.program_company,         "program_company"       },
+  { TYPE_STRING, &sxi.default_graphics_set,    "default_graphics_set"  },
+  { TYPE_STRING, &sxi.default_sounds_set,      "default_sounds_set"    },
+  { TYPE_STRING, &sxi.default_music_set,       "default_music_set"     },
+  { TYPE_STRING, &sxi.fallback_graphics_file,  "fallback_graphics_file"},
+  { TYPE_STRING, &sxi.fallback_sounds_file,    "fallback_sounds_file"  },
+  { TYPE_STRING, &sxi.fallback_music_file,     "fallback_music_file"   },
+  { TYPE_STRING, &sxi.default_level_series,    "default_level_series"  },
+  { TYPE_STRING, &sxi.choose_from_top_leveldir,        "choose_from_top_leveldir" },
+};
+
 static struct TokenInfo options_setup_tokens[] =
 {
   { TYPE_BOOLEAN, &soi.verbose,                "options.verbose"               },
@@ -8195,6 +8243,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->toons = TRUE;
   si->scroll_delay = TRUE;
   si->scroll_delay_value = STD_SCROLL_DELAY;
+  si->engine_snapshot_mode = getStringCopy(STR_SNAPSHOT_MODE_DEFAULT);
   si->soft_scrolling = TRUE;
   si->fade_screens = TRUE;
   si->autorecord = TRUE;
@@ -8217,9 +8266,10 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->sp_show_border_elements = FALSE;
   si->small_game_graphics = FALSE;
 
-  si->graphics_set = getStringCopy(GFX_DEFAULT_SUBDIR);
-  si->sounds_set = getStringCopy(SND_DEFAULT_SUBDIR);
-  si->music_set = getStringCopy(MUS_DEFAULT_SUBDIR);
+  si->graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR);
+  si->sounds_set   = getStringCopy(SND_CLASSIC_SUBDIR);
+  si->music_set    = getStringCopy(MUS_CLASSIC_SUBDIR);
+
   si->override_level_graphics = FALSE;
   si->override_level_sounds = FALSE;
   si->override_level_music = FALSE;
@@ -8300,16 +8350,25 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->system.sdl_audiodriver = getStringCopy(ARG_DEFAULT);
   si->system.audio_fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
 
-  si->options.verbose = FALSE;
+  si->internal.program_title     = getStringCopy(PROGRAM_TITLE_STRING);
+  si->internal.program_author    = getStringCopy(PROGRAM_AUTHOR_STRING);
+  si->internal.program_email     = getStringCopy(PROGRAM_EMAIL_STRING);
+  si->internal.program_website   = getStringCopy(PROGRAM_WEBSITE_STRING);
+  si->internal.program_copyright = getStringCopy(PROGRAM_COPYRIGHT_STRING);
+  si->internal.program_company   = getStringCopy(PROGRAM_COMPANY_STRING);
 
-#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
-  si->toons = FALSE;
-  si->handicap = FALSE;
-  si->fullscreen = TRUE;
-  si->override_level_graphics = AUTO;
-  si->override_level_sounds = AUTO;
-  si->override_level_music = AUTO;
-#endif
+  si->internal.default_graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR);
+  si->internal.default_sounds_set   = getStringCopy(SND_CLASSIC_SUBDIR);
+  si->internal.default_music_set    = getStringCopy(MUS_CLASSIC_SUBDIR);
+
+  si->internal.fallback_graphics_file = getStringCopy(UNDEFINED_FILENAME);
+  si->internal.fallback_sounds_file   = getStringCopy(UNDEFINED_FILENAME);
+  si->internal.fallback_music_file    = getStringCopy(UNDEFINED_FILENAME);
+
+  si->internal.default_level_series = getStringCopy(UNDEFINED_LEVELSET);
+  si->internal.choose_from_top_leveldir = FALSE;
+
+  si->options.verbose = FALSE;
 
 #if defined(PLATFORM_ANDROID)
   si->fullscreen = TRUE;
@@ -8390,6 +8449,13 @@ static void decodeSetupFileHash(SetupFileHash *setup_file_hash)
                 getHashEntry(setup_file_hash, system_setup_tokens[i].text));
   setup.system = syi;
 
+  /* internal setup */
+  sxi = setup.internal;
+  for (i = 0; i < NUM_INTERNAL_SETUP_TOKENS; i++)
+    setSetupInfo(internal_setup_tokens, i,
+                getHashEntry(setup_file_hash, internal_setup_tokens[i].text));
+  setup.internal = sxi;
+
   /* options setup */
   soi = setup.options;
   for (i = 0; i < NUM_OPTIONS_SETUP_TOKENS; i++)
@@ -8414,43 +8480,62 @@ static void decodeSetupFileHash_EditorCascade(SetupFileHash *setup_file_hash)
   setup.editor_cascade = seci;
 }
 
-void LoadSetup()
+void LoadSetupFromFilename(char *filename)
 {
-  char *filename = getSetupFilename();
-  SetupFileHash *setup_file_hash = NULL;
-
-  /* always start with reliable default values */
-  setSetupInfoToDefaults(&setup);
-
-  setup_file_hash = loadSetupFileHash(filename);
+  SetupFileHash *setup_file_hash = loadSetupFileHash(filename);
 
   if (setup_file_hash)
   {
-    char *player_name_new;
-
-    checkSetupFileHashIdentifier(setup_file_hash, filename,getCookie("SETUP"));
     decodeSetupFileHash(setup_file_hash);
 
     freeSetupFileHash(setup_file_hash);
+  }
+  else
+  {
+    Error(ERR_WARN, "using default setup values");
+  }
+}
 
-    /* needed to work around problems with fixed length strings */
-    player_name_new = get_corrected_login_name(setup.player_name);
-    free(setup.player_name);
-    setup.player_name = player_name_new;
+static void LoadSetup_SpecialPostProcessing()
+{
+  char *player_name_new;
 
-    /* "scroll_delay: on(3) / off(0)" was replaced by scroll delay value */
-    if (setup.scroll_delay == FALSE)
-    {
-      setup.scroll_delay_value = MIN_SCROLL_DELAY;
-      setup.scroll_delay = TRUE;                       /* now always "on" */
-    }
+  /* needed to work around problems with fixed length strings */
+  player_name_new = get_corrected_login_name(setup.player_name);
+  free(setup.player_name);
+  setup.player_name = player_name_new;
 
-    /* make sure that scroll delay value stays inside valid range */
-    setup.scroll_delay_value =
-      MIN(MAX(MIN_SCROLL_DELAY, setup.scroll_delay_value), MAX_SCROLL_DELAY);
+  /* "scroll_delay: on(3) / off(0)" was replaced by scroll delay value */
+  if (setup.scroll_delay == FALSE)
+  {
+    setup.scroll_delay_value = MIN_SCROLL_DELAY;
+    setup.scroll_delay = TRUE;                 /* now always "on" */
   }
-  else
-    Error(ERR_WARN, "using default setup values");
+
+  /* make sure that scroll delay value stays inside valid range */
+  setup.scroll_delay_value =
+    MIN(MAX(MIN_SCROLL_DELAY, setup.scroll_delay_value), MAX_SCROLL_DELAY);
+}
+
+void LoadSetup()
+{
+  char *filename;
+
+  /* always start with reliable default values */
+  setSetupInfoToDefaults(&setup);
+
+  /* try to load setup values from default setup file */
+  filename = getDefaultSetupFilename();
+
+  if (fileExists(filename))
+    LoadSetupFromFilename(filename);
+
+  /* try to load setup values from user setup file */
+  filename = getSetupFilename();
+
+  LoadSetupFromFilename(filename);
+
+  LoadSetup_SpecialPostProcessing();
 }
 
 void LoadSetup_EditorCascade()
@@ -8465,7 +8550,6 @@ void LoadSetup_EditorCascade()
 
   if (setup_file_hash)
   {
-    checkSetupFileHashIdentifier(setup_file_hash, filename,getCookie("SETUP"));
     decodeSetupFileHash_EditorCascade(setup_file_hash);
 
     freeSetupFileHash(setup_file_hash);
@@ -8488,9 +8572,7 @@ void SaveSetup()
     return;
   }
 
-  fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
-                                              getCookie("SETUP")));
-  fprintf(file, "\n");
+  fprintFileHeader(file, SETUP_FILENAME);
 
   /* global setup */
   si = setup;
@@ -8537,6 +8619,9 @@ void SaveSetup()
   for (i = 0; i < NUM_SYSTEM_SETUP_TOKENS; i++)
     fprintf(file, "%s\n", getSetupLine(system_setup_tokens, "", i));
 
+  /* internal setup */
+  /* (internal setup values not saved to user setup file) */
+
   /* options setup */
   soi = setup.options;
   fprintf(file, "\n");
@@ -8563,12 +8648,9 @@ void SaveSetup_EditorCascade()
     return;
   }
 
-  fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
-                                              getCookie("SETUP")));
-  fprintf(file, "\n");
+  fprintFileHeader(file, EDITORCASCADE_FILENAME);
 
   seci = setup.editor_cascade;
-  fprintf(file, "\n");
   for (i = 0; i < NUM_EDITOR_CASCADE_SETUP_TOKENS; i++)
     fprintf(file, "%s\n", getSetupLine(editor_cascade_setup_tokens, "", i));
 
@@ -9763,24 +9845,27 @@ void CreateLevelSketchImages()
 /* create and save images for custom and group elements (raw BMP format)     */
 /* ------------------------------------------------------------------------- */
 
-void CreateCustomElementImages()
+void CreateCustomElementImages(char *directory)
 {
 #if defined(TARGET_SDL)
-  char *filename = "graphics.classic/RocksCE.bmp";
-  Bitmap *bitmap;
+  char *src_basename = "RocksCE-template.ilbm";
+  char *dst_basename = "RocksCE.bmp";
+  char *src_filename = getPath2(directory, src_basename);
+  char *dst_filename = getPath2(directory, dst_basename);
   Bitmap *src_bitmap;
-  int dummy_graphic = IMG_CUSTOM_99;
+  Bitmap *bitmap;
   int yoffset_ce = 0;
   int yoffset_ge = (TILEY * NUM_CUSTOM_ELEMENTS / 16);
-  int src_x, src_y;
   int i;
 
+  SDLInitVideoDisplay();
+
+  src_bitmap = LoadImage(src_filename);
+
   bitmap = CreateBitmap(TILEX * 16 * 2,
                        TILEY * (NUM_CUSTOM_ELEMENTS + NUM_GROUP_ELEMENTS) / 16,
                        DEFAULT_DEPTH);
 
-  getFixedGraphicSource(dummy_graphic, 0, &src_bitmap, &src_x, &src_y);
-
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
   {
     int x = i % 16;
@@ -9846,8 +9931,8 @@ void CreateCustomElementImages()
     }
   }
 
-  if (SDL_SaveBMP(bitmap->surface, filename) != 0)
-    Error(ERR_EXIT, "cannot save CE graphics file '%s'", filename);
+  if (SDL_SaveBMP(bitmap->surface, dst_filename) != 0)
+    Error(ERR_EXIT, "cannot save CE graphics file '%s'", dst_filename);
 
   FreeBitmap(bitmap);