X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Ffiles.c;h=1e44ad714fae1c8c10dc28134d70ec2060707d40;hp=ce0a95befddb0ff20ff3f7c0be7ae3fa44d81d7d;hb=c21cf4c301f745142f3cbb4987efe6446a3a8c4e;hpb=5d50a7e10873581345ee63a5afafd43dbd45809b diff --git a/src/files.c b/src/files.c index ce0a95be..1e44ad71 100644 --- a/src/files.c +++ b/src/files.c @@ -48,6 +48,7 @@ /* file names and filename extensions */ #ifndef MSDOS #define USERDATA_DIRECTORY ".rocksndiamonds" +#define LEVELSETUP_DIRECTORY "levelsetup" #define SETUP_FILENAME "setup.conf" #define LEVELSETUP_FILENAME "levelsetup.conf" #define LEVELINFO_FILENAME "levelinfo.conf" @@ -56,6 +57,7 @@ #define SCOREFILE_EXTENSION "score" #else #define USERDATA_DIRECTORY "userdata" +#define LEVELSETUP_DIRECTORY "lvlsetup" #define SETUP_FILENAME "setup.cnf" #define LEVELSETUP_FILENAME "lvlsetup.cnf" #define LEVELINFO_FILENAME "lvlinfo.cnf" @@ -256,6 +258,23 @@ static char *getScoreDir(char *level_subdir) return score_dir; } +static char *getLevelSetupDir(char *level_subdir) +{ + static char *levelsetup_dir = NULL; + char *data_dir = getUserDataDir(); + char *levelsetup_subdir = LEVELSETUP_DIRECTORY; + + if (levelsetup_dir) + free(levelsetup_dir); + + if (strlen(level_subdir) > 0) + levelsetup_dir = getPath3(data_dir, levelsetup_subdir, level_subdir); + else + levelsetup_dir = getPath2(data_dir, levelsetup_subdir); + + return levelsetup_dir; +} + static char *getLevelFilename(int nr) { static char *filename = NULL; @@ -339,6 +358,13 @@ static void InitUserLevelDirectory(char *level_subdir) } } +static void InitLevelSetupDirectory(char *level_subdir) +{ + createDirectory(getUserDataDir(), "user data"); + createDirectory(getLevelSetupDir(""), "main level setup"); + createDirectory(getLevelSetupDir(level_subdir), "level setup"); +} + static void setLevelInfoToDefaults() { int i, x, y; @@ -355,6 +381,8 @@ static void setLevelInfoToDefaults() level.amoeba_speed = 10; level.time_magic_wall = 10; level.time_wheel = 10; + level.time_light = 10; + level.time_timegate = 10; level.amoeba_content = EL_DIAMANT; level.double_speed = FALSE; level.gravity = FALSE; @@ -985,6 +1013,8 @@ void SaveScore(int level_nr) #define TOKEN_STR_FILE_IDENTIFIER "file_identifier" #define TOKEN_STR_LAST_LEVEL_SERIES "last_level_series" +#define TOKEN_STR_LAST_PLAYED_LEVEL "last_played_level" +#define TOKEN_STR_HANDICAP_LEVEL "handicap_level" #define TOKEN_STR_PLAYER_PREFIX "player_" #define TOKEN_VALUE_POSITION 30 @@ -995,14 +1025,20 @@ void SaveScore(int level_nr) #define SETUP_TOKEN_SOUND_LOOPS 2 #define SETUP_TOKEN_SOUND_MUSIC 3 #define SETUP_TOKEN_SOUND_SIMPLE 4 + +#if 0 #define SETUP_TOKEN_TOONS 5 #define SETUP_TOKEN_DOUBLE_BUFFERING 6 -#define SETUP_TOKEN_SCROLL_DELAY 7 -#define SETUP_TOKEN_SOFT_SCROLLING 8 -#define SETUP_TOKEN_FADING 9 -#define SETUP_TOKEN_AUTORECORD 10 -#define SETUP_TOKEN_QUICK_DOORS 11 -#define SETUP_TOKEN_TEAM_MODE 12 +#endif + +#define SETUP_TOKEN_SCROLL_DELAY 5 +#define SETUP_TOKEN_SOFT_SCROLLING 6 +#define SETUP_TOKEN_FADING 7 +#define SETUP_TOKEN_AUTORECORD 8 +#define SETUP_TOKEN_QUICK_DOORS 9 +#define SETUP_TOKEN_TEAM_MODE 10 +#define SETUP_TOKEN_HANDICAP 11 +#define SETUP_TOKEN_TIME_LIMIT 12 /* player setup */ #define SETUP_TOKEN_USE_JOYSTICK 13 @@ -1025,15 +1061,16 @@ void SaveScore(int level_nr) /* level directory info */ #define LEVELINFO_TOKEN_NAME 29 #define LEVELINFO_TOKEN_NAME_SHORT 30 -#define LEVELINFO_TOKEN_AUTHOR 31 -#define LEVELINFO_TOKEN_IMPORTED_FROM 32 -#define LEVELINFO_TOKEN_LEVELS 33 -#define LEVELINFO_TOKEN_FIRST_LEVEL 34 -#define LEVELINFO_TOKEN_SORT_PRIORITY 35 -#define LEVELINFO_TOKEN_READONLY 36 +#define LEVELINFO_TOKEN_NAME_SORTING 31 +#define LEVELINFO_TOKEN_AUTHOR 32 +#define LEVELINFO_TOKEN_IMPORTED_FROM 33 +#define LEVELINFO_TOKEN_LEVELS 34 +#define LEVELINFO_TOKEN_FIRST_LEVEL 35 +#define LEVELINFO_TOKEN_SORT_PRIORITY 36 +#define LEVELINFO_TOKEN_READONLY 37 #define FIRST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_PLAYER_NAME -#define LAST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_TEAM_MODE +#define LAST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_TIME_LIMIT #define FIRST_PLAYER_SETUP_TOKEN SETUP_TOKEN_USE_JOYSTICK #define LAST_PLAYER_SETUP_TOKEN SETUP_TOKEN_KEY_BOMB @@ -1063,14 +1100,20 @@ static struct { TYPE_SWITCH, &si.sound_loops, "repeating_sound_loops" }, { TYPE_SWITCH, &si.sound_music, "background_music" }, { TYPE_SWITCH, &si.sound_simple, "simple_sound_effects" }, + +#if 0 { TYPE_SWITCH, &si.toons, "toons" }, { TYPE_SWITCH, &si.double_buffering, "double_buffering" }, +#endif + { TYPE_SWITCH, &si.scroll_delay, "scroll_delay" }, { TYPE_SWITCH, &si.soft_scrolling, "soft_scrolling" }, { TYPE_SWITCH, &si.fading, "screen_fading" }, { TYPE_SWITCH, &si.autorecord, "automatic_tape_recording" }, { TYPE_SWITCH, &si.quick_doors, "quick_doors" }, { TYPE_SWITCH, &si.team_mode, "team_mode" }, + { TYPE_SWITCH, &si.handicap, "handicap" }, + { TYPE_SWITCH, &si.time_limit, "time_limit" }, /* player setup */ { TYPE_BOOLEAN, &sii.use_joystick, ".use_joystick" }, @@ -1093,6 +1136,7 @@ static struct /* level directory info */ { TYPE_STRING, &ldi.name, "name" }, { TYPE_STRING, &ldi.name_short, "name_short" }, + { TYPE_STRING, &ldi.name_sorting, "name_sorting" }, { TYPE_STRING, &ldi.author, "author" }, { TYPE_STRING, &ldi.imported_from, "imported_from" }, { TYPE_INTEGER, &ldi.levels, "levels" }, @@ -1358,14 +1402,21 @@ static void checkSetupFileListIdentifier(struct SetupFileList *setup_file_list, static void setLevelDirInfoToDefaults(struct LevelDirInfo *ldi) { + ldi->filename = NULL; ldi->name = getStringCopy(ANONYMOUS_NAME); ldi->name_short = NULL; + ldi->name_sorting = NULL; ldi->author = getStringCopy(ANONYMOUS_NAME); ldi->imported_from = NULL; ldi->levels = 0; ldi->first_level = 0; + ldi->last_level = 0; ldi->sort_priority = LEVELCLASS_UNDEFINED; /* default: least priority */ ldi->readonly = TRUE; + ldi->user_defined = FALSE; + ldi->color = 0; + ldi->class_desc = NULL; + ldi->handicap_level = 0; } static void setSetupInfoToDefaults(struct SetupInfo *si) @@ -1386,6 +1437,9 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->fading = FALSE; si->autorecord = TRUE; si->quick_doors = FALSE; + si->team_mode = FALSE; + si->handicap = TRUE; + si->time_limit = TRUE; for (i=0; i leveldir[level_series_nr].last_level) - last_level_nr = leveldir[level_series_nr].last_level; - } - - return last_level_nr; -} - static int compareLevelDirInfoEntries(const void *object1, const void *object2) { const struct LevelDirInfo *entry1 = object1; @@ -1521,8 +1551,8 @@ static int compareLevelDirInfoEntries(const void *object1, const void *object2) if (entry1->sort_priority == entry2->sort_priority) { - char *name1 = getStringToLower(entry1->name_short); - char *name2 = getStringToLower(entry2->name_short); + char *name1 = getStringToLower(entry1->name_sorting); + char *name2 = getStringToLower(entry2->name_sorting); compare_result = strcmp(name1, name2); @@ -1577,6 +1607,10 @@ static int LoadLevelInfoFromLevelDir(char *level_directory, int start_entry) if (setup_file_list) { +#if 0 + DrawInitText(dir_entry->d_name, 150, FC_YELLOW); +#endif + checkSetupFileListIdentifier(setup_file_list, LEVELINFO_COOKIE); setLevelDirInfoToDefaults(&leveldir[current_entry]); @@ -1585,10 +1619,18 @@ static int LoadLevelInfoFromLevelDir(char *level_directory, int start_entry) setSetupInfo(i, getTokenValue(setup_file_list, token_info[i].text)); leveldir[current_entry] = ldi; +#if 1 + DrawInitText(leveldir[current_entry].name, 150, FC_YELLOW); +#endif + if (leveldir[current_entry].name_short == NULL) leveldir[current_entry].name_short = getStringCopy(leveldir[current_entry].name); + if (leveldir[current_entry].name_sorting == NULL) + leveldir[current_entry].name_sorting = + getStringCopy(leveldir[current_entry].name_short); + leveldir[current_entry].filename = getStringCopy(dir_entry->d_name); leveldir[current_entry].last_level = leveldir[current_entry].first_level + @@ -1598,6 +1640,15 @@ static int LoadLevelInfoFromLevelDir(char *level_directory, int start_entry) leveldir[current_entry].color = LEVELCOLOR(&leveldir[current_entry]); leveldir[current_entry].class_desc = getLevelClassDescription(&leveldir[current_entry]); +#if 0 + leveldir[current_entry].handicap_level = + leveldir[current_entry].first_level; /* default value */ +#else + leveldir[current_entry].handicap_level = + (leveldir[current_entry].user_defined ? + leveldir[current_entry].last_level : + leveldir[current_entry].first_level); +#endif freeSetupFileList(setup_file_list); current_entry++; @@ -1609,13 +1660,15 @@ static int LoadLevelInfoFromLevelDir(char *level_directory, int start_entry) free(filename); } - if (current_entry == MAX_LEVDIR_ENTRIES) - Error(ERR_WARN, "using %d level directories -- ignoring the rest", - current_entry); - closedir(dir); - if (current_entry == start_entry) + if (current_entry == MAX_LEVDIR_ENTRIES) + { + Error(ERR_WARN, "maximum of %d level directories reached", current_entry); + Error(ERR_WARN, "remaining level directories ignored in directory '%s'", + level_directory); + } + else if (current_entry == start_entry) Error(ERR_WARN, "cannot find any valid level series in directory '%s'", level_directory); @@ -1629,6 +1682,8 @@ void LoadLevelInfo() num_leveldirs = 0; leveldir_nr = 0; + DrawInitText("Loading level series:", 120, FC_GREEN); + num_leveldirs = LoadLevelInfoFromLevelDir(options.level_directory, num_leveldirs); num_leveldirs = LoadLevelInfoFromLevelDir(getUserLevelDir(""), @@ -1671,7 +1726,9 @@ static void SaveUserLevelInfo() getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, LEVELINFO_COOKIE)); for (i=FIRST_LEVELINFO_TOKEN; i<=LAST_LEVELINFO_TOKEN; i++) - if (i != LEVELINFO_TOKEN_NAME_SHORT && i != LEVELINFO_TOKEN_IMPORTED_FROM) + if (i != LEVELINFO_TOKEN_NAME_SHORT && + i != LEVELINFO_TOKEN_NAME_SORTING && + i != LEVELINFO_TOKEN_IMPORTED_FROM) fprintf(file, "%s\n", getSetupLine("", i)); fclose(file); @@ -1833,54 +1890,48 @@ void SaveSetup() chmod(filename, SETUP_PERMS); } -void LoadLevelSetup() +void LoadLevelSetup_LastSeries() { char *filename; + struct SetupFileList *level_setup_list = NULL; /* always start with reliable default values */ leveldir_nr = 0; - level_nr = 0; - filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME); + /* ----------------------------------------------------------------------- */ + /* ~/.rocksndiamonds/levelsetup.conf */ + /* ----------------------------------------------------------------------- */ - if (level_setup_list) - freeSetupFileList(level_setup_list); - - level_setup_list = loadSetupFileList(filename); + filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME); - if (level_setup_list) + if ((level_setup_list = loadSetupFileList(filename))) { char *last_level_series = getTokenValue(level_setup_list, TOKEN_STR_LAST_LEVEL_SERIES); leveldir_nr = getLevelSeriesNrFromLevelSeriesName(last_level_series); - level_nr = getLastPlayedLevelOfLevelSeries(last_level_series); checkSetupFileListIdentifier(level_setup_list, LEVELSETUP_COOKIE); + + freeSetupFileList(level_setup_list); } else - { - level_setup_list = newSetupFileList(TOKEN_STR_FILE_IDENTIFIER, - LEVELSETUP_COOKIE); Error(ERR_WARN, "using default setup values"); - } free(filename); } -void SaveLevelSetup() +void SaveLevelSetup_LastSeries() { char *filename; - struct SetupFileList *list_entry = level_setup_list; + char *level_subdir = leveldir[leveldir_nr].filename; FILE *file; - InitUserDataDirectory(); - - setTokenValue(level_setup_list, - TOKEN_STR_LAST_LEVEL_SERIES, leveldir[leveldir_nr].filename); + /* ----------------------------------------------------------------------- */ + /* ~/.rocksndiamonds/levelsetup.conf */ + /* ----------------------------------------------------------------------- */ - setTokenValue(level_setup_list, - leveldir[leveldir_nr].filename, int2str(level_nr, 0)); + InitUserDataDirectory(); filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME); @@ -1893,19 +1944,161 @@ void SaveLevelSetup() fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, LEVELSETUP_COOKIE)); - while (list_entry) + fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_LEVEL_SERIES, + level_subdir)); + + fclose(file); + free(filename); + + chmod(filename, SETUP_PERMS); +} + +static void checkSeriesInfo(int leveldir_nr) +{ + static char *level_directory = NULL; + DIR *dir; + struct dirent *dir_entry; + + /* check for more levels besides the 'levels' field of 'levelinfo.conf' */ + + level_directory = getPath2((leveldir[leveldir_nr].user_defined ? + getUserLevelDir("") : + options.level_directory), + leveldir[leveldir_nr].filename); + + if ((dir = opendir(level_directory)) == NULL) { - if (strcmp(list_entry->token, TOKEN_STR_FILE_IDENTIFIER) != 0) - fprintf(file, "%s\n", - getFormattedSetupEntry(list_entry->token, list_entry->value)); + Error(ERR_WARN, "cannot read level directory '%s'", level_directory); + return; + } - /* just to make things nicer :) */ - if (strcmp(list_entry->token, TOKEN_STR_LAST_LEVEL_SERIES) == 0) - fprintf(file, "\n"); + while ((dir_entry = readdir(dir)) != NULL) /* last directory entry */ + { + if (strlen(dir_entry->d_name) > 4 && + dir_entry->d_name[3] == '.' && + strcmp(&dir_entry->d_name[4], LEVELFILE_EXTENSION) == 0) + { + char levelnum_str[4]; + int levelnum_value; + + strncpy(levelnum_str, dir_entry->d_name, 3); + levelnum_str[3] = '\0'; + + levelnum_value = atoi(levelnum_str); - list_entry = list_entry->next; + if (levelnum_value < leveldir[leveldir_nr].first_level) + { + Error(ERR_WARN, "additional level %d found", levelnum_value); + leveldir[leveldir_nr].first_level = levelnum_value; + } + else if (levelnum_value > leveldir[leveldir_nr].last_level) + { + Error(ERR_WARN, "additional level %d found", levelnum_value); + leveldir[leveldir_nr].last_level = levelnum_value; + } + } } + closedir(dir); +} + +void LoadLevelSetup_SeriesInfo(int leveldir_nr) +{ + char *filename; + struct SetupFileList *level_setup_list = NULL; + char *level_subdir = leveldir[leveldir_nr].filename; + + /* always start with reliable default values */ +#if 0 + level_nr = 0; + leveldir[leveldir_nr].handicap_level = 0; +#else + level_nr = leveldir[leveldir_nr].first_level; +#endif + + checkSeriesInfo(leveldir_nr); + + /* ----------------------------------------------------------------------- */ + /* ~/.rocksndiamonds/levelsetup//levelsetup.conf */ + /* ----------------------------------------------------------------------- */ + + level_subdir = leveldir[leveldir_nr].filename; + + filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME); + + if ((level_setup_list = loadSetupFileList(filename))) + { + char *token_value; + + token_value = getTokenValue(level_setup_list, TOKEN_STR_LAST_PLAYED_LEVEL); + + if (token_value) + { + level_nr = atoi(token_value); + + if (level_nr < leveldir[leveldir_nr].first_level) + level_nr = leveldir[leveldir_nr].first_level; + if (level_nr > leveldir[leveldir_nr].last_level) + level_nr = leveldir[leveldir_nr].last_level; + } + + token_value = getTokenValue(level_setup_list, TOKEN_STR_HANDICAP_LEVEL); + + if (token_value) + { + int level_nr = atoi(token_value); + + if (level_nr < leveldir[leveldir_nr].first_level) + level_nr = leveldir[leveldir_nr].first_level; + if (level_nr > leveldir[leveldir_nr].last_level + 1) + level_nr = leveldir[leveldir_nr].last_level; + + if (leveldir[leveldir_nr].user_defined) + level_nr = leveldir[leveldir_nr].last_level; + + leveldir[leveldir_nr].handicap_level = level_nr; + } + + checkSetupFileListIdentifier(level_setup_list, LEVELSETUP_COOKIE); + + freeSetupFileList(level_setup_list); + } + else + Error(ERR_WARN, "using default setup values"); + + free(filename); +} + +void SaveLevelSetup_SeriesInfo(int leveldir_nr) +{ + char *filename; + char *level_subdir = leveldir[leveldir_nr].filename; + char *level_nr_str = int2str(level_nr, 0); + char *handicap_level_str = int2str(leveldir[leveldir_nr].handicap_level, 0); + FILE *file; + + /* ----------------------------------------------------------------------- */ + /* ~/.rocksndiamonds/levelsetup//levelsetup.conf */ + /* ----------------------------------------------------------------------- */ + + InitLevelSetupDirectory(level_subdir); + + filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME); + + if (!(file = fopen(filename, "w"))) + { + Error(ERR_WARN, "cannot write setup file '%s'", filename); + free(filename); + return; + } + + fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, + LEVELSETUP_COOKIE)); + fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_PLAYED_LEVEL, + level_nr_str)); + fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_HANDICAP_LEVEL, + handicap_level_str)); + fclose(file); free(filename); @@ -1913,39 +2106,22 @@ void SaveLevelSetup() } #ifdef MSDOS -static boolean initErrorFile() +void initErrorFile() { char *filename; - FILE *error_file; InitUserDataDirectory(); filename = getPath2(getUserDataDir(), ERROR_FILENAME); - error_file = fopen(filename, "w"); + unlink(filename); free(filename); - - if (error_file == NULL) - return FALSE; - - fclose(error_file); - - return TRUE; } FILE *openErrorFile() { - static boolean first_access = TRUE; char *filename; FILE *error_file; - if (first_access) - { - if (!initErrorFile()) - return NULL; - - first_access = FALSE; - } - filename = getPath2(getUserDataDir(), ERROR_FILENAME); error_file = fopen(filename, "a"); free(filename);