#define CONF_MASK_BYTES 0xc0
#define CONF_MASK_TOKEN 0x3f
-#define CONF_LAST_ENTRY (CONF_MASK_1_BYTE | 0)
-
-#define CONF_VALUE_INTEGER_1 (CONF_MASK_1_BYTE | 1)
-#define CONF_VALUE_INTEGER_2 (CONF_MASK_1_BYTE | 2)
-#define CONF_VALUE_INTEGER_3 (CONF_MASK_1_BYTE | 3)
-#define CONF_VALUE_INTEGER_4 (CONF_MASK_1_BYTE | 4)
-#define CONF_VALUE_INTEGER_5 (CONF_MASK_1_BYTE | 5)
-#define CONF_VALUE_INTEGER_6 (CONF_MASK_1_BYTE | 6)
-#define CONF_VALUE_INTEGER_7 (CONF_MASK_1_BYTE | 7)
-#define CONF_VALUE_INTEGER_8 (CONF_MASK_1_BYTE | 8)
-#define CONF_VALUE_BOOLEAN_1 (CONF_MASK_1_BYTE | 9)
-#define CONF_VALUE_BOOLEAN_2 (CONF_MASK_1_BYTE | 10)
-#define CONF_VALUE_BOOLEAN_3 (CONF_MASK_1_BYTE | 11)
-#define CONF_VALUE_BOOLEAN_4 (CONF_MASK_1_BYTE | 12)
-#define CONF_VALUE_BOOLEAN_5 (CONF_MASK_1_BYTE | 13)
-#define CONF_VALUE_BOOLEAN_6 (CONF_MASK_1_BYTE | 14)
-#define CONF_VALUE_BOOLEAN_7 (CONF_MASK_1_BYTE | 15)
-#define CONF_VALUE_BOOLEAN_8 (CONF_MASK_1_BYTE | 16)
-
-#define CONF_VALUE_ELEMENT_1 (CONF_MASK_2_BYTE | 1)
-#define CONF_VALUE_ELEMENT_2 (CONF_MASK_2_BYTE | 2)
-#define CONF_VALUE_ELEMENT_3 (CONF_MASK_2_BYTE | 3)
-#define CONF_VALUE_ELEMENT_4 (CONF_MASK_2_BYTE | 4)
-#define CONF_VALUE_ELEMENT_5 (CONF_MASK_2_BYTE | 5)
-#define CONF_VALUE_ELEMENT_6 (CONF_MASK_2_BYTE | 6)
-#define CONF_VALUE_ELEMENT_7 (CONF_MASK_2_BYTE | 7)
-#define CONF_VALUE_ELEMENT_8 (CONF_MASK_2_BYTE | 8)
-
-#define CONF_VALUE_ELEMENTS (CONF_MASK_MULTI_BYTES | 1)
-#define CONF_VALUE_CONTENTS (CONF_MASK_MULTI_BYTES | 2)
+#define CONF_VALUE_1_BYTE(x) (CONF_MASK_1_BYTE | (x))
+#define CONF_VALUE_2_BYTE(x) (CONF_MASK_2_BYTE | (x))
+#define CONF_VALUE_4_BYTE(x) (CONF_MASK_4_BYTE | (x))
+#define CONF_VALUE_MULTI_BYTES(x) (CONF_MASK_MULTI_BYTES | (x))
+
+/* a sequence of configuration values can be terminated by this value */
+#define CONF_LAST_ENTRY CONF_VALUE_1_BYTE(0)
+
+/* these definitions are just for convenience of use and readability */
+#define CONF_VALUE_8_BIT(x) CONF_VALUE_1_BYTE(x)
+#define CONF_VALUE_16_BIT(x) CONF_VALUE_2_BYTE(x)
+#define CONF_VALUE_32_BIT(x) CONF_VALUE_4_BYTE(x)
+#define CONF_VALUE_BYTES(x) CONF_VALUE_MULTI_BYTES(x)
+
+#define CONF_VALUE_INTEGER_1 CONF_VALUE_8_BIT(1)
+#define CONF_VALUE_INTEGER_2 CONF_VALUE_8_BIT(2)
+#define CONF_VALUE_INTEGER_3 CONF_VALUE_8_BIT(3)
+#define CONF_VALUE_INTEGER_4 CONF_VALUE_8_BIT(4)
+#define CONF_VALUE_INTEGER_5 CONF_VALUE_8_BIT(5)
+#define CONF_VALUE_INTEGER_6 CONF_VALUE_8_BIT(6)
+#define CONF_VALUE_INTEGER_7 CONF_VALUE_8_BIT(7)
+#define CONF_VALUE_INTEGER_8 CONF_VALUE_8_BIT(8)
+#define CONF_VALUE_BOOLEAN_1 CONF_VALUE_8_BIT(9)
+#define CONF_VALUE_BOOLEAN_2 CONF_VALUE_8_BIT(10)
+#define CONF_VALUE_BOOLEAN_3 CONF_VALUE_8_BIT(11)
+#define CONF_VALUE_BOOLEAN_4 CONF_VALUE_8_BIT(12)
+#define CONF_VALUE_BOOLEAN_5 CONF_VALUE_8_BIT(13)
+#define CONF_VALUE_BOOLEAN_6 CONF_VALUE_8_BIT(14)
+#define CONF_VALUE_BOOLEAN_7 CONF_VALUE_8_BIT(15)
+#define CONF_VALUE_BOOLEAN_8 CONF_VALUE_8_BIT(16)
+
+#define CONF_VALUE_ELEMENT_1 CONF_VALUE_16_BIT(1)
+#define CONF_VALUE_ELEMENT_2 CONF_VALUE_16_BIT(2)
+#define CONF_VALUE_ELEMENT_3 CONF_VALUE_16_BIT(3)
+#define CONF_VALUE_ELEMENT_4 CONF_VALUE_16_BIT(4)
+#define CONF_VALUE_ELEMENT_5 CONF_VALUE_16_BIT(5)
+#define CONF_VALUE_ELEMENT_6 CONF_VALUE_16_BIT(6)
+#define CONF_VALUE_ELEMENT_7 CONF_VALUE_16_BIT(7)
+#define CONF_VALUE_ELEMENT_8 CONF_VALUE_16_BIT(8)
+#if 0
+#define CONF_VALUE_ELEMENTS CONF_VALUE_BYTES(1)
+#define CONF_VALUE_CONTENTS CONF_VALUE_BYTES(2)
+#endif
+
+#if 0
#define CONF_VALUE_INTEGER(x) ((x) >= CONF_VALUE_INTEGER_1 && \
(x) <= CONF_VALUE_INTEGER_8)
#define CONF_VALUE_BOOLEAN(x) ((x) >= CONF_VALUE_BOOLEAN_1 && \
(x) <= CONF_VALUE_BOOLEAN_8)
+#endif
#define CONF_VALUE_NUM_BYTES(x) ((x) == CONF_MASK_1_BYTE ? 1 : \
(x) == CONF_MASK_2_BYTE ? 2 : \
(x) == CONF_MASK_4_BYTE ? 4 : 0)
+#if 0
#define CONF_CONTENT_NUM_ELEMENTS (3 * 3)
#define CONF_CONTENT_NUM_BYTES (CONF_CONTENT_NUM_ELEMENTS * 2)
#define CONF_ELEMENT_NUM_BYTES (2)
CONF_ELEMENT_NUM_BYTES : \
(t) == CONF_VALUE_CONTENTS ? \
CONF_CONTENT_NUM_BYTES : 1)
+#endif
+
+#define CONF_CONTENT_NUM_ELEMENTS (3 * 3)
+#define CONF_CONTENT_NUM_BYTES (CONF_CONTENT_NUM_ELEMENTS * 2)
+#define CONF_ELEMENT_NUM_BYTES (2)
+
+#define CONF_ENTITY_NUM_BYTES(t) ((t) == TYPE_ELEMENT || \
+ (t) == TYPE_ELEMENT_LIST ? \
+ CONF_ELEMENT_NUM_BYTES : \
+ (t) == TYPE_CONTENT || \
+ (t) == TYPE_CONTENT_LIST ? \
+ CONF_CONTENT_NUM_BYTES : 1)
#define CONF_ELEMENT_BYTE_POS(i) ((i) * CONF_ELEMENT_NUM_BYTES)
#define CONF_ELEMENTS_ELEMENT(b,i) ((b[CONF_ELEMENT_BYTE_POS(i)] << 8) | \
static void LoadLevel_InitPlayfield(struct LevelInfo *, char *);
#endif
+/* temporary variables used to store pointers to structure members */
static struct LevelInfo li;
-
-static struct
+static struct ElementInfo xx_ei, yy_ei;
+static struct ElementChangeInfo xx_change;
+static struct ElementGroupInfo xx_group;
+static unsigned int xx_event_bits[NUM_CE_BITFIELDS];
+static char xx_default_description[MAX_ELEMENT_NAME_LEN + 1];
+static int xx_default_description_length;
+static int xx_num_contents;
+static int xx_current_change_page;
+
+struct ElementFileConfig
{
int element; /* element for which data is to be stored */
- int type; /* type of data to be stored */
+ int data_type; /* internal type of data */
+ int conf_type; /* special type identifier stored in file */
/* (mandatory) */
void *value; /* variable that holds the data to be stored */
int default_value; /* initial default value for this variable */
/* (optional) */
+ void *value_copy; /* variable that holds the data to be copied */
void *num_entities; /* number of entities for multi-byte data */
int default_num_entities; /* default number of entities for this data */
int max_num_entities; /* maximal number of entities for this data */
-} element_conf[] =
+ char *default_string; /* optional default string for string data */
+};
+
+static struct ElementFileConfig element_conf[] =
{
/* ---------- 1-byte values ---------------------------------------------- */
{
- EL_EMC_ANDROID, CONF_VALUE_INTEGER_1,
+ EL_EMC_ANDROID,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.android_move_time, 10
},
{
- EL_EMC_ANDROID, CONF_VALUE_INTEGER_2,
+ EL_EMC_ANDROID,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_2,
&li.android_clone_time, 10
},
{
- EL_EMC_LENSES, CONF_VALUE_INTEGER_1,
+ EL_EMC_LENSES,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.lenses_score, 10
},
{
- EL_EMC_LENSES, CONF_VALUE_INTEGER_2,
+ EL_EMC_LENSES,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_2,
&li.lenses_time, 10
},
{
- EL_EMC_MAGNIFIER, CONF_VALUE_INTEGER_1,
+ EL_EMC_MAGNIFIER,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.magnify_score, 10
},
{
- EL_EMC_MAGNIFIER, CONF_VALUE_INTEGER_2,
+ EL_EMC_MAGNIFIER,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_2,
&li.magnify_time, 10
},
{
- EL_ROBOT, CONF_VALUE_INTEGER_1,
+ EL_ROBOT,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.slurp_score, 10
},
{
- EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_1,
+ EL_GAME_OF_LIFE,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.game_of_life[0], 2
},
{
- EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_2,
+ EL_GAME_OF_LIFE,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_2,
&li.game_of_life[1], 3
},
{
- EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_3,
+ EL_GAME_OF_LIFE,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_3,
&li.game_of_life[2], 3
},
{
- EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_4,
+ EL_GAME_OF_LIFE,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_4,
&li.game_of_life[3], 3
},
{
- EL_BIOMAZE, CONF_VALUE_INTEGER_1,
+ EL_BIOMAZE,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.biomaze[0], 2
},
{
- EL_BIOMAZE, CONF_VALUE_INTEGER_2,
+ EL_BIOMAZE,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_2,
&li.biomaze[1], 3
},
{
- EL_BIOMAZE, CONF_VALUE_INTEGER_3,
+ EL_BIOMAZE,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_3,
&li.biomaze[2], 3
},
{
- EL_BIOMAZE, CONF_VALUE_INTEGER_4,
+ EL_BIOMAZE,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_4,
&li.biomaze[3], 3
},
{
- EL_BALLOON, CONF_VALUE_INTEGER_1,
+ EL_BALLOON,
+ TYPE_BITFIELD, CONF_VALUE_INTEGER_1,
&li.wind_direction_initial, MV_NONE
},
{
- EL_TIMEGATE_SWITCH, CONF_VALUE_INTEGER_1,
+ EL_TIMEGATE_SWITCH,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.time_timegate, 10
},
{
- EL_LIGHT_SWITCH_ACTIVE, CONF_VALUE_INTEGER_1,
+ EL_LIGHT_SWITCH_ACTIVE,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.time_light, 10
},
{
- EL_SHIELD_NORMAL, CONF_VALUE_INTEGER_1,
+ EL_SHIELD_NORMAL,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.shield_normal_time, 10
},
{
- EL_SHIELD_DEADLY, CONF_VALUE_INTEGER_1,
+ EL_SHIELD_DEADLY,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.shield_deadly_time, 10
},
{
- EL_EXTRA_TIME, CONF_VALUE_INTEGER_1,
+ EL_EXTRA_TIME,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.extra_time, 10
},
{
- EL_EXTRA_TIME, CONF_VALUE_INTEGER_2,
+ EL_EXTRA_TIME,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_2,
&li.extra_time_score, 10
},
{
- EL_TIME_ORB_FULL, CONF_VALUE_INTEGER_1,
+ EL_TIME_ORB_FULL,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.time_orb_time, 10
},
{
- EL_TIME_ORB_FULL, CONF_VALUE_BOOLEAN_1,
+ EL_TIME_ORB_FULL,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_1,
&li.use_time_orb_bug, FALSE
},
{
- EL_PLAYER_1, CONF_VALUE_BOOLEAN_1,
+ EL_PLAYER_1,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_1,
&li.block_snap_field, TRUE
},
{
- EL_PLAYER_1, CONF_VALUE_BOOLEAN_2,
+ EL_PLAYER_1,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_2,
&li.use_start_element[0], FALSE
},
{
- EL_PLAYER_2, CONF_VALUE_BOOLEAN_2,
+ EL_PLAYER_2,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_2,
&li.use_start_element[1], FALSE
},
{
- EL_PLAYER_3, CONF_VALUE_BOOLEAN_2,
+ EL_PLAYER_3,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_2,
&li.use_start_element[2], FALSE
},
{
- EL_PLAYER_4, CONF_VALUE_BOOLEAN_2,
+ EL_PLAYER_4,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_2,
&li.use_start_element[3], FALSE
},
{
- EL_PLAYER_1, CONF_VALUE_BOOLEAN_3,
+ EL_PLAYER_1,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_3,
&li.use_artwork_element[0], FALSE
},
{
- EL_PLAYER_2, CONF_VALUE_BOOLEAN_3,
+ EL_PLAYER_2,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_3,
&li.use_artwork_element[1], FALSE
},
{
- EL_PLAYER_3, CONF_VALUE_BOOLEAN_3,
+ EL_PLAYER_3,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_3,
&li.use_artwork_element[2], FALSE
},
{
- EL_PLAYER_4, CONF_VALUE_BOOLEAN_3,
+ EL_PLAYER_4,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_3,
&li.use_artwork_element[3], FALSE
},
{
- EL_PLAYER_1, CONF_VALUE_BOOLEAN_4,
+ EL_PLAYER_1,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_4,
&li.use_explosion_element[0], FALSE
},
{
- EL_PLAYER_2, CONF_VALUE_BOOLEAN_4,
+ EL_PLAYER_2,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_4,
&li.use_explosion_element[1], FALSE
},
{
- EL_PLAYER_3, CONF_VALUE_BOOLEAN_4,
+ EL_PLAYER_3,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_4,
&li.use_explosion_element[2], FALSE
},
{
- EL_PLAYER_4, CONF_VALUE_BOOLEAN_4,
+ EL_PLAYER_4,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_4,
&li.use_explosion_element[3], FALSE
},
{
- EL_PLAYER_1, CONF_VALUE_BOOLEAN_5,
+ EL_PLAYER_1,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_5,
&li.continuous_snapping, TRUE
},
{
- EL_PLAYER_1, CONF_VALUE_INTEGER_1,
+ EL_PLAYER_1,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.initial_player_stepsize, STEPSIZE_NORMAL
},
{
- EL_EMC_MAGIC_BALL, CONF_VALUE_INTEGER_1,
+ EL_EMC_MAGIC_BALL,
+ TYPE_INTEGER, CONF_VALUE_INTEGER_1,
&li.ball_time, 10
},
{
- EL_EMC_MAGIC_BALL, CONF_VALUE_BOOLEAN_1,
+ EL_EMC_MAGIC_BALL,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_1,
&li.ball_random, FALSE
},
{
- EL_EMC_MAGIC_BALL, CONF_VALUE_BOOLEAN_2,
+ EL_EMC_MAGIC_BALL,
+ TYPE_BOOLEAN, CONF_VALUE_BOOLEAN_2,
&li.ball_state_initial, FALSE
},
/* ---------- 2-byte values ---------------------------------------------- */
{
- EL_PLAYER_1, CONF_VALUE_ELEMENT_1,
+ EL_PLAYER_1,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_1,
&li.start_element[0], EL_PLAYER_1
},
{
- EL_PLAYER_2, CONF_VALUE_ELEMENT_1,
+ EL_PLAYER_2,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_1,
&li.start_element[1], EL_PLAYER_2
},
{
- EL_PLAYER_3, CONF_VALUE_ELEMENT_1,
+ EL_PLAYER_3,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_1,
&li.start_element[2], EL_PLAYER_3
},
{
- EL_PLAYER_4, CONF_VALUE_ELEMENT_1,
+ EL_PLAYER_4,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_1,
&li.start_element[3], EL_PLAYER_4
},
{
- EL_PLAYER_1, CONF_VALUE_ELEMENT_2,
+ EL_PLAYER_1,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_2,
&li.artwork_element[0], EL_PLAYER_1
},
{
- EL_PLAYER_2, CONF_VALUE_ELEMENT_2,
+ EL_PLAYER_2,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_2,
&li.artwork_element[1], EL_PLAYER_2
},
{
- EL_PLAYER_3, CONF_VALUE_ELEMENT_2,
+ EL_PLAYER_3,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_2,
&li.artwork_element[2], EL_PLAYER_3
},
{
- EL_PLAYER_4, CONF_VALUE_ELEMENT_2,
+ EL_PLAYER_4,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_2,
&li.artwork_element[3], EL_PLAYER_4
},
{
- EL_PLAYER_1, CONF_VALUE_ELEMENT_3,
+ EL_PLAYER_1,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_3,
&li.explosion_element[0], EL_PLAYER_1
},
{
- EL_PLAYER_2, CONF_VALUE_ELEMENT_3,
+ EL_PLAYER_2,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_3,
&li.explosion_element[1], EL_PLAYER_2
},
{
- EL_PLAYER_3, CONF_VALUE_ELEMENT_3,
+ EL_PLAYER_3,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_3,
&li.explosion_element[2], EL_PLAYER_3
},
{
- EL_PLAYER_4, CONF_VALUE_ELEMENT_3,
+ EL_PLAYER_4,
+ TYPE_ELEMENT, CONF_VALUE_ELEMENT_3,
&li.explosion_element[3], EL_PLAYER_4
},
/* ---------- multi-byte values ------------------------------------------ */
{
- EL_EMC_MAGIC_BALL, CONF_VALUE_CONTENTS,
- &li.ball_content, EL_EMPTY,
+ EL_EMC_ANDROID,
+ TYPE_ELEMENT_LIST, CONF_VALUE_BYTES(1),
+ &li.android_clone_element[0], EL_EMPTY, NULL,
+ &li.num_android_clone_elements, 1, MAX_ANDROID_ELEMENTS
+ },
+ {
+ EL_EMC_MAGIC_BALL,
+ TYPE_CONTENT_LIST, CONF_VALUE_BYTES(2),
+ &li.ball_content, EL_EMPTY, NULL,
&li.num_ball_contents, 4, MAX_ELEMENT_CONTENTS
},
+
{
- EL_EMC_ANDROID, CONF_VALUE_ELEMENTS,
- &li.android_clone_element[0], EL_EMPTY,
- &li.num_android_clone_elements, 1, MAX_ANDROID_ELEMENTS
+ -1,
+ -1, -1,
+ NULL, -1,
+ },
+};
+
+static struct ElementFileConfig custom_element_conf[] =
+{
+ {
+ -1,
+ TYPE_STRING, CONF_VALUE_BYTES(1),
+ &xx_ei.description[0], -1,
+ &yy_ei.description[0],
+ &xx_default_description_length, -1, MAX_ELEMENT_NAME_LEN,
+ &xx_default_description[0]
+ },
+
+ {
+ -1,
+ TYPE_BITFIELD, CONF_VALUE_32_BIT(1),
+ &xx_ei.properties[EP_BITFIELD_BASE_NR], EP_BITMASK_BASE_DEFAULT,
+ &yy_ei.properties[EP_BITFIELD_BASE_NR]
+ },
+#if 0
+ /* (reserved) */
+ {
+ -1,
+ TYPE_BITFIELD, CONF_VALUE_32_BIT(2),
+ &xx_ei.properties[EP_BITFIELD_BASE_NR + 1], EP_BITMASK_DEFAULT,
+ &yy_ei.properties[EP_BITFIELD_BASE_NR + 1]
+ },
+#endif
+
+ {
+ -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(1),
+ &xx_ei.use_gfx_element, FALSE,
+ &yy_ei.use_gfx_element
+ },
+ {
+ -1,
+ TYPE_ELEMENT, CONF_VALUE_16_BIT(1),
+ &xx_ei.gfx_element, EL_EMPTY_SPACE,
+ &yy_ei.gfx_element
+ },
+
+ {
+ -1,
+ TYPE_BITFIELD, CONF_VALUE_8_BIT(2),
+ &xx_ei.access_direction, MV_ALL_DIRECTIONS,
+ &yy_ei.access_direction
+ },
+
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(2),
+ &xx_ei.collect_score_initial, 10,
+ &yy_ei.collect_score_initial
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(3),
+ &xx_ei.collect_count_initial, 1,
+ &yy_ei.collect_count_initial
+ },
+
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(4),
+ &xx_ei.ce_value_fixed_initial, 0,
+ &yy_ei.ce_value_fixed_initial
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(5),
+ &xx_ei.ce_value_random_initial, 0,
+ &yy_ei.ce_value_random_initial
+ },
+ {
+ -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(3),
+ &xx_ei.use_last_ce_value, FALSE,
+ &yy_ei.use_last_ce_value
+ },
+
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(6),
+ &xx_ei.push_delay_fixed, 8,
+ &yy_ei.push_delay_fixed
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(7),
+ &xx_ei.push_delay_random, 8,
+ &yy_ei.push_delay_random
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(8),
+ &xx_ei.drop_delay_fixed, 0,
+ &yy_ei.drop_delay_fixed
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(9),
+ &xx_ei.drop_delay_random, 0,
+ &yy_ei.drop_delay_random
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(10),
+ &xx_ei.move_delay_fixed, 0,
+ &yy_ei.move_delay_fixed
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(11),
+ &xx_ei.move_delay_random, 0,
+ &yy_ei.move_delay_random
+ },
+
+ {
+ -1,
+ TYPE_BITFIELD, CONF_VALUE_32_BIT(3),
+ &xx_ei.move_pattern, MV_ALL_DIRECTIONS,
+ &yy_ei.move_pattern
+ },
+ {
+ -1,
+ TYPE_BITFIELD, CONF_VALUE_8_BIT(4),
+ &xx_ei.move_direction_initial, MV_START_AUTOMATIC,
+ &yy_ei.move_direction_initial
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(5),
+ &xx_ei.move_stepsize, TILEX / 8,
+ &yy_ei.move_stepsize
+ },
+
+ {
+ -1,
+ TYPE_ELEMENT, CONF_VALUE_16_BIT(12),
+ &xx_ei.move_enter_element, EL_EMPTY_SPACE,
+ &yy_ei.move_enter_element
+ },
+ {
+ -1,
+ TYPE_ELEMENT, CONF_VALUE_16_BIT(13),
+ &xx_ei.move_leave_element, EL_EMPTY_SPACE,
+ &yy_ei.move_leave_element
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(6),
+ &xx_ei.move_leave_type, LEAVE_TYPE_UNLIMITED,
+ &yy_ei.move_leave_type
+ },
+
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(7),
+ &xx_ei.slippery_type, SLIPPERY_ANY_RANDOM,
+ &yy_ei.slippery_type
+ },
+
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(8),
+ &xx_ei.explosion_type, EXPLODES_3X3,
+ &yy_ei.explosion_type
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(14),
+ &xx_ei.explosion_delay, 16,
+ &yy_ei.explosion_delay
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(15),
+ &xx_ei.ignition_delay, 8,
+ &yy_ei.ignition_delay
+ },
+
+ {
+ -1,
+ TYPE_CONTENT_LIST, CONF_VALUE_BYTES(2),
+ &xx_ei.content, EL_EMPTY_SPACE,
+ &yy_ei.content,
+ &xx_num_contents, 1, 1
+ },
+
+ /* ---------- "num_change_pages" must be the last entry ------------------- */
+
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(9),
+ &xx_ei.num_change_pages, -1, /* value must always be saved */
+ &yy_ei.num_change_pages
+ },
+
+ {
+ -1,
+ -1, -1,
+ NULL, -1,
+ NULL
+ },
+};
+
+static struct ElementFileConfig custom_element_change_conf[] =
+{
+ /* ---------- "current_change_page" must be the first entry --------------- */
+
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(1),
+ &xx_current_change_page, -1 /* value must always be saved */
+ },
+
+ /* ---------- (the remaining entries can be in any order) ----------------- */
+
+ {
+ -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(2),
+ &xx_change.can_change, FALSE
+ },
+
+ {
+ -1,
+ TYPE_BITFIELD, CONF_VALUE_32_BIT(1),
+ &xx_event_bits[0], 0
+ },
+ {
+ -1,
+ TYPE_BITFIELD, CONF_VALUE_32_BIT(2),
+ &xx_event_bits[1], 0
+ },
+
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(3),
+ &xx_change.trigger_player, CH_PLAYER_ANY
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(4),
+ &xx_change.trigger_side, CH_SIDE_ANY
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(5),
+ &xx_change.trigger_page, CH_PAGE_ANY
+ },
+
+ {
+ -1,
+ TYPE_ELEMENT, CONF_VALUE_16_BIT(1),
+ &xx_change.target_element, EL_EMPTY_SPACE
+ },
+
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(2),
+ &xx_change.delay_fixed, 0
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(3),
+ &xx_change.delay_random, 0
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(4),
+ &xx_change.delay_frames, FRAMES_PER_SECOND
+ },
+
+ {
+ -1,
+ TYPE_ELEMENT, CONF_VALUE_16_BIT(5),
+ &xx_change.trigger_element, EL_EMPTY_SPACE
+ },
+
+ {
+ -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(6),
+ &xx_change.explode, FALSE
+ },
+ {
+ -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(7),
+ &xx_change.use_target_content, FALSE
+ },
+ {
+ -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(8),
+ &xx_change.only_if_complete, FALSE
+ },
+ {
+ -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(9),
+ &xx_change.use_random_replace, FALSE
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(10),
+ &xx_change.random_percentage, 100
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(11),
+ &xx_change.replace_when, CP_WHEN_EMPTY
},
{
+ -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(12),
+ &xx_change.has_action, FALSE
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(13),
+ &xx_change.action_type, CA_NO_ACTION
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(14),
+ &xx_change.action_mode, CA_MODE_UNDEFINED
+ },
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_16_BIT(6),
+ &xx_change.action_arg, CA_ARG_UNDEFINED
+ },
+
+ {
+ -1,
+ TYPE_CONTENT_LIST, CONF_VALUE_BYTES(1),
+ &xx_change.target_content, EL_EMPTY_SPACE, NULL,
+ &xx_num_contents, 1, 1
+ },
+
+ {
+ -1,
+ -1, -1,
+ NULL, -1,
+ },
+};
+
+static struct ElementFileConfig group_element_conf[] =
+{
+ {
+ -1,
+ TYPE_STRING, CONF_VALUE_BYTES(1),
+ &xx_ei.description[0], -1, NULL,
+ &xx_default_description_length, -1, MAX_ELEMENT_NAME_LEN,
+ &xx_default_description[0]
+ },
+
+ {
+ -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(1),
+ &xx_ei.use_gfx_element, FALSE
+ },
+ {
+ -1,
+ TYPE_ELEMENT, CONF_VALUE_16_BIT(1),
+ &xx_ei.gfx_element, EL_EMPTY_SPACE
+ },
+
+ {
+ -1,
+ TYPE_INTEGER, CONF_VALUE_8_BIT(2),
+ &xx_group.choice_mode, ANIM_RANDOM
+ },
+
+ {
+ -1,
+ TYPE_ELEMENT_LIST, CONF_VALUE_BYTES(2),
+ &xx_group.element[0], EL_EMPTY_SPACE, NULL,
+ &xx_group.num_elements, 1, MAX_ELEMENTS_IN_GROUP
+ },
+
+ {
+ -1,
-1, -1,
NULL, -1,
},
};
-/* ========================================================================= */
-/* level file functions */
-/* ========================================================================= */
+/* ========================================================================= */
+/* level file functions */
+/* ========================================================================= */
+
+static void resetEventFlags(struct ElementChangeInfo *change)
+{
+ int i;
+
+ for (i = 0; i < NUM_CHANGE_EVENTS; i++)
+ change->has_event[i] = FALSE;
+}
+
+static void resetEventBits()
+{
+ int i;
+
+ for (i = 0; i < NUM_CE_BITFIELDS; i++)
+ xx_event_bits[i] = 0;
+}
+
+static void setEventFlagsFromEventBits(struct ElementChangeInfo *change)
+{
+ int i;
+
+ /* important: only change event flag if corresponding event bit is set */
+ for (i = 0; i < NUM_CHANGE_EVENTS; i++)
+ if (xx_event_bits[CH_EVENT_BITFIELD_NR(i)] & CH_EVENT_BIT(i))
+ change->has_event[i] = TRUE;
+}
+
+static void setEventBitsFromEventFlags(struct ElementChangeInfo *change)
+{
+ int i;
+
+ /* important: only change event bit if corresponding event flag is set */
+ for (i = 0; i < NUM_CHANGE_EVENTS; i++)
+ if (change->has_event[i])
+ xx_event_bits[CH_EVENT_BITFIELD_NR(i)] |= CH_EVENT_BIT(i);
+}
+
+static char *getDefaultElementDescription(struct ElementInfo *ei)
+{
+ static char description[MAX_ELEMENT_NAME_LEN + 1];
+ char *default_description = (ei->custom_description != NULL ?
+ ei->custom_description :
+ ei->editor_description);
+ int i;
+
+ /* always start with reliable default values */
+ for (i = 0; i < MAX_ELEMENT_NAME_LEN + 1; i++)
+ description[i] = '\0';
+
+ /* truncate element description to MAX_ELEMENT_NAME_LEN bytes */
+ strncpy(description, default_description, MAX_ELEMENT_NAME_LEN);
+
+ return &description[0];
+}
+
+static void setElementDescriptionToDefault(struct ElementInfo *ei)
+{
+ char *default_description = getDefaultElementDescription(ei);
+ int i;
+
+ for (i = 0; i < MAX_ELEMENT_NAME_LEN + 1; i++)
+ ei->description[i] = default_description[i];
+}
+
+static void setConfigToDefaultsFromConfigList(struct ElementFileConfig *config)
+{
+ int i;
+
+ for (i = 0; config[i].data_type != -1; i++)
+ {
+ int default_value = config[i].default_value;
+ int data_type = config[i].data_type;
+ int conf_type = config[i].conf_type;
+ int byte_mask = conf_type & CONF_MASK_BYTES;
+
+ if (byte_mask == CONF_MASK_MULTI_BYTES)
+ {
+ int default_num_entities = config[i].default_num_entities;
+ int max_num_entities = config[i].max_num_entities;
+
+ *(int *)(config[i].num_entities) = default_num_entities;
+
+ if (data_type == TYPE_STRING)
+ {
+ char *default_string = config[i].default_string;
+ char *string = (char *)(config[i].value);
+
+ strncpy(string, default_string, max_num_entities);
+ }
+ else if (data_type == TYPE_ELEMENT_LIST)
+ {
+ int *element_array = (int *)(config[i].value);
+ int j;
+
+ for (j = 0; j < max_num_entities; j++)
+ element_array[j] = default_value;
+ }
+ else if (data_type == TYPE_CONTENT_LIST)
+ {
+ struct Content *content = (struct Content *)(config[i].value);
+ int c, x, y;
+
+ for (c = 0; c < max_num_entities; c++)
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ content[c].e[x][y] = default_value;
+ }
+ }
+ else /* constant size configuration data (1, 2 or 4 bytes) */
+ {
+ if (data_type == TYPE_BOOLEAN)
+ *(boolean *)(config[i].value) = default_value;
+ else
+ *(int *) (config[i].value) = default_value;
+ }
+ }
+}
+
+static void copyConfigFromConfigList(struct ElementFileConfig *config)
+{
+ int i;
+
+ for (i = 0; config[i].data_type != -1; i++)
+ {
+ int data_type = config[i].data_type;
+ int conf_type = config[i].conf_type;
+ int byte_mask = conf_type & CONF_MASK_BYTES;
+
+ if (byte_mask == CONF_MASK_MULTI_BYTES)
+ {
+ int max_num_entities = config[i].max_num_entities;
+
+ if (data_type == TYPE_STRING)
+ {
+ char *string = (char *)(config[i].value);
+ char *string_copy = (char *)(config[i].value_copy);
+
+ strncpy(string_copy, string, max_num_entities);
+ }
+ else if (data_type == TYPE_ELEMENT_LIST)
+ {
+ int *element_array = (int *)(config[i].value);
+ int *element_array_copy = (int *)(config[i].value_copy);
+ int j;
+
+ for (j = 0; j < max_num_entities; j++)
+ element_array_copy[j] = element_array[j];
+ }
+ else if (data_type == TYPE_CONTENT_LIST)
+ {
+ struct Content *content = (struct Content *)(config[i].value);
+ struct Content *content_copy = (struct Content *)(config[i].value_copy);
+ int c, x, y;
+
+ for (c = 0; c < max_num_entities; c++)
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ content_copy[c].e[x][y] = content[c].e[x][y];
+ }
+ }
+ else /* constant size configuration data (1, 2 or 4 bytes) */
+ {
+ if (data_type == TYPE_BOOLEAN)
+ *(boolean *)(config[i].value_copy) = *(boolean *)(config[i].value);
+ else
+ *(int *) (config[i].value_copy) = *(int *) (config[i].value);
+ }
+ }
+}
+
+#if 1
+void copyElementInfo(struct ElementInfo *ei_from, struct ElementInfo *ei_to)
+{
+#if 1
+ int i;
+#else
+ int i, x, y;
+#endif
+
+#if 1
+ xx_ei = *ei_from; /* copy element data into temporary buffer */
+ yy_ei = *ei_to; /* copy element data into temporary buffer */
+
+ copyConfigFromConfigList(custom_element_conf);
+
+ *ei_from = xx_ei;
+ *ei_to = yy_ei;
+#endif
+
+#if 0
+ /* ---------- copy element description ---------- */
+ for (i = 0; i < MAX_ELEMENT_NAME_LEN + 1; i++)
+ ei_to->description[i] = ei_from->description[i];
+
+ /* ---------- copy element base properties ---------- */
+ ei_to->properties[EP_BITFIELD_BASE_NR] =
+ ei_from->properties[EP_BITFIELD_BASE_NR];
+
+ /* ---------- copy custom property values ---------- */
+
+ ei_to->use_gfx_element = ei_from->use_gfx_element;
+ ei_to->gfx_element = ei_from->gfx_element;
-static void setLevelInfoToDefaultsFromConfigList(struct LevelInfo *level)
-{
- int i;
+ ei_to->access_direction = ei_from->access_direction;
- li = *level; /* copy level information into temporary buffer */
+ ei_to->collect_score_initial = ei_from->collect_score_initial;
+ ei_to->collect_count_initial = ei_from->collect_count_initial;
- for (i = 0; element_conf[i].element != -1; i++)
- {
- int default_value = element_conf[i].default_value;
- int type = element_conf[i].type;
- int bytes = type & CONF_MASK_BYTES;
+ ei_to->ce_value_fixed_initial = ei_from->ce_value_fixed_initial;
+ ei_to->ce_value_random_initial = ei_from->ce_value_random_initial;
+ ei_to->use_last_ce_value = ei_from->use_last_ce_value;
- if (bytes == CONF_MASK_MULTI_BYTES)
- {
- int default_num_entities = element_conf[i].default_num_entities;
- int max_num_entities = element_conf[i].max_num_entities;
+ ei_to->push_delay_fixed = ei_from->push_delay_fixed;
+ ei_to->push_delay_random = ei_from->push_delay_random;
+ ei_to->drop_delay_fixed = ei_from->drop_delay_fixed;
+ ei_to->drop_delay_random = ei_from->drop_delay_random;
+ ei_to->move_delay_fixed = ei_from->move_delay_fixed;
+ ei_to->move_delay_random = ei_from->move_delay_random;
- *(int *)(element_conf[i].num_entities) = default_num_entities;
+ ei_to->move_pattern = ei_from->move_pattern;
+ ei_to->move_direction_initial = ei_from->move_direction_initial;
+ ei_to->move_stepsize = ei_from->move_stepsize;
- if (type == CONF_VALUE_ELEMENTS)
- {
- int *element_array = (int *)(element_conf[i].value);
- int j;
+ ei_to->move_enter_element = ei_from->move_enter_element;
+ ei_to->move_leave_element = ei_from->move_leave_element;
+ ei_to->move_leave_type = ei_from->move_leave_type;
- for (j = 0; j < max_num_entities; j++)
- element_array[j] = default_value;
- }
- else if (type == CONF_VALUE_CONTENTS)
- {
- struct Content *content = (struct Content *)(element_conf[i].value);
- int c, x, y;
+ ei_to->slippery_type = ei_from->slippery_type;
- for (c = 0; c < max_num_entities; c++)
- for (y = 0; y < 3; y++)
- for (x = 0; x < 3; x++)
- content[c].e[x][y] = default_value;
- }
- }
- else /* constant size configuration data (1, 2 or 4 bytes) */
- {
- if (CONF_VALUE_BOOLEAN(type))
- *(boolean *)(element_conf[i].value) = default_value;
- else
- *(int *) (element_conf[i].value) = default_value;
- }
- }
+ ei_to->explosion_type = ei_from->explosion_type;
+ ei_to->explosion_delay = ei_from->explosion_delay;
+ ei_to->ignition_delay = ei_from->ignition_delay;
+
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ ei_to->content.e[x][y] = ei_from->content.e[x][y];
+#endif
+
+ /* ---------- reinitialize and copy change pages ---------- */
+
+ ei_to->num_change_pages = ei_from->num_change_pages;
+ ei_to->current_change_page = ei_from->current_change_page;
+
+ setElementChangePages(ei_to, ei_to->num_change_pages);
- *level = li; /* copy temporary buffer back to level information */
+ for (i = 0; i < ei_to->num_change_pages; i++)
+ ei_to->change_page[i] = ei_from->change_page[i];
+
+ /* ---------- copy group element info ---------- */
+ if (ei_from->group != NULL && ei_to->group != NULL) /* group or internal */
+ *ei_to->group = *ei_from->group;
+
+ /* mark this custom element as modified */
+ ei_to->modified_settings = TRUE;
}
+#endif
void setElementChangePages(struct ElementInfo *ei, int change_pages)
{
void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
{
+#if 0
int i, x, y;
+#endif
+
+#if 1
+ xx_change = *change; /* copy change data into temporary buffer */
+ xx_num_contents = 1;
+ setConfigToDefaultsFromConfigList(custom_element_change_conf);
+
+ *change = xx_change;
+
+ resetEventFlags(change);
+#endif
+
+#if 0
change->can_change = FALSE;
for (i = 0; i < NUM_CHANGE_EVENTS; i++)
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
change->target_content.e[x][y] = EL_EMPTY_SPACE;
+#endif
change->direct_action = 0;
change->other_action = 0;
static void setLevelInfoToDefaults(struct LevelInfo *level)
{
static boolean clipboard_elements_initialized = FALSE;
+#if 0
int i, j, x, y;
+#else
+ int i, x, y;
+#endif
#if 1
InitElementPropertiesStatic();
#endif
- setLevelInfoToDefaultsFromConfigList(level);
+#if 1
+ li = *level; /* copy level data into temporary buffer */
+
+ setConfigToDefaultsFromConfigList(element_conf);
+
+ *level = li; /* copy temporary buffer back to level data */
+#endif
+
setLevelInfoToDefaults_EM();
level->native_em_level = &native_em_level;
level->amoeba_content = EL_DIAMOND;
+#if 0
level->game_of_life[0] = 2;
level->game_of_life[1] = 3;
level->game_of_life[2] = 3;
level->biomaze[1] = 3;
level->biomaze[2] = 3;
level->biomaze[3] = 3;
+#endif
#if 0
level->double_speed = FALSE;
level->wind_direction_initial = MV_NONE;
level->ball_random = FALSE;
level->ball_state_initial = FALSE;
+
for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
level->ball_content[i].e[x][y] = EL_EMPTY;
-#endif
-#if 0
+
for (i = 0; i < 16; i++)
level->android_array[i] = FALSE;
#endif
int element = i;
struct ElementInfo *ei = &element_info[element];
+#if 1
+ if (IS_CUSTOM_ELEMENT(element) ||
+ IS_GROUP_ELEMENT(element) ||
+ IS_INTERNAL_ELEMENT(element))
+ {
+ xx_ei = *ei; /* copy element data into temporary buffer */
+
+ setConfigToDefaultsFromConfigList(custom_element_conf);
+
+ *ei = xx_ei;
+ }
+#endif
+
/* never initialize clipboard elements after the very first time */
+ /* (to be able to use clipboard elements between several levels) */
if (IS_CLIPBOARD_ELEMENT(element) && clipboard_elements_initialized)
continue;
IS_GROUP_ELEMENT(element) ||
IS_INTERNAL_ELEMENT(element))
{
+#if 1
+ setElementDescriptionToDefault(ei);
+#else
for (j = 0; j < MAX_ELEMENT_NAME_LEN + 1; j++)
ei->description[j] = '\0';
strncpy(ei->description, ei->custom_description,MAX_ELEMENT_NAME_LEN);
else
strcpy(ei->description, ei->editor_description);
+#endif
+#if 0
ei->use_gfx_element = FALSE;
ei->gfx_element = EL_EMPTY_SPACE;
+#endif
ei->modified_settings = FALSE;
}
if (IS_CUSTOM_ELEMENT(element) ||
IS_INTERNAL_ELEMENT(element))
{
+#if 0
ei->access_direction = MV_ALL_DIRECTIONS;
ei->collect_score_initial = 10; /* special default */
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
ei->content.e[x][y] = EL_EMPTY_SPACE;
+#endif
ei->access_type = 0;
ei->access_layer = 0;
#endif
#endif
+#if 0
/* now set default properties */
SET_PROPERTY(element, EP_CAN_MOVE_INTO_ACID, TRUE);
+#endif
}
if (IS_GROUP_ELEMENT(element) ||
group = ei->group;
+#if 1
+ xx_group = *group; /* copy group data into temporary buffer */
+
+ setConfigToDefaultsFromConfigList(group_element_conf);
+
+ *group = xx_group;
+#endif
+
+#if 0
for (j = 0; j < MAX_ELEMENTS_IN_GROUP; j++)
group->element[j] = EL_EMPTY_SPACE;
group->num_elements = 1;
group->choice_mode = ANIM_RANDOM;
+#endif
}
}
return;
/* try to determine better author name than 'anonymous' */
- if (strcmp(leveldir_current->author, ANONYMOUS_NAME) != 0)
+ if (!strEqual(leveldir_current->author, ANONYMOUS_NAME))
{
strncpy(level->author, leveldir_current->author, MAX_LEVEL_AUTHOR_LEN);
level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
{
char *id_lower = getStringToLower(filetype_id_list[i].id);
- if (strcmp(filetype_id_lower, id_lower) == 0)
+ if (strEqual(filetype_id_lower, id_lower))
filetype = filetype_id_list[i].filetype;
free(id_lower);
#if 1
if (IS_CUSTOM_ELEMENT(element))
- element_info[element].properties[EP_BITFIELD_BASE] = properties;
+ element_info[element].properties[EP_BITFIELD_BASE_NR] = properties;
else
Error(ERR_WARN, "invalid custom element number %d", element);
#else
if (IS_CUSTOM_ELEMENT(element))
- Properties[element][EP_BITFIELD_BASE] = properties;
+ Properties[element][EP_BITFIELD_BASE_NR] = properties;
else
Error(ERR_WARN, "invalid custom element number %d", element);
#endif
{
int element = getFile16BitBE(file);
struct ElementInfo *ei = &element_info[element];
- unsigned long event_bits;
+ unsigned int event_bits;
if (!IS_CUSTOM_ELEMENT(element))
{
ei->description[MAX_ELEMENT_NAME_LEN] = 0;
#if 1
- ei->properties[EP_BITFIELD_BASE] = getFile32BitBE(file);
+ ei->properties[EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
#else
- Properties[element][EP_BITFIELD_BASE] = getFile32BitBE(file);
+ Properties[element][EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
#endif
/* some free bytes for future properties and padding */
ei->description[MAX_ELEMENT_NAME_LEN] = 0;
#if 1
- ei->properties[EP_BITFIELD_BASE] = getFile32BitBE(file);
+ ei->properties[EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
#else
- Properties[element][EP_BITFIELD_BASE] = getFile32BitBE(file);
+ Properties[element][EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
#endif
ReadUnusedBytesFromFile(file, 4); /* reserved for more base properties */
for (i = 0; i < ei->num_change_pages; i++)
{
struct ElementChangeInfo *change = &ei->change_page[i];
- unsigned long event_bits;
+ unsigned int event_bits;
/* always start with reliable default values */
setElementChangeInfoToDefaults(change);
return chunk_size;
}
+static int LoadLevel_MicroChunk(FILE *file, struct ElementFileConfig *config,
+ int element)
+{
+ int micro_chunk_size = 0;
+ int conf_type = getFile8Bit(file);
+ int byte_mask = conf_type & CONF_MASK_BYTES;
+ boolean element_found = FALSE;
+ int i;
+
+ micro_chunk_size += 1;
+
+ if (byte_mask == CONF_MASK_MULTI_BYTES)
+ {
+ int num_bytes = getFile16BitBE(file);
+ byte *buffer = checked_malloc(num_bytes);
+
+#if 0
+ printf("::: - found multi bytes\n");
+#endif
+
+ ReadBytesFromFile(file, buffer, num_bytes);
+
+ for (i = 0; config[i].data_type != -1; i++)
+ {
+ if (config[i].element == element &&
+ config[i].conf_type == conf_type)
+ {
+ int data_type = config[i].data_type;
+ int num_entities = num_bytes / CONF_ENTITY_NUM_BYTES(data_type);
+ int max_num_entities = config[i].max_num_entities;
+
+ if (num_entities > max_num_entities)
+ {
+ Error(ERR_WARN,
+ "truncating number of entities for element %d from %d to %d",
+ element, num_entities, max_num_entities);
+
+ num_entities = max_num_entities;
+ }
+
+ *(int *)(config[i].num_entities) = num_entities;
+
+ element_found = TRUE;
+
+ if (data_type == TYPE_STRING)
+ {
+ char *string = (char *)(config[i].value);
+ int j;
+
+ for (j = 0; j < max_num_entities; j++)
+ string[j] = (j < num_entities ? buffer[j] : '\0');
+ }
+ else if (data_type == TYPE_ELEMENT_LIST)
+ {
+ int *element_array = (int *)(config[i].value);
+ int j;
+
+ for (j = 0; j < num_entities; j++)
+ element_array[j] =
+ getMappedElement(CONF_ELEMENTS_ELEMENT(buffer, j));
+ }
+ else if (data_type == TYPE_CONTENT_LIST)
+ {
+ struct Content *content= (struct Content *)(config[i].value);
+ int c, x, y;
+
+ for (c = 0; c < num_entities; c++)
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ content[c].e[x][y] =
+ getMappedElement(CONF_CONTENTS_ELEMENT(buffer, c, x, y));
+ }
+ else
+ element_found = FALSE;
+
+ break;
+ }
+ }
+
+ checked_free(buffer);
+
+ micro_chunk_size += 2 + num_bytes;
+ }
+ else /* constant size configuration data (1, 2 or 4 bytes) */
+ {
+ int value = (byte_mask == CONF_MASK_1_BYTE ? getFile8Bit (file) :
+ byte_mask == CONF_MASK_2_BYTE ? getFile16BitBE(file) :
+ byte_mask == CONF_MASK_4_BYTE ? getFile32BitBE(file) : 0);
+
+#if 0
+ printf("::: - found single bytes\n");
+#endif
+
+ for (i = 0; config[i].data_type != -1; i++)
+ {
+ if (config[i].element == element &&
+ config[i].conf_type == conf_type)
+ {
+ int data_type = config[i].data_type;
+
+ if (data_type == TYPE_BOOLEAN)
+ *(boolean *)(config[i].value) = value;
+ else
+ *(int *) (config[i].value) = value;
+
+ element_found = TRUE;
+
+ break;
+ }
+ }
+
+ micro_chunk_size += CONF_VALUE_NUM_BYTES(byte_mask);
+ }
+
+ if (!element_found)
+ Error(ERR_WARN, "cannot load micro chunk value for element %d", element);
+
+ return micro_chunk_size;
+}
+
static int LoadLevel_CONF(FILE *file, int chunk_size, struct LevelInfo *level)
{
int real_chunk_size = 0;
- int i;
+
+#if 1
+ li = *level; /* copy level data into temporary buffer */
+#endif
while (!feof(file))
{
int element = getFile16BitBE(file);
- int type = getFile8Bit(file);
- int bytes = type & CONF_MASK_BYTES;
+#if 1
+ real_chunk_size += 2;
+ real_chunk_size += LoadLevel_MicroChunk(file, element_conf, element);
+#else
+ int conf_type = getFile8Bit(file);
+ int byte_mask = conf_type & CONF_MASK_BYTES;
boolean element_found = FALSE;
+ int i;
real_chunk_size += 3;
- li = *level; /* copy level information into temporary buffer */
+#if 0
+ li = *level; /* copy level data into temporary buffer */
+#endif
- if (bytes == CONF_MASK_MULTI_BYTES)
+ if (byte_mask == CONF_MASK_MULTI_BYTES)
{
int num_bytes = getFile16BitBE(file);
byte *buffer = checked_malloc(num_bytes);
- ReadBytesFromFile(file, buffer, num_bytes);
+ ReadBytesFromFile(file, buffer, num_bytes);
+
+ for (i = 0; element_conf[i].data_type != -1; i++)
+ {
+ if (element_conf[i].element == element &&
+ element_conf[i].conf_type == conf_type)
+ {
+ int data_type = element_conf[i].data_type;
+ int num_entities = num_bytes / CONF_ENTITY_NUM_BYTES(data_type);
+ int max_num_entities = element_conf[i].max_num_entities;
+
+ if (num_entities > max_num_entities)
+ {
+ Error(ERR_WARN,
+ "truncating number of entities for element %d from %d to %d",
+ element, num_entities, max_num_entities);
+
+ num_entities = max_num_entities;
+ }
+
+ *(int *)(element_conf[i].num_entities) = num_entities;
+
+ element_found = TRUE;
+
+ if (data_type == TYPE_ELEMENT_LIST)
+ {
+ int *element_array = (int *)(element_conf[i].value);
+ int j;
+
+ for (j = 0; j < num_entities; j++)
+ element_array[j] =
+ getMappedElement(CONF_ELEMENTS_ELEMENT(buffer, j));
+ }
+ else if (data_type == TYPE_CONTENT_LIST)
+ {
+ struct Content *content= (struct Content *)(element_conf[i].value);
+ int c, x, y;
+
+ for (c = 0; c < num_entities; c++)
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ content[c].e[x][y] =
+ getMappedElement(CONF_CONTENTS_ELEMENT(buffer, c, x, y));
+ }
+ else
+ element_found = FALSE;
+
+ break;
+ }
+ }
+
+ checked_free(buffer);
+
+ real_chunk_size += 2 + num_bytes;
+ }
+ else /* constant size configuration data (1, 2 or 4 bytes) */
+ {
+ int value = (byte_mask == CONF_MASK_1_BYTE ? getFile8Bit (file) :
+ byte_mask == CONF_MASK_2_BYTE ? getFile16BitBE(file) :
+ byte_mask == CONF_MASK_4_BYTE ? getFile32BitBE(file) : 0);
+
+ for (i = 0; element_conf[i].data_type != -1; i++)
+ {
+ if (element_conf[i].element == element &&
+ element_conf[i].conf_type == conf_type)
+ {
+ int data_type = element_conf[i].data_type;
+
+ if (data_type == TYPE_BOOLEAN)
+ *(boolean *)(element_conf[i].value) = value;
+ else
+ *(int *) (element_conf[i].value) = value;
+
+ element_found = TRUE;
+
+ break;
+ }
+ }
+
+ real_chunk_size += CONF_VALUE_NUM_BYTES(byte_mask);
+ }
+
+ if (!element_found)
+ Error(ERR_WARN, "cannot load CONF value for element %d", element);
+#endif
+
+#if 0
+ *level = li; /* copy temporary buffer back to level data */
+#endif
+
+#if 1
+ if (real_chunk_size >= chunk_size)
+ break;
+#else
+ if (conf_type == CONF_LAST_ENTRY || real_chunk_size >= chunk_size)
+ break;
+#endif
+ }
+
+#if 1
+ *level = li; /* copy temporary buffer back to level data */
+#endif
+
+ return real_chunk_size;
+}
+
+static int LoadLevel_CUSX(FILE *file, int chunk_size, struct LevelInfo *level)
+{
+ int element = getFile16BitBE(file);
+ int real_chunk_size = 2;
+ struct ElementInfo *ei = &element_info[element];
+ int i;
+
+#if 0
+ printf("::: CUSX: loading element '%s' ...\n", EL_NAME(element));
+#endif
+
+ xx_ei = *ei; /* copy element data into temporary buffer */
+
+ xx_ei.num_change_pages = -1;
+
+ while (!feof(file))
+ {
+ real_chunk_size += LoadLevel_MicroChunk(file, custom_element_conf, -1);
+
+#if 0
+ printf("::: - real_chunk_size now %d\n", real_chunk_size);
+#endif
+
+ if (xx_ei.num_change_pages != -1)
+ break;
+
+ if (real_chunk_size >= chunk_size)
+ break;
+ }
- for (i = 0; element_conf[i].element != -1; i++)
- {
- if (element_conf[i].element == element &&
- element_conf[i].type == type)
- {
- int num_entities = num_bytes / CONF_ENTITY_NUM_BYTES(type);
- int max_num_entities = element_conf[i].max_num_entities;
+ *ei = xx_ei;
- if (num_entities > max_num_entities)
- {
- Error(ERR_WARN,
- "truncating number of entities for element %d from %d to %d",
- element, num_entities, max_num_entities);
+ if (ei->num_change_pages == -1)
+ {
+ Error(ERR_WARN, "LoadLevel_CUSX(): missing 'num_change_pages' for '%s'",
+ EL_NAME(element));
- num_entities = max_num_entities;
- }
+ ei->num_change_pages = 1;
- *(int *)(element_conf[i].num_entities) = num_entities;
+ setElementChangePages(ei, 1);
+ setElementChangeInfoToDefaults(ei->change);
- element_found = TRUE;
+ return real_chunk_size;
+ }
- if (type == CONF_VALUE_ELEMENTS)
- {
- int *element_array = (int *)(element_conf[i].value);
- int j;
+ /* initialize number of change pages stored for this custom element */
+ setElementChangePages(ei, ei->num_change_pages);
+ for (i = 0; i < ei->num_change_pages; i++)
+ setElementChangeInfoToDefaults(&ei->change_page[i]);
- for (j = 0; j < num_entities; j++)
- element_array[j] =
- getMappedElement(CONF_ELEMENTS_ELEMENT(buffer, j));
- }
- else if (type == CONF_VALUE_CONTENTS)
- {
- struct Content *content= (struct Content *)(element_conf[i].value);
- int c, x, y;
+ /* start with reading properties for the first change page */
+ xx_current_change_page = 0;
- for (c = 0; c < num_entities; c++)
- for (y = 0; y < 3; y++)
- for (x = 0; x < 3; x++)
- content[c].e[x][y] =
- getMappedElement(CONF_CONTENTS_ELEMENT(buffer, c, x, y));
- }
- else
- element_found = FALSE;
+ while (!feof(file))
+ {
+ struct ElementChangeInfo *change = &ei->change_page[xx_current_change_page];
- break;
- }
- }
+ xx_change = *change; /* copy change data into temporary buffer */
- checked_free(buffer);
+ resetEventBits(); /* reset bits; change page might have changed */
- real_chunk_size += 2 + num_bytes;
- }
- else /* constant size configuration data (1, 2 or 4 bytes) */
- {
- int value = (bytes == CONF_MASK_1_BYTE ? getFile8Bit (file) :
- bytes == CONF_MASK_2_BYTE ? getFile16BitBE(file) :
- bytes == CONF_MASK_4_BYTE ? getFile32BitBE(file) : 0);
+ real_chunk_size += LoadLevel_MicroChunk(file,custom_element_change_conf,-1);
- for (i = 0; element_conf[i].element != -1; i++)
- {
- if (element_conf[i].element == element &&
- element_conf[i].type == type)
- {
- if (CONF_VALUE_BOOLEAN(type))
- *(boolean *)(element_conf[i].value) = value;
- else
- *(int *) (element_conf[i].value) = value;
+ *change = xx_change;
- element_found = TRUE;
+ setEventFlagsFromEventBits(change);
- break;
- }
- }
+ if (real_chunk_size >= chunk_size)
+ break;
+ }
- real_chunk_size += CONF_VALUE_NUM_BYTES(bytes);
- }
+ return real_chunk_size;
+}
+
+static int LoadLevel_GRPX(FILE *file, int chunk_size, struct LevelInfo *level)
+{
+ int element = getFile16BitBE(file);
+ int real_chunk_size = 2;
+ struct ElementInfo *ei = &element_info[element];
+ struct ElementGroupInfo *group = ei->group;
- *level = li; /* copy temporary buffer back to level information */
+ xx_ei = *ei; /* copy element data into temporary buffer */
+ xx_group = *group; /* copy group data into temporary buffer */
- if (!element_found)
- Error(ERR_WARN, "cannot load CONF value for element %d", element);
+ while (!feof(file))
+ {
+ real_chunk_size += LoadLevel_MicroChunk(file, group_element_conf, -1);
- if (type == CONF_LAST_ENTRY || real_chunk_size >= chunk_size)
+ if (real_chunk_size >= chunk_size)
break;
}
+ *ei = xx_ei;
+ *group = xx_group;
+
return real_chunk_size;
}
}
getFileChunkBE(file, chunk_name, NULL);
- if (strcmp(chunk_name, "RND1") == 0)
+ if (strEqual(chunk_name, "RND1"))
{
getFile32BitBE(file); /* not used */
getFileChunkBE(file, chunk_name, NULL);
- if (strcmp(chunk_name, "CAVE") != 0)
+ if (!strEqual(chunk_name, "CAVE"))
{
level->no_valid_file = TRUE;
{ "CUS4", -1, LoadLevel_CUS4 },
{ "GRP1", -1, LoadLevel_GRP1 },
{ "CONF", -1, LoadLevel_CONF },
+#if 1
+ { "CUSX", -1, LoadLevel_CUSX },
+ { "GRPX", -1, LoadLevel_GRPX },
+#endif
{ NULL, 0, NULL }
};
int i = 0;
while (chunk_info[i].name != NULL &&
- strcmp(chunk_name, chunk_info[i].name) != 0)
+ !strEqual(chunk_name, chunk_info[i].name))
i++;
if (chunk_info[i].name == NULL)
if (reading_multipart_level &&
(!is_multipart_level ||
- strcmp(level->name, multipart_level.name) != 0))
+ !strEqual(level->name, multipart_level.name)))
{
/* we are already reading parts of a multi-part level, but this level is
either not a multi-part level, or a part of a different multi-part
int element = EL_CUSTOM_START + i;
/* order of checking and copying events to be mapped is important */
+ /* (do not change the start and end value -- they are constant) */
for (j = CE_BY_OTHER_ACTION; j >= CE_VALUE_GETS_ZERO; j--)
{
if (HAS_CHANGE_EVENT(element, j - 2))
}
/* order of checking and copying events to be mapped is important */
+ /* (do not change the start and end value -- they are constant) */
for (j = CE_PLAYER_COLLECTS_X; j >= CE_HITTING_SOMETHING; j--)
{
if (HAS_CHANGE_EVENT(element, j - 1))
#if 1
struct ElementInfo *ei = &element_info[element];
- if (ei->properties[EP_BITFIELD_BASE] != EP_BITMASK_DEFAULT)
+ if (ei->properties[EP_BITFIELD_BASE_NR] != EP_BITMASK_DEFAULT)
{
if (check < num_changed_custom_elements)
{
putFile16BitBE(file, element);
- putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE]);
+ putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE_NR]);
}
check++;
}
#else
- if (Properties[element][EP_BITFIELD_BASE] != EP_BITMASK_DEFAULT)
+ if (Properties[element][EP_BITFIELD_BASE_NR] != EP_BITMASK_DEFAULT)
{
if (check < num_changed_custom_elements)
{
putFile16BitBE(file, element);
- putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]);
+ putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE_NR]);
}
check++;
putFile8Bit(file, ei->description[j]);
#if 1
- putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE]);
+ putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE_NR]);
#else
- putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]);
+ putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE_NR]);
#endif
/* some free bytes for future properties and padding */
}
#endif
+#if 0
static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
{
struct ElementInfo *ei = &element_info[element];
putFile8Bit(file, ei->description[i]);
#if 1
- putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE]);
+ putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE_NR]);
#else
- putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]);
+ putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE_NR]);
#endif
WriteUnusedBytesToFile(file, 4); /* reserved for more base properties */
for (i = 0; i < ei->num_change_pages; i++)
{
struct ElementChangeInfo *change = &ei->change_page[i];
- unsigned long event_bits;
+ unsigned int event_bits;
/* bits 0 - 31 of "has_event[]" ... */
event_bits = 0;
putFile8Bit(file, event_bits);
}
}
+#endif
+#if 0
static void SaveLevel_GRP1(FILE *file, struct LevelInfo *level, int element)
{
struct ElementInfo *ei = &element_info[element];
for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++)
putFile16BitBE(file, group->element[i]);
}
+#endif
+
+static int SaveLevel_MicroChunk(FILE *file, struct ElementFileConfig *entry)
+{
+ int data_type = entry->data_type;
+ int conf_type = entry->conf_type;
+ int byte_mask = conf_type & CONF_MASK_BYTES;
+ int element = entry->element;
+ int default_value = entry->default_value;
+ int num_bytes = 0;
+ boolean modified = FALSE;
+
+ if (byte_mask != CONF_MASK_MULTI_BYTES)
+ {
+ void *value_ptr = entry->value;
+ int value = (data_type == TYPE_BOOLEAN ? *(boolean *)value_ptr :
+ *(int *)value_ptr);
+
+ /* check if any settings have been modified before saving them */
+ if (value != default_value)
+ modified = TRUE;
+
+ if (!modified) /* do not save unmodified default settings */
+ return 0;
+
+ if (element != -1)
+ num_bytes += putFile16BitBE(file, element);
+
+ num_bytes += putFile8Bit(file, conf_type);
+ num_bytes += (byte_mask == CONF_MASK_1_BYTE ? putFile8Bit (file, value) :
+ byte_mask == CONF_MASK_2_BYTE ? putFile16BitBE(file, value) :
+ byte_mask == CONF_MASK_4_BYTE ? putFile32BitBE(file, value) :
+ 0);
+
+ return num_bytes;
+ }
+ else if (data_type == TYPE_STRING)
+ {
+ char *default_string = entry->default_string;
+ char *string = (char *)(entry->value);
+ int string_length = strlen(string);
+ int i;
+
+ /* check if any settings have been modified before saving them */
+ if (!strEqual(string, default_string))
+ modified = TRUE;
+
+ if (!modified) /* do not save unmodified default settings */
+ return 0;
+
+ if (element != -1)
+ num_bytes += putFile16BitBE(file, element);
+
+ num_bytes += putFile8Bit(file, conf_type);
+ num_bytes += putFile16BitBE(file, string_length);
+
+ for (i = 0; i < string_length; i++)
+ num_bytes += putFile8Bit(file, string[i]);
+
+ return num_bytes;
+ }
+ else if (data_type == TYPE_ELEMENT_LIST)
+ {
+ int *element_array = (int *)(entry->value);
+ int num_elements = *(int *)(entry->num_entities);
+ int i;
+
+ /* check if any settings have been modified before saving them */
+ for (i = 0; i < num_elements; i++)
+ if (element_array[i] != default_value)
+ modified = TRUE;
+
+ if (!modified) /* do not save unmodified default settings */
+ return 0;
+
+ if (element != -1)
+ num_bytes += putFile16BitBE(file, element);
+
+ num_bytes += putFile8Bit(file, conf_type);
+ num_bytes += putFile16BitBE(file, num_elements * CONF_ELEMENT_NUM_BYTES);
+
+ for (i = 0; i < num_elements; i++)
+ num_bytes += putFile16BitBE(file, element_array[i]);
+
+ return num_bytes;
+ }
+ else if (data_type == TYPE_CONTENT_LIST)
+ {
+ struct Content *content = (struct Content *)(entry->value);
+ int num_contents = *(int *)(entry->num_entities);
+ int i, x, y;
+
+ /* check if any settings have been modified before saving them */
+ for (i = 0; i < num_contents; i++)
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ if (content[i].e[x][y] != default_value)
+ modified = TRUE;
+
+ if (!modified) /* do not save unmodified default settings */
+ return 0;
+
+ if (element != -1)
+ num_bytes += putFile16BitBE(file, element);
+
+ num_bytes += putFile8Bit(file, conf_type);
+ num_bytes += putFile16BitBE(file, num_contents * CONF_CONTENT_NUM_BYTES);
+
+ for (i = 0; i < num_contents; i++)
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ num_bytes += putFile16BitBE(file, content[i].e[x][y]);
+
+ return num_bytes;
+ }
+
+ return 0;
+}
-static int SaveLevel_CONF_Value(FILE *file, int pos)
+#if 0
+
+static int SaveLevel_MicroChunk_SingleValue(FILE *file,
+ struct ElementFileConfig *entry)
{
- int default_value = element_conf[pos].default_value;
- int element = element_conf[pos].element;
- int type = element_conf[pos].type;
- int bytes = type & CONF_MASK_BYTES;
- void *value_ptr = element_conf[pos].value;
- int value = (CONF_VALUE_BOOLEAN(type) ? *(boolean *)value_ptr :
+ int default_value = entry->default_value;
+ int element = entry->element;
+ int data_type = entry->data_type;
+ int conf_type = entry->conf_type;
+ int byte_mask = conf_type & CONF_MASK_BYTES;
+ void *value_ptr = entry->value;
+ int value = (data_type == TYPE_BOOLEAN ? *(boolean *)value_ptr :
*(int *)value_ptr);
int num_bytes = 0;
boolean modified = FALSE;
if (!modified) /* do not save unmodified default settings */
return 0;
- if (bytes == CONF_MASK_MULTI_BYTES)
- Error(ERR_EXIT, "SaveLevel_CONF_Value: cannot save multi-byte values");
+#if 0
+ printf("::: %02x, %d: %d != %d\n",
+ byte_mask, conf_type & CONF_MASK_TOKEN,
+ value, default_value);
+#endif
+
+ if (element != -1)
+ num_bytes += putFile16BitBE(file, element);
- num_bytes += putFile16BitBE(file, element);
- num_bytes += putFile8Bit(file, type);
- num_bytes += (bytes == CONF_MASK_1_BYTE ? putFile8Bit (file, value) :
- bytes == CONF_MASK_2_BYTE ? putFile16BitBE(file, value) :
- bytes == CONF_MASK_4_BYTE ? putFile32BitBE(file, value) : 0);
+ num_bytes += putFile8Bit(file, conf_type);
+ num_bytes += (byte_mask == CONF_MASK_1_BYTE ? putFile8Bit (file, value) :
+ byte_mask == CONF_MASK_2_BYTE ? putFile16BitBE(file, value) :
+ byte_mask == CONF_MASK_4_BYTE ? putFile32BitBE(file, value) :0);
return num_bytes;
}
-static int SaveLevel_CONF_Elements(FILE *file, int pos)
+static int SaveLevel_MicroChunk_ElementList(FILE *file,
+ struct ElementFileConfig *entry)
{
- int *element_array = (int *)(element_conf[pos].value);
- int num_elements = *(int *)element_conf[pos].num_entities;
- int default_value = element_conf[pos].default_value;
- int element = element_conf[pos].element;
- int type = element_conf[pos].type;
+ int *element_array = (int *)(entry->value);
+ int num_elements = *(int *)(entry->num_entities);
+ int default_value = entry->default_value;
+ int element = entry->element;
+ int conf_type = entry->conf_type;
int num_bytes = 0;
boolean modified = FALSE;
int i;
if (!modified) /* do not save unmodified default settings */
return 0;
- num_bytes += putFile16BitBE(file, element);
- num_bytes += putFile8Bit(file, type);
+ if (element != -1)
+ num_bytes += putFile16BitBE(file, element);
+
+ num_bytes += putFile8Bit(file, conf_type);
num_bytes += putFile16BitBE(file, num_elements * CONF_ELEMENT_NUM_BYTES);
for (i = 0; i < num_elements; i++)
return num_bytes;
}
-static int SaveLevel_CONF_Contents(FILE *file, int pos)
+static int SaveLevel_MicroChunk_ContentList(FILE *file,
+ struct ElementFileConfig *entry)
{
- struct Content *content = (struct Content *)(element_conf[pos].value);
- int num_contents = *(int *)element_conf[pos].num_entities;
- int default_value = element_conf[pos].default_value;
- int element = element_conf[pos].element;
- int type = element_conf[pos].type;
+ struct Content *content = (struct Content *)(entry->value);
+ int num_contents = *(int *)(entry->num_entities);
+ int default_value = entry->default_value;
+ int element = entry->element;
+ int conf_type = entry->conf_type;
int num_bytes = 0;
boolean modified = FALSE;
int i, x, y;
if (!modified) /* do not save unmodified default settings */
return 0;
- num_bytes += putFile16BitBE(file, element);
- num_bytes += putFile8Bit(file, type);
+ if (element != -1)
+ num_bytes += putFile16BitBE(file, element);
+
+ num_bytes += putFile8Bit(file, conf_type);
num_bytes += putFile16BitBE(file, num_contents * CONF_CONTENT_NUM_BYTES);
for (i = 0; i < num_contents; i++)
return num_bytes;
}
+#endif
+
static int SaveLevel_CONF(FILE *file, struct LevelInfo *level)
{
int chunk_size = 0;
int i;
- li = *level; /* copy level information into temporary buffer */
+ li = *level; /* copy level data into temporary buffer */
+
+ for (i = 0; element_conf[i].data_type != -1; i++)
+ {
+#if 1
+ chunk_size += SaveLevel_MicroChunk(file, &element_conf[i]);
+#else
+ struct ElementFileConfig *config = &element_conf[i];
+ int data_type = config->data_type;
+ int conf_type = config->conf_type;
+ int byte_mask = conf_type & CONF_MASK_BYTES;
+
+ if (byte_mask != CONF_MASK_MULTI_BYTES)
+ chunk_size += SaveLevel_MicroChunk_SingleValue(file, config);
+ else if (data_type == TYPE_ELEMENT_LIST)
+ chunk_size += SaveLevel_MicroChunk_ElementList(file, config);
+ else if (data_type == TYPE_CONTENT_LIST)
+ chunk_size += SaveLevel_MicroChunk_ContentList(file, config);
+#endif
+ }
+
+ return chunk_size;
+}
+
+static int SaveLevel_CUSX(FILE *file, struct LevelInfo *level, int element)
+{
+ struct ElementInfo *ei = &element_info[element];
+ int chunk_size = 0;
+ int i, j;
+
+ chunk_size += putFile16BitBE(file, element);
+
+ xx_ei = *ei; /* copy element data into temporary buffer */
+
+ /* set default description string for this specific element */
+ strcpy(xx_default_description, getDefaultElementDescription(ei));
+
+ /* set (fixed) number of content areas (may have been overwritten earlier) */
+ xx_num_contents = 1;
+
+#if 0
+ printf("::: - element config\n");
+#endif
+
+ for (i = 0; custom_element_conf[i].data_type != -1; i++)
+ chunk_size += SaveLevel_MicroChunk(file, &custom_element_conf[i]);
+
+#if 0
+ printf("::: - change pages\n");
+#endif
- for (i = 0; element_conf[i].element != -1; i++)
+ for (i = 0; i < ei->num_change_pages; i++)
{
- int type = element_conf[i].type;
- int bytes = type & CONF_MASK_BYTES;
+ struct ElementChangeInfo *change = &ei->change_page[i];
+
+ xx_current_change_page = i;
+
+ xx_change = *change; /* copy change data into temporary buffer */
+
+#if 0
+ printf("::: %d: xx_change.action_mode == %d\n",
+ i, xx_change.action_mode);
+ printf("::: %d: xx_change.action_arg == %d\n",
+ i, xx_change.action_arg);
+#endif
+
+ resetEventBits();
+ setEventBitsFromEventFlags(change);
- if (bytes != CONF_MASK_MULTI_BYTES)
- chunk_size += SaveLevel_CONF_Value(file, i);
- else if (type == CONF_VALUE_ELEMENTS)
- chunk_size += SaveLevel_CONF_Elements(file, i);
- else if (type == CONF_VALUE_CONTENTS)
- chunk_size += SaveLevel_CONF_Contents(file, i);
+ for (j = 0; custom_element_change_conf[j].data_type != -1; j++)
+ chunk_size += SaveLevel_MicroChunk(file, &custom_element_change_conf[j]);
+
+#if 0
+ if (element == EL_CUSTOM_START)
+ printf("::: - saving change page %d / %d (%d bytes)\n",
+ i, ei->num_change_pages, chunk_size);
+#endif
}
return chunk_size;
}
+static int SaveLevel_GRPX(FILE *file, struct LevelInfo *level, int element)
+{
+ struct ElementInfo *ei = &element_info[element];
+ struct ElementGroupInfo *group = ei->group;
+ int chunk_size = 0;
+ int i;
+
+ chunk_size += putFile16BitBE(file, element);
+
+ xx_ei = *ei; /* copy element data into temporary buffer */
+ xx_group = *group; /* copy group data into temporary buffer */
+
+ /* set default description string for this specific element */
+ strcpy(xx_default_description, getDefaultElementDescription(ei));
+
+ for (i = 0; group_element_conf[i].data_type != -1; i++)
+ chunk_size += SaveLevel_MicroChunk(file, &group_element_conf[i]);
+
+ return chunk_size;
+}
+
static void SaveLevelFromFilename(struct LevelInfo *level, char *filename)
{
int body_chunk_size, conf_chunk_size;
}
}
- /* check for non-default custom elements (unless using template level) */
+ /* if not using template level, check for non-default custom/group elements */
if (!level->use_custom_template)
{
+#if 0
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
{
int element = EL_CUSTOM_START + i;
SaveLevel_CUS4(file, level, element);
}
}
- }
- /* check for non-default group elements (unless using template level) */
- if (!level->use_custom_template)
- {
for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
{
int element = EL_GROUP_START + i;
SaveLevel_GRP1(file, level, element);
}
}
+#endif
}
- conf_chunk_size = SaveLevel_CONF(NULL, level); /* get chunk size */
+ conf_chunk_size = SaveLevel_CONF(NULL, level);
- /* check for non-default configuration settings to be saved in CONF chunk */
+ /* check if non-default element settings need to be saved */
if (conf_chunk_size > 0)
{
putFileChunkBE(file, "CONF", conf_chunk_size);
SaveLevel_CONF(file, level);
}
+ /* if not using template level, check for non-default custom/group elements */
+ if (!level->use_custom_template)
+ {
+ /* (element number, number of change pages, change page number) */
+ int cusx_chunk_size_no_changes = (2) + (1 + 1) + (1 + 1);
+ /* (element number only) */
+ int grpx_chunk_size_no_changes = (2);
+
+#if 1
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+ int cusx_chunk_size = SaveLevel_CUSX(NULL, level, element);
+
+ /* check if non-default element settings need to be saved */
+ if (cusx_chunk_size > cusx_chunk_size_no_changes)
+ {
+#if 1
+ printf("::: SAVING CE %d\n", i + 1);
+#endif
+
+ putFileChunkBE(file, "CUSX", cusx_chunk_size);
+ SaveLevel_CUSX(file, level, element);
+ }
+ }
+
+ for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
+ {
+ int element = EL_GROUP_START + i;
+ int grpx_chunk_size = SaveLevel_GRPX(NULL, level, element);
+
+ /* check if non-default element settings need to be saved */
+ if (grpx_chunk_size > grpx_chunk_size_no_changes)
+ {
+#if 1
+ printf("::: SAVING GE %d\n", i + 1);
+#endif
+
+ putFileChunkBE(file, "GRPX", grpx_chunk_size);
+ SaveLevel_GRPX(file, level, element);
+ }
+ }
+#endif
+ }
+
fclose(file);
SetFilePermissions(filename, PERMS_PRIVATE);
}
getFileChunkBE(file, chunk_name, NULL);
- if (strcmp(chunk_name, "RND1") == 0)
+ if (strEqual(chunk_name, "RND1"))
{
getFile32BitBE(file); /* not used */
getFileChunkBE(file, chunk_name, NULL);
- if (strcmp(chunk_name, "TAPE") != 0)
+ if (!strEqual(chunk_name, "TAPE"))
{
tape.no_valid_file = TRUE;
int i = 0;
while (chunk_info[i].name != NULL &&
- strcmp(chunk_name, chunk_info[i].name) != 0)
+ !strEqual(chunk_name, chunk_info[i].name))
i++;
if (chunk_info[i].name == NULL)
#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_SKIP_LEVELS 13
-#define SETUP_TOKEN_TIME_LIMIT 14
-#define SETUP_TOKEN_FULLSCREEN 15
-#define SETUP_TOKEN_ASK_ON_ESCAPE 16
-#define SETUP_TOKEN_ASK_ON_ESCAPE_EDITOR 17
-#define SETUP_TOKEN_QUICK_SWITCH 18
-#define SETUP_TOKEN_INPUT_ON_FOCUS 19
-#define SETUP_TOKEN_PREFER_AGA_GRAPHICS 20
-#define SETUP_TOKEN_GRAPHICS_SET 21
-#define SETUP_TOKEN_SOUNDS_SET 22
-#define SETUP_TOKEN_MUSIC_SET 23
-#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 24
-#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 25
-#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 26
-
-#define NUM_GLOBAL_SETUP_TOKENS 27
+#define SETUP_TOKEN_SHOW_TITLESCREEN 10
+#define SETUP_TOKEN_QUICK_DOORS 11
+#define SETUP_TOKEN_TEAM_MODE 12
+#define SETUP_TOKEN_HANDICAP 13
+#define SETUP_TOKEN_SKIP_LEVELS 14
+#define SETUP_TOKEN_TIME_LIMIT 15
+#define SETUP_TOKEN_FULLSCREEN 16
+#define SETUP_TOKEN_ASK_ON_ESCAPE 17
+#define SETUP_TOKEN_ASK_ON_ESCAPE_EDITOR 18
+#define SETUP_TOKEN_QUICK_SWITCH 19
+#define SETUP_TOKEN_INPUT_ON_FOCUS 20
+#define SETUP_TOKEN_PREFER_AGA_GRAPHICS 21
+#define SETUP_TOKEN_GRAPHICS_SET 22
+#define SETUP_TOKEN_SOUNDS_SET 23
+#define SETUP_TOKEN_MUSIC_SET 24
+#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 25
+#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 26
+#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 27
+
+#define NUM_GLOBAL_SETUP_TOKENS 28
/* editor setup */
#define SETUP_TOKEN_EDITOR_EL_BOULDERDASH 0
#define SETUP_TOKEN_EDITOR_EL_HEADLINES 10
#define SETUP_TOKEN_EDITOR_EL_USER_DEFINED 11
#define SETUP_TOKEN_EDITOR_EL_DYNAMIC 12
+#define SETUP_TOKEN_EDITOR_SHOW_ELEMENT_TOKEN 13
-#define NUM_EDITOR_SETUP_TOKENS 13
+#define NUM_EDITOR_SETUP_TOKENS 14
/* editor cascade setup */
#define SETUP_TOKEN_EDITOR_CASCADE_BD 0
{ TYPE_SWITCH, &si.soft_scrolling, "soft_scrolling" },
{ TYPE_SWITCH, &si.fading, "screen_fading" },
{ TYPE_SWITCH, &si.autorecord, "automatic_tape_recording" },
+ { TYPE_SWITCH, &si.show_titlescreen, "show_titlescreen" },
{ TYPE_SWITCH, &si.quick_doors, "quick_doors" },
{ TYPE_SWITCH, &si.team_mode, "team_mode" },
{ TYPE_SWITCH, &si.handicap, "handicap" },
{ TYPE_SWITCH, &sei.el_headlines, "editor.el_headlines" },
{ TYPE_SWITCH, &sei.el_user_defined, "editor.el_user_defined" },
{ TYPE_SWITCH, &sei.el_dynamic, "editor.el_dynamic" },
+ { TYPE_SWITCH, &sei.show_element_token,"editor.show_element_token" },
};
static struct TokenInfo editor_cascade_setup_tokens[] =
si->soft_scrolling = TRUE;
si->fading = FALSE;
si->autorecord = TRUE;
+ si->show_titlescreen = TRUE;
si->quick_doors = FALSE;
si->team_mode = FALSE;
si->handicap = TRUE;
si->editor.el_user_defined = FALSE;
si->editor.el_dynamic = TRUE;
+ si->editor.show_element_token = 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;
freeSetupFileHash(setup_file_hash);
}
-void LoadSpecialMenuDesignSettings()
+static void LoadSpecialMenuDesignSettingsFromFilename(char *filename)
{
- char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
SetupFileHash *setup_file_hash;
- int i, j;
+ int i;
- /* always start with reliable default values from default config */
- for (i = 0; image_config_vars[i].token != NULL; i++)
- for (j = 0; image_config[j].token != NULL; j++)
- if (strcmp(image_config_vars[i].token, image_config[j].token) == 0)
- *image_config_vars[i].value =
- get_auto_parameter_value(image_config_vars[i].token,
- image_config[j].value);
+#if 0
+ printf("LoadSpecialMenuDesignSettings from file '%s' ...\n", filename);
+#endif
if ((setup_file_hash = loadSetupFileHash(filename)) == NULL)
return;
freeSetupFileHash(setup_file_hash);
}
+void LoadSpecialMenuDesignSettings()
+{
+ char *filename_base = UNDEFINED_FILENAME, *filename_local;
+ int i, j;
+
+ /* always start with reliable default values from default config */
+ for (i = 0; image_config_vars[i].token != NULL; i++)
+ for (j = 0; image_config[j].token != NULL; j++)
+ if (strEqual(image_config_vars[i].token, image_config[j].token))
+ *image_config_vars[i].value =
+ get_auto_parameter_value(image_config_vars[i].token,
+ image_config[j].value);
+
+#if 1
+ if (!SETUP_OVERRIDE_ARTWORK(setup, ARTWORK_TYPE_GRAPHICS))
+ {
+ /* first look for special settings configured in level series config */
+ filename_base = getCustomArtworkLevelConfigFilename(ARTWORK_TYPE_GRAPHICS);
+
+ if (fileExists(filename_base))
+ LoadSpecialMenuDesignSettingsFromFilename(filename_base);
+ }
+
+ filename_local = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
+
+ if (filename_local != NULL && !strEqual(filename_base, filename_local))
+ LoadSpecialMenuDesignSettingsFromFilename(filename_local);
+
+#else
+
+ filename_local = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
+
+ LoadSpecialMenuDesignSettingsFromFilename(filename_local);
+#endif
+}
+
void LoadUserDefinedEditorElementList(int **elements, int *num_elements)
{
char *filename = getEditorSetupFilename();
char *basename, boolean is_sound)
{
for (; list != NULL; list = list->next)
- if (list->is_sound == is_sound && strcmp(list->basename, basename) == 0)
+ if (list->is_sound == is_sound && strEqual(list->basename, basename))
return TRUE;
return FALSE;
if (music->filename == NULL)
continue;
- if (strcmp(music->filename, UNDEFINED_FILENAME) == 0)
+ if (strEqual(music->filename, UNDEFINED_FILENAME))
continue;
/* a configured file may be not recognized as music */
if (music->filename == NULL)
continue;
- if (strcmp(basename, music->filename) == 0)
+ if (strEqual(basename, music->filename))
{
music_already_used = TRUE;
break;
if (sound->filename == NULL)
continue;
- if (strcmp(sound->filename, UNDEFINED_FILENAME) == 0)
+ if (strEqual(sound->filename, UNDEFINED_FILENAME))
continue;
/* a configured file may be not recognized as sound */
char *element_value, *action_value, *direction_value;
int delay = atoi(list->value);
- if (strcmp(list->token, "end") == 0)
+ if (strEqual(list->token, "end"))
{
add_helpanim_entry(HELPANIM_LIST_NEXT, -1, -1, -1, &num_list_entries);