rnd-20020313-1-src
authorHolger Schemel <info@artsoft.org>
Wed, 13 Mar 2002 00:43:10 +0000 (01:43 +0100)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:36:03 +0000 (10:36 +0200)
src/files.c
src/libgame/misc.c
src/libgame/misc.h
src/main.h

index d78ec4f16b1df20e4e3a9e6bdb5806ac6459e75e..95df54bcf79e365e65c2214678b302f978027d66 100644 (file)
@@ -37,7 +37,7 @@
 #endif
 
 /* file identifier strings */
-#define LEVEL_COOKIE           "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.4"
+#define LEVEL_COOKIE           "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_2.0"
 #define SCORE_COOKIE           "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2"
 #define TAPE_COOKIE            "ROCKSNDIAMONDS_TAPE_FILE_VERSION_1.2"
 #define SETUP_COOKIE           "ROCKSNDIAMONDS_SETUP_FILE_VERSION_1.2"
@@ -46,6 +46,7 @@
 /* old file identifiers for backward compatibility */
 #define LEVEL_COOKIE_10                "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.0"
 #define LEVEL_COOKIE_12                "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.2"
+#define LEVEL_COOKIE_14                "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.4"
 #define TAPE_COOKIE_10         "ROCKSNDIAMONDS_LEVELREC_FILE_VERSION_1.0"
 
 /* file names and filename extensions */
@@ -214,9 +215,9 @@ static int getFileVersionFromCookieString(const char *cookie)
   if (strncmp(ptr_cookie1, pattern1, len_pattern1) != 0)
     return -1;
 
-  if (ptr_cookie2[0] <= '0' || ptr_cookie2[0] >= '9' ||
+  if (ptr_cookie2[0] < '0' || ptr_cookie2[0] > '9' ||
       ptr_cookie2[1] != '.' ||
-      ptr_cookie2[2] <= '0' || ptr_cookie2[2] >= '9')
+      ptr_cookie2[2] < '0' || ptr_cookie2[2] > '9')
     return -1;
 
   version_major = ptr_cookie2[0] - '0';
@@ -412,6 +413,8 @@ static void setLevelInfoToDefaults()
   level.file_version = FILE_VERSION_ACTUAL;
   level.game_version = GAME_VERSION_ACTUAL;
 
+  level.encoding_16bit = FALSE;                /* default: only 8-bit elements */
+
   lev_fieldx = level.fieldx = STD_LEV_FIELDX;
   lev_fieldy = level.fieldy = STD_LEV_FIELDY;
 
@@ -495,7 +498,7 @@ static int checkLevelElement(int element)
   return element;
 }
 
-void LoadLevel(int level_nr)
+void OLD_LoadLevel(int level_nr)
 {
   int i, x, y;
   char *filename = getLevelFilename(level_nr);
@@ -642,7 +645,7 @@ void LoadLevel(int level_nr)
     }
 
     /* next check body chunk identifier and chunk length */
-    if (strcmp(chunk, "BODY") || chunk_length != lev_fieldx * lev_fieldy)
+    if (strcmp(chunk, "BODY") != 0 || chunk_length != lev_fieldx * lev_fieldy)
     {
       Error(ERR_WARN, "wrong 'BODY' chunk of level file '%s'", filename);
       fclose(file);
@@ -691,11 +694,223 @@ void LoadLevel(int level_nr)
   SetBorderElement();
 }
 
