X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsetup.c;h=51c6f646616827e29fe59134b4405355a167a0d2;hb=2c4f8dc7bc7d04f5e23a6ad9f3e7594bf902ba56;hp=940d6bad827d9fab1639f101e65d0505839bd7c3;hpb=6945f3749927053ee70b47133b2998557a452f75;p=rocksndiamonds.git diff --git a/src/libgame/setup.c b/src/libgame/setup.c index 940d6bad..51c6f646 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -98,25 +98,25 @@ static char *levelclass_desc[NUM_LEVELCLASS_DESC] = #define MAX_COOKIE_LEN 256 -#define ARTWORKINFO_FILENAME(type) ((type) == TREE_TYPE_GRAPHICS_DIR ? \ - GRAPHICSINFO_FILENAME : \ - (type) == TREE_TYPE_SOUNDS_DIR ? \ - SOUNDSINFO_FILENAME : \ - (type) == TREE_TYPE_MUSIC_DIR ? \ +#define ARTWORKINFO_FILENAME(type) ((type) == ARTWORK_TYPE_GRAPHICS ? \ + GRAPHICSINFO_FILENAME : \ + (type) == ARTWORK_TYPE_SOUNDS ? \ + SOUNDSINFO_FILENAME : \ + (type) == ARTWORK_TYPE_MUSIC ? \ MUSICINFO_FILENAME : "") -#define ARTWORK_DIRECTORY(type) ((type) == TREE_TYPE_GRAPHICS_DIR ? \ - GRAPHICS_DIRECTORY : \ - (type) == TREE_TYPE_SOUNDS_DIR ? \ - SOUNDS_DIRECTORY : \ - (type) == TREE_TYPE_MUSIC_DIR ? \ +#define ARTWORK_DIRECTORY(type) ((type) == ARTWORK_TYPE_GRAPHICS ? \ + GRAPHICS_DIRECTORY : \ + (type) == ARTWORK_TYPE_SOUNDS ? \ + SOUNDS_DIRECTORY : \ + (type) == ARTWORK_TYPE_MUSIC ? \ MUSIC_DIRECTORY : "") -#define OPTIONS_ARTWORK_DIRECTORY(type) ((type) == TREE_TYPE_GRAPHICS_DIR ? \ - options.graphics_directory : \ - (type) == TREE_TYPE_SOUNDS_DIR ? \ - options.sounds_directory : \ - (type) == TREE_TYPE_MUSIC_DIR ? \ +#define OPTIONS_ARTWORK_DIRECTORY(type) ((type) == ARTWORK_TYPE_GRAPHICS ? \ + options.graphics_directory : \ + (type) == ARTWORK_TYPE_SOUNDS ? \ + options.sounds_directory : \ + (type) == ARTWORK_TYPE_MUSIC ? \ options.music_directory : "") @@ -268,6 +268,23 @@ static char *getDefaultMusicDir(char *music_subdir) return music_dir; } +static char *getDefaultArtworkSet(int type) +{ + return (type == TREE_TYPE_GRAPHICS_DIR ? GRAPHICS_SUBDIR : + type == TREE_TYPE_SOUNDS_DIR ? SOUNDS_SUBDIR : + type == TREE_TYPE_MUSIC_DIR ? MUSIC_SUBDIR : ""); +} + +static char *getDefaultArtworkDir(int type) +{ + return (type == TREE_TYPE_GRAPHICS_DIR ? + getDefaultGraphicsDir(GRAPHICS_SUBDIR) : + type == TREE_TYPE_SOUNDS_DIR ? + getDefaultSoundsDir(SOUNDS_SUBDIR) : + type == TREE_TYPE_MUSIC_DIR ? + getDefaultMusicDir(MUSIC_SUBDIR) : ""); +} + static char *getUserGraphicsDir() { static char *usergraphics_dir = NULL; @@ -312,45 +329,63 @@ static char *getSetupArtworkDir(TreeInfo *ti) void setLevelArtworkDir(TreeInfo *ti) { - char **artwork_path_ptr, *artwork_set; + char **artwork_path_ptr, **artwork_set_ptr; TreeInfo *level_artwork; if (ti == NULL || leveldir_current == NULL) return; - artwork_path_ptr = - (ti->type == TREE_TYPE_GRAPHICS_DIR ? &leveldir_current->graphics_path : - ti->type == TREE_TYPE_SOUNDS_DIR ? &leveldir_current->sounds_path : - &leveldir_current->music_path); - - artwork_set = - (ti->type == TREE_TYPE_GRAPHICS_DIR ? leveldir_current->graphics_set : - ti->type == TREE_TYPE_SOUNDS_DIR ? leveldir_current->sounds_set : - leveldir_current->music_set); - - if ((level_artwork = getTreeInfoFromIdentifier(ti, artwork_set)) == NULL) - return; + artwork_path_ptr = &(LEVELDIR_ARTWORK_PATH(leveldir_current, ti->type)); + artwork_set_ptr = &(LEVELDIR_ARTWORK_SET( leveldir_current, ti->type)); if (*artwork_path_ptr != NULL) free(*artwork_path_ptr); - *artwork_path_ptr = getStringCopy(getSetupArtworkDir(level_artwork)); + if ((level_artwork = getTreeInfoFromIdentifier(ti, *artwork_set_ptr))) + *artwork_path_ptr = getStringCopy(getSetupArtworkDir(level_artwork)); + else + { + /* No (or non-existing) artwork configured in "levelinfo.conf". This would + normally result in using the artwork configured in the setup menu. But + if an artwork subdirectory exists (which might contain custom artwork + or an artwork configuration file), this level artwork must be treated + as relative to the default "classic" artwork, not to the artwork that + is currently configured in the setup menu. */ + + char *dir = getPath2(getCurrentLevelDir(), ARTWORK_DIRECTORY(ti->type)); + + if (*artwork_set_ptr != NULL) + free(*artwork_set_ptr); + + if (fileExists(dir)) + { + *artwork_path_ptr = getStringCopy(getDefaultArtworkDir(ti->type)); + *artwork_set_ptr = getStringCopy(getDefaultArtworkSet(ti->type)); + } + else + { + *artwork_path_ptr = getStringCopy(UNDEFINED_FILENAME); + *artwork_set_ptr = NULL; + } + + free(dir); + } } -static char *getLevelArtworkDir(int type) +inline static char *getLevelArtworkSet(int type) { - char *artwork_path; + if (leveldir_current == NULL) + return NULL; + + return LEVELDIR_ARTWORK_SET(leveldir_current, type); +} +inline static char *getLevelArtworkDir(int type) +{ if (leveldir_current == NULL) return UNDEFINED_FILENAME; - artwork_path = - (type == TREE_TYPE_GRAPHICS_DIR ? leveldir_current->graphics_path : - type == TREE_TYPE_SOUNDS_DIR ? leveldir_current->sounds_path : - type == TREE_TYPE_MUSIC_DIR ? leveldir_current->music_path : - UNDEFINED_FILENAME); - - return artwork_path; + return LEVELDIR_ARTWORK_PATH(leveldir_current, type); } char *getLevelFilename(int nr) @@ -361,7 +396,11 @@ char *getLevelFilename(int nr) if (filename != NULL) free(filename); - sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION); + if (nr < 0) + sprintf(basename, "template.%s", LEVELFILE_EXTENSION); + else + sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION); + filename = getPath2(getCurrentLevelDir(), basename); return filename; @@ -441,6 +480,7 @@ static char *getCorrectedImageBasename(char *basename) char *getCustomImageFilename(char *basename) { static char *filename = NULL; + boolean skip_setup_artwork = FALSE; if (filename != NULL) free(filename); @@ -449,28 +489,38 @@ char *getCustomImageFilename(char *basename) if (!setup.override_level_graphics) { - /* 1st try: look for special artwork configured in level series config */ - filename = getPath2(getLevelArtworkDir(TREE_TYPE_GRAPHICS_DIR), basename); + /* 1st try: look for special artwork in current level series directory */ + filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename); if (fileExists(filename)) return filename; free(filename); - /* 2nd try: look for special artwork in current level series directory */ - filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename); + /* check if there is special artwork configured in level series config */ + if (getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) != NULL) + { + /* 2nd try: look for special artwork configured in level series config */ + filename = getPath2(getLevelArtworkDir(ARTWORK_TYPE_GRAPHICS), basename); + if (fileExists(filename)) + return filename; + + free(filename); + + /* take missing artwork configured in level set config from default */ + skip_setup_artwork = TRUE; + } + } + + if (!skip_setup_artwork) + { + /* 3rd try: look for special artwork in configured artwork directory */ + filename = getPath2(getSetupArtworkDir(artwork.gfx_current), basename); if (fileExists(filename)) return filename; free(filename); } - /* 3rd try: look for special artwork in configured artwork directory */ - filename = getPath2(getSetupArtworkDir(artwork.gfx_current), basename); - if (fileExists(filename)) - return filename; - - free(filename); - /* 4th try: look for default artwork in new default artwork directory */ filename = getPath2(getDefaultGraphicsDir(GRAPHICS_SUBDIR), basename); if (fileExists(filename)) @@ -489,34 +539,45 @@ char *getCustomImageFilename(char *basename) char *getCustomSoundFilename(char *basename) { static char *filename = NULL; + boolean skip_setup_artwork = FALSE; if (filename != NULL) free(filename); if (!setup.override_level_sounds) { - /* 1st try: look for special artwork configured in level series config */ - filename = getPath2(getLevelArtworkDir(TREE_TYPE_SOUNDS_DIR), basename); + /* 1st try: look for special artwork in current level series directory */ + filename = getPath3(getCurrentLevelDir(), SOUNDS_DIRECTORY, basename); if (fileExists(filename)) return filename; free(filename); - /* 2nd try: look for special artwork in current level series directory */ - filename = getPath3(getCurrentLevelDir(), SOUNDS_DIRECTORY, basename); + /* check if there is special artwork configured in level series config */ + if (getLevelArtworkSet(ARTWORK_TYPE_SOUNDS) != NULL) + { + /* 2nd try: look for special artwork configured in level series config */ + filename = getPath2(getLevelArtworkDir(TREE_TYPE_SOUNDS_DIR), basename); + if (fileExists(filename)) + return filename; + + free(filename); + + /* take missing artwork configured in level set config from default */ + skip_setup_artwork = TRUE; + } + } + + if (!skip_setup_artwork) + { + /* 3rd try: look for special artwork in configured artwork directory */ + filename = getPath2(getSetupArtworkDir(artwork.snd_current), basename); if (fileExists(filename)) return filename; free(filename); } - /* 3rd try: look for special artwork in configured artwork directory */ - filename = getPath2(getSetupArtworkDir(artwork.snd_current), basename); - if (fileExists(filename)) - return filename; - - free(filename); - /* 4th try: look for default artwork in new default artwork directory */ filename = getPath2(getDefaultSoundsDir(SOUNDS_SUBDIR), basename); if (fileExists(filename)) @@ -547,37 +608,60 @@ char *getCustomArtworkConfigFilename(int type) return getCustomArtworkFilename(ARTWORKINFO_FILENAME(type), type); } +char *getCustomArtworkLevelConfigFilename(int type) +{ + static char *filename = NULL; + + if (filename != NULL) + free(filename); + + filename = getPath2(getLevelArtworkDir(type), ARTWORKINFO_FILENAME(type)); + + return filename; +} + char *getCustomMusicDirectory(void) { static char *directory = NULL; + boolean skip_setup_artwork = FALSE; if (directory != NULL) free(directory); if (!setup.override_level_music) { - /* 1st try: look for special artwork configured in level series config */ - directory = getStringCopy(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR)); + /* 1st try: look for special artwork in current level series directory */ + directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY); if (fileExists(directory)) return directory; free(directory); - /* 2nd try: look for special artwork in current level series directory */ - directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY); + /* check if there is special artwork configured in level series config */ + if (getLevelArtworkSet(ARTWORK_TYPE_MUSIC) != NULL) + { + /* 2nd try: look for special artwork configured in level series config */ + directory = getStringCopy(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR)); + if (fileExists(directory)) + return directory; + + free(directory); + + /* take missing artwork configured in level set config from default */ + skip_setup_artwork = TRUE; + } + } + + if (!skip_setup_artwork) + { + /* 3rd try: look for special artwork in configured artwork directory */ + directory = getStringCopy(getSetupArtworkDir(artwork.mus_current)); if (fileExists(directory)) return directory; free(directory); } - /* 3rd try: look for special artwork in configured artwork directory */ - directory = getStringCopy(getSetupArtworkDir(artwork.mus_current)); - if (fileExists(directory)) - return directory; - - free(directory); - /* 4th try: look for default artwork in new default artwork directory */ directory = getStringCopy(getDefaultMusicDir(MUSIC_SUBDIR)); if (fileExists(directory)) @@ -1040,6 +1124,18 @@ char *getFormattedSetupEntry(char *token, char *value) return entry; } +SetupFileList *newSetupFileList(char *token, char *value) +{ + SetupFileList *new = checked_malloc(sizeof(SetupFileList)); + + new->token = getStringCopy(token); + new->value = getStringCopy(value); + + new->next = NULL; + + return new; +} + void freeSetupFileList(SetupFileList *list) { if (list == NULL) @@ -1054,19 +1150,7 @@ void freeSetupFileList(SetupFileList *list) free(list); } -SetupFileList *newSetupFileList(char *token, char *value) -{ - SetupFileList *new = checked_malloc(sizeof(SetupFileList)); - - new->token = getStringCopy(token); - new->value = getStringCopy(value); - - new->next = NULL; - - return new; -} - -char *getTokenValue(SetupFileList *list, char *token) +char *getListEntry(SetupFileList *list, char *token) { if (list == NULL) return NULL; @@ -1074,10 +1158,10 @@ char *getTokenValue(SetupFileList *list, char *token) if (strcmp(list->token, token) == 0) return list->value; else - return getTokenValue(list->next, token); + return getListEntry(list->next, token); } -void setTokenValue(SetupFileList *list, char *token, char *value) +void setListEntry(SetupFileList *list, char *token, char *value) { if (list == NULL) return; @@ -1092,7 +1176,7 @@ void setTokenValue(SetupFileList *list, char *token, char *value) else if (list->next == NULL) list->next = newSetupFileList(token, value); else - setTokenValue(list->next, token, value); + setListEntry(list->next, token, value); } #ifdef DEBUG @@ -1125,11 +1209,19 @@ static unsigned int get_hash_from_key(void *key) /* djb2 - this algorithm (k=33) was first reported by dan bernstein many years ago in - comp.lang.c. another version of this algorithm (now favored by bernstein) - uses xor: hash(i) = hash(i - 1) * 33 ^ str[i]; the magic of number 33 (why + This algorithm (k=33) was first reported by Dan Bernstein many years ago in + 'comp.lang.c'. Another version of this algorithm (now favored by Bernstein) + uses XOR: hash(i) = hash(i - 1) * 33 ^ str[i]; the magic of number 33 (why it works better than many other constants, prime or not) has never been adequately explained. + + If you just want to have a good hash function, and cannot wait, djb2 + is one of the best string hash functions i know. It has excellent + distribution and speed on many different sets of keys and table sizes. + You are not likely to do better with one of the "well known" functions + such as PJW, K&R, etc. + + Ozan (oz) Yigit [http://www.cs.yorku.ca/~oz/hash.html] */ char *str = (char *)key; @@ -1147,15 +1239,6 @@ static int keys_are_equal(void *key1, void *key2) return (strcmp((char *)key1, (char *)key2) == 0); } -void freeSetupFileHash(SetupFileHash *hash) -{ - if (hash == NULL) - return; - - hashtable_destroy(hash, 1); /* 1 == also free values */ - free(hash); -} - SetupFileHash *newSetupFileHash() { SetupFileHash *new_hash = @@ -1164,6 +1247,14 @@ SetupFileHash *newSetupFileHash() return new_hash; } +void freeSetupFileHash(SetupFileHash *hash) +{ + if (hash == NULL) + return; + + hashtable_destroy(hash, 1); /* 1 == also free values stored in hash */ +} + char *getHashEntry(SetupFileHash *hash, char *token) { if (hash == NULL) @@ -1191,26 +1282,6 @@ void setHashEntry(SetupFileHash *hash, char *token, char *value) #ifdef DEBUG static void printSetupFileHash(SetupFileHash *hash) { -#if 0 - if (hash == NULL) - return; - - /* iterator constructor only returns valid iterator for non-empty hash */ - if (hash != NULL && hashtable_count(hash) > 0) - { - struct hashtable_itr *itr = hashtable_iterator(hash); - - do - { - printf("token: '%s'\n", (char *)hashtable_iterator_key(itr)); - printf("value: '%s'\n", (char *)hashtable_iterator_value(itr)); - } - while (hashtable_iterator_advance(itr)); - - free(itr); - } -#endif - BEGIN_HASH_ITERATION(hash, itr) { printf("token: '%s'\n", HASH_ITERATION_TOKEN(itr)); @@ -1221,14 +1292,19 @@ static void printSetupFileHash(SetupFileHash *hash) #endif #endif -SetupFileHash *loadSetupFileHash(char *filename) +static void *loadSetupFileData(char *filename, boolean use_hash) { int line_len; char line[MAX_LINE_LEN]; char *token, *value, *line_ptr; - SetupFileHash *setup_file_hash = newSetupFileHash(); + void *setup_file_data; FILE *file; + if (use_hash) + setup_file_data = newSetupFileHash(); + else + setup_file_data = newSetupFileList("", ""); + if (!(file = fopen(filename, MODE_READ))) { Error(ERR_WARN, "cannot open configuration file '%s'", filename); @@ -1288,15 +1364,46 @@ SetupFileHash *loadSetupFileHash(char *filename) break; if (*token && *value) - setHashEntry(setup_file_hash, token, value); + { + if (use_hash) + setHashEntry((SetupFileHash *)setup_file_data, token, value); + else + setListEntry((SetupFileList *)setup_file_data, token, value); + } } fclose(file); - if (hashtable_count(setup_file_hash) == 0) - Error(ERR_WARN, "configuration file '%s' is empty", filename); + if (use_hash) + { + if (hashtable_count((SetupFileHash *)setup_file_data) == 0) + Error(ERR_WARN, "configuration file '%s' is empty", filename); + } + else + { + SetupFileList *setup_file_list = (SetupFileList *)setup_file_data; + SetupFileList *first_valid_list_entry = setup_file_list->next; + + /* free empty list header */ + setup_file_list->next = NULL; + freeSetupFileList(setup_file_list); + setup_file_data = first_valid_list_entry; - return setup_file_hash; + if (first_valid_list_entry == NULL) + Error(ERR_WARN, "configuration file '%s' is empty", filename); + } + + return setup_file_data; +} + +SetupFileList *loadSetupFileList(char *filename) +{ + return (SetupFileList *)loadSetupFileData(filename, FALSE); +} + +SetupFileHash *loadSetupFileHash(char *filename) +{ + return (SetupFileHash *)loadSetupFileData(filename, TRUE); } void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash, @@ -1411,7 +1518,8 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent) { Error(ERR_WARN, "setTreeInfoToDefaultsFromParent(): parent == NULL"); - setTreeInfoToDefaults(ldi, TREE_TYPE_GENERIC); + setTreeInfoToDefaults(ldi, TREE_TYPE_UNDEFINED); + return; } @@ -1995,16 +2103,25 @@ void LoadArtworkInfo() /* 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, GRAPHICS_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, SOUNDS_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, MUSIC_SUBDIR); if (artwork.mus_current == NULL) artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first); @@ -2089,6 +2206,9 @@ void LoadLevelArtworkInfo() { artwork.gfx_current = getTreeInfoFromIdentifier(artwork.gfx_first, setup.graphics_set); + if (artwork.gfx_current == NULL) + artwork.gfx_current = + getTreeInfoFromIdentifier(artwork.gfx_first, GRAPHICS_SUBDIR); if (artwork.gfx_current == NULL) artwork.gfx_current = getFirstValidTreeInfoEntry(artwork.gfx_first); } @@ -2097,6 +2217,9 @@ void LoadLevelArtworkInfo() { artwork.snd_current = getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set); + if (artwork.snd_current == NULL) + artwork.snd_current = + getTreeInfoFromIdentifier(artwork.snd_first, SOUNDS_SUBDIR); if (artwork.snd_current == NULL) artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first); } @@ -2105,6 +2228,9 @@ void LoadLevelArtworkInfo() { artwork.mus_current = getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set); + if (artwork.mus_current == NULL) + artwork.mus_current = + getTreeInfoFromIdentifier(artwork.mus_first, MUSIC_SUBDIR); if (artwork.mus_current == NULL) artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first); } @@ -2345,6 +2471,7 @@ static void checkSeriesInfo() levelnum_value = atoi(levelnum_str); +#if 0 if (levelnum_value < leveldir_current->first_level) { Error(ERR_WARN, "additional level %d found", levelnum_value); @@ -2355,6 +2482,7 @@ static void checkSeriesInfo() Error(ERR_WARN, "additional level %d found", levelnum_value); leveldir_current->last_level = levelnum_value; } +#endif } }