rnd-20140114-1-src
[rocksndiamonds.git] / src / libgame / misc.c
index eb7f75d90029c1a7bfd8198b798673ec91881e31..ae4b5d78e797c470863e88e09313172700eeca0d 100644 (file)
@@ -65,6 +65,22 @@ static void fPrintLog(FILE *stream, char *format, va_list ap)
 }
 #endif
 
+static void vfprintf_nonewline(FILE *stream, char *format, va_list ap)
+{
+#if defined(PLATFORM_ANDROID)
+  // (prefix text of logging output is currently skipped on Android)
+  //__android_log_vprint(android_log_prio, program.program_title, format, ap);
+#else
+  va_list ap2;
+  va_copy(ap2, ap);
+
+  vfprintf(stream, format, ap);
+  vfprintf(stderr, format, ap2);
+
+  va_end(ap2);
+#endif
+}
+
 static void vfprintf_newline(FILE *stream, char *format, va_list ap)
 {
 #if defined(PLATFORM_ANDROID)
@@ -72,11 +88,28 @@ static void vfprintf_newline(FILE *stream, char *format, va_list ap)
 #else
   char *newline = STRING_NEWLINE;
 
+  va_list ap2;
+  va_copy(ap2, ap);
+
   vfprintf(stream, format, ap);
   fprintf(stream, "%s", newline);
+
+  vfprintf(stderr, format, ap2);
+  fprintf(stderr, "%s", newline);
+
+  va_end(ap2);
 #endif
 }
 
+static void fprintf_nonewline(FILE *stream, char *format, ...)
+{
+  va_list ap;
+
+  va_start(ap, format);
+  vfprintf_nonewline(stream, format, ap);
+  va_end(ap);
+}
+
 static void fprintf_newline(FILE *stream, char *format, ...)
 {
   va_list ap;
@@ -91,7 +124,7 @@ void fprintf_line(FILE *stream, char *line_chars, int line_length)
   int i;
 
   for (i = 0; i < line_length; i++)
-    fprintf(stream, "%s", line_chars);
+    fprintf_nonewline(stream, "%s", line_chars);
 
   fprintf_newline(stream, "");
 }
@@ -441,7 +474,7 @@ unsigned int get_random_number(int nr, int max)
 /* system info functions                                                     */
 /* ------------------------------------------------------------------------- */
 
