X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Ffiles.c;h=71d01e945fd9f35c3d38ee7736d2e38e2f1d44a0;hp=daaaaa72dcef77d08db0378f12d236d9b90e75a7;hb=3ae3dff29ac1a6022b1e5af414ba2c99391148c8;hpb=19e168a132d1c0543a13cbf9495f579c137dea94 diff --git a/src/files.c b/src/files.c index daaaaa72..71d01e94 100644 --- a/src/files.c +++ b/src/files.c @@ -26,7 +26,7 @@ #define MAX_LINE_LEN 1000 /* maximal input line length */ #define CHUNK_ID_LEN 4 /* IFF style chunk id length */ #define LEVEL_HEADER_SIZE 80 /* size of level file header */ -#define LEVEL_HEADER_UNUSED 18 /* unused level header bytes */ +#define LEVEL_HEADER_UNUSED 17 /* unused level header bytes */ #define TAPE_HEADER_SIZE 20 /* size of tape file header */ #define TAPE_HEADER_UNUSED 7 /* unused tape header bytes */ #define FILE_VERSION_1_0 10 /* old 1.0 file version */ @@ -58,8 +58,9 @@ #define LEVELSETUP_FILENAME "lvlsetup.cnf" #define LEVELINFO_FILENAME "lvlinfo.cnf" #define LEVELFILE_EXTENSION "lvl" -#define TAPEFILE_EXTENSION "rec" +#define TAPEFILE_EXTENSION "tap" #define SCOREFILE_EXTENSION "sco" +#define ERROR_FILENAME "error.out" #endif /* file permissions for newly written files */ @@ -72,6 +73,46 @@ #define TAPE_PERMS LEVEL_PERMS #define SETUP_PERMS LEVEL_PERMS +/* sort priorities of level series (also used as level series classes) */ +#define LEVELCLASS_TUTORIAL_START 10 +#define LEVELCLASS_TUTORIAL_END 99 +#define LEVELCLASS_CLASSICS_START 100 +#define LEVELCLASS_CLASSICS_END 199 +#define LEVELCLASS_CONTRIBUTION_START 200 +#define LEVELCLASS_CONTRIBUTION_END 299 +#define LEVELCLASS_USER_START 300 +#define LEVELCLASS_USER_END 399 + +#define LEVELCLASS_TUTORIAL LEVELCLASS_TUTORIAL_START +#define LEVELCLASS_CLASSICS LEVELCLASS_CLASSICS_START +#define LEVELCLASS_CONTRIBUTION LEVELCLASS_CONTRIBUTION_START +#define LEVELCLASS_USER LEVELCLASS_USER_START +#define LEVELCLASS_UNDEFINED 999 + +#define IS_LEVELCLASS_TUTORIAL(n) \ + (leveldir[n].sort_priority >= LEVELCLASS_TUTORIAL_START && \ + leveldir[n].sort_priority <= LEVELCLASS_TUTORIAL_END) +#define IS_LEVELCLASS_CLASSICS(n) \ + (leveldir[n].sort_priority >= LEVELCLASS_CLASSICS_START && \ + leveldir[n].sort_priority <= LEVELCLASS_CLASSICS_END) +#define IS_LEVELCLASS_CONTRIBUTION(n) \ + (leveldir[n].sort_priority >= LEVELCLASS_CONTRIBUTION_START && \ + leveldir[n].sort_priority <= LEVELCLASS_CONTRIBUTION_END) +#define IS_LEVELCLASS_USER(n) \ + (leveldir[n].sort_priority >= LEVELCLASS_USER_START && \ + leveldir[n].sort_priority <= LEVELCLASS_USER_END) + +#define LEVELCLASS(n) (IS_LEVELCLASS_TUTORIAL(n) ? LEVELCLASS_TUTORIAL : \ + IS_LEVELCLASS_CLASSICS(n) ? LEVELCLASS_CLASSICS : \ + IS_LEVELCLASS_CONTRIBUTION(n) ? LEVELCLASS_CONTRIBUTION : \ + IS_LEVELCLASS_USER(n) ? LEVELCLASS_USER : \ + LEVELCLASS_UNDEFINED) + +#define LEVELCOLOR(n) (IS_LEVELCLASS_TUTORIAL(n) ? FC_BLUE : \ + IS_LEVELCLASS_CLASSICS(n) ? FC_YELLOW : \ + IS_LEVELCLASS_CONTRIBUTION(n) ? FC_GREEN : \ + IS_LEVELCLASS_USER(n) ? FC_RED : FC_BLUE) + static void SaveUserLevelInfo(); /* for 'InitUserLevelDir()' */ static char *getSetupLine(char *, int); /* for 'SaveUserLevelInfo()' */ @@ -80,7 +121,7 @@ static char *getGlobalDataDir() return GAME_DIR; } -static char *getUserDataDir() +char *getUserDataDir() { static char *userdata_dir = NULL; @@ -154,7 +195,7 @@ static char *getScoreDir(char *level_subdir) static char *getLevelFilename(int nr) { static char *filename = NULL; - char basename[20 + strlen(LEVELFILE_EXTENSION)]; + char basename[MAX_FILENAME_LEN]; if (filename != NULL) free(filename); @@ -172,7 +213,7 @@ static char *getLevelFilename(int nr) static char *getTapeFilename(int nr) { static char *filename = NULL; - char basename[20 + strlen(LEVELFILE_EXTENSION)]; + char basename[MAX_FILENAME_LEN]; if (filename != NULL) free(filename); @@ -186,7 +227,7 @@ static char *getTapeFilename(int nr) static char *getScoreFilename(int nr) { static char *filename = NULL; - char basename[20 + strlen(LEVELFILE_EXTENSION)]; + char basename[MAX_FILENAME_LEN]; if (filename != NULL) free(filename); @@ -234,6 +275,27 @@ static void InitUserLevelDirectory(char *level_subdir) } } +static void getFileChunk(FILE *file, char *chunk_buffer, int *chunk_length) +{ + fgets(chunk_buffer, CHUNK_ID_LEN + 1, file); + + *chunk_length = + (fgetc(file) << 24) | + (fgetc(file) << 16) | + (fgetc(file) << 8) | + (fgetc(file) << 0); +} + +static void putFileChunk(FILE *file, char *chunk_name, int chunk_length) +{ + fputs(chunk_name, file); + + fputc((chunk_length >> 24) & 0xff, file); + fputc((chunk_length >> 16) & 0xff, file); + fputc((chunk_length >> 8) & 0xff, file); + fputc((chunk_length >> 0) & 0xff, file); +} + static void setLevelInfoToDefaults() { int i, x, y; @@ -241,8 +303,8 @@ static void setLevelInfoToDefaults() lev_fieldx = level.fieldx = STD_LEV_FIELDX; lev_fieldy = level.fieldy = STD_LEV_FIELDY; - for(x=0; x= FILE_VERSION_1_2) { - /* first check header chunk identifier and chunk length */ - fgets(chunk, CHUNK_ID_LEN + 1, file); - chunk_length = - (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file); + getFileChunk(file, chunk, &chunk_length); if (strcmp(chunk, "HEAD") || chunk_length != LEVEL_HEADER_SIZE) { Error(ERR_WARN, "wrong 'HEAD' chunk of level file '%s'", filename); @@ -321,22 +420,33 @@ void LoadLevel(int level_nr) level.time = (fgetc(file)<<8) | fgetc(file); level.edelsteine = (fgetc(file)<<8) | fgetc(file); - for(i=0; i= FILE_VERSION_1_2) { + getFileChunk(file, chunk, &chunk_length); + + /* look for optional author chunk */ + if (strcmp(chunk, "AUTH") == 0 && chunk_length == MAX_LEVEL_AUTHOR_LEN) + { + for(i=0; i> 24) & 0xff, file); - fputc((chunk_length >> 16) & 0xff, file); - fputc((chunk_length >> 8) & 0xff, file); - fputc((chunk_length >> 0) & 0xff, file); + putFileChunk(file, "HEAD", LEVEL_HEADER_SIZE); fputc(level.fieldx, file); fputc(level.fieldy, file); @@ -398,7 +537,7 @@ void SaveLevel(int level_nr) fputc(level.edelsteine / 256, file); fputc(level.edelsteine % 256, file); - for(i=0; i> 24) & 0xff, file); - fputc((chunk_length >> 16) & 0xff, file); - fputc((chunk_length >> 8) & 0xff, file); - fputc((chunk_length >> 0) & 0xff, file); + for(i=0; i 0) - continue; - if (tape.player_participates[j]) tape.pos[i].action[j] = fgetc(file); } @@ -804,9 +962,11 @@ void SaveScore(int level_nr) /* level directory info */ #define LEVELINFO_TOKEN_NAME 29 -#define LEVELINFO_TOKEN_LEVELS 30 -#define LEVELINFO_TOKEN_SORT_PRIORITY 31 -#define LEVELINFO_TOKEN_READONLY 32 +#define LEVELINFO_TOKEN_AUTHOR 30 +#define LEVELINFO_TOKEN_LEVELS 31 +#define LEVELINFO_TOKEN_FIRST_LEVEL 32 +#define LEVELINFO_TOKEN_SORT_PRIORITY 33 +#define LEVELINFO_TOKEN_READONLY 34 #define FIRST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_PLAYER_NAME #define LAST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_TEAM_MODE @@ -868,7 +1028,9 @@ static struct /* level directory info */ { TYPE_STRING, &ldi.name, "name" }, + { TYPE_STRING, &ldi.author, "author" }, { TYPE_INTEGER, &ldi.levels, "levels" }, + { TYPE_INTEGER, &ldi.first_level, "first_level" }, { TYPE_INTEGER, &ldi.sort_priority, "sort_priority" }, { TYPE_BOOLEAN, &ldi.readonly, "readonly" } }; @@ -1041,7 +1203,7 @@ static struct SetupFileList *loadSetupFileList(char *filename) /* cut trailing comment or whitespace from input line */ for (line_ptr = line; *line_ptr; line_ptr++) { - if (*line_ptr == '#' || *line_ptr == '\n') + if (*line_ptr == '#' || *line_ptr == '\n' || *line_ptr == '\r') { *line_ptr = '\0'; break; @@ -1130,9 +1292,11 @@ static void checkSetupFileListIdentifier(struct SetupFileList *setup_file_list, static void setLevelDirInfoToDefaults(struct LevelDirInfo *ldi) { - ldi->name = getStringCopy("non-existing"); + ldi->name = getStringCopy(ANONYMOUS_NAME); + ldi->author = getStringCopy(ANONYMOUS_NAME); ldi->levels = 0; - ldi->sort_priority = 999; /* default: least priority */ + ldi->first_level = 0; + ldi->sort_priority = LEVELCLASS_UNDEFINED; /* default: least priority */ ldi->readonly = TRUE; } @@ -1143,16 +1307,16 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->player_name = getStringCopy(getLoginName()); si->sound = TRUE; - si->sound_loops = FALSE; - si->sound_music = FALSE; - si->sound_simple = FALSE; + si->sound_loops = TRUE; + si->sound_music = TRUE; + si->sound_simple = TRUE; si->toons = TRUE; si->double_buffering = TRUE; si->direct_draw = !si->double_buffering; - si->scroll_delay = FALSE; + si->scroll_delay = TRUE; si->soft_scrolling = TRUE; si->fading = FALSE; - si->autorecord = FALSE; + si->autorecord = TRUE; si->quick_doors = FALSE; for (i=0; i highest_level_nr) - last_level_nr = highest_level_nr; + if (last_level_nr < leveldir[level_series_nr].first_level) + last_level_nr = leveldir[level_series_nr].first_level; + if (last_level_nr > leveldir[level_series_nr].last_level) + last_level_nr = leveldir[level_series_nr].last_level; } return last_level_nr; @@ -1354,8 +1516,12 @@ static int LoadLevelInfoFromLevelDir(char *level_directory, int start_entry) leveldir[current_entry] = ldi; leveldir[current_entry].filename = getStringCopy(dir_entry->d_name); + leveldir[current_entry].last_level = + leveldir[current_entry].first_level + + leveldir[current_entry].levels - 1; leveldir[current_entry].user_defined = (level_directory == options.level_directory ? FALSE : TRUE); + leveldir[current_entry].color = LEVELCOLOR(current_entry); freeSetupFileList(setup_file_list); current_entry++; @@ -1415,9 +1581,14 @@ static void SaveUserLevelInfo() return; } + /* always start with reliable default values */ + setLevelDirInfoToDefaults(&ldi); + ldi.name = getLoginName(); + ldi.author = getRealName(); ldi.levels = 100; - ldi.sort_priority = 300; + ldi.first_level = 1; + ldi.sort_priority = LEVELCLASS_USER_START; ldi.readonly = FALSE; fprintf(file, "%s\n\n", @@ -1663,3 +1834,63 @@ void SaveLevelSetup() chmod(filename, SETUP_PERMS); } + +#ifdef MSDOS +static boolean initErrorFile() +{ + char *filename; + FILE *error_file; + + InitUserDataDirectory(); + + filename = getPath2(getUserDataDir(), ERROR_FILENAME); + error_file = fopen(filename, "w"); + free(filename); + + if (error_file == NULL) + return FALSE; + + fclose(error_file); + + return TRUE; +} + +FILE *openErrorFile() +{ + static boolean first_access = TRUE; + char *filename; + FILE *error_file; + + if (first_access) + { + if (!initErrorFile()) + return NULL; + + first_access = FALSE; + } + + filename = getPath2(getUserDataDir(), ERROR_FILENAME); + error_file = fopen(filename, "a"); + free(filename); + + return error_file; +} + +void dumpErrorFile() +{ + char *filename; + FILE *error_file; + + filename = getPath2(getUserDataDir(), ERROR_FILENAME); + error_file = fopen(filename, "r"); + free(filename); + + if (error_file != NULL) + { + while (!feof(error_file)) + fputc(fgetc(error_file), stderr); + + fclose(error_file); + } +} +#endif