+static void LoadLevel_HEAD(struct LevelInfo *level, FILE *file)
+{
+  int i, x, y;
+
+  lev_fieldx = level->fieldx = fgetc(file);
+  lev_fieldy = level->fieldy = fgetc(file);
+
+  level->time          = getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN);
+  level->gems_needed   = getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN);
+
+  for(i=0; i<MAX_LEVEL_NAME_LEN; i++)
+    level->name[i] = fgetc(file);
+  level->name[MAX_LEVEL_NAME_LEN] = 0;
+
+  for(i=0; i<LEVEL_SCORE_ELEMENTS; i++)
+    level->score[i] = fgetc(file);
+
+  level->num_yam_contents = STD_ELEMENT_CONTENTS;
+  for(i=0; i<MAX_ELEMENT_CONTENTS; i++)
+  {
+    for(y=0; y<3; y++)
+    {
+      for(x=0; x<3; x++)
+      {
+       if (i < STD_ELEMENT_CONTENTS)
+         level->yam_content[i][x][y] = checkLevelElement(fgetc(file));
+       else
+         level->yam_content[i][x][y] = EL_LEERRAUM;
+      }
+    }
+  }
+
+  level->amoeba_speed          = fgetc(file);
+  level->time_magic_wall       = fgetc(file);
+  level->time_wheel            = fgetc(file);
+  level->amoeba_content                = checkLevelElement(fgetc(file));
+  level->double_speed          = (fgetc(file) == 1 ? TRUE : FALSE);
+  level->gravity               = (fgetc(file) == 1 ? TRUE : FALSE);
+
+  level->encoding_16bit                = (fgetc(file) == 1 ? TRUE : FALSE);
+
+  for(i=0; i<LEVEL_HEADER_UNUSED; i++) /* skip unused header bytes */
+    fgetc(file);
+}
+
+static void LoadLevel_AUTH(struct LevelInfo *level, FILE *file)
+{
+  int i;
+
+  for(i=0; i<MAX_LEVEL_AUTHOR_LEN; i++)
+    level->author[i] = fgetc(file);
+  level->author[MAX_LEVEL_NAME_LEN] = 0;
+}
+
+static void LoadLevel_CONT(struct LevelInfo *level, FILE *file)
+{
+  int i, x, y;
+
+  fgetc(file);
+  level->num_yam_contents = fgetc(file);
+  fgetc(file);
+  fgetc(file);
+
+  if (level->num_yam_contents < 1 ||
+      level->num_yam_contents > MAX_ELEMENT_CONTENTS)
+  {
+#if DEBUG
+    printf("WARNING: num_yam_contents == %d (corrected)\n",
+          level->num_yam_contents);
+#endif
+    level->num_yam_contents = STD_ELEMENT_CONTENTS;
+  }
+
+  for(i=0; i<MAX_ELEMENT_CONTENTS; i++)
+    for(y=0; y<3; y++)
+      for(x=0; x<3; x++)
+       level->yam_content[i][x][y] =
+         checkLevelElement(level->encoding_16bit ?
+                           getFile16BitInteger(file,
+                                               BYTE_ORDER_BIG_ENDIAN) :
+                           fgetc(file));
+}
+
+static void LoadLevel_BODY(struct LevelInfo *level, FILE *file)
+{
+  int x, y;
+
+  /* now read in the valid level fields from level file */
+  for(y=0; y<lev_fieldy; y++)
+    for(x=0; x<lev_fieldx; x++)
+      Feld[x][y] = Ur[x][y] =
+       checkLevelElement(level->encoding_16bit ?
+                         getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN) :
+                         fgetc(file));
+}
+
+void LoadLevel(int level_nr)
+{
+  char *filename = getLevelFilename(level_nr);
+  char cookie[MAX_LINE_LEN];
+  char chunk[CHUNK_ID_LEN + 1];
+  int chunk_length;
+  FILE *file;
+
+  /* always start with reliable default values */
+  setLevelInfoToDefaults();
+
+  if (!(file = fopen(filename, MODE_READ)))
+  {
+    Error(ERR_WARN, "cannot read level '%s' - creating new level", filename);
+    return;
+  }
+
+  /* check file identifier */
+  fgets(cookie, MAX_LINE_LEN, file);
+  if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
+    cookie[strlen(cookie) - 1] = '\0';
+
+  if (!checkCookieString(cookie, LEVEL_COOKIE))        /* unknown file format */
+  {
+    Error(ERR_WARN, "unknown format of level file '%s'", filename);
+    fclose(file);
+    return;
+  }
+
+  if ((level.file_version = getFileVersionFromCookieString(cookie)) == -1)
+  {
+    Error(ERR_WARN, "unsupported version of level file '%s'", filename);
+    fclose(file);
+    return;
+  }
+
+  if (level.file_version < FILE_VERSION_1_2)
+  {
+    /* level files from versions before 1.2.0 without chunk structure */
+    LoadLevel_HEAD(&level, file);
+    LoadLevel_BODY(&level, file);
+  }
+  else
+  {
+    getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_BIG_ENDIAN);
+    if (strcmp(chunk, "HEAD") || chunk_length != LEVEL_HEADER_SIZE)
+    {
+      Error(ERR_WARN, "wrong 'HEAD' chunk of level file '%s'", filename);
+      fclose(file);
+      return;
+    }
+
+    LoadLevel_HEAD(&level, file);
+
+    getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_BIG_ENDIAN);
+
+    /* look for optional author chunk */
+    if (strcmp(chunk, "AUTH") == 0 && chunk_length == MAX_LEVEL_AUTHOR_LEN)
+    {
+      LoadLevel_AUTH(&level, file);
+
+      getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_BIG_ENDIAN);
+    }
+
+    /* look for optional content chunk */
+    if (strcmp(chunk, "CONT") == 0 &&
+       chunk_length == 4 + MAX_ELEMENT_CONTENTS * 3 * 3)
+    {
+      LoadLevel_CONT(&level, file);
+
+      getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_BIG_ENDIAN);
+    }
+
+    /* next check body chunk identifier and chunk length */
+    if (strcmp(chunk, "BODY") != 0 || chunk_length != lev_fieldx * lev_fieldy)
+    {
+      Error(ERR_WARN, "wrong 'BODY' chunk of level file '%s'", filename);
+      fclose(file);
+      return;
+    }
+
+    LoadLevel_BODY(&level, file);
+  }
+
+  fclose(file);
+
+  if (IS_LEVELCLASS_CONTRIBUTION(leveldir_current) ||
+      IS_LEVELCLASS_USER(leveldir_current))
+  {
+    /* for user contributed and private levels, use the version of
+       the game engine the levels were created for */
+    level.game_version = level.file_version;
+
+    /* player was faster than monsters in pre-1.0 levels */
+    if (level.file_version == FILE_VERSION_1_0)
+    {
+      Error(ERR_WARN, "level file '%s' has version number 1.0", filename);
+      Error(ERR_WARN, "using high speed movement for player");
+      level.double_speed = TRUE;
+    }
+  }
+  else
+  {
+    /* always use the latest version of the game engine for all but
+       user contributed and private levels */
+    level.game_version = GAME_VERSION_ACTUAL;
+  }
+
+  /* determine border element for this level */
+  SetBorderElement();
+}
+
 void SaveLevel(int level_nr)
 {
   int i, x, y;
   char *filename = getLevelFilename(level_nr);
-  boolean encoding_16bit = FALSE;      /* default: maximal 256 elements */
+#if 0
+  boolean encoding_16bit_amoeba = FALSE;
+  boolean encoding_16bit_yamyam = FALSE;
+#endif
+  boolean encoding_16bit = FALSE;      /* default: only 8-bit elements */
   char *oldest_possible_cookie;
   FILE *file;
 
index e144979a7bb40ed1c2a38132e7860629477041ff..1e481dc3f37041b2d08dfa1112e59af6b1180e94 100644 (file)
@@ -700,8 +700,8 @@ void putFile32BitInteger(FILE *file, int value, int byte_order)
   }
 }
 
