#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 */
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;
/* default: only one element in group */
element_info[element].group->num_elements = 1;
+
+ element_info[element].group->choice_mode = ANIM_RANDOM;
}
}
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;
}
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)
{
case LEVEL_FILE_TYPE_UNKNOWN:
default:
- sprintf(basename, leveldir_current->level_filename, nr);
+ sprintf(basename, level_filename, nr);
break;
}
+ free(level_filename);
+
return basename;
}
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);
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;
}
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)
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;
}
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);
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));
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));
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]);
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);
}