rnd-20020803-1-src
[rocksndiamonds.git] / src / files.c
index 7683103022d5eab1ce410a2badb9a76e174692d7..58cc705c9c1c6f227ca7df73e3ad9065d5cda033 100644 (file)
@@ -1,7 +1,7 @@
 /***********************************************************
 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-* (c) 1995-2001 Artsoft Entertainment                      *
+* (c) 1995-2002 Artsoft Entertainment                      *
 *               Holger Schemel                             *
 *               Detmolder Strasse 189                      *
 *               33604 Bielefeld                            *
@@ -30,7 +30,7 @@
 #define LEVEL_CHUNK_CNT2_SIZE  160     /* size of level CNT2 chunk   */
 #define LEVEL_CHUNK_CNT2_UNUSED        11      /* unused CNT2 chunk bytes    */
 #define TAPE_HEADER_SIZE       20      /* size of tape file header   */
-#define TAPE_HEADER_UNUSED     7       /* unused tape header bytes   */
+#define TAPE_HEADER_UNUSED     3       /* unused tape header bytes   */
 
 /* file identifier strings */
 #define LEVEL_COOKIE_TMPL      "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x"
@@ -140,7 +140,8 @@ static int checkLevelElement(int element)
 
 static int LoadLevel_VERS(FILE *file, int chunk_size, struct LevelInfo *level)
 {
-  ReadChunk_VERS(file, &(level->file_version), &(level->game_version));
+  level->file_version = getFileVersion(file);
+  level->game_version = getFileVersion(file);
 
   return chunk_size;
 }
@@ -444,6 +445,10 @@ void LoadLevel(int level_nr)
       /* player was faster than monsters in (pre-)1.0 levels */
       level.double_speed = TRUE;
     }
+
+    /* Default behaviour for EM style gems was "slippery" only in 2.0.1 */
+    if (level.game_version == VERSION_IDENT(2,0,1))
+      level.em_slippery_gems = TRUE;
   }
   else
   {
@@ -471,6 +476,12 @@ void LoadLevel(int level_nr)
   SetBorderElement();
 }
 
+static void SaveLevel_VERS(FILE *file, struct LevelInfo *level)
+{
+  putFileVersion(file, level->file_version);
+  putFileVersion(file, level->game_version);
+}
+
 static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level)
 {
   int i, x, y;
@@ -610,6 +621,8 @@ void SaveLevel(int level_nr)
     return;
   }
 
+  level.file_version = FILE_VERSION_ACTUAL;
+  level.game_version = GAME_VERSION_ACTUAL;
 
   /* check level field for 16-bit elements */
   level.encoding_16bit_field = FALSE;
@@ -638,7 +651,7 @@ void SaveLevel(int level_nr)
   putFileChunkBE(file, "CAVE", CHUNK_SIZE_NONE);
 
   putFileChunkBE(file, "VERS", FILE_VERS_CHUNK_SIZE);
-  WriteChunk_VERS(file, FILE_VERSION_ACTUAL, GAME_VERSION_ACTUAL);
+  SaveLevel_VERS(file, &level);
 
   putFileChunkBE(file, "HEAD", LEVEL_HEADER_SIZE);
   SaveLevel_HEAD(file, &level);
@@ -677,8 +690,6 @@ static void setTapeInfoToDefaults()
   int i;
 
   /* always start with reliable default values (empty tape) */
-  tape.file_version = FILE_VERSION_ACTUAL;
-  tape.game_version = GAME_VERSION_ACTUAL;
   TapeErase();
 
   /* default values (also for pre-1.2 tapes) with only the first player */
@@ -700,7 +711,8 @@ static void setTapeInfoToDefaults()
 
 static int LoadTape_VERS(FILE *file, int chunk_size, struct TapeInfo *tape)
 {
-  ReadChunk_VERS(file, &(tape->file_version), &(tape->game_version));
+  tape->file_version = getFileVersion(file);
+  tape->game_version = getFileVersion(file);
 
   return chunk_size;
 }
@@ -717,8 +729,7 @@ static int LoadTape_HEAD(FILE *file, int chunk_size, struct TapeInfo *tape)
   if (tape->file_version >= FILE_VERSION_1_2)
   {
     byte store_participating_players = fgetc(file);
-
-    ReadUnusedBytesFromFile(file, TAPE_HEADER_UNUSED);
+    int engine_version;
 
     /* since version 1.2, tapes store which players participate in the tape */
     tape->num_participating_players = 0;
@@ -732,6 +743,12 @@ static int LoadTape_HEAD(FILE *file, int chunk_size, struct TapeInfo *tape)
        tape->num_participating_players++;
       }
     }
+
+    ReadUnusedBytesFromFile(file, TAPE_HEADER_UNUSED);
+
+    engine_version = getFileVersion(file);
+    if (engine_version > 0)
+      tape->engine_version = engine_version;
   }
 
   return chunk_size;
@@ -939,6 +956,12 @@ void LoadTape(int level_nr)
   tape.length_seconds = GetTapeLength();
 }
 
