From: Holger Schemel Date: Wed, 13 Mar 2002 00:43:10 +0000 (+0100) Subject: rnd-20020313-1-src X-Git-Tag: 2.0.1^2~15 X-Git-Url: https://git.artsoft.org/?a=commitdiff_plain;h=f2c89dee62e731d161c6e2b3e6a0471a4609fb87;p=rocksndiamonds.git rnd-20020313-1-src --- diff --git a/src/files.c b/src/files.c index d78ec4f1..95df54bc 100644 --- a/src/files.c +++ b/src/files.c @@ -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; iname[i] = fgetc(file); + level->name[MAX_LEVEL_NAME_LEN] = 0; + + for(i=0; iscore[i] = fgetc(file); + + level->num_yam_contents = STD_ELEMENT_CONTENTS; + for(i=0; iyam_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; iauthor[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; iyam_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; yencoding_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; diff --git a/src/libgame/misc.c b/src/libgame/misc.c index e144979a..1e481dc3 100644 --- a/src/libgame/misc.c +++ b/src/libgame/misc.c @@ -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, diff --git a/src/libgame/misc.h b/src/libgame/misc.h index 9f912957..5c7a01bf 100644 --- a/src/libgame/misc.h +++ b/src/libgame/misc.h @@ -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); diff --git a/src/main.h b/src/main.h index da78d778..99e566ee 100644 --- a/src/main.h +++ b/src/main.h @@ -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;