X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fmisc.c;h=eda87185ec74990bc6ac9efbee0b648a93d82436;hb=7ecf99096c7c23909ada034e05d971464f66552f;hp=2bff745d64eff0d29dae8f48eea174b28e855de7;hpb=3ae70b9d27b4b2c038f35b0aa5985c368542a486;p=rocksndiamonds.git diff --git a/src/libgame/misc.c b/src/libgame/misc.c index 2bff745d..eda87185 100644 --- a/src/libgame/misc.c +++ b/src/libgame/misc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "platform.h" @@ -42,25 +43,47 @@ /* platform independent wrappers for printf() et al. (newline aware) */ /* ------------------------------------------------------------------------- */ +#if defined(PLATFORM_ANDROID) +static int android_log_prio = ANDROID_LOG_INFO; +#endif + +#if 0 +static void vfPrintLog(FILE *stream, char *format, va_list ap) +{ +} + +static void vfPrintLog(FILE *stream, char *format, va_list ap) +{ +} + +static void fPrintLog(FILE *stream, char *format, va_list ap) +{ +} + +static void fPrintLog(FILE *stream, char *format, va_list ap) +{ +} +#endif + static void vfprintf_newline(FILE *stream, char *format, va_list ap) { +#if defined(PLATFORM_ANDROID) + __android_log_vprint(android_log_prio, program.program_title, format, ap); +#else char *newline = STRING_NEWLINE; vfprintf(stream, format, ap); - fprintf(stream, "%s", newline); +#endif } static void fprintf_newline(FILE *stream, char *format, ...) { - if (format) - { - va_list ap; + va_list ap; - va_start(ap, format); - vfprintf_newline(stream, format, ap); - va_end(ap); - } + va_start(ap, format); + vfprintf_newline(stream, format, ap); + va_end(ap); } void fprintf_line(FILE *stream, char *line_chars, int line_length) @@ -418,7 +441,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); @@ -494,7 +517,7 @@ char *getRealName() else real_name = ANONYMOUS_NAME; } -#elif defined(PLATFORM_UNIX) +#elif defined(PLATFORM_UNIX) && !defined(PLATFORM_ANDROID) if (real_name == NULL) { struct passwd *pwd; @@ -632,11 +655,23 @@ char *getStringCat3(char *s1, char *s2, char *s3) char *getPath2(char *path1, char *path2) { +#if defined(PLATFORM_ANDROID) + // workaround for reading from APK assets directory -- skip leading "./" + if (strEqual(path1, ".")) + return getStringCopy(path2); +#endif + return getStringCat2WithSeparator(path1, path2, STRING_PATH_SEPARATOR); } char *getPath3(char *path1, char *path2, char *path3) { +#if defined(PLATFORM_ANDROID) + // workaround for reading from APK assets directory -- skip leading "./" + if (strEqual(path1, ".")) + return getStringCat2WithSeparator(path2, path3, STRING_PATH_SEPARATOR); +#endif + return getStringCat3WithSeparator(path1, path2, path3, STRING_PATH_SEPARATOR); } @@ -800,9 +835,13 @@ void GetOptions(char *argv[], void (*print_usage_function)(void)) options.debug = FALSE; options.debug_x11_sync = FALSE; +#if 1 + options.verbose = TRUE; +#else #if !defined(PLATFORM_UNIX) if (*options_left == NULL) /* no options given -- enable verbose mode */ options.verbose = TRUE; +#endif #endif while (*options_left) @@ -1007,6 +1046,14 @@ void Error(int mode, char *format, ...) static boolean last_line_was_separator = FALSE; char *process_name = ""; +#if defined(PLATFORM_ANDROID) + 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 /* display warnings only when running in verbose mode */ if (mode & ERR_WARN && !options.verbose) @@ -1406,7 +1453,9 @@ 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 */ + + { KSYM_Menu, "XK_Menu", "menu" }, /* menu key */ + { KSYM_Back, "XK_Back", "back" }, /* back key */ /* ASCII 0x20 to 0x40 keys (except numbers) */ { KSYM_space, "XK_space", "space" }, @@ -1853,16 +1902,297 @@ void dumpList(ListNode *node_first) } +/* ------------------------------------------------------------------------- */ +/* functions for file handling */ +/* ------------------------------------------------------------------------- */ + +File *openFile(char *filename, char *mode) +{ + File *file = checked_calloc(sizeof(File)); + + file->file = fopen(filename, mode); + + if (file->file != NULL) + { + file->filename = getStringCopy(filename); + + return file; + } + +#if defined(PLATFORM_ANDROID) + file->asset_file = SDL_RWFromFile(filename, mode); + + if (file->asset_file != NULL) + { + file->file_is_asset = TRUE; + file->filename = getStringCopy(filename); + + return file; + } +#endif + + checked_free(file); + + return NULL; +} + +int closeFile(File *file) +{ + if (file == NULL) + return -1; + + int result; + +#if defined(PLATFORM_ANDROID) + if (file->asset_file) + result = SDL_RWclose(file->asset_file); +#endif + + if (file->file) + result = fclose(file->file); + + checked_free(file->filename); + checked_free(file); + + return result; +} + +int checkEndOfFile(File *file) +{ +#if defined(PLATFORM_ANDROID) + if (file->file_is_asset) + return file->end_of_file; +#endif + + return feof(file->file); +} + +char *getStringFromFile(File *file, char *line, int size) +{ +#if defined(PLATFORM_ANDROID) + if (file->file_is_asset) + { + if (file->end_of_file) + return NULL; + + char *line_ptr = line; + int num_bytes_read = 0; + + while (num_bytes_read < size - 1 && + SDL_RWread(file->asset_file, line_ptr, 1, 1) == 1 && + *line_ptr++ != '\n') + num_bytes_read++; + + *line_ptr = '\0'; + + if (strlen(line) == 0) + { + file->end_of_file = TRUE; + + return NULL; + } + + return line; + } +#endif + + return fgets(line, size, file->file); +} + + +/* ------------------------------------------------------------------------- */ +/* functions for directory handling */ +/* ------------------------------------------------------------------------- */ + +Directory *openDirectory(char *dir_name) +{ + Directory *dir = checked_calloc(sizeof(Directory)); + + dir->dir = opendir(dir_name); + + if (dir->dir != NULL) + { + dir->filename = getStringCopy(dir_name); + + return dir; + } + +#if defined(PLATFORM_ANDROID) + char *asset_toc_filename = getPath2(dir_name, ASSET_TOC_BASENAME); + + dir->asset_toc_file = SDL_RWFromFile(asset_toc_filename, MODE_READ); + + checked_free(asset_toc_filename); + + if (dir->asset_toc_file != NULL) + { + dir->directory_is_asset = TRUE; + dir->filename = getStringCopy(dir_name); + + return dir; + } +#endif + + checked_free(dir); + + return NULL; +} + +int closeDirectory(Directory *dir) +{ + if (dir == NULL) + return -1; + + int result; + +#if defined(PLATFORM_ANDROID) + if (dir->asset_toc_file) + result = SDL_RWclose(dir->asset_toc_file); +#endif + + if (dir->dir) + result = closedir(dir->dir); + + if (dir->dir_entry) + freeDirectoryEntry(dir->dir_entry); + + checked_free(dir->filename); + checked_free(dir); + + return result; +} + +DirectoryEntry *readDirectory(Directory *dir) +{ + if (dir->dir_entry) + freeDirectoryEntry(dir->dir_entry); + + dir->dir_entry = NULL; + +#if defined(PLATFORM_ANDROID) + if (dir->directory_is_asset) + { + char line[MAX_LINE_LEN]; + char *line_ptr = line; + int num_bytes_read = 0; + + while (num_bytes_read < MAX_LINE_LEN - 1 && + SDL_RWread(dir->asset_toc_file, line_ptr, 1, 1) == 1 && + *line_ptr != '\n') + { + line_ptr++; + num_bytes_read++; + } + + *line_ptr = '\0'; + + if (strlen(line) == 0) + return NULL; + + dir->dir_entry = checked_calloc(sizeof(DirectoryEntry)); + + dir->dir_entry->is_directory = FALSE; + if (line[strlen(line) - 1] == '/') + { + dir->dir_entry->is_directory = TRUE; + + line[strlen(line) - 1] = '\0'; + } + + dir->dir_entry->basename = getStringCopy(line); + dir->dir_entry->filename = getPath2(dir->filename, line); + + return dir->dir_entry; + } +#endif + + struct dirent *dir_entry = readdir(dir->dir); + + if (dir_entry == NULL) + return NULL; + + dir->dir_entry = checked_calloc(sizeof(DirectoryEntry)); + + dir->dir_entry->basename = getStringCopy(dir_entry->d_name); + dir->dir_entry->filename = getPath2(dir->filename, dir_entry->d_name); + + struct stat file_status; + + dir->dir_entry->is_directory = + (stat(dir->dir_entry->filename, &file_status) == 0 && + (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; +} + +void freeDirectoryEntry(DirectoryEntry *dir_entry) +{ + if (dir_entry == NULL) + return; + + checked_free(dir_entry->basename); + checked_free(dir_entry->filename); + checked_free(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; - return (access(filename, F_OK) == 0); + boolean success = (access(filename, F_OK) == 0); + +#if defined(PLATFORM_ANDROID) + if (!success) + { + // this might be an asset file; check by trying to open it + SDL_RWops *file = SDL_RWFromFile(filename, MODE_READ); + + success = (file != NULL); + + if (success) + SDL_RWclose(file); + } +#endif + + return success; } boolean fileHasPrefix(char *basename, char *prefix) @@ -1913,23 +2243,38 @@ boolean FileIsGraphic(char *filename) { char *basename = getBaseNamePtr(filename); +#if defined(TARGET_SDL) + return (!fileHasSuffix(basename, "txt") && + !fileHasSuffix(basename, "conf")); +#else return fileHasSuffix(basename, "pcx"); +#endif } boolean FileIsSound(char *filename) { char *basename = getBaseNamePtr(filename); +#if defined(TARGET_SDL) + return (!fileHasSuffix(basename, "txt") && + !fileHasSuffix(basename, "conf")); +#else return fileHasSuffix(basename, "wav"); +#endif } boolean FileIsMusic(char *filename) { char *basename = getBaseNamePtr(filename); +#if defined(TARGET_SDL) + return (!fileHasSuffix(basename, "txt") && + !fileHasSuffix(basename, "conf")); +#else if (FileIsSound(basename)) return TRUE; +#if 0 #if defined(TARGET_SDL) if ((fileHasPrefix(basename, "mod") && !fileHasSuffix(basename, "txt")) || fileHasSuffix(basename, "mod") || @@ -1941,9 +2286,11 @@ boolean FileIsMusic(char *filename) fileHasSuffix(basename, "mp3") || fileHasSuffix(basename, "ogg")) return TRUE; +#endif #endif return FALSE; +#endif } boolean FileIsArtworkType(char *basename, int type) @@ -2201,10 +2548,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++) @@ -2219,6 +2569,7 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list, config_list[i].value); is_file_entry = FALSE; + break; } } @@ -2236,6 +2587,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") && @@ -2245,6 +2597,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; @@ -3035,6 +3388,7 @@ static void LoadCustomArtwork(struct ArtworkListInfo *artwork_info, if (strEqual(file_list_entry->filename, UNDEFINED_FILENAME)) { deleteArtworkListEntry(artwork_info, listnode); + return; } @@ -3050,6 +3404,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]); @@ -3058,6 +3414,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 @@ -3109,8 +3467,12 @@ void openErrorFile() InitUserDataDirectory(); if ((program.error_file = fopen(program.error_filename, MODE_WRITE)) == NULL) - fprintf_newline(stderr, "ERROR: cannot open file '%s' for writing!", - program.error_filename); + { + program.error_file = stderr; + + Error(ERR_WARN, "cannot open file '%s' for writing: %s", + program.error_filename, strerror(errno)); + } } void closeErrorFile() @@ -3151,8 +3513,11 @@ void NotifyUserAboutErrorFile() #if DEBUG -#define DEBUG_NUM_TIMESTAMPS 5 -#define DEBUG_TIME_IN_MICROSECONDS 0 +#define DEBUG_PRINT_INIT_TIMESTAMPS TRUE +#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() @@ -3216,7 +3581,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)), @@ -3240,4 +3609,69 @@ void debug_print_parent_only(char *format, ...) printf("\n"); } } + +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"); +} + +#endif /* DEBUG */