+#define LEVEL_COOKIE_TMPL "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x"
+#define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x"
+#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2"
+
+/* values for "CONF" chunk */
+#define CONF_MASK_1_BYTE 0x00
+#define CONF_MASK_2_BYTE 0x40
+#define CONF_MASK_4_BYTE 0x80
+#define CONF_MASK_MULTI_BYTES 0xc0
+
+#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_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)
+
+#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)
+
+#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) == CONF_VALUE_ELEMENTS ? \
+ CONF_ELEMENT_NUM_BYTES : \
+ (t) == CONF_VALUE_CONTENTS ? \
+ 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) | \
+ (b[CONF_ELEMENT_BYTE_POS(i) + 1]))
+
+#define CONF_CONTENT_ELEMENT_POS(c,x,y) ((c) * CONF_CONTENT_NUM_ELEMENTS + \
+ (y) * 3 + (x))
+#define CONF_CONTENT_BYTE_POS(c,x,y) (CONF_CONTENT_ELEMENT_POS(c,x,y) * \
+ CONF_ELEMENT_NUM_BYTES)
+#define CONF_CONTENTS_ELEMENT(b,c,x,y) ((b[CONF_CONTENT_BYTE_POS(c,x,y)]<< 8)|\
+ (b[CONF_CONTENT_BYTE_POS(c,x,y) + 1]))
+
+static struct LevelInfo li;
+
+static struct
+{
+ int element; /* element for which data is to be stored */
+ int type; /* type of data to be stored */
+
+ /* (mandatory) */
+ void *value; /* variable that holds the data to be stored */
+ int default_value; /* initial default value for this variable */
+
+ /* (optional) */
+ 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[] =
+{
+ /* ---------- 1-byte values ---------------------------------------------- */
+
+ {
+ EL_EMC_ANDROID, CONF_VALUE_INTEGER_1,
+ &li.android_move_time, 10
+ },
+ {
+ EL_EMC_ANDROID, CONF_VALUE_INTEGER_2,
+ &li.android_clone_time, 10
+ },
+ {
+ EL_EMC_LENSES, CONF_VALUE_INTEGER_1,
+ &li.lenses_score, 10
+ },
+ {
+ EL_EMC_LENSES, CONF_VALUE_INTEGER_2,
+ &li.lenses_time, 10
+ },
+ {
+ EL_EMC_MAGNIFIER, CONF_VALUE_INTEGER_1,
+ &li.magnify_score, 10
+ },
+ {
+ EL_EMC_MAGNIFIER, CONF_VALUE_INTEGER_2,
+ &li.magnify_time, 10
+ },
+ {
+ EL_ROBOT, CONF_VALUE_INTEGER_1,
+ &li.slurp_score, 10
+ },
+ {
+ EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_1,
+ &li.game_of_life[0], 2
+ },
+ {
+ EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_2,
+ &li.game_of_life[1], 3
+ },
+ {
+ EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_3,
+ &li.game_of_life[2], 3
+ },
+ {
+ EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_4,
+ &li.game_of_life[3], 3
+ },
+ {
+ EL_BIOMAZE, CONF_VALUE_INTEGER_1,
+ &li.biomaze[0], 2
+ },
+ {
+ EL_BIOMAZE, CONF_VALUE_INTEGER_2,
+ &li.biomaze[1], 3
+ },
+ {
+ EL_BIOMAZE, CONF_VALUE_INTEGER_3,
+ &li.biomaze[2], 3
+ },
+ {
+ EL_BIOMAZE, CONF_VALUE_INTEGER_4,
+ &li.biomaze[3], 3
+ },
+ {
+ EL_BALLOON, CONF_VALUE_INTEGER_1,
+ &li.wind_direction_initial, MV_NONE
+ },
+ {
+ EL_TIMEGATE_SWITCH, CONF_VALUE_INTEGER_1,
+ &li.time_timegate, 10
+ },
+ {
+ EL_LIGHT_SWITCH_ACTIVE, CONF_VALUE_INTEGER_1,
+ &li.time_light, 10
+ },
+ {
+ EL_SHIELD_NORMAL, CONF_VALUE_INTEGER_1,
+ &li.shield_normal_time, 10
+ },
+ {
+ EL_SHIELD_DEADLY, CONF_VALUE_INTEGER_1,
+ &li.shield_deadly_time, 10
+ },
+ {
+ EL_EXTRA_TIME, CONF_VALUE_INTEGER_1,
+ &li.extra_time, 10
+ },
+ {
+ EL_EXTRA_TIME, CONF_VALUE_INTEGER_2,
+ &li.extra_time_score, 10
+ },
+ {
+ EL_TIME_ORB_FULL, CONF_VALUE_INTEGER_1,
+ &li.time_orb_time, 10
+ },
+ {
+ EL_TIME_ORB_FULL, CONF_VALUE_BOOLEAN_1,
+ &li.use_time_orb_bug, FALSE
+ },
+ {
+ EL_PLAYER_1, CONF_VALUE_BOOLEAN_1,
+ &li.block_snap_field, TRUE
+ },
+ {
+ EL_PLAYER_1, CONF_VALUE_BOOLEAN_2,
+ &li.use_start_element[0], FALSE
+ },
+ {
+ EL_PLAYER_2, CONF_VALUE_BOOLEAN_2,
+ &li.use_start_element[1], FALSE
+ },
+ {
+ EL_PLAYER_3, CONF_VALUE_BOOLEAN_2,
+ &li.use_start_element[2], FALSE
+ },
+ {
+ EL_PLAYER_4, CONF_VALUE_BOOLEAN_2,
+ &li.use_start_element[3], FALSE
+ },
+ {
+ EL_PLAYER_1, CONF_VALUE_BOOLEAN_3,
+ &li.use_artwork_element[0], FALSE
+ },
+ {
+ EL_PLAYER_2, CONF_VALUE_BOOLEAN_3,
+ &li.use_artwork_element[1], FALSE
+ },
+ {
+ EL_PLAYER_3, CONF_VALUE_BOOLEAN_3,
+ &li.use_artwork_element[2], FALSE
+ },
+ {
+ EL_PLAYER_4, CONF_VALUE_BOOLEAN_3,
+ &li.use_artwork_element[3], FALSE
+ },
+ {
+ EL_PLAYER_1, CONF_VALUE_BOOLEAN_4,
+ &li.use_explosion_element[0], FALSE
+ },
+ {
+ EL_PLAYER_2, CONF_VALUE_BOOLEAN_4,
+ &li.use_explosion_element[1], FALSE
+ },
+ {
+ EL_PLAYER_3, CONF_VALUE_BOOLEAN_4,
+ &li.use_explosion_element[2], FALSE
+ },
+ {
+ EL_PLAYER_4, CONF_VALUE_BOOLEAN_4,
+ &li.use_explosion_element[3], FALSE
+ },
+ {
+ EL_PLAYER_1, CONF_VALUE_INTEGER_1,
+ &li.initial_player_stepsize, STEPSIZE_NORMAL
+ },
+ {
+ EL_EMC_MAGIC_BALL, CONF_VALUE_INTEGER_1,
+ &li.ball_time, 10
+ },
+ {
+ EL_EMC_MAGIC_BALL, CONF_VALUE_BOOLEAN_1,
+ &li.ball_random, FALSE
+ },
+ {
+ EL_EMC_MAGIC_BALL, CONF_VALUE_BOOLEAN_2,
+ &li.ball_state_initial, FALSE
+ },
+
+ /* ---------- 2-byte values ---------------------------------------------- */
+
+ {
+ EL_PLAYER_1, CONF_VALUE_ELEMENT_1,
+ &li.start_element[0], EL_PLAYER_1
+ },
+ {
+ EL_PLAYER_2, CONF_VALUE_ELEMENT_1,
+ &li.start_element[1], EL_PLAYER_2
+ },
+ {
+ EL_PLAYER_3, CONF_VALUE_ELEMENT_1,
+ &li.start_element[2], EL_PLAYER_3
+ },
+ {
+ EL_PLAYER_4, CONF_VALUE_ELEMENT_1,
+ &li.start_element[3], EL_PLAYER_4
+ },
+ {
+ EL_PLAYER_1, CONF_VALUE_ELEMENT_2,
+ &li.artwork_element[0], EL_PLAYER_1
+ },
+ {
+ EL_PLAYER_2, CONF_VALUE_ELEMENT_2,
+ &li.artwork_element[1], EL_PLAYER_2
+ },
+ {
+ EL_PLAYER_3, CONF_VALUE_ELEMENT_2,
+ &li.artwork_element[2], EL_PLAYER_3
+ },
+ {
+ EL_PLAYER_4, CONF_VALUE_ELEMENT_2,
+ &li.artwork_element[3], EL_PLAYER_4
+ },
+ {
+ EL_PLAYER_1, CONF_VALUE_ELEMENT_3,
+ &li.explosion_element[0], EL_PLAYER_1
+ },
+ {
+ EL_PLAYER_2, CONF_VALUE_ELEMENT_3,
+ &li.explosion_element[1], EL_PLAYER_2
+ },
+ {
+ EL_PLAYER_3, CONF_VALUE_ELEMENT_3,
+ &li.explosion_element[2], EL_PLAYER_3
+ },
+ {
+ EL_PLAYER_4, 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,
+ &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,
+ NULL, -1,
+ },
+};
+
+static struct
+{
+ int filetype;
+ char *id;
+}
+filetype_id_list[] =
+{
+ { LEVEL_FILE_TYPE_RND, "RND" },
+ { LEVEL_FILE_TYPE_BD, "BD" },
+ { LEVEL_FILE_TYPE_EM, "EM" },
+ { LEVEL_FILE_TYPE_SP, "SP" },
+ { LEVEL_FILE_TYPE_DX, "DX" },
+ { LEVEL_FILE_TYPE_SB, "SB" },
+ { LEVEL_FILE_TYPE_DC, "DC" },
+ { -1, NULL },
+};