X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=1bcbec75a4341748095f29dd9cba338414c88868;hb=e0e2697df0d0da483a91b1248c120aef6b3caf9b;hp=9b5b73f5b302b002695091b382af99f7ea8f33da;hpb=4311b2aed4570447d0e082334e8b8a6b7da6e9f9;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index 9b5b73f5..1bcbec75 100644 --- a/src/files.c +++ b/src/files.c @@ -12,7 +12,6 @@ ***********************************************************/ #include -#include #include #include "libgame/libgame.h" @@ -20,14 +19,14 @@ #include "files.h" #include "tools.h" #include "tape.h" -#include "joystick.h" + #define CHUNK_ID_LEN 4 /* IFF style chunk id length */ #define CHUNK_SIZE_UNDEFINED 0 /* undefined chunk size == 0 */ #define CHUNK_SIZE_NONE -1 /* do not write chunk size */ #define FILE_VERS_CHUNK_SIZE 8 /* size of file version chunk */ #define LEVEL_HEADER_SIZE 80 /* size of level file header */ -#define LEVEL_HEADER_UNUSED 15 /* unused level header bytes */ +#define LEVEL_HEADER_UNUSED 14 /* unused level header bytes */ #define LEVEL_CHUNK_CNT2_SIZE 160 /* size of level CNT2 chunk */ #define LEVEL_CHUNK_CNT2_UNUSED 11 /* unused CNT2 chunk bytes */ #define TAPE_HEADER_SIZE 20 /* size of tape file header */ @@ -37,328 +36,11 @@ #define LEVEL_COOKIE_TMPL "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x" #define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x" #define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2" -#define SETUP_COOKIE "ROCKSNDIAMONDS_SETUP_FILE_VERSION_1.2" -#define LEVELSETUP_COOKIE "ROCKSNDIAMONDS_LEVELSETUP_FILE_VERSION_1.2" -#define LEVELINFO_COOKIE "ROCKSNDIAMONDS_LEVELINFO_FILE_VERSION_1.2" - -/* file names and filename extensions */ -#if !defined(PLATFORM_MSDOS) -#define LEVELSETUP_DIRECTORY "levelsetup" -#define SETUP_FILENAME "setup.conf" -#define LEVELSETUP_FILENAME "levelsetup.conf" -#define LEVELINFO_FILENAME "levelinfo.conf" -#define LEVELFILE_EXTENSION "level" -#define TAPEFILE_EXTENSION "tape" -#define SCOREFILE_EXTENSION "score" -#else -#define LEVELSETUP_DIRECTORY "lvlsetup" -#define SETUP_FILENAME "setup.cnf" -#define LEVELSETUP_FILENAME "lvlsetup.cnf" -#define LEVELINFO_FILENAME "lvlinfo.cnf" -#define LEVELFILE_EXTENSION "lvl" -#define TAPEFILE_EXTENSION "tap" -#define SCOREFILE_EXTENSION "sco" -#endif - -/* sort priorities of level series (also used as level series classes) */ -#define LEVELCLASS_TUTORIAL_START 10 -#define LEVELCLASS_TUTORIAL_END 99 -#define LEVELCLASS_CLASSICS_START 100 -#define LEVELCLASS_CLASSICS_END 199 -#define LEVELCLASS_CONTRIBUTION_START 200 -#define LEVELCLASS_CONTRIBUTION_END 299 -#define LEVELCLASS_USER_START 300 -#define LEVELCLASS_USER_END 399 -#define LEVELCLASS_BD_START 400 -#define LEVELCLASS_BD_END 499 -#define LEVELCLASS_EM_START 500 -#define LEVELCLASS_EM_END 599 -#define LEVELCLASS_SP_START 600 -#define LEVELCLASS_SP_END 699 -#define LEVELCLASS_DX_START 700 -#define LEVELCLASS_DX_END 799 - -#define LEVELCLASS_TUTORIAL LEVELCLASS_TUTORIAL_START -#define LEVELCLASS_CLASSICS LEVELCLASS_CLASSICS_START -#define LEVELCLASS_CONTRIBUTION LEVELCLASS_CONTRIBUTION_START -#define LEVELCLASS_USER LEVELCLASS_USER_START -#define LEVELCLASS_BD LEVELCLASS_BD_START -#define LEVELCLASS_EM LEVELCLASS_EM_START -#define LEVELCLASS_SP LEVELCLASS_SP_START -#define LEVELCLASS_DX LEVELCLASS_DX_START - -#define LEVELCLASS_UNDEFINED 999 - -#define NUM_LEVELCLASS_DESC 8 -char *levelclass_desc[NUM_LEVELCLASS_DESC] = -{ - "Tutorial Levels", - "Classic Originals", - "Contributions", - "Private Levels", - "Boulderdash", - "Emerald Mine", - "Supaplex", - "DX Boulderdash" -}; - -#define IS_LEVELCLASS_TUTORIAL(p) \ - ((p)->sort_priority >= LEVELCLASS_TUTORIAL_START && \ - (p)->sort_priority <= LEVELCLASS_TUTORIAL_END) -#define IS_LEVELCLASS_CLASSICS(p) \ - ((p)->sort_priority >= LEVELCLASS_CLASSICS_START && \ - (p)->sort_priority <= LEVELCLASS_CLASSICS_END) -#define IS_LEVELCLASS_CONTRIBUTION(p) \ - ((p)->sort_priority >= LEVELCLASS_CONTRIBUTION_START && \ - (p)->sort_priority <= LEVELCLASS_CONTRIBUTION_END) -#define IS_LEVELCLASS_USER(p) \ - ((p)->sort_priority >= LEVELCLASS_USER_START && \ - (p)->sort_priority <= LEVELCLASS_USER_END) -#define IS_LEVELCLASS_BD(p) \ - ((p)->sort_priority >= LEVELCLASS_BD_START && \ - (p)->sort_priority <= LEVELCLASS_BD_END) -#define IS_LEVELCLASS_EM(p) \ - ((p)->sort_priority >= LEVELCLASS_EM_START && \ - (p)->sort_priority <= LEVELCLASS_EM_END) -#define IS_LEVELCLASS_SP(p) \ - ((p)->sort_priority >= LEVELCLASS_SP_START && \ - (p)->sort_priority <= LEVELCLASS_SP_END) -#define IS_LEVELCLASS_DX(p) \ - ((p)->sort_priority >= LEVELCLASS_DX_START && \ - (p)->sort_priority <= LEVELCLASS_DX_END) - -#define LEVELCLASS(n) (IS_LEVELCLASS_TUTORIAL(n) ? LEVELCLASS_TUTORIAL : \ - IS_LEVELCLASS_CLASSICS(n) ? LEVELCLASS_CLASSICS : \ - IS_LEVELCLASS_CONTRIBUTION(n) ? LEVELCLASS_CONTRIBUTION : \ - IS_LEVELCLASS_USER(n) ? LEVELCLASS_USER : \ - IS_LEVELCLASS_BD(n) ? LEVELCLASS_BD : \ - IS_LEVELCLASS_EM(n) ? LEVELCLASS_EM : \ - IS_LEVELCLASS_SP(n) ? LEVELCLASS_SP : \ - IS_LEVELCLASS_DX(n) ? LEVELCLASS_DX : \ - LEVELCLASS_UNDEFINED) - -#define LEVELCOLOR(n) (IS_LEVELCLASS_TUTORIAL(n) ? FC_BLUE : \ - IS_LEVELCLASS_CLASSICS(n) ? FC_RED : \ - IS_LEVELCLASS_BD(n) ? FC_GREEN : \ - IS_LEVELCLASS_EM(n) ? FC_YELLOW : \ - IS_LEVELCLASS_SP(n) ? FC_GREEN : \ - IS_LEVELCLASS_DX(n) ? FC_YELLOW : \ - IS_LEVELCLASS_CONTRIBUTION(n) ? FC_GREEN : \ - IS_LEVELCLASS_USER(n) ? FC_RED : \ - FC_BLUE) - -#define LEVELSORTING(n) (IS_LEVELCLASS_TUTORIAL(n) ? 0 : \ - IS_LEVELCLASS_CLASSICS(n) ? 1 : \ - IS_LEVELCLASS_BD(n) ? 2 : \ - IS_LEVELCLASS_EM(n) ? 3 : \ - IS_LEVELCLASS_SP(n) ? 4 : \ - IS_LEVELCLASS_DX(n) ? 5 : \ - IS_LEVELCLASS_CONTRIBUTION(n) ? 6 : \ - IS_LEVELCLASS_USER(n) ? 7 : \ - 9) - -char *getLevelClassDescription(struct LevelDirInfo *ldi) -{ - int position = ldi->sort_priority / 100; - - if (position >= 0 && position < NUM_LEVELCLASS_DESC) - return levelclass_desc[position]; - else - return "Unknown Level Class"; -} - -static void SaveUserLevelInfo(); /* for 'InitUserLevelDir()' */ -static char *getSetupLine(char *, int); /* for 'SaveUserLevelInfo()' */ -static char *getUserLevelDir(char *level_subdir) -{ - static char *userlevel_dir = NULL; - char *data_dir = getUserDataDir(); - char *userlevel_subdir = LEVELS_DIRECTORY; - if (userlevel_dir) - free(userlevel_dir); - - if (strlen(level_subdir) > 0) - userlevel_dir = getPath3(data_dir, userlevel_subdir, level_subdir); - else - userlevel_dir = getPath2(data_dir, userlevel_subdir); - - return userlevel_dir; -} - -static char *getTapeDir(char *level_subdir) -{ - static char *tape_dir = NULL; - char *data_dir = getUserDataDir(); - char *tape_subdir = TAPES_DIRECTORY; - - if (tape_dir) - free(tape_dir); - - if (strlen(level_subdir) > 0) - tape_dir = getPath3(data_dir, tape_subdir, level_subdir); - else - tape_dir = getPath2(data_dir, tape_subdir); - - return tape_dir; -} - -static char *getScoreDir(char *level_subdir) -{ - static char *score_dir = NULL; - char *data_dir = options.rw_base_directory; - char *score_subdir = SCORES_DIRECTORY; - - if (score_dir) - free(score_dir); - - if (strlen(level_subdir) > 0) - score_dir = getPath3(data_dir, score_subdir, level_subdir); - else - score_dir = getPath2(data_dir, score_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; - char basename[MAX_FILENAME_LEN]; - - if (filename != NULL) - free(filename); - - sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION); - filename = getPath3((leveldir_current->user_defined ? - getUserLevelDir("") : - options.level_directory), - leveldir_current->fullpath, - basename); - - return filename; -} - -static char *getTapeFilename(int nr) -{ - static char *filename = NULL; - char basename[MAX_FILENAME_LEN]; - - if (filename != NULL) - free(filename); - - sprintf(basename, "%03d.%s", nr, TAPEFILE_EXTENSION); - filename = getPath2(getTapeDir(leveldir_current->filename), basename); - - return filename; -} - -static char *getScoreFilename(int nr) -{ - static char *filename = NULL; - char basename[MAX_FILENAME_LEN]; - - if (filename != NULL) - free(filename); - - sprintf(basename, "%03d.%s", nr, SCOREFILE_EXTENSION); - filename = getPath2(getScoreDir(leveldir_current->filename), basename); - - return filename; -} - -static void InitTapeDirectory(char *level_subdir) -{ - createDirectory(getUserDataDir(), "user data", PERMS_PRIVATE); - createDirectory(getTapeDir(""), "main tape", PERMS_PRIVATE); - createDirectory(getTapeDir(level_subdir), "level tape", PERMS_PRIVATE); -} - -static void InitScoreDirectory(char *level_subdir) -{ - createDirectory(getScoreDir(""), "main score", PERMS_PUBLIC); - createDirectory(getScoreDir(level_subdir), "level score", PERMS_PUBLIC); -} - -static void InitUserLevelDirectory(char *level_subdir) -{ - if (access(getUserLevelDir(level_subdir), F_OK) != 0) - { - createDirectory(getUserDataDir(), "user data", PERMS_PRIVATE); - createDirectory(getUserLevelDir(""), "main user level", PERMS_PRIVATE); - createDirectory(getUserLevelDir(level_subdir), "user level",PERMS_PRIVATE); - - SaveUserLevelInfo(); - } -} - -static void InitLevelSetupDirectory(char *level_subdir) -{ - createDirectory(getUserDataDir(), "user data", PERMS_PRIVATE); - createDirectory(getLevelSetupDir(""), "main level setup", PERMS_PRIVATE); - createDirectory(getLevelSetupDir(level_subdir), "level setup",PERMS_PRIVATE); -} - -static void ReadChunk_VERS(FILE *file, int *file_version, int *game_version) -{ - int file_version_major, file_version_minor, file_version_patch; - int game_version_major, game_version_minor, game_version_patch; - - file_version_major = fgetc(file); - file_version_minor = fgetc(file); - file_version_patch = fgetc(file); - fgetc(file); /* not used */ - - game_version_major = fgetc(file); - game_version_minor = fgetc(file); - game_version_patch = fgetc(file); - fgetc(file); /* not used */ - - *file_version = VERSION_IDENT(file_version_major, - file_version_minor, - file_version_patch); - - *game_version = VERSION_IDENT(game_version_major, - game_version_minor, - game_version_patch); -} - -static void WriteChunk_VERS(FILE *file, int file_version, int game_version) -{ - int file_version_major = VERSION_MAJOR(file_version); - int file_version_minor = VERSION_MINOR(file_version); - int file_version_patch = VERSION_PATCH(file_version); - int game_version_major = VERSION_MAJOR(game_version); - int game_version_minor = VERSION_MINOR(game_version); - int game_version_patch = VERSION_PATCH(game_version); - - fputc(file_version_major, file); - fputc(file_version_minor, file); - fputc(file_version_patch, file); - fputc(0, file); /* not used */ - - fputc(game_version_major, file); - fputc(game_version_minor, file); - fputc(game_version_patch, file); - fputc(0, file); /* not used */ -} +/* ========================================================================= */ +/* level file functions */ +/* ========================================================================= */ static void setLevelInfoToDefaults() { @@ -388,6 +70,7 @@ static void setLevelInfoToDefaults() level.amoeba_content = EL_DIAMANT; level.double_speed = FALSE; level.gravity = FALSE; + level.em_slippery_gems = FALSE; for(i=0; iamoeba_content = checkLevelElement(fgetc(file)); level->double_speed = (fgetc(file) == 1 ? TRUE : FALSE); level->gravity = (fgetc(file) == 1 ? TRUE : FALSE); - level->encoding_16bit_field = (fgetc(file) == 1 ? TRUE : FALSE); + level->em_slippery_gems = (fgetc(file) == 1 ? TRUE : FALSE); ReadUnusedBytesFromFile(file, LEVEL_HEADER_UNUSED); @@ -673,6 +356,9 @@ void LoadLevel(int level_nr) fclose(file); return; } + + /* pre-2.0 level files have no game version, so use file version here */ + level.game_version = level.file_version; } if (level.file_version < FILE_VERSION_1_2) @@ -744,23 +430,44 @@ void LoadLevel(int level_nr) if (IS_LEVELCLASS_CONTRIBUTION(leveldir_current) || IS_LEVELCLASS_USER(leveldir_current)) { - /* for user contributed and private levels, use the version of - the game engine the levels were created for */ - level.game_version = level.file_version; - - /* player was faster than monsters in pre-1.0 levels */ + /* For user contributed and private levels, use the version of + the game engine the levels were created for. + Since 2.0.1, the game engine version is now directly stored + in the level file (chunk "VERS"), so there is no need anymore + to set the game version from the file version (except for old, + pre-2.0 levels, where the game version is still taken from the + file format version used to store the level -- see above). */ + + /* do some special adjustments to support older level versions */ if (level.file_version == FILE_VERSION_1_0) { Error(ERR_WARN, "level file '%s' has version number 1.0", filename); Error(ERR_WARN, "using high speed movement for player"); + + /* player was faster than monsters in (pre-)1.0 levels */ level.double_speed = TRUE; } } else { - /* always use the latest version of the game engine for all but - user contributed and private levels */ + /* Always use the latest version of the game engine for all but + user contributed and private levels; this allows for actual + corrections in the game engine to take effect for existing, + converted levels (from "classic" or other existing games) to + make the game emulation more accurate, while (hopefully) not + breaking existing levels created from other players. */ + level.game_version = GAME_VERSION_ACTUAL; + + /* Set special EM style gems behaviour: EM style gems slip down from + normal, steel and growing wall. As this is a more fundamental change, + it seems better to set the default behaviour to "off" (as it is more + natural) and make it configurable in the level editor (as a property + of gem style elements). Already existing converted levels (neither + private nor contributed levels) are changed to the new behaviour. */ + + if (level.file_version < FILE_VERSION_2_0) + level.em_slippery_gems = TRUE; } /* determine border element for this level */ @@ -796,8 +503,8 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level) file); fputc((level->double_speed ? 1 : 0), file); fputc((level->gravity ? 1 : 0), file); - fputc((level->encoding_16bit_field ? 1 : 0), file); + fputc((level->em_slippery_gems ? 1 : 0), file); WriteUnusedBytesToFile(file, LEVEL_HEADER_UNUSED); } @@ -965,6 +672,11 @@ void SaveLevel(int level_nr) SetFilePermissions(filename, PERMS_PRIVATE); } + +/* ========================================================================= */ +/* tape file functions */ +/* ========================================================================= */ + static void setTapeInfoToDefaults() { int i; @@ -1159,9 +871,10 @@ void LoadTape(int level_nr) fclose(file); return; } - } - tape.game_version = tape.file_version; + /* pre-2.0 tape files have no game version, so use file version here */ + tape.game_version = tape.file_version; + } if (tape.file_version < FILE_VERSION_1_2) { @@ -1360,6 +1073,11 @@ void DumpTape(struct TapeInfo *tape) printf("-------------------------------------------------------------------------------\n"); } + +/* ========================================================================= */ +/* score file functions */ +/* ========================================================================= */ + void LoadScore(int level_nr) { int i; @@ -1437,13 +1155,11 @@ void SaveScore(int level_nr) SetFilePermissions(filename, PERMS_PUBLIC); } -/* ------------------------------------------------------------------------- */ -/* setup file stuff */ -/* ------------------------------------------------------------------------- */ -#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" +/* ========================================================================= */ +/* setup file functions */ +/* ========================================================================= */ + #define TOKEN_STR_PLAYER_PREFIX "player_" /* global setup */ @@ -1462,54 +1178,32 @@ void SaveScore(int level_nr) #define SETUP_TOKEN_TIME_LIMIT 12 #define SETUP_TOKEN_FULLSCREEN 13 +#define NUM_GLOBAL_SETUP_TOKENS 14 + /* player setup */ -#define SETUP_TOKEN_USE_JOYSTICK 14 -#define SETUP_TOKEN_JOY_DEVICE_NAME 15 -#define SETUP_TOKEN_JOY_XLEFT 16 -#define SETUP_TOKEN_JOY_XMIDDLE 17 -#define SETUP_TOKEN_JOY_XRIGHT 18 -#define SETUP_TOKEN_JOY_YUPPER 19 -#define SETUP_TOKEN_JOY_YMIDDLE 20 -#define SETUP_TOKEN_JOY_YLOWER 21 -#define SETUP_TOKEN_JOY_SNAP 22 -#define SETUP_TOKEN_JOY_BOMB 23 -#define SETUP_TOKEN_KEY_LEFT 24 -#define SETUP_TOKEN_KEY_RIGHT 25 -#define SETUP_TOKEN_KEY_UP 26 -#define SETUP_TOKEN_KEY_DOWN 27 -#define SETUP_TOKEN_KEY_SNAP 28 -#define SETUP_TOKEN_KEY_BOMB 29 - -/* level directory info */ -#define LEVELINFO_TOKEN_NAME 30 -#define LEVELINFO_TOKEN_NAME_SHORT 31 -#define LEVELINFO_TOKEN_NAME_SORTING 32 -#define LEVELINFO_TOKEN_AUTHOR 33 -#define LEVELINFO_TOKEN_IMPORTED_FROM 34 -#define LEVELINFO_TOKEN_LEVELS 35 -#define LEVELINFO_TOKEN_FIRST_LEVEL 36 -#define LEVELINFO_TOKEN_SORT_PRIORITY 37 -#define LEVELINFO_TOKEN_LEVEL_GROUP 38 -#define LEVELINFO_TOKEN_READONLY 39 - -#define FIRST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_PLAYER_NAME -#define LAST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_FULLSCREEN - -#define FIRST_PLAYER_SETUP_TOKEN SETUP_TOKEN_USE_JOYSTICK -#define LAST_PLAYER_SETUP_TOKEN SETUP_TOKEN_KEY_BOMB - -#define FIRST_LEVELINFO_TOKEN LEVELINFO_TOKEN_NAME -#define LAST_LEVELINFO_TOKEN LEVELINFO_TOKEN_READONLY +#define SETUP_TOKEN_USE_JOYSTICK 0 +#define SETUP_TOKEN_JOY_DEVICE_NAME 1 +#define SETUP_TOKEN_JOY_XLEFT 2 +#define SETUP_TOKEN_JOY_XMIDDLE 3 +#define SETUP_TOKEN_JOY_XRIGHT 4 +#define SETUP_TOKEN_JOY_YUPPER 5 +#define SETUP_TOKEN_JOY_YMIDDLE 6 +#define SETUP_TOKEN_JOY_YLOWER 7 +#define SETUP_TOKEN_JOY_SNAP 8 +#define SETUP_TOKEN_JOY_BOMB 9 +#define SETUP_TOKEN_KEY_LEFT 10 +#define SETUP_TOKEN_KEY_RIGHT 11 +#define SETUP_TOKEN_KEY_UP 12 +#define SETUP_TOKEN_KEY_DOWN 13 +#define SETUP_TOKEN_KEY_SNAP 14 +#define SETUP_TOKEN_KEY_BOMB 15 + +#define NUM_PLAYER_SETUP_TOKENS 16 static struct SetupInfo si; static struct SetupInputInfo sii; -static struct LevelDirInfo ldi; -static struct -{ - int type; - void *value; - char *text; -} token_info[] = + +static struct TokenInfo global_setup_tokens[] = { /* global setup */ { TYPE_STRING, &si.player_name, "player_name" }, @@ -1525,8 +1219,11 @@ static struct { TYPE_SWITCH, &si.team_mode, "team_mode" }, { TYPE_SWITCH, &si.handicap, "handicap" }, { TYPE_SWITCH, &si.time_limit, "time_limit" }, - { TYPE_SWITCH, &si.fullscreen, "fullscreen" }, + { TYPE_SWITCH, &si.fullscreen, "fullscreen" } +}; +static struct TokenInfo player_setup_tokens[] = +{ /* player setup */ { TYPE_BOOLEAN, &sii.use_joystick, ".use_joystick" }, { TYPE_STRING, &sii.joy.device_name, ".joy.device_name" }, @@ -1543,86 +1240,9 @@ static struct { TYPE_KEY, &sii.key.up, ".key.move_up" }, { TYPE_KEY, &sii.key.down, ".key.move_down" }, { TYPE_KEY, &sii.key.snap, ".key.snap_field" }, - { TYPE_KEY, &sii.key.bomb, ".key.place_bomb" }, - - /* 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" }, - { TYPE_INTEGER, &ldi.first_level, "first_level" }, - { TYPE_INTEGER, &ldi.sort_priority, "sort_priority" }, - { TYPE_BOOLEAN, &ldi.level_group, "level_group" }, - { TYPE_BOOLEAN, &ldi.readonly, "readonly" } + { TYPE_KEY, &sii.key.bomb, ".key.place_bomb" } }; -static void setLevelDirInfoToDefaults(struct LevelDirInfo *ldi) -{ - ldi->filename = NULL; - ldi->fullpath = NULL; - ldi->basepath = 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->level_group = FALSE; - ldi->parent_link = FALSE; - ldi->user_defined = FALSE; - ldi->readonly = TRUE; - ldi->color = 0; - ldi->class_desc = NULL; - ldi->handicap_level = 0; - ldi->cl_first = -1; - ldi->cl_cursor = -1; - - ldi->node_parent = NULL; - ldi->node_group = NULL; - ldi->next = NULL; -} - -static void setLevelDirInfoToDefaultsFromParent(struct LevelDirInfo *ldi, - struct LevelDirInfo *parent) -{ - if (parent == NULL) - { - setLevelDirInfoToDefaults(ldi); - return; - } - - /* first copy all values from the parent structure ... */ - *ldi = *parent; - - /* ... then set all fields to default that cannot be inherited from parent. - This is especially important for all those fields that can be set from - the 'levelinfo.conf' config file, because the function 'setSetupInfo()' - calls 'free()' for all already set token values which requires that no - other structure's pointer may point to them! - */ - - ldi->filename = NULL; - ldi->fullpath = NULL; - ldi->basepath = NULL; - ldi->name = getStringCopy(ANONYMOUS_NAME); - ldi->name_short = NULL; - ldi->name_sorting = NULL; - ldi->author = getStringCopy(parent->author); - ldi->imported_from = getStringCopy(parent->imported_from); - - ldi->level_group = FALSE; - ldi->parent_link = FALSE; - - ldi->node_parent = parent; - ldi->node_group = NULL; - ldi->next = NULL; -} - static void setSetupInfoToDefaults(struct SetupInfo *si) { int i; @@ -1649,7 +1269,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) for (i=0; iinput[i].use_joystick = FALSE; - si->input[i].joy.device_name = getStringCopy(joystick_device_name[i]); + si->input[i].joy.device_name=getStringCopy(getDeviceNameFromJoystickNr(i)); si->input[i].joy.xleft = JOYSTICK_XLEFT; si->input[i].joy.xmiddle = JOYSTICK_XMIDDLE; si->input[i].joy.xright = JOYSTICK_XRIGHT; @@ -1667,41 +1287,6 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) } } -static void setSetupInfo(int token_nr, char *token_value) -{ - int token_type = token_info[token_nr].type; - void *setup_value = token_info[token_nr].value; - - if (token_value == NULL) - return; - - /* set setup field to corresponding token value */ - switch (token_type) - { - case TYPE_BOOLEAN: - case TYPE_SWITCH: - *(boolean *)setup_value = get_string_boolean_value(token_value); - break; - - case TYPE_KEY: - *(Key *)setup_value = getKeyFromX11KeyName(token_value); - break; - - case TYPE_INTEGER: - *(int *)setup_value = get_string_integer_value(token_value); - break; - - case TYPE_STRING: - if (*(char **)setup_value != NULL) - free(*(char **)setup_value); - *(char **)setup_value = getStringCopy(token_value); - break; - - default: - break; - } -} - static void decodeSetupFileList(struct SetupFileList *setup_file_list) { int i, pnr; @@ -1711,8 +1296,9 @@ static void decodeSetupFileList(struct SetupFileList *setup_file_list) /* handle global setup values */ si = setup; - for (i=FIRST_GLOBAL_SETUP_TOKEN; i<=LAST_GLOBAL_SETUP_TOKEN; i++) - setSetupInfo(i, getTokenValue(setup_file_list, token_info[i].text)); + for (i=0; iparent_link || entry2->parent_link) - compare_result = (entry1->parent_link ? -1 : +1); - else if (entry1->sort_priority == entry2->sort_priority) - { - char *name1 = getStringToLower(entry1->name_sorting); - char *name2 = getStringToLower(entry2->name_sorting); - - compare_result = strcmp(name1, name2); - - free(name1); - free(name2); - } - else if (LEVELSORTING(entry1) == LEVELSORTING(entry2)) - compare_result = entry1->sort_priority - entry2->sort_priority; - else - compare_result = LEVELSORTING(entry1) - LEVELSORTING(entry2); - - return compare_result; -} - -static void createParentLevelDirNode(struct LevelDirInfo *node_parent) -{ - struct LevelDirInfo *leveldir_new = newLevelDirInfo(); - - setLevelDirInfoToDefaults(leveldir_new); - - leveldir_new->node_parent = node_parent; - leveldir_new->parent_link = TRUE; - - leveldir_new->name = ".. (parent directory)"; - leveldir_new->name_short = getStringCopy(leveldir_new->name); - leveldir_new->name_sorting = getStringCopy(leveldir_new->name); - - leveldir_new->filename = ".."; - leveldir_new->fullpath = getStringCopy(node_parent->fullpath); - - leveldir_new->sort_priority = node_parent->sort_priority; - leveldir_new->class_desc = getLevelClassDescription(leveldir_new); - - pushLevelDirInfo(&node_parent->node_group, leveldir_new); -} - -static void LoadLevelInfoFromLevelDir(struct LevelDirInfo **node_first, - struct LevelDirInfo *node_parent, - char *level_directory) -{ - DIR *dir; - struct dirent *dir_entry; - boolean valid_entry_found = FALSE; - - if ((dir = opendir(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 */ - { - struct SetupFileList *setup_file_list = NULL; - struct stat file_status; - char *directory_name = dir_entry->d_name; - char *directory_path = getPath2(level_directory, directory_name); - char *filename = NULL; - - /* skip entries for current and parent directory */ - if (strcmp(directory_name, ".") == 0 || - strcmp(directory_name, "..") == 0) - { - 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; - } - - filename = getPath2(directory_path, LEVELINFO_FILENAME); - setup_file_list = loadSetupFileList(filename); - - if (setup_file_list) - { - struct LevelDirInfo *leveldir_new = newLevelDirInfo(); - int i; - - checkSetupFileListIdentifier(setup_file_list, LEVELINFO_COOKIE); - setLevelDirInfoToDefaultsFromParent(leveldir_new, node_parent); - - /* set all structure fields according to the token/value pairs */ - ldi = *leveldir_new; - for (i=FIRST_LEVELINFO_TOKEN; i<=LAST_LEVELINFO_TOKEN; i++) - setSetupInfo(i, getTokenValue(setup_file_list, token_info[i].text)); - *leveldir_new = ldi; - - DrawInitText(leveldir_new->name, 150, FC_YELLOW); - - if (leveldir_new->name_short == NULL) - leveldir_new->name_short = getStringCopy(leveldir_new->name); - - if (leveldir_new->name_sorting == NULL) - leveldir_new->name_sorting = getStringCopy(leveldir_new->name); - - leveldir_new->filename = getStringCopy(directory_name); - - if (node_parent == NULL) /* top level group */ - { - leveldir_new->basepath = level_directory; - leveldir_new->fullpath = leveldir_new->filename; - } - else /* sub level group */ - { - leveldir_new->basepath = node_parent->basepath; - leveldir_new->fullpath = getPath2(node_parent->fullpath, - directory_name); - } - - if (leveldir_new->levels < 1) - leveldir_new->levels = 1; - - leveldir_new->last_level = - leveldir_new->first_level + leveldir_new->levels - 1; - - leveldir_new->user_defined = - (leveldir_new->basepath == options.level_directory ? FALSE : TRUE); - - leveldir_new->color = LEVELCOLOR(leveldir_new); - leveldir_new->class_desc = getLevelClassDescription(leveldir_new); - - leveldir_new->handicap_level = /* set handicap to default value */ - (leveldir_new->user_defined ? - leveldir_new->last_level : - leveldir_new->first_level); - - pushLevelDirInfo(node_first, leveldir_new); - - freeSetupFileList(setup_file_list); - valid_entry_found = TRUE; - - if (leveldir_new->level_group) - { - /* create node to link back to current level directory */ - createParentLevelDirNode(leveldir_new); - - /* step into sub-directory and look for more level series */ - LoadLevelInfoFromLevelDir(&leveldir_new->node_group, - leveldir_new, directory_path); - } - } - else - Error(ERR_WARN, "ignoring level directory '%s'", directory_path); - - free(directory_path); - free(filename); - } - - closedir(dir); - - if (!valid_entry_found) - Error(ERR_WARN, "cannot find any valid level series in directory '%s'", - level_directory); -} - -void LoadLevelInfo() -{ - InitUserLevelDirectory(getLoginName()); - - DrawInitText("Loading level series:", 120, FC_GREEN); - - LoadLevelInfoFromLevelDir(&leveldir_first, NULL, options.level_directory); - LoadLevelInfoFromLevelDir(&leveldir_first, NULL, getUserLevelDir("")); - - leveldir_current = getFirstValidLevelSeries(leveldir_first); - - if (leveldir_first == NULL) - Error(ERR_EXIT, "cannot find any valid level series in any directory"); - - sortLevelDirInfo(&leveldir_first, compareLevelDirInfoEntries); - -#if 0 - dumpLevelDirInfo(leveldir_first, 0); -#endif -} - -static void SaveUserLevelInfo() -{ - char *filename; - FILE *file; - int i; - - filename = getPath2(getUserLevelDir(getLoginName()), LEVELINFO_FILENAME); - - if (!(file = fopen(filename, MODE_WRITE))) - { - Error(ERR_WARN, "cannot write level info file '%s'", filename); - free(filename); - return; - } - - /* always start with reliable default values */ - setLevelDirInfoToDefaults(&ldi); - - ldi.name = getLoginName(); - ldi.author = getRealName(); - ldi.levels = 100; - ldi.first_level = 1; - ldi.sort_priority = LEVELCLASS_USER_START; - ldi.readonly = FALSE; - - fprintf(file, "%s\n\n", - 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_NAME_SORTING && - i != LEVELINFO_TOKEN_IMPORTED_FROM) - fprintf(file, "%s\n", getSetupLine("", i)); - - fclose(file); - free(filename); - - SetFilePermissions(filename, PERMS_PRIVATE); -} - void LoadSetup() { - char *filename; + char *filename = getSetupFilename(); struct SetupFileList *setup_file_list = NULL; /* always start with reliable default values */ setSetupInfoToDefaults(&setup); - filename = getPath2(getSetupDir(), SETUP_FILENAME); - setup_file_list = loadSetupFileList(filename); if (setup_file_list) { - checkSetupFileListIdentifier(setup_file_list, SETUP_COOKIE); + checkSetupFileListIdentifier(setup_file_list, getCookie("SETUP")); decodeSetupFileList(setup_file_list); setup.direct_draw = !setup.double_buffering; @@ -2001,99 +1354,31 @@ void LoadSetup() } else Error(ERR_WARN, "using default setup values"); - - free(filename); -} - -static char *getSetupLine(char *prefix, int token_nr) -{ - int i; - static char entry[MAX_LINE_LEN]; - int token_type = token_info[token_nr].type; - void *setup_value = token_info[token_nr].value; - char *token_text = token_info[token_nr].text; - - /* start with the prefix, token and some spaces to format output line */ - sprintf(entry, "%s%s:", prefix, token_text); - for (i=strlen(entry); ifilename; - FILE *file; - - /* ----------------------------------------------------------------------- */ - /* ~/.rocksndiamonds/levelsetup.conf */ - /* ----------------------------------------------------------------------- */ - - InitUserDataDirectory(); - - filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME); - - 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, - LEVELSETUP_COOKIE)); - fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_LEVEL_SERIES, - level_subdir)); - - fclose(file); - free(filename); - - SetFilePermissions(filename, PERMS_PRIVATE); -} - -static void checkSeriesInfo() -{ - 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_current->user_defined ? - getUserLevelDir("") : - options.level_directory), - leveldir_current->fullpath); - - if ((dir = opendir(level_directory)) == NULL) - { - Error(ERR_WARN, "cannot read level directory '%s'", level_directory); - return; - } - - 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); - - 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; - } - } - } - - closedir(dir); -} - -void LoadLevelSetup_SeriesInfo() -{ - char *filename; - struct SetupFileList *level_setup_list = NULL; - char *level_subdir = leveldir_current->filename; - - /* always start with reliable default values */ - level_nr = leveldir_current->first_level; - - checkSeriesInfo(leveldir_current); - - /* ----------------------------------------------------------------------- */ - /* ~/.rocksndiamonds/levelsetup//levelsetup.conf */ - /* ----------------------------------------------------------------------- */ - - level_subdir = leveldir_current->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_current->first_level) - level_nr = leveldir_current->first_level; - if (level_nr > leveldir_current->last_level) - level_nr = leveldir_current->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_current->first_level) - level_nr = leveldir_current->first_level; - if (level_nr > leveldir_current->last_level + 1) - level_nr = leveldir_current->last_level; - - if (leveldir_current->user_defined) - level_nr = leveldir_current->last_level; - - leveldir_current->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() -{ - char *filename; - char *level_subdir = leveldir_current->filename; - char *level_nr_str = int2str(level_nr, 0); - char *handicap_level_str = int2str(leveldir_current->handicap_level, 0); - FILE *file; - - /* ----------------------------------------------------------------------- */ - /* ~/.rocksndiamonds/levelsetup//levelsetup.conf */ - /* ----------------------------------------------------------------------- */ - - InitLevelSetupDirectory(level_subdir); - - filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME); - - 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, - 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); SetFilePermissions(filename, PERMS_PRIVATE); }