+static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename)
+{
+ int x, y;
+
+ /* map elements that have changed in newer versions */
+ for(y=0; y<level->fieldy; y++)
+ {
+ for(x=0; x<level->fieldx; x++)
+ {
+ int element = level->field[x][y];
+
+ if (level->game_version <= VERSION_IDENT(2,2,0,0))
+ {
+ /* map game font elements */
+ element = (element == EL_CHAR('[') ? EL_CHAR_AUMLAUT :
+ element == EL_CHAR('\\') ? EL_CHAR_OUMLAUT :
+ element == EL_CHAR(']') ? EL_CHAR_UUMLAUT :
+ element == EL_CHAR('^') ? EL_CHAR_COPYRIGHT : element);
+ }
+
+ if (level->game_version < VERSION_IDENT(3,0,0,0))
+ {
+ /* map Supaplex gravity tube elements */
+ element = (element == EL_SP_GRAVITY_PORT_LEFT ? EL_SP_PORT_LEFT :
+ element == EL_SP_GRAVITY_PORT_RIGHT ? EL_SP_PORT_RIGHT :
+ element == EL_SP_GRAVITY_PORT_UP ? EL_SP_PORT_UP :
+ element == EL_SP_GRAVITY_PORT_DOWN ? EL_SP_PORT_DOWN :
+ element);
+ }
+
+ level->field[x][y] = element;
+ }
+ }
+
+ /* copy elements to runtime playfield array */
+ for(x=0; x<MAX_LEV_FIELDX; x++)
+ for(y=0; y<MAX_LEV_FIELDY; y++)
+ Feld[x][y] = level->field[x][y];
+
+ /* initialize level size variables for faster access */
+ lev_fieldx = level->fieldx;
+ lev_fieldy = level->fieldy;
+
+ /* determine border element for this level */
+ SetBorderElement();
+}
+
+void LoadLevelTemplate(int level_nr)
+{
+ char *filename = getLevelFilename(level_nr);
+
+ LoadLevelFromFilename(&level_template, filename);
+
+ LoadLevel_InitVersion(&level, filename);
+ LoadLevel_InitElements(&level, filename);
+
+ ActivateLevelTemplate();
+}
+
+void LoadLevel(int level_nr)
+{
+ char *filename = getLevelFilename(level_nr);
+
+ LoadLevelFromFilename(&level, filename);
+
+ if (level.use_custom_template)
+ LoadLevelTemplate(-1);
+
+#if 1
+ LoadLevel_InitVersion(&level, filename);
+ LoadLevel_InitElements(&level, filename);
+ LoadLevel_InitPlayfield(&level, filename);
+#else
+ LoadLevel_InitLevel(&level, filename);
+#endif
+}
+
+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;
+
+ putFile8Bit(file, level->fieldx);
+ putFile8Bit(file, level->fieldy);
+
+ putFile16BitBE(file, level->time);
+ putFile16BitBE(file, level->gems_needed);
+
+ for(i=0; i<MAX_LEVEL_NAME_LEN; i++)
+ putFile8Bit(file, level->name[i]);
+
+ for(i=0; i<LEVEL_SCORE_ELEMENTS; i++)
+ putFile8Bit(file, level->score[i]);
+
+ for(i=0; i<STD_ELEMENT_CONTENTS; i++)
+ for(y=0; y<3; y++)
+ for(x=0; x<3; x++)
+ putFile8Bit(file, (level->encoding_16bit_yamyam ? EL_EMPTY :
+ level->yamyam_content[i][x][y]));
+ putFile8Bit(file, level->amoeba_speed);
+ putFile8Bit(file, level->time_magic_wall);
+ putFile8Bit(file, level->time_wheel);
+ putFile8Bit(file, (level->encoding_16bit_amoeba ? EL_EMPTY :
+ level->amoeba_content));
+ putFile8Bit(file, (level->double_speed ? 1 : 0));
+ putFile8Bit(file, (level->initial_gravity ? 1 : 0));
+ putFile8Bit(file, (level->encoding_16bit_field ? 1 : 0));
+ putFile8Bit(file, (level->em_slippery_gems ? 1 : 0));
+
+ putFile8Bit(file, (level->use_custom_template ? 1 : 0));
+
+ WriteUnusedBytesToFile(file, LEVEL_HEADER_UNUSED);
+}
+
+static void SaveLevel_AUTH(FILE *file, struct LevelInfo *level)