+static void SaveTape_VERS(FILE *file, struct TapeInfo *tape)
+{
+  putFileVersion(file, tape->file_version);
+  putFileVersion(file, tape->game_version);
+}
+
 static void SaveTape_HEAD(FILE *file, struct TapeInfo *tape)
 {
   int i;
@@ -955,7 +978,10 @@ static void SaveTape_HEAD(FILE *file, struct TapeInfo *tape)
 
   fputc(store_participating_players, file);
 
+  /* unused bytes not at the end here for 4-byte alignment of engine_version */
   WriteUnusedBytesToFile(file, TAPE_HEADER_UNUSED);
+
+  putFileVersion(file, tape->engine_version);
 }
 
 static void SaveTape_BODY(FILE *file, struct TapeInfo *tape)
@@ -997,6 +1023,9 @@ void SaveTape(int level_nr)
     return;
   }
 
+  tape.file_version = FILE_VERSION_ACTUAL;
+  tape.game_version = GAME_VERSION_ACTUAL;
+
   /* count number of participating players  */
   for(i=0; i<MAX_PLAYERS; i++)
     if (tape.player_participates[i])
@@ -1008,7 +1037,7 @@ void SaveTape(int level_nr)
   putFileChunkBE(file, "TAPE", CHUNK_SIZE_NONE);
 
   putFileChunkBE(file, "VERS", FILE_VERS_CHUNK_SIZE);
-  WriteChunk_VERS(file, FILE_VERSION_ACTUAL, GAME_VERSION_ACTUAL);
+  SaveTape_VERS(file, &tape);
 
   putFileChunkBE(file, "HEAD", TAPE_HEADER_SIZE);
   SaveTape_HEAD(file, &tape);
@@ -1038,7 +1067,7 @@ void DumpTape(struct TapeInfo *tape)
 
   printf("\n");
   printf("-------------------------------------------------------------------------------\n");
