X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsetup.c;h=2a86f2be07706c0380ea7ad7a13494f401a1ca39;hb=512f7bbfa113ed92bebc8a3a7d436b38c0227d59;hp=eec6cb5a6ca1f6b5d187037bc32dcf35ebc172e5;hpb=f11d2545f41637e871283f7624dccc8243d05138;p=rocksndiamonds.git diff --git a/src/libgame/setup.c b/src/libgame/setup.c index eec6cb5a..2a86f2be 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -4,7 +4,7 @@ // (c) 1995-2014 by Artsoft Entertainment // Holger Schemel // info@artsoft.org -// http://www.artsoft.org/ +// https://www.artsoft.org/ // ---------------------------------------------------------------------------- // setup.c // ============================================================================ @@ -18,11 +18,6 @@ #include "platform.h" -#if !defined(PLATFORM_WIN32) -#include -#include -#endif - #include "setup.h" #include "joystick.h" #include "text.h" @@ -99,6 +94,7 @@ static int token_comment_position = TOKEN_COMMENT_POSITION_DEFAULT; static SetupFileHash *artworkinfo_cache_old = NULL; static SetupFileHash *artworkinfo_cache_new = NULL; +static SetupFileHash *optional_tokens_hash = NULL; static boolean use_artworkinfo_cache = TRUE; @@ -178,7 +174,7 @@ static char *getNetworkDir(void) return network_dir; } -static char *getLevelDirFromTreeInfo(TreeInfo *node) +char *getLevelDirFromTreeInfo(TreeInfo *node) { static char *level_dir = NULL; @@ -457,7 +453,7 @@ char *getProgramMainDataPath(char *command_filename, char *base_path) { // check if the program's main data base directory is configured if (!strEqual(base_path, ".")) - return base_path; + return getStringCopy(base_path); /* if the program is configured to start from current directory (default), determine program package directory from program binary (some versions @@ -494,22 +490,41 @@ char *getProgramMainDataPath(char *command_filename, char *base_path) char *getProgramConfigFilename(char *command_filename) { - char *command_filename_1 = getStringCopy(command_filename); + static char *config_filename_1 = NULL; + static char *config_filename_2 = NULL; + static char *config_filename_3 = NULL; + static boolean initialized = FALSE; + + if (!initialized) + { + char *command_filename_1 = getStringCopy(command_filename); + + // strip trailing executable suffix from command filename + if (strSuffix(command_filename_1, ".exe")) + command_filename_1[strlen(command_filename_1) - 4] = '\0'; - // strip trailing executable suffix from command filename - if (strSuffix(command_filename_1, ".exe")) - command_filename_1[strlen(command_filename_1) - 4] = '\0'; + char *ro_base_path = getProgramMainDataPath(command_filename, RO_BASE_PATH); + char *conf_directory = getPath2(ro_base_path, CONF_DIRECTORY); - char *ro_base_path = getProgramMainDataPath(command_filename, RO_BASE_PATH); - char *conf_directory = getPath2(ro_base_path, CONF_DIRECTORY); + char *command_basepath = getBasePath(command_filename); + char *command_basename = getBaseNameNoSuffix(command_filename); + char *command_filename_2 = getPath2(command_basepath, command_basename); - char *command_basepath = getBasePath(command_filename); - char *command_basename = getBaseNameNoSuffix(command_filename); - char *command_filename_2 = getPath2(command_basepath, command_basename); + config_filename_1 = getStringCat2(command_filename_1, ".conf"); + config_filename_2 = getStringCat2(command_filename_2, ".conf"); + config_filename_3 = getPath2(conf_directory, SETUP_FILENAME); - char *config_filename_1 = getStringCat2(command_filename_1, ".conf"); - char *config_filename_2 = getStringCat2(command_filename_2, ".conf"); - char *config_filename_3 = getPath2(conf_directory, SETUP_FILENAME); + checked_free(ro_base_path); + checked_free(conf_directory); + + checked_free(command_basepath); + checked_free(command_basename); + + checked_free(command_filename_1); + checked_free(command_filename_2); + + initialized = TRUE; + } // 1st try: look for config file that exactly matches the binary filename if (fileExists(config_filename_1)) @@ -800,9 +815,7 @@ char *getCustomImageFilename(char *basename) { free(filename); - if (options.debug) - Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", - basename); + Warn("cannot find artwork file '%s' (using fallback)", basename); // 6th try: look for fallback artwork in old default artwork directory // (needed to prevent errors when trying to access unused artwork files) @@ -873,9 +886,7 @@ char *getCustomSoundFilename(char *basename) { free(filename); - if (options.debug) - Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", - basename); + Warn("cannot find artwork file '%s' (using fallback)", basename); // 6th try: look for fallback artwork in old default artwork directory // (needed to prevent errors when trying to access unused artwork files) @@ -946,9 +957,7 @@ char *getCustomMusicFilename(char *basename) { free(filename); - if (options.debug) - Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", - basename); + Warn("cannot find artwork file '%s' (using fallback)", basename); // 6th try: look for fallback artwork in old default artwork directory // (needed to prevent errors when trying to access unused artwork files) @@ -1074,7 +1083,8 @@ void InitUserLevelDirectory(char *level_subdir) createDirectory(getUserLevelDir(NULL), "main user level", PERMS_PRIVATE); createDirectory(getUserLevelDir(level_subdir), "user level", PERMS_PRIVATE); - SaveUserLevelInfo(); + if (setup.internal.create_user_levelset) + SaveUserLevelInfo(); } } @@ -1282,21 +1292,59 @@ static boolean adjustTreeGraphicsForEMC(TreeInfo *node) while (node) { - if (node->graphics_set_ecs && !setup.prefer_aga_graphics && - !strEqual(node->graphics_set, node->graphics_set_ecs)) + boolean want_ecs = (setup.prefer_aga_graphics == FALSE); + boolean want_aga = (setup.prefer_aga_graphics == TRUE); + boolean has_only_ecs = (!node->graphics_set && !node->graphics_set_aga); + boolean has_only_aga = (!node->graphics_set && !node->graphics_set_ecs); + char *graphics_set = NULL; + + if (node->graphics_set_ecs && (want_ecs || has_only_ecs)) + graphics_set = node->graphics_set_ecs; + + if (node->graphics_set_aga && (want_aga || has_only_aga)) + graphics_set = node->graphics_set_aga; + + if (graphics_set && !strEqual(node->graphics_set, graphics_set)) { - setString(&node->graphics_set, node->graphics_set_ecs); + setString(&node->graphics_set, graphics_set); settings_changed = TRUE; } - else if (node->graphics_set_aga && setup.prefer_aga_graphics && - !strEqual(node->graphics_set, node->graphics_set_aga)) + + if (node->node_group != NULL) + settings_changed |= adjustTreeGraphicsForEMC(node->node_group); + + node = node->next; + } + + return settings_changed; +} + +static boolean adjustTreeSoundsForEMC(TreeInfo *node) +{ + boolean settings_changed = FALSE; + + while (node) + { + boolean want_default = (setup.prefer_lowpass_sounds == FALSE); + boolean want_lowpass = (setup.prefer_lowpass_sounds == TRUE); + boolean has_only_default = (!node->sounds_set && !node->sounds_set_lowpass); + boolean has_only_lowpass = (!node->sounds_set && !node->sounds_set_default); + char *sounds_set = NULL; + + if (node->sounds_set_default && (want_default || has_only_default)) + sounds_set = node->sounds_set_default; + + if (node->sounds_set_lowpass && (want_lowpass || has_only_lowpass)) + sounds_set = node->sounds_set_lowpass; + + if (sounds_set && !strEqual(node->sounds_set, sounds_set)) { - setString(&node->graphics_set, node->graphics_set_aga); + setString(&node->sounds_set, sounds_set); settings_changed = TRUE; } if (node->node_group != NULL) - settings_changed |= adjustTreeGraphicsForEMC(node->node_group); + settings_changed |= adjustTreeSoundsForEMC(node->node_group); node = node->next; } @@ -1308,19 +1356,19 @@ void dumpTreeInfo(TreeInfo *node, int depth) { int i; - printf("Dumping TreeInfo:\n"); + Debug("tree", "Dumping TreeInfo:"); while (node) { for (i = 0; i < (depth + 1) * 3; i++) - printf(" "); + DebugContinued("", " "); - printf("'%s' / '%s'\n", node->identifier, node->name); + DebugContinued("tree", "'%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); + Debug("tree", "subdir == '%s' ['%s', '%s'] [%d])", + node->subdir, node->fullpath, node->basepath, node->in_user_dir); */ if (node->node_group != NULL) @@ -1451,10 +1499,10 @@ char *getHomeDir(void) { if ((dir = getenv("HOME")) == NULL) { - struct passwd *pwd; + dir = getUnixHomeDir(); - if ((pwd = getpwuid(getuid())) != NULL) - dir = getStringCopy(pwd->pw_dir); + if (dir != NULL) + dir = getStringCopy(dir); else dir = "."; } @@ -1580,8 +1628,7 @@ void createDirectory(char *dir, char *text, int permission_class) } if (posix_mkdir(dir, dir_mode) != 0) - Error(ERR_WARN, "cannot create %s directory '%s': %s", - text, dir, strerror(errno)); + Warn("cannot create %s directory '%s': %s", text, dir, strerror(errno)); if (permission_class == PERMS_PUBLIC && !running_setgid) chmod(dir, dir_mode); @@ -1778,8 +1825,8 @@ static void printSetupFileList(SetupFileList *list) if (!list) return; - printf("token: '%s'\n", list->token); - printf("value: '%s'\n", list->value); + Debug("setup:printSetupFileList", "token: '%s'", list->token); + Debug("setup:printSetupFileList", "value: '%s'", list->value); printSetupFileList(list->next); } @@ -1839,7 +1886,7 @@ SetupFileHash *newSetupFileHash(void) create_hashtable(16, 0.75, get_hash_from_key, keys_are_equal); if (new_hash == NULL) - Error(ERR_EXIT, "create_hashtable() failed -- out of memory"); + Fail("create_hashtable() failed -- out of memory"); return new_hash; } @@ -1872,7 +1919,7 @@ void setHashEntry(SetupFileHash *hash, char *token, char *value) // change value; if it does not exist, insert it as new if (!change_hash_entry(hash, token, value_copy)) if (!insert_hash_entry(hash, getStringCopy(token), value_copy)) - Error(ERR_EXIT, "cannot insert into hash -- aborting"); + Fail("cannot insert into hash -- aborting"); } char *removeHashEntry(SetupFileHash *hash, char *token) @@ -1889,8 +1936,8 @@ static void printSetupFileHash(SetupFileHash *hash) { BEGIN_HASH_ITERATION(hash, itr) { - printf("token: '%s'\n", HASH_ITERATION_TOKEN(itr)); - printf("value: '%s'\n", HASH_ITERATION_VALUE(itr)); + Debug("setup:printSetupFileHash", "token: '%s'", HASH_ITERATION_TOKEN(itr)); + Debug("setup:printSetupFileHash", "value: '%s'", HASH_ITERATION_VALUE(itr)); } END_HASH_ITERATION(hash, itr) } @@ -1995,25 +2042,25 @@ static boolean getTokenValueFromSetupLineExt(char *line, { if (!token_value_separator_warning) { - Error(ERR_INFO_LINE, "-"); + Debug("setup", "---"); if (filename != NULL) { - Error(ERR_WARN, "missing token/value separator(s) in config file:"); - Error(ERR_INFO, "- config file: '%s'", filename); + Debug("setup", "missing token/value separator(s) in config file:"); + Debug("setup", "- config file: '%s'", filename); } else { - Error(ERR_WARN, "missing token/value separator(s):"); + Debug("setup", "missing token/value separator(s):"); } token_value_separator_warning = TRUE; } if (filename != NULL) - Error(ERR_INFO, "- line %d: '%s'", line_nr, line_raw); + Debug("setup", "- line %d: '%s'", line_nr, line_raw); else - Error(ERR_INFO, "- line: '%s'", line_raw); + Debug("setup", "- line: '%s'", line_raw); } #endif } @@ -2066,7 +2113,7 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename, if (!(file = openFile(filename, MODE_READ))) { #if DEBUG_NO_CONFIG_FILE - Error(ERR_DEBUG, "cannot open configuration file '%s'", filename); + Debug("setup", "cannot open configuration file '%s'", filename); #endif return FALSE; @@ -2147,7 +2194,7 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename, } else { - Error(ERR_WARN, "ignoring already processed file '%s'", value); + Warn("ignoring already processed file '%s'", value); } } else @@ -2162,16 +2209,16 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename, { 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); + Debug("setup", "---"); + Debug("setup", "duplicate token(s) found in config file:"); + Debug("setup", "- 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); + Debug("setup", "- token: '%s' (in line %d)", token, line_nr); + Debug("setup", " old value: '%s'", old_value); + Debug("setup", " new value: '%s'", value); } #endif @@ -2191,16 +2238,16 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename, #if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING if (token_value_separator_warning) - Error(ERR_INFO_LINE, "-"); + Debug("setup", "---"); #endif #if CHECK_TOKEN__WARN_IF_ALREADY_EXISTS_IN_HASH if (token_already_exists_warning) - Error(ERR_INFO_LINE, "-"); + Debug("setup", "---"); #endif if (token_count == 0 && include_count == 0) - Error(ERR_WARN, "configuration file '%s' is empty", filename); + Warn("configuration file '%s' is empty", filename); if (top_recursion_level) freeSetupFileHash(include_filename_hash); @@ -2214,7 +2261,7 @@ static void saveSetupFileHash(SetupFileHash *hash, char *filename) if (!(file = fopen(filename, MODE_WRITE))) { - Error(ERR_WARN, "cannot write configuration file '%s'", filename); + Warn("cannot write configuration file '%s'", filename); return; } @@ -2294,15 +2341,18 @@ SetupFileHash *loadSetupFileHash(char *filename) #define LEVELINFO_TOKEN_GRAPHICS_SET_ECS 17 #define LEVELINFO_TOKEN_GRAPHICS_SET_AGA 18 #define LEVELINFO_TOKEN_GRAPHICS_SET 19 -#define LEVELINFO_TOKEN_SOUNDS_SET 20 -#define LEVELINFO_TOKEN_MUSIC_SET 21 -#define LEVELINFO_TOKEN_FILENAME 22 -#define LEVELINFO_TOKEN_FILETYPE 23 -#define LEVELINFO_TOKEN_SPECIAL_FLAGS 24 -#define LEVELINFO_TOKEN_HANDICAP 25 -#define LEVELINFO_TOKEN_SKIP_LEVELS 26 - -#define NUM_LEVELINFO_TOKENS 27 +#define LEVELINFO_TOKEN_SOUNDS_SET_DEFAULT 20 +#define LEVELINFO_TOKEN_SOUNDS_SET_LOWPASS 21 +#define LEVELINFO_TOKEN_SOUNDS_SET 22 +#define LEVELINFO_TOKEN_MUSIC_SET 23 +#define LEVELINFO_TOKEN_FILENAME 24 +#define LEVELINFO_TOKEN_FILETYPE 25 +#define LEVELINFO_TOKEN_SPECIAL_FLAGS 26 +#define LEVELINFO_TOKEN_HANDICAP 27 +#define LEVELINFO_TOKEN_SKIP_LEVELS 28 +#define LEVELINFO_TOKEN_USE_EMC_TILES 29 + +#define NUM_LEVELINFO_TOKENS 30 static LevelDirTree ldi; @@ -2329,13 +2379,16 @@ static struct TokenInfo levelinfo_tokens[] = { TYPE_STRING, &ldi.graphics_set_ecs, "graphics_set.ecs" }, { TYPE_STRING, &ldi.graphics_set_aga, "graphics_set.aga" }, { TYPE_STRING, &ldi.graphics_set, "graphics_set" }, + { TYPE_STRING, &ldi.sounds_set_default,"sounds_set.default" }, + { TYPE_STRING, &ldi.sounds_set_lowpass,"sounds_set.lowpass" }, { TYPE_STRING, &ldi.sounds_set, "sounds_set" }, { TYPE_STRING, &ldi.music_set, "music_set" }, { TYPE_STRING, &ldi.level_filename, "filename" }, { TYPE_STRING, &ldi.level_filetype, "filetype" }, { TYPE_STRING, &ldi.special_flags, "special_flags" }, { TYPE_BOOLEAN, &ldi.handicap, "handicap" }, - { TYPE_BOOLEAN, &ldi.skip_levels, "skip_levels" } + { TYPE_BOOLEAN, &ldi.skip_levels, "skip_levels" }, + { TYPE_BOOLEAN, &ldi.use_emc_tiles, "use_emc_tiles" } }; static struct TokenInfo artworkinfo_tokens[] = @@ -2359,6 +2412,15 @@ static struct TokenInfo artworkinfo_tokens[] = { -1, NULL, NULL }, }; +static char *optional_tokens[] = +{ + "program_title", + "program_copyright", + "program_company", + + NULL +}; + static void setTreeInfoToDefaults(TreeInfo *ti, int type) { ti->type = type; @@ -2408,6 +2470,8 @@ static void setTreeInfoToDefaults(TreeInfo *ti, int type) ti->graphics_set_ecs = NULL; ti->graphics_set_aga = NULL; ti->graphics_set = NULL; + ti->sounds_set_default = NULL; + ti->sounds_set_lowpass = NULL; ti->sounds_set = NULL; ti->music_set = NULL; ti->graphics_path = getStringCopy(UNDEFINED_FILENAME); @@ -2427,6 +2491,8 @@ static void setTreeInfoToDefaults(TreeInfo *ti, int type) ti->readonly = TRUE; ti->handicap = TRUE; ti->skip_levels = FALSE; + + ti->use_emc_tiles = FALSE; } } @@ -2434,7 +2500,7 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent) { if (parent == NULL) { - Error(ERR_WARN, "setTreeInfoToDefaultsFromParent(): parent == NULL"); + Warn("setTreeInfoToDefaultsFromParent(): parent == NULL"); setTreeInfoToDefaults(ti, TREE_TYPE_UNDEFINED); @@ -2485,6 +2551,8 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent) ti->graphics_set_ecs = getStringCopy(parent->graphics_set_ecs); ti->graphics_set_aga = getStringCopy(parent->graphics_set_aga); ti->graphics_set = getStringCopy(parent->graphics_set); + ti->sounds_set_default = getStringCopy(parent->sounds_set_default); + ti->sounds_set_lowpass = getStringCopy(parent->sounds_set_lowpass); ti->sounds_set = getStringCopy(parent->sounds_set); ti->music_set = getStringCopy(parent->music_set); ti->graphics_path = getStringCopy(UNDEFINED_FILENAME); @@ -2504,6 +2572,8 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent) ti->readonly = parent->readonly; ti->handicap = parent->handicap; ti->skip_levels = parent->skip_levels; + + ti->use_emc_tiles = parent->use_emc_tiles; } } @@ -2543,6 +2613,8 @@ static TreeInfo *getTreeInfoCopy(TreeInfo *ti) ti_copy->graphics_set_ecs = getStringCopy(ti->graphics_set_ecs); ti_copy->graphics_set_aga = getStringCopy(ti->graphics_set_aga); ti_copy->graphics_set = getStringCopy(ti->graphics_set); + ti_copy->sounds_set_default = getStringCopy(ti->sounds_set_default); + ti_copy->sounds_set_lowpass = getStringCopy(ti->sounds_set_lowpass); ti_copy->sounds_set = getStringCopy(ti->sounds_set); ti_copy->music_set = getStringCopy(ti->music_set); ti_copy->graphics_path = getStringCopy(ti->graphics_path); @@ -2569,6 +2641,8 @@ static TreeInfo *getTreeInfoCopy(TreeInfo *ti) ti_copy->handicap = ti->handicap; ti_copy->skip_levels = ti->skip_levels; + ti_copy->use_emc_tiles = ti->use_emc_tiles; + ti_copy->color = ti->color; ti_copy->class_desc = getStringCopy(ti->class_desc); ti_copy->handicap_level = ti->handicap_level; @@ -2610,6 +2684,8 @@ void freeTreeInfo(TreeInfo *ti) checked_free(ti->graphics_set_ecs); checked_free(ti->graphics_set_aga); checked_free(ti->graphics_set); + checked_free(ti->sounds_set_default); + checked_free(ti->sounds_set_lowpass); checked_free(ti->sounds_set); checked_free(ti->music_set); @@ -2879,6 +2955,16 @@ static TreeInfo *getArtworkInfoCacheEntry(LevelDirTree *level_node, int type) if (!use_artworkinfo_cache) return NULL; + if (optional_tokens_hash == NULL) + { + int i; + + // create hash from list of optional tokens (for quick access) + optional_tokens_hash = newSetupFileHash(); + for (i = 0; optional_tokens[i] != NULL; i++) + setHashEntry(optional_tokens_hash, optional_tokens[i], ""); + } + if (cached) { int i; @@ -2890,16 +2976,28 @@ static TreeInfo *getArtworkInfoCacheEntry(LevelDirTree *level_node, int type) ldi = *artwork_info; for (i = 0; artworkinfo_tokens[i].type != -1; i++) { - char *token = getCacheToken(token_prefix, artworkinfo_tokens[i].text); + char *token_suffix = artworkinfo_tokens[i].text; + char *token = getCacheToken(token_prefix, token_suffix); char *value = getHashEntry(artworkinfo_cache_old, token); + boolean optional = + (getHashEntry(optional_tokens_hash, token_suffix) != NULL); - // if defined, use value from cache, else keep default value - if (value != NULL) - setSetupInfo(artworkinfo_tokens, i, value); + setSetupInfo(artworkinfo_tokens, i, value); + + // check if cache entry for this item is mandatory, but missing + if (value == NULL && !optional) + { + Warn("missing cache entry '%s'", token); + + cached = FALSE; + } } *artwork_info = ldi; + } + if (cached) + { char *filename_levelinfo = getPath2(getLevelDirFromTreeInfo(level_node), LEVELINFO_FILENAME); char *filename_artworkinfo = getPath2(getSetupArtworkDir(artwork_info), @@ -3118,28 +3216,37 @@ static boolean CheckZipFileForDirectory(char *zip_filename, char *directory, return TRUE; } -boolean ExtractZipFileIntoDirectory(char *zip_filename, char *directory, - int tree_type) +char *ExtractZipFileIntoDirectory(char *zip_filename, char *directory, + int tree_type) { boolean zip_file_valid = CheckZipFileForDirectory(zip_filename, directory, tree_type); - Error(ERR_DEBUG, "zip file '%s': %s", zip_filename, - (zip_file_valid ? "EXTRACT" : "REJECT")); - if (!zip_file_valid) - return FALSE; + { + Warn("zip file '%s' rejected!", zip_filename); + + return NULL; + } char **zip_entries = zip_extract(zip_filename, directory); - boolean zip_file_extracted = (zip_entries != NULL); + if (zip_entries == NULL) + { + Warn("zip file '%s' could not be extracted!", zip_filename); - if (zip_file_extracted) - Error(ERR_DEBUG, "zip file successfully extracted!"); - else - Error(ERR_DEBUG, "zip file could not be extracted!"); + return NULL; + } + + Info("zip file '%s' successfully extracted!", zip_filename); - return zip_file_extracted; + // first zip file entry contains top level directory + char *top_dir = zip_entries[0]; + + // remove trailing directory separator from top level directory + top_dir[strlen(top_dir) - 1] = '\0'; + + return top_dir; } static void ProcessZipFilesInDirectory(char *directory, int tree_type) @@ -3152,7 +3259,7 @@ static void ProcessZipFilesInDirectory(char *directory, int tree_type) // display error if directory is main "options.graphics_directory" etc. if (tree_type == TREE_TYPE_LEVEL_DIR || directory == OPTIONS_ARTWORK_DIRECTORY(tree_type)) - Error(ERR_WARN, "cannot read directory '%s'", directory); + Warn("cannot read directory '%s'", directory); return; } @@ -3171,10 +3278,9 @@ static void ProcessZipFilesInDirectory(char *directory, int tree_type) if (!fileExists(zip_filename_extracted) && !fileExists(zip_filename_rejected)) { - boolean zip_file_extracted = ExtractZipFileIntoDirectory(zip_filename, - directory, - tree_type); - char *marker_filename = (zip_file_extracted ? zip_filename_extracted : + char *top_dir = ExtractZipFileIntoDirectory(zip_filename, directory, + tree_type); + char *marker_filename = (top_dir != NULL ? zip_filename_extracted : zip_filename_rejected); FILE *marker_file; @@ -3219,7 +3325,7 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first, if (setup_file_hash == NULL) { #if DEBUG_NO_CONFIG_FILE - Error(ERR_WARN, "ignoring level directory '%s'", directory_path); + Debug("setup", "ignoring level directory '%s'", directory_path); #endif free(directory_path); @@ -3330,7 +3436,7 @@ static void LoadLevelInfoFromLevelDir(TreeInfo **node_first, if ((dir = openDirectory(level_directory)) == NULL) { - Error(ERR_WARN, "cannot read level directory '%s'", level_directory); + Warn("cannot read level directory '%s'", level_directory); return; } @@ -3380,7 +3486,7 @@ static void LoadLevelInfoFromLevelDir(TreeInfo **node_first, } if (!valid_entry_found) - Error(ERR_WARN, "cannot find any valid level series in directory '%s'", + Warn("cannot find any valid level series in directory '%s'", level_directory); } @@ -3394,6 +3500,16 @@ boolean AdjustGraphicsForEMC(void) return settings_changed; } +boolean AdjustSoundsForEMC(void) +{ + boolean settings_changed = FALSE; + + settings_changed |= adjustTreeSoundsForEMC(leveldir_first_all); + settings_changed |= adjustTreeSoundsForEMC(leveldir_first); + + return settings_changed; +} + void LoadLevelInfo(void) { InitUserLevelDirectory(getLoginName()); @@ -3413,12 +3529,13 @@ void LoadLevelInfo(void) cloneTree(&leveldir_first, leveldir_first_all, TRUE); AdjustGraphicsForEMC(); + AdjustSoundsForEMC(); // before sorting, the first entries will be from the user directory leveldir_current = getFirstValidTreeInfoEntry(leveldir_first); if (leveldir_first == NULL) - Error(ERR_EXIT, "cannot find any valid level series in any directory"); + Fail("cannot find any valid level series in any directory"); sortTreeInfo(&leveldir_first); @@ -3466,7 +3583,7 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first, { #if DEBUG_NO_CONFIG_FILE if (!strEqual(directory_name, ".")) - Error(ERR_WARN, "ignoring artwork directory '%s'", directory_path); + Debug("setup", "ignoring artwork directory '%s'", directory_path); #endif free(directory_path); @@ -3581,7 +3698,7 @@ static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first, { // 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); + Warn("cannot read directory '%s'", base_directory); return; } @@ -3623,8 +3740,7 @@ static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first, base_directory, ".", type); if (!valid_entry_found) - Error(ERR_WARN, "cannot find any valid artwork in directory '%s'", - base_directory); + Warn("cannot find any valid artwork in directory '%s'", base_directory); } static TreeInfo *getDummyArtworkInfo(int type) @@ -3645,6 +3761,34 @@ static TreeInfo *getDummyArtworkInfo(int type) return artwork_new; } +void SetCurrentArtwork(int type) +{ + ArtworkDirTree **current_ptr = ARTWORK_CURRENT_PTR(artwork, type); + ArtworkDirTree *first_node = ARTWORK_FIRST_NODE(artwork, type); + char *setup_set = SETUP_ARTWORK_SET(setup, type); + char *default_subdir = ARTWORK_DEFAULT_SUBDIR(type); + + // set current artwork to artwork configured in setup menu + *current_ptr = getTreeInfoFromIdentifier(first_node, setup_set); + + // if not found, set current artwork to default artwork + if (*current_ptr == NULL) + *current_ptr = getTreeInfoFromIdentifier(first_node, default_subdir); + + // if not found, set current artwork to first artwork in tree + if (*current_ptr == NULL) + *current_ptr = getFirstValidTreeInfoEntry(first_node); +} + +void ChangeCurrentArtworkIfNeeded(int type) +{ + char *current_identifier = ARTWORK_CURRENT_IDENTIFIER(artwork, type); + char *setup_set = SETUP_ARTWORK_SET(setup, type); + + if (!strEqual(current_identifier, setup_set)) + SetCurrentArtwork(type); +} + void LoadArtworkInfo(void) { LoadArtworkInfoCache(); @@ -3680,38 +3824,21 @@ void LoadArtworkInfo(void) artwork.mus_first = getDummyArtworkInfo(TREE_TYPE_MUSIC_DIR); // before sorting, the first entries will be from the user directory - artwork.gfx_current = - getTreeInfoFromIdentifier(artwork.gfx_first, setup.graphics_set); - if (artwork.gfx_current == NULL) - artwork.gfx_current = - getTreeInfoFromIdentifier(artwork.gfx_first, GFX_DEFAULT_SUBDIR); - if (artwork.gfx_current == NULL) - artwork.gfx_current = getFirstValidTreeInfoEntry(artwork.gfx_first); - - artwork.snd_current = - getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set); - if (artwork.snd_current == NULL) - artwork.snd_current = - getTreeInfoFromIdentifier(artwork.snd_first, SND_DEFAULT_SUBDIR); - if (artwork.snd_current == NULL) - artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first); - - artwork.mus_current = - getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set); - if (artwork.mus_current == NULL) - artwork.mus_current = - getTreeInfoFromIdentifier(artwork.mus_first, MUS_DEFAULT_SUBDIR); - if (artwork.mus_current == NULL) - artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first); + SetCurrentArtwork(ARTWORK_TYPE_GRAPHICS); + SetCurrentArtwork(ARTWORK_TYPE_SOUNDS); + SetCurrentArtwork(ARTWORK_TYPE_MUSIC); artwork.gfx_current_identifier = artwork.gfx_current->identifier; artwork.snd_current_identifier = artwork.snd_current->identifier; artwork.mus_current_identifier = artwork.mus_current->identifier; #if ENABLE_UNUSED_CODE - printf("graphics set == %s\n\n", artwork.gfx_current_identifier); - printf("sounds set == %s\n\n", artwork.snd_current_identifier); - printf("music set == %s\n\n", artwork.mus_current_identifier); + Debug("setup:LoadArtworkInfo", "graphics set == %s", + artwork.gfx_current_identifier); + Debug("setup:LoadArtworkInfo", "sounds set == %s", + artwork.snd_current_identifier); + Debug("setup:LoadArtworkInfo", "music set == %s", + artwork.mus_current_identifier); #endif sortTreeInfo(&artwork.gfx_first); @@ -3801,39 +3928,9 @@ void LoadLevelArtworkInfo(void) print_timestamp_time("SaveArtworkInfoCache"); // needed for reloading level artwork not known at ealier stage - - if (!strEqual(artwork.gfx_current_identifier, setup.graphics_set)) - { - artwork.gfx_current = - getTreeInfoFromIdentifier(artwork.gfx_first, setup.graphics_set); - if (artwork.gfx_current == NULL) - artwork.gfx_current = - getTreeInfoFromIdentifier(artwork.gfx_first, GFX_DEFAULT_SUBDIR); - if (artwork.gfx_current == NULL) - artwork.gfx_current = getFirstValidTreeInfoEntry(artwork.gfx_first); - } - - if (!strEqual(artwork.snd_current_identifier, setup.sounds_set)) - { - artwork.snd_current = - getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set); - if (artwork.snd_current == NULL) - artwork.snd_current = - getTreeInfoFromIdentifier(artwork.snd_first, SND_DEFAULT_SUBDIR); - if (artwork.snd_current == NULL) - artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first); - } - - if (!strEqual(artwork.mus_current_identifier, setup.music_set)) - { - artwork.mus_current = - getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set); - if (artwork.mus_current == NULL) - artwork.mus_current = - getTreeInfoFromIdentifier(artwork.mus_first, MUS_DEFAULT_SUBDIR); - if (artwork.mus_current == NULL) - artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first); - } + ChangeCurrentArtworkIfNeeded(ARTWORK_TYPE_GRAPHICS); + ChangeCurrentArtworkIfNeeded(ARTWORK_TYPE_SOUNDS); + ChangeCurrentArtworkIfNeeded(ARTWORK_TYPE_MUSIC); print_timestamp_time("getTreeInfoFromIdentifier"); @@ -3852,13 +3949,34 @@ void LoadLevelArtworkInfo(void) print_timestamp_done("LoadLevelArtworkInfo"); } -static boolean AddUserLevelSetToLevelInfoExt(char *level_subdir_new) +static boolean AddTreeSetToTreeInfoExt(TreeInfo *tree_node_old, char *tree_dir, + char *tree_subdir_new, int type) { - // get level info tree node of first (original) user level set - char *level_subdir_old = getLoginName(); - LevelDirTree *leveldir_old = getTreeInfoFromIdentifier(leveldir_first, - level_subdir_old); - if (leveldir_old == NULL) // should not happen + if (tree_node_old == NULL) + { + if (type == TREE_TYPE_LEVEL_DIR) + { + // get level info tree node of personal user level set + tree_node_old = getTreeInfoFromIdentifier(leveldir_first, getLoginName()); + + // this may happen if "setup.internal.create_user_levelset" is FALSE + // or if file "levelinfo.conf" is missing in personal user level set + if (tree_node_old == NULL) + tree_node_old = leveldir_first->node_group; + } + else + { + // get artwork info tree node of first artwork set + tree_node_old = ARTWORK_FIRST_NODE(artwork, type); + } + } + + if (tree_dir == NULL) + tree_dir = TREE_USERDIR(type); + + if (tree_node_old == NULL || + tree_dir == NULL || + tree_subdir_new == NULL) // should not happen return FALSE; int draw_deactivation_mask = GetDrawDeactivationMask(); @@ -3866,33 +3984,54 @@ static boolean AddUserLevelSetToLevelInfoExt(char *level_subdir_new) // override draw deactivation mask (temporarily disable drawing) SetDrawDeactivationMask(REDRAW_ALL); - // load new level set config and add it next to first user level set - LoadLevelInfoFromLevelConf(&leveldir_old->next, NULL, - leveldir_old->basepath, level_subdir_new); + if (type == TREE_TYPE_LEVEL_DIR) + { + // load new level set config and add it next to first user level set + LoadLevelInfoFromLevelConf(&tree_node_old->next, + tree_node_old->node_parent, + tree_dir, tree_subdir_new); + } + else + { + // load new artwork set config and add it next to first artwork set + LoadArtworkInfoFromArtworkConf(&tree_node_old->next, + tree_node_old->node_parent, + tree_dir, tree_subdir_new, type); + } // set draw deactivation mask to previous value SetDrawDeactivationMask(draw_deactivation_mask); - // get level info tree node of newly added user level set - LevelDirTree *leveldir_new = getTreeInfoFromIdentifier(leveldir_first, - level_subdir_new); - if (leveldir_new == NULL) // should not happen + // get first node of level or artwork info tree + TreeInfo **tree_node_first = TREE_FIRST_NODE_PTR(type); + + // get tree info node of newly added level or artwork set + TreeInfo *tree_node_new = getTreeInfoFromIdentifier(*tree_node_first, + tree_subdir_new); + + if (tree_node_new == NULL) // should not happen return FALSE; // correct top link and parent node link of newly created tree node - leveldir_new->node_top = leveldir_old->node_top; - leveldir_new->node_parent = leveldir_old->node_parent; + tree_node_new->node_top = tree_node_old->node_top; + tree_node_new->node_parent = tree_node_old->node_parent; - // sort level info tree to adjust position of newly added level set - sortTreeInfo(&leveldir_first); + // sort tree info to adjust position of newly added tree set + sortTreeInfo(tree_node_first); return TRUE; } +void AddTreeSetToTreeInfo(TreeInfo *tree_node, char *tree_dir, + char *tree_subdir_new, int type) +{ + if (!AddTreeSetToTreeInfoExt(tree_node, tree_dir, tree_subdir_new, type)) + Fail("internal tree info structure corrupted -- aborting"); +} + void AddUserLevelSetToLevelInfo(char *level_subdir_new) { - if (!AddUserLevelSetToLevelInfoExt(level_subdir_new)) - Error(ERR_EXIT, "internal level set structure corrupted -- aborting"); + AddTreeSetToTreeInfo(NULL, NULL, level_subdir_new, TREE_TYPE_LEVEL_DIR); } char *getArtworkIdentifierForUserLevelSet(int type) @@ -3922,8 +4061,17 @@ TreeInfo *getArtworkTreeInfoForUserLevelSet(int type) { char *artwork_set = getArtworkIdentifierForUserLevelSet(type); TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type); + TreeInfo *ti = getTreeInfoFromIdentifier(artwork_first_node, artwork_set); - return getTreeInfoFromIdentifier(artwork_first_node, artwork_set); + if (ti == NULL) + { + ti = getTreeInfoFromIdentifier(artwork_first_node, + ARTWORK_DEFAULT_SUBDIR(type)); + if (ti == NULL) + Fail("cannot find default graphics -- should not happen"); + } + + return ti; } boolean checkIfCustomArtworkExistsForCurrentLevelSet(void) @@ -4020,7 +4168,8 @@ boolean CreateUserLevelSet(char *level_subdir, char *level_name, if (!(file = fopen(filename, MODE_WRITE))) { - Error(ERR_WARN, "cannot write level info file '%s'", filename); + Warn("cannot write level info file '%s'", filename); + free(filename); return FALSE; @@ -4231,7 +4380,7 @@ void LoadLevelSetup_LastSeries(void) } else { - Error(ERR_DEBUG, "using default setup values"); + Debug("setup", "using default setup values"); } free(filename); @@ -4255,7 +4404,7 @@ static void SaveLevelSetup_LastSeries_Ext(boolean deactivate_last_level_series) if (!(file = fopen(filename, MODE_WRITE))) { - Error(ERR_WARN, "cannot write setup file '%s'", filename); + Warn("cannot write setup file '%s'", filename); free(filename); @@ -4291,6 +4440,11 @@ static void checkSeriesInfo(void) { static char *level_directory = NULL; Directory *dir; +#if 0 + DirectoryEntry *dir_entry; +#endif + + checked_free(level_directory); // check for more levels besides the 'levels' field of 'levelinfo.conf' @@ -4301,11 +4455,42 @@ static void checkSeriesInfo(void) if ((dir = openDirectory(level_directory)) == NULL) { - Error(ERR_WARN, "cannot read level directory '%s'", level_directory); + Warn("cannot read level directory '%s'", level_directory); return; } +#if 0 + while ((dir_entry = readDirectory(dir)) != NULL) // loop all entries + { + 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) + { + Warn("additional level %d found", levelnum_value); + + leveldir_current->first_level = levelnum_value; + } + else if (levelnum_value > leveldir_current->last_level) + { + Warn("additional level %d found", levelnum_value); + + leveldir_current->last_level = levelnum_value; + } + } + } +#endif + closeDirectory(dir); } @@ -4401,7 +4586,7 @@ void LoadLevelSetup_SeriesInfo(void) } else { - Error(ERR_DEBUG, "using default setup values"); + Debug("setup", "using default setup values"); } free(filename); @@ -4426,8 +4611,10 @@ void SaveLevelSetup_SeriesInfo(void) if (!(file = fopen(filename, MODE_WRITE))) { - Error(ERR_WARN, "cannot write setup file '%s'", filename); + Warn("cannot write setup file '%s'", filename); + free(filename); + return; }