X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=cb4c6a605a173139931c8203c7f39353b77275a6;hb=c2a639c0b2c1a9a2bd14de86932a47429ae918a4;hp=36751f4630437fb12df9e828268a5e960e02760a;hpb=a2c9a458aaa4ac568f07ecd25b19fbca3f766e6b;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index 36751f46..cb4c6a60 100644 --- a/src/files.c +++ b/src/files.c @@ -13,6 +13,8 @@ #include #include +#include +#include #include "libgame/libgame.h" @@ -612,7 +614,7 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level) { Error(ERR_WARN, "invalid custom element number %d", element); - element = EL_DEFAULT; /* dummy element used for artwork config */ + element = EL_DUMMY; } for(j=0; jgame_version == VERSION_IDENT(2,0,1)) + if (level->game_version == VERSION_IDENT(2,0,1,0)) level->em_slippery_gems = TRUE; } else @@ -982,7 +984,7 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename) leveldir_current->sort_priority, filename); #endif -#if 1 +#if 0 printf("\n::: Use latest game engine version for this level.\n"); #endif @@ -1023,7 +1025,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) /* map custom element change events that have changed in newer versions (these following values were accidentally changed in version 3.0.1) */ - if (level->game_version <= VERSION_IDENT(3,0,0)) + if (level->game_version <= VERSION_IDENT(3,0,0,0)) { for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) { @@ -1067,7 +1069,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) } /* initialize "can_change" field for old levels with only one change page */ - if (level->game_version <= VERSION_IDENT(3,0,2)) + if (level->game_version <= VERSION_IDENT(3,0,2,0)) { for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) { @@ -1078,8 +1080,9 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) } } - /* set default push delay values (corrected since version 3.0.7) */ - if (level->game_version < VERSION_IDENT(3,0,7)) +#if 0 + /* set default push delay values (corrected since version 3.0.7-1) */ + if (level->game_version < VERSION_IDENT(3,0,7,1)) { game.default_push_delay_fixed = 2; game.default_push_delay_random = 8; @@ -1100,6 +1103,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) if (element_info[element].push_delay_random == -1) element_info[element].push_delay_random = game.default_push_delay_random; } +#endif /* initialize element properties for level editor etc. */ InitElementPropertiesEngine(level->game_version); @@ -1116,7 +1120,7 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename) { int element = level->field[x][y]; - if (level->game_version <= VERSION_IDENT(2,2,0)) + if (level->game_version <= VERSION_IDENT(2,2,0,0)) { /* map game font elements */ element = (element == EL_CHAR('[') ? EL_CHAR_AUMLAUT : @@ -1125,7 +1129,7 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename) element == EL_CHAR('^') ? EL_CHAR_COPYRIGHT : element); } - if (level->game_version < VERSION_IDENT(3,0,0)) + if (level->game_version < VERSION_IDENT(3,0,0,0)) { /* map Supaplex gravity tube elements */ element = (element == EL_SP_GRAVITY_PORT_LEFT ? EL_SP_PORT_LEFT : @@ -1995,8 +1999,8 @@ void LoadTapeFromFilename(char *filename) tape.length_seconds = GetTapeLength(); #if 0 - printf("tape game version: %d\n", tape.game_version); - printf("tape engine version: %d\n", tape.engine_version); + printf("::: tape game version: %d\n", tape.game_version); + printf("::: tape engine version: %d\n", tape.engine_version); #endif } @@ -2297,8 +2301,9 @@ void SaveScore(int level_nr) #define SETUP_TOKEN_EDITOR_EL_CUSTOM 8 #define SETUP_TOKEN_EDITOR_EL_CUSTOM_MORE 9 #define SETUP_TOKEN_EDITOR_EL_HEADLINES 10 +#define SETUP_TOKEN_EDITOR_EL_USER_DEFINED 11 -#define NUM_EDITOR_SETUP_TOKENS 11 +#define NUM_EDITOR_SETUP_TOKENS 12 /* shortcut setup */ #define SETUP_TOKEN_SHORTCUT_SAVE_GAME 0 @@ -2385,6 +2390,7 @@ static struct TokenInfo editor_setup_tokens[] = { TYPE_SWITCH, &sei.el_custom, "editor.el_custom" }, { TYPE_SWITCH, &sei.el_custom_more, "editor.el_custom_more" }, { TYPE_SWITCH, &sei.el_headlines, "editor.el_headlines" }, + { TYPE_SWITCH, &sei.el_user_defined, "editor.el_user_defined" }, }; static struct TokenInfo shortcut_setup_tokens[] = @@ -2483,6 +2489,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->editor.el_custom_more = FALSE; si->editor.el_headlines = TRUE; + si->editor.el_user_defined = FALSE; si->shortcut.save_game = DEFAULT_KEY_SAVE_GAME; si->shortcut.load_game = DEFAULT_KEY_LOAD_GAME; @@ -2754,3 +2761,500 @@ void LoadSpecialMenuDesignSettings() freeSetupFileHash(setup_file_hash); } + +static char *itoa(unsigned int i) +{ + static char *a = NULL; + + if (a != NULL) + free(a); + + if (i > 2147483647) /* yes, this is a kludge */ + i = 2147483647; + + a = checked_malloc(10 + 1); + + sprintf(a, "%d", i); + + return a; +} + +void LoadUserDefinedEditorElementList(int **elements, int *num_elements) +{ + char *filename = getEditorSetupFilename(); + SetupFileList *setup_file_list, *list; + SetupFileHash *element_hash; + int num_unknown_tokens = 0; + int i; + + if ((setup_file_list = loadSetupFileList(filename)) == NULL) + return; + + element_hash = newSetupFileHash(); + + for (i=0; i < NUM_FILE_ELEMENTS; i++) + setHashEntry(element_hash, element_info[i].token_name, itoa(i)); + + /* determined size may be larger than needed (due to unknown elements) */ + *num_elements = 0; + for (list = setup_file_list; list != NULL; list = list->next) + (*num_elements)++; + + /* add space for up to 3 more elements for padding that may be needed */ + *num_elements += 3; + + *elements = checked_malloc(*num_elements * sizeof(int)); + + *num_elements = 0; + for (list = setup_file_list; list != NULL; list = list->next) + { + char *value = getHashEntry(element_hash, list->token); + + if (value) + { + (*elements)[(*num_elements)++] = atoi(value); + } + else + { + if (num_unknown_tokens == 0) + { + Error(ERR_RETURN_LINE, "-"); + Error(ERR_RETURN, "warning: unknown token(s) found in config file:"); + Error(ERR_RETURN, "- config file: '%s'", filename); + + num_unknown_tokens++; + } + + Error(ERR_RETURN, "- token: '%s'", list->token); + } + } + + if (num_unknown_tokens > 0) + Error(ERR_RETURN_LINE, "-"); + + while (*num_elements % 4) /* pad with empty elements, if needed */ + (*elements)[(*num_elements)++] = EL_EMPTY; + + freeSetupFileList(setup_file_list); + freeSetupFileHash(element_hash); + +#if 0 + /* TEST-ONLY */ + for (i=0; i < *num_elements; i++) + printf("editor: element '%s' [%d]\n", + element_info[(*elements)[i]].token_name, (*elements)[i]); +#endif +} + +static struct MusicFileInfo *get_music_file_info(char *basename) +{ + SetupFileHash *setup_file_hash = NULL; + struct MusicFileInfo tmp_music_file_info, *new_music_file_info; + char *filename_music = getCustomMusicFilename(basename); + char *filename_prefix, *filename_info; + struct + { + char *token; + char **value_ptr; + } + token_to_value_ptr[] = + { + { "context", &tmp_music_file_info.context }, + { "title", &tmp_music_file_info.title }, + { "artist", &tmp_music_file_info.artist }, + { "album", &tmp_music_file_info.album }, + { "year", &tmp_music_file_info.year }, + { NULL, NULL }, + }; + int i; + + if (filename_music == NULL) + return NULL; + + /* ---------- try to replace file extension ---------- */ + + filename_prefix = getStringCopy(filename_music); + if (strrchr(filename_prefix, '.') != NULL) + *strrchr(filename_prefix, '.') = '\0'; + filename_info = getStringCat2(filename_prefix, ".txt"); + +#if 0 + printf("trying to load file '%s'...\n", filename_info); +#endif + + if (fileExists(filename_info)) + setup_file_hash = loadSetupFileHash(filename_info); + + free(filename_prefix); + free(filename_info); + + if (setup_file_hash == NULL) + { + /* ---------- try to add file extension ---------- */ + + filename_prefix = getStringCopy(filename_music); + filename_info = getStringCat2(filename_prefix, ".txt"); + +#if 0 + printf("trying to load file '%s'...\n", filename_info); +#endif + + if (fileExists(filename_info)) + setup_file_hash = loadSetupFileHash(filename_info); + + free(filename_prefix); + free(filename_info); + } + + if (setup_file_hash == NULL) + return NULL; + + /* ---------- music file info found ---------- */ + + for (i = 0; token_to_value_ptr[i].token != NULL; i++) + { + char *value = getHashEntry(setup_file_hash, token_to_value_ptr[i].token); + + *token_to_value_ptr[i].value_ptr = getStringCopy(value); /* may be NULL */ + } + + new_music_file_info = checked_calloc(sizeof(struct MusicFileInfo)); + *new_music_file_info = tmp_music_file_info; + + return new_music_file_info; +} + +void LoadMusicInfo() +{ + char *music_directory = getCustomMusicDirectory(); + int num_music = getMusicListSize(); + DIR *dir; + struct dirent *dir_entry; + struct FileInfo *music; + struct MusicFileInfo *next, **new; + int i; + + while (music_file_info != NULL) + { + next = music_file_info->next; + + if (music_file_info->context) + free(music_file_info->context); + if (music_file_info->title) + free(music_file_info->title); + if (music_file_info->artist) + free(music_file_info->artist); + if (music_file_info->album) + free(music_file_info->album); + if (music_file_info->year) + free(music_file_info->year); + + free(music_file_info); + + music_file_info = next; + } + + new = &music_file_info; + + for (i=0; i < num_music; i++) + { + music = getMusicListEntry(i); + + if (strcmp(music->filename, UNDEFINED_FILENAME) == 0) + continue; + +#if 0 + printf("::: -> '%s'\n", music->filename); +#endif + + *new = get_music_file_info(music->filename); + if (*new != NULL) + new = &(*new)->next; + } + + if ((dir = opendir(music_directory)) == NULL) + { + Error(ERR_WARN, "cannot read music directory '%s'", music_directory); + return; + } + + while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */ + { + char *basename = dir_entry->d_name; + boolean music_already_used = FALSE; + int i; + + for (i=0; i < num_music; i++) + { + music = getMusicListEntry(i); + + if (strcmp(basename, music->filename) == 0) + { + music_already_used = TRUE; + break; + } + } + + if (music_already_used) + continue; + + if (!FileIsSound(basename) && !FileIsMusic(basename)) + continue; + +#if 0 + printf("::: -> '%s'\n", basename); +#endif + + *new = get_music_file_info(basename); + if (*new != NULL) + new = &(*new)->next; + } + + closedir(dir); + +#if 0 + /* TEST-ONLY */ + for (next = music_file_info; next != NULL; next = next->next) + printf("::: title == '%s'\n", next->title); +#endif +} + +void add_demo_anim(int element, int action, int direction, int delay, + int *num_list_entries) +{ + struct DemoAnimInfo *new_list_entry; + (*num_list_entries)++; + + demo_anim_info = + checked_realloc(demo_anim_info, + *num_list_entries * sizeof(struct DemoAnimInfo)); + new_list_entry = &demo_anim_info[*num_list_entries - 1]; + + new_list_entry->element = element; + new_list_entry->action = action; + new_list_entry->direction = direction; + new_list_entry->delay = delay; +} + +void print_unknown_token(char *filename, char *token, int token_nr) +{ + if (token_nr == 0) + { + Error(ERR_RETURN_LINE, "-"); + Error(ERR_RETURN, "warning: unknown token(s) found in config file:"); + Error(ERR_RETURN, "- config file: '%s'", filename); + } + + Error(ERR_RETURN, "- token: '%s'", token); +} + +void print_unknown_token_end(int token_nr) +{ + if (token_nr > 0) + Error(ERR_RETURN_LINE, "-"); +} + +void LoadDemoAnimInfo() +{ + char *filename = getDemoAnimInfoFilename(); + SetupFileList *setup_file_list, *list; + SetupFileHash *element_hash, *action_hash, *direction_hash; + int num_list_entries = 0; + int num_unknown_tokens = 0; + int i; + + if ((setup_file_list = loadSetupFileList(filename)) == NULL) + { + /* use reliable default values from static configuration */ + SetupFileList *insert_ptr; + + insert_ptr = setup_file_list = + newSetupFileList(demo_anim_info_config[0].token, + demo_anim_info_config[0].value); + + for (i=1; demo_anim_info_config[i].token; i++) + insert_ptr = addListEntry(insert_ptr, + demo_anim_info_config[i].token, + demo_anim_info_config[i].value); + } + + element_hash = newSetupFileHash(); + action_hash = newSetupFileHash(); + direction_hash = newSetupFileHash(); + + for (i=0; i < MAX_NUM_ELEMENTS; i++) + setHashEntry(element_hash, element_info[i].token_name, itoa(i)); + + for (i=0; i < NUM_ACTIONS; i++) + setHashEntry(action_hash, element_action_info[i].suffix, + itoa(element_action_info[i].value)); + + /* do not store direction index (bit) here, but direction value! */ + for (i=0; i < NUM_DIRECTIONS; i++) + setHashEntry(direction_hash, element_direction_info[i].suffix, + itoa(1 << element_direction_info[i].value)); + + for (list = setup_file_list; list != NULL; list = list->next) + { + char *element_token, *action_token, *direction_token; + char *element_value, *action_value, *direction_value; + int delay = atoi(list->value); + + if (strcmp(list->token, "end") == 0) + { + add_demo_anim(-1, -1, -1, -1, &num_list_entries); + + continue; + } + + element_token = list->token; + element_value = getHashEntry(element_hash, element_token); + + if (element_value != NULL) + { + /* element found */ + add_demo_anim(atoi(element_value), -1, -1, delay, &num_list_entries); + + continue; + } + + if (strchr(element_token, '.') == NULL) + { + /* no further suffixes found -- this is not an element */ + print_unknown_token(filename, list->token, num_unknown_tokens++); + + continue; + } + + action_token = strchr(element_token, '.'); + element_token = getStringCopy(element_token); + *strchr(element_token, '.') = '\0'; + + element_value = getHashEntry(element_hash, element_token); + + if (element_value == NULL) + { + /* this is not an element */ + print_unknown_token(filename, list->token, num_unknown_tokens++); + free(element_token); + + continue; + } + + action_value = getHashEntry(action_hash, action_token); + + if (action_value != NULL) + { + /* action found */ + add_demo_anim(atoi(element_value), atoi(action_value), -1, delay, + &num_list_entries); + free(element_token); + + continue; + } + + direction_token = action_token; + direction_value = getHashEntry(direction_hash, direction_token); + + if (direction_value != NULL) + { + /* direction found */ + add_demo_anim(atoi(element_value), -1, atoi(direction_value), delay, + &num_list_entries); + free(element_token); + + continue; + } + + if (strchr(action_token + 1, '.') == NULL) + { + /* no further suffixes found -- this is not an action or direction */ + print_unknown_token(filename, list->token, num_unknown_tokens++); + free(element_token); + + continue; + } + + direction_token = strchr(action_token + 1, '.'); + action_token = getStringCopy(action_token); + *strchr(action_token + 1, '.') = '\0'; + + action_value = getHashEntry(action_hash, action_token); + + if (action_value == NULL) + { + /* this is not an action */ + print_unknown_token(filename, list->token, num_unknown_tokens++); + free(element_token); + free(action_token); + + continue; + } + + direction_value = getHashEntry(direction_hash, direction_token); + + if (direction_value != NULL) + { + /* direction found */ + add_demo_anim(atoi(element_value), atoi(action_value), + atoi(direction_value), delay, &num_list_entries); + free(element_token); + free(action_token); + + continue; + } + + print_unknown_token(filename, list->token, num_unknown_tokens++); + + free(element_token); + free(action_token); + } + + print_unknown_token_end(num_unknown_tokens); + + add_demo_anim(-999, -999, -999, -999, &num_list_entries); + + freeSetupFileList(setup_file_list); + freeSetupFileHash(element_hash); + freeSetupFileHash(action_hash); + freeSetupFileHash(direction_hash); + +#if 0 + /* TEST ONLY */ + for (i=0; i < num_list_entries; i++) + printf("::: %d, %d, %d => %d\n", + demo_anim_info[i].element, + demo_anim_info[i].action, + demo_anim_info[i].direction, + demo_anim_info[i].delay); +#endif +} + +void LoadDemoAnimText() +{ + char *filename = getDemoAnimTextFilename(); + int i; + + if (demo_anim_text != NULL) + freeSetupFileHash(demo_anim_text); + + if ((demo_anim_text = loadSetupFileHash(filename)) == NULL) + { + /* use reliable default values from static configuration */ + demo_anim_text = newSetupFileHash(); + + for (i=0; demo_anim_text_config[i].token; i++) + setHashEntry(demo_anim_text, demo_anim_text_config[i].token, + demo_anim_text_config[i].value); + } + +#if 0 + /* TEST ONLY */ + BEGIN_HASH_ITERATION(demo_anim_text, itr) + { + printf("::: '%s' => '%s'\n", + HASH_ITERATION_TOKEN(itr), HASH_ITERATION_VALUE(itr)); + } + END_HASH_ITERATION(hash, itr) +#endif +}