+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
return COMPILE_DATE_STRING;
}
+char *getProgramTitleString()
+{
+ return program.program_title;
+}
+
char *getProgramVersionString()
{
static char program_version_string[32];
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;
#include "main.h"
char *getCompileDateString(void);
-char *getProgramReleaseVersionString(void);
-char *getProgramFullVersionString(void);
+char *getProgramTitleString(void);
char *getProgramVersionString(void);
char *getProgramInitString(void);
char *getWindowTitleString(void);
#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
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[] =
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" },
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;
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;
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++)
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()
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");
void LoadScore(int);
void SaveScore(int);
+void LoadSetupFromFilename(char *);
void LoadSetup();
void SaveSetup();
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);
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);
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 :
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;
return filename;
}
+char *getDefaultSetupFilename()
+{
+ return program.config_filename;
+}
+
char *getEditorSetupFilename()
{
static char *filename = NULL;
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 */
}
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 */
}
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 */
}
/* 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)))
{
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);
/* 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,
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();
/* 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]"
#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"
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 */
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;
struct SetupInputInfo input[MAX_PLAYERS];
struct SetupTouchInfo touch;
struct SetupSystemInfo system;
+ struct SetupInternalInfo internal;
struct OptionInfo options;
};
/* function definitions */
void InitProgramInfo(char *, char *, char *, char *, char *, char *, char *,
- int);
+ char *, int);
void SetWindowTitle();
#include "game.h"
#include "tape.h"
#include "tools.h"
+#include "files.h"
#include "events.h"
#include "config.h"
}
}
+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);
#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.)
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
{
{
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,
},
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()
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)
leveldir_current = leveldir_current->node_parent;
}
}
-#endif
void HandleTitleScreen(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();
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,
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");