#define LEVEL_CHUNK_CNT2_SIZE 160 /* size of level CNT2 chunk */
#define LEVEL_CHUNK_CNT2_UNUSED 11 /* unused CNT2 chunk bytes */
#define TAPE_HEADER_SIZE 20 /* size of tape file header */
-#define TAPE_HEADER_UNUSED 7 /* unused tape header bytes */
+#define TAPE_HEADER_UNUSED 3 /* unused tape header bytes */
/* file identifier strings */
#define LEVEL_COOKIE_TMPL "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x"
#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2"
+/* ========================================================================= */
+/* level file functions */
+/* ========================================================================= */
+
static void setLevelInfoToDefaults()
{
int i, x, y;
static int LoadLevel_VERS(FILE *file, int chunk_size, struct LevelInfo *level)
{
- ReadChunk_VERS(file, &(level->file_version), &(level->game_version));
+ level->file_version = getFileVersion(file);
+ level->game_version = getFileVersion(file);
return chunk_size;
}
lev_fieldx = level->fieldx = fgetc(file);
lev_fieldy = level->fieldy = fgetc(file);
- level->time = getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN);
- level->gems_needed = getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN);
+ level->time = getFile16BitBE(file);
+ level->gems_needed = getFile16BitBE(file);
for(i=0; i<MAX_LEVEL_NAME_LEN; i++)
level->name[i] = fgetc(file);
for(x=0; x<3; x++)
level->yam_content[i][x][y] =
checkLevelElement(level->encoding_16bit_field ?
- getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN) :
- fgetc(file));
+ getFile16BitBE(file) : fgetc(file));
return chunk_size;
}
for(x=0; x<level->fieldx; x++)
Feld[x][y] = Ur[x][y] =
checkLevelElement(level->encoding_16bit_field ?
- getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN) :
- fgetc(file));
+ getFile16BitBE(file) : fgetc(file));
return chunk_size;
}
int num_contents, content_xsize, content_ysize;
int content_array[MAX_ELEMENT_CONTENTS][3][3];
- element = checkLevelElement(getFile16BitInteger(file,BYTE_ORDER_BIG_ENDIAN));
+ element = checkLevelElement(getFile16BitBE(file));
num_contents = fgetc(file);
content_xsize = fgetc(file);
content_ysize = fgetc(file);
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] =
- checkLevelElement(getFile16BitInteger(file, BYTE_ORDER_BIG_ENDIAN));
+ content_array[i][x][y] = checkLevelElement(getFile16BitBE(file));
/* correct invalid number of content fields -- should never happen */
if (num_contents < 1 || num_contents > MAX_ELEMENT_CONTENTS)
return;
}
- getFileChunk(file, chunk_name, NULL, BYTE_ORDER_BIG_ENDIAN);
+ getFileChunkBE(file, chunk_name, NULL);
if (strcmp(chunk_name, "RND1") == 0)
{
- getFile32BitInteger(file, BYTE_ORDER_BIG_ENDIAN); /* not used */
+ getFile32BitBE(file); /* not used */
- getFileChunk(file, chunk_name, NULL, BYTE_ORDER_BIG_ENDIAN);
+ getFileChunkBE(file, chunk_name, NULL);
if (strcmp(chunk_name, "CAVE") != 0)
{
Error(ERR_WARN, "unknown format of level file '%s'", filename);
{ NULL, 0, NULL }
};
- while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_BIG_ENDIAN))
+ while (getFileChunkBE(file, chunk_name, &chunk_size))
{
int i = 0;
/* player was faster than monsters in (pre-)1.0 levels */
level.double_speed = TRUE;
}
+
+ /* Default behaviour for EM style gems was "slippery" only in 2.0.1 */
+ if (level.game_version == VERSION_IDENT(2,0,1))
+ level.em_slippery_gems = TRUE;
}
else
{
SetBorderElement();
}
+static void SaveLevel_VERS(FILE *file, struct LevelInfo *level)
+{
+ putFileVersion(file, level->file_version);
+ putFileVersion(file, level->game_version);
+}
+
static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level)
{
int i, x, y;
fputc(level->fieldx, file);
fputc(level->fieldy, file);
- putFile16BitInteger(file, level->time, BYTE_ORDER_BIG_ENDIAN);
- putFile16BitInteger(file, level->gems_needed, BYTE_ORDER_BIG_ENDIAN);
+ putFile16BitBE(file, level->time);
+ putFile16BitBE(file, level->gems_needed);
for(i=0; i<MAX_LEVEL_NAME_LEN; i++)
fputc(level->name[i], file);
for(y=0; y<3; y++)
for(x=0; x<3; x++)
if (level->encoding_16bit_field)
- putFile16BitInteger(file, level->yam_content[i][x][y],
- BYTE_ORDER_BIG_ENDIAN);
+ putFile16BitBE(file, level->yam_content[i][x][y]);
else
fputc(level->yam_content[i][x][y], file);
}
for(y=0; y<level->fieldy; y++)
for(x=0; x<level->fieldx; x++)
if (level->encoding_16bit_field)
- putFile16BitInteger(file, Ur[x][y], BYTE_ORDER_BIG_ENDIAN);
+ putFile16BitBE(file, Ur[x][y]);
else
fputc(Ur[x][y], file);
}
return;
}
- putFile16BitInteger(file, element, BYTE_ORDER_BIG_ENDIAN);
+ putFile16BitBE(file, element);
fputc(num_contents, file);
fputc(content_xsize, file);
fputc(content_ysize, file);
for(i=0; i<MAX_ELEMENT_CONTENTS; i++)
for(y=0; y<3; y++)
for(x=0; x<3; x++)
- putFile16BitInteger(file, content_array[i][x][y],
- BYTE_ORDER_BIG_ENDIAN);
+ putFile16BitBE(file, content_array[i][x][y]);
}
void SaveLevel(int level_nr)
return;
}
+ level.file_version = FILE_VERSION_ACTUAL;
+ level.game_version = GAME_VERSION_ACTUAL;
/* check level field for 16-bit elements */
level.encoding_16bit_field = FALSE;
body_chunk_size =
level.fieldx * level.fieldy * (level.encoding_16bit_field ? 2 : 1);
- putFileChunk(file, "RND1", CHUNK_SIZE_UNDEFINED, BYTE_ORDER_BIG_ENDIAN);
- putFileChunk(file, "CAVE", CHUNK_SIZE_NONE, BYTE_ORDER_BIG_ENDIAN);
+ putFileChunkBE(file, "RND1", CHUNK_SIZE_UNDEFINED);
+ putFileChunkBE(file, "CAVE", CHUNK_SIZE_NONE);
- putFileChunk(file, "VERS", FILE_VERS_CHUNK_SIZE, BYTE_ORDER_BIG_ENDIAN);
- WriteChunk_VERS(file, FILE_VERSION_ACTUAL, GAME_VERSION_ACTUAL);
+ putFileChunkBE(file, "VERS", FILE_VERS_CHUNK_SIZE);
+ SaveLevel_VERS(file, &level);
- putFileChunk(file, "HEAD", LEVEL_HEADER_SIZE, BYTE_ORDER_BIG_ENDIAN);
+ putFileChunkBE(file, "HEAD", LEVEL_HEADER_SIZE);
SaveLevel_HEAD(file, &level);
- putFileChunk(file, "AUTH", MAX_LEVEL_AUTHOR_LEN, BYTE_ORDER_BIG_ENDIAN);
+ putFileChunkBE(file, "AUTH", MAX_LEVEL_AUTHOR_LEN);
SaveLevel_AUTH(file, &level);
- putFileChunk(file, "BODY", body_chunk_size, BYTE_ORDER_BIG_ENDIAN);
+ putFileChunkBE(file, "BODY", body_chunk_size);
SaveLevel_BODY(file, &level);
if (level.encoding_16bit_yamyam ||
level.num_yam_contents != STD_ELEMENT_CONTENTS)
{
- putFileChunk(file, "CNT2", LEVEL_CHUNK_CNT2_SIZE, BYTE_ORDER_BIG_ENDIAN);
+ putFileChunkBE(file, "CNT2", LEVEL_CHUNK_CNT2_SIZE);
SaveLevel_CNT2(file, &level, EL_MAMPFER);
}
if (level.encoding_16bit_amoeba)
{
- putFileChunk(file, "CNT2", LEVEL_CHUNK_CNT2_SIZE, BYTE_ORDER_BIG_ENDIAN);
+ putFileChunkBE(file, "CNT2", LEVEL_CHUNK_CNT2_SIZE);
SaveLevel_CNT2(file, &level, EL_AMOEBE_BD);
}
SetFilePermissions(filename, PERMS_PRIVATE);
}
+
+/* ========================================================================= */
+/* tape file functions */
+/* ========================================================================= */
+
static void setTapeInfoToDefaults()
{
int i;
/* 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 */
static int LoadTape_VERS(FILE *file, int chunk_size, struct TapeInfo *tape)
{
- ReadChunk_VERS(file, &(tape->file_version), &(tape->game_version));
+ tape->file_version = getFileVersion(file);
+ tape->game_version = getFileVersion(file);
return chunk_size;
}
{
int i;
- tape->random_seed = getFile32BitInteger(file, BYTE_ORDER_BIG_ENDIAN);
- tape->date = getFile32BitInteger(file, BYTE_ORDER_BIG_ENDIAN);
- tape->length = getFile32BitInteger(file, BYTE_ORDER_BIG_ENDIAN);
+ tape->random_seed = getFile32BitBE(file);
+ tape->date = getFile32BitBE(file);
+ tape->length = getFile32BitBE(file);
/* read header fields that are new since version 1.2 */
if (tape->file_version >= FILE_VERSION_1_2)
{
byte store_participating_players = fgetc(file);
-
- ReadUnusedBytesFromFile(file, TAPE_HEADER_UNUSED);
+ int engine_version;
/* since version 1.2, tapes store which players participate in the tape */
tape->num_participating_players = 0;
tape->num_participating_players++;
}
}
+
+ ReadUnusedBytesFromFile(file, TAPE_HEADER_UNUSED);
+
+ engine_version = getFileVersion(file);
+ if (engine_version > 0)
+ tape->engine_version = engine_version;
}
return chunk_size;
}
else if (tape->file_version < FILE_VERSION_2_0)
{
+ /* convert pre-2.0 tapes to new tape format */
+
if (tape->pos[i].delay > 1)
{
/* action part */
if (!(file = fopen(filename, MODE_READ)))
return;
- getFileChunk(file, chunk_name, NULL, BYTE_ORDER_BIG_ENDIAN);
+ getFileChunkBE(file, chunk_name, NULL);
if (strcmp(chunk_name, "RND1") == 0)
{
- getFile32BitInteger(file, BYTE_ORDER_BIG_ENDIAN); /* not used */
+ getFile32BitBE(file); /* not used */
- getFileChunk(file, chunk_name, NULL, BYTE_ORDER_BIG_ENDIAN);
+ getFileChunkBE(file, chunk_name, NULL);
if (strcmp(chunk_name, "TAPE") != 0)
{
Error(ERR_WARN, "unknown format of tape file '%s'", filename);
{ NULL, 0, NULL }
};
- while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_BIG_ENDIAN))
+ while (getFileChunkBE(file, chunk_name, &chunk_size))
{
int i = 0;
tape.length_seconds = GetTapeLength();
}
+static void SaveTape_VERS(FILE *file, struct TapeInfo *tape)
+{
+ putFileVersion(file, tape->file_version);
+ putFileVersion(file, tape->game_version);
+}
+
static void SaveTape_HEAD(FILE *file, struct TapeInfo *tape)
{
int i;
if (tape->player_participates[i])
store_participating_players |= (1 << i);
- putFile32BitInteger(file, tape->random_seed, BYTE_ORDER_BIG_ENDIAN);
- putFile32BitInteger(file, tape->date, BYTE_ORDER_BIG_ENDIAN);
- putFile32BitInteger(file, tape->length, BYTE_ORDER_BIG_ENDIAN);
+ putFile32BitBE(file, tape->random_seed);
+ putFile32BitBE(file, tape->date);
+ putFile32BitBE(file, tape->length);
fputc(store_participating_players, file);
+ /* unused bytes not at the end here for 4-byte alignment of engine_version */
WriteUnusedBytesToFile(file, TAPE_HEADER_UNUSED);
+
+ putFileVersion(file, tape->engine_version);
}
static void SaveTape_BODY(FILE *file, struct TapeInfo *tape)
return;
}
+ tape.file_version = FILE_VERSION_ACTUAL;
+ tape.game_version = GAME_VERSION_ACTUAL;
+
/* count number of participating players */
for(i=0; i<MAX_PLAYERS; i++)
if (tape.player_participates[i])
body_chunk_size = (num_participating_players + 1) * tape.length;
- putFileChunk(file, "RND1", CHUNK_SIZE_UNDEFINED, BYTE_ORDER_BIG_ENDIAN);
- putFileChunk(file, "TAPE", CHUNK_SIZE_NONE, BYTE_ORDER_BIG_ENDIAN);
+ putFileChunkBE(file, "RND1", CHUNK_SIZE_UNDEFINED);
+ putFileChunkBE(file, "TAPE", CHUNK_SIZE_NONE);
- putFileChunk(file, "VERS", FILE_VERS_CHUNK_SIZE, BYTE_ORDER_BIG_ENDIAN);
- WriteChunk_VERS(file, FILE_VERSION_ACTUAL, GAME_VERSION_ACTUAL);
+ putFileChunkBE(file, "VERS", FILE_VERS_CHUNK_SIZE);
+ SaveTape_VERS(file, &tape);
- putFileChunk(file, "HEAD", TAPE_HEADER_SIZE, BYTE_ORDER_BIG_ENDIAN);
+ putFileChunkBE(file, "HEAD", TAPE_HEADER_SIZE);
SaveTape_HEAD(file, &tape);
- putFileChunk(file, "BODY", body_chunk_size, BYTE_ORDER_BIG_ENDIAN);
+ putFileChunkBE(file, "BODY", body_chunk_size);
SaveTape_BODY(file, &tape);
fclose(file);
printf("\n");
printf("-------------------------------------------------------------------------------\n");
- printf("Tape of Level %d (file version %06d, game version %06d\n",
+ printf("Tape of Level %d (file version %06d, game version %06d)\n",
tape->level_nr, tape->file_version, tape->game_version);
printf("-------------------------------------------------------------------------------\n");
printf("-------------------------------------------------------------------------------\n");
}
+
+/* ========================================================================= */
+/* score file functions */
+/* ========================================================================= */
+
void LoadScore(int level_nr)
{
int i;
SetFilePermissions(filename, PERMS_PUBLIC);
}
+
+
+/* ========================================================================= */
+/* setup file functions */
+/* ========================================================================= */
+
+#define TOKEN_STR_PLAYER_PREFIX "player_"
+
+/* global setup */
+#define SETUP_TOKEN_PLAYER_NAME 0
+#define SETUP_TOKEN_SOUND 1
+#define SETUP_TOKEN_SOUND_LOOPS 2
+#define SETUP_TOKEN_SOUND_MUSIC 3
+#define SETUP_TOKEN_SOUND_SIMPLE 4
+#define SETUP_TOKEN_TOONS 5
+#define SETUP_TOKEN_SCROLL_DELAY 6
+#define SETUP_TOKEN_SOFT_SCROLLING 7
+#define SETUP_TOKEN_FADING 8
+#define SETUP_TOKEN_AUTORECORD 9
+#define SETUP_TOKEN_QUICK_DOORS 10
+#define SETUP_TOKEN_TEAM_MODE 11
+#define SETUP_TOKEN_HANDICAP 12
+#define SETUP_TOKEN_TIME_LIMIT 13
+#define SETUP_TOKEN_FULLSCREEN 14
+#define SETUP_TOKEN_ASK_ON_ESCAPE 15
+#define SETUP_TOKEN_GRAPHICS_SET 16
+#define SETUP_TOKEN_SOUNDS_SET 17
+#define SETUP_TOKEN_MUSIC_SET 18
+#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 19
+#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 20
+#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 21
+
+#define NUM_GLOBAL_SETUP_TOKENS 22
+
+/* shortcut setup */
+#define SETUP_TOKEN_SAVE_GAME 0
+#define SETUP_TOKEN_LOAD_GAME 1
+#define SETUP_TOKEN_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 NUM_PLAYER_SETUP_TOKENS 16
+
+static struct SetupInfo si;
+static struct SetupShortcutInfo ssi;
+static struct SetupInputInfo sii;
+
+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.sound_music, "background_music" },
+ { TYPE_SWITCH, &si.sound_simple, "simple_sound_effects" },
+ { TYPE_SWITCH, &si.toons, "toons" },
+ { TYPE_SWITCH, &si.scroll_delay, "scroll_delay" },
+ { TYPE_SWITCH, &si.soft_scrolling, "soft_scrolling" },
+ { TYPE_SWITCH, &si.fading, "screen_fading" },
+ { TYPE_SWITCH, &si.autorecord, "automatic_tape_recording" },
+ { TYPE_SWITCH, &si.quick_doors, "quick_doors" },
+ { TYPE_SWITCH, &si.team_mode, "team_mode" },
+ { TYPE_SWITCH, &si.handicap, "handicap" },
+ { TYPE_SWITCH, &si.time_limit, "time_limit" },
+ { TYPE_SWITCH, &si.fullscreen, "fullscreen" },
+ { TYPE_SWITCH, &si.ask_on_escape, "ask_on_escape" },
+ { TYPE_STRING, &si.graphics_set, "graphics_set" },
+ { TYPE_STRING, &si.sounds_set, "sounds_set" },
+ { TYPE_STRING, &si.music_set, "music_set" },
+ { TYPE_SWITCH, &si.override_level_graphics, "override_level_graphics" },
+ { TYPE_SWITCH, &si.override_level_sounds, "override_level_sounds" },
+ { TYPE_SWITCH, &si.override_level_music, "override_level_music" },
+};
+
+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_INTEGER, &sii.joy.xmiddle, ".joy.xmiddle" },
+ { TYPE_INTEGER, &sii.joy.xright, ".joy.xright" },
+ { TYPE_INTEGER, &sii.joy.yupper, ".joy.yupper" },
+ { TYPE_INTEGER, &sii.joy.ymiddle, ".joy.ymiddle" },
+ { TYPE_INTEGER, &sii.joy.ylower, ".joy.ylower" },
+ { TYPE_INTEGER, &sii.joy.snap, ".joy.snap_field" },
+ { TYPE_INTEGER, &sii.joy.bomb, ".joy.place_bomb" },
+ { TYPE_KEY_X11, &sii.key.left, ".key.move_left" },
+ { TYPE_KEY_X11, &sii.key.right, ".key.move_right" },
+ { TYPE_KEY_X11, &sii.key.up, ".key.move_up" },
+ { TYPE_KEY_X11, &sii.key.down, ".key.move_down" },
+ { TYPE_KEY_X11, &sii.key.snap, ".key.snap_field" },
+ { TYPE_KEY_X11, &sii.key.bomb, ".key.place_bomb" }
+};
+
+static void setSetupInfoToDefaults(struct SetupInfo *si)
+{
+ int i;
+
+ si->player_name = getStringCopy(getLoginName());
+
+ si->sound = TRUE;
+ 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 = TRUE;
+ si->soft_scrolling = TRUE;
+ si->fading = FALSE;
+ si->autorecord = TRUE;
+ si->quick_doors = FALSE;
+ si->team_mode = FALSE;
+ si->handicap = TRUE;
+ si->time_limit = TRUE;
+ si->fullscreen = FALSE;
+ si->ask_on_escape = TRUE;
+
+ si->graphics_set = getStringCopy(GRAPHICS_SUBDIR);
+ si->sounds_set = getStringCopy(SOUNDS_SUBDIR);
+ si->music_set = getStringCopy(MUSIC_SUBDIR);
+ si->override_level_graphics = FALSE;
+ si->override_level_sounds = FALSE;
+ si->override_level_music = FALSE;
+
+ si->shortcut.save_game = DEFAULT_KEY_SAVE_GAME;
+ si->shortcut.load_game = DEFAULT_KEY_LOAD_GAME;
+ si->shortcut.toggle_pause = DEFAULT_KEY_TOGGLE_PAUSE;
+
+ for (i=0; i<MAX_PLAYERS; i++)
+ {
+ si->input[i].use_joystick = FALSE;
+ si->input[i].joy.device_name=getStringCopy(getDeviceNameFromJoystickNr(i));
+ si->input[i].joy.xleft = JOYSTICK_XLEFT;
+ si->input[i].joy.xmiddle = JOYSTICK_XMIDDLE;
+ si->input[i].joy.xright = JOYSTICK_XRIGHT;
+ si->input[i].joy.yupper = JOYSTICK_YUPPER;
+ si->input[i].joy.ymiddle = JOYSTICK_YMIDDLE;
+ 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 : 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);
+ }
+}
+
+static void decodeSetupFileList(struct SetupFileList *setup_file_list)
+{
+ int i, pnr;
+
+ if (!setup_file_list)
+ 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));
+ setup = si;
+
+ /* 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));
+ setup.shortcut = ssi;
+
+ /* player setup */
+ for (pnr=0; pnr<MAX_PLAYERS; pnr++)
+ {
+ char prefix[30];
+
+ sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1);
+
+ sii = setup.input[pnr];
+ for (i=0; i<NUM_PLAYER_SETUP_TOKENS; i++)
+ {
+ char full_token[100];
+
+ sprintf(full_token, "%s%s", prefix, player_setup_tokens[i].text);
+ setSetupInfo(player_setup_tokens, i,
+ getTokenValue(setup_file_list, full_token));
+ }
+ setup.input[pnr] = sii;
+ }
+}
+
+void LoadSetup()
+{
+ char *filename = getSetupFilename();
+ struct SetupFileList *setup_file_list = NULL;
+
+ /* always start with reliable default values */
+ setSetupInfoToDefaults(&setup);
+
+ setup_file_list = loadSetupFileList(filename);
+
+ if (setup_file_list)
+ {
+ checkSetupFileListIdentifier(setup_file_list, getCookie("SETUP"));
+ decodeSetupFileList(setup_file_list);
+
+ setup.direct_draw = !setup.double_buffering;
+
+ freeSetupFileList(setup_file_list);
+
+ /* 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;
+ }
+ }
+ else
+ Error(ERR_WARN, "using default setup values");
+}
+
+void SaveSetup()
+{
+ char *filename = getSetupFilename();
+ FILE *file;
+ int i, pnr;
+
+ InitUserDataDirectory();
+
+ if (!(file = fopen(filename, MODE_WRITE)))
+ {
+ Error(ERR_WARN, "cannot write setup file '%s'", filename);
+ return;
+ }
+
+ fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
+ getCookie("SETUP")));
+ fprintf(file, "\n");
+
+ /* global setup */
+ 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)
+ fprintf(file, "\n");
+ }
+
+ /* shortcut setup */
+ ssi = setup.shortcut;
+ fprintf(file, "\n");
+ for (i=0; i<NUM_SHORTCUT_SETUP_TOKENS; i++)
+ fprintf(file, "%s\n", getSetupLine(shortcut_setup_tokens, "", i));
+
+ /* player setup */
+ for (pnr=0; pnr<MAX_PLAYERS; pnr++)
+ {
+ char prefix[30];
+
+ sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1);
+ fprintf(file, "\n");
+
+ sii = setup.input[pnr];
+ for (i=0; i<NUM_PLAYER_SETUP_TOKENS; i++)
+ fprintf(file, "%s\n", getSetupLine(player_setup_tokens, prefix, i));
+ }
+
+ fclose(file);
+
+ SetFilePermissions(filename, PERMS_PRIVATE);
+}