/***********************************************************
* Rocks'n'Diamonds -- McDuffin Strikes Back! *
*----------------------------------------------------------*
-* (c) 1995-2001 Artsoft Entertainment *
+* (c) 1995-2002 Artsoft Entertainment *
* Holger Schemel *
* Detmolder Strasse 189 *
* 33604 Bielefeld *
#include "libgame/libgame.h"
#include "files.h"
+#include "init.h"
#include "tools.h"
#include "tape.h"
for(x=0; x<MAX_LEV_FIELDX; x++)
for(y=0; y<MAX_LEV_FIELDY; y++)
- Feld[x][y] = Ur[x][y] = EL_ERDREICH;
+ Feld[x][y] = Ur[x][y] = EL_SAND;
level.time = 100;
level.gems_needed = 0;
level.time_wheel = 10;
level.time_light = 10;
level.time_timegate = 10;
- level.amoeba_content = EL_DIAMANT;
+ level.amoeba_content = EL_DIAMOND;
level.double_speed = FALSE;
level.gravity = FALSE;
level.em_slippery_gems = FALSE;
for(x=0; x<3; x++)
for(y=0; y<3; y++)
level.yam_content[i][x][y] =
- (i < STD_ELEMENT_CONTENTS ? EL_FELSBROCKEN : EL_LEERRAUM);
+ (i < STD_ELEMENT_CONTENTS ? EL_ROCK : EL_EMPTY);
- Feld[0][0] = Ur[0][0] = EL_SPIELFIGUR;
+ Feld[0][0] = Ur[0][0] = EL_PLAYER_1;
Feld[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] =
- Ur[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] = EL_AUSGANG_ZU;
+ Ur[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] = EL_EXIT_CLOSED;
- BorderElement = EL_BETON;
+ for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ level.custom_element_successor[i] = EL_EMPTY_SPACE;
+ Properties[EL_CUSTOM_START + i][EP_BITFIELD_BASE] = EP_BITMASK_DEFAULT;
+ }
+
+ BorderElement = EL_STEELWALL;
+
+ level.no_level_file = FALSE;
+
+ if (leveldir_current == NULL) /* only when dumping level */
+ return;
/* try to determine better author name than 'anonymous' */
if (strcmp(leveldir_current->author, ANONYMOUS_NAME) != 0)
static int checkLevelElement(int element)
{
- if (element >= EL_FIRST_RUNTIME_EL)
+ if (element >= NUM_FILE_ELEMENTS)
{
Error(ERR_WARN, "invalid level element %d", element);
- element = EL_CHAR_FRAGE;
+ element = EL_CHAR_QUESTION;
}
+ else if (element == EL_PLAYER_OBSOLETE)
+ element = EL_PLAYER_1;
+ else if (element == EL_KEY_OBSOLETE)
+ element = EL_KEY_1;
return element;
}
return chunk_size;
}
+static int LoadLevel_BODY(FILE *file, int chunk_size, struct LevelInfo *level)
+{
+ int x, y;
+ int chunk_size_expected = level->fieldx * level->fieldy;
+
+ /* Note: "chunk_size" was wrong before version 2.0 when elements are
+ stored with 16-bit encoding (and should be twice as big then).
+ Even worse, playfield data was stored 16-bit when only yamyam content
+ contained 16-bit elements and vice versa. */
+
+ if (level->encoding_16bit_field && level->file_version >= FILE_VERSION_2_0)
+ chunk_size_expected *= 2;
+
+ if (chunk_size_expected != chunk_size)
+ {
+ ReadUnusedBytesFromFile(file, chunk_size);
+ return chunk_size_expected;
+ }
+
+ for(y=0; y<level->fieldy; y++)
+ for(x=0; x<level->fieldx; x++)
+ Feld[x][y] = Ur[x][y] =
+ checkLevelElement(level->encoding_16bit_field ?
+ getFile16BitBE(file) : fgetc(file));
+ return chunk_size;
+}
+
static int LoadLevel_CONT(FILE *file, int chunk_size, struct LevelInfo *level)
{
int i, x, y;
return chunk_size;
}
-static int LoadLevel_BODY(FILE *file, int chunk_size, struct LevelInfo *level)
-{
- int x, y;
- int chunk_size_expected = level->fieldx * level->fieldy;
-
- /* Note: "chunk_size" was wrong before version 2.0 when elements are
- stored with 16-bit encoding (and should be twice as big then).
- Even worse, playfield data was stored 16-bit when only yamyam content
- contained 16-bit elements and vice versa. */
-
- if (level->encoding_16bit_field && level->file_version >= FILE_VERSION_2_0)
- chunk_size_expected *= 2;
-
- if (chunk_size_expected != chunk_size)
- {
- ReadUnusedBytesFromFile(file, chunk_size);
- return chunk_size_expected;
- }
-
- for(y=0; y<level->fieldy; y++)
- for(x=0; x<level->fieldx; x++)
- Feld[x][y] = Ur[x][y] =
- checkLevelElement(level->encoding_16bit_field ?
- getFile16BitBE(file) : fgetc(file));
- return chunk_size;
-}
-
static int LoadLevel_CNT2(FILE *file, int chunk_size, struct LevelInfo *level)
{
int i, x, y;
if (num_contents < 1 || num_contents > MAX_ELEMENT_CONTENTS)
num_contents = STD_ELEMENT_CONTENTS;
- if (element == EL_MAMPFER)
+ if (element == EL_YAMYAM)
{
level->num_yam_contents = num_contents;
for(x=0; x<3; x++)
level->yam_content[i][x][y] = content_array[i][x][y];
}
- else if (element == EL_AMOEBE_BD)
+ else if (element == EL_BD_AMOEBA)
{
level->amoeba_content = content_array[0][0][0];
}
return chunk_size;
}
-void LoadLevel(int level_nr)
+static int LoadLevel_CUS1(FILE *file, int chunk_size, struct LevelInfo *level)
+{
+ int num_changed_custom_elements = getFile16BitBE(file);
+ int chunk_size_expected = 2 + num_changed_custom_elements * 6;
+ int i;
+
+ if (chunk_size_expected != chunk_size)
+ {
+ ReadUnusedBytesFromFile(file, chunk_size - 2);
+ return chunk_size_expected;
+ }
+
+ for (i=0; i < num_changed_custom_elements; i++)
+ {
+ int element = getFile16BitBE(file);
+ int properties = getFile32BitBE(file);
+
+ if (IS_CUSTOM_ELEMENT(element))
+ Properties[element][EP_BITFIELD_BASE] = properties;
+ else
+ Error(ERR_WARN, "invalid custom element number %d", element);
+ }
+
+ return chunk_size;
+}
+
+static int LoadLevel_CUS2(FILE *file, int chunk_size, struct LevelInfo *level)
+{
+ int num_changed_custom_elements = getFile16BitBE(file);
+ int chunk_size_expected = 2 + num_changed_custom_elements * 4;
+ int i;
+
+ if (chunk_size_expected != chunk_size)
+ {
+ ReadUnusedBytesFromFile(file, chunk_size - 2);
+ return chunk_size_expected;
+ }
+
+ for (i=0; i < num_changed_custom_elements; i++)
+ {
+ int element = getFile16BitBE(file);
+ int custom_element_successor = getFile16BitBE(file);
+ int i = element - EL_CUSTOM_START;
+
+ if (IS_CUSTOM_ELEMENT(element))
+ level->custom_element_successor[i] = custom_element_successor;
+ else
+ Error(ERR_WARN, "invalid custom element number %d", element);
+ }
+
+ return chunk_size;
+}
+
+void LoadLevelFromFilename(char *filename)
{
- char *filename = getLevelFilename(level_nr);
char cookie[MAX_LINE_LEN];
char chunk_name[CHUNK_ID_LEN + 1];
int chunk_size;
if (!(file = fopen(filename, MODE_READ)))
{
+ level.no_level_file = TRUE;
+
Error(ERR_WARN, "cannot read level '%s' - creating new level", filename);
return;
}
{ "VERS", FILE_VERS_CHUNK_SIZE, LoadLevel_VERS },
{ "HEAD", LEVEL_HEADER_SIZE, LoadLevel_HEAD },
{ "AUTH", MAX_LEVEL_AUTHOR_LEN, LoadLevel_AUTH },
- { "CONT", -1, LoadLevel_CONT },
{ "BODY", -1, LoadLevel_BODY },
+ { "CONT", -1, LoadLevel_CONT },
{ "CNT2", LEVEL_CHUNK_CNT2_SIZE, LoadLevel_CNT2 },
+ { "CUS1", -1, LoadLevel_CUS1 },
+ { "CUS2", -1, LoadLevel_CUS2 },
{ NULL, 0, NULL }
};
fclose(file);
+ if (leveldir_current == NULL) /* only when dumping level */
+ return;
+
if (IS_LEVELCLASS_CONTRIBUTION(leveldir_current) ||
IS_LEVELCLASS_USER(leveldir_current))
{
level.em_slippery_gems = TRUE;
}
+ /* map some elements which have changed in newer versions */
+ if (level.game_version <= VERSION_IDENT(2,2,0))
+ {
+ int x, y;
+
+ /* map game font elements */
+ for(y=0; y<level.fieldy; y++)
+ {
+ for(x=0; x<level.fieldx; x++)
+ {
+ int element = Ur[x][y];
+
+ if (element == EL_CHAR('['))
+ element = EL_CHAR_AUMLAUT;
+ else if (element == EL_CHAR('\\'))
+ element = EL_CHAR_OUMLAUT;
+ else if (element == EL_CHAR(']'))
+ element = EL_CHAR_UUMLAUT;
+ else if (element == EL_CHAR('^'))
+ element = EL_CHAR_COPYRIGHT;
+
+ Feld[x][y] = Ur[x][y] = element;
+ }
+ }
+ }
+
/* determine border element for this level */
SetBorderElement();
}
+void LoadLevel(int level_nr)
+{
+ char *filename = getLevelFilename(level_nr);
+
+ LoadLevelFromFilename(filename);
+ InitElementPropertiesEngine(level.game_version);
+}
+
static void SaveLevel_VERS(FILE *file, struct LevelInfo *level)
{
putFileVersion(file, level->file_version);
for(i=0; i<STD_ELEMENT_CONTENTS; i++)
for(y=0; y<3; y++)
for(x=0; x<3; x++)
- fputc((level->encoding_16bit_yamyam ? EL_LEERRAUM :
+ fputc((level->encoding_16bit_yamyam ? EL_EMPTY :
level->yam_content[i][x][y]),
file);
fputc(level->amoeba_speed, file);
fputc(level->time_magic_wall, file);
fputc(level->time_wheel, file);
- fputc((level->encoding_16bit_amoeba ? EL_LEERRAUM : level->amoeba_content),
+ fputc((level->encoding_16bit_amoeba ? EL_EMPTY : level->amoeba_content),
file);
fputc((level->double_speed ? 1 : 0), file);
fputc((level->gravity ? 1 : 0), file);
fputc(level->author[i], file);
}
+static void SaveLevel_BODY(FILE *file, struct LevelInfo *level)
+{
+ int x, y;
+
+ for(y=0; y<level->fieldy; y++)
+ for(x=0; x<level->fieldx; x++)
+ if (level->encoding_16bit_field)
+ putFile16BitBE(file, Ur[x][y]);
+ else
+ fputc(Ur[x][y], file);
+}
+
#if 0
static void SaveLevel_CONT(FILE *file, struct LevelInfo *level)
{
int i, x, y;
- fputc(EL_MAMPFER, file);
+ fputc(EL_YAMYAM, file);
fputc(level->num_yam_contents, file);
fputc(0, file);
fputc(0, file);
}
#endif
-static void SaveLevel_BODY(FILE *file, struct LevelInfo *level)
-{
- int x, y;
-
- for(y=0; y<level->fieldy; y++)
- for(x=0; x<level->fieldx; x++)
- if (level->encoding_16bit_field)
- putFile16BitBE(file, Ur[x][y]);
- else
- fputc(Ur[x][y], file);
-}
-
static void SaveLevel_CNT2(FILE *file, struct LevelInfo *level, int element)
{
int i, x, y;
int num_contents, content_xsize, content_ysize;
int content_array[MAX_ELEMENT_CONTENTS][3][3];
- if (element == EL_MAMPFER)
+ if (element == EL_YAMYAM)
{
num_contents = level->num_yam_contents;
content_xsize = 3;
for(x=0; x<3; x++)
content_array[i][x][y] = level->yam_content[i][x][y];
}
- else if (element == EL_AMOEBE_BD)
+ else if (element == EL_BD_AMOEBA)
{
num_contents = 1;
content_xsize = 1;
for(i=0; i<MAX_ELEMENT_CONTENTS; i++)
for(y=0; y<3; y++)
for(x=0; x<3; x++)
- content_array[i][x][y] = EL_LEERRAUM;
+ content_array[i][x][y] = EL_EMPTY;
content_array[0][0][0] = level->amoeba_content;
}
else
putFile16BitBE(file, content_array[i][x][y]);
}
+static void SaveLevel_CUS1(FILE *file, struct LevelInfo *level,
+ int num_changed_custom_elements)
+{
+ int i, check = 0;
+
+ putFile16BitBE(file, num_changed_custom_elements);
+
+ for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+
+ if (Properties[element][EP_BITFIELD_BASE] != EP_BITMASK_DEFAULT)
+ {
+ if (check < num_changed_custom_elements)
+ {
+ putFile16BitBE(file, element);
+ putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]);
+ }
+
+ check++;
+ }
+ }
+
+ if (check != num_changed_custom_elements) /* should not happen */
+ Error(ERR_WARN, "inconsistent number of custom element properties");
+}
+
+static void SaveLevel_CUS2(FILE *file, struct LevelInfo *level,
+ int num_changed_custom_elements)
+{
+ int i, check = 0;
+
+ putFile16BitBE(file, num_changed_custom_elements);
+
+ for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+
+ if (level->custom_element_successor[i] != EL_EMPTY_SPACE)
+ {
+ if (check < num_changed_custom_elements)
+ {
+ putFile16BitBE(file, element);
+ putFile16BitBE(file, level->custom_element_successor[i]);
+ }
+
+ check++;
+ }
+ }
+
+ if (check != num_changed_custom_elements) /* should not happen */
+ Error(ERR_WARN, "inconsistent number of custom element successors");
+}
+
void SaveLevel(int level_nr)
{
- int i, x, y;
char *filename = getLevelFilename(level_nr);
int body_chunk_size;
+ int num_changed_custom_elements1 = 0;
+ int num_changed_custom_elements2 = 0;
+ int i, x, y;
FILE *file;
if (!(file = fopen(filename, MODE_WRITE)))
if (level.amoeba_content > 255)
level.encoding_16bit_amoeba = TRUE;
+ /* calculate size of "BODY" chunk */
body_chunk_size =
level.fieldx * level.fieldy * (level.encoding_16bit_field ? 2 : 1);
+ /* check for non-standard custom elements and calculate "CUS1" chunk size */
+ for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
+ if (Properties[EL_CUSTOM_START +i][EP_BITFIELD_BASE] != EP_BITMASK_DEFAULT)
+ num_changed_custom_elements1++;
+
+ /* check for non-standard custom elements and calculate "CUS2" chunk size */
+ for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
+ if (level.custom_element_successor[i] != EL_EMPTY_SPACE)
+ num_changed_custom_elements2++;
+
putFileChunkBE(file, "RND1", CHUNK_SIZE_UNDEFINED);
putFileChunkBE(file, "CAVE", CHUNK_SIZE_NONE);
level.num_yam_contents != STD_ELEMENT_CONTENTS)
{
putFileChunkBE(file, "CNT2", LEVEL_CHUNK_CNT2_SIZE);
- SaveLevel_CNT2(file, &level, EL_MAMPFER);
+ SaveLevel_CNT2(file, &level, EL_YAMYAM);
}
if (level.encoding_16bit_amoeba)
{
putFileChunkBE(file, "CNT2", LEVEL_CHUNK_CNT2_SIZE);
- SaveLevel_CNT2(file, &level, EL_AMOEBE_BD);
+ SaveLevel_CNT2(file, &level, EL_BD_AMOEBA);
+ }
+
+ if (num_changed_custom_elements1 > 0)
+ {
+ putFileChunkBE(file, "CUS1", 2 + num_changed_custom_elements1 * 6);
+ SaveLevel_CUS1(file, &level, num_changed_custom_elements1);
+ }
+
+ if (num_changed_custom_elements2 > 0)
+ {
+ putFileChunkBE(file, "CUS2", 2 + num_changed_custom_elements2 * 4);
+ SaveLevel_CUS2(file, &level, num_changed_custom_elements2);
}
fclose(file);
SetFilePermissions(filename, PERMS_PRIVATE);
}
+void DumpLevel(struct LevelInfo *level)
+{
+ printf_line("-", 79);
+ printf("Level xxx (file version %06d, game version %06d)\n",
+ level->file_version, level->game_version);
+ printf_line("-", 79);
+
+ printf("Level Author: '%s'\n", level->author);
+ printf("Level Title: '%s'\n", level->name);
+ printf("\n");
+ printf("Playfield Size: %d x %d\n", level->fieldx, level->fieldy);
+ printf("\n");
+ printf("Level Time: %d seconds\n", level->time);
+ printf("Gems needed: %d\n", level->gems_needed);
+ printf("\n");
+ printf("Time for Magic Wall: %d seconds\n", level->time_magic_wall);
+ printf("Time for Wheel: %d seconds\n", level->time_wheel);
+ printf("Time for Light: %d seconds\n", level->time_light);
+ printf("Time for Timegate: %d seconds\n", level->time_timegate);
+ printf("\n");
+ printf("Amoeba Speed: %d\n", level->amoeba_speed);
+ printf("\n");
+ printf("Gravity: %s\n", (level->gravity ? "yes" : "no"));
+ printf("Double Speed Movement: %s\n", (level->double_speed ? "yes" : "no"));
+ printf("EM style slippery gems: %s\n", (level->em_slippery_gems ? "yes" : "no"));
+
+ printf_line("-", 79);
+}
+
/* ========================================================================= */
/* tape file functions */
return chunk_size;
}
+static int LoadTape_INFO(FILE *file, int chunk_size, struct TapeInfo *tape)
+{
+ int level_identifier_size;
+ int i;
+
+ level_identifier_size = getFile16BitBE(file);
+
+ tape->level_identifier =
+ checked_realloc(tape->level_identifier, level_identifier_size);
+
+ for(i=0; i < level_identifier_size; i++)
+ tape->level_identifier[i] = fgetc(file);
+
+ tape->level_nr = getFile16BitBE(file);
+
+ chunk_size = 2 + level_identifier_size + 2;
+
+ return chunk_size;
+}
+
static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape)
{
int i, j;
return chunk_size;
}
-void LoadTape(int level_nr)
+void LoadTapeFromFilename(char *filename)
{
- char *filename = getTapeFilename(level_nr);
char cookie[MAX_LINE_LEN];
char chunk_name[CHUNK_ID_LEN + 1];
FILE *file;
{
{ "VERS", FILE_VERS_CHUNK_SIZE, LoadTape_VERS },
{ "HEAD", TAPE_HEADER_SIZE, LoadTape_HEAD },
+ { "INFO", -1, LoadTape_INFO },
{ "BODY", -1, LoadTape_BODY },
{ NULL, 0, NULL }
};
tape.length_seconds = GetTapeLength();
}
+void LoadTape(int level_nr)
+{
+ char *filename = getTapeFilename(level_nr);
+
+ LoadTapeFromFilename(filename);
+}
+
static void SaveTape_VERS(FILE *file, struct TapeInfo *tape)
{
putFileVersion(file, tape->file_version);
putFileVersion(file, tape->engine_version);
}
+static void SaveTape_INFO(FILE *file, struct TapeInfo *tape)
+{
+ int level_identifier_size = strlen(tape->level_identifier) + 1;
+ int i;
+
+ putFile16BitBE(file, level_identifier_size);
+
+ for(i=0; i < level_identifier_size; i++)
+ fputc(tape->level_identifier[i], file);
+
+ putFile16BitBE(file, tape->level_nr);
+}
+
static void SaveTape_BODY(FILE *file, struct TapeInfo *tape)
{
int i, j;
void SaveTape(int level_nr)
{
- int i;
char *filename = getTapeFilename(level_nr);
FILE *file;
boolean new_tape = TRUE;
int num_participating_players = 0;
+ int info_chunk_size;
int body_chunk_size;
+ int i;
InitTapeDirectory(leveldir_current->filename);
if (tape.player_participates[i])
num_participating_players++;
+ info_chunk_size = 2 + (strlen(tape.level_identifier) + 1) + 2;
body_chunk_size = (num_participating_players + 1) * tape.length;
putFileChunkBE(file, "RND1", CHUNK_SIZE_UNDEFINED);
putFileChunkBE(file, "HEAD", TAPE_HEADER_SIZE);
SaveTape_HEAD(file, &tape);
+ putFileChunkBE(file, "INFO", info_chunk_size);
+ SaveTape_INFO(file, &tape);
+
putFileChunkBE(file, "BODY", body_chunk_size);
SaveTape_BODY(file, &tape);
return;
}
- printf("\n");
- printf("-------------------------------------------------------------------------------\n");
- printf("Tape of Level %d (file version %06d, game version %06d\n",
+ printf_line("-", 79);
+ printf("Tape of Level %03d (file version %06d, game version %06d)\n",
tape->level_nr, tape->file_version, tape->game_version);
- printf("-------------------------------------------------------------------------------\n");
+ printf("Level series identifier: '%s'\n", tape->level_identifier);
+ printf_line("-", 79);
for(i=0; i<tape->length; i++)
{
if (i >= MAX_TAPELEN)
break;
+ printf("%03d: ", i);
+
for(j=0; j<MAX_PLAYERS; j++)
{
if (tape->player_participates[j])
printf("(%03d)\n", tape->pos[i].delay);
}
- printf("-------------------------------------------------------------------------------\n");
+ printf_line("-", 79);
}
#define NUM_GLOBAL_SETUP_TOKENS 22
+/* editor setup */
+#define SETUP_TOKEN_EDITOR_EL_BOULDERDASH 0
+#define SETUP_TOKEN_EDITOR_EL_EMERALD_MINE 1
+#define SETUP_TOKEN_EDITOR_EL_MORE 2
+#define SETUP_TOKEN_EDITOR_EL_SOKOBAN 3
+#define SETUP_TOKEN_EDITOR_EL_SUPAPLEX 4
+#define SETUP_TOKEN_EDITOR_EL_DIAMOND_CAVES 5
+#define SETUP_TOKEN_EDITOR_EL_DX_BOULDERDASH 6
+#define SETUP_TOKEN_EDITOR_EL_CHARS 7
+#define SETUP_TOKEN_EDITOR_EL_CUSTOM 8
+
+#define NUM_EDITOR_SETUP_TOKENS 9
+
/* shortcut setup */
-#define SETUP_TOKEN_SAVE_GAME 0
-#define SETUP_TOKEN_LOAD_GAME 1
-#define SETUP_TOKEN_TOGGLE_PAUSE 2
+#define SETUP_TOKEN_SHORTCUT_SAVE_GAME 0
+#define SETUP_TOKEN_SHORTCUT_LOAD_GAME 1
+#define SETUP_TOKEN_SHORTCUT_TOGGLE_PAUSE 2
#define NUM_SHORTCUT_SETUP_TOKENS 3
/* player setup */
-#define SETUP_TOKEN_USE_JOYSTICK 0
-#define SETUP_TOKEN_JOY_DEVICE_NAME 1
-#define SETUP_TOKEN_JOY_XLEFT 2
-#define SETUP_TOKEN_JOY_XMIDDLE 3
-#define SETUP_TOKEN_JOY_XRIGHT 4
-#define SETUP_TOKEN_JOY_YUPPER 5
-#define SETUP_TOKEN_JOY_YMIDDLE 6
-#define SETUP_TOKEN_JOY_YLOWER 7
-#define SETUP_TOKEN_JOY_SNAP 8
-#define SETUP_TOKEN_JOY_BOMB 9
-#define SETUP_TOKEN_KEY_LEFT 10
-#define SETUP_TOKEN_KEY_RIGHT 11
-#define SETUP_TOKEN_KEY_UP 12
-#define SETUP_TOKEN_KEY_DOWN 13
-#define SETUP_TOKEN_KEY_SNAP 14
-#define SETUP_TOKEN_KEY_BOMB 15
+#define SETUP_TOKEN_PLAYER_USE_JOYSTICK 0
+#define SETUP_TOKEN_PLAYER_JOY_DEVICE_NAME 1
+#define SETUP_TOKEN_PLAYER_JOY_XLEFT 2
+#define SETUP_TOKEN_PLAYER_JOY_XMIDDLE 3
+#define SETUP_TOKEN_PLAYER_JOY_XRIGHT 4
+#define SETUP_TOKEN_PLAYER_JOY_YUPPER 5
+#define SETUP_TOKEN_PLAYER_JOY_YMIDDLE 6
+#define SETUP_TOKEN_PLAYER_JOY_YLOWER 7
+#define SETUP_TOKEN_PLAYER_JOY_SNAP 8
+#define SETUP_TOKEN_PLAYER_JOY_BOMB 9
+#define SETUP_TOKEN_PLAYER_KEY_LEFT 10
+#define SETUP_TOKEN_PLAYER_KEY_RIGHT 11
+#define SETUP_TOKEN_PLAYER_KEY_UP 12
+#define SETUP_TOKEN_PLAYER_KEY_DOWN 13
+#define SETUP_TOKEN_PLAYER_KEY_SNAP 14
+#define SETUP_TOKEN_PLAYER_KEY_BOMB 15
#define NUM_PLAYER_SETUP_TOKENS 16
+/* system setup */
+#define SETUP_TOKEN_SYSTEM_SDL_AUDIODRIVER 0
+#define SETUP_TOKEN_SYSTEM_AUDIO_FRAGMENT_SIZE 1
+
+#define NUM_SYSTEM_SETUP_TOKENS 2
+
+/* options setup */
+#define SETUP_TOKEN_OPTIONS_VERBOSE 0
+
+#define NUM_OPTIONS_SETUP_TOKENS 1
+
+
static struct SetupInfo si;
+static struct SetupEditorInfo sei;
static struct SetupShortcutInfo ssi;
static struct SetupInputInfo sii;
+static struct SetupSystemInfo syi;
+static struct OptionInfo soi;
static struct TokenInfo global_setup_tokens[] =
{
- /* global setup */
{ TYPE_STRING, &si.player_name, "player_name" },
{ TYPE_SWITCH, &si.sound, "sound" },
{ TYPE_SWITCH, &si.sound_loops, "repeating_sound_loops" },
{ TYPE_SWITCH, &si.override_level_music, "override_level_music" },
};
+static struct TokenInfo editor_setup_tokens[] =
+{
+ { TYPE_SWITCH, &sei.el_boulderdash, "editor.el_boulderdash" },
+ { TYPE_SWITCH, &sei.el_emerald_mine, "editor.el_emerald_mine" },
+ { TYPE_SWITCH, &sei.el_more, "editor.el_more" },
+ { TYPE_SWITCH, &sei.el_sokoban, "editor.el_sokoban" },
+ { TYPE_SWITCH, &sei.el_supaplex, "editor.el_supaplex" },
+ { TYPE_SWITCH, &sei.el_diamond_caves, "editor.el_diamond_caves" },
+ { TYPE_SWITCH, &sei.el_dx_boulderdash,"editor.el_dx_boulderdash" },
+ { TYPE_SWITCH, &sei.el_chars, "editor.el_chars" },
+ { TYPE_SWITCH, &sei.el_custom, "editor.el_custom" },
+};
+
static struct TokenInfo shortcut_setup_tokens[] =
{
- /* shortcut setup */
{ TYPE_KEY_X11, &ssi.save_game, "shortcut.save_game" },
{ TYPE_KEY_X11, &ssi.load_game, "shortcut.load_game" },
{ TYPE_KEY_X11, &ssi.toggle_pause, "shortcut.toggle_pause" }
static struct TokenInfo player_setup_tokens[] =
{
- /* player setup */
{ TYPE_BOOLEAN, &sii.use_joystick, ".use_joystick" },
{ TYPE_STRING, &sii.joy.device_name, ".joy.device_name" },
{ TYPE_INTEGER, &sii.joy.xleft, ".joy.xleft" },
{ TYPE_KEY_X11, &sii.key.bomb, ".key.place_bomb" }
};
+static struct TokenInfo system_setup_tokens[] =
+{
+ { TYPE_STRING, &syi.sdl_audiodriver, "system.sdl_audiodriver" },
+ { TYPE_INTEGER, &syi.audio_fragment_size,"system.audio_fragment_size" }
+};
+
+static struct TokenInfo options_setup_tokens[] =
+{
+ { TYPE_BOOLEAN, &soi.verbose, "options.verbose" }
+};
+
+static char *get_corrected_login_name(char *login_name)
+{
+ /* needed because player name must be a fixed length string */
+ char *login_name_new = checked_malloc(MAX_PLAYER_NAME_LEN + 1);
+
+ strncpy(login_name_new, login_name, MAX_PLAYER_NAME_LEN);
+ login_name_new[MAX_PLAYER_NAME_LEN] = '\0';
+
+ if (strlen(login_name) > MAX_PLAYER_NAME_LEN) /* name has been cut */
+ if (strchr(login_name_new, ' '))
+ *strchr(login_name_new, ' ') = '\0';
+
+ return login_name_new;
+}
+
static void setSetupInfoToDefaults(struct SetupInfo *si)
{
int i;
- si->player_name = getStringCopy(getLoginName());
+ si->player_name = get_corrected_login_name(getLoginName());
si->sound = TRUE;
si->sound_loops = TRUE;
si->override_level_sounds = FALSE;
si->override_level_music = FALSE;
+ si->editor.el_boulderdash = TRUE;
+ si->editor.el_emerald_mine = TRUE;
+ si->editor.el_more = TRUE;
+ si->editor.el_sokoban = TRUE;
+ si->editor.el_supaplex = TRUE;
+ si->editor.el_diamond_caves = TRUE;
+ si->editor.el_dx_boulderdash = TRUE;
+ si->editor.el_chars = TRUE;
+ si->editor.el_custom = TRUE;
+
si->shortcut.save_game = DEFAULT_KEY_SAVE_GAME;
si->shortcut.load_game = DEFAULT_KEY_LOAD_GAME;
si->shortcut.toggle_pause = DEFAULT_KEY_TOGGLE_PAUSE;
si->input[i].key.snap = (i == 0 ? DEFAULT_KEY_SNAP : KSYM_UNDEFINED);
si->input[i].key.bomb = (i == 0 ? DEFAULT_KEY_BOMB : KSYM_UNDEFINED);
}
+
+ si->system.sdl_audiodriver = getStringCopy(ARG_DEFAULT);
+ si->system.audio_fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
+
+ si->options.verbose = FALSE;
}
-static void decodeSetupFileList(struct SetupFileList *setup_file_list)
+static void decodeSetupFileHash(SetupFileHash *setup_file_hash)
{
int i, pnr;
- if (!setup_file_list)
+ if (!setup_file_hash)
return;
/* global setup */
si = setup;
for (i=0; i<NUM_GLOBAL_SETUP_TOKENS; i++)
setSetupInfo(global_setup_tokens, i,
- getTokenValue(setup_file_list, global_setup_tokens[i].text));
+ getHashEntry(setup_file_hash, global_setup_tokens[i].text));
setup = si;
+ /* editor setup */
+ sei = setup.editor;
+ for (i=0; i<NUM_EDITOR_SETUP_TOKENS; i++)
+ setSetupInfo(editor_setup_tokens, i,
+ getHashEntry(setup_file_hash,editor_setup_tokens[i].text));
+ setup.editor = sei;
+
/* shortcut setup */
ssi = setup.shortcut;
for (i=0; i<NUM_SHORTCUT_SETUP_TOKENS; i++)
setSetupInfo(shortcut_setup_tokens, i,
- getTokenValue(setup_file_list,shortcut_setup_tokens[i].text));
+ getHashEntry(setup_file_hash,shortcut_setup_tokens[i].text));
setup.shortcut = ssi;
/* player setup */
sprintf(full_token, "%s%s", prefix, player_setup_tokens[i].text);
setSetupInfo(player_setup_tokens, i,
- getTokenValue(setup_file_list, full_token));
+ getHashEntry(setup_file_hash, full_token));
}
setup.input[pnr] = sii;
}
+
+ /* system setup */
+ syi = setup.system;
+ for (i=0; i<NUM_SYSTEM_SETUP_TOKENS; i++)
+ setSetupInfo(system_setup_tokens, i,
+ getHashEntry(setup_file_hash, system_setup_tokens[i].text));
+ setup.system = syi;
+
+ /* options setup */
+ soi = setup.options;
+ for (i=0; i<NUM_OPTIONS_SETUP_TOKENS; i++)
+ setSetupInfo(options_setup_tokens, i,
+ getHashEntry(setup_file_hash, options_setup_tokens[i].text));
+ setup.options = soi;
}
void LoadSetup()
{
char *filename = getSetupFilename();
- struct SetupFileList *setup_file_list = NULL;
+ SetupFileHash *setup_file_hash = NULL;
/* always start with reliable default values */
setSetupInfoToDefaults(&setup);
- setup_file_list = loadSetupFileList(filename);
+ setup_file_hash = loadSetupFileHash(filename);
- if (setup_file_list)
+ if (setup_file_hash)
{
- checkSetupFileListIdentifier(setup_file_list, getCookie("SETUP"));
- decodeSetupFileList(setup_file_list);
+ char *player_name_new;
+
+ checkSetupFileHashIdentifier(setup_file_hash, getCookie("SETUP"));
+ decodeSetupFileHash(setup_file_hash);
setup.direct_draw = !setup.double_buffering;
- freeSetupFileList(setup_file_list);
+ freeSetupFileHash(setup_file_hash);
/* needed to work around problems with fixed length strings */
- if (strlen(setup.player_name) > MAX_PLAYER_NAME_LEN)
- setup.player_name[MAX_PLAYER_NAME_LEN] = '\0';
- else if (strlen(setup.player_name) < MAX_PLAYER_NAME_LEN)
- {
- char *new_name = checked_malloc(MAX_PLAYER_NAME_LEN + 1);
-
- strcpy(new_name, setup.player_name);
- free(setup.player_name);
- setup.player_name = new_name;
- }
+ player_name_new = get_corrected_login_name(setup.player_name);
+ free(setup.player_name);
+ setup.player_name = player_name_new;
}
else
Error(ERR_WARN, "using default setup values");
si = setup;
for (i=0; i<NUM_GLOBAL_SETUP_TOKENS; i++)
{
- fprintf(file, "%s\n", getSetupLine(global_setup_tokens, "", i));
-
/* just to make things nicer :) */
- if (i == SETUP_TOKEN_PLAYER_NAME || i == SETUP_TOKEN_GRAPHICS_SET - 1)
+ if (i == SETUP_TOKEN_PLAYER_NAME + 1 ||
+ i == SETUP_TOKEN_GRAPHICS_SET)
fprintf(file, "\n");
+
+ fprintf(file, "%s\n", getSetupLine(global_setup_tokens, "", i));
}
+ /* editor setup */
+ sei = setup.editor;
+ fprintf(file, "\n");
+ for (i=0; i<NUM_EDITOR_SETUP_TOKENS; i++)
+ fprintf(file, "%s\n", getSetupLine(editor_setup_tokens, "", i));
+
/* shortcut setup */
ssi = setup.shortcut;
fprintf(file, "\n");
fprintf(file, "%s\n", getSetupLine(player_setup_tokens, prefix, i));
}
+ /* system setup */
+ syi = setup.system;
+ fprintf(file, "\n");
+ for (i=0; i<NUM_SYSTEM_SETUP_TOKENS; i++)
+ fprintf(file, "%s\n", getSetupLine(system_setup_tokens, "", i));
+
+ /* options setup */
+ soi = setup.options;
+ fprintf(file, "\n");
+ for (i=0; i<NUM_OPTIONS_SETUP_TOKENS; i++)
+ fprintf(file, "%s\n", getSetupLine(options_setup_tokens, "", i));
+
fclose(file);
SetFilePermissions(filename, PERMS_PRIVATE);
}
+
+void LoadCustomElementDescriptions()
+{
+ char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
+ SetupFileHash *setup_file_hash;
+ int i;
+
+ for (i=0; i<NUM_FILE_ELEMENTS; i++)
+ {
+ if (element_info[i].custom_description != NULL)
+ {
+ free(element_info[i].custom_description);
+ element_info[i].custom_description = NULL;
+ }
+ }
+
+ if ((setup_file_hash = loadSetupFileHash(filename)) == NULL)
+ return;
+
+ for (i=0; i<NUM_FILE_ELEMENTS; i++)
+ {
+ char *token = getStringCat2(element_info[i].token_name, ".name");
+ char *value = getHashEntry(setup_file_hash, token);
+
+ if (value != NULL)
+ element_info[i].custom_description = getStringCopy(value);
+
+ free(token);
+ }
+
+ freeSetupFileHash(setup_file_hash);
+}
+
+void LoadSpecialMenuDesignSettings()
+{
+ char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
+ SetupFileHash *setup_file_hash;
+ char *value;
+
+ /* !!! CHANGE THIS !!! (redundant initialization) !!! */
+ global.num_toons = 20;
+ global.menu_draw_xoffset = 0;
+ global.menu_draw_yoffset = 0;
+ global.menu_draw_xoffset_MAIN = 0;
+ global.menu_draw_yoffset_MAIN = 0;
+ global.door_step_offset = 2;
+ global.door_step_delay = 10;
+
+ if ((setup_file_hash = loadSetupFileHash(filename)) == NULL)
+ return;
+
+ value = getHashEntry(setup_file_hash, "global.num_toons");
+ if (value != NULL)
+ global.num_toons = get_integer_from_string(value);
+
+ value = getHashEntry(setup_file_hash, "menu.draw_xoffset");
+ if (value != NULL)
+ global.menu_draw_xoffset = get_integer_from_string(value);
+
+ value = getHashEntry(setup_file_hash, "menu.draw_yoffset");
+ if (value != NULL)
+ global.menu_draw_yoffset = get_integer_from_string(value);
+
+ value = getHashEntry(setup_file_hash, "menu.draw_xoffset.MAIN");
+ if (value != NULL)
+ global.menu_draw_xoffset_MAIN = get_integer_from_string(value);
+
+ value = getHashEntry(setup_file_hash, "menu.draw_yoffset.MAIN");
+ if (value != NULL)
+ global.menu_draw_yoffset_MAIN = get_integer_from_string(value);
+
+ value = getHashEntry(setup_file_hash, "door.step_offset");
+ if (value != NULL)
+ global.door_step_offset = get_integer_from_string(value);
+
+ value = getHashEntry(setup_file_hash, "door.step_delay");
+ if (value != NULL)
+ global.door_step_delay = get_integer_from_string(value);
+
+ freeSetupFileHash(setup_file_hash);
+}