-#if !defined(PLATFORM_MSDOS)
+#if !defined(PLATFORM_MSDOS) && !defined(PLATFORM_ANDROID)
 static char *get_corrected_real_name(char *real_name)
 {
   char *real_name_new = checked_malloc(MAX_USERNAME_LEN + 1);
@@ -1047,8 +1080,11 @@ void Error(int mode, char *format, ...)
   char *process_name = "";
 
 #if defined(PLATFORM_ANDROID)
-  android_log_prio = (mode & ERR_WARN ? ANDROID_LOG_WARN :
-                     mode & ERR_EXIT ? ANDROID_LOG_FATAL : ANDROID_LOG_INFO);
+  android_log_prio = (mode & ERR_DEBUG ? ANDROID_LOG_DEBUG :
+                     mode & ERR_INFO ? ANDROID_LOG_INFO :
+                     mode & ERR_WARN ? ANDROID_LOG_WARN :
+                     mode & ERR_EXIT ? ANDROID_LOG_FATAL :
+                     ANDROID_LOG_UNKNOWN);
 #endif
 
 #if 1
@@ -1080,11 +1116,11 @@ void Error(int mode, char *format, ...)
   {
     va_list ap;
 
-    fprintf(program.error_file, "%s%s: ", program.command_basename,
-           process_name);
+    fprintf_nonewline(program.error_file, "%s%s: ", program.command_basename,
+                     process_name);
 
     if (mode & ERR_WARN)
-      fprintf(program.error_file, "warning: ");
+      fprintf_nonewline(program.error_file, "warning: ");
 
     va_start(ap, format);
     vfprintf_newline(program.error_file, format, ap);
@@ -1205,11 +1241,22 @@ inline void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
    of the (not yet written) chunk, write the correct chunk size and finally
    write the chunk itself */
 
+#if 1
+
+int getFile8BitInteger(File *file)
+{
+  return getByteFromFile(file);
+}
+
+#else
+
 int getFile8BitInteger(FILE *file)
 {
   return fgetc(file);
 }
 
+#endif
+
 int putFile8BitInteger(FILE *file, int value)
 {
   if (file != NULL)
@@ -1218,6 +1265,20 @@ int putFile8BitInteger(FILE *file, int value)
   return 1;
 }
 
+#if 1
+
+int getFile16BitInteger(File *file, int byte_order)
+{
+  if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+    return ((getByteFromFile(file) << 8) |
+           (getByteFromFile(file) << 0));
+  else          /* BYTE_ORDER_LITTLE_ENDIAN */
+    return ((getByteFromFile(file) << 0) |
+           (getByteFromFile(file) << 8));
+}
+
+#else
+
 int getFile16BitInteger(FILE *file, int byte_order)
 {
   if (byte_order == BYTE_ORDER_BIG_ENDIAN)
@@ -1228,6 +1289,8 @@ int getFile16BitInteger(FILE *file, int byte_order)
            (fgetc(file) << 8));
 }
 
+#endif
+
 int putFile16BitInteger(FILE *file, int value, int byte_order)
 {
   if (file != NULL)
@@ -1247,6 +1310,24 @@ int putFile16BitInteger(FILE *file, int value, int byte_order)
   return 2;
 }
 
+#if 1
+
+int getFile32BitInteger(File *file, int byte_order)
+{
+  if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+    return ((getByteFromFile(file) << 24) |
+           (getByteFromFile(file) << 16) |
+           (getByteFromFile(file) <<  8) |
+           (getByteFromFile(file) <<  0));
+  else          /* BYTE_ORDER_LITTLE_ENDIAN */
+    return ((getByteFromFile(file) <<  0) |
+           (getByteFromFile(file) <<  8) |
+           (getByteFromFile(file) << 16) |
+           (getByteFromFile(file) << 24));
+}
+
+#else
+
 int getFile32BitInteger(FILE *file, int byte_order)
 {
   if (byte_order == BYTE_ORDER_BIG_ENDIAN)
@@ -1261,6 +1342,8 @@ int getFile32BitInteger(FILE *file, int byte_order)
            (fgetc(file) << 24));
 }
 
+#endif
+
 int putFile32BitInteger(FILE *file, int value, int byte_order)
 {
   if (file != NULL)
@@ -1284,6 +1367,28 @@ int putFile32BitInteger(FILE *file, int value, int byte_order)
   return 4;
 }
 
