#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
if (size > 20)
size = 20;
- if (size)
+ if (size > 0)
{
sprintf(s, " %09d", number);
return &s[strlen(s) - size];
/* maximal allowed length of a command line option */
#define MAX_OPTION_LEN 256
+#if 1
+
+#ifdef TARGET_SDL
+static unsigned long getCurrentMS()
+{
+ return SDL_GetTicks();
+}
+
+#else /* !TARGET_SDL */
+
+#if defined(PLATFORM_UNIX)
+static unsigned long getCurrentMS()
+{
+ struct timeval current_time;
+
+ gettimeofday(¤t_time, NULL);
+
+ return current_time.tv_sec * 1000 + current_time.tv_usec / 1000;
+}
+#endif /* PLATFORM_UNIX */
+#endif /* !TARGET_SDL */
+
+static unsigned long mainCounter(int mode)
+{
+ static unsigned long base_ms = 0;
+ unsigned long current_ms;
+
+ /* get current system milliseconds */
+ current_ms = getCurrentMS();
+
+ /* reset base timestamp in case of counter reset or wrap-around */
+ if (mode == INIT_COUNTER || current_ms < base_ms)
+ base_ms = current_ms;
+
+ /* return milliseconds since last counter reset */
+ return current_ms - base_ms;
+}
+
+#else
+
#ifdef TARGET_SDL
static unsigned long mainCounter(int mode)
{
#endif /* PLATFORM_UNIX */
#endif /* !TARGET_SDL */
+#endif
+
void InitCounter() /* set counter back to zero */
{
#if !defined(PLATFORM_MSDOS)
{
if (seed == NEW_RANDOMIZE)
{
-#if defined(TARGET_SDL)
- seed = (long)SDL_GetTicks();
-#else
+ /* default random seed */
+ seed = (long)time(NULL); // seconds since the epoch
+
+#if !defined(PLATFORM_WIN32)
+ /* add some more randomness */
struct timeval current_time;
gettimeofday(¤t_time, NULL);
- seed = (long)current_time.tv_usec;
+
+ seed += (long)current_time.tv_usec; // microseconds since the epoch
+#endif
+
+#if defined(TARGET_SDL)
+ /* add some more randomness */
+ seed += (long)SDL_GetTicks(); // milliseconds since SDL init
+#endif
+
+#if 1
+ /* add some more randomness */
+ seed += GetSimpleRandom(1000000);
#endif
}
return real_name;
}
+time_t getFileTimestampEpochSeconds(char *filename)
+{
+ struct stat file_status;
+
+ if (stat(filename, &file_status) != 0) /* cannot stat file */
+ return 0;
+
+ return file_status.st_mtime;
+}
+
/* ------------------------------------------------------------------------- */
/* path manipulation functions */
return s_copy;
}
+char *getStringCopyN(char *s, int n)
+{
+ char *s_copy;
+ int s_len = MAX(0, n);
+
+ if (s == NULL)
+ return NULL;
+
+ s_copy = checked_malloc(s_len + 1);
+ strncpy(s_copy, s, s_len);
+ s_copy[s_len] = '\0';
+
+ return s_copy;
+}
+
char *getStringToLower(char *s)
{
char *s_copy = checked_malloc(strlen(s) + 1);
strcmp(s1, s2) == 0);
}
+boolean strEqualN(char *s1, char *s2, int n)
+{
+ return (s1 == NULL && s2 == NULL ? TRUE :
+ s1 == NULL && s2 != NULL ? FALSE :
+ s1 != NULL && s2 == NULL ? FALSE :
+ strncmp(s1, s2, n) == 0);
+}
+
+boolean strPrefix(char *s, char *prefix)
+{
+ return (s == NULL && prefix == NULL ? TRUE :
+ s == NULL && prefix != NULL ? FALSE :
+ s != NULL && prefix == NULL ? FALSE :
+ strncmp(s, prefix, strlen(prefix)) == 0);
+}
+
+boolean strSuffix(char *s, char *suffix)
+{
+ return (s == NULL && suffix == NULL ? TRUE :
+ s == NULL && suffix != NULL ? FALSE :
+ s != NULL && suffix == NULL ? FALSE :
+ strlen(s) < strlen(suffix) ? FALSE :
+ strncmp(&s[strlen(s) - strlen(suffix)], suffix, strlen(suffix)) == 0);
+}
+
+boolean strPrefixLower(char *s, char *prefix)
+{
+ char *s_lower = getStringToLower(s);
+ boolean match = strPrefix(s_lower, prefix);
+
+ free(s_lower);
+
+ return match;
+}
+
+boolean strSuffixLower(char *s, char *suffix)
+{
+ char *s_lower = getStringToLower(s);
+ boolean match = strSuffix(s_lower, suffix);
+
+ free(s_lower);
+
+ return match;
+}
+
/* ------------------------------------------------------------------------- */
/* command line option handling functions */
options.display_name = NULL;
options.server_host = NULL;
options.server_port = 0;
+
options.ro_base_directory = ro_base_path;
options.rw_base_directory = rw_base_path;
options.level_directory = getPath2(ro_base_path, LEVELS_DIRECTORY);
options.sounds_directory = getPath2(ro_base_path, SOUNDS_DIRECTORY);
options.music_directory = getPath2(ro_base_path, MUSIC_DIRECTORY);
options.docs_directory = getPath2(ro_base_path, DOCS_DIRECTORY);
+
options.execute_command = NULL;
+ options.special_flags = NULL;
+
options.serveronly = FALSE;
options.network = FALSE;
options.verbose = FALSE;
options.debug = FALSE;
+ options.debug_x11_sync = FALSE;
#if !defined(PLATFORM_UNIX)
if (*options_left == NULL) /* no options given -- enable verbose mode */
if (strEqual(option, "--")) /* stop scanning arguments */
break;
- if (strncmp(option, "--", 2) == 0) /* treat '--' like '-' */
+ if (strPrefix(option, "--")) /* treat '--' like '-' */
option++;
option_arg = strchr(option, '=');
{
options.debug = TRUE;
}
+ else if (strncmp(option, "-debug-x11-sync", option_len) == 0)
+ {
+ options.debug_x11_sync = TRUE;
+ }
+ else if (strPrefix(option, "-D"))
+ {
+#if 1
+ options.special_flags = getStringCopy(&option[2]);
+#else
+ char *flags_string = &option[2];
+ unsigned long flags_value;
+
+ if (*flags_string == '\0')
+ Error(ERR_EXIT_HELP, "empty flag ignored");
+
+ flags_value = get_special_flags_function(flags_string);
+
+ if (flags_value == 0)
+ Error(ERR_EXIT_HELP, "unknown flag '%s'", flags_string);
+
+ options.special_flags |= flags_value;
+#endif
+ }
else if (strncmp(option, "-execute", option_len) == 0)
{
if (option_arg == NULL)
free(ptr);
}
+void clear_mem(void *ptr, unsigned long size)
+{
+#if defined(PLATFORM_WIN32)
+ /* for unknown reason, memset() sometimes crashes when compiled with MinGW */
+ char *cptr = (char *)ptr;
+
+ while (size--)
+ *cptr++ = 0;
+#else
+ memset(ptr, 0, size);
+#endif
+}
+
/* ------------------------------------------------------------------------- */
/* various helper functions */
Key key = KSYM_UNDEFINED;
char *name_ptr = *x11name;
- if (strncmp(name_ptr, "XK_", 3) == 0 && strlen(name_ptr) == 4)
+ if (strPrefix(name_ptr, "XK_") && strlen(name_ptr) == 4)
{
char c = name_ptr[3];
else if (c >= '0' && c <= '9')
key = KSYM_0 + (Key)(c - '0');
}
- else if (strncmp(name_ptr, "XK_KP_", 6) == 0 && strlen(name_ptr) == 7)
+ else if (strPrefix(name_ptr, "XK_KP_") && strlen(name_ptr) == 7)
{
char c = name_ptr[6];
if (c >= '0' && c <= '9')
key = KSYM_KP_0 + (Key)(c - '0');
}
- else if (strncmp(name_ptr, "XK_F", 4) == 0 && strlen(name_ptr) <= 6)
+ else if (strPrefix(name_ptr, "XK_F") && strlen(name_ptr) <= 6)
{
char c1 = name_ptr[4];
char c2 = name_ptr[5];
if (d >= 1 && d <= KSYM_NUM_FKEYS)
key = KSYM_F1 + (Key)(d - 1);
}
- else if (strncmp(name_ptr, "XK_", 3) == 0)
+ else if (strPrefix(name_ptr, "XK_"))
{
i = 0;
}
while (translate_key[++i].x11name);
}
- else if (strncmp(name_ptr, "0x", 2) == 0)
+ else if (strPrefix(name_ptr, "0x"))
{
unsigned long value = 0;
if (result == -1)
{
- if (strEqual(s_lower, "false"))
+ if (strEqual(s_lower, "false") ||
+ strEqual(s_lower, "no") ||
+ strEqual(s_lower, "off"))
result = 0;
- else if (strEqual(s_lower, "true"))
+ else if (strEqual(s_lower, "true") ||
+ strEqual(s_lower, "yes") ||
+ strEqual(s_lower, "on"))
result = 1;
else
result = atoi(s);
return result;
}
+int get_switch3_from_string(char *s)
+{
+ char *s_lower = getStringToLower(s);
+ int result = FALSE;
+
+ if (strEqual(s_lower, "true") ||
+ strEqual(s_lower, "yes") ||
+ strEqual(s_lower, "on") ||
+ get_integer_from_string(s) == 1)
+ result = TRUE;
+ else if (strEqual(s_lower, "auto"))
+ result = AUTO;
+
+ free(s_lower);
+
+ return result;
+}
+
/* ------------------------------------------------------------------------- */
/* functions for generic lists */
return TRUE;
#if defined(TARGET_SDL)
- if (fileHasPrefix(basename, "mod") ||
+ if ((fileHasPrefix(basename, "mod") && !fileHasSuffix(basename, "txt")) ||
fileHasSuffix(basename, "mod") ||
fileHasSuffix(basename, "s3m") ||
fileHasSuffix(basename, "it") ||
string_has_parameter(value, "horizontal") ? ANIM_HORIZONTAL :
string_has_parameter(value, "vertical") ? ANIM_VERTICAL :
string_has_parameter(value, "centered") ? ANIM_CENTERED :
- string_has_parameter(value, "fade") ? ANIM_FADE :
- string_has_parameter(value, "crossfade") ? ANIM_CROSSFADE :
ANIM_DEFAULT);
if (string_has_parameter(value, "reverse"))
if (string_has_parameter(value, "static_panel"))
result |= ANIM_STATIC_PANEL;
}
+ else if (strEqual(suffix, ".class"))
+ {
+ result = get_hash_from_key(value);
+ }
+ else if (strEqual(suffix, ".style"))
+ {
+ result = STYLE_DEFAULT;
+
+ if (string_has_parameter(value, "accurate_borders"))
+ result |= STYLE_ACCURATE_BORDERS;
+
+ if (string_has_parameter(value, "inner_corners"))
+ result |= STYLE_INNER_CORNERS;
+ }
+ else if (strEqual(suffix, ".fade_mode"))
+ {
+ result = (string_has_parameter(value, "none") ? FADE_MODE_NONE :
+ string_has_parameter(value, "fade") ? FADE_MODE_FADE :
+ string_has_parameter(value, "crossfade") ? FADE_MODE_CROSSFADE :
+ string_has_parameter(value, "melt") ? FADE_MODE_MELT :
+ FADE_MODE_DEFAULT);
+ }
+#if 1
+ else if (strPrefix(suffix, ".font")) /* (may also be ".font_xyz") */
+#else
+ else if (strEqualN(suffix, ".font", 5)) /* (may also be ".font_xyz") */
+#endif
+ {
+ result = gfx.get_font_from_token_function(value);
+ }
else /* generic parameter of type integer or boolean */
{
result = (strEqual(value, ARG_UNDEFINED) ? ARG_UNDEFINED_VALUE :
file_list[i].redefined = FALSE;
file_list[i].fallback_to_default = FALSE;
+ file_list[i].default_is_cloned = FALSE;
}
}
printf("::: '%s' => '%s'\n", config_list[i].token, config_list[i].value);
#endif
}
+
+ if (strSuffix(config_list[i].token, ".clone_from"))
+ file_list[list_pos].default_is_cloned = TRUE;
}
num_file_list_entries_found = list_pos + 1;
new_list_entry->redefined = FALSE;
new_list_entry->fallback_to_default = FALSE;
+ new_list_entry->default_is_cloned = FALSE;
read_token_parameters(extra_file_hash, suffix_list, new_list_entry);
}
base_index = i;
+#if 0
+ if (IS_PARENT_PROCESS())
+ printf("===> MATCH: '%s', '%s'\n", token, base_prefix);
+#endif
+
if (start_pos + len_base_prefix == len_token) /* exact match */
{
exact_match = TRUE;
+#if 0
+ if (IS_PARENT_PROCESS())
+ printf("===> EXACT MATCH: '%s', '%s'\n", token, base_prefix);
+#endif
+
add_dynamic_file_list_entry(dynamic_file_list,
num_dynamic_file_list_entries,
extra_file_hash,
ext1_index = j;
+#if 0
+ if (IS_PARENT_PROCESS())
+ printf("===> MATCH: '%s', '%s'\n", token, ext1_suffix);
+#endif
+
if (start_pos + len_ext1_suffix == len_token) /* exact match */
{
exact_match = TRUE;
+#if 0
+ if (IS_PARENT_PROCESS())
+ printf("===> EXACT MATCH: '%s', '%s'\n", token, ext1_suffix);
+#endif
+
add_dynamic_file_list_entry(dynamic_file_list,
num_dynamic_file_list_entries,
extra_file_hash,
ext2_index = k;
+#if 0
+ if (IS_PARENT_PROCESS())
+ printf("===> MATCH: '%s', '%s'\n", token, ext2_suffix);
+#endif
+
if (start_pos + len_ext2_suffix == len_token) /* exact match */
{
exact_match = TRUE;
+#if 0
+ if (IS_PARENT_PROCESS())
+ printf("===> EXACT MATCH: '%s', '%s'\n", token, ext2_suffix);
+#endif
+
add_dynamic_file_list_entry(dynamic_file_list,
num_dynamic_file_list_entries,
extra_file_hash,
ext3_index = l;
+#if 0
+ if (IS_PARENT_PROCESS())
+ printf("===> MATCH: '%s', '%s'\n", token, ext3_suffix);
+#endif
+
if (start_pos + len_ext3_suffix == len_token) /* exact match */
{
exact_match = TRUE;
+#if 0
+ if (IS_PARENT_PROCESS())
+ printf("===> EXACT MATCH: '%s', '%s'\n", token, ext3_suffix);
+#endif
+
add_dynamic_file_list_entry(dynamic_file_list,
num_dynamic_file_list_entries,
extra_file_hash,
artwork_info->num_property_mapping_entries = 0;
}
+#if 1
+ if (!GFX_OVERRIDE_ARTWORK(artwork_info->type))
+#else
if (!SETUP_OVERRIDE_ARTWORK(setup, artwork_info->type))
+#endif
{
/* first look for special artwork configured in level series config */
filename_base = getCustomArtworkLevelConfigFilename(artwork_info->type);
+#if 0
+ printf("::: filename_base == '%s' [%s, %s]\n", filename_base,
+ leveldir_current->graphics_set,
+ leveldir_current->graphics_path);
+#endif
+
if (fileExists(filename_base))
LoadArtworkConfigFromFilename(artwork_info, filename_base);
}
basename = file_list_entry->default_filename;
+ /* fail for cloned default artwork that has no default filename defined */
+ if (file_list_entry->default_is_cloned &&
+ strEqual(basename, UNDEFINED_FILENAME))
+ {
+ int error_mode = ERR_WARN;
+
+ /* we can get away without sounds and music, but not without graphics */
+ if (*listnode == NULL && artwork_info->type == ARTWORK_TYPE_GRAPHICS)
+ error_mode = ERR_EXIT;
+
+ Error(error_mode, "token '%s' was cloned and has no default filename",
+ file_list_entry->token);
+
+ return;
+ }
+
/* dynamic artwork has no default filename / skip empty default artwork */
if (basename == NULL || strEqual(basename, UNDEFINED_FILENAME))
return;
error_mode = ERR_EXIT;
Error(error_mode, "cannot load artwork file '%s'", basename);
+
return;
}
}
#if DEBUG
-#define DEBUG_NUM_TIMESTAMPS 3
+#define DEBUG_NUM_TIMESTAMPS 5
#define DEBUG_TIME_IN_MICROSECONDS 0
#if DEBUG_TIME_IN_MICROSECONDS
}
#endif
+char *debug_print_timestamp_get_padding(int padding_size)
+{
+ static char *padding = NULL;
+ int max_padding_size = 100;
+
+ if (padding == NULL)
+ {
+ padding = checked_calloc(max_padding_size + 1);
+ memset(padding, ' ', max_padding_size);
+ }
+
+ return &padding[MAX(0, max_padding_size - padding_size)];
+}
+
void debug_print_timestamp(int counter_nr, char *message)
{
-#if DEBUG_TIME_IN_MICROSECONDS
- static double counter[DEBUG_NUM_TIMESTAMPS][2];
+ int indent_size = 8;
+ int padding_size = 40;
+ float timestamp_interval;
- if (counter_nr >= DEBUG_NUM_TIMESTAMPS)
+ if (counter_nr < 0)
+ Error(ERR_EXIT, "debugging: invalid negative counter");
+ else if (counter_nr >= DEBUG_NUM_TIMESTAMPS)
Error(ERR_EXIT, "debugging: increase DEBUG_NUM_TIMESTAMPS in misc.c");
- counter[counter_nr][0] = Counter_Microseconds();
-
- if (message)
- printf("%s %.3f ms\n", message,
- (counter[counter_nr][0] - counter[counter_nr][1]) / 1000);
+#if DEBUG_TIME_IN_MICROSECONDS
+ static double counter[DEBUG_NUM_TIMESTAMPS][2];
+ char *unit = "ms";
- counter[counter_nr][1] = counter[counter_nr][0];
+ counter[counter_nr][0] = Counter_Microseconds();
#else
static long counter[DEBUG_NUM_TIMESTAMPS][2];
-
- if (counter_nr >= DEBUG_NUM_TIMESTAMPS)
- Error(ERR_EXIT, "debugging: increase DEBUG_NUM_TIMESTAMPS in misc.c");
+ char *unit = "s";
counter[counter_nr][0] = Counter();
+#endif
- if (message)
- printf("%s %.3f s\n", message,
- (float)(counter[counter_nr][0] - counter[counter_nr][1]) / 1000);
-
+ timestamp_interval = counter[counter_nr][0] - counter[counter_nr][1];
counter[counter_nr][1] = counter[counter_nr][0];
-#endif
+
+ if (message)
+ printf("%s%s%s %.3f %s\n",
+ debug_print_timestamp_get_padding(counter_nr * indent_size),
+ message,
+ debug_print_timestamp_get_padding(padding_size - strlen(message)),
+ timestamp_interval / 1000,
+ unit);
}
void debug_print_parent_only(char *format, ...)