/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
+* (c) 1995-2001 Artsoft Entertainment *
+* Holger Schemel *
+* Detmolder Strasse 189 *
+* 33604 Bielefeld *
+* Germany *
+* e-mail: info@artsoft.org *
*----------------------------------------------------------*
-* files.h *
+* files.c *
***********************************************************/
#include <ctype.h>
#include <dirent.h>
#include <sys/stat.h>
+#include "libgame/libgame.h"
+
#include "files.h"
#include "tools.h"
-#include "misc.h"
#include "tape.h"
#include "joystick.h"
-#define MAX_FILENAME_LEN 256 /* maximal filename length */
+#define MAX_FILENAME_LEN 256 /* maximal filename length */
#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 15 /* 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 /* 1.0 file version (old) */
+#define TAPE_HEADER_SIZE 20 /* size of tape file header */
+#define TAPE_HEADER_UNUSED 7 /* unused tape header bytes */
+
+#if 0
+#define FILE_VERSION_1_0 10 /* 1.0 file version (old) */
#define FILE_VERSION_1_2 12 /* 1.2 file version (still in use) */
-#define FILE_VERSION_1_4 14 /* 1.4 file version (new) */
+#define FILE_VERSION_1_4 14 /* 1.4 file version (new) */
+#endif
/* file identifier strings */
#define LEVEL_COOKIE "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.4"
#define TAPE_COOKIE_10 "ROCKSNDIAMONDS_LEVELREC_FILE_VERSION_1.0"
/* file names and filename extensions */
-#ifndef MSDOS
-#define USERDATA_DIRECTORY ".rocksndiamonds"
+#if !defined(PLATFORM_MSDOS)
#define LEVELSETUP_DIRECTORY "levelsetup"
#define SETUP_FILENAME "setup.conf"
#define LEVELSETUP_FILENAME "levelsetup.conf"
#define TAPEFILE_EXTENSION "tape"
#define SCOREFILE_EXTENSION "score"
#else
-#define USERDATA_DIRECTORY "userdata"
#define LEVELSETUP_DIRECTORY "lvlsetup"
#define SETUP_FILENAME "setup.cnf"
#define LEVELSETUP_FILENAME "lvlsetup.cnf"
#define SCOREFILE_EXTENSION "sco"
#endif
-#if defined(MSDOS) || defined(WIN32)
-#define ERROR_FILENAME "error.out"
-#endif
-
-#ifdef WIN32
+#if defined(PLATFORM_WIN32)
#ifndef S_IRGRP
#define S_IRGRP S_IRUSR
#endif
#ifndef S_IXOTH
#define S_IXOTH S_IXUSR
#endif
-#endif
+#endif /* PLATFORM_WIN32 */
/* file permissions for newly written files */
#define MODE_R_ALL (S_IRUSR | S_IRGRP | S_IROTH)
#define MODE_W_ALL (S_IWUSR | S_IWGRP | S_IWOTH)
#define MODE_X_ALL (S_IXUSR | S_IXGRP | S_IXOTH)
-#define USERDATA_DIR_MODE (MODE_R_ALL | MODE_X_ALL | S_IWUSR)
#define LEVEL_PERMS (MODE_R_ALL | MODE_W_ALL)
#define SCORE_PERMS LEVEL_PERMS
#define TAPE_PERMS LEVEL_PERMS
IS_LEVELCLASS_USER(n) ? 7 : \
9)
+static int getFileVersionFromCookieString(const char *cookie)
+{
+ const char *ptr_cookie1, *ptr_cookie2;
+ const char *pattern1 = "_FILE_VERSION_";
+ const char *pattern2 = "?.?";
+ const int len_cookie = strlen(cookie);
+ const int len_pattern1 = strlen(pattern1);
+ const int len_pattern2 = strlen(pattern2);
+ const int len_pattern = len_pattern1 + len_pattern2;
+ int version_major, version_minor;
+
+ if (len_cookie <= len_pattern)
+ return -1;
+
+ ptr_cookie1 = &cookie[len_cookie - len_pattern];
+ ptr_cookie2 = &cookie[len_cookie - len_pattern2];
+
+ if (strncmp(ptr_cookie1, pattern1, len_pattern1) != 0)
+ return -1;
+
+ if (ptr_cookie2[0] <= '0' || ptr_cookie2[0] >= '9' ||
+ ptr_cookie2[1] != '.' ||
+ ptr_cookie2[2] <= '0' || ptr_cookie2[2] >= '9')
+ return -1;
+
+ version_major = ptr_cookie2[0] - '0';
+ version_minor = ptr_cookie2[2] - '0';
+
+ return (version_major * 10 + version_minor);
+}
+
+boolean checkCookieString(const char *cookie, const char *template)
+{
+ const char *pattern = "_FILE_VERSION_?.?";
+ const int len_cookie = strlen(cookie);
+ const int len_template = strlen(template);
+ const int len_pattern = strlen(pattern);
+
+ if (len_cookie != len_template)
+ return FALSE;
+
+ if (strncmp(cookie, template, len_cookie - len_pattern) != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
char *getLevelClassDescription(struct LevelDirInfo *ldi)
{
int position = ldi->sort_priority / 100;
static void SaveUserLevelInfo(); /* for 'InitUserLevelDir()' */
static char *getSetupLine(char *, int); /* for 'SaveUserLevelInfo()' */
-char *getUserDataDir()
-{
- static char *userdata_dir = NULL;
-
- if (!userdata_dir)
- {
- char *home_dir = getHomeDir();
- char *data_dir = USERDATA_DIRECTORY;
-
- userdata_dir = getPath2(home_dir, data_dir);
- }
-
- return userdata_dir;
-}
-
static char *getSetupDir()
{
return getUserDataDir();
return filename;
}
-static void createDirectory(char *dir, char *text)
-{
- if (access(dir, F_OK) != 0)
-#ifdef WIN32
- if (mkdir(dir) != 0)
-#else
- if (mkdir(dir, USERDATA_DIR_MODE) != 0)
-#endif
- Error(ERR_WARN, "cannot create %s directory '%s'", text, dir);
-}
-
-static void InitUserDataDirectory()
-{
- createDirectory(getUserDataDir(), "user data");
-}
-
static void InitTapeDirectory(char *level_subdir)
{
createDirectory(getUserDataDir(), "user data");
{
int i, x, y;
+ level.file_version = FILE_VERSION_ACTUAL;
+ level.game_version = GAME_VERSION_ACTUAL;
+
lev_fieldx = level.fieldx = STD_LEV_FIELDX;
lev_fieldy = level.fieldy = STD_LEV_FIELDY;
char cookie[MAX_LINE_LEN];
char chunk[CHUNK_ID_LEN + 1];
boolean encoding_16bit = FALSE; /* default: maximal 256 elements */
- int file_version = FILE_VERSION_1_4; /* last version of level files */
+ int file_version = FILE_VERSION_ACTUAL;
int chunk_length;
FILE *file;
/* always start with reliable default values */
setLevelInfoToDefaults();
- if (!(file = fopen(filename, "r")))
+ if (!(file = fopen(filename, MODE_READ)))
{
Error(ERR_WARN, "cannot read level '%s' - creating new level", filename);
return;
if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
cookie[strlen(cookie) - 1] = '\0';
+#if 0
if (strcmp(cookie, LEVEL_COOKIE_10) == 0) /* old 1.0 level format */
file_version = FILE_VERSION_1_0;
else if (strcmp(cookie, LEVEL_COOKIE_12) == 0)/* 1.2 (8 bit) level format */
fclose(file);
return;
}
+#else
+ if (!checkCookieString(cookie, LEVEL_COOKIE)) /* unknown file format */
+ {
+ Error(ERR_WARN, "unknown format of level file '%s'", filename);
+ fclose(file);
+ return;
+ }
+
+ file_version = getFileVersionFromCookieString(cookie);
+#endif
+
+ level.file_version = file_version;
/* read chunk "HEAD" */
if (file_version >= FILE_VERSION_1_2)
fclose(file);
- /* player was faster than monsters in pre-1.0 levels */
- if (file_version == FILE_VERSION_1_0 &&
- IS_LEVELCLASS_CONTRIBUTION(leveldir_current))
+ if (IS_LEVELCLASS_CONTRIBUTION(leveldir_current) ||
+ IS_LEVELCLASS_USER(leveldir_current))
{
- Error(ERR_WARN, "level file '%s' has version number 1.0", filename);
- Error(ERR_WARN, "using high speed movement for player");
- level.double_speed = TRUE;
+ /* for user contributed and private levels, use the version of
+ the game engine the levels were created for */
+ level.game_version = file_version;
+
+ /* player was faster than monsters in pre-1.0 levels */
+ if (file_version == FILE_VERSION_1_0)
+ {
+ Error(ERR_WARN, "level file '%s' has version number 1.0", filename);
+ Error(ERR_WARN, "using high speed movement for player");
+ level.double_speed = TRUE;
+ }
+ }
+ else
+ {
+ /* always use the latest version of the game engine for all but
+ user contributed and private levels */
+ level.game_version = GAME_VERSION_ACTUAL;
}
/* determine border element for this level */
char *oldest_possible_cookie;
FILE *file;
- if (!(file = fopen(filename, "w")))
+ if (!(file = fopen(filename, MODE_WRITE)))
{
Error(ERR_WARN, "cannot save level file '%s'", filename);
return;
char chunk[CHUNK_ID_LEN + 1];
FILE *file;
int num_participating_players;
- int file_version = FILE_VERSION_1_2; /* last version of tape files */
+ int file_version = FILE_VERSION_ACTUAL; /* last version of tape files */
int chunk_length;
/* always start with reliable default values (empty tape) */
+ tape.file_version = FILE_VERSION_ACTUAL;
+ tape.game_version = GAME_VERSION_ACTUAL;
TapeErase();
/* default values (also for pre-1.2 tapes) with only the first player */
/* at least one (default: the first) player participates in every tape */
num_participating_players = 1;
- if (!(file = fopen(filename, "r")))
+ if (!(file = fopen(filename, MODE_READ)))
return;
/* check file identifier */
if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
cookie[strlen(cookie) - 1] = '\0';
+#if 0
if (strcmp(cookie, TAPE_COOKIE_10) == 0) /* old 1.0 tape format */
file_version = FILE_VERSION_1_0;
else if (strcmp(cookie, TAPE_COOKIE) != 0) /* unknown tape format */
fclose(file);
return;
}
+#else
+ if (!checkCookieString(cookie, TAPE_COOKIE)) /* unknown file format */
+ {
+ Error(ERR_WARN, "unknown format of tape file '%s'", filename);
+ fclose(file);
+ return;
+ }
+
+ file_version = getFileVersionFromCookieString(cookie);
+#endif
+
+ tape.file_version = file_version;
+ tape.game_version = file_version;
/* read chunk "HEAD" */
if (file_version >= FILE_VERSION_1_2)
}
}
- if (!(file = fopen(filename, "w")))
+ if (!(file = fopen(filename, MODE_WRITE)))
{
Error(ERR_WARN, "cannot save level recording file '%s'", filename);
return;
highscore[i].Score = 0;
}
- if (!(file = fopen(filename, "r")))
+ if (!(file = fopen(filename, MODE_READ)))
return;
/* check file identifier */
if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
cookie[strlen(cookie) - 1] = '\0';
+#if 0
if (strcmp(cookie, SCORE_COOKIE) != 0)
{
Error(ERR_WARN, "wrong file identifier of score file '%s'", filename);
fclose(file);
return;
}
+#else
+ if (!checkCookieString(cookie, SCORE_COOKIE)) /* unknown file format */
+ {
+ Error(ERR_WARN, "unknown format of score file '%s'", filename);
+ fclose(file);
+ return;
+ }
+#endif
for(i=0; i<MAX_SCORE_ENTRIES; i++)
{
InitScoreDirectory(leveldir_current->filename);
- if (!(file = fopen(filename, "w")))
+ if (!(file = fopen(filename, MODE_WRITE)))
{
Error(ERR_WARN, "cannot save score for level %d", level_nr);
return;
FILE *file;
- if (!(file = fopen(filename, "r")))
+ if (!(file = fopen(filename, MODE_READ)))
{
Error(ERR_WARN, "cannot open configuration file '%s'", filename);
return NULL;
si->input[i].joy.ylower = JOYSTICK_YLOWER;
si->input[i].joy.snap = (i == 0 ? JOY_BUTTON_1 : 0);
si->input[i].joy.bomb = (i == 0 ? JOY_BUTTON_2 : 0);
- si->input[i].key.left = (i == 0 ? DEFAULT_KEY_LEFT : KEY_UNDEFINED);
- si->input[i].key.right = (i == 0 ? DEFAULT_KEY_RIGHT : KEY_UNDEFINED);
- si->input[i].key.up = (i == 0 ? DEFAULT_KEY_UP : KEY_UNDEFINED);
- si->input[i].key.down = (i == 0 ? DEFAULT_KEY_DOWN : KEY_UNDEFINED);
- si->input[i].key.snap = (i == 0 ? DEFAULT_KEY_SNAP : KEY_UNDEFINED);
- si->input[i].key.bomb = (i == 0 ? DEFAULT_KEY_BOMB : KEY_UNDEFINED);
+ si->input[i].key.left = (i == 0 ? DEFAULT_KEY_LEFT : KSYM_UNDEFINED);
+ si->input[i].key.right = (i == 0 ? DEFAULT_KEY_RIGHT : KSYM_UNDEFINED);
+ si->input[i].key.up = (i == 0 ? DEFAULT_KEY_UP : KSYM_UNDEFINED);
+ si->input[i].key.down = (i == 0 ? DEFAULT_KEY_DOWN : KSYM_UNDEFINED);
+ si->input[i].key.snap = (i == 0 ? DEFAULT_KEY_SNAP : KSYM_UNDEFINED);
+ si->input[i].key.bomb = (i == 0 ? DEFAULT_KEY_BOMB : KSYM_UNDEFINED);
}
}
filename = getPath2(getUserLevelDir(getLoginName()), LEVELINFO_FILENAME);
- if (!(file = fopen(filename, "w")))
+ if (!(file = fopen(filename, MODE_WRITE)))
{
Error(ERR_WARN, "cannot write level info file '%s'", filename);
free(filename);
filename = getPath2(getSetupDir(), SETUP_FILENAME);
- if (!(file = fopen(filename, "w")))
+ if (!(file = fopen(filename, MODE_WRITE)))
{
Error(ERR_WARN, "cannot write setup file '%s'", filename);
free(filename);
filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
- if (!(file = fopen(filename, "w")))
+ if (!(file = fopen(filename, MODE_WRITE)))
{
Error(ERR_WARN, "cannot write setup file '%s'", filename);
free(filename);
filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME);
- if (!(file = fopen(filename, "w")))
+ if (!(file = fopen(filename, MODE_WRITE)))
{
Error(ERR_WARN, "cannot write setup file '%s'", filename);
free(filename);
chmod(filename, SETUP_PERMS);
}
-
-#if defined(MSDOS) || defined(WIN32)
-void initErrorFile()
-{
- char *filename;
-
- InitUserDataDirectory();
-
- filename = getPath2(getUserDataDir(), ERROR_FILENAME);
- unlink(filename);
- free(filename);
-}
-
-FILE *openErrorFile()
-{
- char *filename;
- FILE *error_file;
-
- 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
+/* LocalWords: Rocks'n
+ */