#include "files.h"
#include "init.h"
+#include "screens.h"
#include "tools.h"
#include "tape.h"
+#include "config.h"
#define ENABLE_UNUSED_CODE 0 /* currently unused functions */
#define ENABLE_HISTORIC_CHUNKS 0 /* only for historic reference */
#define TAPE_CHUNK_VERS_SIZE 8 /* size of file version chunk */
#define TAPE_CHUNK_HEAD_SIZE 20 /* size of tape file header */
-#define TAPE_CHUNK_HEAD_UNUSED 3 /* unused tape header bytes */
+#define TAPE_CHUNK_HEAD_UNUSED 2 /* unused tape header bytes */
#define LEVEL_CHUNK_CNT3_SIZE(x) (LEVEL_CHUNK_CNT3_HEADER + (x))
#define LEVEL_CHUNK_CUS3_SIZE(x) (2 + (x) * LEVEL_CPART_CUS3_SIZE)
&li.auto_exit_sokoban, FALSE
},
+ {
+ -1, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(10),
+ &li.auto_count_gems, FALSE
+ },
+
+ {
+ -1, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(11),
+ &li.solved_by_one_player, FALSE
+ },
+
{
-1, -1,
-1, -1,
TYPE_INTEGER, CONF_VALUE_8_BIT(4),
&li.game_of_life[3], 3
},
+ {
+ EL_GAME_OF_LIFE, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(5),
+ &li.use_life_bugs, FALSE
+ },
{
EL_BIOMAZE, -1,
&li.num_ball_contents, 4, MAX_ELEMENT_CONTENTS
},
- /* ---------- unused values ----------------------------------------------- */
+ {
+ EL_MM_MCDUFFIN, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(1),
+ &li.mm_laser_red, FALSE
+ },
+ {
+ EL_MM_MCDUFFIN, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(2),
+ &li.mm_laser_green, FALSE
+ },
+ {
+ EL_MM_MCDUFFIN, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(3),
+ &li.mm_laser_blue, TRUE
+ },
{
- EL_UNKNOWN, SAVE_CONF_NEVER,
+ EL_DF_LASER, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(1),
+ &li.df_laser_red, TRUE
+ },
+ {
+ EL_DF_LASER, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(2),
+ &li.df_laser_green, TRUE
+ },
+ {
+ EL_DF_LASER, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(3),
+ &li.df_laser_blue, FALSE
+ },
+
+ {
+ EL_MM_FUSE_ACTIVE, -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(1),
+ &li.mm_time_fuse, 25
+ },
+ {
+ EL_MM_BOMB, -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(1),
+ &li.mm_time_bomb, 75
+ },
+ {
+ EL_MM_GRAY_BALL, -1,
TYPE_INTEGER, CONF_VALUE_16_BIT(1),
- &li.score[SC_UNKNOWN_14], 10
+ &li.mm_time_ball, 75
},
+ {
+ EL_MM_STEEL_BLOCK, -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(1),
+ &li.mm_time_block, 75
+ },
+ {
+ EL_MM_LIGHTBALL, -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(1),
+ &li.score[SC_ELEM_BONUS], 10
+ },
+
+ /* ---------- unused values ----------------------------------------------- */
+
{
EL_UNKNOWN, SAVE_CONF_NEVER,
- TYPE_INTEGER, CONF_VALUE_16_BIT(2),
+ TYPE_INTEGER, CONF_VALUE_16_BIT(1),
&li.score[SC_UNKNOWN_15], 10
},
{ LEVEL_FILE_TYPE_DX, "DX" },
{ LEVEL_FILE_TYPE_SB, "SB" },
{ LEVEL_FILE_TYPE_DC, "DC" },
+ { LEVEL_FILE_TYPE_MM, "MM" },
+ { LEVEL_FILE_TYPE_MM, "DF" },
{ -1, NULL },
};
return FALSE;
}
-static struct DateInfo getCurrentDate()
+static struct DateInfo getCurrentDate(void)
{
time_t epoch_seconds = time(NULL);
struct tm *now = localtime(&epoch_seconds);
change->has_event[i] = FALSE;
}
-static void resetEventBits()
+static void resetEventBits(void)
{
int i;
setLevelInfoToDefaults_EM();
setLevelInfoToDefaults_SP();
+ setLevelInfoToDefaults_MM();
level->native_em_level = &native_em_level;
level->native_sp_level = &native_sp_level;
+ level->native_mm_level = &native_mm_level;
level->file_version = FILE_VERSION_ACTUAL;
level->game_version = GAME_VERSION_ACTUAL;
BorderElement = EL_STEELWALL;
+ /* detect custom elements when loading them */
+ level->file_has_custom_elements = FALSE;
+
/* set all bug compatibility flags to "false" => do not emulate this bug */
level->use_action_after_change_bug = FALSE;
level_file_info->nr = 0;
level_file_info->type = LEVEL_FILE_TYPE_UNKNOWN;
level_file_info->packed = FALSE;
- level_file_info->basename = NULL;
- level_file_info->filename = NULL;
+
+ setString(&level_file_info->basename, NULL);
+ setString(&level_file_info->filename, NULL);
}
int getMappedElement_SB(int, boolean);
-static void ActivateLevelTemplate()
+static void ActivateLevelTemplate(void)
{
int x, y;
/* overwrite all individual level settings from template level settings */
level = level_template;
+ /* restore level file info */
+ level.file_info = level_backup.file_info;
+
/* restore playfield size */
level.fieldx = level_backup.fieldx;
level.fieldy = level_backup.fieldy;
static char *getLevelFilenameFromBasename(char *basename)
{
- static char *filename[2] = { NULL, NULL };
- int pos = (strEqual(basename, LEVELTEMPLATE_FILENAME) ? 0 : 1);
+ static char *filename = NULL;
- checked_free(filename[pos]);
+ checked_free(filename);
- filename[pos] = getPath2(getCurrentLevelDir(), basename);
+ filename = getPath2(getCurrentLevelDir(), basename);
- return filename[pos];
+ return filename;
}
static int getFileTypeFromBasename(char *basename)
return LEVEL_FILE_TYPE_UNKNOWN;
}
+static int getFileTypeFromMagicBytes(char *filename, int type)
+{
+ File *file;
+
+ if ((file = openFile(filename, MODE_READ)))
+ {
+ char chunk_name[CHUNK_ID_LEN + 1];
+
+ getFileChunkBE(file, chunk_name, NULL);
+
+ if (strEqual(chunk_name, "MMII") ||
+ strEqual(chunk_name, "MIRR"))
+ type = LEVEL_FILE_TYPE_MM;
+
+ closeFile(file);
+ }
+
+ return type;
+}
+
static boolean checkForPackageFromBasename(char *basename)
{
/* !!! WON'T WORK ANYMORE IF getFileTypeFromBasename() ALSO DETECTS !!!
{
lfi->type = type;
lfi->packed = FALSE;
- lfi->basename = getSingleLevelBasename(lfi->nr, lfi->type);
- lfi->filename = getLevelFilenameFromBasename(lfi->basename);
+
+ setString(&lfi->basename, getSingleLevelBasename(lfi->nr, lfi->type));
+ setString(&lfi->filename, getLevelFilenameFromBasename(lfi->basename));
}
#endif
lfi->type = type;
lfi->packed = FALSE;
- lfi->basename = basename;
- lfi->filename = getLevelFilenameFromBasename(lfi->basename);
+
+ setString(&lfi->basename, basename);
+ setString(&lfi->filename, getLevelFilenameFromBasename(lfi->basename));
}
static void setLevelFileInfo_PackedLevelFilename(struct LevelFileInfo *lfi,
{
lfi->type = type;
lfi->packed = TRUE;
- lfi->basename = getPackedLevelBasename(lfi->type);
- lfi->filename = getLevelFilenameFromBasename(lfi->basename);
+
+ setString(&lfi->basename, getPackedLevelBasename(lfi->type));
+ setString(&lfi->filename, getLevelFilenameFromBasename(lfi->basename));
}
static int getFiletypeFromID(char *filetype_id)
return filetype;
}
-char *getLocalLevelTemplateFilename()
+char *getLocalLevelTemplateFilename(void)
{
return getDefaultLevelFilename(-1);
}
-char *getGlobalLevelTemplateFilename()
+char *getGlobalLevelTemplateFilename(void)
{
/* global variable "leveldir_current" must be modified in the loop below */
LevelDirTree *leveldir_current_last = leveldir_current;
getSingleLevelBasename(-1));
/* replace local level template filename with global template filename */
- lfi->filename = getGlobalLevelTemplateFilename();
+ setString(&lfi->filename, getGlobalLevelTemplateFilename());
/* no fallback if template file not existing */
return;
if (fileExists(lfi->filename))
return;
}
+ else if (leveldir_current->level_filetype != NULL)
+ {
+ int filetype = getFiletypeFromID(leveldir_current->level_filetype);
+
+ /* check for specified native level file with standard file name */
+ setLevelFileInfo_FormatLevelFilename(lfi, filetype,
+ "%03d.%s", nr, LEVELFILE_EXTENSION);
+ if (fileExists(lfi->filename))
+ return;
+ }
/* check for native Rocks'n'Diamonds level file */
setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
{
if (lfi->type == LEVEL_FILE_TYPE_UNKNOWN)
lfi->type = getFileTypeFromBasename(lfi->basename);
+
+ if (lfi->type == LEVEL_FILE_TYPE_RND)
+ lfi->type = getFileTypeFromMagicBytes(lfi->filename, lfi->type);
}
static void setLevelFileInfo(struct LevelFileInfo *level_file_info, int nr)
determineLevelFileInfo_Filetype(level_file_info);
}
+static void copyLevelFileInfo(struct LevelFileInfo *lfi_from,
+ struct LevelFileInfo *lfi_to)
+{
+ lfi_to->nr = lfi_from->nr;
+ lfi_to->type = lfi_from->type;
+ lfi_to->packed = lfi_from->packed;
+
+ setString(&lfi_to->basename, lfi_from->basename);
+ setString(&lfi_to->filename, lfi_from->filename);
+}
+
/* ------------------------------------------------------------------------- */
/* functions for loading R'n'D level */
/* ------------------------------------------------------------------------- */
-int getMappedElement(int element)
+static int getMappedElement(int element)
{
/* remap some (historic, now obsolete) elements */
return element;
}
-int getMappedElementByVersion(int element, int game_version)
+static int getMappedElementByVersion(int element, int game_version)
{
/* remap some elements due to certain game version */
element_info[element].push_delay_random = 8;
}
+ level->file_has_custom_elements = TRUE;
+
return chunk_size;
}
Error(ERR_WARN, "invalid custom element number %d", element);
}
+ level->file_has_custom_elements = TRUE;
+
return chunk_size;
}
ei->modified_settings = TRUE;
}
+ level->file_has_custom_elements = TRUE;
+
return chunk_size;
}
/* mark this custom element as modified */
ei->modified_settings = TRUE;
+ level->file_has_custom_elements = TRUE;
+
return chunk_size;
}
/* mark this group element as modified */
element_info[element].modified_settings = TRUE;
+ level->file_has_custom_elements = TRUE;
+
return chunk_size;
}
break;
}
+ level->file_has_custom_elements = TRUE;
+
return real_chunk_size;
}
*ei = xx_ei;
*group = xx_group;
+ level->file_has_custom_elements = TRUE;
+
return real_chunk_size;
}
/* functions for loading EM level */
/* ------------------------------------------------------------------------- */
-void CopyNativeLevel_RND_to_EM(struct LevelInfo *level)
+static void CopyNativeLevel_RND_to_EM(struct LevelInfo *level)
{
static int ball_xy[8][2] =
{
}
}
-void CopyNativeLevel_EM_to_RND(struct LevelInfo *level)
+static void CopyNativeLevel_EM_to_RND(struct LevelInfo *level)
{
static int ball_xy[8][2] =
{
/* functions for loading SP level */
/* ------------------------------------------------------------------------- */
-void CopyNativeLevel_RND_to_SP(struct LevelInfo *level)
+static void CopyNativeLevel_RND_to_SP(struct LevelInfo *level)
{
struct LevelInfo_SP *level_sp = level->native_sp_level;
LevelInfoType *header = &level_sp->header;
}
}
-void CopyNativeLevel_SP_to_RND(struct LevelInfo *level)
+static void CopyNativeLevel_SP_to_RND(struct LevelInfo *level)
{
struct LevelInfo_SP *level_sp = level->native_sp_level;
LevelInfoType *header = &level_sp->header;
- int i, x, y;
+ boolean num_invalid_elements = 0;
+ int i, j, x, y;
level->fieldx = level_sp->width;
level->fieldy = level_sp->height;
int element_new = getMappedElement(map_element_SP_to_RND(element_old));
if (element_new == EL_UNKNOWN)
- Error(ERR_WARN, "invalid element %d at position %d, %d",
+ {
+ num_invalid_elements++;
+
+ Error(ERR_DEBUG, "invalid element %d at position %d, %d",
element_old, x, y);
+ }
level->field[x][y] = element_new;
}
}
+ if (num_invalid_elements > 0)
+ Error(ERR_WARN, "found %d invalid elements%s", num_invalid_elements,
+ (!options.debug ? " (use '--debug' for more details)" : ""));
+
for (i = 0; i < MAX_PLAYERS; i++)
level->initial_player_gravity[i] =
(header->InitialGravity == 1 ? TRUE : FALSE);
+ /* skip leading spaces */
for (i = 0; i < SP_LEVEL_NAME_LEN; i++)
- level->name[i] = header->LevelTitle[i];
- level->name[SP_LEVEL_NAME_LEN] = '\0';
+ if (header->LevelTitle[i] != ' ')
+ break;
+
+ /* copy level title */
+ for (j = 0; i < SP_LEVEL_NAME_LEN; i++, j++)
+ level->name[j] = header->LevelTitle[i];
+ level->name[j] = '\0';
+
+ /* cut trailing spaces */
+ for (; j > 0; j--)
+ if (level->name[j - 1] == ' ' && level->name[j] == '\0')
+ level->name[j - 1] = '\0';
level->gems_needed = header->InfotronsNeeded;
level_sp->header.DemoRandomSeed = tape.random_seed;
demo->length = 0;
+
for (i = 0; i < tape.length; i++)
{
int demo_action = map_key_RND_to_SP(tape.pos[i].action[0]);
int demo_repeat = tape.pos[i].delay;
+ int demo_entries = (demo_repeat + 15) / 16;
+
+ if (demo->length + demo_entries >= SP_MAX_TAPE_LEN)
+ {
+ Error(ERR_WARN, "tape truncated: size exceeds maximum SP demo size %d",
+ SP_MAX_TAPE_LEN);
+
+ break;
+ }
for (j = 0; j < demo_repeat / 16; j++)
demo->data[demo->length++] = 0xf0 | demo_action;
demo->data[demo->length++] = ((demo_repeat % 16 - 1) << 4) | demo_action;
}
- demo->data[demo->length++] = 0xff;
-
demo->is_available = TRUE;
}
-static void setTapeInfoToDefaults();
+static void setTapeInfoToDefaults(void);
static void CopyNativeTape_SP_to_RND(struct LevelInfo *level)
{
return;
tape.level_nr = demo->level_nr; /* (currently not used) */
- tape.length = demo->length - 1; /* without "end of demo" byte */
tape.random_seed = level_sp->header.DemoRandomSeed;
TapeSetDateFromEpochSeconds(getFileTimestampEpochSeconds(filename));
- for (i = 0; i < demo->length - 1; i++)
+ tape.counter = 0;
+ tape.pos[tape.counter].delay = 0;
+
+ for (i = 0; i < demo->length; i++)
{
int demo_action = demo->data[i] & 0x0f;
int demo_repeat = (demo->data[i] & 0xf0) >> 4;
+ int tape_action = map_key_SP_to_RND(demo_action);
+ int tape_repeat = demo_repeat + 1;
+ byte action[MAX_PLAYERS] = { tape_action, 0, 0, 0 };
+ boolean success = 0;
+ int j;
+
+ for (j = 0; j < tape_repeat; j++)
+ success = TapeAddAction(action);
- tape.pos[i].action[0] = map_key_SP_to_RND(demo_action);
- tape.pos[i].delay = demo_repeat + 1;
+ if (!success)
+ {
+ Error(ERR_WARN, "SP demo truncated: size exceeds maximum tape size %d",
+ MAX_TAPE_LEN);
+
+ break;
+ }
}
- tape.length_frames = GetTapeLengthFrames();
- tape.length_seconds = GetTapeLengthSeconds();
+ TapeHaltRecording();
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* functions for loading MM level */
+/* ------------------------------------------------------------------------- */
+
+static void CopyNativeLevel_RND_to_MM(struct LevelInfo *level)
+{
+ struct LevelInfo_MM *level_mm = level->native_mm_level;
+ int x, y;
+
+ level_mm->fieldx = MIN(level->fieldx, MM_MAX_PLAYFIELD_WIDTH);
+ level_mm->fieldy = MIN(level->fieldy, MM_MAX_PLAYFIELD_HEIGHT);
+
+ level_mm->time = level->time;
+ level_mm->kettles_needed = level->gems_needed;
+ level_mm->auto_count_kettles = level->auto_count_gems;
+
+ level_mm->laser_red = level->mm_laser_red;
+ level_mm->laser_green = level->mm_laser_green;
+ level_mm->laser_blue = level->mm_laser_blue;
+
+ strcpy(level_mm->name, level->name);
+ strcpy(level_mm->author, level->author);
+
+ level_mm->score[SC_EMERALD] = level->score[SC_EMERALD];
+ level_mm->score[SC_PACMAN] = level->score[SC_PACMAN];
+ level_mm->score[SC_KEY] = level->score[SC_KEY];
+ level_mm->score[SC_TIME_BONUS] = level->score[SC_TIME_BONUS];
+ level_mm->score[SC_ELEM_BONUS] = level->score[SC_ELEM_BONUS];
+
+ level_mm->amoeba_speed = level->amoeba_speed;
+ level_mm->time_fuse = level->mm_time_fuse;
+ level_mm->time_bomb = level->mm_time_bomb;
+ level_mm->time_ball = level->mm_time_ball;
+ level_mm->time_block = level->mm_time_block;
+
+ for (x = 0; x < level->fieldx; x++)
+ for (y = 0; y < level->fieldy; y++)
+ Ur[x][y] =
+ level_mm->field[x][y] = map_element_RND_to_MM(level->field[x][y]);
+}
+
+static void CopyNativeLevel_MM_to_RND(struct LevelInfo *level)
+{
+ struct LevelInfo_MM *level_mm = level->native_mm_level;
+ int x, y;
+
+ level->fieldx = MIN(level_mm->fieldx, MAX_LEV_FIELDX);
+ level->fieldy = MIN(level_mm->fieldy, MAX_LEV_FIELDY);
+
+ level->time = level_mm->time;
+ level->gems_needed = level_mm->kettles_needed;
+ level->auto_count_gems = level_mm->auto_count_kettles;
+
+ level->mm_laser_red = level_mm->laser_red;
+ level->mm_laser_green = level_mm->laser_green;
+ level->mm_laser_blue = level_mm->laser_blue;
+
+ strcpy(level->name, level_mm->name);
+
+ /* only overwrite author from 'levelinfo.conf' if author defined in level */
+ if (!strEqual(level_mm->author, ANONYMOUS_NAME))
+ strcpy(level->author, level_mm->author);
+
+ level->score[SC_EMERALD] = level_mm->score[SC_EMERALD];
+ level->score[SC_PACMAN] = level_mm->score[SC_PACMAN];
+ level->score[SC_KEY] = level_mm->score[SC_KEY];
+ level->score[SC_TIME_BONUS] = level_mm->score[SC_TIME_BONUS];
+ level->score[SC_ELEM_BONUS] = level_mm->score[SC_ELEM_BONUS];
+
+ level->amoeba_speed = level_mm->amoeba_speed;
+ level->mm_time_fuse = level_mm->time_fuse;
+ level->mm_time_bomb = level_mm->time_bomb;
+ level->mm_time_ball = level_mm->time_ball;
+ level->mm_time_block = level_mm->time_block;
+
+ for (x = 0; x < level->fieldx; x++)
+ for (y = 0; y < level->fieldy; y++)
+ level->field[x][y] = map_element_MM_to_RND(level_mm->field[x][y]);
}
#define DC_LEVEL_HEADER_SIZE 344
-unsigned short getDecodedWord_DC(unsigned short data_encoded, boolean init)
+static unsigned short getDecodedWord_DC(unsigned short data_encoded,
+ boolean init)
{
static int last_data_encoded;
static int offset1;
return data_decoded;
}
-int getMappedElement_DC(int element)
+static int getMappedElement_DC(int element)
{
switch (element)
{
level->no_valid_file = TRUE;
}
+static void LoadLevelFromFileInfo_MM(struct LevelInfo *level,
+ struct LevelFileInfo *level_file_info,
+ boolean level_info_only)
+{
+ if (!LoadNativeLevel_MM(level_file_info->filename, level_info_only))
+ level->no_valid_file = TRUE;
+}
+
void CopyNativeLevel_RND_to_Native(struct LevelInfo *level)
{
if (level->game_engine_type == GAME_ENGINE_TYPE_EM)
CopyNativeLevel_RND_to_EM(level);
else if (level->game_engine_type == GAME_ENGINE_TYPE_SP)
CopyNativeLevel_RND_to_SP(level);
+ else if (level->game_engine_type == GAME_ENGINE_TYPE_MM)
+ CopyNativeLevel_RND_to_MM(level);
}
void CopyNativeLevel_Native_to_RND(struct LevelInfo *level)
CopyNativeLevel_EM_to_RND(level);
else if (level->game_engine_type == GAME_ENGINE_TYPE_SP)
CopyNativeLevel_SP_to_RND(level);
+ else if (level->game_engine_type == GAME_ENGINE_TYPE_MM)
+ CopyNativeLevel_MM_to_RND(level);
}
void SaveNativeLevel(struct LevelInfo *level)
level->game_engine_type = GAME_ENGINE_TYPE_SP;
break;
+ case LEVEL_FILE_TYPE_MM:
+ LoadLevelFromFileInfo_MM(level, level_file_info, level_info_only);
+ level->game_engine_type = GAME_ENGINE_TYPE_MM;
+ break;
+
case LEVEL_FILE_TYPE_DC:
LoadLevelFromFileInfo_DC(level, level_file_info, level_info_only);
break;
level_file_info.nr = 0; /* unknown level number */
level_file_info.type = LEVEL_FILE_TYPE_RND; /* no others supported yet */
- level_file_info.filename = filename;
+
+ setString(&level_file_info.filename, filename);
LoadLevelFromFileInfo(level, &level_file_info, FALSE);
}
-static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
+static void LoadLevel_InitVersion(struct LevelInfo *level)
{
int i, j;
level->extra_time_score = level->score[SC_TIME_BONUS];
}
+ /* game logic of "game of life" and "biomaze" was buggy before 4.1.1.1 */
+ if (level->game_version < VERSION_IDENT(4,1,1,1))
+ level->use_life_bugs = TRUE;
+
if (level->game_version < VERSION_IDENT(3,2,0,7))
{
/* default behaviour for snapping was "not continuous" before 3.2.0-7 */
/* EM style elements always chain-exploded in R'n'D engine before 3.2.6 */
if (level->game_version < VERSION_IDENT(3,2,6,0))
level->em_explodes_by_fire = TRUE;
+
+ /* levels were solved by the first player entering an exit up to 4.1.0.0 */
+ if (level->game_version <= VERSION_IDENT(4,1,0,0))
+ level->solved_by_one_player = TRUE;
}
-static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
+static void LoadLevel_InitStandardElements(struct LevelInfo *level)
{
- int i, j, x, y;
+ int i, x, y;
+
+ /* map elements that have changed in newer versions */
+ level->amoeba_content = getMappedElementByVersion(level->amoeba_content,
+ level->game_version);
+ for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
+ for (x = 0; x < 3; x++)
+ for (y = 0; y < 3; y++)
+ level->yamyam_content[i].e[x][y] =
+ getMappedElementByVersion(level->yamyam_content[i].e[x][y],
+ level->game_version);
+
+}
+
+static void LoadLevel_InitCustomElements(struct LevelInfo *level)
+{
+ int i, j;
/* map custom element change events that have changed in newer versions
(these following values were accidentally changed in version 3.0.1)
}
}
- /* map elements that have changed in newer versions */
- level->amoeba_content = getMappedElementByVersion(level->amoeba_content,
- level->game_version);
- for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
- for (x = 0; x < 3; x++)
- for (y = 0; y < 3; y++)
- level->yamyam_content[i].e[x][y] =
- getMappedElementByVersion(level->yamyam_content[i].e[x][y],
- level->game_version);
+ /* set some other uninitialized values of custom elements in older levels */
+ if (level->game_version < VERSION_IDENT(3,1,0,0))
+ {
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+
+ element_info[element].access_direction = MV_ALL_DIRECTIONS;
+
+ element_info[element].explosion_delay = 17;
+ element_info[element].ignition_delay = 8;
+ }
+ }
+}
+
+static void LoadLevel_InitElements(struct LevelInfo *level)
+{
+ LoadLevel_InitStandardElements(level);
+
+ if (level->file_has_custom_elements)
+ LoadLevel_InitCustomElements(level);
/* initialize element properties for level editor etc. */
InitElementPropertiesEngine(level->game_version);
- InitElementPropertiesAfterLoading(level->game_version);
InitElementPropertiesGfxElement();
}
-static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename)
+static void LoadLevel_InitPlayfield(struct LevelInfo *level)
{
int x, y;
SetBorderElement();
}
-static void LoadLevel_InitNativeEngines(struct LevelInfo *level,char *filename)
+static void LoadLevel_InitNativeEngines(struct LevelInfo *level)
{
struct LevelFileInfo *level_file_info = &level->file_info;
CopyNativeLevel_RND_to_Native(level);
}
-void LoadLevelTemplate(int nr)
+static void LoadLevelTemplate_LoadAndInit(void)
{
- char *filename;
-
- setLevelFileInfo(&level_template.file_info, nr);
- filename = level_template.file_info.filename;
-
LoadLevelFromFileInfo(&level_template, &level_template.file_info, FALSE);
- LoadLevel_InitVersion(&level_template, filename);
- LoadLevel_InitElements(&level_template, filename);
+ LoadLevel_InitVersion(&level_template);
+ LoadLevel_InitElements(&level_template);
ActivateLevelTemplate();
}
-void LoadLevel(int nr)
+void LoadLevelTemplate(int nr)
{
- char *filename;
+ if (!fileExists(getGlobalLevelTemplateFilename()))
+ {
+ Error(ERR_WARN, "no level template found for this level");
- setLevelFileInfo(&level.file_info, nr);
- filename = level.file_info.filename;
+ return;
+ }
+
+ setLevelFileInfo(&level_template.file_info, nr);
+
+ LoadLevelTemplate_LoadAndInit();
+}
+
+static void LoadNetworkLevelTemplate(struct NetworkLevelInfo *network_level)
+{
+ copyLevelFileInfo(&network_level->tmpl_info, &level_template.file_info);
+
+ LoadLevelTemplate_LoadAndInit();
+}
+static void LoadLevel_LoadAndInit(struct NetworkLevelInfo *network_level)
+{
LoadLevelFromFileInfo(&level, &level.file_info, FALSE);
if (level.use_custom_template)
- LoadLevelTemplate(-1);
+ {
+ if (network_level != NULL)
+ LoadNetworkLevelTemplate(network_level);
+ else
+ LoadLevelTemplate(-1);
+ }
- LoadLevel_InitVersion(&level, filename);
- LoadLevel_InitElements(&level, filename);
- LoadLevel_InitPlayfield(&level, filename);
+ LoadLevel_InitVersion(&level);
+ LoadLevel_InitElements(&level);
+ LoadLevel_InitPlayfield(&level);
- LoadLevel_InitNativeEngines(&level, filename);
+ LoadLevel_InitNativeEngines(&level);
+}
+
+void LoadLevel(int nr)
+{
+ SetLevelSetInfo(leveldir_current->identifier, nr);
+
+ setLevelFileInfo(&level.file_info, nr);
+
+ LoadLevel_LoadAndInit(NULL);
}
void LoadLevelInfoOnly(int nr)
LoadLevelFromFileInfo(&level, &level.file_info, TRUE);
}
+void LoadNetworkLevel(struct NetworkLevelInfo *network_level)
+{
+ SetLevelSetInfo(network_level->leveldir_identifier,
+ network_level->file_info.nr);
+
+ copyLevelFileInfo(&network_level->file_info, &level.file_info);
+
+ LoadLevel_LoadAndInit(network_level);
+}
+
static int SaveLevel_VERS(FILE *file, struct LevelInfo *level)
{
int chunk_size = 0;
SaveLevelFromFilename(&level, filename, FALSE);
}
-void SaveLevelTemplate()
+void SaveLevelTemplate(void)
{
char *filename = getLocalLevelTemplateFilename();
/* tape file functions */
/* ========================================================================= */
-static void setTapeInfoToDefaults()
+static void setTapeInfoToDefaults(void)
{
int i;
}
}
+ tape->use_mouse = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+
ReadUnusedBytesFromFile(file, TAPE_CHUNK_HEAD_UNUSED);
engine_version = getFileVersion(file);
static int LoadTape_BODY(File *file, int chunk_size, struct TapeInfo *tape)
{
int i, j;
- int chunk_size_expected =
- (tape->num_participating_players + 1) * tape->length;
+ int tape_pos_size =
+ (tape->use_mouse ? 3 : tape->num_participating_players) + 1;
+ int chunk_size_expected = tape_pos_size * tape->length;
if (chunk_size_expected != chunk_size)
{
for (i = 0; i < tape->length; i++)
{
if (i >= MAX_TAPE_LEN)
+ {
+ Error(ERR_WARN, "tape truncated -- size exceeds maximum tape size %d",
+ MAX_TAPE_LEN);
+
+ // tape too large; read and ignore remaining tape data from this chunk
+ for (;i < tape->length; i++)
+ ReadUnusedBytesFromFile(file, tape->num_participating_players + 1);
+
break;
+ }
- for (j = 0; j < MAX_PLAYERS; j++)
+ if (tape->use_mouse)
{
- tape->pos[i].action[j] = MV_NONE;
+ tape->pos[i].action[TAPE_ACTION_LX] = getFile8Bit(file);
+ tape->pos[i].action[TAPE_ACTION_LY] = getFile8Bit(file);
+ tape->pos[i].action[TAPE_ACTION_BUTTON] = getFile8Bit(file);
- if (tape->player_participates[j])
- tape->pos[i].action[j] = getFile8Bit(file);
+ tape->pos[i].action[TAPE_ACTION_UNUSED] = 0;
+ }
+ else
+ {
+ for (j = 0; j < MAX_PLAYERS; j++)
+ {
+ tape->pos[i].action[j] = MV_NONE;
+
+ if (tape->player_participates[j])
+ tape->pos[i].action[j] = getFile8Bit(file);
+ }
}
tape->pos[i].delay = getFile8Bit(file);
}
if (i != tape->length)
- chunk_size = (tape->num_participating_players + 1) * i;
+ chunk_size = tape_pos_size * i;
return chunk_size;
}
-void LoadTape_SokobanSolution(char *filename)
+static void LoadTape_SokobanSolution(char *filename)
{
File *file;
int move_delay = TILESIZE / level.initial_player_stepsize[0];
putFile8Bit(file, store_participating_players);
+ putFile8Bit(file, (tape->use_mouse ? 1 : 0));
+
/* unused bytes not at the end here for 4-byte alignment of engine_version */
WriteUnusedBytesToFile(file, TAPE_CHUNK_HEAD_UNUSED);
for (i = 0; i < tape->length; i++)
{
- for (j = 0; j < MAX_PLAYERS; j++)
- if (tape->player_participates[j])
- putFile8Bit(file, tape->pos[i].action[j]);
+ if (tape->use_mouse)
+ {
+ putFile8Bit(file, tape->pos[i].action[TAPE_ACTION_LX]);
+ putFile8Bit(file, tape->pos[i].action[TAPE_ACTION_LY]);
+ putFile8Bit(file, tape->pos[i].action[TAPE_ACTION_BUTTON]);
+ }
+ else
+ {
+ for (j = 0; j < MAX_PLAYERS; j++)
+ if (tape->player_participates[j])
+ putFile8Bit(file, tape->pos[i].action[j]);
+ }
putFile8Bit(file, tape->pos[i].delay);
}
char *filename = getTapeFilename(nr);
FILE *file;
int num_participating_players = 0;
+ int tape_pos_size;
int info_chunk_size;
int body_chunk_size;
int i;
if (tape.player_participates[i])
num_participating_players++;
+ tape_pos_size = (tape.use_mouse ? 3 : num_participating_players) + 1;
+
info_chunk_size = 2 + (strlen(tape.level_identifier) + 1) + 2;
- body_chunk_size = (num_participating_players + 1) * tape.length;
+ body_chunk_size = tape_pos_size * tape.length;
putFileChunkBE(file, "RND1", CHUNK_SIZE_UNDEFINED);
putFileChunkBE(file, "TAPE", CHUNK_SIZE_NONE);
tape.changed = FALSE;
}
-boolean SaveTapeChecked(int nr)
+static boolean SaveTapeCheckedExt(int nr, char *msg_replace, char *msg_saved)
{
char *filename = getTapeFilename(nr);
boolean new_tape = !fileExists(filename);
boolean tape_saved = FALSE;
- if (new_tape || Request("Replace old tape?", REQ_ASK))
+ if (new_tape || Request(msg_replace, REQ_ASK))
{
SaveTape(nr);
if (new_tape)
- Request("Tape saved!", REQ_CONFIRM);
+ Request(msg_saved, REQ_CONFIRM);
tape_saved = TRUE;
}
return tape_saved;
}
+boolean SaveTapeChecked(int nr)
+{
+ return SaveTapeCheckedExt(nr, "Replace old tape?", "Tape saved!");
+}
+
+boolean SaveTapeChecked_LevelSolved(int nr)
+{
+ return SaveTapeCheckedExt(nr, "Level solved! Replace old tape?",
+ "Level solved! Tape saved!");
+}
+
void DumpTape(struct TapeInfo *tape)
{
int tape_frame_counter;
char *filename = getScoreFilename(nr);
FILE *file;
- InitScoreDirectory(leveldir_current->subdir);
+ /* used instead of "leveldir_current->subdir" (for network games) */
+ InitScoreDirectory(levelset.identifier);
if (!(file = fopen(filename, MODE_WRITE)))
{
#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_SCROLL_DELAY_VALUE 7
-#define SETUP_TOKEN_ENGINE_SNAPSHOT_MODE 8
-#define SETUP_TOKEN_ENGINE_SNAPSHOT_MEMORY 9
-#define SETUP_TOKEN_FADE_SCREENS 10
-#define SETUP_TOKEN_AUTORECORD 11
-#define SETUP_TOKEN_SHOW_TITLESCREEN 12
-#define SETUP_TOKEN_QUICK_DOORS 13
-#define SETUP_TOKEN_TEAM_MODE 14
-#define SETUP_TOKEN_HANDICAP 15
-#define SETUP_TOKEN_SKIP_LEVELS 16
-#define SETUP_TOKEN_INCREMENT_LEVELS 17
-#define SETUP_TOKEN_TIME_LIMIT 18
-#define SETUP_TOKEN_FULLSCREEN 19
-#define SETUP_TOKEN_WINDOW_SCALING_PERCENT 20
-#define SETUP_TOKEN_WINDOW_SCALING_QUALITY 21
-#define SETUP_TOKEN_SCREEN_RENDERING_MODE 22
-#define SETUP_TOKEN_ASK_ON_ESCAPE 23
-#define SETUP_TOKEN_ASK_ON_ESCAPE_EDITOR 24
-#define SETUP_TOKEN_QUICK_SWITCH 25
-#define SETUP_TOKEN_INPUT_ON_FOCUS 26
-#define SETUP_TOKEN_PREFER_AGA_GRAPHICS 27
-#define SETUP_TOKEN_GAME_FRAME_DELAY 28
-#define SETUP_TOKEN_SP_SHOW_BORDER_ELEMENTS 29
-#define SETUP_TOKEN_SMALL_GAME_GRAPHICS 30
-#define SETUP_TOKEN_SHOW_SNAPSHOT_BUTTONS 31
-#define SETUP_TOKEN_GRAPHICS_SET 32
-#define SETUP_TOKEN_SOUNDS_SET 33
-#define SETUP_TOKEN_MUSIC_SET 34
-#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 35
-#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 36
-#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 37
-#define SETUP_TOKEN_VOLUME_SIMPLE 38
-#define SETUP_TOKEN_VOLUME_LOOPS 39
-#define SETUP_TOKEN_VOLUME_MUSIC 40
-#define SETUP_TOKEN_TOUCH_CONTROL_TYPE 41
-#define SETUP_TOKEN_TOUCH_MOVE_DISTANCE 42
-#define SETUP_TOKEN_TOUCH_DROP_DISTANCE 43
-
-#define NUM_GLOBAL_SETUP_TOKENS 44
+enum
+{
+ SETUP_TOKEN_PLAYER_NAME = 0,
+ SETUP_TOKEN_SOUND,
+ SETUP_TOKEN_SOUND_LOOPS,
+ SETUP_TOKEN_SOUND_MUSIC,
+ SETUP_TOKEN_SOUND_SIMPLE,
+ SETUP_TOKEN_TOONS,
+ SETUP_TOKEN_SCROLL_DELAY,
+ SETUP_TOKEN_SCROLL_DELAY_VALUE,
+ SETUP_TOKEN_ENGINE_SNAPSHOT_MODE,
+ SETUP_TOKEN_ENGINE_SNAPSHOT_MEMORY,
+ SETUP_TOKEN_FADE_SCREENS,
+ SETUP_TOKEN_AUTORECORD,
+ SETUP_TOKEN_SHOW_TITLESCREEN,
+ SETUP_TOKEN_QUICK_DOORS,
+ SETUP_TOKEN_TEAM_MODE,
+ SETUP_TOKEN_HANDICAP,
+ SETUP_TOKEN_SKIP_LEVELS,
+ SETUP_TOKEN_INCREMENT_LEVELS,
+ SETUP_TOKEN_AUTO_PLAY_NEXT_LEVEL,
+ SETUP_TOKEN_SKIP_SCORES_AFTER_GAME,
+ SETUP_TOKEN_TIME_LIMIT,
+ SETUP_TOKEN_FULLSCREEN,
+ SETUP_TOKEN_WINDOW_SCALING_PERCENT,
+ SETUP_TOKEN_WINDOW_SCALING_QUALITY,
+ SETUP_TOKEN_SCREEN_RENDERING_MODE,
+ SETUP_TOKEN_VSYNC_MODE,
+ SETUP_TOKEN_ASK_ON_ESCAPE,
+ SETUP_TOKEN_ASK_ON_ESCAPE_EDITOR,
+ SETUP_TOKEN_QUICK_SWITCH,
+ SETUP_TOKEN_INPUT_ON_FOCUS,
+ SETUP_TOKEN_PREFER_AGA_GRAPHICS,
+ SETUP_TOKEN_GAME_SPEED_EXTENDED,
+ SETUP_TOKEN_GAME_FRAME_DELAY,
+ SETUP_TOKEN_SP_SHOW_BORDER_ELEMENTS,
+ SETUP_TOKEN_SMALL_GAME_GRAPHICS,
+ SETUP_TOKEN_SHOW_SNAPSHOT_BUTTONS,
+ SETUP_TOKEN_GRAPHICS_SET,
+ SETUP_TOKEN_SOUNDS_SET,
+ SETUP_TOKEN_MUSIC_SET,
+ SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS,
+ SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS,
+ SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC,
+ SETUP_TOKEN_VOLUME_SIMPLE,
+ SETUP_TOKEN_VOLUME_LOOPS,
+ SETUP_TOKEN_VOLUME_MUSIC,
+ SETUP_TOKEN_NETWORK_MODE,
+ SETUP_TOKEN_NETWORK_PLAYER_NR,
+ SETUP_TOKEN_NETWORK_SERVER_HOSTNAME,
+ SETUP_TOKEN_TOUCH_CONTROL_TYPE,
+ SETUP_TOKEN_TOUCH_MOVE_DISTANCE,
+ SETUP_TOKEN_TOUCH_DROP_DISTANCE,
+ SETUP_TOKEN_TOUCH_TRANSPARENCY,
+ SETUP_TOKEN_TOUCH_DRAW_OUTLINED,
+ SETUP_TOKEN_TOUCH_DRAW_PRESSED,
+ SETUP_TOKEN_TOUCH_GRID_XSIZE_0,
+ SETUP_TOKEN_TOUCH_GRID_YSIZE_0,
+ SETUP_TOKEN_TOUCH_GRID_XSIZE_1,
+ SETUP_TOKEN_TOUCH_GRID_YSIZE_1,
+
+ NUM_GLOBAL_SETUP_TOKENS
+};
+
+/* auto setup */
+enum
+{
+ SETUP_TOKEN_AUTO_EDITOR_ZOOM_TILESIZE = 0,
+
+ NUM_AUTO_SETUP_TOKENS
+};
/* editor setup */
-#define SETUP_TOKEN_EDITOR_EL_CLASSIC 0
-#define SETUP_TOKEN_EDITOR_EL_CUSTOM 1
-#define SETUP_TOKEN_EDITOR_EL_USER_DEFINED 2
-#define SETUP_TOKEN_EDITOR_EL_DYNAMIC 3
-#define SETUP_TOKEN_EDITOR_EL_HEADLINES 4
-#define SETUP_TOKEN_EDITOR_SHOW_ELEMENT_TOKEN 5
+enum
+{
+ SETUP_TOKEN_EDITOR_EL_CLASSIC = 0,
+ SETUP_TOKEN_EDITOR_EL_CUSTOM,
+ SETUP_TOKEN_EDITOR_EL_USER_DEFINED,
+ SETUP_TOKEN_EDITOR_EL_DYNAMIC,
+ SETUP_TOKEN_EDITOR_EL_HEADLINES,
+ SETUP_TOKEN_EDITOR_SHOW_ELEMENT_TOKEN,
-#define NUM_EDITOR_SETUP_TOKENS 6
+ NUM_EDITOR_SETUP_TOKENS
+};
/* editor cascade setup */
-#define SETUP_TOKEN_EDITOR_CASCADE_BD 0
-#define SETUP_TOKEN_EDITOR_CASCADE_EM 1
-#define SETUP_TOKEN_EDITOR_CASCADE_EMC 2
-#define SETUP_TOKEN_EDITOR_CASCADE_RND 3
-#define SETUP_TOKEN_EDITOR_CASCADE_SB 4
-#define SETUP_TOKEN_EDITOR_CASCADE_SP 5
-#define SETUP_TOKEN_EDITOR_CASCADE_DC 6
-#define SETUP_TOKEN_EDITOR_CASCADE_DX 7
-#define SETUP_TOKEN_EDITOR_CASCADE_TEXT 8
-#define SETUP_TOKEN_EDITOR_CASCADE_STEELTEXT 9
-#define SETUP_TOKEN_EDITOR_CASCADE_CE 10
-#define SETUP_TOKEN_EDITOR_CASCADE_GE 11
-#define SETUP_TOKEN_EDITOR_CASCADE_REF 12
-#define SETUP_TOKEN_EDITOR_CASCADE_USER 13
-#define SETUP_TOKEN_EDITOR_CASCADE_DYNAMIC 14
-
-#define NUM_EDITOR_CASCADE_SETUP_TOKENS 15
+enum
+{
+ SETUP_TOKEN_EDITOR_CASCADE_BD = 0,
+ SETUP_TOKEN_EDITOR_CASCADE_EM,
+ SETUP_TOKEN_EDITOR_CASCADE_EMC,
+ SETUP_TOKEN_EDITOR_CASCADE_RND,
+ SETUP_TOKEN_EDITOR_CASCADE_SB,
+ SETUP_TOKEN_EDITOR_CASCADE_SP,
+ SETUP_TOKEN_EDITOR_CASCADE_DC,
+ SETUP_TOKEN_EDITOR_CASCADE_DX,
+ SETUP_TOKEN_EDITOR_CASCADE_TEXT,
+ SETUP_TOKEN_EDITOR_CASCADE_STEELTEXT,
+ SETUP_TOKEN_EDITOR_CASCADE_CE,
+ SETUP_TOKEN_EDITOR_CASCADE_GE,
+ SETUP_TOKEN_EDITOR_CASCADE_REF,
+ SETUP_TOKEN_EDITOR_CASCADE_USER,
+ SETUP_TOKEN_EDITOR_CASCADE_DYNAMIC,
+
+ NUM_EDITOR_CASCADE_SETUP_TOKENS
+};
/* shortcut setup */
-#define SETUP_TOKEN_SHORTCUT_SAVE_GAME 0
-#define SETUP_TOKEN_SHORTCUT_LOAD_GAME 1
-#define SETUP_TOKEN_SHORTCUT_TOGGLE_PAUSE 2
-#define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_1 3
-#define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_2 4
-#define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_3 5
-#define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_4 6
-#define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_ALL 7
-#define SETUP_TOKEN_SHORTCUT_TAPE_EJECT 8
-#define SETUP_TOKEN_SHORTCUT_TAPE_EXTRA 9
-#define SETUP_TOKEN_SHORTCUT_TAPE_STOP 10
-#define SETUP_TOKEN_SHORTCUT_TAPE_PAUSE 11
-#define SETUP_TOKEN_SHORTCUT_TAPE_RECORD 12
-#define SETUP_TOKEN_SHORTCUT_TAPE_PLAY 13
-#define SETUP_TOKEN_SHORTCUT_SOUND_SIMPLE 14
-#define SETUP_TOKEN_SHORTCUT_SOUND_LOOPS 15
-#define SETUP_TOKEN_SHORTCUT_SOUND_MUSIC 16
-#define SETUP_TOKEN_SHORTCUT_SNAP_LEFT 17
-#define SETUP_TOKEN_SHORTCUT_SNAP_RIGHT 18
-#define SETUP_TOKEN_SHORTCUT_SNAP_UP 19
-#define SETUP_TOKEN_SHORTCUT_SNAP_DOWN 20
-
-#define NUM_SHORTCUT_SETUP_TOKENS 21
+enum
+{
+ SETUP_TOKEN_SHORTCUT_SAVE_GAME = 0,
+ SETUP_TOKEN_SHORTCUT_LOAD_GAME,
+ SETUP_TOKEN_SHORTCUT_TOGGLE_PAUSE,
+ SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_1,
+ SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_2,
+ SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_3,
+ SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_4,
+ SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_ALL,
+ SETUP_TOKEN_SHORTCUT_TAPE_EJECT,
+ SETUP_TOKEN_SHORTCUT_TAPE_EXTRA,
+ SETUP_TOKEN_SHORTCUT_TAPE_STOP,
+ SETUP_TOKEN_SHORTCUT_TAPE_PAUSE,
+ SETUP_TOKEN_SHORTCUT_TAPE_RECORD,
+ SETUP_TOKEN_SHORTCUT_TAPE_PLAY,
+ SETUP_TOKEN_SHORTCUT_SOUND_SIMPLE,
+ SETUP_TOKEN_SHORTCUT_SOUND_LOOPS,
+ SETUP_TOKEN_SHORTCUT_SOUND_MUSIC,
+ SETUP_TOKEN_SHORTCUT_SNAP_LEFT,
+ SETUP_TOKEN_SHORTCUT_SNAP_RIGHT,
+ SETUP_TOKEN_SHORTCUT_SNAP_UP,
+ SETUP_TOKEN_SHORTCUT_SNAP_DOWN,
+
+ NUM_SHORTCUT_SETUP_TOKENS
+};
/* player setup */
-#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_DROP 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_DROP 15
-
-#define NUM_PLAYER_SETUP_TOKENS 16
+enum
+{
+ SETUP_TOKEN_PLAYER_USE_JOYSTICK = 0,
+ SETUP_TOKEN_PLAYER_JOY_DEVICE_NAME,
+ SETUP_TOKEN_PLAYER_JOY_XLEFT,
+ SETUP_TOKEN_PLAYER_JOY_XMIDDLE,
+ SETUP_TOKEN_PLAYER_JOY_XRIGHT,
+ SETUP_TOKEN_PLAYER_JOY_YUPPER,
+ SETUP_TOKEN_PLAYER_JOY_YMIDDLE,
+ SETUP_TOKEN_PLAYER_JOY_YLOWER,
+ SETUP_TOKEN_PLAYER_JOY_SNAP,
+ SETUP_TOKEN_PLAYER_JOY_DROP,
+ SETUP_TOKEN_PLAYER_KEY_LEFT,
+ SETUP_TOKEN_PLAYER_KEY_RIGHT,
+ SETUP_TOKEN_PLAYER_KEY_UP,
+ SETUP_TOKEN_PLAYER_KEY_DOWN,
+ SETUP_TOKEN_PLAYER_KEY_SNAP,
+ SETUP_TOKEN_PLAYER_KEY_DROP,
+
+ NUM_PLAYER_SETUP_TOKENS
+};
/* system setup */
-#define SETUP_TOKEN_SYSTEM_SDL_VIDEODRIVER 0
-#define SETUP_TOKEN_SYSTEM_SDL_AUDIODRIVER 1
-#define SETUP_TOKEN_SYSTEM_AUDIO_FRAGMENT_SIZE 2
+enum
+{
+ SETUP_TOKEN_SYSTEM_SDL_VIDEODRIVER = 0,
+ SETUP_TOKEN_SYSTEM_SDL_AUDIODRIVER,
+ SETUP_TOKEN_SYSTEM_AUDIO_FRAGMENT_SIZE,
-#define NUM_SYSTEM_SETUP_TOKENS 3
+ NUM_SYSTEM_SETUP_TOKENS
+};
/* internal setup */
-#define SETUP_TOKEN_INT_PROGRAM_TITLE 0
-#define SETUP_TOKEN_INT_PROGRAM_AUTHOR 1
-#define SETUP_TOKEN_INT_PROGRAM_EMAIL 2
-#define SETUP_TOKEN_INT_PROGRAM_WEBSITE 3
-#define SETUP_TOKEN_INT_PROGRAM_COPYRIGHT 4
-#define SETUP_TOKEN_INT_PROGRAM_COMPANY 5
-#define SETUP_TOKEN_INT_PROGRAM_ICON_FILE 6
-#define SETUP_TOKEN_INT_DEFAULT_GRAPHICS_SET 7
-#define SETUP_TOKEN_INT_DEFAULT_SOUNDS_SET 8
-#define SETUP_TOKEN_INT_DEFAULT_MUSIC_SET 9
-#define SETUP_TOKEN_INT_FALLBACK_GRAPHICS_FILE 10
-#define SETUP_TOKEN_INT_FALLBACK_SOUNDS_FILE 11
-#define SETUP_TOKEN_INT_FALLBACK_MUSIC_FILE 12
-#define SETUP_TOKEN_INT_DEFAULT_LEVEL_SERIES 13
-#define SETUP_TOKEN_INT_CHOOSE_FROM_TOP_LEVELDIR 14
-#define SETUP_TOKEN_INT_DEFAULT_WINDOW_WIDTH 15
-#define SETUP_TOKEN_INT_DEFAULT_WINDOW_HEIGHT 16
-
-#define NUM_INTERNAL_SETUP_TOKENS 17
+enum
+{
+ SETUP_TOKEN_INT_PROGRAM_TITLE = 0,
+ SETUP_TOKEN_INT_PROGRAM_VERSION,
+ SETUP_TOKEN_INT_PROGRAM_AUTHOR,
+ SETUP_TOKEN_INT_PROGRAM_EMAIL,
+ SETUP_TOKEN_INT_PROGRAM_WEBSITE,
+ SETUP_TOKEN_INT_PROGRAM_COPYRIGHT,
+ SETUP_TOKEN_INT_PROGRAM_COMPANY,
+ SETUP_TOKEN_INT_PROGRAM_ICON_FILE,
+ SETUP_TOKEN_INT_DEFAULT_GRAPHICS_SET,
+ SETUP_TOKEN_INT_DEFAULT_SOUNDS_SET,
+ SETUP_TOKEN_INT_DEFAULT_MUSIC_SET,
+ SETUP_TOKEN_INT_FALLBACK_GRAPHICS_FILE,
+ SETUP_TOKEN_INT_FALLBACK_SOUNDS_FILE,
+ SETUP_TOKEN_INT_FALLBACK_MUSIC_FILE,
+ SETUP_TOKEN_INT_DEFAULT_LEVEL_SERIES,
+ SETUP_TOKEN_INT_CHOOSE_FROM_TOP_LEVELDIR,
+ SETUP_TOKEN_INT_SHOW_SCALING_IN_TITLE,
+ SETUP_TOKEN_INT_DEFAULT_WINDOW_WIDTH,
+ SETUP_TOKEN_INT_DEFAULT_WINDOW_HEIGHT,
+
+ NUM_INTERNAL_SETUP_TOKENS
+};
/* debug setup */
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_0 0
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_1 1
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_2 2
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_3 3
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_4 4
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_5 5
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_6 6
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_7 7
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_8 8
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_9 9
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_0 10
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_1 11
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_2 12
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_3 13
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_4 14
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_5 15
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_6 16
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_7 17
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_8 18
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_9 19
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_USE_MOD_KEY 20
-#define SETUP_TOKEN_DEBUG_FRAME_DELAY_GAME_ONLY 21
-#define SETUP_TOKEN_DEBUG_SHOW_FRAMES_PER_SECOND 22
-
-#define NUM_DEBUG_SETUP_TOKENS 23
+enum
+{
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_0 = 0,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_1,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_2,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_3,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_4,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_5,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_6,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_7,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_8,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_9,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_0,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_1,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_2,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_3,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_4,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_5,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_6,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_7,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_8,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_KEY_9,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_USE_MOD_KEY,
+ SETUP_TOKEN_DEBUG_FRAME_DELAY_GAME_ONLY,
+ SETUP_TOKEN_DEBUG_SHOW_FRAMES_PER_SECOND,
+
+ NUM_DEBUG_SETUP_TOKENS
+};
/* options setup */
-#define SETUP_TOKEN_OPTIONS_VERBOSE 0
+enum
+{
+ SETUP_TOKEN_OPTIONS_VERBOSE = 0,
-#define NUM_OPTIONS_SETUP_TOKENS 1
+ NUM_OPTIONS_SETUP_TOKENS
+};
static struct SetupInfo si;
+static struct SetupAutoSetupInfo sasi;
static struct SetupEditorInfo sei;
static struct SetupEditorCascadeInfo seci;
static struct SetupShortcutInfo ssi;
{ TYPE_SWITCH, &si.handicap, "handicap" },
{ TYPE_SWITCH, &si.skip_levels, "skip_levels" },
{ TYPE_SWITCH, &si.increment_levels, "increment_levels" },
+ { TYPE_SWITCH, &si.auto_play_next_level, "auto_play_next_level" },
+ { TYPE_SWITCH, &si.skip_scores_after_game, "skip_scores_after_game" },
{ TYPE_SWITCH, &si.time_limit, "time_limit" },
{ TYPE_SWITCH, &si.fullscreen, "fullscreen" },
{ TYPE_INTEGER,&si.window_scaling_percent, "window_scaling_percent" },
{ TYPE_STRING, &si.window_scaling_quality, "window_scaling_quality" },
{ TYPE_STRING, &si.screen_rendering_mode, "screen_rendering_mode" },
+ { TYPE_STRING, &si.vsync_mode, "vsync_mode" },
{ TYPE_SWITCH, &si.ask_on_escape, "ask_on_escape" },
{ TYPE_SWITCH, &si.ask_on_escape_editor, "ask_on_escape_editor" },
{ TYPE_SWITCH, &si.quick_switch, "quick_player_switch" },
{ TYPE_SWITCH, &si.input_on_focus, "input_on_focus" },
{ TYPE_SWITCH, &si.prefer_aga_graphics, "prefer_aga_graphics" },
+ { TYPE_SWITCH, &si.game_speed_extended, "game_speed_extended" },
{ TYPE_INTEGER,&si.game_frame_delay, "game_frame_delay" },
{ TYPE_SWITCH, &si.sp_show_border_elements, "sp_show_border_elements" },
{ TYPE_SWITCH, &si.small_game_graphics, "small_game_graphics" },
{ TYPE_INTEGER,&si.volume_simple, "volume_simple" },
{ TYPE_INTEGER,&si.volume_loops, "volume_loops" },
{ TYPE_INTEGER,&si.volume_music, "volume_music" },
+ { TYPE_SWITCH, &si.network_mode, "network_mode" },
+ { TYPE_PLAYER, &si.network_player_nr, "network_player" },
+ { TYPE_STRING, &si.network_server_hostname, "network_server_hostname" },
{ TYPE_STRING, &si.touch.control_type, "touch.control_type" },
{ TYPE_INTEGER,&si.touch.move_distance, "touch.move_distance" },
{ TYPE_INTEGER,&si.touch.drop_distance, "touch.drop_distance" },
+ { TYPE_INTEGER,&si.touch.transparency, "touch.transparency" },
+ { TYPE_INTEGER,&si.touch.draw_outlined, "touch.draw_outlined" },
+ { TYPE_INTEGER,&si.touch.draw_pressed, "touch.draw_pressed" },
+ { TYPE_INTEGER,&si.touch.grid_xsize[0], "touch.virtual_buttons.0.xsize" },
+ { TYPE_INTEGER,&si.touch.grid_ysize[0], "touch.virtual_buttons.0.ysize" },
+ { TYPE_INTEGER,&si.touch.grid_xsize[1], "touch.virtual_buttons.1.xsize" },
+ { TYPE_INTEGER,&si.touch.grid_ysize[1], "touch.virtual_buttons.1.ysize" },
+};
+
+static struct TokenInfo auto_setup_tokens[] =
+{
+ { TYPE_INTEGER,&sasi.editor_zoom_tilesize, "editor.zoom_tilesize" },
};
static struct TokenInfo editor_setup_tokens[] =
{ TYPE_SWITCH, &seci.el_sp, "editor.cascade.el_sp" },
{ TYPE_SWITCH, &seci.el_dc, "editor.cascade.el_dc" },
{ TYPE_SWITCH, &seci.el_dx, "editor.cascade.el_dx" },
+ { TYPE_SWITCH, &seci.el_mm, "editor.cascade.el_mm" },
+ { TYPE_SWITCH, &seci.el_df, "editor.cascade.el_df" },
{ TYPE_SWITCH, &seci.el_chars, "editor.cascade.el_chars" },
{ TYPE_SWITCH, &seci.el_steel_chars, "editor.cascade.el_steel_chars" },
{ TYPE_SWITCH, &seci.el_ce, "editor.cascade.el_ce" },
static struct TokenInfo internal_setup_tokens[] =
{
{ TYPE_STRING, &sxi.program_title, "program_title" },
+ { TYPE_STRING, &sxi.program_version, "program_version" },
{ TYPE_STRING, &sxi.program_author, "program_author" },
{ TYPE_STRING, &sxi.program_email, "program_email" },
{ TYPE_STRING, &sxi.program_website, "program_website" },
{ TYPE_STRING, &sxi.fallback_music_file, "fallback_music_file" },
{ TYPE_STRING, &sxi.default_level_series, "default_level_series" },
{ TYPE_BOOLEAN,&sxi.choose_from_top_leveldir, "choose_from_top_leveldir" },
+ { TYPE_BOOLEAN,&sxi.show_scaling_in_title, "show_scaling_in_title" },
{ TYPE_INTEGER,&sxi.default_window_width, "default_window_width" },
{ TYPE_INTEGER,&sxi.default_window_height, "default_window_height" },
};
si->handicap = TRUE;
si->skip_levels = TRUE;
si->increment_levels = TRUE;
+ si->auto_play_next_level = TRUE;
+ si->skip_scores_after_game = FALSE;
si->time_limit = TRUE;
si->fullscreen = FALSE;
si->window_scaling_percent = STD_WINDOW_SCALING_PERCENT;
si->window_scaling_quality = getStringCopy(SCALING_QUALITY_DEFAULT);
si->screen_rendering_mode = getStringCopy(STR_SPECIAL_RENDERING_DEFAULT);
+ si->vsync_mode = getStringCopy(STR_VSYNC_MODE_DEFAULT);
si->ask_on_escape = TRUE;
si->ask_on_escape_editor = TRUE;
si->quick_switch = FALSE;
si->input_on_focus = FALSE;
si->prefer_aga_graphics = TRUE;
+ si->game_speed_extended = FALSE;
si->game_frame_delay = GAME_FRAME_DELAY;
si->sp_show_border_elements = FALSE;
si->small_game_graphics = FALSE;
si->volume_loops = 100; /* percent */
si->volume_music = 100; /* percent */
+ si->network_mode = FALSE;
+ si->network_player_nr = 0; /* first player */
+ si->network_server_hostname = getStringCopy(STR_NETWORK_AUTO_DETECT);
+
si->touch.control_type = getStringCopy(TOUCH_CONTROL_DEFAULT);
si->touch.move_distance = TOUCH_MOVE_DISTANCE_DEFAULT; /* percent */
si->touch.drop_distance = TOUCH_DROP_DISTANCE_DEFAULT; /* percent */
+ si->touch.transparency = TOUCH_TRANSPARENCY_DEFAULT; /* percent */
+ si->touch.draw_outlined = TRUE;
+ si->touch.draw_pressed = TRUE;
+
+ for (i = 0; i < 2; i++)
+ {
+ char *default_grid_button[6][2] =
+ {
+ { " ", " ^^ " },
+ { " ", " ^^ " },
+ { " ", "<< >>" },
+ { " ", "<< >>" },
+ { "111222", " vv " },
+ { "111222", " vv " }
+ };
+ int grid_xsize = DEFAULT_GRID_XSIZE(i);
+ int grid_ysize = DEFAULT_GRID_YSIZE(i);
+ int min_xsize = MIN(6, grid_xsize);
+ int min_ysize = MIN(6, grid_ysize);
+ int startx = grid_xsize - min_xsize;
+ int starty = grid_ysize - min_ysize;
+ int x, y;
+
+ // virtual buttons grid can only be set to defaults if video is initialized
+ // (this will be repeated if virtual buttons are not loaded from setup file)
+ if (video.initialized)
+ {
+ si->touch.grid_xsize[i] = grid_xsize;
+ si->touch.grid_ysize[i] = grid_ysize;
+ }
+ else
+ {
+ si->touch.grid_xsize[i] = -1;
+ si->touch.grid_ysize[i] = -1;
+ }
+
+ for (x = 0; x < MAX_GRID_XSIZE; x++)
+ for (y = 0; y < MAX_GRID_YSIZE; y++)
+ si->touch.grid_button[i][x][y] = CHAR_GRID_BUTTON_NONE;
+
+ for (x = 0; x < min_xsize; x++)
+ for (y = 0; y < min_ysize; y++)
+ si->touch.grid_button[i][x][starty + y] =
+ default_grid_button[y][0][x];
+
+ for (x = 0; x < min_xsize; x++)
+ for (y = 0; y < min_ysize; y++)
+ si->touch.grid_button[i][startx + x][starty + y] =
+ default_grid_button[y][1][x];
+ }
+
+ si->touch.grid_initialized = video.initialized;
si->editor.el_boulderdash = TRUE;
si->editor.el_emerald_mine = TRUE;
si->editor.el_supaplex = TRUE;
si->editor.el_diamond_caves = TRUE;
si->editor.el_dx_boulderdash = TRUE;
+
+ si->editor.el_mirror_magic = TRUE;
+ si->editor.el_deflektor = TRUE;
+
si->editor.el_chars = TRUE;
si->editor.el_steel_chars = TRUE;
si->system.audio_fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
si->internal.program_title = getStringCopy(PROGRAM_TITLE_STRING);
+ si->internal.program_version = getStringCopy(getProgramRealVersionString());
si->internal.program_author = getStringCopy(PROGRAM_AUTHOR_STRING);
si->internal.program_email = getStringCopy(PROGRAM_EMAIL_STRING);
si->internal.program_website = getStringCopy(PROGRAM_WEBSITE_STRING);
si->internal.default_level_series = getStringCopy(UNDEFINED_LEVELSET);
si->internal.choose_from_top_leveldir = FALSE;
+ si->internal.show_scaling_in_title = TRUE;
si->internal.default_window_width = WIN_XSIZE_DEFAULT;
si->internal.default_window_height = WIN_YSIZE_DEFAULT;
#endif
}
+static void setSetupInfoToDefaults_AutoSetup(struct SetupInfo *si)
+{
+ si->auto_setup.editor_zoom_tilesize = MINI_TILESIZE;
+}
+
static void setSetupInfoToDefaults_EditorCascade(struct SetupInfo *si)
{
si->editor_cascade.el_bd = TRUE;
si->editor_cascade.el_dc = TRUE;
si->editor_cascade.el_dx = TRUE;
+ si->editor_cascade.el_mm = TRUE;
+ si->editor_cascade.el_df = TRUE;
+
si->editor_cascade.el_chars = FALSE;
si->editor_cascade.el_steel_chars = FALSE;
si->editor_cascade.el_ce = FALSE;
return hide_setup_token;
}
-static void setHideSetupEntry(void *setup_value_raw)
+void setHideSetupEntry(void *setup_value)
{
- /* !!! DIRTY WORKAROUND; TO BE FIXED AFTER THE MM ENGINE RELEASE !!! */
- void *setup_value = setup_value_raw - (void *)&si + (void *)&setup;
-
char *hide_setup_token = getHideSetupToken(setup_value);
if (setup_value != NULL)
setHashEntry(hide_setup_hash, hide_setup_token, "");
}
+static void setHideSetupEntryRaw(char *token_text, void *setup_value_raw)
+{
+ /* !!! DIRTY WORKAROUND; TO BE FIXED AFTER THE MM ENGINE RELEASE !!! */
+ void *setup_value = setup_value_raw - (void *)&si + (void *)&setup;
+
+ setHideSetupEntry(setup_value);
+}
+
boolean hideSetupEntry(void *setup_value)
{
char *hide_setup_token = getHideSetupToken(setup_value);
/* check if this setup option should be hidden in the setup menu */
if (token_hide_value != NULL && get_boolean_from_string(token_hide_value))
- setHideSetupEntry(token_info[token_nr].value);
+ setHideSetupEntryRaw(token_text, token_info[token_nr].value);
}
static void setSetupInfoFromTokenInfo(SetupFileHash *setup_file_hash,
setSetupInfoFromTokenInfo(setup_file_hash, global_setup_tokens, i);
setup = si;
+ /* virtual buttons setup */
+ setup.touch.grid_initialized = TRUE;
+ for (i = 0; i < 2; i++)
+ {
+ int grid_xsize = setup.touch.grid_xsize[i];
+ int grid_ysize = setup.touch.grid_ysize[i];
+ int x, y;
+
+ // if virtual buttons are not loaded from setup file, repeat initializing
+ // virtual buttons grid with default values later when video is initialized
+ if (grid_xsize == -1 ||
+ grid_ysize == -1)
+ {
+ setup.touch.grid_initialized = FALSE;
+
+ continue;
+ }
+
+ for (y = 0; y < grid_ysize; y++)
+ {
+ char token_string[MAX_LINE_LEN];
+
+ sprintf(token_string, "touch.virtual_buttons.%d.%02d", i, y);
+
+ char *value_string = getHashEntry(setup_file_hash, token_string);
+
+ if (value_string == NULL)
+ continue;
+
+ for (x = 0; x < grid_xsize; x++)
+ {
+ char c = value_string[x];
+
+ setup.touch.grid_button[i][x][y] =
+ (c == '.' ? CHAR_GRID_BUTTON_NONE : c);
+ }
+ }
+ }
+
/* editor setup */
sei = setup.editor;
for (i = 0; i < NUM_EDITOR_SETUP_TOKENS; i++)
for (i = 0; i < NUM_OPTIONS_SETUP_TOKENS; i++)
setSetupInfoFromTokenInfo(setup_file_hash, options_setup_tokens, i);
setup.options = soi;
+
+ setHideRelatedSetupEntries();
+}
+
+static void decodeSetupFileHash_AutoSetup(SetupFileHash *setup_file_hash)
+{
+ int i;
+
+ if (!setup_file_hash)
+ return;
+
+ /* auto setup */
+ sasi = setup.auto_setup;
+ for (i = 0; i < NUM_AUTO_SETUP_TOKENS; i++)
+ setSetupInfo(auto_setup_tokens, i,
+ getHashEntry(setup_file_hash,
+ auto_setup_tokens[i].text));
+ setup.auto_setup = sasi;
}
static void decodeSetupFileHash_EditorCascade(SetupFileHash *setup_file_hash)
}
}
-static void LoadSetup_SpecialPostProcessing()
+static void LoadSetup_SpecialPostProcessing(void)
{
char *player_name_new;
MIN(MAX(MIN_SCROLL_DELAY, setup.scroll_delay_value), MAX_SCROLL_DELAY);
}
-void LoadSetup()
+void LoadSetup(void)
{
char *filename;
LoadSetup_SpecialPostProcessing();
}
-void LoadSetup_EditorCascade()
+void LoadSetup_AutoSetup(void)
+{
+ char *filename = getPath2(getSetupDir(), AUTOSETUP_FILENAME);
+ SetupFileHash *setup_file_hash = NULL;
+
+ /* always start with reliable default values */
+ setSetupInfoToDefaults_AutoSetup(&setup);
+
+ setup_file_hash = loadSetupFileHash(filename);
+
+ if (setup_file_hash)
+ {
+ decodeSetupFileHash_AutoSetup(setup_file_hash);
+
+ freeSetupFileHash(setup_file_hash);
+ }
+
+ free(filename);
+}
+
+void LoadSetup_EditorCascade(void)
{
char *filename = getPath2(getSetupDir(), EDITORCASCADE_FILENAME);
SetupFileHash *setup_file_hash = NULL;
fclose(file);
}
-void SaveSetup()
+void SaveSetup(void)
{
char *filename = getSetupFilename();
FILE *file;
if (i == SETUP_TOKEN_PLAYER_NAME + 1 ||
i == SETUP_TOKEN_GRAPHICS_SET ||
i == SETUP_TOKEN_VOLUME_SIMPLE ||
- i == SETUP_TOKEN_TOUCH_CONTROL_TYPE)
+ i == SETUP_TOKEN_NETWORK_MODE ||
+ i == SETUP_TOKEN_TOUCH_CONTROL_TYPE ||
+ i == SETUP_TOKEN_TOUCH_GRID_XSIZE_0 ||
+ i == SETUP_TOKEN_TOUCH_GRID_XSIZE_1)
fprintf(file, "\n");
fprintf(file, "%s\n", getSetupLine(global_setup_tokens, "", i));
}
+ /* virtual buttons setup */
+ for (i = 0; i < 2; i++)
+ {
+ int grid_xsize = setup.touch.grid_xsize[i];
+ int grid_ysize = setup.touch.grid_ysize[i];
+ int x, y;
+
+ fprintf(file, "\n");
+
+ for (y = 0; y < grid_ysize; y++)
+ {
+ char token_string[MAX_LINE_LEN];
+ char value_string[MAX_LINE_LEN];
+
+ sprintf(token_string, "touch.virtual_buttons.%d.%02d", i, y);
+
+ for (x = 0; x < grid_xsize; x++)
+ {
+ char c = setup.touch.grid_button[i][x][y];
+
+ value_string[x] = (c == CHAR_GRID_BUTTON_NONE ? '.' : c);
+ }
+
+ value_string[grid_xsize] = '\0';
+
+ fprintf(file, "%s\n", getFormattedSetupEntry(token_string, value_string));
+ }
+ }
+
/* editor setup */
sei = setup.editor;
fprintf(file, "\n");
SetFilePermissions(filename, PERMS_PRIVATE);
}
-void SaveSetup_EditorCascade()
+void SaveSetup_AutoSetup(void)
+{
+ char *filename = getPath2(getSetupDir(), AUTOSETUP_FILENAME);
+ FILE *file;
+ int i;
+
+ InitUserDataDirectory();
+
+ if (!(file = fopen(filename, MODE_WRITE)))
+ {
+ Error(ERR_WARN, "cannot write auto setup file '%s'", filename);
+ free(filename);
+ return;
+ }
+
+ fprintFileHeader(file, AUTOSETUP_FILENAME);
+
+ sasi = setup.auto_setup;
+ for (i = 0; i < NUM_AUTO_SETUP_TOKENS; i++)
+ fprintf(file, "%s\n", getSetupLine(auto_setup_tokens, "", i));
+
+ fclose(file);
+
+ SetFilePermissions(filename, PERMS_PRIVATE);
+
+ free(filename);
+}
+
+void SaveSetup_EditorCascade(void)
{
char *filename = getPath2(getSetupDir(), EDITORCASCADE_FILENAME);
FILE *file;
free(filename);
}
-void LoadCustomElementDescriptions()
+void LoadCustomElementDescriptions(void)
{
char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
SetupFileHash *setup_file_hash;
return get_parameter_value(value_raw, suffix, TYPE_INTEGER);
}
-void InitMenuDesignSettings_Static()
+void InitMenuDesignSettings_Static(void)
{
int i;
}
}
-static void InitMenuDesignSettings_SpecialPreProcessing()
+static void InitMenuDesignSettings_SpecialPreProcessing(void)
{
int i;
}
}
-static void InitMenuDesignSettings_SpecialPostProcessing()
+static void InitMenuDesignSettings_SpecialPostProcessing(void)
{
static struct
{
*game_buttons_xy[i].dst = *game_buttons_xy[i].src;
}
-static void InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics()
+static void InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics(void)
{
static struct
{
menu.draw_yoffset_setup[i] = get_integer_from_string(value_2);
}
+ /* special case: initialize with default values that may be overwritten */
+ /* (eg, init "menu.line_spacing.INFO[XXX]" from "menu.line_spacing.INFO") */
+ for (i = 0; i < NUM_SPECIAL_GFX_INFO_ARGS; i++)
+ {
+ char *value_1 = getHashEntry(setup_file_hash,"menu.left_spacing.INFO");
+ char *value_2 = getHashEntry(setup_file_hash,"menu.right_spacing.INFO");
+ char *value_3 = getHashEntry(setup_file_hash,"menu.top_spacing.INFO");
+ char *value_4 = getHashEntry(setup_file_hash,"menu.bottom_spacing.INFO");
+ char *value_5 = getHashEntry(setup_file_hash,"menu.paragraph_spacing.INFO");
+ char *value_6 = getHashEntry(setup_file_hash,"menu.headline1_spacing.INFO");
+ char *value_7 = getHashEntry(setup_file_hash,"menu.headline2_spacing.INFO");
+ char *value_8 = getHashEntry(setup_file_hash,"menu.line_spacing.INFO");
+ char *value_9 = getHashEntry(setup_file_hash,"menu.extra_spacing.INFO");
+
+ if (value_1 != NULL)
+ menu.left_spacing_info[i] = get_integer_from_string(value_1);
+ if (value_2 != NULL)
+ menu.right_spacing_info[i] = get_integer_from_string(value_2);
+ if (value_3 != NULL)
+ menu.top_spacing_info[i] = get_integer_from_string(value_3);
+ if (value_4 != NULL)
+ menu.bottom_spacing_info[i] = get_integer_from_string(value_4);
+ if (value_5 != NULL)
+ menu.paragraph_spacing_info[i] = get_integer_from_string(value_5);
+ if (value_6 != NULL)
+ menu.headline1_spacing_info[i] = get_integer_from_string(value_6);
+ if (value_7 != NULL)
+ menu.headline2_spacing_info[i] = get_integer_from_string(value_7);
+ if (value_8 != NULL)
+ menu.line_spacing_info[i] = get_integer_from_string(value_8);
+ if (value_9 != NULL)
+ menu.extra_spacing_info[i] = get_integer_from_string(value_9);
+ }
+
/* special case: initialize with default values that may be overwritten */
/* (eg, init "menu.enter_screen.SCORES.xyz" from "menu.enter_screen.xyz") */
for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
freeSetupFileHash(setup_file_hash);
}
-void LoadMenuDesignSettings()
+void LoadMenuDesignSettings(void)
{
char *filename_base = UNDEFINED_FILENAME, *filename_local;
InitMenuDesignSettings_SpecialPostProcessing();
}
-void LoadMenuDesignSettings_AfterGraphics()
+void LoadMenuDesignSettings_AfterGraphics(void)
{
InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics();
}
return music_info_listed_ext(list, basename, TRUE);
}
-void LoadMusicInfo()
+void LoadMusicInfo(void)
{
char *music_directory = getCustomMusicDirectory();
int num_music = getMusicListSize();
}
}
-void add_helpanim_entry(int element, int action, int direction, int delay,
- int *num_list_entries)
+static void add_helpanim_entry(int element, int action, int direction,
+ int delay, int *num_list_entries)
{
struct HelpAnimInfo *new_list_entry;
(*num_list_entries)++;
new_list_entry->delay = delay;
}
-void print_unknown_token(char *filename, char *token, int token_nr)
+static void print_unknown_token(char *filename, char *token, int token_nr)
{
if (token_nr == 0)
{
Error(ERR_INFO, "- token: '%s'", token);
}
-void print_unknown_token_end(int token_nr)
+static void print_unknown_token_end(int token_nr)
{
if (token_nr > 0)
Error(ERR_INFO_LINE, "-");
}
-void LoadHelpAnimInfo()
+void LoadHelpAnimInfo(void)
{
char *filename = getHelpAnimFilename();
SetupFileList *setup_file_list = NULL, *list;
#endif
}
-void LoadHelpTextInfo()
+void LoadHelpTextInfo(void)
{
char *filename = getHelpTextFilename();
int i;
#define MAX_NUM_CONVERT_LEVELS 1000
-void ConvertLevels()
+void ConvertLevels(void)
{
static LevelDirTree *convert_leveldir = NULL;
static int convert_level_nr = -1;
/* create and save images for use in level sketches (raw BMP format) */
/* ------------------------------------------------------------------------- */
-void CreateLevelSketchImages()
+void CreateLevelSketchImages(void)
{
#if defined(TARGET_SDL)
Bitmap *bitmap1;