+
+#define CHUNK_ID_LEN 4 /* IFF style chunk id length */
+#define CHUNK_SIZE_UNDEFINED 0 /* undefined chunk size == 0 */
+#define CHUNK_SIZE_NONE -1 /* do not write chunk size */
+#define FILE_VERS_CHUNK_SIZE 8 /* size of file version chunk */
+#define LEVEL_HEADER_SIZE 80 /* size of level file header */
+#define LEVEL_HEADER_UNUSED 14 /* unused level header bytes */
+#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 */
+
+/* file identifier strings */
+#define LEVEL_COOKIE_TMPL "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x"
+#define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x"
+#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2"
+
+
+/* ========================================================================= */
+/* level file functions */
+/* ========================================================================= */
+
+static void setLevelInfoToDefaults()
+{
+ int i, x, y;
+
+ level.file_version = FILE_VERSION_ACTUAL;
+ level.game_version = GAME_VERSION_ACTUAL;
+
+ level.encoding_16bit_field = FALSE; /* default: only 8-bit elements */
+ level.encoding_16bit_yamyam = FALSE; /* default: only 8-bit elements */
+ level.encoding_16bit_amoeba = FALSE; /* default: only 8-bit elements */
+
+ lev_fieldx = level.fieldx = STD_LEV_FIELDX;
+ lev_fieldy = level.fieldy = STD_LEV_FIELDY;
+
+ for(x=0; x<MAX_LEV_FIELDX; x++)
+ for(y=0; y<MAX_LEV_FIELDY; y++)
+ Feld[x][y] = Ur[x][y] = EL_ERDREICH;
+
+ level.time = 100;
+ level.gems_needed = 0;
+ level.amoeba_speed = 10;
+ level.time_magic_wall = 10;
+ level.time_wheel = 10;
+ level.time_light = 10;
+ level.time_timegate = 10;
+ level.amoeba_content = EL_DIAMANT;
+ level.double_speed = FALSE;
+ level.gravity = FALSE;
+ level.em_slippery_gems = FALSE;
+
+ 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';
+
+ strcpy(level.name, NAMELESS_LEVEL_NAME);
+ strcpy(level.author, ANONYMOUS_NAME);
+
+ for(i=0; i<LEVEL_SCORE_ELEMENTS; i++)
+ level.score[i] = 10;
+
+ level.num_yam_contents = STD_ELEMENT_CONTENTS;
+ for(i=0; i<MAX_ELEMENT_CONTENTS; i++)
+ for(x=0; x<3; x++)
+ for(y=0; y<3; y++)
+ level.yam_content[i][x][y] =
+ (i < STD_ELEMENT_CONTENTS ? EL_FELSBROCKEN : EL_LEERRAUM);
+
+ Feld[0][0] = Ur[0][0] = EL_SPIELFIGUR;
+ Feld[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] =
+ Ur[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] = EL_AUSGANG_ZU;
+
+ BorderElement = EL_BETON;
+
+ /* try to determine better author name than 'anonymous' */
+ if (strcmp(leveldir_current->author, ANONYMOUS_NAME) != 0)
+ {
+ strncpy(level.author, leveldir_current->author, MAX_LEVEL_AUTHOR_LEN);
+ level.author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ }
+ else
+ {
+ switch (LEVELCLASS(leveldir_current))
+ {
+ case LEVELCLASS_TUTORIAL:
+ strcpy(level.author, PROGRAM_AUTHOR_STRING);
+ break;
+
+ case LEVELCLASS_CONTRIBUTION:
+ strncpy(level.author, leveldir_current->name,MAX_LEVEL_AUTHOR_LEN);
+ level.author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ break;
+
+ case LEVELCLASS_USER:
+ strncpy(level.author, getRealName(), MAX_LEVEL_AUTHOR_LEN);
+ level.author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ break;
+
+ default:
+ /* keep default value */
+ break;
+ }
+ }
+}
+
+static int checkLevelElement(int element)
+{
+ if (element >= EL_FIRST_RUNTIME_EL)
+ {
+ Error(ERR_WARN, "invalid level element %d", element);
+ element = EL_CHAR_FRAGE;
+ }
+
+ return element;
+}
+
+static int LoadLevel_VERS(FILE *file, int chunk_size, struct LevelInfo *level)
+{
+ ReadChunk_VERS(file, &(level->file_version), &(level->game_version));
+
+ return chunk_size;
+}
+
+static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level)
+{
+ 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<STD_ELEMENT_CONTENTS; i++)
+ for(y=0; y<3; y++)
+ for(x=0; x<3; x++)
+ level->yam_content[i][x][y] = checkLevelElement(fgetc(file));
+
+ 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_field = (fgetc(file) == 1 ? TRUE : FALSE);
+ level->em_slippery_gems = (fgetc(file) == 1 ? TRUE : FALSE);
+
+ ReadUnusedBytesFromFile(file, LEVEL_HEADER_UNUSED);
+
+ return chunk_size;
+}
+
+static int LoadLevel_AUTH(FILE *file, int chunk_size, struct LevelInfo *level)