+#if 1
+
+boolean getFileChunk(File *file, char *chunk_name, int *chunk_size,
+                    int byte_order)
+{
+  const int chunk_name_length = 4;
+
+  /* read chunk name */
+  if (getStringFromFile(file, chunk_name, chunk_name_length + 1) == NULL)
+    return FALSE;
+
+  if (chunk_size != NULL)
+  {
+    /* read chunk size */
+    *chunk_size = getFile32BitInteger(file, byte_order);
+  }
+
+  return (checkEndOfFile(file) ? FALSE : TRUE);
+}
+
+#else
+
 boolean getFileChunk(FILE *file, char *chunk_name, int *chunk_size,
                     int byte_order)
 {
@@ -1302,6 +1407,8 @@ boolean getFileChunk(FILE *file, char *chunk_name, int *chunk_size,
   return (feof(file) || ferror(file) ? FALSE : TRUE);
 }
 
+#endif
+
 int putFileChunk(FILE *file, char *chunk_name, int chunk_size,
                 int byte_order)
 {
@@ -1325,6 +1432,21 @@ int putFileChunk(FILE *file, char *chunk_name, int chunk_size,
   return num_bytes;
 }
 
+#if 1
+
+int getFileVersion(File *file)
+{
+  int version_major = getByteFromFile(file);
+  int version_minor = getByteFromFile(file);
+  int version_patch = getByteFromFile(file);
+  int version_build = getByteFromFile(file);
+
+  return VERSION_IDENT(version_major, version_minor, version_patch,
+                      version_build);
+}
+
+#else
+
 int getFileVersion(FILE *file)
 {
   int version_major = fgetc(file);
@@ -1336,6 +1458,8 @@ int getFileVersion(FILE *file)
                       version_build);
 }
 
+#endif
+
 int putFileVersion(FILE *file, int version)
 {
   if (file != NULL)
@@ -1354,6 +1478,18 @@ int putFileVersion(FILE *file, int version)
   return 4;
 }
 
+#if 1
+
+void ReadBytesFromFile(File *file, byte *buffer, unsigned int bytes)
+{
+  int i;
+
+  for (i = 0; i < bytes && !checkEndOfFile(file); i++)
+    buffer[i] = getByteFromFile(file);
+}
+
+#else
+
 void ReadBytesFromFile(FILE *file, byte *buffer, unsigned int bytes)
 {
   int i;
@@ -1362,6 +1498,8 @@ void ReadBytesFromFile(FILE *file, byte *buffer, unsigned int bytes)
     buffer[i] = fgetc(file);
 }
 
+#endif
+
 void WriteBytesToFile(FILE *file, byte *buffer, unsigned int bytes)
 {
   int i;
@@ -1370,12 +1508,24 @@ void WriteBytesToFile(FILE *file, byte *buffer, unsigned int bytes)
     fputc(buffer[i], file);
 }
 
+#if 1
+
+void ReadUnusedBytesFromFile(File *file, unsigned int bytes)
+{
+  while (bytes-- && !checkEndOfFile(file))
+    getByteFromFile(file);
+}
+
+#else
+
 void ReadUnusedBytesFromFile(FILE *file, unsigned int bytes)
 {
   while (bytes-- && !feof(file))
     fgetc(file);
 }
 
+#endif
+
 void WriteUnusedBytesToFile(FILE *file, unsigned int bytes)
 {
   while (bytes--)
@@ -1450,7 +1600,11 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
     { KSYM_End,                "XK_End",               "end" },
     { KSYM_Page_Up,    "XK_Page_Up",           "page up" },
     { KSYM_Page_Down,  "XK_Page_Down",         "page down" },
-    { KSYM_Menu,       "XK_Menu",              "menu" },        /* Win-Menu */
+
+#if defined(TARGET_SDL2)
+    { KSYM_Menu,       "XK_Menu",              "menu" },        /* menu key */
+    { KSYM_Back,       "XK_Back",              "back" },        /* back key */
+#endif
 
     /* ASCII 0x20 to 0x40 keys (except numbers) */
     { KSYM_space,      "XK_space",             "space" },
@@ -1490,8 +1644,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
     { KSYM_braceright, "XK_braceright",        "brace right" },
     { KSYM_asciitilde, "XK_asciitilde",        "~" },
 
-#if !defined(TARGET_SDL2)
-    /* special (non-ASCII) keys */
+    /* special (non-ASCII) keys (ISO-Latin-1) */
     { KSYM_degree,     "XK_degree",            "°" },
     { KSYM_Adiaeresis, "XK_Adiaeresis",        "Ä" },
     { KSYM_Odiaeresis, "XK_Odiaeresis",        "Ö" },
@@ -1500,6 +1653,34 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
     { KSYM_odiaeresis, "XK_odiaeresis",        "ö" },
     { KSYM_udiaeresis, "XK_udiaeresis",        "ü" },
     { KSYM_ssharp,     "XK_ssharp",            "sharp s" },
+
+#if defined(TARGET_SDL2)
+    /* special (non-ASCII) keys (UTF-8, for reverse mapping only) */
+    { KSYM_degree,     "XK_degree",            "\xc2\xb0" },
+    { KSYM_Adiaeresis, "XK_Adiaeresis",        "\xc3\x84" },
+    { KSYM_Odiaeresis, "XK_Odiaeresis",        "\xc3\x96" },
+    { KSYM_Udiaeresis, "XK_Udiaeresis",        "\xc3\x9c" },
+    { KSYM_adiaeresis, "XK_adiaeresis",        "\xc3\xa4" },
+    { KSYM_odiaeresis, "XK_odiaeresis",        "\xc3\xb6" },
+    { KSYM_udiaeresis, "XK_udiaeresis",        "\xc3\xbc" },
+    { KSYM_ssharp,     "XK_ssharp",            "\xc3\x9f" },
+
+    /* other keys (for reverse mapping only) */
+    { KSYM_space,      "XK_space",             " " },
+#endif
+
+#if defined(TARGET_SDL2)
+    /* keypad keys are not in numerical order in SDL2 */
+    { KSYM_KP_0,       "XK_KP_0",              "keypad 0" },
+    { KSYM_KP_1,       "XK_KP_1",              "keypad 1" },
+    { KSYM_KP_2,       "XK_KP_2",              "keypad 2" },
+    { KSYM_KP_3,       "XK_KP_3",              "keypad 3" },
+    { KSYM_KP_4,       "XK_KP_4",              "keypad 4" },
+    { KSYM_KP_5,       "XK_KP_5",              "keypad 5" },
+    { KSYM_KP_6,       "XK_KP_6",              "keypad 6" },
+    { KSYM_KP_7,       "XK_KP_7",              "keypad 7" },
+    { KSYM_KP_8,       "XK_KP_8",              "keypad 8" },
+    { KSYM_KP_9,       "XK_KP_9",              "keypad 9" },
 #endif
 
     /* end-of-array identifier */
@@ -1519,8 +1700,10 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       sprintf(name_buffer, "%c", 'a' + (char)(key - KSYM_a));
     else if (key >= KSYM_0 && key <= KSYM_9)
       sprintf(name_buffer, "%c", '0' + (char)(key - KSYM_0));
+#if !defined(TARGET_SDL2)
     else if (key >= KSYM_KP_0 && key <= KSYM_KP_9)
       sprintf(name_buffer, "keypad %c", '0' + (char)(key - KSYM_KP_0));
+#endif
     else if (key >= KSYM_FKEY_FIRST && key <= KSYM_FKEY_LAST)
       sprintf(name_buffer, "F%d", (int)(key - KSYM_FKEY_FIRST + 1));
     else if (key == KSYM_UNDEFINED)
@@ -1556,8 +1739,10 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       sprintf(name_buffer, "XK_%c", 'a' + (char)(key - KSYM_a));
     else if (key >= KSYM_0 && key <= KSYM_9)
       sprintf(name_buffer, "XK_%c", '0' + (char)(key - KSYM_0));
+#if !defined(TARGET_SDL2)
     else if (key >= KSYM_KP_0 && key <= KSYM_KP_9)
       sprintf(name_buffer, "XK_KP_%c", '0' + (char)(key - KSYM_KP_0));
+#endif
     else if (key >= KSYM_FKEY_FIRST && key <= KSYM_FKEY_LAST)
       sprintf(name_buffer, "XK_F%d", (int)(key - KSYM_FKEY_FIRST + 1));
     else if (key == KSYM_UNDEFINED)
@@ -1585,17 +1770,34 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
   else if (mode == TRANSLATE_KEYNAME_TO_KEYSYM)
   {
     Key key = KSYM_UNDEFINED;
+    char *name_ptr = *name;
+
+    if (strlen(*name) == 1)
+    {
+      char c = name_ptr[0];
+
+      if (c >= 'A' && c <= 'Z')
+       key = KSYM_A + (Key)(c - 'A');
+      else if (c >= 'a' && c <= 'z')
+       key = KSYM_a + (Key)(c - 'a');
+      else if (c >= '0' && c <= '9')
+       key = KSYM_0 + (Key)(c - '0');
+    }
 
-    i = 0;
-    do
+    if (key == KSYM_UNDEFINED)
     {
-      if (strEqual(translate_key[i].name, *name))
+      i = 0;
+
+      do
       {
-       key = translate_key[i].key;
-       break;
+       if (strEqual(translate_key[i].name, *name))
+       {
+         key = translate_key[i].key;
+         break;
+       }
       }
+      while (translate_key[++i].x11name);
     }
-    while (translate_key[++i].x11name);
 
     if (key == KSYM_UNDEFINED)
       Error(ERR_WARN, "getKeyFromKeyName(): not completely implemented");
@@ -1618,6 +1820,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       else if (c >= '0' && c <= '9')
        key = KSYM_0 + (Key)(c - '0');
     }
+#if !defined(TARGET_SDL2)
     else if (strPrefix(name_ptr, "XK_KP_") && strlen(name_ptr) == 7)
     {
       char c = name_ptr[6];
@@ -1625,6 +1828,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       if (c >= '0' && c <= '9')
        key = KSYM_KP_0 + (Key)(c - '0');
     }
+#endif
     else if (strPrefix(name_ptr, "XK_F") && strlen(name_ptr) <= 6)
     {
       char c1 = name_ptr[4];
@@ -1936,7 +2140,7 @@ int closeFile(File *file)
   if (file == NULL)
     return -1;
 
-  int result;
+  int result = 0;
 
 #if defined(PLATFORM_ANDROID)
   if (file->asset_file)
@@ -1962,6 +2166,64 @@ int checkEndOfFile(File *file)
   return feof(file->file);
 }
 
+size_t readFile(File *file, void *buffer, size_t item_size, size_t num_items)
+{
+#if defined(PLATFORM_ANDROID)
+  if (file->file_is_asset)
+  {
+    if (file->end_of_file)
+      return 0;
+
+    size_t num_items_read =
+      SDL_RWread(file->asset_file, buffer, item_size, num_items);
+
+    if (num_items_read < num_items)
+      file->end_of_file = TRUE;
+
+    return num_items_read;
+  }
+#endif
+
+  return fread(buffer, item_size, num_items, file->file);
+}
+
+int seekFile(File *file, long offset, int whence)
+{
+#if defined(PLATFORM_ANDROID)
+  if (file->file_is_asset)
+  {
+    int sdl_whence = (whence == SEEK_SET ? RW_SEEK_SET :
+                     whence == SEEK_CUR ? RW_SEEK_CUR :
+                     whence == SEEK_END ? RW_SEEK_END : 0);
+
+    return (SDL_RWseek(file->asset_file, offset, sdl_whence) == -1 ? -1 : 0);
+  }
+#endif
+
+  return fseek(file->file, offset, whence);
+}
+
+int getByteFromFile(File *file)
+{
+#if defined(PLATFORM_ANDROID)
+  if (file->file_is_asset)
+  {
+    if (file->end_of_file)
+      return EOF;
+
+    byte c;
+    size_t num_bytes_read = SDL_RWread(file->asset_file, &c, 1, 1);
+
+    if (num_bytes_read < 1)
+      file->end_of_file = TRUE;
+
+    return (file->end_of_file ? EOF : (int)c);
+  }
+#endif
+
+  return fgetc(file->file);
+}
+
 char *getStringFromFile(File *file, char *line, int size)
 {
 #if defined(PLATFORM_ANDROID)
@@ -2038,7 +2300,7 @@ int closeDirectory(Directory *dir)
   if (dir == NULL)
     return -1;
 
-  int result;
+  int result = 0;
 
 #if defined(PLATFORM_ANDROID)
   if (dir->asset_toc_file)
@@ -2087,7 +2349,7 @@ DirectoryEntry *readDirectory(Directory *dir)
     dir->dir_entry = checked_calloc(sizeof(DirectoryEntry));
 
     dir->dir_entry->is_directory = FALSE;
-    if (line[strlen(line) - 1] = '/')
+    if (line[strlen(line) - 1] == '/')
     {
       dir->dir_entry->is_directory = TRUE;
 
@@ -2115,7 +2377,13 @@ DirectoryEntry *readDirectory(Directory *dir)
 
   dir->dir_entry->is_directory =
     (stat(dir->dir_entry->filename, &file_status) == 0 &&
-     (file_status.st_mode & S_IFMT) != S_IFDIR);
+     (file_status.st_mode & S_IFMT) == S_IFDIR);
+
+#if 0
+  Error(ERR_INFO, "::: '%s' is directory: %d",
+       dir->dir_entry->basename,
+       dir->dir_entry->is_directory);
+#endif
 
   return dir->dir_entry;
 }
@@ -2135,23 +2403,53 @@ void freeDirectoryEntry(DirectoryEntry *dir_entry)
 /* functions for checking files and filenames                                */
 /* ------------------------------------------------------------------------- */
 
+boolean directoryExists(char *dir_name)
+{
+  if (dir_name == NULL)
+    return FALSE;
+
+  boolean success = (access(dir_name, F_OK) == 0);
+
+#if defined(PLATFORM_ANDROID)
+  if (!success)
+  {
+    // this might be an asset directory; check by trying to open toc file
+    char *asset_toc_filename = getPath2(dir_name, ASSET_TOC_BASENAME);
+    SDL_RWops *file = SDL_RWFromFile(asset_toc_filename, MODE_READ);
+
+    checked_free(asset_toc_filename);
+
+    success = (file != NULL);
+
+    if (success)
+      SDL_RWclose(file);
+  }
+#endif
+
+  return success;
+}
+
 boolean fileExists(char *filename)
 {
   if (filename == NULL)
     return FALSE;
 
+  boolean success = (access(filename, F_OK) == 0);
+
 #if defined(PLATFORM_ANDROID)
-  // workaround: check if file exists by opening and closing it
-  SDL_RWops *file = SDL_RWFromFile(filename, MODE_READ);
-  boolean success = (file != NULL);
+  if (!success)
+  {
+    // this might be an asset file; check by trying to open it
+    SDL_RWops *file = SDL_RWFromFile(filename, MODE_READ);
 
-  if (success)
-    SDL_RWclose(file);
+    success = (file != NULL);
 
-  return success;
-#else
-  return (access(filename, F_OK) == 0);
+    if (success)
+      SDL_RWclose(file);
+  }
 #endif
+
+  return success;
 }
 
 boolean fileHasPrefix(char *basename, char *prefix)
@@ -2198,27 +2496,49 @@ boolean fileHasSuffix(char *basename, char *suffix)
   return FALSE;
 }
 
+#if defined(TARGET_SDL)
+static boolean FileCouldBeArtwork(char *basename)
+{
+  return (!strEqual(basename, ".") &&
+         !strEqual(basename, "..") &&
+         !fileHasSuffix(basename, "txt") &&
+         !fileHasSuffix(basename, "conf"));
+}
+#endif
+
 boolean FileIsGraphic(char *filename)
 {
   char *basename = getBaseNamePtr(filename);
 
+#if defined(TARGET_SDL)
+  return FileCouldBeArtwork(basename);
+#else
   return fileHasSuffix(basename, "pcx");
+#endif
 }
 
 boolean FileIsSound(char *filename)
 {
   char *basename = getBaseNamePtr(filename);
 
+#if defined(TARGET_SDL)
+  return FileCouldBeArtwork(basename);
+#else
   return fileHasSuffix(basename, "wav");
+#endif
 }
 
 boolean FileIsMusic(char *filename)
 {
   char *basename = getBaseNamePtr(filename);
 
+#if defined(TARGET_SDL)
+  return FileCouldBeArtwork(basename);
+#else
   if (FileIsSound(basename))
     return TRUE;
 
+#if 0
 #if defined(TARGET_SDL)
   if ((fileHasPrefix(basename, "mod") && !fileHasSuffix(basename, "txt")) ||
       fileHasSuffix(basename, "mod") ||
@@ -2230,9 +2550,11 @@ boolean FileIsMusic(char *filename)
       fileHasSuffix(basename, "mp3") ||
       fileHasSuffix(basename, "ogg"))
     return TRUE;
+#endif
 #endif
 
   return FALSE;
+#endif
 }
 
 boolean FileIsArtworkType(char *basename, int type)
@@ -2490,10 +2812,13 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
   }
 
   list_pos = 0;
