#include <ctype.h>
#include <dirent.h>
#include <sys/stat.h>
-#include <unistd.h>
+
+#include "libgame/libgame.h"
#include "files.h"
#include "tools.h"
-#include "misc.h"
#include "tape.h"
#include "joystick.h"
#define TAPE_COOKIE_10 "ROCKSNDIAMONDS_LEVELREC_FILE_VERSION_1.0"
/* file names and filename extensions */
-#ifndef MSDOS
+#if !defined(PLATFORM_MSDOS)
#define USERDATA_DIRECTORY ".rocksndiamonds"
#define LEVELSETUP_DIRECTORY "levelsetup"
#define SETUP_FILENAME "setup.conf"
#define LEVELFILE_EXTENSION "lvl"
#define TAPEFILE_EXTENSION "tap"
#define SCOREFILE_EXTENSION "sco"
+#endif
+
+#if !defined(PLATFORM_UNIX)
#define ERROR_FILENAME "error.out"
#endif
+#if defined(PLATFORM_WIN32)
+#ifndef S_IRGRP
+#define S_IRGRP S_IRUSR
+#endif
+#ifndef S_IROTH
+#define S_IROTH S_IRUSR
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP S_IWUSR
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH S_IWUSR
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP S_IXUSR
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH S_IXUSR
+#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)
static void createDirectory(char *dir, char *text)
{
if (access(dir, F_OK) != 0)
+#if defined(PLATFORM_WIN32)
+ if (mkdir(dir) != 0)
+#else
if (mkdir(dir, USERDATA_DIR_MODE) != 0)
+#endif
Error(ERR_WARN, "cannot create %s directory '%s'", text, dir);
}
switch (LEVELCLASS(leveldir_current))
{
case LEVELCLASS_TUTORIAL:
- strcpy(level.author, PROGRAM_AUTHOR_STRING);
- break;
+ strcpy(level.author, PROGRAM_AUTHOR_STRING);
+ break;
case LEVELCLASS_CONTRIBUTION:
- strncpy(level.author, leveldir_current->name,MAX_LEVEL_AUTHOR_LEN);
- level.author[MAX_LEVEL_AUTHOR_LEN] = '\0';
- break;
+ strncpy(level.author, leveldir_current->name,MAX_LEVEL_AUTHOR_LEN);
+ level.author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ break;
case LEVELCLASS_USER:
- strncpy(level.author, getRealName(), MAX_LEVEL_AUTHOR_LEN);
- level.author[MAX_LEVEL_AUTHOR_LEN] = '\0';
- break;
+ strncpy(level.author, getRealName(), MAX_LEVEL_AUTHOR_LEN);
+ level.author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ break;
default:
- /* keep default value */
- break;
+ /* keep default value */
+ break;
}
}
}
+static int checkLevelElement(int element)
+{
+ if (element >= EL_FIRST_RUNTIME_EL)
+ {
+ Error(ERR_WARN, "invalid level element %d", element);
+ element = EL_CHAR_FRAGE;
+ }
+
+ return element;
+}
+
void LoadLevel(int level_nr)
{
int i, x, y;
for(x=0; x<3; x++)
{
if (i < STD_ELEMENT_CONTENTS)
- level.yam_content[i][x][y] = fgetc(file);
+ level.yam_content[i][x][y] = checkLevelElement(fgetc(file));
else
level.yam_content[i][x][y] = EL_LEERRAUM;
}
level.amoeba_speed = fgetc(file);
level.time_magic_wall = fgetc(file);
level.time_wheel = fgetc(file);
- level.amoeba_content = fgetc(file);
+ level.amoeba_content = checkLevelElement(fgetc(file));
level.double_speed = (fgetc(file) == 1 ? TRUE : FALSE);
level.gravity = (fgetc(file) == 1 ? TRUE : FALSE);
for(y=0; y<3; y++)
for(x=0; x<3; x++)
level.yam_content[i][x][y] =
- (encoding_16bit ?
- getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN) :
- fgetc(file));
+ checkLevelElement(encoding_16bit ?
+ getFile16BitInteger(file,
+ BYTE_ORDER_BIG_ENDIAN) :
+ fgetc(file));
getFileChunk(file, chunk, &chunk_length, BYTE_ORDER_BIG_ENDIAN);
}
for(y=0; y<lev_fieldy; y++)
for(x=0; x<lev_fieldx; x++)
Feld[x][y] = Ur[x][y] =
- (encoding_16bit ?
- getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN) :
- fgetc(file));
+ checkLevelElement(encoding_16bit ?
+ getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN) :
+ fgetc(file));
fclose(file);
#define SETUP_TOKEN_TEAM_MODE 10
#define SETUP_TOKEN_HANDICAP 11
#define SETUP_TOKEN_TIME_LIMIT 12
+#define SETUP_TOKEN_FULLSCREEN 13
/* player setup */
-#define SETUP_TOKEN_USE_JOYSTICK 13
-#define SETUP_TOKEN_JOY_DEVICE_NAME 14
-#define SETUP_TOKEN_JOY_XLEFT 15
-#define SETUP_TOKEN_JOY_XMIDDLE 16
-#define SETUP_TOKEN_JOY_XRIGHT 17
-#define SETUP_TOKEN_JOY_YUPPER 18
-#define SETUP_TOKEN_JOY_YMIDDLE 19
-#define SETUP_TOKEN_JOY_YLOWER 20
-#define SETUP_TOKEN_JOY_SNAP 21
-#define SETUP_TOKEN_JOY_BOMB 22
-#define SETUP_TOKEN_KEY_LEFT 23
-#define SETUP_TOKEN_KEY_RIGHT 24
-#define SETUP_TOKEN_KEY_UP 25
-#define SETUP_TOKEN_KEY_DOWN 26
-#define SETUP_TOKEN_KEY_SNAP 27
-#define SETUP_TOKEN_KEY_BOMB 28
+#define SETUP_TOKEN_USE_JOYSTICK 14
+#define SETUP_TOKEN_JOY_DEVICE_NAME 15
+#define SETUP_TOKEN_JOY_XLEFT 16
+#define SETUP_TOKEN_JOY_XMIDDLE 17
+#define SETUP_TOKEN_JOY_XRIGHT 18
+#define SETUP_TOKEN_JOY_YUPPER 19
+#define SETUP_TOKEN_JOY_YMIDDLE 20
+#define SETUP_TOKEN_JOY_YLOWER 21
+#define SETUP_TOKEN_JOY_SNAP 22
+#define SETUP_TOKEN_JOY_BOMB 23
+#define SETUP_TOKEN_KEY_LEFT 24
+#define SETUP_TOKEN_KEY_RIGHT 25
+#define SETUP_TOKEN_KEY_UP 26
+#define SETUP_TOKEN_KEY_DOWN 27
+#define SETUP_TOKEN_KEY_SNAP 28
+#define SETUP_TOKEN_KEY_BOMB 29
/* level directory info */
-#define LEVELINFO_TOKEN_NAME 29
-#define LEVELINFO_TOKEN_NAME_SHORT 30
-#define LEVELINFO_TOKEN_NAME_SORTING 31
-#define LEVELINFO_TOKEN_AUTHOR 32
-#define LEVELINFO_TOKEN_IMPORTED_FROM 33
-#define LEVELINFO_TOKEN_LEVELS 34
-#define LEVELINFO_TOKEN_FIRST_LEVEL 35
-#define LEVELINFO_TOKEN_SORT_PRIORITY 36
-#define LEVELINFO_TOKEN_LEVEL_GROUP 37
-#define LEVELINFO_TOKEN_READONLY 38
+#define LEVELINFO_TOKEN_NAME 30
+#define LEVELINFO_TOKEN_NAME_SHORT 31
+#define LEVELINFO_TOKEN_NAME_SORTING 32
+#define LEVELINFO_TOKEN_AUTHOR 33
+#define LEVELINFO_TOKEN_IMPORTED_FROM 34
+#define LEVELINFO_TOKEN_LEVELS 35
+#define LEVELINFO_TOKEN_FIRST_LEVEL 36
+#define LEVELINFO_TOKEN_SORT_PRIORITY 37
+#define LEVELINFO_TOKEN_LEVEL_GROUP 38
+#define LEVELINFO_TOKEN_READONLY 39
#define FIRST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_PLAYER_NAME
-#define LAST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_TIME_LIMIT
+#define LAST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_FULLSCREEN
#define FIRST_PLAYER_SETUP_TOKEN SETUP_TOKEN_USE_JOYSTICK
#define LAST_PLAYER_SETUP_TOKEN SETUP_TOKEN_KEY_BOMB
#define TYPE_BOOLEAN 1
#define TYPE_SWITCH 2
-#define TYPE_KEYSYM 3
+#define TYPE_KEY 3
#define TYPE_INTEGER 4
#define TYPE_STRING 5
{ TYPE_SWITCH, &si.team_mode, "team_mode" },
{ TYPE_SWITCH, &si.handicap, "handicap" },
{ TYPE_SWITCH, &si.time_limit, "time_limit" },
+ { TYPE_SWITCH, &si.fullscreen, "fullscreen" },
/* player setup */
{ TYPE_BOOLEAN, &sii.use_joystick, ".use_joystick" },
{ TYPE_INTEGER, &sii.joy.ylower, ".joy.ylower" },
{ TYPE_INTEGER, &sii.joy.snap, ".joy.snap_field" },
{ TYPE_INTEGER, &sii.joy.bomb, ".joy.place_bomb" },
- { TYPE_KEYSYM, &sii.key.left, ".key.move_left" },
- { TYPE_KEYSYM, &sii.key.right, ".key.move_right" },
- { TYPE_KEYSYM, &sii.key.up, ".key.move_up" },
- { TYPE_KEYSYM, &sii.key.down, ".key.move_down" },
- { TYPE_KEYSYM, &sii.key.snap, ".key.snap_field" },
- { TYPE_KEYSYM, &sii.key.bomb, ".key.place_bomb" },
+ { TYPE_KEY, &sii.key.left, ".key.move_left" },
+ { TYPE_KEY, &sii.key.right, ".key.move_right" },
+ { TYPE_KEY, &sii.key.up, ".key.move_up" },
+ { TYPE_KEY, &sii.key.down, ".key.move_down" },
+ { TYPE_KEY, &sii.key.snap, ".key.snap_field" },
+ { TYPE_KEY, &sii.key.bomb, ".key.place_bomb" },
/* level directory info */
{ TYPE_STRING, &ldi.name, "name" },
ldi->next = NULL;
}
+static void setLevelDirInfoToDefaultsFromParent(struct LevelDirInfo *ldi,
+ struct LevelDirInfo *parent)
+{
+ if (parent == NULL)
+ {
+ setLevelDirInfoToDefaults(ldi);
+ return;
+ }
+
+ /* first copy all values from the parent structure ... */
+ *ldi = *parent;
+
+ /* ... then set all fields to default that cannot be inherited from parent.
+ This is especially important for all those fields that can be set from
+ the 'levelinfo.conf' config file, because the function 'setSetupInfo()'
+ calls 'free()' for all already set token values which requires that no
+ other structure's pointer may point to them!
+ */
+
+ ldi->filename = NULL;
+ ldi->fullpath = NULL;
+ ldi->basepath = NULL;
+ ldi->name = getStringCopy(ANONYMOUS_NAME);
+ ldi->name_short = NULL;
+ ldi->name_sorting = NULL;
+ ldi->author = getStringCopy(parent->author);
+ ldi->imported_from = getStringCopy(parent->imported_from);
+
+ ldi->level_group = FALSE;
+ ldi->parent_link = FALSE;
+
+ ldi->node_parent = parent;
+ ldi->node_group = NULL;
+ ldi->next = NULL;
+}
+
static void setSetupInfoToDefaults(struct SetupInfo *si)
{
int i;
si->team_mode = FALSE;
si->handicap = TRUE;
si->time_limit = TRUE;
+ si->fullscreen = FALSE;
for (i=0; i<MAX_PLAYERS; i++)
{
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_UNDEFINDED);
- si->input[i].key.right = (i == 0 ? DEFAULT_KEY_RIGHT : KEY_UNDEFINDED);
- si->input[i].key.up = (i == 0 ? DEFAULT_KEY_UP : KEY_UNDEFINDED);
- si->input[i].key.down = (i == 0 ? DEFAULT_KEY_DOWN : KEY_UNDEFINDED);
- si->input[i].key.snap = (i == 0 ? DEFAULT_KEY_SNAP : KEY_UNDEFINDED);
- si->input[i].key.bomb = (i == 0 ? DEFAULT_KEY_BOMB : KEY_UNDEFINDED);
+ 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);
}
}
*(boolean *)setup_value = get_string_boolean_value(token_value);
break;
- case TYPE_KEYSYM:
- *(KeySym *)setup_value = getKeySymFromX11KeyName(token_value);
+ case TYPE_KEY:
+ *(Key *)setup_value = getKeyFromX11KeyName(token_value);
break;
case TYPE_INTEGER:
int i;
checkSetupFileListIdentifier(setup_file_list, LEVELINFO_COOKIE);
- setLevelDirInfoToDefaults(leveldir_new);
-
- leveldir_new->node_parent = node_parent;
+ setLevelDirInfoToDefaultsFromParent(leveldir_new, node_parent);
/* set all structure fields according to the token/value pairs */
ldi = *leveldir_new;
strcat(entry, (*(boolean *)setup_value ? "on" : "off"));
break;
- case TYPE_KEYSYM:
+ case TYPE_KEY:
{
- KeySym keysym = *(KeySym *)setup_value;
- char *keyname = getKeyNameFromKeySym(keysym);
+ Key key = *(Key *)setup_value;
+ char *keyname = getKeyNameFromKey(key);
- strcat(entry, getX11KeyNameFromKeySym(keysym));
+ strcat(entry, getX11KeyNameFromKey(key));
for (i=strlen(entry); i<50; i++)
strcat(entry, " ");
level_directory = getPath2((leveldir_current->user_defined ?
getUserLevelDir("") :
options.level_directory),
- leveldir_current->filename);
+ leveldir_current->fullpath);
if ((dir = opendir(level_directory)) == NULL)
{
chmod(filename, SETUP_PERMS);
}
-#ifdef MSDOS
+#if !defined(PLATFORM_UNIX)
void initErrorFile()
{
char *filename;