X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Flibgame%2Fsetup.c;h=16c11dfdcfdc0ce5d34f24b9e3e861ade2678620;hp=fe4c98ba697d173d7294e25bc9c3264199dfabba;hb=abe44529b439ad39b4d8dbf19cbd67c9b9844279;hpb=80aa0e4b2b060112407417a9d2896395023a21cc diff --git a/src/libgame/setup.c b/src/libgame/setup.c index fe4c98ba..16c11dfd 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -1,21 +1,20 @@ -/*********************************************************** -* Artsoft Retro-Game Library * -*----------------------------------------------------------* -* (c) 1994-2006 Artsoft Entertainment * -* Holger Schemel * -* Detmolder Strasse 189 * -* 33604 Bielefeld * -* Germany * -* e-mail: info@artsoft.org * -*----------------------------------------------------------* -* setup.c * -***********************************************************/ +// ============================================================================ +// Artsoft Retro-Game Library +// ---------------------------------------------------------------------------- +// (c) 1995-2014 by Artsoft Entertainment +// Holger Schemel +// info@artsoft.org +// http://www.artsoft.org/ +// ---------------------------------------------------------------------------- +// setup.c +// ============================================================================ #include #include #include #include #include +#include #include "platform.h" @@ -356,7 +355,7 @@ char *setLevelArtworkDir(TreeInfo *ti) checked_free(*artwork_set_ptr); - if (fileExists(dir)) + if (directoryExists(dir)) { *artwork_path_ptr = getStringCopy(getClassicArtworkDir(ti->type)); *artwork_set_ptr = getStringCopy(getClassicArtworkSet(ti->type)); @@ -597,34 +596,7 @@ char *getLevelSetTitleMessageFilename(int nr, boolean initial) static char *getCorrectedArtworkBasename(char *basename) { - char *basename_corrected = basename; - -#if defined(PLATFORM_MSDOS) - if (program.filename_prefix != NULL) - { - int prefix_len = strlen(program.filename_prefix); - - if (strncmp(basename, program.filename_prefix, prefix_len) == 0) - basename_corrected = &basename[prefix_len]; - - /* if corrected filename is still longer than standard MS-DOS filename - size (8 characters + 1 dot + 3 characters file extension), shorten - filename by writing file extension after 8th basename character */ - if (strlen(basename_corrected) > 8 + 1 + 3) - { - static char *msdos_filename = NULL; - - checked_free(msdos_filename); - - msdos_filename = getStringCopy(basename_corrected); - strncpy(&msdos_filename[8], &basename[strlen(basename) - (1+3)], 1+3 +1); - - basename_corrected = msdos_filename; - } - } -#endif - - return basename_corrected; + return basename; } char *getCustomImageFilename(char *basename) @@ -879,7 +851,7 @@ char *getCustomMusicDirectory(void) { /* 1st try: look for special artwork in current level series directory */ directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY); - if (fileExists(directory)) + if (directoryExists(directory)) return directory; free(directory); @@ -889,7 +861,7 @@ char *getCustomMusicDirectory(void) { /* 2nd try: look for special artwork configured in level series config */ directory = getStringCopy(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR)); - if (fileExists(directory)) + if (directoryExists(directory)) return directory; free(directory); @@ -903,7 +875,7 @@ char *getCustomMusicDirectory(void) { /* 3rd try: look for special artwork in configured artwork directory */ directory = getStringCopy(getSetupArtworkDir(artwork.mus_current)); - if (fileExists(directory)) + if (directoryExists(directory)) return directory; free(directory); @@ -911,14 +883,14 @@ char *getCustomMusicDirectory(void) /* 4th try: look for default artwork in new default artwork directory */ directory = getStringCopy(getDefaultMusicDir(MUS_DEFAULT_SUBDIR)); - if (fileExists(directory)) + if (directoryExists(directory)) return directory; free(directory); /* 5th try: look for default artwork in old default artwork directory */ directory = getStringCopy(options.music_directory); - if (fileExists(directory)) + if (directoryExists(directory)) return directory; return NULL; /* cannot find specified artwork file anywhere */ @@ -942,7 +914,7 @@ static void SaveUserLevelInfo(); void InitUserLevelDirectory(char *level_subdir) { - if (!fileExists(getUserLevelDir(level_subdir))) + if (!directoryExists(getUserLevelDir(level_subdir))) { createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE); createDirectory(getUserLevelDir(NULL), "main user level", PERMS_PRIVATE); @@ -1184,8 +1156,13 @@ void dumpTreeInfo(TreeInfo *node, int depth) for (i = 0; i < (depth + 1) * 3; i++) printf(" "); + printf("'%s' / '%s'\n", node->identifier, node->name); + + /* + // use for dumping artwork info tree printf("subdir == '%s' ['%s', '%s'] [%d])\n", node->subdir, node->fullpath, node->basepath, node->in_user_dir); + */ if (node->node_group != NULL) dumpTreeInfo(node->node_group, depth + 1); @@ -1369,9 +1346,14 @@ char *getUserGameDataDir(void) { static char *user_game_data_dir = NULL; +#if defined(PLATFORM_ANDROID) + if (user_game_data_dir == NULL) + user_game_data_dir = (char *)SDL_AndroidGetInternalStoragePath(); +#else if (user_game_data_dir == NULL) user_game_data_dir = getPath2(getPersonalDataDir(), program.userdata_subdir); +#endif return user_game_data_dir; } @@ -1383,7 +1365,7 @@ void updateUserGameDataDir() char *userdata_dir_new = getUserGameDataDir(); /* do not free() this */ /* convert old Unix style game data directory to Mac OS X style, if needed */ - if (fileExists(userdata_dir_old) && !fileExists(userdata_dir_new)) + if (directoryExists(userdata_dir_old) && !directoryExists(userdata_dir_new)) { if (rename(userdata_dir_old, userdata_dir_new) != 0) { @@ -1450,9 +1432,10 @@ void createDirectory(char *dir, char *text, int permission_class) else dir_mode |= MODE_W_ALL; - if (!fileExists(dir)) + if (!directoryExists(dir)) if (posix_mkdir(dir, dir_mode) != 0) - Error(ERR_WARN, "cannot create %s directory '%s'", text, dir); + Error(ERR_WARN, "cannot create %s directory '%s': %s", + text, dir, strerror(errno)); if (permission_class == PERMS_PUBLIC && !running_setgid) chmod(dir, dir_mode); @@ -1911,6 +1894,196 @@ boolean getTokenValueFromSetupLine(char *line, char **token, char **value) } #if 1 + +#if 1 +static boolean loadSetupFileData(void *setup_file_data, char *filename, + boolean top_recursion_level, boolean is_hash) +{ + static SetupFileHash *include_filename_hash = NULL; + char line[MAX_LINE_LEN], line_raw[MAX_LINE_LEN], previous_line[MAX_LINE_LEN]; + char *token, *value, *line_ptr; + void *insert_ptr = NULL; + boolean read_continued_line = FALSE; + File *file; + int line_nr = 0, token_count = 0, include_count = 0; + +#if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING + token_value_separator_warning = FALSE; +#endif + +#if CHECK_TOKEN__WARN_IF_ALREADY_EXISTS_IN_HASH + token_already_exists_warning = FALSE; +#endif + +#if 0 + Error(ERR_INFO, "===== opening file: '%s'", filename); +#endif + + if (!(file = openFile(filename, MODE_READ))) + { + Error(ERR_WARN, "cannot open configuration file '%s'", filename); + + return FALSE; + } + +#if 0 + Error(ERR_INFO, "===== reading file: '%s'", filename); +#endif + + /* use "insert pointer" to store list end for constant insertion complexity */ + if (!is_hash) + insert_ptr = setup_file_data; + + /* on top invocation, create hash to mark included files (to prevent loops) */ + if (top_recursion_level) + include_filename_hash = newSetupFileHash(); + + /* mark this file as already included (to prevent including it again) */ + setHashEntry(include_filename_hash, getBaseNamePtr(filename), "true"); + + while (!checkEndOfFile(file)) + { + /* read next line of input file */ + if (!getStringFromFile(file, line, MAX_LINE_LEN)) + break; + +#if 0 + Error(ERR_INFO, "got line: '%s'", line); +#endif + + /* check if line was completely read and is terminated by line break */ + if (strlen(line) > 0 && line[strlen(line) - 1] == '\n') + line_nr++; + + /* cut trailing line break (this can be newline and/or carriage return) */ + for (line_ptr = &line[strlen(line)]; line_ptr >= line; line_ptr--) + if ((*line_ptr == '\n' || *line_ptr == '\r') && *(line_ptr + 1) == '\0') + *line_ptr = '\0'; + + /* copy raw input line for later use (mainly debugging output) */ + strcpy(line_raw, line); + + if (read_continued_line) + { +#if 0 + /* !!! ??? WHY ??? !!! */ + /* cut leading whitespaces from input line */ + for (line_ptr = line; *line_ptr; line_ptr++) + if (*line_ptr != ' ' && *line_ptr != '\t') + break; +#endif + + /* append new line to existing line, if there is enough space */ + if (strlen(previous_line) + strlen(line_ptr) < MAX_LINE_LEN) + strcat(previous_line, line_ptr); + + strcpy(line, previous_line); /* copy storage buffer to line */ + + read_continued_line = FALSE; + } + + /* if the last character is '\', continue at next line */ + if (strlen(line) > 0 && line[strlen(line) - 1] == '\\') + { + line[strlen(line) - 1] = '\0'; /* cut off trailing backslash */ + strcpy(previous_line, line); /* copy line to storage buffer */ + + read_continued_line = TRUE; + + continue; + } + + if (!getTokenValueFromSetupLineExt(line, &token, &value, filename, + line_raw, line_nr, FALSE)) + continue; + + if (*token) + { + if (strEqual(token, "include")) + { + if (getHashEntry(include_filename_hash, value) == NULL) + { + char *basepath = getBasePath(filename); + char *basename = getBaseName(value); + char *filename_include = getPath2(basepath, basename); + +#if 0 + Error(ERR_INFO, "[including file '%s']", filename_include); +#endif + + loadSetupFileData(setup_file_data, filename_include, FALSE, is_hash); + + free(basepath); + free(basename); + free(filename_include); + + include_count++; + } + else + { + Error(ERR_WARN, "ignoring already processed file '%s'", value); + } + } + else + { + if (is_hash) + { +#if CHECK_TOKEN__WARN_IF_ALREADY_EXISTS_IN_HASH + char *old_value = + getHashEntry((SetupFileHash *)setup_file_data, token); + + if (old_value != NULL) + { + if (!token_already_exists_warning) + { + Error(ERR_INFO_LINE, "-"); + Error(ERR_WARN, "duplicate token(s) found in config file:"); + Error(ERR_INFO, "- config file: '%s'", filename); + + token_already_exists_warning = TRUE; + } + + Error(ERR_INFO, "- token: '%s' (in line %d)", token, line_nr); + Error(ERR_INFO, " old value: '%s'", old_value); + Error(ERR_INFO, " new value: '%s'", value); + } +#endif + + setHashEntry((SetupFileHash *)setup_file_data, token, value); + } + else + { + insert_ptr = addListEntry((SetupFileList *)insert_ptr, token, value); + } + + token_count++; + } + } + } + + closeFile(file); + +#if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING + if (token_value_separator_warning) + Error(ERR_INFO_LINE, "-"); +#endif + +#if CHECK_TOKEN__WARN_IF_ALREADY_EXISTS_IN_HASH + if (token_already_exists_warning) + Error(ERR_INFO_LINE, "-"); +#endif + + if (token_count == 0 && include_count == 0) + Error(ERR_WARN, "configuration file '%s' is empty", filename); + + if (top_recursion_level) + freeSetupFileHash(include_filename_hash); + + return TRUE; +} + +#else + static boolean loadSetupFileData(void *setup_file_data, char *filename, boolean top_recursion_level, boolean is_hash) { @@ -2085,6 +2258,8 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename, return TRUE; } +#endif + #else static boolean loadSetupFileData(void *setup_file_data, char *filename, @@ -2722,6 +2897,14 @@ void freeTreeInfo(TreeInfo *ti) checked_free(ti->special_flags); } + // recursively free child node + if (ti->node_group) + freeTreeInfo(ti->node_group); + + // recursively free next node + if (ti->next) + freeTreeInfo(ti->next); + checked_free(ti); } @@ -2772,7 +2955,7 @@ static int compareTreeInfoEntries(const void *object1, const void *object2) { const TreeInfo *entry1 = *((TreeInfo **)object1); const TreeInfo *entry2 = *((TreeInfo **)object2); - int class_sorting1, class_sorting2; + int class_sorting1 = 0, class_sorting2 = 0; int compare_result; if (entry1->type == TREE_TYPE_LEVEL_DIR) @@ -2780,7 +2963,9 @@ static int compareTreeInfoEntries(const void *object1, const void *object2) class_sorting1 = LEVELSORTING(entry1); class_sorting2 = LEVELSORTING(entry2); } - else + else if (entry1->type == TREE_TYPE_GRAPHICS_DIR || + entry1->type == TREE_TYPE_SOUNDS_DIR || + entry1->type == TREE_TYPE_MUSIC_DIR) { class_sorting1 = ARTWORKSORTING(entry1); class_sorting2 = ARTWORKSORTING(entry2); @@ -3220,41 +3405,71 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first, return TRUE; } +#if 1 static void LoadLevelInfoFromLevelDir(TreeInfo **node_first, TreeInfo *node_parent, char *level_directory) { - DIR *dir; - struct dirent *dir_entry; + Directory *dir; + DirectoryEntry *dir_entry; boolean valid_entry_found = FALSE; - if ((dir = opendir(level_directory)) == NULL) +#if 0 + Error(ERR_INFO, "looking for levels in '%s' ...", level_directory); +#endif + + if ((dir = openDirectory(level_directory)) == NULL) { Error(ERR_WARN, "cannot read level directory '%s'", level_directory); + return; } - while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */ +#if 0 + Error(ERR_INFO, "opening '%s' succeeded ...", level_directory); +#endif + + while ((dir_entry = readDirectory(dir)) != NULL) /* loop all entries */ { - struct stat file_status; - char *directory_name = dir_entry->d_name; + char *directory_name = dir_entry->basename; char *directory_path = getPath2(level_directory, directory_name); +#if 0 + Error(ERR_INFO, "checking entry '%s' ...", directory_name); +#endif + /* skip entries for current and parent directory */ if (strEqual(directory_name, ".") || strEqual(directory_name, "..")) { free(directory_path); + continue; } +#if 1 + /* find out if directory entry is itself a directory */ + if (!dir_entry->is_directory) /* not a directory */ + { + free(directory_path); + +#if 0 + Error(ERR_INFO, "* entry '%s' is not a directory ...", directory_name); +#endif + + continue; + } +#else /* find out if directory entry is itself a directory */ + struct stat file_status; if (stat(directory_path, &file_status) != 0 || /* cannot stat file */ (file_status.st_mode & S_IFMT) != S_IFDIR) /* not a directory */ { free(directory_path); + continue; } +#endif free(directory_path); @@ -3268,7 +3483,7 @@ static void LoadLevelInfoFromLevelDir(TreeInfo **node_first, directory_name); } - closedir(dir); + closeDirectory(dir); /* special case: top level directory may directly contain "levelinfo.conf" */ if (node_parent == NULL && !valid_entry_found) @@ -3283,15 +3498,94 @@ static void LoadLevelInfoFromLevelDir(TreeInfo **node_first, level_directory); } -boolean AdjustGraphicsForEMC() -{ - boolean settings_changed = FALSE; +#else - settings_changed |= adjustTreeGraphicsForEMC(leveldir_first_all); - settings_changed |= adjustTreeGraphicsForEMC(leveldir_first); +static void LoadLevelInfoFromLevelDir(TreeInfo **node_first, + TreeInfo *node_parent, + char *level_directory) +{ + DIR *dir; + struct dirent *dir_entry; + boolean valid_entry_found = FALSE; - return settings_changed; -} +#if 1 + Error(ERR_INFO, "looking for levels in '%s' ...", level_directory); +#endif + + if ((dir = opendir(level_directory)) == NULL) + { + Error(ERR_WARN, "cannot read level directory '%s'", level_directory); + + return; + } + +#if 1 + Error(ERR_INFO, "opening '%s' succeeded ...", level_directory); +#endif + + while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */ + { + struct stat file_status; + char *directory_name = dir_entry->d_name; + char *directory_path = getPath2(level_directory, directory_name); + +#if 1 + Error(ERR_INFO, "checking entry '%s' ...", directory_name); +#endif + + /* skip entries for current and parent directory */ + if (strEqual(directory_name, ".") || + strEqual(directory_name, "..")) + { + free(directory_path); + continue; + } + + /* find out if directory entry is itself a directory */ + if (stat(directory_path, &file_status) != 0 || /* cannot stat file */ + (file_status.st_mode & S_IFMT) != S_IFDIR) /* not a directory */ + { + free(directory_path); + continue; + } + + free(directory_path); + + if (strEqual(directory_name, GRAPHICS_DIRECTORY) || + strEqual(directory_name, SOUNDS_DIRECTORY) || + strEqual(directory_name, MUSIC_DIRECTORY)) + continue; + + valid_entry_found |= LoadLevelInfoFromLevelConf(node_first, node_parent, + level_directory, + directory_name); + } + + closedir(dir); + + /* special case: top level directory may directly contain "levelinfo.conf" */ + if (node_parent == NULL && !valid_entry_found) + { + /* check if this directory directly contains a file "levelinfo.conf" */ + valid_entry_found |= LoadLevelInfoFromLevelConf(node_first, node_parent, + level_directory, "."); + } + + if (!valid_entry_found) + Error(ERR_WARN, "cannot find any valid level series in directory '%s'", + level_directory); +} +#endif + +boolean AdjustGraphicsForEMC() +{ + boolean settings_changed = FALSE; + + settings_changed |= adjustTreeGraphicsForEMC(leveldir_first_all); + settings_changed |= adjustTreeGraphicsForEMC(leveldir_first); + + return settings_changed; +} void LoadLevelInfo() { @@ -3324,6 +3618,154 @@ void LoadLevelInfo() #endif } +#if 1 + +static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first, + TreeInfo *node_parent, + char *base_directory, + char *directory_name, int type) +{ + char *directory_path = getPath2(base_directory, directory_name); + char *filename = getPath2(directory_path, ARTWORKINFO_FILENAME(type)); + SetupFileHash *setup_file_hash = NULL; + TreeInfo *artwork_new = NULL; + int i; + + if (fileExists(filename)) + setup_file_hash = loadSetupFileHash(filename); + + if (setup_file_hash == NULL) /* no config file -- look for artwork files */ + { + Directory *dir; + DirectoryEntry *dir_entry; + boolean valid_file_found = FALSE; + + if ((dir = openDirectory(directory_path)) != NULL) + { + while ((dir_entry = readDirectory(dir)) != NULL) + { + char *entry_name = dir_entry->basename; + + if (FileIsArtworkType(entry_name, type)) + { + valid_file_found = TRUE; + + break; + } + } + + closeDirectory(dir); + } + + if (!valid_file_found) + { + if (!strEqual(directory_name, ".")) + Error(ERR_WARN, "ignoring artwork directory '%s'", directory_path); + + free(directory_path); + free(filename); + + return FALSE; + } + } + + artwork_new = newTreeInfo(); + + if (node_parent) + setTreeInfoToDefaultsFromParent(artwork_new, node_parent); + else + setTreeInfoToDefaults(artwork_new, type); + + artwork_new->subdir = getStringCopy(directory_name); + + if (setup_file_hash) /* (before defining ".color" and ".class_desc") */ + { +#if 0 + checkSetupFileHashIdentifier(setup_file_hash, filename, getCookie("...")); +#endif + + /* set all structure fields according to the token/value pairs */ + ldi = *artwork_new; + for (i = 0; i < NUM_LEVELINFO_TOKENS; i++) + setSetupInfo(levelinfo_tokens, i, + getHashEntry(setup_file_hash, levelinfo_tokens[i].text)); + *artwork_new = ldi; + + if (strEqual(artwork_new->name, ANONYMOUS_NAME)) + setString(&artwork_new->name, artwork_new->subdir); + + if (artwork_new->identifier == NULL) + artwork_new->identifier = getStringCopy(artwork_new->subdir); + + if (artwork_new->name_sorting == NULL) + artwork_new->name_sorting = getStringCopy(artwork_new->name); + } + + if (node_parent == NULL) /* top level group */ + { + artwork_new->basepath = getStringCopy(base_directory); + artwork_new->fullpath = getStringCopy(artwork_new->subdir); + } + else /* sub level group */ + { + artwork_new->basepath = getStringCopy(node_parent->basepath); + artwork_new->fullpath = getPath2(node_parent->fullpath, directory_name); + } + + artwork_new->in_user_dir = + (!strEqual(artwork_new->basepath, OPTIONS_ARTWORK_DIRECTORY(type))); + + /* (may use ".sort_priority" from "setup_file_hash" above) */ + artwork_new->color = ARTWORKCOLOR(artwork_new); + + setString(&artwork_new->class_desc, getLevelClassDescription(artwork_new)); + + if (setup_file_hash == NULL) /* (after determining ".user_defined") */ + { + if (strEqual(artwork_new->subdir, ".")) + { + if (artwork_new->user_defined) + { + setString(&artwork_new->identifier, "private"); + artwork_new->sort_priority = ARTWORKCLASS_PRIVATE; + } + else + { + setString(&artwork_new->identifier, "classic"); + artwork_new->sort_priority = ARTWORKCLASS_CLASSICS; + } + + /* set to new values after changing ".sort_priority" */ + artwork_new->color = ARTWORKCOLOR(artwork_new); + + setString(&artwork_new->class_desc, + getLevelClassDescription(artwork_new)); + } + else + { + setString(&artwork_new->identifier, artwork_new->subdir); + } + + setString(&artwork_new->name, artwork_new->identifier); + setString(&artwork_new->name_sorting, artwork_new->name); + } + +#if 0 + DrawInitText(artwork_new->name, 150, FC_YELLOW); +#endif + + pushTreeInfo(node_first, artwork_new); + + freeSetupFileHash(setup_file_hash); + + free(directory_path); + free(filename); + + return TRUE; +} + +#else + static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first, TreeInfo *node_parent, char *base_directory, @@ -3467,6 +3909,82 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first, return TRUE; } +#endif + +#if 1 + +static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first, + TreeInfo *node_parent, + char *base_directory, int type) +{ + Directory *dir; + DirectoryEntry *dir_entry; + boolean valid_entry_found = FALSE; + + if ((dir = openDirectory(base_directory)) == NULL) + { + /* display error if directory is main "options.graphics_directory" etc. */ + if (base_directory == OPTIONS_ARTWORK_DIRECTORY(type)) + Error(ERR_WARN, "cannot read directory '%s'", base_directory); + + return; + } + + while ((dir_entry = readDirectory(dir)) != NULL) /* loop all entries */ + { + char *directory_name = dir_entry->basename; + char *directory_path = getPath2(base_directory, directory_name); + + /* skip directory entries for current and parent directory */ + if (strEqual(directory_name, ".") || + strEqual(directory_name, "..")) + { + free(directory_path); + + continue; + } + +#if 1 + /* skip directory entries which are not a directory */ + if (!dir_entry->is_directory) /* not a directory */ + { + free(directory_path); + + continue; + } +#else + /* skip directory entries which are not a directory or are not accessible */ + struct stat file_status; + if (stat(directory_path, &file_status) != 0 || /* cannot stat file */ + (file_status.st_mode & S_IFMT) != S_IFDIR) /* not a directory */ + { + free(directory_path); + + continue; + } +#endif + + free(directory_path); + + /* check if this directory contains artwork with or without config file */ + valid_entry_found |= LoadArtworkInfoFromArtworkConf(node_first, node_parent, + base_directory, + directory_name, type); + } + + closeDirectory(dir); + + /* check if this directory directly contains artwork itself */ + valid_entry_found |= LoadArtworkInfoFromArtworkConf(node_first, node_parent, + base_directory, ".", + type); + if (!valid_entry_found) + Error(ERR_WARN, "cannot find any valid artwork in directory '%s'", + base_directory); +} + +#else + static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first, TreeInfo *node_parent, char *base_directory, int type) @@ -3525,6 +4043,8 @@ static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first, base_directory); } +#endif + static TreeInfo *getDummyArtworkInfo(int type) { /* this is only needed when there is completely no artwork available */ @@ -3692,14 +4212,23 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node, void LoadLevelArtworkInfo() { + print_timestamp_init("LoadLevelArtworkInfo"); + DrawInitText("Looking for custom level artwork", 120, FC_GREEN); + print_timestamp_time("DrawTimeText"); + LoadArtworkInfoFromLevelInfo(&artwork.gfx_first, leveldir_first_all); + print_timestamp_time("LoadArtworkInfoFromLevelInfo (gfx)"); LoadArtworkInfoFromLevelInfo(&artwork.snd_first, leveldir_first_all); + print_timestamp_time("LoadArtworkInfoFromLevelInfo (snd)"); LoadArtworkInfoFromLevelInfo(&artwork.mus_first, leveldir_first_all); + print_timestamp_time("LoadArtworkInfoFromLevelInfo (mus)"); SaveArtworkInfoCache(); + print_timestamp_time("SaveArtworkInfoCache"); + /* needed for reloading level artwork not known at ealier stage */ if (!strEqual(artwork.gfx_current_identifier, setup.graphics_set)) @@ -3735,15 +4264,21 @@ void LoadLevelArtworkInfo() artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first); } + print_timestamp_time("getTreeInfoFromIdentifier"); + sortTreeInfo(&artwork.gfx_first); sortTreeInfo(&artwork.snd_first); sortTreeInfo(&artwork.mus_first); + print_timestamp_time("sortTreeInfo"); + #if 0 dumpTreeInfo(artwork.gfx_first, 0); dumpTreeInfo(artwork.snd_first, 0); dumpTreeInfo(artwork.mus_first, 0); #endif + + print_timestamp_done("LoadLevelArtworkInfo"); } static void SaveUserLevelInfo() @@ -3944,12 +4479,16 @@ void LoadLevelSetup_LastSeries() free(filename); } -void SaveLevelSetup_LastSeries() +static void SaveLevelSetup_LastSeries_Ext(boolean deactivate_last_level_series) { /* ----------------------------------------------------------------------- */ /* ~/./levelsetup.conf */ /* ----------------------------------------------------------------------- */ + // check if the current level directory structure is available at this point + if (leveldir_current == NULL) + return; + char *filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME); char *level_subdir = leveldir_current->subdir; FILE *file; @@ -3959,12 +4498,18 @@ void SaveLevelSetup_LastSeries() if (!(file = fopen(filename, MODE_WRITE))) { Error(ERR_WARN, "cannot write setup file '%s'", filename); + free(filename); + return; } fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, getCookie("LEVELSETUP"))); + + if (deactivate_last_level_series) + fprintf(file, "# %s\n# ", "the following level set may have caused a problem and was deactivated"); + fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_LEVEL_SERIES, level_subdir)); @@ -3975,6 +4520,74 @@ void SaveLevelSetup_LastSeries() free(filename); } +void SaveLevelSetup_LastSeries() +{ + SaveLevelSetup_LastSeries_Ext(FALSE); +} + +void SaveLevelSetup_LastSeries_Deactivate() +{ + SaveLevelSetup_LastSeries_Ext(TRUE); +} + +#if 1 + +static void checkSeriesInfo() +{ + static char *level_directory = NULL; + Directory *dir; +#if 0 + DirectoryEntry *dir_entry; +#endif + + /* check for more levels besides the 'levels' field of 'levelinfo.conf' */ + + level_directory = getPath2((leveldir_current->in_user_dir ? + getUserLevelDir(NULL) : + options.level_directory), + leveldir_current->fullpath); + + if ((dir = openDirectory(level_directory)) == NULL) + { + Error(ERR_WARN, "cannot read level directory '%s'", level_directory); + + return; + } + +#if 0 + while ((dir_entry = readDirectory(dir)) != NULL) /* last directory entry */ + { + if (strlen(dir_entry->basename) > 4 && + dir_entry->basename[3] == '.' && + strEqual(&dir_entry->basename[4], LEVELFILE_EXTENSION)) + { + char levelnum_str[4]; + int levelnum_value; + + strncpy(levelnum_str, dir_entry->basename, 3); + levelnum_str[3] = '\0'; + + levelnum_value = atoi(levelnum_str); + + if (levelnum_value < leveldir_current->first_level) + { + Error(ERR_WARN, "additional level %d found", levelnum_value); + leveldir_current->first_level = levelnum_value; + } + else if (levelnum_value > leveldir_current->last_level) + { + Error(ERR_WARN, "additional level %d found", levelnum_value); + leveldir_current->last_level = levelnum_value; + } + } + } +#endif + + closeDirectory(dir); +} + +#else + static void checkSeriesInfo() { static char *level_directory = NULL; @@ -4029,6 +4642,8 @@ static void checkSeriesInfo() closedir(dir); } +#endif + void LoadLevelSetup_SeriesInfo() { char *filename;