+
   for (i = 0; config_list[i].token != NULL; i++)
   {
     int len_config_token = strlen(config_list[i].token);
+#if 0
     int len_config_value = strlen(config_list[i].value);
+#endif
     boolean is_file_entry = TRUE;
 
     for (j = 0; suffix_list[j].token != NULL; j++)
@@ -2508,6 +2833,7 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
                  config_list[i].value);
 
        is_file_entry = FALSE;
+
        break;
       }
     }
@@ -2525,6 +2851,7 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
       if (list_pos >= num_file_list_entries)
        break;
 
+#if 0
       /* simple sanity check if this is really a file definition */
       if (!strEqual(&config_list[i].value[len_config_value - 4], ".pcx") &&
          !strEqual(&config_list[i].value[len_config_value - 4], ".wav") &&
@@ -2534,6 +2861,7 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
              config_list[i].token, config_list[i].value);
        Error(ERR_EXIT, "This seems to be no valid definition -- please fix");
       }
+#endif
 
       file_list[list_pos].token = config_list[i].token;
       file_list[list_pos].default_filename = config_list[i].value;
@@ -3324,6 +3652,7 @@ static void LoadCustomArtwork(struct ArtworkListInfo *artwork_info,
   if (strEqual(file_list_entry->filename, UNDEFINED_FILENAME))
   {
     deleteArtworkListEntry(artwork_info, listnode);
+
     return;
   }
 
@@ -3339,6 +3668,8 @@ void ReloadCustomArtworkList(struct ArtworkListInfo *artwork_info)
     artwork_info->num_dynamic_file_list_entries;
   int i;
 
+  print_timestamp_init("ReloadCustomArtworkList");
+
   for (i = 0; i < num_file_list_entries; i++)
     LoadCustomArtwork(artwork_info, &artwork_info->artwork_list[i],
                      &file_list[i]);
@@ -3347,6 +3678,8 @@ void ReloadCustomArtworkList(struct ArtworkListInfo *artwork_info)
     LoadCustomArtwork(artwork_info, &artwork_info->dynamic_artwork_list[i],
                      &dynamic_file_list[i]);
 
+  print_timestamp_done("ReloadCustomArtworkList");
+
 #if 0
   dumpList(artwork_info->content_list);
 #endif
@@ -3444,8 +3777,11 @@ void NotifyUserAboutErrorFile()
 
 #if DEBUG
 
-#define DEBUG_NUM_TIMESTAMPS           5
-#define DEBUG_TIME_IN_MICROSECONDS     0
+#define DEBUG_PRINT_INIT_TIMESTAMPS            FALSE
+#define DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH      10
+
+#define DEBUG_NUM_TIMESTAMPS                   10
+#define DEBUG_TIME_IN_MICROSECONDS             0
 
 #if DEBUG_TIME_IN_MICROSECONDS
 static double Counter_Microseconds()
@@ -3509,7 +3845,11 @@ void debug_print_timestamp(int counter_nr, char *message)
   counter[counter_nr][1] = counter[counter_nr][0];
 
   if (message)
+#if 1
+    Error(ERR_DEBUG, "%s%s%s %.3f %s",
+#else
     printf("%s%s%s %.3f %s\n",
+#endif
           debug_print_timestamp_get_padding(counter_nr * indent_size),
           message,
           debug_print_timestamp_get_padding(padding_size - strlen(message)),
@@ -3533,4 +3873,69 @@ void debug_print_parent_only(char *format, ...)
     printf("\n");
   }
 }
+
+#endif /* DEBUG */
+
+void print_timestamp_ext(char *message, char *mode)
+{
+#if DEBUG_PRINT_INIT_TIMESTAMPS
+  static char *debug_message = NULL;
+  static char *last_message = NULL;
+  static int counter_nr = 0;
+  int max_depth = DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH;
+
+  checked_free(debug_message);
+  debug_message = getStringCat3(mode, " ", message);
+
+  if (strEqual(mode, "INIT"))
+  {
+    debug_print_timestamp(counter_nr, NULL);
+
+    if (counter_nr + 1 < max_depth)
+      debug_print_timestamp(counter_nr, debug_message);
+
+    counter_nr++;
+
+    debug_print_timestamp(counter_nr, NULL);
+  }
+  else if (strEqual(mode, "DONE"))
+  {
+    counter_nr--;
+
+    if (counter_nr + 1 < max_depth ||
+       (counter_nr == 0 && max_depth == 1))
+    {
+      last_message = message;
+
+      if (counter_nr == 0 && max_depth == 1)
+      {
+       checked_free(debug_message);
+       debug_message = getStringCat3("TIME", " ", message);
+      }
+
+      debug_print_timestamp(counter_nr, debug_message);
+    }
+  }
+  else if (!strEqual(mode, "TIME") ||
+          !strEqual(message, last_message))
+  {
+    if (counter_nr < max_depth)
+      debug_print_timestamp(counter_nr, debug_message);
+  }
 #endif
+}
+
+void print_timestamp_init(char *message)
+{
+  print_timestamp_ext(message, "INIT");
+}
+
+void print_timestamp_time(char *message)
+{
+  print_timestamp_ext(message, "TIME");
+}
+
+void print_timestamp_done(char *message)
+{
+  print_timestamp_ext(message, "DONE");
+}