-  printf("Tape of Level %d (file version %06d, game version %06d\n",
+  printf("Tape of Level %d (file version %06d, game version %06d)\n",
         tape->level_nr, tape->file_version, tape->game_version);
   printf("-------------------------------------------------------------------------------\n");
 
@@ -1157,57 +1186,60 @@ void SaveScore(int level_nr)
 /* setup file functions                                                      */
 /* ========================================================================= */
 
-#define TOKEN_STR_PLAYER_PREFIX                "player_"
+#define TOKEN_STR_PLAYER_PREFIX                        "player_"
 
 /* global setup */
-#define SETUP_TOKEN_PLAYER_NAME                0
-#define SETUP_TOKEN_SOUND              1
-#define SETUP_TOKEN_SOUND_LOOPS                2
-#define SETUP_TOKEN_SOUND_MUSIC                3
-#define SETUP_TOKEN_SOUND_SIMPLE       4
-#define SETUP_TOKEN_TOONS              5
-#define SETUP_TOKEN_SCROLL_DELAY       6
-#define SETUP_TOKEN_SOFT_SCROLLING     7
-#define SETUP_TOKEN_FADING             8
-#define SETUP_TOKEN_AUTORECORD         9
-#define SETUP_TOKEN_QUICK_DOORS                10
-#define SETUP_TOKEN_TEAM_MODE          11
-#define SETUP_TOKEN_HANDICAP           12
-#define SETUP_TOKEN_TIME_LIMIT         13
-#define SETUP_TOKEN_FULLSCREEN         14
-#define SETUP_TOKEN_ASK_ON_ESCAPE      15
-#define SETUP_TOKEN_GRAPHICS_SET       16
-#define SETUP_TOKEN_SOUNDS_SET         17
-#define SETUP_TOKEN_MUSIC_SET          18
-
-#define NUM_GLOBAL_SETUP_TOKENS                19
+#define SETUP_TOKEN_PLAYER_NAME                        0
+#define SETUP_TOKEN_SOUND                      1
+#define SETUP_TOKEN_SOUND_LOOPS                        2
+#define SETUP_TOKEN_SOUND_MUSIC                        3
+#define SETUP_TOKEN_SOUND_SIMPLE               4
+#define SETUP_TOKEN_TOONS                      5
+#define SETUP_TOKEN_SCROLL_DELAY               6
+#define SETUP_TOKEN_SOFT_SCROLLING             7
+#define SETUP_TOKEN_FADING                     8
+#define SETUP_TOKEN_AUTORECORD                 9
+#define SETUP_TOKEN_QUICK_DOORS                        10
+#define SETUP_TOKEN_TEAM_MODE                  11
+#define SETUP_TOKEN_HANDICAP                   12
+#define SETUP_TOKEN_TIME_LIMIT                 13
+#define SETUP_TOKEN_FULLSCREEN                 14
+#define SETUP_TOKEN_ASK_ON_ESCAPE              15
+#define SETUP_TOKEN_GRAPHICS_SET               16
+#define SETUP_TOKEN_SOUNDS_SET                 17
+#define SETUP_TOKEN_MUSIC_SET                  18
+#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS    19
+#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS      20
+#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC       21
+
+#define NUM_GLOBAL_SETUP_TOKENS                        22
 
 /* shortcut setup */
-#define SETUP_TOKEN_SAVE_GAME          0
-#define SETUP_TOKEN_LOAD_GAME          1
-#define SETUP_TOKEN_TOGGLE_PAUSE       2
+#define SETUP_TOKEN_SAVE_GAME                  0
+#define SETUP_TOKEN_LOAD_GAME                  1
+#define SETUP_TOKEN_TOGGLE_PAUSE               2
 
-#define NUM_SHORTCUT_SETUP_TOKENS      3
+#define NUM_SHORTCUT_SETUP_TOKENS              3
 
 /* player setup */
-#define SETUP_TOKEN_USE_JOYSTICK       0
-#define SETUP_TOKEN_JOY_DEVICE_NAME    1
-#define SETUP_TOKEN_JOY_XLEFT          2
-#define SETUP_TOKEN_JOY_XMIDDLE                3
-#define SETUP_TOKEN_JOY_XRIGHT         4
-#define SETUP_TOKEN_JOY_YUPPER         5
-#define SETUP_TOKEN_JOY_YMIDDLE                6
-#define SETUP_TOKEN_JOY_YLOWER         7
-#define SETUP_TOKEN_JOY_SNAP           8
-#define SETUP_TOKEN_JOY_BOMB           9
-#define SETUP_TOKEN_KEY_LEFT           10
-#define SETUP_TOKEN_KEY_RIGHT          11
-#define SETUP_TOKEN_KEY_UP             12
-#define SETUP_TOKEN_KEY_DOWN           13
-#define SETUP_TOKEN_KEY_SNAP           14
-#define SETUP_TOKEN_KEY_BOMB           15
-
-#define NUM_PLAYER_SETUP_TOKENS                16
+#define SETUP_TOKEN_USE_JOYSTICK               0
+#define SETUP_TOKEN_JOY_DEVICE_NAME            1
+#define SETUP_TOKEN_JOY_XLEFT                  2
+#define SETUP_TOKEN_JOY_XMIDDLE                        3
+#define SETUP_TOKEN_JOY_XRIGHT                 4
+#define SETUP_TOKEN_JOY_YUPPER                 5
+#define SETUP_TOKEN_JOY_YMIDDLE                        6
+#define SETUP_TOKEN_JOY_YLOWER                 7
+#define SETUP_TOKEN_JOY_SNAP                   8
+#define SETUP_TOKEN_JOY_BOMB                   9
+#define SETUP_TOKEN_KEY_LEFT                   10
+#define SETUP_TOKEN_KEY_RIGHT                  11
+#define SETUP_TOKEN_KEY_UP                     12
+#define SETUP_TOKEN_KEY_DOWN                   13
+#define SETUP_TOKEN_KEY_SNAP                   14
+#define SETUP_TOKEN_KEY_BOMB                   15
+
+#define NUM_PLAYER_SETUP_TOKENS                        16
 
 static struct SetupInfo si;
 static struct SetupShortcutInfo ssi;
@@ -1235,14 +1267,17 @@ static struct TokenInfo global_setup_tokens[] =
   { TYPE_STRING, &si.graphics_set,     "graphics_set"                  },
   { TYPE_STRING, &si.sounds_set,       "sounds_set"                    },
   { TYPE_STRING, &si.music_set,                "music_set"                     },
+  { TYPE_SWITCH, &si.override_level_graphics, "override_level_graphics"        },
+  { TYPE_SWITCH, &si.override_level_sounds,   "override_level_sounds"  },
+  { TYPE_SWITCH, &si.override_level_music,    "override_level_music"   },
 };
 
 static struct TokenInfo shortcut_setup_tokens[] =
 {
   /* shortcut setup */
-  { TYPE_KEY_X11, &ssi.save_game,              "shortcut.save_game"    },
-  { TYPE_KEY_X11, &ssi.load_game,              "shortcut.load_game"    },
-  { TYPE_KEY_X11, &ssi.toggle_pause,           "shortcut.toggle_pause" }
+  { TYPE_KEY_X11, &ssi.save_game,      "shortcut.save_game"            },
+  { TYPE_KEY_X11, &ssi.load_game,      "shortcut.load_game"            },
+  { TYPE_KEY_X11, &ssi.toggle_pause,   "shortcut.toggle_pause"         }
 };
 
 static struct TokenInfo player_setup_tokens[] =
@@ -1293,6 +1328,9 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->graphics_set = getStringCopy(GRAPHICS_SUBDIR);
   si->sounds_set = getStringCopy(SOUNDS_SUBDIR);
   si->music_set = getStringCopy(MUSIC_SUBDIR);
+  si->override_level_graphics = FALSE;
+  si->override_level_sounds = FALSE;
+  si->override_level_music = FALSE;
 
   si->shortcut.save_game = DEFAULT_KEY_SAVE_GAME;
   si->shortcut.load_game = DEFAULT_KEY_LOAD_GAME;