-void getFileChunk(FILE *file, char *chunk_buffer, int *chunk_length,
-                 int byte_order)
+boolean getFileChunk(FILE *file, char *chunk_buffer, int *chunk_length,
+                    int byte_order)
 {
   const int chunk_identifier_length = 4;
 
@@ -710,6 +710,8 @@ void getFileChunk(FILE *file, char *chunk_buffer, int *chunk_length,
 
   /* read chunk length */
   *chunk_length = getFile32BitInteger(file, byte_order);
+
+  return (feof(file) || ferror(file) ? FALSE : TRUE);
 }
 
 void putFileChunk(FILE *file, char *chunk_name, int chunk_length,
index 9f9129579d64d306d684f731575a58d15dcdd2d2..5c7a01bfc1af0f5ea73b97bdfd0e60bb9ca704c6 100644 (file)
@@ -71,7 +71,7 @@ short getFile16BitInteger(FILE *, int);
 void putFile16BitInteger(FILE *, short, int);
 int getFile32BitInteger(FILE *, int);
 void putFile32BitInteger(FILE *, int, int);
-void getFileChunk(FILE *, char *, int *, int);
+boolean getFileChunk(FILE *, char *, int *, int);
 void putFileChunk(FILE *, char *, int, int);
 char *getKeyNameFromKey(Key);
 char *getX11KeyNameFromKey(Key);
index da78d7787b2bd37006c554e120aec3a736ed0a36..99e566ee2be34e5587619c16931c8f274635d5f9 100644 (file)
@@ -324,6 +324,8 @@ struct LevelInfo
 {
   int file_version;    /* version of file this level was stored with */
   int game_version;    /* version of game engine to play this level */
+  boolean encoding_16bit;      /* level contains 16-bit elements */
+
   int fieldx;
   int fieldy;
   int time;