From 142d88521dfcde187ea315279d79203c00e1b0f3 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Tue, 10 Dec 2013 01:52:33 +0100 Subject: [PATCH] rnd-20131210-1-src --- src/conftime.h | 2 +- src/events.c | 7 + src/libgame/misc.c | 122 +++++++++++++-- src/libgame/misc.h | 35 +++-- src/libgame/setup.c | 352 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 497 insertions(+), 21 deletions(-) diff --git a/src/conftime.h b/src/conftime.h index ce6bfee6..537f0a44 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "2013-12-09 21:41" +#define COMPILE_DATE_STRING "2013-12-10 01:00" diff --git a/src/events.c b/src/events.c index 75e32c71..8f595ece 100644 --- a/src/events.c +++ b/src/events.c @@ -152,6 +152,13 @@ void EventLoop(void) { switch (event.type) { +#if defined(PLATFORM_ANDROID) + // !!! TEST ONLY !!! + case SDL_QUIT: + case SDL_FINGERDOWN: + CloseAllAndExit(0); +#endif + case EVENT_BUTTONPRESS: case EVENT_BUTTONRELEASE: HandleButtonEvent((ButtonEvent *) &event); diff --git a/src/libgame/misc.c b/src/libgame/misc.c index 9d6e0cc9..eb7f75d9 100644 --- a/src/libgame/misc.c +++ b/src/libgame/misc.c @@ -835,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) @@ -1894,12 +1898,110 @@ void dumpList(ListNode *node_first) /* ------------------------------------------------------------------------- */ -/* functions for reading directories */ +/* 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 */ /* ------------------------------------------------------------------------- */ -struct Directory *openDirectory(char *dir_name) +Directory *openDirectory(char *dir_name) { - struct Directory *dir = checked_calloc(sizeof(struct Directory)); + Directory *dir = checked_calloc(sizeof(Directory)); dir->dir = opendir(dir_name); @@ -1931,7 +2033,7 @@ struct Directory *openDirectory(char *dir_name) return NULL; } -int closeDirectory(struct Directory *dir) +int closeDirectory(Directory *dir) { if (dir == NULL) return -1; @@ -1955,7 +2057,7 @@ int closeDirectory(struct Directory *dir) return result; } -struct DirectoryEntry *readDirectory(struct Directory *dir) +DirectoryEntry *readDirectory(Directory *dir) { if (dir->dir_entry) freeDirectoryEntry(dir->dir_entry); @@ -1967,14 +2069,12 @@ struct DirectoryEntry *readDirectory(struct Directory *dir) { char line[MAX_LINE_LEN]; char *line_ptr = line; - char *last_line_ptr = line_ptr; int num_bytes_read = 0; - while (num_bytes_read < MAX_LINE_LEN && + while (num_bytes_read < MAX_LINE_LEN - 1 && SDL_RWread(dir->asset_toc_file, line_ptr, 1, 1) == 1 && *line_ptr != '\n') { - last_line_ptr = line_ptr; line_ptr++; num_bytes_read++; } @@ -1984,7 +2084,7 @@ struct DirectoryEntry *readDirectory(struct Directory *dir) if (strlen(line) == 0) return NULL; - dir->dir_entry = checked_calloc(sizeof(struct DirectoryEntry)); + dir->dir_entry = checked_calloc(sizeof(DirectoryEntry)); dir->dir_entry->is_directory = FALSE; if (line[strlen(line) - 1] = '/') @@ -2006,7 +2106,7 @@ struct DirectoryEntry *readDirectory(struct Directory *dir) if (dir_entry == NULL) return NULL; - dir->dir_entry = checked_calloc(sizeof(struct DirectoryEntry)); + 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); @@ -2020,7 +2120,7 @@ struct DirectoryEntry *readDirectory(struct Directory *dir) return dir->dir_entry; } -void freeDirectoryEntry(struct DirectoryEntry *dir_entry) +void freeDirectoryEntry(DirectoryEntry *dir_entry) { if (dir_entry == NULL) return; diff --git a/src/libgame/misc.h b/src/libgame/misc.h index 12c28c32..431d5913 100644 --- a/src/libgame/misc.h +++ b/src/libgame/misc.h @@ -78,25 +78,37 @@ /* structure definitions */ -struct DirectoryEntry +typedef struct +{ + char *filename; + FILE *file; + boolean end_of_file; + +#if defined(PLATFORM_ANDROID) + boolean file_is_asset; + SDL_RWops *asset_file; +#endif +} File; + +typedef struct { boolean is_directory; char *basename; char *filename; -}; +} DirectoryEntry; -struct Directory +typedef struct { char *filename; DIR *dir; - struct DirectoryEntry *dir_entry; + DirectoryEntry *dir_entry; #if defined(PLATFORM_ANDROID) boolean directory_is_asset; SDL_RWops *asset_toc_file; char *current_entry; #endif -}; +} Directory; /* function definitions */ @@ -212,10 +224,15 @@ void deleteNodeFromList(ListNode **, char *, void (*function)(void *)); ListNode *getNodeFromKey(ListNode *, char *); int getNumNodes(ListNode *); -struct Directory *openDirectory(char *); -int closeDirectory(struct Directory *); -struct DirectoryEntry *readDirectory(struct Directory *); -void freeDirectoryEntry(struct DirectoryEntry *); +File *openFile(char *, char *); +int closeFile(File *); +int checkEndOfFile(File *); +char *getStringFromFile(File *, char *, int); + +Directory *openDirectory(char *); +int closeDirectory(Directory *); +DirectoryEntry *readDirectory(Directory *); +void freeDirectoryEntry(DirectoryEntry *); boolean fileExists(char *); boolean FileIsGraphic(char *); diff --git a/src/libgame/setup.c b/src/libgame/setup.c index 921ffdad..b9c9899c 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -1918,6 +1918,196 @@ boolean getTokenValueFromSetupLine(char *line, char **token, char **value) } #if 1 + +#if 1 +static boolean loadSetupFileData(void *setup_file_data, char *filename, + boolean top_recursion_level, boolean is_hash) +{ + static SetupFileHash *include_filename_hash = NULL; + char line[MAX_LINE_LEN], line_raw[MAX_LINE_LEN], previous_line[MAX_LINE_LEN]; + char *token, *value, *line_ptr; + void *insert_ptr = NULL; + boolean read_continued_line = FALSE; + File *file; + int line_nr = 0, token_count = 0, include_count = 0; + +#if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING + token_value_separator_warning = FALSE; +#endif + +#if CHECK_TOKEN__WARN_IF_ALREADY_EXISTS_IN_HASH + token_already_exists_warning = FALSE; +#endif + +#if 0 + Error(ERR_INFO, "===== opening file: '%s'", filename); +#endif + + if (!(file = openFile(filename, MODE_READ))) + { + Error(ERR_WARN, "cannot open configuration file '%s'", filename); + + return FALSE; + } + +#if 0 + Error(ERR_INFO, "===== reading file: '%s'", filename); +#endif + + /* use "insert pointer" to store list end for constant insertion complexity */ + if (!is_hash) + insert_ptr = setup_file_data; + + /* on top invocation, create hash to mark included files (to prevent loops) */ + if (top_recursion_level) + include_filename_hash = newSetupFileHash(); + + /* mark this file as already included (to prevent including it again) */ + setHashEntry(include_filename_hash, getBaseNamePtr(filename), "true"); + + while (!checkEndOfFile(file)) + { + /* read next line of input file */ + if (!getStringFromFile(file, line, MAX_LINE_LEN)) + break; + +#if 0 + Error(ERR_INFO, "got line: '%s'", line); +#endif + + /* check if line was completely read and is terminated by line break */ + if (strlen(line) > 0 && line[strlen(line) - 1] == '\n') + line_nr++; + + /* cut trailing line break (this can be newline and/or carriage return) */ + for (line_ptr = &line[strlen(line)]; line_ptr >= line; line_ptr--) + if ((*line_ptr == '\n' || *line_ptr == '\r') && *(line_ptr + 1) == '\0') + *line_ptr = '\0'; + + /* copy raw input line for later use (mainly debugging output) */ + strcpy(line_raw, line); + + if (read_continued_line) + { +#if 0 + /* !!! ??? WHY ??? !!! */ + /* cut leading whitespaces from input line */ + for (line_ptr = line; *line_ptr; line_ptr++) + if (*line_ptr != ' ' && *line_ptr != '\t') + break; +#endif + + /* append new line to existing line, if there is enough space */ + if (strlen(previous_line) + strlen(line_ptr) < MAX_LINE_LEN) + strcat(previous_line, line_ptr); + + strcpy(line, previous_line); /* copy storage buffer to line */ + + read_continued_line = FALSE; + } + + /* if the last character is '\', continue at next line */ + if (strlen(line) > 0 && line[strlen(line) - 1] == '\\') + { + line[strlen(line) - 1] = '\0'; /* cut off trailing backslash */ + strcpy(previous_line, line); /* copy line to storage buffer */ + + read_continued_line = TRUE; + + continue; + } + + if (!getTokenValueFromSetupLineExt(line, &token, &value, filename, + line_raw, line_nr, FALSE)) + continue; + + if (*token) + { + if (strEqual(token, "include")) + { + if (getHashEntry(include_filename_hash, value) == NULL) + { + char *basepath = getBasePath(filename); + char *basename = getBaseName(value); + char *filename_include = getPath2(basepath, basename); + +#if 0 + Error(ERR_INFO, "[including file '%s']", filename_include); +#endif + + loadSetupFileData(setup_file_data, filename_include, FALSE, is_hash); + + free(basepath); + free(basename); + free(filename_include); + + include_count++; + } + else + { + Error(ERR_WARN, "ignoring already processed file '%s'", value); + } + } + else + { + if (is_hash) + { +#if CHECK_TOKEN__WARN_IF_ALREADY_EXISTS_IN_HASH + char *old_value = + getHashEntry((SetupFileHash *)setup_file_data, token); + + if (old_value != NULL) + { + if (!token_already_exists_warning) + { + Error(ERR_INFO_LINE, "-"); + Error(ERR_WARN, "duplicate token(s) found in config file:"); + Error(ERR_INFO, "- config file: '%s'", filename); + + token_already_exists_warning = TRUE; + } + + Error(ERR_INFO, "- token: '%s' (in line %d)", token, line_nr); + Error(ERR_INFO, " old value: '%s'", old_value); + Error(ERR_INFO, " new value: '%s'", value); + } +#endif + + setHashEntry((SetupFileHash *)setup_file_data, token, value); + } + else + { + insert_ptr = addListEntry((SetupFileList *)insert_ptr, token, value); + } + + token_count++; + } + } + } + + closeFile(file); + +#if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING + if (token_value_separator_warning) + Error(ERR_INFO_LINE, "-"); +#endif + +#if CHECK_TOKEN__WARN_IF_ALREADY_EXISTS_IN_HASH + if (token_already_exists_warning) + Error(ERR_INFO_LINE, "-"); +#endif + + if (token_count == 0 && include_count == 0) + Error(ERR_WARN, "configuration file '%s' is empty", filename); + + if (top_recursion_level) + freeSetupFileHash(include_filename_hash); + + return TRUE; +} + +#else + static boolean loadSetupFileData(void *setup_file_data, char *filename, boolean top_recursion_level, boolean is_hash) { @@ -2092,6 +2282,8 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename, return TRUE; } +#endif + #else static boolean loadSetupFileData(void *setup_file_data, char *filename, @@ -3229,6 +3421,97 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first, return TRUE; } +#if 1 +static void LoadLevelInfoFromLevelDir(TreeInfo **node_first, + TreeInfo *node_parent, + char *level_directory) +{ + Directory *dir; + DirectoryEntry *dir_entry; + boolean valid_entry_found = FALSE; + +#if 0 + Error(ERR_INFO, "looking for levels in '%s' ...", level_directory); +#endif + + if ((dir = openDirectory(level_directory)) == NULL) + { + Error(ERR_WARN, "cannot read level directory '%s'", level_directory); + + return; + } + +#if 0 + Error(ERR_INFO, "opening '%s' succeeded ...", level_directory); +#endif + + while ((dir_entry = readDirectory(dir)) != NULL) /* loop all entries */ + { + struct stat file_status; + char *directory_name = dir_entry->basename; + char *directory_path = getPath2(level_directory, directory_name); + +#if 0 + Error(ERR_INFO, "checking entry '%s' ...", directory_name); +#endif + + /* skip entries for current and parent directory */ + if (strEqual(directory_name, ".") || + strEqual(directory_name, "..")) + { + free(directory_path); + + continue; + } + +#if 1 + /* find out if directory entry is itself a directory */ + if (!dir_entry->is_directory) /* not a directory */ + { + free(directory_path); + + continue; + } +#else + /* find out if directory entry is itself a directory */ + if (stat(directory_path, &file_status) != 0 || /* cannot stat file */ + (file_status.st_mode & S_IFMT) != S_IFDIR) /* not a directory */ + { + free(directory_path); + + continue; + } +#endif + + free(directory_path); + + if (strEqual(directory_name, GRAPHICS_DIRECTORY) || + strEqual(directory_name, SOUNDS_DIRECTORY) || + strEqual(directory_name, MUSIC_DIRECTORY)) + continue; + + valid_entry_found |= LoadLevelInfoFromLevelConf(node_first, node_parent, + level_directory, + directory_name); + } + + closeDirectory(dir); + + /* special case: top level directory may directly contain "levelinfo.conf" */ + if (node_parent == NULL && !valid_entry_found) + { + /* check if this directory directly contains a file "levelinfo.conf" */ + valid_entry_found |= LoadLevelInfoFromLevelConf(node_first, node_parent, + level_directory, "."); + } + + if (!valid_entry_found) + Error(ERR_WARN, "cannot find any valid level series in directory '%s'", + level_directory); +} + +#else + static void LoadLevelInfoFromLevelDir(TreeInfo **node_first, TreeInfo *node_parent, char *level_directory) @@ -3248,12 +3531,20 @@ static void LoadLevelInfoFromLevelDir(TreeInfo **node_first, return; } +#if 1 + Error(ERR_INFO, "opening '%s' succeeded ...", level_directory); +#endif + while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */ { struct stat file_status; char *directory_name = dir_entry->d_name; char *directory_path = getPath2(level_directory, directory_name); +#if 1 + Error(ERR_INFO, "checking entry '%s' ...", directory_name); +#endif + /* skip entries for current and parent directory */ if (strEqual(directory_name, ".") || strEqual(directory_name, "..")) @@ -3296,6 +3587,7 @@ static void LoadLevelInfoFromLevelDir(TreeInfo **node_first, Error(ERR_WARN, "cannot find any valid level series in directory '%s'", level_directory); } +#endif boolean AdjustGraphicsForEMC() { @@ -4009,6 +4301,64 @@ void SaveLevelSetup_LastSeries_Deactivate() SaveLevelSetup_LastSeries_Ext(TRUE); } +#if 1 + +static void checkSeriesInfo() +{ + static char *level_directory = NULL; + Directory *dir; +#if 0 + DirectoryEntry *dir_entry; +#endif + + /* check for more levels besides the 'levels' field of 'levelinfo.conf' */ + + level_directory = getPath2((leveldir_current->in_user_dir ? + getUserLevelDir(NULL) : + options.level_directory), + leveldir_current->fullpath); + + if ((dir = openDirectory(level_directory)) == NULL) + { + Error(ERR_WARN, "cannot read level directory '%s'", level_directory); + + return; + } + +#if 0 + while ((dir_entry = readDirectory(dir)) != NULL) /* last directory entry */ + { + if (strlen(dir_entry->basename) > 4 && + dir_entry->basename[3] == '.' && + strEqual(&dir_entry->basename[4], LEVELFILE_EXTENSION)) + { + char levelnum_str[4]; + int levelnum_value; + + strncpy(levelnum_str, dir_entry->basename, 3); + levelnum_str[3] = '\0'; + + levelnum_value = atoi(levelnum_str); + + if (levelnum_value < leveldir_current->first_level) + { + Error(ERR_WARN, "additional level %d found", levelnum_value); + leveldir_current->first_level = levelnum_value; + } + else if (levelnum_value > leveldir_current->last_level) + { + Error(ERR_WARN, "additional level %d found", levelnum_value); + leveldir_current->last_level = levelnum_value; + } + } + } +#endif + + closeDirectory(dir); +} + +#else + static void checkSeriesInfo() { static char *level_directory = NULL; @@ -4063,6 +4413,8 @@ static void checkSeriesInfo() closedir(dir); } +#endif + void LoadLevelSetup_SeriesInfo() { char *filename; -- 2.34.1