From: Holger Schemel Date: Mon, 13 Apr 2015 23:50:33 +0000 (+0200) Subject: added program config file support for run-time special edition support X-Git-Tag: 4.0.0.0-rc1~216 X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=commitdiff_plain;h=4e745044fe35b4b093b1490a6e3da0fe4ee512de added program config file support for run-time special edition support --- diff --git a/ChangeLog b/ChangeLog index 0a7168dc..9c67528f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,52 @@ +2015-04-14 + * added run-time "special edition" support; + this change is especially targeted to the "R'n'D jue" special edition + of R'n'D, which changed some defaults at compile-time in previous + versions, like: + - using a different default artwork set (with fallback artwork for + classic artwork not existing in the special edition), + - using a different default level set, + - using a different program name and user data directory, + - starting with different default setup values and + - using custom artwork even at a very early stage of startup + (like initial fonts and initial loading/busy animation); + these changes can now all be accomplished at run-time by using a new + program-specific configuration file in the same location and with the + same name as the game binary (minus a potential binary file extension + ".exe", plus a configuration file extension ".conf", so a binary file + "rnd_jue.exe" would be complemented by a new file "rnd_jue.conf" in + the same directory); + this config file can contain all options found in "setup.conf" plus + the following new, internal "special edition" default settings: + - program_title (like "R'n'D jue") + - program_author (like "Juergen Bonhagen") + - program_email (like "jue@artsoft.org") + - program_website (like "http://jue.artsoft.org/") + - program_copyright (like "(c) 2015 by jue") + - program_company (like "A game by jue") + - default_graphics_set (like "jue0") + - default_sounds_set (like "jue0") + - default_music_set (like "jue0") + - fallback_graphics_file (like "fallback.png") + - fallback_sounds_file (like "fallback.wav") + - fallback_music_file (like "fallback.wav") + - default_level_series (like "jue_start") + - choose_from_top_leveldir ("true" or "false") + where the "default" artwork set definitions are used to specify new + default artwork that replaces the "classic" artwork sets, while the + "fallback" settings specify artwork files used for all artwork files + that would exist in the classic artwork sets, but are not defined or + cannot be found in the new default artwork set; the program title is + used for things like window title, title screens and user data folder + name, and the entry point for choosing a level set can be changed + from the current level set location to the topmost level tree node + +2015-04-07 + * added sound definitions for pressing and releasing main menu buttons + +2015-03-31 + * fixed slow tape quick-loading due to unneeded tape area update + 2015-03-30 * replaced stop/play buttons in game panel with save/load buttons diff --git a/src/config.c b/src/config.c index da6d1a96..3b75f709 100644 --- a/src/config.c +++ b/src/config.c @@ -20,6 +20,11 @@ char *getCompileDateString() return COMPILE_DATE_STRING; } +char *getProgramTitleString() +{ + return program.program_title; +} + char *getProgramVersionString() { static char program_version_string[32]; @@ -37,11 +42,11 @@ char *getProgramInitString() if (program_init_string == NULL) { - program_init_string = checked_malloc(strlen(PROGRAM_TITLE_STRING) + 1 + + program_init_string = checked_malloc(strlen(getProgramTitleString()) + 1 + strlen(getProgramVersionString()) + 1); sprintf(program_init_string, "%s %s", - PROGRAM_TITLE_STRING, getProgramVersionString()); + getProgramTitleString(), getProgramVersionString()); } return program_init_string; diff --git a/src/config.h b/src/config.h index 48641ab1..f6320360 100644 --- a/src/config.h +++ b/src/config.h @@ -15,8 +15,7 @@ #include "main.h" char *getCompileDateString(void); -char *getProgramReleaseVersionString(void); -char *getProgramFullVersionString(void); +char *getProgramTitleString(void); char *getProgramVersionString(void); char *getProgramInitString(void); char *getWindowTitleString(void); diff --git a/src/files.c b/src/files.c index 4dab8195..62bab202 100644 --- a/src/files.c +++ b/src/files.c @@ -8021,6 +8021,24 @@ void SaveScore(int nr) #define NUM_SYSTEM_SETUP_TOKENS 3 +/* internal setup */ +#define SETUP_TOKEN_INT_PROGRAM_TITLE 0 +#define SETUP_TOKEN_INT_PROGRAM_AUTHOR 1 +#define SETUP_TOKEN_INT_PROGRAM_EMAIL 2 +#define SETUP_TOKEN_INT_PROGRAM_WEBSITE 3 +#define SETUP_TOKEN_INT_PROGRAM_COPYRIGHT 4 +#define SETUP_TOKEN_INT_PROGRAM_COMPANY 5 +#define SETUP_TOKEN_INT_DEFAULT_GRAPHICS_SET 6 +#define SETUP_TOKEN_INT_DEFAULT_SOUNDS_SET 7 +#define SETUP_TOKEN_INT_DEFAULT_MUSIC_SET 8 +#define SETUP_TOKEN_INT_FALLBACK_GRAPHICS_FILE 9 +#define SETUP_TOKEN_INT_FALLBACK_SOUNDS_FILE 10 +#define SETUP_TOKEN_INT_FALLBACK_MUSIC_FILE 11 +#define SETUP_TOKEN_INT_DEFAULT_LEVEL_SERIES 12 +#define SETUP_TOKEN_INT_CHOOSE_FROM_TOP_LEVELDIR 13 + +#define NUM_INTERNAL_SETUP_TOKENS 14 + /* options setup */ #define SETUP_TOKEN_OPTIONS_VERBOSE 0 @@ -8033,6 +8051,7 @@ static struct SetupEditorCascadeInfo seci; static struct SetupShortcutInfo ssi; static struct SetupInputInfo sii; static struct SetupSystemInfo syi; +static struct SetupInternalInfo sxi; static struct OptionInfo soi; static struct TokenInfo global_setup_tokens[] = @@ -8168,11 +8187,29 @@ static struct TokenInfo player_setup_tokens[] = static struct TokenInfo system_setup_tokens[] = { - { TYPE_STRING, &syi.sdl_videodriver, "system.sdl_videodriver" }, - { TYPE_STRING, &syi.sdl_audiodriver, "system.sdl_audiodriver" }, + { TYPE_STRING, &syi.sdl_videodriver, "system.sdl_videodriver" }, + { TYPE_STRING, &syi.sdl_audiodriver, "system.sdl_audiodriver" }, { TYPE_INTEGER, &syi.audio_fragment_size,"system.audio_fragment_size" }, }; +static struct TokenInfo internal_setup_tokens[] = +{ + { TYPE_STRING, &sxi.program_title, "program_title" }, + { TYPE_STRING, &sxi.program_author, "program_author" }, + { TYPE_STRING, &sxi.program_email, "program_email" }, + { TYPE_STRING, &sxi.program_website, "program_website" }, + { TYPE_STRING, &sxi.program_copyright, "program_copyright" }, + { TYPE_STRING, &sxi.program_company, "program_company" }, + { TYPE_STRING, &sxi.default_graphics_set, "default_graphics_set" }, + { TYPE_STRING, &sxi.default_sounds_set, "default_sounds_set" }, + { TYPE_STRING, &sxi.default_music_set, "default_music_set" }, + { TYPE_STRING, &sxi.fallback_graphics_file, "fallback_graphics_file"}, + { TYPE_STRING, &sxi.fallback_sounds_file, "fallback_sounds_file" }, + { TYPE_STRING, &sxi.fallback_music_file, "fallback_music_file" }, + { TYPE_STRING, &sxi.default_level_series, "default_level_series" }, + { TYPE_STRING, &sxi.choose_from_top_leveldir, "choose_from_top_leveldir" }, +}; + static struct TokenInfo options_setup_tokens[] = { { TYPE_BOOLEAN, &soi.verbose, "options.verbose" }, @@ -8229,9 +8266,10 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->sp_show_border_elements = FALSE; si->small_game_graphics = FALSE; - si->graphics_set = getStringCopy(GFX_DEFAULT_SUBDIR); - si->sounds_set = getStringCopy(SND_DEFAULT_SUBDIR); - si->music_set = getStringCopy(MUS_DEFAULT_SUBDIR); + si->graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR); + si->sounds_set = getStringCopy(SND_CLASSIC_SUBDIR); + si->music_set = getStringCopy(MUS_CLASSIC_SUBDIR); + si->override_level_graphics = FALSE; si->override_level_sounds = FALSE; si->override_level_music = FALSE; @@ -8312,16 +8350,25 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->system.sdl_audiodriver = getStringCopy(ARG_DEFAULT); si->system.audio_fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE; - si->options.verbose = FALSE; + si->internal.program_title = getStringCopy(PROGRAM_TITLE_STRING); + si->internal.program_author = getStringCopy(PROGRAM_AUTHOR_STRING); + si->internal.program_email = getStringCopy(PROGRAM_EMAIL_STRING); + si->internal.program_website = getStringCopy(PROGRAM_WEBSITE_STRING); + si->internal.program_copyright = getStringCopy(PROGRAM_COPYRIGHT_STRING); + si->internal.program_company = getStringCopy(PROGRAM_COMPANY_STRING); -#if defined(CREATE_SPECIAL_EDITION_RND_JUE) - si->toons = FALSE; - si->handicap = FALSE; - si->fullscreen = TRUE; - si->override_level_graphics = AUTO; - si->override_level_sounds = AUTO; - si->override_level_music = AUTO; -#endif + si->internal.default_graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR); + si->internal.default_sounds_set = getStringCopy(SND_CLASSIC_SUBDIR); + si->internal.default_music_set = getStringCopy(MUS_CLASSIC_SUBDIR); + + si->internal.fallback_graphics_file = getStringCopy(UNDEFINED_FILENAME); + si->internal.fallback_sounds_file = getStringCopy(UNDEFINED_FILENAME); + si->internal.fallback_music_file = getStringCopy(UNDEFINED_FILENAME); + + si->internal.default_level_series = getStringCopy(UNDEFINED_LEVELSET); + si->internal.choose_from_top_leveldir = FALSE; + + si->options.verbose = FALSE; #if defined(PLATFORM_ANDROID) si->fullscreen = TRUE; @@ -8402,6 +8449,13 @@ static void decodeSetupFileHash(SetupFileHash *setup_file_hash) getHashEntry(setup_file_hash, system_setup_tokens[i].text)); setup.system = syi; + /* internal setup */ + sxi = setup.internal; + for (i = 0; i < NUM_INTERNAL_SETUP_TOKENS; i++) + setSetupInfo(internal_setup_tokens, i, + getHashEntry(setup_file_hash, internal_setup_tokens[i].text)); + setup.internal = sxi; + /* options setup */ soi = setup.options; for (i = 0; i < NUM_OPTIONS_SETUP_TOKENS; i++) @@ -8426,42 +8480,62 @@ static void decodeSetupFileHash_EditorCascade(SetupFileHash *setup_file_hash) setup.editor_cascade = seci; } -void LoadSetup() +void LoadSetupFromFilename(char *filename) { - char *filename = getSetupFilename(); - SetupFileHash *setup_file_hash = NULL; - - /* always start with reliable default values */ - setSetupInfoToDefaults(&setup); - - setup_file_hash = loadSetupFileHash(filename); + SetupFileHash *setup_file_hash = loadSetupFileHash(filename); if (setup_file_hash) { - char *player_name_new; - decodeSetupFileHash(setup_file_hash); freeSetupFileHash(setup_file_hash); + } + else + { + Error(ERR_WARN, "using default setup values"); + } +} - /* needed to work around problems with fixed length strings */ - player_name_new = get_corrected_login_name(setup.player_name); - free(setup.player_name); - setup.player_name = player_name_new; +static void LoadSetup_SpecialPostProcessing() +{ + char *player_name_new; - /* "scroll_delay: on(3) / off(0)" was replaced by scroll delay value */ - if (setup.scroll_delay == FALSE) - { - setup.scroll_delay_value = MIN_SCROLL_DELAY; - setup.scroll_delay = TRUE; /* now always "on" */ - } + /* needed to work around problems with fixed length strings */ + player_name_new = get_corrected_login_name(setup.player_name); + free(setup.player_name); + setup.player_name = player_name_new; - /* make sure that scroll delay value stays inside valid range */ - setup.scroll_delay_value = - MIN(MAX(MIN_SCROLL_DELAY, setup.scroll_delay_value), MAX_SCROLL_DELAY); + /* "scroll_delay: on(3) / off(0)" was replaced by scroll delay value */ + if (setup.scroll_delay == FALSE) + { + setup.scroll_delay_value = MIN_SCROLL_DELAY; + setup.scroll_delay = TRUE; /* now always "on" */ } - else - Error(ERR_WARN, "using default setup values"); + + /* make sure that scroll delay value stays inside valid range */ + setup.scroll_delay_value = + MIN(MAX(MIN_SCROLL_DELAY, setup.scroll_delay_value), MAX_SCROLL_DELAY); +} + +void LoadSetup() +{ + char *filename; + + /* always start with reliable default values */ + setSetupInfoToDefaults(&setup); + + /* try to load setup values from default setup file */ + filename = getDefaultSetupFilename(); + + if (fileExists(filename)) + LoadSetupFromFilename(filename); + + /* try to load setup values from user setup file */ + filename = getSetupFilename(); + + LoadSetupFromFilename(filename); + + LoadSetup_SpecialPostProcessing(); } void LoadSetup_EditorCascade() @@ -8545,6 +8619,9 @@ void SaveSetup() for (i = 0; i < NUM_SYSTEM_SETUP_TOKENS; i++) fprintf(file, "%s\n", getSetupLine(system_setup_tokens, "", i)); + /* internal setup */ + /* (internal setup values not saved to user setup file) */ + /* options setup */ soi = setup.options; fprintf(file, "\n"); diff --git a/src/files.h b/src/files.h index 3041cc83..2a3900eb 100644 --- a/src/files.h +++ b/src/files.h @@ -54,6 +54,7 @@ boolean SaveTapeChecked(int); void LoadScore(int); void SaveScore(int); +void LoadSetupFromFilename(char *); void LoadSetup(); void SaveSetup(); diff --git a/src/init.c b/src/init.c index b0ed61da..e54a016b 100644 --- a/src/init.c +++ b/src/init.c @@ -5087,52 +5087,79 @@ void InitGfx() font_height = getFontHeight(FC_RED); DrawInitText(getProgramInitString(), 20, FC_YELLOW); - DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED); - DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED); + DrawInitText(setup.internal.program_copyright, 50, FC_RED); + DrawInitText(setup.internal.program_website, WIN_YSIZE - 20 - font_height, + FC_RED); DrawInitText("Loading graphics", 120, FC_GREEN); - /* initialize busy animation with default values */ + /* initialize settings for busy animation with default values */ int parameter[NUM_GFX_ARGS]; for (i = 0; i < NUM_GFX_ARGS; i++) parameter[i] = get_graphic_parameter_value(image_config_suffix[i].value, image_config_suffix[i].token, image_config_suffix[i].type); - /* determine settings for busy animation (when displaying startup messages) */ - for (i = 0; image_config[i].token != NULL; i++) + char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY; + int len_anim_token = strlen(anim_token); + + /* read settings for busy animation from default custom artwork config */ + char *gfx_config_filename = getPath3(options.graphics_directory, + GFX_DEFAULT_SUBDIR, + GRAPHICSINFO_FILENAME); + + if (fileExists(gfx_config_filename)) { - char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY; - int len_anim_token = strlen(anim_token); + SetupFileHash *setup_file_hash = loadSetupFileHash(gfx_config_filename); - if (strEqual(image_config[i].token, anim_token)) - filename_anim_initial = image_config[i].value; - else if (strlen(image_config[i].token) > len_anim_token && - strncmp(image_config[i].token, anim_token, len_anim_token) == 0) + if (setup_file_hash) { - for (j = 0; image_config_suffix[j].token != NULL; j++) + char *filename = getHashEntry(setup_file_hash, anim_token); + + if (filename) { - if (strEqual(&image_config[i].token[len_anim_token], - image_config_suffix[j].token)) - parameter[j] = - get_graphic_parameter_value(image_config[i].value, - image_config_suffix[j].token, - image_config_suffix[j].type); + filename_anim_initial = getStringCopy(filename); + + for (j = 0; image_config_suffix[j].token != NULL; j++) + { + int type = image_config_suffix[j].type; + char *suffix = image_config_suffix[j].token; + char *token = getStringCat2(anim_token, suffix); + char *value = getHashEntry(setup_file_hash, token); + + checked_free(token); + + if (value) + parameter[j] = get_graphic_parameter_value(value, suffix, type); + } } + + freeSetupFileHash(setup_file_hash); } } -#if defined(CREATE_SPECIAL_EDITION_RND_JUE) - filename_anim_initial = "loading.pcx"; - - parameter[GFX_ARG_X] = 0; - parameter[GFX_ARG_Y] = 0; - parameter[GFX_ARG_WIDTH] = 128; - parameter[GFX_ARG_HEIGHT] = 40; - parameter[GFX_ARG_FRAMES] = 32; - parameter[GFX_ARG_DELAY] = 4; - parameter[GFX_ARG_FRAMES_PER_LINE] = ARG_UNDEFINED_VALUE; -#endif + if (filename_anim_initial == NULL) + { + /* read settings for busy animation from static default artwork config */ + for (i = 0; image_config[i].token != NULL; i++) + { + if (strEqual(image_config[i].token, anim_token)) + filename_anim_initial = getStringCopy(image_config[i].value); + else if (strlen(image_config[i].token) > len_anim_token && + strncmp(image_config[i].token, anim_token, len_anim_token) == 0) + { + for (j = 0; image_config_suffix[j].token != NULL; j++) + { + if (strEqual(&image_config[i].token[len_anim_token], + image_config_suffix[j].token)) + parameter[j] = + get_graphic_parameter_value(image_config[i].value, + image_config_suffix[j].token, + image_config_suffix[j].type); + } + } + } + } if (filename_anim_initial == NULL) /* should not happen */ Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY); @@ -5143,6 +5170,8 @@ void InitGfx() anim_initial.bitmaps[IMG_BITMAP_STANDARD] = LoadCustomImage(filename_anim_initial); + checked_free(filename_anim_initial); + graphic_info = &anim_initial; /* graphic == 0 => anim_initial */ set_graphic_parameters_ext(0, parameter, anim_initial.bitmaps); diff --git a/src/libgame/misc.c b/src/libgame/misc.c index 052509f6..660f4df6 100644 --- a/src/libgame/misc.c +++ b/src/libgame/misc.c @@ -1073,6 +1073,9 @@ void Error(int mode, char *format, ...) static boolean last_line_was_separator = FALSE; char *process_name = ""; + if (program.error_file == NULL) + return; + #if defined(PLATFORM_ANDROID) android_log_prio = (mode & ERR_DEBUG ? ANDROID_LOG_DEBUG : mode & ERR_INFO ? ANDROID_LOG_INFO : diff --git a/src/libgame/setup.c b/src/libgame/setup.c index 56215296..5fc8ccc7 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -393,6 +393,17 @@ inline static char *getLevelArtworkDir(int type) return LEVELDIR_ARTWORK_PATH(leveldir_current, type); } +char *getProgramConfigFilename(char *command_filename_ptr) +{ + char *command_filename = getStringCopy(command_filename_ptr); + + // strip trailing executable suffix from command filename + if (strSuffix(command_filename, ".exe")) + command_filename[strlen(command_filename) - 4] = '\0'; + + return getStringCat2(command_filename, ".conf"); +} + char *getTapeFilename(int nr) { static char *filename = NULL; @@ -456,6 +467,11 @@ char *getSetupFilename() return filename; } +char *getDefaultSetupFilename() +{ + return program.config_filename; +} + char *getEditorSetupFilename() { static char *filename = NULL; @@ -659,18 +675,20 @@ char *getCustomImageFilename(char *basename) if (fileExists(filename)) return filename; -#if defined(CREATE_SPECIAL_EDITION) - free(filename); + if (!strEqual(GFX_FALLBACK_FILENAME, UNDEFINED_FILENAME)) + { + free(filename); - if (options.debug) - Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", basename); + if (options.debug) + Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", + basename); - /* 6th try: look for fallback artwork in old default artwork directory */ - /* (needed to prevent errors when trying to access unused artwork files) */ - filename = getImg2(options.graphics_directory, GFX_FALLBACK_FILENAME); - if (fileExists(filename)) - return filename; -#endif + /* 6th try: look for fallback artwork in old default artwork directory */ + /* (needed to prevent errors when trying to access unused artwork files) */ + filename = getImg2(options.graphics_directory, GFX_FALLBACK_FILENAME); + if (fileExists(filename)) + return filename; + } return NULL; /* cannot find specified artwork file anywhere */ } @@ -730,18 +748,20 @@ char *getCustomSoundFilename(char *basename) if (fileExists(filename)) return filename; -#if defined(CREATE_SPECIAL_EDITION) - free(filename); + if (!strEqual(SND_FALLBACK_FILENAME, UNDEFINED_FILENAME)) + { + free(filename); - if (options.debug) - Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", basename); + if (options.debug) + Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", + basename); - /* 6th try: look for fallback artwork in old default artwork directory */ - /* (needed to prevent errors when trying to access unused artwork files) */ - filename = getPath2(options.sounds_directory, SND_FALLBACK_FILENAME); - if (fileExists(filename)) - return filename; -#endif + /* 6th try: look for fallback artwork in old default artwork directory */ + /* (needed to prevent errors when trying to access unused artwork files) */ + filename = getPath2(options.sounds_directory, SND_FALLBACK_FILENAME); + if (fileExists(filename)) + return filename; + } return NULL; /* cannot find specified artwork file anywhere */ } @@ -801,18 +821,20 @@ char *getCustomMusicFilename(char *basename) if (fileExists(filename)) return filename; -#if defined(CREATE_SPECIAL_EDITION) - free(filename); + if (!strEqual(MUS_FALLBACK_FILENAME, UNDEFINED_FILENAME)) + { + free(filename); - if (options.debug) - Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", basename); + if (options.debug) + Error(ERR_WARN, "cannot find artwork file '%s' (using fallback)", + basename); - /* 6th try: look for fallback artwork in old default artwork directory */ - /* (needed to prevent errors when trying to access unused artwork files) */ - filename = getPath2(options.music_directory, MUS_FALLBACK_FILENAME); - if (fileExists(filename)) - return filename; -#endif + /* 6th try: look for fallback artwork in old default artwork directory */ + /* (needed to prevent errors when trying to access unused artwork files) */ + filename = getPath2(options.music_directory, MUS_FALLBACK_FILENAME); + if (fileExists(filename)) + return filename; + } return NULL; /* cannot find specified artwork file anywhere */ } @@ -3626,12 +3648,13 @@ void LoadLevelSetup_LastSeries() /* always start with reliable default values */ leveldir_current = getFirstValidTreeInfoEntry(leveldir_first); -#if defined(CREATE_SPECIAL_EDITION_RND_JUE) - leveldir_current = getTreeInfoFromIdentifier(leveldir_first, - "jue_start"); - if (leveldir_current == NULL) - leveldir_current = getFirstValidTreeInfoEntry(leveldir_first); -#endif + if (!strEqual(DEFAULT_LEVELSET, UNDEFINED_LEVELSET)) + { + leveldir_current = getTreeInfoFromIdentifier(leveldir_first, + DEFAULT_LEVELSET); + if (leveldir_current == NULL) + leveldir_current = getFirstValidTreeInfoEntry(leveldir_first); + } if ((level_setup_hash = loadSetupFileHash(filename))) { diff --git a/src/libgame/setup.h b/src/libgame/setup.h index c2f0692e..1f3b7b81 100644 --- a/src/libgame/setup.h +++ b/src/libgame/setup.h @@ -222,10 +222,12 @@ typedef struct hashtable SetupFileHash; char *setLevelArtworkDir(TreeInfo *); +char *getProgramConfigFilename(char *); char *getTapeFilename(int); char *getSolutionTapeFilename(int); char *getScoreFilename(int); char *getSetupFilename(void); +char *getDefaultSetupFilename(void); char *getEditorSetupFilename(void); char *getHelpAnimFilename(void); char *getHelpTextFilename(void); diff --git a/src/libgame/system.c b/src/libgame/system.c index c04c77e5..9a0bed5a 100644 --- a/src/libgame/system.c +++ b/src/libgame/system.c @@ -64,7 +64,7 @@ int FrameCounter = 0; /* init/close functions */ /* ========================================================================= */ -void InitProgramInfo(char *argv0, +void InitProgramInfo(char *argv0, char *config_filename, char *userdata_subdir, char *userdata_subdir_unix, char *program_title, char *icon_title, char *sdl_icon_filename, char *cookie_prefix, @@ -73,6 +73,8 @@ void InitProgramInfo(char *argv0, program.command_basepath = getBasePath(argv0); program.command_basename = getBaseName(argv0); + program.config_filename = config_filename; + program.userdata_subdir = userdata_subdir; program.userdata_subdir_unix = userdata_subdir_unix; program.userdata_path = getUserGameDataDir(); diff --git a/src/libgame/system.h b/src/libgame/system.h index eff54525..d0a22f24 100644 --- a/src/libgame/system.h +++ b/src/libgame/system.h @@ -372,6 +372,9 @@ /* default value for undefined filename */ #define UNDEFINED_FILENAME "[NONE]" +/* default value for undefined levelset */ +#define UNDEFINED_LEVELSET "[NONE]" + /* default value for undefined parameter */ #define ARG_DEFAULT "[DEFAULT]" @@ -408,21 +411,15 @@ #define SND_CLASSIC_SUBDIR "snd_classic" #define MUS_CLASSIC_SUBDIR "mus_classic" -#if defined(CREATE_SPECIAL_EDITION_RND_JUE) -#define GFX_DEFAULT_SUBDIR "jue0" -#define SND_DEFAULT_SUBDIR "jue0" -#define MUS_DEFAULT_SUBDIR "jue0" -#else -#define GFX_DEFAULT_SUBDIR GFX_CLASSIC_SUBDIR -#define SND_DEFAULT_SUBDIR SND_CLASSIC_SUBDIR -#define MUS_DEFAULT_SUBDIR MUS_CLASSIC_SUBDIR -#endif +#define GFX_DEFAULT_SUBDIR (setup.internal.default_graphics_set) +#define SND_DEFAULT_SUBDIR (setup.internal.default_sounds_set) +#define MUS_DEFAULT_SUBDIR (setup.internal.default_music_set) -#if defined(CREATE_SPECIAL_EDITION) -#define GFX_FALLBACK_FILENAME "fallback.pcx" -#define SND_FALLBACK_FILENAME "fallback.wav" -#define MUS_FALLBACK_FILENAME "fallback.wav" -#endif +#define GFX_FALLBACK_FILENAME (setup.internal.fallback_graphics_file) +#define SND_FALLBACK_FILENAME (setup.internal.fallback_sounds_file) +#define MUS_FALLBACK_FILENAME (setup.internal.fallback_music_file) + +#define DEFAULT_LEVELSET (setup.internal.default_level_series) /* file names and filename extensions */ #define LEVELSETUP_DIRECTORY "levelsetup" @@ -664,6 +661,8 @@ struct ProgramInfo char *command_basepath; /* path to the program binary */ char *command_basename; /* base filename of the program binary */ + char *config_filename; /* optional global program config filename */ + char *maindata_path; /* main game data (installation) directory */ char *userdata_subdir; /* personal user game data directory */ @@ -937,6 +936,28 @@ struct SetupSystemInfo int audio_fragment_size; }; +struct SetupInternalInfo +{ + char *program_title; + char *program_author; + char *program_email; + char *program_website; + char *program_copyright; + char *program_company; + + char *default_graphics_set; + char *default_sounds_set; + char *default_music_set; + + char *fallback_graphics_file; + char *fallback_sounds_file; + char *fallback_music_file; + + char *default_level_series; + + boolean choose_from_top_leveldir; +}; + struct SetupInfo { char *player_name; @@ -988,6 +1009,7 @@ struct SetupInfo struct SetupInputInfo input[MAX_PLAYERS]; struct SetupTouchInfo touch; struct SetupSystemInfo system; + struct SetupInternalInfo internal; struct OptionInfo options; }; @@ -1275,7 +1297,7 @@ extern int FrameCounter; /* function definitions */ void InitProgramInfo(char *, char *, char *, char *, char *, char *, char *, - int); + char *, int); void SetWindowTitle(); diff --git a/src/main.c b/src/main.c index 17a1b3cb..1e912477 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,7 @@ #include "game.h" #include "tape.h" #include "tools.h" +#include "files.h" #include "events.h" #include "config.h" @@ -5624,11 +5625,51 @@ static void print_version() } } +static void InitProgramConfig(char *command_filename) +{ + char *command_basename = getBaseName(command_filename); + char *config_filename = getProgramConfigFilename(command_filename); + char *program_title = PROGRAM_TITLE_STRING; + char *userdata_subdir; + char *userdata_subdir_unix; + + // read default program config, if existing + if (fileExists(config_filename)) + LoadSetupFromFilename(config_filename); + + // set program title from potentially redefined program title + if (setup.internal.program_title != NULL && + strlen(setup.internal.program_title) > 0) + program_title = getStringCopy(setup.internal.program_title); + + // strip trailing executable suffix from command basename + if (strSuffix(command_basename, ".exe")) + command_basename[strlen(command_basename) - 4] = '\0'; + + userdata_subdir_unix = getStringCat2(".", command_basename); + +#if defined(PLATFORM_WIN32) || defined(PLATFORM_MACOSX) + userdata_subdir = program_title; +#elif defined(PLATFORM_UNIX) + userdata_subdir = userdata_subdir_unix; +#else + userdata_subdir = USERDATA_DIRECTORY_OTHER; +#endif + + InitProgramInfo(command_filename, + config_filename, + userdata_subdir, + userdata_subdir_unix, + program_title, + program_title, + SDL_ICON_FILENAME, + COOKIE_PREFIX, + GAME_VERSION_ACTUAL); +} + int main(int argc, char *argv[]) { - InitProgramInfo(argv[0], USERDATA_DIRECTORY, USERDATA_DIRECTORY_UNIX, - PROGRAM_TITLE_STRING, ICON_TITLE_STRING, SDL_ICON_FILENAME, - COOKIE_PREFIX, GAME_VERSION_ACTUAL); + InitProgramConfig(argv[0]); InitWindowTitleFunction(getWindowTitleString); InitExitMessageFunction(DisplayExitMessage); diff --git a/src/main.h b/src/main.h index aeceace3..5b919cd3 100644 --- a/src/main.h +++ b/src/main.h @@ -1985,37 +1985,15 @@ #define PROGRAM_TITLE_STRING "Rocks'n'Diamonds" #define PROGRAM_AUTHOR_STRING "Holger Schemel" -#define PROGRAM_COPYRIGHT_STRING "Copyright \xa9""1995-2015 by Holger Schemel" #define PROGRAM_EMAIL_STRING "info@artsoft.org" #define PROGRAM_WEBSITE_STRING "http://www.artsoft.org/" -#define PROGRAM_GAME_BY_STRING "A Game by Artsoft Entertainment" -#define PROGRAM_UNIX_DATADIR_STRING ".rocksndiamonds" - -#if defined(CREATE_SPECIAL_EDITION_RND_JUE) -#undef PROGRAM_TITLE_STRING -#define PROGRAM_TITLE_STRING "R'n'D jue" -#undef PROGRAM_UNIX_DATADIR_STRING -#define PROGRAM_UNIX_DATADIR_STRING ".rnd_jue" -#endif +#define PROGRAM_COPYRIGHT_STRING "Copyright \xa9""1995-2015 by Holger Schemel" +#define PROGRAM_COMPANY_STRING "A Game by Artsoft Entertainment" -#define ICON_TITLE_STRING PROGRAM_TITLE_STRING #define COOKIE_PREFIX "ROCKSNDIAMONDS" -#define USERDATA_DIRECTORY_WIN32 PROGRAM_TITLE_STRING -#define USERDATA_DIRECTORY_MACOSX PROGRAM_TITLE_STRING -#define USERDATA_DIRECTORY_UNIX PROGRAM_UNIX_DATADIR_STRING #define USERDATA_DIRECTORY_OTHER "userdata" -#if defined(PLATFORM_WIN32) -#define USERDATA_DIRECTORY USERDATA_DIRECTORY_WIN32 -#elif defined(PLATFORM_MACOSX) -#define USERDATA_DIRECTORY USERDATA_DIRECTORY_MACOSX -#elif defined(PLATFORM_UNIX) -#define USERDATA_DIRECTORY USERDATA_DIRECTORY_UNIX -#else -#define USERDATA_DIRECTORY USERDATA_DIRECTORY_OTHER -#endif - #define SDL_ICON_FILENAME "RocksIcon32x32.png" /* file version numbers for resource files (levels, tapes, score, setup, etc.) diff --git a/src/screens.c b/src/screens.c index 212e2b4c..6e661ea5 100644 --- a/src/screens.c +++ b/src/screens.c @@ -504,9 +504,6 @@ static char *main_text_level_year = NULL; static char *main_text_level_imported_from = NULL; static char *main_text_level_imported_by = NULL; static char *main_text_level_tested_by = NULL; -static char *main_text_title_1 = PROGRAM_TITLE_STRING; -static char *main_text_title_2 = PROGRAM_COPYRIGHT_STRING; -static char *main_text_title_3 = PROGRAM_GAME_BY_STRING; struct MainControlInfo { @@ -656,19 +653,19 @@ static struct MainControlInfo main_controls[] = { MAIN_CONTROL_TITLE_1, NULL, -1, - &menu.main.text.title_1, &main_text_title_1, + &menu.main.text.title_1, &setup.internal.program_title, NULL, NULL, }, { MAIN_CONTROL_TITLE_2, NULL, -1, - &menu.main.text.title_2, &main_text_title_2, + &menu.main.text.title_2, &setup.internal.program_copyright, NULL, NULL, }, { MAIN_CONTROL_TITLE_3, NULL, -1, - &menu.main.text.title_3, &main_text_title_3, + &menu.main.text.title_3, &setup.internal.program_company, NULL, NULL, }, @@ -1212,8 +1209,9 @@ static void drawChooseTreeCursor(int ypos, boolean active) void DrawHeadline() { - DrawTextSCentered(MENU_TITLE1_YPOS, FONT_TITLE_1, PROGRAM_TITLE_STRING); - DrawTextSCentered(MENU_TITLE2_YPOS, FONT_TITLE_2, PROGRAM_COPYRIGHT_STRING); + DrawTextSCentered(MENU_TITLE1_YPOS, FONT_TITLE_1, getProgramTitleString()); + DrawTextSCentered(MENU_TITLE2_YPOS, FONT_TITLE_2, + setup.internal.program_copyright); } int effectiveGameStatus() @@ -1473,11 +1471,11 @@ void DrawMainMenu() DrawMainMenuExt(REDRAW_ALL, FALSE); } -#if defined(CREATE_SPECIAL_EDITION_RND_JUE) static void gotoTopLevelDir() { - /* move upwards to top level directory */ - while (leveldir_current->node_parent) + /* move upwards until inside (but not above) top level directory */ + while (leveldir_current->node_parent && + !strEqual(leveldir_current->node_parent->subdir, STRING_TOP_DIRECTORY)) { /* write a "path" into level tree for easy navigation to last level */ if (leveldir_current->node_parent->node_group->cl_first == -1) @@ -1502,7 +1500,6 @@ static void gotoTopLevelDir() leveldir_current = leveldir_current->node_parent; } } -#endif void HandleTitleScreen(int mx, int my, int dx, int dy, int button) { @@ -1835,9 +1832,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) SaveLevelSetup_LastSeries(); SaveLevelSetup_SeriesInfo(); -#if defined(CREATE_SPECIAL_EDITION_RND_JUE) - gotoTopLevelDir(); -#endif + if (setup.internal.choose_from_top_leveldir) + gotoTopLevelDir(); ChangeViewportPropertiesIfNeeded(); @@ -2855,11 +2851,11 @@ void DrawInfoScreen_Program() DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_2, "If you like it, send e-mail to:"); DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_3, - PROGRAM_EMAIL_STRING); + setup.internal.program_email); DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, "More information and levels:"); DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3, - PROGRAM_WEBSITE_STRING); + setup.internal.program_website); DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_2, "If you have created new levels,"); DrawTextSCentered(ystart2 + 8 * ystep, FONT_TEXT_2, @@ -2931,7 +2927,7 @@ void DrawInfoScreen_Version() DrawTextSCentered(ystart1, FONT_TEXT_1, "Version Information:"); DrawTextF(xstart1, ystart2, font_header, "Name"); - DrawTextF(xstart2, ystart2, font_text, PROGRAM_TITLE_STRING); + DrawTextF(xstart2, ystart2, font_text, getProgramTitleString()); ystart2 += ystep; DrawTextF(xstart1, ystart2, font_header, "Version");