X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsetup.c;h=acee4a9fd2634ddb52320b2a9df1722a28052685;hb=03cdc074bb51b3157f45bba85c9376aaf63deaf5;hp=0a406540224696e012e1243fe9944407a62a4863;hpb=e8ccf9773b632c21b7739da2c8869b842743ab17;p=rocksndiamonds.git diff --git a/src/libgame/setup.c b/src/libgame/setup.c index 0a406540..acee4a9f 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -70,6 +70,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 SetupFileHash *missing_file_hash = NULL; static boolean use_artworkinfo_cache = TRUE; static boolean update_artworkinfo_cache = FALSE; @@ -78,6 +79,16 @@ static boolean update_artworkinfo_cache = FALSE; // file functions // ---------------------------------------------------------------------------- +static void WarnUsingFallback(char *filename) +{ + if (getHashEntry(missing_file_hash, filename) == NULL) + { + setHashEntry(missing_file_hash, filename, ""); + + Debug("setup", "cannot find artwork file '%s' (using fallback)", filename); + } +} + static char *getLevelClassDescription(TreeInfo *ti) { int position = ti->sort_priority / 100; @@ -153,6 +164,19 @@ static char *getScoreTapeDir(char *level_subdir, int nr) return score_tape_dir; } +static char *getScoreCacheTapeDir(char *level_subdir, int nr) +{ + static char *score_cache_tape_dir = NULL; + char tape_subdir[MAX_FILENAME_LEN]; + + checked_free(score_cache_tape_dir); + + sprintf(tape_subdir, "%03d", nr); + score_cache_tape_dir = getPath2(getScoreCacheDir(level_subdir), tape_subdir); + + return score_cache_tape_dir; +} + static char *getUserSubdir(int nr) { static char user_subdir[16] = { 0 }; @@ -492,7 +516,7 @@ char *getProgramMainDataPath(char *command_filename, char *base_path) set the current working directory to the program package directory) */ char *main_data_path = getBasePath(command_filename); -#if defined(PLATFORM_MACOSX) +#if defined(PLATFORM_MAC) if (strSuffix(main_data_path, MAC_APP_BINARY_SUBDIR)) { char *main_data_path_old = main_data_path; @@ -569,6 +593,34 @@ char *getProgramConfigFilename(char *command_filename) return config_filename_3; } +static char *getPlatformConfigFilename(char *config_filename) +{ + static char *platform_config_filename = NULL; + static boolean initialized = FALSE; + + if (!initialized) + { + char *config_basepath = getBasePath(config_filename); + char *config_basename = getBaseNameNoSuffix(config_filename); + char *config_filename_prefix = getPath2(config_basepath, config_basename); + char *platform_string_lower = getStringToLower(PLATFORM_STRING); + char *platform_suffix = getStringCat2("-", platform_string_lower); + + platform_config_filename = getStringCat3(config_filename_prefix, + platform_suffix, ".conf"); + + checked_free(config_basepath); + checked_free(config_basename); + checked_free(config_filename_prefix); + checked_free(platform_string_lower); + checked_free(platform_suffix); + + initialized = TRUE; + } + + return platform_config_filename; +} + char *getTapeFilename(int nr) { static char *filename = NULL; @@ -694,6 +746,21 @@ char *getScoreTapeFilename(char *basename_no_ext, int nr) return filename; } +char *getScoreCacheTapeFilename(char *basename_no_ext, int nr) +{ + static char *filename = NULL; + char basename[MAX_FILENAME_LEN]; + + checked_free(filename); + + sprintf(basename, "%s.%s", basename_no_ext, TAPEFILE_EXTENSION); + + // used instead of "leveldir_current->subdir" (for network games) + filename = getPath2(getScoreCacheTapeDir(levelset.identifier, nr), basename); + + return filename; +} + char *getSetupFilename(void) { static char *filename = NULL; @@ -710,6 +777,11 @@ char *getDefaultSetupFilename(void) return program.config_filename; } +char *getPlatformSetupFilename(void) +{ + return getPlatformConfigFilename(program.config_filename); +} + char *getEditorSetupFilename(void) { static char *filename = NULL; @@ -853,6 +925,65 @@ char *getLevelSetTitleMessageFilename(int nr, boolean initial) return NULL; // cannot find specified artwork file anywhere } +static char *getCreditsBasename(int nr) +{ + static char basename[32]; + + sprintf(basename, "credits_%d.txt", nr + 1); + + return basename; +} + +char *getCreditsFilename(int nr, boolean global) +{ + char *basename = getCreditsBasename(nr); + char *basepath = NULL; + static char *credits_subdir = NULL; + static char *filename = NULL; + + if (credits_subdir == NULL) + credits_subdir = getPath2(DOCS_DIRECTORY, CREDITS_DIRECTORY); + + checked_free(filename); + + // look for credits file in the game's base or current level set directory + basepath = (global ? options.base_directory : getCurrentLevelDir()); + + filename = getPath3(basepath, credits_subdir, basename); + if (fileExists(filename)) + return filename; + + return NULL; // cannot find credits file +} + +static char *getProgramInfoBasename(int nr) +{ + static char basename[32]; + + sprintf(basename, "program_%d.txt", nr + 1); + + return basename; +} + +char *getProgramInfoFilename(int nr) +{ + char *basename = getProgramInfoBasename(nr); + static char *info_subdir = NULL; + static char *filename = NULL; + + if (info_subdir == NULL) + info_subdir = getPath2(DOCS_DIRECTORY, PROGRAM_INFO_DIRECTORY); + + checked_free(filename); + + // look for program info file in the game's base directory + filename = getPath3(options.base_directory, info_subdir, basename); + if (fileExists(filename)) + return filename; + + return NULL; // cannot find program info file +} + static char *getCorrectedArtworkBasename(char *basename) { return basename; @@ -917,7 +1048,7 @@ char *getCustomImageFilename(char *basename) { free(filename); - Warn("cannot find artwork file '%s' (using fallback)", basename); + WarnUsingFallback(basename); // 6th try: look for fallback artwork in old default artwork directory // (needed to prevent errors when trying to access unused artwork files) @@ -988,7 +1119,7 @@ char *getCustomSoundFilename(char *basename) { free(filename); - Warn("cannot find artwork file '%s' (using fallback)", basename); + WarnUsingFallback(basename); // 6th try: look for fallback artwork in old default artwork directory // (needed to prevent errors when trying to access unused artwork files) @@ -1059,7 +1190,7 @@ char *getCustomMusicFilename(char *basename) { free(filename); - Warn("cannot find artwork file '%s' (using fallback)", basename); + WarnUsingFallback(basename); // 6th try: look for fallback artwork in old default artwork directory // (needed to prevent errors when trying to access unused artwork files) @@ -1155,33 +1286,81 @@ char *getCustomMusicDirectory(void) return NULL; // cannot find specified artwork file anywhere } +void MarkTapeDirectoryUploadsAsComplete(char *level_subdir) +{ + char *filename = getPath2(getTapeDir(level_subdir), UPLOADED_FILENAME); + + touchFile(filename); + + checked_free(filename); +} + +void MarkTapeDirectoryUploadsAsIncomplete(char *level_subdir) +{ + char *filename = getPath2(getTapeDir(level_subdir), UPLOADED_FILENAME); + + unlink(filename); + + checked_free(filename); +} + +boolean CheckTapeDirectoryUploadsComplete(char *level_subdir) +{ + char *filename = getPath2(getTapeDir(level_subdir), UPLOADED_FILENAME); + boolean success = fileExists(filename); + + checked_free(filename); + + return success; +} + +void InitMissingFileHash(void) +{ + if (missing_file_hash == NULL) + freeSetupFileHash(missing_file_hash); + + missing_file_hash = newSetupFileHash(); +} + void InitTapeDirectory(char *level_subdir) { - createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE); - createDirectory(getTapeDir(NULL), "main tape", PERMS_PRIVATE); - createDirectory(getTapeDir(level_subdir), "level tape", PERMS_PRIVATE); + boolean new_tape_dir = !directoryExists(getTapeDir(level_subdir)); + + createDirectory(getUserGameDataDir(), "user data"); + createDirectory(getTapeDir(NULL), "main tape"); + createDirectory(getTapeDir(level_subdir), "level tape"); + + if (new_tape_dir) + MarkTapeDirectoryUploadsAsComplete(level_subdir); } void InitScoreDirectory(char *level_subdir) { - createDirectory(getMainUserGameDataDir(), "main user data", PERMS_PRIVATE); - createDirectory(getScoreDir(NULL), "main score", PERMS_PRIVATE); - createDirectory(getScoreDir(level_subdir), "level score", PERMS_PRIVATE); + createDirectory(getMainUserGameDataDir(), "main user data"); + createDirectory(getScoreDir(NULL), "main score"); + createDirectory(getScoreDir(level_subdir), "level score"); } void InitScoreCacheDirectory(char *level_subdir) { - createDirectory(getMainUserGameDataDir(), "main user data", PERMS_PRIVATE); - createDirectory(getCacheDir(), "cache data", PERMS_PRIVATE); - createDirectory(getScoreCacheDir(NULL), "main score", PERMS_PRIVATE); - createDirectory(getScoreCacheDir(level_subdir), "level score", PERMS_PRIVATE); + createDirectory(getMainUserGameDataDir(), "main user data"); + createDirectory(getCacheDir(), "cache data"); + createDirectory(getScoreCacheDir(NULL), "main score"); + createDirectory(getScoreCacheDir(level_subdir), "level score"); } void InitScoreTapeDirectory(char *level_subdir, int nr) { InitScoreDirectory(level_subdir); - createDirectory(getScoreTapeDir(level_subdir, nr), "score tape", PERMS_PRIVATE); + createDirectory(getScoreTapeDir(level_subdir, nr), "score tape"); +} + +void InitScoreCacheTapeDirectory(char *level_subdir, int nr) +{ + InitScoreCacheDirectory(level_subdir); + + createDirectory(getScoreCacheTapeDir(level_subdir, nr), "score tape"); } static void SaveUserLevelInfo(void); @@ -1190,12 +1369,15 @@ void InitUserLevelDirectory(char *level_subdir) { if (!directoryExists(getUserLevelDir(level_subdir))) { - createDirectory(getMainUserGameDataDir(), "main user data", PERMS_PRIVATE); - createDirectory(getUserLevelDir(NULL), "main user level", PERMS_PRIVATE); - createDirectory(getUserLevelDir(level_subdir), "user level", PERMS_PRIVATE); + createDirectory(getMainUserGameDataDir(), "main user data"); + createDirectory(getUserLevelDir(NULL), "main user level"); if (setup.internal.create_user_levelset) + { + createDirectory(getUserLevelDir(level_subdir), "user level"); + SaveUserLevelInfo(); + } } } @@ -1203,24 +1385,24 @@ void InitNetworkLevelDirectory(char *level_subdir) { if (!directoryExists(getNetworkLevelDir(level_subdir))) { - createDirectory(getMainUserGameDataDir(), "main user data", PERMS_PRIVATE); - createDirectory(getNetworkDir(), "network data", PERMS_PRIVATE); - createDirectory(getNetworkLevelDir(NULL), "main network level", PERMS_PRIVATE); - createDirectory(getNetworkLevelDir(level_subdir), "network level", PERMS_PRIVATE); + createDirectory(getMainUserGameDataDir(), "main user data"); + createDirectory(getNetworkDir(), "network data"); + createDirectory(getNetworkLevelDir(NULL), "main network level"); + createDirectory(getNetworkLevelDir(level_subdir), "network level"); } } void InitLevelSetupDirectory(char *level_subdir) { - createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE); - createDirectory(getLevelSetupDir(NULL), "main level setup", PERMS_PRIVATE); - createDirectory(getLevelSetupDir(level_subdir), "level setup", PERMS_PRIVATE); + createDirectory(getUserGameDataDir(), "user data"); + createDirectory(getLevelSetupDir(NULL), "main level setup"); + createDirectory(getLevelSetupDir(level_subdir), "level setup"); } static void InitCacheDirectory(void) { - createDirectory(getMainUserGameDataDir(), "main user data", PERMS_PRIVATE); - createDirectory(getCacheDir(), "cache data", PERMS_PRIVATE); + createDirectory(getMainUserGameDataDir(), "main user data"); + createDirectory(getCacheDir(), "cache data"); } @@ -1606,7 +1788,7 @@ void sortTreeInfo(TreeInfo **node_first) // some stuff from "files.c" // ============================================================================ -#if defined(PLATFORM_WIN32) +#if defined(PLATFORM_WINDOWS) #ifndef S_IRGRP #define S_IRGRP S_IRUSR #endif @@ -1631,7 +1813,7 @@ void sortTreeInfo(TreeInfo **node_first) #ifndef S_ISGID #define S_ISGID 0 #endif -#endif // PLATFORM_WIN32 +#endif // PLATFORM_WINDOWS // file permissions for newly written files #define MODE_R_ALL (S_IRUSR | S_IRGRP | S_IROTH) @@ -1655,7 +1837,7 @@ char *getHomeDir(void) { static char *dir = NULL; -#if defined(PLATFORM_WIN32) +#if defined(PLATFORM_WINDOWS) if (dir == NULL) { dir = checked_malloc(MAX_PATH + 1); @@ -1664,7 +1846,7 @@ char *getHomeDir(void) strcpy(dir, "."); } #elif defined(PLATFORM_EMSCRIPTEN) - dir = "/persistent"; + dir = PERSISTENT_DIRECTORY; #elif defined(PLATFORM_UNIX) if (dir == NULL) { @@ -1689,7 +1871,7 @@ char *getPersonalDataDir(void) { static char *personal_data_dir = NULL; -#if defined(PLATFORM_MACOSX) +#if defined(PLATFORM_MAC) if (personal_data_dir == NULL) personal_data_dir = getPath2(getHomeDir(), "Documents"); #else @@ -1743,7 +1925,7 @@ static mode_t posix_umask(mode_t mask) static int posix_mkdir(const char *pathname, mode_t mode) { -#if defined(PLATFORM_WIN32) +#if defined(PLATFORM_WINDOWS) return mkdir(pathname); #else return mkdir(pathname, mode); @@ -1759,13 +1941,14 @@ static boolean posix_process_running_setgid(void) #endif } -void createDirectory(char *dir, char *text, int permission_class) +void createDirectory(char *dir, char *text) { if (directoryExists(dir)) return; // leave "other" permissions in umask untouched, but ensure group parts // of USERDATA_DIR_MODE are not masked + int permission_class = PERMS_PRIVATE; mode_t dir_mode = (permission_class == PERMS_PRIVATE ? DIR_PERMS_PRIVATE : DIR_PERMS_PUBLIC); mode_t last_umask = posix_umask(0); @@ -1794,17 +1977,17 @@ void createDirectory(char *dir, char *text, int permission_class) void InitMainUserDataDirectory(void) { - createDirectory(getMainUserGameDataDir(), "main user data", PERMS_PRIVATE); + createDirectory(getMainUserGameDataDir(), "main user data"); } void InitUserDataDirectory(void) { - createDirectory(getMainUserGameDataDir(), "main user data", PERMS_PRIVATE); + createDirectory(getMainUserGameDataDir(), "main user data"); if (user.nr != 0) { - createDirectory(getUserDir(-1), "users", PERMS_PRIVATE); - createDirectory(getUserDir(user.nr), "user data", PERMS_PRIVATE); + createDirectory(getUserDir(-1), "users"); + createDirectory(getUserDir(user.nr), "user data"); } } @@ -2042,7 +2225,7 @@ unsigned int get_hash_from_key(void *key) return hash; } -static int keys_are_equal(void *key1, void *key2) +int hash_keys_are_equal(void *key1, void *key2) { return (strEqual((char *)key1, (char *)key2)); } @@ -2050,7 +2233,7 @@ static int keys_are_equal(void *key1, void *key2) SetupFileHash *newSetupFileHash(void) { SetupFileHash *new_hash = - create_hashtable(16, 0.75, get_hash_from_key, keys_are_equal); + create_hashtable(16, 0.75, get_hash_from_key, hash_keys_are_equal); if (new_hash == NULL) Fail("create_hashtable() failed -- out of memory"); @@ -2544,11 +2727,13 @@ SetupFileHash *loadSetupFileHash(char *filename) #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 LEVELINFO_TOKEN_EMPTY_LEVEL_NAME 27 +#define LEVELINFO_TOKEN_FORCE_LEVEL_NAME 28 +#define LEVELINFO_TOKEN_HANDICAP 29 +#define LEVELINFO_TOKEN_SKIP_LEVELS 30 +#define LEVELINFO_TOKEN_USE_EMC_TILES 31 -#define NUM_LEVELINFO_TOKENS 30 +#define NUM_LEVELINFO_TOKENS 32 static LevelDirTree ldi; @@ -2582,6 +2767,8 @@ static struct TokenInfo levelinfo_tokens[] = { TYPE_STRING, &ldi.level_filename, "filename" }, { TYPE_STRING, &ldi.level_filetype, "filetype" }, { TYPE_STRING, &ldi.special_flags, "special_flags" }, + { TYPE_STRING, &ldi.empty_level_name, "empty_level_name" }, + { TYPE_BOOLEAN, &ldi.force_level_name, "force_level_name" }, { TYPE_BOOLEAN, &ldi.handicap, "handicap" }, { TYPE_BOOLEAN, &ldi.skip_levels, "skip_levels" }, { TYPE_BOOLEAN, &ldi.use_emc_tiles, "use_emc_tiles" } @@ -2679,6 +2866,9 @@ static void setTreeInfoToDefaults(TreeInfo *ti, int type) ti->special_flags = NULL; + ti->empty_level_name = NULL; + ti->force_level_name = FALSE; + ti->levels = 0; ti->first_level = 0; ti->last_level = 0; @@ -2761,6 +2951,9 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent) ti->special_flags = getStringCopy(parent->special_flags); + ti->empty_level_name = getStringCopy(parent->empty_level_name); + ti->force_level_name = parent->force_level_name; + ti->levels = parent->levels; ti->first_level = parent->first_level; ti->last_level = parent->last_level; @@ -2823,6 +3016,9 @@ static TreeInfo *getTreeInfoCopy(TreeInfo *ti) ti_copy->special_flags = getStringCopy(ti->special_flags); + ti_copy->empty_level_name = getStringCopy(ti->empty_level_name); + ti_copy->force_level_name = ti->force_level_name; + ti_copy->levels = ti->levels; ti_copy->first_level = ti->first_level; ti_copy->last_level = ti->last_level; @@ -3047,6 +3243,17 @@ static void setTreeInfoParentNodes(TreeInfo *node, TreeInfo *node_parent) } } +TreeInfo *addTopTreeInfoNode(TreeInfo *node_first) +{ + // add top tree node with back link node in previous tree + node_first = createTopTreeInfoNode(node_first); + + // set all parent links (back links) in complete tree + setTreeInfoParentNodes(node_first, NULL); + + return node_first; +} + // ---------------------------------------------------------------------------- // functions for handling level and custom artwork info cache @@ -4181,11 +4388,8 @@ static void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node) LoadArtworkInfoFromLevelInfoExt(artwork_node, NULL, leveldir_first_all, TRUE); LoadArtworkInfoFromLevelInfoExt(artwork_node, NULL, leveldir_first_all, FALSE); - // add top tree node over all three separate sub-trees - *artwork_node = createTopTreeInfoNode(*artwork_node); - - // set all parent links (back links) in complete artwork tree - setTreeInfoParentNodes(*artwork_node, NULL); + // add top tree node over all sub-trees and set parent links + *artwork_node = addTopTreeInfoNode(*artwork_node); } void LoadLevelArtworkInfo(void) @@ -4442,7 +4646,7 @@ boolean CreateUserLevelSet(char *level_subdir, char *level_name, int i; // create user level sub-directory, if needed - createDirectory(getUserLevelDir(level_subdir), "user level", PERMS_PRIVATE); + createDirectory(getUserLevelDir(level_subdir), "user level"); filename = getPath2(getUserLevelDir(level_subdir), LEVELINFO_FILENAME);