X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame_mm%2Fmm_files.c;h=fc59d7988ea29c2df7ad8056a8dfc2be061e3290;hp=d31d8c81d2d50da8609c506ce08ab708652cc666;hb=12a8fd3a64d6bee5ca5f5b89e4a00b49d78bbd2c;hpb=0a82d94ecb53afceb830366ca8f0a5ff09997109 diff --git a/src/game_mm/mm_files.c b/src/game_mm/mm_files.c index d31d8c81..fc59d798 100644 --- a/src/game_mm/mm_files.c +++ b/src/game_mm/mm_files.c @@ -18,21 +18,31 @@ #include "mm_main.h" -#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 19 /* unused level header bytes */ - -/* file identifier strings */ +#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 19 // unused level header bytes + +// file identifier strings #define LEVEL_COOKIE_TMPL "MIRRORMAGIC_LEVEL_FILE_VERSION_x.x" #define SCORE_COOKIE "MIRRORMAGIC_SCORE_FILE_VERSION_1.4" -/* ========================================================================= */ -/* level file functions */ -/* ========================================================================= */ +int default_score[LEVEL_SCORE_ELEMENTS] = +{ + [SC_COLLECTIBLE] = 10, + [SC_PACMAN] = 50, + [SC_KEY] = 10, + [SC_TIME_BONUS] = 1, + [SC_LIGHTBALL] = 10, +}; + + +// ============================================================================ +// level file functions +// ============================================================================ static void ReadChunk_MM_VERS(File *file, int *file_version, int *game_version) { @@ -42,12 +52,12 @@ static void ReadChunk_MM_VERS(File *file, int *file_version, int *game_version) file_version_major = getFile8Bit(file); file_version_minor = getFile8Bit(file); file_version_patch = getFile8Bit(file); - getFile8Bit(file); /* not used */ + getFile8Bit(file); // not used game_version_major = getFile8Bit(file); game_version_minor = getFile8Bit(file); game_version_patch = getFile8Bit(file); - getFile8Bit(file); /* not used */ + getFile8Bit(file); // not used *file_version = MM_VERSION_IDENT(file_version_major, file_version_minor, @@ -70,53 +80,55 @@ static void WriteChunk_MM_VERS(FILE *file, int file_version, int game_version) fputc(file_version_major, file); fputc(file_version_minor, file); fputc(file_version_patch, file); - fputc(0, file); /* not used */ + fputc(0, file); // not used fputc(game_version_major, file); fputc(game_version_minor, file); fputc(game_version_patch, file); - fputc(0, file); /* not used */ + fputc(0, file); // not used } -void setLevelInfoToDefaults_MM() +void setLevelInfoToDefaults_MM(void) { int i, x, y; native_mm_level.file_version = MM_FILE_VERSION_ACTUAL; native_mm_level.game_version = MM_GAME_VERSION_ACTUAL; - native_mm_level.encoding_16bit_field = FALSE; /* default: only 8-bit elements */ + native_mm_level.encoding_16bit_field = FALSE; // default: only 8-bit elements - lev_fieldx = native_mm_level.fieldx = STD_LEV_FIELDX; - lev_fieldy = native_mm_level.fieldy = STD_LEV_FIELDY; + native_mm_level.fieldx = STD_LEV_FIELDX; + native_mm_level.fieldy = STD_LEV_FIELDY; - for(x=0; xfile_version), &(level->game_version)); + ReadChunk_MM_VERS(file, &level->file_version, &level->game_version); return chunk_size; } -static int LoadLevel_MM_HEAD(File *file, int chunk_size, struct LevelInfo_MM *level) +static int LoadLevel_MM_HEAD(File *file, int chunk_size, + struct LevelInfo_MM *level) { int i; int laser_color; - lev_fieldx = level->fieldx = getFile8Bit(file); - lev_fieldy = level->fieldy = getFile8Bit(file); + level->fieldx = getFile8Bit(file); + level->fieldy = getFile8Bit(file); level->time = getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN); level->kettles_needed = getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN); - for(i=0; ifile_version <= MM_FILE_VERSION_2_0) + level->time *= 4; + + for (i = 0; i < MAX_LEVEL_NAME_LEN; i++) level->name[i] = getFile8Bit(file); level->name[MAX_LEVEL_NAME_LEN] = 0; - for(i=0; iscore[i] = getFile8Bit(file); + // scores were 0 and hardcoded in game engine in level files up to 2.0.x + if (level->file_version <= MM_FILE_VERSION_2_0) + for (i = 0; i < LEVEL_SCORE_ELEMENTS; i++) + if (level->score[i] == 0) + level->score[i] = default_score[i]; + level->auto_count_kettles = (getFile8Bit(file) == 1 ? TRUE : FALSE); level->amoeba_speed = getFile8Bit(file); level->time_fuse = getFile8Bit(file); + // fuse time was 0 and hardcoded in game engine in level files up to 2.0.x + if (level->file_version <= MM_FILE_VERSION_2_0) + level->time_fuse = 25; + laser_color = getFile8Bit(file); level->laser_red = (laser_color >> 2) & 0x01; level->laser_green = (laser_color >> 1) & 0x01; @@ -172,18 +200,20 @@ static int LoadLevel_MM_HEAD(File *file, int chunk_size, struct LevelInfo_MM *le return chunk_size; } -static int LoadLevel_MM_AUTH(File *file, int chunk_size, struct LevelInfo_MM *level) +static int LoadLevel_MM_AUTH(File *file, int chunk_size, + struct LevelInfo_MM *level) { int i; - for(i=0; iauthor[i] = getFile8Bit(file); level->author[MAX_LEVEL_NAME_LEN] = 0; return chunk_size; } -static int LoadLevel_MM_BODY(File *file, int chunk_size, struct LevelInfo_MM *level) +static int LoadLevel_MM_BODY(File *file, int chunk_size, + struct LevelInfo_MM *level) { int x, y; int chunk_size_expected = level->fieldx * level->fieldy; @@ -199,12 +229,13 @@ static int LoadLevel_MM_BODY(File *file, int chunk_size, struct LevelInfo_MM *le if (chunk_size_expected != chunk_size) { ReadUnusedBytesFromFile(file, chunk_size); + return chunk_size_expected; } - for(y=0; yfieldy; y++) - for(x=0; xfieldx; x++) - native_mm_level.field[x][y] = Feld[x][y] = Ur[x][y] = + for (y = 0; y < level->fieldy; y++) + for (x = 0; x < level->fieldx; x++) + native_mm_level.field[x][y] = Ur[x][y] = checkLevelElement(level->encoding_16bit_field ? getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN) : getFile8Bit(file)); @@ -233,7 +264,7 @@ boolean LoadNativeLevel_MM(char *filename, boolean level_info_only) { NULL, 0, NULL } }; - /* always start with reliable default values */ + // always start with reliable default values setLevelInfoToDefaults_MM(); if (!(file = openFile(filename, MODE_READ))) @@ -247,18 +278,19 @@ boolean LoadNativeLevel_MM(char *filename, boolean level_info_only) getFileChunk(file, chunk_name, NULL, BYTE_ORDER_BIG_ENDIAN); if (strcmp(chunk_name, "MMII") == 0) { - getFile32BitInteger(file, BYTE_ORDER_BIG_ENDIAN); /* not used */ + getFile32BitInteger(file, BYTE_ORDER_BIG_ENDIAN); // not used getFileChunk(file, chunk_name, NULL, BYTE_ORDER_BIG_ENDIAN); if (strcmp(chunk_name, "CAVE") != 0) { Error(ERR_WARN, "unknown format of level file '%s'", filename); + closeFile(file); return FALSE; } } - else /* check for pre-2.0 file format with cookie string */ + else // check for pre-2.0 file format with cookie string { strcpy(cookie, chunk_name); getStringFromFile(file, &cookie[4], MAX_LINE_LEN - 4); @@ -268,14 +300,17 @@ boolean LoadNativeLevel_MM(char *filename, boolean level_info_only) if (!checkCookieString(cookie, LEVEL_COOKIE_TMPL)) { Error(ERR_WARN, "unknown format of level file '%s'", filename); + closeFile(file); return FALSE; } - if ((native_mm_level.file_version = getFileVersionFromCookieString(cookie)) == -1) + if ((native_mm_level.file_version = getFileVersionFromCookieString(cookie)) + == -1) { Error(ERR_WARN, "unsupported version of level file '%s'", filename); + closeFile(file); return FALSE; @@ -294,6 +329,7 @@ boolean LoadNativeLevel_MM(char *filename, boolean level_info_only) { Error(ERR_WARN, "unknown chunk '%s' in level file '%s'", chunk_name, filename); + ReadUnusedBytesFromFile(file, chunk_size); } else if (chunk_info[i].size != -1 && @@ -301,22 +337,21 @@ boolean LoadNativeLevel_MM(char *filename, boolean level_info_only) { Error(ERR_WARN, "wrong size (%d) of chunk '%s' in level file '%s'", chunk_size, chunk_name, filename); + ReadUnusedBytesFromFile(file, chunk_size); } else { - /* call function to load this level chunk */ + // call function to load this level chunk int chunk_size_expected = (chunk_info[i].loader)(file, chunk_size, &native_mm_level); - /* the size of some chunks cannot be checked before reading other - chunks first (like "HEAD" and "BODY") that contain some header - information, so check them here */ + // the size of some chunks cannot be checked before reading other + // chunks first (like "HEAD" and "BODY") that contain some header + // information, so check them here if (chunk_size_expected != chunk_size) - { Error(ERR_WARN, "wrong size (%d) of chunk '%s' in level file '%s'", chunk_size, chunk_name, filename); - } } } @@ -336,10 +371,10 @@ static void SaveLevel_MM_HEAD(FILE *file, struct LevelInfo_MM *level) putFile16BitInteger(file, level->time, BYTE_ORDER_BIG_ENDIAN); putFile16BitInteger(file, level->kettles_needed, BYTE_ORDER_BIG_ENDIAN); - for(i=0; iname[i], file); - for(i=0; iscore[i], file); fputc((level->auto_count_kettles ? 1 : 0), file); @@ -360,7 +395,7 @@ static void SaveLevel_MM_AUTH(FILE *file, struct LevelInfo_MM *level) { int i; - for(i=0; iauthor[i], file); } @@ -368,8 +403,8 @@ static void SaveLevel_MM_BODY(FILE *file, struct LevelInfo_MM *level) { int x, y; - for(y=0; yfieldy; y++) - for(x=0; xfieldx; x++) + for (y = 0; y < level->fieldy; y++) + for (x = 0; x < level->fieldx; x++) if (level->encoding_16bit_field) putFile16BitInteger(file, Ur[x][y], BYTE_ORDER_BIG_ENDIAN); else @@ -385,18 +420,21 @@ void SaveNativeLevel_MM(char *filename) if (!(file = fopen(filename, MODE_WRITE))) { Error(ERR_WARN, "cannot save level file '%s'", filename); + return; } - /* check level field for 16-bit elements */ + // check level field for 16-bit elements native_mm_level.encoding_16bit_field = FALSE; - for(y=0; y 255) native_mm_level.encoding_16bit_field = TRUE; body_chunk_size = - native_mm_level.fieldx * native_mm_level.fieldy * (native_mm_level.encoding_16bit_field ? 2 : 1); + native_mm_level.fieldx * native_mm_level.fieldy * + (native_mm_level.encoding_16bit_field ? 2 : 1); putFileChunk(file, "MMII", CHUNK_SIZE_UNDEFINED, BYTE_ORDER_BIG_ENDIAN); putFileChunk(file, "CAVE", CHUNK_SIZE_NONE, BYTE_ORDER_BIG_ENDIAN);