X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=f364ae95b93295dbdf6eb60082fba96ce82a4522;hb=c64be0354d88b9776537a907f524993e29e074aa;hp=1f98f641e2ea8bd38eda6ea27a935ed84c8d5bf0;hpb=5dd3c868d9df906623a5fc0ff2124655a14e3715;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index 1f98f641..f364ae95 100644 --- a/src/files.c +++ b/src/files.c @@ -29,7 +29,7 @@ #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 13 /* unused level header bytes */ +#define LEVEL_HEADER_UNUSED 11 /* 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 LEVEL_CHUNK_CNT3_HEADER 16 /* size of level CNT3 header */ @@ -150,6 +150,8 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) level->double_speed = FALSE; level->initial_gravity = FALSE; level->em_slippery_gems = FALSE; + level->block_last_field = FALSE; + level->sp_block_last_field = TRUE; level->use_custom_template = FALSE; @@ -258,6 +260,8 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) /* default: only one element in group */ element_info[element].group->num_elements = 1; + + element_info[element].group->choice_mode = ANIM_RANDOM; } } @@ -304,6 +308,7 @@ static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info) level_file_info->nr = 0; level_file_info->type = LEVEL_FILE_TYPE_UNKNOWN; level_file_info->packed = FALSE; + level_file_info->basename = NULL; level_file_info->filename = NULL; } @@ -325,13 +330,40 @@ static char *getLevelFilenameFromBasename(char *basename) return filename; } +static int getFileTypeFromBasename(char *basename) +{ + static char *filename = NULL; + struct stat file_status; + + /* ---------- try to determine file type from filename ---------- */ + + /* check for typical filename of a Supaplex level package file */ + if (strlen(basename) == 10 && (strncmp(basename, "levels.d", 8) == 0 || + strncmp(basename, "LEVELS.D", 8) == 0)) + return LEVEL_FILE_TYPE_SP; + + /* ---------- try to determine file type from filesize ---------- */ + + checked_free(filename); + filename = getPath2(getCurrentLevelDir(), basename); + + if (stat(filename, &file_status) == 0) + { + /* check for typical filesize of a Supaplex level package file */ + if (file_status.st_size == 170496) + return LEVEL_FILE_TYPE_SP; + } + + return LEVEL_FILE_TYPE_UNKNOWN; +} + static char *getSingleLevelBasename(int nr, int type) { static char basename[MAX_FILENAME_LEN]; + char *level_filename = getStringCopy(leveldir_current->level_filename); - if (leveldir_current->level_filename == NULL) - leveldir_current->level_filename = - getStringCat2("%%03d.", LEVELFILE_EXTENSION); + if (level_filename == NULL) + level_filename = getStringCat2("%03d.", LEVELFILE_EXTENSION); switch (type) { @@ -348,10 +380,12 @@ static char *getSingleLevelBasename(int nr, int type) case LEVEL_FILE_TYPE_UNKNOWN: default: - sprintf(basename, leveldir_current->level_filename, nr); + sprintf(basename, level_filename, nr); break; } + free(level_filename); + return basename; } @@ -374,28 +408,18 @@ static char *getPackedLevelBasename(int type) while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */ { char *entry_basename = dir_entry->d_name; - boolean valid_entry_found = FALSE; + int entry_type = getFileTypeFromBasename(entry_basename); - switch (type) + if (entry_type != LEVEL_FILE_TYPE_UNKNOWN) /* found valid level package */ { - case LEVEL_FILE_TYPE_SP: - if (strlen(entry_basename) == 10 && - (strncmp(entry_basename, "levels.d", 8) == 0 || - strncmp(entry_basename, "LEVELS.D", 8) == 0)) - { - /* looks like a typical filename of a Supaplex level package file */ - strcpy(basename, entry_basename); - valid_entry_found = TRUE; - } - break; + if (type == LEVEL_FILE_TYPE_UNKNOWN || + type == entry_type) + { + strcpy(basename, entry_basename); - default: - valid_entry_found = TRUE; break; + } } - - if (valid_entry_found) - break; } closedir(dir); @@ -408,23 +432,42 @@ static char *getSingleLevelFilename(int nr, int type) return getLevelFilenameFromBasename(getSingleLevelBasename(nr, type)); } +#if 0 static char *getPackedLevelFilename(int type) { return getLevelFilenameFromBasename(getPackedLevelBasename(type)); } +#endif char *getDefaultLevelFilename(int nr) { return getSingleLevelFilename(nr, LEVEL_FILE_TYPE_RND); } -static void setLevelFileInfo_Filename(struct LevelFileInfo *lfi) +static void setLevelFileInfo_SingleLevelFilename(struct LevelFileInfo *lfi, + int type) +{ + lfi->type = type; + lfi->packed = FALSE; + lfi->basename = getSingleLevelBasename(lfi->nr, lfi->type); + lfi->filename = getLevelFilenameFromBasename(lfi->basename); +} + +static void setLevelFileInfo_PackedLevelFilename(struct LevelFileInfo *lfi, + int type) +{ + lfi->type = type; + lfi->packed = TRUE; + lfi->basename = getPackedLevelBasename(lfi->type); + lfi->filename = getLevelFilenameFromBasename(lfi->basename); +} + +static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi) { /* special case: level number is negative => check for level template file */ if (lfi->nr < 0) { - lfi->type = LEVEL_FILE_TYPE_RND; - lfi->filename = getDefaultLevelFilename(lfi->nr); + setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_RND); return; } @@ -432,66 +475,34 @@ static void setLevelFileInfo_Filename(struct LevelFileInfo *lfi) if (leveldir_current->level_filename != NULL) { /* check for file name/pattern specified in "levelinfo.conf" */ - lfi->type = LEVEL_FILE_TYPE_UNKNOWN; - lfi->filename = getSingleLevelFilename(lfi->nr, lfi->type); + setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN); if (fileExists(lfi->filename)) return; } /* check for native Rocks'n'Diamonds level file */ - lfi->type = LEVEL_FILE_TYPE_RND; - lfi->filename = getSingleLevelFilename(lfi->nr, lfi->type); + setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_RND); if (fileExists(lfi->filename)) return; /* check for classic Emerald Mine level file */ - lfi->type = LEVEL_FILE_TYPE_EM; - lfi->filename = getSingleLevelFilename(lfi->nr, lfi->type); + setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_EM); if (fileExists(lfi->filename)) return; - /* check for packed Supaplex level file */ - lfi->type = LEVEL_FILE_TYPE_SP; - lfi->filename = getPackedLevelFilename(lfi->type); + /* check for various packed level file formats */ + setLevelFileInfo_PackedLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN); if (fileExists(lfi->filename)) return; /* no known level file found -- try to use default values */ - lfi->type = LEVEL_FILE_TYPE_UNKNOWN; - lfi->filename = getSingleLevelFilename(lfi->nr, lfi->type); + setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN); } -static void setLevelFileInfo_Filetype(struct LevelFileInfo *lfi) +static void determineLevelFileInfo_Filetype(struct LevelFileInfo *lfi) { - struct stat file_status; - - if (lfi->type != LEVEL_FILE_TYPE_UNKNOWN) - return; - - /* ---------- try to determine file type from filename ---------- */ - - if (strlen(lfi->filename) == 10 && - (strncmp(lfi->filename, "levels.d", 8) == 0 || - strncmp(lfi->filename, "LEVELS.D", 8) == 0)) - { - /* looks like a typical filename of a Supaplex level package file */ - lfi->type = LEVEL_FILE_TYPE_SP; - - return; - } - - /* ---------- try to determine file type from file status ---------- */ - - if (stat(lfi->filename, &file_status) == 0) - { - if (file_status.st_size == 170496) - { - /* looks like a typical filesize of a Supaplex level package file */ - lfi->type = LEVEL_FILE_TYPE_SP; - - return; - } - } + if (lfi->type == LEVEL_FILE_TYPE_UNKNOWN) + lfi->type = getFileTypeFromBasename(lfi->basename); } static struct LevelFileInfo *getLevelFileInfo(int nr) @@ -503,8 +514,8 @@ static struct LevelFileInfo *getLevelFileInfo(int nr) level_file_info.nr = nr; /* set requested level number */ - setLevelFileInfo_Filename(&level_file_info); - setLevelFileInfo_Filetype(&level_file_info); + determineLevelFileInfo_Filename(&level_file_info); + determineLevelFileInfo_Filetype(&level_file_info); return &level_file_info; } @@ -616,6 +627,8 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level) level->initial_gravity = (getFile8Bit(file) == 1 ? TRUE : FALSE); level->encoding_16bit_field = (getFile8Bit(file) == 1 ? TRUE : FALSE); level->em_slippery_gems = (getFile8Bit(file) == 1 ? TRUE : FALSE); + level->block_last_field = (getFile8Bit(file) == 1 ? TRUE : FALSE); + level->sp_block_last_field = (getFile8Bit(file) == 1 ? TRUE : FALSE); level->use_custom_template = (getFile8Bit(file) == 1 ? TRUE : FALSE); @@ -1070,8 +1083,10 @@ static int LoadLevel_GRP1(FILE *file, int chunk_size, struct LevelInfo *level) ei->use_gfx_element = getFile8Bit(file); ei->gfx_element = getMappedElement(getFile16BitBE(file)); + group->choice_mode = getFile8Bit(file); + /* some free bytes for future values and padding */ - ReadUnusedBytesFromFile(file, 4); + ReadUnusedBytesFromFile(file, 3); for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++) group->element[i] = getMappedElement(getFile16BitBE(file)); @@ -2126,6 +2141,8 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level) 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->block_last_field ? 1 : 0)); + putFile8Bit(file, (level->sp_block_last_field ? 1 : 0)); putFile8Bit(file, (level->use_custom_template ? 1 : 0)); @@ -2481,8 +2498,10 @@ static void SaveLevel_GRP1(FILE *file, struct LevelInfo *level, int element) putFile8Bit(file, ei->use_gfx_element); putFile16BitBE(file, ei->gfx_element); + putFile8Bit(file, group->choice_mode); + /* some free bytes for future values and padding */ - WriteUnusedBytesToFile(file, 4); + WriteUnusedBytesToFile(file, 3); for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++) putFile16BitBE(file, group->element[i]); @@ -2625,24 +2644,26 @@ void DumpLevel(struct LevelInfo *level) level->file_version, level->game_version); printf_line("-", 79); - printf("Level Author: '%s'\n", level->author); - printf("Level Title: '%s'\n", level->name); + printf("Level author: '%s'\n", level->author); + printf("Level title: '%s'\n", level->name); printf("\n"); - printf("Playfield Size: %d x %d\n", level->fieldx, level->fieldy); + printf("Playfield size: %d x %d\n", level->fieldx, level->fieldy); printf("\n"); - printf("Level Time: %d seconds\n", level->time); + printf("Level time: %d seconds\n", level->time); printf("Gems needed: %d\n", level->gems_needed); printf("\n"); - printf("Time for Magic Wall: %d seconds\n", level->time_magic_wall); - printf("Time for Wheel: %d seconds\n", level->time_wheel); - printf("Time for Light: %d seconds\n", level->time_light); - printf("Time for Timegate: %d seconds\n", level->time_timegate); + printf("Time for magic wall: %d seconds\n", level->time_magic_wall); + printf("Time for wheel: %d seconds\n", level->time_wheel); + printf("Time for light: %d seconds\n", level->time_light); + printf("Time for timegate: %d seconds\n", level->time_timegate); printf("\n"); - printf("Amoeba Speed: %d\n", level->amoeba_speed); + printf("Amoeba speed: %d\n", level->amoeba_speed); printf("\n"); - printf("Gravity: %s\n", (level->initial_gravity ? "yes" : "no")); - printf("Double Speed Movement: %s\n", (level->double_speed ? "yes" : "no")); - printf("EM style slippery gems: %s\n", (level->em_slippery_gems ? "yes" : "no")); + printf("Initial gravity: %s\n", (level->initial_gravity ? "yes" : "no")); + printf("Double speed movement: %s\n", (level->double_speed ? "yes" : "no")); + printf("EM style slippery gems: %s\n", (level->em_slippery_gems ? "yes" : "no")); + printf("Player blocks last field: %s\n", (level->block_last_field ? "yes" : "no")); + printf("SP player blocks last field: %s\n", (level->sp_block_last_field ? "yes" : "no")); printf_line("-", 79); }